Imported Upstream version 1.28.0 upstream accepted/tizen/unified/20240829.091441 accepted/tizen/unified/dev/20240901.214717 accepted/tizen/unified/x/20240829.105233 upstream/1.28.0
authorHyeongseok Oh <hseok82.oh@samsung.com>
Wed, 28 Aug 2024 08:36:59 +0000 (17:36 +0900)
committerHyeongseok Oh <hseok82.oh@samsung.com>
Wed, 28 Aug 2024 08:36:59 +0000 (17:36 +0900)
3333 files changed:
.ahub/sam/exclude.txt
.ahub/tcchecker-tca/config.yaml
.clang-format
.github/workflows/check-format.yml
.github/workflows/check-pr-commit.yml
.github/workflows/deploy-github-pages.yml
.github/workflows/run-onert-micro-unit-tests.yml
.readthedocs.yml
Makefile.template
README.md
compiler/CMakeLists.txt
compiler/adtidas/exclude.me [new file with mode: 0644]
compiler/ann-api/exclude.me [new file with mode: 0644]
compiler/ann-ref/exclude.me [new file with mode: 0644]
compiler/arser/include/arser/arser.h
compiler/arser/tests/arser.test.cpp
compiler/bino/exclude.me [new file with mode: 0644]
compiler/caffe2circle/exclude.me [new file with mode: 0644]
compiler/caffegen/exclude.me [new file with mode: 0644]
compiler/circle-eval-diff/src/InputDataLoader.cpp
compiler/circle-execution-plan/pal/ScratchpadHelperLinux.h
compiler/circle-inspect/CMakeLists.txt
compiler/circle-inspect/requires.cmake
compiler/circle-inspect/src/Dump.cpp
compiler/circle-interpreter-test/requires.cmake
compiler/circle-interpreter/src/CircleInterpreter.cpp
compiler/circle-mpqsolver/CMakeLists.txt
compiler/circle-mpqsolver/src/CircleMPQSolver.cpp
compiler/circle-mpqsolver/src/MPQSolver.cpp
compiler/circle-mpqsolver/src/MPQSolver.h
compiler/circle-mpqsolver/src/bisection/BisectionSolver.cpp
compiler/circle-mpqsolver/src/bisection/BisectionSolver.h
compiler/circle-mpqsolver/src/bisection/BisectionSolver.test.cpp [new file with mode: 0644]
compiler/circle-mpqsolver/src/bisection/DepthParameterizer.test.cpp
compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.cpp
compiler/circle-mpqsolver/src/bisection/VISQErrorApproximator.test.cpp
compiler/circle-mpqsolver/src/core/DataProvider.cpp [new file with mode: 0644]
compiler/circle-mpqsolver/src/core/DataProvider.h [new file with mode: 0644]
compiler/circle-mpqsolver/src/core/Dumper.cpp
compiler/circle-mpqsolver/src/core/Dumper.h
compiler/circle-mpqsolver/src/core/Dumper.test.cpp [new file with mode: 0644]
compiler/circle-mpqsolver/src/core/DumpingHooks.cpp
compiler/circle-mpqsolver/src/core/DumpingHooks.h
compiler/circle-mpqsolver/src/core/DumpingHooks.test.cpp [new file with mode: 0644]
compiler/circle-mpqsolver/src/core/ErrorMetric.cpp
compiler/circle-mpqsolver/src/core/ErrorMetric.test.cpp
compiler/circle-mpqsolver/src/core/Evaluator.cpp
compiler/circle-mpqsolver/src/core/Evaluator.h
compiler/circle-mpqsolver/src/core/Evaluator.test.cpp [new file with mode: 0644]
compiler/circle-mpqsolver/src/core/Quantizer.cpp
compiler/circle-mpqsolver/src/core/Quantizer.h
compiler/circle-mpqsolver/src/core/Quantizer.test.cpp
compiler/circle-mpqsolver/src/core/SolverHooks.h
compiler/circle-mpqsolver/src/core/TestHelper.h
compiler/circle-mpqsolver/src/core/TestHelper.test.cpp [new file with mode: 0644]
compiler/circle-mpqsolver/src/pattern/PatternResolver.cpp [new file with mode: 0644]
compiler/circle-mpqsolver/src/pattern/PatternResolver.h [new file with mode: 0644]
compiler/circle-mpqsolver/src/pattern/PatternResolver.test.cpp [new file with mode: 0644]
compiler/circle-mpqsolver/src/pattern/PatternSolver.cpp [new file with mode: 0644]
compiler/circle-mpqsolver/src/pattern/PatternSolver.h [new file with mode: 0644]
compiler/circle-mpqsolver/src/pattern/PatternSolver.test.cpp [new file with mode: 0644]
compiler/circle-operator/CMakeLists.txt
compiler/circle-operator/requires.cmake
compiler/circle-operator/src/Dump.cpp
compiler/circle-opselector/driver/Driver.cpp
compiler/circle-opselector/src/OpSelector.cpp
compiler/circle-part-driver/src/PModelsRunner.cpp
compiler/circle-part-value-py-test/CMakeLists.txt [new file with mode: 0644]
compiler/circle-part-value-py-test/README.md [new file with mode: 0644]
compiler/circle-part-value-py-test/conftest.py [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.002.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.003.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Net_UnpackAdd_001.001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Net_UnpackAdd_001.002.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Net_UnpackAdd_001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Add_Sqrt_000.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Add_Sqrt_Rsqrt_000.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Add_Sub_000.001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Add_Sub_000.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Add_Sub_001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Add_Sub_002.001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Add_Sub_002.002.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_If_Add_Sub_000.001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_If_Add_Sub_001.001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Mul_Sqrt_FC_nobias_000_000.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Mul_Sqrt_FC_nobias_000_001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Mul_Sqrt_FC_nobias_000_002.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Split_Add_000.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_000.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_002.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_003.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_000.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_002.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_003.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_004.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias_001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias_002.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias_003.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_While_000.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/Part_While_001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/SignatureDef_MultiOut_000.part [new file with mode: 0644]
compiler/circle-part-value-py-test/parts/SignatureDef_MultiOut_001.part [new file with mode: 0644]
compiler/circle-part-value-py-test/requires.cmake [new file with mode: 0644]
compiler/circle-part-value-py-test/test.lst [new file with mode: 0644]
compiler/circle-part-value-py-test/test_circle_part_value.py [new file with mode: 0644]
compiler/circle-part-value-test/exclude.me [new file with mode: 0644]
compiler/circle-quantizer-dredd-recipe-test/test.lst
compiler/circle-quantizer/src/CircleQuantizer.cpp
compiler/circle-tensordump/CMakeLists.txt
compiler/circle-tensordump/requires.cmake
compiler/circle-verify/CMakeLists.txt
compiler/circle-verify/requires.cmake
compiler/circle2circle-dredd-recipe-test/test.lst
compiler/circle2circle/src/Circle2Circle.cpp
compiler/circlechef/CMakeLists.txt
compiler/circlechef/circle/CMakeLists.txt
compiler/circlechef/circle/src/CircleImport.cpp
compiler/circlechef/circle/src/CircleImport.h
compiler/circlechef/circle/src/CircleOpChefs.h
compiler/circlechef/circle/src/CircleOpRegistry.h
compiler/circlechef/circle/src/Convert.cpp
compiler/circlechef/circle/src/Convert.h
compiler/circlechef/circle/src/Op/GRU.cpp [new file with mode: 0644]
compiler/circlechef/circle/src/Op/GRU.h [new file with mode: 0644]
compiler/circlechef/circle/src/RecipeChef.cpp
compiler/circlechef/core/CMakeLists.txt
compiler/circlechef/core/src/Convert.cpp
compiler/circlechef/core/src/Convert.test.cpp
compiler/circlechef/core/src/DataChef.def
compiler/circlechef/core/src/ModelChef.cpp
compiler/circlechef/core/src/Op/FullyConnected.cpp [new file with mode: 0644]
compiler/circlechef/core/src/Op/FullyConnected.h [new file with mode: 0644]
compiler/circlechef/core/src/Op/GRU.cpp [new file with mode: 0644]
compiler/circlechef/core/src/Op/GRU.h [new file with mode: 0644]
compiler/circlechef/core/src/OpChef.def
compiler/circlechef/core/src/OpChefs.h
compiler/circlechef/proto/circlechef.proto
compiler/circlechef/requires.cmake
compiler/circlechef/tests/int4_datatype/test.recipe [new file with mode: 0644]
compiler/circlechef/tests/uint4_datatype/test.recipe [new file with mode: 0644]
compiler/circledump/CMakeLists.txt
compiler/circledump/README.md
compiler/circledump/requires.cmake
compiler/circledump/src/Dump.cpp
compiler/circledump/src/OpPrinter.cpp
compiler/cli/exclude.me [new file with mode: 0644]
compiler/coco/exclude.me [new file with mode: 0644]
compiler/common-artifacts/CMakeLists.txt
compiler/common-artifacts/exclude.lst
compiler/common-artifacts/src/TestDataGenerator.cpp
compiler/dalgona/src/Dalgona.cpp
compiler/dio-hdf5/include/dio_hdf5/HDF5Importer.h
compiler/dio-hdf5/src/HDF5Importer.cpp
compiler/embedded-import-value-test/src/TestDriver.cpp
compiler/enco-intf/exclude.me [new file with mode: 0644]
compiler/enco/exclude.me [new file with mode: 0644]
compiler/enco/frontend/tflite/CMakeLists.txt
compiler/enco/test/tflite/CMakeLists.txt
compiler/encodump/exclude.me [new file with mode: 0644]
compiler/exo/CMakeLists.txt
compiler/exo/exclude.me [new file with mode: 0644]
compiler/fipe/exclude.me [new file with mode: 0644]
compiler/hermes-std/include/hermes/ConsoleReporter.h
compiler/hermes-std/src/ConsoleReporter.cpp
compiler/kuma/exclude.me [new file with mode: 0644]
compiler/loco/include/loco/IR/DataType.h
compiler/loco/include/loco/IR/DataTypeTraits.h
compiler/loco/include/loco/IR/NodePool.h
compiler/loco/src/IR/MockupNode.h
compiler/loco/src/Service/GraphBuilder.h
compiler/loco/src/Service/TypeInference.test.cpp
compiler/locop/src/FormattedGraph.cpp
compiler/luci-compute/CMakeLists.txt
compiler/luci-compute/include/luci_compute/DepthwiseConv2D.h [new file with mode: 0644]
compiler/luci-compute/include/luci_compute/FullyConnected.h [new file with mode: 0644]
compiler/luci-compute/include/luci_compute/Types.h [new file with mode: 0644]
compiler/luci-compute/requires.cmake [new file with mode: 0644]
compiler/luci-compute/src/ConvertTypes.cpp [new file with mode: 0644]
compiler/luci-compute/src/ConvertTypes.h [new file with mode: 0644]
compiler/luci-compute/src/ConvertTypes.test.cpp [new file with mode: 0644]
compiler/luci-compute/src/ConvertValues.cpp [new file with mode: 0644]
compiler/luci-compute/src/ConvertValues.h [new file with mode: 0644]
compiler/luci-compute/src/ConvertValues.test.cpp [new file with mode: 0644]
compiler/luci-compute/src/DepthwiseConv2D.cpp [new file with mode: 0644]
compiler/luci-compute/src/DepthwiseConv2D.test.cpp [new file with mode: 0644]
compiler/luci-compute/src/FullyConnected.cpp [new file with mode: 0644]
compiler/luci-compute/src/FullyConnected.test.cpp [new file with mode: 0644]
compiler/luci-eval-driver/src/EvalDriver.cpp
compiler/luci-interpreter/include/luci_interpreter/BuddyMemoryManager.h
compiler/luci-interpreter/include/luci_interpreter/Interpreter.h
compiler/luci-interpreter/include/luci_interpreter/core/DataType.h
compiler/luci-interpreter/include/luci_interpreter/core/Tensor.h
compiler/luci-interpreter/pal/linux/KernelsToBuild.lst
compiler/luci-interpreter/pal/linux/PALBroadcastTo.h [new file with mode: 0644]
compiler/luci-interpreter/pal/linux/PALConv2d.h
compiler/luci-interpreter/pal/linux/PALRelu0To1.h [new file with mode: 0644]
compiler/luci-interpreter/pal/linux/pal.cmake
compiler/luci-interpreter/src/CMakeLists.txt
compiler/luci-interpreter/src/Interpreter.cpp
compiler/luci-interpreter/src/SimpleMemoryManager.cpp
compiler/luci-interpreter/src/SimpleMemoryManager.test.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/core/KernelParams.h
compiler/luci-interpreter/src/kernels/Abs.cpp
compiler/luci-interpreter/src/kernels/Add.cpp
compiler/luci-interpreter/src/kernels/AveragePool2D.cpp
compiler/luci-interpreter/src/kernels/BatchMatMul.cpp
compiler/luci-interpreter/src/kernels/BatchToSpaceND.cpp
compiler/luci-interpreter/src/kernels/BroadcastTo.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/BroadcastTo.h [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/BroadcastTo.test.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Concatenation.cpp
compiler/luci-interpreter/src/kernels/Conv2D.cpp
compiler/luci-interpreter/src/kernels/Cos.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Cos.h [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Cos.test.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/CumSum.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/CumSum.h [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/CumSum.test.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/DepthToSpace.cpp
compiler/luci-interpreter/src/kernels/DepthwiseConv2D.cpp
compiler/luci-interpreter/src/kernels/Dequantize.cpp
compiler/luci-interpreter/src/kernels/Div.cpp
compiler/luci-interpreter/src/kernels/Elu.cpp
compiler/luci-interpreter/src/kernels/Equal.cpp
compiler/luci-interpreter/src/kernels/Exp.cpp
compiler/luci-interpreter/src/kernels/ExpandDims.cpp
compiler/luci-interpreter/src/kernels/Fill.cpp
compiler/luci-interpreter/src/kernels/Floor.cpp
compiler/luci-interpreter/src/kernels/FloorDiv.cpp
compiler/luci-interpreter/src/kernels/FloorMod.cpp
compiler/luci-interpreter/src/kernels/FullyConnected.cpp
compiler/luci-interpreter/src/kernels/FullyConnected.h
compiler/luci-interpreter/src/kernels/FullyConnected.test.cpp
compiler/luci-interpreter/src/kernels/Gather.cpp
compiler/luci-interpreter/src/kernels/Gelu.cpp
compiler/luci-interpreter/src/kernels/Greater.cpp
compiler/luci-interpreter/src/kernels/GreaterEqual.cpp
compiler/luci-interpreter/src/kernels/HardSwish.cpp
compiler/luci-interpreter/src/kernels/InstanceNorm.cpp
compiler/luci-interpreter/src/kernels/L2Normalize.cpp
compiler/luci-interpreter/src/kernels/L2Pool2D.cpp
compiler/luci-interpreter/src/kernels/LeakyRelu.cpp
compiler/luci-interpreter/src/kernels/Less.cpp
compiler/luci-interpreter/src/kernels/LessEqual.cpp
compiler/luci-interpreter/src/kernels/LocalResponseNormalization.cpp
compiler/luci-interpreter/src/kernels/Log.cpp
compiler/luci-interpreter/src/kernels/LogSoftmax.cpp
compiler/luci-interpreter/src/kernels/LogicalAnd.cpp
compiler/luci-interpreter/src/kernels/LogicalNot.cpp
compiler/luci-interpreter/src/kernels/Logistic.cpp
compiler/luci-interpreter/src/kernels/MaxPool2D.cpp
compiler/luci-interpreter/src/kernels/Maximum.cpp
compiler/luci-interpreter/src/kernels/Mean.cpp
compiler/luci-interpreter/src/kernels/Minimum.cpp
compiler/luci-interpreter/src/kernels/MirrorPad.cpp
compiler/luci-interpreter/src/kernels/Mul.cpp
compiler/luci-interpreter/src/kernels/Neg.cpp
compiler/luci-interpreter/src/kernels/NotEqual.cpp
compiler/luci-interpreter/src/kernels/NotEqual.h
compiler/luci-interpreter/src/kernels/NotEqual.test.cpp
compiler/luci-interpreter/src/kernels/PRelu.cpp
compiler/luci-interpreter/src/kernels/Pack.cpp
compiler/luci-interpreter/src/kernels/Pad.cpp
compiler/luci-interpreter/src/kernels/PadV2.cpp
compiler/luci-interpreter/src/kernels/Pow.cpp
compiler/luci-interpreter/src/kernels/Quantize.cpp
compiler/luci-interpreter/src/kernels/ReduceMax.cpp
compiler/luci-interpreter/src/kernels/ReduceMax.h
compiler/luci-interpreter/src/kernels/ReduceMax.test.cpp
compiler/luci-interpreter/src/kernels/ReduceProd.cpp
compiler/luci-interpreter/src/kernels/Relu.cpp
compiler/luci-interpreter/src/kernels/Relu0To1.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Relu0To1.h [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Relu0To1.test.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Relu6.cpp
compiler/luci-interpreter/src/kernels/ResizeBilinear.cpp
compiler/luci-interpreter/src/kernels/ResizeNearestNeighbor.cpp
compiler/luci-interpreter/src/kernels/Rsqrt.cpp
compiler/luci-interpreter/src/kernels/SVDF.cpp
compiler/luci-interpreter/src/kernels/Select.cpp
compiler/luci-interpreter/src/kernels/Select.h
compiler/luci-interpreter/src/kernels/SelectV2.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/SelectV2.h [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/SelectV2.test.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Shape.cpp
compiler/luci-interpreter/src/kernels/Sin.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Sin.h [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Sin.test.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Slice.cpp
compiler/luci-interpreter/src/kernels/Softmax.cpp
compiler/luci-interpreter/src/kernels/SpaceToBatchND.cpp
compiler/luci-interpreter/src/kernels/SpaceToDepth.cpp
compiler/luci-interpreter/src/kernels/Split.cpp
compiler/luci-interpreter/src/kernels/SplitV.cpp
compiler/luci-interpreter/src/kernels/Sqrt.cpp
compiler/luci-interpreter/src/kernels/Square.cpp
compiler/luci-interpreter/src/kernels/SquaredDifference.cpp
compiler/luci-interpreter/src/kernels/StridedSlice.cpp
compiler/luci-interpreter/src/kernels/Sub.cpp
compiler/luci-interpreter/src/kernels/Sum.cpp
compiler/luci-interpreter/src/kernels/Tanh.cpp
compiler/luci-interpreter/src/kernels/Tile.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Tile.h [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Tile.test.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/kernels/Transpose.cpp
compiler/luci-interpreter/src/kernels/Transpose.test.cpp
compiler/luci-interpreter/src/kernels/TransposeConv.cpp
compiler/luci-interpreter/src/kernels/Unpack.cpp
compiler/luci-interpreter/src/kernels/Utils.cpp
compiler/luci-interpreter/src/loader/GraphLoader.cpp
compiler/luci-interpreter/src/loader/KernelBuilder.test.cpp
compiler/luci-interpreter/src/loader/nodes/BroadcastTo.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/loader/nodes/Cos.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/loader/nodes/CumSum.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/loader/nodes/FullyConnected.cpp
compiler/luci-interpreter/src/loader/nodes/Relu0To1.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/loader/nodes/SelectV2.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/loader/nodes/Sin.cpp [new file with mode: 0644]
compiler/luci-interpreter/src/loader/nodes/Tile.cpp [new file with mode: 0644]
compiler/luci-pass-value-py-test/CMakeLists.txt [new file with mode: 0644]
compiler/luci-pass-value-py-test/README.md [new file with mode: 0644]
compiler/luci-pass-value-py-test/conftest.py [new file with mode: 0644]
compiler/luci-pass-value-py-test/requires.cmake [new file with mode: 0644]
compiler/luci-pass-value-py-test/test.lst [new file with mode: 0644]
compiler/luci-pass-value-py-test/test_luci_eval.py [new file with mode: 0644]
compiler/luci-pass-value-test/exclude.me [new file with mode: 0644]
compiler/luci-pass-value-test/test.lst
compiler/luci-ref-value-py-test/CMakeLists.txt [new file with mode: 0644]
compiler/luci-ref-value-py-test/README.md [new file with mode: 0644]
compiler/luci-ref-value-py-test/conftest.py [new file with mode: 0644]
compiler/luci-ref-value-py-test/requires.cmake [new file with mode: 0644]
compiler/luci-ref-value-py-test/test.lst [new file with mode: 0644]
compiler/luci-ref-value-py-test/test_luci_eval.py [new file with mode: 0644]
compiler/luci-value-py-test/CMakeLists.txt [new file with mode: 0644]
compiler/luci-value-py-test/README.md [new file with mode: 0644]
compiler/luci-value-py-test/conftest.py [new file with mode: 0644]
compiler/luci-value-py-test/requires.cmake [new file with mode: 0644]
compiler/luci-value-py-test/test.lst [new file with mode: 0644]
compiler/luci-value-py-test/test_luci_eval.py [new file with mode: 0644]
compiler/luci-value-py-test/test_luci_eval_ref.py [new file with mode: 0644]
compiler/luci-value-test/exclude.me [new file with mode: 0644]
compiler/luci-value-test/test.lst
compiler/luci/export/CMakeLists.txt
compiler/luci/export/src/CircleBuiltinTypesExtractor.h
compiler/luci/export/src/CircleExportMetadata.cpp
compiler/luci/export/src/CircleExporterImpl.cpp
compiler/luci/export/src/CircleExporterUtils.cpp
compiler/luci/export/src/CircleOps.lst
compiler/luci/export/src/CircleTensorExporter.cpp
compiler/luci/import/CMakeLists.txt
compiler/luci/import/include/luci/Import/CircleReader.h
compiler/luci/import/include/luci/Import/Nodes.h
compiler/luci/import/include/luci/Import/Nodes/CircleBroadcastTo.h [new file with mode: 0644]
compiler/luci/import/include/luci/Import/Nodes/CircleCumSum.h [new file with mode: 0644]
compiler/luci/import/include/luci/Import/Nodes/CircleGRU.h [new file with mode: 0644]
compiler/luci/import/include/luci/Import/Nodes/CircleRelu0To1.h [new file with mode: 0644]
compiler/luci/import/src/CircleImportMetadata.cpp
compiler/luci/import/src/CircleReader.cpp
compiler/luci/import/src/GraphBuilderRegistry.cpp
compiler/luci/import/src/Importer.test.cpp
compiler/luci/import/src/Nodes/CircleBroadcastTo.cpp [new file with mode: 0644]
compiler/luci/import/src/Nodes/CircleConst.cpp
compiler/luci/import/src/Nodes/CircleCumSum.cpp [new file with mode: 0644]
compiler/luci/import/src/Nodes/CircleGRU.cpp [new file with mode: 0644]
compiler/luci/import/src/Nodes/CircleRelu0To1.cpp [new file with mode: 0644]
compiler/luci/import/src/ValidateHelpers.cpp
compiler/luci/lang/include/luci/IR/CircleNodes.h
compiler/luci/lang/include/luci/IR/CircleNodes.lst
compiler/luci/lang/include/luci/IR/DataTypeHelper.h [new file with mode: 0644]
compiler/luci/lang/include/luci/IR/Nodes/CircleBroadcastTo.h [new file with mode: 0644]
compiler/luci/lang/include/luci/IR/Nodes/CircleCumSum.h [new file with mode: 0644]
compiler/luci/lang/include/luci/IR/Nodes/CircleGRU.h [new file with mode: 0644]
compiler/luci/lang/include/luci/IR/Nodes/CircleRelu0To1.h [new file with mode: 0644]
compiler/luci/lang/include/luci/IR/SparsityParam.h
compiler/luci/lang/src/DataTypeHelper.cpp [new file with mode: 0644]
compiler/luci/lang/src/Nodes/CircleBroadcastTo.test.cpp [new file with mode: 0644]
compiler/luci/lang/src/Nodes/CircleConst.cpp
compiler/luci/lang/src/Nodes/CircleCumSum.test.cpp [new file with mode: 0644]
compiler/luci/lang/src/Nodes/CircleGRU.test.cpp [new file with mode: 0644]
compiler/luci/lang/src/Nodes/CircleRelu0To1.test.cpp [new file with mode: 0644]
compiler/luci/logex/src/CircleNodeSummaryBuilder.cpp
compiler/luci/logex/src/CircleNodeSummaryBuilders.cpp
compiler/luci/logex/src/CircleNodeSummaryBuilders.h
compiler/luci/partition/CMakeLists.txt
compiler/luci/partition/include/luci/ConnectNode.h
compiler/luci/partition/src/Nodes/CircleBroadcastTo.cpp [new file with mode: 0644]
compiler/luci/partition/src/Nodes/CircleBroadcastTo.test.cpp [new file with mode: 0644]
compiler/luci/partition/src/Nodes/CircleCumSum.cpp [new file with mode: 0644]
compiler/luci/partition/src/Nodes/CircleCumSum.test.cpp [new file with mode: 0644]
compiler/luci/partition/src/Nodes/CircleGRU.cpp [new file with mode: 0644]
compiler/luci/partition/src/Nodes/CircleGRU.test.cpp [new file with mode: 0644]
compiler/luci/partition/src/Nodes/CircleRelu0To1.cpp [new file with mode: 0644]
compiler/luci/partition/src/Nodes/CircleRelu0To1.test.cpp [new file with mode: 0644]
compiler/luci/partition/src/PartitionIRDump.cpp
compiler/luci/pass/CMakeLists.txt
compiler/luci/pass/include/luci/CircleOptimizer.h
compiler/luci/pass/include/luci/CircleQuantizer.h
compiler/luci/pass/include/luci/Pass/CommonSubExpressionEliminationPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/DecomposeSoftmaxPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FoldMulPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FoldReshapePass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FoldShapePass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FoldSqueezePass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FuseAddToFullyConnectedBiasPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FuseAddWithConvPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FuseHorizontalFullyConnectedPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FuseMulToFullyConnectedWeightsPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FuseMulWithConvPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FuseMulWithDivPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FuseRsqrtPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/FuseSliceWithTConvPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/QuantizeOnnxFakeQuantModelPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/QuantizeWithMinMaxPass.h
compiler/luci/pass/include/luci/Pass/RemoveGatherGuardPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/RemoveQDQForMixedPrecisionOpPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryAddPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryTransposeNetPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/ReplaceWithFCGeluFCPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/ResolveFormerCustomOpPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/TransformSqrtDivToRsqrtMulPass.h [new file with mode: 0644]
compiler/luci/pass/include/luci/Pass/XpSepActFromTransposeConvPass.h [new file with mode: 0644]
compiler/luci/pass/src/CircleOptimizer.cpp
compiler/luci/pass/src/CircleOptimizerUtils.cpp [deleted file]
compiler/luci/pass/src/CircleOptimizerUtils.h [deleted file]
compiler/luci/pass/src/CircleQuantizer.cpp
compiler/luci/pass/src/CircleQuantizer.test.cpp
compiler/luci/pass/src/CircleShapeInferencePass.cpp
compiler/luci/pass/src/CommonSubExpressionEliminationPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/CommonSubExpressionEliminationPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/ConvertNCHWToNHWCPass.cpp
compiler/luci/pass/src/ConvertToFakeQuantizedModelPass.cpp
compiler/luci/pass/src/CopyQuantParamPass.cpp
compiler/luci/pass/src/DecomposeHardSwishPass.cpp
compiler/luci/pass/src/DecomposeSoftmaxPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/DecomposeSoftmaxPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FoldAddV2Pass.cpp
compiler/luci/pass/src/FoldCastPass.cpp
compiler/luci/pass/src/FoldDepthwiseConv2DPass.cpp
compiler/luci/pass/src/FoldDepthwiseConv2DPass.test.cpp
compiler/luci/pass/src/FoldDequantizePass.cpp
compiler/luci/pass/src/FoldDequantizePass.test.cpp
compiler/luci/pass/src/FoldFullyConnectedPass.cpp
compiler/luci/pass/src/FoldFullyConnectedPass.test.cpp
compiler/luci/pass/src/FoldGatherPass.cpp
compiler/luci/pass/src/FoldMulPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FoldMulPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FoldReshapePass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FoldReshapePass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FoldShapePass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FoldShapePass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FoldSparseToDensePass.cpp
compiler/luci/pass/src/FoldSqueezePass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FoldSqueezePass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.cpp
compiler/luci/pass/src/ForwardReshapeToUnaryOpPass.test.cpp
compiler/luci/pass/src/ForwardTransposeOpPass.cpp
compiler/luci/pass/src/FuseAddToFullyConnectedBiasPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseAddToFullyConnectedBiasPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseAddWithConvPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseAddWithConvPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseAddWithFullyConnectedPass.cpp
compiler/luci/pass/src/FuseAddWithFullyConnectedPass.test.cpp
compiler/luci/pass/src/FuseHorizontalFullyConnectedPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseHorizontalFullyConnectedPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseMulToFullyConnectedWeightsPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseMulToFullyConnectedWeightsPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseMulWithConvPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseMulWithConvPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseMulWithDivPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseMulWithDivPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseRsqrtPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseRsqrtPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseSliceWithTConvPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/FuseSliceWithTConvPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/InsertQuantizeOpOnDTypeMismatch.cpp [new file with mode: 0644]
compiler/luci/pass/src/InsertQuantizeOpOnDTypeMismatch.h [new file with mode: 0644]
compiler/luci/pass/src/InsertQuantizeOpOnDTypeMismatch.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/PassTestGraphs.h
compiler/luci/pass/src/PropagateQParamForwardPass.cpp
compiler/luci/pass/src/QuantizationUtils.cpp
compiler/luci/pass/src/QuantizationUtils.h
compiler/luci/pass/src/QuantizeActivation.cpp
compiler/luci/pass/src/QuantizeActivation.h
compiler/luci/pass/src/QuantizeOnnxDequantizeLinearPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/QuantizeOnnxDequantizeLinearPass.h [new file with mode: 0644]
compiler/luci/pass/src/QuantizeOnnxDequantizeLinearPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/QuantizeOnnxFakeQuantModelPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/QuantizeOnnxFakeQuantModelPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/QuantizeOnnxQDQPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/QuantizeOnnxQDQPass.h [new file with mode: 0644]
compiler/luci/pass/src/QuantizeOnnxQDQPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/QuantizeWeights.cpp
compiler/luci/pass/src/QuantizeWeightsOnly.cpp
compiler/luci/pass/src/QuantizeWeightsOnly.h
compiler/luci/pass/src/QuantizeWithMinMaxPass.cpp
compiler/luci/pass/src/QuantizeWithMinMaxPass.test.cpp
compiler/luci/pass/src/QuantizeWithPredecessorPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/QuantizeWithPredecessorPass.h [new file with mode: 0644]
compiler/luci/pass/src/QuantizeWithPredecessorPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/RemoveDuplicateConstPass.cpp
compiler/luci/pass/src/RemoveGatherGuardPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/RemoveGatherGuardPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/RemoveQDQForMixedPrecisionOpPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/RemoveQDQForMixedPrecisionOpPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/RemoveUnnecessaryAddPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/RemoveUnnecessaryAddPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/RemoveUnnecessaryTransposeNetPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/RemoveUnnecessaryTransposeNetPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/ReplaceNonConstFCWithBatchMatMulPass.cpp
compiler/luci/pass/src/ReplaceWithFCGeluFCPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/ReplaceWithFCGeluFCPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/RequantizePass.cpp
compiler/luci/pass/src/ResolveCustomOpAddPass.cpp
compiler/luci/pass/src/ResolveCustomOpAddPass.test.cpp
compiler/luci/pass/src/ResolveFormerCustomOpPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/ResolveFormerCustomOpPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/SubstitutePadV2ToPadPass.cpp
compiler/luci/pass/src/SubstituteSqueezeToReshapePass.cpp
compiler/luci/pass/src/TransformMinMaxToRelu6Pass.cpp
compiler/luci/pass/src/TransformMinReluToRelu6Pass.cpp
compiler/luci/pass/src/TransformSqrtDivToRsqrtMulPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/TransformSqrtDivToRsqrtMulPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/UnrollUnidirectionalSequenceLSTMPass.cpp
compiler/luci/pass/src/XpSepActFromTransposeConvPass.cpp [new file with mode: 0644]
compiler/luci/pass/src/XpSepActFromTransposeConvPass.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/helpers/Compute.cpp [new file with mode: 0644]
compiler/luci/pass/src/helpers/Compute.h [new file with mode: 0644]
compiler/luci/pass/src/helpers/ExpressionCache.cpp [new file with mode: 0644]
compiler/luci/pass/src/helpers/ExpressionCache.h [new file with mode: 0644]
compiler/luci/pass/src/helpers/ExpressionCache.test.cpp [new file with mode: 0644]
compiler/luci/pass/src/helpers/LayerInfoMap.cpp
compiler/luci/pass/src/helpers/Shape.cpp [new file with mode: 0644]
compiler/luci/pass/src/helpers/Shape.h [new file with mode: 0644]
compiler/luci/pass/src/helpers/SparsityFormatConverter.cpp
compiler/luci/pass/src/helpers/Strings.cpp
compiler/luci/pass/src/helpers/Strings.test.cpp
compiler/luci/requires.cmake
compiler/luci/service/include/luci/Service/CircleShapeInference.h
compiler/luci/service/include/luci/Service/CircleTypeInference.h
compiler/luci/service/src/ChangeOutputs.cpp
compiler/luci/service/src/CircleCloneNode.h
compiler/luci/service/src/CircleShapeInferenceRule.cpp
compiler/luci/service/src/CircleTypeInferenceRule.cpp
compiler/luci/service/src/Nodes/CircleBroadcastTo.cpp [new file with mode: 0644]
compiler/luci/service/src/Nodes/CircleBroadcastTo.test.cpp [new file with mode: 0644]
compiler/luci/service/src/Nodes/CircleConst.cpp
compiler/luci/service/src/Nodes/CircleConst.test.cpp
compiler/luci/service/src/Nodes/CircleCumSum.cpp [new file with mode: 0644]
compiler/luci/service/src/Nodes/CircleCumSum.test.cpp [new file with mode: 0644]
compiler/luci/service/src/Nodes/CircleGRU.cpp [new file with mode: 0644]
compiler/luci/service/src/Nodes/CircleGRU.test.cpp [new file with mode: 0644]
compiler/luci/service/src/Nodes/CircleRelu0To1.cpp [new file with mode: 0644]
compiler/luci/service/src/Nodes/CircleRelu0To1.test.cpp [new file with mode: 0644]
compiler/luci/service/src/ShapeInfer_StridedSlice.cpp
compiler/luci/tests/test.lst
compiler/minmax-embedder-value-test/CMakeLists.txt [new file with mode: 0644]
compiler/minmax-embedder-value-test/README.md [new file with mode: 0644]
compiler/minmax-embedder-value-test/gen/CMakeLists.txt [new file with mode: 0644]
compiler/minmax-embedder-value-test/gen/src/Cast.h [new file with mode: 0644]
compiler/minmax-embedder-value-test/gen/src/DataGen.cpp [new file with mode: 0644]
compiler/minmax-embedder-value-test/gen/src/DataGen.h [new file with mode: 0644]
compiler/minmax-embedder-value-test/gen/src/Driver.cpp [new file with mode: 0644]
compiler/minmax-embedder-value-test/gen/src/H5Writer.cpp [new file with mode: 0644]
compiler/minmax-embedder-value-test/gen/src/H5Writer.h [new file with mode: 0644]
compiler/minmax-embedder-value-test/gen/src/ModelSpec.h [new file with mode: 0644]
compiler/minmax-embedder-value-test/requires.cmake [new file with mode: 0644]
compiler/minmax-embedder-value-test/test.lst [new file with mode: 0644]
compiler/minmax-embedder-value-test/testall.sh [new file with mode: 0755]
compiler/minmax-embedder/CMakeLists.txt [new file with mode: 0644]
compiler/minmax-embedder/README.md [new file with mode: 0644]
compiler/minmax-embedder/driver/Driver.cpp [new file with mode: 0644]
compiler/minmax-embedder/include/minmax-embedder/Embedder.h [new file with mode: 0644]
compiler/minmax-embedder/requires.cmake [new file with mode: 0644]
compiler/minmax-embedder/src/Embedder.cpp [new file with mode: 0644]
compiler/minmax-embedder/src/Embedder.test.cpp [new file with mode: 0644]
compiler/minmax-embedder/src/h5/Reader.cpp [new file with mode: 0644]
compiler/minmax-embedder/src/h5/Reader.h [new file with mode: 0644]
compiler/mio-circle/CMakeLists.txt
compiler/mio-circle/exclude.me [new file with mode: 0644]
compiler/mio-circle04/CMakeLists.txt
compiler/mio-circle04/exclude.me [new file with mode: 0644]
compiler/mio-circle05/CMakeLists.txt
compiler/mio-circle05/exclude.me [new file with mode: 0644]
compiler/mio-circle06/CMakeLists.txt
compiler/mio-circle06/exclude.me [new file with mode: 0644]
compiler/mio-circle07/CMakeLists.txt [new file with mode: 0644]
compiler/mio-circle07/README.md [new file with mode: 0644]
compiler/mio-circle07/example.cpp [new file with mode: 0644]
compiler/mio-circle07/exclude.me [new file with mode: 0644]
compiler/mio-circle07/include/mio_circle/Helper.h [new file with mode: 0644]
compiler/mio-circle07/include/mio_circle/Reader.h [new file with mode: 0644]
compiler/mio-circle07/src/Helper.cpp [new file with mode: 0644]
compiler/mio-circle07/src/Helper.test.cpp [new file with mode: 0644]
compiler/mio-circle07/src/Reader.cpp [new file with mode: 0644]
compiler/mio-circle07/src/Reader.test.cpp [new file with mode: 0644]
compiler/mio-circle08/CMakeLists.txt [new file with mode: 0644]
compiler/mio-circle08/README.md [new file with mode: 0644]
compiler/mio-circle08/example.cpp [new file with mode: 0644]
compiler/mio-circle08/include/mio_circle/Helper.h [new file with mode: 0644]
compiler/mio-circle08/include/mio_circle/Reader.h [new file with mode: 0644]
compiler/mio-circle08/src/Helper.cpp [new file with mode: 0644]
compiler/mio-circle08/src/Helper.test.cpp [new file with mode: 0644]
compiler/mio-circle08/src/Reader.cpp [new file with mode: 0644]
compiler/mio-circle08/src/Reader.test.cpp [new file with mode: 0644]
compiler/mio-tf/exclude.me [new file with mode: 0644]
compiler/mio-tflite/CMakeLists.txt
compiler/mio-tflite/exclude.me [new file with mode: 0644]
compiler/mio-tflite2121/CMakeLists.txt
compiler/mio-tflite260/CMakeLists.txt
compiler/mio-tflite260/exclude.me [new file with mode: 0644]
compiler/mio-tflite280/CMakeLists.txt
compiler/mio-tflite280/exclude.me [new file with mode: 0644]
compiler/mir-interpreter/exclude.me [new file with mode: 0644]
compiler/mir-interpreter/src/ops/Common.h
compiler/mir/exclude.me [new file with mode: 0644]
compiler/mir/include/mir/Graph.h
compiler/mir/src/mir_caffe2_importer/caffe2_op_creator.h
compiler/mir/src/mir_caffe_importer/caffe_op_creator.h
compiler/mir/src/mir_onnx_importer/CMakeLists.txt
compiler/mir/src/mir_onnx_importer/ONNXHelpers.h
compiler/mir/src/mir_tflite_importer/CMakeLists.txt
compiler/mir/src/mir_tflite_importer/tflite_op_creator.h
compiler/mir/unittests/ShapeRange.cpp
compiler/mir2loco/exclude.me [new file with mode: 0644]
compiler/moco-log/exclude.me [new file with mode: 0644]
compiler/moco-tf/exclude.me [new file with mode: 0644]
compiler/moco-value-pbtxt-test/exclude.me [new file with mode: 0644]
compiler/moco/exclude.me [new file with mode: 0644]
compiler/nest/core/include/nest/Closure.h
compiler/nest/core/include/nest/Domain.h
compiler/nest/core/include/nest/expr/DerefNode.h
compiler/nest/exclude.me [new file with mode: 0644]
compiler/nike/exclude.me [new file with mode: 0644]
compiler/nnc/backends/acl_soft_backend/AclCppGenerator.cpp
compiler/nnc/backends/acl_soft_backend/CMakeLists.txt
compiler/nnc/backends/soft_backend/CMakeLists.txt
compiler/nnc/backends/soft_backend/CPPGenerator.cpp
compiler/nnc/exclude.me [new file with mode: 0644]
compiler/nnc/unittests/soft_backend/CPPOperations.cpp
compiler/nnkit-caffe/exclude.me [new file with mode: 0644]
compiler/nnkit-intf/exclude.me [new file with mode: 0644]
compiler/nnkit-misc/exclude.me [new file with mode: 0644]
compiler/nnkit-mocotf/exclude.me [new file with mode: 0644]
compiler/nnkit-onnxrt/exclude.me [new file with mode: 0644]
compiler/nnkit-tf/exclude.me [new file with mode: 0644]
compiler/nnkit-tflite/exclude.me [new file with mode: 0644]
compiler/nnkit/exclude.me [new file with mode: 0644]
compiler/nnop/exclude.me [new file with mode: 0644]
compiler/nnsuite/conv/nnkit-caffe/ConvBackend.test.cpp
compiler/nnsuite/conv/nnkit-tflite/ConvBackend.test.cpp
compiler/nnsuite/exclude.me [new file with mode: 0644]
compiler/one-cmds/CMakeLists.txt
compiler/one-cmds/dummy-driver/CMakeLists.txt
compiler/one-cmds/dummy-driver/src/dummy-compile.cpp
compiler/one-cmds/dummy-driver/src/dummy-compiler.cpp [new file with mode: 0644]
compiler/one-cmds/dummy-driver/src/dummy-profile.cpp
compiler/one-cmds/how-to-use-one-commands.txt
compiler/one-cmds/one-build
compiler/one-cmds/one-codegen
compiler/one-cmds/one-create-quant-dataset [new file with mode: 0644]
compiler/one-cmds/one-import-onnx
compiler/one-cmds/one-init
compiler/one-cmds/one-prepare-venv
compiler/one-cmds/one-prepare-venv.aarch64
compiler/one-cmds/one-prepare-venv.u1804
compiler/one-cmds/one-profile
compiler/one-cmds/one-quantize
compiler/one-cmds/onecc
compiler/one-cmds/onecc.template.cfg
compiler/one-cmds/onelib/CfgRunner.py
compiler/one-cmds/onelib/argumentparse.py [new file with mode: 0644]
compiler/one-cmds/onelib/backends.py
compiler/one-cmds/onelib/constant.py
compiler/one-cmds/onelib/utils.py
compiler/one-cmds/tests/CMakeLists.txt
compiler/one-cmds/tests/OONE-BUILD_014.cfg [deleted file]
compiler/one-cmds/tests/one-build_001.cfg [deleted file]
compiler/one-cmds/tests/one-build_001.test [deleted file]
compiler/one-cmds/tests/one-build_002.cfg [deleted file]
compiler/one-cmds/tests/one-build_002.test [deleted file]
compiler/one-cmds/tests/one-build_003.cfg [deleted file]
compiler/one-cmds/tests/one-build_003.test [deleted file]
compiler/one-cmds/tests/one-build_004.cfg [deleted file]
compiler/one-cmds/tests/one-build_004.test [deleted file]
compiler/one-cmds/tests/one-build_005.cfg [deleted file]
compiler/one-cmds/tests/one-build_005.test [deleted file]
compiler/one-cmds/tests/one-build_006.cfg [deleted file]
compiler/one-cmds/tests/one-build_006.test [deleted file]
compiler/one-cmds/tests/one-build_007.cfg [deleted file]
compiler/one-cmds/tests/one-build_007.test [deleted file]
compiler/one-cmds/tests/one-build_008.cfg [deleted file]
compiler/one-cmds/tests/one-build_008.test [deleted file]
compiler/one-cmds/tests/one-build_009.cfg [deleted file]
compiler/one-cmds/tests/one-build_009.test [deleted file]
compiler/one-cmds/tests/one-build_010.cfg [deleted file]
compiler/one-cmds/tests/one-build_010.test [deleted file]
compiler/one-cmds/tests/one-build_011.cfg [deleted file]
compiler/one-cmds/tests/one-build_011.test [deleted file]
compiler/one-cmds/tests/one-build_012.cfg [deleted file]
compiler/one-cmds/tests/one-build_012.test [deleted file]
compiler/one-cmds/tests/one-build_013.cfg [deleted file]
compiler/one-cmds/tests/one-build_013.test [deleted file]
compiler/one-cmds/tests/one-build_014.cfg [deleted file]
compiler/one-cmds/tests/one-build_014.test [deleted file]
compiler/one-cmds/tests/one-build_neg_001.test [deleted file]
compiler/one-cmds/tests/one-build_neg_002.cfg [deleted file]
compiler/one-cmds/tests/one-build_neg_002.test [deleted file]
compiler/one-cmds/tests/one-build_neg_003.cfg [deleted file]
compiler/one-cmds/tests/one-build_neg_003.test [deleted file]
compiler/one-cmds/tests/one-build_neg_004.cfg [deleted file]
compiler/one-cmds/tests/one-build_neg_004.test [deleted file]
compiler/one-cmds/tests/one-build_neg_005.cfg [deleted file]
compiler/one-cmds/tests/one-build_neg_005.test [deleted file]
compiler/one-cmds/tests/one-build_neg_006.cfg [deleted file]
compiler/one-cmds/tests/one-build_neg_006.test [deleted file]
compiler/one-cmds/tests/one-build_neg_007.test [deleted file]
compiler/one-cmds/tests/one-build_neg_008.test [deleted file]
compiler/one-cmds/tests/one-build_neg_009.test [deleted file]
compiler/one-cmds/tests/one-codegen_005.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_005.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_005.test [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_006.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_006.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_006.test [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_007.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_007.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_007.test [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_008.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_008.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_008.py [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_008.test [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_009.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_009.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_009.py [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_009.test [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_010.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_010.test [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_011.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_011.test [new file with mode: 0644]
compiler/one-cmds/tests/one-codegen_neg_001.test
compiler/one-cmds/tests/one-codegen_neg_002.test
compiler/one-cmds/tests/one-codegen_neg_003.test
compiler/one-cmds/tests/one-create-quant-dataset_001.test [new file with mode: 0644]
compiler/one-cmds/tests/one-create-quant-dataset_002.test [new file with mode: 0644]
compiler/one-cmds/tests/one-create-quant-dataset_neg_001.test [new file with mode: 0644]
compiler/one-cmds/tests/one-create-quant-dataset_neg_002.test [new file with mode: 0644]
compiler/one-cmds/tests/one-create-quant-dataset_neg_003.test [new file with mode: 0644]
compiler/one-cmds/tests/one-create-quant-dataset_neg_004.test [new file with mode: 0644]
compiler/one-cmds/tests/one-create-quant-dataset_neg_005.test [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_005.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_005.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_005.test [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_006.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_006.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_006.test [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_007.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_007.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_007.test [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_008.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_008.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_008.py [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_008.test [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_009.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_009.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_009.py [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_009.test [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_010.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_010.test [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_011.ini [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_011.test [new file with mode: 0644]
compiler/one-cmds/tests/one-profile_neg_001.test
compiler/one-cmds/tests/one-profile_neg_002.test
compiler/one-cmds/tests/one-profile_neg_003.test
compiler/one-cmds/tests/one-quantize_022.cfg [new file with mode: 0644]
compiler/one-cmds/tests/one-quantize_022.qconf.json [new file with mode: 0644]
compiler/one-cmds/tests/one-quantize_022.test [new file with mode: 0644]
compiler/one-cmds/tests/one-quantize_023.test [new file with mode: 0644]
compiler/one-cmds/tests/one-quantize_024.test [new file with mode: 0644]
compiler/one-cmds/tests/one-quantize_neg_024.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_059.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_059.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_060.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_060.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_060.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_061.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_061.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_061.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_062.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_062.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_062.py [new file with mode: 0644]
compiler/one-cmds/tests/onecc_062.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_063.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_063.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_063.py [new file with mode: 0644]
compiler/one-cmds/tests/onecc_063.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_064.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_064.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_064.py [new file with mode: 0644]
compiler/one-cmds/tests/onecc_064.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_065.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_065.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_065.py [new file with mode: 0644]
compiler/one-cmds/tests/onecc_065.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_066.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_066.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_066.py [new file with mode: 0644]
compiler/one-cmds/tests/onecc_066.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_067.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_067.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_067.py [new file with mode: 0644]
compiler/one-cmds/tests/onecc_067.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_068.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_068.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_068.py [new file with mode: 0644]
compiler/one-cmds/tests/onecc_068.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_069.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_069.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_069.py [new file with mode: 0644]
compiler/one-cmds/tests/onecc_069.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_neg_037.test [new file with mode: 0644]
compiler/one-cmds/tests/onecc_neg_038.cfg [new file with mode: 0644]
compiler/one-cmds/tests/onecc_neg_038.ini [new file with mode: 0644]
compiler/one-cmds/tests/onecc_neg_038.py [new file with mode: 0644]
compiler/one-cmds/tests/onecc_neg_038.test [new file with mode: 0644]
compiler/one-cmds/tests/onnx_legalize_run_compare.py
compiler/one-cmds/tests/prepare_test_materials.sh
compiler/one-cmds/tests/preprocess_images.py
compiler/one-cmds/tests/preprocess_images_numpy.py [new file with mode: 0644]
compiler/one-cmds/tests/rawdata2hdf5_002.test [new file with mode: 0644]
compiler/one-cmds/tests/rawdata2hdf5_neg_004.test
compiler/one-cmds/validate-onnx2circle/validate_onnx2circle.py
compiler/onecc-docker/README.md
compiler/onecc-docker/debian/control
compiler/onecc-docker/docker/Dockerfile
compiler/onecc-docker/onecc-docker
compiler/oneco-value-pbtxt-test/exclude.me [new file with mode: 0644]
compiler/oneco/exclude.me [new file with mode: 0644]
compiler/onnx2circle/exclude.me [new file with mode: 0644]
compiler/onnx2tflite-integration-test/exclude.me [new file with mode: 0644]
compiler/onnx2tflite/exclude.me [new file with mode: 0644]
compiler/onnxkit/exclude.me [new file with mode: 0644]
compiler/oops/include/oops/UserExn.h
compiler/pepper-assert/exclude.me [new file with mode: 0644]
compiler/pepper-env/exclude.me [new file with mode: 0644]
compiler/pepper-str/include/pepper/str.h
compiler/pics/CMakeLists.txt
compiler/pics/requires.cmake
compiler/plier-tf/exclude.me [new file with mode: 0644]
compiler/pota-quantization-value-test/CMakeLists.txt
compiler/pota-quantization-value-test/compare_tensors.py [deleted file]
compiler/pota-quantization-value-test/compare_tensors_all.py [new file with mode: 0644]
compiler/pota-quantization-value-test/gen_h5_explicit_inputs.py [deleted file]
compiler/pota-quantization-value-test/gen_h5_explicit_inputs_all.py [new file with mode: 0644]
compiler/pota-quantization-value-test/test_fake_wquant.sh
compiler/pota-quantization-value-test/test_fake_wquant_with_config.sh
compiler/pota-quantization-value-test/test_parallel_record_minmax.sh
compiler/pota-quantization-value-test/test_quantization.sh
compiler/pota-quantization-value-test/test_quantization_with_config.sh
compiler/pota-quantization-value-test/test_record_minmax.sh
compiler/pota-quantization-value-test/test_wo_quantization.sh
compiler/pp/include/pp/Format.h
compiler/pp/include/pp/IndentedStringBuilder.h
compiler/pp/include/pp/LinearDocument.h
compiler/q-implant-qparam-test/CMakeLists.txt [new file with mode: 0644]
compiler/q-implant-qparam-test/README.md [new file with mode: 0644]
compiler/q-implant-qparam-test/q_implant_qparam_test.py [new file with mode: 0644]
compiler/q-implant-qparam-test/q_implant_qparam_test.sh [new file with mode: 0755]
compiler/q-implant-qparam-test/q_implant_validator.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Add_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Add_001/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Add_002/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/AveragePool2D_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Concatenation_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Conv2D_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Conv2D_001/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Conv2D_002/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Conv2D_003/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Conv2D_004/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Conv2D_005/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_001/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_002/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_003/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/MaxPool2D_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Mean_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Mul_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Mul_001/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Pad_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Reshape_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/qparam/Softmax_000/__init__.py [new file with mode: 0644]
compiler/q-implant-qparam-test/requires.cmake [new file with mode: 0644]
compiler/q-implant-qparam-test/test.lst [new file with mode: 0644]
compiler/q-implant-qparam-test/test_utils.py [new file with mode: 0644]
compiler/q-implant/CMakeLists.txt [new file with mode: 0644]
compiler/q-implant/README.md [new file with mode: 0644]
compiler/q-implant/driver/Driver.cpp [new file with mode: 0644]
compiler/q-implant/include/QImplant.h [new file with mode: 0644]
compiler/q-implant/requires.cmake [new file with mode: 0644]
compiler/q-implant/src/QImplant.cpp [new file with mode: 0644]
compiler/rawdata2hdf5/rawdata2hdf5
compiler/record-minmax-conversion-test/gen_h5_random_inputs.py [deleted file]
compiler/record-minmax-conversion-test/gen_h5_random_inputs_all.py [new file with mode: 0644]
compiler/record-minmax-conversion-test/testall.sh
compiler/record-minmax/src/RecordMinMax.cpp
compiler/souschef/include/souschef/Data/Constant.h
compiler/souschef/include/souschef/Data/Explicit.h
compiler/souschef/include/souschef/TensorFiller.h
compiler/souschef/src/Explicit.cpp
compiler/tf2circle-conversion-test/exclude.me [new file with mode: 0644]
compiler/tf2circle-dredd-pb-test/exclude.me [new file with mode: 0644]
compiler/tf2circle-dredd-pbtxt-test/exclude.me [new file with mode: 0644]
compiler/tf2circle-model-test/exclude.me [new file with mode: 0644]
compiler/tf2circle-ui-check/exclude.me [new file with mode: 0644]
compiler/tf2circle-value-pbtxt-remote-test/exclude.me [new file with mode: 0644]
compiler/tf2circle/exclude.me [new file with mode: 0644]
compiler/tf2tflite-dredd-pb-test/exclude.me [new file with mode: 0644]
compiler/tf2tflite-dredd-pbtxt-test/exclude.me [new file with mode: 0644]
compiler/tf2tflite-value-pb-test/exclude.me [new file with mode: 0644]
compiler/tf2tflite-value-pbtxt-test/exclude.me [new file with mode: 0644]
compiler/tf2tflite/exclude.me [new file with mode: 0644]
compiler/tfinfo-v2/exclude.me [new file with mode: 0644]
compiler/tfkit/exclude.me [new file with mode: 0644]
compiler/tfl-inspect/src/Dump.cpp
compiler/tfl-inspect/src/Reader.cpp
compiler/tfl-inspect/src/Reader.h
compiler/tflchef/core/src/Convert.cpp
compiler/tflchef/core/src/CustomOp/AddV2.cpp
compiler/tflchef/core/src/CustomOp/All.cpp
compiler/tflchef/core/src/CustomOp/BatchMatMulV2.cpp
compiler/tflchef/core/src/CustomOp/BroadcastTo.cpp
compiler/tflchef/core/src/CustomOp/Erf.cpp
compiler/tflchef/core/src/CustomOp/MatMul.cpp
compiler/tflchef/core/src/CustomOp/MatrixBandPart.cpp
compiler/tflchef/core/src/CustomOp/MaxPoolWithArgmax.cpp
compiler/tflchef/core/src/DataChef.def
compiler/tflchef/core/src/ModelChef.cpp
compiler/tflchef/core/src/Op/BroadcastTo.cpp [new file with mode: 0644]
compiler/tflchef/core/src/Op/BroadcastTo.h [new file with mode: 0644]
compiler/tflchef/core/src/Op/CumSum.cpp [new file with mode: 0644]
compiler/tflchef/core/src/Op/CumSum.h [new file with mode: 0644]
compiler/tflchef/core/src/Op/ReLU0To1.cpp [new file with mode: 0644]
compiler/tflchef/core/src/Op/ReLU0To1.h [new file with mode: 0644]
compiler/tflchef/core/src/OpChef.def
compiler/tflchef/core/src/OpChefs.h
compiler/tflchef/core/src/OpUtils.cpp [new file with mode: 0644]
compiler/tflchef/core/src/OpUtils.h [new file with mode: 0644]
compiler/tflchef/proto/tflchef.proto
compiler/tflchef/requires.cmake
compiler/tflchef/tests/custom_erf/test.recipe
compiler/tflchef/tests/short_int4/test.recipe [new file with mode: 0644]
compiler/tflchef/tests/short_int4_quant/test.recipe [new file with mode: 0644]
compiler/tflchef/tflite/src/Convert.h
compiler/tflchef/tflite/src/Op/Abs.cpp
compiler/tflchef/tflite/src/Op/Add.cpp
compiler/tflchef/tflite/src/Op/AddN.cpp
compiler/tflchef/tflite/src/Op/ArgMax.cpp
compiler/tflchef/tflite/src/Op/ArgMin.cpp
compiler/tflchef/tflite/src/Op/AveragePool2D.cpp
compiler/tflchef/tflite/src/Op/BatchMatMul.cpp
compiler/tflchef/tflite/src/Op/BatchToSpaceND.cpp
compiler/tflchef/tflite/src/Op/BidirectionalSequenceLSTM.cpp
compiler/tflchef/tflite/src/Op/BroadcastTo.cpp [new file with mode: 0644]
compiler/tflchef/tflite/src/Op/Cast.cpp
compiler/tflchef/tflite/src/Op/Ceil.cpp
compiler/tflchef/tflite/src/Op/Concatenation.cpp
compiler/tflchef/tflite/src/Op/Conv2D.cpp
compiler/tflchef/tflite/src/Op/Cos.cpp
compiler/tflchef/tflite/src/Op/CumSum.cpp [new file with mode: 0644]
compiler/tflchef/tflite/src/Op/DepthToSpace.cpp
compiler/tflchef/tflite/src/Op/DepthwiseConv2D.cpp
compiler/tflchef/tflite/src/Op/Dequantize.cpp
compiler/tflchef/tflite/src/Op/Div.cpp
compiler/tflchef/tflite/src/Op/ELU.cpp
compiler/tflchef/tflite/src/Op/Equal.cpp
compiler/tflchef/tflite/src/Op/Exp.cpp
compiler/tflchef/tflite/src/Op/ExpandDims.cpp
compiler/tflchef/tflite/src/Op/FakeQuant.cpp
compiler/tflchef/tflite/src/Op/Fill.cpp
compiler/tflchef/tflite/src/Op/Floor.cpp
compiler/tflchef/tflite/src/Op/FloorDiv.cpp
compiler/tflchef/tflite/src/Op/FloorMod.cpp
compiler/tflchef/tflite/src/Op/FullyConnected.cpp
compiler/tflchef/tflite/src/Op/Gather.cpp
compiler/tflchef/tflite/src/Op/GatherNd.cpp
compiler/tflchef/tflite/src/Op/Gelu.cpp
compiler/tflchef/tflite/src/Op/Greater.cpp
compiler/tflchef/tflite/src/Op/GreaterEqual.cpp
compiler/tflchef/tflite/src/Op/HardSwish.cpp
compiler/tflchef/tflite/src/Op/L2Normalize.cpp
compiler/tflchef/tflite/src/Op/L2Pool2D.cpp
compiler/tflchef/tflite/src/Op/LeakyRelu.cpp
compiler/tflchef/tflite/src/Op/Less.cpp
compiler/tflchef/tflite/src/Op/LessEqual.cpp
compiler/tflchef/tflite/src/Op/LocalResponseNormalization.cpp
compiler/tflchef/tflite/src/Op/Log.cpp
compiler/tflchef/tflite/src/Op/LogSoftmax.cpp
compiler/tflchef/tflite/src/Op/LogicalAnd.cpp
compiler/tflchef/tflite/src/Op/LogicalNot.cpp
compiler/tflchef/tflite/src/Op/LogicalOr.cpp
compiler/tflchef/tflite/src/Op/Logistic.cpp
compiler/tflchef/tflite/src/Op/MatrixDiag.cpp
compiler/tflchef/tflite/src/Op/MatrixSetDiag.cpp
compiler/tflchef/tflite/src/Op/MaxPool2D.cpp
compiler/tflchef/tflite/src/Op/Maximum.cpp
compiler/tflchef/tflite/src/Op/Mean.cpp
compiler/tflchef/tflite/src/Op/Minimum.cpp
compiler/tflchef/tflite/src/Op/MirrorPad.cpp
compiler/tflchef/tflite/src/Op/Mul.cpp
compiler/tflchef/tflite/src/Op/Neg.cpp
compiler/tflchef/tflite/src/Op/NonMaxSuppressionV4.cpp
compiler/tflchef/tflite/src/Op/NonMaxSuppressionV5.cpp
compiler/tflchef/tflite/src/Op/NotEqual.cpp
compiler/tflchef/tflite/src/Op/OneHot.cpp
compiler/tflchef/tflite/src/Op/PRelu.cpp
compiler/tflchef/tflite/src/Op/Pack.cpp
compiler/tflchef/tflite/src/Op/Pad.cpp
compiler/tflchef/tflite/src/Op/PadV2.cpp
compiler/tflchef/tflite/src/Op/Pow.cpp
compiler/tflchef/tflite/src/Op/Quantize.cpp
compiler/tflchef/tflite/src/Op/Range.cpp
compiler/tflchef/tflite/src/Op/Rank.cpp
compiler/tflchef/tflite/src/Op/ReLU.cpp
compiler/tflchef/tflite/src/Op/ReLU0To1.cpp [new file with mode: 0644]
compiler/tflchef/tflite/src/Op/ReLU6.cpp
compiler/tflchef/tflite/src/Op/ReLUN1To1.cpp
compiler/tflchef/tflite/src/Op/ReduceAny.cpp
compiler/tflchef/tflite/src/Op/ReduceMax.cpp
compiler/tflchef/tflite/src/Op/ReduceMin.cpp
compiler/tflchef/tflite/src/Op/ReduceProd.cpp
compiler/tflchef/tflite/src/Op/Reshape.cpp
compiler/tflchef/tflite/src/Op/ResizeBilinear.cpp
compiler/tflchef/tflite/src/Op/ResizeNearestNeighbor.cpp
compiler/tflchef/tflite/src/Op/ReverseSequence.cpp
compiler/tflchef/tflite/src/Op/ReverseV2.cpp
compiler/tflchef/tflite/src/Op/Round.cpp
compiler/tflchef/tflite/src/Op/Rsqrt.cpp
compiler/tflchef/tflite/src/Op/SVDF.cpp
compiler/tflchef/tflite/src/Op/ScatterNd.cpp
compiler/tflchef/tflite/src/Op/SegmentSum.cpp
compiler/tflchef/tflite/src/Op/Select.cpp
compiler/tflchef/tflite/src/Op/SelectV2.cpp
compiler/tflchef/tflite/src/Op/Shape.cpp
compiler/tflchef/tflite/src/Op/Sin.cpp
compiler/tflchef/tflite/src/Op/Slice.cpp
compiler/tflchef/tflite/src/Op/Softmax.cpp
compiler/tflchef/tflite/src/Op/SpaceToBatchND.cpp
compiler/tflchef/tflite/src/Op/SpaceToDepth.cpp
compiler/tflchef/tflite/src/Op/SparseToDense.cpp
compiler/tflchef/tflite/src/Op/Split.cpp
compiler/tflchef/tflite/src/Op/SplitV.cpp
compiler/tflchef/tflite/src/Op/Sqrt.cpp
compiler/tflchef/tflite/src/Op/Square.cpp
compiler/tflchef/tflite/src/Op/SquaredDifference.cpp
compiler/tflchef/tflite/src/Op/Squeeze.cpp
compiler/tflchef/tflite/src/Op/StridedSlice.cpp
compiler/tflchef/tflite/src/Op/Sub.cpp
compiler/tflchef/tflite/src/Op/Sum.cpp
compiler/tflchef/tflite/src/Op/Tanh.cpp
compiler/tflchef/tflite/src/Op/Tile.cpp
compiler/tflchef/tflite/src/Op/TopKV2.cpp
compiler/tflchef/tflite/src/Op/Transpose.cpp
compiler/tflchef/tflite/src/Op/TransposeConv.cpp
compiler/tflchef/tflite/src/Op/UnidirectionalSequenceLSTM.cpp
compiler/tflchef/tflite/src/Op/Unique.cpp
compiler/tflchef/tflite/src/Op/Unpack.cpp
compiler/tflchef/tflite/src/Op/Where.cpp
compiler/tflchef/tflite/src/Op/While.cpp [new file with mode: 0644]
compiler/tflchef/tflite/src/Op/ZerosLike.cpp
compiler/tflchef/tflite/src/Op/include/Abs.h
compiler/tflchef/tflite/src/Op/include/Add.h
compiler/tflchef/tflite/src/Op/include/AddN.h
compiler/tflchef/tflite/src/Op/include/ArgMax.h
compiler/tflchef/tflite/src/Op/include/ArgMin.h
compiler/tflchef/tflite/src/Op/include/AveragePool2D.h
compiler/tflchef/tflite/src/Op/include/BatchMatMul.h
compiler/tflchef/tflite/src/Op/include/BatchToSpaceND.h
compiler/tflchef/tflite/src/Op/include/BidirectionalSequenceLSTM.h
compiler/tflchef/tflite/src/Op/include/BroadcastTo.h [new file with mode: 0644]
compiler/tflchef/tflite/src/Op/include/Cast.h
compiler/tflchef/tflite/src/Op/include/Ceil.h
compiler/tflchef/tflite/src/Op/include/Concatenation.h
compiler/tflchef/tflite/src/Op/include/Conv2D.h
compiler/tflchef/tflite/src/Op/include/Cos.h
compiler/tflchef/tflite/src/Op/include/CumSum.h [new file with mode: 0644]
compiler/tflchef/tflite/src/Op/include/DepthToSpace.h
compiler/tflchef/tflite/src/Op/include/DepthwiseConv2D.h
compiler/tflchef/tflite/src/Op/include/Dequantize.h
compiler/tflchef/tflite/src/Op/include/Div.h
compiler/tflchef/tflite/src/Op/include/ELU.h
compiler/tflchef/tflite/src/Op/include/Equal.h
compiler/tflchef/tflite/src/Op/include/Exp.h
compiler/tflchef/tflite/src/Op/include/ExpandDims.h
compiler/tflchef/tflite/src/Op/include/FakeQuant.h
compiler/tflchef/tflite/src/Op/include/Fill.h
compiler/tflchef/tflite/src/Op/include/Floor.h
compiler/tflchef/tflite/src/Op/include/FloorDiv.h
compiler/tflchef/tflite/src/Op/include/FloorMod.h
compiler/tflchef/tflite/src/Op/include/FullyConnected.h
compiler/tflchef/tflite/src/Op/include/Gather.h
compiler/tflchef/tflite/src/Op/include/GatherNd.h
compiler/tflchef/tflite/src/Op/include/Gelu.h
compiler/tflchef/tflite/src/Op/include/Greater.h
compiler/tflchef/tflite/src/Op/include/GreaterEqual.h
compiler/tflchef/tflite/src/Op/include/HardSwish.h
compiler/tflchef/tflite/src/Op/include/L2Normalize.h
compiler/tflchef/tflite/src/Op/include/L2Pool2D.h
compiler/tflchef/tflite/src/Op/include/LeakyRelu.h
compiler/tflchef/tflite/src/Op/include/Less.h
compiler/tflchef/tflite/src/Op/include/LessEqual.h
compiler/tflchef/tflite/src/Op/include/LocalResponseNormalization.h
compiler/tflchef/tflite/src/Op/include/Log.h
compiler/tflchef/tflite/src/Op/include/LogSoftmax.h
compiler/tflchef/tflite/src/Op/include/LogicalAnd.h
compiler/tflchef/tflite/src/Op/include/LogicalNot.h
compiler/tflchef/tflite/src/Op/include/LogicalOr.h
compiler/tflchef/tflite/src/Op/include/Logistic.h
compiler/tflchef/tflite/src/Op/include/MatrixDiag.h
compiler/tflchef/tflite/src/Op/include/MatrixSetDiag.h
compiler/tflchef/tflite/src/Op/include/MaxPool2D.h
compiler/tflchef/tflite/src/Op/include/Maximum.h
compiler/tflchef/tflite/src/Op/include/Mean.h
compiler/tflchef/tflite/src/Op/include/Minimum.h
compiler/tflchef/tflite/src/Op/include/MirrorPad.h
compiler/tflchef/tflite/src/Op/include/Mul.h
compiler/tflchef/tflite/src/Op/include/Neg.h
compiler/tflchef/tflite/src/Op/include/NonMaxSuppressionV4.h
compiler/tflchef/tflite/src/Op/include/NonMaxSuppressionV5.h
compiler/tflchef/tflite/src/Op/include/NotEqual.h
compiler/tflchef/tflite/src/Op/include/OneHot.h
compiler/tflchef/tflite/src/Op/include/PRelu.h
compiler/tflchef/tflite/src/Op/include/Pack.h
compiler/tflchef/tflite/src/Op/include/Pad.h
compiler/tflchef/tflite/src/Op/include/PadV2.h
compiler/tflchef/tflite/src/Op/include/Pow.h
compiler/tflchef/tflite/src/Op/include/Quantize.h
compiler/tflchef/tflite/src/Op/include/Range.h
compiler/tflchef/tflite/src/Op/include/Rank.h
compiler/tflchef/tflite/src/Op/include/ReLU.h
compiler/tflchef/tflite/src/Op/include/ReLU0To1.h [new file with mode: 0644]
compiler/tflchef/tflite/src/Op/include/ReLU6.h
compiler/tflchef/tflite/src/Op/include/ReLUN1To1.h
compiler/tflchef/tflite/src/Op/include/ReduceAny.h
compiler/tflchef/tflite/src/Op/include/ReduceMax.h
compiler/tflchef/tflite/src/Op/include/ReduceMin.h
compiler/tflchef/tflite/src/Op/include/ReduceProd.h
compiler/tflchef/tflite/src/Op/include/Reshape.h
compiler/tflchef/tflite/src/Op/include/ResizeBilinear.h
compiler/tflchef/tflite/src/Op/include/ResizeNearestNeighbor.h
compiler/tflchef/tflite/src/Op/include/ReverseSequence.h
compiler/tflchef/tflite/src/Op/include/ReverseV2.h
compiler/tflchef/tflite/src/Op/include/Round.h
compiler/tflchef/tflite/src/Op/include/Rsqrt.h
compiler/tflchef/tflite/src/Op/include/SVDF.h
compiler/tflchef/tflite/src/Op/include/ScatterNd.h
compiler/tflchef/tflite/src/Op/include/SegmentSum.h
compiler/tflchef/tflite/src/Op/include/Select.h
compiler/tflchef/tflite/src/Op/include/SelectV2.h
compiler/tflchef/tflite/src/Op/include/Shape.h
compiler/tflchef/tflite/src/Op/include/Sin.h
compiler/tflchef/tflite/src/Op/include/Slice.h
compiler/tflchef/tflite/src/Op/include/Softmax.h
compiler/tflchef/tflite/src/Op/include/SpaceToBatchND.h
compiler/tflchef/tflite/src/Op/include/SpaceToDepth.h
compiler/tflchef/tflite/src/Op/include/SparseToDense.h
compiler/tflchef/tflite/src/Op/include/Split.h
compiler/tflchef/tflite/src/Op/include/SplitV.h
compiler/tflchef/tflite/src/Op/include/Sqrt.h
compiler/tflchef/tflite/src/Op/include/Square.h
compiler/tflchef/tflite/src/Op/include/SquaredDifference.h
compiler/tflchef/tflite/src/Op/include/Squeeze.h
compiler/tflchef/tflite/src/Op/include/StridedSlice.h
compiler/tflchef/tflite/src/Op/include/Sub.h
compiler/tflchef/tflite/src/Op/include/Sum.h
compiler/tflchef/tflite/src/Op/include/Tanh.h
compiler/tflchef/tflite/src/Op/include/Tile.h
compiler/tflchef/tflite/src/Op/include/TopKV2.h
compiler/tflchef/tflite/src/Op/include/Transpose.h
compiler/tflchef/tflite/src/Op/include/TransposeConv.h
compiler/tflchef/tflite/src/Op/include/UnidirectionalSequenceLSTM.h
compiler/tflchef/tflite/src/Op/include/Unique.h
compiler/tflchef/tflite/src/Op/include/Unpack.h
compiler/tflchef/tflite/src/Op/include/Where.h
compiler/tflchef/tflite/src/Op/include/While.h [new file with mode: 0644]
compiler/tflchef/tflite/src/Op/include/ZerosLike.h
compiler/tflchef/tflite/src/RecipeChef.cpp
compiler/tflchef/tflite/src/TFliteImport.cpp
compiler/tflchef/tflite/src/TFliteImport.h
compiler/tflchef/tflite/src/TFliteOpChef.h
compiler/tflchef/tflite/src/TFliteOpChefs.h
compiler/tflchef/tflite/src/TFliteOpRegistry.h
compiler/tfldump/src/Dump.cpp
compiler/tfldump/src/OpPrinter.cpp
compiler/tfldump/src/Read.cpp
compiler/tfldump/src/Read.h
compiler/tflite2circle/CMakeLists.txt
compiler/tflite2circle/requires.cmake
compiler/tflite2circle/src/BuildBuiltinOptions.h
compiler/tflite2circle/src/BuildBuiltinOptions/BroadcastToOptions.cpp [new file with mode: 0644]
compiler/tflite2circle/src/BuildBuiltinOptions/BroadcastToOptions.h [new file with mode: 0644]
compiler/tflite2circle/src/BuildBuiltinOptions/CumSumOptions.cpp [new file with mode: 0644]
compiler/tflite2circle/src/BuildBuiltinOptions/CumSumOptions.h [new file with mode: 0644]
compiler/tflite2circle/src/CircleModel.cpp
compiler/tflite2circle/src/DataLookup.cpp
compiler/tflite2circle/src/TFLBuiltinOptions.lst
compiler/tflite2circle/src/TFLOperator.lst
compiler/tflite2circle/src/TFLTensorType.lst
compiler/tfts/exclude.me [new file with mode: 0644]
compiler/vconone/CMakeLists.txt
compute/ARMComputeEx/arm_compute/core/NEON/NEElementwiseOperationFuncs.h [deleted file]
compute/ARMComputeEx/arm_compute/core/NEON/kernels/NEBinaryLogicalOperationKernel.h [deleted file]
compute/ARMComputeEx/arm_compute/runtime/NEON/functions/NEBinaryLogicalOperation.h [deleted file]
compute/ARMComputeEx/src/core/CL/cl_kernels/gemmlowp.cl
compute/ARMComputeEx/src/core/NEON/NEElementwiseOperationFuncs.cpp [deleted file]
compute/ARMComputeEx/src/core/NEON/kernels/NEBinaryLogicalOperationKernel.cpp [deleted file]
compute/ARMComputeEx/src/core/NEON/kernels/NEOneHotKernel.cpp
compute/ARMComputeEx/src/runtime/NEON/functions/NEBinaryLogicalOperation.cpp [deleted file]
compute/cker/CMakeLists.txt
compute/cker/include/cker/NeonTensorUtils.h
compute/cker/include/cker/Types.h
compute/cker/include/cker/eigen/EigenSupport.h
compute/cker/include/cker/eigen/depthwise_conv_op.h [new file with mode: 0644]
compute/cker/include/cker/eigen/eigen_backward_spatial_convolutions.h [new file with mode: 0644]
compute/cker/include/cker/eigen/eigen_convolution_helpers.h
compute/cker/include/cker/eigen/eigen_spatial_convolutions-inl.h
compute/cker/include/cker/eigen/eigen_spatial_convolutions.h
compute/cker/include/cker/eigen/redux_functor.h [new file with mode: 0644]
compute/cker/include/cker/eigen/training_ops.h [new file with mode: 0644]
compute/cker/include/cker/operation/BinaryArithmeticOps.h
compute/cker/include/cker/operation/Concatenation.h
compute/cker/include/cker/operation/FloorMod.h [new file with mode: 0644]
compute/cker/include/cker/operation/Helper/MatmulBCast.h
compute/cker/include/cker/operation/Helper/RandomOpCpu.h
compute/cker/include/cker/operation/Logistic.h
compute/cker/include/cker/operation/SplitV.h
compute/cker/include/cker/operation/StridedSlice.h
compute/cker/include/cker/operation/reference/BinaryArithmeticOps.h
compute/cker/include/cker/train/operation/BinaryArithmetic.h [new file with mode: 0644]
compute/cker/include/cker/train/operation/Conv.h [new file with mode: 0644]
compute/cker/include/cker/train/operation/DepthwiseConv.h [new file with mode: 0644]
compute/cker/include/cker/train/operation/Loss.h
compute/cker/include/cker/train/operation/MaxPool.h [new file with mode: 0644]
compute/cker/include/cker/train/operation/Pad.h [new file with mode: 0644]
compute/cker/include/cker/train/operation/ReLU6.h [new file with mode: 0644]
compute/cker/include/cker/train/operation/ReduceMean.h [new file with mode: 0644]
compute/cker/include/cker/train/operation/SoftMax.h [new file with mode: 0644]
compute/cker/include/cker/train/optimizer/Adam.h [new file with mode: 0644]
compute/cker/include/cker/train/optimizer/SGD.h [new file with mode: 0644]
compute/cker/src/FloorMod.test.cc [new file with mode: 0644]
compute/cker/src/Mul.test.cc [new file with mode: 0644]
compute/cker/src/train/Adam.test.cc [new file with mode: 0644]
compute/cker/src/train/BinaryArithmetic.test.cc [new file with mode: 0644]
compute/cker/src/train/Conv.test.cc [new file with mode: 0644]
compute/cker/src/train/DepthwiseConv.test.cc [new file with mode: 0644]
compute/cker/src/train/Loss.test.cc
compute/cker/src/train/MaxPool.test.cc [new file with mode: 0644]
compute/cker/src/train/Pad.test.cc [new file with mode: 0644]
compute/cker/src/train/ReduceMean.test.cc [new file with mode: 0644]
compute/cker/src/train/Relu6.test.cc [new file with mode: 0644]
compute/cker/src/train/SGD.test.cc [new file with mode: 0644]
compute/cker/src/train/SoftMax.test.cc [new file with mode: 0644]
docs/conf.py
docs/howto/how-to-build-compiler.md
docs/howto/how-to-cross-build-runtime-for-aarch64.md
docs/howto/how-to-cross-build-runtime-for-android.md
docs/howto/how-to-cross-build-runtime-for-arm.md
docs/howto/how-to-introduce-a-new-operation-into-runtime.md
docs/howto/how-to-use-nnapi-binding.md
docs/howto/how-to-use-nnfw-api.md
docs/howto/how-to-use-nnfw-python-api.md [new file with mode: 0644]
docs/howto/how-to-use-specific-backend.md
docs/nnfw/howto/CrossBuildForAndroid.md [deleted file]
docs/overview/background.md
docs/overview/roadmap.md
docs/release/1.26/index.rst [new file with mode: 0644]
docs/release/1.26/release-note-1.26.0.md [new file with mode: 0644]
docs/release/1.27/index.rst [new file with mode: 0644]
docs/release/1.27/release-note-1.27.0.md [new file with mode: 0644]
docs/release/1.27/release-note-1.27.1.md [new file with mode: 0644]
docs/release/1.27/release-note-1.27.2.md [new file with mode: 0644]
docs/release/1.28/index.rst [new file with mode: 0644]
docs/release/1.28/release-note_1.28.0.md [new file with mode: 0644]
docs/release/onert-micro/2.0/release-note-2.0.0-pre.md [new file with mode: 0644]
docs/runtime/backend-api.md
docs/runtime/compute.md
docs/runtime/controlflow-operations.md
docs/runtime/core.md
docs/runtime/executors.md
docs/runtime/heterogeneous-execution.md
docs/runtime/transfer_learning.md [new file with mode: 0644]
docs/runtime/transfer_learning_result.png [new file with mode: 0644]
infra/3rdparty/.gitignore [deleted file]
infra/3rdparty/Eigen/fd6845384b86/URL.default [deleted file]
infra/3rdparty/Eigen/fd6845384b86/URL.info [deleted file]
infra/buildtool/CMakeLists.txt [new file with mode: 0644]
infra/cmake/modules/IdentifyPlatform.cmake
infra/cmake/packages/AbseilSourceConfig.cmake
infra/cmake/packages/BoostSourceConfig.cmake
infra/cmake/packages/CpuInfoSourceConfig.cmake
infra/cmake/packages/Eigen-fd6845384b86Config.cmake [deleted file]
infra/cmake/packages/EigenSource-fd6845384b86Config.cmake [deleted file]
infra/cmake/packages/FarmhashSourceConfig.cmake
infra/cmake/packages/FlatBuffers-2.0/FlatBuffersConfig.cmake
infra/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfig.cmake [new file with mode: 0644]
infra/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfigVersion.cmake [new file with mode: 0644]
infra/cmake/packages/FlatBuffersSource-23.5.26/FlatBuffersSourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/FlatBuffersSource-23.5.26/FlatBuffersSourceConfigVersion.cmake [new file with mode: 0644]
infra/cmake/packages/Fp16SourceConfig.cmake
infra/cmake/packages/FxdivSourceConfig.cmake
infra/cmake/packages/GTestSourceConfig.cmake
infra/cmake/packages/LibnpySourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/MLDtypesSourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/NEON2SSESourceConfig.cmake
infra/cmake/packages/NoniusSourceConfig.cmake
infra/cmake/packages/PthreadpoolSourceConfig.cmake
infra/cmake/packages/Pybind11SourceConfig.cmake
infra/cmake/packages/TensorFlowConfig.cmake [deleted file]
infra/cmake/packages/TensorFlowEigenSource-2.12.1/TensorFlowEigenSourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowEigenSource-2.12.1/TensorFlowEigenSourceConfigVersion.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowEigenSource-2.16.1/TensorFlowEigenSourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowEigenSource-2.16.1/TensorFlowEigenSourceConfigVersion.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowGEMMLowpSource-2.12.1/TensorFlowGEMMLowpSourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowGEMMLowpSource-2.12.1/TensorFlowGEMMLowpSourceConfigVersion.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowGEMMLowpSource-2.16.1/TensorFlowGEMMLowpSourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowGEMMLowpSource-2.16.1/TensorFlowGEMMLowpSourceConfigVersion.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowLite-1.13.1/Lite/CMakeLists.txt [deleted file]
infra/cmake/packages/TensorFlowLite-1.13.1/TensorFlowLiteConfig.cmake [deleted file]
infra/cmake/packages/TensorFlowLite-1.13.1/TensorFlowLiteConfigVersion.cmake [deleted file]
infra/cmake/packages/TensorFlowRuySource-2.12.1/TensorFlowRuySourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowRuySource-2.12.1/TensorFlowRuySourceConfigVersion.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowRuySource-2.16.1/TensorFlowRuySourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowRuySource-2.16.1/TensorFlowRuySourceConfigVersion.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowSource-2.16.1/TensorFlowSourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowSource-2.16.1/TensorFlowSourceConfigVersion.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowThreadpoolSource-2.12.1/TensorFlowThreadpoolSourceConfig.cmake [new file with mode: 0644]
infra/cmake/packages/TensorFlowThreadpoolSource-2.12.1/TensorFlowThreadpoolSourceConfigVersion.cmake [new file with mode: 0644]
infra/cmake/packages/XnnpackSource.patch [new file with mode: 0644]
infra/cmake/packages/XnnpackSourceConfig.cmake
infra/command/build-docker-image
infra/command/docker-run
infra/command/docker-shell [new file with mode: 0644]
infra/command/format
infra/command/gen-coverage-report
infra/config/docker.configuration
infra/debian/compiler/changelog
infra/debian/compiler/docs/one-codegen.1
infra/debian/compiler/docs/one-import-bcq.1
infra/debian/compiler/docs/one-import-onnx.1
infra/debian/compiler/docs/one-import-tf.1
infra/debian/compiler/docs/one-import-tflite.1
infra/debian/compiler/docs/one-import.1
infra/debian/compiler/docs/one-infer.1
infra/debian/compiler/docs/one-optimize.1
infra/debian/compiler/docs/one-pack.1
infra/debian/compiler/docs/one-partition.1
infra/debian/compiler/docs/one-profile.1
infra/debian/compiler/docs/one-quantize.1
infra/debian/compiler/docs/onecc.1
infra/debian/compiler/one-compiler.install
infra/debian/compiler/one-compiler.links
infra/debian/compiler/postinst
infra/debian/compiler/rules
infra/debian/runtime/control
infra/debian/runtime/nnfw-plugin-dev.install [new file with mode: 0644]
infra/debian/runtime/nnfw.install
infra/debian/runtime/rules
infra/docker/android-sdk/Dockerfile [new file with mode: 0644]
infra/docker/bionic/Dockerfile
infra/docker/focal/Dockerfile
infra/docker/focal/Dockerfile.aarch64
infra/docker/jammy/Dockerfile
infra/docker/jammy/Dockerfile.aarch64
infra/docker/noble/Dockerfile [new file with mode: 0644]
infra/docker/noble/Dockerfile.aarch64 [new file with mode: 0644]
infra/nncc/CMakeLists.txt
infra/nncc/Makefile.arm32
infra/nncc/cmake/CfgOptionFlags.cmake
infra/nncc/cmake/buildtool/cross/toolchain_aarch64-linux.cmake [new file with mode: 0644]
infra/nncc/cmake/options/options_riscv64-tizen.cmake [new file with mode: 0644]
infra/nncc/command/docker-nncc [deleted file]
infra/nncc/command/docker-run [deleted file]
infra/nncc/command/docker-shell [deleted file]
infra/nncc/command/install [new file with mode: 0644]
infra/nncc/command/utcount
infra/nncc/config/docker.configuration [deleted file]
infra/nnfw/CMakeLists.txt
infra/nnfw/cmake/CfgOptionFlags.cmake
infra/nnfw/cmake/buildtool/config/config_armv7hl-tizen.cmake
infra/nnfw/cmake/buildtool/config/config_armv7l-linux.cmake
infra/nnfw/cmake/buildtool/config/config_armv7l-tizen.cmake
infra/nnfw/cmake/buildtool/config/config_riscv64-tizen.cmake [new file with mode: 0644]
infra/nnfw/cmake/buildtool/cross/toolchain_aarch64-android.cmake
infra/nnfw/cmake/options/options_aarch64-android.cmake
infra/nnfw/cmake/options/options_aarch64-linux.cmake
infra/nnfw/cmake/options/options_aarch64-tizen.cmake
infra/nnfw/cmake/options/options_armv7hl-tizen.cmake
infra/nnfw/cmake/options/options_armv7l-linux.cmake
infra/nnfw/cmake/options/options_armv7l-tizen.cmake
infra/nnfw/cmake/options/options_i686-tizen.cmake
infra/nnfw/cmake/options/options_riscv64-tizen.cmake [new file with mode: 0644]
infra/nnfw/cmake/options/options_x86_64-linux.cmake
infra/nnfw/cmake/options/options_x86_64-tizen.cmake
infra/nnfw/cmake/packages/ARMComputeConfig.cmake
infra/nnfw/cmake/packages/BoostConfig.cmake
infra/nnfw/cmake/packages/EigenConfig.cmake
infra/nnfw/cmake/packages/FlatBuffers-2.0/FlatBuffersConfig.cmake [moved from infra/nnfw/cmake/packages/FlatBuffersConfig.cmake with 100% similarity]
infra/nnfw/cmake/packages/FlatBuffers-2.0/FlatBuffersConfigVersion.cmake [new file with mode: 0644]
infra/nnfw/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfig.cmake [new file with mode: 0644]
infra/nnfw/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfigVersion.cmake [new file with mode: 0644]
infra/nnfw/cmake/packages/GEMMLowpConfig.cmake
infra/nnfw/cmake/packages/Giounix2.0Config.cmake
infra/nnfw/cmake/packages/HDF5Config.cmake
infra/nnfw/cmake/packages/LuciConfig.cmake
infra/nnfw/cmake/packages/OouraFFTConfig.cmake [new file with mode: 0644]
infra/nnfw/cmake/packages/Pybind11Config.cmake [new file with mode: 0644]
infra/nnfw/cmake/packages/RuyConfig.cmake
infra/nnfw/cmake/packages/TRIXEngineConfig.cmake
infra/nnfw/cmake/packages/TRIXEngineConfigVersion.cmake
infra/nnfw/cmake/packages/TensorFlowGpuConfig.cmake
infra/nnfw/cmake/packages/TensorFlowLite-2.16.1/TensorFlowLite/CMakeLists.txt [new file with mode: 0644]
infra/nnfw/cmake/packages/TensorFlowLite-2.16.1/TensorFlowLiteConfig.cmake [new file with mode: 0644]
infra/nnfw/cmake/packages/TensorFlowLite-2.16.1/TensorFlowLiteConfigVersion.cmake [new file with mode: 0644]
infra/nnfw/cmake/packages/TensorFlowLite-2.8.0/TensorFlowLite/CMakeLists.txt [deleted file]
infra/nnfw/cmake/packages/TensorFlowLite-2.8.0/TensorFlowLiteConfig.cmake [deleted file]
infra/nnfw/cmake/packages/TensorFlowLite-2.8.0/TensorFlowLiteConfigVersion.cmake [deleted file]
infra/nnfw/cmake/packages/TensorFlowLiteGpu/CMakeLists.txt
infra/nnfw/cmake/packages/XnnpackConfig.cmake
infra/nnfw/command/build
infra/nnfw/command/configure
infra/nnfw/command/docker-run [deleted file]
infra/nnfw/command/docker-run-user [deleted file]
infra/nnfw/command/docker-shell [deleted file]
infra/nnfw/command/install
infra/nnfw/config/docker.configuration [deleted file]
infra/nnfw/config/gbs.conf
infra/nnfw/python/.gitignore [new file with mode: 0644]
infra/nnfw/python/README.md [new file with mode: 0644]
infra/nnfw/python/pack.sh [new file with mode: 0644]
infra/nnfw/python/setup.py [new file with mode: 0644]
infra/packaging/build
infra/packaging/preset/20230907
infra/packaging/preset/20230907_windows
infra/scripts/compiler_modules.sh
infra/scripts/configure_collect_nnpkgs.sh [new file with mode: 0755]
infra/scripts/docker_build_nncc.sh [deleted file]
infra/scripts/docker_collect_nnpkg_resources.sh [deleted file]
infra/scripts/test_coverage.sh
nnpackage/schema/circle_schema.fbs
onert-micro/CMakeLists.txt
onert-micro/eval-driver/CMakeLists.txt
onert-micro/eval-driver/Driver.cpp
onert-micro/eval-driver/TrainingDriver.cpp [new file with mode: 0644]
onert-micro/examples/README.md [new file with mode: 0644]
onert-micro/examples/models/speech_recognition/speech_recognition_float.tflite [new file with mode: 0644]
onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/CMakeLists.txt [new file with mode: 0644]
onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/main.cpp [new file with mode: 0644]
onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/mbed-sources.cmake [new file with mode: 0644]
onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/mbed_config.h [new file with mode: 0644]
onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/speech_recognition_float.circle.h [new file with mode: 0644]
onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/test_data.h [new file with mode: 0644]
onert-micro/externals/.FORMATDENY [new file with mode: 0644]
onert-micro/externals/CMakeLists.txt
onert-micro/externals/gen/circle-generated/circle/schema_generated.h
onert-micro/externals/gen/circle-generated/circle/traininfo_generated.h [new file with mode: 0644]
onert-micro/luci-interpreter/CMakeLists.txt
onert-micro/luci-interpreter/include/luci_interpreter/Interpreter.h
onert-micro/luci-interpreter/include/luci_interpreter/TrainableWeightStorage.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/TrainingOnertMicro.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/TestDataBatchToSpaceNDBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/broadcast_to/FloatBroadcastToKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/broadcast_to/NegBroadcastToKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/broadcast_to/TestDataBroadcastToBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/cast/FloatCastKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/cast/NegCastKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/cast/TestDataCastBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/ceil/FloatCeilKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/ceil/NegCeilKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/ceil/TestDataCeilBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/conv2d/NegConv2DKernel.h
onert-micro/luci-interpreter/include/luci_interpreter/test_models/cos/FloatCosKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/cos/NegCosKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/cos/TestDataCosBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/depth_to_space/FloatDepthToSpaceKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/depth_to_space/NegDepthToSpaceKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/depth_to_space/TestDataDepthToSpaceBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/depthwise_conv_2d/FloatDepthwiseConv2DKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/depthwise_conv_2d/NegDepthwiseConv2DKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/depthwise_conv_2d/TestDataDepthwiseConv2DBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/dequantize/FloatDequantizeKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/dequantize/NegDequantizeKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/dequantize/TestDataDequantizeBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/floor/FloatFloorKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/floor/NegFloorKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/floor/TestDataFloorBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/floordiv/FloatFloorDivKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/floordiv/NegFloorDivKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/floordiv/TestDataFloorDivBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/floormod/FloatFloorModKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/floormod/NegFloorModKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/floormod/TestDataFloorModBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather_nd/FloatGatherNDKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather_nd/NegGatherNDKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather_nd/TestDataGatherNDBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/if/IfKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/if/NegIfKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_normalization/FloatL2NormalizeKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_normalization/NegL2NormalizeKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_normalization/TestDataL2NormalizeBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_poop_2d/FloatL2Pool2DKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_poop_2d/NegL2Pool2DKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_poop_2d/TestDataL2Pool2DBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/log/FloatLogKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/log/NegLogKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/log/TestDataLogBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/log_softmax/FloatLogSoftmaxKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/log_softmax/NegLogSoftmaxKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/log_softmax/TestDataLogSoftmaxBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_not/BoolLogicalNotKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_not/NegLogicalNotKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_not/TestDataLogicalNotBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/maximum/FloatMaximumKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/maximum/NegMaximumKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/maximum/TestDataMaximumBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/mean/FloatMeanKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/mean/NegMeanKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/mean/TestDataMeanBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/minimum/FloatMinimumKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/minimum/NegMinimumKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/minimum/TestDataMinimumBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/mirror_pad/FloatMirrorPadKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/mirror_pad/NegMirrorPadKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/mirror_pad/TestDataMirrorPadBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/prelu/FloatPReluKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/prelu/NegPReluKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/prelu/TestDataPReluBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/quantize/FloatQuantizeKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/quantize/NegQuantizeKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/quantize/TestDataQuantizeBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_max/FloatReduceMaxKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_max/NegReduceMaxKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_max/TestDataReduceMaxBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_nearest_neighbor/FloatResizeNearestNeighborKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_nearest_neighbor/NegResizeNearestNeighborKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_nearest_neighbor/TestDataResizeNearestNeighborBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/round/FloatRoundKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/round/NegRoundKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/round/TestDataRoundBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/rsqrt/FloatRsqrtKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/rsqrt/NegRsqrtKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/rsqrt/TestDataRsqrtBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/select_v2/FloatSelectV2Kernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/select_v2/NegSelectV2Kernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/select_v2/TestDataSelectV2Base.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/sin/FloatSinKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/sin/NegSinKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/sin/TestDataSinBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_batch_nd/FloatSpaceToBatchNDKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_batch_nd/NegSpaceToBatchNDKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_batch_nd/TestDataSpaceToBatchNDBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_depth/FloatSpaceToDepthKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_depth/NegSpaceToDepthKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_depth/TestDataSpaceToDepthBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/sqrt/FloatSqrtKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/sqrt/NegSqrtKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/sqrt/TestDataSqrtBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/square/FloatSquareKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/square/NegSquareKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/square/TestDataSquareBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/squared_difference/FloatSquaredDifferenceKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/squared_difference/NegSquaredDifferenceKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/squared_difference/TestDataSquaredDifferenceBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/squeeze/FloatSqueezeKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/squeeze/NegSqueezeKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/squeeze/TestDataSqueezeBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/sum/FloatSumKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/sum/NegSumKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/sum/TestDataSumBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/svdf/FloatSVDFKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/svdf/NegSVDFKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/svdf/TestDataSVDFBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose_conv/FloatTransposeConvKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose_conv/NegTransposeConvKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose_conv/TestDataTransposeConvBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/unpack/FloatUnpackKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/unpack/NegUnpackKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/unpack/TestDataUnpackBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/zeros_like/FloatZerosLikeKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/zeros_like/NegZerosLikeKernel.h [new file with mode: 0644]
onert-micro/luci-interpreter/include/luci_interpreter/test_models/zeros_like/TestDataZerosLikeBase.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/cmsisnn/KernelsToBuild.lst
onert-micro/luci-interpreter/pal/cmsisnn/KernelsToTrain.lst [new file with mode: 0644]
onert-micro/luci-interpreter/pal/cmsisnn/PALAdd.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/cmsisnn/PALAveragePool2D.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/cmsisnn/PALConv2d.h
onert-micro/luci-interpreter/pal/cmsisnn/PALFullyConnected.h
onert-micro/luci-interpreter/pal/cmsisnn/PALL2Pool2D.h [deleted file]
onert-micro/luci-interpreter/pal/cmsisnn/PALMaxPool2D.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/cmsisnn/PALMul.h
onert-micro/luci-interpreter/pal/cmsisnn/PALSVDF.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/cmsisnn/PALSoftmax.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/cmsisnn/pal.cmake
onert-micro/luci-interpreter/pal/common/Broadcast.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALAddCommon.h
onert-micro/luci-interpreter/pal/common/PALArithmeticOpCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALBatchToSpaceND.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALBinaryOpCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALBroadcastTo.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALCeil.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALCosCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALDepthToSpace.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALDepthwiseConv2DCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALDequantize.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALDiv.h
onert-micro/luci-interpreter/pal/common/PALFloorCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALFloorDivCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALFloorModCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALFullyConnectedCommon.h
onert-micro/luci-interpreter/pal/common/PALGatherND.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALL2Normalize.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALL2Pool2D.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALLog.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALLogSoftmax.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALLogicalNotCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALMaxPool2DCommon.h
onert-micro/luci-interpreter/pal/common/PALMaximumCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALMean.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALMinimumCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALMirrorPad.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALMulCommon.h
onert-micro/luci-interpreter/pal/common/PALPreluCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALQuantize.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALResizeNearestNeighbor.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALRound.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALRsqrt.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALSVDFCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALSelectV2.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALSinCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALSoftmax.h [deleted file]
onert-micro/luci-interpreter/pal/common/PALSoftmaxCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALSpaceToBatchND.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALSpaceToDepth.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALSqrt.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALSquareCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALSquaredDifference.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALSub.h
onert-micro/luci-interpreter/pal/common/PALTransposeConv.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/common/PALUnidirectionalSequenceLSTMCommon.h
onert-micro/luci-interpreter/pal/common/PALUtils.h
onert-micro/luci-interpreter/pal/common/Params.h
onert-micro/luci-interpreter/pal/mcu/KernelsToBuild.lst
onert-micro/luci-interpreter/pal/mcu/KernelsToTrain.lst [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALAveragePool2D.h
onert-micro/luci-interpreter/pal/mcu/PALCos.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALDepthwiseConv2D.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALFloor.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALFloorDiv.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALFloorMod.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALFullyConnected.h
onert-micro/luci-interpreter/pal/mcu/PALL2Pool2D.h [deleted file]
onert-micro/luci-interpreter/pal/mcu/PALLogicalNot.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALMaxPool2D.h
onert-micro/luci-interpreter/pal/mcu/PALMaximum.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALMinimum.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALSVDF.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALSin.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALSoftmax.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALSquare.h [new file with mode: 0644]
onert-micro/luci-interpreter/pal/mcu/PALUnidirectionalSequenceLSTM.h
onert-micro/luci-interpreter/src/CMakeLists.txt
onert-micro/luci-interpreter/src/Interpreter.cpp
onert-micro/luci-interpreter/src/TrainingOnertMicro.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/core/CMakeLists.txt
onert-micro/luci-interpreter/src/core/GradientCalculationStorage.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/core/GradientCalculationStorage.h [new file with mode: 0644]
onert-micro/luci-interpreter/src/core/RuntimeGraph.cpp
onert-micro/luci-interpreter/src/core/RuntimeGraph.h
onert-micro/luci-interpreter/src/core/RuntimeModule.h
onert-micro/luci-interpreter/src/core/TrainableWeightStorage.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/core/TrainingGraph.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/core/TrainingGraph.h [new file with mode: 0644]
onert-micro/luci-interpreter/src/core/TrainingModule.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/core/TrainingModule.h [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Abs.cpp
onert-micro/luci-interpreter/src/kernels/Add.cpp
onert-micro/luci-interpreter/src/kernels/Add.test.cpp
onert-micro/luci-interpreter/src/kernels/AveragePool2D.cpp
onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.cpp
onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h [deleted file]
onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.test.cpp
onert-micro/luci-interpreter/src/kernels/BinaryOpCommon.h
onert-micro/luci-interpreter/src/kernels/BroadcastTo.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/BroadcastTo.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Builders.h
onert-micro/luci-interpreter/src/kernels/CMakeLists.txt
onert-micro/luci-interpreter/src/kernels/Cast.cpp
onert-micro/luci-interpreter/src/kernels/Cast.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Cast.test.cpp
onert-micro/luci-interpreter/src/kernels/Ceil.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Ceil.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/ComparisonCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Conv2D.cpp
onert-micro/luci-interpreter/src/kernels/Conv2D.test.cpp
onert-micro/luci-interpreter/src/kernels/ConvolutionCommon.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/ConvolutionCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Cos.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Cos.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/DepthToSpace.cpp
onert-micro/luci-interpreter/src/kernels/DepthToSpace.h [deleted file]
onert-micro/luci-interpreter/src/kernels/DepthToSpace.test.cpp
onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.cpp
onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.h [deleted file]
onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.test.cpp
onert-micro/luci-interpreter/src/kernels/Dequantize.cpp
onert-micro/luci-interpreter/src/kernels/Dequantize.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Dequantize.test.cpp
onert-micro/luci-interpreter/src/kernels/Div.cpp
onert-micro/luci-interpreter/src/kernels/Div.test.cpp
onert-micro/luci-interpreter/src/kernels/Equal.cpp
onert-micro/luci-interpreter/src/kernels/Floor.cpp
onert-micro/luci-interpreter/src/kernels/Floor.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Floor.test.cpp
onert-micro/luci-interpreter/src/kernels/FloorDiv.cpp
onert-micro/luci-interpreter/src/kernels/FloorDiv.h [deleted file]
onert-micro/luci-interpreter/src/kernels/FloorDiv.test.cpp
onert-micro/luci-interpreter/src/kernels/FloorMod.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/FloorMod.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/FullyConnected.cpp
onert-micro/luci-interpreter/src/kernels/FullyConnected.train.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/GatherND.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/GatherND.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Greater.cpp
onert-micro/luci-interpreter/src/kernels/GreaterEqual.cpp
onert-micro/luci-interpreter/src/kernels/If.cpp
onert-micro/luci-interpreter/src/kernels/If.h [deleted file]
onert-micro/luci-interpreter/src/kernels/If.test.cpp
onert-micro/luci-interpreter/src/kernels/KernelBuilder.cpp
onert-micro/luci-interpreter/src/kernels/KernelBuilder.h
onert-micro/luci-interpreter/src/kernels/L2Normalize.cpp
onert-micro/luci-interpreter/src/kernels/L2Normalize.h [deleted file]
onert-micro/luci-interpreter/src/kernels/L2Normalize.test.cpp
onert-micro/luci-interpreter/src/kernels/L2Pool2D.cpp
onert-micro/luci-interpreter/src/kernels/L2Pool2D.h [deleted file]
onert-micro/luci-interpreter/src/kernels/L2Pool2D.test.cpp
onert-micro/luci-interpreter/src/kernels/Less.cpp
onert-micro/luci-interpreter/src/kernels/LessEqual.cpp
onert-micro/luci-interpreter/src/kernels/Log.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Log.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/LogSoftmax.cpp
onert-micro/luci-interpreter/src/kernels/LogSoftmax.h [deleted file]
onert-micro/luci-interpreter/src/kernels/LogSoftmax.test.cpp
onert-micro/luci-interpreter/src/kernels/LogicalNot.cpp
onert-micro/luci-interpreter/src/kernels/LogicalNot.test.cpp
onert-micro/luci-interpreter/src/kernels/Logistic.cpp
onert-micro/luci-interpreter/src/kernels/MaxPool2D.cpp
onert-micro/luci-interpreter/src/kernels/Maximum.cpp
onert-micro/luci-interpreter/src/kernels/Maximum.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Maximum.test.cpp
onert-micro/luci-interpreter/src/kernels/Mean.cpp
onert-micro/luci-interpreter/src/kernels/Mean.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Mean.test.cpp
onert-micro/luci-interpreter/src/kernels/Minimum.cpp
onert-micro/luci-interpreter/src/kernels/Minimum.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Minimum.test.cpp
onert-micro/luci-interpreter/src/kernels/MirrorPad.cpp
onert-micro/luci-interpreter/src/kernels/MirrorPad.h [deleted file]
onert-micro/luci-interpreter/src/kernels/MirrorPad.test.cpp
onert-micro/luci-interpreter/src/kernels/Mul.cpp
onert-micro/luci-interpreter/src/kernels/Mul.test.cpp
onert-micro/luci-interpreter/src/kernels/NotEqual.cpp
onert-micro/luci-interpreter/src/kernels/PRelu.cpp
onert-micro/luci-interpreter/src/kernels/PRelu.h [deleted file]
onert-micro/luci-interpreter/src/kernels/PRelu.test.cpp
onert-micro/luci-interpreter/src/kernels/PadCommon.cpp
onert-micro/luci-interpreter/src/kernels/Pool2DCommon.h [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Quantize.cpp
onert-micro/luci-interpreter/src/kernels/Quantize.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Quantize.test.cpp
onert-micro/luci-interpreter/src/kernels/ReduceMax.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/ReduceMax.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Reshape.cpp
onert-micro/luci-interpreter/src/kernels/ResizeBilinear.h [deleted file]
onert-micro/luci-interpreter/src/kernels/ResizeNearestNeighbor.cpp
onert-micro/luci-interpreter/src/kernels/ResizeNearestNeighbor.h [deleted file]
onert-micro/luci-interpreter/src/kernels/ResizeNearestNeighbor.test.cpp
onert-micro/luci-interpreter/src/kernels/Round.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Round.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Rsqrt.cpp
onert-micro/luci-interpreter/src/kernels/Rsqrt.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Rsqrt.test.cpp
onert-micro/luci-interpreter/src/kernels/SVDF.cpp
onert-micro/luci-interpreter/src/kernels/SVDF.h [deleted file]
onert-micro/luci-interpreter/src/kernels/SVDF.test.cpp
onert-micro/luci-interpreter/src/kernels/SelectV2.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/SelectV2.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Sin.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Sin.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Softmax.cpp
onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.cpp
onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.h [deleted file]
onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.test.cpp
onert-micro/luci-interpreter/src/kernels/SpaceToDepth.cpp
onert-micro/luci-interpreter/src/kernels/SpaceToDepth.h [deleted file]
onert-micro/luci-interpreter/src/kernels/SpaceToDepth.test.cpp
onert-micro/luci-interpreter/src/kernels/Sqrt.cpp
onert-micro/luci-interpreter/src/kernels/Sqrt.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Sqrt.test.cpp
onert-micro/luci-interpreter/src/kernels/Square.cpp
onert-micro/luci-interpreter/src/kernels/Square.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Square.test.cpp
onert-micro/luci-interpreter/src/kernels/SquaredDifference.cpp
onert-micro/luci-interpreter/src/kernels/SquaredDifference.h [deleted file]
onert-micro/luci-interpreter/src/kernels/SquaredDifference.test.cpp
onert-micro/luci-interpreter/src/kernels/Squeeze.cpp
onert-micro/luci-interpreter/src/kernels/Squeeze.test.cpp
onert-micro/luci-interpreter/src/kernels/Sub.cpp
onert-micro/luci-interpreter/src/kernels/Sub.test.cpp
onert-micro/luci-interpreter/src/kernels/Sum.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/Sum.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/TransposeConv.cpp
onert-micro/luci-interpreter/src/kernels/TransposeConv.h [deleted file]
onert-micro/luci-interpreter/src/kernels/TransposeConv.test.cpp
onert-micro/luci-interpreter/src/kernels/Unpack.cpp
onert-micro/luci-interpreter/src/kernels/Unpack.h [deleted file]
onert-micro/luci-interpreter/src/kernels/Unpack.test.cpp
onert-micro/luci-interpreter/src/kernels/Utils.cpp
onert-micro/luci-interpreter/src/kernels/Utils.h
onert-micro/luci-interpreter/src/kernels/ZerosLike.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/kernels/ZerosLike.test.cpp [new file with mode: 0644]
onert-micro/luci-interpreter/src/loader/GraphLoader.cpp
onert-micro/onert-micro/CMakeLists.txt [new file with mode: 0644]
onert-micro/onert-micro/include/OMConfig.h [new file with mode: 0644]
onert-micro/onert-micro/include/OMInterpreter.h [new file with mode: 0644]
onert-micro/onert-micro/include/OMStatus.h [new file with mode: 0644]
onert-micro/onert-micro/include/OMTrainingInterpreter.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/OMDataType.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/OMKernelData.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/OMKernelType.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/OMRuntimeContext.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/OMRuntimeGraph.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/OMRuntimeModule.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/OMRuntimeShape.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/OMRuntimeStorage.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/OMTrainingRuntimeModule.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/OMUtils.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/memory/OMMemoryManager.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/memory/OMRuntimeAllocator.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/reader/OMCircleReader.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/reader/OMWeightOnlyFormatReader.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/train/OMCheckpointLoader.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/train/OMCheckpointSaver.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/train/OMTrainingHandler.h [new file with mode: 0644]
onert-micro/onert-micro/include/core/train/OMTrainingStorage.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/OMExecuteArgs.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/OMKernelExecute.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/OMKernelExecutionBuilder.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/OMRuntimeKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/OMTestUtils.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/OMUtils.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/kernels/ArgCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/kernels/ComparisonCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/kernels/ConvolutionCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/kernels/MathCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/kernels/PoolingCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/kernels/ReadKernelDataCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/kernels/ReluCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/kernels/ReshapeCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/execute/kernels/SpacesBatchesNDCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/import/OMConfigureArgs.h [new file with mode: 0644]
onert-micro/onert-micro/include/import/OMExecutionPlanCreator.h [new file with mode: 0644]
onert-micro/onert-micro/include/import/OMKernelConfiguration.h [new file with mode: 0644]
onert-micro/onert-micro/include/import/OMKernelConfigureBuilder.h [new file with mode: 0644]
onert-micro/onert-micro/include/import/helpers/OMArgCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/import/helpers/OMConfigureSISOKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/import/helpers/OMConfigureTISOKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/import/helpers/OMPadCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/import/helpers/OMPooingCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/import/helpers/OMSpacesBatchesNDCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/onert-micro-version.h [new file with mode: 0644]
onert-micro/onert-micro/include/onert-micro.h [new file with mode: 0644]
onert-micro/onert-micro/include/optimize/BuildPass.lst [new file with mode: 0644]
onert-micro/onert-micro/include/optimize/OMGraphStatus.h [new file with mode: 0644]
onert-micro/onert-micro/include/optimize/OMOptimizePassesBuilder.h [new file with mode: 0644]
onert-micro/onert-micro/include/optimize/OMOptimizer.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/CustomKernelsToBuild.lst [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/KernelsToBuild.lst [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/KernelsToTrain.lst [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/PALAdd.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/PALAveragePool2D.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/PALConv2D.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/PALDepthwiseConv2D.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/PALFullyConnected.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/PALMaxPool2D.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/PALMul.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/PALSoftmax.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/cmsisnn/pal.cmake [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALAbs.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALAddCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALAddNCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALArgMinMaxCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALArithmeticOpCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALAveragePool2DCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALBatchToSpaceNDCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALBinaryOpCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALComparisons.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALConcatenation.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALConv2DCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALConv2DInputGrad.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALConv2DWeightGrad.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALCosCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALDepthwiseConv2DCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALDequantize.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALDivCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALExpCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALFloorCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALFloorDivCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALFloorModCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALFullyConnectedCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALFullyConnectedInputGrad.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALFullyConnectedWeightGrad.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALGatherND.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALL2Normalize.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALL2Pool2DCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALLogCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALLogSoftmax.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALLogistic.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALMaxPool2DCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALMaxPool2DInputGrad.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALMaximumCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALMinimumCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALMulCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALNegCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALPad.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALReluCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALReluInputGrad.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALRoundCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALRsqrtCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSISOOperation.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSinCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSlice.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSoftmaxCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSoftmaxInputGrad.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSpaceToBatchNDCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSpaceToDepthCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSplit.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSqrtCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSquareCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSquaredDifferenceCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALStridedSlice.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALSubCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALTanhCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALTransposeCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALTransposeConvCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALUnaryOpCommon.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALUnpack.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/PALUtils.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/common/ProcessBroadcastShapes.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/CustomKernelsToBuild.lst [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/KernelsToTrain.lst [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALAdd.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALAddN.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALArgMax.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALArgMin.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALAveragePool2D.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALBatchToSpaceND.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALConv2D.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALCos.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALDepthwiseConv2D.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALDiv.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALExp.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALFloor.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALFloorDiv.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALFloorMod.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALFullyConnected.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALL2Pool2D.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALLog.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALMaxPool2D.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALMaximum.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALMinimum.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALMul.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALNeg.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALRound.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALRsqrt.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALSin.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALSoftmax.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALSpaceToBatchND.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALSpaceToDepth.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALSqrt.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALSquare.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALSquaredDifference.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALSub.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALTanh.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALTranspose.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/PALTransposeConv.h [new file with mode: 0644]
onert-micro/onert-micro/include/pal/mcu/pal.cmake [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/TestDataBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/abs/FloatAbsKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/abs/NegAbsKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/abs/TestDataAbsBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/add/FloatAddKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/add/IntAddKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/add/NegAddKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/add/QuantAddKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/add/TestDataAddBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/add_n/FloatAddNKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/add_n/NegAddNKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/add_n/TestDataAddNBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/arg_max/FloatArgMaxKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/arg_max/NegArgMaxKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/arg_max/TestDataArgMaxBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/arg_min/FloatArgMinKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/arg_min/NegArgMinKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/arg_min/TestDataArgMinBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/averagepool2d/FloatAveragePool2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/averagepool2d/NegAveragePool2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/averagepool2d/QuantAveragePool2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/averagepool2d/TestDataAveragePool2DBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/batch_to_space_nd/TestDataBatchToSpaceNDBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/concatenation/FloatConcatenationKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/concatenation/IntConcatenationKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/concatenation/NegConcatenationKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/concatenation/TestDataConcatenationBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/conv2d/FloatConv2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/conv2d/NegConv2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/conv2d/QuantConv2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/conv2d/TestDataConv2DBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/cos/FloatCosKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/cos/NegCosKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/cos/TestDataCosBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/depthwise_conv_2d/FloatDepthwiseConv2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/depthwise_conv_2d/NegDepthwiseConv2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/depthwise_conv_2d/QuantDepthwiseConv2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/depthwise_conv_2d/TestDataDepthwiseConv2DBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/dequantize/FloatDequantizeKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/dequantize/NegDequantizeKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/dequantize/TestDataDequantizeBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/div/FloatDivKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/div/IntDivKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/div/NegDivKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/div/TestDataDivBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/equal/FloatEqualKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/equal/IntEqualKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/equal/TestDataEqualBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/exp/FloatExpKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/exp/NegExpKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/exp/TestDataExpBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/expand_dims/ExpandDimsKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/floor/FloatFloorKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/floor/NegFloorKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/floor/TestDataFloorBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/floordiv/FloatFloorDivKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/floordiv/NegFloorDivKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/floordiv/TestDataFloorDivBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/floormod/FloatFloorModKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/floormod/NegFloorModKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/floormod/TestDataFloorModBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/fully_connected/FloatFullyConnectedKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/fully_connected/NegFullyConnectedKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/fully_connected/QuantFullyConnectedKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/fully_connected/TestDataFullyConnectedBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/gather/FloatGatherKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/gather/IntGatherKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/gather/NegGatherKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/gather/TestDataGatherBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/gather_nd/FloatGatherNDKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/gather_nd/NegGatherNDKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/gather_nd/TestDataGatherNDBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/greater/FloatGreaterKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/greater/NegGreaterKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/greater/TestDataGreaterBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/greater_equal/FloatGreaterEqualKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/greater_equal/NegGreaterEqualKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/greater_equal/TestDataGreaterEqualBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/l2_normalization/FloatL2NormalizeKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/l2_normalization/NegL2NormalizeKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/l2_normalization/TestDataL2NormalizeBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/l2pool2d/FloatL2Pool2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/l2pool2d/NegL2Pool2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/l2pool2d/TestDataL2Pool2DBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/leaky_relu/FloatLeakyReLUKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/leaky_relu/NegLeakyReLUKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/leaky_relu/TestDataLeakyReLUBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/less/FloatLessKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/less/IntLessKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/less/NegTestDataLessKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/less/QuantLessKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/less/TestDataLessBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/less_equal/FloatLessEqualKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/less_equal/TestDataLessEqualBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/log/FloatLogKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/log/NegLogKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/log/TestDataLogBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/log_softmax/FloatLogSoftmaxKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/log_softmax/NegLogSoftmaxKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/log_softmax/TestDataLogSoftmaxBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/logistic/FloatLogisticKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/logistic/NegLogisticKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/logistic/TestDataLogisticBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/maximum/FloatMaximumKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/maximum/NegMaximumKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/maximum/TestDataMaximumBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/maxpool2d/FloatMaxPool2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/maxpool2d/NegMaxPool2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/maxpool2d/QuantMaxPool2DKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/maxpool2d/TestDataMaxPool2DBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/minimum/FloatMinimumKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/minimum/NegMinimumKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/minimum/TestDataMinimumBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/mul/FloatMulKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/mul/IntMulKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/mul/NegMulKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/mul/QuantMulKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/mul/TestDataMulBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/neg/FloatNegKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/neg/NegNegKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/neg/TestDataNegBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/notequal/FloatNotEqualKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/notequal/TestDataNotEqualBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/pack/PackKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/pack/TestDataPackBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/pad/FloatPadKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/pad/NegPadKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/pad/TestDataPadBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/relu/FloatReLUKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/relu/NegReLUKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/relu/TestDataReLUBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/relu6/FloatReLU6Kernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/relu6/NegReLU6Kernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/relu6/TestDataReLU6Base.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/reshape/ReshapeKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/round/FloatRoundKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/round/NegRoundKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/round/TestDataRoundBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/rsqrt/FloatRsqrtKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/rsqrt/NegRsqrtKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/rsqrt/TestDataRsqrtBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/shape/NegShapeKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/shape/ShapeKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/sin/FloatSinKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/sin/NegSinKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/sin/TestDataSinBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/slice/FloatSliceKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/slice/IntSliceKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/slice/NegSliceKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/slice/TestDataSliceBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/softmax/FloatSoftmaxKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/softmax/NegSoftmaxKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/softmax/QuantSoftmaxKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/softmax/TestDataSoftmaxBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/space_to_batch_nd/FloatSpaceToBatchNDKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/space_to_batch_nd/NegSpaceToBatchNDKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/space_to_batch_nd/TestDataSpaceToBatchNDBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/space_to_depth/FloatSpaceToDepthKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/space_to_depth/NegSpaceToDepthKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/space_to_depth/TestDataSpaceToDepthBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/split/FloatSplitKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/split/NegSplitKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/split/TestDataSplitBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/sqrt/FloatSqrtKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/sqrt/NegSqrtKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/sqrt/TestDataSqrtBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/square/FloatSquareKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/square/NegSquareKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/square/TestDataSquareBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/squared_difference/FloatSquaredDifferenceKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/squared_difference/NegSquaredDifferenceKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/squared_difference/TestDataSquaredDifferenceBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/strided_slice/StridedSliceKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/sub/FloatSubKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/sub/IntSubKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/sub/NegSubKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/sub/TestDataSubBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/tanh/FloatTanhKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/tanh/NegTanhKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/tanh/TestDataTanhBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/transpose/NegTransposeKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/transpose/TransposeKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/transpose_conv/FloatTransposeConvKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/transpose_conv/NegTransposeConvKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/transpose_conv/TestDataTransposeConvBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/unpack/FloatUnpackKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/unpack/NegUnpackKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/unpack/TestDataUnpackBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/while/NegWhileKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/test_models/while/WhileKernel.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/OMBackpropExecute.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/OMBackpropExecuteArgs.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/OMBackpropExecutionBuilder.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/losses_functions/CrossEntropy.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/losses_functions/MSE.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/metrics/Accuracy.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/metrics/CrossEntropy.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/metrics/MAE.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/metrics/MSE.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/OMTestTrainBase.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/OMTestUtils.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/boston_housing_task/BostonHousingTask.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/boston_housing_task/data/test_input.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/boston_housing_task/data/test_target.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/boston_housing_task/data/train_input.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/boston_housing_task/data/train_target.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/models/boston_housing.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/models/checkoint_simple_example_model.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/models/numbers_classification_model.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/models/saved_checkpoint_example.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/numbers_classification_task/NumbersClassificationTask.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/numbers_classification_task/data/train_input.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/tests/numbers_classification_task/data/train_target.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/train_optimizers/Adam.h [new file with mode: 0644]
onert-micro/onert-micro/include/train/train_optimizers/SGD.h [new file with mode: 0644]
onert-micro/onert-micro/src/CMakeLists.txt [new file with mode: 0644]
onert-micro/onert-micro/src/OMInterpreter.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/OMTrainingInterpreter.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/api/CMakeLists.txt [new file with mode: 0644]
onert-micro/onert-micro/src/api/onert-micro.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/CMakeLists.txt [new file with mode: 0644]
onert-micro/onert-micro/src/core/OMDataType.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/OMKernelType.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/OMRuntimeContext.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/OMRuntimeGraph.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/OMRuntimeModule.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/OMRuntimeStorage.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/OMTrainingRuntimeModule.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/OMUtils.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/memory/OMMemoryManager.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/memory/OMRuntimeAllocator.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/reader/OMCircleReader.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/reader/OMWeightOnlyFormatReader.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/train/OMCheckpointLoader.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/train/OMCheckpointSaver.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/train/OMTrainingHandler.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/core/train/OMTrainingStorage.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/CMakeLists.txt [new file with mode: 0644]
onert-micro/onert-micro/src/execute/OMKernelExecute.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/OMKernelExecutionBuilder.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/OMRuntimeKernel.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/OMTestUtils.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/OMUtils.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Abs.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Add.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/AddN.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/ArgCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/ArgMax.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/ArgMin.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/AveragePool2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/BatchToSpaceND.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Concatenation.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Conv2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/ConvolutionCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Cos.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/DepthwiseConv2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Dequantize.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Div.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Equal.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Exp.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/ExpandDims.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Floor.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/FloorDiv.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/FloorMod.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/FullyConnected.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Gather.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/GatherND.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Greater.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/GreaterEqual.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/L2Normalize.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/L2Pool2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/LeakyRelu.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Less.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/LessEqual.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Log.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/LogSoftmax.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Logistic.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/MathCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Maximum.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Minimum.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Mul.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Neg.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/NotEqual.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Pack.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Pad.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/PoolingCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/ReadKernelDataCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Relu.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Relu6.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/ReluCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Reshape.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/ReshapeCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Round.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Rsqrt.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Shape.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Sin.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Slice.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Softmax.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/SpaceToBatchND.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/SpaceToDepth.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/SpacesBatchesNDCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Split.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Sqrt.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Square.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/SquaredDifference.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/StridedSlice.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Sub.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Tanh.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Transpose.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/TransposeConv.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/Unpack.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/While.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Abs.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Add.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/AddN.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/ArgMax.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/ArgMin.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/AveragePool2D.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/BatchToSpaceND.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Concatenation.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Conv2D.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Cos.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/DepthwiseConv2D.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Dequantize.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Div.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Equal.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Exp.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/ExpandDims.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Floor.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/FloorDiv.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/FloorMod.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/FullyConnected.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Gather.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/GatherND.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Greater.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/GreaterEqual.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/L2Normalize.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/L2Pool2D.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/LeakyRelu.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Less.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/LessEqual.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Log.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/LogSoftmax.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Logistic.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/MaxPool2D.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Maximum.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Minimum.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Mul.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Neg.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/NotEqual.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Pack.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Pad.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Relu.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Relu6.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Reshape.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Round.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Rsqrt.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Shape.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Sin.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Slice.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Softmax.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/SpaceToBatchND.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/SpaceToDepth.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Split.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Sqrt.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Square.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/SquaredDifference.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/StridedSlice.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Sub.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Tanh.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Transpose.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/TransposeConv.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/Unpack.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/execute/kernels/tests/While.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/CMakeLists.txt [new file with mode: 0644]
onert-micro/onert-micro/src/import/OMExecutionPlanCreator.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/OMKernelConfiguration.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/OMKernelConfigureBuilder.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/helpers/OMArgCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/helpers/OMConfigureSISOKernel.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/helpers/OMConfigureTISOKernel.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/helpers/OMPadCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/helpers/OMPoolingCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/helpers/OMSpacesBatchesNDCommon.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Abs.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Add.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/AddN.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/ArgMax.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/ArgMin.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/AveragePool2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/BatchToSpaceND.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Concatenation.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Conv2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Cos.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/DepthwiseConv2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Dequantize.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Div.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Equal.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Exp.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/ExpandDims.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Floor.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/FloorDiv.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/FloorMod.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/FullyConnected.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Gather.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/GatherND.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Greater.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/GreaterEqual.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/L2Normalize.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/L2Pool2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/LeakyRelu.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Less.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/LessEqual.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Log.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/LogSoftmax.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Logistic.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/MaxPool2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Maximum.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Minimum.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Mul.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Neg.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/NotEqual.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Pack.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Pad.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Relu.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Relu6.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Reshape.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Round.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Rsqrt.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Shape.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Sin.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Slice.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Softmax.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/SpaceToBatchND.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/SpaceToDepth.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Split.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Sqrt.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Square.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/SquaredDifference.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/StridedSlice.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Sub.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Tanh.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Transpose.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/TransposeConv.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/Unpack.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/import/kernels/While.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/optimize/CMakeLists.txt [new file with mode: 0644]
onert-micro/onert-micro/src/optimize/OMOptimizer.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/optimize/pass/FindInplaceOpPass.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/CMakeLists.txt [new file with mode: 0644]
onert-micro/onert-micro/src/train/OMBackpropExecute.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/OMBackpropExecutionBuilder.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/kernels/Conv2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/kernels/FullyConnected.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/kernels/MaxPool2D.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/kernels/Reshape.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/kernels/Softmax.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/losses_functions/CrossEntropy.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/losses_functions/MSE.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/metrics/Accuracy.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/metrics/CrossEntropy.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/metrics/MAE.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/metrics/MSE.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/tests/BostonHousingTask.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/tests/CheckpointsHandler.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/tests/NumbersClassificationTask.test.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/train_optimizers/Adam.cpp [new file with mode: 0644]
onert-micro/onert-micro/src/train/train_optimizers/SGD.cpp [new file with mode: 0644]
onert-micro/standalone/CMakeLists.txt
packaging/ABSEIL.tar.gz
packaging/CPUINFO.tar.gz
packaging/EGL_HEADERS.tar.gz [deleted file]
packaging/FARMHASH.tar.gz
packaging/FLATBUFFERS-2.0.tar.gz [deleted file]
packaging/FLATBUFFERS-23.5.26.tar.gz [new file with mode: 0644]
packaging/FP16.tar.gz
packaging/FXDIV.tar.gz
packaging/MLDTYPES.tar.gz [new file with mode: 0644]
packaging/NEON2SSE.tar.gz [new file with mode: 0644]
packaging/OPENCL_HEADERS.tar.gz [deleted file]
packaging/OPENGL_HEADERS.tar.gz [deleted file]
packaging/PTHREADPOOL.tar.gz
packaging/TENSORFLOW-2.16.1-EIGEN.tar.gz [new file with mode: 0644]
packaging/TENSORFLOW-2.16.1-GEMMLOWP.tar.gz [new file with mode: 0644]
packaging/TENSORFLOW-2.16.1-RUY.tar.gz [new file with mode: 0644]
packaging/TENSORFLOW-2.16.1.tar.gz [new file with mode: 0644]
packaging/TENSORFLOW-2.8.0-EIGEN.tar.gz [deleted file]
packaging/TENSORFLOW-2.8.0-GEMMLOWP.tar.gz [deleted file]
packaging/TENSORFLOW-2.8.0-RUY.tar.gz [deleted file]
packaging/TENSORFLOW-2.8.0.tar.gz [deleted file]
packaging/VULKAN.tar.gz [deleted file]
packaging/XNNPACK.tar.gz
packaging/nnfw.spec
res/CircleRecipes/CircleBatchMatMul_I4_000/test.recipe [new file with mode: 0644]
res/CircleRecipes/CircleBatchMatMul_U4_000/test.recipe [new file with mode: 0644]
res/CircleRecipes/CircleFullyConnected_U4_000/test.recipe [new file with mode: 0644]
res/CircleRecipes/CircleFullyConnected_U4_001/test.recipe [new file with mode: 0644]
res/CircleRecipes/CircleFullyConnected_U4_002/ref.input0 [new file with mode: 0644]
res/CircleRecipes/CircleFullyConnected_U4_002/ref.output0 [new file with mode: 0644]
res/CircleRecipes/CircleFullyConnected_U4_002/test.recipe [new file with mode: 0644]
res/CircleRecipes/GRU_000/test.recipe [new file with mode: 0644]
res/CircleRecipes/GRU_000/test.reverse [new file with mode: 0644]
res/CircleSchema/0.6/circle_schema.fbs
res/CircleSchema/0.7/circle_schema.fbs [new file with mode: 0644]
res/CircleSchema/0.8/circle_schema.fbs [new file with mode: 0644]
res/TensorFlowLiteRecipes/All_000/test.recipe
res/TensorFlowLiteRecipes/BatchMatMulV2_000/test.recipe
res/TensorFlowLiteRecipes/BatchMatMulV2_001/test.recipe
res/TensorFlowLiteRecipes/BroadcastTo_000/test.recipe
res/TensorFlowLiteRecipes/BroadcastTo_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/BroadcastTo_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/BroadcastTo_001/test.reverse [new file with mode: 0644]
res/TensorFlowLiteRecipes/CSE_Quantize_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/CSE_Quantize_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/CSE_Quantize_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/CSE_Quantize_001/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/CSE_Transpose_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/CSE_Transpose_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/CSE_Transpose_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/CSE_Transpose_001/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/CumSum_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/CumSum_000/test.reverse [new file with mode: 0644]
res/TensorFlowLiteRecipes/FullyConnected_I4_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/FullyConnected_I4_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/FullyConnected_I4_002/ref.input0 [new file with mode: 0644]
res/TensorFlowLiteRecipes/FullyConnected_I4_002/ref.output0 [new file with mode: 0644]
res/TensorFlowLiteRecipes/FullyConnected_I4_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/MatMul_000/test.recipe
res/TensorFlowLiteRecipes/MatrixBandPart_000/test.recipe
res/TensorFlowLiteRecipes/MaxPoolWithArgmax_000/test.recipe
res/TensorFlowLiteRecipes/MaxPoolWithArgmax_001/test.recipe
res/TensorFlowLiteRecipes/MaxPoolWithArgmax_002/test.recipe
res/TensorFlowLiteRecipes/Net_Add_FloorMod_Gather_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Add_FloorMod_Gather_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Add_FullyConnected_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Add_FullyConnected_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Add_FullyConnected_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Add_FullyConnected_001/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Add_FullyConnected_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Add_FullyConnected_002/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_BroadcastTo_AddV2_000/test.recipe
res/TensorFlowLiteRecipes/Net_BroadcastTo_AddV2_001/test.recipe
res/TensorFlowLiteRecipes/Net_BroadcastTo_AddV2_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_BroadcastTo_AddV2_002/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Add_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Add_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Add_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Add_001/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Add_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Add_002/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Mul_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Mul_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Mul_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Mul_001/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Mul_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Mul_002/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Mul_003/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Conv_Mul_003/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_FC_Gelu_FC_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_FC_Gelu_FC_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Gather_SparseToDense_AddV2_000/test.recipe
res/TensorFlowLiteRecipes/Net_Gelu_000/test.recipe
res/TensorFlowLiteRecipes/Net_Gelu_001/test.recipe
res/TensorFlowLiteRecipes/Net_Horizontal_FullyConnected_Add_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Horizontal_FullyConnected_Add_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Add_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Add_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Add_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Add_001/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Add_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Add_002/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Add_003/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Add_003/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Div_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Div_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Div_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_Div_001/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_001/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_002/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Reshape_Mean_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Shape_Add_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Shape_Add_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Sqrt_Div_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Sqrt_Div_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_TConv_Slice_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_TConv_Slice_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_TConv_Slice_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_TConv_Slice_001/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_TConv_Slice_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_TConv_Slice_002/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_TConv_Slice_003/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_TConv_Slice_003/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Trans_Reshape_Trans_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Net_Trans_Reshape_Trans_000/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Quant_Mul_002/test.qconf.json [new file with mode: 0644]
res/TensorFlowLiteRecipes/Quant_Mul_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Quant_Mul_002/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/ReLU0To1_000/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/ReLU0To1_000/test.reverse [new file with mode: 0644]
res/TensorFlowLiteRecipes/Softmax_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Softmax_001/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Softmax_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Softmax_002/test.rule [new file with mode: 0644]
res/TensorFlowLiteRecipes/Tile_001/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Tile_001/test.reverse [new file with mode: 0644]
res/TensorFlowLiteRecipes/Tile_002/test.recipe [new file with mode: 0644]
res/TensorFlowLiteRecipes/Tile_002/test.reverse [new file with mode: 0644]
res/TensorFlowLiteRecipes/TransposeConv_002/test.recipe [new file with mode: 0644]
runtime/3rdparty/half/README.md [new file with mode: 0644]
runtime/3rdparty/half/include/half/ChangeLog.txt
runtime/3rdparty/half/include/half/LICENSE.txt
runtime/3rdparty/half/include/half/README.txt
runtime/3rdparty/half/include/half/include/half.hpp
runtime/3rdparty/jsoncpp/README.md
runtime/3rdparty/jsoncpp/json/json-forwards.h
runtime/3rdparty/jsoncpp/json/json.h
runtime/3rdparty/jsoncpp/jsoncpp.cpp
runtime/contrib/TFLiteSharp/TFLiteNative/include/tflite_log.h
runtime/contrib/android/api/Prebuilt.mk
runtime/contrib/android/api/build.gradle
runtime/contrib/android/build.gradle
runtime/contrib/android/gradle/wrapper/gradle-wrapper.jar
runtime/contrib/android/gradle/wrapper/gradle-wrapper.properties
runtime/contrib/android/gradlew
runtime/contrib/android/gradlew.bat
runtime/contrib/detection/CMakeLists.txt
runtime/contrib/detection/detection.cpp
runtime/contrib/gpu_cl/Backend.h [moved from runtime/onert/backend/gpu_cl/Backend.h with 100% similarity]
runtime/contrib/gpu_cl/BackendContext.cc [new file with mode: 0644]
runtime/contrib/gpu_cl/BackendContext.h [moved from runtime/onert/backend/gpu_cl/BackendContext.h with 100% similarity]
runtime/contrib/gpu_cl/CMakeLists.txt [new file with mode: 0644]
runtime/contrib/gpu_cl/ClConstantInitializer.cc [moved from runtime/onert/backend/gpu_cl/ClConstantInitializer.cc with 100% similarity]
runtime/contrib/gpu_cl/ClConstantInitializer.h [new file with mode: 0644]
runtime/contrib/gpu_cl/ClFunction.h [moved from runtime/onert/backend/gpu_cl/ClFunction.h with 100% similarity]
runtime/contrib/gpu_cl/Config.cc [moved from runtime/onert/backend/gpu_cl/Config.cc with 100% similarity]
runtime/contrib/gpu_cl/Config.h [moved from runtime/onert/backend/gpu_cl/Config.h with 100% similarity]
runtime/contrib/gpu_cl/ConstantInitializer.cc [moved from runtime/onert/backend/gpu_cl/ConstantInitializer.cc with 100% similarity]
runtime/contrib/gpu_cl/ConstantInitializer.h [moved from runtime/onert/backend/gpu_cl/ConstantInitializer.h with 100% similarity]
runtime/contrib/gpu_cl/KernelGenerator.cc [new file with mode: 0644]
runtime/contrib/gpu_cl/KernelGenerator.h [moved from runtime/onert/backend/gpu_cl/KernelGenerator.h with 100% similarity]
runtime/contrib/gpu_cl/MemoryManager.h [moved from runtime/onert/backend/gpu_cl/MemoryManager.h with 100% similarity]
runtime/contrib/gpu_cl/TensorBuilder.cc [moved from runtime/onert/backend/gpu_cl/TensorBuilder.cc with 100% similarity]
runtime/contrib/gpu_cl/TensorBuilder.h [moved from runtime/onert/backend/gpu_cl/TensorBuilder.h with 100% similarity]
runtime/contrib/gpu_cl/TensorManager.cc [moved from runtime/onert/backend/gpu_cl/TensorManager.cc with 100% similarity]
runtime/contrib/gpu_cl/TensorManager.h [moved from runtime/onert/backend/gpu_cl/TensorManager.h with 100% similarity]
runtime/contrib/gpu_cl/TensorRegistry.h [moved from runtime/onert/backend/gpu_cl/TensorRegistry.h with 100% similarity]
runtime/contrib/gpu_cl/Utils.h [moved from runtime/onert/backend/gpu_cl/Utils.h with 100% similarity]
runtime/contrib/gpu_cl/gpu_cl.cc [moved from runtime/onert/backend/gpu_cl/gpu_cl.cc with 100% similarity]
runtime/contrib/gpu_cl/operand/CLTensor.cc [moved from runtime/onert/backend/gpu_cl/operand/CLTensor.cc with 100% similarity]
runtime/contrib/gpu_cl/operand/CLTensor.h [moved from runtime/onert/backend/gpu_cl/operand/CLTensor.h with 100% similarity]
runtime/contrib/gpu_cl/operand/ICLTensor.cc [new file with mode: 0644]
runtime/contrib/gpu_cl/operand/ICLTensor.h [moved from runtime/onert/backend/gpu_cl/operand/ICLTensor.h with 100% similarity]
runtime/contrib/logging/CMakeLists.txt
runtime/contrib/logging/src/nnapi_logging.cc
runtime/contrib/mlapse/tfl/CMakeLists.txt
runtime/contrib/mlapse/tfl/mlapse/benchmark_runner.cc
runtime/contrib/style_transfer_app/CMakeLists.txt
runtime/contrib/style_transfer_app/src/args.cc
runtime/contrib/style_transfer_app/src/jpeg_helper.cc
runtime/contrib/tflite_classify/CMakeLists.txt
runtime/contrib/tflite_classify/src/tflite_classify.cc
runtime/libs/benchmark/CMakeLists.txt [deleted file]
runtime/libs/benchmark/src/Result.cpp [deleted file]
runtime/libs/circle-schema/CMakeLists.txt [new file with mode: 0644]
runtime/libs/circle-schema/include/circle_schema_generated.h [new file with mode: 0644]
runtime/libs/circle-schema/include/circle_traininfo.fbs [new file with mode: 0644]
runtime/libs/circle-schema/include/circle_traininfo_generated.h [new file with mode: 0644]
runtime/libs/misc/include/misc/RandomGenerator.h [deleted file]
runtime/libs/misc/include/misc/benchmark.h [deleted file]
runtime/libs/misc/include/misc/string_helpers.h
runtime/libs/misc/include/misc/to_underlying.h [new file with mode: 0644]
runtime/libs/misc/src/RandomGenerator.cpp [deleted file]
runtime/libs/tflite/CMakeLists.txt [deleted file]
runtime/libs/tflite/include/tflite/Diff.h [deleted file]
runtime/libs/tflite/include/tflite/InterpreterSession.h [deleted file]
runtime/libs/tflite/include/tflite/RandomInputInitializer.h [deleted file]
runtime/libs/tflite/src/Diff.cpp [deleted file]
runtime/libs/tflite/src/RandomInputInitializer.cpp [deleted file]
runtime/onert/CMakeLists.txt
runtime/onert/api/CMakeLists.txt
runtime/onert/api/include/nnfw.h [deleted file]
runtime/onert/api/include/nnfw_experimental.h [deleted file]
runtime/onert/api/include/nnfw_internal.h [deleted file]
runtime/onert/api/include/nnfw_version.h [deleted file]
runtime/onert/api/nnapi/CMakeLists.txt [moved from runtime/onert/frontend/nnapi/CMakeLists.txt with 100% similarity]
runtime/onert/api/nnapi/compilation.cc [moved from runtime/onert/frontend/nnapi/compilation.cc with 100% similarity]
runtime/onert/api/nnapi/event.cc [moved from runtime/onert/frontend/nnapi/event.cc with 100% similarity]
runtime/onert/api/nnapi/execution.cc [moved from runtime/onert/frontend/nnapi/execution.cc with 100% similarity]
runtime/onert/api/nnapi/memory.cc [moved from runtime/onert/frontend/nnapi/memory.cc with 100% similarity]
runtime/onert/api/nnapi/model.cc [moved from runtime/onert/frontend/nnapi/model.cc with 100% similarity]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksCompilation.cc [new file with mode: 0644]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksCompilation.h [new file with mode: 0644]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksEvent.cc [moved from runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksEvent.cc with 100% similarity]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksEvent.h [moved from runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksEvent.h with 100% similarity]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksExecution.cc [new file with mode: 0644]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksExecution.h [moved from runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.h with 100% similarity]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksMemory.cc [moved from runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksMemory.cc with 100% similarity]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksMemory.h [moved from runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksMemory.h with 100% similarity]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksModel.cc [new file with mode: 0644]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksModel.h [moved from runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.h with 100% similarity]
runtime/onert/api/nnapi/wrapper/ANeuralNetworksModel.test.cc [moved from runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.test.cc with 100% similarity]
runtime/onert/api/nnapi/wrapper/NNAPIConvert.cc [moved from runtime/onert/frontend/nnapi/wrapper/NNAPIConvert.cc with 100% similarity]
runtime/onert/api/nnapi/wrapper/NNAPIConvert.h [moved from runtime/onert/frontend/nnapi/wrapper/NNAPIConvert.h with 100% similarity]
runtime/onert/api/nnapi/wrapper/OperationFactory.cc [moved from runtime/onert/frontend/nnapi/wrapper/OperationFactory.cc with 100% similarity]
runtime/onert/api/nnapi/wrapper/OperationFactory.h [moved from runtime/onert/frontend/nnapi/wrapper/OperationFactory.h with 100% similarity]
runtime/onert/api/nnfw/CMakeLists.txt [new file with mode: 0644]
runtime/onert/api/nnfw/include/nnfw.h [new file with mode: 0644]
runtime/onert/api/nnfw/include/nnfw_experimental.h [new file with mode: 0644]
runtime/onert/api/nnfw/include/nnfw_internal.h [new file with mode: 0644]
runtime/onert/api/nnfw/include/nnfw_version.h [new file with mode: 0644]
runtime/onert/api/nnfw/src/CustomKernel.cc [moved from runtime/onert/api/src/CustomKernel.cc with 100% similarity]
runtime/onert/api/nnfw/src/CustomKernel.h [moved from runtime/onert/api/src/CustomKernel.h with 100% similarity]
runtime/onert/api/nnfw/src/CustomKernelRegistry.cc [moved from runtime/onert/api/src/CustomKernelRegistry.cc with 100% similarity]
runtime/onert/api/nnfw/src/CustomKernelRegistry.h [moved from runtime/onert/api/src/CustomKernelRegistry.h with 100% similarity]
runtime/onert/api/nnfw/src/OpMap.lst [new file with mode: 0644]
runtime/onert/api/nnfw/src/nnfw_api.cc [new file with mode: 0644]
runtime/onert/api/nnfw/src/nnfw_api_internal.cc [new file with mode: 0644]
runtime/onert/api/nnfw/src/nnfw_api_internal.h [new file with mode: 0644]
runtime/onert/api/nnfw/src/nnfw_debug.cc [moved from runtime/onert/api/src/nnfw_debug.cc with 100% similarity]
runtime/onert/api/python/CMakeLists.txt [new file with mode: 0644]
runtime/onert/api/python/include/nnfw_api_wrapper.h [new file with mode: 0644]
runtime/onert/api/python/package/__init__.py [new file with mode: 0644]
runtime/onert/api/python/package/libnnfw_api_pybind.py [new file with mode: 0644]
runtime/onert/api/python/src/nnfw_api_wrapper.cc [new file with mode: 0644]
runtime/onert/api/python/src/nnfw_api_wrapper_pybind.cc [new file with mode: 0644]
runtime/onert/api/src/OpMap.lst [deleted file]
runtime/onert/api/src/nnfw_api.cc [deleted file]
runtime/onert/api/src/nnfw_api_internal.cc [deleted file]
runtime/onert/api/src/nnfw_api_internal.h [deleted file]
runtime/onert/backend/CMakeLists.txt
runtime/onert/backend/acl_cl/CMakeLists.txt
runtime/onert/backend/acl_cl/KernelGenerator.cc
runtime/onert/backend/acl_cl/Optimizer.cc
runtime/onert/backend/acl_common/AclKernelGen.h
runtime/onert/backend/acl_neon/CMakeLists.txt
runtime/onert/backend/acl_neon/KernelGenerator.cc
runtime/onert/backend/acl_neon/Optimizer.cc
runtime/onert/backend/cl_common/include/cl_common/BackendContext.h
runtime/onert/backend/cpu/BackendContext.cc
runtime/onert/backend/cpu/CMakeLists.txt
runtime/onert/backend/cpu/KernelGenerator.cc
runtime/onert/backend/cpu/ops/BinaryArithmeticLayer.cc
runtime/onert/backend/cpu/ops/BinaryArithmeticLayer.h
runtime/onert/backend/cpu/ops/CompareLayer.cc
runtime/onert/backend/cpu/ops/ConvolutionLayer.cc
runtime/onert/backend/cpu/ops/ConvolutionLayer.h
runtime/onert/backend/cpu/ops/DepthwiseConvolutionLayer.h
runtime/onert/backend/cpu/ops/DetectionPostProcessLayer.cc
runtime/onert/backend/cpu/ops/ElementwiseActivationLayer.cc
runtime/onert/backend/cpu/ops/ElementwiseBinaryLayer.cc
runtime/onert/backend/cpu/ops/ElementwiseBinaryLayer.h
runtime/onert/backend/cpu/ops/ElementwiseUnaryLayer.cc
runtime/onert/backend/cpu/ops/MeanLayer.h
runtime/onert/backend/cpu/ops/OperationUtils.h
runtime/onert/backend/cpu/ops/PadLayer.cc
runtime/onert/backend/cpu/ops/PadLayer.h
runtime/onert/backend/cpu/ops/PoolLayer.h
runtime/onert/backend/cpu/ops/ReduceLayer.cc
runtime/onert/backend/cpu/ops/SoftMaxLayer.h
runtime/onert/backend/gpu_cl/BackendContext.cc [deleted file]
runtime/onert/backend/gpu_cl/CMakeLists.txt [deleted file]
runtime/onert/backend/gpu_cl/ClConstantInitializer.h [deleted file]
runtime/onert/backend/gpu_cl/KernelGenerator.cc [deleted file]
runtime/onert/backend/gpu_cl/operand/ICLTensor.cc [deleted file]
runtime/onert/backend/ruy/BackendContext.cc
runtime/onert/backend/ruy/CMakeLists.txt
runtime/onert/backend/ruy/KernelGenerator.cc
runtime/onert/backend/train/Backend.h
runtime/onert/backend/train/BackendContext.cc
runtime/onert/backend/train/BackendContext.h
runtime/onert/backend/train/CMakeLists.txt
runtime/onert/backend/train/DisposableTensorIndex.h [new file with mode: 0644]
runtime/onert/backend/train/KernelGenerator.cc
runtime/onert/backend/train/KernelGenerator.h
runtime/onert/backend/train/MemoryManager.cc [new file with mode: 0644]
runtime/onert/backend/train/MemoryManager.h
runtime/onert/backend/train/MemoryPlanner.cc [new file with mode: 0644]
runtime/onert/backend/train/MemoryPlanner.h [new file with mode: 0644]
runtime/onert/backend/train/MemoryPlanner.test.cc [new file with mode: 0644]
runtime/onert/backend/train/MemoryPlannerFactory.cc [new file with mode: 0644]
runtime/onert/backend/train/MemoryPlannerFactory.h [new file with mode: 0644]
runtime/onert/backend/train/Tensor.h
runtime/onert/backend/train/TensorBuilder.cc
runtime/onert/backend/train/TensorBuilder.h
runtime/onert/backend/train/TensorManager.cc
runtime/onert/backend/train/TensorManager.h
runtime/onert/backend/train/TensorRegistry.h
runtime/onert/backend/train/ops/BackPropAccumulator.cc [new file with mode: 0644]
runtime/onert/backend/train/ops/BackPropAccumulator.h [new file with mode: 0644]
runtime/onert/backend/train/ops/BackPropInitializer.cc [new file with mode: 0644]
runtime/onert/backend/train/ops/BackPropInitializer.h [new file with mode: 0644]
runtime/onert/backend/train/ops/BinaryArithmeticLayer.cc [new file with mode: 0644]
runtime/onert/backend/train/ops/BinaryArithmeticLayer.h [new file with mode: 0644]
runtime/onert/backend/train/ops/ConvolutionLayer.cc
runtime/onert/backend/train/ops/ConvolutionLayer.h
runtime/onert/backend/train/ops/DepthwiseConvolutionLayer.cc [new file with mode: 0644]
runtime/onert/backend/train/ops/DepthwiseConvolutionLayer.h [new file with mode: 0644]
runtime/onert/backend/train/ops/ElementwiseActivationLayer.cc
runtime/onert/backend/train/ops/ElementwiseActivationLayer.h
runtime/onert/backend/train/ops/FullyConnectedLayer.cc
runtime/onert/backend/train/ops/FullyConnectedLayer.h
runtime/onert/backend/train/ops/GradientApplier.cc
runtime/onert/backend/train/ops/GradientApplier.h
runtime/onert/backend/train/ops/LossCategoricalCrossentropyLayer.cc [new file with mode: 0644]
runtime/onert/backend/train/ops/LossCategoricalCrossentropyLayer.h [new file with mode: 0644]
runtime/onert/backend/train/ops/LossLayer.cc
runtime/onert/backend/train/ops/LossLayer.h
runtime/onert/backend/train/ops/LossMeanSquaredErrorLayer.cc [new file with mode: 0644]
runtime/onert/backend/train/ops/LossMeanSquaredErrorLayer.h [new file with mode: 0644]
runtime/onert/backend/train/ops/MeanLayer.cc [new file with mode: 0644]
runtime/onert/backend/train/ops/MeanLayer.h [new file with mode: 0644]
runtime/onert/backend/train/ops/OperationUtils.cc [new file with mode: 0644]
runtime/onert/backend/train/ops/OperationUtils.h
runtime/onert/backend/train/ops/PadLayer.cc [new file with mode: 0644]
runtime/onert/backend/train/ops/PadLayer.h [new file with mode: 0644]
runtime/onert/backend/train/ops/PoolLayer.cc
runtime/onert/backend/train/ops/PoolLayer.h
runtime/onert/backend/train/ops/ReshapeLayer.cc
runtime/onert/backend/train/ops/ReshapeLayer.h
runtime/onert/backend/train/ops/SoftMaxLayer.cc [new file with mode: 0644]
runtime/onert/backend/train/ops/SoftMaxLayer.h [new file with mode: 0644]
runtime/onert/backend/train/optimizer/Adam.cc [new file with mode: 0644]
runtime/onert/backend/train/optimizer/Adam.h [new file with mode: 0644]
runtime/onert/backend/train/optimizer/Optimizers.h [new file with mode: 0644]
runtime/onert/backend/train/optimizer/Optimizers.test.cc [new file with mode: 0644]
runtime/onert/backend/train/optimizer/SGD.cc [new file with mode: 0644]
runtime/onert/backend/train/optimizer/SGD.h [new file with mode: 0644]
runtime/onert/backend/trix/BackendContext.cc
runtime/onert/backend/trix/BatchThreadPool.h
runtime/onert/backend/trix/CMakeLists.txt
runtime/onert/backend/trix/DevContext.cc
runtime/onert/backend/trix/KernelGenerator.cc
runtime/onert/backend/xnnpack/BackendContext.cc
runtime/onert/backend/xnnpack/CMakeLists.txt
runtime/onert/backend/xnnpack/KernelGenerator.cc
runtime/onert/backend/xnnpack/ops/ConvolutionLayer.cc
runtime/onert/backend/xnnpack/ops/DepthwiseConvolutionLayer.cc
runtime/onert/backend/xnnpack/ops/FullyConnectedLayer.cc
runtime/onert/core/CMakeLists.txt
runtime/onert/core/include/backend/BackendContext.h
runtime/onert/core/include/backend/IPortableTensor.h
runtime/onert/core/include/backend/basic/BackendContextHelpers.h
runtime/onert/core/include/backend/basic/IMemoryPlanner.h
runtime/onert/core/include/backend/basic/MemoryManager.h
runtime/onert/core/include/backend/basic/Tensor.h
runtime/onert/core/include/backend/basic/train/TrainableBackendContextHelpers.h
runtime/onert/core/include/backend/basic/train/TrainableTensor.h
runtime/onert/core/include/backend/train/ITensorRegistry.h
runtime/onert/core/include/backend/train/TrainableBackendContext.h
runtime/onert/core/include/compiler/Compiler.h
runtime/onert/core/include/compiler/CompilerFactory.h
runtime/onert/core/include/compiler/CompilerOptions.h
runtime/onert/core/include/compiler/StaticShapeInferer.h
runtime/onert/core/include/compiler/train/TrainingInfo.h [deleted file]
runtime/onert/core/include/exec/DynamicShapeInferer.h
runtime/onert/core/include/exec/Execution.h
runtime/onert/core/include/exec/ExecutionContext.h [new file with mode: 0644]
runtime/onert/core/include/exec/FunctionSequence.h
runtime/onert/core/include/exec/IExecutor.h
runtime/onert/core/include/exec/IExecutors.h
runtime/onert/core/include/exec/IODescription.h [deleted file]
runtime/onert/core/include/exec/MinMaxMap.h
runtime/onert/core/include/exec/train/TrainableFnSequence.h
runtime/onert/core/include/exec/train/optimizer/Optimizer.h
runtime/onert/core/include/exec/train/optimizer/OptimizerCode.h [deleted file]
runtime/onert/core/include/exec/train/optimizer/SGD.h [deleted file]
runtime/onert/core/include/exporter/CircleExporter.h [new file with mode: 0644]
runtime/onert/core/include/ir/Index.h
runtime/onert/core/include/ir/Model.h
runtime/onert/core/include/ir/Operand.h
runtime/onert/core/include/ir/OperandInfo.h
runtime/onert/core/include/ir/operation/ElementwiseBinary.h
runtime/onert/core/include/ir/operation/Loss.h
runtime/onert/core/include/ir/train/ITrainableOperation.h
runtime/onert/core/include/ir/train/Index.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/LossCode.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/LossInfo.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/Operations.Include.h
runtime/onert/core/include/ir/train/Operations.lst
runtime/onert/core/include/ir/train/OptimizerCode.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/OptimizerInfo.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/TrainableGraph.h
runtime/onert/core/include/ir/train/TrainableOperation.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/TrainingInfo.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/UseDefChain.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/UseDefChains.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/operation/BinaryArithmetic.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/operation/Conv2D.h
runtime/onert/core/include/ir/train/operation/DepthwiseConv2D.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/operation/ElementwiseActivation.h
runtime/onert/core/include/ir/train/operation/FullyConnected.h
runtime/onert/core/include/ir/train/operation/Loss.h
runtime/onert/core/include/ir/train/operation/Pad.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/operation/Permute.h
runtime/onert/core/include/ir/train/operation/Pool2D.h
runtime/onert/core/include/ir/train/operation/Reduce.h [new file with mode: 0644]
runtime/onert/core/include/ir/train/operation/Reshape.h
runtime/onert/core/include/ir/train/operation/Softmax.h
runtime/onert/core/include/ir/train/operation/UntrainableOperation.h
runtime/onert/core/include/loader/CircleLoader.h [new file with mode: 0644]
runtime/onert/core/include/loader/ILoader.h [new file with mode: 0644]
runtime/onert/core/include/loader/ModelLoader.h [new file with mode: 0644]
runtime/onert/core/include/loader/TFLiteLoader.h [new file with mode: 0644]
runtime/onert/core/include/loader/TrainInfoLoader.h [new file with mode: 0644]
runtime/onert/core/include/odc/CodegenManager.h [new file with mode: 0644]
runtime/onert/core/include/odc/ICodegen.h [new file with mode: 0644]
runtime/onert/core/include/odc/IQuantizer.h
runtime/onert/core/include/odc/QuantizeManager.h
runtime/onert/core/include/odc/QuantizeType.h [new file with mode: 0644]
runtime/onert/core/include/util/Config.lst
runtime/onert/core/include/util/Index.h
runtime/onert/core/include/util/MinMaxMap.h
runtime/onert/core/include/util/ObjectManager.h
runtime/onert/core/include/util/ShapeInference.h
runtime/onert/core/include/util/logging.h
runtime/onert/core/src/backend/IPortableTensor.cc
runtime/onert/core/src/backend/basic/MemoryManager.cc
runtime/onert/core/src/backend/basic/MemoryPlanner.h
runtime/onert/core/src/backend/basic/MemoryPlannerFactory.cc
runtime/onert/core/src/backend/basic/MemoryPlannerFactory.h
runtime/onert/core/src/backend/basic/StaticTensorManager.cc
runtime/onert/core/src/backend/basic/Tensor.cc
runtime/onert/core/src/backend/basic/TensorBuilder.cc
runtime/onert/core/src/backend/builtin/Backend.h
runtime/onert/core/src/backend/builtin/BackendContext.cc
runtime/onert/core/src/backend/builtin/IOTensor.cc
runtime/onert/core/src/backend/builtin/IOTensor.h
runtime/onert/core/src/backend/builtin/TensorBuilder.cc
runtime/onert/core/src/backend/builtin/UserTensor.cc
runtime/onert/core/src/backend/builtin/UserTensor.h
runtime/onert/core/src/backend/builtin/kernel/IfLayer.cc
runtime/onert/core/src/backend/builtin/kernel/IfLayer.h
runtime/onert/core/src/backend/builtin/kernel/PermuteLayer.h
runtime/onert/core/src/backend/builtin/kernel/WhileLayer.cc
runtime/onert/core/src/backend/builtin/train/BackendContext.cc
runtime/onert/core/src/backend/builtin/train/BackendContext.h
runtime/onert/core/src/backend/builtin/train/KernelGenerator.cc
runtime/onert/core/src/backend/builtin/train/KernelGenerator.h
runtime/onert/core/src/backend/builtin/train/Tensor.h
runtime/onert/core/src/backend/builtin/train/TensorRegistry.h
runtime/onert/core/src/backend/builtin/train/kernel/PermuteLayer.cc
runtime/onert/core/src/backend/builtin/train/kernel/PermuteLayer.h
runtime/onert/core/src/compiler/Compiler.cc
runtime/onert/core/src/compiler/CompilerFactory.cc
runtime/onert/core/src/compiler/CompilerOptions.cc
runtime/onert/core/src/compiler/ExecutorFactory.cc
runtime/onert/core/src/compiler/ExecutorFactory.h
runtime/onert/core/src/compiler/HEScheduler.cc
runtime/onert/core/src/compiler/HEScheduler.test.cc
runtime/onert/core/src/compiler/Linear.cc
runtime/onert/core/src/compiler/MultiModelCompiler.cc
runtime/onert/core/src/compiler/MultiModelCompiler.h
runtime/onert/core/src/compiler/ShapeValidator.cc
runtime/onert/core/src/compiler/ShapeValidator.h
runtime/onert/core/src/compiler/StaticShapeInferer.cc
runtime/onert/core/src/compiler/TensorRegistries.h
runtime/onert/core/src/compiler/pass/ConstantInsertionPass.cc
runtime/onert/core/src/compiler/pass/PermutationInsertionPass.cc
runtime/onert/core/src/compiler/train/LoweredTrainableGraph.cc
runtime/onert/core/src/compiler/train/StaticBackwardShapeInferer.cc [new file with mode: 0644]
runtime/onert/core/src/compiler/train/StaticBackwardShapeInferer.h [new file with mode: 0644]
runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.cc [deleted file]
runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.h [deleted file]
runtime/onert/core/src/compiler/train/TensorRegistries.h
runtime/onert/core/src/compiler/train/TrainableOperationConverter.cc
runtime/onert/core/src/compiler/train/TrainableOperationConverter.h
runtime/onert/core/src/compiler/train/TrainingCompiler.cc
runtime/onert/core/src/compiler/train/TrainingCompiler.h
runtime/onert/core/src/compiler/train/UntrainableOperationConverter.cc
runtime/onert/core/src/compiler/train/pass/LossInsertionPass.cc
runtime/onert/core/src/compiler/train/pass/LossInsertionPass.h
runtime/onert/core/src/compiler/train/pass/Pass.h
runtime/onert/core/src/dumper/dot/DotDumper.cc
runtime/onert/core/src/dumper/dot/DotDumper.h
runtime/onert/core/src/dumper/dot/OperandNode.cc
runtime/onert/core/src/dumper/h5/MinMaxDumper.cc
runtime/onert/core/src/dumper/h5/MinMaxDumper.h
runtime/onert/core/src/dumper/text/GraphDumper.cc
runtime/onert/core/src/dumper/text/GraphDumper.h
runtime/onert/core/src/exec/DataflowExecutor.cc
runtime/onert/core/src/exec/DataflowExecutor.h
runtime/onert/core/src/exec/DynamicShapeInferer.cc
runtime/onert/core/src/exec/EdgeTensor.cc [new file with mode: 0644]
runtime/onert/core/src/exec/EdgeTensor.h [new file with mode: 0644]
runtime/onert/core/src/exec/Execution.cc
runtime/onert/core/src/exec/Execution.test.cc
runtime/onert/core/src/exec/ExecutionContext.cc [new file with mode: 0644]
runtime/onert/core/src/exec/ExecutionObservee.cc
runtime/onert/core/src/exec/ExecutionObservee.h
runtime/onert/core/src/exec/ExecutionObservers.cc
runtime/onert/core/src/exec/ExecutionObservers.h
runtime/onert/core/src/exec/ExecutorBase.cc
runtime/onert/core/src/exec/ExecutorBase.h
runtime/onert/core/src/exec/Executors.cc [deleted file]
runtime/onert/core/src/exec/Executors.h [deleted file]
runtime/onert/core/src/exec/IPermuteFunction.h
runtime/onert/core/src/exec/IPermuteFunction.test.cc
runtime/onert/core/src/exec/LinearExecutor.cc
runtime/onert/core/src/exec/LinearExecutor.h
runtime/onert/core/src/exec/MinMaxData.cc [new file with mode: 0644]
runtime/onert/core/src/exec/MinMaxData.h [new file with mode: 0644]
runtime/onert/core/src/exec/MinMaxRecorder.cc
runtime/onert/core/src/exec/MinMaxRecorder.h
runtime/onert/core/src/exec/MultiModelExecutors.cc [new file with mode: 0644]
runtime/onert/core/src/exec/MultiModelExecutors.h [new file with mode: 0644]
runtime/onert/core/src/exec/ParallelExecutor.cc
runtime/onert/core/src/exec/ParallelExecutor.h
runtime/onert/core/src/exec/SingleModelExecutors.cc
runtime/onert/core/src/exec/SingleModelExecutors.h
runtime/onert/core/src/exec/feature/MockTensor.test.h [moved from runtime/onert/core/src/exec/feature/MockTensor.h with 100% similarity]
runtime/onert/core/src/exec/feature/nchw/Reader.h
runtime/onert/core/src/exec/feature/nchw/Reader.test.cc
runtime/onert/core/src/exec/feature/nchw/View.test.cc
runtime/onert/core/src/exec/feature/nhwc/Reader.h
runtime/onert/core/src/exec/feature/nhwc/Reader.test.cc
runtime/onert/core/src/exec/feature/nhwc/View.test.cc
runtime/onert/core/src/exec/train/TrainableExecutor.cc
runtime/onert/core/src/exec/train/TrainableExecutor.h
runtime/onert/core/src/exec/train/TrainableExecutors.cc
runtime/onert/core/src/exec/train/TrainableExecutors.h
runtime/onert/core/src/exec/train/TrainableFnSequence.cc
runtime/onert/core/src/exec/train/optimizer/OptimizerCode.cc [deleted file]
runtime/onert/core/src/exec/train/optimizer/OptimizerHelpers.h [deleted file]
runtime/onert/core/src/exec/train/optimizer/SGD.cc [deleted file]
runtime/onert/core/src/exporter/CircleExporter.cc [new file with mode: 0644]
runtime/onert/core/src/exporter/TrainInfoBuilder.h [new file with mode: 0644]
runtime/onert/core/src/ir/Graph.cc
runtime/onert/core/src/ir/OperationDumper.cc
runtime/onert/core/src/ir/OperationValidator.cc
runtime/onert/core/src/ir/operation/ElementwiseBinary.cc
runtime/onert/core/src/ir/operation/Loss.cc
runtime/onert/core/src/ir/train/LossCode.cc [new file with mode: 0644]
runtime/onert/core/src/ir/train/OptimizerCode.cc [new file with mode: 0644]
runtime/onert/core/src/ir/train/TrainableGraph.cc
runtime/onert/core/src/ir/train/TrainableGraph.test.cc [new file with mode: 0644]
runtime/onert/core/src/ir/train/TrainingInfo.cc [new file with mode: 0644]
runtime/onert/core/src/ir/train/UseDefChain.cc [new file with mode: 0644]
runtime/onert/core/src/ir/train/UseDefGenerator.cc [new file with mode: 0644]
runtime/onert/core/src/ir/train/UseDefGenerator.h [new file with mode: 0644]
runtime/onert/core/src/ir/train/operation/BinaryArithmetic.cc [new file with mode: 0644]
runtime/onert/core/src/ir/train/operation/DepthwiseConv2D.cc [new file with mode: 0644]
runtime/onert/core/src/ir/train/operation/Loss.cc
runtime/onert/core/src/ir/train/operation/Pad.cc [new file with mode: 0644]
runtime/onert/core/src/ir/train/operation/Reduce.cc [new file with mode: 0644]
runtime/onert/core/src/ir/train/operation/UntrainableOperation.test.cc [new file with mode: 0644]
runtime/onert/core/src/ir/verifier/Verifier.cc
runtime/onert/core/src/ir/verifier/Verifier.h
runtime/onert/core/src/loader/BaseLoader.h [new file with mode: 0644]
runtime/onert/core/src/loader/CircleLoader.cc [new file with mode: 0644]
runtime/onert/core/src/loader/ModelLoader.cc [new file with mode: 0644]
runtime/onert/core/src/loader/TFLiteLoader.cc [new file with mode: 0644]
runtime/onert/core/src/loader/TrainInfoLoader.cc [new file with mode: 0644]
runtime/onert/core/src/loader/tflite_schema.fbs [moved from runtime/onert/frontend/tflite/tflite_schema.fbs with 100% similarity]
runtime/onert/core/src/loader/tflite_schema_generated.h [new file with mode: 0644]
runtime/onert/core/src/odc/CodegenLoader.cc [new file with mode: 0644]
runtime/onert/core/src/odc/CodegenLoader.h [new file with mode: 0644]
runtime/onert/core/src/odc/CodegenManager.cc [new file with mode: 0644]
runtime/onert/core/src/odc/QuantizeManager.cc
runtime/onert/core/src/odc/QuantizeManager.test.cc
runtime/onert/core/src/util/EventWriter.h
runtime/onert/core/src/util/ShapeInference.cc
runtime/onert/frontend/base_loader/CMakeLists.txt [deleted file]
runtime/onert/frontend/base_loader/include/base_loader.h [deleted file]
runtime/onert/frontend/circle/CMakeLists.txt [deleted file]
runtime/onert/frontend/circle/include/circle_loader.h [deleted file]
runtime/onert/frontend/circle/src/circle_loader.cc [deleted file]
runtime/onert/frontend/circle_schema/CMakeLists.txt [deleted file]
runtime/onert/frontend/circle_schema/include/circle_schema_generated.h [deleted file]
runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.cc [deleted file]
runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.h [deleted file]
runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.cc [deleted file]
runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc [deleted file]
runtime/onert/frontend/tflite/CMakeLists.txt [deleted file]
runtime/onert/frontend/tflite/include/tflite_loader.h [deleted file]
runtime/onert/frontend/tflite/src/tflite_loader.cc [deleted file]
runtime/onert/frontend/tflite/src/tflite_schema_generated.h [deleted file]
runtime/onert/frontend/tflite/tflite_schema-1.13.1.fbs [deleted file]
runtime/onert/frontend/trix/CMakeLists.txt [deleted file]
runtime/onert/frontend/trix/include/trix_loader.h [deleted file]
runtime/onert/frontend/trix/src/trix_loader.cc [deleted file]
runtime/onert/frontend/trix/src/trix_loader_dummy.cc [deleted file]
runtime/onert/loader/CMakeLists.txt [moved from runtime/onert/frontend/CMakeLists.txt with 100% similarity]
runtime/onert/loader/trix/CMakeLists.txt [new file with mode: 0644]
runtime/onert/loader/trix/TrixLoader.cc [new file with mode: 0644]
runtime/onert/odc/CMakeLists.txt
runtime/onert/odc/Embedder.cc [new file with mode: 0644]
runtime/onert/odc/Embedder.h [new file with mode: 0644]
runtime/onert/odc/MinMaxReader.cc [new file with mode: 0644]
runtime/onert/odc/MinMaxReader.h [new file with mode: 0644]
runtime/onert/odc/Quantizer.cc
runtime/onert/odc/Quantizer.h
runtime/onert/odc/Quantizer.test.cc
runtime/onert/sample/minimal-python/README.md [new file with mode: 0644]
runtime/onert/sample/minimal-python/src/minimal.py [new file with mode: 0644]
runtime/service/npud/backend/trix/CMakeLists.txt
tests/CMakeLists.txt
tests/custom_op/CMakeLists.txt
tests/libs/CMakeLists.txt [new file with mode: 0644]
tests/libs/benchmark/CMakeLists.txt [new file with mode: 0644]
tests/libs/benchmark/include/benchmark.h [moved from runtime/libs/benchmark/include/benchmark.h with 100% similarity]
tests/libs/benchmark/include/benchmark/Accumulator.h [new file with mode: 0644]
tests/libs/benchmark/include/benchmark/CsvHeader.lst [moved from runtime/libs/benchmark/include/benchmark/CsvHeader.lst with 100% similarity]
tests/libs/benchmark/include/benchmark/CsvWriter.h [moved from runtime/libs/benchmark/include/benchmark/CsvWriter.h with 100% similarity]
tests/libs/benchmark/include/benchmark/MemoryInfo.h [moved from runtime/libs/benchmark/include/benchmark/MemoryInfo.h with 100% similarity]
tests/libs/benchmark/include/benchmark/MemoryPoller.h [moved from runtime/libs/benchmark/include/benchmark/MemoryPoller.h with 100% similarity]
tests/libs/benchmark/include/benchmark/Phase.h [moved from runtime/libs/benchmark/include/benchmark/Phase.h with 100% similarity]
tests/libs/benchmark/include/benchmark/Phases.h [moved from runtime/libs/benchmark/include/benchmark/Phases.h with 100% similarity]
tests/libs/benchmark/include/benchmark/RandomGenerator.h [new file with mode: 0644]
tests/libs/benchmark/include/benchmark/Result.h [moved from runtime/libs/benchmark/include/benchmark/Result.h with 100% similarity]
tests/libs/benchmark/include/benchmark/Types.h [moved from runtime/libs/benchmark/include/benchmark/Types.h with 100% similarity]
tests/libs/benchmark/src/CsvWriter.cpp [moved from runtime/libs/benchmark/src/CsvWriter.cpp with 100% similarity]
tests/libs/benchmark/src/MemoryInfo.cpp [moved from runtime/libs/benchmark/src/MemoryInfo.cpp with 100% similarity]
tests/libs/benchmark/src/MemoryPoller.cpp [moved from runtime/libs/benchmark/src/MemoryPoller.cpp with 100% similarity]
tests/libs/benchmark/src/Phases.cpp [moved from runtime/libs/benchmark/src/Phases.cpp with 100% similarity]
tests/libs/benchmark/src/RandomGenerator.cpp [new file with mode: 0644]
tests/libs/benchmark/src/Result.cpp [new file with mode: 0644]
tests/libs/nnapi/CMakeLists.txt [moved from runtime/libs/nnapi/CMakeLists.txt with 100% similarity]
tests/libs/nnapi/include/NeuralNetworksExShim.h [moved from runtime/libs/nnapi/include/NeuralNetworksExShim.h with 100% similarity]
tests/libs/nnapi/include/NeuralNetworksLoadHelpers.h [moved from runtime/libs/nnapi/include/NeuralNetworksLoadHelpers.h with 100% similarity]
tests/libs/nnapi/include/NeuralNetworksShim.h [moved from runtime/libs/nnapi/include/NeuralNetworksShim.h with 100% similarity]
tests/libs/nnapi/include/NeuralNetworksTypes.h [moved from runtime/libs/nnapi/include/NeuralNetworksTypes.h with 100% similarity]
tests/libs/rua/CMakeLists.txt [moved from runtime/libs/rua/CMakeLists.txt with 100% similarity]
tests/libs/rua/README.md [moved from runtime/libs/rua/README.md with 100% similarity]
tests/libs/rua/anchor/CMakeLists.txt [moved from runtime/libs/rua/anchor/CMakeLists.txt with 100% similarity]
tests/libs/rua/anchor/include/rua/Anchor.h [moved from runtime/libs/rua/anchor/include/rua/Anchor.h with 100% similarity]
tests/libs/rua/anchor/src/Anchor.cpp [moved from runtime/libs/rua/anchor/src/Anchor.cpp with 100% similarity]
tests/libs/rua/core/CMakeLists.txt [moved from runtime/libs/rua/core/CMakeLists.txt with 100% similarity]
tests/libs/rua/core/include/rua/Service.h [moved from runtime/libs/rua/core/include/rua/Service.h with 100% similarity]
tests/libs/rua/dyn/CMakeLists.txt [moved from runtime/libs/rua/dyn/CMakeLists.txt with 100% similarity]
tests/libs/rua/dyn/include/rua/DynamicBinder.h [moved from runtime/libs/rua/dyn/include/rua/DynamicBinder.h with 100% similarity]
tests/libs/rua/dyn/src/DynamicBinder.cpp [moved from runtime/libs/rua/dyn/src/DynamicBinder.cpp with 100% similarity]
tests/libs/rua/shim/CMakeLists.txt [moved from runtime/libs/rua/shim/CMakeLists.txt with 100% similarity]
tests/libs/rua/shim/include/rua/Shim.h [moved from runtime/libs/rua/shim/include/rua/Shim.h with 100% similarity]
tests/libs/tflite/CMakeLists.txt [new file with mode: 0644]
tests/libs/tflite/include/tflite/Assert.h [moved from runtime/libs/tflite/include/tflite/Assert.h with 100% similarity]
tests/libs/tflite/include/tflite/Diff.h [new file with mode: 0644]
tests/libs/tflite/include/tflite/InputIndex.h [moved from runtime/libs/tflite/include/tflite/InputIndex.h with 100% similarity]
tests/libs/tflite/include/tflite/InterpreterSession.h [new file with mode: 0644]
tests/libs/tflite/include/tflite/RandomInputInitializer.h [new file with mode: 0644]
tests/libs/tflite/include/tflite/Session.h [moved from runtime/libs/tflite/include/tflite/Session.h with 100% similarity]
tests/libs/tflite/include/tflite/TensorView.h [moved from runtime/libs/tflite/include/tflite/TensorView.h with 100% similarity]
tests/libs/tflite/src/Diff.cpp [new file with mode: 0644]
tests/libs/tflite/src/RandomInputInitializer.cpp [new file with mode: 0644]
tests/libs/tflite/src/TensorView.test.cpp [moved from runtime/libs/tflite/src/TensorView.test.cpp with 100% similarity]
tests/nnapi/CMakeLists.txt
tests/nnfw_api/CMakeLists.txt
tests/nnfw_api/lib/CircleGen.cc [new file with mode: 0644]
tests/nnfw_api/lib/CircleGen.h [new file with mode: 0644]
tests/nnfw_api/lib/CirclePlusGen.cc [new file with mode: 0644]
tests/nnfw_api/lib/CirclePlusGen.h [new file with mode: 0644]
tests/nnfw_api/lib/GenModelTest.h [new file with mode: 0644]
tests/nnfw_api/lib/GenModelTrain.h [new file with mode: 0644]
tests/nnfw_api/lib/NNPackages.cc [moved from tests/nnfw_api/src/NNPackages.cc with 100% similarity]
tests/nnfw_api/lib/NNPackages.h [moved from tests/nnfw_api/src/NNPackages.h with 100% similarity]
tests/nnfw_api/lib/common.cc [moved from tests/nnfw_api/src/common.cc with 100% similarity]
tests/nnfw_api/lib/common.h [moved from tests/nnfw_api/src/common.h with 100% similarity]
tests/nnfw_api/lib/fixtures.h [moved from tests/nnfw_api/src/fixtures.h with 100% similarity]
tests/nnfw_api/main.cc [moved from tests/nnfw_api/src/main.cc with 100% similarity]
tests/nnfw_api/src/CircleGen.cc [deleted file]
tests/nnfw_api/src/CircleGen.h [deleted file]
tests/nnfw_api/src/GenModelTest.h [deleted file]
tests/nnfw_api/src/GenModelTests.test.cc [deleted file]
tests/nnfw_api/src/GenModelTests/BranchModelTrain.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/General.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/ModelTestDynamicTensor.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/ModelTestInputReshaping.test.cc [moved from tests/nnfw_api/src/ModelTestInputReshaping.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/Trainability.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Add.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/MaxPool2D.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Mean.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Mul.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Pad.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Relu.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Relu6.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Reshape.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Softmax.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Sub.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/one_op_tests/Add.test.cc [moved from tests/nnfw_api/src/one_op_tests/Add.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/AddN.test.cc [moved from tests/nnfw_api/src/one_op_tests/AddN.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/ArgMinMax.test.cc [moved from tests/nnfw_api/src/one_op_tests/ArgMinMax.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/AveragePool2D.test.cc [moved from tests/nnfw_api/src/one_op_tests/AveragePool2D.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/BatchToSpaceND.test.cc [moved from tests/nnfw_api/src/one_op_tests/BatchToSpaceND.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Cast.test.cc [moved from tests/nnfw_api/src/one_op_tests/Cast.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Concat.test.cc [moved from tests/nnfw_api/src/one_op_tests/Concat.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Conv2D.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/one_op_tests/Cos.test.cc [moved from tests/nnfw_api/src/one_op_tests/Cos.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/DepthToSpace.test.cc [moved from tests/nnfw_api/src/one_op_tests/DepthToSpace.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/DepthwiseConv2D.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/one_op_tests/DetectionPostProcess.test.cc [moved from tests/nnfw_api/src/one_op_tests/DetectionPostProcess.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Elu.test.cc [moved from tests/nnfw_api/src/one_op_tests/Elu.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Equal.test.cc [moved from tests/nnfw_api/src/one_op_tests/Equal.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/ExpandDims.test.cc [moved from tests/nnfw_api/src/one_op_tests/ExpandDims.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Fill.test.cc [moved from tests/nnfw_api/src/one_op_tests/Fill.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Floor.test.cc [moved from tests/nnfw_api/src/one_op_tests/Floor.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/FloorDiv.test.cc [moved from tests/nnfw_api/src/one_op_tests/FloorDiv.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/FloorMod.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/one_op_tests/FullyConnected.test.cc [moved from tests/nnfw_api/src/one_op_tests/FullyConnected.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Greater.test.cc [moved from tests/nnfw_api/src/one_op_tests/Greater.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/GreaterEqual.test.cc [moved from tests/nnfw_api/src/one_op_tests/GreaterEqual.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/If.test.cc [moved from tests/nnfw_api/src/one_op_tests/If.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/InstanceNorm.test.cc [moved from tests/nnfw_api/src/one_op_tests/InstanceNorm.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/L2Normalization.test.cc [moved from tests/nnfw_api/src/one_op_tests/L2Normalization.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/LeakyRelu.test.cc [moved from tests/nnfw_api/src/one_op_tests/LeakyRelu.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Less.test.cc [moved from tests/nnfw_api/src/one_op_tests/Less.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/LessEqual.test.cc [moved from tests/nnfw_api/src/one_op_tests/LessEqual.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/LogSoftmax.test.cc [moved from tests/nnfw_api/src/one_op_tests/LogSoftmax.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Mean.test.cc [moved from tests/nnfw_api/src/one_op_tests/Mean.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Mul.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/one_op_tests/Neg.test.cc [moved from tests/nnfw_api/src/one_op_tests/Neg.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/NotEqual.test.cc [moved from tests/nnfw_api/src/one_op_tests/NotEqual.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/OneHot.test.cc [moved from tests/nnfw_api/src/one_op_tests/OneHot.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Pad.test.cc [moved from tests/nnfw_api/src/one_op_tests/Pad.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/PadV2.test.cc [moved from tests/nnfw_api/src/one_op_tests/PadV2.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Quantize.test.cc [moved from tests/nnfw_api/src/one_op_tests/Quantize.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Rank.test.cc [moved from tests/nnfw_api/src/one_op_tests/Rank.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Reduce.test.cc [moved from tests/nnfw_api/src/one_op_tests/Reduce.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Relu.test.cc [moved from tests/nnfw_api/src/one_op_tests/Relu.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Relu6.test.cc [moved from tests/nnfw_api/src/one_op_tests/Relu6.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/ResizeBilinear.test.cc [moved from tests/nnfw_api/src/one_op_tests/ResizeBilinear.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/ResizeNearestNeighbor.test.cc [moved from tests/nnfw_api/src/one_op_tests/ResizeNearestNeighbor.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Reverse.test.cc [moved from tests/nnfw_api/src/one_op_tests/Reverse.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Select.test.cc [moved from tests/nnfw_api/src/one_op_tests/Select.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Shape.test.cc [moved from tests/nnfw_api/src/one_op_tests/Shape.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Slice.test.cc [moved from tests/nnfw_api/src/one_op_tests/Slice.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Softmax.test.cc [moved from tests/nnfw_api/src/one_op_tests/Softmax.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Split.test.cc [moved from tests/nnfw_api/src/one_op_tests/Split.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Sqrt.test.cc [moved from tests/nnfw_api/src/one_op_tests/Sqrt.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Square.test.cc [moved from tests/nnfw_api/src/one_op_tests/Square.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/StridedSlice.test.cc [moved from tests/nnfw_api/src/one_op_tests/StridedSlice.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Sub.test.cc [moved from tests/nnfw_api/src/one_op_tests/Sub.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Tile.test.cc [moved from tests/nnfw_api/src/one_op_tests/Tile.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/Transpose.test.cc [moved from tests/nnfw_api/src/one_op_tests/Transpose.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/While.test.cc [moved from tests/nnfw_api/src/one_op_tests/While.test.cc with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_tests/WhileTestModel.h [moved from tests/nnfw_api/src/one_op_tests/WhileTestModel.h with 100% similarity]
tests/nnfw_api/src/GenModelTests/one_op_trains/Conv2D.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/one_op_trains/DepthwiseConvolution.test.cc [new file with mode: 0644]
tests/nnfw_api/src/GenModelTests/one_op_trains/FullyConnected.test.cc [new file with mode: 0644]
tests/nnfw_api/src/ModelTestDynamicTensor.test.cc [deleted file]
tests/nnfw_api/src/NNPackageTests/AddModelLoaded.test.cc [new file with mode: 0644]
tests/nnfw_api/src/NNPackageTests/AddSessionPrepared.test.cc [new file with mode: 0644]
tests/nnfw_api/src/NNPackageTests/FourAddModelsSetInput.test.cc [moved from tests/nnfw_api/src/ValidationTestFourAddModelsSetInput.test.cc with 100% similarity]
tests/nnfw_api/src/NNPackageTests/MultipleSessions.test.cc [new file with mode: 0644]
tests/nnfw_api/src/NNPackageTests/SessionCreated.test.cc [new file with mode: 0644]
tests/nnfw_api/src/NNPackageTests/SingleSession.test.cc [new file with mode: 0644]
tests/nnfw_api/src/ValidationTestAddModelLoaded.test.cc [deleted file]
tests/nnfw_api/src/ValidationTestAddSessionPrepared.test.cc [deleted file]
tests/nnfw_api/src/ValidationTestMultipleSessions.test.cc [deleted file]
tests/nnfw_api/src/ValidationTestSessionCreated.test.cc [deleted file]
tests/nnfw_api/src/ValidationTestSingleSession.test.cc [deleted file]
tests/nnfw_api/src/one_op_tests/Conv2D.test.cc [deleted file]
tests/nnfw_api/src/one_op_tests/DepthwiseConv2D.test.cc [deleted file]
tests/nnfw_api/src/one_op_tests/Mul.test.cc [deleted file]
tests/scripts/benchmark.sh
tests/tools/onert_run/src/allocation.h
tests/tools/onert_run/src/args.cc
tests/tools/onert_run/src/args.h
tests/tools/onert_run/src/formatter.h [deleted file]
tests/tools/onert_run/src/h5formatter.cc
tests/tools/onert_run/src/h5formatter.h
tests/tools/onert_run/src/onert_run.cc
tests/tools/onert_run/src/randomgen.cc
tests/tools/onert_run/src/randomgen.h
tests/tools/onert_run/src/rawformatter.cc
tests/tools/onert_run/src/rawformatter.h
tests/tools/onert_run/src/types.h
tests/tools/onert_train/CMakeLists.txt
tests/tools/onert_train/README.md
tests/tools/onert_train/src/args.cc
tests/tools/onert_train/src/args.h
tests/tools/onert_train/src/dataloader.h [new file with mode: 0644]
tests/tools/onert_train/src/measure.h
tests/tools/onert_train/src/metrics.cc [new file with mode: 0644]
tests/tools/onert_train/src/metrics.h [new file with mode: 0644]
tests/tools/onert_train/src/nnfw_util.cc
tests/tools/onert_train/src/nnfw_util.h
tests/tools/onert_train/src/onert_train.cc
tests/tools/onert_train/src/randomgen.cc
tests/tools/onert_train/src/rawdataloader.cc
tests/tools/onert_train/src/rawdataloader.h
tests/tools/onert_train/test/rawdataloader.test.cc
tests/tools/tflite_comparator/CMakeLists.txt
tests/tools/tflite_comparator/src/args.cc
tests/tools/tflite_comparator/src/args.h
tests/tools/tflite_comparator/src/tflite_comparator.cc
tests/tools/tflite_run/CMakeLists.txt
tests/tools/tflite_run/src/args.cc
tests/tools/tflite_run/src/args.h
tests/tools/tflite_run/src/tflite_run.cc
tools/CMakeLists.txt
tools/circle_plus_gen/README.md [new file with mode: 0644]
tools/circle_plus_gen/example/sample.circle [new file with mode: 0644]
tools/circle_plus_gen/example/sample_tparam.circle [new file with mode: 0644]
tools/circle_plus_gen/example/tparam_sgd_scce.json [new file with mode: 0644]
tools/circle_plus_gen/example/train_tparam.json [new file with mode: 0644]
tools/circle_plus_gen/how-to-write-tparam-json.md [new file with mode: 0644]
tools/circle_plus_gen/lib/__init__.py [new file with mode: 0644]
tools/circle_plus_gen/lib/circle_plus.py [new file with mode: 0644]
tools/circle_plus_gen/lib/json_parser.py [new file with mode: 0644]
tools/circle_plus_gen/lib/train_param.py [new file with mode: 0644]
tools/circle_plus_gen/lib/utils.py [new file with mode: 0644]
tools/circle_plus_gen/main.py [new file with mode: 0644]
tools/circle_plus_gen/requirements.txt [new file with mode: 0644]
tools/circle_plus_gen/schema/__init__.py [new file with mode: 0644]
tools/circle_plus_gen/schema/_gen.py [new file with mode: 0644]
tools/circle_plus_gen/schema/circle_schema_generated.py [new file with mode: 0644]
tools/circle_plus_gen/schema/circle_traininfo_generated.py [new file with mode: 0644]
tools/circle_plus_gen/test/__init__.py [new file with mode: 0644]
tools/circle_plus_gen/test/test_circle_plus.py [new file with mode: 0644]
tools/cross/aarch64/sources.list.bionic [deleted file]
tools/cross/aarch64/sources.list.noble [new file with mode: 0644]
tools/cross/arm/sources.list.bionic [deleted file]
tools/cross/arm/sources.list.noble [new file with mode: 0644]
tools/cross/install_android_ndk.sh
tools/cross/install_android_sdk.sh
tools/cross/install_rootfs.sh
tools/generate_datafile/tf_dataset_converter/README.md
tools/generate_datafile/tf_dataset_converter/argparser.py
tools/generate_datafile/tf_dataset_converter/datasets.py
tools/generate_datafile/tf_dataset_converter/main.py
tools/kbenchmark/Args.cc
tools/kbenchmark/CMakeLists.txt
tools/tflite_accuracy/CMakeLists.txt [deleted file]
tools/tflite_accuracy/README.md [deleted file]
tools/tflite_accuracy/src/labels.h [deleted file]
tools/tflite_accuracy/src/tflite_accuracy.cc [deleted file]

index 3c2b71f..cd808b0 100644 (file)
@@ -1,52 +1,49 @@
 # External code: Android NN API
-/ONE/compiler/ann-api/include/NeuralNetworks.h
-/ONE/compiler/ann-ref
+compiler/ann-api/include/NeuralNetworks.h
+compiler/ann-ref/
 
 # Eigen
-/ONE/compiler/nnc/backends/soft_backend/code_snippets/eigen.def
+compiler/nnc/backends/soft_backend/code_snippets/eigen.def
 
 # Frontend test tools that are needed for release package build
-/ONE/compiler/circlechef
-/ONE/compiler/circle-verify
-/ONE/compiler/luci/tester
+compiler/circlechef/
+compiler/circle-verify/
+compiler/luci/tester/
 
 # Exclude IR headers which have lots of similar patterns
 # TODO remove this when refactoring is possible
-/ONE/compiler/luci/lang/include/luci/IR/Nodes
-/ONE/compiler/luci/import/include/luci/Import/Nodes
-/ONE/compiler/loco/include/loco/IR
-/ONE/compiler/tflchef/tflite/src/Op/include
+compiler/luci/lang/include/luci/IR/Nodes/
+compiler/luci/import/include/luci/Import/Nodes/
+compiler/loco/include/loco/IR/
+compiler/tflchef/tflite/src/Op/include/
 
 # Exclude interpreter kernels which have similar patterns
-/ONE/compiler/luci-interpreter/src/kernels
-/ONE/compiler/locomotiv/src/Node
-
-# Test codes
-/ONE/tests
+compiler/luci-interpreter/src/kernels/
+compiler/locomotiv/src/Node/
 
 # Flatbuffers generated
-/ONE/runtime/onert/frontend/circle_schema/include/circle_schema_generated.h
-/ONE/runtime/onert/frontend/tflite/src/tflite_schema_generated.h
+runtime/libs/circle-schema/include/circle_schema_generated.h
+runtime/libs/circle-schema/include/circle_traininfo_generated.h
+runtime/onert/core/src/loader/tflite_schema_generated.h
 
 # External code: Android NN API
-/ONE/runtime/nnapi-header/include/NeuralNetworks.h
-/ONE/runtime/nnapi-header/include/NeuralNetworksExtensions.h
+runtime/nnapi-header/include/NeuralNetworks.h
+runtime/nnapi-header/include/NeuralNetworksExtensions.h
 
 # External code: Tensorflow lite
-/ONE/runtime/libs/nnapi
-/ONE/runtime/libs/profiling
+runtime/libs/profiling/
 
 # External code: 3rd party
-/ONE/runtime/3rdparty
+runtime/3rdparty/
 
 # External code: compute libraries
-/ONE/compute
+compute/
 
 # Experimental subprojects not for release
-/ONE/runtime/contrib
+runtime/contrib/
 
 # Downloaded externals
-/ONE/externals
+externals/
 
 # Intermediate code for runtime build (refer nnfw.spec file's nncc_workspace)
-/ONE/build/nncc/
+build/nncc/
index 12fbabe..ecae5f5 100644 (file)
@@ -12,10 +12,12 @@ test:
       - /tests/nnfw_api
 
     testFile:
-      - extension: test.cpp
-        any: true
-      - extension: test.cc
-        any: true
+      - extension: cpp
+        ends:
+          - .test
+      - extension: cc
+        ends:
+          - .test
     testCase:
       - condition:
         - functionName:
@@ -136,9 +138,9 @@ test:
       - /compiler/vconone
 
     testFile:
-      - extension: .test.cpp
-        any: true
-
+      - extension: cpp
+        ends:
+          - .test
     testCase:
       - condition:
         - functionName:
index 9243c9a..0f20ca4 100644 (file)
@@ -21,6 +21,7 @@ BinPackArguments: true
 BinPackParameters: true
 BraceWrapping:
   AfterClass:             true
+  AfterCaseLabel:         true
   AfterControlStatement:  true
   AfterEnum:              true
   AfterFunction:          true
index dcfb8d5..ba8d4bf 100644 (file)
@@ -21,18 +21,21 @@ jobs:
 
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Setup python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: '3.x'
 
-      # C format: clang-format-8
+      # C format: clang-format-16
       # Python format: yapf==0.22.0
       - name: Install packages
         run: |
-          sudo apt-get install -y clang-format-8
+          sudo apt-get install -y gnupg2 software-properties-common
+          wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
+          sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-16 main"
+          sudo apt-get update && sudo apt-get install -qqy clang-format-16
           python -m pip install --upgrade pip
           pip install yapf==0.22.0
 
@@ -41,7 +44,7 @@ jobs:
 
       # Upload patch file if failed
       - name: Store archive
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v4
         if: failure()
         with:
           name: format-patch
@@ -54,7 +57,7 @@ jobs:
 
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           # Fetch all history and branch (default: 1)
           # Require all history to get file creation date
index 7fa84b1..5dc2de1 100644 (file)
@@ -24,7 +24,7 @@ jobs:
 
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           # Checkout PR head commit
           # Checkout Action use merge commit as default
index d474a27..5f7a04b 100644 (file)
@@ -20,7 +20,7 @@ jobs:
 
     steps:
       - name: 'Checkout'
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
       - name: 'Generate HTML'
         uses: mattnotmitt/doxygen-action@v1.9
         with:
@@ -28,7 +28,7 @@ jobs:
       - name: 'Tar artifact'
         run: tar -zcf doxygen.tar.gz -C doxygen/html ./
       - name: 'Generate artifact'
-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
         with:
           name: doxygen-html
           path: doxygen.tar.gz
index 8b27e63..3256c75 100644 (file)
@@ -31,7 +31,7 @@ jobs:
         with:
           release: '12.2.Rel1' # <-- The compiler release to use
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           # Checkout PR head commit
           # Checkout Action use merge commit as default
@@ -43,5 +43,5 @@ jobs:
           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
+          make -j$(nproc) onert_micro_execute_kernels_test
+          ./onert-micro/eval-driver/onert-micro/src/execute/onert_micro_execute_kernels_test
index 701a526..206831e 100644 (file)
@@ -3,7 +3,13 @@
 # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
 
 # Required
-version: 1.4
+version: 2
+
+# Set the OS, Python version and other tools you might need
+build:
+  os: ubuntu-lts-latest
+  tools:
+    python: "3"
 
 # Build documentation in the docs/ directory with Sphinx
 sphinx:
@@ -17,6 +23,5 @@ formats:
 
 # Optionally set the version of Python and requirements required to build your docs
 python:
-  version: 3.7
   install:
     - requirements: docs/requirements.txt
index 7621a2f..cecafca 100644 (file)
@@ -8,6 +8,8 @@ HOST_OS?=linux
 TARGET_OS?=linux
 COVERAGE_BUILD?=0
 OPTIONS?=
+OPTIONS_NNCC?=
+INSTALL_OPTIONS?=
 
 # make TARGET and TYPE to lowercase
 HOST_ARCH_LC=$(shell echo $(HOST_ARCH) | tr A-Z a-z)
@@ -36,6 +38,7 @@ endif
 ifeq ($(CROSS_BUILD),1)
        TOOLCHAIN_FILE=cmake/buildtool/cross/toolchain_$(TARGET_ARCH_LC)-$(TARGET_OS).cmake
        OPTIONS+= -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE)
+       OPTIONS_NNCC+= -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE)
 endif
 
 ifneq ($(filter create-covsuite,$(MAKECMDGOALS)),)
@@ -50,10 +53,12 @@ endif
 
 ifneq ($(EXTERNAL_VOLUME),)
        OPTIONS+= -DNNAS_EXTERNALS_DIR=$(EXTERNAL_VOLUME)
+       OPTIONS_NNCC+= -DNNAS_EXTERNALS_DIR=$(EXTERNAL_VOLUME)
 endif
 
 ifeq ($(TARGET_OS),android)
        OPTIONS+= -DNDK_DIR=$(NDK_DIR)
+       OPTIONS_NNCC+= -DNDK_DIR=$(NDK_DIR)
 endif
 
 ifneq ($(ANDROID_BUILD_TOOLS_DIR),)
@@ -78,13 +83,19 @@ else
        NPROCS?=1
 endif
 
+ifeq ($(BUILD_TYPE_LC),release)
+       INSTALL_OPTIONS+= --strip
+endif
+
 WORKHOME=$(CURDIR)/Product
 WORKFOLDER=$(TARGET_ARCH_LC)-$(TARGET_OS).$(BUILD_TYPE_LC)
 WORKSPACE=$(WORKHOME)/$(WORKFOLDER)
+BUILDTOOL_WORKSPACE=$(WORKHOME)/buildtool
 
 INSTALL_PATH?=$(WORKSPACE)/out
 OVERLAY_FOLDER?=$(WORKSPACE)/overlay
 INSTALL_ALIAS=$(WORKHOME)/out
+BUILDTOOL_PATH?=$(BUILDTOOL_WORKSPACE)/out
 
 TIMESTAMP_CONFIGURE=$(WORKSPACE)/CONFIGURE
 TIMESTAMP_BUILD=$(WORKSPACE)/BUILD
@@ -104,11 +115,13 @@ export NNCC_WORKSPACE=$(NNCC_FOLDER)
 ###
 ### Default target
 ###
-all: install
+all: prepare-buildtool prepare-nncc configure build install
 
 ###
-### Command (public)
+### Command (build step)
 ###
+prepare-buildtool: prepare_buildtool_internal
+
 prepare-nncc: prepare_nncc_internal
 
 configure: configure_internal
@@ -117,13 +130,16 @@ build: build_internal
 
 install: install_all_internal
 
-create-package: runtime_tar_internal
+###
+### Command (public)
+###
+create-package: all runtime_tar_internal
 
-create-aclpack: acl_tar_internal
+create-aclpack: configure acl_tar_internal
 
-create-testsuite: test_suite_internal
+create-testsuite: all test_suite_internal
 
-create-covsuite: coverage_suite_internal
+create-covsuite: all coverage_suite_internal
 
 clean:
        rm -rf $(WORKSPACE)
@@ -133,57 +149,59 @@ distclean:
        rm -rf externals
        rm -rf tests/nnapi/src/generated/
 
-# create_package, create_acl_tar: to be removed
-create_package: runtime_tar_internal
-create_acl_tar: acl_tar_internal
-
 ###
 ### Command (internal)
 ###
 $(WORKSPACE):
        mkdir -p $@
 
+prepare_buildtool_internal: $(WORKSPACE)
+       cmake -S infra/buildtool -B $(BUILDTOOL_WORKSPACE)/obj -DBUILDTOOL_PATH=$(BUILDTOOL_PATH)
+       cmake --build $(BUILDTOOL_WORKSPACE)/obj/ -j$(NPROCS)
 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) \
+ifeq (,$(findstring android,$(TARGET_OS)))
+       EXTERNAL_FLATC=$(BUILDTOOL_PATH)/bin/flatc ./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"
+               -DBUILD_WHITELIST="luci;foder;pepper-csv2vec;loco;locop;logo;logo-core;mio-circle08;luci-compute;oops;hermes;hermes-std;angkor;pp;pepper-strcast;pepper-str" \
+               $(OPTIONS_NNCC)
        ./nncc build -j$(NPROCS)
-       cmake --install $(NNCC_FOLDER)
+       cmake --install $(NNCC_FOLDER) $(INSTALL_OPTIONS)
 # 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
+       @mkdir -p ${OVERLAY_FOLDER}/include/luci/IR
        @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
+       @cp compiler/luci/lang/include/luci/IR/CircleNodes.lst ${OVERLAY_FOLDER}/include/luci/IR
        @echo "Done prepare-nncc"
+endif
 
 configure_internal: $(WORKSPACE)
 ifneq ($(DEBIAN_BUILD),)
        test -d externals || mkdir -p externals
        find packaging/ -type f -name "*.tar.gz" | xargs -i tar xf {} -C externals
 endif
-       NNFW_INSTALL_PREFIX=$(INSTALL_PATH) ./nnfw configure \
+       ./nnfw configure \
                -DCMAKE_BUILD_TYPE=$(BUILD_TYPE_LC) \
                -DNNFW_OVERLAY_DIR=$(OVERLAY_FOLDER) \
                -DEXTERNALS_BUILD_THREADS=$(NPROCS) \
                $(OPTIONS)
 
-build_internal: configure_internal
+build_internal:
        ./nnfw build -j $(NPROCS)
 
-install_internal: build_internal
-       ./nnfw install
+install_internal:
+       ./nnfw install --prefix $(INSTALL_PATH) $(INSTALL_OPTIONS)
        rm -rf $(INSTALL_ALIAS)
        ln -s $(INSTALL_PATH) $(INSTALL_ALIAS)
 
-runtime_tar_internal: build_internal install_internal
+runtime_tar_internal:
        tar -zcf $(WORKSPACE)/onert-package.tar.gz -C $(INSTALL_PATH) lib
        tar -zcf $(WORKSPACE)/onert-devel-package.tar.gz -C $(INSTALL_PATH) include/nnfw
        tar -zcf $(WORKSPACE)/onert-plugin-devel-package.tar.gz -C $(INSTALL_PATH) include/onert
        tar -zcf $(WORKSPACE)/onert-test-package.tar.gz -C $(INSTALL_PATH) $(shell ls $(INSTALL_PATH) -I lib -I include)
 
-acl_tar_internal: configure_internal
+acl_tar_internal:
        tar -zcf $(WORKSPACE)/onert-acl.tar.gz -C ${OVERLAY_FOLDER} lib/libarm_compute.so lib/libarm_compute_core.so lib/libarm_compute_graph.so
 
 install_acl_internal:
index e3ed259..e47d42c 100644 (file)
--- a/README.md
+++ b/README.md
@@ -23,7 +23,6 @@ as Tensorflow or PyTorch in a unified form at runtime.
 
 - [Background](docs/overview/background.md)
 - [Roadmap](docs/overview/roadmap.md)
-- [Overall Architecture](docs/overview/overall-architecture.md)
 
 ## Getting started
 
index ef13df8..445979f 100644 (file)
@@ -71,6 +71,14 @@ function(add_compiler_directory DIR)
     endforeach(ACCEPTED_DIR)
   else()
     set(ENABLE ${BUILD_COMPILER_${PREFIX}})
+    if(ENABLE_EXCLUDE_ME)
+      # skip if "exclude.me" file exist
+      set(EXCLUDE_ME_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${DIR}/exclude.me")
+      if(EXISTS ${EXCLUDE_ME_FILE})
+        message(STATUS "Exclude ${PREFIX}")
+        set(ENABLE OFF)
+      endif()
+    endif()
   endif()
 
   # This line prevents some errors in this CMakeLists.txt
diff --git a/compiler/adtidas/exclude.me b/compiler/adtidas/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/ann-api/exclude.me b/compiler/ann-api/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/ann-ref/exclude.me b/compiler/ann-ref/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 43f99dc..1a7dd9d 100644 (file)
@@ -252,7 +252,16 @@ public:
 
   Argument &help(std::string help_message)
   {
-    _help_message = help_message;
+    _help_message.emplace_back(help_message);
+    return *this;
+  }
+
+  Argument &help(std::initializer_list<std::string> help_messages)
+  {
+    if (help_messages.size() == 0)
+      throw std::runtime_error("Empty help message list");
+
+    _help_message = help_messages;
     return *this;
   }
 
@@ -304,7 +313,7 @@ private:
   std::string _short_name;
   std::vector<std::string> _names;
   std::string _type = "string";
-  std::string _help_message;
+  std::vector<std::string> _help_message;
   std::function<void(void)> _func;
   uint32_t _nargs{1};
   bool _is_required{false};
@@ -600,11 +609,14 @@ public:
         {
           stream.width(length_of_longest_arg);
           stream << std::left << arser::internal::make_comma_concatenated(arg._names) << "\t";
-          for (size_t i = 0; i < arg._help_message.length(); i += message_width)
+          for (size_t i = 0; i < arg._help_message.size(); i++)
           {
-            if (i)
-              stream << std::string(length_of_longest_arg, ' ') << "\t";
-            stream << arg._help_message.substr(i, message_width) << std::endl;
+            for (size_t j = 0; j < arg._help_message[i].length(); j += message_width)
+            {
+              if (i || j)
+                stream << std::string(length_of_longest_arg, ' ') << "\t";
+              stream << arg._help_message[i].substr(j, message_width) << std::endl;
+            }
           }
         }
         std::cout << std::endl;
@@ -638,19 +650,22 @@ template <typename T> T Arser::get_impl(const std::string &arg_name, T *)
     throw std::runtime_error(
       "Type mismatch. "
       "You called get using a type different from the one you specified."
-      "Accumulated argument is returned as std::vector of the specified type");
+      "Accumulated argument is returned as std::vector of the specified type: " +
+      arg_name);
 
   if (arg->second->_type != TypeName<T>::Get())
     throw std::runtime_error("Type mismatch. "
                              "You called get() method with a type different "
                              "from the one you specified. "
                              "Please check the type of what you specified in "
-                             "add_argument() method.");
+                             "add_argument() method: " +
+                             arg_name);
 
   if (arg->second->_values.size() == 0)
     throw std::runtime_error("Wrong access. "
                              "You must make sure that the argument is given before accessing it. "
-                             "You can do it by calling arser[\"argument\"].");
+                             "You can do it by calling arser[\"" +
+                             arg_name + "\"].");
 
   return internal::lexical_cast<T>(arg->second->_values[0]);
 }
@@ -667,8 +682,10 @@ template <typename T> std::vector<T> Arser::get_impl(const std::string &arg_name
   if (arg->second->_is_accumulated)
   {
     if (arg->second->_type != TypeName<T>::Get())
-      throw std::runtime_error("Type mismatch. "
-                               "You called get using a type different from the one you specified.");
+      throw std::runtime_error(
+        "Type mismatch. "
+        "You called get using a type different from the one you specified: " +
+        arg_name);
 
     std::vector<T> data;
     for (auto values : arg->second->_accum_values)
@@ -680,8 +697,10 @@ template <typename T> std::vector<T> Arser::get_impl(const std::string &arg_name
   }
 
   if (arg->second->_type != TypeName<std::vector<T>>::Get())
-    throw std::runtime_error("Type mismatch. "
-                             "You called get using a type different from the one you specified.");
+    throw std::runtime_error(
+      "Type mismatch. "
+      ". You called get using a type different from the one you specified: " +
+      arg_name);
 
   std::vector<T> data;
   std::transform(arg->second->_values.begin(), arg->second->_values.end(), std::back_inserter(data),
@@ -702,13 +721,15 @@ std::vector<std::vector<T>> Arser::get_impl(const std::string &arg_name,
 
   if (not arg->second->_is_accumulated)
     throw std::runtime_error("Type mismatch. "
-                             "You called get using a type different from the one you specified.");
+                             "You called get using a type different from the one you specified: " +
+                             arg_name);
 
   if (arg->second->_type != TypeName<std::vector<T>>::Get())
     throw std::runtime_error(
       "Type mismatch. "
       "You called get using a type different from the one you specified."
-      "Accumulated argument is returned as std::vector of the specified type");
+      "Accumulated argument is returned as std::vector of the specified type: " +
+      arg_name);
 
   std::vector<std::vector<T>> result;
   for (auto values : arg->second->_accum_values)
index 63121b8..1357b81 100644 (file)
@@ -478,3 +478,38 @@ TEST(BasicTest, AccumulateScalarOptions_WrongType_NEG)
 
   EXPECT_THROW(arser.get<float>("--specify"), std::runtime_error);
 }
+
+TEST(HelpMessageTest, MultilineHelp)
+{
+  /* arrange */
+  Arser arser;
+
+  arser.add_argument("-v", "--verbose")
+    .nargs(0)
+    .help({"Provides additional details", "Default: No"});
+
+  std::ostringstream oss;
+  std::string expected_out = "Usage: ./arser [-h] [-v] \n"
+                             "\n"
+                             "[Optional argument]\n"
+                             "-h, --help   \tShow help message and exit\n"
+                             "-v, --verbose\tProvides additional details\n"
+                             "             \tDefault: No\n";
+
+  test::Prompt prompt("./arser -v");
+  /* act */
+  arser.parse(prompt.argc(), prompt.argv());
+  oss << arser;
+
+  /* assert */
+  EXPECT_EQ(expected_out, oss.str());
+}
+
+TEST(HelpMessageTest, MultilineHelpEmpty_NEG)
+{
+  /* arrange */
+  Arser arser;
+  std::initializer_list<std::string> help_msg = {};
+
+  EXPECT_THROW(arser.add_argument("-v", "--verbose").nargs(0).help(help_msg), std::runtime_error);
+}
diff --git a/compiler/bino/exclude.me b/compiler/bino/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/caffe2circle/exclude.me b/compiler/caffe2circle/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/caffegen/exclude.me b/compiler/caffegen/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 7b491a3..231f251 100644 (file)
@@ -19,6 +19,7 @@
 #include <dio_hdf5/HDF5Importer.h>
 #include <loco/IR/Graph.h>
 #include <luci/IR/CircleNodes.h>
+#include <luci/IR/DataTypeHelper.h>
 
 #include <cstring>
 #include <dirent.h>
@@ -55,7 +56,7 @@ std::vector<size_t> getEachByteSizeOf(const std::vector<loco::Node *> &nodes)
   for (const auto node : nodes)
   {
     const auto input_node = loco::must_cast<const luci::CircleInput *>(node);
-    const auto dtype_size = loco::size(input_node->dtype());
+    const auto dtype_size = luci::size(input_node->dtype());
     size_t element_size = 1;
 
     for (uint32_t index = 0; index < input_node->rank(); index++)
@@ -76,7 +77,7 @@ size_t getTotalByteSizeOf(const std::vector<loco::Node *> &nodes)
   for (const auto node : nodes)
   {
     const auto input_node = loco::must_cast<const luci::CircleInput *>(node);
-    size_t byte_size = loco::size(input_node->dtype());
+    size_t byte_size = luci::size(input_node->dtype());
 
     for (uint32_t index = 0; index < input_node->rank(); index++)
     {
index 811aa67..988015a 100644 (file)
@@ -18,6 +18,7 @@
 #define CIRCLE_EXECUTION_PLAN_SCRATCHPAD_HELPER_LINUX_H
 
 #include "IScratchpadHelper.h"
+#include <luci/IR/DataTypeHelper.h>
 #include <loco/IR/DataTypeTraits.h>
 
 namespace circle_planner
@@ -45,14 +46,14 @@ public:
     for (int32_t i = 0; i < lhs->rank(); ++i)
       scratchpad_size *= lhs->dim(i).value();
 
-    scratchpad_sizes.push_back(scratchpad_size * loco::size(lhs->dtype()));
+    scratchpad_sizes.push_back(scratchpad_size * luci::size(lhs->dtype()));
 
     // Scratchpad for rhs
     scratchpad_size = 1;
     for (int32_t i = 0; i < rhs->rank(); ++i)
       scratchpad_size *= rhs->dim(i).value();
 
-    scratchpad_sizes.push_back(scratchpad_size * loco::size(rhs->dtype()));
+    scratchpad_sizes.push_back(scratchpad_size * luci::size(rhs->dtype()));
 
     return scratchpad_sizes;
   }
index 8edfde4..76e65dd 100644 (file)
@@ -1,6 +1,6 @@
-if(NOT TARGET mio_circle06)
+if(NOT TARGET mio_circle08)
   return()
-endif(NOT TARGET mio_circle06)
+endif(NOT TARGET mio_circle08)
 
 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_circle06)
-target_link_libraries(circle-inspect mio_circle06_helper)
+target_link_libraries(circle-inspect mio_circle08)
+target_link_libraries(circle-inspect mio_circle08_helper)
 target_link_libraries(circle-inspect safemain)
index b3a2638..8a57c8f 100644 (file)
@@ -1,4 +1,4 @@
 require("arser")
 require("foder")
-require("mio-circle06")
+require("mio-circle08")
 require("safemain")
index 868fc2b..373ac67 100644 (file)
@@ -36,7 +36,7 @@ void DumpOperators::run(std::ostream &os, const circle::Model *model)
     auto ops = reader.operators();
 
     // dump operators
-    for (uint32_t i = 0; i < ops->Length(); ++i)
+    for (uint32_t i = 0; i < ops->size(); ++i)
     {
       const auto op = ops->Get(i);
 
@@ -56,7 +56,7 @@ const circle::Operator *operator_match_output(mio::circle::Reader &reader, const
 {
   auto ops = reader.operators();
 
-  for (uint32_t i = 0; i < ops->Length(); ++i)
+  for (uint32_t i = 0; i < ops->size(); ++i)
   {
     const auto op = ops->Get(i);
 
@@ -75,7 +75,7 @@ size_t tensor_buffer_size(mio::circle::Reader &reader, const int32_t tensor_id)
 {
   auto tensors = reader.tensors();
 
-  if (tensor_id < 0 || tensor_id >= tensors->Length())
+  if (tensor_id < 0 || tensor_id >= tensors->size())
   {
     throw std::runtime_error("Invalid Tensor ID");
   }
@@ -105,7 +105,7 @@ void DumpConv2DWeight::run(std::ostream &os, const circle::Model *model)
     auto ops = reader.operators();
 
     // dump Conv2D, DepthwiseConv2D and its weight input operator
-    for (uint32_t i = 0; i < ops->Length(); ++i)
+    for (uint32_t i = 0; i < ops->size(); ++i)
     {
       const auto op = ops->Get(i);
       auto bc = reader.builtin_code(op);
@@ -158,7 +158,7 @@ void DumpOperatorVersion::run(std::ostream &os, const circle::Model *model)
   auto ops = reader.operators();
 
   // Dump operators' version
-  for (uint32_t i = 0; i < ops->Length(); ++i)
+  for (uint32_t i = 0; i < ops->size(); ++i)
   {
     const auto op = ops->Get(i);
 
@@ -192,7 +192,7 @@ void DumpTensorDType::run(std::ostream &os, const circle::Model *model)
     reader.select_subgraph(g);
     auto tensors = reader.tensors();
 
-    for (uint32_t i = 0; i < tensors->Length(); ++i)
+    for (uint32_t i = 0; i < tensors->size(); ++i)
     {
       const auto tensor = tensors->Get(i);
 
@@ -217,7 +217,7 @@ void DumpConstants::run(std::ostream &os, const circle::Model *model)
     reader.select_subgraph(g);
     auto tensors = reader.tensors();
 
-    for (uint32_t i = 0; i < tensors->Length(); ++i)
+    for (uint32_t i = 0; i < tensors->size(); ++i)
     {
       const auto tensor = tensors->Get(i);
       if (tensor->is_variable())
index 5ca5749..da5d3b6 100644 (file)
@@ -1,3 +1,3 @@
 require("common-artifacts")
 require("circle-interpreter")
-require("luci-value-test")
+require("luci-value-py-test")
index 48c29a5..9c4c879 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <arser/arser.h>
 #include <luci/ImporterEx.h>
+#include <luci/IR/DataTypeHelper.h>
 #include <luci_interpreter/Interpreter.h>
 #include <vconone/vconone.h>
 
@@ -51,7 +52,7 @@ void writeDataToFile(const std::string &filename, const char *data, size_t data_
 
 template <typename NodeT> size_t getTensorSize(const NodeT *node)
 {
-  uint32_t tensor_size = loco::size(node->dtype());
+  uint32_t tensor_size = luci::size(node->dtype());
   for (uint32_t i = 0; i < node->rank(); ++i)
     tensor_size *= node->dim(i).value();
   return tensor_size;
@@ -135,7 +136,8 @@ int entry(int argc, char **argv)
   for (int i = 0; i < module->graph()->outputs()->size(); i++)
   {
     const auto *output_node = loco::must_cast<const luci::CircleOutput *>(output_nodes[i]);
-    std::vector<char> output_data(getTensorSize(output_node));
+    size_t output_size = interpreter.getOutputTensorSize(output_node);
+    std::vector<char> output_data(output_size);
     interpreter.readOutputTensor(output_node, output_data.data(), output_data.size());
 
     // Output data is written in ${output_file}n
index 9af9fc2..ffc7f37 100644 (file)
@@ -37,6 +37,15 @@ set(TEST_SOURCES
     "src/core/Quantizer.cpp"
     "src/bisection/VISQErrorApproximator.cpp"
     "src/core/ErrorMetric.cpp"
+    "src/pattern/PatternResolver.cpp"
+    "src/pattern/PatternSolver.cpp"
+    "src/core/Dumper.cpp"
+    "src/core/DumpingHooks.cpp"
+    "src/core/Evaluator.cpp"
+    "src/MPQSolver.cpp"
+    "src/core/SolverOutput.cpp"
+    "src/bisection/BisectionSolver.cpp"
+    "src/core/DataProvider.cpp"
 )
 
 nnas_find_package(GTest REQUIRED)
@@ -46,3 +55,8 @@ 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)
+target_link_libraries(circle_mpqsolver_test luci_testhelper)
+target_link_libraries(circle_mpqsolver_test luci_import)
+target_link_libraries(circle_mpqsolver_test luci_export)
+target_link_libraries(circle_mpqsolver_test luci_interpreter)
+target_link_libraries(circle_mpqsolver_test dio_hdf5)
index 12981be..0e0ff7e 100644 (file)
 #include <luci/CircleFileExpContract.h>
 
 #include "bisection/BisectionSolver.h"
-#include <core/SolverOutput.h>
+#include "core/DataProvider.h"
+#include "core/SolverOutput.h"
+#include "pattern/PatternSolver.h"
+#include "core/SolverOutput.h"
+#include "core/Quantizer.h"
 
 #include <iostream>
 #include <iomanip>
@@ -47,6 +51,9 @@ int handleAutoAlgorithm(arser::Arser &arser, mpqsolver::bisection::BisectionSolv
 int entry(int argc, char **argv)
 {
   const std::string bisection_str = "--bisection";
+  const std::string patterns_str = "--patterns";
+  const std::string layernorm_str = "--u8_layernorm_with_s16_variance";
+  const std::string softmax_str = "--u8_softmax_with_s16_sub_exp";
   const std::string save_intermediate_str = "--save_intermediate";
 
   arser::Arser arser("circle-mpqsolver provides light-weight methods for finding a high-quality "
@@ -55,7 +62,8 @@ int entry(int argc, char **argv)
   arser::Helper::add_version(arser, print_version);
   arser::Helper::add_verbose(arser);
 
-  arser.add_argument("--data").required(true).help("Path to the test data");
+  // if patterns are set we don't need data
+  arser.add_argument("--data").required(false).default_value("").help("Path to the test data");
   arser.add_argument("--data_format").required(false).help("Test data format (default: h5)");
 
   arser.add_argument("--qerror_ratio")
@@ -65,10 +73,26 @@ int entry(int argc, char **argv)
 
   arser.add_argument(bisection_str)
     .nargs(1)
+    .required(false)
     .type(arser::DataType::STR)
     .help("Single optional argument for bisection method. "
           "Whether input node should be quantized to Q16: 'auto', 'true', 'false'.");
 
+  arser.add_argument(patterns_str)
+    .nargs(0)
+    .required(false)
+    .help("Argument to define patterns applied (LayerNorm is the only supported) ");
+
+  arser.add_argument(layernorm_str)
+    .nargs(0)
+    .required(false)
+    .help("Use int16 for computing variance in uint8 layer normalization");
+
+  arser.add_argument(softmax_str)
+    .nargs(0)
+    .required(false)
+    .help("Use int16 for computing sub and exp in uint8 softmax");
+
   arser.add_argument("--input_model")
     .required(true)
     .help("Input float model with min max initialized");
@@ -83,6 +107,30 @@ int entry(int argc, char **argv)
     .default_value("uint8")
     .help("Data type of quantized model's outputs (default: uint8)");
 
+  arser.add_argument("--quantized_dtype")
+    .type(arser::DataType::STR)
+    .default_value("uint8")
+    .help("Data type of quantized model (supported: uint8 (default), int16)");
+
+  arser.add_argument("--granularity")
+    .type(arser::DataType::STR)
+    .default_value("channel")
+    .help("Granularity of quantization scheme on weight (supported: layer, channel (default)). "
+          "Activation is quantized per layer.");
+
+  arser.add_argument("--TF-style_maxpool")
+    .nargs(0)
+    .default_value(false)
+    .help("Force MaxPool Op to have the same input/output quantparams. NOTE: This feature can "
+          "degrade accuracy of some models");
+
+  arser.add_argument("--save_min_max")
+    .nargs(0)
+    .default_value(false)
+    .help("Save recorded min/max values.");
+
+  // TODO Support --config
+
   arser.add_argument("--output_model").required(true).help("Output quantized model");
 
   arser.add_argument("--visq_file")
@@ -119,6 +167,10 @@ int entry(int argc, char **argv)
   auto output_model_path = arser.get<std::string>("--output_model");
   auto input_dtype = arser.get<std::string>("--input_dtype");
   auto output_dtype = arser.get<std::string>("--output_dtype");
+  auto quantized_dtype = arser.get<std::string>("--quantized_dtype");
+  auto granularity = arser.get<std::string>("--granularity");
+  auto TF_style_maxpool = arser["--TF-style_maxpool"] and arser.get<bool>("--TF-style_maxpool");
+  auto save_min_max = arser["--save_min_max"] and arser.get<bool>("--save_min_max");
 
   float qerror_ratio = arser.get<float>("--qerror_ratio");
   if (qerror_ratio < 0.0 || qerror_ratio > 1.f)
@@ -127,24 +179,54 @@ int entry(int argc, char **argv)
     return EXIT_FAILURE;
   }
 
+  if (arser[bisection_str] && arser[patterns_str])
+  {
+    // only one solver can be used for now
+    std::cerr << "ERROR: only one method is allowed to use" << std::endl;
+    return EXIT_FAILURE;
+  }
+
   SolverOutput::get() << ">> Searching mixed precision configuration \n"
                       << "model:" << input_model_path << "\n"
                       << "dataset: " << data_path << "\n"
+                      << "quantized dtype: " << quantized_dtype << "\n"
+                      << "granularity: " << granularity << "\n"
                       << "input dtype: " << input_dtype << "\n"
-                      << "output dtype: " << output_dtype << "\n";
+                      << "output dtype: " << output_dtype << "\n"
+                      << "TF_style_maxpool: " << (TF_style_maxpool ? "True" : "False") << "\n"
+                      << "save_min_max: " << (save_min_max ? "True" : "False") << "\n";
+
+  std::unique_ptr<mpqsolver::MPQSolver> solver;
+
+  // Create quantizer parameters
+  mpqsolver::core::Quantizer::Context ctx;
+  {
+    ctx.output_model_dtype = quantized_dtype;
+    ctx.granularity = granularity;
+    ctx.input_type = input_dtype;
+    ctx.output_type = output_dtype;
+    ctx.save_min_max = save_min_max;
+    ctx.TF_style_maxpool = TF_style_maxpool;
+  }
 
   if (arser[bisection_str])
   {
     // optimize
+    SolverOutput::get() << "Automatic mixed quantization using bisection\n";
+
     using namespace mpqsolver::bisection;
 
-    BisectionSolver solver(data_path, qerror_ratio, input_dtype, output_dtype);
+    auto bi_solver = std::make_unique<BisectionSolver>(ctx, qerror_ratio);
+    auto input_data =
+      std::make_unique<mpqsolver::core::H5FileDataProvider>(data_path, input_model_path);
+    bi_solver->setInputData(std::move(input_data));
+
     {
       auto value = arser.get<std::string>(bisection_str);
       if (value == "auto")
       {
         SolverOutput::get() << "algorithm: bisection (auto)\n";
-        if (!handleAutoAlgorithm(arser, solver))
+        if (!handleAutoAlgorithm(arser, *bi_solver))
         {
           return EXIT_FAILURE;
         }
@@ -152,12 +234,12 @@ int entry(int argc, char **argv)
       else if (value == "true")
       {
         SolverOutput::get() << "algorithm: bisection (Q16AtFront)";
-        solver.algorithm(BisectionSolver::Algorithm::ForceQ16Front);
+        bi_solver->algorithm(BisectionSolver::Algorithm::ForceQ16Front);
       }
       else if (value == "false")
       {
         SolverOutput::get() << "algorithm: bisection (Q8AtFront)";
-        solver.algorithm(BisectionSolver::Algorithm::ForceQ16Back);
+        bi_solver->algorithm(BisectionSolver::Algorithm::ForceQ16Back);
       }
       else
       {
@@ -167,37 +249,26 @@ 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)
+    solver.reset(bi_solver.release());
+  }
+  else if (arser[patterns_str])
+  {
+    SolverOutput::get() << "Automatic mixed quantization using patterns\n";
+
+    std::vector<mpqsolver::pattern::QuantizationPattern> patterns;
+    if (arser[layernorm_str])
     {
-      std::cerr << "ERROR: Failed to build mixed precision model" << input_model_path << std::endl;
-      return EXIT_FAILURE;
+      patterns.push_back(mpqsolver::pattern::QuantizationPattern::Q8LayerNormWithQ16Variance);
     }
-
-    // save optimized
+    if (arser[softmax_str])
     {
-      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))
-      {
-        std::cerr << "ERROR: Failed to export mixed precision model" << input_model_path
-                  << std::endl;
-        return EXIT_FAILURE;
-      }
+      patterns.push_back(mpqsolver::pattern::QuantizationPattern::Q8SoftmaxWithQ16SubExp);
     }
+
+    solver = std::make_unique<mpqsolver::pattern::PatternSolver>(ctx, patterns);
   }
   else
   {
@@ -205,5 +276,33 @@ int entry(int argc, char **argv)
     return EXIT_FAILURE;
   }
 
+  if (arser[save_intermediate_str])
+  {
+    auto data_path = arser.get<std::string>(save_intermediate_str);
+    if (!data_path.empty())
+    {
+      solver->setSaveIntermediate(data_path);
+    }
+  }
+
+  auto optimized = solver->run(input_model_path);
+  if (optimized == nullptr)
+  {
+    std::cerr << "ERROR: Failed to build mixed precision model" << input_model_path << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  // 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))
+    {
+      std::cerr << "ERROR: Failed to export mixed precision model" << input_model_path << std::endl;
+      return EXIT_FAILURE;
+    }
+  }
+
   return EXIT_SUCCESS;
 }
index 10cfbb6..7ed7493 100644 (file)
 
 #include "MPQSolver.h"
 
+#include <luci/ImporterEx.h>
+#include <iostream>
+
 using namespace mpqsolver;
 
-MPQSolver::MPQSolver(const std::string &input_data_path, float qerror_ratio,
-                     const std::string &input_quantization, const std::string &output_quantization)
-  : _input_data_path(input_data_path), _qerror_ratio(qerror_ratio),
-    _input_quantization(input_quantization), _output_quantization(output_quantization)
+MPQSolver::MPQSolver(const core::Quantizer::Context &ctx)
 {
+  _quantizer = std::make_unique<core::Quantizer>(ctx);
 }
 
-void MPQSolver::set_save_intermediate(const std::string &save_path)
+void MPQSolver::setSaveIntermediate(const std::string &save_path)
 {
-  _hooks = std::make_unique<core::DumpingHooks>(save_path);
+  _hooks = std::make_unique<core::DumpingHooks>(save_path, _quantizer->getContext());
+}
+
+std::unique_ptr<luci::Module> MPQSolver::readModule(const std::string &path)
+{
+  luci::ImporterEx importerex;
+  auto module = importerex.importVerifyModule(path);
+  if (module.get() == nullptr)
+  {
+    throw std::runtime_error("Failed to load model");
+  }
+
+  return module;
 }
index 6c5d25d..0903806 100644 (file)
  * limitations under the License.
  */
 
-#ifndef __MPQSOLVER_MPQSOLEVR_SOLVER_H__
-#define __MPQSOLVER_MPQSOLEVR_SOLVER_H__
+#ifndef __MPQSOLVER_MPQSOLVER_SOLVER_H__
+#define __MPQSOLVER_MPQSOLVER_SOLVER_H__
 
-#include <core/DumpingHooks.h>
+#include "core/Quantizer.h"
+#include "core/DumpingHooks.h"
+
+#include <luci/IR/CircleNodes.h>
 
 #include <memory>
 #include <string>
@@ -28,13 +31,8 @@ namespace mpqsolver
 class MPQSolver
 {
 public:
-  /**
-   * @brief construct Solver using input_data_path for .h5 file,
-   * qerror_ratio to set target qerror, and input_quantization/output_quantization to set
-   * quantization type at input/output respectively
-   */
-  MPQSolver(const std::string &input_data_path, float qerror_ratio,
-            const std::string &input_quantization, const std::string &output_quantization);
+  MPQSolver(const core::Quantizer::Context &ctx);
+
   virtual ~MPQSolver() = default;
 
   /**
@@ -45,16 +43,18 @@ public:
   /**
    * @brief set all intermediate artifacts to be saved
    */
-  void set_save_intermediate(const std::string &save_path);
+  void setSaveIntermediate(const std::string &save_path);
+
+protected:
+  std::unique_ptr<luci::Module> readModule(const std::string &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::Quantizer> _quantizer;
   std::unique_ptr<core::DumpingHooks> _hooks;
 };
 
 } // namespace mpqsolver
 
-#endif //__MPQSOLVER_MPQSOLEVR_SOLVER_H__
+#endif //__MPQSOLVER_MPQSOLVER_SOLVER_H__
index 976dac5..d36ccfe 100644 (file)
@@ -18,8 +18,9 @@
 #include "DepthParameterizer.h"
 #include "VISQErrorApproximator.h"
 
-#include <core/ErrorMetric.h>
-#include <core/SolverOutput.h>
+#include "core/DataProvider.h"
+#include "core/ErrorMetric.h"
+#include "core/SolverOutput.h"
 
 #include <luci/ImporterEx.h>
 
@@ -72,36 +73,22 @@ bool front_has_higher_error(const NodeDepthType &nodes_depth, const std::string
   return error_at_input > error_at_output;
 }
 
-std::unique_ptr<luci::Module> read_module(const std::string &path)
-{
-  luci::ImporterEx importerex;
-  auto module = importerex.importVerifyModule(path);
-  if (module.get() == nullptr)
-  {
-    std::cerr << "ERROR: Failed to load " << path << std::endl;
-    return nullptr;
-  }
-
-  return module;
-}
-
 } // namespace
 
-BisectionSolver::BisectionSolver(const std::string &input_data_path, float qerror_ratio,
-                                 const std::string &input_quantization,
-                                 const std::string &output_quantization)
-  : MPQSolver(input_data_path, qerror_ratio, input_quantization, output_quantization)
+BisectionSolver::BisectionSolver(const mpqsolver::core::Quantizer::Context &ctx, float qerror_ratio)
+  : MPQSolver(ctx), _qerror_ratio(qerror_ratio)
 {
-  _quantizer = std::make_unique<core::Quantizer>(_input_quantization, _output_quantization);
 }
 
 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);
+  auto model = readModule(flt_path);
+  assert(model != nullptr);
+
   // get fake quantized model for evaluation
-  if (!_quantizer->fake_quantize(model.get(), def_quant, layers))
+  if (!_quantizer->fakeQuantize(model.get(), def_quant, layers))
   {
     throw std::runtime_error("Failed to produce fake-quantized model.");
   }
@@ -113,9 +100,15 @@ void BisectionSolver::algorithm(Algorithm algorithm) { _algorithm = algorithm; }
 
 void BisectionSolver::setVisqPath(const std::string &visq_path) { _visq_data_path = visq_path; }
 
+void BisectionSolver::setInputData(std::unique_ptr<mpqsolver::core::DataProvider> &&data)
+{
+  _input_data = std::move(data);
+}
+
 std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_path)
 {
-  auto module = read_module(module_path);
+  auto module = readModule(module_path);
+  assert(module != nullptr);
 
   float min_depth = 0.f;
   float max_depth = 0.f;
@@ -130,7 +123,11 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
   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());
+  if (!_input_data)
+  {
+    throw std::runtime_error("no input data");
+  }
+  core::DatasetEvaluator evaluator(module.get(), *_input_data.get(), *metric.get());
 
   core::LayerParams layer_params;
   float int16_qerror =
@@ -140,10 +137,10 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
   float uint8_qerror =
     evaluate(evaluator, module_path, "uint8" /* default quant_dtype */, layer_params);
   SolverOutput::get() << "Full uint8 model qerror: " << uint8_qerror << "\n";
-  _quantizer->set_hook(_hooks.get());
+  _quantizer->setHook(_hooks.get());
   if (_hooks)
   {
-    _hooks->on_begin_solver(module_path, uint8_qerror, int16_qerror);
+    _hooks->onBeginSolver(module_path, uint8_qerror, int16_qerror);
   }
 
   if (int16_qerror > uint8_qerror)
@@ -154,19 +151,46 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
   _qerror = int16_qerror + _qerror_ratio * std::fabs(uint8_qerror - int16_qerror);
   SolverOutput::get() << "Target qerror: " << _qerror << "\n";
 
-  if (uint8_qerror <= _qerror)
+  // it'is assumed that int16_qerror <= _qerror <= uint8_qerror,
+  if (int16_qerror >= _qerror)
+  {
+    // return Q16 model (we can not make it more accurate)
+    if (!_quantizer->quantize(module.get(), "int16", layer_params))
+    {
+      std::cerr << "ERROR: Failed to quantize model" << std::endl;
+      return nullptr;
+    }
+
+    if (_hooks)
+    {
+      _hooks->onEndSolver(layer_params, "int16", int16_qerror);
+    }
+
+    SolverOutput::get() << "The best configuration is int16 configuration\n";
+    return module;
+  }
+  else if (uint8_qerror <= _qerror)
   {
-    // no need for bisectioning just return Q8 model
+    // return Q8 model (we can not make it less accurate)
     if (!_quantizer->quantize(module.get(), "uint8", layer_params))
     {
       std::cerr << "ERROR: Failed to quantize model" << std::endl;
       return nullptr;
     }
+
+    if (_hooks)
+    {
+      _hooks->onEndSolver(layer_params, "uint8", uint8_qerror);
+    }
+
+    SolverOutput::get() << "The best configuration is uint8 configuration\n";
+    return module;
   }
 
+  // search for optimal mixed precision quantization configuration
   int last_depth = -1;
   float best_depth = -1;
-  float best_accuracy = -1;
+  float best_error = -1; // minimal error
   core::LayerParams best_params;
   if (module->size() != 1)
   {
@@ -207,11 +231,6 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
 
   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)
@@ -219,6 +238,11 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
       break;
     }
 
+    if (_hooks)
+    {
+      _hooks->onBeginIteration();
+    }
+
     SolverOutput::get() << "Looking for the optimal configuration in [" << min_depth << " , "
                         << max_depth << "] depth segment\n";
 
@@ -249,34 +273,34 @@ std::unique_ptr<luci::Module> BisectionSolver::run(const std::string &module_pat
       }
     }
 
-    float cur_accuracy = evaluate(evaluator, module_path, "uint8", layer_params);
+    float cur_error = evaluate(evaluator, module_path, "uint8", layer_params);
 
     if (_hooks)
     {
-      _hooks->on_end_iteration(layer_params, "uint8", cur_accuracy);
+      _hooks->onEndIteration(layer_params, "uint8", cur_error);
     }
 
-    if (cur_accuracy < _qerror)
+    if (cur_error < _qerror)
     {
-      SolverOutput::get() << "Qerror at depth " << cut_depth << " is " << cur_accuracy
+      SolverOutput::get() << "Qerror at depth " << cut_depth << " is " << cur_error
                           << " < 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;
+      best_error = cur_error;
     }
     else
     {
-      SolverOutput::get() << "Qerror at depth " << cut_depth << " is " << cur_accuracy
-                          << (cur_accuracy > _qerror ? " > " : " == ") << "target qerror ("
-                          << _qerror << ")\n";
+      SolverOutput::get() << "Qerror at depth " << cut_depth << " is " << cur_error
+                          << (cur_error > _qerror ? " > " : " == ") << "target qerror (" << _qerror
+                          << ")\n";
       int16_front ? (min_depth = cut_depth) : (max_depth = cut_depth);
     }
   }
 
   if (_hooks)
   {
-    _hooks->on_end_solver(best_params, "uint8", best_accuracy);
+    _hooks->onEndSolver(best_params, "uint8", best_error);
   }
 
   SolverOutput::get() << "Found the best configuration at depth " << best_depth << "\n";
index 83851c0..a3191c5 100644 (file)
@@ -17,9 +17,8 @@
 #ifndef __MPQSOLVER_BISECTION_SOLVER_H__
 #define __MPQSOLVER_BISECTION_SOLVER_H__
 
-#include <core/Quantizer.h>
-#include <core/Evaluator.h>
-#include <MPQSolver.h>
+#include "core/Evaluator.h"
+#include "MPQSolver.h"
 
 #include <luci/IR/Module.h>
 
@@ -46,12 +45,13 @@ public:
 
 public:
   /**
-   * @brief construct Solver using input_data_path for .h5 file,
-   * qerror_ratio to set target qerror, and input_quantization/output_quantization to set
-   * quantization type at input/output respectively
+   * @brief Construct a new Bisection Solver object
+   *
+   * @param ctx - quantizer context
+   * @param qerror_ratio - target error ratio
    */
-  BisectionSolver(const std::string &input_data_path, float qerror_ratio,
-                  const std::string &input_quantization, const std::string &output_quantization);
+  BisectionSolver(const mpqsolver::core::Quantizer::Context &ctx, float qerror_ratio);
+
   BisectionSolver() = delete;
 
   /**
@@ -60,6 +60,11 @@ public:
   std::unique_ptr<luci::Module> run(const std::string &module_path) override;
 
   /**
+   * @brief set data provider
+   */
+  void setInputData(std::unique_ptr<mpqsolver::core::DataProvider> &&data);
+
+  /**
    * @brief set used algorithm
    */
   void algorithm(Algorithm algorithm);
@@ -76,10 +81,11 @@ private:
                  const std::string &def_quant, core::LayerParams &layers);
 
 private:
-  float _qerror = 0.f; // quantization error
+  const float _qerror_ratio = 0.f; // quantization error ratio
+  float _qerror = 0.f;             // quantization error
   Algorithm _algorithm = Algorithm::ForceQ16Front;
-  std::unique_ptr<core::Quantizer> _quantizer;
   std::string _visq_data_path;
+  std::unique_ptr<mpqsolver::core::DataProvider> _input_data;
 };
 
 } // namespace bisection
diff --git a/compiler/circle-mpqsolver/src/bisection/BisectionSolver.test.cpp b/compiler/circle-mpqsolver/src/bisection/BisectionSolver.test.cpp
new file mode 100644 (file)
index 0000000..a7a7d24
--- /dev/null
@@ -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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "BisectionSolver.h"
+
+#include "core/SolverOutput.h"
+#include "core/TestHelper.h"
+
+#include <luci/CircleExporter.h>
+#include <luci/CircleFileExpContract.h>
+
+namespace
+{
+
+class CircleMPQSolverBisectionSolverTestF : public ::testing::Test
+{
+public:
+  CircleMPQSolverBisectionSolverTestF()
+  {
+    char module_template[] = "CircleMPQSolverBisectionSolverTest-CIRCLE-XXXXXX";
+    mpqsolver::test::io_utils::makeTemporaryFile(module_template);
+    _module_path = module_template;
+  }
+
+  ~CircleMPQSolverBisectionSolverTestF() { unlink(_module_path.c_str()); }
+
+protected:
+  mpqsolver::test::models::AddGraph _g;
+  std::string _module_path;
+};
+
+} // namespace
+
+TEST_F(CircleMPQSolverBisectionSolverTestF, verifyResultsTest)
+{
+  // create network
+  auto m = luci::make_module();
+  _g.init();
+  _g.transfer_to(m.get());
+
+  // export to _module_path
+  luci::CircleExporter exporter;
+  luci::CircleFileExpContract contract(m.get(), _module_path);
+  EXPECT_TRUE(exporter.invoke(&contract));
+
+  // create solver
+  mpqsolver::core::Quantizer::Context ctx;
+  mpqsolver::bisection::BisectionSolver solver(ctx, 0.5);
+  auto data = mpqsolver::test::data_utils::getAllZeroSingleDataProvider();
+  solver.setInputData(std::move(data));
+  solver.algorithm(mpqsolver::bisection::BisectionSolver::Algorithm::ForceQ16Back);
+  SolverOutput::get().TurnOn(false);
+
+  // run solver
+  auto res = solver.run(_module_path);
+  EXPECT_TRUE(res.get() != nullptr);
+}
+
+TEST(CircleMPQSolverBisectionSolverTest, empty_path_NEG)
+{
+  mpqsolver::core::Quantizer::Context ctx;
+  mpqsolver::bisection::BisectionSolver solver(ctx, 0.0);
+  solver.algorithm(mpqsolver::bisection::BisectionSolver::Algorithm::ForceQ16Back);
+  EXPECT_ANY_THROW(solver.run(""));
+}
index 504032d..c874247 100644 (file)
 #include <gtest/gtest.h>
 
 #include "DepthParameterizer.h"
-#include <core/TestHelper.h>
+#include "core/TestHelper.h"
 
 #include <luci/IR/CircleNodes.h>
 
 namespace
 {
 
-class NConvGraph final : public SimpleGraph
+class NConvGraph final : public mpqsolver::test::models::SimpleGraph
 {
 protected:
   loco::Node *insertGraphBody(loco::Node *input) override
@@ -43,7 +43,7 @@ protected:
     _conv->padding(luci::Padding::SAME);
     _conv->fusedActivationFunction(luci::FusedActFunc::NONE);
     _conv->dtype(loco::DataType::FLOAT32);
-    _conv->shape({1, _width, _height, _channel_size});
+    _conv->shape({1, _height, _width, _channel_size});
     _conv->name("conv");
     _conv->filter(_filter);
     _conv->bias(_bias);
index ee6376a..c810497 100644 (file)
@@ -44,7 +44,7 @@ void VISQErrorApproximator::init(std::istream &visq_data)
 
   auto layers = completeJsonData["error"][0];
   auto names = layers.getMemberNames();
-  for (auto name : names)
+  for (const auto &name : names)
   {
     auto value = layers[name].asFloat();
     _layer_errors[name] = value;
index ccacb1a..5542abe 100644 (file)
 
 #include "VISQErrorApproximator.h"
 
+#include "core/TestHelper.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";
@@ -57,8 +36,8 @@ TEST(CircleMPQSolverVISQErrorApproximatorTest, verifyResultsTest)
   auto data = Json::writeString(builder, error_data);
 
   char path[] = "VISQErrorApproximator-TEST-XXXXXX";
-  makeTemporaryFile(path);
-  writeDataToFile(path, data);
+  mpqsolver::test::io_utils::makeTemporaryFile(path);
+  mpqsolver::test::io_utils::writeDataToFile(path, data);
 
   mpqsolver::bisection::VISQErrorApproximator approximator;
   EXPECT_NO_THROW(approximator.init(path));
@@ -74,8 +53,8 @@ TEST(CircleMPQSolverVISQErrorApproximatorTest, verifyResultsTest_NEG)
   auto data = Json::writeString(builder, error_data);
 
   char path[] = "VISQErrorApproximator-TEST-NEG-XXXXXX";
-  makeTemporaryFile(path);
-  writeDataToFile(path, data);
+  mpqsolver::test::io_utils::makeTemporaryFile(path);
+  mpqsolver::test::io_utils::writeDataToFile(path, data);
 
   mpqsolver::bisection::VISQErrorApproximator approximator;
   EXPECT_THROW(approximator.init(path), std::exception);
diff --git a/compiler/circle-mpqsolver/src/core/DataProvider.cpp b/compiler/circle-mpqsolver/src/core/DataProvider.cpp
new file mode 100644 (file)
index 0000000..889e278
--- /dev/null
@@ -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 "DataProvider.h"
+
+#include <luci/ImporterEx.h>
+#include <luci/IR/CircleNodes.h>
+
+using namespace mpqsolver::core;
+
+using Shape = std::vector<loco::Dimension>;
+
+namespace
+{
+
+// Check the type and the shape of input_node
+// Throw an exception if type or shape does not match
+void verifyTypeShape(const luci::CircleNode *input_node, const loco::DataType &dtype,
+                     const Shape &shape)
+{
+  assert(input_node != nullptr); // FIX_CALLER_UNLESS
+
+  // Type check
+  if (dtype != input_node->dtype())
+    throw std::runtime_error("Wrong input type.");
+
+  if (shape.size() != input_node->rank())
+    throw std::runtime_error("Input rank mismatch.");
+
+  for (uint32_t i = 0; i < shape.size(); i++)
+  {
+    if (not(shape.at(i) == input_node->dim(i)))
+      throw std::runtime_error("Input shape mismatch.");
+  }
+}
+
+} // namespace
+
+H5FileDataProvider::H5FileDataProvider(const std::string &h5file, const std::string &module_path)
+  : _importer(h5file)
+{
+  _importer.importGroup("value");
+  _is_raw_data = _importer.isRawData();
+
+  luci::ImporterEx importerex;
+  _module = importerex.importVerifyModule(module_path);
+  if (_module.get() != nullptr)
+  {
+    _input_nodes = loco::input_nodes(_module.get()->graph());
+  }
+}
+
+size_t H5FileDataProvider::numSamples() const { return _importer.numData(); }
+
+uint32_t H5FileDataProvider::numInputs(uint32_t sample) const
+{
+  return static_cast<uint32_t>(_importer.numInputs(sample));
+}
+
+void H5FileDataProvider::getSampleInput(uint32_t sample, uint32_t input, InputData &data) const
+{
+  if (_is_raw_data)
+  {
+    _importer.readTensor(sample, input, data.data().data(), data.data().size());
+  }
+  else
+  {
+    loco::DataType dtype;
+    Shape shape;
+    _importer.readTensor(sample, input, &dtype, &shape, data.data().data(), data.data().size());
+
+    // Check the type and the shape of the input data is valid
+    auto input_node = loco::must_cast<luci::CircleNode *>(_input_nodes.at(input));
+    verifyTypeShape(input_node, dtype, shape);
+  }
+}
diff --git a/compiler/circle-mpqsolver/src/core/DataProvider.h b/compiler/circle-mpqsolver/src/core/DataProvider.h
new file mode 100644 (file)
index 0000000..d234ab2
--- /dev/null
@@ -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 __MPQSOLVER_DATA_PROVIDER_H__
+#define __MPQSOLVER_DATA_PROVIDER_H__
+
+#include <dio_hdf5/HDF5Importer.h>
+
+#include <luci/IR/Module.h>
+
+#include <string>
+#include <vector>
+
+namespace mpqsolver
+{
+namespace core
+{
+
+struct InputData
+{
+  InputData(size_t size) : _data(size) {}
+
+  const std::vector<char> &data() const { return _data; }
+
+  std::vector<char> &data() { return _data; }
+
+private:
+  std::vector<char> _data;
+};
+
+class DataProvider
+{
+public:
+  virtual ~DataProvider() = default;
+  virtual size_t numSamples() const = 0;
+  virtual uint32_t numInputs(uint32_t sample) const = 0;
+  virtual void getSampleInput(uint32_t sample, uint32_t input, InputData &data) const = 0;
+};
+
+class H5FileDataProvider final : public DataProvider
+{
+public:
+  H5FileDataProvider(const std::string &h5file, const std::string &module_path);
+  size_t numSamples() const override;
+  uint32_t numInputs(uint32_t sample) const override;
+  void getSampleInput(uint32_t sample, uint32_t input, InputData &data) const override;
+
+private:
+  std::vector<loco::Node *> _input_nodes;
+  std::unique_ptr<luci::Module> _module;
+  dio::hdf5::HDF5Importer _importer;
+  bool _is_raw_data = false;
+};
+
+} // namespace core
+} // namespace mpqsolver
+
+#endif //__MPQSOLVER_DATA_PROVIDER_H__
index 3a94cb3..29a0bd1 100644 (file)
@@ -40,14 +40,14 @@ const std::string layer_granularity_key = "granularity";
 
 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::setModelPath(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
+void Dumper::dumpMPQConfiguration(const LayerParams &layers, const std::string &def_dtype,
+                                  const std::string &def_granularity, const std::string &path) const
 {
   Json::Value mpq_data;
   mpq_data[default_dtype_key] = def_dtype;
-  mpq_data[default_granularity_key] = "channel";
+  mpq_data[default_granularity_key] = def_granularity;
   mpq_data[model_key] = _model_path;
 
   Json::Value layers_data;
@@ -64,10 +64,10 @@ void Dumper::dump_MPQ_configuration(const LayerParams &layers, const std::string
   Json::StreamWriterBuilder builder;
   auto data = Json::writeString(builder, mpq_data);
 
-  write_data_to_file(path, data);
+  writeDataToFile(path, data);
 }
 
-void Dumper::prepare_directory(const std::string &dir_path) const
+void Dumper::prepareDirectory(const std::string &dir_path) const
 {
   struct stat sb;
   if (stat(dir_path.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode))
@@ -79,22 +79,23 @@ void Dumper::prepare_directory(const std::string &dir_path) const
   }
 }
 
-void Dumper::dump_MPQ_configuration(const LayerParams &layers, const std::string &def_dtype,
-                                    int step) const
+void Dumper::dumpMPQConfiguration(const LayerParams &layers, const std::string &def_dtype,
+                                  const std::string &def_granularity, int step) const
 {
-  prepare_directory(_dir_path);
+  prepareDirectory(_dir_path);
   std::string path = _dir_path + "/Configuration_" + std::to_string(step) + ".mpq.json";
-  dump_MPQ_configuration(layers, def_dtype, path);
+  dumpMPQConfiguration(layers, def_dtype, def_granularity, path);
 }
 
-void Dumper::dump_final_MPQ(const LayerParams &layers, const std::string &def_dtype) const
+void Dumper::dumpFinalMPQ(const LayerParams &layers, const std::string &def_dtype,
+                          const std::string &def_granularity) const
 {
-  prepare_directory(_dir_path);
+  prepareDirectory(_dir_path);
   std::string path = _dir_path + "/FinalConfiguration" + ".mpq.json";
-  dump_MPQ_configuration(layers, def_dtype, path);
+  dumpMPQConfiguration(layers, def_dtype, def_granularity, path);
 }
 
-void Dumper::write_data_to_file(const std::string &path, const std::string &data) const
+void Dumper::writeDataToFile(const std::string &path, const std::string &data) const
 {
   std::ofstream file;
   file.open(path);
@@ -102,7 +103,7 @@ void Dumper::write_data_to_file(const std::string &path, const std::string &data
   file.close();
 }
 
-void Dumper::save_circle(luci::Module *module, std::string &path) const
+void Dumper::saveCircle(luci::Module *module, std::string &path) const
 {
   luci::CircleExporter exporter;
   luci::CircleFileExpContract contract(module, path);
@@ -112,13 +113,13 @@ void Dumper::save_circle(luci::Module *module, std::string &path) const
   }
 }
 
-void Dumper::dump_quantized(luci::Module *module, uint32_t step) const
+void Dumper::dumpQuantized(luci::Module *module, uint32_t step) const
 {
   std::string path = _dir_path + "/quantized_" + std::to_string(step) + ".mpq.circle";
-  save_circle(module, path);
+  saveCircle(module, path);
 }
 
-void Dumper::dump_error(float error, const std::string &tag, const std::string &path) const
+void Dumper::dumpError(float error, const std::string &tag, const std::string &path) const
 {
   std::ofstream file;
   file.open(path, std::ios_base::app);
@@ -126,35 +127,35 @@ void Dumper::dump_error(float error, const std::string &tag, const std::string &
   file.close();
 }
 
-void Dumper::prepare_for_error_dumping() const
+void Dumper::prepareForErrorDumping() const
 {
-  prepare_directory(_dir_path);
-  std::string path = get_error_path();
+  prepareDirectory(_dir_path);
+  std::string path = getErrorPath();
   std::ofstream file;
   file.open(path); // create empty
   file.close();
 }
 
-void Dumper::dump_Q8_error(float error) const
+void Dumper::dumpQ8Error(float error) const
 {
-  std::string path = get_error_path();
-  dump_error(error, "Q8", path);
+  std::string path = getErrorPath();
+  dumpError(error, "Q8", path);
 }
 
-void Dumper::dump_Q16_error(float error) const
+void Dumper::dumpQ16Error(float error) const
 {
-  std::string path = get_error_path();
-  dump_error(error, "Q16", path);
+  std::string path = getErrorPath();
+  dumpError(error, "Q16", path);
 }
 
-void Dumper::dump_MPQ_error(float error, uint32_t step) const
+void Dumper::dumpMPQError(float error, uint32_t step) const
 {
-  std::string path = get_error_path();
-  dump_error(error, std::to_string(step), path);
+  std::string path = getErrorPath();
+  dumpError(error, std::to_string(step), path);
 }
 
-void Dumper::dump_MPQ_error(float error) const
+void Dumper::dumpMPQError(float error) const
 {
-  std::string path = get_error_path();
-  dump_error(error, "FINAL", path);
+  std::string path = getErrorPath();
+  dumpError(error, "FINAL", path);
 }
index 220b54a..48762f2 100644 (file)
@@ -39,67 +39,70 @@ public:
   /**
    * @brief sets model path for further usage
    */
-  void set_model_path(const std::string &model_path);
+  void setModelPath(const std::string &model_path);
 
   /**
    * @brief dumps mpq configuration
    * @param layers specific quantization parameters
    * @param def_dtype default quantization data type
+   * @param def_granularity default granularity
    * @param step id of mpq configuration
    */
-  void dump_MPQ_configuration(const LayerParams &layers, const std::string &def_dtype,
-                              int step) const;
+  void dumpMPQConfiguration(const LayerParams &layers, const std::string &def_dtype,
+                            const std::string &def_granularity, int step) const;
 
   /**
    * @brief dumps final mpq configuration
    * @param layers specific quantization parameters
    * @param def_dtype default quantization data type
+   * @param def_granularity default granularity
    */
-  void dump_final_MPQ(const LayerParams &layers, const std::string &def_dtype) const;
+  void dumpFinalMPQ(const LayerParams &layers, const std::string &def_dtype,
+                    const std::string &def_granularity) 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;
+  void dumpQuantized(luci::Module *module, uint32_t step) const;
 
   /**
    * @brief create file for error dumping
    */
-  void prepare_for_error_dumping() const;
+  void prepareForErrorDumping() const;
 
   /**
    * @brief append error of Q8 quantization
    */
-  void dump_Q8_error(float error) const;
+  void dumpQ8Error(float error) const;
 
   /**
    * @brief append error of Q16 quantization
    */
-  void dump_Q16_error(float error) const;
+  void dumpQ16Error(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;
+  void dumpMPQError(float error, uint32_t step) const;
 
   /**
    * @brief dump final error
    * @param error final error of quantization
    */
-  void dump_MPQ_error(float error) const;
+  void dumpMPQError(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"; }
+  void writeDataToFile(const std::string &path, const std::string &data) const;
+  void dumpMPQConfiguration(const LayerParams &layers, const std::string &def_dtype,
+                            const std::string &def_granularity, const std::string &path) const;
+  void prepareDirectory(const std::string &dir_path) const;
+  void saveCircle(luci::Module *module, std::string &path) const;
+  void dumpError(float error, const std::string &tag, const std::string &path) const;
+  std::string getErrorPath() const { return _dir_path + "/errors" + ".mpq.txt"; }
 
 private:
   std::string _dir_path;
diff --git a/compiler/circle-mpqsolver/src/core/Dumper.test.cpp b/compiler/circle-mpqsolver/src/core/Dumper.test.cpp
new file mode 100644 (file)
index 0000000..40c4d7f
--- /dev/null
@@ -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 <gtest/gtest.h>
+
+#include "Dumper.h"
+#include "core/TestHelper.h"
+
+#include <fstream>
+#include <ftw.h>
+#include <string>
+
+namespace
+{
+
+class CircleMPQSolverDumperTest : public ::testing::Test
+{
+public:
+  CircleMPQSolverDumperTest()
+  {
+    char folderTemplate[] = "CircleMPQSolverDumperTestXXXXXX";
+    _folder = mpqsolver::test::io_utils::makeTemporaryFolder(folderTemplate);
+  }
+
+  ~CircleMPQSolverDumperTest()
+  {
+    // cleanup
+    auto callback = [](const char *child, const struct stat *, int, struct FTW *) {
+      return remove(child);
+    };
+    nftw(_folder.c_str(), callback, 128, FTW_DEPTH | FTW_MOUNT | FTW_PHYS);
+  }
+
+protected:
+  std::string _folder;
+};
+
+} // namespace
+
+TEST_F(CircleMPQSolverDumperTest, verifyResultsTest)
+{
+  mpqsolver::core::Dumper dumper(_folder);
+  dumper.setModelPath("");
+  mpqsolver::core::LayerParams params;
+  auto const step = 0;
+  dumper.dumpMPQConfiguration(params, "uint8", "channel", step);
+
+  std::string step_path = _folder + "/Configuration_" + std::to_string(step) + ".mpq.json";
+  EXPECT_TRUE(mpqsolver::test::io_utils::isFileExists(step_path));
+
+  dumper.dumpFinalMPQ(params, "uint8", "channel");
+  std::string fin_path = _folder + "/FinalConfiguration" + ".mpq.json";
+  EXPECT_TRUE(mpqsolver::test::io_utils::isFileExists(fin_path));
+
+  dumper.prepareForErrorDumping();
+  std::string errors_path = _folder + "/errors" + ".mpq.txt";
+  EXPECT_TRUE(mpqsolver::test::io_utils::isFileExists(errors_path));
+}
+
+TEST_F(CircleMPQSolverDumperTest, empty_path_NEG)
+{
+  mpqsolver::core::Dumper dumper("");
+  dumper.setModelPath("");
+
+  mpqsolver::core::LayerParams params;
+  auto const step = 0;
+  EXPECT_THROW(dumper.dumpMPQConfiguration(params, "uint8", "channel", step), std::runtime_error);
+  EXPECT_THROW(dumper.dumpFinalMPQ(params, "uint8", "channel"), std::runtime_error);
+  EXPECT_THROW(dumper.prepareForErrorDumping(), std::runtime_error);
+}
index 4d0522b..d1517fa 100644 (file)
  */
 
 #include "DumpingHooks.h"
+#include <cmath>
 
 using namespace mpqsolver::core;
 
-DumpingHooks::DumpingHooks(const std::string &save_path)
-  : _save_path(save_path), _dumper(_save_path)
+DumpingHooks::DumpingHooks(const std::string &save_path, const Quantizer::Context &ctx)
+  : _save_path(save_path), _dumper(_save_path), _ctx(ctx)
 {
 }
 
-void DumpingHooks::on_begin_solver(const std::string &model_path, float q8error, float q16error)
+void DumpingHooks::onBeginSolver(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);
+  _dumper.setModelPath(_model_path);
+  if (!std::isnan(q8error) || !std::isnan(q16error))
+  {
+    _dumper.prepareForErrorDumping();
+  }
+  if (!std::isnan(q8error))
+  {
+    _dumper.dumpQ8Error(q8error);
+  }
+  if (!std::isnan(q16error))
+  {
+    _dumper.dumpQ16Error(q16error);
+  }
 }
 
-void DumpingHooks::on_begin_iteration()
+void DumpingHooks::onBeginIteration()
 {
   _in_iterations = true;
   _num_of_iterations += 1;
 }
 
-void DumpingHooks::on_end_iteration(const LayerParams &layers, const std::string &def_type,
-                                    float error) const
+void DumpingHooks::onEndIteration(const LayerParams &layers, const std::string &def_type,
+                                  float error)
 {
-  _dumper.dump_MPQ_configuration(layers, def_type, _num_of_iterations);
-  _dumper.dump_MPQ_error(error, _num_of_iterations);
+  _dumper.dumpMPQConfiguration(layers, def_type, _ctx.granularity, _num_of_iterations);
+  _dumper.dumpMPQError(error, _num_of_iterations);
+  _in_iterations = false;
 }
 
-void DumpingHooks::on_end_solver(const LayerParams &layers, const std::string &def_dtype,
-                                 float qerror)
+void DumpingHooks::onEndSolver(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;
+  _dumper.dumpFinalMPQ(layers, def_dtype, _ctx.granularity);
+  if (!std::isnan(qerror))
+  {
+    _dumper.dumpMPQError(qerror);
+  }
 }
 
-void DumpingHooks::on_quantized(luci::Module *module) const
+void DumpingHooks::onQuantized(luci::Module *module) const
 {
   if (_in_iterations)
   {
-    _dumper.dump_quantized(module, _num_of_iterations);
+    _dumper.dumpQuantized(module, _num_of_iterations);
   }
 }
index c432a9a..0367af2 100644 (file)
@@ -19,9 +19,9 @@
 
 #include <luci/IR/Module.h>
 
-#include <core/Quantizer.h>
-#include <core/SolverHooks.h>
-#include <core/Dumper.h>
+#include "core/Quantizer.h"
+#include "core/SolverHooks.h"
+#include "core/Dumper.h"
 
 #include <string>
 
@@ -40,42 +40,42 @@ public:
    * @brief DumpingHooks constructor
    * @param save_path directory where all intermediate data will be saved
    */
-  DumpingHooks(const std::string &save_path);
+  DumpingHooks(const std::string &save_path, const Quantizer::Context &ctx);
 
   /**
    * @brief called on successfull quantization
    */
-  virtual void on_quantized(luci::Module *module) const override;
+  virtual void onQuantized(luci::Module *module) const override;
 
   /**
-   * @brief called on the start of iterative search
+   * @brief called on the start of mpq search
    */
-  virtual void on_begin_solver(const std::string &model_path, float q8error,
-                               float q16error) override;
+  virtual void onBeginSolver(const std::string &model_path, float q8error, float q16error) override;
 
   /**
    * @brief called on the start of current iteration
    */
-  virtual void on_begin_iteration() override;
+  virtual void onBeginIteration() 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;
+  virtual void onEndIteration(const LayerParams &layers, const std::string &def_dtype,
+                              float error) override;
 
   /**
-   * @brief called at the end of iterative search
+   * @brief called at the end of mpq search
    */
-  virtual void on_end_solver(const LayerParams &layers, const std::string &def_dtype,
-                             float qerror) override;
+  virtual void onEndSolver(const LayerParams &layers, const std::string &def_dtype,
+                           float qerror) override;
 
-protected:
+private:
   std::string _model_path;
   std::string _save_path;
   Dumper _dumper;
   uint32_t _num_of_iterations = 0;
   bool _in_iterations = false;
+  Quantizer::Context _ctx;
 };
 
 } // namespace core
diff --git a/compiler/circle-mpqsolver/src/core/DumpingHooks.test.cpp b/compiler/circle-mpqsolver/src/core/DumpingHooks.test.cpp
new file mode 100644 (file)
index 0000000..192862b
--- /dev/null
@@ -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 <gtest/gtest.h>
+
+#include "DumpingHooks.h"
+#include "core/TestHelper.h"
+
+#include <cmath>
+#include <ftw.h>
+#include <string>
+
+namespace
+{
+
+class CircleMPQSolverDumpingHooksTest : public ::testing::Test
+{
+public:
+  CircleMPQSolverDumpingHooksTest()
+  {
+    char folderTemplate[] = "CircleMPQSolverDumpingHooksTestXXXXXX";
+    _folder = mpqsolver::test::io_utils::makeTemporaryFolder(folderTemplate);
+  }
+
+  ~CircleMPQSolverDumpingHooksTest()
+  {
+    // cleanup
+    auto callback = [](const char *child, const struct stat *, int, struct FTW *) {
+      return remove(child);
+    };
+    nftw(_folder.c_str(), callback, 128, FTW_DEPTH | FTW_MOUNT | FTW_PHYS);
+  }
+
+protected:
+  std::string _folder;
+};
+
+} // namespace
+
+TEST_F(CircleMPQSolverDumpingHooksTest, verifyResultsTest)
+{
+  mpqsolver::core::Quantizer::Context ctx;
+  mpqsolver::core::DumpingHooks hooks(_folder, ctx);
+  EXPECT_NO_THROW(hooks.onBeginSolver("model_path.circle", 0.0, 1.0));
+  std::string errors_path = _folder + "/errors" + ".mpq.txt";
+  EXPECT_TRUE(mpqsolver::test::io_utils::isFileExists(errors_path));
+
+  hooks.onBeginIteration();
+
+  EXPECT_NO_THROW(
+    hooks.onEndIteration(mpqsolver::core::LayerParams(), ctx.output_model_dtype, 0.0));
+  std::string current_mpq_path = _folder + "/Configuration_" + std::to_string(1) + ".mpq.json";
+  EXPECT_TRUE(mpqsolver::test::io_utils::isFileExists(current_mpq_path));
+
+  EXPECT_NO_THROW(hooks.onEndSolver(mpqsolver::core::LayerParams(), ctx.output_model_dtype, 0.5));
+  std::string final_mpq_path = _folder + "/FinalConfiguration" + ".mpq.json";
+  EXPECT_TRUE(mpqsolver::test::io_utils::isFileExists(final_mpq_path));
+}
+
+TEST_F(CircleMPQSolverDumpingHooksTest, verify_NAN_results_test)
+{
+  mpqsolver::core::Quantizer::Context ctx;
+  mpqsolver::core::DumpingHooks hooks(_folder, ctx);
+  EXPECT_NO_THROW(hooks.onBeginSolver("model_path.circle", NAN, NAN));
+  std::string errors_path = _folder + "/errors" + ".mpq.txt";
+  EXPECT_TRUE(not mpqsolver::test::io_utils::isFileExists(errors_path));
+
+  EXPECT_NO_THROW(hooks.onEndSolver(mpqsolver::core::LayerParams(), ctx.output_model_dtype, NAN));
+  std::string final_mpq_path = _folder + "/FinalConfiguration" + ".mpq.json";
+  EXPECT_TRUE(mpqsolver::test::io_utils::isFileExists(final_mpq_path));
+}
+
+TEST_F(CircleMPQSolverDumpingHooksTest, empty_path_NEG)
+{
+  mpqsolver::core::Quantizer::Context ctx;
+  mpqsolver::core::DumpingHooks hooks("", ctx);
+  EXPECT_ANY_THROW(hooks.onBeginSolver("", -1, -1));
+  hooks.onBeginIteration();
+  EXPECT_ANY_THROW(hooks.onQuantized(nullptr));
+  EXPECT_ANY_THROW(
+    hooks.onEndIteration(mpqsolver::core::LayerParams(), ctx.output_model_dtype, -1));
+  EXPECT_ANY_THROW(hooks.onEndSolver(mpqsolver::core::LayerParams(), ctx.output_model_dtype, -1));
+}
+
+TEST_F(CircleMPQSolverDumpingHooksTest, empty_NAN_path_NEG)
+{
+  mpqsolver::core::Quantizer::Context ctx;
+  mpqsolver::core::DumpingHooks hooks("", ctx);
+  EXPECT_NO_THROW(hooks.onBeginSolver("", NAN, NAN));
+  EXPECT_ANY_THROW(hooks.onEndSolver(mpqsolver::core::LayerParams(), ctx.output_model_dtype, NAN));
+}
index 23ddfcb..23e17dc 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "ErrorMetric.h"
 
+#include <luci/IR/DataTypeHelper.h>
 #include <loco/IR/DataType.h>
 #include <loco/IR/DataTypeTraits.h>
 
@@ -29,10 +30,13 @@ using namespace mpqsolver::core;
  */
 float MAEMetric::compute(const WholeOutput &first, const WholeOutput &second) const
 {
-  assert(first.size() == second.size());
+  if (first.size() != second.size())
+  {
+    throw std::runtime_error("Can not compare vectors of different sizes");
+  }
 
-  float error = 0.f;
-  size_t output_size = 0;
+  double output_errors = 0.; // mean over mean outputs errors
+  size_t num_output_errors = 0;
 
   for (size_t sample_index = 0; sample_index < first.size(); ++sample_index)
   {
@@ -42,24 +46,30 @@ float MAEMetric::compute(const WholeOutput &first, const WholeOutput &second) co
       const Buffer &first_elementary = first[sample_index][out_index];
       const Buffer &second_elementary = second[sample_index][out_index];
       assert(first_elementary.size() == second_elementary.size());
-      size_t cur_size = first_elementary.size() / loco::size(loco::DataType::FLOAT32);
+      size_t cur_size = first_elementary.size() / luci::size(loco::DataType::FLOAT32);
+
+      double output_error = 0.; // mean error oevr current output
 
       const float *first_floats = reinterpret_cast<const float *>(first_elementary.data());
       const float *second_floats = reinterpret_cast<const float *>(second_elementary.data());
       for (size_t index = 0; index < cur_size; index++)
       {
-        float ref_value = *(first_floats + index);
-        float cur_value = *(second_floats + index);
-        error += std::fabs(ref_value - cur_value);
+        double ref_value = static_cast<double>(*(first_floats + index));
+        double cur_value = static_cast<double>(*(second_floats + index));
+        output_error += std::fabs(ref_value - cur_value);
+      }
+      if (cur_size != 0)
+      {
+        output_errors += (output_error / cur_size);
+        num_output_errors += 1;
       }
-      output_size += cur_size;
     }
   }
 
-  if (output_size == 0)
+  if (num_output_errors == 0)
   {
-    throw std::runtime_error("nothing to compare");
+    throw std::runtime_error("Nothing to compare");
   }
 
-  return error / output_size;
+  return static_cast<float>(output_errors / num_output_errors);
 }
index 232d9bc..a271138 100644 (file)
@@ -48,6 +48,84 @@ TEST(CircleMPQSolverMAEMetricTest, verifyResultsTest)
   EXPECT_FLOAT_EQ(value, 1.f);
 }
 
+TEST(CircleMPQSolverMAEMetricTest, verifyComplexResultsTest)
+{
+  // test for model with a pair of outputs
+
+  size_t num_elements = 512;
+  mpqsolver::core::WholeOutput target, source;
+  // construct target
+  {
+    // let first target output be 0.0
+    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);
+
+    // first target output
+    mpqsolver::core::Output out = mpqsolver::core::Output(1, buffer);
+    {
+      // let second target output be 0.25
+      std::vector<float> float_buffer(num_elements / 2, 0.25f);
+      auto const char_buffer = reinterpret_cast<char *>(float_buffer.data());
+      auto const char_buffer_size = num_elements / 2 * sizeof(float) / sizeof(char);
+      std::vector<char> buffer(char_buffer, char_buffer + char_buffer_size);
+      // second target output
+      out.emplace_back(buffer);
+    }
+
+    // target consists of single sample (each sample consists of two outputs)
+    target = mpqsolver::core::WholeOutput(1, out);
+  }
+
+  // construct target
+  {
+    // let first source output be 1.f
+    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);
+    // first source output
+    mpqsolver::core::Output out = mpqsolver::core::Output(1, buffer);
+    {
+      // let second source output be 1.f
+      std::vector<float> float_buffer(num_elements / 2, 1.0f);
+      auto const char_buffer = reinterpret_cast<char *>(float_buffer.data());
+      auto const char_buffer_size = num_elements / 2 * sizeof(float) / sizeof(char);
+      std::vector<char> buffer(char_buffer, char_buffer + char_buffer_size);
+      // second source output
+      out.emplace_back(buffer);
+    }
+
+    // source consists of single sample (each sample consists of two outputs)
+    source = mpqsolver::core::WholeOutput(1, out);
+  }
+
+  mpqsolver::core::MAEMetric metric;
+  float value = metric.compute(target, source);
+  EXPECT_FLOAT_EQ(value, 0.875f); // (|0 - 1| + |0.25 - 1|) / 2 = 1.75 / 2 = 0.875
+}
+
+TEST(CircleMPQSolverMAEMetricTest, different_samples_NEG)
+{
+  mpqsolver::core::MAEMetric metric;
+
+  size_t num_elements = 512;
+  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);
+
+  // let target be zero of two samples
+  mpqsolver::core::WholeOutput target = mpqsolver::core::WholeOutput(2, out);
+
+  // let source be zero of single sample
+  mpqsolver::core::WholeOutput source;
+
+  EXPECT_ANY_THROW(metric.compute(target, source));
+}
+
 TEST(CircleMPQSolverMAEMetricTest, verifyResultsTest_NEG)
 {
   mpqsolver::core::MAEMetric metric;
index c7afda5..98decb5 100644 (file)
 
 #include "Evaluator.h"
 
+#include "core/DataProvider.h"
+
+#include <luci/IR/DataTypeHelper.h>
+
 #include <luci_interpreter/Interpreter.h>
 
 #include <dio_hdf5/HDF5Importer.h>
@@ -31,20 +35,20 @@ using namespace luci;
 
 template <typename NodeT> size_t get_tensor_size(const NodeT *node)
 {
-  uint32_t tensor_size = loco::size(node->dtype());
+  uint32_t tensor_size = luci::size(node->dtype());
   for (uint32_t i = 0; i < node->rank(); ++i)
     tensor_size *= node->dim(i).value();
   return tensor_size;
 }
 
-WholeOutput compute_outputs(const luci::Module *module, const std::string &h5file)
+WholeOutput compute_outputs(const luci::Module *module, const DataProvider *data_provider)
 {
-  dio::hdf5::HDF5Importer importer{h5file};
-  importer.importGroup("value");
-
-  bool is_raw_data = importer.isRawData();
+  if (data_provider == nullptr)
+  {
+    throw std::runtime_error("No data");
+  }
 
-  const auto num_records = importer.numData();
+  const auto num_records = data_provider->numSamples();
   if (num_records == 0)
     throw std::runtime_error("The input data file does not contain any record.");
   const auto input_nodes = loco::input_nodes(module->graph());
@@ -54,31 +58,19 @@ WholeOutput compute_outputs(const luci::Module *module, const std::string &h5fil
 
   // Create interpreter.
   luci_interpreter::Interpreter interpreter(module);
-  for (int32_t record_idx = 0; record_idx < num_records; record_idx++)
+  for (uint32_t record_idx = 0; record_idx < num_records; record_idx++)
   {
-    if (num_inputs != static_cast<uint32_t>(importer.numInputs(record_idx)))
+    if (num_inputs != data_provider->numInputs(record_idx))
       throw std::runtime_error("Wrong number of inputs.");
     for (uint32_t input_idx = 0; input_idx < num_inputs; input_idx++)
     {
       const auto *input_node = loco::must_cast<const luci::CircleInput *>(input_nodes[input_idx]);
       assert(input_node->index() == input_idx);
 
-      std::vector<char> input_data(get_tensor_size(input_node));
-
-      if (!is_raw_data)
-      {
-        loco::DataType dtype;
-        Shape shape;
-        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(), input_data.size());
-      }
-
-      interpreter.writeInputTensor(input_node, input_data.data(), input_data.size());
+      InputData input_data(get_tensor_size(input_node));
+      data_provider->getSampleInput(record_idx, input_idx, input_data);
+
+      interpreter.writeInputTensor(input_node, input_data.data().data(), input_data.data().size());
     }
 
     interpreter.interpret();
@@ -103,11 +95,11 @@ WholeOutput compute_outputs(const luci::Module *module, const std::string &h5fil
 
 } // namespace
 
-DatasetEvaluator::DatasetEvaluator(const luci::Module *ref_module, const std::string &h5file,
+DatasetEvaluator::DatasetEvaluator(const luci::Module *ref_module, const DataProvider &provider,
                                    const ErrorMetric &metric)
-  : _ref_module(ref_module), _h5file(h5file), _metric(&metric)
+  : _ref_module(ref_module), _provider(&provider), _metric(&metric)
 {
-  _ref_output = compute_outputs(_ref_module, _h5file);
+  _ref_output = compute_outputs(_ref_module, _provider);
 }
 
 void DatasetEvaluator::validate(const luci::Module *trgt_fq_module) const
@@ -132,7 +124,7 @@ float DatasetEvaluator::evaluate(const luci::Module *trgt_fq_module) const
 
   validate(trgt_fq_module);
 
-  const WholeOutput &cur_output = compute_outputs(trgt_fq_module, _h5file);
+  const WholeOutput &cur_output = compute_outputs(trgt_fq_module, _provider);
   float error = _metric->compute(_ref_output, cur_output);
   return error;
 }
index 9820508..0f50bb5 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "ErrorMetric.h"
 
+#include "DataProvider.h"
+
 #include <luci/IR/Module.h>
 #include <luci/CircleQuantizer.h>
 
@@ -34,9 +36,9 @@ class DatasetEvaluator final
 {
 public:
   /**
-   * @brief create Evaluator for comparing output of ref_module on h5file
+   * @brief create Evaluator for comparing output of ref_module on provider
    */
-  DatasetEvaluator(const luci::Module *ref_module, const std::string &h5file,
+  DatasetEvaluator(const luci::Module *ref_module, const DataProvider &provider,
                    const ErrorMetric &metric);
   DatasetEvaluator() = delete;
   ~DatasetEvaluator() = default;
@@ -55,7 +57,7 @@ private:
 
 private:
   const luci::Module *_ref_module = nullptr;
-  std::string _h5file;
+  const DataProvider *_provider = nullptr;
   WholeOutput _ref_output;
   const ErrorMetric *_metric = nullptr;
 };
diff --git a/compiler/circle-mpqsolver/src/core/Evaluator.test.cpp b/compiler/circle-mpqsolver/src/core/Evaluator.test.cpp
new file mode 100644 (file)
index 0000000..757257a
--- /dev/null
@@ -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 <gtest/gtest.h>
+
+#include "Evaluator.h"
+
+#include "DataProvider.h"
+#include "TestHelper.h"
+
+TEST(CircleMPQSolverEvaluatorTest, verifyResultsTest)
+{
+  // create nn module
+  auto m = luci::make_module();
+  mpqsolver::test::models::AddGraph g;
+  g.init();
+  g.transfer_to(m.get());
+
+  mpqsolver::core::MAEMetric metric;
+  auto data = mpqsolver::test::data_utils::getAllZeroSingleDataProvider();
+  mpqsolver::core::DatasetEvaluator evaluator(m.get(), *data.get(), metric);
+  float value = evaluator.evaluate(m.get());
+  EXPECT_FLOAT_EQ(value, 0.f);
+}
+
+TEST(CircleMPQSolverEvaluatorTest, empty_path_NEG)
+{
+  mpqsolver::core::MAEMetric metric;
+  EXPECT_ANY_THROW(mpqsolver::core::H5FileDataProvider data("", "");
+                   mpqsolver::core::DatasetEvaluator evaluator(nullptr, data, metric));
+}
index 4217931..3eea87d 100644 (file)
@@ -49,12 +49,7 @@ bool make_model_fake_quantized(luci::Module *module)
 
 } // namespace
 
-Quantizer::Quantizer(const std::string &input_dtype, const std::string &output_dtype)
-  : _input_dtype(input_dtype), _output_dtype(output_dtype)
-{
-}
-
-void Quantizer::set_hook(const QuantizerHook *hook) { _hook = hook; }
+void Quantizer::setHook(const QuantizerHook *hook) { _hook = hook; }
 
 /**
  * @brief quantize recorded module (min/max initialized) with specified parameters
@@ -67,7 +62,6 @@ bool Quantizer::quantize(luci::Module *module, const std::string &quant_dtype,
     return false;
 
   static const std::string default_dtype = "float32";
-  static const std::string granularity_type = "channel";
 
   luci::CircleQuantizer quantizer;
 
@@ -76,10 +70,18 @@ bool Quantizer::quantize(luci::Module *module, const std::string &quant_dtype,
 
   options->param(AlgorithmParameters::Quantize_input_model_dtype, default_dtype);
   options->param(AlgorithmParameters::Quantize_output_model_dtype, quant_dtype);
-  options->param(AlgorithmParameters::Quantize_granularity, granularity_type);
-  options->param(AlgorithmParameters::Quantize_input_type, _input_dtype);
-  options->param(AlgorithmParameters::Quantize_output_type, _output_dtype);
-  options->param(AlgorithmParameters::Quantize_TF_style_maxpool, "False");
+  // Only channel-wise quantization is supported for int16
+  // TODO Fix this if this assumption breaks
+  if (quant_dtype == "int16")
+    options->param(AlgorithmParameters::Quantize_granularity, "channel");
+  else
+    options->param(AlgorithmParameters::Quantize_granularity, _ctx.granularity);
+
+  options->param(AlgorithmParameters::Quantize_input_type, _ctx.input_type);
+  options->param(AlgorithmParameters::Quantize_output_type, _ctx.output_type);
+  options->param(AlgorithmParameters::Quantize_TF_style_maxpool,
+                 _ctx.TF_style_maxpool ? "True" : "False");
+  options->param(AlgorithmParameters::Quantize_save_min_max, _ctx.save_min_max ? "True" : "False");
 
   if (!layer_params.empty())
   {
@@ -108,18 +110,27 @@ bool Quantizer::quantize(luci::Module *module, const std::string &quant_dtype,
 
   if (_hook)
   {
-    _hook->on_quantized(module);
+    _hook->onQuantized(module);
   }
 
   return true;
 }
 
 /**
+ * @brief quantize recorded module (min/max initialized) with specified parameters
+ * returns true on success
+ */
+bool Quantizer::quantize(luci::Module *module, LayerParams &layer_params)
+{
+  return quantize(module, _ctx.output_model_dtype, layer_params);
+}
+
+/**
  * @brief fake_quantize recorded module (min/max initialized) with specified parameters
  * returns true on success
  */
-bool Quantizer::fake_quantize(luci::Module *module, const std::string &quant_dtype,
-                              LayerParams &layer_params)
+bool Quantizer::fakeQuantize(luci::Module *module, const std::string &quant_dtype,
+                             LayerParams &layer_params)
 {
   if (!quantize(module, quant_dtype, layer_params))
     return false;
index 259d5c4..2001ce0 100644 (file)
@@ -38,18 +38,30 @@ struct QuantizerHook
    * @brief called on successfull quantization
    * @param module quantized module
    */
-  virtual void on_quantized(luci::Module *module) const = 0;
+  virtual void onQuantized(luci::Module *module) const = 0;
 };
 
 class Quantizer
 {
 public:
-  Quantizer(const std::string &input_dtype, const std::string &output_type);
+  struct Context
+  {
+    std::string output_model_dtype = "uint8";
+    std::string granularity = "channel";
+    std::string input_type = "uint8";
+    std::string output_type = "uint8";
+    bool TF_style_maxpool = false;
+    bool save_min_max = false;
+    // TODO Support layer info
+  };
+
+public:
+  Quantizer(const Context &ctx) : _ctx(ctx) {}
 
   /**
    * @brief set hook on the end of quantization event
    */
-  void set_hook(const QuantizerHook *callback);
+  void setHook(const QuantizerHook *callback);
 
   /**
    * @brief quantize recorded module (min/max initialized) with specified parameters
@@ -58,15 +70,22 @@ public:
   bool quantize(luci::Module *module, const std::string &quant_dtype, LayerParams &layer_params);
 
   /**
+   * @brief quantize recorded module (min/max initialized) with specified parameters
+   * returns true on success
+   */
+  bool quantize(luci::Module *module, LayerParams &layer_params);
+
+  /**
    * @brief fake_quantize recorded module (min/max initialized) with specified parameters
    * returns true on success
    */
-  bool fake_quantize(luci::Module *module, const std::string &quant_dtype,
-                     LayerParams &layer_params);
+  bool fakeQuantize(luci::Module *module, const std::string &quant_dtype,
+                    LayerParams &layer_params);
+
+  const Context &getContext() const { return _ctx; }
 
 private:
-  std::string _input_dtype = "uint8";
-  std::string _output_dtype = "uint8";
+  Context _ctx;
   const QuantizerHook *_hook = nullptr;
 };
 
index 7d7e74f..93c7ac0 100644 (file)
 
 #include <luci/IR/CircleNodes.h>
 
-#include <cmath>
-
-namespace
-{
-
-class AddGraph final : public SimpleGraph
-{
-protected:
-  void initInput(loco::Node *input) override
-  {
-    auto ci_input = loco::must_cast<luci::CircleNode *>(input);
-    initMinMax(ci_input);
-  }
-
-  void initMinMax(luci::CircleNode *node)
-  {
-    auto qparam = std::make_unique<luci::CircleQuantParam>();
-    qparam->min.assign(1, _a_min);
-    qparam->max.assign(1, _a_max);
-    node->quantparam(std::move(qparam));
-  }
-
-  loco::Node *insertGraphBody(loco::Node *input) override
-  {
-    _add = _g->nodes()->create<luci::CircleAdd>();
-    _beta = _g->nodes()->create<luci::CircleConst>();
-
-    _add->dtype(loco::DataType::FLOAT32);
-    _beta->dtype(loco::DataType::FLOAT32);
-
-    uint32_t channel_size = 16;
-    _add->shape({1, _channel_size, _width, _height});
-    _beta->shape({1, _channel_size, _width, _height});
-
-    _beta->size<loco::DataType::FLOAT32>(channel_size);
-    _add->x(input);
-    _add->y(_beta);
-    _add->fusedActivationFunction(luci::FusedActFunc::NONE);
-
-    _add->name("add");
-    _beta->name("beta");
-    initMinMax(_add);
-
-    return _add;
-  }
-
-public:
-  float _a_min = -1.f;
-  float _a_max = 1.f;
-  luci::CircleAdd *_add = nullptr;
-  luci::CircleConst *_beta = nullptr;
-};
-
-} // namespace
+using namespace mpqsolver::test::models;
 
 TEST(CircleMPQSolverQuantizerTest, verifyResultsTest)
 {
@@ -84,10 +31,10 @@ TEST(CircleMPQSolverQuantizerTest, verifyResultsTest)
   float range = g._a_max - g._a_min;
   g.transfer_to(m.get());
 
-  std::string def_quant = "uint8";
-  mpqsolver::core::Quantizer quantizer(def_quant, def_quant);
+  mpqsolver::core::Quantizer::Context context;
+  mpqsolver::core::Quantizer quantizer(context);
   mpqsolver::core::LayerParams params;
-  auto res = quantizer.quantize(m.get(), def_quant, params);
+  auto res = quantizer.quantize(m.get(), context.output_model_dtype, params);
   EXPECT_TRUE(res);
   auto quant_param = add->quantparam();
   EXPECT_TRUE(quant_param != nullptr);
@@ -99,9 +46,9 @@ TEST(CircleMPQSolverQuantizerTest, verifyResultsTest)
 
 TEST(CircleMPQSolverQuantizerTest, verifyResultsTest_NEG)
 {
-  std::string def_quant = "uint8";
-  mpqsolver::core::Quantizer quantizer(def_quant, def_quant);
+  mpqsolver::core::Quantizer::Context context;
+  mpqsolver::core::Quantizer quantizer(context);
   mpqsolver::core::LayerParams params;
-  auto res = quantizer.quantize(nullptr, def_quant, params);
+  auto res = quantizer.quantize(nullptr, context.output_model_dtype, params);
   EXPECT_TRUE(!res);
 }
index 851a699..06f8d76 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <luci/IR/Module.h>
 
-#include <core/Quantizer.h>
+#include "core/Quantizer.h"
 
 #include <string>
 
@@ -32,17 +32,17 @@ class SolverHooks
 {
 public:
   /**
-   * @brief called on the start of iterative search
+   * @brief called on the start of mpq search
    * @param model_path path of original float model to quantize
-   * @param q8error error of Q8 quantization
-   * @param q16error error of Q16 quantization
+   * @param q8error error of Q8 quantization (if NAN, then not applicable)
+   * @param q16error error of Q16 quantization (if NAN, then not applicable)
    */
-  virtual void on_begin_solver(const std::string &model_path, float q8error, float q16error) = 0;
+  virtual void onBeginSolver(const std::string &model_path, float q8error, float q16error) = 0;
 
   /**
    * @brief called on the start of current iteration
    */
-  virtual void on_begin_iteration() = 0;
+  virtual void onBeginIteration() = 0;
 
   /**
    * @brief called at the end of current iteration
@@ -50,17 +50,17 @@ public:
    * @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;
+  virtual void onEndIteration(const LayerParams &layers, const std::string &def_dtype,
+                              float error) = 0;
 
   /**
-   * @brief called at the end of iterative search
+   * @brief called at the end of mpq search
    * @param layers model nodes with specific quantization parameters
    * @param def_dtype default quantization dtype
-   * @param qerror final error of quantization
+   * @param qerror final error of quantization (if NAN, then not applicable)
    */
-  virtual void on_end_solver(const LayerParams &layers, const std::string &def_dtype,
-                             float qerror) = 0;
+  virtual void onEndSolver(const LayerParams &layers, const std::string &def_dtype,
+                           float qerror) = 0;
 };
 
 } // namespace core
index f930738..5165e40 100644 (file)
 #ifndef __MPQSOLVER_TEST_HELPER_H__
 #define __MPQSOLVER_TEST_HELPER_H__
 
+#include "DataProvider.h"
+
 #include <luci/IR/CircleNodes.h>
 #include <luci/IR/Module.h>
+#include <luci/test/TestIOGraph.h>
+
+namespace mpqsolver
+{
+namespace test
+{
+namespace models
+{
 
+/**
+ * @brief base class of simple graphs used for testing
+ */
 class SimpleGraph
 {
 public:
   SimpleGraph() : _g(loco::make_graph()) {}
 
 public:
-  void init()
-  {
-    _input = _g->nodes()->create<luci::CircleInput>();
-    _output = _g->nodes()->create<luci::CircleOutput>();
-    _input->name("input");
-    _output->name("output");
-
-    auto graph_input = _g->inputs()->create();
-    _input->index(graph_input->index());
-    auto graph_output = _g->outputs()->create();
-    _output->index(graph_output->index());
-
-    graph_input->dtype(loco::DataType::FLOAT32);
-    _input->dtype(loco::DataType::FLOAT32);
-    _output->dtype(loco::DataType::FLOAT32);
-    graph_output->dtype(loco::DataType::FLOAT32);
-
-    graph_input->shape({1, _channel_size, _width, _height});
-    _input->shape({1, _channel_size, _width, _height});
-    _output->shape({1, _channel_size, _width, _height});
-    graph_output->shape({1, _channel_size, _width, _height});
-
-    auto graph_body = insertGraphBody(_input);
-    _output->from(graph_body);
-
-    initInput(_input);
-  }
+  void init();
 
   virtual ~SimpleGraph() = default;
-  void transfer_to(luci::Module *module)
-  {
-    // WARNING: after g is transfered, _graph_inputs, _inputs
-    //          and _graph_outputs, _outputs in TestOsGraphlet will be invalid.
-    //          arrays are not cleared as this is just helpers to unit tests
-    module->add(std::move(_g));
-  }
+  void transfer_to(luci::Module *module);
 
 protected:
   virtual loco::Node *insertGraphBody(loco::Node *input) = 0;
-  virtual void initInput(loco::Node *input){};
+  virtual void initInput(loco::Node *){};
 
 public:
   std::unique_ptr<loco::Graph> _g;
@@ -76,4 +57,90 @@ public:
   uint32_t _height = 4;
 };
 
+/**
+ * @brief simple model with just an Add of input and constant
+ */
+class AddGraph final : public SimpleGraph
+{
+private:
+  void initInput(loco::Node *input) override;
+  void initMinMax(luci::CircleNode *node);
+
+  loco::Node *insertGraphBody(loco::Node *input) override;
+
+public:
+  float _a_min = -1.f;
+  float _a_max = 1.f;
+  luci::CircleAdd *_add = nullptr;
+  luci::CircleConst *_beta = nullptr;
+};
+
+class SoftmaxGraphlet
+{
+public:
+  SoftmaxGraphlet() = default;
+  virtual ~SoftmaxGraphlet() = default;
+
+  void init(loco::Graph *g);
+
+protected:
+  void initMinMax(luci::CircleNode *node, float min, float max);
+
+public:
+  luci::CircleAbs *_ifm = nullptr;
+  luci::CircleReduceMax *_max = nullptr;
+  luci::CircleSub *_sub = nullptr;
+  luci::CircleExp *_exp = nullptr;
+  luci::CircleSum *_sum = nullptr;
+  luci::CircleDiv *_div = nullptr;
+
+protected:
+  luci::CircleConst *_softmax_indices = nullptr;
+};
+
+class SoftmaxTestGraph : public luci::test::TestIOGraph, public SoftmaxGraphlet
+{
+public:
+  SoftmaxTestGraph() = default;
+
+  void init(void);
+};
+
+} // namespace models
+
+namespace io_utils
+{
+
+/**
+ * @brief create valid name of temporary file
+ */
+void makeTemporaryFile(char *name_template);
+
+/**
+ * @brief write data to file_path
+ */
+void writeDataToFile(const std::string &file_path, const std::string &data);
+
+/**
+ * @brief create valid name of temporary folder
+ */
+std::string makeTemporaryFolder(char *name_template);
+
+/**
+ * @brief checks whether file exists
+ */
+bool isFileExists(const std::string &file_path);
+
+} // namespace io_utils
+
+namespace data_utils
+{
+
+std::unique_ptr<mpqsolver::core::DataProvider> getAllZeroSingleDataProvider();
+
+} // namespace data_utils
+
+} // namespace test
+} // namespace mpqsolver
+
 #endif //__MPQSOLVER_TEST_HELPER_H__
diff --git a/compiler/circle-mpqsolver/src/core/TestHelper.test.cpp b/compiler/circle-mpqsolver/src/core/TestHelper.test.cpp
new file mode 100644 (file)
index 0000000..e5e7c8e
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "TestHelper.h"
+
+#include <fstream>
+#include <H5Cpp.h>
+
+namespace mpqsolver
+{
+namespace test
+{
+namespace models
+{
+
+void SimpleGraph::init()
+{
+  _input = _g->nodes()->create<luci::CircleInput>();
+  _output = _g->nodes()->create<luci::CircleOutput>();
+  _input->name("input");
+  _output->name("output");
+
+  auto graph_input = _g->inputs()->create();
+  _input->index(graph_input->index());
+  auto graph_output = _g->outputs()->create();
+  _output->index(graph_output->index());
+
+  graph_input->dtype(loco::DataType::FLOAT32);
+  _input->dtype(loco::DataType::FLOAT32);
+  _output->dtype(loco::DataType::FLOAT32);
+  graph_output->dtype(loco::DataType::FLOAT32);
+
+  graph_input->shape({1, _height, _width, _channel_size});
+  _input->shape({1, _height, _width, _channel_size});
+  _output->shape({1, _height, _width, _channel_size});
+  graph_output->shape({1, _height, _width, _channel_size});
+
+  auto graph_body = insertGraphBody(_input);
+  _output->from(graph_body);
+
+  initInput(_input);
+}
+
+void SimpleGraph::transfer_to(luci::Module *module)
+{
+  // WARNING: after g is transfered, _graph_inputs, _inputs
+  //          and _graph_outputs, _outputs in TestOsGraphlet will be invalid.
+  //          arrays are not cleared as this is just helpers to unit tests
+  module->add(std::move(_g));
+}
+
+void AddGraph::initInput(loco::Node *input)
+{
+  auto ci_input = loco::must_cast<luci::CircleNode *>(input);
+  initMinMax(ci_input);
+}
+
+void AddGraph::initMinMax(luci::CircleNode *node)
+{
+  auto qparam = std::make_unique<luci::CircleQuantParam>();
+  qparam->min.assign(1, _a_min);
+  qparam->max.assign(1, _a_max);
+  node->quantparam(std::move(qparam));
+}
+
+loco::Node *AddGraph::insertGraphBody(loco::Node *input)
+{
+  _add = _g->nodes()->create<luci::CircleAdd>();
+  _beta = _g->nodes()->create<luci::CircleConst>();
+
+  _add->dtype(loco::DataType::FLOAT32);
+  _beta->dtype(loco::DataType::FLOAT32);
+
+  _add->shape({1, _height, _width, _channel_size});
+  _beta->shape({1, _height, _width, _channel_size});
+
+  _beta->size<loco::DataType::FLOAT32>(_channel_size * _width * _height);
+  _add->x(input);
+  _add->y(_beta);
+  _add->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+  _add->name("add");
+  _beta->name("beta");
+  initMinMax(_add);
+
+  return _add;
+}
+
+void SoftmaxGraphlet::initMinMax(luci::CircleNode *node, float min, float max)
+{
+  auto qparam = std::make_unique<luci::CircleQuantParam>();
+  qparam->min.assign(1, min);
+  qparam->max.assign(1, max);
+  node->quantparam(std::move(qparam));
+}
+
+void SoftmaxGraphlet::init(loco::Graph *g)
+{
+  _ifm = nullptr;
+
+  _ifm = g->nodes()->create<luci::CircleAbs>();
+  _max = g->nodes()->create<luci::CircleReduceMax>();
+  _sub = g->nodes()->create<luci::CircleSub>();
+  _exp = g->nodes()->create<luci::CircleExp>();
+  _sum = g->nodes()->create<luci::CircleSum>();
+  _div = g->nodes()->create<luci::CircleDiv>();
+  _softmax_indices = g->nodes()->create<luci::CircleConst>();
+
+  _ifm->name("ifm");
+  _max->name("maximum_of_ifm");
+  _sub->name("sub");
+  _exp->name("exp");
+  _sum->name("sum");
+  _div->name("div");
+  _softmax_indices->name("reduction_indices");
+
+  initMinMax(_ifm, 0, 1);
+  initMinMax(_max, 0, 1);
+  initMinMax(_sub, 0, 1);
+  initMinMax(_exp, 0, 1);
+  initMinMax(_sum, 0, 1);
+  initMinMax(_div, 0, 1);
+
+  _softmax_indices->dtype(loco::DataType::S32);
+  _softmax_indices->size<loco::DataType::S32>(1);
+  _softmax_indices->shape({1});
+  _softmax_indices->at<loco::DataType::S32>(0) = -1;
+  _softmax_indices->shape_status(luci::ShapeStatus::VALID);
+
+  _max->keep_dims(true);
+  _sum->keep_dims(true);
+}
+
+void SoftmaxTestGraph::init(void)
+{
+  TestIOGraph::init({1, 12, 11, 15}, {1, 12, 11, 15});
+  SoftmaxGraphlet::init(g());
+
+  _ifm->x(input());
+  _max->input(_ifm);
+  _max->reduction_indices(_softmax_indices);
+
+  _sub->x(_ifm);
+  _sub->y(_max);
+  _sub->fusedActivationFunction(luci::FusedActFunc::NONE);
+  _exp->x(_sub);
+  _sum->input(_exp);
+  _sum->reduction_indices(_softmax_indices);
+  _div->x(_exp);
+  _div->y(_sum);
+  _div->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+  output()->from(_div);
+
+  initMinMax(input(), 0, 1);
+  initMinMax(output(), 0, 1);
+}
+
+} // namespace models
+
+namespace io_utils
+{
+
+void makeTemporaryFile(char *name_template)
+{
+  int fd = mkstemp(name_template);
+  if (fd == -1)
+  {
+    throw std::runtime_error{"mkstemp failed"};
+  }
+}
+
+void writeDataToFile(const std::string &path, const std::string &data)
+{
+  std::ofstream file;
+  file.open(path);
+  file << data;
+  file.close();
+}
+
+std::string makeTemporaryFolder(char *name_template)
+{
+  auto const res = mkdtemp(name_template);
+  if (res == nullptr)
+  {
+    throw std::runtime_error{"mkdtemp failed"};
+  }
+  return res;
+}
+
+bool isFileExists(const std::string &path)
+{
+  std::ifstream f(path);
+  return f.good();
+}
+
+} // namespace io_utils
+
+namespace data_utils
+{
+
+class SingleDataProvider final : public core::DataProvider
+{
+public:
+  SingleDataProvider() = default;
+  size_t numSamples() const override { return 1; }
+  uint32_t numInputs(uint32_t) const override { return 1; }
+  void getSampleInput(uint32_t, uint32_t, core::InputData &data) const
+  {
+    size_t size = data.data().size() / sizeof(float);
+    auto floats = reinterpret_cast<float *>(data.data().data());
+    for (uint32_t idx = 0; idx < size; idx++)
+    {
+      floats[idx] = 0.f; // or any other value
+    }
+  }
+};
+
+std::unique_ptr<mpqsolver::core::DataProvider> getAllZeroSingleDataProvider()
+{
+  return std::make_unique<SingleDataProvider>();
+}
+
+} // namespace data_utils
+
+} // namespace test
+} // namespace mpqsolver
diff --git a/compiler/circle-mpqsolver/src/pattern/PatternResolver.cpp b/compiler/circle-mpqsolver/src/pattern/PatternResolver.cpp
new file mode 100644 (file)
index 0000000..947a8f8
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PatternResolver.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+using namespace mpqsolver::pattern;
+
+using LayerParam = luci::CircleQuantizer::Options::LayerParam;
+
+namespace
+{
+
+/**
+ * SUBGRAPH PATTERN
+ *  LayerNorm := (ifm - |ifm|) / sqrt(|(ifm - |ifm|)^2| + eps)
+ *    - |x|: mean of x
+ *    - Below diagram shows LayerNorm pattern to quantize.
+ *
+ *                 [In]
+ *                   |
+ *                   V
+ *                  ifm -----+   (reduction indicies)
+ *                   |       |       |
+ *                   |       V       V
+ *                   |      mean_of_ifm
+ *                   V       |
+ *     +------------sub <----+
+ *     |             |
+ *     |             V           (reduction indicies)
+ *     |          sub_squared           |
+ *     |             |                  |
+ *     |             V                  |
+ *     |       mean_as_variance <-------+    (const_as_eps)
+ *     |             |                          |
+ *     |             V                          |
+ *     |          add_eps<----------------------+
+ *     |             |
+ *     |             V
+ *     |           rsqrt
+ *     |             |
+ *     |             V
+ *     +------>mul_as_terminal
+ *                   |
+ *                   V
+ *                 [Out]
+ *
+ */
+class LayerNormPattern final
+{
+public:
+  LayerNormPattern(luci::CircleMul *candidate)
+  {
+    assert(candidate);
+    mul_as_terminal = candidate;
+  }
+
+public:
+  bool matched();
+
+  std::vector<luci::CircleNode *> get_q16_nodes()
+  {
+    return {sub_squared, mean_as_variance, add_eps, rsqrt};
+  }
+
+  std::vector<luci::CircleNode *> get_q8_nodes() { return {mean_of_ifm, sub, mul_as_terminal}; }
+
+public:
+  loco::Node *ifm = nullptr;
+  luci::CircleMean *mean_of_ifm = nullptr;      // = |ifm|
+  luci::CircleSub *sub = nullptr;               // = ifm - |ifm|
+  luci::CircleMul *sub_squared = nullptr;       // = (ifm - |ifm|)^2
+  luci::CircleMean *mean_as_variance = nullptr; // = |(ifm - |ifm|)^2|
+  luci::CircleAdd *add_eps = nullptr;           // = |(ifm - |ifm|)^2| + eps
+  luci::CircleRsqrt *rsqrt = nullptr;           // = 1.0 / sqrt(|(ifm - |ifm|)^2| + eps)
+  luci::CircleMul *mul_as_terminal = nullptr;   // = (ifm - |ifm|) / sqrt(|(ifm - |ifm|)^2| + eps)
+};
+
+#define CHECK_OR_FALSE(condition) \
+  if (not(condition))             \
+    return false;
+
+bool LayerNormPattern::matched()
+{
+  sub = dynamic_cast<luci::CircleSub *>(mul_as_terminal->x());
+  rsqrt = dynamic_cast<luci::CircleRsqrt *>(mul_as_terminal->y());
+  if (!sub || !rsqrt)
+  {
+    sub = dynamic_cast<luci::CircleSub *>(mul_as_terminal->y());
+    rsqrt = dynamic_cast<luci::CircleRsqrt *>(mul_as_terminal->x());
+  }
+  CHECK_OR_FALSE(rsqrt != nullptr && sub != nullptr);
+
+  ifm = dynamic_cast<luci::CircleNode *>(sub->x());
+  mean_of_ifm = dynamic_cast<luci::CircleMean *>(sub->y());
+  CHECK_OR_FALSE(ifm != nullptr && mean_of_ifm != nullptr);
+
+  add_eps = dynamic_cast<luci::CircleAdd *>(rsqrt->x());
+  CHECK_OR_FALSE(add_eps != nullptr);
+
+  auto const *eps = dynamic_cast<luci::CircleConst *>(add_eps->x());
+  mean_as_variance = dynamic_cast<luci::CircleMean *>(add_eps->y());
+  if (!eps || !mean_as_variance)
+  {
+    eps = dynamic_cast<luci::CircleConst *>(add_eps->y());
+    mean_as_variance = dynamic_cast<luci::CircleMean *>(add_eps->x());
+  }
+
+  CHECK_OR_FALSE(eps != nullptr && mean_as_variance != nullptr);
+
+  // eps should be scalar value
+  CHECK_OR_FALSE(eps->size<loco::DataType::FLOAT32>() == 1);
+
+  sub_squared = dynamic_cast<luci::CircleMul *>(mean_as_variance->input());
+  CHECK_OR_FALSE(sub_squared != nullptr);
+
+  // check that sub_squared = sub * sub
+  CHECK_OR_FALSE(sub_squared->x() == sub_squared->y() && sub_squared->x() == sub);
+
+  auto const mean_as_variance_indices =
+    dynamic_cast<luci::CircleConst *>(mean_as_variance->reduction_indices());
+  auto const mean_of_ifm_indices =
+    dynamic_cast<luci::CircleConst *>(mean_of_ifm->reduction_indices());
+
+  // check validity of reduction indices
+  CHECK_OR_FALSE(mean_of_ifm_indices != nullptr && mean_as_variance_indices != nullptr);
+
+  // check dtype of reduction indices
+  CHECK_OR_FALSE(mean_of_ifm_indices->dtype() == loco::DataType::S32 &&
+                 mean_as_variance_indices->dtype() == loco::DataType::S32);
+
+  // reduction indices of both mean operations must be the same
+  CHECK_OR_FALSE(mean_as_variance_indices->size<loco::DataType::S32>() ==
+                 mean_of_ifm_indices->size<loco::DataType::S32>());
+
+  std::set<int32_t> set_of_mean_as_variance_indices;
+  std::set<int32_t> set_of_mean_of_ifm_indices;
+  for (uint32_t index = 0; index < mean_as_variance_indices->size<loco::DataType::S32>(); index++)
+  {
+    set_of_mean_as_variance_indices.insert(
+      mean_as_variance_indices->at<loco::DataType::S32>(index));
+    set_of_mean_of_ifm_indices.insert(mean_of_ifm_indices->at<loco::DataType::S32>(index));
+  }
+  // now make sure that reduction indices of mean_as_variance are the same as mean_of_ifm
+  CHECK_OR_FALSE(set_of_mean_as_variance_indices == set_of_mean_of_ifm_indices);
+
+  return true;
+}
+
+/**
+ * SUBGRAPH PATTERN
+ *  SoftmaxPattern := (exp(ifm - max(ifm))) / sum(exp(ifm - max(ifm)))
+ *    - Below diagram shows Softmax pattern to quantize.
+ *
+ *         [In]    [CircleConst(=-1)]
+ *          | \          /
+ *          |  \        /
+ *          | [CircleReduceMax]
+ *          |    /
+ *          |   /
+ *          |  /
+ *        [Sub]               [CircleConst(=-1)]
+ *          |                        |
+ *          |                        |
+ *        [Exp]                      |
+ *          | \                      |
+ *          |  \                     |
+ *          |  [CircleSum]-----------+
+ *          |  /
+ *          | /
+ *        [Div]
+ *          |
+ *          |
+ *      [CircleNode]
+ */
+class SoftmaxPattern final
+{
+public:
+  SoftmaxPattern(luci::CircleDiv *candidate)
+  {
+    assert(candidate);
+    _div_as_terminal = candidate;
+  }
+
+public:
+  bool matched();
+
+  std::vector<luci::CircleNode *> get_q16_nodes() { return {_sub, _exp}; }
+
+  std::vector<luci::CircleNode *> get_q8_nodes() { return {_ifm, _max, _sum, _div_as_terminal}; }
+
+public:
+  luci::CircleNode *_ifm = nullptr;            // input feature map
+  luci::CircleReduceMax *_max = nullptr;       // = max(_ifm)
+  luci::CircleSub *_sub = nullptr;             // = _ifm - max(_ifm)
+  luci::CircleExp *_exp = nullptr;             // = exp(_ifm - max(_ifm))
+  luci::CircleSum *_sum = nullptr;             // = sum(exp(_ifm - max(_ifm)))
+  luci::CircleDiv *_div_as_terminal = nullptr; // = exp(_ifm - max(_ifm))/sum(exp(_ifm - max(_ifm)))
+};
+
+bool SoftmaxPattern::matched()
+{
+  _exp = dynamic_cast<luci::CircleExp *>(_div_as_terminal->x());
+  _sum = dynamic_cast<luci::CircleSum *>(_div_as_terminal->y());
+  CHECK_OR_FALSE(_exp != nullptr && _sum != nullptr);
+
+  CHECK_OR_FALSE(_sum->input() == _exp);
+  CHECK_OR_FALSE(_sum->keep_dims() == true);
+
+  auto const sum_indices = dynamic_cast<luci::CircleConst *>(_sum->reduction_indices());
+  CHECK_OR_FALSE(sum_indices != nullptr);
+
+  _sub = dynamic_cast<luci::CircleSub *>(_exp->x());
+  CHECK_OR_FALSE(_sub != nullptr);
+
+  _ifm = loco::must_cast<luci::CircleNode *>(_sub->x());
+
+  _max = dynamic_cast<luci::CircleReduceMax *>(_sub->y());
+  CHECK_OR_FALSE(_max != nullptr);
+
+  CHECK_OR_FALSE(_max->input() == _ifm);
+  CHECK_OR_FALSE(_max->keep_dims() == true);
+
+  auto const max_indices = dynamic_cast<luci::CircleConst *>(_max->reduction_indices());
+  CHECK_OR_FALSE(max_indices != nullptr);
+
+  // check dtype of reduction indices
+  CHECK_OR_FALSE(max_indices->dtype() == loco::DataType::S32 &&
+                 sum_indices->dtype() == loco::DataType::S32);
+
+  // reduction of max and sum must be done over the last (channel) dimension
+  {
+    CHECK_OR_FALSE(max_indices->size<loco::DataType::S32>() == 1 &&
+                   sum_indices->size<loco::DataType::S32>() == 1);
+
+    auto const rank = _ifm->rank();
+    int32_t last_dim = (rank == 0) ? 0 : rank - 1;
+
+    CHECK_OR_FALSE(max_indices->at<loco::DataType::S32>(0) == -1 ||
+                   max_indices->at<loco::DataType::S32>(0) == last_dim);
+
+    CHECK_OR_FALSE(sum_indices->at<loco::DataType::S32>(0) == -1 ||
+                   sum_indices->at<loco::DataType::S32>(0) == last_dim);
+  }
+
+  return true;
+}
+
+#undef CHECK_OR_FALSE
+
+} // namespace
+
+std::map<luci::CircleNode *, LayerParam>
+Q8LayerNormWithQ16VarianceResolver::resolve(const luci::Module *module)
+{
+  if (!module)
+  {
+    throw std::runtime_error("No module for pattern resolving");
+  }
+
+  std::map<luci::CircleNode *, LayerParam> nodes_params;
+  for (size_t idx = 0; idx < module->size(); ++idx)
+  {
+    auto graph = module->graph(idx);
+
+    for (auto node : loco::active_nodes(loco::output_nodes(graph)))
+    {
+      auto const mul = dynamic_cast<luci::CircleMul *>(node);
+      if (!mul)
+        continue;
+
+      LayerNormPattern pattern(mul);
+      if (!pattern.matched())
+        continue;
+
+      // set quantization parameters of recognized pattern
+      for (auto q16_node : pattern.get_q16_nodes())
+      {
+        LayerParam param = {q16_node->name(), "int16", "channel"};
+        nodes_params[q16_node] = param;
+      }
+
+      for (auto q8_node : pattern.get_q8_nodes())
+      {
+        LayerParam param = {q8_node->name(), "uint8", "channel"};
+        nodes_params[q8_node] = param;
+      }
+    }
+  }
+
+  return nodes_params;
+}
+
+std::map<luci::CircleNode *, LayerParam>
+Q8SoftmaxWithQ16SubExpResolver::resolve(const luci::Module *module)
+{
+  if (!module)
+  {
+    throw std::runtime_error("No module for pattern resolving");
+  }
+
+  std::map<luci::CircleNode *, LayerParam> nodes_params;
+  for (size_t idx = 0; idx < module->size(); ++idx)
+  {
+    auto graph = module->graph(idx);
+
+    for (auto node : loco::active_nodes(loco::output_nodes(graph)))
+    {
+      auto const div = dynamic_cast<luci::CircleDiv *>(node);
+      if (!div)
+        continue;
+
+      SoftmaxPattern pattern(div);
+      if (!pattern.matched())
+        continue;
+
+      // set quantization parameters of recognized pattern
+      for (auto q16_node : pattern.get_q16_nodes())
+      {
+        LayerParam param = {q16_node->name(), "int16", "channel"};
+        nodes_params[q16_node] = param;
+      }
+
+      for (auto q8_node : pattern.get_q8_nodes())
+      {
+        LayerParam param = {q8_node->name(), "uint8", "channel"};
+        nodes_params[q8_node] = param;
+      }
+    }
+  }
+
+  return nodes_params;
+}
diff --git a/compiler/circle-mpqsolver/src/pattern/PatternResolver.h b/compiler/circle-mpqsolver/src/pattern/PatternResolver.h
new file mode 100644 (file)
index 0000000..c005bc7
--- /dev/null
@@ -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 __MPQSOLVER_PATTERN_RESOLVER_H__
+#define __MPQSOLVER_PATTERN_RESOLVER_H__
+
+#include <luci/CircleQuantizer.h>
+#include <luci/IR/Module.h>
+#include <luci/IR/CircleNodes.h>
+
+#include <map>
+
+namespace mpqsolver
+{
+namespace pattern
+{
+
+class PatternResolver
+{
+public:
+  virtual ~PatternResolver() = default;
+  virtual std::map<luci::CircleNode *, luci::CircleQuantizer::Options::LayerParam>
+  resolve(const luci::Module *module) = 0;
+};
+
+class Q8LayerNormWithQ16VarianceResolver : public PatternResolver
+{
+public:
+  /**
+   * @brief resolve all nodes of LayerNorm pattern as prescribed
+   */
+  std::map<luci::CircleNode *, luci::CircleQuantizer::Options::LayerParam>
+  resolve(const luci::Module *module) override;
+};
+
+class Q8SoftmaxWithQ16SubExpResolver : public PatternResolver
+{
+public:
+  /**
+   * @brief resolve all nodes of Softmax pattern as prescribed
+   */
+  std::map<luci::CircleNode *, luci::CircleQuantizer::Options::LayerParam>
+  resolve(const luci::Module *module) override;
+};
+
+} // namespace pattern
+} // namespace mpqsolver
+
+#endif //__MPQSOLVER_PATTERN_RESOLVER_H__
diff --git a/compiler/circle-mpqsolver/src/pattern/PatternResolver.test.cpp b/compiler/circle-mpqsolver/src/pattern/PatternResolver.test.cpp
new file mode 100644 (file)
index 0000000..1f08c95
--- /dev/null
@@ -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 "PatternResolver.h"
+
+#include "core/TestHelper.h"
+
+#include <luci/CircleQuantizer.h>
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <cmath>
+#include <gtest/gtest.h>
+
+using LayerParam = luci::CircleQuantizer::Options::LayerParam;
+
+namespace
+{
+
+using namespace luci::test;
+
+class LayerNormGraphlet
+{
+public:
+  LayerNormGraphlet() = default;
+  virtual ~LayerNormGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    ifm = nullptr;
+
+    ifm = g->nodes()->create<luci::CircleAbs>();
+    mean_of_ifm = g->nodes()->create<luci::CircleMean>();
+    sub = g->nodes()->create<luci::CircleSub>();
+    sub_squared = g->nodes()->create<luci::CircleMul>();
+    mean_as_variance = g->nodes()->create<luci::CircleMean>();
+    add_eps = g->nodes()->create<luci::CircleAdd>();
+    rsqrt = g->nodes()->create<luci::CircleRsqrt>();
+    mul = g->nodes()->create<luci::CircleMul>();
+    _eps = g->nodes()->create<luci::CircleConst>();
+    _mean_of_ifm_indices = g->nodes()->create<luci::CircleConst>();
+    _mean_as_variance_indices = g->nodes()->create<luci::CircleConst>();
+
+    ifm->name("ifm");
+    mean_of_ifm->name("mean_of_ifm");
+    sub->name("sub");
+    sub_squared->name("sub_squared");
+    mean_as_variance->name("mean_as_variance");
+    add_eps->name("add_eps");
+    rsqrt->name("rsqrt");
+    mul->name("mul");
+    _eps->name("eps");
+    _mean_of_ifm_indices->name("mean_of_ifm_indices");
+    _mean_as_variance_indices->name("mean_as_variance_indices");
+
+    _eps->dtype(loco::DataType::FLOAT32);
+    _eps->size<loco::DataType::FLOAT32>(1);
+    _eps->shape({1});
+    _eps->at<loco::DataType::FLOAT32>(0) = 1.e-05f;
+    _eps->shape_status(luci::ShapeStatus::VALID);
+
+    _mean_of_ifm_indices->dtype(loco::DataType::S32);
+    _mean_of_ifm_indices->size<loco::DataType::S32>(1);
+    _mean_of_ifm_indices->shape({1});
+    _mean_of_ifm_indices->at<loco::DataType::S32>(0) = -1;
+    _mean_of_ifm_indices->shape_status(luci::ShapeStatus::VALID);
+
+    _mean_as_variance_indices->dtype(loco::DataType::S32);
+    _mean_as_variance_indices->size<loco::DataType::S32>(1);
+    _mean_as_variance_indices->shape({1});
+    _mean_as_variance_indices->at<loco::DataType::S32>(0) = -1;
+    _mean_as_variance_indices->shape_status(luci::ShapeStatus::VALID);
+  }
+
+public:
+  luci::CircleAbs *ifm = nullptr;
+  luci::CircleMean *mean_of_ifm = nullptr;
+  luci::CircleSub *sub = nullptr;
+  luci::CircleMul *sub_squared = nullptr;
+  luci::CircleMean *mean_as_variance = nullptr;
+  luci::CircleAdd *add_eps = nullptr;
+  luci::CircleRsqrt *rsqrt = nullptr;
+  luci::CircleMul *mul = nullptr;
+
+protected:
+  luci::CircleConst *_eps = nullptr;
+  luci::CircleConst *_mean_of_ifm_indices = nullptr;
+  luci::CircleConst *_mean_as_variance_indices = nullptr;
+};
+
+class LayerNormTestGraph : public TestIOGraph, public LayerNormGraphlet
+{
+public:
+  LayerNormTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({1, 12, 11, 15}, {1, 12, 11, 15});
+    LayerNormGraphlet::init(g());
+
+    ifm->x(input());
+    mean_of_ifm->input(ifm);
+    mean_of_ifm->reduction_indices(_mean_of_ifm_indices);
+    sub->x(ifm);
+    sub->y(mean_of_ifm);
+    sub_squared->x(sub);
+    sub_squared->y(sub);
+    mean_as_variance->input(sub_squared);
+    mean_as_variance->reduction_indices(_mean_as_variance_indices);
+    add_eps->x(mean_as_variance);
+    add_eps->y(_eps);
+    rsqrt->x(add_eps);
+    mul->x(sub);
+    mul->y(rsqrt);
+
+    output()->from(mul);
+  }
+};
+
+} // namespace
+
+TEST(LayerNormPatternResolverTest, resolve_pattern)
+{
+  auto m = luci::make_module();
+  LayerNormTestGraph g;
+  g.init();
+  g.transfer_to(m.get());
+
+  std::map<luci::CircleNode *, LayerParam> params;
+  mpqsolver::pattern::Q8LayerNormWithQ16VarianceResolver resolver;
+  EXPECT_NO_THROW({ params = resolver.resolve(m.get()); });
+
+  std::set<luci::CircleNode *> q16_nodes = {g.sub_squared, g.mean_as_variance, g.add_eps, g.rsqrt};
+  std::set<luci::CircleNode *> q8_nodes = {g.mean_of_ifm, g.sub, g.mul};
+
+  // params of all valid layers are set
+  EXPECT_EQ(params.size(), q16_nodes.size() + q8_nodes.size());
+
+  for (auto param : params)
+  {
+    // params of all layers are set as prescribed
+    if (q16_nodes.find(param.first) != q16_nodes.end())
+    {
+      EXPECT_STREQ(param.second.dtype.c_str(), "int16");
+    }
+    else if (q8_nodes.find(param.first) != q8_nodes.end())
+    {
+      EXPECT_STREQ(param.second.dtype.c_str(), "uint8");
+    }
+  }
+}
+
+TEST(LayerNormPatternResolverTest, resolve_pattern_NEG)
+{
+  std::map<luci::CircleNode *, LayerParam> params;
+  mpqsolver::pattern::Q8LayerNormWithQ16VarianceResolver resolver;
+  EXPECT_ANY_THROW(resolver.resolve(nullptr));
+}
+
+TEST(SoftmaxResolverTest, resolve_pattern)
+{
+  auto m = luci::make_module();
+  mpqsolver::test::models::SoftmaxTestGraph g;
+  g.init();
+  g.transfer_to(m.get());
+
+  std::map<luci::CircleNode *, LayerParam> params;
+  mpqsolver::pattern::Q8SoftmaxWithQ16SubExpResolver resolver;
+  EXPECT_NO_THROW({ params = resolver.resolve(m.get()); });
+
+  std::set<luci::CircleNode *> q16_nodes = {g._sub, g._exp};
+  std::set<luci::CircleNode *> q8_nodes = {g._ifm, g._max, g._sum, g._div};
+
+  // params of all valid layers are set
+  EXPECT_EQ(params.size(), q16_nodes.size() + q8_nodes.size());
+
+  for (auto param : params)
+  {
+    // params of all layers are set as prescribed
+    if (q16_nodes.find(param.first) != q16_nodes.end())
+    {
+      EXPECT_STREQ(param.second.dtype.c_str(), "int16");
+    }
+    else if (q8_nodes.find(param.first) != q8_nodes.end())
+    {
+      EXPECT_STREQ(param.second.dtype.c_str(), "uint8");
+    }
+  }
+}
+
+TEST(SoftmaxPatternResolverTest, resolve_pattern_NEG)
+{
+  mpqsolver::pattern::Q8SoftmaxWithQ16SubExpResolver resolver;
+  EXPECT_ANY_THROW(resolver.resolve(nullptr));
+}
diff --git a/compiler/circle-mpqsolver/src/pattern/PatternSolver.cpp b/compiler/circle-mpqsolver/src/pattern/PatternSolver.cpp
new file mode 100644 (file)
index 0000000..064a726
--- /dev/null
@@ -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.
+ */
+
+#include "PatternSolver.h"
+
+#include "PatternResolver.h"
+
+#include <iostream>
+#include <cmath>
+
+using namespace mpqsolver::pattern;
+
+using LayerParam = luci::CircleQuantizer::Options::LayerParam;
+using LayerParams = luci::CircleQuantizer::Options::LayerParams;
+
+PatternSolver::PatternSolver(const mpqsolver::core::Quantizer::Context &ctx,
+                             const std::vector<QuantizationPattern> &patterns)
+  : MPQSolver(ctx)
+{
+  MPQOptions options{patterns};
+  setMPQOptions(options);
+}
+
+std::unique_ptr<luci::Module> PatternSolver::run(const std::string &module_path)
+{
+  auto module = readModule(module_path);
+  assert(module != nullptr);
+
+  _quantizer->setHook(_hooks.get());
+  if (_hooks)
+  {
+    _hooks->onBeginSolver(module_path, NAN, NAN);
+  }
+
+  resolvePatterns(module.get());
+
+  auto layer_params = getFrozenParams();
+
+  if (_hooks)
+  {
+    _hooks->onEndSolver(layer_params, _quantizer->getContext().output_model_dtype, NAN);
+  }
+
+  if (!_quantizer->quantize(module.get(), layer_params))
+  {
+    throw std::runtime_error("Failed to quantize model");
+  }
+
+  return module;
+}
+
+void PatternSolver::setMPQOptions(MPQOptions &options) { _options = options; }
+
+LayerParams PatternSolver::getFrozenParams() const
+{
+  LayerParams params;
+  for (const auto &node_to_param : _frozen._node_to_param)
+  {
+    params.push_back(std::make_shared<LayerParam>(node_to_param.second));
+  }
+
+  return params;
+}
+
+void PatternSolver::resolvePatterns(luci::Module *module)
+{
+  _frozen._node_to_param.clear();
+
+  for (auto pattern : _options._patterns)
+  {
+    std::unique_ptr<pattern::PatternResolver> resolver;
+    switch (pattern)
+    {
+      case QuantizationPattern::Q8LayerNormWithQ16Variance:
+        resolver = std::make_unique<pattern::Q8LayerNormWithQ16VarianceResolver>();
+        break;
+      case QuantizationPattern::Q8SoftmaxWithQ16SubExp:
+        resolver = std::make_unique<pattern::Q8SoftmaxWithQ16SubExpResolver>();
+        break;
+      default:
+        throw std::runtime_error("Unsupported pattern to resolve");
+    }
+
+    auto const resolved = resolver->resolve(module);
+    for (const auto &node_param : resolved)
+    {
+      auto const frozen = _frozen._node_to_param.find(node_param.first);
+      if (frozen == _frozen._node_to_param.end())
+      {
+        // node was not previously defined - just set it (no ambiguity)
+        _frozen._node_to_param[node_param.first] = node_param.second;
+      }
+      else if (frozen->second.dtype != node_param.second.dtype)
+      {
+        // ambiguity (incoming description conflicts with current)
+        throw std::runtime_error("Resolved patterns contradict each other");
+      }
+    }
+  }
+}
diff --git a/compiler/circle-mpqsolver/src/pattern/PatternSolver.h b/compiler/circle-mpqsolver/src/pattern/PatternSolver.h
new file mode 100644 (file)
index 0000000..52d7402
--- /dev/null
@@ -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.
+ */
+
+#ifndef __MPQSOLVER_PATTERN_SOLVER_H__
+#define __MPQSOLVER_PATTERN_SOLVER_H__
+
+#include "MPQSolver.h"
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace mpqsolver
+{
+namespace pattern
+{
+
+enum class QuantizationPattern
+{
+  Q8LayerNormWithQ16Variance,
+  Q8SoftmaxWithQ16SubExp,
+};
+
+struct MPQOptions
+{
+  std::vector<QuantizationPattern> _patterns;
+};
+
+struct FrozenNodes
+{
+  std::map<luci::CircleNode *, luci::CircleQuantizer::Options::LayerParam> _node_to_param;
+};
+
+class PatternSolver final : public MPQSolver
+{
+public:
+  /**
+   * @brief construct PatternSolver using qunatization context and patterns to apply
+   */
+  PatternSolver(const mpqsolver::core::Quantizer::Context &ctx,
+                const std::vector<QuantizationPattern> &patterns);
+
+  /**
+   * @brief run solver for recorded float module at module_path
+   */
+  std::unique_ptr<luci::Module> run(const std::string &module_path) override;
+
+private:
+  /**
+   * @brief set quantization options
+   */
+  void setMPQOptions(MPQOptions &options);
+
+  /**
+   * @brief fill _frozen with prescribed quantization parameters of resolved nodes
+   */
+  void resolvePatterns(luci::Module *module);
+
+  /**
+   * @brief transform _frozen nodes to Quantizer friendly form
+   */
+  luci::CircleQuantizer::Options::LayerParams getFrozenParams() const;
+
+private:
+  MPQOptions _options; // options for mpq quantization
+  FrozenNodes _frozen; // nodes with prescribed quantization parameters
+};
+
+} // namespace pattern
+} // namespace mpqsolver
+
+#endif //__MPQSOLVER_PATTERN_SOLVER_H__
diff --git a/compiler/circle-mpqsolver/src/pattern/PatternSolver.test.cpp b/compiler/circle-mpqsolver/src/pattern/PatternSolver.test.cpp
new file mode 100644 (file)
index 0000000..90ff0f8
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PatternSolver.h"
+
+#include "core/TestHelper.h"
+
+#include <luci/CircleExporter.h>
+#include <luci/CircleFileExpContract.h>
+
+using namespace mpqsolver::pattern;
+
+namespace
+{
+
+class CircleMPQSolverPatternSolverTest : public ::testing::Test
+{
+public:
+  CircleMPQSolverPatternSolverTest()
+  {
+    char module_template[] = "CircleMPQSolverPatternSolverTest-CIRCLE-XXXXXX";
+    mpqsolver::test::io_utils::makeTemporaryFile(module_template);
+    _module_path = module_template;
+  }
+
+  ~CircleMPQSolverPatternSolverTest() { unlink(_module_path.c_str()); }
+
+protected:
+  mpqsolver::test::models::SoftmaxTestGraph _g;
+  std::string _module_path;
+};
+
+} // namespace
+
+TEST_F(CircleMPQSolverPatternSolverTest, verify_results)
+{
+  auto m = luci::make_module();
+  _g.init();
+  _g.transfer_to(m.get());
+
+  // export to _module_path
+  luci::CircleExporter exporter;
+  luci::CircleFileExpContract contract(m.get(), _module_path);
+  EXPECT_TRUE(exporter.invoke(&contract));
+
+  // Create quantizer parameters
+  mpqsolver::core::Quantizer::Context ctx;
+  {
+    ctx.output_model_dtype = "uint8";
+    ctx.granularity = "channel";
+    ctx.input_type = "uint8";
+    ctx.output_type = "uint8";
+    ctx.save_min_max = false;
+    ctx.TF_style_maxpool = false;
+  }
+
+  // create solver
+  mpqsolver::pattern::PatternSolver solver(
+    ctx, std::vector<QuantizationPattern>(1, QuantizationPattern::Q8SoftmaxWithQ16SubExp));
+
+  // run solver
+  auto const res = solver.run(_module_path);
+  EXPECT_TRUE(res.get() != nullptr);
+  ASSERT_EQ(1, res.get()->size());
+
+  auto const graph = res.get()->graph();
+  ASSERT_NE(nullptr, graph);
+
+  uint32_t exp_count = 0;
+  for (auto node : loco::postorder_traversal(loco::output_nodes(graph)))
+  {
+    auto const exp = dynamic_cast<luci::CircleExp *>(node);
+    if (exp != nullptr)
+    {
+      exp_count += 1;
+      auto const dtype = exp->dtype();
+      // pattern was applied
+      ASSERT_EQ(loco::DataType::S16, dtype);
+    }
+  }
+
+  // the model has a single exp node
+  ASSERT_EQ(1, exp_count);
+}
+
+TEST_F(CircleMPQSolverPatternSolverTest, empty_patterns_NEG)
+{
+  auto m = luci::make_module();
+  _g.init();
+  _g.transfer_to(m.get());
+
+  // export to _module_path
+  luci::CircleExporter exporter;
+  luci::CircleFileExpContract contract(m.get(), _module_path);
+  EXPECT_TRUE(exporter.invoke(&contract));
+
+  // Create quantizer parameters
+  mpqsolver::core::Quantizer::Context ctx;
+  {
+    ctx.output_model_dtype = "uint8";
+    ctx.granularity = "channel";
+    ctx.input_type = "uint8";
+    ctx.output_type = "uint8";
+    ctx.save_min_max = false;
+    ctx.TF_style_maxpool = false;
+  }
+
+  // create solver
+  mpqsolver::pattern::PatternSolver solver(ctx, std::vector<QuantizationPattern>());
+
+  // run solver
+  auto const res = solver.run(_module_path);
+  EXPECT_TRUE(res.get() != nullptr);
+  ASSERT_EQ(1, res.get()->size());
+
+  auto const graph = res.get()->graph();
+  ASSERT_NE(nullptr, graph);
+
+  uint32_t exp_count = 0;
+  for (auto node : loco::postorder_traversal(loco::output_nodes(graph)))
+  {
+    auto const exp = dynamic_cast<luci::CircleExp *>(node);
+    if (exp != nullptr)
+    {
+      exp_count += 1;
+      auto const dtype = exp->dtype();
+      // pattern was not applied
+      ASSERT_EQ(loco::DataType::U8, dtype);
+    }
+  }
+
+  // the model has a single exp node
+  ASSERT_EQ(1, exp_count);
+}
+
+TEST_F(CircleMPQSolverPatternSolverTest, empty_path_NEG)
+{
+  // Create quantizer parameters
+  mpqsolver::core::Quantizer::Context ctx;
+  {
+    ctx.output_model_dtype = "uint8";
+    ctx.granularity = "channel";
+    ctx.input_type = "uint8";
+    ctx.output_type = "uint8";
+    ctx.save_min_max = false;
+    ctx.TF_style_maxpool = false;
+  }
+
+  // create solver
+  mpqsolver::pattern::PatternSolver solver(
+    ctx, std::vector<QuantizationPattern>(1, QuantizationPattern::Q8LayerNormWithQ16Variance));
+
+  EXPECT_ANY_THROW(solver.run(""));
+}
index 33d9a96..a13e76e 100644 (file)
@@ -1,6 +1,6 @@
-if(NOT TARGET mio_circle06)
+if(NOT TARGET mio_circle08)
   return()
-endif(NOT TARGET mio_circle06)
+endif(NOT TARGET mio_circle08)
 
 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_circle06)
-target_link_libraries(circle-operator mio_circle06_helper)
+target_link_libraries(circle-operator mio_circle08)
+target_link_libraries(circle-operator mio_circle08_helper)
 target_link_libraries(circle-operator safemain)
 
 install(TARGETS circle-operator DESTINATION bin)
index b3a2638..8a57c8f 100644 (file)
@@ -1,4 +1,4 @@
 require("arser")
 require("foder")
-require("mio-circle06")
+require("mio-circle08")
 require("safemain")
index 36bfe86..dc26022 100644 (file)
@@ -27,7 +27,7 @@ namespace
 void dump_ops(std::ostream &os, mio::circle::Reader &reader, const cirops::DumpOption &option)
 {
   auto ops = reader.operators();
-  for (uint32_t i = 0; i < ops->Length(); ++i)
+  for (uint32_t i = 0; i < ops->size(); ++i)
   {
     const auto op = ops->Get(i);
     const auto op_name = reader.opcode_name(op);
index 5ad2b9c..8cfa248 100644 (file)
@@ -80,10 +80,9 @@ int entry(int argc, char **argv)
   auto module = opselector::getModule(input_path);
 
   // TODO support two or more subgraphs
-  if (module.get()->size() != 1)
+  if (module.get()->size() > 1)
   {
-    std::cerr << "ERROR: Not support two or more subgraphs" << std::endl;
-    return EXIT_FAILURE;
+    std::cout << "WARNING: Only first subgraph's operators will be selected" << std::endl;
   }
 
   opselector::OpSelector op_selector{module.get()};
index 09a6654..a069d88 100644 (file)
@@ -68,7 +68,7 @@ bool is_number(const std::vector<std::string> &vec)
 {
   for (const auto &s : vec)
   {
-    if (not::is_number(s))
+    if (not ::is_number(s))
     {
       return false;
     }
@@ -94,6 +94,15 @@ public:
   bool visit(const luci::CircleNode *) final { return false; }
 };
 
+class IsMultiGraphNode final : public luci::CircleNodeVisitor<bool>
+{
+public:
+  bool visit(const luci::CircleIf *) final { return true; }
+  bool visit(const luci::CircleWhile *) final { return true; }
+  // default is false
+  bool visit(const luci::CircleNode *) final { return false; }
+};
+
 std::unique_ptr<loco::Graph> make_graph(const std::vector<const luci::CircleNode *> nodes)
 {
   auto graph = loco::make_graph();
@@ -119,6 +128,14 @@ std::unique_ptr<loco::Graph> make_graph(const std::vector<const luci::CircleNode
       // the node isn't graph input if it is an other node's input
       if (std::find(nodes.begin(), nodes.end(), arg) != nodes.end())
         continue;
+      // do not set graph input if the node is CircleOutputExclude.
+      auto circle_output_exclude = dynamic_cast<luci::CircleOutputExclude *>(arg);
+      if (circle_output_exclude)
+      {
+        auto clone = luci::clone_node(circle_output_exclude, graph.get());
+        ctx.emplace(circle_output_exclude, clone);
+        continue;
+      }
       auto circle_const = dynamic_cast<luci::CircleConst *>(arg);
       if (circle_const != nullptr)
       {
@@ -247,10 +264,7 @@ namespace opselector
 
 OpSelector::OpSelector(const luci::Module *module) : _module{module}
 {
-  if (_module->size() != 1)
-  {
-    throw std::runtime_error{"ERROR: Not support two or more subgraphs"};
-  }
+  // DO NOTHING
 }
 
 template <>
@@ -262,7 +276,7 @@ OpSelector::select_by<SelectType::ID>(const std::vector<std::string> &comma_toke
   for (const auto &comma_token : comma_tokens)
   {
     auto dash_tokens = ::split_into_vector(comma_token, '-');
-    if (not::is_number(dash_tokens))
+    if (not ::is_number(dash_tokens))
     {
       throw std::runtime_error{
         "ERROR: To select operator by id, please use these args: [0-9], '-', ','"};
@@ -367,8 +381,6 @@ std::unique_ptr<luci::Module> OpSelector::select_by(const std::string &str)
     throw std::runtime_error{"ERROR: Nothing was entered."};
   }
 
-  assert(_module->size() == 1);
-
   auto selected_nodes = select_by<SELECT_TYPE>(colon_tokens);
 
   // multiout node should be considered
@@ -387,6 +399,17 @@ std::unique_ptr<luci::Module> OpSelector::select_by(const std::string &str)
   }
   selected_nodes.insert(selected_nodes.end(), output_nodes.begin(), output_nodes.end());
 
+  // TODO support two or more subgraphs
+  for (const auto &n : selected_nodes)
+  {
+    IsMultiGraphNode multigraph_visitor;
+    bool isMultiGraph = n->accept(&multigraph_visitor);
+    if (isMultiGraph)
+    {
+      throw std::runtime_error{"ERROR: If or While operator can't be selected."};
+    }
+  }
+
   auto new_module = std::make_unique<luci::Module>();
   new_module->add(::make_graph(selected_nodes));
 
index dd2ffe2..b7ab320 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <luci/IR/Nodes/CircleInput.h>
 #include <luci/IR/Nodes/CircleOutput.h>
+#include <luci/IR/DataTypeHelper.h>
 #include <luci/Importer.h>
 #include <luci/Log.h>
 #include <luci_interpreter/Interpreter.h>
@@ -78,7 +79,7 @@ void save_shape(const std::string &shape_filename, const luci::CircleOutput *out
 
 template <typename NodeT> size_t tensor_size(const NodeT *node)
 {
-  uint32_t tsize = loco::size(node->dtype());
+  uint32_t tsize = luci::size(node->dtype());
   for (uint32_t i = 0; i < node->rank(); ++i)
   {
     assert(node->dim(i).known());
diff --git a/compiler/circle-part-value-py-test/CMakeLists.txt b/compiler/circle-part-value-py-test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6a29131
--- /dev/null
@@ -0,0 +1,110 @@
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
+
+unset(RECIPE_LIST)
+unset(PARTITION_LIST)
+unset(OUTPUT_COUNT_LIST)
+unset(TEST_DEPS)
+
+macro(add RECIPE_NAME PARTITION_NAME OUTPUT_COUNT)
+  list(APPEND RECIPE_LIST ${RECIPE_NAME})
+  list(APPEND PARTITION_LIST ${PARTITION_NAME})
+  list(APPEND OUTPUT_COUNT_LIST ${OUTPUT_COUNT})
+endmacro(add)
+
+# Read "test.lst"
+include("test.lst")
+
+list(LENGTH RECIPE_LIST RECIPE_LENGTH)
+math(EXPR RECIPE_LENGTH_M1 "${RECIPE_LENGTH} - 1")
+
+foreach(IDX RANGE ${RECIPE_LENGTH_M1})
+  list(GET RECIPE_LIST ${IDX} RECIPE_NAME)
+  list(GET PARTITION_LIST ${IDX} PARTITION_NAME)
+  list(GET OUTPUT_COUNT_LIST ${IDX} OUTPUT_COUNT)
+
+  # NOTE about the name:
+  # Use '.recipe' name for source tflite and circle files
+  # Use '.part' name for actual test folder and test files
+
+  # Output to a folder
+  set(PARTITIONER_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PARTITION_NAME}")
+
+  add_custom_command(OUTPUT ${PARTITIONER_OUTPUT_PATH}
+    COMMAND ${CMAKE_COMMAND} -E make_directory "${PARTITIONER_OUTPUT_PATH}"
+    COMMENT "Make directory ${PARTITIONER_OUTPUT_PATH}"
+  )
+
+  # Copy tflite
+  set(TFLITE_SRC_PATH "${ARTIFACTS_BIN_PATH}/${RECIPE_NAME}.tflite")
+  set(TFLITE_DST_PATH "${PARTITIONER_OUTPUT_PATH}/${PARTITION_NAME}.tflite")
+
+  add_custom_command(OUTPUT ${TFLITE_DST_PATH}
+    COMMAND ${CMAKE_COMMAND} -E copy "${TFLITE_SRC_PATH}" "${TFLITE_DST_PATH}"
+    DEPENDS ${TFLITE_SRC_PATH}
+    COMMENT "Copy ${RECIPE_NAME}.tflite"
+  )
+  list(APPEND TEST_DEPS ${TFLITE_DST_PATH})
+
+  # Copy circle
+  set(CIRCLE_SRC_PATH "${ARTIFACTS_BIN_PATH}/${RECIPE_NAME}.circle")
+  set(CIRCLE_DST_PATH "${PARTITIONER_OUTPUT_PATH}/${PARTITION_NAME}.circle")
+
+  add_custom_command(OUTPUT ${CIRCLE_DST_PATH}
+    COMMAND ${CMAKE_COMMAND} -E copy "${CIRCLE_SRC_PATH}" "${CIRCLE_DST_PATH}"
+    DEPENDS ${CIRCLE_SRC_PATH}
+    COMMENT "Copy ${RECIPE_NAME}.circle"
+  )
+  list(APPEND TEST_DEPS ${CIRCLE_DST_PATH})
+
+  # Copy .part
+  set(PART_FILE "${PARTITION_NAME}.part")
+  set(PART_SRC_PATH "${CMAKE_CURRENT_SOURCE_DIR}/parts/${PART_FILE}")
+  set(PART_DST_PATH "${PARTITIONER_OUTPUT_PATH}/${PART_FILE}")
+
+  add_custom_command(OUTPUT ${PART_DST_PATH}
+    COMMAND ${CMAKE_COMMAND} -E copy "${PART_SRC_PATH}" "${PART_DST_PATH}"
+    DEPENDS ${PART_SRC_PATH}
+    COMMENT "Copy ${PART_FILE}"
+  )
+  list(APPEND TEST_DEPS ${PART_DST_PATH})
+
+  # Partition connection file to generate
+  set(PARTITIONER_CONN_JSON "${PARTITIONER_OUTPUT_PATH}/${PARTITION_NAME}.conn.json")
+
+  # Run partitioner
+  add_custom_command(OUTPUT ${PARTITIONER_CONN_JSON}
+    COMMAND circle-partitioner "--part_file" "${PART_FILE}" "--input_file"
+            "${PARTITION_NAME}.circle" "--work_path" "${PARTITIONER_OUTPUT_PATH}"
+    DEPENDS circle-partitioner ${PART_DST_PATH} ${CIRCLE_DST_PATH}
+    COMMENT "Parition ${RECIPE_NAME}.circle with ${PART_FILE}"
+  )
+  list(APPEND TEST_DEPS ${PARTITIONER_CONN_JSON})
+
+  # Write .excnt file; expected count of output models
+  set(COUNT_FILE "${PARTITION_NAME}.excnt")
+  set(COUNT_FILE_PATH "${PARTITIONER_OUTPUT_PATH}/${COUNT_FILE}")
+  add_custom_command(OUTPUT ${COUNT_FILE_PATH}
+    COMMAND echo ${OUTPUT_COUNT} > ${COUNT_FILE_PATH}
+    DEPENDS ${PART_SRC_PATH} ${PARTITIONER_OUTPUT_PATH}
+    COMMENT "Write ${COUNT_FILE} with ${OUTPUT_COUNT}"
+  )
+  list(APPEND TEST_DEPS ${COUNT_FILE_PATH})
+endforeach(IDX)
+
+add_custom_target(circle_part_value_py_test_prepare ALL DEPENDS ${TEST_DEPS})
+add_dependencies(circle_part_value_py_test_prepare common_artifacts_deps)
+
+set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_12_1")
+set(TEST_LIST_FILE "test.lst")
+
+add_test(NAME circle_part_value_py_test
+  COMMAND ${VIRTUALENV}/bin/python -m pytest -sv test_circle_part_value.py
+        --test_list ${TEST_LIST_FILE}
+        --bin_dir ${CMAKE_CURRENT_BINARY_DIR}
+        --circle_part_driver $<TARGET_FILE:circle_part_driver>
+  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
diff --git a/compiler/circle-part-value-py-test/README.md b/compiler/circle-part-value-py-test/README.md
new file mode 100644 (file)
index 0000000..5ae38fa
--- /dev/null
@@ -0,0 +1,15 @@
+# circle-part-value-py-test
+
+_circle-part-value-py-test_ evaluates partitioned models produced by circle-partitioner.
+
+### Process of evaluation
+
+Evaluation process is like how _luci-value-test_ does.
+
+1) generates random input and stores to reference input file(s)
+2) executes tflite file from common-artifacts for reference output
+3) partitions circle file with .part file and produces into output folder
+4) executes produced partitioned circle models with reference input file(s)
+5) saves output(s) of circle models to file(s)
+6) compares reference output with saved output file(s)
+7) fail test if values differ
diff --git a/compiler/circle-part-value-py-test/conftest.py b/compiler/circle-part-value-py-test/conftest.py
new file mode 100644 (file)
index 0000000..63a78f4
--- /dev/null
@@ -0,0 +1,32 @@
+import re
+
+
+def extract_test_args(s):
+    p = re.compile('add\\((.*)\\)')
+    result = p.search(s)
+    return result.group(1)
+
+
+def pytest_addoption(parser):
+    parser.addoption("--test_list", action="store", help="Path to test list")
+    parser.addoption("--bin_dir", action="store", help="Directory including artifacts")
+    parser.addoption(
+        "--circle_part_driver", action="store", help="Path to circle part driver")
+
+
+def pytest_generate_tests(metafunc):
+    list_path = metafunc.config.getoption('test_list')
+    bin_dir = metafunc.config.getoption('bin_dir')
+    circle_part_driver = metafunc.config.getoption('circle_part_driver')
+
+    with open(list_path) as f:
+        contents = [line.rstrip() for line in f]
+
+    comment_removed = [line for line in contents if not line.startswith('#')]
+    newline_removed = [line for line in comment_removed if line.startswith('add(')]
+    test_args = [extract_test_args(line) for line in newline_removed]
+    # add(RECIPE_NAME PARTITION_NAME EXPECTED_OUTPUT_COUNT)
+    partition_list = [(arg.split()[1], bin_dir, circle_part_driver) for arg in test_args]
+
+    if 'test_name' in metafunc.fixturenames:
+        metafunc.parametrize('test_name,bin_dir,part_driver_path', partition_list)
diff --git a/compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.001.part b/compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.001.part
new file mode 100644 (file)
index 0000000..01b8c70
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+ADD=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.002.part b/compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.002.part
new file mode 100644 (file)
index 0000000..dc378a4
--- /dev/null
@@ -0,0 +1,8 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SUB=acl_cl
+DIV=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.003.part b/compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.003.part
new file mode 100644 (file)
index 0000000..eee3fd1
--- /dev/null
@@ -0,0 +1,9 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opname
+
+[OPNAME]
+Mean_as_variance=acl_cl
+Add_as_variance=acl_cl
+Pow=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.part b/compiler/circle-part-value-py-test/parts/Net_InstanceNorm_003.part
new file mode 100644 (file)
index 0000000..d4d439d
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+DIV=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Net_UnpackAdd_001.001.part b/compiler/circle-part-value-py-test/parts/Net_UnpackAdd_001.001.part
new file mode 100644 (file)
index 0000000..496971e
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,npu
+default=cpu
+comply=opcode
+
+[OPCODE]
+ADD=npu
diff --git a/compiler/circle-part-value-py-test/parts/Net_UnpackAdd_001.002.part b/compiler/circle-part-value-py-test/parts/Net_UnpackAdd_001.002.part
new file mode 100644 (file)
index 0000000..9913fea
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,npu
+default=cpu
+comply=opcode
+
+[OPCODE]
+UNPACK=npu
diff --git a/compiler/circle-part-value-py-test/parts/Net_UnpackAdd_001.part b/compiler/circle-part-value-py-test/parts/Net_UnpackAdd_001.part
new file mode 100644 (file)
index 0000000..c63efc5
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,npu
+default=npu
+comply=opcode
+
+[OPCODE]
+UNPACK=cpu
diff --git a/compiler/circle-part-value-py-test/parts/Part_Add_Sqrt_000.part b/compiler/circle-part-value-py-test/parts/Part_Add_Sqrt_000.part
new file mode 100644 (file)
index 0000000..402af87
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Add_Sqrt_Rsqrt_000.part b/compiler/circle-part-value-py-test/parts/Part_Add_Sqrt_Rsqrt_000.part
new file mode 100644 (file)
index 0000000..c6dba9f
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+RSQRT=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Add_Sub_000.001.part b/compiler/circle-part-value-py-test/parts/Part_Add_Sub_000.001.part
new file mode 100644 (file)
index 0000000..179cad1
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opname
+
+[OPNAME]
+add1=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Add_Sub_000.part b/compiler/circle-part-value-py-test/parts/Part_Add_Sub_000.part
new file mode 100644 (file)
index 0000000..905137c
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SUB=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Add_Sub_001.part b/compiler/circle-part-value-py-test/parts/Part_Add_Sub_001.part
new file mode 100644 (file)
index 0000000..41ce4b2
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opname
+
+[OPNAME]
+some/node/add2;and/another=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Add_Sub_002.001.part b/compiler/circle-part-value-py-test/parts/Part_Add_Sub_002.001.part
new file mode 100644 (file)
index 0000000..030653e
--- /dev/null
@@ -0,0 +1,9 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opname
+
+[OPNAME]
+add1=cpu
+add2=acl_cl
+ofm=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Add_Sub_002.002.part b/compiler/circle-part-value-py-test/parts/Part_Add_Sub_002.002.part
new file mode 100644 (file)
index 0000000..837b362
--- /dev/null
@@ -0,0 +1,9 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opname
+
+[OPNAME]
+add1=acl_cl
+add2=acl_cl
+ofm=cpu
diff --git a/compiler/circle-part-value-py-test/parts/Part_If_Add_Sub_000.001.part b/compiler/circle-part-value-py-test/parts/Part_If_Add_Sub_000.001.part
new file mode 100644 (file)
index 0000000..01b8c70
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+ADD=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_If_Add_Sub_001.001.part b/compiler/circle-part-value-py-test/parts/Part_If_Add_Sub_001.001.part
new file mode 100644 (file)
index 0000000..01b8c70
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+ADD=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Mul_Sqrt_FC_nobias_000_000.part b/compiler/circle-part-value-py-test/parts/Part_Mul_Sqrt_FC_nobias_000_000.part
new file mode 100644 (file)
index 0000000..ad08421
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,npu
+default=npu
+comply=opcode
+
+[OPCODE]
+MUL=npu
diff --git a/compiler/circle-part-value-py-test/parts/Part_Mul_Sqrt_FC_nobias_000_001.part b/compiler/circle-part-value-py-test/parts/Part_Mul_Sqrt_FC_nobias_000_001.part
new file mode 100644 (file)
index 0000000..c82b741
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,npu
+default=npu
+comply=opcode
+
+[OPCODE]
+SQRT=cpu
diff --git a/compiler/circle-part-value-py-test/parts/Part_Mul_Sqrt_FC_nobias_000_002.part b/compiler/circle-part-value-py-test/parts/Part_Mul_Sqrt_FC_nobias_000_002.part
new file mode 100644 (file)
index 0000000..d9d2a8e
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,npu
+default=npu
+comply=opcode
+
+[OPCODE]
+FULLY_CONNECTED=cpu
diff --git a/compiler/circle-part-value-py-test/parts/Part_Split_Add_000.part b/compiler/circle-part-value-py-test/parts/Part_Split_Add_000.part
new file mode 100644 (file)
index 0000000..91af566
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,npu
+default=npu
+comply=opcode
+
+[OPCODE]
+SPLIT=cpu
diff --git a/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_000.part b/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_000.part
new file mode 100644 (file)
index 0000000..402af87
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_001.part b/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_001.part
new file mode 100644 (file)
index 0000000..402af87
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_002.part b/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_002.part
new file mode 100644 (file)
index 0000000..402af87
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_003.part b/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_003.part
new file mode 100644 (file)
index 0000000..402af87
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_000.part b/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_000.part
new file mode 100644 (file)
index 0000000..402af87
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_001.part b/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_001.part
new file mode 100644 (file)
index 0000000..402af87
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_002.part b/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_002.part
new file mode 100644 (file)
index 0000000..402af87
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+SQRT=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_003.part b/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_003.part
new file mode 100644 (file)
index 0000000..0ec264c
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+WWW=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_004.part b/compiler/circle-part-value-py-test/parts/Part_Sqrt_Rsqrt_Add_004.part
new file mode 100644 (file)
index 0000000..febab22
--- /dev/null
@@ -0,0 +1,6 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
diff --git a/compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias.part b/compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias.part
new file mode 100644 (file)
index 0000000..d4d439d
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+DIV=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias_001.part b/compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias_001.part
new file mode 100644 (file)
index 0000000..dbd174e
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,npu
+default=npu
+comply=opcode
+
+[OPCODE]
+TANH=cpu
diff --git a/compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias_002.part b/compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias_002.part
new file mode 100644 (file)
index 0000000..475439a
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,npu
+default=cpu
+comply=opcode
+
+[OPCODE]
+FULLY_CONNECTED=npu
diff --git a/compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias_003.part b/compiler/circle-part-value-py-test/parts/Part_Tanh_FC_nobias_003.part
new file mode 100644 (file)
index 0000000..d9d2a8e
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,npu
+default=npu
+comply=opcode
+
+[OPCODE]
+FULLY_CONNECTED=cpu
diff --git a/compiler/circle-part-value-py-test/parts/Part_While_000.part b/compiler/circle-part-value-py-test/parts/Part_While_000.part
new file mode 100644 (file)
index 0000000..e469eeb
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+MAXIMUM=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/Part_While_001.part b/compiler/circle-part-value-py-test/parts/Part_While_001.part
new file mode 100644 (file)
index 0000000..e469eeb
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+MAXIMUM=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/SignatureDef_MultiOut_000.part b/compiler/circle-part-value-py-test/parts/SignatureDef_MultiOut_000.part
new file mode 100644 (file)
index 0000000..e469eeb
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+MAXIMUM=acl_cl
diff --git a/compiler/circle-part-value-py-test/parts/SignatureDef_MultiOut_001.part b/compiler/circle-part-value-py-test/parts/SignatureDef_MultiOut_001.part
new file mode 100644 (file)
index 0000000..e469eeb
--- /dev/null
@@ -0,0 +1,7 @@
+[partition]
+backends=cpu,acl_cl
+default=cpu
+comply=opcode
+
+[OPCODE]
+MAXIMUM=acl_cl
diff --git a/compiler/circle-part-value-py-test/requires.cmake b/compiler/circle-part-value-py-test/requires.cmake
new file mode 100644 (file)
index 0000000..a9301f9
--- /dev/null
@@ -0,0 +1,3 @@
+require("common-artifacts")
+require("circle-partitioner")
+require("circle-part-driver")
diff --git a/compiler/circle-part-value-py-test/test.lst b/compiler/circle-part-value-py-test/test.lst
new file mode 100644 (file)
index 0000000..b7a3f40
--- /dev/null
@@ -0,0 +1,58 @@
+# Add recipe names from /res/TensorFlowLiteRecipes to test.
+# Only add items exist in common-artifacts test: tflite/circle files are copied as source.
+#
+# add(RECIPE_NAME PARTITION_NAME EXPECTED_OUTPUT_COUNT)
+#     EXPECTED_OUTPUT_COUNT: 0 for skip expected count test
+
+add(Part_Add_Sub_000 Part_Add_Sub_000 2)
+add(Part_Sqrt_Rsqrt_000 Part_Sqrt_Rsqrt_000 2)
+add(Part_Sqrt_Rsqrt_001 Part_Sqrt_Rsqrt_001 2)
+add(Part_Sqrt_Rsqrt_002 Part_Sqrt_Rsqrt_002 4)
+add(Part_Sqrt_Rsqrt_003 Part_Sqrt_Rsqrt_003 3)
+add(Part_Sqrt_Rsqrt_Add_000 Part_Sqrt_Rsqrt_Add_000 3)
+add(Part_Sqrt_Rsqrt_Add_001 Part_Sqrt_Rsqrt_Add_001 3)
+add(Part_Sqrt_Rsqrt_Add_002 Part_Sqrt_Rsqrt_Add_002 4)
+add(Part_Sqrt_Rsqrt_Add_003 Part_Sqrt_Rsqrt_Add_003 1)
+add(Part_Sqrt_Rsqrt_Add_004 Part_Sqrt_Rsqrt_Add_004 1)
+add(Part_Add_Sqrt_000 Part_Add_Sqrt_000 3)
+add(Part_Add_Sqrt_Rsqrt_000 Part_Add_Sqrt_Rsqrt_000 3)
+add(Net_InstanceNorm_003 Net_InstanceNorm_003 3)
+add(Net_InstanceNorm_003 Net_InstanceNorm_003.001 5)
+# skip expected count for now
+add(Net_InstanceNorm_003 Net_InstanceNorm_003.002 0)
+
+# comply=opname
+add(Part_Add_Sub_000 Part_Add_Sub_000.001 3)
+add(Part_Add_Sub_001 Part_Add_Sub_001 3)
+add(Part_Add_Sub_002 Part_Add_Sub_002.001 2)
+add(Part_Add_Sub_002 Part_Add_Sub_002.002 2)
+add(Net_InstanceNorm_003 Net_InstanceNorm_003.003 3)
+
+# IF with subgraphs
+add(Part_If_Add_Sub_000 Part_If_Add_Sub_000.001 3)
+add(Part_If_Add_Sub_001 Part_If_Add_Sub_001.001 3)
+
+# WHILE with subgraphs
+add(Part_While_000 Part_While_000 3)
+add(Part_While_001 Part_While_001 3)
+
+# UNPACK with multiple outputs
+add(Net_UnpackAdd_001 Net_UnpackAdd_001 2)
+add(Net_UnpackAdd_001 Net_UnpackAdd_001.001 2)
+add(Net_UnpackAdd_001 Net_UnpackAdd_001.002 2)
+
+# Other multiple outputs
+add(Part_Split_Add_000 Part_Split_Add_000 2)
+
+# test SignatureDef, with any OPCODE
+add(SignatureDef_MultiOut_000 SignatureDef_MultiOut_000 0)
+add(SignatureDef_MultiOut_001 SignatureDef_MultiOut_001 0)
+
+# FC with nobias
+add(Part_Tanh_FC_nobias Part_Tanh_FC_nobias 1)
+add(Part_Tanh_FC_nobias Part_Tanh_FC_nobias_001 2)
+add(Part_Tanh_FC_nobias Part_Tanh_FC_nobias_002 2)
+add(Part_Tanh_FC_nobias Part_Tanh_FC_nobias_003 2)
+add(Part_Mul_Sqrt_FC_nobias_000 Part_Mul_Sqrt_FC_nobias_000_000 0)
+add(Part_Mul_Sqrt_FC_nobias_000 Part_Mul_Sqrt_FC_nobias_000_001 0)
+add(Part_Mul_Sqrt_FC_nobias_000 Part_Mul_Sqrt_FC_nobias_000_002 0)
diff --git a/compiler/circle-part-value-py-test/test_circle_part_value.py b/compiler/circle-part-value-py-test/test_circle_part_value.py
new file mode 100644 (file)
index 0000000..9852487
--- /dev/null
@@ -0,0 +1,147 @@
+import numpy as np
+import tensorflow as tf
+import subprocess
+import os
+import json
+
+
+# Compares the execution result of TFLite interpreter and partitioned model(s) from a circle model.
+def part_eval(test_name, bin_dir, circle_part_driver):
+    artifacts_dir = os.path.join(bin_dir, test_name)
+    tflite_model = os.path.join(artifacts_dir, test_name + ".tflite")
+    circle_model = os.path.join(artifacts_dir, test_name + ".circle")
+    partition_conn_ini = os.path.join(artifacts_dir, test_name + ".conn.ini")
+    partition_conn_json = os.path.join(artifacts_dir, test_name + ".conn.json")
+    expected_count = os.path.join(artifacts_dir, test_name + ".excnt")
+
+    # Check expected count of models from partitioning
+    try:
+        with open(expected_count, "r") as expected_count_file:
+            expected_count_line = expected_count_file.readline()
+
+        expected_count_line = int(expected_count_line)
+        if expected_count_line:
+            with open(partition_conn_json) as json_file:
+                json_data = json.load(json_file)
+                parts_value = json_data["parts"]
+                if len(parts_value) != expected_count_line:
+                    print("Partitioned model count differs from expected:",
+                          expected_count_line)
+                    assert False
+
+                print("Partitioned model count expected: ", expected_count_line)
+        else:
+            print("Skip expected partitioned model count check: 0")
+
+    except:
+        print("Skip expected partitioned model count check: error")
+
+    # Build TFLite interpreter.
+    interpreter = tf.lite.Interpreter(tflite_model)
+    interpreter.allocate_tensors()
+
+    # Read SignatureDef and get output tensor id orders for remapping
+    full_signatures = interpreter._get_full_signature_list()
+    full_signatures_outputs_remap = None
+    if full_signatures != None:
+        signature_serving_default = full_signatures.get('serving_default', None)
+        if signature_serving_default != None:
+            signature_outputs = signature_serving_default['outputs']
+
+            full_signatures_outputs_remap = []
+            for index, (key, value) in enumerate(signature_outputs.items()):
+                full_signatures_outputs_remap.append(value)
+
+    # Generate random input data.
+    num_inputs = len(interpreter.get_input_details())
+    for i in range(num_inputs):
+        input_details = interpreter.get_input_details()[i]
+        if input_details["dtype"] == np.float32:
+            input_data = np.array(
+                np.random.random_sample(input_details["shape"]), input_details["dtype"])
+        elif input_details["dtype"] == np.uint8:
+            input_data = np.array(
+                np.random.randint(0, 256, size=input_details["shape"]),
+                input_details["dtype"])
+        elif input_details["dtype"] == np.int16:
+            input_data = np.array(
+                np.random.randint(0, 100, size=input_details["shape"]),
+                input_details["dtype"])
+        elif input_details["dtype"] == np.int32:
+            input_data = np.array(
+                np.random.randint(0, 100, size=input_details["shape"]),
+                input_details["dtype"])
+        elif input_details["dtype"] == np.int64:
+            input_data = np.array(
+                np.random.randint(0, 100, size=input_details["shape"]),
+                input_details["dtype"])
+        elif input_details["dtype"] == np.bool_:
+            input_data = np.array(
+                np.random.choice(a=[True, False], size=input_details["shape"]),
+                input_details["dtype"])
+        else:
+            assert False, "Unsupported input dtype"
+
+        interpreter.set_tensor(input_details["index"], input_data)
+        input_data.tofile(circle_model + ".input" + str(i))
+
+    # Do inference
+    interpreter.invoke()
+
+    # Execute circle-part-driver.
+    partition_command = [
+        circle_part_driver, partition_conn_ini,
+        str(num_inputs), circle_model + ".input", circle_model + ".output"
+    ]
+    print("Run: ")
+    for arg in partition_command:
+        print("    ", arg, "\\")
+    print("", flush=True)
+
+    # working directory into the folder as ini has relative filename of the model
+    subprocess.run(partition_command, check=True, cwd=artifacts_dir)
+
+    # Compare the results.
+    inpt_output_details = interpreter.get_output_details()
+    for idx in range(len(inpt_output_details)):
+        output_details = inpt_output_details[idx]
+        output_data = np.fromfile(circle_model + ".output" + str(idx),
+                                  output_details["dtype"])
+        shape_file = open(circle_model + ".output" + str(idx) + ".shape", 'r')
+        output_shape = [int(i) for i in shape_file.read().split(',')]
+        luci_output_data = np.reshape(output_data, output_shape)
+        output_tensor = output_details["index"]
+        if full_signatures_outputs_remap != None:
+            output_tensor = full_signatures_outputs_remap[idx]
+        intp_output_data = interpreter.get_tensor(output_tensor)
+        if output_details["dtype"] == np.uint8:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=0, atol=0
+            ), "Execution result of " + tflite_model + " does not match with " + circle_model
+        elif output_details["dtype"] == np.float32:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=1.e-5, atol=1.e-5
+            ), "Execution result of " + tflite_model + " does not match with " + circle_model
+        elif output_details["dtype"] == np.int64:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=0, atol=0
+            ), "Execution result of " + tflite_model + " does not match with " + circle_model
+        elif output_details["dtype"] == np.int32:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=0, atol=0
+            ), "Execution result of " + tflite_model + " does not match with " + circle_model
+        elif output_details["dtype"] == np.int16:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=0, atol=0
+            ), "Execution result of " + tflite_model + " does not match with " + circle_model
+        elif output_details["dtype"] == np.bool_:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=0, atol=0
+            ), "Execution result of " + tflite_model + " does not match with " + circle_model
+        else:
+            assert False, "Unsupported data type: " + output_details["dtype"]
+
+
+# arguments must be in sync with `conftest.py`
+def test_circle_part_value(test_name: str, bin_dir: str, part_driver_path: str):
+    part_eval(test_name, bin_dir, part_driver_path)
diff --git a/compiler/circle-part-value-test/exclude.me b/compiler/circle-part-value-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 309069b..c4ad8ae 100644 (file)
@@ -46,6 +46,7 @@ Add(Quant_Logistic_001 DTYPE int16 GRANULARITY channel USE_QCONFIG)
 Add(Quant_MaxPool2D_001 DTYPE int16 GRANULARITY channel USE_QCONFIG)
 Add(Quant_Mean_001 DTYPE int16 GRANULARITY channel USE_QCONFIG)
 Add(Quant_Mul_001 DTYPE int16 GRANULARITY channel USE_QCONFIG)
+Add(Quant_Mul_002 DTYPE int16 GRANULARITY channel USE_QCONFIG)
 Add(Quant_Neg_001 DTYPE int16 GRANULARITY channel USE_QCONFIG)
 Add(Quant_Pad_001 DTYPE int16 GRANULARITY channel USE_QCONFIG)
 Add(Quant_PRelu_001 DTYPE int16 GRANULARITY channel USE_QCONFIG)
index 02b96f9..f18642f 100644 (file)
 #include <vconone/vconone.h>
 #include <json.h>
 
-#include <functional>
 #include <iostream>
 #include <map>
 #include <string>
 
-using OptionHook = std::function<int(const char **)>;
-
 using LayerParam = luci::CircleQuantizer::Options::LayerParam;
+using LayerParams = luci::CircleQuantizer::Options::LayerParams;
+using LayerParamsSet = luci::CircleQuantizer::Options::LayerParamsSet;
 using Algorithms = luci::CircleQuantizer::Options::Algorithm;
 using AlgorithmParameters = luci::CircleQuantizer::Options::AlgorithmParameters;
 
-std::vector<std::shared_ptr<LayerParam>> read_layer_params(std::string &filename)
+struct QConfReader
 {
-  Json::Value root;
-  std::ifstream ifs(filename);
+  void init(const std::string &filename)
+  {
+    std::ifstream ifs;
+
+    ifs.open(filename);
+
+    // Failed to open cfg file
+    if (not ifs.is_open())
+      throw std::runtime_error("Cannot open config file. " + filename);
+
+    JSONCPP_STRING errs;
+    Json::CharReaderBuilder builder;
 
-  // Failed to open cfg file
-  if (not ifs.is_open())
-    throw std::runtime_error("Cannot open config file. " + filename);
+    // Failed to parse
+    if (not parseFromStream(builder, ifs, &_root, &errs))
+      throw std::runtime_error("Cannot parse config file (json format). " + errs);
 
-  Json::CharReaderBuilder builder;
-  JSONCPP_STRING errs;
+    ifs.close();
+  }
+
+  Json::Value &root(void) { return _root; }
 
-  // Failed to parse
-  if (not parseFromStream(builder, ifs, &root, &errs))
-    throw std::runtime_error("Cannot parse config file (json format). " + errs);
+private:
+  Json::Value _root;
+};
 
-  auto layers = root["layers"];
-  std::vector<std::shared_ptr<LayerParam>> p;
+LayerParams read_layer_params(std::string &filename)
+{
+  QConfReader qcr;
+  qcr.init(filename);
+
+  auto layers = qcr.root()["layers"];
+  LayerParams p;
   for (auto layer : layers)
   {
     if (layer.isMember("name"))
@@ -87,6 +103,46 @@ std::vector<std::shared_ptr<LayerParam>> read_layer_params(std::string &filename
   return p;
 }
 
+LayerParamsSet read_layer_params_set(std::string &filename)
+{
+  LayerParamsSet lpss;
+
+  // read default values
+  LayerParams lps = read_layer_params(filename);
+  lpss.emplace_back(lps);
+
+  QConfReader qcr;
+  qcr.init(filename);
+
+  auto layers = qcr.root()["layers"];
+  // alternate names
+  for (const auto &layer : layers)
+  {
+    const std::string key_alt_names = "alternate";
+    if (layer.isMember(key_alt_names))
+    {
+      auto alternate = layer[key_alt_names];
+      for (const auto &altkey : alternate.getMemberNames())
+      {
+        LayerParams lps;
+        for (const auto &altvalue : alternate[altkey])
+        {
+          auto l = std::make_shared<LayerParam>();
+          {
+            l->name = altvalue.asString();
+            l->dtype = layer["dtype"].asString();
+            l->granularity = layer["granularity"].asString();
+          }
+          lps.emplace_back(l);
+        }
+        lpss.emplace_back(lps);
+      }
+    }
+  }
+
+  return lpss;
+}
+
 void print_exclusive_options(void)
 {
   std::cout << "Use only one of the 3 options below." << std::endl;
@@ -95,6 +151,7 @@ void print_exclusive_options(void)
   std::cout << "    --requantize" << std::endl;
   std::cout << "    --force_quantparam" << std::endl;
   std::cout << "    --quantize_weights" << std::endl;
+  std::cout << "    --quantize_onnx_fq_model" << std::endl;
 }
 
 void print_version(void)
@@ -112,6 +169,7 @@ int entry(int argc, char **argv)
 
   const std::string qdqw = "--quantize_dequantize_weights";
   const std::string qwmm = "--quantize_with_minmax";
+  const std::string qofm = "--quantize_onnx_fq_model";
   const std::string rq = "--requantize";
   const std::string fq = "--force_quantparam";
   const std::string cq = "--copy_quantparam";
@@ -123,11 +181,16 @@ int entry(int argc, char **argv)
 
   const std::string gpd = "--generate_profile_data";
 
+  const std::string save_min_max = "--save_min_max";
+
   arser::Arser arser("circle-quantizer provides circle model quantization");
 
   arser::Helper::add_version(arser, print_version);
   arser::Helper::add_verbose(arser);
 
+  arser.add_argument(qofm).nargs(0).default_value(false).help(
+    "Quantize Onnx fake-quantized (with QDQ) model");
+
   arser.add_argument(qdqw)
     .nargs(3)
     .type(arser::DataType::STR_VEC)
@@ -148,6 +211,11 @@ int entry(int argc, char **argv)
     .help("Force MaxPool Op to have the same input/output quantparams. NOTE: This feature can "
           "degrade accuracy of some models");
 
+  arser.add_argument(save_min_max)
+    .nargs(0)
+    .default_value(false)
+    .help("Save recorded min/max values.");
+
   arser.add_argument(fake_quant)
     .nargs(0)
     .help("Convert a quantized model to a fake-quantized model. NOTE: This feature will "
@@ -213,7 +281,7 @@ int entry(int argc, char **argv)
   }
 
   {
-    // only one of qdqw, qwmm, rq, fq, cq, fake_quant, qw option can be used
+    // only one of qdqw, qwmm, rq, fq, cq, fake_quant, qw, qofm option can be used
     int32_t opt_used = arser[qdqw] ? 1 : 0;
     opt_used += arser[qwmm] ? 1 : 0;
     opt_used += arser[rq] ? 1 : 0;
@@ -221,6 +289,7 @@ int entry(int argc, char **argv)
     opt_used += arser[cq] ? 1 : 0;
     opt_used += arser[fake_quant] ? 1 : 0;
     opt_used += arser[qw] ? 1 : 0;
+    opt_used += arser.get<bool>(qofm) ? 1 : 0;
     if (opt_used != 1)
     {
       print_exclusive_options();
@@ -257,6 +326,10 @@ int entry(int argc, char **argv)
         auto layer_params = read_layer_params(filename);
 
         options->layer_params(AlgorithmParameters::Quantize_layer_params, layer_params);
+
+        auto layer_params_set = read_layer_params_set(filename);
+
+        options->layer_params_set(layer_params_set);
       }
       catch (const std::runtime_error &e)
       {
@@ -291,6 +364,9 @@ int entry(int argc, char **argv)
     if (arser[tf_maxpool] and arser.get<bool>(tf_maxpool))
       options->param(AlgorithmParameters::Quantize_TF_style_maxpool, "True");
 
+    if (arser[save_min_max] and arser.get<bool>(save_min_max))
+      options->param(AlgorithmParameters::Quantize_save_min_max, "True");
+
     if (arser[cfg])
     {
       auto filename = arser.get<std::string>(cfg);
@@ -299,6 +375,10 @@ int entry(int argc, char **argv)
         auto layer_params = read_layer_params(filename);
 
         options->layer_params(AlgorithmParameters::Quantize_layer_params, layer_params);
+
+        auto layer_params_set = read_layer_params_set(filename);
+
+        options->layer_params_set(layer_params_set);
       }
       catch (const std::runtime_error &e)
       {
@@ -308,6 +388,13 @@ int entry(int argc, char **argv)
     }
   }
 
+  if (arser.get<bool>(qofm))
+  {
+    options->enable(Algorithms::QuantizeOnnxFakeQuantizedModel);
+
+    options->param(AlgorithmParameters::Quantize_input_model_dtype, "onnx_fake_quant");
+  }
+
   if (arser[rq])
   {
     auto values = arser.get<std::vector<std::string>>(rq);
index ed6ddc4..c65f634 100644 (file)
@@ -1,6 +1,6 @@
-if(NOT TARGET mio_circle06)
+if(NOT TARGET mio_circle08)
   return()
-endif(NOT TARGET mio_circle06)
+endif(NOT TARGET mio_circle08)
 
 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_circle06)
-target_link_libraries(circle-tensordump PRIVATE mio_circle06_helper)
+target_link_libraries(circle-tensordump PRIVATE mio_circle08)
+target_link_libraries(circle-tensordump PRIVATE mio_circle08_helper)
 target_link_libraries(circle-tensordump PRIVATE safemain)
 
 install(TARGETS circle-tensordump DESTINATION bin)
index b3a2638..8a57c8f 100644 (file)
@@ -1,4 +1,4 @@
 require("arser")
 require("foder")
-require("mio-circle06")
+require("mio-circle08")
 require("safemain")
index cdf74cc..3ccdd03 100644 (file)
@@ -1,14 +1,14 @@
-if(NOT TARGET mio_circle06)
-  message(STATUS "Skip circle-verify: mio_circle06 not found")
+if(NOT TARGET mio_circle08)
+  message(STATUS "Skip circle-verify: mio_circle08 not found")
   return()
-endif(NOT TARGET mio_circle06)
+endif(NOT TARGET mio_circle08)
 
 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_circle06)
+target_link_libraries(circle-verify mio_circle08)
 target_link_libraries(circle-verify safemain)
 target_link_libraries(circle-verify cwrap)
 target_link_libraries(circle-verify foder)
index 2fd44ad..d382ef9 100644 (file)
@@ -1,5 +1,5 @@
 require("arser")
-require("mio-circle06")
+require("mio-circle08")
 require("safemain")
 require("cwrap")
 require("foder")
index 2dd24af..4bf6a80 100644 (file)
 
 ## TFLITE RECIPE
 
-Add(Net_Preactivation_BN_000 PASS fuse_preactivation_batchnorm)
+Add(BatchMatMulV2_000 PASS resolve_customop_batchmatmul)
+Add(BroadcastTo_000 PASS resolve_former_customop)
+Add(DepthwiseConv2D_003 PASS)
+Add(FullyConnected_007 PASS replace_non_const_fc_with_batch_matmul)
+Add(FullyConnected_008 PASS replace_non_const_fc_with_batch_matmul)
+Add(HardSwish_001 PASS decompose_hardswish)
+Add(MatMul_000 PASS resolve_customop_matmul)
+Add(MaxPoolWithArgmax_000 PASS resolve_customop_max_pool_with_argmax)
+Add(MaxPoolWithArgmax_001 PASS resolve_customop_max_pool_with_argmax)
+Add(MaxPoolWithArgmax_002 PASS resolve_customop_max_pool_with_argmax)
+Add(Net_Add_FloorMod_Gather_000 PASS remove_gather_guard)
+Add(Net_Add_FullyConnected_000 PASS fuse_add_to_fullyconnected_bias)
+Add(Net_Add_FullyConnected_001 PASS fuse_add_to_fullyconnected_bias)
+Add(Net_Add_FullyConnected_002 PASS fuse_add_to_fullyconnected_bias)
 Add(Net_BroadcastTo_AddV2_000 PASS resolve_customop_add)
 Add(Net_BroadcastTo_AddV2_001 PASS resolve_customop_add)
+Add(Net_BroadcastTo_AddV2_002 PASS resolve_customop_add)
+Add(Net_Conv_Add_000 PASS fuse_add_with_conv)
+Add(Net_Conv_Add_001 PASS fuse_add_with_conv)
+Add(Net_Conv_Add_002 PASS fuse_add_with_conv)
 Add(Net_Conv_Add_Mul_000 PASS fuse_batchnorm_with_conv)
 Add(Net_Conv_Add_Mul_001 PASS fuse_batchnorm_with_conv)
 Add(Net_Conv_Add_Mul_002 PASS fuse_batchnorm_with_conv)
 Add(Net_Conv_FakeQuant_000 PASS remove_fakequant)
-Add(Net_Conv_QuantDequant_000 PASS remove_quantdequant)
 Add(Net_Conv_Min_Max_000 PASS transform_min_max_to_relu6)
 Add(Net_Conv_Min_Relu_000 PASS transform_min_relu_to_relu6)
+Add(Net_Conv_Mul_000 PASS fuse_mul_with_conv)
+Add(Net_Conv_Mul_001 PASS fuse_mul_with_conv)
+Add(Net_Conv_Mul_002 PASS fuse_mul_with_conv)
+Add(Net_Conv_Mul_003 PASS fuse_mul_with_conv)
 Add(Net_Conv_PReluGraph_000 PASS fuse_prelu)
+Add(Net_Conv_QuantDequant_000 PASS remove_quantdequant)
 Add(Net_Conv_Relu6_000 PASS fuse_activation_function)
 Add(Net_Duplicate_Weights_000 PASS remove_duplicate_const)
 Add(Net_DwConv_BN_000 PASS fuse_batchnorm_with_dwconv)
 Add(Net_DwConv_BN_001 PASS fuse_batchnorm_with_dwconv)
+Add(Net_FC_Gelu_FC_000 PASS replace_with_fc_gelu_fc)
 Add(Net_FullyConnected_Add_000 PASS fold_fully_connected)
+Add(Net_Gelu_000 PASS fuse_gelu)
+Add(Net_Gelu_001 PASS fuse_gelu)
+Add(Net_Horizontal_FullyConnected_Add_000 PASS fuse_horizontal_fc_layers)
+Add(Net_InstanceNorm_001 PASS fuse_instnorm)
+Add(Net_InstanceNorm_003 PASS fuse_instnorm)
+Add(Net_InstanceNorm_004 PASS fuse_instnorm)
+Add(Net_InstanceNorm_005 PASS fuse_instnorm)
+Add(Net_InstanceNorm_006 PASS fuse_instnorm)
+Add(Net_InstanceNorm_007 PASS fuse_instnorm)
+Add(Net_Maximum_Minimum_000 PASS transform_min_max_to_relu6)
+Add(Net_Mul_Add_000 PASS remove_unnecessary_add)
+Add(Net_Mul_Add_001 PASS remove_unnecessary_add)
+Add(Net_Mul_Add_002 PASS remove_unnecessary_add)
+Add(Net_Mul_Add_003 PASS remove_unnecessary_add)
+Add(Net_Mul_Div_000 PASS fuse_mul_with_div)
+Add(Net_Mul_Div_001 PASS fuse_mul_with_div)
+Add(Net_Mul_FullyConnected_000 PASS fuse_mul_to_fullyconnected_weights fold_mul)
+Add(Net_Mul_FullyConnected_001 PASS fuse_mul_to_fullyconnected_weights fold_mul)
+Add(Net_Mul_FullyConnected_002 PASS fuse_mul_to_fullyconnected_weights fold_mul)
+Add(Net_Preactivation_BN_000 PASS fuse_preactivation_batchnorm)
 Add(Net_Reshape_Reshape_000 PASS remove_redundant_reshape)
+Add(Net_Shape_Add_000 PASS fold_shape)
+Add(Net_Sqrt_Div_000 PASS transform_sqrt_div_to_rsqrt_mul)
 Add(Net_Squeeze_Squeeze_000 PASS substitute_squeeze_to_reshape)
 Add(Net_TConv_Add_000 PASS fuse_add_with_tconv)
 Add(Net_TConv_Add_001 PASS fuse_add_with_tconv)
@@ -37,26 +81,22 @@ Add(Net_TConv_BN_002 PASS fuse_batchnorm_with_tconv)
 Add(Net_TConv_BN_003 PASS fuse_batchnorm_with_tconv)
 Add(Net_TConv_BN_004 PASS fuse_batchnorm_with_tconv)
 Add(Net_TConv_BN_005 PASS fuse_batchnorm_with_tconv)
-Add(Net_InstanceNorm_001 PASS fuse_instnorm)
-Add(Net_InstanceNorm_003 PASS fuse_instnorm)
-Add(Net_InstanceNorm_004 PASS fuse_instnorm)
-Add(Net_InstanceNorm_005 PASS fuse_instnorm)
-Add(Net_InstanceNorm_006 PASS fuse_instnorm)
-Add(Net_InstanceNorm_007 PASS fuse_instnorm)
-Add(Net_Maximum_Minimum_000 PASS transform_min_max_to_relu6)
-Add(BatchMatMulV2_000 PASS resolve_customop_batchmatmul)
-Add(MatMul_000 PASS resolve_customop_matmul)
-Add(DepthwiseConv2D_003 PASS)
+Add(Net_TConv_Slice_000 PASS fuse_slice_with_tconv)
+Add(Net_TConv_Slice_001 PASS fuse_slice_with_tconv)
+Add(Net_TConv_Slice_002 PASS fuse_slice_with_tconv)
+Add(Net_TConv_Slice_003 PASS fuse_slice_with_tconv)
+Add(Net_Trans_Reshape_Trans_000 PASS remove_unnecessary_transpose)
 Add(PadV2_001 PASS substitute_padv2_to_pad)
+Add(Softmax_001 PASS decompose_softmax)
+Add(Softmax_002 PASS decompose_softmax)
 Add(StridedSlice_003 PASS substitute_strided_slice_to_reshape)
-Add(MaxPoolWithArgmax_000 PASS resolve_customop_max_pool_with_argmax)
-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)
+
+# CSE test
+
+Add(CSE_Quantize_000 PASS common_subexpression_elimination)
+Add(CSE_Quantize_001 PASS common_subexpression_elimination)
+Add(CSE_Transpose_000 PASS common_subexpression_elimination)
+Add(CSE_Transpose_001 PASS common_subexpression_elimination)
 
 ## CIRCLE RECIPE
 
@@ -74,24 +114,24 @@ Add(REGRESS_ONNX_Conv_BN_001 PASS
       remove_unnecessary_reshape
       fuse_batchnorm_with_conv)
 
-Add(REGRESS_ONNX_Conv_BN_Relu6_001 PASS
+Add(REGRESS_ONNX_Conv_BN_MeanMean_001 PASS
       convert_nchw_to_nhwc
       nchw_to_nhwc_input_shape
       nchw_to_nhwc_output_shape
       remove_redundant_transpose
-      transform_min_max_to_relu6
       fuse_batchnorm_with_conv
-      fuse_activation_function)
+      fuse_activation_function
+      fuse_mean_with_mean
+      fuse_transpose_with_mean)
 
-Add(REGRESS_ONNX_Conv_BN_MeanMean_001 PASS
+Add(REGRESS_ONNX_Conv_BN_Relu6_001 PASS
       convert_nchw_to_nhwc
       nchw_to_nhwc_input_shape
       nchw_to_nhwc_output_shape
       remove_redundant_transpose
+      transform_min_max_to_relu6
       fuse_batchnorm_with_conv
-      fuse_activation_function
-      fuse_mean_with_mean
-      fuse_transpose_with_mean)
+      fuse_activation_function)
 
 Add(REGRESS_ONNX_Mul_Mul_000 PASS
       convert_nchw_to_nhwc)
index 6a7be22..757c368 100644 (file)
@@ -81,13 +81,22 @@ int entry(int argc, char **argv)
   add_switch(arser, "--fold_fully_connected",
              "This will fold FullyConnected operator with constant inputs");
   add_switch(arser, "--fold_gather", "This will fold Gather operator");
+  add_switch(arser, "--fold_mul", "This will fold Mul operator");
+  add_switch(arser, "--fold_reshape", "This will fold Reshape operator");
+  add_switch(arser, "--fold_shape", "This will fold Shape operator");
   add_switch(arser, "--fold_sparse_to_dense", "This will fold SparseToDense operator");
+  add_switch(arser, "--fold_squeeze", "This will fold Squeeze operator");
   add_switch(arser, "--forward_reshape_to_unaryop",
              "This will move Reshape after UnaryOp for centain condition");
   add_switch(arser, "--forward_transpose_op",
              "This will move Transpose Op forward if possible (for further optimization)");
   add_switch(arser, "--fuse_activation_function",
              "This will fuse Activation function to a preceding operator");
+  add_switch(arser, "--fuse_horizontal_fc_layers",
+             "This will fuse horizontal FullyConnected layers");
+  add_switch(arser, "--fuse_add_to_fullyconnected_bias",
+             "This will fuse Add to following FullyConnected bias");
+  add_switch(arser, "--fuse_add_with_conv", "This will fuse Add operator to Convolution operator");
   add_switch(arser, "--fuse_add_with_fully_connected",
              "This will fuse Add operator to FullyConnected operator");
   add_switch(arser, "--fuse_add_with_tconv",
@@ -103,6 +112,14 @@ int entry(int argc, char **argv)
   add_switch(arser, "--fuse_mean_with_mean",
              "This will fuse two Mean operations when they follow one by one. This will fold them "
              "into one operation and merge reduction indices.");
+  add_switch(arser, "--fuse_mul_to_fullyconnected_weights",
+             "This will fuse Mul to following FullyConnected weights");
+  add_switch(arser, "--fuse_mul_with_conv",
+             "This will fuse Mul operation with a preceding Conv if possible.");
+  add_switch(arser, "--fuse_mul_with_div",
+             "This will fuse Mul operation with a Div operation whose numerator is const.");
+  add_switch(arser, "--fuse_slice_with_tconv",
+             "This will fuse Slice operation with a preceding TConv if possible.");
   add_switch(arser, "--fuse_transpose_with_mean",
              "This will fuse Mean operation with a preceding Transpose under certain conditions.");
   add_switch(arser, "--make_batchnorm_gamma_positive",
@@ -113,23 +130,35 @@ int entry(int argc, char **argv)
              "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, "--fuse_rsqrt", "This will fuse operators to Rsqrt 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_gather_guard",
+             "This will remove Add/FloorMod guards of Gather indices with certain conditions. "
+             "CAUTION: user must guarantee that indices are all non-negative values.");
+  add_switch(arser, "--remove_qdq_for_mpo",
+             "This will remove QDQ to simulate mixed-precision operator");
   add_switch(arser, "--remove_quantdequant", "This will remove Quantize-Dequantize sequence");
   add_switch(arser, "--remove_redundant_quantize", "This will remove redundant Quantize operators");
   add_switch(arser, "--remove_redundant_reshape",
              "This will fuse or remove subsequent Reshape operators");
   add_switch(arser, "--remove_redundant_transpose",
              "This will fuse or remove subsequent Transpose operators");
+  add_switch(arser, "--remove_unnecessary_add",
+             "This will remove unnecessary add of zero constant");
   add_switch(arser, "--remove_unnecessary_reshape",
              "This will remove unnecessary reshape operators");
   add_switch(arser, "--remove_unnecessary_slice", "This will remove unnecessary slice operators");
   add_switch(arser, "--remove_unnecessary_strided_slice",
              "This will remove unnecessary strided slice operators");
   add_switch(arser, "--remove_unnecessary_split", "This will remove unnecessary split operators");
+  add_switch(arser, "--remove_unnecessary_transpose",
+             "This will remove unnecessary transpose operators");
   add_switch(arser, "--replace_cw_mul_add_with_depthwise_conv",
              "This will replace channel-wise mul/add with DepthwiseConv2D operator");
   add_switch(arser, "--replace_sub_with_add", "This will replace sub with add operator");
+  add_switch(arser, "--replace_with_fc_gelu_fc",
+             "This will replace a specific pattern into FC + Gelu + FC pattern.");
   add_switch(arser, "--resolve_customop_add", "This will convert Custom(Add) to Add operator");
   add_switch(arser, "--resolve_customop_batchmatmul",
              "This will convert Custom(BatchMatmul) to BatchMatmul operator");
@@ -139,6 +168,8 @@ int entry(int argc, char **argv)
              "This will convert Custom(MaxPoolWithArgmax) to equivalent set of operators");
   add_switch(arser, "--resolve_customop_splitv",
              "This will convert Custom(SplitV) to SplitV operator");
+  add_switch(arser, "--resolve_former_customop",
+             "This will convert a former custom op to builtin in from schema version upgrade");
   add_switch(arser, "--shuffle_weight_to_16x1float32",
              "This will convert weight format of FullyConnected to SHUFFLED16x1FLOAT32. Note that "
              "it only converts weights whose row is a multiple of 16");
@@ -169,13 +200,25 @@ 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, "--transform_sqrt_div_to_rsqrt_mul",
+             "Transform Sqrt-Div pattern to Rsqrt-Mul operators");
   add_switch(arser, "--decompose_hardswish",
              "Decompose HardSwish operator to Add, Mul and Relu6 operators");
+  add_switch(arser, "--decompose_softmax",
+             "Decompose Softmax operator into multiple operators for special backends");
+  add_switch(arser, "--common_subexpression_elimination",
+             "Perform common subexpression elimination");
   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.");
 
+  // NOTE Experimental options; these will be removed someday
+  //      Add experimental options here
+  add_switch(arser, "--exp_disable_sep_transposeconv_actfunc",
+             "This will turn off experimental separation of activation function from "
+             "TransposeConv.");
+
   // 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.
@@ -237,16 +280,30 @@ int entry(int argc, char **argv)
     options->enable(Algorithms::FoldFullyConnected);
   if (arser.get<bool>("--fold_gather"))
     options->enable(Algorithms::FoldGather);
+  if (arser.get<bool>("--fold_mul"))
+    options->enable(Algorithms::FoldMul);
+  if (arser.get<bool>("--fold_reshape"))
+    options->enable(Algorithms::FoldReshape);
+  if (arser.get<bool>("--fold_shape"))
+    options->enable(Algorithms::FoldShape);
   if (arser.get<bool>("--fold_sparse_to_dense"))
     options->enable(Algorithms::FoldSparseToDense);
+  if (arser.get<bool>("--fold_squeeze"))
+    options->enable(Algorithms::FoldSqueeze);
   if (arser.get<bool>("--forward_reshape_to_unaryop"))
     options->enable(Algorithms::ForwardReshapeToUnaryOp);
   if (arser.get<bool>("--forward_transpose_op"))
     options->enable(Algorithms::ForwardTransposeOp);
   if (arser.get<bool>("--fuse_activation_function"))
     options->enable(Algorithms::FuseActivationFunction);
+  if (arser.get<bool>("--fuse_horizontal_fc_layers"))
+    options->enable(Algorithms::FuseHorizontalFullyConnected);
   if (arser.get<bool>("--fuse_batchnorm_with_conv"))
     options->enable(Algorithms::FuseBatchNormWithConv);
+  if (arser.get<bool>("--fuse_add_to_fullyconnected_bias"))
+    options->enable(Algorithms::FuseAddToFullyConnectedBias);
+  if (arser.get<bool>("--fuse_add_with_conv"))
+    options->enable(Algorithms::FuseAddWithConv);
   if (arser.get<bool>("--fuse_add_with_fully_connected"))
     options->enable(Algorithms::FuseAddWithFullyConnected);
   if (arser.get<bool>("--fuse_add_with_tconv"))
@@ -255,12 +312,20 @@ int entry(int argc, char **argv)
     options->enable(Algorithms::FuseBatchNormWithDwConv);
   if (arser.get<bool>("--fuse_batchnorm_with_tconv"))
     options->enable(Algorithms::FuseBatchNormWithTConv);
+  if (arser.get<bool>("--fuse_mul_to_fullyconnected_weights"))
+    options->enable(Algorithms::FuseMulToFullyConnectedWeights);
+  if (arser.get<bool>("--fuse_slice_with_tconv"))
+    options->enable(Algorithms::FuseSliceWithTConv);
   if (arser.get<bool>("--fuse_bcq"))
     options->enable(Algorithms::FuseBCQ);
   if (arser.get<bool>("--fuse_instnorm"))
     options->enable(Algorithms::FuseInstanceNorm);
   if (arser.get<bool>("--fuse_mean_with_mean"))
     options->enable(Algorithms::FuseMeanWithMean);
+  if (arser.get<bool>("--fuse_mul_with_conv"))
+    options->enable(Algorithms::FuseMulWithConv);
+  if (arser.get<bool>("--fuse_mul_with_div"))
+    options->enable(Algorithms::FuseMulWithDiv);
   if (arser.get<bool>("--make_batchnorm_gamma_positive"))
     options->enable(Algorithms::MakeBatchNormGammaPositive);
   if (arser.get<bool>("--fuse_preactivation_batchnorm"))
@@ -269,12 +334,18 @@ int entry(int argc, char **argv)
     options->enable(Algorithms::FusePRelu);
   if (arser.get<bool>("--fuse_gelu"))
     options->enable(Algorithms::FuseGelu);
+  if (arser.get<bool>("--fuse_rsqrt"))
+    options->enable(Algorithms::FuseRsqrt);
   if (arser.get<bool>("--fuse_transpose_with_mean"))
     options->enable(Algorithms::FuseTransposeWithMean);
   if (arser.get<bool>("--remove_duplicate_const"))
     options->enable(Algorithms::RemoveDuplicateConst);
   if (arser.get<bool>("--remove_fakequant"))
     options->enable(Algorithms::RemoveFakeQuant);
+  if (arser.get<bool>("--remove_gather_guard"))
+    options->enable(Algorithms::RemoveGatherGuard);
+  if (arser.get<bool>("--remove_qdq_for_mpo"))
+    options->enable(Algorithms::RemoveQDQForMixedPrecisionOp);
   if (arser.get<bool>("--remove_quantdequant"))
     options->enable(Algorithms::RemoveQuantDequantSeq);
   if (arser.get<bool>("--remove_redundant_quantize"))
@@ -283,6 +354,8 @@ int entry(int argc, char **argv)
     options->enable(Algorithms::RemoveRedundantReshape);
   if (arser.get<bool>("--remove_redundant_transpose"))
     options->enable(Algorithms::RemoveRedundantTranspose);
+  if (arser.get<bool>("--remove_unnecessary_add"))
+    options->enable(Algorithms::RemoveUnnecessaryAdd);
   if (arser.get<bool>("--remove_unnecessary_reshape"))
     options->enable(Algorithms::RemoveUnnecessaryReshape);
   if (arser.get<bool>("--remove_unnecessary_slice"))
@@ -291,10 +364,14 @@ int entry(int argc, char **argv)
     options->enable(Algorithms::RemoveUnnecessaryStridedSlice);
   if (arser.get<bool>("--remove_unnecessary_split"))
     options->enable(Algorithms::RemoveUnnecessarySplit);
+  if (arser.get<bool>("--remove_unnecessary_transpose"))
+    options->enable(Algorithms::RemoveUnnecessaryTranspose);
   if (arser.get<bool>("--replace_cw_mul_add_with_depthwise_conv"))
     options->enable(Algorithms::ReplaceMulAddWithDepthwiseConv);
   if (arser.get<bool>("--replace_sub_with_add"))
     options->enable(Algorithms::ReplaceSubWithAdd);
+  if (arser.get<bool>("--replace_with_fc_gelu_fc"))
+    options->enable(Algorithms::ReplaceWithFCGeluFC);
   if (arser.get<bool>("--resolve_customop_add"))
     options->enable(Algorithms::ResolveCustomOpAdd);
   if (arser.get<bool>("--resolve_customop_batchmatmul"))
@@ -305,6 +382,8 @@ int entry(int argc, char **argv)
     options->enable(Algorithms::ResolveCustomOpMaxPoolWithArgmax);
   if (arser.get<bool>("--resolve_customop_splitv"))
     options->enable(Algorithms::ResolveCustomOpSplitV);
+  if (arser.get<bool>("--resolve_former_customop"))
+    options->enable(Algorithms::ResolveFormerCustomOp);
   if (arser.get<bool>("--shuffle_weight_to_16x1float32"))
     options->enable(Algorithms::ShuffleWeightTo16x1Float32);
   if (arser.get<bool>("--replace_non_const_fc_with_batch_matmul"))
@@ -325,13 +404,27 @@ 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>("--transform_sqrt_div_to_rsqrt_mul"))
+    options->enable(Algorithms::TransformSqrtDivToRsqrtMul);
+  if (arser.get<bool>("--common_subexpression_elimination"))
+    options->enable(Algorithms::CommonSubExpressionElimination);
   if (arser.get<bool>("--decompose_hardswish"))
     options->enable(Algorithms::DecomposeHardSwishPass);
+  if (arser.get<bool>("--decompose_softmax"))
+    options->enable(Algorithms::DecomposeSoftmaxPass);
   if (arser.get<bool>("--expand_broadcast_const"))
     options->enable(Algorithms::ExpandBroadcastConst);
   if (arser.get<bool>("--unroll_unidirseqlstm"))
     options->enable(Algorithms::UnrollUnidirSeqLSTM);
 
+  // NOTE Experimental options; these will be removed someday
+  //      Add experimental options here
+  // NOTE XpSepActFromTransposeConv is enabled for default
+  //      exp_disable_sep_act_transposeconv is to turn it off
+  //      which will leave TransposeConv with fused activation
+  if (!arser.get<bool>("--exp_disable_sep_transposeconv_actfunc"))
+    options->enable(Algorithms::XpSepActFromTransposeConv);
+
   if (arser.get<bool>("--mute_warnings"))
     settings->set(luci::UserSettings::Key::MuteWarnings, true);
   if (arser.get<bool>("--disable_validation"))
index 56c501c..18b58a9 100644 (file)
@@ -5,10 +5,10 @@ if(NOT Protobuf_FOUND)
   return()
 endif(NOT Protobuf_FOUND)
 
-if(NOT TARGET mio_circle06)
-  message(STATUS "circlechef: SKIP (missing mio-circle06)")
+if(NOT TARGET mio_circle08)
+  message(STATUS "circlechef: SKIP (missing mio-circle08)")
   return()
-endif(NOT TARGET mio_circle06)
+endif(NOT TARGET mio_circle08)
 
 # Recipe Parser
 add_subdirectory(proto)
index cdd6040..e50d4a6 100644 (file)
@@ -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_circle06)
-target_link_libraries(circlechef_circle mio_circle06_helper)
+target_link_libraries(circlechef_circle mio_circle08)
+target_link_libraries(circlechef_circle mio_circle08_helper)
 target_link_libraries(circlechef_circle cwrap)
 target_link_libraries(circlechef_circle souschef)
index f8756ef..f983d3e 100644 (file)
@@ -44,7 +44,7 @@ bool CircleImport::select_sub_graph(uint32_t sgindex)
   _inputs.clear();
   _outputs.clear();
 
-  if (_subgraphs->Length() <= sgindex)
+  if (_subgraphs->size() <= sgindex)
   {
     assert(false);
     return false;
index 9c1d161..69453fd 100644 (file)
@@ -54,7 +54,7 @@ public:
   const std::vector<int32_t> &inputs() const { return _inputs; }
   const std::vector<int32_t> &outputs() const { return _outputs; }
 
-  uint32_t num_subgraph() const { return _subgraphs->Length(); }
+  uint32_t num_subgraph() const { return _subgraphs->size(); }
 
   circle::BuiltinOperator builtin_code(const circle::Operator *op) const;
   std::string opcode_name(const circle::Operator *op) const;
index 6a0ce5d..cf8f658 100644 (file)
@@ -21,6 +21,7 @@
 #include "Op/BatchMatMul.h"
 #include "Op/BCQFullyConnected.h"
 #include "Op/BCQGather.h"
+#include "Op/GRU.h"
 #include "Op/InstanceNorm.h"
 
 #endif // __CIRCLE_OP_CHEFS_H__
index 2bf1e19..a018784 100644 (file)
@@ -58,6 +58,7 @@ private:
     REG_TFL_OP(BATCH_MATMUL, CircleOpBatchMatMul);
     REG_TFL_OP(BCQ_FULLY_CONNECTED, CircleOpBCQFullyConnected);
     REG_TFL_OP(BCQ_GATHER, CircleOpBCQGather);
+    REG_TFL_OP(GRU, CircleOpGRU);
     REG_TFL_OP(INSTANCE_NORM, CircleOpInstanceNorm);
 #undef REG_TFL_OP
   }
index 248687f..8f11e00 100644 (file)
@@ -31,10 +31,14 @@ circlechef::TensorType as_circlechef_type(const circle::TensorType type)
       return circlechef::INT64;
     case circle::TensorType_UINT8:
       return circlechef::UINT8;
+    case circle::TensorType_UINT4:
+      return circlechef::UINT4;
     case circle::TensorType_BOOL:
       return circlechef::BOOL;
     case circle::TensorType_INT16:
       return circlechef::INT16;
+    case circle::TensorType_INT4:
+      return circlechef::INT4;
     // TODO handle other types
     // TensorType_FLOAT16
     // TensorType_STRING
index 7842c4b..050c24b 100644 (file)
@@ -45,8 +45,8 @@ template <typename T> std::vector<T> as_index_vector(const flatbuffers::Vector<T
   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++)
+  std::vector<T> ret(flat_array->size());
+  for (uint32_t i = 0; i < flat_array->size(); i++)
   {
     ret[i] = flat_array->Get(i);
   }
diff --git a/compiler/circlechef/circle/src/Op/GRU.cpp b/compiler/circlechef/circle/src/Op/GRU.cpp
new file mode 100644 (file)
index 0000000..a45daf2
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GRU.h"
+
+#include "Convert.h"
+
+namespace circlechef
+{
+
+void CircleOpGRU::filler(const circle::Operator *op, CircleImport *import,
+                         circlechef::ModelRecipe *model_recipe) const
+{
+  // index 1, 2, 3, 4, 5 maybe constant
+  const std::vector<int32_t> &inputs = as_index_vector(op->inputs());
+  assert(inputs.size() == 6);
+
+  import->set_tensor_filler(inputs[1]); // set gaussian filler
+  import->set_tensor_filler(inputs[2]);
+  import->set_tensor_filler(inputs[3]);
+  import->set_tensor_filler(inputs[4]);
+  import->set_tensor_filler(inputs[5]);
+}
+
+circlechef::Operation *CircleOpGRU::build(const circle::Operator *op, CircleImport *import,
+                                          circlechef::ModelRecipe *model_recipe) const
+{
+  auto op_params = op->builtin_options_as_GRUOptions();
+  assert(op_params != nullptr);
+
+  auto operation = model_recipe->add_operation();
+
+  operation->set_type("GRU");
+
+  auto op_options = operation->mutable_gru_options();
+
+  op_options->set_activation(as_circlechef_activation(op_params->fused_activation_function()));
+  op_options->set_return_sequences(op_params->return_sequences());
+  op_options->set_time_major(op_params->time_major());
+
+  return operation;
+}
+
+} // namespace circlechef
diff --git a/compiler/circlechef/circle/src/Op/GRU.h b/compiler/circlechef/circle/src/Op/GRU.h
new file mode 100644 (file)
index 0000000..bfd8671
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CIRCLE_OP_CIRCLE_GRU_H__
+#define __CIRCLE_OP_CIRCLE_GRU_H__
+
+#include "CircleOpChef.h"
+
+namespace circlechef
+{
+
+/**
+ * @brief circlechef operator builder for GRU
+ */
+class CircleOpGRU : public CircleOpChef
+{
+public:
+  void filler(const circle::Operator *op, CircleImport *import,
+              circlechef::ModelRecipe *model_recipe) const override;
+  circlechef::Operation *build(const circle::Operator *op, CircleImport *import,
+                               circlechef::ModelRecipe *model_recipe) const override;
+};
+
+} // namespace circlechef
+
+#endif // __CIRCLE_OP_CIRCLE_GRU_H__
index e21bca8..645a714 100644 (file)
@@ -82,7 +82,7 @@ std::unique_ptr<ModelRecipe> generate_recipe(const circle::Model *model)
   auto operators = circle_import.operators();
 
   // operand fillers for adding all operators
-  for (uint32_t i = 0; i < operators->Length(); ++i)
+  for (uint32_t i = 0; i < operators->size(); ++i)
   {
     const auto *op = operators->Get(i);
     circle::BuiltinOperator builtincode = circle_import.builtin_code(op);
@@ -99,7 +99,7 @@ std::unique_ptr<ModelRecipe> generate_recipe(const circle::Model *model)
   }
 
   // add all operands(tensors)
-  for (uint32_t i = 0; i < tensors->Length(); ++i)
+  for (uint32_t i = 0; i < tensors->size(); ++i)
   {
     auto tensor = tensors->Get(i);
 
@@ -198,7 +198,7 @@ std::unique_ptr<ModelRecipe> generate_recipe(const circle::Model *model)
   }
 
   // add all operators
-  for (uint32_t i = 0; i < operators->Length(); ++i)
+  for (uint32_t i = 0; i < operators->size(); ++i)
   {
     const auto *op = operators->Get(i);
     circle::BuiltinOperator builtincode = circle_import.builtin_code(op);
index dc1dbc4..073abbd 100644 (file)
@@ -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_circle06)
+target_link_libraries(circlechef_core PUBLIC mio_circle08)
 target_link_libraries(circlechef_core PUBLIC souschef)
 target_link_libraries(circlechef_core PRIVATE nncc_coverage)
 
index 6066324..d2c70de 100644 (file)
@@ -56,18 +56,22 @@ circle::TensorType as_circle_tensortype(const circlechef::TensorType &value)
   {
     case circlechef::FLOAT32:
       return circle::TensorType_FLOAT32;
+    case circlechef::INT64:
+      return circle::TensorType_INT64;
     case circlechef::INT32:
       return circle::TensorType_INT32;
+    case circlechef::INT16:
+      return circle::TensorType_INT16;
+    case circlechef::INT4:
+      return circle::TensorType_INT4;
     case circlechef::UINT8:
       return circle::TensorType_UINT8;
-    case circlechef::INT64:
-      return circle::TensorType_INT64;
+    case circlechef::UINT4:
+      return circle::TensorType_UINT4;
     case circlechef::STRING:
       return circle::TensorType_STRING;
     case circlechef::BOOL:
       return circle::TensorType_BOOL;
-    case circlechef::INT16:
-      return circle::TensorType_INT16;
     default:
       break;
   }
index b17f5df..8946b6e 100644 (file)
@@ -44,11 +44,13 @@ TEST(ConvertTest, as_circle_activation_NEG)
 TEST(ConvertTest, as_circle_tensortype)
 {
   ASSERT_EQ(circle::TensorType_FLOAT32, as_circle_tensortype(circlechef::FLOAT32));
+  ASSERT_EQ(circle::TensorType_INT64, as_circle_tensortype(circlechef::INT64));
   ASSERT_EQ(circle::TensorType_INT32, as_circle_tensortype(circlechef::INT32));
+  ASSERT_EQ(circle::TensorType_INT16, as_circle_tensortype(circlechef::INT16));
+  ASSERT_EQ(circle::TensorType_INT4, as_circle_tensortype(circlechef::INT4));
   ASSERT_EQ(circle::TensorType_UINT8, as_circle_tensortype(circlechef::UINT8));
-  ASSERT_EQ(circle::TensorType_INT64, as_circle_tensortype(circlechef::INT64));
+  ASSERT_EQ(circle::TensorType_UINT4, as_circle_tensortype(circlechef::UINT4));
   ASSERT_EQ(circle::TensorType_BOOL, as_circle_tensortype(circlechef::BOOL));
-  ASSERT_EQ(circle::TensorType_INT16, as_circle_tensortype(circlechef::INT16));
 }
 
 TEST(ConvertTest, as_circle_tensortype_NEG)
index c634c04..ae3a074 100644 (file)
@@ -5,19 +5,26 @@
 // DATA_CHEF(TYPE, NAME, FACTORY_CLASS)
 //  "TYPE" SHOULD BE an enum tag of tflchef::TensorType
 DATA_CHEF(FLOAT32, constant, ConstantDataChefFactory<float>)
-DATA_CHEF(BOOL, constant, ConstantDataChefFactory<bool>)
-DATA_CHEF(UINT8, constant, ConstantDataChefFactory<uint8_t>)
-DATA_CHEF(INT16, constant, ConstantDataChefFactory<int16_t>)
-DATA_CHEF(INT32, constant, ConstantDataChefFactory<int32_t>)
 DATA_CHEF(INT64, constant, ConstantDataChefFactory<int64_t>)
+DATA_CHEF(INT32, constant, ConstantDataChefFactory<int32_t>)
+DATA_CHEF(INT16, constant, ConstantDataChefFactory<int16_t>)
+DATA_CHEF(INT4, constant, ConstantInt4DataChefFactory)
+DATA_CHEF(UINT8, constant, ConstantDataChefFactory<uint8_t>)
+DATA_CHEF(UINT4, constant, ConstantUint4DataChefFactory)
+DATA_CHEF(BOOL, constant, ConstantDataChefFactory<bool>)
+
+DATA_CHEF(FLOAT32, explicit, ExplicitDataChefFactory<float>)
 DATA_CHEF(INT64, explicit, ExplicitDataChefFactory<int64_t>)
 DATA_CHEF(INT32, explicit, ExplicitDataChefFactory<int32_t>)
 DATA_CHEF(INT16, explicit, ExplicitDataChefFactory<int16_t>)
+DATA_CHEF(INT4, explicit, ExplicitInt4DataChefFactory)
 DATA_CHEF(UINT8, explicit, ExplicitDataChefFactory<uint8_t>)
-DATA_CHEF(BOOL, explicit, ExplicitDataChefFactory<bool>)
-DATA_CHEF(FLOAT32, explicit, ExplicitDataChefFactory<float>)
+DATA_CHEF(UINT4, explicit, ExplicitUint4DataChefFactory)
 DATA_CHEF(STRING, explicit, ExplicitDataChefFactory<std::string>)
+DATA_CHEF(BOOL, explicit, ExplicitDataChefFactory<bool>)
+
 DATA_CHEF(FLOAT32, gaussian, GaussianFloat32DataChefFactory)
 DATA_CHEF(INT32, gaussian, GaussianInt32DataChefFactory)
 DATA_CHEF(INT16, gaussian, GaussianInt16DataChefFactory)
 DATA_CHEF(UINT8, gaussian, GaussianUint8DataChefFactory)
+
index 6c5206d..62f6c8c 100644 (file)
@@ -89,9 +89,11 @@ DataChefRegistry &data_chef_registry(const circlechef::TensorType &type)
   static DataChefRegistry s64;
   static DataChefRegistry fp32;
   static DataChefRegistry u8;
+  static DataChefRegistry u4;
   static DataChefRegistry string;
   static DataChefRegistry boolean;
   static DataChefRegistry s16;
+  static DataChefRegistry s4;
 
   switch (type)
   {
@@ -103,12 +105,16 @@ DataChefRegistry &data_chef_registry(const circlechef::TensorType &type)
       return fp32;
     case circlechef::UINT8:
       return u8;
+    case circlechef::UINT4:
+      return u4;
     case circlechef::STRING:
       return string;
     case circlechef::BOOL:
       return boolean;
     case circlechef::INT16:
       return s16;
+    case circlechef::INT4:
+      return s4;
     default:
       break;
   }
@@ -135,10 +141,10 @@ gather_builtincode_map(const ::circlechef::ModelRecipe &model_recipe)
 
   for (const auto &operation : model_recipe.operation())
   {
-    auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
-    if (op_chef->code() == circle::BuiltinOperator_CUSTOM)
+    if (operation.type() == "Custom")
       continue;
 
+    auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
     // Various operation version is unified as the highest version among them
     if (builtin_map.find(op_chef->code()) == builtin_map.end() ||
         builtin_map[op_chef->code()] < operation.version())
@@ -151,10 +157,10 @@ gather_builtincode_map(const ::circlechef::ModelRecipe &model_recipe)
     const auto &graph = model_recipe.graph(g);
     for (const auto &operation : graph.operation())
     {
-      auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
-      if (op_chef->code() == circle::BuiltinOperator_CUSTOM)
+      if (operation.type() == "Custom")
         continue;
 
+      auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
       // Various operation version is unified as the highest version among them
       if (builtin_map.find(op_chef->code()) == builtin_map.end() ||
           builtin_map[op_chef->code()] < operation.version())
@@ -171,9 +177,11 @@ std::set<std::string> gather_customcode_set(const ::circlechef::ModelRecipe &mod
   std::set<std::string> customcode_set;
   for (const auto &operation : model_recipe.operation())
   {
-    auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
-    if (op_chef->code() == circle::BuiltinOperator_CUSTOM)
-      customcode_set.insert(operation.type());
+    if (operation.type() == "Custom")
+    {
+      assert(not operation.custom_code().empty());
+      customcode_set.insert(operation.custom_code());
+    }
   }
 
   // Add ops used in Graphs(subgraphs)
@@ -182,9 +190,11 @@ std::set<std::string> gather_customcode_set(const ::circlechef::ModelRecipe &mod
     const auto &graph = model_recipe.graph(g);
     for (const auto &operation : graph.operation())
     {
-      auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
-      if (op_chef->code() == circle::BuiltinOperator_CUSTOM)
-        customcode_set.insert(operation.type());
+      if (operation.type() == "Custom")
+      {
+        assert(not operation.custom_code().empty());
+        customcode_set.insert(operation.custom_code());
+      }
     }
   }
 
@@ -296,6 +306,34 @@ template <typename T> void cook_graph(const T &graph, CookParams &cp)
       // Create Data
       int32_t count = (element_count(dims) > 0) ? element_count(dims) : filler.arg_size();
       auto data_vec = chef->generate(count);
+      // pack for INT4 and replace data_vec
+      if (operand.type() == circlechef::TensorType::INT4)
+      {
+        uint32_t packed = (count + 1) / 2;
+        std::vector<uint8_t> data_packed(packed);
+        for (uint32_t idx = 0; idx < packed; ++idx)
+        {
+          uint32_t sidx = idx * 2;
+          data_packed[idx] = data_vec[sidx++] & 0x0f;
+          if (sidx < count)
+            data_packed[idx] |= data_vec[sidx] << 4;
+        }
+        data_vec = data_packed;
+      }
+      // pack for UINT4 and replace data_vec
+      else if (operand.type() == circlechef::TensorType::UINT4)
+      {
+        uint32_t packed = (count + 1) / 2;
+        std::vector<uint8_t> data_packed(packed);
+        for (uint32_t idx = 0; idx < packed; ++idx)
+        {
+          uint32_t sidx = idx * 2;
+          data_packed[idx] = data_vec[sidx++] & 0x0f;
+          if (sidx < count)
+            data_packed[idx] |= data_vec[sidx] << 4;
+        }
+        data_vec = data_packed;
+      }
       auto data = flatbuffer_builder->CreateVector(data_vec);
 
       // Create Buffer
@@ -418,7 +456,11 @@ template <typename T> void cook_graph(const T &graph, CookParams &cp)
   {
     assert(operation.has_type());
 
-    auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
+    std::string op_type = operation.type();
+    if (not operation.custom_code().empty())
+      op_type = operation.custom_code();
+
+    auto op_chef = op_chef_registry().lookup(op_type).create(&operation);
 
     // Create 'inputs'
     std::vector<int32_t> input_vec = as_dataset(operation.input()).map(lookup).vectorize();
diff --git a/compiler/circlechef/core/src/Op/FullyConnected.cpp b/compiler/circlechef/core/src/Op/FullyConnected.cpp
new file mode 100644 (file)
index 0000000..cb567b9
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "FullyConnected.h"
+#include "Convert.h"
+
+#include <cassert>
+
+flatbuffers::Offset<void> FullyConnectedChef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+  auto &operation = (*_operation);
+
+  assert(operation.has_fullyconnected_options());
+
+  auto circle_activation = as_circle_activation(operation.fullyconnected_options().activation());
+
+  circle::FullyConnectedOptionsBuilder fc_options_builder{fbb};
+  fc_options_builder.add_fused_activation_function(circle_activation);
+  fc_options_builder.add_keep_num_dims(operation.fullyconnected_options().keep_num_dims());
+
+  return fc_options_builder.Finish().Union();
+}
+
+std::unique_ptr<OpChef>
+FullyConnectedChefFactory::create(const circlechef::Operation *operation) const
+{
+  return std::unique_ptr<OpChef>{new FullyConnectedChef{operation}};
+}
diff --git a/compiler/circlechef/core/src/Op/FullyConnected.h b/compiler/circlechef/core/src/Op/FullyConnected.h
new file mode 100644 (file)
index 0000000..56c74bb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_FULLYCONNECTED_H__
+#define __OP_FULLYCONNECTED_H__
+
+#include "OpChef.h"
+
+class FullyConnectedChef final : public OpChef
+{
+public:
+  explicit FullyConnectedChef(const circlechef::Operation *operation) : _operation{operation}
+  {
+    // DO NOTHING
+  }
+
+public:
+  circle::BuiltinOperator code(void) const override
+  {
+    return circle::BuiltinOperator_FULLY_CONNECTED;
+  }
+
+  circle::BuiltinOptions type(void) const override
+  {
+    return circle::BuiltinOptions_FullyConnectedOptions;
+  }
+
+  flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+  const circlechef::Operation *_operation;
+};
+
+struct FullyConnectedChefFactory final : public OpChefFactory
+{
+  std::unique_ptr<OpChef> create(const circlechef::Operation *operation) const override;
+};
+
+#endif // __OP_FULLYCONNECTED_H__
diff --git a/compiler/circlechef/core/src/Op/GRU.cpp b/compiler/circlechef/core/src/Op/GRU.cpp
new file mode 100644 (file)
index 0000000..c32e9d2
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GRU.h"
+
+#include "Convert.h"
+
+flatbuffers::Offset<void> GRUChef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+  auto &operation = (*_operation);
+
+  assert(operation.has_gru_options());
+  auto circle_activation = as_circle_activation(operation.gru_options().activation());
+  auto return_sequences = operation.gru_options().return_sequences();
+  auto time_major = operation.gru_options().time_major();
+
+  circle::GRUOptionsBuilder options_builder{fbb};
+  options_builder.add_fused_activation_function(circle_activation);
+  options_builder.add_return_sequences(return_sequences);
+  options_builder.add_time_major(time_major);
+
+  return options_builder.Finish().Union();
+}
+
+std::unique_ptr<OpChef> GRUChefFactory::create(const circlechef::Operation *operation) const
+{
+  return std::unique_ptr<OpChef>{new GRUChef{operation}};
+}
diff --git a/compiler/circlechef/core/src/Op/GRU.h b/compiler/circlechef/core/src/Op/GRU.h
new file mode 100644 (file)
index 0000000..0215cb7
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CIRCLE_GRU_H__
+#define __OP_CIRCLE_GRU_H__
+
+#include "OpChef.h"
+
+class GRUChef final : public OpChef
+{
+public:
+  explicit GRUChef(const circlechef::Operation *operation) : _operation{operation}
+  {
+    // DO NOTHING
+  }
+
+public:
+  circle::BuiltinOperator code(void) const override { return circle::BuiltinOperator_GRU; }
+
+  circle::BuiltinOptions type(void) const override { return circle::BuiltinOptions_GRUOptions; }
+
+  flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+  const circlechef::Operation *_operation;
+};
+
+struct GRUChefFactory final : public OpChefFactory
+{
+  std::unique_ptr<OpChef> create(const circlechef::Operation *operation) const override;
+};
+
+#endif // __OP_CIRCLE_GRU_H__
index 3128d3b..6084f6c 100644 (file)
@@ -7,4 +7,6 @@
 OP_CHEF(BatchMatMul, BatchMatMulChefFactory)
 OP_CHEF(BCQFullyConnected, BCQFullyConnectedChefFactory)
 OP_CHEF(BCQGather, BCQGatherChefFactory)
+OP_CHEF(FullyConnected, FullyConnectedChefFactory)
+OP_CHEF(GRU, GRUChefFactory)
 OP_CHEF(InstanceNorm, InstanceNormChefFactory)
index e13c5e0..10fb30c 100644 (file)
@@ -20,6 +20,8 @@
 #include "Op/BatchMatMul.h"
 #include "Op/BCQFullyConnected.h"
 #include "Op/BCQGather.h"
+#include "Op/FullyConnected.h"
+#include "Op/GRU.h"
 #include "Op/InstanceNorm.h"
 
 #endif // __OP_CHEFS_H__
index d5e0857..234d746 100644 (file)
@@ -14,6 +14,7 @@ package circlechef;
 
 // This enum value corresponds to TensorType in TensorFlow Lite schema
 enum TensorType {
+  UINT4 = -1;
   FLOAT32 = 0;
   INT32 = 2;
   UINT8 = 3;
@@ -21,6 +22,7 @@ enum TensorType {
   STRING = 5;
   BOOL = 6;
   INT16 = 7;
+  INT4 = 17;
 }
 
 message TensorShape {
@@ -76,6 +78,17 @@ message InstanceNormOptions {
   optional Activation activation = 2 [default = NONE];
 }
 
+message FullyConnectedOptions {
+  optional Activation activation = 1 [default = NONE];
+  optional bool keep_num_dims = 2 [ default = false ];
+}
+
+message GRUOptions {
+  optional Activation activation = 1 [default = NONE];
+  optional bool return_sequences = 2 [default = false];
+  optional bool time_major = 3 [default = false];
+}
+
 message BCQFullyConnectedOptions {
   optional int32 weights_hidden_size = 1 [default = 0];
   optional Activation activation = 2 [default = NONE];
@@ -91,11 +104,14 @@ message Operation {
   repeated string input = 2;
   repeated string output = 3;
   optional int32 version = 4 [default = 1];
+  optional string custom_code = 5;
 
   optional BatchMatMulOptions batch_matmul_options = 100;
   optional InstanceNormOptions instance_norm_options = 101;
   optional BCQFullyConnectedOptions bcq_fully_connected_options = 102;
   optional BCQGatherOptions bcq_gather_options = 103;
+  optional GRUOptions gru_options = 104;
+  optional FullyConnectedOptions fullyconnected_options = 105;
 }
 
 // For additional subgraphs
index 67eaa27..77bfddc 100644 (file)
@@ -1,7 +1,6 @@
 require("arser")
-require("nnkit")
 require("cwrap")
-require("mio-circle06")
+require("mio-circle08")
 require("safemain")
 require("hermes")
 require("hermes-std")
diff --git a/compiler/circlechef/tests/int4_datatype/test.recipe b/compiler/circlechef/tests/int4_datatype/test.recipe
new file mode 100644 (file)
index 0000000..6bc50b0
--- /dev/null
@@ -0,0 +1,34 @@
+operand {
+  name: "ifm1"
+  type: INT4
+  shape { dim: 1 dim: 4 dim: 4 dim: 1 }
+}
+operand {
+  name: "constant"
+  type: INT4
+  shape { dim: 1 dim: 4 dim: 4 dim: 1 }
+  filler {
+    tag: "explicit"
+    arg: "-8" arg: "-7"  arg: "-6"  arg: "-5"
+    arg: "-4"  arg: "-3"  arg: "-2"  arg: "-1"
+    arg: "0"  arg: "1" arg: "2" arg: "3"
+    arg: "4"  arg: "5" arg: "6" arg: "7"
+  }
+}
+operand {
+  name: "ofm"
+  type: INT4
+  shape { dim: 1 dim: 4 dim: 4 dim: 1 }
+}
+operation {
+  type: "BatchMatMul"
+  input: "ifm1"
+  input: "constant"
+  output: "ofm"
+  batch_matmul_options {
+    adjoint_lhs: false
+    adjoint_rhs: false
+  }
+}
+input: "ifm1"
+output: "ofm"
diff --git a/compiler/circlechef/tests/uint4_datatype/test.recipe b/compiler/circlechef/tests/uint4_datatype/test.recipe
new file mode 100644 (file)
index 0000000..ce7e872
--- /dev/null
@@ -0,0 +1,34 @@
+operand {
+  name: "ifm1"
+  type: UINT4
+  shape { dim: 1 dim: 4 dim: 4 dim: 1 }
+}
+operand {
+  name: "constant"
+  type: UINT4
+  shape { dim: 1 dim: 4 dim: 4 dim: 1 }
+  filler {
+    tag: "explicit"
+    arg: "0" arg: "1"  arg: "2"  arg: "3"
+    arg: "4"  arg: "5"  arg: "6"  arg: "7"
+    arg: "8"  arg: "9" arg: "10" arg: "11"
+    arg: "12"  arg: "13" arg: "14" arg: "15"
+  }
+}
+operand {
+  name: "ofm"
+  type: UINT4
+  shape { dim: 1 dim: 4 dim: 4 dim: 1 }
+}
+operation {
+  type: "BatchMatMul"
+  input: "ifm1"
+  input: "constant"
+  output: "ofm"
+  batch_matmul_options {
+    adjoint_lhs: false
+    adjoint_rhs: false
+  }
+}
+input: "ifm1"
+output: "ofm"
index b732673..9945ba0 100644 (file)
@@ -1,7 +1,7 @@
-if(NOT TARGET mio_circle06)
-  message(STATUS "Skip circledump: mio_circle06 not found")
+if(NOT TARGET mio_circle08)
+  message(STATUS "Skip circledump: mio_circle08 not found")
   return()
-endif(NOT TARGET mio_circle06)
+endif(NOT TARGET mio_circle08)
 
 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_circle06)
-target_link_libraries(circledump mio_circle06_helper)
+target_link_libraries(circledump mio_circle08)
+target_link_libraries(circledump mio_circle08_helper)
 target_link_libraries(circledump safemain)
 
 install(TARGETS circledump DESTINATION bin)
index f71194b..9fa2653 100644 (file)
@@ -65,6 +65,6 @@ O T(3) ofm
 
 ### Dependency
 
-- mio-circle06
+- mio-circle08
 - safemain
 - FlatBuffers
index b3a2638..8a57c8f 100644 (file)
@@ -1,4 +1,4 @@
 require("arser")
 require("foder")
-require("mio-circle06")
+require("mio-circle08")
 require("safemain")
index 69427a2..1669316 100644 (file)
@@ -126,24 +126,11 @@ void dump_sub_graph(std::ostream &os, mio::circle::Reader &reader)
 {
   auto tensors = reader.tensors();
   auto operators = reader.operators();
-  auto data_format = reader.data_format();
-
-  // dump data_format
-  os << "Data Format:" << std::endl;
-  if (data_format == circle::DataFormat::DataFormat_CHANNELS_LAST)
-  {
-    os << "CHANNEL_LAST (NHWC for 2d, NDHWC for 3d data)" << std::endl;
-  }
-  else if (data_format == circle::DataFormat::DataFormat_CHANNELS_FIRST)
-  {
-    os << "CHANNEL_FIRST (NCHW for 2d, NCDHW for 3d data)" << std::endl;
-  }
-  os << std::endl;
 
   // dump operands(tensors)
   os << "Operands: T(subgraph index : tensor index) TYPE (shape) (shape_signature) "
      << "B(buffer index) (variable) OperandName" << std::endl;
-  for (uint32_t i = 0; i < tensors->Length(); ++i)
+  for (uint32_t i = 0; i < tensors->size(); ++i)
   {
     // TODO refactor to some better structure
     auto tensor = tensors->Get(i);
@@ -294,7 +281,7 @@ void dump_sub_graph(std::ostream &os, mio::circle::Reader &reader)
   os << "    Option(values) ... <-- depending on OpCode" << std::endl;
   os << "    I T(tensor index) OperandName <-- as input" << std::endl;
   os << "    O T(tensor index) OperandName <-- as output" << std::endl;
-  for (uint32_t i = 0; i < operators->Length(); ++i)
+  for (uint32_t i = 0; i < operators->size(); ++i)
   {
     const auto op = operators->Get(i);
     circle::BuiltinOperator builtincode = reader.builtin_code(op);
@@ -392,7 +379,7 @@ void dump_model(std::ostream &os, const circle::Model *model)
 
   // dump buffer
   os << "Buffers: B(index) (length) values, if any" << std::endl;
-  for (uint32_t i = 0; i < buffers->Length(); ++i)
+  for (uint32_t i = 0; i < buffers->size(); ++i)
   {
     const uint8_t *buff_data;
     size_t size = reader.buffer_info(i, &buff_data);
@@ -410,7 +397,7 @@ void dump_model(std::ostream &os, const circle::Model *model)
   if (metadata != nullptr)
   {
     os << "metadata : B(index) name" << std::endl;
-    for (uint32_t i = 0; i < metadata->Length(); ++i)
+    for (uint32_t i = 0; i < metadata->size(); ++i)
     {
       const auto buff_id = metadata->Get(i)->buffer();
       const auto metadata_name = metadata->Get(i)->name()->str();
@@ -430,14 +417,14 @@ void dump_model(std::ostream &os, const circle::Model *model)
   if (signaturedefs != nullptr)
   {
     os << "SignatureDef" << std::endl;
-    for (uint32_t i = 0; i < signaturedefs->Length(); ++i)
+    for (uint32_t i = 0; i < signaturedefs->size(); ++i)
     {
       auto sign_i = signaturedefs->Get(i);
       os << "S(" << i << ") signature_key(" << sign_i->signature_key()->c_str() << "), sub_graph("
          << sign_i->subgraph_index() << ")" << std::endl;
 
       auto inputs_i = sign_i->inputs();
-      for (uint32_t t = 0; t < inputs_i->Length(); ++t)
+      for (uint32_t t = 0; t < inputs_i->size(); ++t)
       {
         auto inputs_i_t = inputs_i->Get(t);
         os << "    I(" << t << ")"
@@ -446,7 +433,7 @@ void dump_model(std::ostream &os, const circle::Model *model)
       }
 
       auto outputs_i = sign_i->outputs();
-      for (uint32_t t = 0; t < outputs_i->Length(); ++t)
+      for (uint32_t t = 0; t < outputs_i->size(); ++t)
       {
         auto outputs_i_t = outputs_i->Get(t);
         os << "    O(" << t << ")"
index bfcb1ec..61a0941 100644 (file)
@@ -135,7 +135,7 @@ public:
     if (auto conv_params = op->builtin_options_as_Conv2DOptions())
     {
       os << "    ";
-      os << "Padding(" << conv_params->padding() << ") ";
+      os << "Padding(" << EnumNamePadding(conv_params->padding()) << ") ";
       os << "Stride.W(" << conv_params->stride_w() << ") ";
       os << "Stride.H(" << conv_params->stride_h() << ") ";
       os << "Dilation.W(" << conv_params->dilation_w_factor() << ") ";
@@ -184,7 +184,7 @@ public:
     if (auto pool_params = op->builtin_options_as_Pool2DOptions())
     {
       os << "    ";
-      os << "Padding(" << pool_params->padding() << ") ";
+      os << "Padding(" << EnumNamePadding(pool_params->padding()) << ") ";
       os << "Stride.W(" << pool_params->stride_w() << ") ";
       os << "Stride.H(" << pool_params->stride_h() << ") ";
       os << "Filter.W(" << pool_params->filter_width() << ") ";
@@ -298,7 +298,7 @@ public:
     if (auto conv_params = op->builtin_options_as_DepthwiseConv2DOptions())
     {
       os << "    ";
-      os << "Padding(" << conv_params->padding() << ") ";
+      os << "Padding(" << EnumNamePadding(conv_params->padding()) << ") ";
       os << "Stride.W(" << conv_params->stride_w() << ") ";
       os << "Stride.H(" << conv_params->stride_h() << ") ";
       os << "DepthMultiplier(" << conv_params->depth_multiplier() << ") ";
@@ -662,7 +662,7 @@ public:
     if (auto params = op->builtin_options_as_TransposeConvOptions())
     {
       os << "    ";
-      os << "Padding(" << params->padding() << ") ";
+      os << "Padding(" << EnumNamePadding(params->padding()) << ") ";
       os << "Stride.W(" << params->stride_w() << ") ";
       os << "Stride.H(" << params->stride_h() << ") ";
       os << "Activation(" << EnumNameActivationFunctionType(params->fused_activation_function())
@@ -791,6 +791,24 @@ public:
   }
 };
 
+class GRUPrinter : public OpPrinter
+{
+public:
+  void options(const circle::Operator *op, std::ostream &os) const override
+  {
+    if (auto *params = op->builtin_options_as_GRUOptions())
+    {
+      os << "    ";
+      os << "Activation(" << EnumNameActivationFunctionType(params->fused_activation_function())
+         << ") ";
+      os << "return_sequences(" << params->return_sequences() << ") ";
+      os << "time_major(" << params->time_major() << ") ";
+
+      os << std::endl;
+    }
+  }
+};
+
 class InstanceNormPrinter : public OpPrinter
 {
 public:
@@ -853,6 +871,7 @@ OpPrinterRegistry::OpPrinterRegistry()
   // There is no Option for PRELU
   // There is no Option for RELU
   // There is no Option for RELU6
+  // There is no Option for RELU_0_TO_1
   // There is no Option for RELU_N1_TO_1
   _op_map[circle::BuiltinOperator_REDUCE_ANY] = make_unique<ReducerPrinter>();
   _op_map[circle::BuiltinOperator_REDUCE_MAX] = make_unique<ReducerPrinter>();
@@ -891,6 +910,7 @@ OpPrinterRegistry::OpPrinterRegistry()
   // Circle only
   _op_map[circle::BuiltinOperator_BCQ_FULLY_CONNECTED] = make_unique<BCQFullyConnectedPrinter>();
   _op_map[circle::BuiltinOperator_BCQ_GATHER] = make_unique<BCQGatherPrinter>();
+  _op_map[circle::BuiltinOperator_GRU] = make_unique<GRUPrinter>();
   _op_map[circle::BuiltinOperator_INSTANCE_NORM] = make_unique<InstanceNormPrinter>();
 }
 
diff --git a/compiler/cli/exclude.me b/compiler/cli/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/coco/exclude.me b/compiler/coco/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 2b03203..61c2f44 100644 (file)
@@ -49,6 +49,7 @@ if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64")
     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 ${CMAKE_COMMAND} -E echo "pytest==7.4.3" >> ${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
@@ -63,6 +64,7 @@ else(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64")
     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 ${CMAKE_COMMAND} -E echo "pytest==7.4.3" >> ${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
index 7505522..25eb124 100644 (file)
@@ -30,7 +30,6 @@ tcgenerate(BatchToSpaceND_000)
 tcgenerate(BroadcastTo_000) # luci-interpreter doesn't support custom operator
 tcgenerate(Ceil_000)
 tcgenerate(Conv2D_003) # runtime doesn't support dilation
-tcgenerate(Cos_000)
 tcgenerate(Densify_000) # luci-interpreter doesn't support
 tcgenerate(DepthwiseConv2D_001) # runtime doesn't support dilation
 tcgenerate(DepthwiseConv2D_003) # runtime doesn't support dilation
@@ -42,6 +41,9 @@ tcgenerate(Fill_000)
 tcgenerate(Fill_001)
 tcgenerate(FloorMod_000)
 tcgenerate(FloorMod_001)
+tcgenerate(FullyConnected_I4_000)
+tcgenerate(FullyConnected_I4_001)
+tcgenerate(FullyConnected_I4_002)
 tcgenerate(FullyConnected_U8_000)
 tcgenerate(GatherNd_000)
 tcgenerate(GatherNd_001)
@@ -69,6 +71,7 @@ tcgenerate(Net_Conv_FakeQuant_000) # luci-interpreter doesn't support FakeQuant
 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_FC_Gelu_FC_000) # luci-interpreter doesn't support custom operator Erf
 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
@@ -130,7 +133,6 @@ tcgenerate(SelectV2_000)
 tcgenerate(SelectV2_001)
 tcgenerate(SelectV2_002)
 tcgenerate(Shape_000)
-tcgenerate(Sin_000)
 tcgenerate(Slice_001) # luci-interpreter doesn't support Slice with -1
 tcgenerate(SpaceToBatchND_000)
 tcgenerate(SpaceToBatchND_001)
@@ -143,7 +145,6 @@ tcgenerate(Sum_000)
 tcgenerate(Sum_001)
 tcgenerate(Sum_dynamic_000) # TestDataGenerator does not support unknown dimension
 tcgenerate(Sum_dynamic_001) # TestDataGenerator does not support unknown dimension
-tcgenerate(Tile_000)
 tcgenerate(Tile_U8_000)
 tcgenerate(TopKV2_000)
 tcgenerate(TopKV2_001)
@@ -167,5 +168,11 @@ tcgenerate(ZerosLike_000)
 tcgenerate(BCQFullyConnected_000)
 tcgenerate(BCQFullyConnected_001)
 tcgenerate(BCQGather_000)
+tcgenerate(CircleBatchMatMul_I4_000)
+tcgenerate(CircleBatchMatMul_U4_000)
+tcgenerate(CircleFullyConnected_U4_000)
+tcgenerate(CircleFullyConnected_U4_001)
+tcgenerate(CircleFullyConnected_U4_002)
+tcgenerate(GRU_000) # luci-interpreter does not support custom GRU
 tcgenerate(InstanceNorm_000)
 tcgenerate(InstanceNorm_001)
index 7481050..72f4fbb 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <arser/arser.h>
 #include <foder/FileLoader.h>
+#include <luci/IR/DataTypeHelper.h>
 #include <luci/Importer.h>
 #include <luci_interpreter/Interpreter.h>
 
@@ -265,7 +266,7 @@ int entry(int argc, char **argv)
         input_file.createDataSet("value/" + std::to_string(input_index), dtype, *dataspace));
 
       auto data_size = ::element_num(dims);
-      auto dtype_size = loco::size(input_node->dtype());
+      auto dtype_size = luci::size(input_node->dtype());
       auto byte_size = dtype_size * data_size;
       std::vector<int8_t> data(byte_size);
 
@@ -329,7 +330,7 @@ int entry(int argc, char **argv)
       auto dataset = std::make_unique<H5::DataSet>(
         output_file.createDataSet("value/" + std::to_string(output_index), dtype, *dataspace));
 
-      uint32_t tensor_bytesize = loco::size(output_node->dtype());
+      uint32_t tensor_bytesize = luci::size(output_node->dtype());
       tensor_bytesize *= ::element_num(dims);
       std::vector<int8_t> output_data(tensor_bytesize);
       interpreter.readOutputTensor(output_node, output_data.data(), output_data.size());
index 1a35b6d..e662c20 100644 (file)
@@ -18,6 +18,7 @@
 #include "PythonHooks.h"
 #include "RandomUtils.h"
 
+#include <luci/IR/DataTypeHelper.h>
 #include <luci/Importer.h>
 #include <foder/FileLoader.h>
 #include <dio_hdf5/HDF5Importer.h>
@@ -51,7 +52,7 @@ template <typename NodeT> size_t getByteSize(const NodeT *node)
 {
   assert(node != nullptr); // FIX_CALLER_UNLESS
 
-  uint32_t dtype_size = loco::size(node->dtype());
+  uint32_t dtype_size = luci::size(node->dtype());
   return static_cast<size_t>(dtype_size) * static_cast<size_t>(numElements(node));
 }
 
index add4411..7ddda55 100644 (file)
@@ -61,16 +61,16 @@ public:
    * @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, size_t buffer_bytes);
+                  std::vector<loco::Dimension> *shape, void *buffer, size_t buffer_bytes) const;
 
   // Read a raw tensor (no type/shape is specified)
-  void readTensor(int32_t data_idx, int32_t input_idx, void *buffer, size_t buffer_bytes);
+  void readTensor(int32_t data_idx, int32_t input_idx, void *buffer, size_t buffer_bytes) const;
 
-  bool isRawData() { return _group.attrExists("rawData"); }
+  bool isRawData() const { return _group.attrExists("rawData"); }
 
-  int32_t numData() { return _group.getNumObjs(); }
+  int32_t numData() const { return _group.getNumObjs(); }
 
-  int32_t numInputs(int32_t data_idx);
+  int32_t numInputs(int32_t data_idx) const;
 
 private:
   H5::H5File _file;
index 9208990..2213961 100644 (file)
@@ -122,14 +122,14 @@ HDF5Importer::HDF5Importer(const std::string &path)
   _file = H5::H5File(path, H5F_ACC_RDONLY);
 }
 
-int32_t HDF5Importer::numInputs(int32_t record_idx)
+int32_t HDF5Importer::numInputs(int32_t record_idx) const
 {
   auto records = _group.openGroup(std::to_string(record_idx));
   return records.getNumObjs();
 }
 
 void HDF5Importer::readTensor(int32_t record_idx, int32_t input_idx, void *buffer,
-                              size_t buffer_bytes)
+                              size_t buffer_bytes) const
 {
   auto record = _group.openGroup(std::to_string(record_idx));
   auto tensor = record.openDataSet(std::to_string(input_idx));
@@ -141,7 +141,7 @@ void HDF5Importer::readTensor(int32_t record_idx, int32_t input_idx, void *buffe
 }
 
 void HDF5Importer::readTensor(int32_t record_idx, int32_t input_idx, DataType *dtype, Shape *shape,
-                              void *buffer, size_t buffer_bytes)
+                              void *buffer, size_t buffer_bytes) const
 {
   auto record = _group.openGroup(std::to_string(record_idx));
   auto tensor = record.openDataSet(std::to_string(input_idx));
index 63fd745..b937ba5 100644 (file)
@@ -17,6 +17,7 @@
 #include <luci_interpreter/GraphBuilderRegistry.h>
 #include <luci_interpreter/Interpreter.h>
 
+#include <luci/IR/DataTypeHelper.h>
 #include <luci/Importer.h>
 
 #include <cstdlib>
@@ -31,7 +32,7 @@ namespace
 
 uint32_t tensor_size_of(const luci::CircleNode *node)
 {
-  uint32_t tensor_size = loco::size(node->dtype());
+  uint32_t tensor_size = luci::size(node->dtype());
   for (uint32_t i = 0; i < node->rank(); ++i)
     tensor_size *= node->dim(i).value();
   return tensor_size;
@@ -45,8 +46,8 @@ std::vector<uint8_t> random_data_for(const luci::CircleInput *node)
 
   // define size of buffer in elements
   const auto dtype = node->dtype();
-  assert(inputs_data.size() % loco::size(dtype) == 0); // FIX ME UNLESS
-  const auto element_count = inputs_data.size() / loco::size(dtype);
+  assert(inputs_data.size() % luci::size(dtype) == 0); // FIX ME UNLESS
+  const auto element_count = inputs_data.size() / luci::size(dtype);
 
   // random generator engine
   std::random_device device;
diff --git a/compiler/enco-intf/exclude.me b/compiler/enco-intf/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/enco/exclude.me b/compiler/enco/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 995e66f..c71bde7 100644 (file)
@@ -1,4 +1,4 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 
 if(NOT FlatBuffers_FOUND)
   return()
index 81d5ed2..8c831af 100644 (file)
@@ -18,6 +18,10 @@ endfunction(get_test_configuration)
 ###
 ### Prepare test(s)
 ###
+if(NOT TARGET nnkit_tflite_backend)
+  return()
+endif(NOT TARGET nnkit_tflite_backend)
+
 if(NOT TARGET tflchef-file)
   return()
 endif(NOT TARGET tflchef-file)
diff --git a/compiler/encodump/exclude.me b/compiler/encodump/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 645db71..697c39d 100644 (file)
@@ -1,4 +1,4 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 
 if(NOT FlatBuffers_FOUND)
   message(STATUS "Build exo: FALSE (missing FlatBuffers)")
diff --git a/compiler/exo/exclude.me b/compiler/exo/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/fipe/exclude.me b/compiler/fipe/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index c55e46a..6e037dc 100644 (file)
@@ -32,6 +32,7 @@ struct ConsoleReporter final : public hermes::Sink
 
 private:
   bool _is_colored = false;
+  bool _env_checked = false;
 };
 
 } // namespace hermes
index 524ed59..03f60ad 100644 (file)
@@ -42,12 +42,16 @@ static constexpr const char *kTermColorResetAllCode = "\033[0m";
 
 void ConsoleReporter::notify(const hermes::Message *m)
 {
-  const char *env_color_p = std::getenv("ONE_HERMES_COLOR");
-  if (env_color_p)
+  if (not _env_checked)
   {
-    auto env_color_str = std::string(env_color_p);
-    if ((env_color_str == "1") or (env_color_str == "ON"))
-      _is_colored = true;
+    const char *env_color_p = std::getenv("ONE_HERMES_COLOR");
+    if (env_color_p)
+    {
+      auto env_color_str = std::string(env_color_p);
+      if ((env_color_str == "1") or (env_color_str == "ON"))
+        _is_colored = true;
+    }
+    _env_checked = true;
   }
 
   if (_is_colored)
diff --git a/compiler/kuma/exclude.me b/compiler/kuma/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index b89edf2..bb42165 100644 (file)
@@ -27,11 +27,13 @@ enum class DataType
 {
   Unknown, // Unknown type (serves as a default value)
 
+  U4,  // 4-bit unsigned integer
   U8,  // 8-bit unsigned integer
   U16, // 16-bit unsigned integer
   U32, // 32-bit unsigned integer
   U64, // 64-bit unsigned integer
 
+  S4,  // 4-bit signed integer
   S8,  // 8-bit signed integer
   S16, // 16-bit signed integer
   S32, // 32-bit signed integer
index 6be46c3..6bb3e57 100644 (file)
@@ -35,12 +35,24 @@ template <DataType DT> struct DataTypeImpl
 };
 
 // TODO Support other enum values
+template <> struct DataTypeImpl<DataType::S4>
+{
+  // Use C++ int8_t type for 4bit integer
+  using Type = int8_t;
+};
+
 template <> struct DataTypeImpl<DataType::S8>
 {
   // Use C++ int8_t type for 8bit integer
   using Type = int8_t;
 };
 
+template <> struct DataTypeImpl<DataType::U4>
+{
+  // Use C++ uint8_t type for unsigned 4bit integer
+  using Type = uint8_t;
+};
+
 template <> struct DataTypeImpl<DataType::U8>
 {
   // Use C++ uint8_t type for unsigned 8bit integer
@@ -123,8 +135,12 @@ inline uint32_t size(DataType data_type)
 {
   switch (data_type)
   {
+    case DataType::S4:
+      throw std::runtime_error("S4 type is not supported by loco::size");
     case DataType::S8:
       return sizeof(DataTypeImpl<DataType::S8>::Type);
+    case DataType::U4:
+      throw std::runtime_error("U4 type is not supported by loco::size");
     case DataType::U8:
       return sizeof(DataTypeImpl<DataType::U8>::Type);
     case DataType::S16:
index 4db4caa..77823c5 100644 (file)
@@ -34,7 +34,7 @@ public:
   ~NodePool();
 
 public:
-  template <typename Derived, typename... Args> Derived *create(Args &&... args)
+  template <typename Derived, typename... Args> Derived *create(Args &&...args)
   {
     std::unique_ptr<Derived> ptr{new Derived(std::forward<Args>(args)...)};
     ptr->graph(_graph);
index 16eaccf..45a231d 100644 (file)
@@ -46,7 +46,7 @@ public:
   Node *arg(uint32_t N) const final { return _arg.node(); }
   void drop(void) final { _arg.node(nullptr); }
 
-  Node *in(void)const { return _arg.node(); }
+  Node *in(void) const { return _arg.node(); }
   void in(Node *node) { _arg.node(node); }
 
 private:
index 74eed2a..f301520 100644 (file)
@@ -87,7 +87,7 @@ public:
 public:
   // "Layer" is in theory a subgraph builder.
   template <typename Layer, typename... Args>
-  auto push(Args &&... args)
+  auto push(Args &&...args)
     -> decltype(static_cast<Layer *>(nullptr)->operator()(static_cast<Context *>(nullptr)))
   {
     Layer layer{std::forward<Args>(args)...};
index 0d2cc88..b3895b1 100644 (file)
@@ -233,17 +233,23 @@ public:
 
 TEST(MultiDialectTypeInferenceRuleTest, test1)
 {
-  // Create a simple network : Pull - S8 - U8 - Push
+  // Create a simple network : Pull - S4 - S8 - U4 - U8 - Push
   auto g = loco::make_graph();
 
   auto pull_node = g->nodes()->create<loco::Pull>();
   pull_node->dtype(loco::DataType::FLOAT32);
 
+  auto s4_node = g->nodes()->create<TestOpNode<loco::DataType::S4>>();
+  s4_node->input(pull_node);
+
   auto s8_node = g->nodes()->create<TestOpNode<loco::DataType::S8>>();
-  s8_node->input(pull_node);
+  s8_node->input(s4_node);
+
+  auto u4_node = g->nodes()->create<TestOpNode<loco::DataType::U4>>();
+  u4_node->input(s8_node);
 
   auto u8_node = g->nodes()->create<TestOpNode<loco::DataType::U8>>();
-  u8_node->input(s8_node);
+  u8_node->input(u4_node);
 
   auto push_node = g->nodes()->create<loco::Push>();
   push_node->from(u8_node);
@@ -257,26 +263,38 @@ TEST(MultiDialectTypeInferenceRuleTest, test1)
   loco::link(graph_output, push_node);
 
   // initially they don't have type info
+  ASSERT_FALSE(loco::dtype_known(s4_node));
   ASSERT_FALSE(loco::dtype_known(s8_node));
+  ASSERT_FALSE(loco::dtype_known(u4_node));
   ASSERT_FALSE(loco::dtype_known(u8_node));
 
   // Run Type Inference
   TestTypeInferenceRule<loco::DataType::U8> u8_rule;
   TestTypeInferenceRule<loco::DataType::S8> s8_rule;
+  TestTypeInferenceRule<loco::DataType::S4> s4_rule;
+  TestTypeInferenceRule<loco::DataType::U4> u4_rule;
   loco::CanonicalTypeInferenceRule canon_rule;
 
   loco::MultiDialectTypeInferenceRule rules;
 
   rules.bind(TestDialect<loco::DataType::S8>::get(), &s8_rule)
     .bind(TestDialect<loco::DataType::U8>::get(), &u8_rule)
+    .bind(TestDialect<loco::DataType::S4>::get(), &s4_rule)
+    .bind(TestDialect<loco::DataType::U4>::get(), &u4_rule)
     .bind(loco::CanonicalDialect::get(), &canon_rule);
 
   loco::apply(&rules).to(g.get());
 
   // Verify!
+  ASSERT_TRUE(loco::dtype_known(s4_node));
+  ASSERT_EQ(loco::DataType::S4, loco::dtype_get(s4_node));
+
   ASSERT_TRUE(loco::dtype_known(s8_node));
   ASSERT_EQ(loco::DataType::S8, loco::dtype_get(s8_node));
 
+  ASSERT_TRUE(loco::dtype_known(u4_node));
+  ASSERT_EQ(loco::DataType::U4, loco::dtype_get(u4_node));
+
   ASSERT_TRUE(loco::dtype_known(u8_node));
   ASSERT_EQ(loco::DataType::U8, loco::dtype_get(u8_node));
 }
index 94bfbd2..6040371 100644 (file)
@@ -41,6 +41,8 @@ std::string str(const loco::DataType &dtype)
     case loco::DataType::Unknown:
       return "Unknown";
 
+    case loco::DataType::U4:
+      return "U4";
     case loco::DataType::U8:
       return "U8";
     case loco::DataType::U16:
@@ -50,6 +52,8 @@ std::string str(const loco::DataType &dtype)
     case loco::DataType::U64:
       return "U64";
 
+    case loco::DataType::S4:
+      return "S4";
     case loco::DataType::S8:
       return "S8";
     case loco::DataType::S16:
index b7ddb44..fdfefa1 100644 (file)
@@ -1,23 +1,59 @@
-nnas_find_package(TensorFlowSource EXACT 2.8.0 QUIET)
-nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.8.0 QUIET)
-nnas_find_package(TensorFlowRuySource EXACT 2.8.0 QUIET)
+nnas_find_package(TensorFlowSource EXACT 2.16.1 QUIET)
+nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.16.1 QUIET)
+nnas_find_package(TensorFlowRuySource EXACT 2.16.1 QUIET)
+nnas_find_package(NEON2SSESource QUIET)
 
 if(NOT TensorFlowSource_FOUND)
-  message(STATUS "Build luci-compute: FAILED (missing TensorFlowSource 2.8.0)")
+  message(STATUS "Build luci-compute: FAILED (missing TensorFlowSource 2.16.1)")
   return()
 endif(NOT TensorFlowSource_FOUND)
 
 if(NOT TensorFlowGEMMLowpSource_FOUND)
-  message(STATUS "Build luci-compute: FAILED (missing TensorFlowGEMMLowpSource 2.8.0)")
+  message(STATUS "Build luci-compute: FAILED (missing TensorFlowGEMMLowpSource 2.16.1)")
   return()
 endif(NOT TensorFlowGEMMLowpSource_FOUND)
 
 if(NOT TensorFlowRuySource_FOUND)
-  message(STATUS "Build luci-compute: FAILED (missing TensorFlowRuySource 2.8.0)")
+  message(STATUS "Build luci-compute: FAILED (missing TensorFlowRuySource 2.16.1)")
   return()
 endif(NOT TensorFlowRuySource_FOUND)
 
-add_library(luci_compute INTERFACE)
-target_include_directories(luci_compute SYSTEM INTERFACE "${TensorFlowSource_DIR}")
-target_include_directories(luci_compute SYSTEM INTERFACE "${TensorFlowGEMMLowpSource_DIR}")
-target_include_directories(luci_compute SYSTEM INTERFACE "${TensorFlowRuySource_DIR}")
+if(NOT NEON2SSESource_FOUND)
+  message(STATUS "Build luci-compute: FAILED (missing NEON2SSESource)")
+  return()
+endif(NOT NEON2SSESource_FOUND)
+
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+# Require for tflite::RuntimeShape
+list(APPEND SOURCES "${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/runtime_shape.cc")
+
+if (NOT LUCI_LIBRARY_TYPE)
+  set(LUCI_LIBRARY_TYPE "SHARED")
+endif(NOT LUCI_LIBRARY_TYPE)
+
+add_library(luci_compute ${LUCI_LIBRARY_TYPE} ${SOURCES})
+target_include_directories(luci_compute PUBLIC include)
+target_include_directories(luci_compute PRIVATE src)
+target_include_directories(luci_compute SYSTEM PRIVATE "${TensorFlowSource_DIR}")
+target_include_directories(luci_compute SYSTEM PRIVATE "${TensorFlowGEMMLowpSource_DIR}")
+target_include_directories(luci_compute SYSTEM PRIVATE "${TensorFlowRuySource_DIR}")
+target_include_directories(luci_compute SYSTEM PRIVATE "${NEON2SSESource_DIR}")
+target_link_libraries(luci_compute PUBLIC loco)
+install(TARGETS luci_compute DESTINATION lib)
+
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(luci_compute_test ${TESTS})
+target_include_directories(luci_compute_test PRIVATE src)
+target_link_libraries(luci_compute_test luci_compute)
+target_include_directories(luci_compute_test SYSTEM PRIVATE "${TensorFlowSource_DIR}")
+target_include_directories(luci_compute_test SYSTEM PRIVATE "${TensorFlowGEMMLowpSource_DIR}")
+target_include_directories(luci_compute_test SYSTEM PRIVATE "${TensorFlowRuySource_DIR}")
+target_include_directories(luci_compute_test SYSTEM PRIVATE "${NEON2SSESource_DIR}")
diff --git a/compiler/luci-compute/include/luci_compute/DepthwiseConv2D.h b/compiler/luci-compute/include/luci_compute/DepthwiseConv2D.h
new file mode 100644 (file)
index 0000000..4f76485
--- /dev/null
@@ -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_COMPUTE_DEPTHWISE_CONV2D_H__
+#define __LUCI_COMPUTE_DEPTHWISE_CONV2D_H__
+
+#include "Types.h"
+
+#include <loco/IR/TensorShape.h>
+
+namespace luci
+{
+namespace compute
+{
+
+// TODO extract some common for multiple Ops
+class DepthwiseConv2D
+{
+public:
+  DepthwiseConv2D() = default;
+
+public:
+  DepthwiseParams &params(void) { return _params; }
+
+  void input(const loco::TensorShape &shape, const float *data)
+  {
+    _input_shape = shape;
+    _input_data = data;
+  }
+
+  void filter(const loco::TensorShape &shape, const float *data)
+  {
+    _filter_shape = shape;
+    _filter_data = data;
+  }
+
+  void bias(const loco::TensorShape &shape, const float *data)
+  {
+    _bias_shape = shape;
+    _bias_data = data;
+  }
+
+  void fused_act_func(FusedActFunc func) { _fused_act_func = func; };
+
+  void output(float *data) { _output_data = data; }
+
+public:
+  bool prepare(void);
+  const loco::TensorShape &output_shape(void) const { return _output_shape; }
+  void compute(void);
+
+private:
+  // param to pass to compute kernel
+  DepthwiseParams _params = {};
+  // shape and data for inputs
+  loco::TensorShape _input_shape;
+  loco::TensorShape _filter_shape;
+  loco::TensorShape _bias_shape;
+  const float *_input_data = nullptr;
+  const float *_filter_data = nullptr;
+  const float *_bias_data = nullptr;
+  FusedActFunc _fused_act_func = FusedActFunc::UNDEFINED;
+
+  // compute results
+  loco::TensorShape _output_shape;
+  float *_output_data = nullptr;
+};
+
+} // namespace compute
+} // namespace luci
+
+#endif // __LUCI_COMPUTE_DEPTHWISE_CONV2D_H__
diff --git a/compiler/luci-compute/include/luci_compute/FullyConnected.h b/compiler/luci-compute/include/luci_compute/FullyConnected.h
new file mode 100644 (file)
index 0000000..e97264a
--- /dev/null
@@ -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_COMPUTE_FULLY_CONNECTED_H__
+#define __LUCI_COMPUTE_FULLY_CONNECTED_H__
+
+#include "Types.h"
+
+#include <loco/IR/TensorShape.h>
+
+namespace luci
+{
+namespace compute
+{
+
+// TODO extract some common for multiple Ops
+class FullyConnected
+{
+public:
+  FullyConnected() = default;
+
+public:
+  FullyConnectedParams &params(void) { return _params; }
+
+  bool keep_num_dims(void) const { return _keep_num_dims; }
+  void keep_num_dims(bool knd) { _keep_num_dims = knd; }
+
+  void input(const loco::TensorShape &shape, const float *data)
+  {
+    _input_shape = shape;
+    _input_data = data;
+  }
+
+  void weights(const loco::TensorShape &shape, const float *data)
+  {
+    _weights_shape = shape;
+    _weights_data = data;
+  }
+
+  void bias(const loco::TensorShape &shape, const float *data)
+  {
+    _bias_shape = shape;
+    _bias_data = data;
+  }
+
+  void fused_act_func(FusedActFunc func) { _fused_act_func = func; };
+
+  void output(float *data) { _output_data = data; }
+
+public:
+  bool prepare(void);
+  const loco::TensorShape &output_shape(void) const { return _output_shape; }
+  void compute(void);
+
+private:
+  // param to pass to compute kernel
+  FullyConnectedParams _params = {};
+  // new param from tflite version 5
+  bool _keep_num_dims = false;
+  // shape and data for inputs
+  loco::TensorShape _input_shape;
+  loco::TensorShape _weights_shape;
+  loco::TensorShape _bias_shape;
+  const float *_input_data = nullptr;
+  const float *_weights_data = nullptr;
+  const float *_bias_data = nullptr;
+  FusedActFunc _fused_act_func = FusedActFunc::UNDEFINED;
+
+  // compute results
+  loco::TensorShape _output_shape;
+  float *_output_data = nullptr;
+};
+
+} // namespace compute
+} // namespace luci
+
+#endif // __LUCI_COMPUTE_FULLY_CONNECTED_H__
diff --git a/compiler/luci-compute/include/luci_compute/Types.h b/compiler/luci-compute/include/luci_compute/Types.h
new file mode 100644 (file)
index 0000000..7f64306
--- /dev/null
@@ -0,0 +1,124 @@
+/* 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.
+ */
+
+// portion copied from TF2.8.0 tensorflow/lite/kernels/internal/types.h
+
+#ifndef __LUCI_COMPUTE_TYPES_H__
+#define __LUCI_COMPUTE_TYPES_H__
+
+#include <cassert>
+#include <cstdint>
+#include <vector>
+
+namespace luci
+{
+namespace compute
+{
+
+// from tflite as-is
+enum class PaddingType : uint8_t
+{
+  kNone,
+  kSame,
+  kValid
+};
+
+// from tflite as-is
+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;
+};
+
+// from tflite as-is
+struct DepthwiseParams
+{
+  PaddingType padding_type;
+  PaddingValues padding_values;
+  int16_t stride_width;
+  int16_t stride_height;
+  int16_t dilation_width_factor;
+  int16_t dilation_height_factor;
+  int16_t depth_multiplier;
+  // uint8_t inference params.
+  // TODO(b/65838351): Use smaller types if appropriate.
+  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;
+  const int32_t *output_multiplier_per_channel;
+  const int32_t *output_shift_per_channel;
+};
+
+// from tflite, with tidy long comments
+enum class FullyConnectedWeightsFormat : uint8_t
+{
+  kDefault,
+  kShuffled4x16Int8,
+};
+
+// from tflite as-is
+struct FullyConnectedParams
+{
+  // uint8_t inference params.
+  // TODO(b/65838351): Use smaller types if appropriate.
+  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;
+  FullyConnectedWeightsFormat weights_format;
+};
+
+// from luci as-is
+enum class FusedActFunc
+{
+  UNDEFINED, // This is not defined by TFLite or Circle. This was added to
+             // prevent programming error.
+  NONE,
+  RELU,
+  RELU_N1_TO_1,
+  RELU6,
+  TANH,
+  SIGN_BIT
+};
+
+} // namespace compute
+} // namespace luci
+
+#endif // __LUCI_COMPUTE_TYPES_H__
diff --git a/compiler/luci-compute/requires.cmake b/compiler/luci-compute/requires.cmake
new file mode 100644 (file)
index 0000000..44f6870
--- /dev/null
@@ -0,0 +1 @@
+require("loco")
diff --git a/compiler/luci-compute/src/ConvertTypes.cpp b/compiler/luci-compute/src/ConvertTypes.cpp
new file mode 100644 (file)
index 0000000..9e4ae17
--- /dev/null
@@ -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 "ConvertTypes.h"
+
+#include <cassert>
+#include <stdexcept>
+
+namespace luci
+{
+namespace compute
+{
+
+tflite::RuntimeShape tflite_shape(const loco::TensorShape &shape)
+{
+  tflite::RuntimeShape runtime_shape(shape.rank());
+  for (uint32_t i = 0; i < shape.rank(); ++i)
+  {
+    if (not shape.dim(i).known())
+      throw std::runtime_error("luci-comp tflite_shape shape unknown.");
+    runtime_shape.SetDim(i, shape.dim(i).value());
+  }
+  return runtime_shape;
+}
+
+tflite::PaddingType tflite_padding(const PaddingType type)
+{
+  switch (type)
+  {
+    case PaddingType::kSame:
+      return tflite::PaddingType::kSame;
+    case PaddingType::kValid:
+      return tflite::PaddingType::kValid;
+    default:
+      break;
+  }
+  throw std::runtime_error("luci-comp tflite_padding unsupported type.");
+}
+
+tflite::FullyConnectedWeightsFormat tflite_weights_format(const FullyConnectedWeightsFormat type)
+{
+  switch (type)
+  {
+    case FullyConnectedWeightsFormat::kDefault:
+      return tflite::FullyConnectedWeightsFormat::kDefault;
+    case FullyConnectedWeightsFormat::kShuffled4x16Int8:
+      return tflite::FullyConnectedWeightsFormat::kShuffled4x16Int8;
+    default:
+      break;
+  }
+  throw std::runtime_error("luci-comp tflite_weights_format unsupported type.");
+}
+
+} // namespace compute
+} // namespace luci
diff --git a/compiler/luci-compute/src/ConvertTypes.h b/compiler/luci-compute/src/ConvertTypes.h
new file mode 100644 (file)
index 0000000..43e4fe1
--- /dev/null
@@ -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_COMPUTE_CONVERT_TYPES_H__
+#define __LUCI_COMPUTE_CONVERT_TYPES_H__
+
+#include "luci_compute/Types.h"
+
+#include <loco/IR/TensorShape.h>
+
+#include <tensorflow/lite/kernels/internal/types.h>
+
+namespace luci
+{
+namespace compute
+{
+
+tflite::RuntimeShape tflite_shape(const loco::TensorShape &shape);
+
+tflite::PaddingType tflite_padding(const PaddingType type);
+
+tflite::FullyConnectedWeightsFormat tflite_weights_format(const FullyConnectedWeightsFormat type);
+
+} // namespace compute
+} // namespace luci
+
+#endif // __LUCI_COMPUTE_CONVERT_TYPES_H__
diff --git a/compiler/luci-compute/src/ConvertTypes.test.cpp b/compiler/luci-compute/src/ConvertTypes.test.cpp
new file mode 100644 (file)
index 0000000..f19af5a
--- /dev/null
@@ -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.
+ */
+
+#include "ConvertTypes.h"
+
+#include <gtest/gtest.h>
+
+TEST(ConvertTypes, tflite_shape)
+{
+  loco::TensorShape shape;
+  shape.rank(2);
+  shape.dim(0) = 1;
+  shape.dim(1) = 2;
+
+  auto tflite_shape = luci::compute::tflite_shape(shape);
+  EXPECT_EQ(tflite_shape.DimensionsCount(), 2);
+  EXPECT_EQ(tflite_shape.Dims(0), 1);
+  EXPECT_EQ(tflite_shape.Dims(1), 2);
+}
+
+TEST(ConvertTypes, tflite_shape_NEG)
+{
+  loco::TensorShape shape;
+  shape.rank(2);
+  shape.dim(0) = 1;
+
+  ASSERT_ANY_THROW(luci::compute::tflite_shape(shape));
+}
+
+TEST(ConvertTypes, tflite_padding)
+{
+  auto pts = luci::compute::PaddingType::kSame;
+  ASSERT_EQ(luci::compute::tflite_padding(pts), tflite::PaddingType::kSame);
+  auto ptv = luci::compute::PaddingType::kValid;
+  ASSERT_EQ(luci::compute::tflite_padding(ptv), tflite::PaddingType::kValid);
+}
+
+TEST(ConvertTypes, tflite_padding_NEG)
+{
+  auto pt = luci::compute::PaddingType::kNone;
+  ASSERT_ANY_THROW(luci::compute::tflite_padding(pt));
+}
+
+TEST(ConvertTypes, tflite_weights_format)
+{
+  auto fwf = luci::compute::FullyConnectedWeightsFormat::kDefault;
+  ASSERT_EQ(luci::compute::tflite_weights_format(fwf),
+            tflite::FullyConnectedWeightsFormat::kDefault);
+}
+
+TEST(ConvertTypes, tflite_weights_format_NEG)
+{
+  // force convert with invalid value as future unhandled value
+  luci::compute::FullyConnectedWeightsFormat fwf =
+    static_cast<luci::compute::FullyConnectedWeightsFormat>(250);
+  ASSERT_ANY_THROW(luci::compute::tflite_weights_format(fwf));
+}
diff --git a/compiler/luci-compute/src/ConvertValues.cpp b/compiler/luci-compute/src/ConvertValues.cpp
new file mode 100644 (file)
index 0000000..5a18725
--- /dev/null
@@ -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 "ConvertValues.h"
+
+#include <limits> // std::numeric_limits
+#include <stdexcept>
+
+namespace luci
+{
+namespace compute
+{
+
+void get_act_minmax(const FusedActFunc act, float &act_min, float &act_max)
+{
+  switch (act)
+  {
+    case FusedActFunc::NONE:
+    case FusedActFunc::TANH:
+      act_min = std::numeric_limits<float>::lowest();
+      act_max = std::numeric_limits<float>::max();
+      break;
+    case FusedActFunc::RELU:
+      act_min = 0;
+      act_max = std::numeric_limits<float>::max();
+      break;
+    case FusedActFunc::RELU_N1_TO_1:
+      act_min = -1;
+      act_max = 1;
+      break;
+    case FusedActFunc::RELU6:
+      act_min = 0;
+      act_max = 6;
+      break;
+    default:
+      throw std::runtime_error("luci-comp get_act_minmax unsupported type.");
+  }
+}
+
+} // namespace compute
+} // namespace luci
diff --git a/compiler/luci-compute/src/ConvertValues.h b/compiler/luci-compute/src/ConvertValues.h
new file mode 100644 (file)
index 0000000..506752d
--- /dev/null
@@ -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 __LUCI_COMPUTE_CONVERT_VALUES_H__
+#define __LUCI_COMPUTE_CONVERT_VALUES_H__
+
+#include "luci_compute/Types.h"
+
+namespace luci
+{
+namespace compute
+{
+
+void get_act_minmax(const FusedActFunc act, float &act_min, float &act_max);
+
+} // namespace compute
+} // namespace luci
+
+#endif // __LUCI_COMPUTE_CONVERT_VALUES_H__
diff --git a/compiler/luci-compute/src/ConvertValues.test.cpp b/compiler/luci-compute/src/ConvertValues.test.cpp
new file mode 100644 (file)
index 0000000..ed68fda
--- /dev/null
@@ -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 "ConvertValues.h"
+
+#include <gtest/gtest.h>
+
+TEST(ConvertValues, get_act_minmax)
+{
+  auto func = luci::compute::FusedActFunc::RELU6;
+  float act_min, act_max;
+  ASSERT_NO_THROW(luci::compute::get_act_minmax(func, act_min, act_max));
+  EXPECT_EQ(act_min, 0);
+  EXPECT_EQ(act_max, 6);
+}
+
+TEST(ConvertValues, get_act_minmax_NEG)
+{
+  // force convert with invalid value as future unhandled value
+  luci::compute::FusedActFunc func = static_cast<luci::compute::FusedActFunc>(250);
+  float act_min, act_max;
+  ASSERT_ANY_THROW(luci::compute::get_act_minmax(func, act_min, act_max));
+}
diff --git a/compiler/luci-compute/src/DepthwiseConv2D.cpp b/compiler/luci-compute/src/DepthwiseConv2D.cpp
new file mode 100644 (file)
index 0000000..739fc9c
--- /dev/null
@@ -0,0 +1,171 @@
+/* Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_compute/Types.h"
+#include "luci_compute/DepthwiseConv2D.h"
+
+#include "ConvertTypes.h"
+#include "ConvertValues.h"
+
+#include <tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h>
+
+#include <cassert>
+#include <cstdint>
+
+namespace luci
+{
+namespace compute
+{
+
+namespace
+{
+
+int32_t compute_output(PaddingType padding, int32_t in_size, int32_t filter_size, int32_t stride,
+                       int32_t dilation_rate)
+{
+  assert(in_size > 0);
+  assert(filter_size > 0);
+  assert(stride > 0);
+  assert(dilation_rate > 0);
+
+  auto const effective_filter_size = (filter_size - 1) * dilation_rate + 1;
+  switch (padding)
+  {
+    case PaddingType::kSame:
+      return (in_size + stride - 1) / stride;
+
+    case PaddingType::kValid:
+      return (in_size + stride - effective_filter_size) / stride;
+
+    default:
+      return -1;
+  }
+  return -1;
+}
+
+int16_t compute_padding(int32_t out_size, int32_t in_size, int32_t filter_size, int32_t stride,
+                        int32_t dilation_rate)
+{
+  assert(out_size > 0);
+  assert(in_size > 0);
+  assert(filter_size > 0);
+  assert(stride > 0);
+  assert(dilation_rate > 0);
+
+  auto const effective_filter_size = (filter_size - 1) * dilation_rate + 1;
+  auto const padding = ((out_size - 1) * stride + effective_filter_size - in_size) / 2;
+  assert(padding < INT16_MAX);
+  return padding > 0 ? static_cast<int16_t>(padding) : 0;
+}
+
+} // namespace
+
+bool DepthwiseConv2D::prepare(void)
+{
+  // TODO support other ranks if necessary
+  if (_input_shape.rank() != 4 || _filter_shape.rank() != 4)
+    return false;
+  // if bias exist, check if rank is 1
+  if (_bias_data && _bias_shape.rank() != 1)
+    return false;
+
+  auto const input_batches = _input_shape.dim(0).value();
+  auto const input_height = _input_shape.dim(1).value();
+  auto const input_width = _input_shape.dim(2).value();
+  auto const input_depth = _input_shape.dim(3).value();
+
+  auto const filter_height = _filter_shape.dim(1).value();
+  auto const filter_width = _filter_shape.dim(2).value();
+  auto const filter_channels_out = _filter_shape.dim(3).value();
+
+  if (filter_channels_out % input_depth != 0)
+    return false; // wrong input/output depth ratio
+
+  if (_params.depth_multiplier != static_cast<int32_t>(filter_channels_out / input_depth))
+    return false; // wrong depth multiplier value
+
+  if (_bias_shape.dim(0).value() != filter_channels_out)
+    return false; // unsupported bias value
+
+  auto output_height = compute_output(_params.padding_type, input_height, filter_height,
+                                      _params.stride_height, _params.dilation_height_factor);
+  if (output_height < 0)
+    return false;
+
+  auto output_width = compute_output(_params.padding_type, input_width, filter_width,
+                                     _params.stride_width, _params.dilation_width_factor);
+  if (output_width < 0)
+    return false;
+
+  get_act_minmax(_fused_act_func, _params.float_activation_min, _params.float_activation_max);
+
+  _output_shape.rank(4);
+  _output_shape.dim(0) = input_batches;
+  _output_shape.dim(1) = output_height;
+  _output_shape.dim(2) = output_width;
+  _output_shape.dim(3) = filter_channels_out;
+
+  _params.padding_values.height =
+    compute_padding(output_height, input_height, filter_height, _params.stride_height,
+                    _params.dilation_height_factor);
+  _params.padding_values.width = compute_padding(
+    output_width, input_width, filter_width, _params.stride_width, _params.dilation_width_factor);
+
+  return true;
+}
+
+void DepthwiseConv2D::compute(void)
+{
+  assert(_input_data != nullptr);
+  assert(_filter_data != nullptr);
+  // NOTE _bias_shape can be nullptr
+  assert(_output_data != nullptr);
+
+  // NOTE if this fails, structure may have changed
+  static_assert(sizeof(compute::DepthwiseParams) == sizeof(tflite::DepthwiseParams));
+
+  tflite::DepthwiseParams params;
+
+  // clang-format off
+  params.padding_type                   = tflite_padding(_params.padding_type);
+  params.padding_values.width           = _params.padding_values.width;
+  params.padding_values.height          = _params.padding_values.height;
+  params.padding_values.width_offset    = _params.padding_values.width_offset;
+  params.padding_values.height_offset   = _params.padding_values.height_offset;
+  params.stride_width                   = _params.stride_width;
+  params.stride_height                  = _params.stride_height;
+  params.dilation_width_factor          = _params.dilation_width_factor;
+  params.dilation_height_factor         = _params.dilation_height_factor;
+  params.depth_multiplier               = _params.depth_multiplier;
+  params.input_offset                   = _params.input_offset;
+  params.weights_offset                 = _params.weights_offset;
+  params.output_offset                  = _params.output_offset;
+  params.output_multiplier              = _params.output_multiplier;
+  params.output_shift                   = _params.output_shift;
+  params.quantized_activation_min       = _params.quantized_activation_min;
+  params.quantized_activation_max       = _params.quantized_activation_max;
+  params.float_activation_min           = _params.float_activation_min;
+  params.float_activation_max           = _params.float_activation_max;
+  params.output_multiplier_per_channel  = _params.output_multiplier_per_channel;
+  params.output_shift_per_channel       = _params.output_shift_per_channel;
+  // clang-format on
+
+  tflite::reference_ops::DepthwiseConv(
+    params, tflite_shape(_input_shape), _input_data, tflite_shape(_filter_shape), _filter_data,
+    tflite_shape(_bias_shape), _bias_data, tflite_shape(_output_shape), _output_data);
+}
+
+} // namespace compute
+} // namespace luci
diff --git a/compiler/luci-compute/src/DepthwiseConv2D.test.cpp b/compiler/luci-compute/src/DepthwiseConv2D.test.cpp
new file mode 100644 (file)
index 0000000..adf2503
--- /dev/null
@@ -0,0 +1,143 @@
+/* Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ConvertValues.h"
+
+#include <luci_compute/DepthwiseConv2D.h>
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+class DepthwiseConv2DTest : public ::testing::Test
+{
+protected:
+  loco::TensorShape tensor_shape(const std::initializer_list<uint32_t> shape)
+  {
+    loco::TensorShape tensor_shape;
+    tensor_shape.rank(shape.size());
+    uint32_t i = 0;
+    for (auto it = shape.begin(); it != shape.end(); ++it, ++i)
+      tensor_shape.dim(i) = *it;
+    return tensor_shape;
+  }
+
+  std::vector<uint32_t> vector_shape(const loco::TensorShape &tensor_shape)
+  {
+    std::vector<uint32_t> shape;
+    for (uint32_t r = 0; r < tensor_shape.rank(); ++r)
+      shape.push_back(tensor_shape.dim(r).value());
+    return shape;
+  }
+
+protected:
+  luci::compute::DepthwiseConv2D _dwconv2d;
+};
+
+TEST_F(DepthwiseConv2DTest, prepare_compute)
+{
+  auto input_shape = tensor_shape({1, 4, 2, 2});
+  std::vector<float> input_data{
+    1,  2,  7,  8,  //
+    3,  4,  9,  10, //
+    5,  6,  11, 12, //
+    13, 14, 15, 16, //
+  };
+  auto filter_shape = tensor_shape({1, 2, 2, 4});
+  std::vector<float> filter_data{
+    1,  2,   3,   4,   //
+    -9, 10,  -11, 12,  //
+    5,  6,   7,   8,   //
+    13, -14, 15,  -16, //
+  };
+  auto bias_shape = tensor_shape({4});
+  std::vector<float> bias_data{1, 2, 3, 4};
+
+  auto &params = _dwconv2d.params();
+  params.padding_type = luci::compute::PaddingType::kValid;
+  params.stride_height = 2;
+  params.stride_width = 1;
+  params.dilation_height_factor = 1;
+  params.dilation_width_factor = 1;
+  params.depth_multiplier = 2;
+
+  _dwconv2d.input(input_shape, input_data.data());
+  _dwconv2d.filter(filter_shape, filter_data.data());
+  _dwconv2d.bias(bias_shape, bias_data.data());
+  _dwconv2d.fused_act_func(luci::compute::FusedActFunc::RELU);
+
+  EXPECT_TRUE(_dwconv2d.prepare());
+
+  auto output_shape = _dwconv2d.output_shape();
+  auto output_count = loco::element_count(&output_shape);
+  std::vector<float> output_data_vector;
+  output_data_vector.resize(output_count);
+
+  _dwconv2d.output(output_data_vector.data());
+
+  ASSERT_NO_THROW(_dwconv2d.compute());
+
+  std::vector<float> ref_output_data{
+    71,  0, 99,  0,  //
+    167, 0, 227, 28, //
+  };
+  std::vector<uint32_t> ref_output_shape{1, 2, 1, 4};
+  std::vector<uint32_t> output_shape_vector = vector_shape(output_shape);
+
+  EXPECT_THAT(output_data_vector, ref_output_data);
+  EXPECT_THAT(output_shape_vector, ref_output_shape);
+}
+
+TEST_F(DepthwiseConv2DTest, prepare_invalid_rank_NEG)
+{
+  auto input_shape = tensor_shape({2}); // expect rank 4
+  std::vector<float> input_data{1, 2};
+  auto filter_shape = tensor_shape({2});
+  std::vector<float> filter_data{1, 2};
+  auto bias_shape = tensor_shape({1});
+  std::vector<float> bias_data{1};
+
+  _dwconv2d.input(input_shape, input_data.data());
+  _dwconv2d.filter(filter_shape, filter_data.data());
+  _dwconv2d.bias(bias_shape, bias_data.data());
+  _dwconv2d.fused_act_func(luci::compute::FusedActFunc::RELU);
+
+  EXPECT_FALSE(_dwconv2d.prepare());
+}
+
+TEST_F(DepthwiseConv2DTest, prepare_invalid_shape_NEG)
+{
+  auto input_shape = tensor_shape({1, 4, 2, 2});
+  std::vector<float> input_data{
+    1,  2,  7,  8,  //
+    3,  4,  9,  10, //
+    5,  6,  11, 12, //
+    13, 14, 15, 16, //
+  };
+  auto filter_shape = tensor_shape({1, 2, 2, 3}); // expect ,,, 4
+  std::vector<float> filter_data{
+    1,  2,  3,   4,  //
+    -9, 10, -11, 12, //
+    5,  6,  7,   8,  //
+  };
+  auto bias_shape = tensor_shape({4});
+  std::vector<float> bias_data{1, 2, 3, 4};
+
+  _dwconv2d.input(input_shape, input_data.data());
+  _dwconv2d.filter(filter_shape, filter_data.data());
+  _dwconv2d.bias(bias_shape, bias_data.data());
+  _dwconv2d.fused_act_func(luci::compute::FusedActFunc::RELU);
+
+  EXPECT_FALSE(_dwconv2d.prepare());
+}
diff --git a/compiler/luci-compute/src/FullyConnected.cpp b/compiler/luci-compute/src/FullyConnected.cpp
new file mode 100644 (file)
index 0000000..112c943
--- /dev/null
@@ -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.
+ */
+
+#include "luci_compute/Types.h"
+#include "luci_compute/FullyConnected.h"
+
+#include "ConvertTypes.h"
+#include "ConvertValues.h"
+
+#include <tensorflow/lite/kernels/internal/reference/fully_connected.h>
+
+#include <cassert>
+#include <cstdint>
+
+namespace luci
+{
+namespace compute
+{
+
+namespace
+{
+
+} // namespace
+
+bool FullyConnected::prepare(void)
+{
+  if (_input_shape.rank() < 1 || _weights_shape.rank() != 2)
+    return false;
+
+  auto const input_elems = element_count(&_input_shape);
+  auto const weights_height = _weights_shape.dim(0).value();
+  auto const weights_width = _weights_shape.dim(1).value();
+  if (weights_height == 0 || weights_width == 0)
+    return false;
+  if (input_elems % weights_width != 0)
+    return false;
+  auto const batch_size = input_elems / weights_width;
+  auto const num_units = weights_height;
+  if (_bias_data)
+  {
+    if (element_count(&_bias_shape) != num_units)
+      return false;
+  }
+
+  get_act_minmax(_fused_act_func, _params.float_activation_min, _params.float_activation_max);
+
+  if (_keep_num_dims)
+  {
+    _output_shape.rank(_input_shape.rank());
+    for (uint32_t i = 0; i < _input_shape.rank(); i++)
+      _output_shape.dim(i) = _input_shape.dim(i);
+    _output_shape.dim(_input_shape.rank() - 1) = num_units;
+  }
+  else
+  {
+    _output_shape.rank(2);
+    _output_shape.dim(0) = batch_size;
+    _output_shape.dim(1) = num_units;
+  }
+
+  return true;
+}
+
+void FullyConnected::compute(void)
+{
+  assert(_input_data != nullptr);
+  assert(_weights_data != nullptr);
+  // NOTE _bias_shape can be nullptr
+  assert(_output_data != nullptr);
+
+  // NOTE if this fails, structure may have changed
+  static_assert(sizeof(compute::FullyConnectedParams) == sizeof(tflite::FullyConnectedParams));
+
+  tflite::FullyConnectedParams params;
+
+  // clang-format off
+  params.input_offset             = _params.input_offset;
+  params.weights_offset           = _params.weights_offset;
+  params.output_offset            = _params.output_offset;
+  params.output_multiplier        = _params.output_multiplier;
+  params.output_shift             = _params.output_shift;
+  params.quantized_activation_min = _params.quantized_activation_min;
+  params.quantized_activation_max = _params.quantized_activation_max;
+  params.float_activation_min     = _params.float_activation_min;
+  params.float_activation_max     = _params.float_activation_max;
+  params.lhs_cacheable            = _params.lhs_cacheable;
+  params.rhs_cacheable            = _params.rhs_cacheable;
+  params.weights_format           = tflite_weights_format(_params.weights_format);
+  // clang-format on
+
+  tflite::reference_ops::FullyConnected(
+    params, tflite_shape(_input_shape), _input_data, tflite_shape(_weights_shape), _weights_data,
+    tflite_shape(_bias_shape), _bias_data, tflite_shape(_output_shape), _output_data);
+}
+
+} // namespace compute
+} // namespace luci
diff --git a/compiler/luci-compute/src/FullyConnected.test.cpp b/compiler/luci-compute/src/FullyConnected.test.cpp
new file mode 100644 (file)
index 0000000..3e35288
--- /dev/null
@@ -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.
+ */
+
+#include "ConvertValues.h"
+
+#include <luci_compute/FullyConnected.h>
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+class FullyConnectedTest : public ::testing::Test
+{
+protected:
+  loco::TensorShape tensor_shape(const std::initializer_list<uint32_t> shape)
+  {
+    loco::TensorShape tensor_shape;
+    tensor_shape.rank(shape.size());
+    uint32_t i = 0;
+    for (auto it = shape.begin(); it != shape.end(); ++it, ++i)
+      tensor_shape.dim(i) = *it;
+    return tensor_shape;
+  }
+
+  std::vector<uint32_t> vector_shape(const loco::TensorShape &tensor_shape)
+  {
+    std::vector<uint32_t> shape;
+    for (uint32_t r = 0; r < tensor_shape.rank(); ++r)
+      shape.push_back(tensor_shape.dim(r).value());
+    return shape;
+  }
+
+protected:
+  luci::compute::FullyConnected _fc;
+};
+
+TEST_F(FullyConnectedTest, prepare_compute)
+{
+  auto input_shape = tensor_shape({3, 2, 2, 1});
+  std::vector<float> input_data{
+    -3, -5, 5,  4,  //
+    9,  -2, -3, -2, //
+    -4, 9,  -8, 1,  //
+  };
+  auto weights_shape = tensor_shape({3, 6});
+  std::vector<float> weights_data{
+    -3, -7, 4, -4, -6, 4,  //
+    3,  5,  2, 3,  -3, -8, //
+    -3, 7,  4, 9,  0,  -5, //
+  };
+  auto bias_shape = tensor_shape({3});
+  std::vector<float> bias_data{-1, -5, -8};
+
+  auto &params = _fc.params();
+  params.weights_format = luci::compute::FullyConnectedWeightsFormat::kDefault;
+
+  _fc.input(input_shape, input_data.data());
+  _fc.weights(weights_shape, weights_data.data());
+  _fc.bias(bias_shape, bias_data.data());
+  _fc.fused_act_func(luci::compute::FusedActFunc::RELU);
+
+  EXPECT_TRUE(_fc.prepare());
+
+  auto output_shape = _fc.output_shape();
+  auto output_count = loco::element_count(&output_shape);
+  std::vector<float> output_data_vector;
+  output_data_vector.resize(output_count);
+
+  _fc.output(output_data_vector.data());
+
+  ASSERT_NO_THROW(_fc.compute());
+
+  std::vector<float> ref_output_data{
+    0,  0,  32, //
+    22, 11, 47, //
+  };
+  std::vector<uint32_t> ref_output_shape{2, 3};
+  std::vector<uint32_t> output_shape_vector = vector_shape(output_shape);
+
+  EXPECT_THAT(output_data_vector, ref_output_data);
+  EXPECT_THAT(output_shape_vector, ref_output_shape);
+}
+
+TEST_F(FullyConnectedTest, prepare_invalid_rank_NEG)
+{
+  auto input_shape = tensor_shape({3});
+  std::vector<float> input_data{-3, -5, 5};
+  auto weights_shape = tensor_shape({3}); // expect rank 2
+  std::vector<float> weights_data{-3, -7, 4};
+  auto bias_shape = tensor_shape({3});
+  std::vector<float> bias_data{-1, -5, -8};
+
+  _fc.input(input_shape, input_data.data());
+  _fc.weights(weights_shape, weights_data.data());
+  _fc.bias(bias_shape, bias_data.data());
+  _fc.fused_act_func(luci::compute::FusedActFunc::RELU);
+
+  EXPECT_FALSE(_fc.prepare());
+}
+
+TEST_F(FullyConnectedTest, prepare_invalid_shape_NEG)
+{
+  auto input_shape = tensor_shape({3, 2, 2, 1});
+  std::vector<float> input_data{
+    -3, -5, 5,  4,  //
+    9,  -2, -3, -2, //
+    -4, 9,  -8, 1,  //
+  };
+  auto weights_shape = tensor_shape({3, 5}); // expect 3, 6
+  std::vector<float> weights_data{
+    -3, -7, 4, -4, -6, //
+    3,  5,  2, 3,  -3, //
+    -3, 7,  4, 9,  0,  //
+  };
+  auto bias_shape = tensor_shape({3});
+  std::vector<float> bias_data{-1, -5, -8};
+
+  _fc.input(input_shape, input_data.data());
+  _fc.weights(weights_shape, weights_data.data());
+  _fc.bias(bias_shape, bias_data.data());
+  _fc.fused_act_func(luci::compute::FusedActFunc::RELU);
+
+  EXPECT_FALSE(_fc.prepare());
+}
index fb48f67..22f13f0 100644 (file)
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <luci/IR/DataTypeHelper.h>
 #include <luci/ImporterEx.h>
 #include <luci_interpreter/Interpreter.h>
 
@@ -48,7 +49,7 @@ void writeDataToFile(const std::string &filename, const char *data, size_t data_
 
 template <typename NodeT> size_t getTensorSize(const NodeT *node)
 {
-  uint32_t tensor_size = loco::size(node->dtype());
+  uint32_t tensor_size = luci::size(node->dtype());
   for (uint32_t i = 0; i < node->rank(); ++i)
     tensor_size *= node->dim(i).value();
   return tensor_size;
index 205baa6..fec0899 100644 (file)
@@ -114,7 +114,7 @@ private:
     const int32_t l = lowerLog2(block->size + sizeof(Block));
 
     const int64_t address = ((uint8_t *)block - (uint8_t *)_start_block);
-    buddy = (Block *)((address ^ (1 << l)) + (uint8_t *)_start_block);
+    buddy = (Block *)((address ^ (1LL << l)) + (uint8_t *)_start_block);
 
     if (!buddy->is_free || buddy->size != block->size)
       return nullptr;
index 8e2f457..d64961c 100644 (file)
@@ -60,6 +60,8 @@ public:
 
   void readOutputTensor(const luci::CircleOutput *output_node, void *data, size_t data_size);
 
+  size_t getOutputTensorSize(const luci::CircleOutput *output_node);
+
   void interpret();
 
   void attachObserver(ExecutionObserver *observer);
index 27bf719..57499a6 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <loco/IR/DataType.h>
 #include <loco/IR/DataTypeTraits.h>
+#include <luci/IR/DataTypeHelper.h>
 
 #include <cstddef>
 
@@ -29,7 +30,7 @@ using DataType = loco::DataType;
 
 template <DataType DT> using DataTypeImpl = loco::DataTypeImpl<DT>;
 
-inline size_t getDataTypeSize(DataType data_type) { return loco::size(data_type); }
+inline size_t getDataTypeSize(DataType data_type) { return luci::size(data_type); }
 
 } // namespace luci_interpreter
 
index ad33887..f118ee2 100644 (file)
@@ -60,6 +60,17 @@ public:
     return result;
   }
 
+  // TODO Replace num_elements
+  int64_t large_num_elements() const
+  {
+    int64_t result = 1;
+    for (const int32_t dim : _dims)
+    {
+      result *= dim;
+    }
+    return result;
+  }
+
   bool operator==(const Shape &other) const { return _dims == other._dims; }
 
   bool operator!=(const Shape &other) const { return !operator==(other); }
index e4d42de..4cccfbc 100644 (file)
@@ -4,9 +4,12 @@ REGISTER_KERNEL(ArgMax)
 REGISTER_KERNEL(AveragePool2D)
 REGISTER_KERNEL(BatchMatMul)
 REGISTER_KERNEL(BatchToSpaceND)
+REGISTER_KERNEL(BroadcastTo)
 REGISTER_KERNEL(Cast)
 REGISTER_KERNEL(Concatenation)
 REGISTER_KERNEL(Conv2D)
+REGISTER_KERNEL(Cos)
+REGISTER_KERNEL(CumSum)
 REGISTER_KERNEL(DepthToSpace)
 REGISTER_KERNEL(DepthwiseConv2D)
 REGISTER_KERNEL(Dequantize)
@@ -57,6 +60,7 @@ REGISTER_KERNEL(Quantize)
 REGISTER_KERNEL(ReduceMax)
 REGISTER_KERNEL(ReduceProd)
 REGISTER_KERNEL(Relu)
+REGISTER_KERNEL(Relu0To1)
 REGISTER_KERNEL(Relu6)
 REGISTER_KERNEL(Reshape)
 REGISTER_KERNEL(ResizeBilinear)
@@ -64,7 +68,9 @@ REGISTER_KERNEL(ResizeNearestNeighbor)
 REGISTER_KERNEL(ReverseV2)
 REGISTER_KERNEL(Rsqrt)
 REGISTER_KERNEL(Select)
+REGISTER_KERNEL(SelectV2)
 REGISTER_KERNEL(Shape)
+REGISTER_KERNEL(Sin)
 REGISTER_KERNEL(Slice)
 REGISTER_KERNEL(Softmax)
 REGISTER_KERNEL(SpaceToBatchND)
@@ -80,6 +86,7 @@ REGISTER_KERNEL(Sub)
 REGISTER_KERNEL(Sum)
 REGISTER_KERNEL(SVDF)
 REGISTER_KERNEL(Tanh)
+REGISTER_KERNEL(Tile)
 REGISTER_KERNEL(Transpose)
 REGISTER_KERNEL(TransposeConv)
 REGISTER_KERNEL(UnidirectionalSequenceLSTM)
diff --git a/compiler/luci-interpreter/pal/linux/PALBroadcastTo.h b/compiler/luci-interpreter/pal/linux/PALBroadcastTo.h
new file mode 100644 (file)
index 0000000..2296410
--- /dev/null
@@ -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_INTERPRETER_PAL_BROADCASTTO_H
+#define LUCI_INTERPRETER_PAL_BROADCASTTO_H
+
+#include <tensorflow/lite/kernels/internal/reference/broadcast_to.h>
+
+namespace luci_interpreter_pal
+{
+
+static inline void BroadcastTo(const tflite::RuntimeShape &input_shape, const char *input_data,
+                               const tflite::RuntimeShape &output_shape, char *output_data,
+                               TfLiteType data_type)
+{
+  // BroadcastTo op supports up to 8 kMaxDims in tensorflow.
+  // but, currently we support up to 5 dims because there is a compiler bug in 7.4.0 gcc version.
+  // https://github.com/tensorflow/tensorflow/blob/932af96ae91b4fa647dc50ad0f14c3e0b60affab/tensorflow/lite/kernels/broadcast_to.cc#L118
+  constexpr int kMaxDims = 5;
+  tflite::reference_ops::BroadcastTo<kMaxDims>(input_shape, input_data, output_shape, output_data,
+                                               data_type);
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_BROADCASTTO_H
index 985a15f..8ffcd86 100644 (file)
@@ -111,9 +111,11 @@ static inline void SetupScratchpadTensor(luci_interpreter::Tensor *scratchpad,
     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};
+    // im2col_shape
+    // data_type_size is added because we use U8 for scratchpad buffer dtype
+    luci_interpreter::Shape scratchpad_shape{batches, output_height, output_width,
+                                             input_depth * filter_height * filter_width,
+                                             data_type_size};
     scratchpad->resize(scratchpad_shape);
   }
   else
diff --git a/compiler/luci-interpreter/pal/linux/PALRelu0To1.h b/compiler/luci-interpreter/pal/linux/PALRelu0To1.h
new file mode 100644 (file)
index 0000000..0960d52
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_RELU0TO1_H
+#define LUCI_INTERPRETER_PAL_RELU0TO1_H
+
+#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
+
+namespace luci_interpreter_pal
+{
+static inline void Relu0To1(const tflite::RuntimeShape &input_shape, const float *input_data,
+                            const tflite::RuntimeShape &output_shape, float *output_data)
+{
+  tflite::optimized_ops::Relu0To1(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_RELU0TO1_H
index 28f6352..e31105f 100644 (file)
@@ -25,10 +25,11 @@ elseif("${TARGET_ARCH}" STREQUAL "aarch64")
 endif()
 
 macro(initialize_pal)
-    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)
+    nnas_find_package(TensorFlowSource EXACT 2.12.1 QUIET)
+    nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.12.1 QUIET)
+    nnas_find_package(TensorFlowEigenSource EXACT 2.12.1 QUIET)
+    nnas_find_package(TensorFlowRuySource EXACT 2.12.1 QUIET)
+    nnas_find_package(TensorFlowThreadpoolSource EXACT 2.12.1 QUIET)
 
     if (NOT TensorFlowSource_FOUND)
         message(STATUS "Skipping luci-interpreter: TensorFlow not found")
@@ -50,6 +51,11 @@ macro(initialize_pal)
         return()
     endif ()
 
+    if (NOT TensorFlowThreadpoolSource_FOUND)
+        message(STATUS "Skipping luci-interpreter: Threadpool not found")
+        return()
+    endif ()
+
     find_package(Threads REQUIRED)
 
     set(PAL_INITIALIZED TRUE)
@@ -61,6 +67,7 @@ macro(add_pal_to_target TGT)
             "${TensorFlowRuySource_DIR}"
             "${TensorFlowGEMMLowpSource_DIR}"
             "${TensorFlowEigenSource_DIR}"
+            "${TensorFlowThreadpoolSource_DIR}/include"
             "${TensorFlowSource_DIR}")
     target_include_directories(${TGT} PRIVATE ${LUCI_INTERPRETER_PAL_DIR})
 
@@ -68,7 +75,10 @@ macro(add_pal_to_target TGT)
     # 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)
+            ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/quantization_util.cc
+            ${TensorFlowSource_DIR}/tensorflow/lite/kernels/internal/portable_tensor_utils.cc
+            ${TensorFlowSource_DIR}/tensorflow/lite/kernels/kernel_util.cc
+            ${TensorFlowSource_DIR}/tensorflow/lite/core/c/common.cc)
 
     if(TARGET_ARCH_BASE STREQUAL "arm")
         # NOTE may need to revise this list for version upgrade
@@ -126,6 +136,7 @@ macro(add_pal_to_target TGT)
             "${TensorFlowRuySource_DIR}"
             "${TensorFlowGEMMLowpSource_DIR}"
             "${TensorFlowEigenSource_DIR}"
+            "${TensorFlowThreadpoolSource_DIR}/include"
             "${TensorFlowSource_DIR}"
     )
 
index 997b75a..401b8f3 100644 (file)
@@ -39,7 +39,7 @@ else ()
   add_library(${LUCI_INTERPRETER_BINARY} STATIC ${SOURCES})
 endif ()
 
-set(TEST_SOURCES BuddyMemoryManager.test.cpp)
+set(TEST_SOURCES SimpleMemoryManager.test.cpp BuddyMemoryManager.test.cpp)
 
 target_include_directories(${LUCI_INTERPRETER_BINARY} PUBLIC "${LUCI_INTERPRETER_INCLUDE_DIR}")
 target_include_directories(${LUCI_INTERPRETER_BINARY} PRIVATE "${LUCI_INTERPRETER_SOURCE_DIR}")
@@ -57,5 +57,5 @@ endif(NOT ENABLE_TEST)
 
 nnas_find_package(GTest REQUIRED)
 
-GTest_AddTest(buddy_manager_test ${TEST_SOURCES})
-target_link_libraries(buddy_manager_test ${LUCI_INTERPRETER_BINARY})
+GTest_AddTest(luci_interpreter_memory_manager_test ${TEST_SOURCES})
+target_link_libraries(luci_interpreter_memory_manager_test ${LUCI_INTERPRETER_BINARY})
index 8cf272e..fd46ec3 100644 (file)
@@ -125,6 +125,20 @@ void Interpreter::readOutputTensor(const luci::CircleOutput *output_node, void *
     tensor->readData(data, data_size);
 }
 
+size_t Interpreter::getOutputTensorSize(const luci::CircleOutput *output_node)
+{
+  Tensor *tensor = _runtime_module->getOutputTensors()[output_node->index()];
+  if (tensor == nullptr)
+  {
+    const std::string &name = output_node->name();
+    throw std::runtime_error("Cannot find tensor size for output node named \"" + name + "\".");
+  }
+
+  size_t tensor_size = luci_interpreter::getDataTypeSize(tensor->element_type());
+  tensor_size *= tensor->shape().num_elements();
+  return tensor_size;
+}
+
 void Interpreter::interpret() { _runtime_module->execute(); }
 
 void Interpreter::attachObserver(ExecutionObserver *observer)
index 230e398..a39c34a 100644 (file)
@@ -30,7 +30,9 @@ void SimpleMemoryManager::allocate_memory(luci_interpreter::Tensor &tensor)
     release_memory(tensor);
   }
   const auto element_size = getDataTypeSize(tensor.element_type());
-  const auto num_elements = tensor.shape().num_elements();
+
+  // Use large_num_elements to avoid overflow
+  const auto num_elements = tensor.shape().large_num_elements();
 
   auto *data = new uint8_t[num_elements * element_size];
   tensor.set_data_buffer(data);
diff --git a/compiler/luci-interpreter/src/SimpleMemoryManager.test.cpp b/compiler/luci-interpreter/src/SimpleMemoryManager.test.cpp
new file mode 100644 (file)
index 0000000..18902e3
--- /dev/null
@@ -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.
+ */
+
+#include "luci_interpreter/SimpleMemoryManager.h"
+#include <gtest/gtest.h>
+
+using namespace luci_interpreter;
+using namespace testing;
+
+TEST(SimpleMemoryManager, basic)
+{
+  SimpleMemoryManager smm;
+  Tensor t(DataType::U8, Shape({1, 16, 16, 256}), AffineQuantization{}, "t");
+
+  EXPECT_NO_THROW(smm.allocate_memory(t));
+  EXPECT_NO_THROW(smm.release_memory(t));
+}
+
+TEST(SimpleMemoryManager, huge)
+{
+  SimpleMemoryManager smm;
+  Tensor t(DataType::U8, Shape({1, 512, 512, 256 * 3 * 3 * 4}), AffineQuantization{}, "t");
+
+  EXPECT_NO_THROW(smm.allocate_memory(t));
+  EXPECT_NO_THROW(smm.release_memory(t));
+}
+
+TEST(SimpleMemoryManager, string_dtype_NEG)
+{
+  SimpleMemoryManager smm;
+  Tensor t(DataType::STRING, Shape({1, 16, 16, 4}), AffineQuantization{}, "t");
+
+  EXPECT_ANY_THROW(smm.allocate_memory(t));
+}
+
+TEST(SimpleMemoryManager, negative_shape_NEG)
+{
+  SimpleMemoryManager smm;
+  Tensor t(DataType::U8, Shape({1, 16, 16, -4}), AffineQuantization{}, "t");
+
+  EXPECT_ANY_THROW(smm.allocate_memory(t));
+}
index 4ddbcef..132ed5c 100644 (file)
@@ -65,6 +65,12 @@ struct Conv2DParams
   Activation activation;
 };
 
+struct CumSumParams
+{
+  bool exclusive;
+  bool reverse;
+};
+
 struct DepthToSpaceParams
 {
   int block_size;
index 5c63315..35e1b9d 100644 (file)
@@ -42,7 +42,7 @@ void Abs::execute() const
       eval<float>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Abs Unsupported type.");
   }
 }
 
index d7bf308..e954b61 100644 (file)
@@ -70,7 +70,7 @@ void Add::execute() const
       evalQuantizedS16();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Add Unsupported type.");
   }
 }
 
index d3bade9..cd42bcb 100644 (file)
@@ -99,7 +99,7 @@ void AveragePool2D::execute() const
       evalSInt8();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp AveragePool2D Unsupported type.");
   }
 }
 
index 24ca229..c159e55 100644 (file)
@@ -58,7 +58,7 @@ void BatchMatMul::configure()
 
   // TODO Support non-float types
   if (lhs->element_type() != DataType::FLOAT32 || rhs->element_type() != DataType::FLOAT32)
-    throw std::runtime_error("Unsupported type.");
+    throw std::runtime_error("luci-intp BatchMatMul(1) Unsupported type.");
 
   LUCI_INTERPRETER_CHECK(lhs->element_type() == rhs->element_type());
 
@@ -180,7 +180,7 @@ void BatchMatMul::execute() const
                                         getTensorData<float>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp BatchMatMul(2) Unsupported type.");
   }
 }
 
index bd315ff..3df0f6a 100644 (file)
@@ -96,7 +96,7 @@ void BatchToSpaceND::execute() const
         getTensorData<uint8_t>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp BatchToSpaceND Unsupported type.");
   }
 }
 
diff --git a/compiler/luci-interpreter/src/kernels/BroadcastTo.cpp b/compiler/luci-interpreter/src/kernels/BroadcastTo.cpp
new file mode 100644 (file)
index 0000000..a0ae0f8
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/BroadcastTo.h"
+#include "kernels/Utils.h"
+
+#include "PALBroadcastTo.h"
+
+#include <stdexcept>
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+namespace
+{
+
+// TODO Extract this function to Utils.h
+Shape extractShapeFromTensor(const Tensor *tensor)
+{
+  Shape shape(tensor->shape().num_elements());
+
+  // Ensures the shape is 1D tensor
+  LUCI_INTERPRETER_CHECK(tensor->shape().num_dims() == 1);
+
+  if (tensor->element_type() == DataType::S32)
+  {
+    const auto *shape_data = tensor->data<int32_t>();
+    for (int i = 0; i < tensor->shape().num_elements(); ++i)
+    {
+      // Ensures the dim value of shape is positive.
+      LUCI_INTERPRETER_CHECK(shape_data[i] >= 0);
+
+      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)
+    {
+      // Ensures the dim value of shape is positive.
+      LUCI_INTERPRETER_CHECK(shape_data[i] >= 0);
+
+      shape.dim(i) = static_cast<int32_t>(shape_data[i]);
+      // Check value overflow
+      LUCI_INTERPRETER_CHECK(static_cast<int64_t>(shape.dim(i)) == shape_data[i]);
+    }
+  }
+  else
+  {
+    LUCI_INTERPRETER_CHECK(false);
+  }
+  return shape;
+}
+
+} // namespace
+
+BroadcastTo::BroadcastTo(const Tensor *input, const Tensor *shape, Tensor *output)
+  : Kernel({input, shape}, {output})
+{
+}
+
+void BroadcastTo::configure()
+{
+  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+
+  Shape output_shape = extractShapeFromTensor(shape());
+
+  int input_rank = input()->shape().num_dims();
+  int output_rank = output_shape.num_dims();
+
+  // Ensures output rank is not less than input rank
+  LUCI_INTERPRETER_CHECK(input_rank <= output_rank);
+
+  // Check if output shape is broadcastable from input shape
+  // from https://www.tensorflow.org/api_docs/python/tf/broadcast_to
+  // if a tensor has fewer axes than necessary its shape is padded on the left with ones.
+  int extending_rank = output_rank - input_rank;
+  for (int idx = 0; idx < input_rank; ++idx)
+  {
+    LUCI_INTERPRETER_CHECK(input()->shape().dim(idx) == 1 ||
+                           input()->shape().dim(idx) == output_shape.dim(extending_rank + idx));
+  }
+
+  output()->resize(output_shape);
+}
+
+void BroadcastTo::execute() const
+{
+  switch (input()->element_type())
+  {
+    case DataType::FLOAT32:
+      evalFloat();
+      break;
+    case DataType::BOOL:
+      evalBool();
+      break;
+    default:
+      throw std::runtime_error("luci-intp BroadcastTo Unsupported type.");
+  }
+}
+
+void BroadcastTo::evalFloat() const
+{
+  luci_interpreter_pal::BroadcastTo(getTensorShape(input()), getTensorData<char>(input()),
+                                    getTensorShape(output()), getTensorData<char>(output()),
+                                    TfLiteType::kTfLiteFloat32);
+}
+
+void BroadcastTo::evalBool() const
+{
+  luci_interpreter_pal::BroadcastTo(getTensorShape(input()), getTensorData<char>(input()),
+                                    getTensorShape(output()), getTensorData<char>(output()),
+                                    TfLiteType::kTfLiteBool);
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/BroadcastTo.h b/compiler/luci-interpreter/src/kernels/BroadcastTo.h
new file mode 100644 (file)
index 0000000..0037dfc
--- /dev/null
@@ -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.
+ */
+
+#ifndef LUCI_INTERPRETER_KERNELS_BROADCASTTO_H
+#define LUCI_INTERPRETER_KERNELS_BROADCASTTO_H
+
+#include "core/Kernel.h"
+#include "core/KernelParams.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class BroadcastTo : public Kernel
+{
+public:
+  BroadcastTo(const Tensor *input, const Tensor *shape, Tensor *output);
+
+  const Tensor *input() const { return _inputs[0]; }
+  const Tensor *shape() const { return _inputs[1]; }
+  Tensor *output() const { return _outputs[0]; }
+
+  void configure() override;
+  void execute() const override;
+
+private:
+  void evalFloat() const;
+  void evalBool() const;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_BROADCASTTO_H
diff --git a/compiler/luci-interpreter/src/kernels/BroadcastTo.test.cpp b/compiler/luci-interpreter/src/kernels/BroadcastTo.test.cpp
new file mode 100644 (file)
index 0000000..dffaaa4
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * 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/BroadcastTo.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.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> shape_shape,
+           std::initializer_list<int32_t> output_shape, std::initializer_list<float> input_data,
+           std::initializer_list<T> shape_data, std::initializer_list<float> output_data)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  constexpr DataType element_type = DataType::FLOAT32;
+  constexpr DataType shape_type = getElementType<T>();
+
+  Tensor input_tensor =
+    makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
+  Tensor shape_tensor = makeInputTensor<shape_type>(shape_shape, shape_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(element_type);
+
+  BroadcastTo kernel(&input_tensor, &shape_tensor, &output_tensor);
+
+  kernel.configure();
+  memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(output_data));
+}
+
+template <typename T>
+void Check_bool(std::initializer_list<int32_t> input_shape,
+                std::initializer_list<int32_t> shape_shape,
+                std::initializer_list<int32_t> output_shape,
+                std::initializer_list<uint8_t> input_data, std::initializer_list<T> shape_data,
+                std::initializer_list<uint8_t> output_data)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  constexpr DataType element_type = DataType::BOOL;
+  constexpr DataType shape_type = getElementType<T>();
+
+  Tensor input_tensor =
+    makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
+  Tensor shape_tensor = makeInputTensor<shape_type>(shape_shape, shape_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(element_type);
+
+  BroadcastTo kernel(&input_tensor, &shape_tensor, &output_tensor);
+
+  kernel.configure();
+  memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  EXPECT_THAT(extractTensorData<uint8_t>(output_tensor), ::testing::ElementsAreArray(output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), output_shape);
+}
+
+class BroadcastToTest : public ::testing::Test
+{
+};
+
+TEST_F(BroadcastToTest, SimpleS32)
+{
+  Check<int32_t>(/*input_shape*/ {1, 3}, /*shape_shape*/ {2}, /*output_shape*/ {2, 3},
+                 /*input_data*/
+                 {1, 2, 3},
+                 /*shape_data*/
+                 {2, 3},
+                 /*output_data*/
+                 {
+                   1, 2, 3, // Row 1
+                   1, 2, 3, // Row 2
+                 });
+  SUCCEED();
+}
+
+TEST_F(BroadcastToTest, SimpleS64)
+{
+  Check<int64_t>(/*input_shape*/ {1, 3}, /*shape_shape*/ {2}, /*output_shape*/ {2, 3},
+                 /*input_data*/
+                 {1, 2, 3},
+                 /*shape_data*/
+                 {2, 3},
+                 /*output_data*/
+                 {
+                   1, 2, 3, // Row 1
+                   1, 2, 3, // Row 2
+                 });
+  SUCCEED();
+}
+
+TEST_F(BroadcastToTest, SimpleBool)
+{
+  Check_bool<int32_t>(/*input_shape*/ {1, 3}, /*shape_shape*/ {2}, /*output_shape*/ {2, 3},
+                      /*input_data*/
+                      {true, false, true},
+                      /*shape_data*/
+                      {2, 3},
+                      /*output_data*/
+                      {
+                        true, false, true, // Row 1
+                        true, false, true, // Row 2
+                      });
+  SUCCEED();
+}
+
+TEST_F(BroadcastToTest, DifferentInOutType_NEG)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+
+  Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1, 3}, {1, 2, 3}, memory_manager.get());
+  Tensor shape_tensor = makeInputTensor<DataType::S32>({2}, {2, 3}, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::U8);
+
+  BroadcastTo kernel(&input_tensor, &shape_tensor, &output_tensor);
+
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(BroadcastToTest, BroadcastAble_NEG)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>({2, 3}, {1, 2, 3, 1, 2, 3}, memory_manager.get());
+  Tensor shape_tensor = makeInputTensor<DataType::S32>({2}, {2, 6}, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  BroadcastTo kernel(&input_tensor, &shape_tensor, &output_tensor);
+
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+
+} // namespace kernels
+} // namespace luci_interpreter
index 46ee594..f2f556b 100644 (file)
@@ -107,7 +107,7 @@ void Concatenation::execute() const
       evalGeneric<int64_t>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Concatenation Unsupported type.");
   }
 }
 
index 234f954..9aae9da 100644 (file)
@@ -75,7 +75,7 @@ void Conv2D::configure()
   }
   else
   {
-    throw std::runtime_error("Unsupported type.");
+    throw std::runtime_error("luci-intp Conv2D(1) Unsupported type.");
   }
   LUCI_INTERPRETER_CHECK(output()->element_type() == input()->element_type());
 
@@ -143,7 +143,7 @@ void Conv2D::execute() const
         evalFloat();
         break;
       }
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Conv2D(2) Unsupported type.");
     case DataType::U8:
       if (filter()->scales().size() == 1)
       {
@@ -164,7 +164,7 @@ void Conv2D::execute() const
       evalQuantizedS16();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Conv2D(3) Unsupported type.");
   }
 }
 
diff --git a/compiler/luci-interpreter/src/kernels/Cos.cpp b/compiler/luci-interpreter/src/kernels/Cos.cpp
new file mode 100644 (file)
index 0000000..c14593d
--- /dev/null
@@ -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/Cos.h"
+
+#include "kernels/Utils.h"
+
+#include <cmath>
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+namespace
+{
+
+template <typename T>
+inline void CalcCos(const T *input_data, const size_t num_elements, T *output_data)
+{
+  for (size_t idx = 0; idx < num_elements; ++idx)
+  {
+    output_data[idx] = std::cos(input_data[idx]);
+  }
+}
+
+} // namespace
+
+Cos::Cos(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+
+void Cos::configure()
+{
+  LUCI_INTERPRETER_CHECK(input()->element_type() == DataType::FLOAT32);
+  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+  output()->resize(input()->shape());
+}
+
+void Cos::execute() const
+{
+  switch (input()->element_type())
+  {
+    case DataType::FLOAT32:
+      evalFloat();
+      break;
+    default:
+      throw std::runtime_error("luci-intp Cos Unsupported type.");
+  }
+}
+
+void Cos::evalFloat() const
+{
+  const int size = tflite::MatchingFlatSize(getTensorShape(input()), getTensorShape(output()));
+  CalcCos(getTensorData<float>(input()), size, getTensorData<float>(output()));
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Cos.h b/compiler/luci-interpreter/src/kernels/Cos.h
new file mode 100644 (file)
index 0000000..6097c5b
--- /dev/null
@@ -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_KERNELS_COS_H
+#define LUCI_INTERPRETER_KERNELS_COS_H
+
+#include "core/Kernel.h"
+#include "core/KernelParams.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class Cos : public Kernel
+{
+public:
+  Cos(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_COS_H
diff --git a/compiler/luci-interpreter/src/kernels/Cos.test.cpp b/compiler/luci-interpreter/src/kernels/Cos.test.cpp
new file mode 100644 (file)
index 0000000..ad7ea6f
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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/Cos.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.h"
+
+#include <cmath>
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+#define PI 3.14159265358979323846
+
+TEST(CosTest, Float)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  Shape input_shape{1, 1, 3};
+  std::vector<float> input_data{0.0f, PI / 3.0f, -PI / 3.0f};
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  Cos kernel(&input_tensor, &output_tensor);
+  kernel.configure();
+  memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  std::vector<int32_t> ref_output_shape{1, 1, 3};
+  std::vector<float> ref_output_data{std::cos(0.0f), std::cos(PI / 3.0f), std::cos(-PI / 3.0f)};
+  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST(SinTest, InvalidDType_NEG)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  Shape input_shape{1, 1, 3};
+  std::vector<int64_t> input_data{1l, 2l, 3l};
+  Tensor input_tensor =
+    makeInputTensor<DataType::S64>(input_shape, input_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::S64);
+
+  Cos kernel(&input_tensor, &output_tensor);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/CumSum.cpp b/compiler/luci-interpreter/src/kernels/CumSum.cpp
new file mode 100644 (file)
index 0000000..4c54172
--- /dev/null
@@ -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.
+ */
+
+#include "kernels/CumSum.h"
+
+#include <tensorflow/lite/kernels/internal/optimized/optimized_ops.h>
+
+#include "kernels/Utils.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+CumSum::CumSum(const Tensor *input, const Tensor *axis, Tensor *output, const CumSumParams &params)
+  : KernelWithParams<CumSumParams>({input, axis}, {output}, params)
+{
+}
+
+void CumSum::configure()
+{
+  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+  LUCI_INTERPRETER_CHECK(input()->shape().num_dims() >= 1);
+
+  LUCI_INTERPRETER_CHECK(axis()->element_type() == DataType::S32);
+  LUCI_INTERPRETER_CHECK(axis()->shape().num_dims() == 0);
+
+  output()->resize(input()->shape());
+}
+
+void CumSum::execute() const
+{
+  switch (input()->element_type())
+  {
+    case DataType::FLOAT32:
+      tflite::optimized_ops::CumSum(getTensorData<float>(input()), getTensorShape(input()),
+                                    *getTensorData<int32_t>(axis()), params().exclusive,
+                                    params().reverse, getTensorData<float>(output()));
+      break;
+    case DataType::S32:
+      tflite::optimized_ops::CumSum(getTensorData<int32_t>(input()), getTensorShape(input()),
+                                    *getTensorData<int32_t>(axis()), params().exclusive,
+                                    params().reverse, getTensorData<int32_t>(output()));
+      break;
+    case DataType::S64:
+      tflite::optimized_ops::CumSum(getTensorData<int64_t>(input()), getTensorShape(input()),
+                                    *getTensorData<int32_t>(axis()), params().exclusive,
+                                    params().reverse, getTensorData<int64_t>(output()));
+      break;
+    default:
+      throw std::runtime_error("luci-intp CumSum Unsupported type.");
+  }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/CumSum.h b/compiler/luci-interpreter/src/kernels/CumSum.h
new file mode 100644 (file)
index 0000000..bc08480
--- /dev/null
@@ -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_KERNELS_CUMSUM_H
+#define LUCI_INTERPRETER_KERNELS_CUMSUM_H
+
+#include <cstdint>
+
+#include "core/Kernel.h"
+#include "core/KernelParams.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class CumSum : public KernelWithParams<CumSumParams>
+{
+public:
+  CumSum(const Tensor *input, const Tensor *axis, Tensor *output, const CumSumParams &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_CUMSUM_H
diff --git a/compiler/luci-interpreter/src/kernels/CumSum.test.cpp b/compiler/luci-interpreter/src/kernels/CumSum.test.cpp
new file mode 100644 (file)
index 0000000..2a8ea98
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/CumSum.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+using namespace testing;
+
+class CumSumTest : public ::testing::Test
+{
+protected:
+  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
+
+  std::unique_ptr<IMemoryManager> _memory_manager;
+};
+
+TEST_F(CumSumTest, Float)
+{
+  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8};
+  std::vector<int32_t> axis_data{2};
+  Shape input_shape{1, 1, 2, 4};
+  Shape axis_shape(0);
+  std::vector<float> output_data{1, 2, 3, 4, 6, 8, 10, 12};
+  std::vector<int32_t> output_shape{1, 1, 2, 4};
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
+
+  Tensor axis_tensor = makeInputTensor<DataType::S32>(axis_shape, axis_data, _memory_manager.get());
+
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  CumSumParams params{false, false};
+
+  CumSum kernel(&input_tensor, &axis_tensor, &output_tensor, params);
+  kernel.configure();
+  _memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  EXPECT_THAT(extractTensorData<float>(output_tensor), ::testing::ElementsAreArray(output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+}
+
+TEST_F(CumSumTest, Int32)
+{
+  std::vector<int32_t> input_data{1, 2, 3, 4, 5, 6, 7, 8};
+  std::vector<int32_t> axis_data{2};
+  Shape input_shape{1, 1, 2, 4};
+  Shape axis_shape(0);
+  std::vector<int32_t> output_data{1, 2, 3, 4, 6, 8, 10, 12};
+  std::vector<int32_t> output_shape{1, 1, 2, 4};
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::S32>(input_shape, input_data, _memory_manager.get());
+
+  Tensor axis_tensor = makeInputTensor<DataType::S32>(axis_shape, axis_data, _memory_manager.get());
+
+  Tensor output_tensor = makeOutputTensor(DataType::S32);
+
+  CumSumParams params{false, false};
+
+  CumSum kernel(&input_tensor, &axis_tensor, &output_tensor, params);
+  kernel.configure();
+  _memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  EXPECT_THAT(extractTensorData<int32_t>(output_tensor), ::testing::ElementsAreArray(output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+}
+
+TEST_F(CumSumTest, Int64)
+{
+  std::vector<int64_t> input_data{1, 2, 3, 4, 5, 6, 7, 8};
+  std::vector<int32_t> axis_data{2};
+  Shape input_shape{1, 1, 2, 4};
+  Shape axis_shape(0);
+  std::vector<int64_t> output_data{1, 2, 3, 4, 6, 8, 10, 12};
+  std::vector<int32_t> output_shape{1, 1, 2, 4};
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::S64>(input_shape, input_data, _memory_manager.get());
+
+  Tensor axis_tensor = makeInputTensor<DataType::S32>(axis_shape, axis_data, _memory_manager.get());
+
+  Tensor output_tensor = makeOutputTensor(DataType::S64);
+
+  CumSumParams params{false, false};
+
+  CumSum kernel(&input_tensor, &axis_tensor, &output_tensor, params);
+  kernel.configure();
+  _memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  EXPECT_THAT(extractTensorData<int64_t>(output_tensor), ::testing::ElementsAreArray(output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+}
+
+TEST_F(CumSumTest, Float_Reverse)
+{
+  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8};
+  std::vector<int32_t> axis_data{2};
+  Shape input_shape{1, 1, 2, 4};
+  Shape axis_shape(0);
+  std::vector<float> output_data{6, 8, 10, 12, 5, 6, 7, 8};
+  std::vector<int32_t> output_shape{1, 1, 2, 4};
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
+
+  Tensor axis_tensor = makeInputTensor<DataType::S32>(axis_shape, axis_data, _memory_manager.get());
+
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  CumSumParams params{false, true};
+
+  CumSum kernel(&input_tensor, &axis_tensor, &output_tensor, params);
+  kernel.configure();
+  _memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  EXPECT_THAT(extractTensorData<float>(output_tensor), ::testing::ElementsAreArray(output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+}
+
+TEST_F(CumSumTest, Float_Exclusive)
+{
+  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8};
+  std::vector<int32_t> axis_data{2};
+  Shape input_shape{1, 1, 4, 2};
+  Shape axis_shape(0);
+  std::vector<float> output_data{0, 0, 1, 2, 4, 6, 9, 12};
+  std::vector<int32_t> output_shape{1, 1, 4, 2};
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
+
+  Tensor axis_tensor = makeInputTensor<DataType::S32>(axis_shape, axis_data, _memory_manager.get());
+
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  CumSumParams params{true, false};
+
+  CumSum kernel(&input_tensor, &axis_tensor, &output_tensor, params);
+  kernel.configure();
+  _memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  EXPECT_THAT(extractTensorData<float>(output_tensor), ::testing::ElementsAreArray(output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+}
+
+TEST_F(CumSumTest, InputShapeInvalid_NEG)
+{
+  std::vector<float> input_data{1};
+  std::vector<int32_t> axis_data{2};
+  Shape input_shape(0);
+  Shape axis_shape(0);
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
+
+  Tensor axis_tensor = makeInputTensor<DataType::S32>(axis_shape, axis_data, _memory_manager.get());
+
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  CumSumParams params{false, false};
+
+  CumSum kernel(&input_tensor, &axis_tensor, &output_tensor, params);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(CumSumTest, AxisShapeInvalid_NEG)
+{
+  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8};
+  std::vector<int32_t> axis_data{2};
+  Shape input_shape{1, 1, 2, 4};
+  Shape axis_shape{1};
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
+
+  Tensor axis_tensor = makeInputTensor<DataType::S32>(axis_shape, axis_data, _memory_manager.get());
+
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  CumSumParams params{false, false};
+
+  CumSum kernel(&input_tensor, &axis_tensor, &output_tensor, params);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(CumSumTest, AxisTypeInvalid_NEG)
+{
+  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8};
+  std::vector<float> axis_data{2};
+  Shape input_shape{1, 1, 2, 4};
+  Shape axis_shape(0);
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
+
+  Tensor axis_tensor =
+    makeInputTensor<DataType::FLOAT32>(axis_shape, axis_data, _memory_manager.get());
+
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  CumSumParams params{false, false};
+
+  CumSum kernel(&input_tensor, &axis_tensor, &output_tensor, params);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+
+} // namespace kernels
+} // namespace luci_interpreter
index 3a9acd1..ec5c918 100644 (file)
@@ -72,7 +72,7 @@ void DepthToSpace::execute() const
                                          getTensorData<uint8_t>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported Type.");
+      throw std::runtime_error("luci-intp DepthToSpace Unsupported Type.");
   }
 }
 
index c554c30..a48416f 100644 (file)
@@ -75,7 +75,7 @@ void DepthwiseConv2D::configure()
   }
   else
   {
-    throw std::runtime_error("Unsupported type.");
+    throw std::runtime_error("luci-intp DepthwiseConv2D(1) Unsupported type.");
   }
   LUCI_INTERPRETER_CHECK(output()->element_type() == input()->element_type());
 
@@ -130,7 +130,7 @@ void DepthwiseConv2D::execute() const
         evalFloat();
         break;
       }
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp DepthwiseConv2D(2) Unsupported type.");
     case DataType::U8:
       if (filter()->scales().size() == 1)
       {
@@ -151,7 +151,7 @@ void DepthwiseConv2D::execute() const
       evalQuantizedS16();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp DepthwiseConv2D(3) Unsupported type.");
   }
 }
 
index 96399e5..883d9b5 100644 (file)
@@ -71,7 +71,7 @@ void Dequantize::execute() const
       break;
     }
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Dequantize Unsupported type.");
   }
 }
 
index dd15322..190077a 100644 (file)
@@ -56,7 +56,7 @@ void Div::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Div Unsupported type.");
   }
 }
 
index 697d63b..a5f366e 100644 (file)
@@ -44,7 +44,7 @@ void Elu::execute() const
                                 getTensorShape(output()), getTensorData<float>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Elu Unsupported type.");
   }
 }
 
index a57e127..c3c11b1 100644 (file)
@@ -59,7 +59,7 @@ void Equal::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Equal Unsupported type.");
   }
 }
 
index e7c560a..e276f7f 100644 (file)
@@ -42,7 +42,7 @@ void Exp::execute() const
       evalFloat();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Exp Unsupported type.");
   }
 }
 
index ba35c99..5cbc4e2 100644 (file)
@@ -40,7 +40,7 @@ void ExpandDims::configure()
       axis_value = static_cast<int32_t>(*getTensorData<int64_t>(axis()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp ExpandDims Unsupported type.");
   }
 
   const auto input_shape = input()->shape();
index e09d633..8bea85f 100644 (file)
@@ -80,7 +80,7 @@ void Fill::configure()
       configureShape<int64_t>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Fill(1) Unsupported type.");
   }
 }
 
@@ -109,7 +109,7 @@ void Fill::execute() const
                                   getTensorShape(output()), getTensorData<float>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Fill(2) Unsupported type.");
   }
 }
 
index e3c4246..f15ee24 100644 (file)
@@ -43,7 +43,7 @@ void Floor::execute() const
       break;
 
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Floor Unsupported type.");
   }
 }
 
index a7a10a3..f2e617c 100644 (file)
@@ -48,7 +48,7 @@ void FloorDiv::execute() const
       evalFloat();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp FloorDiv Unsupported type.");
   }
 }
 
index a64fcad..8238883 100644 (file)
@@ -75,7 +75,7 @@ void FloorMod::execute() const
       evalInteger<int64_t>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp FloorMod Unsupported type.");
   }
 }
 
index bd2bb2f..ce34655 100644 (file)
@@ -54,9 +54,23 @@ void FullyConnected::configure()
     LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::S8);
     LUCI_INTERPRETER_CHECK(!bias() || bias()->element_type() == DataType::S32)
   }
+  else if (weights()->element_type() == DataType::S4)
+  {
+    // TODO support other combinations when needed
+    LUCI_INTERPRETER_CHECK(input()->element_type() == DataType::FLOAT32);
+    LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::FLOAT32);
+    LUCI_INTERPRETER_CHECK(!bias() || bias()->element_type() == DataType::FLOAT32)
+  }
+  else if (weights()->element_type() == DataType::U4)
+  {
+    // TODO support other combinations when needed
+    LUCI_INTERPRETER_CHECK(input()->element_type() == DataType::FLOAT32);
+    LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::FLOAT32);
+    LUCI_INTERPRETER_CHECK(!bias() || bias()->element_type() == DataType::FLOAT32)
+  }
   else
   {
-    throw std::runtime_error("Unsupported type.");
+    throw std::runtime_error("luci-intp FullyConnected(1) Unsupported type.");
   }
 
   const Shape &input_shape = input()->shape();
@@ -70,9 +84,6 @@ void FullyConnected::configure()
   const int32_t batch_size = input_shape.num_elements() / weights_shape.dim(1);
   const int32_t num_units = weights_shape.dim(0);
 
-  if (bias())
-    LUCI_INTERPRETER_CHECK(bias()->shape().num_elements() == weights()->shape().dim(0));
-
   if (params().keep_num_dims == false)
   {
     output()->resize({batch_size, num_units});
@@ -89,19 +100,41 @@ void FullyConnected::configure()
 
 void FullyConnected::execute() const
 {
-  switch (input()->element_type())
+  const bool is_hybrid =
+    (input()->element_type() == DataType::FLOAT32 &&
+     (weights()->element_type() == DataType::S4 || weights()->element_type() == DataType::U4) &&
+     output()->element_type() == DataType::FLOAT32 &&
+     (!bias() || bias()->element_type() == DataType::FLOAT32));
+  if (is_hybrid)
+  {
+    switch (weights()->element_type())
+    {
+      case DataType::S4:
+        evalHybridWI4AF32();
+        break;
+      case DataType::U4:
+        evalHybridWU4AF32();
+        break;
+      default:
+        throw std::runtime_error("luci-intp FullyConnected(3) Unsupported type.");
+    }
+  }
+  else
   {
-    case DataType::U8:
-      evalQuantized();
-      break;
-    case DataType::S8:
-      evalQuantizedS8();
-      break;
-    case DataType::FLOAT32:
-      evalFloat();
-      break;
-    default:
-      throw std::runtime_error("Unsupported type.");
+    switch (input()->element_type())
+    {
+      case DataType::U8:
+        evalQuantized();
+        break;
+      case DataType::S8:
+        evalQuantizedS8();
+        break;
+      case DataType::FLOAT32:
+        evalFloat();
+        break;
+      default:
+        throw std::runtime_error("luci-intp FullyConnected(2) Unsupported type.");
+    }
   }
 }
 
@@ -188,5 +221,130 @@ void FullyConnected::evalQuantizedS8() const
     getTensorShape(output()), getTensorData<int8_t>(output()));
 }
 
+void FullyConnected::evalHybridWI4AF32() const
+{
+  float activation_min{};
+  float activation_max{};
+  calculateActivationRange(_params.activation, &activation_min, &activation_max);
+
+  tflite::FullyConnectedParams params{};
+  params.float_activation_min = activation_min;
+  params.float_activation_max = activation_max;
+  params.weights_format = tflite::FullyConnectedWeightsFormat::kDefault;
+
+  const int8_t *weights_int4 = getTensorData<int8_t>(weights());
+  float *weights_float = getTensorData<float>(scratch());
+  const Shape &weights_shape = weights()->shape();
+  const auto weights_scales = weights()->scales();
+  const auto weights_quantized_dimension = weights()->quantized_dimension();
+  // Invariant for per-channel quantization of FC weights.
+  LUCI_INTERPRETER_CHECK(weights_quantized_dimension == 0);
+
+  if (weights_scales.size() == 1)
+  {
+    // Per tensor
+    const auto scale = weights()->scale();
+    for (int32_t i = 0; i < weights_shape.num_elements(); ++i)
+    {
+      weights_float[i] = scale * static_cast<float>(weights_int4[i]);
+    }
+  }
+  else
+  {
+    // Per channel
+    const int32_t quant_dim_size = weights_shape.dim(weights_quantized_dimension);
+
+    size_t outer_dims_size = 1;
+    size_t inner_dims_size = 1;
+    for (int i = 0; i < weights_quantized_dimension; ++i)
+      outer_dims_size *= weights_shape.dim(i);
+    for (int i = weights_quantized_dimension + 1; i < weights_shape.num_dims(); ++i)
+      inner_dims_size *= weights_shape.dim(i);
+
+    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 = weights_scales[channel];
+        size_t offset = inner_dims_size * (quant_dim_size * outer_it + channel);
+        for (size_t inner_it = 0; inner_it < inner_dims_size; ++inner_it)
+        {
+          LUCI_INTERPRETER_CHECK(offset + inner_it <
+                                 static_cast<size_t>(weights_shape.num_elements()));
+          weights_float[offset + inner_it] =
+            scale * static_cast<float>(weights_int4[offset + inner_it]);
+        }
+      }
+  }
+
+  tflite::reference_ops::FullyConnected(
+    params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(scratch()),
+    getTensorData<float>(scratch()), getTensorShape(bias()), getTensorData<float>(bias()),
+    getTensorShape(output()), getTensorData<float>(output()));
+}
+
+void FullyConnected::evalHybridWU4AF32() const
+{
+  float activation_min{};
+  float activation_max{};
+  calculateActivationRange(_params.activation, &activation_min, &activation_max);
+
+  tflite::FullyConnectedParams params{};
+  params.float_activation_min = activation_min;
+  params.float_activation_max = activation_max;
+  params.weights_format = tflite::FullyConnectedWeightsFormat::kDefault;
+
+  const auto *weights_uint4 = getTensorData<uint8_t>(weights());
+  auto *weights_float = getTensorData<float>(scratch());
+  const Shape &weights_shape = weights()->shape();
+  const auto weights_scales = weights()->scales();
+  const auto weights_zero_points = weights()->zero_points();
+  const auto weights_quantized_dimension = weights()->quantized_dimension();
+  LUCI_INTERPRETER_CHECK(weights_quantized_dimension == 0);
+  if (weights_scales.size() == 1)
+  {
+    // Per tensor
+    const auto scale = weights()->scale();
+    const auto zero_point = weights()->zero_point();
+    LUCI_INTERPRETER_CHECK(zero_point >= 0 and zero_point <= 15);
+    for (int32_t i = 0; i < weights_shape.num_elements(); ++i)
+    {
+      weights_float[i] =
+        scale * static_cast<float>(static_cast<int32_t>(weights_uint4[i]) - zero_point);
+    }
+  }
+  else
+  {
+    // Per channel
+    const int32_t quant_dim_size = weights_shape.dim(weights_quantized_dimension);
+
+    size_t outer_dims_size = 1;
+    size_t inner_dims_size = 1;
+    for (int i = 0; i < weights_quantized_dimension; ++i)
+      outer_dims_size *= weights_shape.dim(i);
+    for (int i = weights_quantized_dimension + 1; i < weights_shape.num_dims(); ++i)
+      inner_dims_size *= weights_shape.dim(i);
+
+    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 = weights_zero_points[channel];
+        LUCI_INTERPRETER_CHECK(zero_point >= 0 and zero_point <= 15);
+        float scale = weights_scales[channel];
+        size_t offset = inner_dims_size * (quant_dim_size * outer_it + channel);
+        for (size_t inner_it = 0; inner_it < inner_dims_size; ++inner_it)
+        {
+          weights_float[offset + inner_it] =
+            scale *
+            static_cast<float>(static_cast<int32_t>(weights_uint4[offset + inner_it]) - zero_point);
+        }
+      }
+  }
+
+  tflite::reference_ops::FullyConnected(
+    params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(scratch()),
+    getTensorData<float>(scratch()), getTensorShape(bias()), getTensorData<float>(bias()),
+    getTensorShape(output()), getTensorData<float>(output()));
+}
+
 } // namespace kernels
 } // namespace luci_interpreter
index 2a7c068..860775e 100644 (file)
@@ -30,11 +30,17 @@ class FullyConnected : public KernelWithParams<FullyConnectedParams>
 public:
   FullyConnected(const Tensor *input, const Tensor *weights, const Tensor *bias, Tensor *output,
                  const FullyConnectedParams &params);
-
+  FullyConnected(const Tensor *input, const Tensor *weights, const Tensor *bias, Tensor *output,
+                 Tensor *scratch, const FullyConnectedParams &params)
+    : FullyConnected(input, weights, bias, output, params)
+  {
+    _scratch = scratch;
+  }
   const Tensor *input() const { return _inputs[0]; }
   const Tensor *weights() const { return _inputs[1]; }
   const Tensor *bias() const { return _inputs[2]; }
   Tensor *output() const { return _outputs[0]; }
+  Tensor *scratch() const { return _scratch; }
 
   void configure() override;
   void execute() const override;
@@ -43,6 +49,9 @@ private:
   void evalFloat() const;
   void evalQuantized() const;
   void evalQuantizedS8() const;
+  void evalHybridWI4AF32() const;
+  void evalHybridWU4AF32() const;
+  Tensor *_scratch = nullptr;
 };
 
 } // namespace kernels
index 4474cc4..ddb9693 100644 (file)
@@ -154,6 +154,370 @@ TYPED_TEST(FullyConnectedTest, Simple)
                    });
 }
 
+TEST(FullyConnectedTest, SimpleS4PerTensor)
+{
+  std::initializer_list<int32_t> input_shape{1, 2};
+  std::initializer_list<int32_t> weights_shape{4, 2};
+  std::initializer_list<int32_t> bias_shape{4};
+  std::initializer_list<int32_t> output_shape{1, 4};
+  std::initializer_list<float> input_data{
+    1, 3, // batch = 0
+  };
+  std::initializer_list<int8_t> weights_initializer{
+    0,  1,  // unit = 0
+    0,  0,  // unit = 1
+    -1, -1, // unit = 2
+    0,  0,  // unit = 3
+  };
+  std::initializer_list<float> bias_data{0, 1, 2, 3};
+  std::initializer_list<float> output_data{
+    1.5, 1, 0, 3, // batch = 0
+  };
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  std::vector<int8_t> quantized_data(weights_initializer);
+  Tensor weights_tensor(DataType::S4, weights_shape, {{0.5}, {0}}, "");
+  memory_manager->allocate_memory(weights_tensor);
+  weights_tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(int8_t));
+  Tensor weights_scratch(DataType::FLOAT32, weights_shape, {}, "");
+  memory_manager->allocate_memory(weights_scratch);
+
+  Tensor bias_tensor =
+    makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  const float quantized_tolerance = getTolerance(-8, 7, 15);
+
+  FullyConnectedParams params{};
+  params.activation = Activation::RELU;
+
+  FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor,
+                        &weights_scratch, 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, quantized_tolerance));
+}
+
+TEST(FullyConnectedTest, SimpleS4PerChannel)
+{
+  std::initializer_list<int32_t> input_shape{1, 2};
+  std::initializer_list<int32_t> weights_shape{4, 2};
+  std::initializer_list<int32_t> bias_shape{4};
+  std::initializer_list<int32_t> output_shape{1, 4};
+  std::initializer_list<float> input_data{
+    1, 3, // batch = 0
+  };
+  std::initializer_list<int8_t> weights_initializer{
+    0,  1,  // unit = 0
+    0,  0,  // unit = 1
+    -1, -1, // unit = 2
+    0,  0,  // unit = 3
+  };
+  std::initializer_list<float> bias_data{0, 1, 2, 3};
+  std::initializer_list<float> output_data{
+    1.5, 1, 0, 3, // batch = 0
+  };
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  std::vector<int8_t> quantized_data(weights_initializer);
+  Tensor weights_tensor(DataType::S4, weights_shape, {{0.5, 0.5, 0.5, 0.5}, {0, 0, 0, 0}, 0}, "");
+  memory_manager->allocate_memory(weights_tensor);
+  weights_tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(int8_t));
+  Tensor weights_scratch(DataType::FLOAT32, weights_shape, {}, "");
+  memory_manager->allocate_memory(weights_scratch);
+
+  Tensor bias_tensor =
+    makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  const float quantized_tolerance = getTolerance(-8, 7, 15);
+
+  FullyConnectedParams params{};
+  params.activation = Activation::RELU;
+
+  FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor,
+                        &weights_scratch, 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, quantized_tolerance));
+}
+
+TEST(FullyConnectedTest, SimpleS4WrongBiasType_NEG)
+{
+  std::initializer_list<int32_t> input_shape{1, 2};
+  std::initializer_list<int32_t> weights_shape{4, 2};
+  std::initializer_list<int32_t> bias_shape{4};
+  std::initializer_list<float> input_data{
+    1, 3, // batch = 0
+  };
+  std::initializer_list<int8_t> weights_initializer{
+    0,  1,  // unit = 0
+    0,  0,  // unit = 1
+    -1, -1, // unit = 2
+    0,  0,  // unit = 3
+  };
+  std::initializer_list<int8_t> bias_data{0, 1, 2, 3};
+
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  std::vector<int8_t> quantized_data(weights_initializer);
+  Tensor weights_tensor(DataType::S4, weights_shape, {{0.5}, {8}}, "");
+  memory_manager->allocate_memory(weights_tensor);
+  weights_tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(int8_t));
+  Tensor weights_scratch(DataType::FLOAT32, weights_shape, {}, "");
+  memory_manager->allocate_memory(weights_scratch);
+
+  Tensor bias_tensor = makeInputTensor<DataType::S8>(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,
+                        &weights_scratch, params);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(FullyConnectedTest, SimpleS4WrongInputType_NEG)
+{
+  std::initializer_list<int32_t> input_shape{1, 2};
+  std::initializer_list<int32_t> weights_shape{4, 2};
+  std::initializer_list<int32_t> bias_shape{4};
+  std::initializer_list<int8_t> input_data{
+    1, 3, // batch = 0
+  };
+  std::initializer_list<int8_t> weights_initializer{
+    0,  1,  // unit = 0
+    0,  0,  // unit = 1
+    -1, -1, // unit = 2
+    0,  0,  // unit = 3
+  };
+  std::initializer_list<float> bias_data{0, 1, 2, 3};
+
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::S8>(input_shape, input_data, memory_manager.get());
+  std::vector<int8_t> quantized_data(weights_initializer);
+  Tensor weights_tensor(DataType::S4, weights_shape, {{0.5}, {8}}, "");
+  memory_manager->allocate_memory(weights_tensor);
+  weights_tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(int8_t));
+  Tensor weights_scratch(DataType::FLOAT32, weights_shape, {}, "");
+  memory_manager->allocate_memory(weights_scratch);
+
+  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,
+                        &weights_scratch, params);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(FullyConnectedTest, SimpleU4PerTensor)
+{
+  std::initializer_list<int32_t> input_shape{1, 2};
+  std::initializer_list<int32_t> weights_shape{4, 2};
+  std::initializer_list<int32_t> bias_shape{4};
+  std::initializer_list<int32_t> output_shape{1, 4};
+  std::initializer_list<float> input_data{
+    1, 3, // batch = 0
+  };
+  std::initializer_list<uint8_t> weights_initializer{
+    8, 9, // unit = 0
+    8, 8, // unit = 1
+    7, 7, // unit = 2
+    8, 8, // unit = 3
+  };
+  std::initializer_list<float> bias_data{0, 1, 2, 3};
+  std::initializer_list<float> output_data{
+    1.5, 1, 0, 3, // batch = 0
+  };
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  std::vector<uint8_t> quantized_data(weights_initializer);
+  Tensor weights_tensor(DataType::U4, weights_shape, {{0.5}, {8}}, "");
+  memory_manager->allocate_memory(weights_tensor);
+  weights_tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(uint8_t));
+  Tensor weights_scratch(DataType::FLOAT32, weights_shape, {}, "");
+  memory_manager->allocate_memory(weights_scratch);
+
+  Tensor bias_tensor =
+    makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  const float quantized_tolerance = getTolerance(0, 15, 15);
+
+  FullyConnectedParams params{};
+  params.activation = Activation::RELU;
+
+  FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor,
+                        &weights_scratch, 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, quantized_tolerance));
+}
+
+TEST(FullyConnectedTest, SimpleU4PerChannel)
+{
+  std::initializer_list<int32_t> input_shape{1, 2};
+  std::initializer_list<int32_t> weights_shape{4, 2};
+  std::initializer_list<int32_t> bias_shape{4};
+  std::initializer_list<int32_t> output_shape{1, 4};
+  std::initializer_list<float> input_data{
+    1, 3, // batch = 0
+  };
+  std::initializer_list<uint8_t> weights_initializer{
+    8, 9, // unit = 0
+    8, 8, // unit = 1
+    7, 7, // unit = 2
+    8, 8, // unit = 3
+  };
+  std::initializer_list<float> bias_data{0, 1, 2, 3};
+  std::initializer_list<float> output_data{
+    1.5, 1, 0, 3, // batch = 0
+  };
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  std::vector<uint8_t> quantized_data(weights_initializer);
+  Tensor weights_tensor(DataType::U4, weights_shape, {{0.5, 0.5, 0.5, 0.5}, {8, 8, 8, 8}, 0}, "");
+  memory_manager->allocate_memory(weights_tensor);
+  weights_tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(uint8_t));
+  Tensor weights_scratch(DataType::FLOAT32, weights_shape, {}, "");
+  memory_manager->allocate_memory(weights_scratch);
+
+  Tensor bias_tensor =
+    makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  const float quantized_tolerance = getTolerance(0, 15, 15);
+
+  FullyConnectedParams params{};
+  params.activation = Activation::RELU;
+
+  FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor,
+                        &weights_scratch, 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, quantized_tolerance));
+}
+
+TEST(FullyConnectedTest, SimpleU4WrongBiasType_NEG)
+{
+  std::initializer_list<int32_t> input_shape{1, 2};
+  std::initializer_list<int32_t> weights_shape{4, 2};
+  std::initializer_list<int32_t> bias_shape{4};
+  std::initializer_list<int32_t> output_shape{1, 4};
+  std::initializer_list<float> input_data{
+    1, 3, // batch = 0
+  };
+  std::initializer_list<uint8_t> weights_initializer{
+    8, 9, // unit = 0
+    8, 8, // unit = 1
+    7, 7, // unit = 2
+    8, 8, // unit = 3
+  };
+  std::initializer_list<uint8_t> bias_data{0, 1, 2, 3};
+  std::initializer_list<float> output_data{
+    1.5, 1, 0, 3, // batch = 0
+  };
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  std::vector<uint8_t> quantized_data(weights_initializer);
+  Tensor weights_tensor(DataType::U4, weights_shape, {{0.5, 0.5}, {8, 8}, 1}, "");
+  memory_manager->allocate_memory(weights_tensor);
+  weights_tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(uint8_t));
+  Tensor weights_scratch(DataType::FLOAT32, weights_shape, {}, "");
+  memory_manager->allocate_memory(weights_scratch);
+
+  Tensor bias_tensor = makeInputTensor<DataType::U8>(bias_shape, bias_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  const float quantized_tolerance = getTolerance(0, 15, 15);
+
+  FullyConnectedParams params{};
+  params.activation = Activation::RELU;
+
+  FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor,
+                        &weights_scratch, params);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(FullyConnectedTest, SimpleU4WrongInputType_NEG)
+{
+  std::initializer_list<int32_t> input_shape{1, 2};
+  std::initializer_list<int32_t> weights_shape{4, 2};
+  std::initializer_list<int32_t> bias_shape{4};
+  std::initializer_list<int32_t> output_shape{1, 4};
+  std::initializer_list<uint8_t> input_data{
+    1, 3, // batch = 0
+  };
+  std::initializer_list<uint8_t> weights_initializer{
+    8, 9, // unit = 0
+    8, 8, // unit = 1
+    7, 7, // unit = 2
+    8, 8, // unit = 3
+  };
+  std::initializer_list<float> bias_data{0, 1, 2, 3};
+  std::initializer_list<float> output_data{
+    1.5, 1, 0, 3, // batch = 0
+  };
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+
+  Tensor input_tensor =
+    makeInputTensor<DataType::U8>(input_shape, input_data, memory_manager.get());
+  std::vector<uint8_t> quantized_data(weights_initializer);
+  Tensor weights_tensor(DataType::U4, weights_shape, {{0.5, 0.5}, {8, 8}, 1}, "");
+  memory_manager->allocate_memory(weights_tensor);
+  weights_tensor.writeData(quantized_data.data(), quantized_data.size() * sizeof(uint8_t));
+  Tensor weights_scratch(DataType::FLOAT32, weights_shape, {}, "");
+  memory_manager->allocate_memory(weights_scratch);
+
+  Tensor bias_tensor =
+    makeInputTensor<DataType::FLOAT32>(bias_shape, bias_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  const float quantized_tolerance = getTolerance(0, 15, 15);
+
+  FullyConnectedParams params{};
+  params.activation = Activation::RELU;
+
+  FullyConnected kernel(&input_tensor, &weights_tensor, &bias_tensor, &output_tensor,
+                        &weights_scratch, params);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
 TEST(FullyConnectedTest, InvalidBiasType_NEG)
 {
   Shape input_shape{3, 2, 2, 1};
index f125666..c04e7f6 100644 (file)
@@ -42,7 +42,7 @@ void Gather::configure()
   }
   else
   {
-    throw std::runtime_error("Unsupported type.");
+    throw std::runtime_error("luci-intp Gather(1) Unsupported type.");
   }
 
   LUCI_INTERPRETER_CHECK(indices()->element_type() == DataType::S32 ||
@@ -102,7 +102,7 @@ void Gather::execute() const
       evalFloat();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Gather(2) Unsupported type.");
   }
 }
 
index 44e018e..998bb51 100644 (file)
@@ -48,7 +48,7 @@ void Gelu::execute() const
       evalFloat();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Gelu Unsupported type.");
   }
 }
 
index 5ccae3c..e1bc325 100644 (file)
@@ -59,7 +59,7 @@ void Greater::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Greather Unsupported type.");
   }
 }
 
index 27e42c9..f39cbe0 100644 (file)
@@ -62,7 +62,7 @@ void GreaterEqual::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp GreaterEqual Unsupported type.");
   }
 }
 
index b100845..21d7d57 100644 (file)
@@ -44,7 +44,7 @@ void HardSwish::execute() const
                                       getTensorShape(output()), getTensorData<float>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp HardSwish Unsupported type.");
   }
 }
 
index 22a329b..685d4e5 100644 (file)
@@ -55,7 +55,7 @@ void InstanceNorm::execute() const
       evalFloat();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp InstanceNorm Unsupported type.");
   }
 }
 
index 6422295..ab7b272 100644 (file)
@@ -58,7 +58,7 @@ void L2Normalize::execute() const
       eval<uint8_t>(input()->zero_point());
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp L2Normalize Unsupported type.");
   }
 }
 
index 5a88808..615381f 100644 (file)
@@ -80,7 +80,7 @@ void L2Pool2D::execute() const
                                    getTensorData<float>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp L2Pool2D Unsupported type.");
   }
 }
 
index 3833a55..122b7ef 100644 (file)
@@ -59,7 +59,7 @@ void LeakyRelu::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp LeakyRelu Unsupported type.");
   }
 }
 
index 8d26ff2..707f741 100644 (file)
@@ -59,7 +59,7 @@ void Less::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Less Unsupported type.");
   }
 }
 
index b474bc4..a1a9ff8 100644 (file)
@@ -59,7 +59,7 @@ void LessEqual::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp LessEqual Unsupported type.");
   }
 }
 
index a2bf442..64cf99b 100644 (file)
@@ -57,7 +57,7 @@ void LocalResponseNormalization::execute() const
         getTensorData<float>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp LocalResponseNormalizartion Unsupported type.");
   }
 }
 
index fa5f90e..f69caaa 100644 (file)
@@ -37,7 +37,7 @@ void Log::execute() const
       evalFloat();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Log Unsupported type.");
   }
 }
 
index 79c3153..b577cee 100644 (file)
@@ -57,7 +57,7 @@ void LogSoftmax::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp LogSoftmax Unsupported type.");
   }
 }
 
index 8e72632..2baaafb 100644 (file)
@@ -46,7 +46,7 @@ void LogicalAnd::execute() const
       evalLogicalAnd();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp LogicalAnd Unsupported type.");
   }
 }
 
index 65ab961..014ce2d 100644 (file)
@@ -41,7 +41,7 @@ void LogicalNot::execute() const
       evalLogicalNot();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp LogicalNot Unsupported type.");
   }
 }
 
index 58e4f18..fc69aeb 100644 (file)
@@ -49,7 +49,7 @@ void Logistic::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Logistic Unsupported type.");
   }
 }
 
index 8d9760f..a105a27 100644 (file)
@@ -81,7 +81,7 @@ void MaxPool2D::execute() const
       evalSInt16();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp MaxPool2D Unsupported type.");
   }
 }
 
index b102b5e..e384ce8 100644 (file)
@@ -49,7 +49,7 @@ void Maximum::execute() const
       evalMaximum<uint8_t>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Maximum Unsupported type.");
   }
 }
 
index 8e65e0d..3d321cc 100644 (file)
@@ -190,7 +190,7 @@ void Mean::execute() const
       evalQuantizedS16();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Mean Unsupported type.");
   }
 }
 
index 5d3dcde..ae82283 100644 (file)
@@ -49,7 +49,7 @@ void Minimum::execute() const
       evalMinimum<uint8_t>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Minimum Unsupported type.");
   }
 }
 
index bae1eac..c0d2388 100644 (file)
@@ -82,7 +82,7 @@ void MirrorPad::execute() const
       break;
     }
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp MirrorPad Unsupported type.");
   }
 }
 
index 531fb4f..43e3ae6 100644 (file)
@@ -68,7 +68,7 @@ void Mul::execute() const
       evalQuantizedS16();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Mul Unsupported type.");
   }
 }
 
index c6fe08a..fd72f2b 100644 (file)
@@ -44,7 +44,7 @@ void Neg::execute() const
       evalFloat();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Neg Unsupported type.");
   }
 }
 
index 54e5eee..4e0822c 100644 (file)
@@ -58,8 +58,11 @@ void NotEqual::execute() const
     case DataType::U8:
       evalQuantized();
       break;
+    case DataType::BOOL:
+      evalBool();
+      break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp NotEqual Unsupported type.");
   }
 }
 
@@ -138,5 +141,28 @@ void NotEqual::evalQuantized() const
   }
 }
 
+void NotEqual::evalBool() const
+{
+  const auto x_data = getTensorData<bool>(x());
+  const auto y_data = getTensorData<bool>(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);
+  }
+}
+
 } // namespace kernels
 } // namespace luci_interpreter
index d2aafe8..221d2c2 100644 (file)
@@ -40,6 +40,7 @@ private:
   void evalFloat() const;
   template <typename T> void evalInteger() const;
   void evalQuantized() const;
+  void evalBool() const;
 
 private:
   int32_t _x_multiplier = 0;
index 45bf402..7a6d0a3 100644 (file)
@@ -99,6 +99,36 @@ TEST_F(NotEqualTest, FloatBroardcast)
   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({4, 3}));
 }
 
+TEST_F(NotEqualTest, BoolSimple)
+{
+  std::vector<uint8_t> x_data{
+    true,  false, false, // Row 1
+    false, true,  true,  // Row 2
+  };
+
+  std::vector<uint8_t> y_data{
+    false, false, true,  // Row 1
+    true,  true,  false, // Row 2
+  };
+
+  std::vector<bool> ref_output_data{
+    true, false, true, // Row 1
+    true, false, true, // Row 2
+  };
+
+  Tensor x_tensor = makeInputTensor<DataType::BOOL>({2, 3}, x_data, _memory_manager.get());
+  Tensor y_tensor = makeInputTensor<DataType::BOOL>({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}));
+}
+
 template <loco::DataType DType>
 void checkIntegerSimple(luci_interpreter::IMemoryManager *memory_manager)
 {
@@ -281,6 +311,17 @@ TEST_F(NotEqualTest, Float_Broadcast_NEG)
   ASSERT_ANY_THROW(kernel.configure());
 }
 
+TEST_F(NotEqualTest, Bool_Broadcast_NEG)
+{
+  Tensor x_tensor = makeInputTensor<DataType::BOOL>({2}, {true, true}, _memory_manager.get());
+  Tensor y_tensor =
+    makeInputTensor<DataType::BOOL>({3}, {true, false, false}, _memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+
+  NotEqual kernel(&x_tensor, &y_tensor, &output_tensor);
+  ASSERT_ANY_THROW(kernel.configure());
+}
+
 TEST_F(NotEqualTest, Int32_Broadcast_NEG)
 {
   Tensor x_tensor = makeInputTensor<DataType::S32>({2}, {1, 2}, _memory_manager.get());
index 5a6b05c..5a5fba4 100644 (file)
@@ -103,7 +103,7 @@ void PRelu::execute() const
       evalQuantizedS16();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp PRelu Unsupported type.");
   }
 }
 
index 42aab33..8ba6cba 100644 (file)
@@ -48,7 +48,7 @@ void Pack::configure()
       t0->element_type() != DataType::U8 && t0->element_type() != DataType::S8 &&
       t0->element_type() != DataType::S16 && t0->element_type() != DataType::S64)
   {
-    throw std::runtime_error("Unsupported type.");
+    throw std::runtime_error("luci-intp Pack(1) Unsupported type.");
   }
 
   for (uint32_t i = 1; i < _inputs.size(); ++i)
@@ -116,7 +116,7 @@ void Pack::execute() const
       evalGeneric<int64_t>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Pack(2) Unsupported type.");
   }
 }
 
index c07f6e3..b8d600b 100644 (file)
@@ -106,7 +106,7 @@ void Pad::execute() const
       break;
     }
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Pad Unsupported type.");
   }
 }
 
index 197cdaa..d75e572 100644 (file)
@@ -100,7 +100,7 @@ void PadV2::execute() const
       break;
     }
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp PadV2 Unsupported type.");
   }
 }
 
index 722c640..519f1b6 100644 (file)
@@ -50,7 +50,7 @@ void Pow::execute() const
       eval<int32_t>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Pow Unsupported type.");
   }
 }
 
index 0c8544a..70f4f77 100644 (file)
@@ -132,7 +132,7 @@ void Quantize::execute() const
           break;
         }
         default:
-          throw std::runtime_error("Unsupported type.");
+          throw std::runtime_error("luci-intp Quantize(1) Unsupported type.");
       }
       break;
     }
@@ -152,7 +152,7 @@ void Quantize::execute() const
       break;
     }
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Quantize(2) Unsupported type.");
   }
 }
 
index d58cd15..8456afd 100644 (file)
@@ -149,9 +149,12 @@ void ReduceMax::execute() const
     case DataType::FLOAT32:
       evalFloat();
       break;
+    case DataType::BOOL:
+      evalBool();
+      break;
     // TODO Support quantized kernels
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp ReduceMax Unsupported type.");
   }
 }
 
@@ -177,5 +180,27 @@ void ReduceMax::evalFloat() const
     [](const float current, const float in) -> float { return (in > current) ? in : current; });
 }
 
+void ReduceMax::evalBool() 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));
+
+  bool init_value = std::numeric_limits<bool>::lowest();
+  tflite::reference_ops::ReduceGeneric<bool>(
+    getTensorData<bool>(input()), getTensorShape(input()).DimsData(), input()->shape().num_dims(),
+    getTensorData<bool>(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 bool current, const bool in) -> bool { return (in > current) ? in : current; });
+}
+
 } // namespace kernels
 } // namespace luci_interpreter
index 25a6627..f512f66 100644 (file)
@@ -42,6 +42,7 @@ public:
 
 private:
   void evalFloat() const;
+  void evalBool() const;
 };
 
 } // namespace kernels
index ab68882..6c41c39 100644 (file)
@@ -98,6 +98,68 @@ TEST_F(ReduceMaxTest, FloatKeepDims)
   EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
 }
 
+TEST_F(ReduceMaxTest, BoolNotKeepDims)
+{
+  std::vector<uint8_t> input_data = {true, true,  false, false, true, false, false, true,
+                                     true, true,  false, false, true, true,  false, true,
+                                     true, false, true,  false, true, false, false, true};
+
+  std::vector<int32_t> axis_data{1, 0, -3, -3};
+  Tensor input_tensor =
+    makeInputTensor<DataType::BOOL>({4, 3, 2}, input_data, _memory_manager.get());
+  Tensor axis_tensor = makeInputTensor<DataType::S32>({4}, axis_data, _memory_manager.get());
+  Tensor temp_index(DataType::S32, Shape({}), {}, "");
+  Tensor resolved_axes(DataType::S32, Shape({}), {}, "");
+  Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+
+  ReducerParams params{};
+  params.keep_dims = false;
+
+  ReduceMax 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<bool> ref_output_data{true, true};
+  std::initializer_list<int32_t> ref_output_shape{2};
+  EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST_F(ReduceMaxTest, BoolKeepDims)
+{
+  std::vector<uint8_t> input_data = {true, true,  false, false, true, false, false, true,
+                                     true, true,  false, false, true, true,  false, true,
+                                     true, false, true,  false, true, false, false, true};
+
+  std::vector<int32_t> axis_data{0, 2};
+  Tensor input_tensor =
+    makeInputTensor<DataType::BOOL>({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::BOOL);
+
+  ReducerParams params{};
+  params.keep_dims = true;
+
+  ReduceMax 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<bool> ref_output_data{true, true, true};
+  std::initializer_list<int32_t> ref_output_shape{1, 3, 1};
+  EXPECT_THAT(extractTensorData<bool>(output_tensor), ::testing::ElementsAreArray(ref_output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
 } // namespace
 } // namespace kernels
 } // namespace luci_interpreter
index f3fc7d3..24c4780 100644 (file)
@@ -150,7 +150,7 @@ void ReduceProd::execute() const
       break;
     // TODO Support quantized kernels
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp ReduceProd Unsupported type.");
   }
 }
 
index 747ec6c..b88099f 100644 (file)
@@ -59,7 +59,7 @@ void Relu::execute() const
       evalQuantizedS16();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Relu Unsupported type.");
   }
 }
 
diff --git a/compiler/luci-interpreter/src/kernels/Relu0To1.cpp b/compiler/luci-interpreter/src/kernels/Relu0To1.cpp
new file mode 100644 (file)
index 0000000..0488894
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/Relu0To1.h"
+#include "kernels/Utils.h"
+
+#include "PALRelu0To1.h"
+
+#include <stdexcept>
+
+namespace luci_interpreter
+{
+
+namespace kernels
+{
+
+Relu0To1::Relu0To1(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+
+void Relu0To1::configure()
+{
+  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+
+  if (input()->element_type() == DataType::U8)
+  {
+    double multiplier = input()->scale() / output()->scale();
+    quantizeMultiplier(multiplier, &_output_multiplier, &_output_shift);
+  }
+  output()->resize(input()->shape());
+}
+
+void Relu0To1::execute() const
+{
+  switch (input()->element_type())
+  {
+    case DataType::FLOAT32:
+      evalFloat();
+      break;
+    case DataType::U8:
+      evalQuantized();
+      break;
+    default:
+      throw std::runtime_error("luci-intp Relu0To1 Unsupported type.");
+  }
+}
+
+void Relu0To1::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::Relu0To1(input_shape, input_data, output_shape, output_data);
+}
+
+void Relu0To1::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(1.f / output()->scale())));
+
+  luci_interpreter_pal::ReluX(params, getTensorShape(input()), getTensorData<uint8_t>(input()),
+                              getTensorShape(output()), getTensorData<uint8_t>(output()));
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Relu0To1.h b/compiler/luci-interpreter/src/kernels/Relu0To1.h
new file mode 100644 (file)
index 0000000..ae481a7
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_RELU0TO1_H
+#define LUCI_INTERPRETER_KERNELS_RELU0TO1_H
+
+#include "core/Kernel.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class Relu0To1 : public Kernel
+{
+public:
+  Relu0To1(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;
+
+private:
+  int32_t _output_multiplier{0};
+  int32_t _output_shift{0};
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_RELU0TO1_H
diff --git a/compiler/luci-interpreter/src/kernels/Relu0To1.test.cpp b/compiler/luci-interpreter/src/kernels/Relu0To1.test.cpp
new file mode 100644 (file)
index 0000000..61dc3b0
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/Relu0To1.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+class Relu0To1Test : public ::testing::Test
+{
+protected:
+  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
+
+  std::unique_ptr<IMemoryManager> _memory_manager;
+};
+
+TEST_F(Relu0To1Test, FloatSimple)
+{
+  std::vector<float> input_data{
+    0.0f, 0.5f,  0.1f,  // Row 1
+    2.0f, -1.0f, -2.0f, // Row 2
+  };
+
+  std::vector<float> ref_output_data{
+    0.0f, 0.5f, 0.1f, // Row 1
+    1.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);
+
+  Relu0To1 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(Relu0To1Test, Uint8Quantized)
+{
+  // 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.0, -0.6, 0.2, -0.4, //
+    0.3, -2.0, 1.1, -0.1, //
+  };
+
+  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);
+
+  Relu0To1 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({128, 128, 131, 128, 132, 128, 141, 128}));
+  EXPECT_THAT(dequantizeTensorData(output_tensor),
+              FloatArrayNear({0, 0, 0.2, 0, 0.3, 0, 1.0, 0}, tolerance));
+}
+
+TEST_F(Relu0To1Test, 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) * 1;
+  const float tolerance = (in_max - in_min) / 255.0;
+
+  std::vector<float> input_data{
+    0.0, -0.6, 0.2, -0.4, //
+    0.3, -2.0, 1.1, -0.1, //
+  };
+
+  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);
+
+  Relu0To1 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, 60, 0, 80, 0, 255, 0}));
+  EXPECT_THAT(dequantizeTensorData(output_tensor),
+              FloatArrayNear({0, 0, 0.2, 0, 0.3, 0, 1.0, 0}, tolerance));
+}
+
+TEST_F(Relu0To1Test, Input_Output_Type_NEG)
+{
+  Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::U8);
+
+  Relu0To1 kernel(&input_tensor, &output_tensor);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(Relu0To1Test, Invalid_Input_Type_NEG)
+{
+  Tensor input_tensor = makeInputTensor<DataType::S64>({1}, {1}, _memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::S64);
+
+  Relu0To1 kernel(&input_tensor, &output_tensor);
+  kernel.configure();
+  _memory_manager->allocate_memory(output_tensor);
+  EXPECT_ANY_THROW(kernel.execute());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
index 07205ed..06762fe 100644 (file)
@@ -52,7 +52,7 @@ void Relu6::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Relu6 Unsupported type.");
   }
 }
 
index e2ddd6a..8ffc57b 100644 (file)
@@ -66,7 +66,7 @@ void ResizeBilinear::execute() const
         getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<uint8_t>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp ResizeBilinear Unsupported type.");
   }
 }
 
index 306cefb..90c6f98 100644 (file)
@@ -66,7 +66,7 @@ void ResizeNearestNeighbor::execute() const
         getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<uint8_t>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp ResizeNearestNeighbor Unsupported type.");
   }
 }
 
index 6dd92dc..768fcff 100644 (file)
@@ -46,7 +46,7 @@ void Rsqrt::execute() const
       break;
 
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Rsqrt Unsupported type.");
   }
 }
 
index b124e24..62c4793 100644 (file)
@@ -84,7 +84,7 @@ void SVDF::configure()
   }
   else
   {
-    throw std::runtime_error("Unsupported type.");
+    throw std::runtime_error("luci-intp SVDF Unsupported type.");
   }
 
   // Check all the parameters of tensor match within themselves and match the
index b4ab5f6..0ce24db 100644 (file)
@@ -33,8 +33,6 @@ 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;
 }
 
@@ -64,7 +62,7 @@ void Select::execute() const
       evalFloat();
       break;
     default:
-      throw std::runtime_error("Select: unsupported type.");
+      throw std::runtime_error("luci-intp Select unsupported type.");
   }
 }
 
@@ -84,11 +82,6 @@ void Select::evalFloat() const
     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,
index d67b4f5..a378ad5 100644 (file)
@@ -42,8 +42,6 @@ private:
   void evalFloat() const;
 
 private:
-  // 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;
diff --git a/compiler/luci-interpreter/src/kernels/SelectV2.cpp b/compiler/luci-interpreter/src/kernels/SelectV2.cpp
new file mode 100644 (file)
index 0000000..f56b3c3
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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/SelectV2.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
+{
+
+SelectV2::SelectV2(const Tensor *condition, const Tensor *t, const Tensor *e, Tensor *output)
+  : Kernel({condition, t, e}, {output})
+{
+}
+
+void SelectV2::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 t_shape = t()->shape();
+  auto e_shape = e()->shape();
+
+  output()->resize(
+    calculateShapeForBroadcast(cond_shape, calculateShapeForBroadcast(t_shape, e_shape)));
+}
+
+void SelectV2::execute() const
+{
+  auto t_type = t()->element_type();
+  switch (t_type)
+  {
+    case DataType::FLOAT32:
+      evaluate<float>();
+      break;
+    case DataType::S32:
+      evaluate<int32_t>();
+      break;
+    case DataType::S64:
+      evaluate<int64_t>();
+      break;
+    default:
+      throw std::runtime_error("luci-intp SelectV2 unsupported type.");
+  }
+}
+
+template <typename T> void SelectV2::evaluate() 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<T>(t());
+  const auto e_shape = getTensorShape(e());
+  const auto e_data = getTensorData<T>(e());
+  const auto output_shape = getTensorShape(output());
+  auto output_data = getTensorData<T>(output());
+
+  tflite::reference_ops::BroadcastSelect5DSlow<bool, T>(
+    condition_shape, condition_data, t_shape, t_data, e_shape, e_data, output_shape, output_data);
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/SelectV2.h b/compiler/luci-interpreter/src/kernels/SelectV2.h
new file mode 100644 (file)
index 0000000..3c73d94
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#ifndef LUCI_INTERPRETER_KERNELS_SELECTV2_H
+#define LUCI_INTERPRETER_KERNELS_SELECTV2_H
+
+#include "core/Kernel.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class SelectV2 : public Kernel
+{
+public:
+  SelectV2(const Tensor *cond, const Tensor *t, const Tensor *e, Tensor *output);
+
+  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;
+  void execute() const override;
+
+private:
+  template <typename T> void evaluate() const;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_SELECTV2_H
diff --git a/compiler/luci-interpreter/src/kernels/SelectV2.test.cpp b/compiler/luci-interpreter/src/kernels/SelectV2.test.cpp
new file mode 100644 (file)
index 0000000..66809ce
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * 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/SelectV2.h"
+#include "kernels/TestUtils.h"
+
+#include "luci_interpreter/TestMemoryManager.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+class SelectV2Test : 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_single{0};
+
+std::vector<unsigned char> c_data{
+  1, 1, 1, // Row 1
+  0, 0, 0, // Row 2
+};
+
+std::vector<float> f32t_data_single{-0.5};
+
+std::vector<float> f32t_data{
+  0.5, 0.7, 0.9, // Row 1
+  1,   0,   -1,  // Row 2
+};
+
+std::vector<float> f32e_data{
+  0.9, 0.7, 0.5, // Row 1
+  -1,  0,   1,   // Row 2
+};
+
+std::vector<float> ref_f32o_data{
+  0.5, 0.7, 0.9, // Row 1
+  -1,  0,   1,   // Row 2
+};
+
+std::vector<float> ref_broadcast_f32o_data{
+  -0.5, -0.5, -0.5, // Row 1
+  0.9,  0.7,  0.5,  // Row 2
+  -0.5, -0.5, -0.5, // Row 3
+  -1,   0,    1,    // Row 4
+};
+
+std::vector<int32_t> i32t_data_single{2};
+
+std::vector<int32_t> i32t_data{
+  5, -7, 9,  // Row 1
+  1, 0,  -1, // Row 2
+};
+
+std::vector<int32_t> i32e_data{
+  9,  7, -5, // Row 1
+  -1, 0, 1,  // Row 2
+};
+
+std::vector<int32_t> ref_i32o_data{
+  5,  -7, 9, // Row 1
+  -1, 0,  1, // Row 2
+};
+
+std::vector<int32_t> ref_broadcast_i32o_data{
+  2,  2, 2,  // Row 1
+  9,  7, -5, // Row 2
+  2,  2, 2,  // Row 3
+  -1, 0, 1,  // Row 4
+};
+
+TEST_F(SelectV2Test, FloatSimple)
+{
+  Tensor c_tensor = makeInputTensor<DataType::BOOL>({2, 3}, c_data, _memory_manager.get());
+  Tensor t_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, f32t_data, _memory_manager.get());
+  Tensor e_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, f32e_data, _memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  SelectV2 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_f32o_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
+}
+
+TEST_F(SelectV2Test, FloatBroadcast4D)
+{
+  Tensor c_tensor = makeInputTensor<DataType::BOOL>({1, 2, 3, 1}, c_data, _memory_manager.get());
+  Tensor t_tensor =
+    makeInputTensor<DataType::FLOAT32>({1}, f32t_data_single, _memory_manager.get());
+  Tensor e_tensor =
+    makeInputTensor<DataType::FLOAT32>({2, 1, 3, 1}, f32e_data, _memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  SelectV2 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_broadcast_f32o_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 2, 3, 1}));
+}
+
+TEST_F(SelectV2Test, Int32Simple)
+{
+  Tensor c_tensor = makeInputTensor<DataType::BOOL>({2, 3}, c_data, _memory_manager.get());
+  Tensor t_tensor = makeInputTensor<DataType::S32>({2, 3}, i32t_data, _memory_manager.get());
+  Tensor e_tensor = makeInputTensor<DataType::S32>({2, 3}, i32e_data, _memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::S32);
+
+  SelectV2 kernel(&c_tensor, &t_tensor, &e_tensor, &output_tensor);
+  kernel.configure();
+  _memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  EXPECT_THAT(extractTensorData<int32_t>(output_tensor),
+              ::testing::ElementsAreArray(ref_i32o_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 3}));
+}
+
+TEST_F(SelectV2Test, Int32Broadcast4D)
+{
+  Tensor c_tensor = makeInputTensor<DataType::BOOL>({1, 2, 3, 1}, c_data, _memory_manager.get());
+  Tensor t_tensor = makeInputTensor<DataType::S32>({1}, i32t_data_single, _memory_manager.get());
+  Tensor e_tensor = makeInputTensor<DataType::S32>({2, 1, 3, 1}, i32e_data, _memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::S32);
+
+  SelectV2 kernel(&c_tensor, &t_tensor, &e_tensor, &output_tensor);
+  kernel.configure();
+  _memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  EXPECT_THAT(extractTensorData<int32_t>(output_tensor),
+              ::testing::ElementsAreArray(ref_broadcast_i32o_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 2, 3, 1}));
+}
+
+TEST_F(SelectV2Test, 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}, f32t_data, _memory_manager.get());
+  Tensor e_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, f32e_data, _memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  SelectV2 kernel(&c_tensor, &t_tensor, &e_tensor, &output_tensor);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(SelectV2Test, 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}, f32t_data, _memory_manager.get());
+  Tensor e_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, f32e_data, _memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+
+  SelectV2 kernel(&c_tensor, &t_tensor, &e_tensor, &output_tensor);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST_F(SelectV2Test, MixedType_NEG)
+{
+  Tensor c_tensor = makeInputTensor<DataType::BOOL>({2, 3}, c_data, _memory_manager.get());
+  Tensor t_tensor = makeInputTensor<DataType::S32>({2, 3}, i32t_data, _memory_manager.get());
+  Tensor e_tensor = makeInputTensor<DataType::FLOAT32>({2, 3}, f32e_data, _memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  SelectV2 kernel(&c_tensor, &t_tensor, &e_tensor, &output_tensor);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
index 0429fe1..6cc378b 100644 (file)
@@ -50,7 +50,7 @@ void ShapeKernel::execute() const
       evalInt<int64_t>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Shape Unsupported type.");
   }
 }
 
diff --git a/compiler/luci-interpreter/src/kernels/Sin.cpp b/compiler/luci-interpreter/src/kernels/Sin.cpp
new file mode 100644 (file)
index 0000000..11db254
--- /dev/null
@@ -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/Sin.h"
+
+#include "kernels/Utils.h"
+
+#include <cmath>
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+namespace
+{
+
+template <typename T>
+inline void CalcSin(const T *input_data, const size_t num_elements, T *output_data)
+{
+  for (size_t idx = 0; idx < num_elements; ++idx)
+  {
+    output_data[idx] = std::sin(input_data[idx]);
+  }
+}
+
+} // namespace
+
+Sin::Sin(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+
+void Sin::configure()
+{
+  LUCI_INTERPRETER_CHECK(input()->element_type() == DataType::FLOAT32);
+  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+  output()->resize(input()->shape());
+}
+
+void Sin::execute() const
+{
+  switch (input()->element_type())
+  {
+    case DataType::FLOAT32:
+      evalFloat();
+      break;
+    default:
+      throw std::runtime_error("luci-intp Sin Unsupported type.");
+  }
+}
+
+void Sin::evalFloat() const
+{
+  const int size = tflite::MatchingFlatSize(getTensorShape(input()), getTensorShape(output()));
+  CalcSin(getTensorData<float>(input()), size, getTensorData<float>(output()));
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Sin.h b/compiler/luci-interpreter/src/kernels/Sin.h
new file mode 100644 (file)
index 0000000..d42f3da
--- /dev/null
@@ -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_KERNELS_SIN_H
+#define LUCI_INTERPRETER_KERNELS_SIN_H
+
+#include "core/Kernel.h"
+#include "core/KernelParams.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class Sin : public Kernel
+{
+public:
+  Sin(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_SIN_H
diff --git a/compiler/luci-interpreter/src/kernels/Sin.test.cpp b/compiler/luci-interpreter/src/kernels/Sin.test.cpp
new file mode 100644 (file)
index 0000000..1aab252
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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/Sin.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.h"
+
+#include <cmath>
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+#define PI 3.14159265358979323846
+
+using namespace testing;
+
+TEST(SinTest, Float)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  Shape input_shape{1, 1, 3};
+  std::vector<float> input_data{0.0f, PI / 3.0f, -PI / 3.0f};
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  Sin kernel(&input_tensor, &output_tensor);
+  kernel.configure();
+  memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  std::vector<int32_t> ref_output_shape{1, 1, 3};
+  std::vector<float> ref_output_data{std::sin(0.0f), std::sin(PI / 3.0f), std::sin(-PI / 3.0f)};
+  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST(SinTest, InvalidDType_NEG)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  Shape input_shape{1, 1, 3};
+  std::vector<int64_t> input_data{1l, 2l, 3l};
+  Tensor input_tensor =
+    makeInputTensor<DataType::S64>(input_shape, input_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::S64);
+
+  Sin kernel(&input_tensor, &output_tensor);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
index 2fe2c54..d7cf46a 100644 (file)
@@ -90,7 +90,7 @@ void Slice::configure()
   }
   else
   {
-    throw std::runtime_error("Unsupported type.");
+    throw std::runtime_error("luci-intp Slice Unsupported type.");
   }
 }
 
index c230aaa..c195fcd 100644 (file)
@@ -64,7 +64,7 @@ void Softmax::execute() const
       evalQuantized<uint8_t>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Softmax Unsupported type.");
   }
 }
 
index 630cd38..57c6e2e 100644 (file)
@@ -95,7 +95,7 @@ void SpaceToBatchND::execute() const
         getTensorData<uint8_t>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp ShapeToBatchND Unsupported type.");
   }
 }
 
index 7c29e8c..06180ff 100644 (file)
@@ -71,7 +71,7 @@ void SpaceToDepth::execute() const
                                          getTensorData<uint8_t>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp SpaceToDepth Unsupported type.");
   }
 }
 
index 1a563f3..c175bbb 100644 (file)
@@ -72,7 +72,7 @@ void Split::execute() const
       TF_LITE_SPLIT(uint8_t);
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Split Unsupported type.");
   }
 #undef TF_LITE_SPLIT
 }
index aa68208..f3cc504 100644 (file)
@@ -102,7 +102,7 @@ void SplitV::execute() const
       TF_LITE_SPLIT(int16_t);
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp SplitV Unsupported type.");
   }
 #undef TF_LITE_SPLIT
 }
index 46e9fc9..46fe313 100644 (file)
@@ -46,7 +46,7 @@ void Sqrt::execute() const
       break;
 
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Sqrt Unsupported type.");
   }
 }
 
index bc71905..24a85ee 100644 (file)
@@ -46,7 +46,7 @@ void Square::execute() const
       break;
 
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Square Unsupported type.");
   }
 }
 
index 3bafeba..ca76052 100644 (file)
@@ -46,7 +46,7 @@ void SquaredDifference::execute() const
       evalSquaredDifference<float>();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp SquaredDifference Unsupported type.");
   }
 }
 
index a8730d8..993256b 100644 (file)
@@ -141,8 +141,18 @@ void StridedSlice::execute() const
                                           getTensorData<int32_t>(input()), getTensorShape(output()),
                                           getTensorData<int32_t>(output()));
       break;
+    case DataType::S64:
+      tflite::reference_ops::StridedSlice(op_params, getTensorShape(input()),
+                                          getTensorData<int64_t>(input()), getTensorShape(output()),
+                                          getTensorData<int64_t>(output()));
+      break;
+    case DataType::BOOL:
+      tflite::reference_ops::StridedSlice(op_params, getTensorShape(input()),
+                                          getTensorData<bool>(input()), getTensorShape(output()),
+                                          getTensorData<bool>(output()));
+      break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp StridedSlice Unsupported type.");
   }
 }
 
index 1fd583c..abceb6f 100644 (file)
@@ -58,7 +58,7 @@ void Sub::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Sub Unsupported type.");
   }
 }
 
index 645f02c..ef870e4 100644 (file)
@@ -149,7 +149,7 @@ void Sum::execute() const
       evalFloat();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Sum Unsupported type.");
   }
 }
 
index d47a0bd..7cb59be 100644 (file)
@@ -49,7 +49,7 @@ void Tanh::execute() const
       evalQuantized();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Tanh Unsupported type.");
   }
 }
 
diff --git a/compiler/luci-interpreter/src/kernels/Tile.cpp b/compiler/luci-interpreter/src/kernels/Tile.cpp
new file mode 100644 (file)
index 0000000..0ab93f5
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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/Tile.h"
+
+#include "kernels/Utils.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+Tile::Tile(const Tensor *input, const Tensor *multiples, Tensor *output)
+  : Kernel({input, multiples}, {output})
+{
+}
+
+void Tile::configure()
+{
+  LUCI_INTERPRETER_CHECK(input()->shape().num_dims() >= 1);
+  LUCI_INTERPRETER_CHECK(multiples()->shape().num_dims() == 1);
+  LUCI_INTERPRETER_CHECK(multiples()->shape().dim(0) == input()->shape().num_dims());
+  LUCI_INTERPRETER_CHECK(multiples()->element_type() == DataType::S32);
+
+  Shape output_shape(input()->shape().num_dims());
+  const int32_t *muldata = getTensorData<int32_t>(multiples());
+  int32_t num_dim = multiples()->shape().dim(0);
+  for (int32_t dim = 0; dim < num_dim; ++dim)
+  {
+    output_shape.dim(dim) = input()->shape().dim(dim) * muldata[dim];
+  }
+  output()->resize(output_shape);
+}
+
+void Tile::execute() const
+{
+  switch (output()->element_type())
+  {
+    case DataType::FLOAT32:
+      evalFloat();
+      break;
+    default:
+      throw std::runtime_error("luci-intp Tile Unsupported type.");
+  }
+}
+
+namespace
+{
+
+template <typename T, typename M>
+void CopyMultipleTimes(const T *in_data, int32_t in_size, M multiplier, T *out_data)
+{
+  for (M i = 0; i < multiplier; ++i)
+  {
+    const T *in_end = in_data + in_size;
+    T *new_out_data = std::copy(in_data, in_end, out_data);
+    in_data = out_data;
+    out_data = new_out_data;
+  }
+}
+
+template <typename T, typename M>
+std::pair<int, int> TileOneDimension(const tflite::RuntimeShape &in_dimensions, const T *in_data,
+                                     const M *multiples, T *out_data, int dimension)
+{
+  if (in_dimensions.DimensionsCount() == 0)
+  {
+    // If input tensor is a scalar, then just copy it to output (no need to multiply).
+    *out_data = *in_data;
+    return std::make_pair(0, 0);
+  }
+
+  const int dimension_size = in_dimensions.Dims(dimension);
+  if (dimension == in_dimensions.DimensionsCount() - 1)
+  {
+    CopyMultipleTimes(in_data, dimension_size, multiples[dimension], out_data);
+    return std::make_pair(dimension_size, dimension_size * static_cast<int>(multiples[dimension]));
+  }
+
+  int total_stride_size = 0, total_tiled_stride_size = 0;
+  const T *copy_from_data = in_data;
+  T *copy_to_data = out_data;
+  for (int i = 0; i < dimension_size; ++i)
+  {
+    int stride_size = 0, tiled_stride_size = 0;
+    std::tie(stride_size, tiled_stride_size) =
+      TileOneDimension(in_dimensions, copy_from_data, multiples, copy_to_data, dimension + 1);
+    copy_from_data += stride_size;
+    copy_to_data += tiled_stride_size;
+    total_stride_size += stride_size;
+    total_tiled_stride_size += tiled_stride_size;
+  }
+  CopyMultipleTimes(out_data, total_tiled_stride_size, multiples[dimension] - 1,
+                    out_data + total_tiled_stride_size);
+  return std::make_pair(total_stride_size,
+                        static_cast<int>(total_tiled_stride_size * multiples[dimension]));
+}
+
+} // namespace
+
+void Tile::evalFloat() const
+{
+  TileOneDimension(getTensorShape(input()), getTensorData<float>(input()),
+                   getTensorData<int32_t>(multiples()), getTensorData<float>(output()), 0);
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/kernels/Tile.h b/compiler/luci-interpreter/src/kernels/Tile.h
new file mode 100644 (file)
index 0000000..7e3302c
--- /dev/null
@@ -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_INTERPRETER_KERNELS_TILE_H
+#define LUCI_INTERPRETER_KERNELS_TILE_H
+
+#include "core/Kernel.h"
+#include "core/KernelParams.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+class Tile : public Kernel
+{
+public:
+  Tile(const Tensor *input, const Tensor *multiplies, Tensor *output);
+
+  const Tensor *input() const { return _inputs[0]; }
+  const Tensor *multiples() 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_TILE_H
diff --git a/compiler/luci-interpreter/src/kernels/Tile.test.cpp b/compiler/luci-interpreter/src/kernels/Tile.test.cpp
new file mode 100644 (file)
index 0000000..2bb5c12
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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/Tile.h"
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/TestMemoryManager.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+namespace
+{
+
+using namespace testing;
+
+TEST(TileTest, FloatMul12)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  Shape input_shape{1, 3};
+  std::vector<float> input_data{1.0f, 2.0f, 3.0f};
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  Shape mul_shape{2};
+  std::vector<int32_t> mul_data{1, 2};
+  Tensor mul_tensor = makeInputTensor<DataType::S32>(mul_shape, mul_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  Tile kernel(&input_tensor, &mul_tensor, &output_tensor);
+  kernel.configure();
+  memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  std::vector<int32_t> ref_output_shape{1, 6};
+  std::vector<float> ref_output_data{1.0f, 2.0f, 3.0f, 1.0f, 2.0f, 3.0f};
+  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST(TileTest, FloatMul21)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  Shape input_shape{1, 3};
+  std::vector<float> input_data{1.0f, 2.0f, 3.0f};
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  Shape mul_shape{2};
+  std::vector<int32_t> mul_data{2, 1};
+  Tensor mul_tensor = makeInputTensor<DataType::S32>(mul_shape, mul_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  Tile kernel(&input_tensor, &mul_tensor, &output_tensor);
+  kernel.configure();
+  memory_manager->allocate_memory(output_tensor);
+  kernel.execute();
+
+  std::vector<int32_t> ref_output_shape{2, 3};
+  std::vector<float> ref_output_data{1.0f, 2.0f, 3.0f, 1.0f, 2.0f, 3.0f};
+  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+}
+
+TEST(TileTest, MultiplesShapeInvalid_NEG)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  Shape input_shape{1, 3};
+  std::vector<float> input_data{1.0f, 2.0f, 3.0f};
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  Shape mul_shape{3};
+  std::vector<int32_t> mul_data{1, 2, 3};
+  Tensor mul_tensor = makeInputTensor<DataType::S32>(mul_shape, mul_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  Tile kernel(&input_tensor, &mul_tensor, &output_tensor);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(TileTest, MultiplesDTypeInvalid_NEG)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  Shape input_shape{1, 3};
+  std::vector<float> input_data{1.0f, 2.0f, 3.0f};
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  Shape mul_shape{2};
+  std::vector<float> mul_data{1.0f, 2.0f};
+  Tensor mul_tensor = makeInputTensor<DataType::FLOAT32>(mul_shape, mul_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+
+  Tile kernel(&input_tensor, &mul_tensor, &output_tensor);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+TEST(TileTest, MultiplesDimInvalid_NEG)
+{
+  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  Shape input_shape{1, 3};
+  std::vector<float> input_data{1.0f, 2.0f, 3.0f};
+  Tensor input_tensor =
+    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
+  Shape mul_shape{3};
+  std::vector<int32_t> mul_data{1, 2, 3};
+  Tensor mul_tensor = makeInputTensor<DataType::S32>(mul_shape, mul_data, memory_manager.get());
+  Tensor output_tensor = makeOutputTensor(DataType::S32);
+
+  Tile kernel(&input_tensor, &mul_tensor, &output_tensor);
+  EXPECT_ANY_THROW(kernel.configure());
+}
+
+} // namespace
+} // namespace kernels
+} // namespace luci_interpreter
index 802d872..725a952 100644 (file)
@@ -70,13 +70,18 @@ void Transpose::execute() const
                                        getTensorData<float>(input()), getTensorShape(output()),
                                        getTensorData<float>(output()));
       break;
+    case DataType::S64:
+      tflite::reference_ops::Transpose(params, getTensorShape(input()),
+                                       getTensorData<int64_t>(input()), getTensorShape(output()),
+                                       getTensorData<int64_t>(output()));
+      break;
     case DataType::U8:
       tflite::reference_ops::Transpose(params, getTensorShape(input()),
                                        getTensorData<uint8_t>(input()), getTensorShape(output()),
                                        getTensorData<uint8_t>(output()));
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Transpose Unsupported type.");
   }
 }
 
index 43be8f8..a41db63 100644 (file)
@@ -51,7 +51,7 @@ template <typename T> class TransposeTest : public ::testing::Test
 {
 };
 
-using DataTypes = ::testing::Types<float, uint8_t>;
+using DataTypes = ::testing::Types<float, int64_t, uint8_t>;
 TYPED_TEST_SUITE(TransposeTest, DataTypes);
 
 TYPED_TEST(TransposeTest, Small3D)
index 08bfbf3..01bdd80 100644 (file)
@@ -115,18 +115,26 @@ void TransposeConv::execute() const
       evalQuantizedS16();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp TransposeConv Unsupported type.");
   }
 }
 
 void TransposeConv::evalFloat() const
 {
+  float activation_min{};
+  float activation_max{};
+  // TODO support activation
+  assert(_params.activation == Activation::NONE);
+  calculateActivationRange(Activation::NONE, &activation_min, &activation_max);
+
   tflite::ConvParams op_params{};
   op_params.padding_type = tflite::PaddingType::kSame;
   op_params.padding_values.height = _padding_height;
   op_params.padding_values.width = _padding_width;
   op_params.stride_height = params().stride_height;
   op_params.stride_width = params().stride_width;
+  op_params.float_activation_min = activation_min;
+  op_params.float_activation_max = activation_max;
   tflite::reference_ops::TransposeConv(op_params,                                                //
                                        getTensorShape(input()), getTensorData<float>(input()),   //
                                        getTensorShape(filter()), getTensorData<float>(filter()), //
index 9127241..bd38b5d 100644 (file)
@@ -76,7 +76,7 @@ void Unpack::execute() const
     case DataType::U8:
       return executeImpl<uint8_t>();
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp Unpack Unsupported type.");
   }
 }
 
index a04dbcc..edd8761 100644 (file)
@@ -124,10 +124,18 @@ void calculateActivationRangeQuantized(Activation activation, const Tensor *outp
   int32_t qmax{};
   switch (output->element_type())
   {
+    case DataType::U4:
+      qmin = 0;
+      qmax = 15;
+      break;
     case DataType::U8:
       qmin = 0;
       qmax = std::numeric_limits<uint8_t>::max();
       break;
+    case DataType::S4:
+      qmin = -8;
+      qmax = 7;
+      break;
     case DataType::S8:
       qmin = -std::numeric_limits<int8_t>::max();
       qmax = std::numeric_limits<int8_t>::max();
@@ -139,7 +147,7 @@ void calculateActivationRangeQuantized(Activation activation, const Tensor *outp
       qmax = std::numeric_limits<int16_t>::max();
       break;
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp (calculateActivationRangeQuantized) Unsupported type.");
   }
 
   calculateActivationRangeQuantizedImpl(activation, qmin, qmax, output, activation_min,
index ba99a57..cf83713 100644 (file)
@@ -54,10 +54,14 @@ const void *getNodeData(const luci::CircleConst *node, size_t *data_size)
 {
   switch (node->dtype())
   {
+    case DataType::U4:
+      return getNodeDataImpl<DataType::U4>(node, data_size);
     case DataType::U8:
       return getNodeDataImpl<DataType::U8>(node, data_size);
     case DataType::FLOAT32:
       return getNodeDataImpl<DataType::FLOAT32>(node, data_size);
+    case DataType::S4:
+      return getNodeDataImpl<DataType::S4>(node, data_size);
     case DataType::S8:
       return getNodeDataImpl<DataType::S8>(node, data_size);
     case DataType::S16:
@@ -69,7 +73,7 @@ const void *getNodeData(const luci::CircleConst *node, size_t *data_size)
     case DataType::BOOL:
       return getNodeDataImpl<DataType::BOOL>(node, data_size);
     default:
-      throw std::runtime_error("Unsupported type.");
+      throw std::runtime_error("luci-intp (getNodeData) Unsupported type.");
   }
 }
 
index 10a01f4..128d1a4 100644 (file)
@@ -25,6 +25,8 @@
 #include <kernels/Cast.h>
 #include <kernels/Concatenation.h>
 #include <kernels/Conv2D.h>
+#include <kernels/Cos.h>
+#include <kernels/CumSum.h>
 #include <kernels/DepthToSpace.h>
 #include <kernels/DepthwiseConv2D.h>
 #include <kernels/Div.h>
@@ -67,6 +69,7 @@
 #include <kernels/ResizeNearestNeighbor.h>
 #include <kernels/ReverseV2.h>
 #include <kernels/Rsqrt.h>
+#include <kernels/Sin.h>
 #include <kernels/Slice.h>
 #include <kernels/Softmax.h>
 #include <kernels/SpaceToDepth.h>
@@ -78,6 +81,7 @@
 #include <kernels/StridedSlice.h>
 #include <kernels/Sub.h>
 #include <kernels/Tanh.h>
+#include <kernels/Tile.h>
 #include <kernels/Transpose.h>
 #include <kernels/TransposeConv.h>
 #include <kernels/Unpack.h>
@@ -99,7 +103,7 @@ protected:
 
   std::unique_ptr<IMemoryManager> _memory_manager;
 
-  template <typename NodeT, typename... Args> NodeT *createNode(Args &&... args)
+  template <typename NodeT, typename... Args> NodeT *createNode(Args &&...args)
   {
     auto *node = _graph.nodes()->create<NodeT>(std::forward<Args>(args)...);
     // The actual type does not matter for the purpose of the tests.
@@ -299,6 +303,42 @@ TEST_F(KernelBuilderTest, Conv2D)
   EXPECT_THAT(kernel->params().activation, Eq(op->fusedActivationFunction()));
 }
 
+TEST_F(KernelBuilderTest, Cos)
+{
+  auto *input = createInputNode();
+
+  auto *op = createNode<luci::CircleCos>();
+  op->x(input);
+
+  auto kernel = buildKernel<kernels::Cos>(op);
+  ASSERT_THAT(kernel, NotNull());
+
+  checkTensor(kernel->input(), input);
+  checkTensor(kernel->output(), op);
+}
+
+TEST_F(KernelBuilderTest, CumSum)
+{
+  auto *input = createInputNode();
+  auto *axis = createInputNode();
+
+  auto *op = createNode<luci::CircleCumSum>();
+  op->input(input);
+  op->axis(axis);
+
+  op->exclusive(false);
+  op->reverse(false);
+
+  auto kernel = buildKernel<kernels::CumSum>(op);
+  ASSERT_THAT(kernel, NotNull());
+
+  checkTensor(kernel->input(), input);
+  checkTensor(kernel->axis(), axis);
+  checkTensor(kernel->output(), op);
+  EXPECT_THAT(kernel->params().exclusive, Eq(op->exclusive()));
+  EXPECT_THAT(kernel->params().reverse, Eq(op->reverse()));
+}
+
 TEST_F(KernelBuilderTest, DepthToSpace)
 {
   auto *input = createInputNode();
@@ -1069,6 +1109,20 @@ TEST_F(KernelBuilderTest, Rsqrt)
   checkTensor(kernel->output(), op);
 }
 
+TEST_F(KernelBuilderTest, Sin)
+{
+  auto *input = createInputNode();
+
+  auto *op = createNode<luci::CircleSin>();
+  op->x(input);
+
+  auto kernel = buildKernel<kernels::Sin>(op);
+  ASSERT_THAT(kernel, NotNull());
+
+  checkTensor(kernel->input(), input);
+  checkTensor(kernel->output(), op);
+}
+
 TEST_F(KernelBuilderTest, Slice)
 {
   auto *input = createInputNode();
@@ -1286,6 +1340,23 @@ TEST_F(KernelBuilderTest, Tanh)
   checkTensor(kernel->output(), op);
 }
 
+TEST_F(KernelBuilderTest, Tile)
+{
+  auto *input = createInputNode();
+  auto *multiples = createInputNode();
+
+  auto *op = createNode<luci::CircleTile>();
+  op->input(input);
+  op->multiples(multiples);
+
+  auto kernel = buildKernel<kernels::Tile>(op);
+  ASSERT_THAT(kernel, NotNull());
+
+  checkTensor(kernel->input(), input);
+  checkTensor(kernel->multiples(), multiples);
+  checkTensor(kernel->output(), op);
+}
+
 TEST_F(KernelBuilderTest, Transpose)
 {
   auto *input = createInputNode();
diff --git a/compiler/luci-interpreter/src/loader/nodes/BroadcastTo.cpp b/compiler/luci-interpreter/src/loader/nodes/BroadcastTo.cpp
new file mode 100644 (file)
index 0000000..a08bcaf
--- /dev/null
@@ -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.
+ */
+
+#include "Builders.h"
+
+#include "kernels/BroadcastTo.h"
+
+namespace luci_interpreter
+{
+
+std::unique_ptr<Kernel> build_kernel_CircleBroadcastTo(const luci::CircleNode *circle_node,
+                                                       KernelBuilderHelper &helper)
+{
+  const auto *node = loco::must_cast<const luci::CircleBroadcastTo *>(circle_node);
+  assert(node->arity() == 2);
+
+  const Tensor *input = helper.getInputTensor(node->input());
+  const Tensor *shape = helper.getInputTensor(node->shape());
+  Tensor *output = helper.getOutputTensor(node);
+
+  return std::make_unique<kernels::BroadcastTo>(input, shape, output);
+}
+
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/nodes/Cos.cpp b/compiler/luci-interpreter/src/loader/nodes/Cos.cpp
new file mode 100644 (file)
index 0000000..c1e1b21
--- /dev/null
@@ -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 "Builders.h"
+
+#include "kernels/Cos.h"
+
+namespace luci_interpreter
+{
+
+std::unique_ptr<Kernel> build_kernel_CircleCos(const luci::CircleNode *circle_node,
+                                               KernelBuilderHelper &helper)
+{
+  const auto *node = loco::must_cast<const luci::CircleCos *>(circle_node);
+  assert(node->arity() == 1);
+
+  const Tensor *input = helper.getInputTensor(node->x());
+  Tensor *output = helper.getOutputTensor(node);
+
+  return std::make_unique<kernels::Cos>(input, output);
+}
+
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/nodes/CumSum.cpp b/compiler/luci-interpreter/src/loader/nodes/CumSum.cpp
new file mode 100644 (file)
index 0000000..a12e1b6
--- /dev/null
@@ -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.
+ */
+
+#include "Builders.h"
+
+#include "kernels/CumSum.h"
+
+namespace luci_interpreter
+{
+
+std::unique_ptr<Kernel> build_kernel_CircleCumSum(const luci::CircleNode *circle_node,
+                                                  KernelBuilderHelper &helper)
+{
+  const auto *node = loco::must_cast<const luci::CircleCumSum *>(circle_node);
+  const Tensor *input = helper.getInputTensor(node->input());
+  const Tensor *axis = helper.getInputTensor(node->axis());
+  Tensor *output = helper.getOutputTensor(node);
+
+  CumSumParams params{};
+  params.exclusive = node->exclusive();
+  params.reverse = node->reverse();
+
+  return std::make_unique<kernels::CumSum>(input, axis, output, params);
+}
+
+} // namespace luci_interpreter
index b7b742b..d0a53ac 100644 (file)
@@ -35,7 +35,19 @@ std::unique_ptr<Kernel> build_kernel_CircleFullyConnected(const luci::CircleNode
   FullyConnectedParams params{};
   params.activation = node->fusedActivationFunction();
   params.keep_num_dims = node->keep_num_dims();
-
+  if (weights->element_type() == loco::DataType::S4 ||
+      weights->element_type() == loco::DataType::U4)
+  {
+    auto scratchpad =
+      std::make_unique<Tensor>(input->element_type(), weights->shape(), AffineQuantization{}, "");
+    scratchpad->set_observable(false);
+    scratchpad->set_data_buffer(nullptr);
+    Tensor *scratchpad_tmp =
+      helper.getRuntimeGraph(node->graph())->addTensor(std::move(scratchpad));
+    helper.getRuntimeGraph(node->graph())->configureAllocations(scratchpad_tmp);
+    return std::make_unique<kernels::FullyConnected>(input, weights, bias, output, scratchpad_tmp,
+                                                     params);
+  }
   return std::make_unique<kernels::FullyConnected>(input, weights, bias, output, params);
 }
 
diff --git a/compiler/luci-interpreter/src/loader/nodes/Relu0To1.cpp b/compiler/luci-interpreter/src/loader/nodes/Relu0To1.cpp
new file mode 100644 (file)
index 0000000..10a93a1
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/Relu0To1.h"
+
+namespace luci_interpreter
+{
+
+std::unique_ptr<Kernel> build_kernel_CircleRelu0To1(const luci::CircleNode *circle_node,
+                                                    KernelBuilderHelper &helper)
+{
+  const auto *node = loco::must_cast<const luci::CircleRelu0To1 *>(circle_node);
+  assert(node->arity() == 1);
+
+  const Tensor *input = helper.getInputTensor(node->features());
+  Tensor *output = helper.getOutputTensor(node);
+
+  return std::make_unique<kernels::Relu0To1>(input, output);
+}
+
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/nodes/SelectV2.cpp b/compiler/luci-interpreter/src/loader/nodes/SelectV2.cpp
new file mode 100644 (file)
index 0000000..92e5263
--- /dev/null
@@ -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 "Builders.h"
+
+#include "kernels/SelectV2.h"
+
+namespace luci_interpreter
+{
+
+std::unique_ptr<Kernel> build_kernel_CircleSelectV2(const luci::CircleNode *circle_node,
+                                                    KernelBuilderHelper &helper)
+{
+  const auto *node = loco::must_cast<const luci::CircleSelectV2 *>(circle_node);
+  assert(node->arity() == 3);
+
+  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::SelectV2>(c, t, e, output);
+}
+
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/nodes/Sin.cpp b/compiler/luci-interpreter/src/loader/nodes/Sin.cpp
new file mode 100644 (file)
index 0000000..b20062a
--- /dev/null
@@ -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 "Builders.h"
+
+#include "kernels/Sin.h"
+
+namespace luci_interpreter
+{
+
+std::unique_ptr<Kernel> build_kernel_CircleSin(const luci::CircleNode *circle_node,
+                                               KernelBuilderHelper &helper)
+{
+  const auto *node = loco::must_cast<const luci::CircleSin *>(circle_node);
+  assert(node->arity() == 1);
+
+  const Tensor *input = helper.getInputTensor(node->x());
+  Tensor *output = helper.getOutputTensor(node);
+
+  return std::make_unique<kernels::Sin>(input, output);
+}
+
+} // namespace luci_interpreter
diff --git a/compiler/luci-interpreter/src/loader/nodes/Tile.cpp b/compiler/luci-interpreter/src/loader/nodes/Tile.cpp
new file mode 100644 (file)
index 0000000..2e8c178
--- /dev/null
@@ -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.
+ */
+
+#include "Builders.h"
+
+#include "kernels/Tile.h"
+
+namespace luci_interpreter
+{
+
+std::unique_ptr<Kernel> build_kernel_CircleTile(const luci::CircleNode *circle_node,
+                                                KernelBuilderHelper &helper)
+{
+  const auto *node = loco::must_cast<const luci::CircleTile *>(circle_node);
+  assert(node->arity() == 2);
+
+  const Tensor *input = helper.getInputTensor(node->input());
+  const Tensor *multiples = helper.getInputTensor(node->multiples());
+  Tensor *output = helper.getOutputTensor(node);
+
+  return std::make_unique<kernels::Tile>(input, multiples, output);
+}
+
+} // namespace luci_interpreter
diff --git a/compiler/luci-pass-value-py-test/CMakeLists.txt b/compiler/luci-pass-value-py-test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9b59ae6
--- /dev/null
@@ -0,0 +1,53 @@
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_12_1")
+set(TEST_LIST_FILE "test.lst")
+
+get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
+
+macro(eval RECIPE PASS_OPTION)
+  set(CIRCLE_FILE "${RECIPE}.circle")
+  set(CIRCLE_PATH "${ARTIFACTS_BIN_PATH}/${CIRCLE_FILE}")
+
+  set(PASS_CIRCLE_FILE "${RECIPE}.pass.circle")
+  set(PASS_CIRCLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PASS_CIRCLE_FILE}")
+
+  set(DASH_PASS_OPTION "--${PASS_OPTION}")
+  foreach(MORE_OPTIONS ${ARGN})
+    list(APPEND DASH_PASS_OPTION "--${MORE_OPTIONS}")
+  endforeach()
+  # NOTE if there are two options, 'DASH_PASS_OPTION' will be like '--option_a;--option_b'
+  #      add_custom_command() will translate ';' to two arguments as '--optiona_a --optionb'
+  #      do not use set(DASH_PASS_OPTION "${DASH_PASS_OPTION} --${ARG}"))
+  #      as this will become like '"--optiona_a --optionb"' which is one string argument
+
+  # Generate optimized .circle
+  add_custom_command(OUTPUT ${PASS_CIRCLE_OUTPUT_PATH}
+    COMMAND $<TARGET_FILE:circle2circle> ${DASH_PASS_OPTION} ${CIRCLE_PATH} ${PASS_CIRCLE_OUTPUT_PATH}
+    DEPENDS $<TARGET_FILE:circle2circle> ${CIRCLE_PATH}
+    COMMENT "Generate ${PASS_CIRCLE_FILE} with ${DASH_PASS_OPTION}"
+  )
+
+  # depends
+  list(APPEND TEST_DEPS ${PASS_CIRCLE_OUTPUT_PATH})
+
+endmacro(eval)
+
+# Read "test.lst"
+include("test.lst")
+# Read "test.local.lst" if exists
+include("test.local.lst" OPTIONAL)
+
+add_custom_target(luci_pass_value_py_test_files ALL DEPENDS ${TEST_DEPS})
+add_dependencies(luci_pass_value_py_test_files common_artifacts_deps)
+
+add_test(NAME luci_pass_value_py_test
+  COMMAND ${VIRTUALENV}/bin/python -m pytest -sv test_luci_eval.py
+        --test_list ${TEST_LIST_FILE}
+        --tflite_dir ${ARTIFACTS_BIN_PATH}
+        --circle_dir ${CMAKE_CURRENT_BINARY_DIR}
+        --luci_eval_driver $<TARGET_FILE:luci_eval_driver>
+  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
diff --git a/compiler/luci-pass-value-py-test/README.md b/compiler/luci-pass-value-py-test/README.md
new file mode 100644 (file)
index 0000000..8d5626e
--- /dev/null
@@ -0,0 +1,20 @@
+# luci-pass-value-py-test
+
+`luci-pass-value-py-test` validates execution result values of tflite model and
+circle model generated with specific optimization.
+
+The test proceeds as follows:
+
+Step 0: Use tflite and circle file in 'common-artifacts' folder as the source model.
+   - tflite file is used as to generate reference execution result
+   - circle file is used as source of optimization to apply
+
+Step 1: Run circle2circle with given optimization option to produce transformed circle.
+   - "modelfile.circle" -> circle2circle -> "modelfile.pass.circle"
+
+Step 2: Run TFLite interpreter and luci-interpreter for the source tflite and circle, respectively.
+        (with the same input tensors filled with random values)
+   - "modelfile.tflite" ------> TFLite interpreter -> Execution result 1
+   - "modelfile.pass.circle" -> luci-interpreter ---> Execution result 2
+
+Step 3: Compare the execution result 1 and 2. Test is PASSED if results are sames.
diff --git a/compiler/luci-pass-value-py-test/conftest.py b/compiler/luci-pass-value-py-test/conftest.py
new file mode 100644 (file)
index 0000000..be8fa3b
--- /dev/null
@@ -0,0 +1,40 @@
+import re
+
+
+def extract_test_args(s):
+    p = re.compile('eval\\((.*)\\)')
+    result = p.search(s)
+    return result.group(1)
+
+
+def pytest_addoption(parser):
+    parser.addoption("--test_list", action="store", help="Path to test list")
+    parser.addoption(
+        "--tflite_dir", action="store", help="Directory including tflite file")
+    parser.addoption(
+        "--circle_dir", action="store", help="Directory including circle file")
+    parser.addoption(
+        "--luci_eval_driver", action="store", help="Path to luci eval driver")
+
+
+def pytest_generate_tests(metafunc):
+    list_path = metafunc.config.getoption('test_list')
+    tflite_dir = metafunc.config.getoption('tflite_dir')
+    circle_dir = metafunc.config.getoption('circle_dir')
+    eval_driver_path = metafunc.config.getoption('luci_eval_driver')
+    if list_path is None:
+        tests_default_tol = []
+    else:
+        with open(list_path) as f:
+            contents = [line.rstrip() for line in f]
+
+        comment_removed = [line for line in contents if not line.startswith('#')]
+        newline_removed = [line for line in comment_removed if line.startswith('eval(')]
+        test_args = [extract_test_args(line) for line in newline_removed]
+        # eval(TEST_NAME PASS_1 PASS_2 ..)
+        tests_default_tol = [(arg.split()[0], tflite_dir, circle_dir, eval_driver_path)
+                             for arg in test_args]
+
+    if 'test_name' in metafunc.fixturenames:
+        metafunc.parametrize('test_name,tflite_dir,circle_dir,eval_driver_path',
+                             tests_default_tol)
diff --git a/compiler/luci-pass-value-py-test/requires.cmake b/compiler/luci-pass-value-py-test/requires.cmake
new file mode 100644 (file)
index 0000000..19be721
--- /dev/null
@@ -0,0 +1,3 @@
+require("common-artifacts")
+require("luci-eval-driver")
+require("circle2circle")
diff --git a/compiler/luci-pass-value-py-test/test.lst b/compiler/luci-pass-value-py-test/test.lst
new file mode 100644 (file)
index 0000000..287ddcb
--- /dev/null
@@ -0,0 +1,87 @@
+#
+# Format:
+#   eval(MODEL PASS)
+# MODEL: tflite model file name in build/compiler/common-artifacts folder.
+# PASS: Optimization Pass to test. Supports only one Pass for now.
+#
+
+# eval(Net_Preactivation_BN_000 fuse_preactivation_batchnorm) : value diff exist
+# --> https://github.com/Samsung/ONE/issues/5782
+eval(FullyConnected_007 replace_non_const_fc_with_batch_matmul)
+eval(HardSwish_001 decompose_hardswish)
+eval(Net_Add_FloorMod_Gather_000 remove_gather_guard)
+eval(Net_Add_FullyConnected_000 fuse_add_to_fullyconnected_bias)
+eval(Net_Add_FullyConnected_001 fuse_add_to_fullyconnected_bias)
+eval(Net_Add_FullyConnected_002 fuse_add_to_fullyconnected_bias)
+eval(Net_Conv_Add_000 fuse_add_with_conv)
+eval(Net_Conv_Add_001 fuse_add_with_conv)
+# eval(Net_Conv_Add_002 fuse_add_with_conv) --> Conv2D w/o bias fails in tflite interpreter
+eval(Net_Conv_Add_Mul_000 fuse_batchnorm_with_conv)
+eval(Net_Conv_Add_Mul_000 fuse_batchnorm_with_conv)
+eval(Net_Conv_Add_Mul_001 fuse_batchnorm_with_conv)
+eval(Net_Conv_Add_Mul_002 fuse_batchnorm_with_conv)
+eval(Net_Conv_Min_Max_000 transform_min_max_to_relu6)
+eval(Net_Conv_Min_Relu_000 transform_min_relu_to_relu6)
+eval(Net_Conv_Mul_000 fuse_mul_with_conv)
+eval(Net_Conv_Mul_001 fuse_mul_with_conv)
+eval(Net_Conv_Mul_002 fuse_mul_with_conv)
+eval(Net_Conv_Mul_003 fuse_mul_with_conv)
+eval(Net_Conv_PReluGraph_000 fuse_prelu)
+eval(Net_Conv_Relu6_000 fuse_activation_function)
+eval(Net_Densify_Add_000 fold_densify)
+eval(Net_Dequantize_Add_000 fold_dequantize)
+eval(Net_DwConv_BN_000 fuse_batchnorm_with_dwconv)
+eval(Net_DwConv_BN_001 fuse_batchnorm_with_dwconv)
+eval(Net_FullyConnected_Add_000 fold_fully_connected)
+eval(Net_Horizontal_FullyConnected_Add_000 fuse_horizontal_fc_layers)
+eval(Net_InstanceNorm_001 fuse_instnorm)
+eval(Net_InstanceNorm_002 fuse_instnorm)
+eval(Net_InstanceNorm_003 fuse_instnorm)
+eval(Net_Mul_Add_000 remove_unnecessary_add)
+eval(Net_Mul_Add_001 remove_unnecessary_add)
+eval(Net_Mul_Add_002 remove_unnecessary_add)
+eval(Net_Mul_Add_003 remove_unnecessary_add)
+eval(Net_Mul_Div_000 fuse_mul_with_div)
+eval(Net_Mul_Div_001 fuse_mul_with_div)
+eval(Net_Mul_FullyConnected_000 fuse_mul_to_fullyconnected_weights)
+eval(Net_Mul_FullyConnected_001 fuse_mul_to_fullyconnected_weights)
+eval(Net_Mul_FullyConnected_002 fuse_mul_to_fullyconnected_weights)
+eval(Net_Reshape_Mean_000 forward_reshape_to_unaryop)
+eval(Net_Reshape_Neg_000 forward_reshape_to_unaryop)
+eval(Net_Reshape_Reshape_000 remove_redundant_reshape)
+eval(Net_Shape_Add_000 fold_shape)
+eval(Net_Sqrt_Div_000 transform_sqrt_div_to_rsqrt_mul)
+eval(Net_Squeeze_Squeeze_000 substitute_squeeze_to_reshape)
+eval(Net_StridedSlice_StridedSlice_000 remove_unnecessary_strided_slice)
+eval(Net_TConv_Add_000 fuse_add_with_tconv)
+eval(Net_TConv_Add_001 fuse_add_with_tconv)
+eval(Net_TConv_Add_002 fuse_add_with_tconv)
+eval(Net_TConv_BN_000 fuse_batchnorm_with_tconv)
+eval(Net_TConv_BN_001 fuse_batchnorm_with_tconv)
+eval(Net_TConv_BN_002 fuse_batchnorm_with_tconv)
+eval(Net_TConv_BN_003 fuse_batchnorm_with_tconv)
+eval(Net_TConv_BN_004 fuse_batchnorm_with_tconv)
+eval(Net_TConv_BN_005 fuse_batchnorm_with_tconv)
+eval(Net_TConv_Slice_000 fuse_slice_with_tconv)
+eval(Net_TConv_Slice_001 fuse_slice_with_tconv)
+eval(Net_TConv_Slice_002 fuse_slice_with_tconv)
+eval(Net_TConv_Slice_003 fuse_slice_with_tconv)
+eval(Net_Trans_Reshape_Trans_000 remove_unnecessary_transpose)
+eval(Net_Transpose_Add_000 forward_transpose_op)
+eval(Net_Transpose_Abs_000 forward_transpose_op)
+eval(Softmax_001 decompose_softmax)
+eval(Softmax_002 decompose_softmax)
+eval(UnidirectionalSequenceLSTM_003 unroll_unidirseqlstm)
+eval(UnidirectionalSequenceLSTM_004 unroll_unidirseqlstm)
+
+# test for limited support for FLOAT16
+eval(Net_Densify_Dequantize_Add_000 fold_dequantize fold_densify)
+eval(Net_Dequantize_Add_000 fold_dequantize)
+
+# test SignatureDef, with any optimization
+#eval(SignatureDef_MultiOut_000 fuse_instnorm)
+#eval(SignatureDef_MultiOut_001 fuse_instnorm)
+
+# test for common subexpression elimination
+eval(CSE_Quantize_000 common_subexpression_elimination)
+eval(CSE_Transpose_000 common_subexpression_elimination)
diff --git a/compiler/luci-pass-value-py-test/test_luci_eval.py b/compiler/luci-pass-value-py-test/test_luci_eval.py
new file mode 100644 (file)
index 0000000..4cb59c1
--- /dev/null
@@ -0,0 +1,119 @@
+import numpy as np
+import tensorflow as tf
+import subprocess
+import os
+
+
+def luci_eval_verify(test_name,
+                     tflite_dir,
+                     circle_dir,
+                     eval_driver,
+                     rtolf32=1e-5,
+                     atolf32=1e-5):
+    tflite_model = os.path.join(tflite_dir, test_name + ".tflite")
+    circle_model = os.path.join(circle_dir, test_name + ".pass.circle")
+
+    # NOTE reuse f32 value as int value too
+    rtolint = int(rtolf32)
+    atolint = int(atolf32)
+
+    # Build TFLite interpreter.
+    interpreter = tf.lite.Interpreter(tflite_model)
+    interpreter.allocate_tensors()
+
+    # Read SignatureDef and get output tensor id orders for remapping
+    full_signatures = interpreter._get_full_signature_list()
+    full_signatures_outputs_remap = None
+    if full_signatures != None:
+        signature_serving_default = full_signatures.get('serving_default', None)
+        if signature_serving_default != None:
+            signature_outputs = signature_serving_default['outputs']
+
+            full_signatures_outputs_remap = []
+            for index, (key, value) in enumerate(signature_outputs.items()):
+                full_signatures_outputs_remap.append(value)
+
+    # Generate random input data.
+    num_inputs = len(interpreter.get_input_details())
+    for i in range(num_inputs):
+        input_details = interpreter.get_input_details()[i]
+        if input_details["dtype"] == np.float32:
+            input_data = np.array(
+                np.random.random_sample(input_details["shape"]), input_details["dtype"])
+        elif input_details["dtype"] == np.uint8:
+            input_data = np.array(
+                np.random.randint(0, 256, size=input_details["shape"]),
+                input_details["dtype"])
+        elif input_details["dtype"] == np.int16:
+            input_data = np.array(
+                np.random.randint(0, 100, size=input_details["shape"]),
+                input_details["dtype"])
+        elif input_details["dtype"] == np.int32:
+            input_data = np.array(
+                np.random.randint(0, 100, size=input_details["shape"]),
+                input_details["dtype"])
+        elif input_details["dtype"] == np.int64:
+            input_data = np.array(
+                np.random.randint(0, 100, size=input_details["shape"]),
+                input_details["dtype"])
+        elif input_details["dtype"] == np.bool_:
+            input_data = np.array(
+                np.random.choice(a=[True, False], size=input_details["shape"]),
+                input_details["dtype"])
+        else:
+            assert False, "Unsupported input dtype"
+
+        interpreter.set_tensor(input_details["index"], input_data)
+        input_data.tofile(circle_model + ".input" + str(i))
+
+    # Do inference
+    interpreter.invoke()
+
+    # Execute luci interpreter.
+    subprocess.run(
+        [
+            eval_driver, circle_model,
+            str(num_inputs), circle_model + ".input", circle_model + ".output"
+        ],
+        check=True)
+
+    # Compare the results.
+    inpt_output_details = interpreter.get_output_details()
+    for idx in range(len(inpt_output_details)):
+        output_details = inpt_output_details[idx]
+        output_data = np.fromfile(circle_model + ".output" + str(idx),
+                                  output_details["dtype"])
+        shape_file = open(circle_model + ".output" + str(idx) + ".shape", 'r')
+        output_shape = [int(i) for i in shape_file.read().split(',')]
+        luci_output_data = np.reshape(output_data, output_shape)
+        output_tensor = output_details["index"]
+        if full_signatures_outputs_remap != None:
+            output_tensor = full_signatures_outputs_remap[idx]
+        intp_output_data = interpreter.get_tensor(output_tensor)
+        err_msg = "Execution result of " + tflite_model + " does not match with " + circle_model
+        if output_details["dtype"] == np.uint8:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=rtolint, atol=atolint), err_msg
+        elif output_details["dtype"] == np.float32:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=rtolf32, atol=atolf32), err_msg
+        elif output_details["dtype"] == np.int64:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=rtolint, atol=atolint), err_msg
+        elif output_details["dtype"] == np.int32:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=rtolint, atol=atolint), err_msg
+        elif output_details["dtype"] == np.int16:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=rtolint, atol=atolint), err_msg
+        elif output_details["dtype"] == np.bool_:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=0, atol=0), err_msg
+        else:
+            assert False, "Unsupported data type: " + output_details["dtype"]
+
+
+# arguments must be in sync with `conftest.py`
+def test_luci_eval(test_name: str, tflite_dir: str, circle_dir: str,
+                   eval_driver_path: str):
+    luci_eval_verify(test_name, tflite_dir, circle_dir, eval_driver_path)
diff --git a/compiler/luci-pass-value-test/exclude.me b/compiler/luci-pass-value-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 93634b2..d22464c 100644 (file)
@@ -13,6 +13,10 @@ 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(Net_Conv_Mul_000 fuse_mul_with_conv)
+addeval(Net_Conv_Mul_001 fuse_mul_with_conv)
+addeval(Net_Conv_Mul_002 fuse_mul_with_conv)
+addeval(Net_Conv_Mul_003 fuse_mul_with_conv)
 addeval(HardSwish_001 decompose_hardswish)
 addeval(Net_Conv_PReluGraph_000 fuse_prelu)
 addeval(Net_Conv_Relu6_000 fuse_activation_function)
@@ -21,7 +25,12 @@ addeval(Net_Dequantize_Add_000 fold_dequantize)
 addeval(Net_DwConv_BN_000 fuse_batchnorm_with_dwconv)
 addeval(Net_DwConv_BN_001 fuse_batchnorm_with_dwconv)
 addeval(Net_FullyConnected_Add_000 fold_fully_connected)
+addeval(Net_Horizontal_FullyConnected_Add_000 fuse_horizontal_fc_layers)
 addeval(Net_Reshape_Neg_000 forward_reshape_to_unaryop)
+addeval(Net_Mul_Add_000 remove_unnecessary_add)
+addeval(Net_Mul_Add_001 remove_unnecessary_add)
+addeval(Net_Mul_Add_002 remove_unnecessary_add)
+addeval(Net_Mul_Add_003 remove_unnecessary_add)
 addeval(Net_Reshape_Reshape_000 remove_redundant_reshape)
 addeval(Net_Squeeze_Squeeze_000 substitute_squeeze_to_reshape)
 addeval(Net_TConv_Add_000 fuse_add_with_tconv)
@@ -33,6 +42,11 @@ addeval(Net_TConv_BN_002 fuse_batchnorm_with_tconv)
 addeval(Net_TConv_BN_003 fuse_batchnorm_with_tconv)
 addeval(Net_TConv_BN_004 fuse_batchnorm_with_tconv)
 addeval(Net_TConv_BN_005 fuse_batchnorm_with_tconv)
+addeval(Net_TConv_Slice_000 fuse_slice_with_tconv)
+addeval(Net_TConv_Slice_001 fuse_slice_with_tconv)
+addeval(Net_TConv_Slice_002 fuse_slice_with_tconv)
+addeval(Net_TConv_Slice_003 fuse_slice_with_tconv)
+addeval(Net_Trans_Reshape_Trans_000 remove_unnecessary_transpose)
 addeval(Net_InstanceNorm_001 fuse_instnorm)
 addeval(Net_InstanceNorm_002 fuse_instnorm)
 addeval(Net_InstanceNorm_003 fuse_instnorm)
@@ -40,6 +54,8 @@ addeval(Net_StridedSlice_StridedSlice_000 remove_unnecessary_strided_slice)
 addeval(FullyConnected_007 replace_non_const_fc_with_batch_matmul)
 addeval(Net_Transpose_Add_000 forward_transpose_op)
 addeval(Net_Transpose_Abs_000 forward_transpose_op)
+addeval(Softmax_001 decompose_softmax)
+addeval(Softmax_002 decompose_softmax)
 addeval(UnidirectionalSequenceLSTM_003 unroll_unidirseqlstm)
 addeval(UnidirectionalSequenceLSTM_004 unroll_unidirseqlstm)
 
@@ -50,3 +66,7 @@ addeval(Net_Densify_Dequantize_Add_000 fold_dequantize fold_densify)
 # test SignatureDef, with any optimization
 #addeval(SignatureDef_MultiOut_000 fuse_instnorm)
 #addeval(SignatureDef_MultiOut_001 fuse_instnorm)
+
+# test for common subexpression elimination
+addeval(CSE_Quantize_000 common_subexpression_elimination)
+addeval(CSE_Transpose_000 common_subexpression_elimination)
diff --git a/compiler/luci-ref-value-py-test/CMakeLists.txt b/compiler/luci-ref-value-py-test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e147279
--- /dev/null
@@ -0,0 +1,24 @@
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_12_1")
+set(TEST_LIST_FILE "test.lst")
+
+nncc_find_resource(TensorFlowLiteRecipes)
+set(TFLITE_RECIPE_REPO "${TensorFlowLiteRecipes_DIR}")
+
+nncc_find_resource(CircleRecipes)
+set(CIRCLE_RECIPE_REPO "${CircleRecipes_DIR}")
+
+get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
+add_test(NAME luci_ref_value_py_test
+    COMMAND ${VIRTUALENV}/bin/python -m pytest -sv test_luci_eval.py
+            --test_list ${TEST_LIST_FILE}
+            --tflrecipe ${TFLITE_RECIPE_REPO}
+            --circlerecipe ${CIRCLE_RECIPE_REPO}
+            --artifacts ${ARTIFACTS_BIN_PATH}
+            --binary ${CMAKE_CURRENT_BINARY_DIR}
+            --luci_eval_driver $<TARGET_FILE:luci_eval_driver>
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+)
diff --git a/compiler/luci-ref-value-py-test/README.md b/compiler/luci-ref-value-py-test/README.md
new file mode 100644 (file)
index 0000000..56221a4
--- /dev/null
@@ -0,0 +1,28 @@
+# luci-ref-value-py-test
+
+`luci-ref-value-py-test` validates luci IR graph model file (.circle) that current
+`luci-value-py-test` cannot validate, such as tflite models with unsupported
+data types like `INT4`.
+
+The test proceeds as follows:
+
+Step 1: Use tflite file from common-artifacts and generate circle files from tflite file
+(listsed in test.lst).
+```
+"tflite file" -> tflite2circle -> "circle file"
+```
+
+Step 2: Read reference input files and run luci-eval-driver and get output files.
+```
+"circle file" -> luci-evel-driver -> "execution result"
+```
+
+Step 3: Compare with reference output files with the execution result. The result must be the same.
+
+Reference input/output files are text files with simple fixed format like follows.
+- first line is shape like `1,4`
+- second line is data type like `float32`
+- third line is values like `0.1,0.2,0.3,0.4`
+
+Place them in same folder where `test.recipe` file exist, with names `ref.inputN` and `ref.outputN`,
+where `N` is I/O number from `0`.
diff --git a/compiler/luci-ref-value-py-test/conftest.py b/compiler/luci-ref-value-py-test/conftest.py
new file mode 100644 (file)
index 0000000..b7d4690
--- /dev/null
@@ -0,0 +1,118 @@
+import re
+import os
+import shutil
+
+
+def extract_test_args(s):
+    p = re.compile('eval\\((.*)\\)')
+    result = p.search(s)
+    return result.group(1)
+
+
+def pytest_addoption(parser):
+    parser.addoption("--test_list", action="store", help="Path to test list")
+    parser.addoption("--artifacts", action="store", help="Path to test artifacts")
+    parser.addoption("--tflrecipe", action="store", help="Path to tfl recipies")
+    parser.addoption("--circlerecipe", action="store", help="Path to circle recipies")
+    parser.addoption("--binary", action="store", help="Path to test binary")
+    parser.addoption(
+        "--luci_eval_driver", action="store", help="Path to luci eval driver")
+
+
+def copy_if_changed(src_filepath, dst_filepath):
+    do_copy = False
+    if (os.path.isfile(dst_filepath)):
+        file_diff = os.stat(src_filepath).st_mtime - os.stat(dst_filepath).st_mtime
+        if file_diff > 1:
+            print("file:" + src_filepath + " changed, update")
+            do_copy = True
+    else:
+        do_copy = True
+
+    if do_copy:
+        print("file:" + src_filepath + " copy to: " + dst_filepath)
+        shutil.copyfile(src_filepath, dst_filepath)
+
+
+# prepare reference input/output files to build folder for luci-eval-driver
+# from ref data in res/TensorFlowLiteRecipes/*/ref.input* and ref.output*
+# as model_name.ref.input* and model_name.ref.output*
+def copy_ref_files(ref_file_src, ref_file_dst):
+    num_data = 0
+    while True:
+        input_file_src = ref_file_src + str(num_data)
+        if (not os.path.isfile(input_file_src)):
+            break
+        input_file_dst = ref_file_dst + str(num_data)
+        copy_if_changed(input_file_src, input_file_dst)
+        # try next file
+        num_data = num_data + 1
+
+
+# copy circle mode from common-artifacts to build binary
+def copy_circle_model(model_src, model_dst):
+    copy_if_changed(model_src, model_dst)
+
+
+def prepare_materials(test_name, tflrecipe_path, circlerecipe_path, binary_path,
+                      artifacts_path):
+    # tfl? or circle?
+    recipe_path = tflrecipe_path
+    # check with 'test.recipe' file as 'ref.input?' can be absent for no input model
+    test_recipe = os.path.join(recipe_path, test_name, 'test.recipe')
+    if (not os.path.isfile(test_recipe)):
+        recipe_path = circlerecipe_path
+
+    ref_input_src = os.path.join(recipe_path, test_name, 'ref.input')
+    ref_input_dst = os.path.join(binary_path, test_name + '.ref.input')
+    copy_ref_files(ref_input_src, ref_input_dst)
+
+    ref_input_src = os.path.join(recipe_path, test_name, 'ref.output')
+    ref_input_dst = os.path.join(binary_path, test_name + '.ref.output')
+    copy_ref_files(ref_input_src, ref_input_dst)
+
+    cirle_model_src = os.path.join(artifacts_path, test_name + '.circle')
+    cicle_model_dst = os.path.join(binary_path, test_name + '.circle')
+    copy_circle_model(cirle_model_src, cicle_model_dst)
+
+
+def pytest_generate_tests(metafunc):
+    list_path = metafunc.config.getoption('test_list')
+    artifacts_path = metafunc.config.getoption('artifacts')
+    tflrecipe_path = metafunc.config.getoption('tflrecipe')
+    circlerecipe_path = metafunc.config.getoption('circlerecipe')
+    binary_path = metafunc.config.getoption('binary')
+    eval_driver_path = metafunc.config.getoption('luci_eval_driver')
+    if list_path is None:
+        tests_default_tol = []
+        tests_with_tol = []
+    else:
+        with open(list_path) as f:
+            contents = [line.rstrip() for line in f]
+
+        comment_removed = [line for line in contents if not line.startswith('#')]
+        newline_removed = [line for line in comment_removed if line.startswith('eval(')]
+        test_args = [extract_test_args(line) for line in newline_removed]
+        # eval(TEST_NAME)
+        tests_default_tol = [(arg, binary_path, eval_driver_path) for arg in test_args
+                             if len(arg.split()) == 1]
+        # eval(TEST_NAME RTOL ATOL)
+        tests_with_tol = [(arg.split()[0], binary_path, eval_driver_path, arg.split()[1],
+                           arg.split()[2]) for arg in test_args if len(arg.split()) == 3]
+
+        # copy circle file to binary
+        for test_item in tests_default_tol:
+            prepare_materials(test_item[0], tflrecipe_path, circlerecipe_path,
+                              binary_path, artifacts_path)
+
+        for test_item in tests_with_tol:
+            prepare_materials(test_item[0], tflrecipe_path, circlerecipe_path,
+                              binary_path, artifacts_path)
+
+    if 'default_test_name' in metafunc.fixturenames:
+        metafunc.parametrize('default_test_name,binary_path,eval_driver_path',
+                             tests_default_tol)
+
+    if 'tol_test_name' in metafunc.fixturenames:
+        metafunc.parametrize('tol_test_name,binary_path,eval_driver_path,rtolf32,atolf32',
+                             tests_with_tol)
diff --git a/compiler/luci-ref-value-py-test/requires.cmake b/compiler/luci-ref-value-py-test/requires.cmake
new file mode 100644 (file)
index 0000000..c446149
--- /dev/null
@@ -0,0 +1,2 @@
+require("common-artifacts")
+require("luci-eval-driver")
diff --git a/compiler/luci-ref-value-py-test/test.lst b/compiler/luci-ref-value-py-test/test.lst
new file mode 100644 (file)
index 0000000..478a73a
--- /dev/null
@@ -0,0 +1,5 @@
+# test with given reference data
+eval(FullyConnected_I4_002 0.1 0.1)
+
+# circle recipes
+eval(CircleFullyConnected_U4_002 0.1 0.1)
diff --git a/compiler/luci-ref-value-py-test/test_luci_eval.py b/compiler/luci-ref-value-py-test/test_luci_eval.py
new file mode 100644 (file)
index 0000000..cbe991d
--- /dev/null
@@ -0,0 +1,130 @@
+import numpy as np
+import subprocess
+import os
+
+
+# read input/output data files model_name.ref.input* and
+# model_name.ref.output* and return the contents
+def recover_fromfile(path, test_name, suffix):
+    # .ref file format
+    # 1'st line is shape, i.e. "2,4"
+    # 2'nd line is dtype, i.e. "float32"
+    # 3'rd line is comma seperated values
+    ref_filename = test_name + ".ref." + suffix
+    ref_datapath = os.path.join(path, ref_filename)
+
+    num_data = 0
+    parse_shape = []
+    parse_dtype = []
+    parse_value = []
+
+    while True:
+        refnum_filepath = ref_datapath + str(num_data)
+        if (not os.path.isfile(refnum_filepath)):
+            break
+        with open(refnum_filepath, "r") as ref_file:
+            lines = ref_file.readlines()
+            assert len(lines) >= 3, "Invalid file: " + ref_filename + str(num_data)
+        print("load reference data from", test_name)
+        shape = [int(i) for i in lines[0].split(",")]
+        dtype = lines[1].strip("\r\n \t")
+        if dtype == "float32":
+            value = [float(i) for i in lines[2].split(",")]
+        else:
+            assert False, "Unsupported data type: " + dtype
+
+        # validate shape and number of elements
+        num_elements = 1
+        for dim in shape:
+            num_elements = num_elements * dim
+        if num_elements != len(value):
+            assert False, "Number of value elements do not match with shape"
+
+        parse_shape.append(shape)
+        parse_dtype.append(dtype)
+        parse_value.append(value)
+
+        num_data = num_data + 1
+
+    return num_data, parse_shape, parse_dtype, parse_value
+
+
+def recover_inputs(path, test_name):
+    return recover_fromfile(path, test_name, "input")
+
+
+def recover_outputs(path, test_name):
+    return recover_fromfile(path, test_name, "output")
+
+
+# save reference data to input files for luci-eval-driver
+def save_binary_inputs(path, test_name, num_inputs, input_shape, input_dtype, input_data):
+    circle_inputpath = os.path.join(path, test_name + ".circle.input")
+    for index in range(0, num_inputs):
+        # reference input value
+        if input_dtype[index] == "float32":
+            nps = np.asarray(input_data[index], dtype=np.float32)
+            nps.tofile(circle_inputpath + str(index))
+        else:
+            assert False, "Unsupported data type: " + input_dtype[index]
+        # reference input shape
+        nps = np.asarray(input_shape[index], dtype=np.short)
+        nps.tofile(circle_inputpath + str(index) + ".shape", sep=",")
+        # reference input dtype
+        with open(circle_inputpath + str(index) + ".dtype", "w") as dtype_file:
+            dtype_file.write(input_dtype[index])
+
+
+def luci_eval_verify(test_name, binary_path, eval_driver, rtolf32=1e-5, atolf32=1e-5):
+    circle_model = os.path.join(binary_path, test_name + ".circle")
+
+    num_inputs, input_shape, input_dtype, input_data = recover_inputs(
+        binary_path, test_name)
+    assert num_inputs > 0, "No valid reference input file"
+    save_binary_inputs(binary_path, test_name, num_inputs, input_shape, input_dtype,
+                       input_data)
+
+    num_ouputs, output_shape, output_dtype, output_data = recover_outputs(
+        binary_path, test_name)
+    assert num_ouputs > 0, "No valid reference output file"
+
+    # Execute luci interpreter.
+    subprocess.run(
+        [
+            eval_driver, circle_model,
+            str(num_inputs), circle_model + ".input", circle_model + ".output"
+        ],
+        check=True)
+
+    # Compare the results.
+    for idx in range(num_ouputs):
+        luci_output_data = np.fromfile(circle_model + ".output" + str(idx),
+                                       output_dtype[idx])
+        luci_output_data = np.reshape(luci_output_data, output_shape[idx])
+        ref_output_data = np.reshape(output_data[idx], output_shape[idx])
+
+        show_vals_and_stop = False
+        if output_dtype[idx] == "float32":
+            if not np.allclose(
+                    luci_output_data, ref_output_data, rtol=rtolf32, atol=atolf32):
+                show_vals_and_stop = True
+        else:
+            assert False, "Unsupported data type: " + output_dtype[idx]
+
+        if show_vals_and_stop:
+            print("\nreference:\n", ref_output_data)
+            print("luci:\n", luci_output_data)
+            message = "Execution result of " + test_name + " does not match with reference"
+            assert False, message
+
+
+# arguments must be in sync with `conftest.py`
+def test_luci_eval(default_test_name: str, binary_path: str, eval_driver_path: str):
+    luci_eval_verify(default_test_name, binary_path, eval_driver_path)
+
+
+# arguments must be in sync with `conftest.py`
+def test_luci_eval_tol(tol_test_name: str, binary_path: str, eval_driver_path: str,
+                       rtolf32: str, atolf32: str):
+    luci_eval_verify(tol_test_name, binary_path, eval_driver_path, float(rtolf32),
+                     float(atolf32))
diff --git a/compiler/luci-value-py-test/CMakeLists.txt b/compiler/luci-value-py-test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1c62081
--- /dev/null
@@ -0,0 +1,37 @@
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_12_1")
+set(TEST_LIST_FILE "test.lst")
+
+if(NOT CMAKE_CROSSCOMPILING)
+  get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
+  add_test(NAME luci_value_py_test
+      COMMAND ${VIRTUALENV}/bin/python -m pytest -sv test_luci_eval.py
+              --test_list ${TEST_LIST_FILE}
+              --artifacts ${ARTIFACTS_BIN_PATH}
+              --luci_eval_driver $<TARGET_FILE:luci_eval_driver>
+      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+  )
+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
+  #      TensorFlow lite for target device.
+  #      thus, one must run the host test and then run the test in target device
+  #      with the test result files from the host test.
+  if(NOT DEFINED ENV{BUILD_HOST_EXEC})
+    message(STATUS "BUILD_HOST_EXEC not set: Skip luci-value-py-test")
+    return()
+  endif(NOT DEFINED ENV{BUILD_HOST_EXEC})
+
+  set(ARTIFACTS_BIN_PATH $ENV{BUILD_HOST_EXEC}/compiler/common-artifacts)
+  add_test(NAME luci_value_py_test
+      COMMAND ${VIRTUALENV}/bin/python -m pytest -sv test_luci_eval_ref.py
+              --test_list ${TEST_LIST_FILE}
+              --artifacts ${ARTIFACTS_BIN_PATH}
+              --target_artifacts ${CMAKE_CURRENT_BINARY_DIR}
+              --luci_eval_driver $<TARGET_FILE:luci_eval_driver>
+      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+  )
+endif(NOT CMAKE_CROSSCOMPILING)
diff --git a/compiler/luci-value-py-test/README.md b/compiler/luci-value-py-test/README.md
new file mode 100644 (file)
index 0000000..33d34c0
--- /dev/null
@@ -0,0 +1,19 @@
+# luci-value-py-test
+
+`luci-value-py-test` validates luci IR graph model file (.circle)
+
+The test proceeds as follows
+
+Step 1: Generate tflite files and circle files from TFLite recipes (listsed in test.lst).
+```
+"TFLite recipe" -> tflchef -> "tflite file" -> tflite2circle -> "circle file"
+```
+
+Step 2: Run TFLite interpreter and luci-interpreter for the generated tflite and circle, respectively.
+(with the same input tensors filled with random values)
+```
+circle file -> luci-interpreter -------> Execution result 1
+tflite file -> TFLite interpreter -----> Execution result 2
+```
+
+Step 3: Compare the execution result 1 and 2. The result must be the same.
diff --git a/compiler/luci-value-py-test/conftest.py b/compiler/luci-value-py-test/conftest.py
new file mode 100644 (file)
index 0000000..042a265
--- /dev/null
@@ -0,0 +1,74 @@
+import re
+
+
+def extract_test_args(s):
+    p = re.compile('eval\\((.*)\\)')
+    result = p.search(s)
+    return result.group(1)
+
+
+def pytest_addoption(parser):
+    parser.addoption("--test_list", action="store", help="Path to test list")
+    parser.addoption("--artifacts", action="store", help="Path to test artifacts")
+    parser.addoption(
+        "--target_artifacts", action="store", help="Path to test target artifacts")
+    parser.addoption(
+        "--luci_eval_driver", action="store", help="Path to luci eval driver")
+
+
+def pytest_generate_tests(metafunc):
+    list_path = metafunc.config.getoption('test_list')
+    artifacts_path = metafunc.config.getoption('artifacts')
+    target_artifacts_path = metafunc.config.getoption('target_artifacts')
+    eval_driver_path = metafunc.config.getoption('luci_eval_driver')
+    if list_path is None:
+        tests_default_tol = []
+        tests_with_tol = []
+        ref_tests_default_tol = []
+        ref_tests_with_tol = []
+    else:
+        with open(list_path) as f:
+            contents = [line.rstrip() for line in f]
+
+        comment_removed = [line for line in contents if not line.startswith('#')]
+        newline_removed = [line for line in comment_removed if line.startswith('eval(')]
+        test_args = [extract_test_args(line) for line in newline_removed]
+        # eval(TEST_NAME)
+        tests_default_tol = [(arg, artifacts_path, eval_driver_path) for arg in test_args
+                             if len(arg.split()) == 1]
+        # eval(TEST_NAME RTOL ATOL)
+        tests_with_tol = [(arg.split()[0], artifacts_path, eval_driver_path,
+                           arg.split()[1], arg.split()[2]) for arg in test_args
+                          if len(arg.split()) == 3]
+
+    if 'default_test_name' in metafunc.fixturenames:
+        metafunc.parametrize('default_test_name,artifacts_path,eval_driver_path',
+                             tests_default_tol)
+
+    if 'tol_test_name' in metafunc.fixturenames:
+        metafunc.parametrize(
+            'tol_test_name,artifacts_path,eval_driver_path,rtolf32,atolf32',
+            tests_with_tol)
+
+    if target_artifacts_path is not None:
+        # eval(TEST_NAME)
+        ref_tests_default_tol = [(arg, artifacts_path, target_artifacts_path,
+                                  eval_driver_path) for arg in test_args
+                                 if len(arg.split()) == 1]
+        # eval(TEST_NAME RTOL ATOL)
+        ref_tests_with_tol = [(arg.split()[0], artifacts_path,
+                               target_artifacts_path, eval_driver_path, arg.split()[1],
+                               arg.split()[2]) for arg in test_args
+                              if len(arg.split()) == 3]
+        #
+        # for cross platform test
+        #
+        if 'default_ref_test_name' in metafunc.fixturenames:
+            metafunc.parametrize(
+                'default_ref_test_name,ref_artifacts_path,target_artifacts_path,eval_driver_path',
+                ref_tests_default_tol)
+
+        if 'tol_ref_test_name' in metafunc.fixturenames:
+            metafunc.parametrize(
+                'tol_ref_test_name,ref_artifacts_path,target_artifacts_path,eval_driver_path,rtolf32,atolf32',
+                ref_tests_with_tol)
diff --git a/compiler/luci-value-py-test/requires.cmake b/compiler/luci-value-py-test/requires.cmake
new file mode 100644 (file)
index 0000000..c446149
--- /dev/null
@@ -0,0 +1,2 @@
+require("common-artifacts")
+require("luci-eval-driver")
diff --git a/compiler/luci-value-py-test/test.lst b/compiler/luci-value-py-test/test.lst
new file mode 100644 (file)
index 0000000..2c928fb
--- /dev/null
@@ -0,0 +1,211 @@
+eval(Abs_000)
+eval(Add_000)
+eval(Add_001)
+eval(Add_U8_000)
+#eval(AddN_000)
+eval(ArgMax_000)
+eval(ArgMax_001)
+eval(ArgMax_002)
+eval(ArgMax_003)
+eval(ArgMax_U8_000)
+eval(ArgMax_U8_001)
+eval(ArgMax_U8_002)
+eval(ArgMax_U8_003)
+#eval(ArgMin_000)
+#eval(ArgMin_001)
+#eval(ArgMin_002)
+#eval(ArgMin_003)
+#eval(ArgMin_U8_000)
+#eval(ArgMin_U8_001)
+#eval(ArgMin_U8_002)
+#eval(ArgMin_U8_003)
+eval(AveragePool2D_000)
+eval(BatchMatMul_000)
+#eval(BatchMatMulV2_000)
+#eval(BatchMatMulV2_001)
+#eval(BatchToSpaceND_000)
+eval(BroadcastTo_001)
+eval(Cast_000)
+eval(Cast_001)
+#eval(Ceil_000)
+eval(Concatenation_000)
+eval(Concatenation_U8_000)
+eval(Conv2D_000)
+eval(Conv2D_001)
+eval(Conv2D_002)
+eval(Conv2D_003)
+#eval(Conv2D_U8_000) --> test with tolerance
+eval(Conv2D_U8_001)
+eval(Cos_000)
+eval(CumSum_000)
+eval(DepthToSpace_000)
+eval(DepthwiseConv2D_000)
+eval(DepthwiseConv2D_U8_000)
+#eval(DepthwiseConv2D_U8_001)
+eval(DepthwiseConv2D_001)
+eval(Div_000)
+eval(ELU_000)
+eval(Equal_000)
+eval(Exp_000)
+eval(ExpandDims_000)
+#eval(ExpandDims_001)
+#eval(ExpandDims_002)
+eval(ExpandDims_003)
+#eval(Fill_000)
+#eval(Fill_001)
+eval(Floor_000)
+eval(FloorDiv_000)
+eval(FloorDiv_001)
+eval(FloorMod_000)
+eval(FloorMod_001)
+eval(FullyConnected_000)
+eval(FullyConnected_001)
+eval(FullyConnected_002)
+#eval(FullyConnected_U8_000)
+eval(Gather_000)
+#eval(GatherNd_000)
+eval(Gelu_000)
+eval(Greater_000)
+eval(GreaterEqual_000)
+eval(HardSwish_000)
+eval(If_000)
+eval(If_001)
+eval(L2Normalize_000)
+eval(L2Pool2D_000)
+#eval(L2Pool2D_U8_000)
+eval(LeakyRelu_000)
+eval(Less_000)
+eval(LessEqual_000)
+eval(LocalResponseNormalization_000)
+eval(Log_000)
+eval(LogicalAnd_000)
+eval(LogicalNot_000)
+eval(LogicalOr_000)
+eval(Logistic_000)
+eval(LogSoftmax_000)
+#eval(MatMul_000)
+#eval(MatrixDiag_000)
+#eval(MatrixSetDiag_000)
+eval(Maximum_000)
+eval(MaxPool2D_000)
+eval(MaxPool2D_U8_000)
+eval(Mean_000)
+eval(Mean_001)
+eval(Mean_U8_000)
+eval(Minimum_000)
+#eval(MirrorPad_000)
+eval(Mul_000)
+#eval(Mul_U8_000)
+eval(Neg_000)
+eval(NotEqual_000)
+eval(OneHot_000)
+eval(OneHot_001)
+eval(OneHot_002)
+#eval(OneHot_003)
+eval(Pack_000)
+eval(Pack_U8_000)
+eval(Pad_000)
+eval(Pad_U8_000)
+eval(Pow_000)
+eval(PRelu_000)
+#eval(Range_000)
+#eval(Rank_000)
+#eval(ReduceAny_000)
+#eval(ReduceAny_001)
+#eval(ReduceAny_002)
+#eval(ReduceAny_003)
+eval(ReduceMax_000)
+#eval(ReduceMin_000)
+eval(ReduceProd_000)
+eval(ReduceProd_001)
+eval(ReduceProd_002)
+eval(ReduceProd_003)
+eval(ReLU_000)
+eval(ReLU0To1_000)
+eval(ReLU6_000)
+#eval(ReLUN1To1_000)
+eval(Reshape_000)
+eval(Reshape_001)
+eval(Reshape_002)
+#eval(Reshape_003)
+eval(Reshape_U8_000)
+eval(ResizeBilinear_000)
+eval(ResizeNearestNeighbor_000)
+#eval(ReverseSequence_000)
+#eval(ReverseV2_000)
+#eval(Round_000)
+eval(Rsqrt_000)
+#eval(ScatterNd_000)
+#eval(SegmentSum_000)
+eval(Select_000)
+eval(Select_001)
+eval(Select_002)
+eval(SelectV2_000)
+eval(SelectV2_001)
+eval(SelectV2_002)
+eval(Shape_000)
+eval(SignatureDef_MultiOut_000)
+eval(SignatureDef_MultiOut_001)
+eval(Sin_000)
+eval(Slice_000)
+eval(Softmax_000)
+eval(Softmax_U8_000)
+eval(SpaceToBatchND_000)
+eval(SpaceToBatchND_001)
+eval(SpaceToBatchND_002)
+eval(SpaceToBatchND_003)
+eval(SpaceToDepth_000)
+#eval(SparseToDense_000)
+eval(Split_000)
+eval(SplitV_000)
+eval(Sqrt_000)
+eval(Square_000)
+eval(SquaredDifference_000)
+eval(Squeeze_000)
+eval(Squeeze_001)
+eval(StridedSlice_000)
+eval(StridedSlice_001)
+eval(StridedSlice_002)
+eval(StridedSlice_003)
+eval(StridedSlice_004)
+eval(Sub_000)
+eval(Sub_U8_000)
+eval(Sum_000)
+eval(Sum_001)
+eval(Tanh_000)
+eval(Tile_000)
+eval(Tile_001)
+eval(Tile_002)
+#eval(Tile_U8_000)
+#eval(TopKV2_000)
+#eval(TopKV2_001)
+eval(Transpose_000)
+eval(TransposeConv_000)
+eval(UnidirectionalSequenceLSTM_002)
+eval(UnidirectionalSequenceLSTM_003)
+eval(UnidirectionalSequenceLSTM_004)
+eval(Unpack_000)
+eval(Unpack_001)
+eval(Unpack_002)
+eval(Unpack_003)
+eval(UnidirectionalSequenceLSTM_002)
+#eval(Where_000)
+#eval(Where_001)
+eval(While_000)
+eval(While_001)
+eval(While_002)
+#eval(While_003)
+#eval(ZerosLike_000)
+
+# Simple Network test
+eval(Part_While_000)
+eval(Part_While_001)
+
+# Tests with tolerance
+eval(SVDF_000 8e-3 8e-3)
+eval(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
+eval(Conv2D_U8_000 5 5)
+# refer https://github.com/Samsung/ONE/issues/10438
+eval(YUV_TO_RGB_U8_000 1 1)
diff --git a/compiler/luci-value-py-test/test_luci_eval.py b/compiler/luci-value-py-test/test_luci_eval.py
new file mode 100644 (file)
index 0000000..b3fa442
--- /dev/null
@@ -0,0 +1,140 @@
+import numpy as np
+import tensorflow as tf
+import subprocess
+import os
+
+
+def luci_eval_verify(test_name, artifacts, eval_driver, rtolf32=1e-5, atolf32=1e-5):
+    tflite_model = os.path.join(artifacts, test_name + ".tflite")
+    circle_model = os.path.join(artifacts, test_name + ".circle")
+
+    # NOTE reuse f32 value as int value too
+    rtolint = int(rtolf32)
+    atolint = int(atolf32)
+
+    # Build TFLite interpreter.
+    interpreter = tf.lite.Interpreter(tflite_model)
+    interpreter.allocate_tensors()
+
+    # Read SignatureDef and get output tensor id orders for remapping
+    full_signatures = interpreter._get_full_signature_list()
+    full_signatures_outputs_remap = None
+    if full_signatures != None:
+        signature_serving_default = full_signatures.get('serving_default', None)
+        if signature_serving_default != None:
+            signature_outputs = signature_serving_default['outputs']
+
+            full_signatures_outputs_remap = []
+            for index, (key, value) in enumerate(signature_outputs.items()):
+                full_signatures_outputs_remap.append(value)
+
+    # Generate random input data.
+    num_inputs = len(interpreter.get_input_details())
+    for i in range(num_inputs):
+        input_details = interpreter.get_input_details()[i]
+        if input_details["dtype"] == np.float32:
+            input_data = np.array(
+                np.random.random_sample(input_details["shape"]), input_details["dtype"])
+            input_dtype = "float32"
+        elif input_details["dtype"] == np.uint8:
+            input_data = np.array(
+                np.random.randint(0, 256, size=input_details["shape"]),
+                input_details["dtype"])
+            input_dtype = "uint8"
+        elif input_details["dtype"] == np.int16:
+            input_data = np.array(
+                np.random.randint(0, 100, size=input_details["shape"]),
+                input_details["dtype"])
+            input_dtype = "int16"
+        elif input_details["dtype"] == np.int32:
+            input_data = np.array(
+                np.random.randint(0, 100, size=input_details["shape"]),
+                input_details["dtype"])
+            input_dtype = "int32"
+        elif input_details["dtype"] == np.int64:
+            input_data = np.array(
+                np.random.randint(0, 100, size=input_details["shape"]),
+                input_details["dtype"])
+            input_dtype = "int64"
+        elif input_details["dtype"] == np.bool_:
+            input_data = np.array(
+                np.random.choice(a=[True, False], size=input_details["shape"]),
+                input_details["dtype"])
+            input_dtype = "bool"
+        else:
+            assert False, "Unsupported input dtype"
+
+        interpreter.set_tensor(input_details["index"], input_data)
+        input_data.tofile(circle_model + ".input" + str(i))
+        input_details["shape"].tofile(
+            circle_model + ".input" + str(i) + ".shape", sep=',')
+        with open(circle_model + ".input" + str(i) + ".dtype", 'w') as dtype_file:
+            dtype_file.write(input_dtype)
+
+    # Do inference
+    interpreter.invoke()
+
+    # Execute luci interpreter.
+    subprocess.run(
+        [
+            eval_driver, circle_model,
+            str(num_inputs), circle_model + ".input", circle_model + ".output"
+        ],
+        check=True)
+
+    # Compare the results.
+    inpt_output_details = interpreter.get_output_details()
+    for idx in range(len(inpt_output_details)):
+        output_details = inpt_output_details[idx]
+        output_data = np.fromfile(circle_model + ".output" + str(idx),
+                                  output_details["dtype"])
+        shape_file = open(circle_model + ".output" + str(idx) + ".shape", 'r')
+        output_shape = [int(i) for i in shape_file.read().split(',')]
+        luci_output_data = np.reshape(output_data, output_shape)
+        output_tensor = output_details["index"]
+        if full_signatures_outputs_remap != None:
+            output_tensor = full_signatures_outputs_remap[idx]
+        intp_output_data = interpreter.get_tensor(output_tensor)
+        err_msg = "Execution result of " + tflite_model + " does not match with " + circle_model
+        if output_details["dtype"] == np.uint8:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=rtolint, atol=atolint), err_msg
+            output_dtype = "uint8"
+        elif output_details["dtype"] == np.float32:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=rtolf32, atol=atolf32), err_msg
+            output_dtype = "float32"
+        elif output_details["dtype"] == np.int64:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=rtolint, atol=atolint), err_msg
+            output_dtype = "int64"
+        elif output_details["dtype"] == np.int32:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=rtolint, atol=atolint), err_msg
+            output_dtype = "int32"
+        elif output_details["dtype"] == np.int16:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=rtolint, atol=atolint), err_msg
+            output_dtype = "int16"
+        elif output_details["dtype"] == np.bool_:
+            assert np.allclose(
+                luci_output_data, intp_output_data, rtol=0, atol=0), err_msg
+            output_dtype = "bool"
+        else:
+            assert False, "Unsupported data type: " + output_details["dtype"]
+
+        # save outputN.dtype file
+        with open(circle_model + ".output" + str(idx) + ".dtype", 'w') as dtype_file:
+            dtype_file.write(output_dtype)
+
+
+# arguments must be in sync with `conftest.py`
+def test_luci_eval(default_test_name: str, artifacts_path: str, eval_driver_path: str):
+    luci_eval_verify(default_test_name, artifacts_path, eval_driver_path)
+
+
+# arguments must be in sync with `conftest.py`
+def test_luci_eval_tol(tol_test_name: str, artifacts_path: str, eval_driver_path: str,
+                       rtolf32: str, atolf32: str):
+    luci_eval_verify(tol_test_name, artifacts_path, eval_driver_path, float(rtolf32),
+                     float(atolf32))
diff --git a/compiler/luci-value-py-test/test_luci_eval_ref.py b/compiler/luci-value-py-test/test_luci_eval_ref.py
new file mode 100644 (file)
index 0000000..f476c78
--- /dev/null
@@ -0,0 +1,137 @@
+import numpy as np
+import tensorflow as tf
+import subprocess
+import os
+
+#
+# This script compares the execution result of luci-interpreter with that from ref_model path
+#
+# Basic usage:
+#   luci_eval_verifier_ref.py --driver build/compiler/luci-eval-driver/luci_eval_driver
+#           --ref_model ref_model_path --model this_model_path
+# Assumption:
+#   these file exist with its purpose
+#   - ref_model_path.circle; circle model
+#   - ref_model_path.circle.inputN; N'th input numpy data
+#   - ref_model_path.circle.inputN.dtype; N'th input data type in text
+#   - ref_model_path.circle.inputN.shape; N'th input data shape in CSV
+#   - ref_model_path.circle.outputN; N'th output numpy data
+#   - ref_model_path.circle.outputN.dtype; N'th output data type in text
+#   - ref_model_path.circle.outputN.shape; N'th output data shape in CSV
+
+
+def dtype_from_file(file_path):
+    with open(file_path, 'r') as dtype_file:
+        dtype_str = dtype_file.read()
+    if dtype_str == "float32":
+        return np.float32
+    if dtype_str == "uint8":
+        return np.uint8
+    if dtype_str == "int16":
+        return np.int16
+    if dtype_str == "int32":
+        return np.int32
+    if dtype_str == "int64":
+        return np.int64
+    if dtype_str == "bool":
+        return np.bool_
+    assert False, "Unsupported dtype from file: " + dtype_str
+
+
+def luci_eval_verify_ref(test_name,
+                         ref_artifacts,
+                         target_artifacts,
+                         eval_driver,
+                         rtolf32=1e-5,
+                         atolf32=1e-5):
+    circle_model_ref = os.path.join(ref_artifacts, test_name + ".circle")
+    circle_model = os.path.join(target_artifacts, test_name + ".circle")
+
+    # NOTE reuse f32 value as int value too
+    rtolint = int(rtolf32)
+    atolint = int(atolf32)
+
+    # get num of inputs by checking existance of model.inputN
+    check_input = 0
+    while True:
+        input_file_path = circle_model_ref + ".input" + str(check_input)
+        if not os.path.isfile(input_file_path):
+            num_inputs = check_input
+            break
+        check_input = check_input + 1
+
+    assert num_inputs != 0, "input file not exist for " + circle_model_ref
+
+    # get num of outputs by checking existance of model.outputN
+    check_output = 0
+    while True:
+        output_file_path = circle_model_ref + ".output" + str(check_output)
+        if not os.path.isfile(output_file_path):
+            num_outputs = check_output
+            break
+        check_output = check_output + 1
+
+    assert num_outputs != 0, "output file not exist for " + circle_model_ref
+
+    # Execute luci interpreter with reference input
+    subprocess.run(
+        [
+            eval_driver, circle_model_ref,
+            str(num_inputs), circle_model_ref + ".input", circle_model + ".output"
+        ],
+        check=True)
+
+    # Compare the results.
+    for idx in range(num_outputs):
+        output_dtype = dtype_from_file(circle_model_ref + ".output" + str(idx) + ".dtype")
+        shape_file = open(circle_model_ref + ".output" + str(idx) + ".shape", 'r')
+        output_shape = [int(i) for i in shape_file.read().split(',')]
+
+        output_data_ref = np.fromfile(circle_model_ref + ".output" + str(idx),
+                                      output_dtype)
+        luci_output_data_ref = np.reshape(output_data_ref, output_shape)
+
+        output_data = np.fromfile(circle_model + ".output" + str(idx), output_dtype)
+        luci_output_data = np.reshape(output_data, output_shape)
+
+        err_msg = "Execution result of " + circle_model_ref + " does not match with " + circle_model
+        if output_dtype == np.uint8:
+            assert np.allclose(
+                luci_output_data, luci_output_data_ref, rtol=rtolint,
+                atol=atolint), err_msg
+        elif output_dtype == np.float32:
+            assert np.allclose(
+                luci_output_data, luci_output_data_ref, rtol=rtolf32,
+                atol=atolf32), err_msg
+        elif output_dtype == np.int64:
+            assert np.allclose(
+                luci_output_data, luci_output_data_ref, rtol=rtolint,
+                atol=atolint), err_msg
+        elif output_dtype == np.int32:
+            assert np.allclose(
+                luci_output_data, luci_output_data_ref, rtol=rtolint,
+                atol=atolint), err_msg
+        elif output_dtype == np.int16:
+            assert np.allclose(
+                luci_output_data, luci_output_data_ref, rtol=rtolint,
+                atol=atolint), err_msg
+        elif output_dtype == np.bool_:
+            assert np.allclose(
+                luci_output_data, luci_output_data_ref, rtol=0, atol=0), err_msg
+        else:
+            assert False, "Unsupported data type: " + output_dtype
+
+
+# arguments must be in sync with `conftest.py`
+def test_luci_eval_ref(default_ref_test_name: str, ref_artifacts_path: str,
+                       target_artifacts_path: str, eval_driver_path: str):
+    luci_eval_verify_ref(default_ref_test_name, ref_artifacts_path, target_artifacts_path,
+                         eval_driver_path)
+
+
+# arguments must be in sync with `conftest.py`
+def test_luci_eval_tol_ref(tol_ref_test_name: str, ref_artifacts_path: str,
+                           target_artifacts_path: str, eval_driver_path: str,
+                           rtolf32: str, atolf32: str):
+    luci_eval_verify_ref(tol_ref_test_name, ref_artifacts_path, target_artifacts_path,
+                         eval_driver_path, float(rtolf32), float(atolf32))
diff --git a/compiler/luci-value-test/exclude.me b/compiler/luci-value-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 3368b64..591421e 100644 (file)
@@ -35,7 +35,8 @@ addeval(Conv2D_002)
 addeval(Conv2D_003)
 #addeval(Conv2D_U8_000) --> test with tolerance
 addeval(Conv2D_U8_001)
-#addeval(Cos_000)
+addeval(Cos_000)
+addeval(CumSum_000)
 addeval(DepthToSpace_000)
 addeval(DepthwiseConv2D_000)
 addeval(DepthwiseConv2D_U8_000)
@@ -143,7 +144,7 @@ addeval(Select_002)
 #addeval(Shape_000)
 addeval(SignatureDef_MultiOut_000)
 addeval(SignatureDef_MultiOut_001)
-#addeval(Sin_000)
+addeval(Sin_000)
 addeval(Slice_000)
 addeval(Softmax_000)
 addeval(Softmax_U8_000)
@@ -170,7 +171,9 @@ addeval(Sub_U8_000)
 addeval(Sum_000)
 addeval(Sum_001)
 addeval(Tanh_000)
-#addeval(Tile_000)
+addeval(Tile_000)
+addeval(Tile_001)
+addeval(Tile_002)
 #addeval(Tile_U8_000)
 #addeval(TopKV2_000)
 #addeval(TopKV2_001)
@@ -201,6 +204,6 @@ 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)
+addevaltol(Conv2D_U8_000 5 5)
 # refer https://github.com/Samsung/ONE/issues/10438
 addevaltol(YUV_TO_RGB_U8_000 1 1)
index fb0e20e..bc10ad2 100644 (file)
@@ -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_circle06)
+target_link_libraries(luci_export PRIVATE mio_circle08)
 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_circle06)
+target_link_libraries(luci_export_test mio_circle08)
 target_link_libraries(luci_export_test luci_env)
 target_link_libraries(luci_export_test oops)
index 811373f..efc2a51 100644 (file)
@@ -87,6 +87,7 @@ public:
              node->asymmetric_quantize_inputs())
       .Union();
   }
+  flatbuffers::Offset<void> visit(luci::CircleBroadcastTo *) { return _no_option; }
   flatbuffers::Offset<void> visit(luci::CircleCast *node)
   {
     if (node->out_data_type() == loco::DataType::Unknown)
@@ -117,6 +118,10 @@ public:
   {
     return circle::CreateCosOptions(_builder).Union();
   }
+  flatbuffers::Offset<void> visit(luci::CircleCumSum *node)
+  {
+    return circle::CreateCumsumOptions(_builder, node->exclusive(), node->reverse()).Union();
+  }
   flatbuffers::Offset<void> visit(luci::CircleCustom *) { return _no_option; }
   flatbuffers::Offset<void> visit(luci::CircleDensify *)
   {
@@ -353,6 +358,7 @@ public:
     return circle::CreateReducerOptions(_builder, node->keep_dims()).Union();
   }
   flatbuffers::Offset<void> visit(luci::CircleRelu *) { return _no_option; }
+  flatbuffers::Offset<void> visit(luci::CircleRelu0To1 *) { return _no_option; }
   flatbuffers::Offset<void> visit(luci::CircleRelu6 *) { return _no_option; }
   flatbuffers::Offset<void> visit(luci::CircleReluN1To1 *) { return _no_option; }
   flatbuffers::Offset<void> visit(luci::CircleReshape *node)
@@ -530,6 +536,12 @@ public:
     return circle::CreateBCQGatherOptions(_builder, node->input_hidden_size(), node->axis())
       .Union();
   }
+  flatbuffers::Offset<void> visit(luci::CircleGRU *node)
+  {
+    return circle::CreateGRUOptions(_builder, to_circle_actfunc(node->fusedActivationFunction()),
+                                    node->returnSequences(), node->timeMajor())
+      .Union();
+  }
   flatbuffers::Offset<void> visit(luci::CircleInstanceNorm *node)
   {
     return circle::CreateInstanceNormOptions(_builder, node->epsilon(),
index 017002f..25d0168 100644 (file)
@@ -56,7 +56,7 @@ const std::vector<uint8_t> CircleExportMetadata::encoded_execution_plan_table()
     const auto id = kv.first;
     write_u32(data, id);
 
-    const auto plan_vector = kv.second;
+    const auto &plan_vector = kv.second;
     const auto size = plan_vector.size();
     write_u32(data, size);
 
@@ -81,7 +81,7 @@ const std::vector<uint8_t> CircleExportMetadata::encoded_source_table(void)
     const auto id = kv.first;
     write_u32(data, id);
 
-    const auto origin_name = kv.second;
+    const auto &origin_name = kv.second;
     const auto length = origin_name.length();
     write_u32(data, length + 1); // name + '\0
 
@@ -107,7 +107,7 @@ const std::vector<uint8_t> CircleExportMetadata::encoded_op_table(void)
     const auto id = kv.first;
     write_u32(data, id);
 
-    const auto origins = kv.second;
+    const auto &origins = kv.second;
     const auto node_num = origins.size();
     write_u32(data, node_num);
 
index 083add9..014ef45 100644 (file)
@@ -76,7 +76,7 @@ Offset<Vector<Offset<OperatorCode>>>
 encodeOperatorCodes(FlatBufferBuilder &builder, std::unordered_map<luci::OpCode, uint32_t> &opcodes)
 {
   std::vector<Offset<OperatorCode>> operator_codes_vec(opcodes.size());
-  for (auto it : opcodes)
+  for (const auto &it : opcodes)
   {
     uint32_t idx = it.second;
     int8_t dep_code = 127; // BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES
@@ -117,8 +117,7 @@ CircleExporterImpl::exportSubgraph(SerializedGraphData &gd)
   auto outputs = _builder.CreateVector(gd._outputs);
   auto operators = _builder.CreateVector(gd._operators);
   auto name = _builder.CreateString(gd._name);
-  auto df = gd._data_format;
-  auto subgraph = CreateSubGraph(_builder, tensors, inputs, outputs, operators, name, df);
+  auto subgraph = CreateSubGraph(_builder, tensors, inputs, outputs, operators, name);
   return subgraph;
 }
 
@@ -202,9 +201,6 @@ void CircleExporterImpl::exportModule(Module *module)
     // set Subgraph name
     gd._name = graph->name();
 
-    // TODO set this value properly
-    gd._data_format = circle::DataFormat::DataFormat_CHANNELS_LAST;
-
     // parse graph into SerializedModelData structure
     exportOpDefinedTensors(graph, _builder, md, gd);
 
index 9473c2c..6678b0d 100644 (file)
@@ -50,9 +50,13 @@ circle::TensorType to_circle_tensortype(loco::DataType type)
 {
   switch (type)
   {
+    case loco::DataType::U4:
+      return circle::TensorType_UINT4;
     case loco::DataType::U8:
       return circle::TensorType_UINT8;
 
+    case loco::DataType::S4:
+      return circle::TensorType_INT4;
     case loco::DataType::S8:
       return circle::TensorType_INT8;
     case loco::DataType::S16:
index a047f29..8c693ba 100644 (file)
@@ -26,11 +26,13 @@ CIRCLE_NODE(CircleAveragePool2D, BuiltinOperator_AVERAGE_POOL_2D , BuiltinOption
 CIRCLE_NODE(CircleBatchToSpaceND, BuiltinOperator_BATCH_TO_SPACE_ND, BuiltinOptions_BatchToSpaceNDOptions)
 CIRCLE_NODE(CircleBatchMatMul, BuiltinOperator_BATCH_MATMUL, BuiltinOptions_BatchMatMulOptions)
 CIRCLE_NODE(CircleBidirectionalSequenceLSTM, BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM, BuiltinOptions_BidirectionalSequenceLSTMOptions)
+CIRCLE_NODE(CircleBroadcastTo, BuiltinOperator_BROADCAST_TO, BuiltinOptions_NONE)
 CIRCLE_NODE(CircleCast, BuiltinOperator_CAST, BuiltinOptions_CastOptions)
 CIRCLE_NODE(CircleCeil, BuiltinOperator_CEIL, BuiltinOptions_NONE)
 CIRCLE_NODE(CircleConcatenation, BuiltinOperator_CONCATENATION, BuiltinOptions_ConcatenationOptions)
 CIRCLE_NODE(CircleConv2D, BuiltinOperator_CONV_2D, BuiltinOptions_Conv2DOptions)
 CIRCLE_NODE(CircleCos, BuiltinOperator_COS, BuiltinOptions_CosOptions)
+CIRCLE_NODE(CircleCumSum, BuiltinOperator_CUMSUM, BuiltinOptions_CumsumOptions)
 CIRCLE_NODE(CircleCustom, BuiltinOperator_CUSTOM, BuiltinOptions_NONE)
 CIRCLE_NODE(CircleDensify, BuiltinOperator_DENSIFY, BuiltinOptions_DensifyOptions)
 CIRCLE_NODE(CircleDepthToSpace, BuiltinOperator_DEPTH_TO_SPACE, BuiltinOptions_DepthToSpaceOptions)
@@ -92,6 +94,7 @@ CIRCLE_NODE(CircleReduceMax, BuiltinOperator_REDUCE_MAX, BuiltinOptions_ReducerO
 CIRCLE_NODE(CircleReduceMin, BuiltinOperator_REDUCE_MIN, BuiltinOptions_ReducerOptions)
 CIRCLE_NODE(CircleReduceProd, BuiltinOperator_REDUCE_PROD, BuiltinOptions_ReducerOptions)
 CIRCLE_NODE(CircleRelu, BuiltinOperator_RELU, BuiltinOptions_NONE)
+CIRCLE_NODE(CircleRelu0To1, BuiltinOperator_RELU_0_TO_1, BuiltinOptions_NONE)
 CIRCLE_NODE(CircleRelu6, BuiltinOperator_RELU6, BuiltinOptions_NONE)
 CIRCLE_NODE(CircleReluN1To1, BuiltinOperator_RELU_N1_TO_1, BuiltinOptions_NONE)
 CIRCLE_NODE(CircleReshape, BuiltinOperator_RESHAPE, BuiltinOptions_ReshapeOptions)
@@ -136,6 +139,7 @@ CIRCLE_NODE(CircleZerosLike, BuiltinOperator_ZEROS_LIKE, BuiltinOptions_ZerosLik
 // Circle Only
 CIRCLE_NODE(CircleBCQFullyConnected, BuiltinOperator_BCQ_FULLY_CONNECTED, BuiltinOptions_BCQFullyConnectedOptions)
 CIRCLE_NODE(CircleBCQGather, BuiltinOperator_BCQ_GATHER, BuiltinOptions_BCQGatherOptions)
+CIRCLE_NODE(CircleGRU, BuiltinOperator_GRU, BuiltinOptions_GRUOptions)
 CIRCLE_NODE(CircleInstanceNorm, BuiltinOperator_INSTANCE_NORM, BuiltinOptions_InstanceNormOptions)
 // Virtual node(s)
 CIRCLE_VNODE(CircleBidirectionalSequenceLSTMOut)
index 97e8107..0022a0e 100644 (file)
@@ -409,6 +409,31 @@ encodeOpBufferByDType<loco::DataType::STRING>(FlatBufferBuilder &builder, luci::
   return CreateBuffer(builder, array_offset);
 }
 
+template <loco::DataType DT>
+flatbuffers::Offset<circle::Buffer> encodeOpBufferPack4bit(FlatBufferBuilder &builder,
+                                                           luci::CircleConst *c)
+{
+  const uint32_t size = c->size<DT>();
+  const uint32_t raw_size = (size + 1) / 2;
+  std::vector<uint8_t> raw_data(raw_size);
+
+  for (uint32_t i = 0; i < raw_size; ++i)
+  {
+    uint32_t sidx = i * 2;
+    uint8_t data = static_cast<uint8_t>(c->at<DT>(sidx));
+    raw_data[i] = data & 0x0f;
+    sidx++;
+    if (sidx < size)
+    {
+      data = static_cast<uint8_t>(c->at<DT>(sidx));
+      raw_data[i] |= data << 4;
+    }
+  }
+
+  auto array_offset = builder.CreateVector(raw_data.data(), raw_size);
+  return CreateBuffer(builder, array_offset);
+}
+
 template <>
 flatbuffers::Offset<circle::Buffer> encodeOpBuffer(FlatBufferBuilder &builder, luci::CircleConst *c)
 {
@@ -416,6 +441,8 @@ flatbuffers::Offset<circle::Buffer> encodeOpBuffer(FlatBufferBuilder &builder, l
   {
     case loco::DataType::FLOAT32:
       return encodeOpBufferByDType<loco::DataType::FLOAT32>(builder, c);
+    case loco::DataType::S4:
+      return encodeOpBufferPack4bit<loco::DataType::S4>(builder, c);
     case loco::DataType::S8:
       return encodeOpBufferByDType<loco::DataType::S8>(builder, c);
     case loco::DataType::S16:
@@ -424,6 +451,8 @@ flatbuffers::Offset<circle::Buffer> encodeOpBuffer(FlatBufferBuilder &builder, l
       return encodeOpBufferByDType<loco::DataType::S32>(builder, c);
     case loco::DataType::S64:
       return encodeOpBufferByDType<loco::DataType::S64>(builder, c);
+    case loco::DataType::U4:
+      return encodeOpBufferPack4bit<loco::DataType::U4>(builder, c);
     case loco::DataType::U8:
       return encodeOpBufferByDType<loco::DataType::U8>(builder, c);
     case loco::DataType::BOOL:
@@ -477,7 +506,7 @@ encodeSparsityParameters(FlatBufferBuilder &builder, luci::SparsityParam *sparsi
 
   std::vector<flatbuffers::Offset<circle::DimensionMetadata>> dim_metadata_vec;
   auto luci_dim_metadata = sparsityparam->dim_metadata;
-  for (auto it : luci_dim_metadata)
+  for (const auto &it : luci_dim_metadata)
   {
     // array_segments
     auto circle_array_segments = to_circle_sparse_index_vector(builder, it.array_segments());
@@ -526,6 +555,9 @@ bool has_same_values(luci::CircleConst *lhs, luci::CircleConst *rhs)
     case loco::DataType::FLOAT32:
       return has_same_elements<loco::DataType::FLOAT32>(lhs, rhs);
 
+    case loco::DataType::S4:
+      return has_same_elements<loco::DataType::S4>(lhs, rhs);
+
     case loco::DataType::S8:
       return has_same_elements<loco::DataType::S8>(lhs, rhs);
 
@@ -538,6 +570,9 @@ bool has_same_values(luci::CircleConst *lhs, luci::CircleConst *rhs)
     case loco::DataType::S64:
       return has_same_elements<loco::DataType::S64>(lhs, rhs);
 
+    case loco::DataType::U4:
+      return has_same_elements<loco::DataType::U4>(lhs, rhs);
+
     case loco::DataType::U8:
       return has_same_elements<loco::DataType::U8>(lhs, rhs);
 
index 2e7e881..8c1da0e 100644 (file)
@@ -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_circle06)
+target_link_libraries(luci_import PUBLIC mio_circle08)
 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_circle06_helper)
+target_link_libraries(luci_import PRIVATE mio_circle08_helper)
 install(TARGETS luci_import DESTINATION lib)
 install(DIRECTORY include/ DESTINATION include
         FILES_MATCHING PATTERN "*.h")
index a0519f6..36e3cdf 100644 (file)
@@ -106,7 +106,6 @@ public: // direct API
   VectorWrapper<int32_t> inputs() const { return wrap(_current_subgraph->inputs()); }
   VectorWrapper<int32_t> outputs() const { return wrap(_current_subgraph->outputs()); }
   std::string name() const { return fb_string2std_string(_current_subgraph->name()); }
-  circle::DataFormat data_format() const { return _current_subgraph->data_format(); }
   CircleMetadataSet metadata() const { return wrap(_model->metadata()); }
 
   uint32_t num_subgraph() const { return wrap(_model->subgraphs()).size(); }
index e8c8d0a..f3f4871 100644 (file)
 #include "Nodes/CircleBCQFullyConnected.h"
 #include "Nodes/CircleBCQGather.h"
 #include "Nodes/CircleBidirectionalSequenceLSTM.h"
+#include "Nodes/CircleBroadcastTo.h"
 #include "Nodes/CircleCast.h"
 #include "Nodes/CircleCeil.h"
 #include "Nodes/CircleConcatenation.h"
 #include "Nodes/CircleConst.h"
 #include "Nodes/CircleConv2D.h"
 #include "Nodes/CircleCos.h"
+#include "Nodes/CircleCumSum.h"
 #include "Nodes/CircleCustom.h"
 #include "Nodes/CircleDensify.h"
 #include "Nodes/CircleDepthToSpace.h"
@@ -55,6 +57,7 @@
 #include "Nodes/CircleGelu.h"
 #include "Nodes/CircleGreater.h"
 #include "Nodes/CircleGreaterEqual.h"
+#include "Nodes/CircleGRU.h"
 #include "Nodes/CircleHardSwish.h"
 #include "Nodes/CircleIf.h"
 #include "Nodes/CircleInstanceNorm.h"
@@ -96,6 +99,7 @@
 #include "Nodes/CircleReduceMin.h"
 #include "Nodes/CircleReduceProd.h"
 #include "Nodes/CircleRelu.h"
+#include "Nodes/CircleRelu0To1.h"
 #include "Nodes/CircleRelu6.h"
 #include "Nodes/CircleReluN1To1.h"
 #include "Nodes/CircleReshape.h"
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleBroadcastTo.h b/compiler/luci/import/include/luci/Import/Nodes/CircleBroadcastTo.h
new file mode 100644 (file)
index 0000000..9c6f6f4
--- /dev/null
@@ -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_BROADCAST_TO_H__
+#define __LUCI_IMPORT_OP_CIRCLE_BROADCAST_TO_H__
+
+#include "luci/Import/GraphBuilder.h"
+
+namespace luci
+{
+
+class CircleBroadcastToGraphBuilder : 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_BROADCAST_TO_H__
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleCumSum.h b/compiler/luci/import/include/luci/Import/Nodes/CircleCumSum.h
new file mode 100644 (file)
index 0000000..adf7c6c
--- /dev/null
@@ -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_CUMSUM_H__
+#define __LUCI_IMPORT_OP_CIRCLE_CUMSUM_H__
+
+#include "luci/Import/GraphBuilder.h"
+
+namespace luci
+{
+
+class CircleCumSumGraphBuilder : 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_CUMSUM_H__
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleGRU.h b/compiler/luci/import/include/luci/Import/Nodes/CircleGRU.h
new file mode 100644 (file)
index 0000000..ed7935e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_GRU_H__
+#define __LUCI_IMPORT_OP_CIRCLE_GRU_H__
+
+#include "luci/Import/GraphBuilder.h"
+
+namespace luci
+{
+
+class CircleGRUGraphBuilder : 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_GRU_H__
diff --git a/compiler/luci/import/include/luci/Import/Nodes/CircleRelu0To1.h b/compiler/luci/import/include/luci/Import/Nodes/CircleRelu0To1.h
new file mode 100644 (file)
index 0000000..3254d77
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_RELU_0_TO_1_H__
+#define __LUCI_IMPORT_OP_CIRCLE_RELU_0_TO_1_H__
+
+#include "luci/Import/GraphBuilder.h"
+
+namespace luci
+{
+
+class CircleRelu0To1GraphBuilder : 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_RELU_0_TO_1_H__
index 9c1fe73..fbdea8a 100644 (file)
@@ -236,7 +236,7 @@ const OriginTable CircleImportMetadata::origin_table(void)
       std::vector<std::shared_ptr<CircleNodeOrigin>> origins;
       for (auto source_id : source_ids)
       {
-        const auto source_name = _source_table.at(source_id);
+        const auto &source_name = _source_table.at(source_id);
         origins.push_back(single_origin(source_id, source_name));
       }
 
index a42c3f9..9d05a1a 100644 (file)
@@ -54,6 +54,8 @@ loco::DataType luci_datatype(const circle::TensorType type)
       return loco::DataType::S32;
     case circle::TensorType_UINT8:
       return loco::DataType::U8;
+    case circle::TensorType_UINT4:
+      return loco::DataType::U4;
     case circle::TensorType_INT64:
       return loco::DataType::S64;
     case circle::TensorType_STRING:
@@ -66,6 +68,8 @@ loco::DataType luci_datatype(const circle::TensorType type)
       break;
     case circle::TensorType_INT8:
       return loco::DataType::S8;
+    case circle::TensorType_INT4:
+      return loco::DataType::S4;
     default:
       break;
   }
index 9c86832..29edf83 100644 (file)
@@ -38,12 +38,14 @@ GraphBuilderRegistry::GraphBuilderRegistry()
   CIRCLE_NODE(BCQ_FULLY_CONNECTED, CircleBCQFullyConnectedGraphBuilder);                   // 253
   CIRCLE_NODE(BCQ_GATHER, CircleBCQGatherGraphBuilder);                                    // 252
   CIRCLE_NODE(BIDIRECTIONAL_SEQUENCE_LSTM, CircleBidirectionalSequenceLSTMGraphBuilder);   // 52
+  CIRCLE_NODE(BROADCAST_TO, CircleBroadcastToGraphBuilder);                                // 130
   CIRCLE_NODE(CAST, CircleCastGraphBuilder);                                               // 53
   CIRCLE_NODE(CEIL, CircleCeilGraphBuilder);                                               // 104
   CIRCLE_NODE(CUSTOM, CircleCustomGraphBuilder);                                           // 32
   CIRCLE_NODE(CONCATENATION, CircleConcatenationGraphBuilder);                             // 2
   CIRCLE_NODE(CONV_2D, CircleConv2DGraphBuilder);                                          // 3
   CIRCLE_NODE(COS, CircleCosGraphBuilder);                                                 // 108
+  CIRCLE_NODE(CUMSUM, CircleCumSumGraphBuilder);                                           // 128
   CIRCLE_NODE(DENSIFY, CircleDensifyGraphBuilder);                                         // 124
   CIRCLE_NODE(DEPTH_TO_SPACE, CircleDepthToSpaceGraphBuilder);                             // 5
   CIRCLE_NODE(DEPTHWISE_CONV_2D, CircleDepthwiseConv2DGraphBuilder);                       // 4
@@ -64,6 +66,7 @@ GraphBuilderRegistry::GraphBuilderRegistry()
   CIRCLE_NODE(GELU, CircleGeluGraphBuilder);                                               // 150
   CIRCLE_NODE(GREATER, CircleGreaterGraphBuilder);                                         // 61
   CIRCLE_NODE(GREATER_EQUAL, CircleGreaterEqualGraphBuilder);                              // 62
+  CIRCLE_NODE(GRU, CircleGRUGraphBuilder);                                                 // 251
   CIRCLE_NODE(HARD_SWISH, CircleHardSwishGraphBuilder);                                    // 117
   CIRCLE_NODE(IF, CircleIfGraphBuilder);                                                   // 118
   CIRCLE_NODE(INSTANCE_NORM, CircleInstanceNormGraphBuilder);                              // 254
@@ -105,6 +108,7 @@ GraphBuilderRegistry::GraphBuilderRegistry()
   CIRCLE_NODE(REDUCE_MIN, CircleReduceMinGraphBuilder);                                    // 89
   CIRCLE_NODE(REDUCE_PROD, CircleReduceProdGraphBuilder);                                  // 81
   CIRCLE_NODE(RELU, CircleReluGraphBuilder);                                               // 19
+  CIRCLE_NODE(RELU_0_TO_1, CircleRelu0To1GraphBuilder);                                    // 152
   CIRCLE_NODE(RELU6, CircleRelu6GraphBuilder);                                             // 21
   CIRCLE_NODE(RELU_N1_TO_1, CircleReluN1To1GraphBuilder);                                  // 20
   CIRCLE_NODE(RESHAPE, CircleReshapeGraphBuilder);                                         // 22
index 91e4860..6967128 100644 (file)
@@ -50,7 +50,6 @@ struct BasicCircleModel
   {
     model->subgraphs.push_back(std::make_unique<circle::SubGraphT>());
     model->subgraphs.back()->name = "";
-    model->subgraphs.back()->data_format = circle::DataFormat_CHANNELS_LAST;
     return model->subgraphs.size() - 1;
   }
 
diff --git a/compiler/luci/import/src/Nodes/CircleBroadcastTo.cpp b/compiler/luci/import/src/Nodes/CircleBroadcastTo.cpp
new file mode 100644 (file)
index 0000000..2ccd13f
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Import/Nodes/CircleBroadcastTo.h"
+
+#include <luci/IR/Nodes/CircleBroadcastTo.h>
+
+#include <loco.h>
+
+namespace luci
+{
+
+bool CircleBroadcastToGraphBuilder::validate(const ValidateArgs &args) const
+{
+  // TODO Support type check
+  return GraphBuilder::validate(args, 2);
+}
+
+CircleNode *CircleBroadcastToGraphBuilder::build_node(const circle::OperatorT &,
+                                                      const std::vector<CircleNode *> &inputs,
+                                                      loco::Graph *graph) const
+{
+  auto *node = graph->nodes()->create<CircleBroadcastTo>();
+  node->input(inputs.at(0));
+  node->shape(inputs.at(1));
+
+  return node;
+}
+
+} // namespace luci
index 88f2ae3..189f4d8 100644 (file)
@@ -102,6 +102,38 @@ void copy_data<loco::DataType::STRING>(const VectorWrapper<uint8_t> &raw_data,
   }
 }
 
+// NOTE copy_data for S4, U4.
+//      this method will unpack two 4bit elements, packed in 8bit,
+//      to two 8bit elements, having values -8~7, for S4 and 0~15 for U4.
+template <loco::DataType DT>
+void copy_data_4(const VectorWrapper<uint8_t> &raw_data, uint32_t num_elements,
+                 CircleConst *const_node)
+{
+  using T = typename loco::DataTypeImpl<DT>::Type;
+
+  // TODO support sparse?
+  assert(const_node->sparsityparam() == nullptr);
+  if (const_node->sparsityparam())
+    return;
+
+  uint32_t raw_size = (num_elements + 1) / 2;
+  assert(raw_data.size() == raw_size);
+
+  const uint8_t *data = raw_data.data();
+  const_node->size<DT>(num_elements);
+  for (uint32_t i = 0; i < raw_size; ++i)
+  {
+    uint32_t idx = i * 2;
+    // for S4, 1bit for sign, 3bit for value
+    const_node->at<DT>(idx) = static_cast<T>(data[i] << 4) >> 4;
+    if (idx < num_elements)
+    {
+      idx++;
+      const_node->at<DT>(idx) = static_cast<T>(data[i]) >> 4;
+    }
+  }
+}
+
 } // namespace
 
 namespace luci
@@ -170,10 +202,18 @@ CircleNode *CircleConstNodeBuilder::build(TensorIndex tensor_index,
         copy_data<loco::DataType::FLOAT16>(buffer, num_elements, const_node);
         break;
 
+      case loco::DataType::U4:
+        copy_data_4<loco::DataType::U4>(buffer, num_elements, const_node);
+        break;
+
       case loco::DataType::U8:
         copy_data<loco::DataType::U8>(buffer, num_elements, const_node);
         break;
 
+      case loco::DataType::S4:
+        copy_data_4<loco::DataType::S4>(buffer, num_elements, const_node);
+        break;
+
       case loco::DataType::S8:
         copy_data<loco::DataType::S8>(buffer, num_elements, const_node);
         break;
diff --git a/compiler/luci/import/src/Nodes/CircleCumSum.cpp b/compiler/luci/import/src/Nodes/CircleCumSum.cpp
new file mode 100644 (file)
index 0000000..b757fc7
--- /dev/null
@@ -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 "luci/Import/Nodes/CircleCumSum.h"
+
+#include <luci/IR/Nodes/CircleCumSum.h>
+
+#include <loco.h>
+
+namespace luci
+{
+
+bool CircleCumSumGraphBuilder::validate(const ValidateArgs &args) const
+{
+  return GraphBuilder::validate(args, 2);
+}
+
+CircleNode *CircleCumSumGraphBuilder::build_node(const circle::OperatorT &op,
+                                                 const std::vector<CircleNode *> &inputs,
+                                                 loco::Graph *graph) const
+{
+  auto *node = graph->nodes()->create<CircleCumSum>();
+  node->input(inputs.at(0));
+  node->axis(inputs.at(1));
+
+  const auto *options = op.builtin_options.AsCumsumOptions();
+  node->exclusive(options->exclusive);
+  node->reverse(options->reverse);
+
+  return node;
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleGRU.cpp b/compiler/luci/import/src/Nodes/CircleGRU.cpp
new file mode 100644 (file)
index 0000000..51fe5f5
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/CircleGRU.h"
+
+#include <luci/IR/Nodes/CircleHardSwish.h>
+
+#include <loco.h>
+
+namespace luci
+{
+
+bool CircleGRUGraphBuilder::validate(const ValidateArgs &args) const
+{
+  return GraphBuilder::validate(args, 6);
+}
+
+CircleNode *CircleGRUGraphBuilder::build_node(const circle::OperatorT &,
+                                              const std::vector<CircleNode *> &inputs,
+                                              loco::Graph *graph) const
+{
+  auto *node = graph->nodes()->create<CircleGRU>();
+  node->input(inputs.at(0));
+  node->hidden_hidden(inputs.at(1));
+  node->hidden_hidden_bias(inputs.at(2));
+  node->hidden_input(inputs.at(3));
+  node->hidden_input_bias(inputs.at(4));
+  node->state(inputs.at(5));
+
+  return node;
+}
+
+} // namespace luci
diff --git a/compiler/luci/import/src/Nodes/CircleRelu0To1.cpp b/compiler/luci/import/src/Nodes/CircleRelu0To1.cpp
new file mode 100644 (file)
index 0000000..a695784
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/CircleRelu0To1.h"
+
+#include <luci/IR/Nodes/CircleRelu6.h>
+
+#include <loco.h>
+
+namespace luci
+{
+
+bool CircleRelu0To1GraphBuilder::validate(const ValidateArgs &args) const
+{
+  return GraphBuilder::validate(args, 1);
+}
+
+CircleNode *CircleRelu0To1GraphBuilder::build_node(const circle::OperatorT &,
+                                                   const std::vector<CircleNode *> &inputs,
+                                                   loco::Graph *graph) const
+{
+  auto *node = graph->nodes()->create<CircleRelu0To1>();
+  node->features(inputs.at(0));
+
+  return node;
+}
+
+} // namespace luci
index fc02770..9943b80 100644 (file)
@@ -79,6 +79,7 @@ bool validate_minmax(const GraphBuilderBase::ValidateArgs &args)
     case circle::TensorType_FLOAT16:
     case circle::TensorType_FLOAT32:
     case circle::TensorType_FLOAT64:
+    case circle::TensorType_INT16:
     case circle::TensorType_INT32:
     case circle::TensorType_INT64:
     case circle::TensorType_UINT8:
index d643b08..4903653 100644 (file)
 #include "Nodes/CircleBatchMatMul.h"
 #include "Nodes/CircleBatchToSpaceND.h"
 #include "Nodes/CircleBidirectionalSequenceLSTM.h"
+#include "Nodes/CircleBroadcastTo.h"
 #include "Nodes/CircleCast.h"
 #include "Nodes/CircleCeil.h"
 #include "Nodes/CircleConcatenation.h"
 #include "Nodes/CircleConv2D.h"
 #include "Nodes/CircleCos.h"
+#include "Nodes/CircleCumSum.h"
 #include "Nodes/CircleCustom.h"
 #include "Nodes/CircleDensify.h"
 #include "Nodes/CircleDepthToSpace.h"
@@ -92,6 +94,7 @@
 #include "Nodes/CircleReduceMin.h"
 #include "Nodes/CircleReduceProd.h"
 #include "Nodes/CircleRelu.h"
+#include "Nodes/CircleRelu0To1.h"
 #include "Nodes/CircleRelu6.h"
 #include "Nodes/CircleReluN1To1.h"
 #include "Nodes/CircleReshape.h"
 // Circle only
 #include "Nodes/CircleBCQFullyConnected.h"
 #include "Nodes/CircleBCQGather.h"
+#include "Nodes/CircleGRU.h"
 #include "Nodes/CircleInstanceNorm.h"
 // Virtual nodes
 #include "Nodes/CircleConst.h"
index 1646909..a97f6b6 100644 (file)
@@ -24,11 +24,13 @@ CIRCLE_NODE(AVERAGE_POOL_2D, CircleAveragePool2D)
 CIRCLE_NODE(BATCH_TO_SPACE_ND, CircleBatchToSpaceND)
 CIRCLE_NODE(BATCH_MATMUL, CircleBatchMatMul)
 CIRCLE_NODE(BIDIRECTIONAL_SEQUENCE_LSTM, CircleBidirectionalSequenceLSTM)
+CIRCLE_NODE(BROADCAST_TO, CircleBroadcastTo)
 CIRCLE_NODE(CAST, CircleCast)
 CIRCLE_NODE(CEIL, CircleCeil)
 CIRCLE_NODE(CONCATENATION, CircleConcatenation)
 CIRCLE_NODE(CONV_2D, CircleConv2D)
 CIRCLE_NODE(COS, CircleCos)
+CIRCLE_NODE(CUMSUM, CircleCumSum)
 CIRCLE_NODE(CUSTOM, CircleCustom)
 CIRCLE_NODE(DENSIFY, CircleDensify)
 CIRCLE_NODE(DEPTH_TO_SPACE, CircleDepthToSpace)
@@ -50,6 +52,7 @@ CIRCLE_NODE(GATHER_ND, CircleGatherNd)
 CIRCLE_NODE(GELU, CircleGelu)
 CIRCLE_NODE(GREATER, CircleGreater)
 CIRCLE_NODE(GREATER_EQUAL, CircleGreaterEqual)
+CIRCLE_NODE(GRU, CircleGRU)
 CIRCLE_NODE(HARD_SWISH, CircleHardSwish)
 CIRCLE_NODE(IF, CircleIf)
 CIRCLE_NODE(L2_NORMALIZATION, CircleL2Normalize)
@@ -90,6 +93,7 @@ CIRCLE_NODE(REDUCE_MAX, CircleReduceMax)
 CIRCLE_NODE(REDUCE_MIN, CircleReduceMin)
 CIRCLE_NODE(REDUCE_PROD, CircleReduceProd)
 CIRCLE_NODE(RELU, CircleRelu)
+CIRCLE_NODE(RELU_0_TO_1, CircleRelu0To1)
 CIRCLE_NODE(RELU6, CircleRelu6)
 CIRCLE_NODE(RELU_N1_TO_1, CircleReluN1To1)
 CIRCLE_NODE(RESHAPE, CircleReshape)
diff --git a/compiler/luci/lang/include/luci/IR/DataTypeHelper.h b/compiler/luci/lang/include/luci/IR/DataTypeHelper.h
new file mode 100644 (file)
index 0000000..fdc97f5
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_LANG_IR_DATA_TYPE_HELPER_H__
+#define __LUCI_LANG_IR_DATA_TYPE_HELPER_H__
+
+#include <loco/IR/DataType.h>
+#include <loco/IR/DataTypeTraits.h>
+
+namespace luci
+{
+
+/**
+ * @brief Returns the size of the data type.
+ * @note  luci saves S4, U4 in a single byte.
+ *        The extra 4 bits in the MSB side are filled with sign bits.
+ */
+inline uint32_t size(loco::DataType data_type)
+{
+  switch (data_type)
+  {
+    case loco::DataType::S4:
+      return sizeof(loco::DataTypeImpl<loco::DataType::S4>::Type);
+    case loco::DataType::U4:
+      return sizeof(loco::DataTypeImpl<loco::DataType::U4>::Type);
+    default:
+      return loco::size(data_type);
+  }
+}
+
+} // namespace luci
+
+#endif // __LUCI_LANG_IR_DATA_TYPE_HELPER_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleBroadcastTo.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleBroadcastTo.h
new file mode 100644 (file)
index 0000000..8d0591b
--- /dev/null
@@ -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.
+ */
+
+#ifndef __LUCI_IR_CIRCLEBROADCASTTO_H__
+#define __LUCI_IR_CIRCLEBROADCASTTO_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/CircleNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief BroadcastTo in Circle
+ */
+class CircleBroadcastTo final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::BROADCAST_TO>>
+{
+public:
+  loco::Node *input(void) const { return at(0)->node(); }
+  void input(loco::Node *node) { at(0)->node(node); }
+
+public:
+  loco::Node *shape(void) const { return at(1)->node(); }
+  void shape(loco::Node *node) { at(1)->node(node); }
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLEBROADCASTTO_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleCumSum.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleCumSum.h
new file mode 100644 (file)
index 0000000..bbeb8a4
--- /dev/null
@@ -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 __LUCI_IR_CIRCLE_CUMSUM_H__
+#define __LUCI_IR_CIRCLE_CUMSUM_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleNodeMixins.h"
+#include "luci/IR/CircleOpcode.h"
+
+namespace luci
+{
+
+class CircleCumSum final : public FixedArityNode<2, CircleNodeImpl<CircleOpcode::CUMSUM>>
+{
+public:
+  loco::Node *input(void) const { return at(0)->node(); }
+  void input(loco::Node *node) { at(0)->node(node); }
+
+  loco::Node *axis(void) const { return at(1)->node(); }
+  void axis(loco::Node *node) { at(1)->node(node); }
+
+public:
+  bool exclusive(void) const { return _exclusive; }
+  void exclusive(bool exclusive) { _exclusive = exclusive; }
+
+  bool reverse(void) const { return _reverse; }
+  void reverse(bool reverse) { _reverse = reverse; }
+
+private:
+  bool _exclusive{false};
+  bool _reverse{false};
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLE_CUMSUM_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleGRU.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleGRU.h
new file mode 100644 (file)
index 0000000..8977299
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_CIRCLE_GRU_H__
+#define __LUCI_IR_CIRCLE_GRU_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/CircleNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief GRU in Circle
+ */
+class CircleGRU final : public FixedArityNode<6, CircleNodeImpl<CircleOpcode::GRU>>
+{
+public:
+  loco::Node *input(void) const { return at(0)->node(); }
+  void input(loco::Node *node) { at(0)->node(node); }
+
+  loco::Node *hidden_hidden(void) const { return at(1)->node(); }
+  void hidden_hidden(loco::Node *node) { at(1)->node(node); }
+
+  loco::Node *hidden_hidden_bias(void) const { return at(2)->node(); }
+  void hidden_hidden_bias(loco::Node *node) { at(2)->node(node); }
+
+  loco::Node *hidden_input(void) const { return at(3)->node(); }
+  void hidden_input(loco::Node *node) { at(3)->node(node); }
+
+  loco::Node *hidden_input_bias(void) const { return at(4)->node(); }
+  void hidden_input_bias(loco::Node *node) { at(4)->node(node); }
+
+  loco::Node *state(void) const { return at(5)->node(); }
+  void state(loco::Node *node) { at(5)->node(node); }
+
+public:
+  FusedActFunc fusedActivationFunction() const { return _fused_act_fun; }
+  void fusedActivationFunction(FusedActFunc fused_act_fun) { _fused_act_fun = fused_act_fun; }
+
+  bool returnSequences() const { return _return_sequences; }
+  void returnSequences(bool return_sequences) { _return_sequences = return_sequences; }
+
+  bool timeMajor() const { return _time_major; }
+  void timeMajor(bool time_major) { _time_major = time_major; }
+
+private:
+  FusedActFunc _fused_act_fun = FusedActFunc::NONE;
+  bool _return_sequences = false;
+  bool _time_major = false;
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLE_GRU_H__
diff --git a/compiler/luci/lang/include/luci/IR/Nodes/CircleRelu0To1.h b/compiler/luci/lang/include/luci/IR/Nodes/CircleRelu0To1.h
new file mode 100644 (file)
index 0000000..7c648df
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_CIRCLERELU_0_TO_1_H__
+#define __LUCI_IR_CIRCLERELU_0_TO_1_H__
+
+#include "luci/IR/CircleNodeDecl.h"
+#include "luci/IR/CircleOpcode.h"
+
+#include "luci/IR/CircleNodeMixins.h"
+
+namespace luci
+{
+
+/**
+ * @brief RELU_0_TO_1 in Circle
+ */
+class CircleRelu0To1 final : public FixedArityNode<1, CircleNodeImpl<CircleOpcode::RELU_0_TO_1>>
+{
+public:
+  loco::Node *features(void) const { return at(0)->node(); }
+  void features(loco::Node *node) { at(0)->node(node); }
+};
+
+} // namespace luci
+
+#endif // __LUCI_IR_CIRCLERELU_0_TO_1_H__
index 6cfff67..15ddeb1 100644 (file)
@@ -202,8 +202,8 @@ public:
   }
   DimMetaData(DimensionType format, int32_t dense_size, const SparseIndexVector &array_segments,
               const SparseIndexVector &array_indices)
-    : _format{format}, _dense_size{dense_size}, _array_segments{array_segments}, _array_indices{
-                                                                                   array_indices}
+    : _format{format}, _dense_size{dense_size}, _array_segments{array_segments},
+      _array_indices{array_indices}
   {
     // DO NOTHING
   }
diff --git a/compiler/luci/lang/src/DataTypeHelper.cpp b/compiler/luci/lang/src/DataTypeHelper.cpp
new file mode 100644 (file)
index 0000000..f2ea503
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 is to validate DataTypeHelper.h
+#include "luci/IR/DataTypeHelper.h"
diff --git a/compiler/luci/lang/src/Nodes/CircleBroadcastTo.test.cpp b/compiler/luci/lang/src/Nodes/CircleBroadcastTo.test.cpp
new file mode 100644 (file)
index 0000000..f24f739
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/CircleBroadcastTo.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleBroadcastToTest, constructor)
+{
+  luci::CircleBroadcastTo broadcast_to_node;
+
+  ASSERT_EQ(luci::CircleDialect::get(), broadcast_to_node.dialect());
+  ASSERT_EQ(luci::CircleOpcode::BROADCAST_TO, broadcast_to_node.opcode());
+
+  ASSERT_EQ(nullptr, broadcast_to_node.input());
+
+  ASSERT_EQ(nullptr, broadcast_to_node.shape());
+}
+
+TEST(CircleBroadcastToTest, input_NEG)
+{
+  luci::CircleBroadcastTo broadcast_to_node;
+  luci::CircleBroadcastTo node;
+
+  broadcast_to_node.input(&node);
+  broadcast_to_node.shape(&node);
+  ASSERT_NE(nullptr, broadcast_to_node.input());
+  ASSERT_NE(nullptr, broadcast_to_node.shape());
+
+  broadcast_to_node.input(nullptr);
+  broadcast_to_node.shape(nullptr);
+  ASSERT_EQ(nullptr, broadcast_to_node.input());
+  ASSERT_EQ(nullptr, broadcast_to_node.shape());
+}
+
+TEST(CircleBroadcastToTest, arity_NEG)
+{
+  luci::CircleBroadcastTo broadcast_to_node;
+
+  ASSERT_NO_THROW(broadcast_to_node.arg(1));
+  ASSERT_THROW(broadcast_to_node.arg(2), std::out_of_range);
+}
+
+TEST(CircleBroadcastToTest, visit_mutable_NEG)
+{
+  struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+  {
+  };
+
+  luci::CircleBroadcastTo broadcast_to_node;
+
+  TestVisitor tv;
+  ASSERT_THROW(broadcast_to_node.accept(&tv), std::exception);
+}
+
+TEST(CircleBroadcastToTest, visit_NEG)
+{
+  struct TestVisitor final : public luci::CircleNodeVisitor<void>
+  {
+  };
+
+  luci::CircleBroadcastTo broadcast_to_node;
+
+  TestVisitor tv;
+  ASSERT_THROW(broadcast_to_node.accept(&tv), std::exception);
+}
index a4854ec..c17a4e2 100644 (file)
@@ -74,8 +74,10 @@ INSTANTIATE(loco::DataType::S64);
 INSTANTIATE(loco::DataType::S32);
 INSTANTIATE(loco::DataType::S16);
 INSTANTIATE(loco::DataType::S8);
+INSTANTIATE(loco::DataType::S4);
 INSTANTIATE(loco::DataType::FLOAT32);
 INSTANTIATE(loco::DataType::U8);
+INSTANTIATE(loco::DataType::U4);
 INSTANTIATE(loco::DataType::BOOL);
 INSTANTIATE(loco::DataType::FLOAT16);
 
diff --git a/compiler/luci/lang/src/Nodes/CircleCumSum.test.cpp b/compiler/luci/lang/src/Nodes/CircleCumSum.test.cpp
new file mode 100644 (file)
index 0000000..424d9a1
--- /dev/null
@@ -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/IR/Nodes/CircleCumSum.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleCumSumTest, constructor_P)
+{
+  luci::CircleCumSum node;
+
+  ASSERT_EQ(luci::CircleDialect::get(), node.dialect());
+  ASSERT_EQ(luci::CircleOpcode::CUMSUM, node.opcode());
+
+  ASSERT_EQ(nullptr, node.input());
+}
+
+TEST(CircleCumSumTest, input_NEG)
+{
+  luci::CircleCumSum node;
+  luci::CircleCumSum input;
+
+  node.input(&input);
+  ASSERT_NE(nullptr, node.input());
+
+  node.input(nullptr);
+  ASSERT_EQ(nullptr, node.input());
+}
+
+// FIXME
+TEST(CircleCumSumTest, arity_NEG)
+{
+  luci::CircleCumSum node;
+
+  ASSERT_NO_THROW(node.arg(0));
+  ASSERT_NO_THROW(node.arg(1));
+  ASSERT_THROW(node.arg(2), std::out_of_range);
+}
+
+TEST(CircleCumSumTest, visit_mutable_NEG)
+{
+  struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+  {
+  };
+
+  luci::CircleCumSum node;
+
+  TestVisitor tv;
+  ASSERT_THROW(node.accept(&tv), std::exception);
+}
+
+TEST(CircleCumSumTest, visit_NEG)
+{
+  struct TestVisitor final : public luci::CircleNodeVisitor<void>
+  {
+  };
+
+  luci::CircleCumSum node;
+
+  TestVisitor tv;
+  ASSERT_THROW(node.accept(&tv), std::exception);
+}
diff --git a/compiler/luci/lang/src/Nodes/CircleGRU.test.cpp b/compiler/luci/lang/src/Nodes/CircleGRU.test.cpp
new file mode 100644 (file)
index 0000000..f7e6f95
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/CircleGRU.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleGRUTest, constructor)
+{
+  luci::CircleGRU gru_node;
+
+  ASSERT_EQ(luci::CircleDialect::get(), gru_node.dialect());
+  ASSERT_EQ(luci::CircleOpcode::GRU, gru_node.opcode());
+
+  ASSERT_EQ(nullptr, gru_node.input());
+  ASSERT_EQ(nullptr, gru_node.hidden_hidden());
+  ASSERT_EQ(nullptr, gru_node.hidden_hidden_bias());
+  ASSERT_EQ(nullptr, gru_node.hidden_input());
+  ASSERT_EQ(nullptr, gru_node.hidden_input_bias());
+  ASSERT_EQ(nullptr, gru_node.state());
+}
+
+TEST(CircleGRUTest, input_NEG)
+{
+  luci::CircleGRU gru_node;
+  luci::CircleGRU node;
+
+  gru_node.input(&node);
+  ASSERT_NE(nullptr, gru_node.input());
+
+  gru_node.input(nullptr);
+  ASSERT_EQ(nullptr, gru_node.input());
+}
+
+TEST(CircleGRUTest, arity_NEG)
+{
+  luci::CircleGRU gru_node;
+
+  ASSERT_NO_THROW(gru_node.arg(0));
+  ASSERT_NO_THROW(gru_node.arg(1));
+  ASSERT_NO_THROW(gru_node.arg(2));
+  ASSERT_NO_THROW(gru_node.arg(3));
+  ASSERT_NO_THROW(gru_node.arg(4));
+  ASSERT_NO_THROW(gru_node.arg(5));
+  ASSERT_THROW(gru_node.arg(6), std::out_of_range);
+}
+
+TEST(CircleGRUTest, visit_mutable_NEG)
+{
+  struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+  {
+  };
+
+  luci::CircleGRU gru_node;
+
+  TestVisitor tv;
+  ASSERT_THROW(gru_node.accept(&tv), std::exception);
+}
+
+TEST(CircleGRUTest, visit_NEG)
+{
+  struct TestVisitor final : public luci::CircleNodeVisitor<void>
+  {
+  };
+
+  luci::CircleGRU gru_node;
+
+  TestVisitor tv;
+  ASSERT_THROW(gru_node.accept(&tv), std::exception);
+}
diff --git a/compiler/luci/lang/src/Nodes/CircleRelu0To1.test.cpp b/compiler/luci/lang/src/Nodes/CircleRelu0To1.test.cpp
new file mode 100644 (file)
index 0000000..2ac89a7
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/CircleRelu0To1.h"
+
+#include "luci/IR/CircleDialect.h"
+#include "luci/IR/CircleNodeVisitor.h"
+
+#include <gtest/gtest.h>
+
+TEST(CircleRelu0ToTest, constructor)
+{
+  luci::CircleRelu0To1 relu0to1_node;
+
+  ASSERT_EQ(luci::CircleDialect::get(), relu0to1_node.dialect());
+  ASSERT_EQ(luci::CircleOpcode::RELU_0_TO_1, relu0to1_node.opcode());
+
+  ASSERT_EQ(nullptr, relu0to1_node.features());
+}
+
+TEST(CircleRelu0ToTest, input_NEG)
+{
+  luci::CircleRelu0To1 relu0to1_node;
+  luci::CircleRelu0To1 node;
+
+  relu0to1_node.features(&node);
+  ASSERT_NE(nullptr, relu0to1_node.features());
+
+  relu0to1_node.features(nullptr);
+  ASSERT_EQ(nullptr, relu0to1_node.features());
+}
+
+TEST(CircleRelu0ToTest, arity_NEG)
+{
+  luci::CircleRelu0To1 relu0to1_node;
+
+  ASSERT_NO_THROW(relu0to1_node.arg(0));
+  ASSERT_THROW(relu0to1_node.arg(1), std::out_of_range);
+}
+
+TEST(CircleRelu0ToTest, visit_mutable_NEG)
+{
+  struct TestVisitor final : public luci::CircleNodeMutableVisitor<void>
+  {
+  };
+
+  luci::CircleRelu0To1 relu0to1_node;
+
+  TestVisitor tv;
+  ASSERT_THROW(relu0to1_node.accept(&tv), std::exception);
+}
+
+TEST(CircleRelu0ToTest, visit_NEG)
+{
+  struct TestVisitor final : public luci::CircleNodeVisitor<void>
+  {
+  };
+
+  luci::CircleRelu0To1 relu0to1_node;
+
+  TestVisitor tv;
+  ASSERT_THROW(relu0to1_node.accept(&tv), std::exception);
+}
index e7f38d0..2ff37af 100644 (file)
@@ -144,12 +144,14 @@ CircleNodeSummaryBuilder::create_builder(const luci::CircleNode *node)
     CIRCLE_NODE(BCQ_FULLY_CONNECTED, CircleBCQFullyConnectedSummaryBuilder)
     CIRCLE_NODE(BCQ_GATHER, CircleBCQGatherSummaryBuilder)
     CIRCLE_NODE(BIDIRECTIONAL_SEQUENCE_LSTM, CircleBidirectionalSequenceLSTMSummaryBuilder)
+    CIRCLE_NODE(BROADCAST_TO, CircleBroadcastToSummaryBuilder)
     CIRCLE_NODE(CAST, CircleCastSummaryBuilder)
     CIRCLE_NODE(CEIL, CircleCeilSummaryBuilder)
     CIRCLE_NODE(CONCATENATION, CircleConcatenationSummaryBuilder)
     CIRCLE_NODE(CIRCLECONST, CircleConstSummaryBuilder)
     CIRCLE_NODE(CONV_2D, CircleConv2DSummaryBuilder)
     CIRCLE_NODE(COS, CircleCosSummaryBuilder)
+    CIRCLE_NODE(CUMSUM, CircleCumsumSummaryBuilder)
     CIRCLE_NODE(CUSTOM, CircleCustomSummaryBuilder)
     CIRCLE_NODE(DENSIFY, CircleDensifySummaryBuilder)
     CIRCLE_NODE(DEPTH_TO_SPACE, CircleDepthToSpaceSummaryBuilder)
@@ -171,6 +173,7 @@ CircleNodeSummaryBuilder::create_builder(const luci::CircleNode *node)
     CIRCLE_NODE(GELU, CircleGeluSummaryBuilder)
     CIRCLE_NODE(GREATER, CircleGreaterSummaryBuilder)
     CIRCLE_NODE(GREATER_EQUAL, CircleGreaterEqualSummaryBuilder)
+    CIRCLE_NODE(GRU, CircleGRUSummaryBuilder)
     CIRCLE_NODE(HARD_SWISH, CircleHardSwishSummaryBuilder)
     CIRCLE_NODE(IF, CircleIfSummaryBuilder)
     CIRCLE_NODE(INSTANCE_NORM, CircleInstanceNormSummaryBuilder)
@@ -212,6 +215,7 @@ CircleNodeSummaryBuilder::create_builder(const luci::CircleNode *node)
     CIRCLE_NODE(REDUCE_MIN, CircleReduceMinSummaryBuilder)
     CIRCLE_NODE(REDUCE_PROD, CircleReduceProdSummaryBuilder)
     CIRCLE_NODE(RELU, CircleReluSummaryBuilder)
+    CIRCLE_NODE(RELU_0_TO_1, CircleRelu0To1SummaryBuilder)
     CIRCLE_NODE(RELU6, CircleRelu6SummaryBuilder)
     CIRCLE_NODE(RELU_N1_TO_1, CircleReluN1To1SummaryBuilder)
     CIRCLE_NODE(RESHAPE, CircleReshapeSummaryBuilder)
index aba6a86..f0a92ef 100644 (file)
@@ -30,6 +30,8 @@ std::string to_str(loco::DataType type)
 {
   switch (type)
   {
+    case loco::DataType::U4:
+      return "UINT4";
     case loco::DataType::U8:
       return "UINT8";
     case loco::DataType::U16:
@@ -39,6 +41,8 @@ std::string to_str(loco::DataType type)
     case loco::DataType::U64:
       return "UINT64";
 
+    case loco::DataType::S4:
+      return "INT4";
     case loco::DataType::S8:
       return "INT8";
     case loco::DataType::S16:
@@ -108,6 +112,11 @@ std::string to_str(const luci::Stride *stride)
   return std::to_string(stride->h()) + "," + std::to_string(stride->w());
 }
 
+std::string to_str(const luci::Dilation *dilation)
+{
+  return std::to_string(dilation->h()) + "," + std::to_string(dilation->w());
+}
+
 std::string to_str(const luci::Filter *filter)
 {
   return std::to_string(filter->h()) + "," + std::to_string(filter->w());
@@ -343,6 +352,25 @@ void CircleBidirectionalSequenceLSTMSummaryBuilder::build_attributes(const luci:
   s.args().append("asymmetric_quantize_inputs", to_str(lstm->asymmetric_quantize_inputs()));
 }
 
+std::vector<std::string> CircleGRUSummaryBuilder::get_input_names(const luci::CircleNode *)
+{
+  return {"input",        "hidden_hidden",     "hidden_hidden_bias",
+          "hidden_input", "hidden_input_bias", "state"};
+}
+
+void CircleGRUSummaryBuilder::build_attributes(const luci::CircleNode *node, locop::NodeSummary &s)
+{
+  auto gru = loco::must_cast<const luci::CircleGRU *>(node);
+  s.args().append("fused_act_function", to_str(gru->fusedActivationFunction()));
+  s.args().append("return_sequence", to_str(gru->returnSequences()));
+  s.args().append("time_major", to_str(gru->timeMajor()));
+}
+
+std::vector<std::string> CircleBroadcastToSummaryBuilder::get_input_names(const luci::CircleNode *)
+{
+  return {"input", "shape"};
+}
+
 std::vector<std::string> CircleCastSummaryBuilder::get_input_names(const luci::CircleNode *)
 {
   return {"x"};
@@ -425,6 +453,19 @@ void CircleConv2DSummaryBuilder::build_attributes(const luci::CircleNode *node,
   s.args().append("fused_activation_function", to_str(conv2d->fusedActivationFunction()));
 }
 
+std::vector<std::string> CircleCumsumSummaryBuilder::get_input_names(const luci::CircleNode *)
+{
+  return {"input", "axis"};
+}
+
+void CircleCumsumSummaryBuilder::build_attributes(const luci::CircleNode *node,
+                                                  locop::NodeSummary &s)
+{
+  auto cumsum = loco::must_cast<const luci::CircleCumSum *>(node);
+  s.args().append("exclusive", to_str(cumsum->exclusive()));
+  s.args().append("reverse", to_str(cumsum->reverse()));
+}
+
 std::vector<std::string> CircleCustomSummaryBuilder::get_input_names(const luci::CircleNode *node)
 {
   auto input_names = std::vector<std::string>();
index 0bdb05d..f489e9b 100644 (file)
@@ -145,6 +145,12 @@ private:
   void build_attributes(const luci::CircleNode *node, locop::NodeSummary &s);
 };
 
+class CircleBroadcastToSummaryBuilder final : public CircleNodeSummaryBuilder
+{
+private:
+  std::vector<std::string> get_input_names(const luci::CircleNode *);
+};
+
 class CircleCastSummaryBuilder final : public CircleNodeSummaryBuilder
 {
 private:
@@ -183,6 +189,13 @@ class CircleCosSummaryBuilder final : public CircleNodeWithXSummaryBuilder
 {
 };
 
+class CircleCumsumSummaryBuilder final : public CircleNodeSummaryBuilder
+{
+private:
+  std::vector<std::string> get_input_names(const luci::CircleNode *);
+  void build_attributes(const luci::CircleNode *node, locop::NodeSummary &s);
+};
+
 class CircleCustomSummaryBuilder final : public CircleNodeSummaryBuilder
 {
 private:
@@ -294,6 +307,13 @@ class CircleGreaterEqualSummaryBuilder final : public CircleNodeWithXYSummaryBui
 {
 };
 
+class CircleGRUSummaryBuilder final : public CircleNodeSummaryBuilder
+{
+private:
+  std::vector<std::string> get_input_names(const luci::CircleNode *);
+  void build_attributes(const luci::CircleNode *node, locop::NodeSummary &s);
+};
+
 class CircleHardSwishSummaryBuilder final : public CircleNodeWithFEATURESSummaryBuilder
 {
 };
@@ -517,6 +537,10 @@ class CircleReluSummaryBuilder final : public CircleNodeWithFEATURESSummaryBuild
 {
 };
 
+class CircleRelu0To1SummaryBuilder final : public CircleNodeWithFEATURESSummaryBuilder
+{
+};
+
 class CircleRelu6SummaryBuilder final : public CircleNodeWithFEATURESSummaryBuilder
 {
 };
index 304ef63..001194e 100644 (file)
@@ -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_circle06)
+target_link_libraries(luci_partition PRIVATE mio_circle08)
 target_link_libraries(luci_partition PRIVATE nncc_common)
 target_link_libraries(luci_partition PRIVATE pepper_csv2vec)
 target_link_libraries(luci_partition PRIVATE oops)
index d8cbfc6..7539aaf 100644 (file)
@@ -70,12 +70,14 @@ public:
   void visit(const luci::CircleAveragePool2D *) final;
   void visit(const luci::CircleBatchMatMul *) final;
   void visit(const luci::CircleBatchToSpaceND *) final;
+  void visit(const luci::CircleBroadcastTo *) final;
   void visit(const luci::CircleCast *) final;
   void visit(const luci::CircleCeil *) final;
   void visit(const luci::CircleConcatenation *) final;
   void visit(const luci::CircleConst *) final;
   void visit(const luci::CircleConv2D *) final;
   void visit(const luci::CircleCos *) final;
+  void visit(const luci::CircleCumSum *) final;
   void visit(const luci::CircleCustom *) final;
   void visit(const luci::CircleDensify *) final;
   void visit(const luci::CircleDepthToSpace *) final;
@@ -137,6 +139,7 @@ public:
   void visit(const luci::CircleReduceMin *) final;
   void visit(const luci::CircleReduceProd *) final;
   void visit(const luci::CircleRelu *) final;
+  void visit(const luci::CircleRelu0To1 *) final;
   void visit(const luci::CircleRelu6 *) final;
   void visit(const luci::CircleReluN1To1 *) final;
   void visit(const luci::CircleReshape *) final;
@@ -182,6 +185,7 @@ public:
   // Circle Only
   void visit(const luci::CircleBCQFullyConnected *) final;
   void visit(const luci::CircleBCQGather *) final;
+  void visit(const luci::CircleGRU *) final;
   void visit(const luci::CircleInstanceNorm *) final;
 
   // NOTE CircleInput and CircleOutput are not handled here as these need
diff --git a/compiler/luci/partition/src/Nodes/CircleBroadcastTo.cpp b/compiler/luci/partition/src/Nodes/CircleBroadcastTo.cpp
new file mode 100644 (file)
index 0000000..5c1e248
--- /dev/null
@@ -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 "luci/ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleBroadcastTo *node)
+{
+  auto *cloned = loco::must_cast<luci::CircleBroadcastTo *>(cn->find_clone(node));
+
+  luci::CircleNode *input = loco::must_cast<luci::CircleNode *>(node->input());
+  luci::CircleNode *shape = loco::must_cast<luci::CircleNode *>(node->shape());
+
+  cloned->input(cn->find_clone(input));
+  cloned->shape(cn->find_clone(shape));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleBroadcastTo *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleBroadcastTo.test.cpp b/compiler/luci/partition/src/Nodes/CircleBroadcastTo.test.cpp
new file mode 100644 (file)
index 0000000..90f24c5
--- /dev/null
@@ -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 "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::CircleBroadcastTo>
+{
+public:
+  NodeGraphlet() = default;
+};
+
+class TestNodeGraph : public TestIsOGraph<2>, public NodeGraphlet
+{
+public:
+  TestNodeGraph() = default;
+
+public:
+  void init(const ShapeU32 shape)
+  {
+    TestIsOGraph<2>::init({shape, shape}, shape);
+    NodeGraphlet::init(g());
+
+    node()->input(input(0));
+    node()->shape(input(1));
+
+    output()->from(node());
+  }
+};
+
+} // namespace
+
+TEST(ConnectNodeTest, connect_BroadcastTo)
+{
+  TestNodeGraph tng;
+  tng.init({2, 3});
+
+  ConnectionTestHelper cth;
+  cth.prepare_inputs(&tng);
+
+  auto *node = tng.node();
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleBroadcastTo *>(node));
+
+  auto *clone = luci::clone_node(node, cth.graph_clone());
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleBroadcastTo *>(clone));
+
+  cth.clone_connect(node, clone);
+
+  ASSERT_EQ(2, clone->arity());
+  ASSERT_EQ(cth.inputs(0), clone->arg(0));
+  ASSERT_EQ(cth.inputs(1), clone->arg(1));
+}
+
+TEST(ConnectNodeTest, connect_BroadcastTo_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::CircleBroadcastTo *>(node));
+
+  auto *clone = luci::clone_node(node, cth.graph_clone());
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleBroadcastTo *>(clone));
+
+  EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
diff --git a/compiler/luci/partition/src/Nodes/CircleCumSum.cpp b/compiler/luci/partition/src/Nodes/CircleCumSum.cpp
new file mode 100644 (file)
index 0000000..1110c42
--- /dev/null
@@ -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 "luci/ConnectNode.h"
+
+namespace
+{
+
+void connect(luci::ConnectNode *cn, const luci::CircleCumSum *node)
+{
+  auto *cloned = loco::must_cast<luci::CircleCumSum *>(cn->find_clone(node));
+
+  luci::CircleNode *input = loco::must_cast<luci::CircleNode *>(node->input());
+  luci::CircleNode *axis = loco::must_cast<luci::CircleNode *>(node->axis());
+
+  cloned->input(cn->find_clone(input));
+  cloned->axis(cn->find_clone(axis));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleCumSum *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleCumSum.test.cpp b/compiler/luci/partition/src/Nodes/CircleCumSum.test.cpp
new file mode 100644 (file)
index 0000000..9e9cd82
--- /dev/null
@@ -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.
+ */
+
+#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::CircleCumSum>
+{
+public:
+  NodeGraphlet() = default;
+
+public:
+  void init(loco::Graph *g) override
+  {
+    NodeGraphletT<luci::CircleCumSum>::init(g);
+
+    _node->exclusive(false);
+    _node->reverse(false);
+  }
+};
+
+class TestNodeGraph : public TestIsOGraph<2>, public NodeGraphlet
+{
+public:
+  TestNodeGraph() = default;
+
+public:
+  void init(const ShapeU32 shape)
+  {
+    TestIsOGraph<2>::init({shape, {0}}, shape);
+    NodeGraphlet::init(g());
+
+    node()->input(input(0));
+    node()->axis(input(1));
+
+    output()->from(node());
+  }
+};
+
+} // namespace
+
+TEST(ConnectNodeTest, connect_CumSum)
+{
+  TestNodeGraph tng;
+  tng.init({2, 3});
+
+  ConnectionTestHelper cth;
+  cth.prepare_inputs(&tng);
+
+  auto *node = tng.node();
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleCumSum *>(node));
+
+  auto *clone = luci::clone_node(node, cth.graph_clone());
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleCumSum *>(clone));
+
+  cth.clone_connect(node, clone);
+
+  ASSERT_EQ(2, clone->arity());
+  ASSERT_EQ(cth.inputs(0), clone->arg(0));
+  ASSERT_EQ(cth.inputs(1), clone->arg(1));
+}
+
+TEST(ConnectNodeTest, connect_CumSum_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::CircleCumSum *>(node));
+
+  auto *clone = luci::clone_node(node, cth.graph_clone());
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleCumSum *>(clone));
+
+  EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
diff --git a/compiler/luci/partition/src/Nodes/CircleGRU.cpp b/compiler/luci/partition/src/Nodes/CircleGRU.cpp
new file mode 100644 (file)
index 0000000..c0995f4
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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::CircleGRU *node)
+{
+  auto *cloned = loco::must_cast<luci::CircleGRU *>(cn->find_clone(node));
+
+  luci::CircleNode *input = loco::must_cast<luci::CircleNode *>(node->input());
+  luci::CircleNode *hidden_input = loco::must_cast<luci::CircleNode *>(node->hidden_input());
+  luci::CircleNode *hidden_input_bias =
+    loco::must_cast<luci::CircleNode *>(node->hidden_input_bias());
+  luci::CircleNode *hidden_hidden = loco::must_cast<luci::CircleNode *>(node->hidden_hidden());
+  luci::CircleNode *hidden_hidden_bias =
+    loco::must_cast<luci::CircleNode *>(node->hidden_hidden_bias());
+  luci::CircleNode *state = loco::must_cast<luci::CircleNode *>(node->state());
+
+  cloned->input(cn->find_clone(input));
+  cloned->hidden_input(cn->find_clone(hidden_input));
+  cloned->hidden_input_bias(cn->find_clone(hidden_input_bias));
+  cloned->hidden_hidden(cn->find_clone(hidden_hidden));
+  cloned->hidden_hidden_bias(cn->find_clone(hidden_hidden_bias));
+  cloned->state(cn->find_clone(state));
+}
+
+} // namespace
+
+namespace luci
+{
+
+void ConnectNode::visit(const luci::CircleGRU *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleGRU.test.cpp b/compiler/luci/partition/src/Nodes/CircleGRU.test.cpp
new file mode 100644 (file)
index 0000000..c0720a1
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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::CircleGRU>
+{
+public:
+  NodeGraphlet() = default;
+
+public:
+  void init(loco::Graph *g) override
+  {
+    NodeGraphletT<luci::CircleGRU>::init(g);
+
+    _node->fusedActivationFunction(luci::FusedActFunc::NONE);
+  }
+};
+
+class TestNodeGraph : public TestIsOGraph<6>, public NodeGraphlet
+{
+public:
+  TestNodeGraph() = default;
+
+public:
+  void init(const ShapeU32 shape)
+  {
+    TestIsOGraph<6>::init({shape, shape, shape, shape, shape, shape}, shape);
+    NodeGraphlet::init(g());
+
+    node()->input(input(0));
+    node()->hidden_hidden(input(1));
+    node()->hidden_hidden_bias(input(2));
+    node()->hidden_input(input(3));
+    node()->hidden_input_bias(input(4));
+    node()->state(input(5));
+
+    output()->from(node());
+  }
+};
+
+} // namespace
+
+TEST(ConnectNodeTest, connect_CIRCLE_GRU)
+{
+  TestNodeGraph tng;
+  tng.init({10, 1, 4});
+
+  ConnectionTestHelper cth;
+  cth.prepare_inputs(&tng);
+
+  auto *node = tng.node();
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleGRU *>(node));
+
+  auto *clone = luci::clone_node(node, cth.graph_clone());
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleGRU *>(clone));
+
+  cth.clone_connect(node, clone);
+
+  ASSERT_EQ(6, clone->arity());
+  // 24 separate checks is too much
+  for (uint32_t i = 0; i < 6; ++i)
+    ASSERT_EQ(cth.inputs(i), clone->arg(i));
+}
+
+TEST(ConnectNodeTest, connect_CIRCLE_GRU_NEG)
+{
+  TestNodeGraph tng;
+  tng.init({10, 1, 4});
+
+  ConnectionTestHelper cth;
+  cth.prepare_inputs_miss(&tng);
+
+  auto *node = tng.node();
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleGRU *>(node));
+
+  auto *clone = luci::clone_node(node, cth.graph_clone());
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleGRU *>(clone));
+
+  EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
diff --git a/compiler/luci/partition/src/Nodes/CircleRelu0To1.cpp b/compiler/luci/partition/src/Nodes/CircleRelu0To1.cpp
new file mode 100644 (file)
index 0000000..8f9a076
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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::CircleRelu0To1 *node)
+{
+  auto *cloned = loco::must_cast<luci::CircleRelu0To1 *>(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::CircleRelu0To1 *node) { connect(this, node); }
+
+} // namespace luci
diff --git a/compiler/luci/partition/src/Nodes/CircleRelu0To1.test.cpp b/compiler/luci/partition/src/Nodes/CircleRelu0To1.test.cpp
new file mode 100644 (file)
index 0000000..ba7290f
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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::CircleRelu0To1>
+{
+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_Relu0To1)
+{
+  TestNodeGraph tng;
+  tng.init({2, 3});
+
+  ConnectionTestHelper cth;
+  cth.prepare_inputs(&tng);
+
+  auto *node = tng.node();
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleRelu0To1 *>(node));
+
+  auto *clone = luci::clone_node(node, cth.graph_clone());
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleRelu0To1 *>(clone));
+
+  cth.clone_connect(node, clone);
+
+  ASSERT_EQ(1, clone->arity());
+  ASSERT_EQ(cth.inputs(0), clone->arg(0));
+}
+
+TEST(ConnectNodeTest, connect_Relu0To1_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::CircleRelu0To1 *>(node));
+
+  auto *clone = luci::clone_node(node, cth.graph_clone());
+  ASSERT_NO_THROW(loco::must_cast<luci::CircleRelu0To1 *>(clone));
+
+  EXPECT_ANY_THROW(cth.clone_connect(node, clone));
+}
index 0fabfc4..5a78d99 100644 (file)
@@ -56,7 +56,7 @@ void dump(std::ostream &os, const PGroups *pgroups)
   for (auto it = pgroups->node2group.begin(); it != pgroups->node2group.end(); ++it)
   {
     auto node = it->first;
-    auto group = it->second;
+    auto &group = it->second;
     os << "  Node: " << node << "(" << luci::opcode_name(node) << "," << node->name()
        << "): " << group << std::endl;
   }
index ac18a5f..0dd884a 100644 (file)
@@ -1,4 +1,4 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 nnas_find_package(Fp16Source QUIET)
 
 if(NOT FlatBuffers_FOUND)
@@ -35,7 +35,7 @@ target_link_libraries(luci_pass PRIVATE luci_compute)
 target_link_libraries(luci_pass PRIVATE nncc_common)
 target_link_libraries(luci_pass PRIVATE pepper_csv2vec)
 target_link_libraries(luci_pass PRIVATE oops)
-target_link_libraries(luci_pass PRIVATE flatbuffers-2.0)
+target_link_libraries(luci_pass PRIVATE flatbuffers-23.5.26)
 install(TARGETS luci_pass DESTINATION lib)
 install(DIRECTORY include/ DESTINATION include
         FILES_MATCHING PATTERN "*.h")
@@ -51,5 +51,5 @@ target_include_directories(luci_pass_test PRIVATE src)
 target_link_libraries(luci_pass_test luci_pass)
 target_link_libraries(luci_pass_test luci_lang)
 target_link_libraries(luci_pass_test luci_testhelper)
-target_link_libraries(luci_pass_test flatbuffers-2.0)
+target_link_libraries(luci_pass_test flatbuffers-23.5.26)
 #target_link_libraries(luci_pass_test oops)
index 6ebacee..bdae7d5 100644 (file)
@@ -34,20 +34,28 @@ public:
   {
     enum Algorithm
     {
+      FuseAddToFullyConnectedBias,
+      FuseAddWithConv,
       FuseAddWithFullyConnected,
       FuseAddWithTConv,
       FuseBatchNormWithConv,
       FuseBatchNormWithDwConv,
       FuseBatchNormWithTConv,
+      FuseMulToFullyConnectedWeights,
+      FuseSliceWithTConv,
       FuseBCQ,
+      FuseHorizontalFullyConnected,
       FuseInstanceNorm,
       FuseMeanWithMean,
+      FuseMulWithConv,
+      FuseMulWithDiv,
       FuseTransposeWithMean,
       ResolveCustomOpAdd,
       ResolveCustomOpBatchMatMul,
       ResolveCustomOpMatMul,
       ResolveCustomOpMaxPoolWithArgmax,
       ResolveCustomOpSplitV,
+      ResolveFormerCustomOp,
       FoldAddV2,
       FoldCast,
       FoldDensify,
@@ -55,7 +63,11 @@ public:
       FoldFullyConnected,
       FoldDequantize,
       FoldGather,
+      FoldMul,
+      FoldReshape,
+      FoldShape,
       FoldSparseToDense,
+      FoldSqueeze,
       ForwardReshapeToUnaryOp,
       ForwardTransposeOp,
       SparsifyTensorPass,
@@ -64,32 +76,42 @@ public:
       FuseActivationFunction,
       FusePRelu,
       FuseGelu,
+      FuseRsqrt,
       ShuffleWeightTo16x1Float32,
       RemoveRedundantTranspose,
       ReplaceMulAddWithDepthwiseConv,
       ReplaceNonConstFCWithBatchMatMul,
       ReplaceSubWithAdd,
+      ReplaceWithFCGeluFC,
       SubstitutePackToReshape,
       SubstitutePadV2ToPad,
       SubstituteSplitVToSplit,
       SubstituteSqueezeToReshape,
       ExpandBroadcastConst,
       ConvertNCHWToNHWC,
+      CommonSubExpressionElimination,
+      RemoveUnnecessaryAdd,
       RemoveUnnecessarySlice,
       RemoveUnnecessaryStridedSlice,
       RemoveUnnecessarySplit,
       RemoveUnnecessaryReshape,
+      RemoveUnnecessaryTranspose,
       TransformMinMaxToRelu6Pass,
       TransformMinReluToRelu6Pass,
+      TransformSqrtDivToRsqrtMul,
       DecomposeHardSwishPass,
+      DecomposeSoftmaxPass,
       SubstituteStridedSliceToReshape,
       SubstituteTransposeToReshape,
       RemoveRedundantQuantize,
       RemoveRedundantReshape,
       RemoveFakeQuant,
+      RemoveQDQForMixedPrecisionOp,
       RemoveQuantDequantSeq,
       RemoveDuplicateConst,
       UnrollUnidirSeqLSTM,
+      XpSepActFromTransposeConv,
+      RemoveGatherGuard,
     };
 
     enum AlgorithmParameters
index 463f317..8fd19cc 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <loco.h>
 
+#include <iterator>
 #include <string>
 #include <vector>
 
@@ -37,6 +38,24 @@ public:
       std::string granularity;
     };
 
+    using LayerParams = std::vector<std::shared_ptr<LayerParam>>;
+
+    // NOTE ...Set is not related with std::set but used as to denote
+    //      multple 'set' of LayerParams.
+    class LayerParamsSet
+    {
+    public:
+      // some helper methods
+      size_t size(void) const { return items.size(); }
+      template <class... Args> void emplace_back(Args &&...args) { items.emplace_back(args...); }
+      std::vector<LayerParams>::iterator begin() { return items.begin(); };
+      std::vector<LayerParams>::iterator end() { return items.end(); };
+
+    private:
+      // store multiple set of LayerParams
+      std::vector<LayerParams> items;
+    };
+
     enum Algorithm
     {
       QuantizeDequantizeWeights,
@@ -46,6 +65,7 @@ public:
       ForceQuantParam,
       ConvertToFakeQuantizedModel,
       QuantizeWeights,
+      QuantizeOnnxFakeQuantizedModel,
     };
 
     enum AlgorithmParameters
@@ -66,6 +86,7 @@ public:
       Quantize_input_type,
       Quantize_output_type,
       Quantize_TF_style_maxpool,
+      Quantize_save_min_max,
     };
 
     virtual ~Options() = default;
@@ -78,8 +99,10 @@ public:
     virtual std::vector<std::string> params(AlgorithmParameters) const = 0;
 
     // Quantization parameters for multiple layers
-    virtual void layer_params(AlgorithmParameters, std::vector<std::shared_ptr<LayerParam>> &) = 0;
-    virtual std::vector<std::shared_ptr<LayerParam>> layer_params(AlgorithmParameters) const = 0;
+    virtual void layer_params(AlgorithmParameters, LayerParams &) = 0;
+    virtual LayerParams layer_params(AlgorithmParameters) const = 0;
+    virtual void layer_params_set(LayerParamsSet &) = 0;
+    virtual LayerParamsSet layer_params_set(void) const = 0;
   };
 
 public:
diff --git a/compiler/luci/pass/include/luci/Pass/CommonSubExpressionEliminationPass.h b/compiler/luci/pass/include/luci/Pass/CommonSubExpressionEliminationPass.h
new file mode 100644 (file)
index 0000000..30b2167
--- /dev/null
@@ -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_COMMON_SUB_EXPRESSION_ELIMINATION_PASS_H__
+#define __LUCI_COMMON_SUB_EXPRESSION_ELIMINATION_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Pass to perform CSE (Common Sub-expression Elimination)
+ */
+class CommonSubExpressionEliminationPass : public logo::Pass
+{
+public:
+  virtual const char *name(void) const { return "luci::CommonSubExpressionEliminationPass"; }
+
+public:
+  bool run(loco::Graph *graph);
+};
+
+} // namespace luci
+
+#endif //__LUCI_COMMON_SUB_EXPRESSION_ELIMINATION_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/DecomposeSoftmaxPass.h b/compiler/luci/pass/include/luci/Pass/DecomposeSoftmaxPass.h
new file mode 100644 (file)
index 0000000..ecf95b3
--- /dev/null
@@ -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_DECOMPOSE_SOFTMAX_PASS_H__
+#define __LUCI_DECOMPOSE_SOFTMAX_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to decompose Softmax into backend friendly structures
+ */
+struct DecomposeSoftmaxPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::DecomposeSoftmaxPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_DECOMPOSE_SOFTMAX_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FoldMulPass.h b/compiler/luci/pass/include/luci/Pass/FoldMulPass.h
new file mode 100644 (file)
index 0000000..69b661f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FOLD_MUL_PASS_H__
+#define __LUCI_FOLD_MUL_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fold Mul to a constant tensor
+ *
+ */
+struct FoldMulPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FoldMulPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FOLD_MUL_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FoldReshapePass.h b/compiler/luci/pass/include/luci/Pass/FoldReshapePass.h
new file mode 100644 (file)
index 0000000..214b2bf
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FOLD_RESHAPE_PASS_H__
+#define __LUCI_FOLD_RESHAPE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fold Reshape to a constant tensor
+ *
+ */
+struct FoldReshapePass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FoldReshapePass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FOLD_RESHAPE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FoldShapePass.h b/compiler/luci/pass/include/luci/Pass/FoldShapePass.h
new file mode 100644 (file)
index 0000000..0e5dee1
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FOLD_SHAPE_PASS_H__
+#define __LUCI_FOLD_SHAPE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fold Shape to a constant tensor
+ */
+struct FoldShapePass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FoldShapePass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FOLD_SHAPE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FoldSqueezePass.h b/compiler/luci/pass/include/luci/Pass/FoldSqueezePass.h
new file mode 100644 (file)
index 0000000..c7e7f19
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_FOLD_SQUEEZE_PASS_H__
+#define __LUCI_FOLD_SQUEEZE_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fold Squeeze to a constant tensor
+ *
+ */
+struct FoldSqueezePass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FoldSqueezePass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FOLD_SQUEEZE_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseAddToFullyConnectedBiasPass.h b/compiler/luci/pass/include/luci/Pass/FuseAddToFullyConnectedBiasPass.h
new file mode 100644 (file)
index 0000000..9aef478
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_ADD_TO_FULLY_CONNECTED_BIAS_PASS_H__
+#define __LUCI_FUSE_ADD_TO_FULLY_CONNECTED_BIAS_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fuse Add to following FC bias
+ */
+struct FuseAddToFullyConnectedBiasPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FuseAddToFullyConnectedBiasPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FUSE_ADD_TO_FULLY_CONNECTED_BIAS_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseAddWithConvPass.h b/compiler/luci/pass/include/luci/Pass/FuseAddWithConvPass.h
new file mode 100644 (file)
index 0000000..c6c5981
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_ADD_WITH_CONV_PASS_H__
+#define __LUCI_FUSE_ADD_WITH_CONV_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fuse CircleAdd into CircleConv2D
+ */
+struct FuseAddWithConvPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FuseAddWithConvPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FUSE_ADD_WITH_CONV_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseHorizontalFullyConnectedPass.h b/compiler/luci/pass/include/luci/Pass/FuseHorizontalFullyConnectedPass.h
new file mode 100644 (file)
index 0000000..49729c0
--- /dev/null
@@ -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.
+ */
+
+#ifndef __LUCI_FUSE_HORIZONTAL_FULLY_CONNECTED_PASS_H__
+#define __LUCI_FUSE_HORIZONTAL_FULLY_CONNECTED_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+struct FuseHorizontalFullyConnectedPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FuseHorizontalFullyConnectedPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FUSE_HORIZONTAL_FULLY_CONNECTED_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseMulToFullyConnectedWeightsPass.h b/compiler/luci/pass/include/luci/Pass/FuseMulToFullyConnectedWeightsPass.h
new file mode 100644 (file)
index 0000000..583f21e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_MUL_TO_FULLY_CONNECTED_WEIGHTS_PASS_H__
+#define __LUCI_FUSE_MUL_TO_FULLY_CONNECTED_WEIGHTS_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fuse Mul into following FullyConnected
+ */
+struct FuseMulToFullyConnectedWeightsPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FuseMulToFullyConnectedWeightsPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FUSE_MUL_TO_FULLY_CONNECTED_WEIGHTS_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseMulWithConvPass.h b/compiler/luci/pass/include/luci/Pass/FuseMulWithConvPass.h
new file mode 100644 (file)
index 0000000..08977f2
--- /dev/null
@@ -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_FUSE_MUL_WITH_CONV_H__
+#define __LUCI_FUSE_MUL_WITH_CONV_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fuse Mul operation with a preceding Conv
+ */
+struct FuseMulWithConvPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FuseMulWithConvPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FUSE_MUL_WITH_CONV_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseMulWithDivPass.h b/compiler/luci/pass/include/luci/Pass/FuseMulWithDivPass.h
new file mode 100644 (file)
index 0000000..fa9086c
--- /dev/null
@@ -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_MUL_WITH_DIV_PASS_H__
+#define __LUCI_FUSE_MUL_WITH_DIV_PASS_H__
+
+#include <loco.h>
+
+#include <luci/ModulePass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fuse Mul operation with a Div operation
+ */
+struct FuseMulWithDivPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FuseMulWithDivPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif //__LUCI_FUSE_MUL_WITH_DIV_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseRsqrtPass.h b/compiler/luci/pass/include/luci/Pass/FuseRsqrtPass.h
new file mode 100644 (file)
index 0000000..b6a26bc
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_RSQRT_PASS_H__
+#define __LUCI_FUSE_RSQRT_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fuse certain pattern of subgraph into CircleRsqrt
+ */
+struct FuseRsqrtPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FuseRsqrtPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FUSE_RSQRT_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/FuseSliceWithTConvPass.h b/compiler/luci/pass/include/luci/Pass/FuseSliceWithTConvPass.h
new file mode 100644 (file)
index 0000000..2863076
--- /dev/null
@@ -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_FUSE_SLICE_WITH_TCONV_PASS_H__
+#define __LUCI_FUSE_SLICE_WITH_TCONV_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to fuse Slice operation with a preceding TConv
+ */
+struct FuseSliceWithTConvPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::FuseSliceWithTConvPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_FUSE_SLICE_WITH_TCONV_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/QuantizeOnnxFakeQuantModelPass.h b/compiler/luci/pass/include/luci/Pass/QuantizeOnnxFakeQuantModelPass.h
new file mode 100644 (file)
index 0000000..d9a9569
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_ONNX_FAKE_QUANT_MODEL_PASS_H__
+#define __LUCI_QUANTIZE_ONNX_FAKE_QUANT_MODEL_PASS_H__
+
+#include <loco.h>
+
+#include <logo/Pass.h>
+
+#include <memory>
+
+namespace luci
+{
+
+/**
+ * @brief Pass to create a quantized graph from a graph fake-quantized on onnx
+ */
+class QuantizeOnnxFakeQuantModelPass : public logo::Pass
+{
+public:
+  struct Context
+  {
+    loco::DataType default_activation_dtype = loco::DataType::Unknown;
+  };
+
+public:
+  QuantizeOnnxFakeQuantModelPass(std::unique_ptr<Context> &&ctx) : _ctx{std::move(ctx)}
+  {
+    assert(_ctx);                           // FIX_CALLER_UNLESS
+    assert(_ctx->default_activation_dtype); // FIX_CALLER_UNLESS
+  }
+
+  virtual const char *name(void) const { return "luci::QuantizeOnnxFakeQuantModelPass"; }
+
+public:
+  bool run(loco::Graph *graph);
+
+private:
+  std::unique_ptr<Context> _ctx;
+};
+
+} // namespace luci
+
+#endif //__LUCI_QUANTIZE_ONNX_FAKE_QUANT_MODEL_PASS_H__
index 6874046..560cc90 100644 (file)
@@ -42,6 +42,7 @@ public:
     std::vector<loco::DataType> input_types;
     std::vector<loco::DataType> output_types;
     bool TF_style_maxpool = false;
+    bool save_min_max = false;
     std::vector<LayerInfo> layers_info;
   };
 
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveGatherGuardPass.h b/compiler/luci/pass/include/luci/Pass/RemoveGatherGuardPass.h
new file mode 100644 (file)
index 0000000..d514dc3
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_REMOVE_GATHER_GUARD_PASS_H__
+#define __LUCI_REMOVE_GATHER_GUARD_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to remove Add+FloorMod guard ops of Gather
+ * @note  If the indices of Gather is guarenteed to be positive by the user,
+ *        Add/FloorMod guard ops can be removed.
+ *        This pass is to remove Add+FloorMod having INT32/INT64 dtypes
+ *        for some backends cannot process this in quantized models.
+ */
+struct RemoveGatherGuardPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::RemoveGatherGuardPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_GATHER_GUARD_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveQDQForMixedPrecisionOpPass.h b/compiler/luci/pass/include/luci/Pass/RemoveQDQForMixedPrecisionOpPass.h
new file mode 100644 (file)
index 0000000..2da2be8
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_REMOVE_QDQ_FOR_MIXED_PRECISION_OP_PASS_H__
+#define __LUCI_REMOVE_QDQ_FOR_MIXED_PRECISION_OP_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to remove QDQ pattern for mixed-precision Ops
+ */
+struct RemoveQDQForMixedPrecisionOpPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::RemoveQDQForMixedPrecisionOpPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_QDQ_FOR_MIXED_PRECISION_OP_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryAddPass.h b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryAddPass.h
new file mode 100644 (file)
index 0000000..432e834
--- /dev/null
@@ -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_REMOVE_UNNECESSARY_ADD_PASS_H__
+#define __LUCI_REMOVE_UNNECESSARY_ADD_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to temove unnecessary(input and output are same) Add node.
+ */
+struct RemoveUnnecessaryAddPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::RemoveUnnecessaryAddPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_UNNECESSARY_ADD_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryTransposeNetPass.h b/compiler/luci/pass/include/luci/Pass/RemoveUnnecessaryTransposeNetPass.h
new file mode 100644 (file)
index 0000000..c7f7465
--- /dev/null
@@ -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.
+ */
+
+#ifndef __LUCI_REMOVE_UNNECESSARY_TRANSPOSE_NET_PASS_H__
+#define __LUCI_REMOVE_UNNECESSARY_TRANSPOSE_NET_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+struct RemoveUnnecessaryTransposeNetPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::RemoveUnnecessaryTransposeNetPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REMOVE_UNNECESSARY_TRANSPOSE_NET_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/ReplaceWithFCGeluFCPass.h b/compiler/luci/pass/include/luci/Pass/ReplaceWithFCGeluFCPass.h
new file mode 100644 (file)
index 0000000..091cd9e
--- /dev/null
@@ -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_REPLACE_WITH_FC_GELU_FC_PASS_H__
+#define __LUCI_REPLACE_WITH_FC_GELU_FC_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to generate FC-Gelu-FC from a certain Op pattern
+ *
+ * To see the target Op pattern, please visit implementation.
+ * NOTE: The target pattern includes FC fused with div/mul Ops.
+ */
+struct ReplaceWithFCGeluFCPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::ReplaceWithFCGeluFCPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_REPLACE_WITH_FC_GELU_FC_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/ResolveFormerCustomOpPass.h b/compiler/luci/pass/include/luci/Pass/ResolveFormerCustomOpPass.h
new file mode 100644 (file)
index 0000000..cb8a050
--- /dev/null
@@ -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_RESOLVE_FORMER_CUSTOM_OP_PASS_H__
+#define __LUCI_RESOLVE_FORMER_CUSTOM_OP_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief Class to convert a custom operator to a built-in operator.
+ *
+ * @details This pass changes a op formerly used as a custom op to builtin op
+ *          from schema version upgrade.
+ */
+struct ResolveFormerCustomOpPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::ResolveFormerCustomOpPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_RESOLVE_FORMER_CUSTOM_OP_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/TransformSqrtDivToRsqrtMulPass.h b/compiler/luci/pass/include/luci/Pass/TransformSqrtDivToRsqrtMulPass.h
new file mode 100644 (file)
index 0000000..da06524
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_TRANSFORM_SQRT_DIV_TO_RSQRT_MUL_PASS_H__
+#define __LUCI_TRANSFORM_SQRT_DIV_TO_RSQRT_MUL_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to transform Div(X,Sqrt(y)) to Mul(X,Rsqrt(y))
+ */
+struct TransformSqrtDivToRsqrtMulPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::TransformSqrtDivToRsqrtMulPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_TRANSFORM_SQRT_DIV_TO_RSQRT_MUL_PASS_H__
diff --git a/compiler/luci/pass/include/luci/Pass/XpSepActFromTransposeConvPass.h b/compiler/luci/pass/include/luci/Pass/XpSepActFromTransposeConvPass.h
new file mode 100644 (file)
index 0000000..ed78336
--- /dev/null
@@ -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_XP_SEP_ACT_FROM_TRANSPOSE_CONV_PASS_H__
+#define __LUCI_XP_SEP_ACT_FROM_TRANSPOSE_CONV_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Experimental Class to separate activation functions from TransposeConv
+ */
+struct XpSepActFromTransposeConvPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::XpSepActFromTransposeConvPass"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_XP_SEP_ACT_FROM_TRANSPOSE_CONV_PASS_H__
index b011581..aa98fb3 100644 (file)
@@ -17,6 +17,7 @@
 #include "luci/CircleOptimizer.h"
 
 #include "luci/Pass/ConvertNCHWToNHWCPass.h"
+#include "luci/Pass/CommonSubExpressionEliminationPass.h"
 #include "luci/Pass/ExpandBroadcastConstPass.h"
 #include "luci/Pass/FoldAddV2Pass.h"
 #include "luci/Pass/FoldCastPass.h"
 #include "luci/Pass/FoldDequantizePass.h"
 #include "luci/Pass/FoldFullyConnectedPass.h"
 #include "luci/Pass/FoldGatherPass.h"
+#include "luci/Pass/FoldMulPass.h"
+#include "luci/Pass/FoldReshapePass.h"
+#include "luci/Pass/FoldShapePass.h"
 #include "luci/Pass/FoldSparseToDensePass.h"
+#include "luci/Pass/FoldSqueezePass.h"
 #include "luci/Pass/ForwardReshapeToUnaryOpPass.h"
 #include "luci/Pass/ForwardTransposeOpPass.h"
 #include "luci/Pass/FuseActivationFunctionPass.h"
+#include "luci/Pass/FuseAddToFullyConnectedBiasPass.h"
+#include "luci/Pass/FuseAddWithConvPass.h"
 #include "luci/Pass/FuseAddWithFullyConnectedPass.h"
 #include "luci/Pass/FuseAddWithTConvPass.h"
 #include "luci/Pass/FuseBatchNormWithConvPass.h"
 #include "luci/Pass/FuseBatchNormWithDwConvPass.h"
 #include "luci/Pass/FuseBatchNormWithTConvPass.h"
 #include "luci/Pass/FuseBCQPass.h"
+#include "luci/Pass/FuseMulToFullyConnectedWeightsPass.h"
 #include "luci/Pass/FuseInstanceNormPass.h"
 #include "luci/Pass/FuseMeanWithMeanPass.h"
+#include "luci/Pass/FuseMulWithConvPass.h"
+#include "luci/Pass/FuseMulWithDivPass.h"
 #include "luci/Pass/FusePreActivationBatchNormPass.h"
 #include "luci/Pass/FusePReluPass.h"
 #include "luci/Pass/FuseGeluPass.h"
+#include "luci/Pass/FuseRsqrtPass.h"
+#include "luci/Pass/FuseSliceWithTConvPass.h"
+#include "luci/Pass/FuseHorizontalFullyConnectedPass.h"
 #include "luci/Pass/FuseTransposeWithMeanPass.h"
 #include "luci/Pass/MakeBatchNormGammaPositivePass.h"
 #include "luci/Pass/RemoveDuplicateConstPass.h"
 #include "luci/Pass/RemoveFakeQuantPass.h"
+#include "luci/Pass/RemoveGatherGuardPass.h"
+#include "luci/Pass/RemoveQDQForMixedPrecisionOpPass.h"
 #include "luci/Pass/RemoveQuantDequantSeqPass.h"
 #include "luci/Pass/RemoveRedundantReshapePass.h"
 #include "luci/Pass/RemoveRedundantTransposePass.h"
 #include "luci/Pass/RemoveRedundantQuantizePass.h"
+#include "luci/Pass/RemoveUnnecessaryAddPass.h"
 #include "luci/Pass/RemoveUnnecessaryReshapePass.h"
 #include "luci/Pass/RemoveUnnecessaryReshapeNetPass.h"
 #include "luci/Pass/RemoveUnnecessarySlicePass.h"
 #include "luci/Pass/RemoveUnnecessaryStridedSlicePass.h"
 #include "luci/Pass/RemoveUnnecessarySplitPass.h"
+#include "luci/Pass/RemoveUnnecessaryTransposeNetPass.h"
 #include "luci/Pass/ReplaceNonConstFCWithBatchMatMulPass.h"
 #include "luci/Pass/ReplaceMulAddWithDepthwiseConvPass.h"
 #include "luci/Pass/ReplaceSubWithAddPass.h"
+#include "luci/Pass/ReplaceWithFCGeluFCPass.h"
 #include "luci/Pass/ResolveCustomOpAddPass.h"
 #include "luci/Pass/ResolveCustomOpBatchMatMulPass.h"
 #include "luci/Pass/ResolveCustomOpMatMulPass.h"
 #include "luci/Pass/ResolveCustomOpMaxPoolWithArgmaxPass.h"
 #include "luci/Pass/ResolveCustomOpSplitVPass.h"
+#include "luci/Pass/ResolveFormerCustomOpPass.h"
 #include "luci/Pass/SparsifyTensorPass.h"
 #include "luci/Pass/ShuffleWeightTo16x1Float32Pass.h"
 #include "luci/Pass/SubstitutePackToReshapePass.h"
 #include "luci/Pass/SubstituteTransposeToReshapePass.h"
 #include "luci/Pass/TransformMinMaxToRelu6Pass.h"
 #include "luci/Pass/TransformMinReluToRelu6Pass.h"
+#include "luci/Pass/TransformSqrtDivToRsqrtMulPass.h"
 #include "luci/Pass/DecomposeHardSwishPass.h"
+#include "luci/Pass/DecomposeSoftmaxPass.h"
 #include "luci/Pass/UnrollUnidirectionalSequenceLSTMPass.h"
+#include "luci/Pass/XpSepActFromTransposeConvPass.h"
 // TODO add more passes
 
 #include "luci/Pass/CircleShapeInferencePass.h"
@@ -154,6 +176,7 @@ void convert_nchw_to_nhwc(loco::Graph *g, bool preserve_input, bool preserve_out
   phase.emplace_back(std::make_unique<luci::ResolveCustomOpMatMulPass>());
   phase.emplace_back(std::make_unique<luci::ResolveCustomOpMaxPoolWithArgmaxPass>());
   phase.emplace_back(std::make_unique<luci::ResolveCustomOpSplitVPass>());
+  phase.emplace_back(std::make_unique<luci::ResolveFormerCustomOpPass>());
 
   // Fuse FullyConnected with Add
   // Why we perform FuseAddWithFullyConnectedPass before ConvertNCHWToNHWCPass?
@@ -237,6 +260,10 @@ void CircleOptimizer::optimize(loco::Graph *g) const
   phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
   phase.emplace_back(std::make_unique<luci::CircleTypeInferencePass>());
 
+  if (_options->query(Options::Algorithm::CommonSubExpressionElimination))
+  {
+    phase.emplace_back(std::make_unique<luci::CommonSubExpressionEliminationPass>());
+  }
   if (_options->query(Options::Algorithm::ResolveCustomOpAdd))
   {
     phase.emplace_back(std::make_unique<luci::ResolveCustomOpAddPass>());
@@ -249,10 +276,22 @@ void CircleOptimizer::optimize(loco::Graph *g) const
   {
     phase.emplace_back(std::make_unique<luci::ResolveCustomOpMatMulPass>());
   }
+  if (_options->query(Options::Algorithm::ResolveFormerCustomOp))
+  {
+    phase.emplace_back(std::make_unique<luci::ResolveFormerCustomOpPass>());
+  }
   if (_options->query(Options::Algorithm::FuseMeanWithMean))
   {
     phase.emplace_back(std::make_unique<FuseMeanWithMeanPass>());
   }
+  if (_options->query(Options::Algorithm::FuseMulWithConv))
+  {
+    phase.emplace_back(std::make_unique<FuseMulWithConvPass>());
+  }
+  if (_options->query(Options::Algorithm::FuseMulWithDiv))
+  {
+    phase.emplace_back(std::make_unique<FuseMulWithDivPass>());
+  }
   if (_options->query(Options::Algorithm::ResolveCustomOpMaxPoolWithArgmax))
   {
     phase.emplace_back(std::make_unique<luci::ResolveCustomOpMaxPoolWithArgmaxPass>());
@@ -277,6 +316,18 @@ void CircleOptimizer::optimize(loco::Graph *g) const
   {
     phase.emplace_back(std::make_unique<FuseBatchNormWithTConvPass>());
   }
+  if (_options->query(Options::Algorithm::FuseSliceWithTConv))
+  {
+    phase.emplace_back(std::make_unique<FuseSliceWithTConvPass>());
+  }
+  if (_options->query(Options::Algorithm::FuseAddToFullyConnectedBias))
+  {
+    phase.emplace_back(std::make_unique<FuseAddToFullyConnectedBiasPass>());
+  }
+  if (_options->query(Options::Algorithm::FuseAddWithConv))
+  {
+    phase.emplace_back(std::make_unique<FuseAddWithConvPass>());
+  }
   if (_options->query(Options::Algorithm::FuseAddWithFullyConnected))
   {
     phase.emplace_back(std::make_unique<FuseAddWithFullyConnectedPass>());
@@ -289,6 +340,10 @@ void CircleOptimizer::optimize(loco::Graph *g) const
   {
     phase.emplace_back(std::make_unique<FuseActivationFunctionPass>());
   }
+  if (_options->query(Options::Algorithm::FuseMulToFullyConnectedWeights))
+  {
+    phase.emplace_back(std::make_unique<FuseMulToFullyConnectedWeightsPass>());
+  }
   if (_options->query(Options::Algorithm::FusePRelu))
   {
     phase.emplace_back(std::make_unique<FusePReluPass>());
@@ -297,6 +352,14 @@ void CircleOptimizer::optimize(loco::Graph *g) const
   {
     phase.emplace_back(std::make_unique<FuseGeluPass>());
   }
+  if (_options->query(Options::Algorithm::FuseRsqrt))
+  {
+    phase.emplace_back(std::make_unique<FuseRsqrtPass>());
+  }
+  if (_options->query(Options::Algorithm::FuseHorizontalFullyConnected))
+  {
+    phase.emplace_back(std::make_unique<FuseHorizontalFullyConnectedPass>());
+  }
   if (_options->query(Options::Algorithm::FuseTransposeWithMean))
   {
     phase.emplace_back(std::make_unique<FuseTransposeWithMeanPass>());
@@ -329,10 +392,26 @@ void CircleOptimizer::optimize(loco::Graph *g) const
   {
     phase.emplace_back(std::make_unique<luci::FoldGatherPass>());
   }
+  if (_options->query(Options::Algorithm::FoldMul))
+  {
+    phase.emplace_back(std::make_unique<luci::FoldMulPass>());
+  }
+  if (_options->query(Options::Algorithm::FoldReshape))
+  {
+    phase.emplace_back(std::make_unique<luci::FoldReshapePass>());
+  }
+  if (_options->query(Options::Algorithm::FoldShape))
+  {
+    phase.emplace_back(std::make_unique<luci::FoldShapePass>());
+  }
   if (_options->query(Options::Algorithm::FoldSparseToDense))
   {
     phase.emplace_back(std::make_unique<luci::FoldSparseToDensePass>());
   }
+  if (_options->query(Options::Algorithm::FoldSqueeze))
+  {
+    phase.emplace_back(std::make_unique<luci::FoldSqueezePass>());
+  }
   if (_options->query(Options::Algorithm::FusePreActivationBatchNorm))
   {
     phase.emplace_back(std::make_unique<luci::FusePreActivationBatchNormPass>());
@@ -357,10 +436,22 @@ void CircleOptimizer::optimize(loco::Graph *g) const
   {
     phase.emplace_back(std::make_unique<luci::RemoveFakeQuantPass>());
   }
+  if (_options->query(Options::Algorithm::RemoveGatherGuard))
+  {
+    phase.emplace_back(std::make_unique<luci::RemoveGatherGuardPass>());
+  }
+  if (_options->query(Options::Algorithm::RemoveQDQForMixedPrecisionOp))
+  {
+    phase.emplace_back(std::make_unique<luci::RemoveQDQForMixedPrecisionOpPass>());
+  }
   if (_options->query(Options::Algorithm::RemoveQuantDequantSeq))
   {
     phase.emplace_back(std::make_unique<luci::RemoveQuantDequantSeqPass>());
   }
+  if (_options->query(Options::Algorithm::RemoveUnnecessaryAdd))
+  {
+    phase.emplace_back(std::make_unique<luci::RemoveUnnecessaryAddPass>());
+  }
   if (_options->query(Options::Algorithm::RemoveUnnecessaryReshape))
   {
     phase.emplace_back(std::make_unique<luci::RemoveUnnecessaryReshapePass>());
@@ -378,6 +469,10 @@ void CircleOptimizer::optimize(loco::Graph *g) const
   {
     phase.emplace_back(std::make_unique<luci::RemoveUnnecessarySplitPass>());
   }
+  if (_options->query(Options::Algorithm::RemoveUnnecessaryTranspose))
+  {
+    phase.emplace_back(std::make_unique<luci::RemoveUnnecessaryTransposeNetPass>());
+  }
   if (_options->query(Options::Algorithm::RemoveRedundantReshape))
   {
     phase.emplace_back(std::make_unique<luci::RemoveRedundantReshapePass>());
@@ -402,6 +497,10 @@ void CircleOptimizer::optimize(loco::Graph *g) const
   {
     phase.emplace_back(std::make_unique<luci::ReplaceSubWithAddPass>());
   }
+  if (_options->query(Options::Algorithm::ReplaceWithFCGeluFC))
+  {
+    phase.emplace_back(std::make_unique<luci::ReplaceWithFCGeluFCPass>());
+  }
   if (_options->query(Options::Algorithm::SubstitutePackToReshape))
   {
     phase.emplace_back(std::make_unique<luci::SubstitutePackToReshapePass>());
@@ -434,14 +533,30 @@ void CircleOptimizer::optimize(loco::Graph *g) const
   {
     phase.emplace_back(std::make_unique<luci::TransformMinReluToRelu6Pass>());
   }
+  if (_options->query(Options::Algorithm::TransformSqrtDivToRsqrtMul))
+  {
+    phase.emplace_back(std::make_unique<luci::TransformSqrtDivToRsqrtMulPass>());
+  }
   if (_options->query(Options::Algorithm::DecomposeHardSwishPass))
   {
     phase.emplace_back(std::make_unique<luci::DecomposeHardSwishPass>());
   }
+  if (_options->query(Options::Algorithm::DecomposeSoftmaxPass))
+  {
+    phase.emplace_back(std::make_unique<luci::DecomposeSoftmaxPass>());
+  }
   if (_options->query(Options::Algorithm::UnrollUnidirSeqLSTM))
   {
     phase.emplace_back(std::make_unique<luci::UnrollUnidirectionalSequenceLSTMPass>());
   }
+
+  // NOTE Experimental options; these will be removed someday
+  //      Add experimental options here
+  if (_options->query(Options::Algorithm::XpSepActFromTransposeConv))
+  {
+    phase.emplace_back(std::make_unique<luci::XpSepActFromTransposeConvPass>());
+  }
+
   // Forward Reshape/Transpose is done after
   // 1. SubstituteXXXToReshape
   // 2. RemoveRedundantReshape/Transpose
diff --git a/compiler/luci/pass/src/CircleOptimizerUtils.cpp b/compiler/luci/pass/src/CircleOptimizerUtils.cpp
deleted file mode 100644 (file)
index 127573d..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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 "CircleOptimizerUtils.h"
-
-#include <luci/IR/CircleNode.h>
-
-namespace luci
-{
-
-bool has_dynamic_shape(const loco::Node *node)
-{
-  const auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
-  for (uint32_t i = 0; i < circle_node->rank(); ++i)
-    if (!circle_node->dim(i).known())
-      return true;
-  return false;
-}
-
-} // namespace luci
diff --git a/compiler/luci/pass/src/CircleOptimizerUtils.h b/compiler/luci/pass/src/CircleOptimizerUtils.h
deleted file mode 100644 (file)
index e04942b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 __LUCI_CIRCLE_OPTIMIZER_UTILS_H__
-#define __LUCI_CIRCLE_OPTIMIZER_UTILS_H__
-
-#include <loco.h>
-
-namespace luci
-{
-
-bool has_dynamic_shape(const loco::Node *node);
-
-} // namespace luci
-
-#endif // __LUCI_CIRCLE_OPTIMIZER_UTILS_H__
index 9039a83..86ada1f 100644 (file)
@@ -27,6 +27,7 @@
 #include "luci/Pass/QuantizeWithMinMaxPass.h"
 #include "luci/Pass/QuantizeDequantizeWeightsPass.h"
 #include "luci/Pass/QuantizeWeightsPass.h"
+#include "luci/Pass/QuantizeOnnxFakeQuantModelPass.h"
 
 #include "luci/Pass/CircleShapeInferencePass.h"
 #include "luci/Pass/CircleTypeInferencePass.h"
 #include <logo/Phase.h>
 #include <pepper/csv2vec.h>
 
+#include <map>
 #include <memory>
+#include <string>
+#include <unordered_set>
 
 namespace
 {
 
 using namespace luci;
 using LayerParam = luci::CircleQuantizer::Options::LayerParam;
+using LayerParams = luci::CircleQuantizer::Options::LayerParams;
+using LayerParamsSet = luci::CircleQuantizer::Options::LayerParamsSet;
 
 // This function updates user-given input_type to match with the input signature of graph
 // If user gives only one input_type, it will be expanded to the number of graph inputs
@@ -224,15 +230,18 @@ public:
   const std::string param(AlgorithmParameters) const final;
   void params(AlgorithmParameters, std::vector<std::string> &) final;
   std::vector<std::string> params(AlgorithmParameters) const final;
-  void layer_params(AlgorithmParameters, std::vector<std::shared_ptr<LayerParam>> &) final;
-  std::vector<std::shared_ptr<LayerParam>> layer_params(AlgorithmParameters) const final;
+  void layer_params(AlgorithmParameters, LayerParams &) final;
+  LayerParams layer_params(AlgorithmParameters) const final;
+  void layer_params_set(LayerParamsSet &) final;
+  LayerParamsSet layer_params_set(void) const final;
   bool query(Algorithm) final;
 
 private:
   std::vector<Algorithm> _algorithms;
   std::map<AlgorithmParameters, const std::string> _algorithm_params;
   std::map<AlgorithmParameters, std::vector<std::string>> _multiple_params;
-  std::map<AlgorithmParameters, std::vector<std::shared_ptr<LayerParam>>> _layer_params;
+  std::map<AlgorithmParameters, LayerParams> _layer_params;
+  LayerParamsSet _layer_params_set;
 };
 
 void QuantizeOptionsImpl::enable(Algorithm algo) { _algorithms.push_back(algo); }
@@ -273,14 +282,12 @@ std::vector<std::string> QuantizeOptionsImpl::params(AlgorithmParameters param)
   }
 }
 
-void QuantizeOptionsImpl::layer_params(AlgorithmParameters param,
-                                       std::vector<std::shared_ptr<LayerParam>> &vec)
+void QuantizeOptionsImpl::layer_params(AlgorithmParameters param, LayerParams &vec)
 {
   _layer_params[param] = vec;
 }
 
-std::vector<std::shared_ptr<LayerParam>>
-QuantizeOptionsImpl::layer_params(AlgorithmParameters param) const
+LayerParams QuantizeOptionsImpl::layer_params(AlgorithmParameters param) const
 {
   auto param_vec = _layer_params.find(param);
   if (param_vec != _layer_params.end())
@@ -289,10 +296,14 @@ QuantizeOptionsImpl::layer_params(AlgorithmParameters param) const
   }
   else
   {
-    return std::vector<std::shared_ptr<LayerParam>>();
+    return LayerParams();
   }
 }
 
+void QuantizeOptionsImpl::layer_params_set(LayerParamsSet &vec) { _layer_params_set = vec; }
+
+LayerParamsSet QuantizeOptionsImpl::layer_params_set(void) const { return _layer_params_set; }
+
 bool QuantizeOptionsImpl::query(Algorithm algo)
 {
   std::vector<Algorithm>::iterator it = std::find(_algorithms.begin(), _algorithms.end(), algo);
@@ -304,6 +315,66 @@ bool QuantizeOptionsImpl::query(Algorithm algo)
 
 } // namespace
 
+namespace
+{
+
+bool is_valid_params(loco::Graph *g, LayerParams &lps)
+{
+  // no same name in lps
+  std::unordered_set<std::string> us;
+  for (auto &lp : lps)
+  {
+    if (us.find(lp->name) != us.end())
+      throw std::runtime_error("Duplicate name found in configuration: " + lp->name);
+    us.emplace(lp->name);
+  }
+
+  // all name should be found in graph
+  for (auto &lp : lps)
+  {
+    auto &name = lp->name;
+    bool found = false;
+    for (auto node : loco::active_nodes(loco::output_nodes(g)))
+    {
+      auto cnode = loco::must_cast<luci::CircleNode *>(node);
+      if (cnode->opcode() == luci::CircleOpcode::CIRCLEOUTPUT)
+        continue;
+
+      if (cnode->name() == name)
+      {
+        found = true;
+        break;
+      }
+    }
+    if (not found)
+      return false;
+  }
+  return true;
+}
+
+LayerParams find_valid_params(loco::Graph *g, LayerParamsSet &lpss)
+{
+  // valid condition: there should be only one LayerParams that is OK
+  uint32_t valid_count = 0;
+  LayerParams params;
+  for (auto &lps : lpss)
+  {
+    if (is_valid_params(g, lps))
+    {
+      valid_count++;
+      params = lps;
+    }
+  }
+  if (valid_count != 1)
+    throw std::runtime_error(
+      "Configuration file has layer names (and alternates) that can be mapped in multiple or no "
+      "ways. Please update configuration file to have only one valid name mapping.");
+
+  return params;
+}
+
+} // namespace
+
 namespace luci
 {
 
@@ -332,6 +403,7 @@ void CircleQuantizer::quantize(loco::Graph *g) const
       _options->param(Options::AlgorithmParameters::Quantize_output_model_dtype);
     auto granularity = _options->param(Options::AlgorithmParameters::Quantize_granularity);
     auto layer_params = _options->layer_params(Options::AlgorithmParameters::Quantize_layer_params);
+    auto layer_params_set = _options->layer_params_set();
 
     if (!in_array(to_lower_case(input_model_dtype), fakeq_supported_input_model_dtype))
       throw std::runtime_error("Unsupported input type. List of supported input type: " +
@@ -349,10 +421,15 @@ void CircleQuantizer::quantize(loco::Graph *g) const
         str_to_dtype(output_model_dtype) != loco::DataType::U8)
       throw std::runtime_error("Layer-wise quantization only supports uint8 dtype.");
 
+    if (layer_params_set.size() > 1u)
+    {
+      layer_params = find_valid_params(g, layer_params_set);
+    }
+
     // Check dtype/granularity of layer params
     for (auto layer_param : layer_params)
     {
-      auto name = layer_param->name;
+      const auto &name = layer_param->name;
       if (!in_array(to_lower_case(layer_param->dtype), fakeq_supported_output_model_dtype))
       {
         throw std::runtime_error("Unsupported dtype in " + name + ". List of supported dtype: " +
@@ -367,7 +444,7 @@ void CircleQuantizer::quantize(loco::Graph *g) const
     }
 
     // Clear existing quantparams before doing fake quantization
-    for (auto node : loco::active_nodes(loco::output_nodes(g)))
+    for (auto &node : loco::active_nodes(loco::output_nodes(g)))
     {
       auto circle_node = loco::must_cast<luci::CircleNode *>(node);
       if (circle_node->quantparam() != nullptr)
@@ -426,7 +503,11 @@ void CircleQuantizer::quantize(loco::Graph *g) const
     bool TF_style_maxpool =
       _options->param(Options::AlgorithmParameters::Quantize_TF_style_maxpool) == "True";
 
+    bool save_min_max =
+      _options->param(Options::AlgorithmParameters::Quantize_save_min_max) == "True";
+
     auto layer_params = _options->layer_params(Options::AlgorithmParameters::Quantize_layer_params);
+    auto layer_params_set = _options->layer_params_set();
 
     if (!in_array(to_lower_case(input_model_dtype), qwmm_supported_input_model_dtype))
       throw std::runtime_error("Unsupported input type. List of supported input types: " +
@@ -458,10 +539,15 @@ void CircleQuantizer::quantize(loco::Graph *g) const
         str_to_dtype(output_model_dtype) != loco::DataType::U8)
       throw std::runtime_error("Layer-wise quantization only supports uint8 dtype.");
 
+    if (layer_params_set.size() > 1u)
+    {
+      layer_params = find_valid_params(g, layer_params_set);
+    }
+
     // Check dtype/granularity of layer params
     for (auto layer_param : layer_params)
     {
-      auto name = layer_param->name;
+      const auto &name = layer_param->name;
       if (!in_array(to_lower_case(layer_param->dtype), qwmm_supported_output_model_dtype))
       {
         throw std::runtime_error("Unsupported dtype in " + name + ". List of supported dtype: " +
@@ -494,6 +580,7 @@ void CircleQuantizer::quantize(loco::Graph *g) const
       ctx->input_types = input_types;
       ctx->output_types = output_types;
       ctx->TF_style_maxpool = TF_style_maxpool;
+      ctx->save_min_max = save_min_max;
 
       for (auto layer_param : layer_params)
       {
@@ -540,7 +627,7 @@ void CircleQuantizer::quantize(loco::Graph *g) const
   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_output_model_dtype{"int4", "int8", "int16"};
     static const std::vector<std::string> qw_supported_granularity{"channel"};
 
     auto input_model_dtype =
@@ -571,6 +658,30 @@ void CircleQuantizer::quantize(loco::Graph *g) const
     weights_quantizer.run(g);
   }
 
+  if (_options->query(Options::Algorithm::QuantizeOnnxFakeQuantizedModel))
+  {
+    auto ctx = std::make_unique<luci::QuantizeOnnxFakeQuantModelPass::Context>();
+    {
+      ctx->default_activation_dtype = loco::DataType::S16;
+    }
+
+    luci::QuantizeOnnxFakeQuantModelPass quantizer(std::move(ctx));
+
+    quantizer.run(g);
+
+    logo::Phase phase;
+
+    // Default passes
+    phase.emplace_back(std::make_unique<logo::RemoveDeadNodeWithQueryPass>());
+    phase.emplace_back(std::make_unique<luci::CircleShapeInferencePass>());
+    phase.emplace_back(std::make_unique<luci::CircleTypeInferencePass>());
+
+    ProgressReporter prog(g, logo::PhaseStrategy::Restart);
+    logo::PhaseRunner<logo::PhaseStrategy::Restart> phase_runner{g};
+    phase_runner.attach(&prog);
+    phase_runner.run(phase);
+  }
+
   // Requantize
   if (_options->query(Options::Algorithm::Requantize))
   {
index 5766d5f..a161326 100644 (file)
 
 #include "luci/CircleQuantizer.h"
 
+#include <luci/IR/CircleNodes.h>
+
 #include <gtest/gtest.h>
 
+#include <memory>
+
 using namespace luci;
 using Algorithms = luci::CircleQuantizer::Options::Algorithm;
 using AlgorithmParameters = luci::CircleQuantizer::Options::AlgorithmParameters;
@@ -189,3 +193,241 @@ TEST(CircleQuantizerTest, quantize_requant_output_NEG)
 
   EXPECT_THROW(o.quantize(&g), std::runtime_error);
 }
+
+struct SimpleQuantGraph
+{
+  void init(void);
+
+  loco::Graph g;
+
+  luci::CircleInput *input = nullptr;
+  luci::CircleOutput *output = nullptr;
+  luci::CircleConv2D *conv2d1 = nullptr;
+  luci::CircleConv2D *conv2d2 = nullptr;
+  luci::CircleConst *filter = nullptr;
+  luci::CircleConst *bias = nullptr;
+};
+
+// Have two conv layers named "c1" and "c2".
+void SimpleQuantGraph::init()
+{
+  auto graph_input = g.inputs()->create();
+  graph_input->shape({1, 1, 1, 1});
+  graph_input->dtype(loco::DataType::FLOAT32);
+
+  auto graph_output = g.outputs()->create();
+  graph_output->shape({1, 1, 1, 1});
+  graph_output->dtype(loco::DataType::FLOAT32);
+
+  input = g.nodes()->create<luci::CircleInput>();
+  input->dtype(loco::DataType::FLOAT32);
+  input->shape({1, 1, 1, 1});
+  input->shape_status(luci::ShapeStatus::VALID);
+  input->index(graph_input->index());
+
+  filter = g.nodes()->create<luci::CircleConst>();
+  filter->dtype(loco::DataType::FLOAT32);
+  filter->size<loco::DataType::FLOAT32>(1 * 1 * 1 * 1);
+  filter->shape({1, 1, 1, 1});
+  filter->shape_status(luci::ShapeStatus::VALID);
+
+  bias = g.nodes()->create<luci::CircleConst>();
+  bias->dtype(loco::DataType::FLOAT32);
+  bias->size<loco::DataType::FLOAT32>(1);
+  bias->shape({1});
+  bias->shape_status(luci::ShapeStatus::VALID);
+
+  conv2d1 = g.nodes()->create<luci::CircleConv2D>();
+  conv2d1->dtype(loco::DataType::FLOAT32);
+  conv2d1->fusedActivationFunction(luci::FusedActFunc::NONE);
+  conv2d1->input(input);
+  conv2d1->filter(filter);
+  conv2d1->bias(bias);
+  conv2d1->padding(luci::Padding::VALID);
+  conv2d1->name("c1");
+
+  conv2d2 = g.nodes()->create<luci::CircleConv2D>();
+  conv2d2->dtype(loco::DataType::FLOAT32);
+  conv2d2->fusedActivationFunction(luci::FusedActFunc::NONE);
+  conv2d2->input(input);
+  conv2d2->filter(filter);
+  conv2d2->bias(conv2d1);
+  conv2d2->padding(luci::Padding::VALID);
+  conv2d2->name("c2");
+
+  output = g.nodes()->create<luci::CircleOutput>();
+  output->dtype(loco::DataType::FLOAT32);
+  output->from(conv2d2);
+  output->index(graph_output->index());
+}
+
+struct SimpleCircleQuantizer
+{
+  CircleQuantizer::Options *init();
+  void quantize(loco::Graph *g) { cq.quantize(g); }
+
+  luci::CircleQuantizer cq;
+};
+
+CircleQuantizer::Options *SimpleCircleQuantizer::init(void)
+{
+  auto options = cq.options();
+  options->enable(Algorithms::QuantizeDequantizeWeights);
+  options->param(AlgorithmParameters::Quantize_input_model_dtype, "float32");
+  options->param(AlgorithmParameters::Quantize_output_model_dtype, "uint8");
+  options->param(AlgorithmParameters::Quantize_granularity, "layer");
+  return options;
+}
+
+using LayerParam = luci::CircleQuantizer::Options::LayerParam;
+using LayerParams = luci::CircleQuantizer::Options::LayerParams;
+using LayerParamsSet = luci::CircleQuantizer::Options::LayerParamsSet;
+
+TEST(CircleQuantizerTest, quantize_layer_param_set)
+{
+  SimpleQuantGraph sqg;
+  sqg.init();
+
+  LayerParamsSet lpss;
+  {
+    LayerParams lps1;
+    {
+      auto lp1 = std::make_shared<LayerParam>();
+      lp1->name = "x1";
+      lp1->dtype = "int16";
+      lp1->granularity = "channel";
+      lps1.emplace_back(lp1);
+    }
+    lpss.emplace_back(lps1);
+
+    LayerParams lps2;
+    {
+      auto lp2 = std::make_shared<LayerParam>();
+      lp2->name = "c1";
+      lp2->dtype = "int16";
+      lp2->granularity = "channel";
+      lps2.emplace_back(lp2);
+    }
+    lpss.emplace_back(lps2);
+  }
+
+  SimpleCircleQuantizer scq;
+  auto options = scq.init();
+  options->layer_params_set(lpss);
+
+  EXPECT_NO_THROW(scq.quantize(&sqg.g));
+}
+
+TEST(CircleQuantizerTest, invalid_layer_params_NEG)
+{
+  SimpleQuantGraph sqg;
+  sqg.init();
+
+  LayerParamsSet lpss;
+  {
+    // there is no LayerParam with "c1" nor "c2"
+    LayerParams lps1;
+    {
+      auto lp1 = std::make_shared<LayerParam>();
+      lp1->name = "x1";
+      lp1->dtype = "int16";
+      lp1->granularity = "channel";
+      lps1.emplace_back(lp1);
+    }
+    lpss.emplace_back(lps1);
+
+    LayerParams lps2;
+    {
+      auto lp2 = std::make_shared<LayerParam>();
+      lp2->name = "x2";
+      lp2->dtype = "int16";
+      lp2->granularity = "channel";
+      lps2.emplace_back(lp2);
+    }
+    lpss.emplace_back(lps2);
+  }
+
+  SimpleCircleQuantizer scq;
+  auto options = scq.init();
+  options->layer_params_set(lpss);
+
+  EXPECT_THROW(scq.quantize(&sqg.g), std::runtime_error);
+}
+
+TEST(CircleQuantizerTest, duplicate_name_in_layer_params_NEG)
+{
+  SimpleQuantGraph sqg;
+  sqg.init();
+
+  LayerParamsSet lpss;
+  {
+    LayerParams lps1;
+    {
+      // duplicate c1 name in a LayerParams
+      auto lp11 = std::make_shared<LayerParam>();
+      lp11->name = "c1";
+      lp11->dtype = "int16";
+      lp11->granularity = "channel";
+      lps1.emplace_back(lp11);
+
+      auto lp12 = std::make_shared<LayerParam>();
+      lp12->name = "c1";
+      lp12->dtype = "int16";
+      lp12->granularity = "channel";
+      lps1.emplace_back(lp12);
+    }
+    lpss.emplace_back(lps1);
+
+    LayerParams lps2;
+    {
+      auto lp2 = std::make_shared<LayerParam>();
+      lp2->name = "x1";
+      lp2->dtype = "int16";
+      lp2->granularity = "channel";
+      lps2.emplace_back(lp2);
+    }
+    lpss.emplace_back(lps2);
+  }
+
+  SimpleCircleQuantizer scq;
+  auto options = scq.init();
+  options->layer_params_set(lpss);
+
+  EXPECT_THROW(scq.quantize(&sqg.g), std::runtime_error);
+}
+
+TEST(CircleQuantizerTest, duplicate_layer_params_NEG)
+{
+  SimpleQuantGraph sqg;
+  sqg.init();
+
+  LayerParamsSet lpss;
+  {
+    // duplicate "c1" name in a LayerParamsSet
+    LayerParams lps1;
+    {
+      auto lp1 = std::make_shared<LayerParam>();
+      lp1->name = "c1";
+      lp1->dtype = "int16";
+      lp1->granularity = "channel";
+      lps1.emplace_back(lp1);
+    }
+    lpss.emplace_back(lps1);
+
+    LayerParams lps2;
+    {
+      auto lp2 = std::make_shared<LayerParam>();
+      lp2->name = "c1";
+      lp2->dtype = "int16";
+      lp2->granularity = "channel";
+      lps2.emplace_back(lp2);
+    }
+    lpss.emplace_back(lps2);
+  }
+
+  SimpleCircleQuantizer scq;
+  auto options = scq.init();
+  options->layer_params_set(lpss);
+
+  EXPECT_THROW(scq.quantize(&sqg.g), std::runtime_error);
+}
index ddab224..bcfb6d0 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include "helpers/InferenceCandidates.h"
+#include "helpers/Shape.h"
 
 #include "luci/Pass/CircleShapeInferencePass.h"
 
 
 #include <loco.h>
 
-namespace
-{
-
-bool is_same_shape(luci::CircleNode *node, loco::TensorShape shape)
-{
-  if (node->shape_status() != luci::ShapeStatus::VALID)
-    return false;
-
-  if (node->rank() != shape.rank())
-    return false;
-
-  for (uint32_t i = 0; i < node->rank(); ++i)
-  {
-    if (node->dim(i).known() != shape.dim(i).known())
-      return false;
-
-    if (node->dim(i).value() != shape.dim(i).value())
-      return false;
-  }
-
-  return true;
-}
-
-} // namespace
-
 namespace luci
 {
 
diff --git a/compiler/luci/pass/src/CommonSubExpressionEliminationPass.cpp b/compiler/luci/pass/src/CommonSubExpressionEliminationPass.cpp
new file mode 100644 (file)
index 0000000..e90e385
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Pass/CommonSubExpressionEliminationPass.h"
+#include "helpers/ExpressionCache.h"
+
+#include <luci/IR/CircleNodes.h>
+
+using namespace luci::pass;
+
+namespace
+{
+
+// Return true if node is a virtual node
+// TODO Extract this helper to somewhere else
+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");
+  }
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool CommonSubExpressionEliminationPass::run(loco::Graph *g)
+{
+  // Build cache
+  ExpressionCache cache;
+
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto cnode = loco::must_cast<luci::CircleNode *>(node);
+
+    // Skip virtual Ops
+    // Why? virtual Ops do not perform actual computations
+    // NOTE Fix this if the assumption is not true
+    if (virtual_op(cnode->opcode()))
+      continue;
+
+    // Build expression
+    auto expr = Expression::build(cnode);
+
+    // Invalid (NYI) expression
+    if (expr.op == nullptr)
+      continue;
+
+    // Cache hit
+    if (auto saved_node = cache.get(expr))
+    {
+      loco::replace(cnode).with(saved_node);
+      changed = true;
+    }
+    // Cache miss
+    else
+    {
+      cache.put(expr, cnode);
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/CommonSubExpressionEliminationPass.test.cpp b/compiler/luci/pass/src/CommonSubExpressionEliminationPass.test.cpp
new file mode 100644 (file)
index 0000000..fd350a7
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Pass/CommonSubExpressionEliminationPass.h"
+
+#include "PassTestGraphs.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci;
+using namespace luci::test;
+
+class QuantizeGraphlet
+{
+public:
+  QuantizeGraphlet() = default;
+
+  virtual ~QuantizeGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    _quantize = g->nodes()->create<luci::CircleQuantize>();
+
+    auto qparam = std::make_unique<luci::CircleQuantParam>();
+    {
+      qparam->scale.emplace_back(1.0);
+      qparam->zerop.emplace_back(128);
+    }
+    _quantize->name("quantize");
+    _quantize->quantparam(std::move(qparam));
+    _quantize->dtype(loco::DataType::S16);
+  }
+
+protected:
+  luci::CircleQuantize *_quantize = nullptr;
+};
+
+class CSE_QuantizeTestGraph : public CommonSubExpressionEliminationTestGraph,
+                              public QuantizeGraphlet
+{
+public:
+  std::vector<luci::CircleQuantize *> ops;
+
+protected:
+  virtual loco::Node *createExpression(luci::CircleNode *ifm, const std::string &name) override
+  {
+    auto expr = g()->nodes()->create<luci::CircleQuantize>();
+
+    auto qparam = std::make_unique<luci::CircleQuantParam>();
+    {
+      qparam->scale.emplace_back(1.0);
+      qparam->zerop.emplace_back(128);
+    }
+    expr->name(name + "_quantize");
+    expr->quantparam(std::move(qparam));
+    expr->dtype(loco::DataType::S16);
+    expr->shape({1, 8, 8, 32});
+
+    expr->input(ifm);
+
+    ops.emplace_back(expr);
+
+    // Set ifm dtype as uint8
+    ifm->dtype(loco::DataType::U8);
+
+    return expr;
+  };
+
+public:
+  void init(void)
+  {
+    CommonSubExpressionEliminationTestGraph::init({{1, 8, 8, 32}}, {{1, 8, 8, 32}, {1, 8, 8, 32}});
+  }
+};
+
+class CSE_TransposeTestGraph : public CommonSubExpressionEliminationTestGraph
+{
+public:
+  std::vector<luci::CircleTranspose *> ops;
+
+protected:
+  virtual loco::Node *createExpression(luci::CircleNode *ifm, const std::string &name) override
+  {
+    auto perm = g()->nodes()->create<luci::CircleConst>();
+    perm->name(name + "_perm");
+    perm->dtype(loco::DataType::S32);
+    perm->shape({4});
+    perm->size<loco::DataType::S32>(4);
+    perm->at<loco::DataType::S32>(0) = 0;
+    perm->at<loco::DataType::S32>(1) = 3;
+    perm->at<loco::DataType::S32>(2) = 1;
+    perm->at<loco::DataType::S32>(3) = 2;
+
+    auto expr = g()->nodes()->create<luci::CircleTranspose>();
+    expr->name(name + "_transpose");
+    expr->dtype(loco::DataType::FLOAT32);
+    expr->shape({1, 32, 8, 8});
+    expr->a(ifm);
+    expr->perm(perm);
+
+    ops.emplace_back(expr);
+
+    return expr;
+  };
+
+public:
+  void init(void)
+  {
+    CommonSubExpressionEliminationTestGraph::init({{1, 8, 8, 32}}, {{1, 32, 8, 8}, {1, 32, 8, 8}});
+  }
+};
+
+} // namespace
+
+TEST(CommonSubExpressionEliminationTest, Quantize)
+{
+  CSE_QuantizeTestGraph g;
+  luci::CommonSubExpressionEliminationPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(CommonSubExpressionEliminationTest, Quantize_NEG)
+{
+  CSE_QuantizeTestGraph g;
+
+  luci::CommonSubExpressionEliminationPass pass;
+
+  g.init();
+
+  // Different pattern
+  g.ops.at(0)->input(g.ops.at(1));
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
+
+TEST(CommonSubExpressionEliminationTest, Transpose)
+{
+  CSE_TransposeTestGraph g;
+  luci::CommonSubExpressionEliminationPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(CommonSubExpressionEliminationTest, Transpose_NEG)
+{
+  CSE_TransposeTestGraph g;
+
+  luci::CommonSubExpressionEliminationPass pass;
+
+  g.init();
+
+  // Different pattern
+  g.ops.at(0)->a(g.ops.at(1));
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
index ac43202..8d782b3 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 #include "luci/Pass/ConvertNCHWToNHWCPass.h"
-#include "CircleOptimizerUtils.h"
+#include "helpers/Shape.h"
 
 #include <luci/IR/CircleNodes.h>
 #include <luci/IR/CircleNodeVisitor.h>
@@ -98,22 +98,6 @@ bool is_output(const loco::Node *node)
   return false;
 }
 
-bool is_same_shape(const luci::CircleNode *node, const std::vector<loco::Dimension> &shape)
-{
-  if (not node)
-    return false;
-
-  if (shape.size() != node->rank())
-    return false;
-
-  for (uint32_t i = 0; i < shape.size(); i++)
-  {
-    if (not(node->dim(i) == shape[i]))
-      return false;
-  }
-  return true;
-}
-
 enum class DataFormat
 {
   NCHW,
@@ -273,6 +257,27 @@ int32_t nchw_axis_to_nhwc(int32_t axis)
   return to_nhwc[pos_axis];
 }
 
+// Return a new CircleConst with NHWC value
+luci::CircleConst *create_nhwc_axis(luci::CircleConst *axis)
+{
+  assert(axis);                                   // FIX_CALLER_UNLESS
+  assert(axis->dtype() == loco::DataType::S32);   // FIX_CALLER_UNLESS
+  assert(axis->size<loco::DataType::S32>() == 1); // FIX_CALLER_UNLESS
+
+  auto new_axis = axis->graph()->nodes()->create<luci::CircleConst>();
+  new_axis->dtype(loco::DataType::S32);
+  new_axis->size<loco::DataType::S32>(1);
+  new_axis->rank(1);
+  new_axis->dim(0) = 1;
+  new_axis->at<loco::DataType::S32>(0) = nchw_axis_to_nhwc(axis->at<loco::DataType::S32>(0));
+  new_axis->shape_status(luci::ShapeStatus::VALID);
+  new_axis->name(axis->name() + "_NHWC");
+
+  luci::add_origin(new_axis, luci::get_origin(axis));
+
+  return new_axis;
+}
+
 luci::CircleTranspose *create_post_transpose(luci::CircleNode *node)
 {
   return create_4d_transpose(node, {0, 3, 1, 2});
@@ -1270,13 +1275,15 @@ class ConvertNCHWToNHWC final : public luci::CircleNodeMutableVisitor<bool>
     if (axis->size<loco::DataType::S32>() != 1)
       return false;
 
-    axis->at<loco::DataType::S32>(0) = nchw_axis_to_nhwc(axis->at<loco::DataType::S32>(0));
+    auto new_axis = create_nhwc_axis(axis);
+    assert(new_axis); // FIX_ME_UNLESS
 
     // Insert pre-transpose
     const auto pred_node = loco::must_cast<luci::CircleNode *>(node->input());
     auto pre_trans = create_pre_transpose(node);
     pre_trans->a(pred_node);
     node->input(pre_trans);
+    node->split_dim(new_axis);
 
     // Do shape inference for this node again.
     node->shape_status(luci::ShapeStatus::UNDEFINED);
index ae5ab15..4a0bc66 100644 (file)
@@ -87,7 +87,8 @@ bool is_quant_act(const luci::CircleNode *node)
 // 1. dtype is not fp32
 // 2. node has qparam
 // NOTE Quantized const can have the following types
-// u8 (weights, activation), s16 (weights, activation), s32 (bias), s64 (bias)
+// s4 (weights), u4 (weights), u8 (weights, activation),
+// s16 (weights, activation), s32 (bias), s64 (bias)
 bool is_quant_const(const luci::CircleConst *node)
 {
   if (node->dtype() == loco::DataType::FLOAT32)
@@ -197,6 +198,7 @@ struct FakeQuantize final : public luci::CircleNodeMutableVisitor<void>
   void visit(luci::CircleConv2D *node) { fq_activation(node); }
   void visit(luci::CircleDepthwiseConv2D *node) { fq_activation(node); }
   void visit(luci::CircleDiv *node) { fq_activation(node); }
+  void visit(luci::CircleExp *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); }
@@ -204,6 +206,8 @@ struct FakeQuantize final : public luci::CircleNodeMutableVisitor<void>
   void visit(luci::CircleLogistic *node) { fq_activation(node); }
   void visit(luci::CircleLogSoftmax *node) { fq_activation(node); }
   void visit(luci::CircleMaxPool2D *node) { fq_activation(node); }
+  void visit(luci::CircleMaximum *node) { fq_activation(node); }
+  void visit(luci::CircleMinimum *node) { fq_activation(node); }
   void visit(luci::CircleMul *node) { fq_activation(node); }
   void visit(luci::CircleNeg *node) { fq_activation(node); }
   void visit(luci::CirclePad *node) { fq_activation(node); }
index 9b1bb0e..fd6557a 100644 (file)
@@ -59,8 +59,8 @@ bool CopyQuantParamPass::run(loco::Graph *g)
 
   for (uint32_t i = 0; i < _src_tensors.size(); i++)
   {
-    auto src = _src_tensors[i];
-    auto dst = _dst_tensors[i];
+    auto &src = _src_tensors[i];
+    auto &dst = _dst_tensors[i];
 
     auto nodes = get_src_dst(src, dst);
     if (not nodes.src)
@@ -71,6 +71,12 @@ bool CopyQuantParamPass::run(loco::Graph *g)
 
     copy_quantparam(nodes.src, nodes.dst);
 
+    if (auto output = dynamic_cast<luci::CircleOutput *>(nodes.dst))
+    {
+      auto from_node = loco::must_cast<luci::CircleNode *>(output->from());
+      copy_quantparam(output, from_node);
+    }
+
     INFO(l) << "Quantparam of " << src << " is copied to " << dst << std::endl;
   }
 
index bd99d2d..2963cd8 100644 (file)
@@ -16,9 +16,6 @@
 
 #include "luci/Pass/DecomposeHardSwishPass.h"
 
-#include "helpers/NodeFiller.h"
-#include "helpers/TypeMapper.h"
-
 #include <luci/IR/CircleNodes.h>
 #include <luci/Profile/CircleNodeOrigin.h>
 
diff --git a/compiler/luci/pass/src/DecomposeSoftmaxPass.cpp b/compiler/luci/pass/src/DecomposeSoftmaxPass.cpp
new file mode 100644 (file)
index 0000000..0bfd852
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/DecomposeSoftmaxPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+/**
+ *  BEFORE
+ *        [CircleNode]
+ *              |
+ *              |
+ *      [CircleSoftmax]
+ *              |
+ *              |
+ *        [CircleNode]
+ *
+ *
+ *  AFTER
+ *
+ *      [CircleNode]   [CircleConst(=-1)]
+ *          |    \       /           |
+ *          |     \     /            |
+ *          | [CircleReduceMax]      |
+ *          |    /                   |
+ *          |   /                    |
+ *          |  /                     |
+ *        [Sub]                      |
+ *          |                        |
+ *          | [CircleConst(=beta)]   |
+ *          |   /                    |
+ *          |  /                     |
+ *        [Mul] (if beta != 1)       |
+ *          |                        |
+ *        [Exp]                      |
+ *          | \                      |
+ *          |  \                     |
+ *          |  [CircleSum]-----------+
+ *          |  /
+ *          | /
+ *        [Div]
+ *          |
+ *          |
+ *      [CircleNode]
+ */
+bool decompose_softmax(luci::CircleSoftmax *softmax)
+{
+  if (!softmax)
+    return false;
+
+  if (softmax->dtype() != loco::DataType::FLOAT32)
+    return false;
+
+  auto const input = loco::must_cast<luci::CircleNode *>(softmax->logits());
+  auto g = softmax->graph();
+
+  auto const beta = softmax->beta();
+  auto const name = softmax->name();
+  assert(name.length() > 0);
+
+  // fill reduction index (-1) for CircleReduceMax and CircleSum
+  auto index_const = g->nodes()->create<luci::CircleConst>();
+  index_const->shape({}); // scalar
+  index_const->dtype(loco::DataType::S32);
+  index_const->rank(0);
+  index_const->size<loco::DataType::S32>(1);
+  index_const->at<loco::DataType::S32>(0) = -1;
+  index_const->name(name + "/Softmax/reduction_index");
+  luci::add_origin(index_const, luci::get_origin(softmax));
+
+  // Create CircleReduceMax operation
+  auto max = g->nodes()->create<luci::CircleReduceMax>();
+  max->input(input);
+  max->reduction_indices(index_const);
+  max->keep_dims(true);
+  max->name(name + "/Softmax/max");
+  luci::add_origin(max, luci::get_origin(softmax));
+
+  // Create CircleSub operation
+  auto sub = g->nodes()->create<luci::CircleSub>();
+  sub->x(input);
+  sub->y(max);
+  sub->fusedActivationFunction(luci::FusedActFunc::NONE);
+  sub->name(name + "/Softmax/sub");
+  luci::add_origin(sub, luci::get_origin(softmax));
+
+  // input for exp can be either sub or mul (in case beta != 1)
+  loco::Node *exp_input = sub;
+
+  // multiply sub by beta in case it is nonunit
+  if (std::abs(beta - 1.f) > 1.e-05f)
+  {
+    // Create constant for beta
+    auto beta_const = g->nodes()->create<luci::CircleConst>();
+    beta_const->shape({}); // scalar
+    beta_const->dtype(loco::DataType::FLOAT32);
+    beta_const->rank(0);
+    beta_const->size<loco::DataType::FLOAT32>(1);
+    beta_const->at<loco::DataType::FLOAT32>(0) = beta;
+    beta_const->name(name + "/Softmax/beta_const");
+    luci::add_origin(beta_const, luci::get_origin(softmax));
+
+    // Create CircleMul
+    auto mul = g->nodes()->create<luci::CircleMul>();
+    mul->x(sub);
+    mul->y(beta_const);
+    mul->fusedActivationFunction(luci::FusedActFunc::NONE);
+    mul->name(name + "/Softmax/beta_mul");
+    luci::add_origin(mul, luci::get_origin(softmax));
+
+    exp_input = mul;
+  }
+
+  // Create CircleExp operation
+  auto exp = g->nodes()->create<luci::CircleExp>();
+  exp->x(exp_input);
+  exp->name(name + "/Softmax/exp");
+  luci::add_origin(exp, luci::get_origin(softmax));
+
+  // Create CircleSum operation
+  auto sum = g->nodes()->create<luci::CircleSum>();
+  sum->input(exp);
+  sum->reduction_indices(index_const);
+  sum->keep_dims(true);
+  sum->name(name + "/Softmax/sum");
+  luci::add_origin(sum, luci::get_origin(softmax));
+
+  // Create CircleDiv operation
+  auto div = g->nodes()->create<luci::CircleDiv>();
+  div->x(exp);
+  div->y(sum);
+  div->fusedActivationFunction(luci::FusedActFunc::NONE);
+  div->name(name + "/Softmax/div");
+  luci::add_origin(div, luci::get_origin(softmax));
+
+  replace(softmax).with(div);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool DecomposeSoftmaxPass::run(loco::Graph *g)
+{
+  bool changed = false;
+
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto softmax = dynamic_cast<luci::CircleSoftmax *>(node))
+    {
+      if (decompose_softmax(softmax))
+        changed = true;
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/DecomposeSoftmaxPass.test.cpp b/compiler/luci/pass/src/DecomposeSoftmaxPass.test.cpp
new file mode 100644 (file)
index 0000000..481ed45
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Pass/DecomposeSoftmaxPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+/**
+ *  Softmax graph
+ *
+ *        [CircleInput]
+ *              |
+ *              |
+ *       [CircleSoftMax]
+ *              |
+ *              |
+ *        [CircleOutput]
+ */
+template <loco::DataType T> struct SoftmaxGraph
+{
+  loco::Graph _g;
+  luci::CircleInput *_input = nullptr;
+  luci::CircleSoftmax *_softmax = nullptr;
+  luci::CircleOutput *_output = nullptr;
+
+  SoftmaxGraph()
+  {
+    const int N = 1;
+    const int H = 4;
+    const int W = 4;
+    const int C = 3;
+
+    // graph input and output
+    auto graph_input = _g.inputs()->create();
+    auto graph_output = _g.outputs()->create();
+
+    // CircleInput
+    _input = _g.nodes()->create<luci::CircleInput>();
+    _input->index(graph_input->index());
+    _input->shape({N, H, W, C});
+    _input->dtype(T);
+    _input->name("input");
+
+    // CircleSoftmax
+    _softmax = _g.nodes()->create<luci::CircleSoftmax>();
+    _softmax->logits(_input);
+    _softmax->shape({N, H, W, C});
+    _softmax->dtype(T);
+    _softmax->name("softmax");
+    _softmax->beta(0.5f);
+
+    // CircleOutput
+    _output = _g.nodes()->create<luci::CircleOutput>();
+    _output->index(graph_output->index());
+    _output->from(_softmax);
+    _output->shape({N, H, W, C});
+    _output->dtype(T);
+    _output->name("output");
+  }
+};
+
+} // namespace
+
+TEST(DecomposeSoftmaxPass, simple_test)
+{
+  /**
+   *  tests:
+   *    1) decomposition pass has nonnull name
+   *    2) decomposition runs successfully for float32 softmax graph
+   *    3) resulting graph has the following structure:
+   *
+   *      [CircleNode]   [CircleConst(=-1)]
+   *          |    \       /           |
+   *          |     \     /            |
+   *          | [CircleReduceMax]      |
+   *          |    /                   |
+   *          |   /                    |
+   *          |  /                     |
+   *        [Sub]                      |
+   *          |                        |
+   *          | [CircleConst(=0.5)]    |
+   *          |   /                    |
+   *          |  /                     |
+   *        [Mul]                      |
+   *          |                        |
+   *        [Exp]                      |
+   *          | \                      |
+   *          |  \                     |
+   *          |  [CircleSum]-----------+
+   *          |  /
+   *          | /
+   *        [Div]
+   *          |
+   *          |
+   *      [CircleNode]
+   */
+  luci::DecomposeSoftmaxPass pass;
+  SoftmaxGraph<loco::DataType::FLOAT32> softmax_g;
+
+  auto const name = pass.name();
+  ASSERT_NE(nullptr, name);
+
+  auto ret = pass.run(&softmax_g._g);
+  EXPECT_TRUE(ret);
+
+  auto div = dynamic_cast<luci::CircleDiv *>(softmax_g._output->from());
+  EXPECT_NE(nullptr, div);
+
+  auto exp = dynamic_cast<luci::CircleExp *>(div->x());
+  EXPECT_NE(nullptr, exp);
+
+  auto sum = dynamic_cast<luci::CircleSum *>(div->y());
+  EXPECT_NE(nullptr, sum);
+
+  auto exp_1 = dynamic_cast<luci::CircleExp *>(sum->input());
+  EXPECT_EQ(exp, exp_1);
+
+  auto indices = dynamic_cast<luci::CircleConst *>(sum->reduction_indices());
+  EXPECT_NE(nullptr, indices);
+  EXPECT_EQ(indices->dtype(), loco::DataType::S32);
+  EXPECT_EQ(indices->size<loco::DataType::S32>(), 1);
+  EXPECT_EQ(indices->scalar<loco::DataType::S32>(), -1);
+
+  auto mul = dynamic_cast<luci::CircleMul *>(exp->x());
+  EXPECT_NE(nullptr, mul);
+
+  auto sub = dynamic_cast<luci::CircleSub *>(mul->x());
+  EXPECT_NE(nullptr, sub);
+
+  auto beta = dynamic_cast<luci::CircleConst *>(mul->y());
+  EXPECT_NE(nullptr, beta);
+  EXPECT_EQ(beta->dtype(), loco::DataType::FLOAT32);
+  EXPECT_EQ(beta->size<loco::DataType::FLOAT32>(), 1);
+  EXPECT_FLOAT_EQ(beta->scalar<loco::DataType::FLOAT32>(), 0.5f);
+
+  auto input = dynamic_cast<luci::CircleInput *>(sub->x());
+  EXPECT_NE(nullptr, input);
+
+  auto max = dynamic_cast<luci::CircleReduceMax *>(sub->y());
+  EXPECT_NE(nullptr, max);
+
+  auto indices_1 = dynamic_cast<luci::CircleConst *>(max->reduction_indices());
+  EXPECT_NE(nullptr, indices_1);
+  EXPECT_EQ(indices, indices_1);
+
+  auto input_1 = dynamic_cast<luci::CircleInput *>(max->input());
+  EXPECT_NE(nullptr, input_1);
+  EXPECT_EQ(input, input_1);
+}
+
+TEST(DecomposeSoftmaxPass, wrong_condition_NEG)
+{
+  luci::DecomposeSoftmaxPass pass;
+  SoftmaxGraph<loco::DataType::S32> softmax_g;
+
+  auto ret = pass.run(&softmax_g._g);
+  EXPECT_FALSE(ret);
+
+  auto softmax = dynamic_cast<luci::CircleSoftmax *>(softmax_g._output->from());
+  EXPECT_NE(nullptr, softmax);
+}
index 20c1022..7952b6b 100644 (file)
@@ -18,8 +18,6 @@
 
 #include <luci/IR/CircleNodes.h>
 
-#include <iostream>
-
 namespace
 {
 
index 00b86fe..3ecbe2b 100644 (file)
@@ -26,24 +26,41 @@ luci::CircleConst *cast_const(luci::CircleConst *node, loco::DataType from_dtype
 {
   assert(node->dtype() == from_dtype);
 
+  enum CAST_TYPES
+  {
+    CAST_NONE = 0,
+    CAST_S64_S32,
+  };
+
+  CAST_TYPES cast_type = CAST_NONE;
+  if (from_dtype == loco::DataType::S64)
+  {
+    if (to_dtype == loco::DataType::S32)
+      cast_type = CAST_S64_S32;
+  }
+  // TODO: Support more data types
+  if (cast_type == CAST_NONE)
+    return nullptr;
+
   auto name = node->name();
   assert(name.length() > 0);
+
   auto constant = node->graph()->nodes()->create<luci::CircleConst>();
   constant->dtype(to_dtype);
   constant->rank(node->rank());
   uint32_t num_elems = 1;
+
   for (uint32_t i = 0; i < node->rank(); i++)
   {
     constant->dim(i).set(node->dim(i).value());
     num_elems *= node->dim(i).value();
   }
-
   constant->shape_status(luci::ShapeStatus::VALID);
 
   // TODO: Support more data types
-  if (from_dtype == loco::DataType::S64)
+  switch (cast_type)
   {
-    if (to_dtype == loco::DataType::S32)
+    case CAST_S64_S32:
     {
       constant->size<loco::DataType::S32>(num_elems);
       for (uint32_t i = 0; i < num_elems; i++)
@@ -53,7 +70,8 @@ luci::CircleConst *cast_const(luci::CircleConst *node, loco::DataType from_dtype
       constant->name(name + "_S32");
       return constant;
     }
-    return nullptr;
+    default:
+      break;
   }
 
   return nullptr;
index 33f9f1d..455a695 100644 (file)
 
 #include "luci/Pass/FoldDepthwiseConv2DPass.h"
 
-#include <tensorflow/lite/kernels/internal/reference/depthwiseconv_float.h>
+#include "helpers/Compute.h"
+#include "helpers/Shape.h"
 
 #include <luci/IR/CircleNodes.h>
 #include <luci/IR/AttrFusedActFunc.h>
 
 #include <luci/Log.h>
 
-#include <limits> // std::numeric_limits
+#include <luci_compute/DepthwiseConv2D.h>
 
-namespace
+#include <cassert>
+
+namespace luci
 {
 
-// TODO Share activation mix/max and compute_input/output code with luci-interpreter
+namespace
+{
 
-bool compute_output(uint32_t *output_size, luci::Padding padding, int32_t image_size,
-                    int32_t filter_size, int32_t stride, int32_t dilation_rate)
+bool set_params(const luci::CircleDepthwiseConv2D *node, compute::DepthwiseConv2D &cdc)
 {
-  auto const effective_filter_size = (filter_size - 1) * dilation_rate + 1;
-  switch (padding)
-  {
-    case luci::Padding::SAME:
-      *output_size = (image_size + stride - 1) / stride;
-      return true;
+  assert(node);
 
-    case luci::Padding::VALID:
-      *output_size = (image_size + stride - effective_filter_size) / stride;
-      return true;
+  LOGGER(l);
 
-    default:
-    {
-      LOGGER(l);
-      WARN(l) << "Unsupported padding: " << uint32_t(padding);
-      return false;
-    }
+  auto &params = cdc.params();
+  if (!to_compute(node->padding(), params.padding_type))
+  {
+    WARN(l) << "FoldDepthwiseConv2DPass unsupported padding: " << uint32_t(node->padding());
+    return false;
   }
-}
 
-uint32_t compute_padding(int32_t stride, int32_t dilation_rate, int32_t in_size,
-                         int32_t filter_size, int32_t out_size)
-{
-  auto const effective_filter_size = (filter_size - 1) * dilation_rate + 1;
-  auto const padding = ((out_size - 1) * stride + effective_filter_size - in_size) / 2;
-  return padding > 0 ? padding : 0;
-}
+  params.stride_height = node->stride()->h();
+  params.stride_width = node->stride()->w();
+  params.dilation_height_factor = node->dilation()->h();
+  params.dilation_width_factor = node->dilation()->w();
+  params.depth_multiplier = node->depthMultiplier();
 
-bool set_kernel_parameters(tflite::DepthwiseParams *params, luci::CircleDepthwiseConv2D *node,
-                           uint32_t padding_height, uint32_t padding_width)
-{
-  switch (node->fusedActivationFunction())
+  compute::FusedActFunc fac;
+  if (!to_compute(node->fusedActivationFunction(), fac))
   {
-    case luci::FusedActFunc::NONE:
-    case luci::FusedActFunc::TANH:
-      params->float_activation_min = std::numeric_limits<float>::lowest();
-      params->float_activation_max = std::numeric_limits<float>::max();
-      break;
-    case luci::FusedActFunc::RELU:
-      params->float_activation_min = 0;
-      params->float_activation_max = std::numeric_limits<float>::max();
-      break;
-    case luci::FusedActFunc::RELU_N1_TO_1:
-      params->float_activation_min = -1;
-      params->float_activation_max = 1;
-      break;
-    case luci::FusedActFunc::RELU6:
-      params->float_activation_min = 0;
-      params->float_activation_max = 6;
-      break;
-    default:
-    {
-      LOGGER(l);
-      WARN(l) << "Unsupported activation: " << uint32_t(node->fusedActivationFunction());
-      return false;
-    }
+    WARN(l) << "FoldDepthwiseConv2DPass unsupported activation: "
+            << uint32_t(node->fusedActivationFunction());
+    return false;
   }
-
-  params->stride_height = node->stride()->h();
-  params->stride_width = node->stride()->w();
-  params->dilation_height_factor = node->dilation()->h();
-  params->dilation_width_factor = node->dilation()->w();
-  params->depth_multiplier = node->depthMultiplier();
-
-  params->padding_values.height = padding_height;
-  params->padding_values.width = padding_width;
+  cdc.fused_act_func(fac);
 
   return true;
 }
@@ -118,91 +80,59 @@ bool set_kernel_parameters(tflite::DepthwiseParams *params, luci::CircleDepthwis
  */
 bool fold_depthwise_conv_2d(luci::CircleDepthwiseConv2D *node)
 {
-  LOGGER(l);
-
   auto const input = dynamic_cast<luci::CircleConst *>(node->input());
-
   if (input == nullptr)
     return false; // Constant input is required for folding
 
   auto const filter = dynamic_cast<luci::CircleConst *>(node->filter());
-
   if (filter == nullptr)
     return false; // Constant filter is required for folding
-
   if (filter->dim(0).value() != 1)
     return false; // Unsupported batch size
 
   auto const bias = dynamic_cast<luci::CircleConst *>(node->bias());
-
   if (bias == nullptr)
     return false; // Constant bias is required for folding
 
-  auto const input_batches = input->dim(0).value();
-  auto const input_height = input->dim(1).value();
-  auto const input_width = input->dim(2).value();
-  auto const input_depth = input->dim(3).value();
-
-  auto const filter_height = filter->dim(1).value();
-  auto const filter_width = filter->dim(2).value();
-  auto const filter_channels_out = filter->dim(3).value();
-
-  if (filter_channels_out % input_depth != 0)
-    return false; // Wrong input/output depth ratio
-
-  if (node->depthMultiplier() != static_cast<int32_t>(filter_channels_out / input_depth))
-    return false; // Wrong depth multiplier value
-
-  if (bias->rank() != 1 || bias->dim(0).value() != filter_channels_out)
-    return false; // Unsupported bias value
-
-  uint32_t output_height = 0;
-  uint32_t output_width = 0;
-
-  if (!compute_output(&output_height, node->padding(), input_height, filter_height,
-                      node->stride()->h(), node->dilation()->h()))
-    return false; // Unsupported output parameters
+  auto static_shape = [](luci::CircleNode *node) {
+    loco::TensorShape shape;
+    shape.rank(node->rank());
+    for (uint32_t i = 0; i < node->rank(); ++i)
+      shape.dim(i) = node->dim(i);
+    return shape;
+  };
 
-  if (!compute_output(&output_width, node->padding(), input_width, filter_width,
-                      node->stride()->w(), node->dilation()->w()))
-    return false; // Unsupported output parameters
+  auto const input_data = &input->at<loco::DataType::FLOAT32>(0);
+  auto const filter_data = &filter->at<loco::DataType::FLOAT32>(0);
+  auto const bias_data = &bias->at<loco::DataType::FLOAT32>(0);
 
-  auto const padding_height = compute_padding(node->stride()->h(), node->dilation()->h(),
-                                              input_height, filter_height, output_height);
-  auto const padding_width = compute_padding(node->stride()->w(), node->dilation()->w(),
-                                             input_width, filter_width, output_width);
+  compute::DepthwiseConv2D comp_dwconv2d{};
+  if (!set_params(node, comp_dwconv2d))
+    return false;
+  comp_dwconv2d.input(static_shape(input), input_data);
+  comp_dwconv2d.filter(static_shape(filter), filter_data);
+  comp_dwconv2d.bias(static_shape(bias), bias_data);
 
-  tflite::DepthwiseParams params{};
+  if (!comp_dwconv2d.prepare())
+    return false;
 
-  if (!set_kernel_parameters(&params, node, padding_height, padding_width))
-    return false; // Unsupported kernel parameter values
+  auto output_shape = comp_dwconv2d.output_shape();
+  assert(is_same_shape(node, output_shape));
+  auto output_size = loco::element_count(&output_shape);
 
+  // result folded constant node
   auto constant = node->graph()->nodes()->create<luci::CircleConst>();
-  constant->name(node->name());
   constant->dtype(node->dtype());
   constant->rank(node->rank());
+  for (uint32_t i = 0; i < output_shape.rank(); ++i)
+    constant->dim(i).set(output_shape.dim(i).value());
   constant->shape_status(luci::ShapeStatus::VALID);
-  for (uint32_t i = 0; i < node->rank(); ++i)
-    constant->dim(i).set(node->dim(i).value());
-
-  constant->size<loco::DataType::FLOAT32>(input_batches * output_height * output_width *
-                                          filter_channels_out);
-
-  auto const input_data = &input->at<loco::DataType::FLOAT32>(0);
-  auto const filter_data = &filter->at<loco::DataType::FLOAT32>(0);
-  auto const bias_data = &bias->at<loco::DataType::FLOAT32>(0);
-  auto const constant_data = &constant->at<loco::DataType::FLOAT32>(0);
-
-  auto tensor_shape = [](luci::CircleNode *node) {
-    tflite::RuntimeShape runtime_shape(node->rank());
-    for (uint32_t i = 0; i < node->rank(); ++i)
-      runtime_shape.SetDim(i, node->dim(i).value());
-    return runtime_shape;
-  };
+  constant->size<loco::DataType::FLOAT32>(output_size);
+  constant->name(node->name());
 
-  tflite::reference_ops::DepthwiseConv(params, tensor_shape(input), input_data,
-                                       tensor_shape(filter), filter_data, tensor_shape(bias),
-                                       bias_data, tensor_shape(constant), constant_data);
+  auto constant_data = &constant->at<loco::DataType::FLOAT32>(0);
+  comp_dwconv2d.output(constant_data);
+  comp_dwconv2d.compute();
 
   loco::replace(node).with(constant);
 
@@ -211,9 +141,6 @@ bool fold_depthwise_conv_2d(luci::CircleDepthwiseConv2D *node)
 
 } // namespace
 
-namespace luci
-{
-
 /**
  * Constant Folding for DepthwiseConv2D Op
  **/
index 36cae04..3a1b544 100644 (file)
@@ -56,6 +56,7 @@ public:
     _dconv->filter(_dconv_filter);
     _dconv->bias(_dconv_bias);
     _dconv->shape({1, 4, 4, 1});
+    _dconv->shape_status(luci::ShapeStatus::VALID);
     _dconv->stride()->h(1);
     _dconv->stride()->w(1);
     _dconv->depthMultiplier(1);
index b6526de..39652a5 100644 (file)
@@ -40,6 +40,10 @@ bool is_foldable_const(luci::CircleConst *node)
   if (node->quantparam() == nullptr)
     return false;
 
+  if (node->dtype() == loco::DataType::S4)
+    return true;
+  if (node->dtype() == loco::DataType::U4)
+    return true;
   if (node->dtype() == loco::DataType::S8)
     return true;
   if (node->dtype() == loco::DataType::U8)
@@ -105,6 +109,18 @@ luci::CircleConst *dequantized_const_node(luci::CircleConst *const_node)
 
     switch (const_node->dtype())
     {
+      case loco::DataType::U4:
+        new_const_node->at<loco::DataType::FLOAT32>(i) =
+          static_cast<float>(const_node->at<loco::DataType::U4>(i) -
+                             const_node->quantparam()->zerop.at(qd)) *
+          const_node->quantparam()->scale.at(qd);
+        break;
+      case loco::DataType::S4:
+        new_const_node->at<loco::DataType::FLOAT32>(i) =
+          static_cast<float>(const_node->at<loco::DataType::S4>(i) -
+                             const_node->quantparam()->zerop.at(qd)) *
+          const_node->quantparam()->scale.at(qd);
+        break;
       case loco::DataType::S8:
         new_const_node->at<loco::DataType::FLOAT32>(i) =
           static_cast<float>(const_node->at<loco::DataType::S8>(i) -
index 87dff5d..8873fc3 100644 (file)
@@ -86,6 +86,14 @@ protected:
   luci::CircleConst *_input = nullptr;
 };
 
+class U4FoldDequantizeTest : public FoldDequantizeTest<loco::DataType::U4>
+{
+};
+
+class S4FoldDequantizeTest : public FoldDequantizeTest<loco::DataType::S4>
+{
+};
+
 class S8FoldDequantizeTest : public FoldDequantizeTest<loco::DataType::S8>
 {
 };
@@ -205,6 +213,80 @@ TEST_F(U8FoldDequantizeTest, fold_dequant_basic_NEG)
   EXPECT_EQ(nullptr, folded_const);
 }
 
+TEST_F(U4FoldDequantizeTest, fold_dequant_basic)
+{
+  luci::FoldDequantizePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  // Chec type, shape, values of folded const
+  EXPECT_EQ(loco::DataType::FLOAT32, folded_const->dtype());
+  EXPECT_EQ(3, folded_const->rank());
+  EXPECT_EQ(2, folded_const->dim(0).value());
+  EXPECT_EQ(2, folded_const->dim(1).value());
+  EXPECT_EQ(2, folded_const->dim(2).value());
+  EXPECT_EQ(-5.0, folded_const->at<loco::DataType::FLOAT32>(0));
+  EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(1));
+  EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(2));
+  EXPECT_EQ(10.0, folded_const->at<loco::DataType::FLOAT32>(3));
+  EXPECT_EQ(15.0, folded_const->at<loco::DataType::FLOAT32>(4));
+  EXPECT_EQ(20.0, folded_const->at<loco::DataType::FLOAT32>(5));
+  EXPECT_EQ(40.0, folded_const->at<loco::DataType::FLOAT32>(6));
+  EXPECT_EQ(50.0, folded_const->at<loco::DataType::FLOAT32>(7));
+}
+
+TEST_F(U4FoldDequantizeTest, fold_dequant_basic_NEG)
+{
+  createNotFoldablePattern();
+
+  luci::FoldDequantizePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(S4FoldDequantizeTest, fold_dequant_basic)
+{
+  luci::FoldDequantizePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  // Chec type, shape, values of folded const
+  EXPECT_EQ(loco::DataType::FLOAT32, folded_const->dtype());
+  EXPECT_EQ(3, folded_const->rank());
+  EXPECT_EQ(2, folded_const->dim(0).value());
+  EXPECT_EQ(2, folded_const->dim(1).value());
+  EXPECT_EQ(2, folded_const->dim(2).value());
+  EXPECT_EQ(-5.0, folded_const->at<loco::DataType::FLOAT32>(0));
+  EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(1));
+  EXPECT_EQ(0.0, folded_const->at<loco::DataType::FLOAT32>(2));
+  EXPECT_EQ(10.0, folded_const->at<loco::DataType::FLOAT32>(3));
+  EXPECT_EQ(15.0, folded_const->at<loco::DataType::FLOAT32>(4));
+  EXPECT_EQ(20.0, folded_const->at<loco::DataType::FLOAT32>(5));
+  EXPECT_EQ(40.0, folded_const->at<loco::DataType::FLOAT32>(6));
+  EXPECT_EQ(50.0, folded_const->at<loco::DataType::FLOAT32>(7));
+}
+
+TEST_F(S4FoldDequantizeTest, fold_dequant_basic_NEG)
+{
+  createNotFoldablePattern();
+
+  luci::FoldDequantizePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_EQ(nullptr, folded_const);
+}
+
 TEST_F(S8FoldDequantizeTest, fold_dequant_basic)
 {
   luci::FoldDequantizePass pass;
index a3bca7e..8fa0720 100644 (file)
 
 #include "luci/Pass/FoldFullyConnectedPass.h"
 
-#include <tensorflow/lite/kernels/internal/reference/fully_connected.h>
+#include "helpers/Compute.h"
+#include "helpers/Shape.h"
 
 #include <luci/IR/CircleNodes.h>
 #include <luci/IR/AttrFusedActFunc.h>
 
 #include <luci/Log.h>
 
-#include <limits> // std::numeric_limits
+#include <luci_compute/FullyConnected.h>
+
+#include <cassert>
+
+namespace luci
+{
 
 namespace
 {
 
-bool set_kernel_parameters(tflite::FullyConnectedParams *params, luci::CircleFullyConnected *node)
+bool set_params(const luci::CircleFullyConnected *node, compute::FullyConnected &cfc)
 {
-  switch (node->fusedActivationFunction())
+  assert(node);
+
+  LOGGER(l);
+
+  // NOTE only support default for now
+  if (node->weights_format() != luci::CircleFullyConnected::WeightsFormat::DEFAULT)
   {
-    case luci::FusedActFunc::NONE:
-    case luci::FusedActFunc::TANH:
-      params->float_activation_min = std::numeric_limits<float>::lowest();
-      params->float_activation_max = std::numeric_limits<float>::max();
-      break;
-    case luci::FusedActFunc::RELU:
-      params->float_activation_min = 0;
-      params->float_activation_max = std::numeric_limits<float>::max();
-      break;
-    case luci::FusedActFunc::RELU_N1_TO_1:
-      params->float_activation_min = -1;
-      params->float_activation_max = 1;
-      break;
-    case luci::FusedActFunc::RELU6:
-      params->float_activation_min = 0;
-      params->float_activation_max = 6;
-      break;
-    default:
-    {
-      LOGGER(l);
-      WARN(l) << "Unsupported activation: " << uint32_t(node->fusedActivationFunction());
-      return false;
-    }
+    WARN(l) << "FoldFullyConnectedPass unsupported weights_format: "
+            << uint32_t(node->weights_format());
+    return false;
   }
+  cfc.params().weights_format = compute::FullyConnectedWeightsFormat::kDefault;
 
-  assert(node->weights_format() ==
-         luci::CircleFullyConnected::WeightsFormat::DEFAULT); // FIX_CALLER_UNLESS
-  params->weights_format = tflite::FullyConnectedWeightsFormat::kDefault;
+  compute::FusedActFunc fac;
+  if (!to_compute(node->fusedActivationFunction(), fac))
+  {
+    WARN(l) << "FoldFullyConnectedPass unsupported activation: "
+            << uint32_t(node->fusedActivationFunction());
+    return false;
+  }
+  cfc.fused_act_func(fac);
 
   return true;
 }
@@ -85,8 +82,6 @@ bool fold_fully_connected(luci::CircleFullyConnected *node)
 {
   RETURN_FALSE_UNLESS(node != nullptr);
 
-  LOGGER(l);
-
   auto const input = dynamic_cast<luci::CircleConst *>(node->input());
   auto const weights = dynamic_cast<luci::CircleConst *>(node->weights());
   auto const bias = dynamic_cast<luci::CircleConst *>(node->bias());
@@ -94,77 +89,59 @@ bool fold_fully_connected(luci::CircleFullyConnected *node)
 
   RETURN_FALSE_UNLESS(input != nullptr);
   RETURN_FALSE_UNLESS(weights != nullptr);
-  RETURN_FALSE_UNLESS(node->weights_format() == luci::CircleFullyConnected::WeightsFormat::DEFAULT);
   RETURN_FALSE_UNLESS(bias != nullptr or no_bias != nullptr);
 
   RETURN_FALSE_UNLESS(input->dtype() == loco::DataType::FLOAT32);
   RETURN_FALSE_UNLESS(weights->dtype() == loco::DataType::FLOAT32);
+
+  auto const input_data = &input->at<loco::DataType::FLOAT32>(0);
+  auto const weights_data = &weights->at<loco::DataType::FLOAT32>(0);
+  float *bias_data = nullptr;
   if (bias)
+  {
     RETURN_FALSE_UNLESS(bias->dtype() == loco::DataType::FLOAT32);
+    bias_data = &bias->at<loco::DataType::FLOAT32>(0);
+  }
 
-  auto const input_elems = input->size<loco::DataType::FLOAT32>();
+  auto static_shape = [](luci::CircleNode *node) {
+    loco::TensorShape shape;
+    if (not node)
+      return shape;
+    shape.rank(node->rank());
+    for (uint32_t i = 0; i < node->rank(); ++i)
+      shape.dim(i) = node->dim(i);
+    return shape;
+  };
 
-  RETURN_FALSE_UNLESS(weights->rank() == 2);
-  RETURN_FALSE_UNLESS(input_elems % weights->dim(1).value() == 0);
-  auto const batch_size = input_elems / weights->dim(1).value();
-  auto const num_units = weights->dim(0).value();
+  compute::FullyConnected comp_fc{};
+  if (!set_params(node, comp_fc))
+    return false;
+  comp_fc.input(static_shape(input), input_data);
+  comp_fc.weights(static_shape(weights), weights_data);
+  comp_fc.bias(static_shape(bias), bias_data);
 
-  if (bias)
-    RETURN_FALSE_UNLESS(bias->size<loco::DataType::FLOAT32>() == num_units);
+  comp_fc.keep_num_dims(node->keep_num_dims());
 
-  tflite::FullyConnectedParams params{};
-  if (!set_kernel_parameters(&params, node))
-    return false; // Unsupported kernel parameter values
+  if (!comp_fc.prepare())
+    return false;
 
-  std::vector<uint32_t> output_shape;
-  if (node->keep_num_dims() == false)
-  {
-    output_shape.push_back(batch_size);
-    output_shape.push_back(num_units);
-  }
-  else
-  {
-    output_shape.resize(input->rank());
-    for (uint32_t i = 0; i < input->rank(); i++)
-      output_shape[i] = input->dim(i).value();
-    output_shape[input->rank() - 1] = num_units;
-  }
+  const auto &output_shape = comp_fc.output_shape();
+  assert(is_same_shape(node, output_shape));
+  auto output_size = loco::element_count(&output_shape);
 
   auto constant = node->graph()->nodes()->create<luci::CircleConst>();
   {
-    constant->name(node->name());
     constant->dtype(node->dtype());
     constant->rank(node->rank());
-    constant->shape_status(luci::ShapeStatus::VALID);
-    uint32_t num_elem = 1;
     for (uint32_t i = 0; i < node->rank(); ++i)
-    {
       constant->dim(i).set(node->dim(i).value());
-      num_elem *= node->dim(i).value();
-    }
-    constant->size<loco::DataType::FLOAT32>(num_elem);
+    constant->shape_status(luci::ShapeStatus::VALID);
+    constant->size<loco::DataType::FLOAT32>(output_size);
+    constant->name(node->name());
   }
-
-  auto tensor_shape = [](luci::CircleNode *node) {
-    if (node == nullptr)
-      return tflite::RuntimeShape();
-
-    tflite::RuntimeShape runtime_shape(node->rank());
-    for (uint32_t i = 0; i < node->rank(); ++i)
-      runtime_shape.SetDim(i, node->dim(i).value());
-    return runtime_shape;
-  };
-
-  auto tensor_data = [](luci::CircleConst *node) -> float * {
-    if (node == nullptr)
-      return nullptr;
-
-    return &node->at<loco::DataType::FLOAT32>(0);
-  };
-
-  tflite::reference_ops::FullyConnected(
-    params, tensor_shape(input), tensor_data(input), tensor_shape(weights), tensor_data(weights),
-    tensor_shape(bias), tensor_data(bias), tensor_shape(constant), tensor_data(constant));
+  auto constant_data = &constant->at<loco::DataType::FLOAT32>(0);
+  comp_fc.output(constant_data);
+  comp_fc.compute();
 
   loco::replace(node).with(constant);
 
@@ -173,9 +150,6 @@ bool fold_fully_connected(luci::CircleFullyConnected *node)
 
 } // namespace
 
-namespace luci
-{
-
 /**
  * Constant Folding for FullyConnected Op
  **/
index a8e64a2..4a1dd8c 100644 (file)
@@ -58,6 +58,7 @@ public:
     _fc->weights(_fc_weights);
     _fc->bias(_fc_bias);
     _fc->shape({NUM_UNITS});
+    _fc->shape_status(luci::ShapeStatus::VALID);
     _fc->weights_format(luci::CircleFullyConnected::WeightsFormat::DEFAULT);
     _fc->keep_num_dims(true);
 
index f179d74..43422cb 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include "luci/Pass/FoldGatherPass.h"
-#include "CircleOptimizerUtils.h"
 
 #include <luci/IR/CircleNodes.h>
 
diff --git a/compiler/luci/pass/src/FoldMulPass.cpp b/compiler/luci/pass/src/FoldMulPass.cpp
new file mode 100644 (file)
index 0000000..6511291
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FoldMulPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <algorithm>
+
+#define CHECK_OR_FALSE(condition) \
+  if (not(condition))             \
+    return false;
+
+namespace
+{
+
+/**
+ * @return higher rank of x, y or nullptr if not compatible
+ */
+const luci::CircleConst *compatible_shape(const luci::CircleConst *x, const luci::CircleConst *y)
+{
+  if (x->rank() >= y->rank())
+  {
+    uint32_t d = x->rank() - y->rank();
+    for (uint32_t i = 0; i < y->rank(); i++)
+    {
+      // NOTE dim() has only '==' operator
+      if (!(x->dim(i + d) == y->dim(i)))
+        return nullptr;
+    }
+    return x;
+  }
+  else
+  {
+    uint32_t d = y->rank() - x->rank();
+    for (uint32_t i = 0; i < x->rank(); i++)
+    {
+      if (!(x->dim(i) == y->dim(i + d)))
+        return nullptr;
+    }
+    return y;
+  }
+}
+
+/**
+ * Fold Mul to const if both inputs are const
+ **/
+bool fold_mul(luci::CircleMul *mul)
+{
+  CHECK_OR_FALSE(mul);
+  CHECK_OR_FALSE(mul->dtype() == loco::DataType::FLOAT32);
+
+  // Check inputs are const and compatible
+  auto x = dynamic_cast<luci::CircleConst *>(mul->x());
+  auto y = dynamic_cast<luci::CircleConst *>(mul->y());
+  CHECK_OR_FALSE(x);
+  CHECK_OR_FALSE(y);
+  CHECK_OR_FALSE(x->dtype() == y->dtype());
+  const auto xy = compatible_shape(x, y);
+  CHECK_OR_FALSE(xy);
+
+  auto name_x = x->name();
+  auto name_y = y->name();
+  assert(name_x.length() > 0);
+  assert(name_y.length() > 0);
+  auto folded_const = mul->graph()->nodes()->create<luci::CircleConst>();
+  folded_const->dtype(xy->dtype());
+  folded_const->rank(xy->rank());
+  for (uint32_t i = 0; i < xy->rank(); i++)
+    folded_const->dim(i).set(xy->dim(i).value());
+
+  const auto size_x = x->size<loco::DataType::FLOAT32>();
+  const auto size_y = y->size<loco::DataType::FLOAT32>();
+  const auto size_xy = xy->size<loco::DataType::FLOAT32>();
+  folded_const->size<loco::DataType::FLOAT32>(size_xy);
+  for (uint32_t i = 0; i < size_xy; i++)
+  {
+    auto xv = x->at<loco::DataType::FLOAT32>(i % size_x);
+    auto yv = y->at<loco::DataType::FLOAT32>(i % size_y);
+    folded_const->at<loco::DataType::FLOAT32>(i) = xv * yv;
+  }
+
+  folded_const->shape_status(luci::ShapeStatus::VALID);
+  folded_const->name(name_x + "_" + name_y);
+
+  loco::replace(mul).with(folded_const);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * Constant Folding for Mul Op
+ **/
+bool FoldMulPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto mul = dynamic_cast<luci::CircleMul *>(node))
+    {
+      if (fold_mul(mul))
+        changed = true;
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FoldMulPass.test.cpp b/compiler/luci/pass/src/FoldMulPass.test.cpp
new file mode 100644 (file)
index 0000000..0c6de97
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FoldMulPass.h"
+#include "PassTestGraphs.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+/**
+ *  Graph has an Mul Op with constant inputs
+ *
+ *    BEFORE
+ *
+ *    [CircleConst] [CircleConst]
+ *               |    |
+ *             [CircleMul]
+ *                  |
+ *             [CircleNode]
+ *    AFTER
+ *                             [CircleConst] [CircleConst]
+ *                                       |    |
+ *             [CircleConst]           [CircleMul]
+ *                  |
+ *             [CircleNode]
+ */
+
+template <loco::DataType T> class FoldMulTest : public luci::ConstantFoldingAddTestGraph
+{
+public:
+  FoldMulTest(std::initializer_list<uint32_t> shape) : luci::ConstantFoldingAddTestGraph(shape, T)
+  {
+    _mul = _g.nodes()->template create<luci::CircleMul>();
+    _x = _g.nodes()->template create<luci::CircleConst>();
+    _y = _g.nodes()->template create<luci::CircleConst>();
+
+    _mul->dtype(T);
+    _x->dtype(T);
+    _y->dtype(T);
+
+    _mul->shape(shape);
+    _x->shape(shape);
+    _y->shape(shape);
+
+    uint32_t num_elems = 1;
+    for (auto dim = shape.begin(); dim != shape.end(); dim++)
+      num_elems *= *dim;
+
+    _x->size<T>(num_elems);
+    _y->size<T>(num_elems);
+
+    for (uint32_t i = 0; i < num_elems; i++)
+    {
+      _x->at<T>(i) = i + 1;
+      _y->at<T>(i) = i + 1;
+    }
+
+    _mul->x(_x);
+    _mul->y(_y);
+    _mul->name("mul");
+    _x->name("x");
+    _y->name("y");
+  }
+
+  loco::Node *createFoldedPattern() override { return _mul; }
+
+  virtual ~FoldMulTest() = default;
+
+protected:
+  luci::CircleMul *_mul = nullptr;
+  luci::CircleConst *_x = nullptr;
+  luci::CircleConst *_y = nullptr;
+};
+
+class FoldF32MulTest : public FoldMulTest<loco::DataType::FLOAT32>, public ::testing::Test
+{
+public:
+  FoldF32MulTest() : FoldMulTest<loco::DataType::FLOAT32>({3}) {}
+
+  virtual void SetUp() { init(); }
+};
+
+} // namespace
+
+TEST_F(FoldF32MulTest, name)
+{
+  luci::FoldMulPass pass;
+  auto const name = pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST_F(FoldF32MulTest, fold_mul)
+{
+  luci::FoldMulPass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  // Check type, shape, values of folded const
+  EXPECT_EQ(loco::DataType::FLOAT32, folded_const->dtype());
+  EXPECT_EQ(1, folded_const->rank());
+  EXPECT_EQ(3, folded_const->dim(0).value());
+  EXPECT_EQ(1, folded_const->at<loco::DataType::FLOAT32>(0));
+  EXPECT_EQ(4, folded_const->at<loco::DataType::FLOAT32>(1));
+  EXPECT_EQ(9, folded_const->at<loco::DataType::FLOAT32>(2));
+}
+
+TEST_F(FoldF32MulTest, input_type_mismatch_NEG)
+{
+  _x->dtype(loco::DataType::U4);
+
+  luci::FoldMulPass pass;
+  EXPECT_FALSE(pass.run(graph()));
+}
diff --git a/compiler/luci/pass/src/FoldReshapePass.cpp b/compiler/luci/pass/src/FoldReshapePass.cpp
new file mode 100644 (file)
index 0000000..56b19fa
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FoldReshapePass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Service/Nodes/CircleConst.h>
+
+namespace
+{
+
+/**
+ * Fold Reshape to const if it has const input
+ **/
+bool fold_reshape(luci::CircleReshape *reshape)
+{
+  // Check const input
+  auto const_input = dynamic_cast<luci::CircleConst *>(reshape->tensor());
+  if (not const_input)
+    return false;
+
+  // Check const shape
+  auto const_shape = dynamic_cast<luci::CircleConst *>(reshape->shape());
+  if (not const_shape)
+    return false;
+
+  // Check all dimensions are known
+  const auto input_rank = const_input->rank();
+  for (uint32_t i = 0; i < input_rank; i++)
+  {
+    if (not const_input->dim(i).known())
+      return false;
+  }
+
+  // Check all dimensions are known
+  const auto shape_rank = const_shape->rank();
+  if (shape_rank != 1)
+    return false;
+
+  if (not const_shape->dim(0).known())
+    return false;
+
+  std::vector<uint32_t> new_shape;
+  switch (const_shape->dtype())
+  {
+    case loco::DataType::S32:
+      for (uint32_t i = 0; i < const_shape->size<loco::DataType::S32>(); i++)
+      {
+        const auto val = const_shape->at<loco::DataType::S32>(i);
+        if (val < 0)
+          return false;
+
+        new_shape.push_back(static_cast<uint32_t>(val));
+      }
+      break;
+    // TODO Support S64
+    default:
+      return false;
+  }
+
+  if (auto input_qparam = const_input->quantparam())
+  {
+    // Only support per-tensor quantization
+    if (input_qparam->scale.size() != 1)
+      return false;
+
+    if (input_qparam->zerop.size() != 1)
+      return false;
+  }
+
+  auto new_const = luci::clone(const_input);
+  new_const->rank(new_shape.size());
+  for (uint32_t i = 0; i < new_shape.size(); i++)
+  {
+    new_const->dim(i).set(new_shape[i]);
+  }
+
+  new_const->shape_status(luci::ShapeStatus::VALID);
+
+  new_const->name(const_input->name() + "_reshaped");
+  luci::add_origin(
+    new_const, luci::composite_origin({luci::get_origin(reshape), luci::get_origin(const_input)}));
+
+  loco::replace(reshape).with(new_const);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * Constant Folding for Reshape Op
+ **/
+bool FoldReshapePass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto reshape = dynamic_cast<luci::CircleReshape *>(node))
+    {
+      if (fold_reshape(reshape))
+        changed = true;
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FoldReshapePass.test.cpp b/compiler/luci/pass/src/FoldReshapePass.test.cpp
new file mode 100644 (file)
index 0000000..0ae2bce
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FoldReshapePass.h"
+#include "PassTestGraphs.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+std::unique_ptr<luci::CircleQuantParam> gen_qparam(const std::vector<float> &s,
+                                                   const std::vector<int64_t> &zp)
+{
+  auto qparam = std::make_unique<luci::CircleQuantParam>();
+  {
+    for (auto scale : s)
+      qparam->scale.push_back(scale);
+
+    for (auto zerop : zp)
+      qparam->zerop.push_back(zerop);
+  }
+
+  return std::move(qparam);
+}
+
+template <loco::DataType DT> class FoldReshapeTest : public luci::ConstantFoldingAddTestGraph
+{
+public:
+  FoldReshapeTest(std::initializer_list<uint32_t> input_shape,
+                  std::initializer_list<uint32_t> output_shape)
+    : luci::ConstantFoldingAddTestGraph(output_shape, DT)
+  {
+    _reshape = _g.nodes()->template create<luci::CircleReshape>();
+    _x = _g.nodes()->template create<luci::CircleConst>();
+    _shape = _g.nodes()->template create<luci::CircleConst>();
+
+    _reshape->dtype(DT);
+    _x->dtype(DT);
+    _shape->dtype(loco::DataType::S32);
+
+    _reshape->shape(_shape);
+    _x->shape(input_shape);
+    _shape->shape({static_cast<uint32_t>(output_shape.size())});
+
+    uint32_t num_elems = 1;
+    for (auto dim : input_shape)
+      num_elems *= dim;
+
+    _x->size<DT>(num_elems);
+    for (uint32_t i = 0; i < num_elems; i++)
+      _x->at<DT>(i) = i;
+
+    _shape->size<loco::DataType::S32>(output_shape.size());
+    uint32_t i = 0;
+    for (auto dim : output_shape)
+    {
+      _shape->at<loco::DataType::S32>(i++) = static_cast<int32_t>(dim);
+    }
+
+    if (DT == loco::DataType::S16)
+    {
+      _x->quantparam(gen_qparam({1.0}, {0}));
+      _reshape->quantparam(gen_qparam({1.0}, {0}));
+    }
+
+    _reshape->tensor(_x);
+    _reshape->shape(_shape);
+
+    _reshape->name("reshape");
+    _shape->name("shape");
+    _x->name("x");
+  }
+
+  loco::Node *createFoldedPattern() override { return _reshape; }
+
+public:
+  void set_unknown_dim() { _x->dim(0).unset(); }
+  void set_non_per_tensor() { _x->quantparam(gen_qparam({1.0, 2.0}, {0, 0})); }
+
+protected:
+  luci::CircleReshape *_reshape = nullptr;
+  luci::CircleConst *_x = nullptr;
+  luci::CircleConst *_shape = nullptr;
+};
+
+/**
+ *  Graph that has a Reshape Op with constant input
+ *
+ *    BEFORE
+ *
+ *         [CircleConst]
+ *               |
+ *            [Reshape]
+ *
+ *    AFTER
+ *
+ *         [CircleConst]
+ *
+ */
+class FoldFP32ReshapeTest : public FoldReshapeTest<loco::DataType::FLOAT32>, public ::testing::Test
+{
+public:
+  FoldFP32ReshapeTest() : FoldReshapeTest<loco::DataType::FLOAT32>({1, 3}, {3}) {}
+
+  virtual void SetUp() { init(); }
+};
+
+class FoldS16ReshapeTest : public FoldReshapeTest<loco::DataType::S16>, public ::testing::Test
+{
+public:
+  FoldS16ReshapeTest() : FoldReshapeTest<loco::DataType::S16>({1, 3}, {3}) {}
+
+  virtual void SetUp() { init(); }
+};
+
+} // namespace
+
+TEST_F(FoldFP32ReshapeTest, fold_reshape_fp32)
+{
+  luci::FoldReshapePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  // Check type, shape, values of folded const
+  EXPECT_EQ(loco::DataType::FLOAT32, folded_const->dtype());
+  EXPECT_EQ(1, folded_const->rank());
+  EXPECT_EQ(3, folded_const->dim(0).value());
+  EXPECT_EQ(0, folded_const->at<loco::DataType::FLOAT32>(0));
+  EXPECT_EQ(1, folded_const->at<loco::DataType::FLOAT32>(1));
+  EXPECT_EQ(2, folded_const->at<loco::DataType::FLOAT32>(2));
+}
+
+TEST_F(FoldFP32ReshapeTest, fold_reshape_unkown_dim_NEG)
+{
+  set_unknown_dim();
+
+  luci::FoldReshapePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(FoldS16ReshapeTest, fold_reshape_s16)
+{
+  luci::FoldReshapePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  // Check type, shape, values of folded const
+  EXPECT_EQ(loco::DataType::S16, folded_const->dtype());
+  EXPECT_EQ(1, folded_const->rank());
+  EXPECT_EQ(3, folded_const->dim(0).value());
+  EXPECT_EQ(0, folded_const->at<loco::DataType::S16>(0));
+  EXPECT_EQ(1, folded_const->at<loco::DataType::S16>(1));
+  EXPECT_EQ(2, folded_const->at<loco::DataType::S16>(2));
+
+  auto qparam = folded_const->quantparam();
+  EXPECT_NE(nullptr, qparam);
+  EXPECT_EQ(1.0, qparam->scale.at(0));
+  EXPECT_EQ(0, qparam->zerop.at(0));
+}
+
+TEST_F(FoldS16ReshapeTest, fold_non_per_tensor_quant_NEG)
+{
+  set_non_per_tensor();
+
+  luci::FoldReshapePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_EQ(nullptr, folded_const);
+}
diff --git a/compiler/luci/pass/src/FoldShapePass.cpp b/compiler/luci/pass/src/FoldShapePass.cpp
new file mode 100644 (file)
index 0000000..bcf538a
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FoldShapePass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+
+template <loco::DataType OutType> luci::CircleConst *folding(luci::CircleShape *shape)
+{
+  auto input_node = loco::must_cast<luci::CircleNode *>(shape->input());
+  auto name = input_node->name();
+  assert(name.length() > 0);
+  auto shape_status = input_node->shape_status();
+  if (shape_status != luci::ShapeStatus::VALID)
+    return nullptr;
+  auto rank = input_node->rank();
+  // TODO support rank == 0 when possible
+  if (rank == 0)
+    return nullptr;
+  for (uint32_t i = 0; i < rank; i++)
+  {
+    auto dim = input_node->dim(i);
+    if (!dim.known())
+      return nullptr;
+  }
+
+  auto folded_shape = input_node->graph()->nodes()->create<luci::CircleConst>();
+  folded_shape->name(name + "_ConstShape");
+  folded_shape->dtype(OutType);
+  folded_shape->rank(1);
+  folded_shape->dim(0).set(rank);
+  luci::add_origin(folded_shape, luci::get_origin(shape));
+
+  folded_shape->size<OutType>(rank);
+  for (uint32_t i = 0; i < rank; i++)
+    folded_shape->at<OutType>(i) = input_node->dim(i).value();
+
+  return folded_shape;
+}
+
+// Fold Shape to const if the input shape is static
+template <loco::DataType OutType> bool fold_shape(luci::CircleShape *shape)
+{
+  auto folded_shape = folding<OutType>(shape);
+  if (not folded_shape)
+    return false;
+
+  loco::replace(shape).with(folded_shape);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * BEFORE
+ *
+ *     [CircleNode]
+ *           |
+ *     [CircleShape]
+ *           |
+ *     [CircleNode]
+ *
+ * AFTER
+ *
+ *     [CircleConst]  [CircleNode]
+ *           |
+ *     [CircleNode]
+ *
+ */
+bool FoldShapePass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto shape = dynamic_cast<luci::CircleShape *>(node))
+    {
+      auto out_type = shape->out_type();
+      switch (out_type)
+      {
+        case loco::DataType::S32:
+          if (fold_shape<loco::DataType::S32>(shape))
+            changed = true;
+          break;
+        case loco::DataType::S64:
+          if (fold_shape<loco::DataType::S64>(shape))
+            changed = true;
+          break;
+        default:
+          break;
+      }
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FoldShapePass.test.cpp b/compiler/luci/pass/src/FoldShapePass.test.cpp
new file mode 100644 (file)
index 0000000..cece597
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FoldShapePass.h"
+#include "PassTestGraphs.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+template <loco::DataType OutType> class FoldShapeGraph : public luci::ConstantFoldingAddTestGraph
+{
+public:
+  FoldShapeGraph(std::vector<uint32_t> input_shape)
+    : luci::ConstantFoldingAddTestGraph(input_shape, OutType)
+  {
+    _x = _g.nodes()->template create<luci::CircleConst>();
+    _x->name("x");
+    _x->dtype(loco::DataType::S32);
+    _x->rank(input_shape.size());
+    for (uint32_t i = 0; i < input_shape.size(); i++)
+      _x->dim(i).set(input_shape.at(i));
+    _x->shape_status(luci::ShapeStatus::VALID);
+
+    _shape = _g.nodes()->template create<luci::CircleShape>();
+    _shape->name("shape");
+    _shape->out_type(OutType);
+    _shape->input(_x);
+    _shape->shape({4});
+    _shape->rank(1);
+    _shape->dim(0).set(4);
+  }
+
+  loco::Node *createFoldedPattern() override { return _shape; }
+
+protected:
+  luci::CircleShape *_shape = nullptr;
+  luci::CircleConst *_x = nullptr;
+};
+
+/**
+ *  Graph that has a Shape Op
+ *
+ *    BEFORE
+ *
+ *                     [CircleConst]
+ *                           |
+ *    [CircleInput]    [CircleShape]
+ *              \       /
+ *             [CircleAdd]
+ *                  |
+ *            [CircleOutput]
+ *
+ *    AFTER
+ *
+ *    [CircleInput]    [CircleConst]
+ *              \       /
+ *             [CircleAdd]
+ *                  |
+ *            [CircleOutput]
+ *
+ */
+class FoldShapePassGraphTest : public FoldShapeGraph<loco::DataType::S32>, public ::testing::Test
+{
+public:
+  FoldShapePassGraphTest() : FoldShapeGraph<loco::DataType::S32>({1, 8, 8, 64}) {}
+
+  virtual void SetUp() { init(); }
+};
+
+} // namespace
+
+TEST(FoldShapePassTest, name)
+{
+  luci::FoldShapePass pass;
+  auto const name = pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST_F(FoldShapePassGraphTest, fold_shape)
+{
+  luci::FoldShapePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  // Check type, shape, values of folded shape
+  EXPECT_EQ(loco::DataType::S32, folded_const->dtype());
+  EXPECT_EQ(1, folded_const->rank());
+  EXPECT_EQ(4, folded_const->dim(0).value());
+  EXPECT_EQ(1, folded_const->at<loco::DataType::S32>(0));
+  EXPECT_EQ(8, folded_const->at<loco::DataType::S32>(1));
+  EXPECT_EQ(8, folded_const->at<loco::DataType::S32>(2));
+  EXPECT_EQ(64, folded_const->at<loco::DataType::S32>(3));
+}
+
+TEST_F(FoldShapePassGraphTest, undefined_shape_NEG)
+{
+  _x->shape_status(luci::ShapeStatus::UNDEFINED);
+
+  luci::FoldShapePass pass;
+  EXPECT_FALSE(pass.run(graph()));
+}
+
+TEST_F(FoldShapePassGraphTest, unallowed_rank_NEG)
+{
+  _x->rank(0);
+
+  luci::FoldShapePass pass;
+  EXPECT_FALSE(pass.run(graph()));
+}
+
+TEST_F(FoldShapePassGraphTest, unknown_dimension_NEG)
+{
+  _x->dim(0).unset();
+
+  luci::FoldShapePass pass;
+  EXPECT_FALSE(pass.run(graph()));
+}
index ed60d88..0dbc09a 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include "luci/Pass/FoldSparseToDensePass.h"
-#include "CircleOptimizerUtils.h"
 
 #include <luci/IR/CircleNodes.h>
 
diff --git a/compiler/luci/pass/src/FoldSqueezePass.cpp b/compiler/luci/pass/src/FoldSqueezePass.cpp
new file mode 100644 (file)
index 0000000..1ec2f83
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FoldSqueezePass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Service/Nodes/CircleConst.h>
+
+namespace
+{
+
+/**
+ * Fold Squeeze to const if it has const input
+ **/
+bool fold_squeeze(luci::CircleSqueeze *squeeze)
+{
+  // Check squeeze has const input
+  auto const_input = dynamic_cast<luci::CircleConst *>(squeeze->input());
+  if (not const_input)
+    return false;
+
+  // Check all dimensions are known
+  const auto input_rank = const_input->rank();
+  for (uint32_t i = 0; i < input_rank; i++)
+  {
+    if (not const_input->dim(i).known())
+      return false;
+  }
+
+  const auto squeeze_dims = squeeze->squeeze_dims();
+  uint32_t num_squeeze_dims = squeeze_dims.size();
+  std::vector<bool> should_squeeze(input_rank, false);
+  uint32_t num_squeezed_dims = 0;
+
+  // Squeeze all dimensions whose value is 1
+  if (num_squeeze_dims == 0)
+  {
+    for (uint32_t idx = 0; idx < input_rank; ++idx)
+    {
+      if (const_input->dim(idx).value() == 1)
+      {
+        should_squeeze.at(idx) = true;
+        ++num_squeezed_dims;
+      }
+    }
+  }
+  else
+  {
+    for (uint32_t idx = 0; idx < num_squeeze_dims; ++idx)
+    {
+      const int32_t current =
+        squeeze_dims.at(idx) < 0 ? squeeze_dims.at(idx) + input_rank : squeeze_dims.at(idx);
+      assert(current >= 0);
+      assert(current < static_cast<int32_t>(input_rank));
+      assert(const_input->dim(current).value() == 1);
+
+      if (not should_squeeze[current])
+        ++num_squeezed_dims;
+      should_squeeze[current] = true;
+    }
+  }
+
+  auto new_const = luci::clone(const_input);
+  new_const->rank(input_rank - num_squeezed_dims);
+  for (uint32_t in_idx = 0, out_idx = 0; in_idx < input_rank; ++in_idx)
+  {
+    if (should_squeeze.at(in_idx))
+      continue;
+
+    new_const->dim(out_idx++) = const_input->dim(in_idx);
+  }
+
+  new_const->shape_status(luci::ShapeStatus::VALID);
+
+  new_const->name(const_input->name() + "_squeezed");
+  luci::add_origin(
+    new_const, luci::composite_origin({luci::get_origin(squeeze), luci::get_origin(const_input)}));
+
+  loco::replace(squeeze).with(new_const);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * Constant Folding for Squeeze Op
+ **/
+bool FoldSqueezePass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto squeeze = dynamic_cast<luci::CircleSqueeze *>(node))
+    {
+      if (fold_squeeze(squeeze))
+        changed = true;
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FoldSqueezePass.test.cpp b/compiler/luci/pass/src/FoldSqueezePass.test.cpp
new file mode 100644 (file)
index 0000000..b7c6efe
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FoldSqueezePass.h"
+#include "PassTestGraphs.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+template <loco::DataType DT> class FoldSqueezeTest : public luci::ConstantFoldingAddTestGraph
+{
+public:
+  FoldSqueezeTest(std::initializer_list<uint32_t> input_shape,
+                  std::initializer_list<uint32_t> output_shape)
+    : luci::ConstantFoldingAddTestGraph(output_shape, DT)
+  {
+    _squeeze = _g.nodes()->template create<luci::CircleSqueeze>();
+    _x = _g.nodes()->template create<luci::CircleConst>();
+
+    _squeeze->dtype(DT);
+    _x->dtype(DT);
+
+    _squeeze->shape(output_shape);
+    _x->shape(input_shape);
+
+    _squeeze->squeeze_dims({0});
+
+    uint32_t num_elems = 1;
+    for (auto dim = input_shape.begin(); dim != input_shape.end(); dim++)
+      num_elems *= *dim;
+
+    _x->size<DT>(num_elems);
+    for (uint32_t i = 0; i < num_elems; i++)
+      _x->at<DT>(i) = i;
+
+    _squeeze->input(_x);
+
+    _squeeze->name("squeeze");
+    _x->name("x");
+  }
+
+  loco::Node *createFoldedPattern() override { return _squeeze; }
+
+public:
+  void set_unknown_dim() { _x->dim(0).unset(); }
+
+protected:
+  luci::CircleSqueeze *_squeeze = nullptr;
+  luci::CircleConst *_x = nullptr;
+};
+
+/**
+ *  Graph that has a Squeeze Op with constant input
+ *
+ *    BEFORE
+ *
+ *         [CircleConst]
+ *               |
+ *            [Squeeze]
+ *
+ *    AFTER
+ *
+ *         [CircleConst]
+ *
+ */
+class FoldFP32SqueezeTest : public FoldSqueezeTest<loco::DataType::FLOAT32>, public ::testing::Test
+{
+public:
+  FoldFP32SqueezeTest() : FoldSqueezeTest<loco::DataType::FLOAT32>({1, 3}, {3}) {}
+
+  virtual void SetUp() { init(); }
+};
+
+class FoldS16SqueezeTest : public FoldSqueezeTest<loco::DataType::S16>, public ::testing::Test
+{
+public:
+  FoldS16SqueezeTest() : FoldSqueezeTest<loco::DataType::S16>({1, 3}, {3}) {}
+
+  virtual void SetUp() { init(); }
+};
+
+} // namespace
+
+TEST_F(FoldFP32SqueezeTest, fold_squeeze_fp32)
+{
+  luci::FoldSqueezePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  // Check type, shape, values of folded const
+  EXPECT_EQ(loco::DataType::FLOAT32, folded_const->dtype());
+  EXPECT_EQ(1, folded_const->rank());
+  EXPECT_EQ(3, folded_const->dim(0).value());
+  EXPECT_EQ(0, folded_const->at<loco::DataType::FLOAT32>(0));
+  EXPECT_EQ(1, folded_const->at<loco::DataType::FLOAT32>(1));
+  EXPECT_EQ(2, folded_const->at<loco::DataType::FLOAT32>(2));
+}
+
+TEST_F(FoldFP32SqueezeTest, fold_squeeze_unkown_dim_NEG)
+{
+  set_unknown_dim();
+
+  luci::FoldSqueezePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(FoldS16SqueezeTest, fold_squeeze_s16)
+{
+  luci::FoldSqueezePass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  // Check type, shape, values of folded const
+  EXPECT_EQ(loco::DataType::S16, folded_const->dtype());
+  EXPECT_EQ(1, folded_const->rank());
+  EXPECT_EQ(3, folded_const->dim(0).value());
+  EXPECT_EQ(0, folded_const->at<loco::DataType::S16>(0));
+  EXPECT_EQ(1, folded_const->at<loco::DataType::S16>(1));
+  EXPECT_EQ(2, folded_const->at<loco::DataType::S16>(2));
+}
index 3494a6e..21ac7ad 100644 (file)
@@ -16,6 +16,8 @@
 
 #include "luci/Pass/ForwardReshapeToUnaryOpPass.h"
 
+#include "helpers/NodeFiller.h"
+
 #include <luci/IR/CircleNodes.h>
 #include <luci/IR/CircleNodeVisitor.h>
 #include <luci/Log.h>
@@ -76,6 +78,34 @@ luci::CircleReshape *create_cloned_reshape(luci::CircleReshape *reshape)
   return new_reshape;
 }
 
+bool forward_reshape(luci::CircleReshape *reshape, luci::CircleMean *mean, uint32_t axis)
+{
+  assert(reshape != nullptr); // FIX_CALLER_UNLESS
+  assert(mean != nullptr);    // FIX_CALLER_UNLESS
+
+  auto new_reshape = create_cloned_reshape(reshape);
+  if (not new_reshape)
+    return false;
+
+  // reconnect network
+  loco::replace(mean).with(new_reshape);
+  mean->input(reshape->tensor());
+  new_reshape->tensor(mean);
+
+  // Change const shape axis value
+  auto *shape_reshape = loco::must_cast<luci::CircleConst *>(new_reshape->shape());
+  assert(shape_reshape->dtype() == loco::DataType::S32);     // FIX_CALLER_UNLESS
+  assert(axis < shape_reshape->size<loco::DataType::S32>()); // FIX_CALLER_UNLESS
+  // Mean reduction will make value to '1'
+  shape_reshape->at<loco::DataType::S32>(axis) = 1;
+
+  // Do shape inference for this node again.
+  mean->shape_status(luci::ShapeStatus::UNDEFINED);
+  reshape->shape_status(luci::ShapeStatus::UNDEFINED);
+
+  return true;
+}
+
 bool forward_reshape(luci::CircleReshape *reshape, luci::CircleAbs *abs)
 {
   assert(reshape != nullptr); // FIX_CALLER_UNLESS
@@ -146,6 +176,64 @@ bool forward_reshape(luci::CircleReshape *reshape, luci::CircleLogistic *logit)
   return true;
 }
 
+bool forward_reshape(luci::CircleReshape *reshape, luci::CircleMul *div,
+                     luci::CircleConst *const_value)
+{
+  assert(reshape != nullptr); // FIX_CALLER_UNLESS
+  assert(div != nullptr);     // FIX_CALLER_UNLESS
+
+  auto new_reshape = create_cloned_reshape(reshape);
+  if (not new_reshape)
+    return false;
+
+  // reconnect network
+  loco::replace(div).with(new_reshape);
+  if (div->x() == const_value)
+  {
+    div->y(reshape->tensor());
+  }
+  else
+  {
+    assert(div->y() == const_value);
+    div->x(reshape->tensor());
+  }
+  new_reshape->tensor(div);
+
+  // Do shape inference for this node again.
+  div->shape_status(luci::ShapeStatus::UNDEFINED);
+
+  return true;
+}
+
+bool forward_reshape(luci::CircleReshape *reshape, luci::CircleDiv *div,
+                     luci::CircleConst *const_value)
+{
+  assert(reshape != nullptr); // FIX_CALLER_UNLESS
+  assert(div != nullptr);     // FIX_CALLER_UNLESS
+
+  auto new_reshape = create_cloned_reshape(reshape);
+  if (not new_reshape)
+    return false;
+
+  // reconnect network
+  loco::replace(div).with(new_reshape);
+  if (div->x() == const_value)
+  {
+    div->y(reshape->tensor());
+  }
+  else
+  {
+    assert(div->y() == const_value);
+    div->x(reshape->tensor());
+  }
+  new_reshape->tensor(div);
+
+  // Do shape inference for this node again.
+  div->shape_status(luci::ShapeStatus::UNDEFINED);
+
+  return true;
+}
+
 class ForwardReshape final : public luci::CircleNodeMutableVisitor<bool>
 {
 protected:
@@ -156,6 +244,81 @@ protected:
     return false;
   }
 
+  /**
+   * Graph example:
+   *
+   *  BEFORE
+   *               [Input]
+   *              (3, 4, 4)                 [Shape_Const = (1, -1, 4)]
+   *                  |                     |
+   *              [Reshape] ----------------
+   *              (1, 12, 4)
+   *                  |
+   *        [Mean, keep_dims = true]
+   *              (1, 12, 1)
+   *                  |
+   *               [Output]
+   *
+   *  AFTER
+   *               [Input]
+   *              (3, 4, 4)
+   *                  |
+   *         [Mean, keep_dims = true]
+   *              (3, 4, 1)                 [Shape_Const = (1, -1, 1)]
+   *                  |                     |
+   *              [Reshape]-----------------
+   *              (1, 12, 1)
+   *                  |
+   *              [Output]
+   *
+   */
+  bool visit(luci::CircleMean *node)
+  {
+    luci::CircleReshape *reshape = nullptr;
+    luci::CircleConst *axis = nullptr;
+
+    reshape = dynamic_cast<luci::CircleReshape *>(node->input());
+    axis = dynamic_cast<luci::CircleConst *>(node->reduction_indices());
+
+    if (reshape == nullptr or axis == nullptr)
+      return false;
+
+    if (axis->dtype() != loco::DataType::S32)
+      return false;
+
+    // Should be scalar
+    if (axis->size<loco::DataType::S32>() != 1)
+      return false;
+
+    // axis value
+    auto axis_value = axis->at<loco::DataType::S32>(0);
+
+    if (axis_value < 0)
+      axis_value += static_cast<int32_t>(reshape->rank());
+
+    assert(axis_value >= 0);
+
+    if (node->keep_dims() != true)
+      return false;
+
+    auto reshape_input = loco::must_cast<luci::CircleNode *>(reshape->tensor());
+
+    // reshape shouldn't change rank
+    if (reshape_input->rank() != reshape->rank())
+      return false;
+
+    assert(reshape_input->rank() > static_cast<uint32_t>(axis_value));
+
+    for (int32_t i = 0; i <= axis_value; ++i)
+    {
+      if (not reshape_input->dim(i).known() or
+          reshape_input->dim(i).value() != reshape->dim(i).value())
+        return false;
+    }
+
+    return forward_reshape(reshape, node, axis_value);
+  }
+
   bool visit(luci::CircleAbs *node)
   {
     auto reshape = as_reshape(node->x());
@@ -180,6 +343,43 @@ protected:
 
     return forward_reshape(reshape, node);
   }
+
+  bool visit(luci::CircleDiv *node)
+  {
+    luci::CircleReshape *reshape = nullptr;
+    luci::CircleConst *const_value = nullptr;
+
+    if (not luci::fill(&reshape, &const_value).with_commutative_args_of(node))
+      return false;
+
+    if (const_value->dtype() != loco::DataType::FLOAT32)
+      return false;
+
+    // Should be scalar
+    if (const_value->size<loco::DataType::FLOAT32>() != 1)
+      return false;
+
+    return forward_reshape(reshape, node, const_value);
+  }
+
+  bool visit(luci::CircleMul *node)
+  {
+    luci::CircleReshape *reshape = nullptr;
+    luci::CircleConst *const_value = nullptr;
+
+    if (not luci::fill(&reshape, &const_value).with_commutative_args_of(node))
+      return false;
+
+    if (const_value->dtype() != loco::DataType::FLOAT32)
+      return false;
+
+    // Should be scalar
+    if (const_value->size<loco::DataType::FLOAT32>() != 1)
+      return false;
+
+    return forward_reshape(reshape, node, const_value);
+  }
+
   // TODO add more unary operators
 };
 
@@ -201,6 +401,11 @@ namespace luci
  *          |            |           |
  *
  *   UnaryOp: CircleNeg, ...
+ *   Note: Binary Op (Div, Mul) can also be considered as a unary operation
+ *         if one of its inputs is a constant.
+ *         For CircleMean in which the axis is a scalar
+ *         constant and reshape Op does not change the axis on which the mean is
+ *         taken, the Reshape Op can be forwarded.
  *
  * AFTER
  *                       |
index 3735132..ae89e4f 100644 (file)
@@ -173,6 +173,114 @@ protected:
   luci::ForwardReshapeToUnaryOpPass _pass;
 };
 
+/**
+ *  Simple graph for test
+ *
+ *  BEFORE
+ *               [Input]
+ *              (3, 4, 4)                 [Shape_Const = (1, -1, 4)]
+ *                  |                     |
+ *              [Reshape] ----------------
+ *              (1, 12, 4)
+ *                  |
+ *        [Mean, keep_dims = true]
+ *              (1, 12, 1)
+ *                  |
+ *               [Output]
+ *
+ *  AFTER
+ *               [Input]
+ *              (3, 4, 4)
+ *                  |
+ *         [Mean, keep_dims = true]
+ *              (3, 4, 1)                 [Shape_Const = (1, -1, 1)]
+ *                  |                     |
+ *              [Reshape]-----------------
+ *              (1, 12, 1)
+ *                  |
+ *              [Output]
+ *
+ */
+class PatternReshapeMeanGraphlet
+{
+public:
+  PatternReshapeMeanGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    _mean = g->nodes()->create<luci::CircleMean>();
+    _mean_const = g->nodes()->create<luci::CircleConst>();
+    _reshape = g->nodes()->create<luci::CircleReshape>();
+    _reshape_const = g->nodes()->create<luci::CircleConst>();
+
+    _mean->name("_mean");
+    _mean_const->name("_mean_const");
+    _reshape->name("_reshape");
+    _reshape_const->name("_reshape_const");
+  }
+
+public:
+  luci::CircleMean *mean() { return _mean; }
+  luci::CircleConst *mean_const() { return _mean_const; }
+  luci::CircleReshape *reshape() { return _reshape; }
+  luci::CircleConst *reshape_const() { return _reshape_const; }
+
+protected:
+  luci::CircleMean *_mean = nullptr;
+  luci::CircleConst *_mean_const = nullptr;
+  luci::CircleReshape *_reshape = nullptr;
+  luci::CircleConst *_reshape_const = nullptr;
+};
+
+class ForwardReshapeToMeanPatternTestGraph : public TestIOGraph, public PatternReshapeMeanGraphlet
+{
+public:
+  ForwardReshapeToMeanPatternTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({3, 4, 4}, {3, 4, 4});
+    PatternReshapeMeanGraphlet::init(g());
+
+    _reshape_const->rank(1);
+    _reshape_const->dtype(loco::DataType::S32);
+    _reshape_const->size<loco::DataType::S32>(3);
+    _reshape_const->at<loco::DataType::S32>(0) = 1;
+    _reshape_const->at<loco::DataType::S32>(1) = -1;
+    _reshape_const->at<loco::DataType::S32>(2) = 4;
+    _reshape_const->shape_status(luci::ShapeStatus::VALID);
+
+    _reshape->rank(3);
+    _reshape->dim(0).set(3);
+    _reshape->dim(1).set(4);
+    _reshape->dim(2).set(4);
+    _reshape->dtype(loco::DataType::FLOAT32);
+    _reshape->shape_status(luci::ShapeStatus::VALID);
+    _reshape->tensor(input());
+    _reshape->shape(_reshape_const);
+
+    _mean_const->rank(1);
+    _mean_const->dtype(loco::DataType::S32);
+    _mean_const->size<loco::DataType::S32>(1);
+    _mean_const->at<loco::DataType::S32>(0) = -1;
+    _mean_const->shape_status(luci::ShapeStatus::VALID);
+
+    _mean->rank(3);
+    _mean->dim(0).set(1);
+    _mean->dim(1).set(12);
+    _mean->dim(2).set(1);
+    _mean->dtype(loco::DataType::FLOAT32);
+    _mean->shape_status(luci::ShapeStatus::VALID);
+    _mean->input(_reshape);
+    _mean->reduction_indices(_mean_const);
+    _mean->keep_dims(true);
+
+    output()->from(_mean);
+  }
+
+  void invalid_type() { _mean_const->dtype(loco::DataType::FLOAT32); }
+};
+
 } // namespace
 
 TEST(ForwardReshapeToUnaryOpPassTest, name)
@@ -209,3 +317,25 @@ TEST_F(ForwardReshapeToLogisticGraphTest, forward)
   log = dynamic_cast<luci::CircleLogistic *>(reshape->tensor());
   ASSERT_NE(nullptr, log);
 }
+
+TEST(FuseMulWithDivPassTest, forward_reshape_to_mean_pattern)
+{
+  ForwardReshapeToMeanPatternTestGraph g;
+  luci::ForwardReshapeToUnaryOpPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(FuseMulWithDivPassTest, forward_reshape_to_mean_pattern_NEG)
+{
+  ForwardReshapeToMeanPatternTestGraph g;
+  luci::ForwardReshapeToUnaryOpPass pass;
+
+  g.init();
+
+  g.invalid_type();
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
index c76d733..b9f7ae5 100644 (file)
@@ -164,6 +164,7 @@ private:
     {
       if (auto y = dynamic_cast<luci::CircleTranspose *>(node->y()))
       {
+        RETURN_FALSE_UNLESS(node->rank() == y->rank());
         RETURN_FALSE_UNLESS(check_rank_four(x));
         RETURN_FALSE_UNLESS(check_perm(y));
 
@@ -190,6 +191,7 @@ private:
     {
       if (auto x = dynamic_cast<luci::CircleTranspose *>(node->x()))
       {
+        RETURN_FALSE_UNLESS(node->rank() == x->rank());
         RETURN_FALSE_UNLESS(check_rank_four(y));
         RETURN_FALSE_UNLESS(check_perm(x));
 
@@ -289,6 +291,8 @@ public:
   bool visit(luci::CircleNode *) { return false; }
 
   bool visit(luci::CircleAbs *node) { return has_pattern_x(node); }
+
+  bool visit(luci::CircleLogistic *node) { return has_pattern_x(node); }
 };
 
 } // namespace
diff --git a/compiler/luci/pass/src/FuseAddToFullyConnectedBiasPass.cpp b/compiler/luci/pass/src/FuseAddToFullyConnectedBiasPass.cpp
new file mode 100644 (file)
index 0000000..297a345
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseAddToFullyConnectedBiasPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+#include "helpers/NodeFiller.h"
+
+#define CHECK_OR_FALSE(condition) \
+  if (not(condition))             \
+    return false;
+
+namespace
+{
+
+/**
+ *  Fuse Add to following FullyConnected bias if possible
+ *
+ *  BEFORE
+ *                |
+ *           [CircleAdd] [CircleConst] [CircleConst]
+ *                |       |              |
+ *      [CircleFullyConnected] ----------+
+ *                |
+ *
+ *  AFTER
+ *                |
+ *                |        [CircleConst] [CircleConst] [CircleConst]
+ *                |                   |       |         |
+ *                |   [CircleConst] [CircleFullyConnected]   [CircleAdd]
+ *                |       |           |
+ *       [CircleFullyConnected] ------+
+ *                |
+ *
+ */
+bool fuse_add_to_fc_bias(luci::CircleFullyConnected *fc)
+{
+  CHECK_OR_FALSE(fc);
+
+  // check input is Add
+  auto add = dynamic_cast<luci::CircleAdd *>(fc->input());
+  CHECK_OR_FALSE(add);
+  // conditions of Add, FC: to expect constant folding, support only F32
+  CHECK_OR_FALSE(add->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(add->fusedActivationFunction() == luci::FusedActFunc::NONE);
+  CHECK_OR_FALSE(fc->dtype() == loco::DataType::FLOAT32);
+  // support weight with constant
+  auto weights = dynamic_cast<luci::CircleConst *>(fc->weights());
+  CHECK_OR_FALSE(weights);
+  // bias can be constant or outputexclude
+  auto bias = dynamic_cast<luci::CircleNode *>(fc->bias());
+  CHECK_OR_FALSE(bias);
+
+  // Check addition of Add is constant
+  luci::CircleNode *add_input = nullptr;
+  luci::CircleConst *add_shift = nullptr;
+  CHECK_OR_FALSE(luci::fill(&add_input, &add_shift).with_commutative_args_of(add));
+  // support only 1D constant
+  CHECK_OR_FALSE(add_shift->rank() == 1);
+
+  auto graph = fc->graph();
+
+  auto fc_bias = graph->nodes()->create<luci::CircleFullyConnected>();
+  fc_bias->input(add_shift);
+  fc_bias->weights(weights);
+  fc_bias->bias(bias);
+  fc_bias->keep_num_dims(true);
+  fc_bias->fusedActivationFunction(luci::FusedActFunc::NONE);
+  fc_bias->name(fc->name() + "_" + add->name() + "_bias");
+  luci::add_origin(fc_bias,
+                   luci::composite_origin(
+                     {luci::get_origin(add), luci::get_origin(add_shift), luci::get_origin(bias)}));
+
+  auto fc_new = graph->nodes()->create<luci::CircleFullyConnected>();
+  fc_new->input(add_input);
+  fc_new->weights(weights);
+  fc_new->bias(fc_bias);
+  fc_new->weights_format(fc->weights_format());
+  fc_new->keep_num_dims(fc->keep_num_dims());
+  fc_new->fusedActivationFunction(fc->fusedActivationFunction());
+  fc_new->name(fc->name());
+  luci::add_origin(fc_new, luci::get_origin(fc));
+
+  replace(fc).with(fc_new);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool FuseAddToFullyConnectedBiasPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto fc = dynamic_cast<luci::CircleFullyConnected *>(node);
+    if (not fc)
+      continue;
+
+    if (fuse_add_to_fc_bias(fc))
+      changed = true;
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseAddToFullyConnectedBiasPass.test.cpp b/compiler/luci/pass/src/FuseAddToFullyConnectedBiasPass.test.cpp
new file mode 100644 (file)
index 0000000..445ba4b
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseAddToFullyConnectedBiasPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+template <loco::DataType DT> class FuseAddToFullyConnectedBiasPassTestGraph : public TestIOGraph
+{
+public:
+  FuseAddToFullyConnectedBiasPassTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({3, 4}, {3, 6});
+
+    _add = g()->nodes()->create<luci::CircleAdd>();
+    _add_s = g()->nodes()->create<luci::CircleConst>();
+    _fc = g()->nodes()->create<luci::CircleFullyConnected>();
+    _fc_w = g()->nodes()->create<luci::CircleConst>();
+    _fc_b = g()->nodes()->create<luci::CircleConst>();
+
+    _add->name("add");
+    _add_s->name("add_s");
+    _fc->name("fc");
+    _fc_w->name("fc_w");
+    _fc_b->name("fc_b");
+
+    _add->dtype(DT);
+    _fc->dtype(DT);
+    _add->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _fc->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+    _add_s->rank(1);
+    _add_s->dim(0) = 3;
+    _add_s->dtype(DT);
+    _add_s->size<DT>(3);
+    for (uint32_t i = 0; i < 3; ++i)
+    {
+      _add_s->at<DT>(0) = 1.0f;
+    }
+
+    _fc_w->rank(2);
+    _fc_w->dim(0) = 3;
+    _fc_w->dim(1) = 4;
+    _fc_w->dtype(DT);
+    _fc_w->size<DT>(4 * 6);
+    for (uint32_t i = 0; i < 4 * 6; ++i)
+    {
+      _fc_w->at<DT>(0) = 1.0f;
+    }
+
+    _fc_b->rank(1);
+    _fc_b->dim(0) = 6;
+    _fc_b->dtype(DT);
+    _fc_b->size<DT>(6);
+    for (uint32_t i = 0; i < 6; ++i)
+    {
+      _fc_b->at<DT>(0) = 1.0f;
+    }
+
+    _add->x(input());
+    _add->y(_add_s);
+    _fc->input(_add);
+    _fc->weights(_fc_b);
+    _fc->bias(_fc_b);
+
+    output()->from(_fc);
+  }
+
+  luci::CircleAdd *_add = nullptr;
+  luci::CircleFullyConnected *_fc = nullptr;
+  luci::CircleConst *_add_s = nullptr;
+  luci::CircleConst *_fc_w = nullptr;
+  luci::CircleConst *_fc_b = nullptr;
+};
+
+class FuseAddToFullyConnectedBiasPassTest : public ::testing::Test
+{
+public:
+  FuseAddToFullyConnectedBiasPassTest() = default;
+
+protected:
+  FuseAddToFullyConnectedBiasPassTestGraph<loco::DataType::FLOAT32> _graph;
+  luci::FuseAddToFullyConnectedBiasPass _pass;
+};
+
+class FuseAddToFullyConnectedBiasPassS32Test : public ::testing::Test
+{
+public:
+  FuseAddToFullyConnectedBiasPassS32Test() = default;
+
+protected:
+  FuseAddToFullyConnectedBiasPassTestGraph<loco::DataType::S32> _graph;
+  luci::FuseAddToFullyConnectedBiasPass _pass;
+};
+
+} // namespace
+
+TEST_F(FuseAddToFullyConnectedBiasPassTest, name)
+{
+  auto const name = _pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST_F(FuseAddToFullyConnectedBiasPassTest, fuse_add_to_fc_bias)
+{
+  _graph.init();
+
+  EXPECT_TRUE(_pass.run(_graph.g()));
+}
+
+TEST_F(FuseAddToFullyConnectedBiasPassTest, add_fused_act_NEG)
+{
+  _graph.init();
+
+  _graph._add->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+  EXPECT_FALSE(_pass.run(_graph.g()));
+}
+
+TEST_F(FuseAddToFullyConnectedBiasPassTest, add_d2_NEG)
+{
+  _graph.init();
+
+  _graph._add_s->rank(2);
+  _graph._add_s->dim(0) = 1;
+  _graph._add_s->dim(1) = 3;
+
+  EXPECT_FALSE(_pass.run(_graph.g()));
+}
+
+TEST_F(FuseAddToFullyConnectedBiasPassS32Test, dtype_s32_NEG)
+{
+  _graph.init();
+
+  EXPECT_FALSE(_pass.run(_graph.g()));
+}
diff --git a/compiler/luci/pass/src/FuseAddWithConvPass.cpp b/compiler/luci/pass/src/FuseAddWithConvPass.cpp
new file mode 100644 (file)
index 0000000..f6c1e57
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseAddWithConvPass.h"
+
+#include "helpers/NodeFiller.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+/**
+ *  Fuse Add to Conv2D if possible.
+ *
+ *  BEFORE
+ *                  |   [CircleConst]
+ *                  |  / [CircleConst]
+ *                  | / /
+ *         [CircleConv2D] [CircleConst]
+ *                  |    /
+ *             [CircleAdd]
+ *                  |
+ *
+ *  AFTER
+ *                  |                  [CircleConst]
+ *                  +--------------+  / [CircleConst]
+ *                  |              | / /
+ *                  |     [CircleConv2D] [CircleConst]
+ *  [CircleConst]   |              |    /
+ * [CircleConst] \  |         [CircleAdd]
+ *              \ \ |
+ *           [CircleConv2D]
+ *                  |
+ */
+bool fused_add_with_conv(luci::CircleAdd *add)
+{
+  // find the pattern of CircleAdd(CircleConv2D, CircleConst)
+  luci::CircleConst *shift = nullptr;
+  luci::CircleConv2D *conv2d = nullptr;
+  if (not luci::fill(&conv2d, &shift).with_commutative_args_of(add))
+    return false;
+
+  // check conditions for conv2d
+  if (conv2d->rank() != 4)
+    return false;
+  if (conv2d->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return false;
+
+  luci::CircleConst *filter = dynamic_cast<luci::CircleConst *>(conv2d->filter());
+  luci::CircleConst *bias = dynamic_cast<luci::CircleConst *>(conv2d->bias());
+  luci::CircleOutputExclude *biasex = dynamic_cast<luci::CircleOutputExclude *>(conv2d->bias());
+
+  // filter should exist, bias should be const or none(output exclude)
+  if (filter == nullptr || (bias == nullptr && biasex == nullptr))
+    return false;
+  if (filter->rank() != 4)
+    return false;
+  if (filter->dtype() != shift->dtype())
+    return false;
+  // TODO support more data type
+  if (filter->dtype() != loco::DataType::FLOAT32)
+    return false;
+
+  // filter is OHWI
+  uint32_t out_channel = filter->dim(0).value();
+
+  // shape of shift should be [1, 1, 1, out_channel] or [out_channel]
+  if (shift->rank() == 4)
+  {
+    for (uint32_t i = 0; i < 3; ++i)
+      if (shift->dim(i).value() != 1)
+        return false;
+    if (shift->dim(3).value() != out_channel)
+      return false;
+  }
+  else if (shift->rank() == 1)
+  {
+    if (shift->dim(0).value() != out_channel)
+      return false;
+  }
+  else
+    return false;
+
+  auto conv2d_name = conv2d->name();
+  auto shift_name = shift->name();
+  assert(conv2d_name.length() > 0);
+  assert(shift_name.length() > 0);
+  auto bias_name = (bias ? bias->name() : conv2d_name) + ";" + shift_name;
+
+  luci::CircleConv2D *fused_conv2d = add->graph()->nodes()->create<luci::CircleConv2D>();
+  luci::CircleConst *fused_bias = add->graph()->nodes()->create<luci::CircleConst>();
+
+  fused_bias->dtype(conv2d->dtype());
+  fused_bias->rank(1);
+  fused_bias->dim(0).set(out_channel);
+  fused_bias->shape_status(luci::ShapeStatus::VALID);
+  fused_bias->name(bias_name);
+  fused_bias->size<loco::DataType::FLOAT32>(out_channel);
+  // fuse shift to bias
+  for (uint32_t b = 0; b < out_channel; ++b)
+  {
+    auto bias_val = shift->at<loco::DataType::FLOAT32>(b);
+    if (bias)
+      bias_val += bias->at<loco::DataType::FLOAT32>(b);
+    fused_bias->at<loco::DataType::FLOAT32>(b) = bias_val;
+  }
+
+  // Set attributes of fused_conv2d
+  fused_conv2d->input(conv2d->input());
+  fused_conv2d->filter(conv2d->filter());
+  fused_conv2d->bias(fused_bias);
+  fused_conv2d->fusedActivationFunction(add->fusedActivationFunction());
+  fused_conv2d->padding(conv2d->padding());
+  fused_conv2d->stride()->h(conv2d->stride()->h());
+  fused_conv2d->stride()->w(conv2d->stride()->w());
+  fused_conv2d->dilation()->h(conv2d->dilation()->h());
+  fused_conv2d->dilation()->w(conv2d->dilation()->w());
+  fused_conv2d->name(conv2d_name);
+  luci::add_origin(fused_conv2d,
+                   luci::composite_origin({luci::get_origin(add), luci::get_origin(conv2d)}));
+
+  replace(add).with(fused_conv2d);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool FuseAddWithConvPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto add = dynamic_cast<luci::CircleAdd *>(node))
+    {
+      if (fused_add_with_conv(add))
+        changed = true;
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseAddWithConvPass.test.cpp b/compiler/luci/pass/src/FuseAddWithConvPass.test.cpp
new file mode 100644 (file)
index 0000000..c64b457
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseAddWithConvPass.h"
+
+#include "helpers/CreateCircleConst.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+using namespace luci::test;
+
+namespace
+{
+
+#define FILTER_O 4
+#define FILTER_H 1
+#define FILTER_W 1
+#define FILTER_I 6
+
+class Conv2DAddGraphlet
+{
+public:
+  Conv2DAddGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    const ShapeU32 filter_shape = {FILTER_O, FILTER_H, FILTER_W, FILTER_I};
+    const ShapeU32 bias_shape = {FILTER_O};
+
+    _conv_f = luci::create_const_node(g, loco::DataType::FLOAT32, filter_shape, 0.5f);
+    _conv_b = luci::create_const_node(g, loco::DataType::FLOAT32, bias_shape, 0.5f);
+    _conv_f->name("conv_f");
+    _conv_b->name("conv_b");
+
+    _conv = g->nodes()->create<luci::CircleConv2D>();
+    _conv->filter(_conv_f);
+    _conv->bias(_conv_b);
+    _conv->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _conv->dtype(loco::DataType::FLOAT32);
+    _conv->shape({1, 3, 3, FILTER_O});
+    _conv->name("conv");
+
+    const ShapeU32 add_shape = {1, 1, 1, FILTER_O};
+    _add_y = luci::create_const_node(g, loco::DataType::FLOAT32, add_shape, 0.5f);
+    _add_y->name("add_y");
+
+    _add = g->nodes()->create<luci::CircleAdd>();
+    _add->x(_conv);
+    _add->y(_add_y);
+    _add->fusedActivationFunction(luci::FusedActFunc::RELU);
+    _add->dtype(loco::DataType::FLOAT32);
+    _add->shape({1, 3, 3, FILTER_O});
+    _add->name("add");
+
+    // for negative test
+    const ShapeU32 add_shape_2 = {FILTER_O, FILTER_I};
+    _add_y_2 = luci::create_const_node(g, loco::DataType::FLOAT32, add_shape_2, 0.5f);
+    _add_y_2->name("add_y_2");
+  }
+
+protected:
+  luci::CircleConv2D *_conv = nullptr;
+  luci::CircleAdd *_add = nullptr;
+  luci::CircleConst *_conv_f = nullptr;
+  luci::CircleConst *_conv_b = nullptr;
+  luci::CircleConst *_add_y = nullptr;
+  luci::CircleConst *_add_y_2 = nullptr;
+};
+
+class FuseAddWithConvTestGraph : public TestIOGraph, public Conv2DAddGraphlet
+{
+public:
+  FuseAddWithConvTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({1, 3, 3, FILTER_I}, {1, 3, 3, FILTER_O});
+    Conv2DAddGraphlet::init(g());
+
+    _conv->input(input());
+    output()->from(_add);
+  }
+
+  void add_use_2()
+  {
+    // set to not compatible shape
+    _add->y(_add_y_2);
+  }
+};
+
+class FuseAddWithConvPassTest : public ::testing::Test, public FuseAddWithConvTestGraph
+{
+public:
+  luci::FuseAddWithConvPass pass;
+};
+
+} // namespace
+
+TEST_F(FuseAddWithConvPassTest, simple_test)
+{
+  init();
+
+  // Add should exist
+  auto add = dynamic_cast<luci::CircleAdd *>(output()->from());
+  EXPECT_NE(nullptr, add);
+
+  EXPECT_TRUE(pass.run(g()));
+
+  // expect Add is fused into Conv
+  auto conv = dynamic_cast<luci::CircleConv2D *>(output()->from());
+  EXPECT_NE(nullptr, conv);
+}
+
+TEST_F(FuseAddWithConvPassTest, wrong_add_shape_NEG)
+{
+  init();
+  add_use_2();
+
+  // Add const shape is not compatible
+  EXPECT_FALSE(pass.run(g()));
+}
index 1d4a2e3..45b7ef6 100644 (file)
@@ -20,6 +20,8 @@
 #include <luci/Service/Nodes/CircleConst.h>
 #include <luci/Profile/CircleNodeOrigin.h>
 
+#include <cmath>
+
 namespace
 {
 /**
@@ -124,6 +126,184 @@ bool fuse_add_with_fc(luci::CircleFullyConnected *fc)
   return true;
 }
 
+// Return qparam if it exists and its scale/zp's size is the same with len
+// Return nullptr otherwise
+luci::CircleQuantParam *get_qparam(luci::CircleNode *node, uint32_t len)
+{
+  if (node->quantparam() == nullptr)
+    return nullptr;
+
+  if (node->quantparam()->scale.size() != len)
+    return nullptr;
+
+  if (node->quantparam()->zerop.size() != len)
+    return nullptr;
+
+  return node->quantparam();
+}
+
+bool fuse_add_with_s16_fc(luci::CircleFullyConnected *fc)
+{
+  assert(fc);                                 // FIX_CALLER_UNLESS
+  assert(fc->dtype() == loco::DataType::S16); // FIX_CALLER_UNLESS
+
+  if (fc->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return false;
+
+  auto weights = dynamic_cast<luci::CircleConst *>(fc->weights());
+  if (not weights)
+    return false;
+
+  auto fc_output = loco::succs(fc);
+  // Fuse only when FC has a single successor (to avoid weight increase)
+  if (fc_output.size() != 1)
+    return false;
+
+  auto add = dynamic_cast<luci::CircleAdd *>(*fc_output.begin());
+  if (not add)
+    return false;
+
+  // Only support the same dtype with fc
+  if (add->dtype() != loco::DataType::S16)
+    return false;
+
+  // Get addition
+  auto addition = add->x() == fc ? dynamic_cast<luci::CircleConst *>(add->y())
+                                 : dynamic_cast<luci::CircleConst *>(add->x());
+
+  // Non-const addition
+  if (not addition)
+    return false;
+
+  // Check addition dtype
+  if (addition->dtype() != loco::DataType::S16)
+    return false;
+
+  auto rank = addition->rank();
+  // TODO Support scalar addition
+  if (rank == 0)
+    return false;
+
+  for (uint32_t i = 0; i < rank - 1; i++)
+  {
+    if (addition->dim(i).value() != 1)
+      return false;
+  }
+
+  // Check the last dim of addition is the same with the output dim of weight
+  const auto last_dim = addition->dim(rank - 1).value();
+  if (last_dim != weights->dim(0).value())
+    return false;
+
+  auto bias = loco::must_cast<luci::CircleNode *>(fc->bias());
+
+  // Only support (1) constant bias, or (2) no bias
+  if (bias->opcode() != luci::CircleOpcode::CIRCLECONST and
+      bias->opcode() != luci::CircleOpcode::CIRCLEOUTPUTEXCLUDE)
+    return false;
+
+  // If bias is const, its dtype must be s64
+  if (bias->opcode() == luci::CircleOpcode::CIRCLECONST and bias->dtype() != loco::DataType::S64)
+    return false;
+
+  const auto addition_qparam = get_qparam(addition, last_dim);
+  if (addition_qparam == nullptr)
+    return false;
+
+  std::vector<float> fp32_bias(last_dim);
+  for (uint32_t i = 0; i < last_dim; i++)
+  {
+    auto scale = addition_qparam->scale.at(i);
+    if (addition_qparam->zerop.at(i) != 0)
+      return false; // FIX_ME_UNLESS
+
+    auto val = addition->at<loco::DataType::S16>(i);
+    fp32_bias[i] = val * scale;
+  }
+
+  // Add existing bias values
+  if (auto const_bias = dynamic_cast<luci::CircleConst *>(bias))
+  {
+    const auto bias_qparam = get_qparam(const_bias, last_dim);
+    if (bias_qparam == nullptr)
+      return false;
+
+    for (uint32_t i = 0; i < last_dim; i++)
+    {
+      auto scale = bias_qparam->scale.at(i);
+      if (bias_qparam->zerop.at(i) != 0)
+        return false; // FIX_ME_UNLESS
+
+      auto val = const_bias->at<loco::DataType::S64>(i);
+      fp32_bias[i] += val * scale;
+    }
+  }
+
+  const auto add_qparam = get_qparam(add, 1);
+  if (add_qparam == nullptr)
+    return false;
+
+  auto input = loco::must_cast<luci::CircleNode *>(fc->input());
+  const auto input_qparam = get_qparam(input, 1);
+  if (input_qparam == nullptr)
+    return false;
+
+  const auto weights_qparam = get_qparam(weights, last_dim);
+  if (weights_qparam == nullptr)
+    return false;
+
+  auto fused_bias = luci::clone(addition);
+  fused_bias->dtype(loco::DataType::S64);
+  fused_bias->size<loco::DataType::S64>(last_dim);
+
+  // The shape is normalized to [N] to become the bias of FC
+  fused_bias->rank(1);
+  fused_bias->dim(0) = last_dim;
+
+  std::vector<float> new_bias_scale;
+  for (uint32_t i = 0; i < last_dim; i++)
+  {
+    const auto input_scale = input_qparam->scale.at(0);
+    const auto weight_scale = weights_qparam->scale.at(i);
+
+    const float scale = input_scale * weight_scale;
+    const float scale_inv = (scale == 0) ? 0 : 1.0 / scale;
+
+    fused_bias->at<loco::DataType::S64>(i) =
+      static_cast<int64_t>(std::round(fp32_bias.at(i) * scale_inv));
+
+    new_bias_scale.push_back(scale);
+  }
+  std::vector<int64_t> new_bias_zerop(new_bias_scale.size(), 0);
+
+  auto bias_qparam = std::make_unique<luci::CircleQuantParam>();
+  {
+    bias_qparam->scale = new_bias_scale;
+    bias_qparam->zerop = new_bias_zerop;
+  }
+
+  fused_bias->quantparam(std::move(bias_qparam));
+
+  // In-place update. This works because fc is guaranteed to have a single successor
+  fc->bias(fused_bias);
+  fc->fusedActivationFunction(add->fusedActivationFunction());
+
+  auto qparam = std::make_unique<luci::CircleQuantParam>();
+  {
+    qparam->scale.push_back(add_qparam->scale.at(0));
+    qparam->zerop.push_back(add_qparam->scale.at(0));
+  }
+
+  fc->quantparam(std::move(qparam));
+
+  // set origin
+  luci::add_origin(fc, luci::get_origin(add));
+
+  replace(add).with(fc);
+
+  return true;
+}
+
 } // namespace
 
 namespace luci
@@ -138,8 +318,19 @@ bool FuseAddWithFullyConnectedPass::run(loco::Graph *g)
     if (not fc)
       continue;
 
-    if (fuse_add_with_fc(fc))
-      changed = true;
+    switch (fc->dtype())
+    {
+      case loco::DataType::FLOAT32:
+        if (fuse_add_with_fc(fc))
+          changed = true;
+        break;
+      case loco::DataType::S16:
+        if (fuse_add_with_s16_fc(fc))
+          changed = true;
+        break;
+      default:
+        break;
+    }
   }
 
   return changed;
index b132c6b..c96846f 100644 (file)
@@ -121,6 +121,142 @@ public:
   luci::FuseAddWithFullyConnectedPass pass;
 };
 
+std::unique_ptr<luci::CircleQuantParam> gen_qparam(const std::vector<float> &s,
+                                                   const std::vector<int64_t> &zp)
+{
+  auto qparam = std::make_unique<luci::CircleQuantParam>();
+  {
+    for (auto scale : s)
+      qparam->scale.push_back(scale);
+
+    for (auto zerop : zp)
+      qparam->zerop.push_back(zerop);
+  }
+
+  return std::move(qparam);
+}
+
+/**
+ *  Simple graph for test
+ *
+ *  BEFORE
+ *
+ *         [FC]
+ *           |
+ *     [Add w/ Relu]
+ *
+ *  AFTER
+ *
+ *      [FC w/ Relu] (bias updated)
+ *
+ */
+class S16FCAddGraphlet
+{
+public:
+  void init(loco::Graph *g)
+  {
+    std::vector<int16_t> weights_val(16 * 4);
+    _fc_f = luci::create_const_node(g, loco::DataType::S16, {16, 4}, weights_val);
+    {
+      auto qparam = std::make_unique<luci::CircleQuantParam>();
+      {
+        for (uint32_t i = 0; i < 16; i++)
+        {
+          qparam->scale.push_back(1.0);
+          qparam->zerop.push_back(0);
+        }
+      }
+      _fc_f->quantparam(std::move(qparam));
+    }
+
+    std::vector<int64_t> bias_val(16);
+    for (uint32_t i = 0; i < 16; i++)
+      bias_val.at(i) = i;
+
+    _fc_b = luci::create_const_node(g, loco::DataType::S64, {1, 16}, bias_val);
+    {
+      std::vector<float> scale(16, 1.0);
+      std::vector<int64_t> zerop(16, 0);
+
+      auto qparam = gen_qparam(scale, zerop);
+      _fc_b->quantparam(std::move(qparam));
+    }
+
+    _fc = g->nodes()->create<luci::CircleFullyConnected>();
+    _fc->weights(_fc_f);
+    _fc->bias(_fc_b);
+    _fc->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _fc->dtype(loco::DataType::S16);
+    _fc->shape({1, 16});
+    _fc->name("fc");
+
+    std::vector<int16_t> addition_val;
+    for (uint32_t i = 0; i < 16; i++)
+      addition_val.push_back(static_cast<int16_t>(i));
+
+    _add_c = luci::create_const_node(g, loco::DataType::S16, {1, 16}, addition_val);
+    {
+      std::vector<float> scale(16, 1.0);
+      std::vector<int64_t> zerop(16, 0);
+
+      auto qparam = gen_qparam(scale, zerop);
+      _add_c->quantparam(std::move(qparam));
+    }
+
+    _add = g->nodes()->create<luci::CircleAdd>();
+    {
+      auto qparam = gen_qparam({2.0}, {0});
+      _add->quantparam(std::move(qparam));
+    }
+
+    _add->x(_fc);
+    _add->y(_add_c);
+    _add->fusedActivationFunction(luci::FusedActFunc::RELU);
+    _add->dtype(loco::DataType::S16);
+    _add->shape({1, 16});
+    _add->name("add");
+  }
+
+public:
+  luci::CircleFullyConnected *fc() { return _fc; }
+
+protected:
+  luci::CircleFullyConnected *_fc = nullptr;
+  luci::CircleAdd *_add = nullptr;
+  luci::CircleConst *_fc_f = nullptr;
+  luci::CircleConst *_fc_b = nullptr;
+  luci::CircleConst *_add_c = nullptr;
+};
+
+class S16FuseAddWithFCTestGraph : public TestIOGraph, public S16FCAddGraphlet
+{
+public:
+  void init(void)
+  {
+    TestIOGraph::init({1, 4}, {1, 16});
+    input()->dtype(loco::DataType::S16);
+    {
+      auto qparam = gen_qparam({1.0}, {0});
+      input()->quantparam(std::move(qparam));
+    }
+
+    output()->dtype(loco::DataType::S16);
+
+    S16FCAddGraphlet::init(g());
+
+    _fc->input(input());
+
+    output()->from(_add);
+  }
+};
+
+class S16FuseAddWithFullyConnectedPassTest : public ::testing::Test
+{
+public:
+  S16FuseAddWithFCTestGraph g;
+  luci::FuseAddWithFullyConnectedPass pass;
+};
+
 } // namespace
 
 TEST_F(FuseAddWithFullyConnectedPassTest, simple_test)
@@ -150,3 +286,39 @@ TEST_F(FuseAddWithFullyConnectedPassTest, fm_bias_NEG)
   auto ret = pass.run(g.g());
   EXPECT_EQ(false, ret);
 }
+
+TEST_F(S16FuseAddWithFullyConnectedPassTest, fuse_s16)
+{
+  g.init();
+
+  auto ret = pass.run(g.g());
+  EXPECT_EQ(true, ret);
+
+  auto fc = dynamic_cast<luci::CircleFullyConnected *>(g.output()->from());
+  EXPECT_NE(nullptr, fc);
+  EXPECT_NE(nullptr, fc->quantparam());
+  EXPECT_EQ(1, fc->quantparam()->scale.size());
+  EXPECT_EQ(2.0, fc->quantparam()->scale.at(0));
+  EXPECT_EQ(luci::FusedActFunc::RELU, fc->fusedActivationFunction());
+
+  auto bias = loco::must_cast<luci::CircleConst *>(g.fc()->bias());
+  EXPECT_EQ(loco::DataType::S64, bias->dtype());
+  for (uint32_t i = 0; i < bias->size<loco::DataType::S64>(); i++)
+  {
+    EXPECT_EQ(2 * i, bias->at<loco::DataType::S64>(i));
+  }
+
+  auto qparam = bias->quantparam();
+  EXPECT_NE(nullptr, qparam);
+  EXPECT_EQ(1.0, qparam->scale.at(0));
+  EXPECT_EQ(0, qparam->zerop.at(0));
+}
+
+TEST_F(S16FuseAddWithFullyConnectedPassTest, fc_with_null_weights_NEG)
+{
+  g.init();
+  g.fc()->weights(nullptr);
+
+  auto ret = pass.run(g.g());
+  EXPECT_EQ(false, ret);
+}
diff --git a/compiler/luci/pass/src/FuseHorizontalFullyConnectedPass.cpp b/compiler/luci/pass/src/FuseHorizontalFullyConnectedPass.cpp
new file mode 100644 (file)
index 0000000..3aa3725
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Pass/FuseHorizontalFullyConnectedPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/Nodes/CircleConst.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace luci
+{
+
+namespace
+{
+
+bool check_type_and_shape_equality(const CircleNode *left, const CircleNode *right)
+{
+  if (left->dtype() != right->dtype())
+    return false;
+
+  if (left->rank() != right->rank())
+    return false;
+
+  for (uint32_t i = 0; i < left->rank(); ++i)
+  {
+    if (left->dim(i).value() != right->dim(i).value())
+      return false;
+  }
+
+  return true;
+}
+
+// Add right const to left const (left is updated)
+template <loco::DataType D> void sum_const_values(CircleConst *left, const CircleConst *right)
+{
+  assert(check_type_and_shape_equality(left, right)); // FIX CALLER UNLESS
+  const auto size = left->template size<D>();
+
+  for (uint32_t i = 0; i < size; ++i)
+  {
+    left->template at<D>(i) += right->template at<D>(i);
+  }
+}
+
+bool fuse_horizontal_fc_nodes(CircleAdd *add_node)
+{
+  // Let's check left and right FC nodes
+  auto left_fc_node = dynamic_cast<CircleFullyConnected *>(add_node->x());
+  auto right_fc_node = dynamic_cast<CircleFullyConnected *>(add_node->y());
+
+  if (left_fc_node == nullptr or right_fc_node == nullptr)
+    return false;
+
+  if (not check_type_and_shape_equality(left_fc_node, right_fc_node))
+    return false;
+
+  if (left_fc_node->fusedActivationFunction() != FusedActFunc::NONE)
+    return false;
+
+  if (right_fc_node->fusedActivationFunction() != FusedActFunc::NONE)
+    return false;
+
+  // Let's check that FC nodes have the same input
+  if (left_fc_node->input() != right_fc_node->input())
+    return false;
+
+  // Lets check left and right FC weights: type and shape
+  auto left_fc_weights = dynamic_cast<CircleConst *>(left_fc_node->weights());
+  auto right_fc_weights = dynamic_cast<CircleConst *>(right_fc_node->weights());
+
+  if (left_fc_weights == nullptr or right_fc_weights == nullptr)
+    return false;
+
+  if (not check_type_and_shape_equality(left_fc_weights, right_fc_weights))
+    return false;
+
+  // Lets check left and right FC bias: type and shape
+  auto left_fc_bias = dynamic_cast<CircleConst *>(left_fc_node->bias());
+  auto right_fc_bias = dynamic_cast<CircleConst *>(right_fc_node->bias());
+
+  // Support only if both biases are const, or both are non-const
+  // TODO Support the case that one FC has a const bias and another FC has no bias.
+  if ((left_fc_bias == nullptr and right_fc_bias != nullptr) or
+      (left_fc_bias != nullptr and right_fc_bias == nullptr))
+  {
+    return false;
+  }
+
+  // Both left/right bias are const. Check dtype/shape.
+  if (left_fc_bias != nullptr and not check_type_and_shape_equality(left_fc_bias, right_fc_bias))
+    return false;
+
+  // Both left/right bias are non-const. Check left/right fc has no bias.
+  if (left_fc_bias == nullptr)
+  {
+    auto left_no_bias = dynamic_cast<CircleOutputExclude *>(left_fc_node->bias());
+    auto right_no_bias = dynamic_cast<CircleOutputExclude *>(right_fc_node->bias());
+    if (not left_no_bias or not right_no_bias)
+      return false;
+  }
+
+  if (left_fc_weights->dtype() != loco::DataType::FLOAT32)
+    return false;
+
+  if (left_fc_bias != nullptr)
+  {
+    if (left_fc_bias->dtype() != loco::DataType::FLOAT32)
+      return false;
+  }
+
+  // Lets create fused FC weights and bias
+  auto fused_fc_weights = clone(left_fc_weights);
+  add_origin(fused_fc_weights,
+             composite_origin({get_origin(left_fc_weights), get_origin(right_fc_weights)}));
+
+  CircleConst *fused_fc_bias = nullptr;
+  if (left_fc_bias != nullptr)
+  {
+    fused_fc_bias = clone(left_fc_bias);
+    add_origin(fused_fc_bias,
+               composite_origin({get_origin(left_fc_bias), get_origin(right_fc_bias)}));
+  }
+
+  assert(fused_fc_weights->dtype() == loco::DataType::FLOAT32);
+  sum_const_values<loco::DataType::FLOAT32>(fused_fc_weights, right_fc_weights);
+
+  if (fused_fc_bias != nullptr)
+  {
+    assert(fused_fc_bias->dtype() == loco::DataType::FLOAT32);
+    sum_const_values<loco::DataType::FLOAT32>(fused_fc_bias, right_fc_bias);
+  }
+
+  // Create fused FC node
+  auto graph = left_fc_node->graph();
+  auto fused_fc_node = graph->nodes()->create<CircleFullyConnected>();
+  fused_fc_node->input(left_fc_node->input());
+  fused_fc_node->weights(fused_fc_weights);
+  if (fused_fc_bias)
+  {
+    fused_fc_node->bias(fused_fc_bias);
+  }
+  else
+  {
+    assert(nullptr != dynamic_cast<CircleOutputExclude *>(left_fc_node->bias())); // FIX ME UNLESS
+    fused_fc_node->bias(left_fc_node->bias());
+  }
+
+  fused_fc_node->fusedActivationFunction(add_node->fusedActivationFunction());
+  fused_fc_node->name(left_fc_node->name() + "_" + right_fc_node->name() + "_fused");
+
+  add_origin(fused_fc_node, composite_origin({get_origin(left_fc_node), get_origin(right_fc_node),
+                                              get_origin(add_node)}));
+
+  replace(add_node).with(fused_fc_node);
+
+  return true;
+}
+
+} // namespace
+
+/**
+ * @brief  Class to fuse horizontal FC layers
+ *
+ *  Before
+ *
+ *     +---- [In] ----+
+ *     |              |
+ *     V              V
+ *   fc1 (w1, b1)   fc2 (w2, b2)
+ *     |              |
+ *     |              |
+ *     +---> add <----+
+ *            |
+ *            V
+ *          [Out]
+ *
+ *  After
+ *
+ *     [In]
+ *      |
+ *      V
+ *     fc3 (w1+w2, b1+b2)
+ *      |
+ *      V
+ *     [Out]
+ *
+ *     Shape/dtype of fc1, fc2, and fc3 should be the same.
+ */
+bool FuseHorizontalFullyConnectedPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto add_node = dynamic_cast<CircleAdd *>(node);
+    if (not add_node)
+      continue;
+
+    if (fuse_horizontal_fc_nodes(add_node))
+      changed = true;
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseHorizontalFullyConnectedPass.test.cpp b/compiler/luci/pass/src/FuseHorizontalFullyConnectedPass.test.cpp
new file mode 100644 (file)
index 0000000..3dba7f8
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Pass/FuseHorizontalFullyConnectedPass.h"
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+/*
+ *  Before
+ *
+ *     +---- [In] ----+
+ *     |              |
+ *     V              V
+ *   fc1 (w1, b1)   fc2 (w2, b2)
+ *     |              |
+ *     |              |
+ *     +---> add <----+
+ *            |
+ *            V
+ *          [Out]
+ *
+ *  After
+ *
+ *     [In]
+ *      |
+ *      V
+ *     fc3 (w1+w2, b1+b2)
+ *      |
+ *      V
+ *     [Out]
+ */
+class FuseHorizontalFCLayersTestGraph : public TestIOGraph
+{
+public:
+  FuseHorizontalFCLayersTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({1, 10}, {1, 10});
+
+    _left_fc = g()->nodes()->create<luci::CircleFullyConnected>();
+    _right_fc = g()->nodes()->create<luci::CircleFullyConnected>();
+    _left_weight = g()->nodes()->create<luci::CircleConst>();
+    _right_weight = g()->nodes()->create<luci::CircleConst>();
+
+    _left_fc->name("left FC");
+    _right_fc->name("right FC");
+    _left_weight->name("left weight");
+    _right_weight->name("right weight");
+
+    _left_fc->dtype(loco::DataType::FLOAT32);
+    _right_fc->dtype(loco::DataType::FLOAT32);
+
+    _left_fc->shape_status(luci::ShapeStatus::VALID);
+    _right_fc->shape_status(luci::ShapeStatus::VALID);
+
+    _left_fc->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _right_fc->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+    _left_fc->rank(2);
+    _right_fc->rank(2);
+
+    _right_fc->dim(0) = 1;
+    _right_fc->dim(1) = 10;
+
+    _left_fc->dim(0) = 1;
+    _left_fc->dim(1) = 10;
+
+    _left_weight->rank(2);
+    _left_weight->dtype(loco::DataType::FLOAT32);
+    _left_weight->size<loco::DataType::FLOAT32>(5 * 10);
+    for (uint32_t i = 0; i < 5 * 10; ++i)
+    {
+      _left_weight->at<loco::DataType::FLOAT32>(0) = 1.0f;
+    }
+    _left_weight->dim(0) = 5;
+    _left_weight->dim(1) = 10;
+    _left_weight->shape_status(luci::ShapeStatus::VALID);
+
+    _right_weight->rank(2);
+    _right_weight->dtype(loco::DataType::FLOAT32);
+    _right_weight->size<loco::DataType::FLOAT32>(5 * 10);
+    for (uint32_t i = 0; i < 5 * 10; ++i)
+    {
+      _right_weight->at<loco::DataType::FLOAT32>(0) = 2.0f;
+    }
+    _right_weight->dim(0) = 5;
+    _right_weight->dim(1) = 10;
+    _right_weight->shape_status(luci::ShapeStatus::VALID);
+
+    const auto left_output_exclude = g()->nodes()->create<luci::CircleOutputExclude>();
+    const auto right_output_exclude = g()->nodes()->create<luci::CircleOutputExclude>();
+
+    _left_fc->input(input());
+    _left_fc->weights(_left_weight);
+    _left_fc->bias(left_output_exclude);
+    _right_fc->input(input());
+    _right_fc->weights(_right_weight);
+    _right_fc->bias(right_output_exclude);
+
+    _add = g()->nodes()->create<luci::CircleAdd>();
+    _add->dtype(loco::DataType::FLOAT32);
+    _add->rank(2);
+    _add->dim(0) = 1;
+    _add->dim(1) = 5;
+    _add->x(_left_fc);
+    _add->y(_right_fc);
+    _add->shape_status(luci::ShapeStatus::VALID);
+
+    output()->from(_add);
+  }
+
+  luci::CircleFullyConnected *get_left_fc() { return _left_fc; }
+
+private:
+  luci::CircleFullyConnected *_left_fc = nullptr;
+  luci::CircleConst *_left_weight = nullptr;
+  luci::CircleFullyConnected *_right_fc = nullptr;
+  luci::CircleConst *_right_weight = nullptr;
+  luci::CircleAdd *_add = nullptr;
+};
+
+} // namespace
+
+TEST(FuseHorizontalFCLayersPassTest, name)
+{
+  luci::FuseHorizontalFullyConnectedPass pass;
+  auto const name = pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST(FuseHorizontalFCLayersPassTest, fuse_horizontal_nodes)
+{
+  FuseHorizontalFCLayersTestGraph g;
+  luci::FuseHorizontalFullyConnectedPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(FuseHorizontalFCLayersPassTest, fuse_horizontal_nodes_NEG)
+{
+  FuseHorizontalFCLayersTestGraph g;
+  luci::FuseHorizontalFullyConnectedPass pass;
+
+  g.init();
+
+  g.get_left_fc()->fusedActivationFunction(luci::FusedActFunc::RELU6);
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
+
+TEST(FuseHorizontalFCLayersPassTest, wrong_dtype_NEG)
+{
+  FuseHorizontalFCLayersTestGraph g;
+  luci::FuseHorizontalFullyConnectedPass pass;
+
+  g.init();
+
+  g.get_left_fc()->dtype(loco::DataType::S32);
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
diff --git a/compiler/luci/pass/src/FuseMulToFullyConnectedWeightsPass.cpp b/compiler/luci/pass/src/FuseMulToFullyConnectedWeightsPass.cpp
new file mode 100644 (file)
index 0000000..1f41d16
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseMulToFullyConnectedWeightsPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+#include "helpers/NodeFiller.h"
+
+#define CHECK_OR_FALSE(condition) \
+  if (not(condition))             \
+    return false;
+
+namespace
+{
+
+/**
+ *  Fuse Mul to following FullyConnected if possible
+ *
+ *  BEFORE
+ *                |
+ *           [CircleMul] [CircleConst] [CircleConst]
+ *                |       |              |
+ *      [CircleFullyConnected] ----------+
+ *                |
+ *
+ *  AFTER
+ *                |
+ *                | [CircleConst] [CircleConst]
+ *                |         |       |
+ *                |        [CircleMul] [CircleConst]   [CircleMul]
+ *                |          |              |
+ *       [CircleFullyConnected] ------------+
+ *                |
+ *
+ */
+bool fuse_fc_with_mul(luci::CircleFullyConnected *fc)
+{
+  CHECK_OR_FALSE(fc);
+
+  // check input is Mul
+  auto mul = dynamic_cast<luci::CircleMul *>(fc->input());
+  CHECK_OR_FALSE(mul);
+  // conditions of Mul, FC: to expect constant folding, support only F32
+  CHECK_OR_FALSE(mul->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(mul->fusedActivationFunction() == luci::FusedActFunc::NONE);
+  CHECK_OR_FALSE(fc->dtype() == loco::DataType::FLOAT32);
+  // support weight with constant
+  auto weights = dynamic_cast<luci::CircleConst *>(fc->weights());
+  CHECK_OR_FALSE(weights);
+
+  // Check multiplication of Mul is constant
+  luci::CircleNode *mul_input = nullptr;
+  luci::CircleConst *mul_scale = nullptr;
+  CHECK_OR_FALSE(luci::fill(&mul_input, &mul_scale).with_commutative_args_of(mul));
+  // support only 1D constant
+  CHECK_OR_FALSE(mul_scale->rank() == 1);
+
+  auto graph = fc->graph();
+
+  auto fc_weights = graph->nodes()->create<luci::CircleMul>();
+  fc_weights->x(weights);
+  fc_weights->y(mul_scale);
+  fc_weights->fusedActivationFunction(luci::FusedActFunc::NONE);
+  fc_weights->name(mul->name() + "_" + fc->name() + "_weight");
+  luci::add_origin(fc_weights,
+                   luci::composite_origin({luci::get_origin(mul), luci::get_origin(weights),
+                                           luci::get_origin(mul_scale)}));
+
+  auto fc_new = graph->nodes()->create<luci::CircleFullyConnected>();
+  fc_new->input(mul_input);
+  fc_new->weights(fc_weights);
+  fc_new->bias(fc->bias());
+  fc_new->weights_format(fc->weights_format());
+  fc_new->keep_num_dims(fc->keep_num_dims());
+  fc_new->fusedActivationFunction(fc->fusedActivationFunction());
+  fc_new->name(fc->name());
+  luci::add_origin(fc_new, luci::get_origin(fc));
+
+  replace(fc).with(fc_new);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool FuseMulToFullyConnectedWeightsPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto fc = dynamic_cast<luci::CircleFullyConnected *>(node);
+    if (not fc)
+      continue;
+
+    if (fuse_fc_with_mul(fc))
+      changed = true;
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseMulToFullyConnectedWeightsPass.test.cpp b/compiler/luci/pass/src/FuseMulToFullyConnectedWeightsPass.test.cpp
new file mode 100644 (file)
index 0000000..2cb7a4e
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseMulToFullyConnectedWeightsPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+template <loco::DataType DT> class FuseMulToFullyConnectedWeightsPassTestGraph : public TestIOGraph
+{
+public:
+  FuseMulToFullyConnectedWeightsPassTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({3, 4}, {3, 6});
+
+    _mul = g()->nodes()->create<luci::CircleMul>();
+    _mul_s = g()->nodes()->create<luci::CircleConst>();
+    _fc = g()->nodes()->create<luci::CircleFullyConnected>();
+    _fc_w = g()->nodes()->create<luci::CircleConst>();
+    _fc_b = g()->nodes()->create<luci::CircleConst>();
+
+    _mul->name("mul");
+    _mul_s->name("mul_s");
+    _fc->name("fc");
+    _fc_w->name("fc_w");
+    _fc_b->name("fc_b");
+
+    _mul->dtype(DT);
+    _fc->dtype(DT);
+    _mul->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _fc->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+    _mul_s->rank(1);
+    _mul_s->dim(0) = 3;
+    _mul_s->dtype(DT);
+    _mul_s->size<DT>(3);
+    for (uint32_t i = 0; i < 3; ++i)
+    {
+      _mul_s->at<DT>(0) = 1.0f;
+    }
+
+    _fc_w->rank(2);
+    _fc_w->dim(0) = 3;
+    _fc_w->dim(1) = 4;
+    _fc_w->dtype(DT);
+    _fc_w->size<DT>(4 * 6);
+    for (uint32_t i = 0; i < 4 * 6; ++i)
+    {
+      _fc_w->at<DT>(0) = 1.0f;
+    }
+
+    _fc_b->rank(1);
+    _fc_b->dim(0) = 6;
+    _fc_b->dtype(DT);
+    _fc_b->size<DT>(6);
+    for (uint32_t i = 0; i < 6; ++i)
+    {
+      _fc_b->at<DT>(0) = 1.0f;
+    }
+
+    _mul->x(input());
+    _mul->y(_mul_s);
+    _fc->input(_mul);
+    _fc->weights(_fc_b);
+    _fc->bias(_fc_b);
+
+    output()->from(_fc);
+  }
+
+  luci::CircleMul *_mul = nullptr;
+  luci::CircleFullyConnected *_fc = nullptr;
+  luci::CircleConst *_mul_s = nullptr;
+  luci::CircleConst *_fc_w = nullptr;
+  luci::CircleConst *_fc_b = nullptr;
+};
+
+class FuseMulToFullyConnectedWeightsPassTest : public ::testing::Test
+{
+public:
+  FuseMulToFullyConnectedWeightsPassTest() = default;
+
+protected:
+  FuseMulToFullyConnectedWeightsPassTestGraph<loco::DataType::FLOAT32> _graph;
+  luci::FuseMulToFullyConnectedWeightsPass _pass;
+};
+
+class FuseMulToFullyConnectedWeightsPassS32Test : public ::testing::Test
+{
+public:
+  FuseMulToFullyConnectedWeightsPassS32Test() = default;
+
+protected:
+  FuseMulToFullyConnectedWeightsPassTestGraph<loco::DataType::S32> _graph;
+  luci::FuseMulToFullyConnectedWeightsPass _pass;
+};
+
+} // namespace
+
+TEST_F(FuseMulToFullyConnectedWeightsPassTest, name)
+{
+  auto const name = _pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST_F(FuseMulToFullyConnectedWeightsPassTest, fuse_mul_to_fc_weights)
+{
+  _graph.init();
+
+  EXPECT_TRUE(_pass.run(_graph.g()));
+}
+
+TEST_F(FuseMulToFullyConnectedWeightsPassTest, mul_fused_act_NEG)
+{
+  _graph.init();
+
+  _graph._mul->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+  EXPECT_FALSE(_pass.run(_graph.g()));
+}
+
+TEST_F(FuseMulToFullyConnectedWeightsPassTest, mul_d2_NEG)
+{
+  _graph.init();
+
+  _graph._mul_s->rank(2);
+  _graph._mul_s->dim(0) = 1;
+  _graph._mul_s->dim(1) = 3;
+
+  EXPECT_FALSE(_pass.run(_graph.g()));
+}
+
+TEST_F(FuseMulToFullyConnectedWeightsPassS32Test, dtype_s32_NEG)
+{
+  _graph.init();
+
+  EXPECT_FALSE(_pass.run(_graph.g()));
+}
diff --git a/compiler/luci/pass/src/FuseMulWithConvPass.cpp b/compiler/luci/pass/src/FuseMulWithConvPass.cpp
new file mode 100644 (file)
index 0000000..94ad086
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Pass/FuseMulWithConvPass.h"
+
+#include "helpers/NodeFiller.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Service/CircleNodeClone.h>
+#include <luci/Service/Nodes/CircleConst.h>
+
+namespace
+{
+
+#define RETURN_FALSE_UNLESS(cond) \
+  if (not(cond))                  \
+    return false;
+
+inline uint32_t cal_offset(const luci::CircleConst *node, const std::vector<uint32_t> &indices)
+{
+  // sanity check for node's rank
+  assert(node != nullptr && node->rank() == 4);
+
+  // sanity check for indices
+  assert(indices.size() == 4);
+
+  return indices[0] * node->dim(1).value() * node->dim(2).value() * node->dim(3).value() +
+         indices[1] * node->dim(2).value() * node->dim(3).value() +
+         indices[2] * node->dim(3).value() + indices[3];
+}
+
+/**
+ *  Fuse Mul with Conv if possible
+ *
+ *  NOTE: In case mul is channewise constant, we can try to merge mul with nconv,
+ *
+ *  BEFORE
+ *                    |
+ *              [CircleConv2D] (no activation)
+ *                    |
+ *                  [Mul] (channel-wise/scalar constant)
+ *                    |
+ *
+ *  AFTER
+ *                    |
+ *            [CircleConv2D] (with updated kernels, bias, and activation)
+ *                    |
+ *
+ */
+
+bool fuse_mul_with_conv(luci::CircleMul *mul)
+{
+  // sanity check
+  RETURN_FALSE_UNLESS(mul->dtype() == loco::DataType::FLOAT32);
+
+  luci::CircleConst *const_mul_operand = nullptr;
+  luci::CircleConv2D *conv = nullptr;
+  RETURN_FALSE_UNLESS(luci::fill(&const_mul_operand, &conv).with_commutative_args_of(mul));
+
+  // sanity check
+  RETURN_FALSE_UNLESS(conv->dtype() == loco::DataType::FLOAT32 &&
+                      const_mul_operand->dtype() == loco::DataType::FLOAT32);
+
+  //  NOTE for general activation function: S * Act(A * B) != Act(A*(SB))
+  if (conv->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return false;
+
+  // check that const_mul_operand is channel-wise constant or just a scalar
+  RETURN_FALSE_UNLESS(const_mul_operand->rank() == 4 || const_mul_operand->rank() == 1 ||
+                      const_mul_operand->rank() == 0);
+
+  std::vector<float> mul_values;
+  if (const_mul_operand->rank() == 4)
+  {
+    // check channel-wise broadcasting
+    RETURN_FALSE_UNLESS(const_mul_operand->dim(0).value() == 1 &&
+                        const_mul_operand->dim(1).value() == 1 &&
+                        const_mul_operand->dim(2).value() == 1);
+  }
+  else if (const_mul_operand->rank() == 1 || const_mul_operand->rank() == 0)
+  {
+    // sanity check
+    RETURN_FALSE_UNLESS(const_mul_operand->size<loco::DataType::FLOAT32>() != 0);
+  }
+
+  mul_values.resize(const_mul_operand->size<loco::DataType::FLOAT32>());
+  for (uint32_t idx = 0; idx < mul_values.size(); idx++)
+  {
+    mul_values[idx] = const_mul_operand->at<loco::DataType::FLOAT32>(idx);
+  }
+
+  // filter
+  auto const conv_filter = dynamic_cast<luci::CircleConst *>(conv->filter());
+
+  // sanity check
+  RETURN_FALSE_UNLESS(conv_filter != nullptr && conv_filter->rank() == 4 &&
+                      conv_filter->dtype() == loco::DataType::FLOAT32);
+
+  auto const out_channels = conv_filter->dim(0).value();
+
+  // multiplier is either channelwise constant or scalar
+  RETURN_FALSE_UNLESS(out_channels == mul_values.size() || mul_values.size() == 1);
+
+  // bias
+  auto const conv_bias = dynamic_cast<luci::CircleConst *>(conv->bias());
+
+  RETURN_FALSE_UNLESS(conv_bias == nullptr ||
+                      (conv_bias->rank() == 1 && conv_bias->dim(0) == out_channels &&
+                       conv_bias->dtype() == loco::DataType::FLOAT32));
+
+  luci::CircleConst *fused_conv_filter = nullptr;
+  {
+    // fused filter
+    fused_conv_filter = luci::clone(conv_filter);
+    // set values of conv filter multiplied by constant channel-wise
+    for (uint32_t out_chan = 0; out_chan < out_channels; out_chan++)
+    {
+      // for scalar - first element, otherwise - channelwise
+      float mult = mul_values[out_chan % mul_values.size()];
+      for (uint32_t out_height = 0; out_height < fused_conv_filter->dim(1).value(); out_height++)
+      {
+        for (uint32_t out_width = 0; out_width < fused_conv_filter->dim(2).value(); out_width++)
+        {
+          for (uint32_t in_chan = 0; in_chan < fused_conv_filter->dim(3).value(); in_chan++)
+          {
+            std::vector<uint32_t> indices = {out_chan, out_height, out_width, in_chan};
+            auto const data =
+              conv_filter->at<loco::DataType::FLOAT32>(cal_offset(conv_filter, indices));
+            fused_conv_filter->at<loco::DataType::FLOAT32>(cal_offset(fused_conv_filter, indices)) =
+              mult * data;
+          }
+        }
+      }
+    }
+    fused_conv_filter->name(conv_filter->name() + "/FusedMul");
+    luci::add_origin(fused_conv_filter, luci::get_origin(conv_filter));
+  }
+
+  luci::CircleConst *fused_conv_bias = nullptr;
+  if (conv_bias != nullptr)
+  {
+    // fused bias
+    fused_conv_bias = luci::clone(conv_bias);
+    // update bias values
+    for (uint32_t c = 0; c < conv_bias->size<loco::DataType::FLOAT32>(); c++)
+    {
+      // for scalar - first element, otherwise - channelwise
+      float mult = mul_values[c % mul_values.size()];
+      auto const data = conv_bias->at<loco::DataType::FLOAT32>(c);
+      fused_conv_bias->at<loco::DataType::FLOAT32>(c) = mult * data;
+    }
+
+    fused_conv_bias->name(conv_bias->name() + "/FusedMul");
+    luci::add_origin(fused_conv_bias, luci::get_origin(conv_bias));
+  }
+
+  // Configure new CircleConv2D operation.
+  auto *fused_conv = loco::must_cast<luci::CircleConv2D *>(luci::clone_node(conv, mul->graph()));
+  fused_conv->input(conv->input());
+  fused_conv->filter(fused_conv_filter);
+  fused_conv->bias(fused_conv_bias);
+  fused_conv->name(conv->name() + "/FusedMul");
+  fused_conv->fusedActivationFunction(mul->fusedActivationFunction());
+  luci::add_origin(fused_conv,
+                   luci::composite_origin({luci::get_origin(conv), luci::get_origin(mul)}));
+
+  // Replace old mul operation with new fused_conv with updated kernel/bias
+  replace(mul).with(fused_conv);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool FuseMulWithConvPass::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_mul_with_conv(mul))
+      changed = true;
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseMulWithConvPass.test.cpp b/compiler/luci/pass/src/FuseMulWithConvPass.test.cpp
new file mode 100644 (file)
index 0000000..9f215de
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseMulWithConvPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class ConvMulGraphlet
+{
+public:
+  ConvMulGraphlet() = default;
+
+public:
+  void init(loco::Graph *g, bool activation, bool mul_const_shape)
+  {
+    _conv = g->nodes()->create<luci::CircleConv2D>();
+    _conv_filter = g->nodes()->create<luci::CircleConst>();
+    _conv_bias = g->nodes()->create<luci::CircleConst>();
+    _mul = g->nodes()->create<luci::CircleMul>();
+    _mul_const = g->nodes()->create<luci::CircleConst>();
+
+    if (activation)
+    {
+      _conv->fusedActivationFunction(luci::FusedActFunc::RELU);
+    }
+    else
+    {
+      _conv->fusedActivationFunction(luci::FusedActFunc::NONE);
+    }
+
+    _conv->dtype(loco::DataType::FLOAT32);
+    _conv_filter->dtype(loco::DataType::FLOAT32);
+    _conv_bias->dtype(loco::DataType::FLOAT32);
+    _mul->dtype(loco::DataType::FLOAT32);
+    _mul_const->dtype(loco::DataType::FLOAT32);
+
+    _conv->name("conv");
+    _conv_filter->name("conv_filter");
+    _conv_bias->name("conv_bias");
+    _mul->name("mul");
+    _mul_const->name("mul_const");
+
+    _conv_filter->shape({_output_channels, 1, 1, _input_channels});
+    _conv_bias->shape({_output_channels});
+    if (mul_const_shape)
+    {
+      _mul_const->shape({1, 1, _input_dim, _output_channels});
+    }
+    else
+    {
+      _mul_const->shape({1, 1, 1, _output_channels});
+      // initialize _mul_const for positive test
+      _mul_const->size<loco::DataType::FLOAT32>(_output_channels);
+      for (uint32_t i = 0; i < _output_channels; i++)
+      {
+        _mul_const->at<loco::DataType::FLOAT32>(i) = 1.f;
+      }
+    }
+
+    {
+      // initialize bias
+      _conv_bias->size<loco::DataType::FLOAT32>(_output_channels);
+      for (uint32_t i = 0; i < _output_channels; i++)
+      {
+        _conv_bias->at<loco::DataType::FLOAT32>(i) = 0.f;
+      }
+    }
+
+    {
+      // initialize filter
+      _conv_filter->size<loco::DataType::FLOAT32>(_output_channels * _input_channels);
+      for (uint32_t i = 0; i < _conv_filter->size<loco::DataType::FLOAT32>(); i++)
+      {
+        _conv_filter->at<loco::DataType::FLOAT32>(i) = 1.f;
+      }
+    }
+
+    _conv->filter(_conv_filter);
+    _conv->bias(_conv_bias);
+    _conv->padding(luci::Padding::VALID);
+    _conv->stride()->h(1);
+    _conv->stride()->w(1);
+    _mul->x(_mul_const);
+    _mul->y(_conv);
+  }
+
+protected:
+  luci::CircleConv2D *_conv = nullptr;
+  luci::CircleConst *_conv_filter = nullptr;
+  luci::CircleConst *_conv_bias = nullptr;
+  luci::CircleMul *_mul = nullptr;
+  luci::CircleConst *_mul_const = nullptr;
+
+  const uint32_t _input_channels = 32;
+  const uint32_t _output_channels = 64;
+  const uint32_t _input_dim = 64;
+  const ShapeU32 _input_shape = {1, _input_dim, _input_dim, _input_channels};
+  const ShapeU32 _output_shape = {1, _input_dim, _input_dim, _output_channels};
+};
+
+class ConvMulGraph : public TestIOGraph, public ConvMulGraphlet
+{
+public:
+  ConvMulGraph() = default;
+
+public:
+  void init(bool activation, bool mul_const_shape)
+  {
+    TestIOGraph::init(_input_shape, _output_shape);
+    ConvMulGraphlet::init(g(), activation, mul_const_shape);
+
+    _conv->input(input());
+    output()->from(_mul);
+  }
+};
+
+} // namespace
+
+TEST(FuseMulWithConvPass, name_test)
+{
+  luci::FuseMulWithConvPass pass;
+  auto const name = pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST(FuseMulWithConvPass, simple_test)
+{
+  luci::FuseMulWithConvPass pass;
+
+  ConvMulGraph g;
+  g.init(false, false);
+
+  ASSERT_TRUE(pass.run(g.g()));
+
+  // check Mul is removed
+  int count = 0;
+  for (auto node : loco::active_nodes(loco::output_nodes(g.g())))
+  {
+    if (auto mul = dynamic_cast<luci::CircleMul *>(node))
+      count++;
+  }
+  ASSERT_EQ(0, count);
+}
+
+TEST(FuseMulWithConvPass, not_removed_NEG)
+{
+  luci::FuseMulWithConvPass pass;
+  ConvMulGraph g;
+  g.init(false, true);
+
+  ASSERT_FALSE(pass.run(g.g()));
+
+  // check Mul is not removed
+  int count = 0;
+  for (auto node : loco::active_nodes(loco::output_nodes(g.g())))
+  {
+    if (auto mul = dynamic_cast<luci::CircleMul *>(node))
+      count++;
+  }
+  ASSERT_EQ(1, count);
+}
+
+TEST(FuseMulWithConvPass, activation_blocks_removal_NEG)
+{
+  luci::FuseMulWithConvPass pass;
+  ConvMulGraph g;
+  g.init(true, false);
+
+  ASSERT_FALSE(pass.run(g.g()));
+
+  // check Mul is not removed
+  int count = 0;
+  for (auto node : loco::active_nodes(loco::output_nodes(g.g())))
+  {
+    if (auto mul = dynamic_cast<luci::CircleMul *>(node))
+      count++;
+  }
+  ASSERT_EQ(1, count);
+}
diff --git a/compiler/luci/pass/src/FuseMulWithDivPass.cpp b/compiler/luci/pass/src/FuseMulWithDivPass.cpp
new file mode 100644 (file)
index 0000000..c4c7d81
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Pass/FuseMulWithDivPass.h"
+
+#include "helpers/NodeFiller.h"
+
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/IR/CircleNodes.h>
+
+namespace luci
+{
+
+namespace
+{
+
+// Return a new CircleConst with a new value
+luci::CircleConst *create_div_const_with_new_value(luci::CircleConst *div_const,
+                                                   luci::CircleConst *mul_const, float new_value)
+{
+  assert(div_const);                                       // FIX_CALLER_UNLESS
+  assert(div_const->dtype() == loco::DataType::FLOAT32);   // FIX_CALLER_UNLESS
+  assert(div_const->size<loco::DataType::FLOAT32>() == 1); // FIX_CALLER_UNLESS
+
+  auto new_div_const = div_const->graph()->nodes()->create<luci::CircleConst>();
+  new_div_const->dtype(loco::DataType::FLOAT32);
+  new_div_const->size<loco::DataType::FLOAT32>(1);
+  new_div_const->rank(1);
+  new_div_const->dim(0) = 1;
+  new_div_const->at<loco::DataType::FLOAT32>(0) = new_value;
+  new_div_const->shape_status(luci::ShapeStatus::VALID);
+  new_div_const->name(div_const->name() + ";" + mul_const->name());
+
+  luci::add_origin(new_div_const, luci::composite_origin(
+                                    {luci::get_origin(div_const), luci::get_origin(mul_const)}));
+
+  return new_div_const;
+}
+
+// Return a new CircleConst with a new value
+luci::CircleConst *create_mul_const_with_new_value(luci::CircleConst *mul_const,
+                                                   luci::CircleConst *div_const, float new_value)
+{
+  assert(mul_const);                                       // FIX_CALLER_UNLESS
+  assert(mul_const->dtype() == loco::DataType::FLOAT32);   // FIX_CALLER_UNLESS
+  assert(mul_const->size<loco::DataType::FLOAT32>() == 1); // FIX_CALLER_UNLESS
+
+  auto new_mul_const = mul_const->graph()->nodes()->create<luci::CircleConst>();
+  new_mul_const->dtype(loco::DataType::FLOAT32);
+  new_mul_const->rank(0);
+  new_mul_const->size<loco::DataType::FLOAT32>(1);
+  new_mul_const->scalar<loco::DataType::FLOAT32>() = new_value;
+  new_mul_const->shape_status(luci::ShapeStatus::VALID);
+  new_mul_const->name(mul_const->name() + ";" + div_const->name());
+
+  luci::add_origin(new_mul_const, luci::composite_origin(
+                                    {luci::get_origin(mul_const), luci::get_origin(div_const)}));
+
+  return new_mul_const;
+}
+
+/**
+ * Pass to fuse mul(one of the input is const scalar) and
+ * div(numerator is const scalar) as div
+ *
+ * BEFORE
+ *             [CircleNode]                                [Scalar_Mul_Const]
+ *                  |                                               |
+ *          [CirlceMul, (x=CircleNode, y=Scalar_Mul_Const)] --------
+ *                  |
+ *                  |                                     [Scalar_Div_Const]
+ *                  |                                             |
+ *           [CircleDiv, (x=Scalar_Div_Const, y=CirlceMul)] ------
+ *                  |
+ *             [CircleNode]
+ *
+ *  AFTER
+ *            [CircleNode]
+ *                 |                                          [Scalar_new_Div_Const]
+ *                 |                                                   |
+ *          [CircleDiv, (x=Scalar_new_Div_Const, y=CircleNode)] -------
+ *                 |
+ *            [CircleNode]
+ *
+ *          where Scalar_new_Div_Const = Scalar_Div_Const / Scalar_Mul_Const
+ *
+ **/
+bool fuse_mul_with_div_to_div(luci::CircleDiv *div)
+{
+  if (div->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return false;
+
+  luci::CircleConst *div_const = nullptr;
+  luci::CircleMul *mul = nullptr;
+  if (not luci::fill(&div_const, &mul).with_args_of(div))
+    return false;
+
+  if (div_const->dtype() != loco::DataType::FLOAT32)
+    return false;
+
+  if (div_const->size<loco::DataType::FLOAT32>() != 1)
+    return false;
+
+  if (mul->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return false;
+
+  luci::CircleNode *mul_input = nullptr;
+  luci::CircleConst *mul_const = nullptr;
+  if (not luci::fill(&mul_input, &mul_const).with_commutative_args_of(mul))
+    return false;
+
+  if (mul_const->dtype() != loco::DataType::FLOAT32)
+    return false;
+
+  if (mul_const->size<loco::DataType::FLOAT32>() != 1)
+    return false;
+
+  const auto div_value = div_const->at<loco::DataType::FLOAT32>(0);
+  const auto mul_value = mul_const->at<loco::DataType::FLOAT32>(0);
+
+  if (mul_value == 0)
+    return false;
+
+  const auto new_value = div_value / mul_value;
+
+  auto new_div_const = create_div_const_with_new_value(div_const, mul_const, new_value);
+  auto new_div = div->graph()->nodes()->create<luci::CircleDiv>();
+  new_div->fusedActivationFunction(luci::FusedActFunc::NONE);
+  new_div->x(new_div_const);
+  new_div->y(mul_input);
+  new_div->name(div->name());
+  luci::add_origin(new_div, luci::composite_origin({luci::get_origin(div), luci::get_origin(mul)}));
+
+  replace(div).with(new_div);
+
+  return true;
+}
+
+/**
+ * Pass to fuse mul(one of the input is const scalar) and
+ * div(numerator is const scalar) as mul
+ *
+ * BEFORE
+ *             [CircleNode]                                [Scalar_Mul_Const]
+ *                  |                                               |
+ *          [CirlceMul, (x=CircleNode, y=Scalar_Mul_Const)] --------
+ *                  |
+ *                  |                                     [Scalar_Div_Const]
+ *                  |                                             |
+ *           [CircleDiv, (x=CirlceMul, y=Scalar_Div_Const)] ------
+ *                  |
+ *             [CircleNode]
+ *
+ *  AFTER
+ *            [CircleNode]
+ *                 |                                          [Scalar_new_Mul_Const]
+ *                 |                                                   |
+ *          [CircleMul, (x=CircleNode, y=Scalar_new_Mul_Const)] -------
+ *                 |
+ *            [CircleNode]
+ *
+ *          where Scalar_new_Mul_Const = Scalar_Mul_Const / Scalar_Div_Const
+ *
+ **/
+bool fuse_mul_with_div_to_mul(luci::CircleDiv *div)
+{
+  if (div->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return false;
+
+  luci::CircleMul *mul = nullptr;
+  luci::CircleConst *div_const = nullptr;
+  if (not luci::fill(&mul, &div_const).with_args_of(div))
+    return false;
+
+  if (mul->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return false;
+
+  if (div_const->dtype() != loco::DataType::FLOAT32)
+    return false;
+  // TODO support other shape
+  if (div_const->size<loco::DataType::FLOAT32>() != 1)
+    return false;
+
+  luci::CircleNode *mul_input = nullptr;
+  luci::CircleConst *mul_const = nullptr;
+  if (not luci::fill(&mul_input, &mul_const).with_commutative_args_of(mul))
+    return false;
+
+  if (mul_const->dtype() != loco::DataType::FLOAT32)
+    return false;
+  // TODO support other shape
+  if (mul_const->size<loco::DataType::FLOAT32>() != 1)
+    return false;
+
+  const auto mul_value = mul_const->at<loco::DataType::FLOAT32>(0);
+  const auto div_value = div_const->at<loco::DataType::FLOAT32>(0);
+  const auto new_value = mul_value / div_value;
+  auto new_mul_const = create_mul_const_with_new_value(mul_const, div_const, new_value);
+
+  auto new_mul = div->graph()->nodes()->create<luci::CircleMul>();
+  new_mul->fusedActivationFunction(luci::FusedActFunc::NONE);
+  new_mul->x(mul_input);
+  new_mul->y(new_mul_const);
+  new_mul->name(mul->name());
+  luci::add_origin(new_mul, luci::composite_origin({luci::get_origin(div), luci::get_origin(mul)}));
+
+  replace(div).with(new_mul);
+
+  return true;
+}
+
+} // namespace
+
+bool FuseMulWithDivPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto div = dynamic_cast<luci::CircleDiv *>(node);
+    if (not div)
+      continue;
+
+    if (fuse_mul_with_div_to_div(div))
+      changed = true;
+
+    if (fuse_mul_with_div_to_mul(div))
+      changed = true;
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseMulWithDivPass.test.cpp b/compiler/luci/pass/src/FuseMulWithDivPass.test.cpp
new file mode 100644 (file)
index 0000000..67ad48e
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseMulWithDivPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class PatternMulDivGraphlet
+{
+public:
+  PatternMulDivGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    _mul = g->nodes()->create<luci::CircleMul>();
+    _mul->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _mul_const = g->nodes()->create<luci::CircleConst>();
+    _mul_const->rank(1);
+    _mul_const->dtype(loco::DataType::FLOAT32);
+    _mul_const->size<loco::DataType::FLOAT32>(1);
+    _mul_const->at<loco::DataType::FLOAT32>(0) = 1.1f;
+    _mul_const->shape_status(luci::ShapeStatus::VALID);
+
+    _div = g->nodes()->create<luci::CircleDiv>();
+    _div->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _div_const = g->nodes()->create<luci::CircleConst>();
+    _div_const->rank(1);
+    _div_const->dtype(loco::DataType::FLOAT32);
+    _div_const->size<loco::DataType::FLOAT32>(1);
+    _div_const->at<loco::DataType::FLOAT32>(0) = 2.2f;
+    _div_const->shape_status(luci::ShapeStatus::VALID);
+
+    _mul->name("_mul");
+    _mul_const->name("_mul_const");
+
+    _div->name("_div");
+    _div_const->name("_div_const");
+  }
+
+public:
+  luci::CircleMul *mul() { return _mul; }
+  luci::CircleConst *mul_const() { return _mul_const; }
+  luci::CircleDiv *div() { return _div; }
+  luci::CircleConst *div_const() { return _div_const; }
+
+protected:
+  luci::CircleMul *_mul = nullptr;
+  luci::CircleConst *_mul_const = nullptr;
+  luci::CircleDiv *_div = nullptr;
+  luci::CircleConst *_div_const = nullptr;
+};
+
+/**
+ *  Simple graph for test
+ *
+ *  BEFORE
+ *              [Input]
+ *                 |
+ *          [Mul, MUL_Scalar_Const]
+ *                 |
+ *          [Div, DIV_Scalar_Const]
+ *                 |
+ *             [Output]
+ *
+ *  AFTER
+ *              [Input]
+ *                 |
+ *          [Div, Scalar_Const_new]
+ *                 |
+ *             [Output]
+ *
+ *  WHERE: Scalar_Const_new = DIV_Scalar_Const / MUL_Scalar_Const
+ */
+class FuseMulDivPatternTestGraph : public TestIOGraph, public PatternMulDivGraphlet
+{
+public:
+  FuseMulDivPatternTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({1, 2, 3}, {1, 2, 3});
+    PatternMulDivGraphlet::init(g());
+
+    _mul->x(input());
+    _mul->y(_mul_const);
+
+    _div->x(_div_const);
+    _div->y(_mul);
+
+    output()->from(_div);
+  }
+};
+
+class FuseMulDivToMulPatternTestGraph : public TestIOGraph, public PatternMulDivGraphlet
+{
+public:
+  FuseMulDivToMulPatternTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({1, 2, 3}, {1, 2, 3});
+    PatternMulDivGraphlet::init(g());
+
+    _mul->x(input());
+    _mul->y(_mul_const);
+
+    _div->x(_mul);
+    _div->y(_div_const);
+
+    output()->from(_div);
+  }
+};
+
+} // namespace
+
+TEST(FuseMulWithDivPassTest, fus_mul_div_pattern)
+{
+  FuseMulDivPatternTestGraph g;
+  luci::FuseMulWithDivPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(FuseMulWithDivPassTest, fuse_mul_div_NEG)
+{
+  FuseMulDivPatternTestGraph g;
+  luci::FuseMulWithDivPass pass;
+
+  g.init();
+
+  // Add CircleRelu operation between CircleMean and Mul operations
+  auto relu = g.g()->nodes()->create<luci::CircleRelu>();
+  relu->name("relu");
+  relu->features(g.mul());
+  g.div()->y(relu);
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
+
+TEST(FuseMulWithDivPassTest, fuse_mul_div_to_mul_pattern)
+{
+  FuseMulDivToMulPatternTestGraph g;
+  luci::FuseMulWithDivPass pass;
+
+  g.init();
+
+  auto div = dynamic_cast<luci::CircleDiv *>(g.output()->from());
+  EXPECT_NE(div, nullptr);
+
+  EXPECT_TRUE(pass.run(g.g()));
+
+  auto mul = dynamic_cast<luci::CircleMul *>(g.output()->from());
+  EXPECT_NE(mul, nullptr);
+}
+
+TEST(FuseMulWithDivPassTest, fuse_mul_div_to_mul_NEG)
+{
+  FuseMulDivToMulPatternTestGraph g;
+  luci::FuseMulWithDivPass pass;
+
+  g.init();
+
+  // Add CircleRelu operation between CircleMul and Div operations
+  auto relu = g.g()->nodes()->create<luci::CircleRelu>();
+  relu->name("relu");
+  relu->features(g.mul());
+  g.div()->x(relu);
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
diff --git a/compiler/luci/pass/src/FuseRsqrtPass.cpp b/compiler/luci/pass/src/FuseRsqrtPass.cpp
new file mode 100644 (file)
index 0000000..eb3b2c6
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseRsqrtPass.h"
+#include "helpers/NodeFiller.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+#include <cmath>
+#include <cassert>
+
+namespace
+{
+
+/**
+ *  Fuse Sqrt + Div to Rsqrt (1/Sqrt -> Rsqrt)
+ *
+ *  BEFORE
+ *                 |
+ *            [CircleSqrt]
+ *   [CircleConst] |          where Const has value 1.0
+ *             |   |
+ *          [CircleDiv]
+ *              |
+ *
+ *  AFTER
+ *             |
+ *             |               [CircleSqrt]
+ *        [CircleRsqrt]   [CircleConst] |
+ *             |                    |   |
+ *             |                  [CircleDiv]
+ */
+
+// Float comparison
+bool same(float a, float b) { return fabs(a - b) < 1e-5; }
+
+class RsqrtPattern
+{
+public:
+  RsqrtPattern(luci::CircleDiv *candidate)
+  {
+    assert(candidate); // FIX_CALLER_UNLESS
+    _div = candidate;
+  }
+
+#define CHECK_OR_FALSE(condition) \
+  if (not(condition))             \
+    return false;
+
+public:
+  bool matched()
+  {
+    // Check pattern
+    CHECK_OR_FALSE(luci::fill(&_div_const, &_sqrt).with_args_of(_div));
+    _ifm = loco::must_cast<luci::CircleNode *>(_sqrt->x());
+
+    CHECK_OR_FALSE(_div->fusedActivationFunction() == luci::FusedActFunc::NONE);
+
+    // Check div_const = 1
+    switch (_div->dtype())
+    {
+      case loco::DataType::S16:
+        CHECK_OR_FALSE(_div_const->quantparam() != nullptr);
+        CHECK_OR_FALSE(_div_const->quantparam()->scale.size() == 1);
+        CHECK_OR_FALSE(_div_const->quantparam()->zerop.size() == 1);
+        CHECK_OR_FALSE(_div_const->quantparam()->zerop.at(0) == 0);
+        CHECK_OR_FALSE(_div_const->size<loco::DataType::S16>() == 1);
+        CHECK_OR_FALSE(same(1.0, _div_const->at<loco::DataType::S16>(0) *
+                                   _div_const->quantparam()->scale.at(0)));
+        break;
+      // TODO Support more dtypes
+      default:
+        return false;
+    }
+
+    return true;
+  }
+#undef CHECK_OR_FALSE
+
+public:
+  luci::CircleNode *_ifm = nullptr;
+  luci::CircleSqrt *_sqrt = nullptr;
+  luci::CircleDiv *_div = nullptr;
+  luci::CircleConst *_div_const = nullptr;
+};
+
+class FuseRsqrt final
+{
+public:
+  FuseRsqrt(const RsqrtPattern *p) : _p(p) {}
+
+public:
+  void apply(void);
+
+private:
+  luci::CircleRsqrt *create_rsqrt(loco::Graph *graph);
+
+private:
+  const RsqrtPattern *_p = nullptr;
+};
+
+luci::CircleRsqrt *FuseRsqrt::create_rsqrt(loco::Graph *graph)
+{
+  assert(graph);
+
+  auto rsqrt = graph->nodes()->create<luci::CircleRsqrt>();
+  rsqrt->x(_p->_ifm);
+  rsqrt->name(_p->_div->name() + "_rsqrt");
+
+  luci::copy_quantparam(_p->_div, rsqrt);
+
+  return rsqrt;
+}
+
+void FuseRsqrt::apply()
+{
+  auto graph = _p->_div->graph();
+
+  auto rsqrt = create_rsqrt(graph);
+
+  // set origin
+  std::vector<std::shared_ptr<luci::CircleNodeOrigin>> origin_vec{
+    luci::get_origin(_p->_sqrt), luci::get_origin(_p->_div), luci::get_origin(_p->_div_const)};
+
+  luci::add_origin(rsqrt, luci::composite_origin(origin_vec));
+
+  replace(_p->_div).with(rsqrt);
+}
+
+} // namespace
+
+namespace
+{
+
+bool fuse_rsqrt(luci::CircleDiv *div)
+{
+  assert(div);
+
+  RsqrtPattern pattern(div);
+  if (pattern.matched())
+  {
+    FuseRsqrt fuse(&pattern);
+    fuse.apply();
+    return true;
+  }
+
+  return false;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool FuseRsqrtPass::run(loco::Graph *g)
+{
+  bool changed = false;
+
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto div = dynamic_cast<luci::CircleDiv *>(node);
+    if (not div)
+      continue;
+
+    if (fuse_rsqrt(div))
+      changed = true;
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseRsqrtPass.test.cpp b/compiler/luci/pass/src/FuseRsqrtPass.test.cpp
new file mode 100644 (file)
index 0000000..425179a
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseRsqrtPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <cmath>
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+std::unique_ptr<luci::CircleQuantParam> gen_qparam(const std::vector<float> &s,
+                                                   const std::vector<int64_t> &zp)
+{
+  auto qparam = std::make_unique<luci::CircleQuantParam>();
+  {
+    for (auto scale : s)
+      qparam->scale.push_back(scale);
+
+    for (auto zerop : zp)
+      qparam->zerop.push_back(zerop);
+  }
+
+  return std::move(qparam);
+}
+
+class S16RsqrtGraphlet
+{
+public:
+  S16RsqrtGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    _sqrt = g->nodes()->create<luci::CircleSqrt>();
+    _div = g->nodes()->create<luci::CircleDiv>();
+    _div_const = g->nodes()->create<luci::CircleConst>();
+
+    _div->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+    _sqrt->dtype(loco::DataType::S16);
+    _div->dtype(loco::DataType::S16);
+    _div_const->dtype(loco::DataType::S16);
+
+    _div_const->size<loco::DataType::S16>(1);
+    _div_const->shape({1});
+    _div_const->at<loco::DataType::S16>(0) = 1;
+    _div_const->shape_status(luci::ShapeStatus::VALID);
+
+    _sqrt->quantparam(gen_qparam({1.0}, {0}));
+    _div->quantparam(gen_qparam({2.0}, {0}));
+    _div_const->quantparam(gen_qparam({1.0}, {0}));
+  }
+
+  void invalid_act() { _div->fusedActivationFunction(luci::FusedActFunc::RELU); }
+
+protected:
+  luci::CircleSqrt *_sqrt = nullptr;
+  luci::CircleDiv *_div = nullptr;
+  luci::CircleConst *_div_const = nullptr;
+};
+
+class FuseS16RsqrtTestGraph : public TestIOGraph, public S16RsqrtGraphlet
+{
+public:
+  FuseS16RsqrtTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({1}, {1});
+    S16RsqrtGraphlet::init(g());
+
+    _sqrt->x(input());
+    _div->x(_div_const);
+    _div->y(_sqrt);
+
+    output()->from(_div);
+  }
+};
+
+} // namespace
+
+TEST(FuseRsqrtPassTest, s16)
+{
+  FuseS16RsqrtTestGraph g;
+  luci::FuseRsqrtPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(FuseRsqrtPassTest, fuse_invalid_act_NEG)
+{
+  FuseS16RsqrtTestGraph g;
+  luci::FuseRsqrtPass pass;
+
+  g.init();
+  g.invalid_act();
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
diff --git a/compiler/luci/pass/src/FuseSliceWithTConvPass.cpp b/compiler/luci/pass/src/FuseSliceWithTConvPass.cpp
new file mode 100644 (file)
index 0000000..981ec1b
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseSliceWithTConvPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Service/CircleNodeClone.h>
+#include <luci/Service/Nodes/CircleConst.h>
+
+namespace
+{
+
+#define RETURN_FALSE_UNLESS(cond) \
+  if (not(cond))                  \
+    return false;
+
+inline int32_t compute_input_size(luci::Padding padding, int32_t image_size, int32_t filter_size,
+                                  int32_t stride)
+{
+  switch (padding)
+  {
+    case luci::Padding::SAME:
+      return (image_size + stride - 1) / stride;
+    case luci::Padding::VALID:
+      return (image_size + stride - filter_size) / stride;
+    default:
+      throw std::runtime_error("Unsupported padding");
+  }
+}
+
+inline int32_t extract_pad_value(int32_t stride, int32_t in_size, int32_t filter_size,
+                                 int32_t out_size)
+{
+  const int32_t padding = ((in_size - 1) * stride + filter_size - out_size) / 2;
+  return padding > 0 ? padding : 0;
+}
+
+inline uint32_t cal_offset(const luci::CircleConst *node, const uint32_t *indices)
+{
+  return indices[0] * node->dim(1).value() * node->dim(2).value() * node->dim(3).value() +
+         indices[1] * node->dim(2).value() * node->dim(3).value() +
+         indices[2] * node->dim(3).value() + indices[3];
+}
+
+luci::Padding compute_padding(const luci::CircleTransposeConv *tconv, int32_t out_height,
+                              int32_t out_width, int32_t pad_top, int32_t pad_left)
+{
+  auto const filter = dynamic_cast<luci::CircleConst *>(tconv->filter());
+  if (!filter)
+    return luci::Padding::UNDEFINED;
+
+  auto tconv_shape = dynamic_cast<luci::CircleConst *>(tconv->inputSizes());
+  if (!tconv_shape)
+    return luci::Padding::UNDEFINED;
+
+  luci::Padding padding = luci::Padding::UNDEFINED;
+  std::initializer_list<luci::Padding> paddings_to_check = {luci::Padding::VALID,
+                                                            luci::Padding::SAME};
+
+  auto const filter_height = filter->dim(1).value();
+  auto const filter_width = filter->dim(2).value();
+  auto const stride_height = tconv->stride()->h();
+  auto const stride_width = tconv->stride()->w();
+
+  for (auto padding_to_check : paddings_to_check)
+  {
+    auto const in_height =
+      compute_input_size(padding_to_check, out_height, filter_height, stride_height);
+    auto const pad_top_virtual =
+      extract_pad_value(stride_height, in_height, filter_height, out_height);
+    if (pad_top_virtual != pad_top)
+      continue;
+
+    auto const in_width =
+      compute_input_size(padding_to_check, out_width, filter_width, stride_width);
+    auto const pad_left_virtual =
+      extract_pad_value(stride_width, in_width, filter_width, out_width);
+    if (pad_left_virtual == pad_left)
+    {
+      padding = padding_to_check; // correct padding is found
+      break;
+    }
+  }
+
+  return padding;
+}
+
+/**
+ *  Fuse Slice with CircleTransposeConv if possible
+ *
+ *  NOTE: In case predecessor of slice is tconv, we can try to merge slice with tconv,
+ *  because spatial slice is reduction so as padding for tconv,
+ *  while channels slice reduction can be directly modeled in tconv.
+ *  For now there is no option to set explicitely pad values for
+ *  CircleTransposeConv. Only using VALID/SAME and output shape is the only way
+ *  to set pad values. That is why not all numerical values of pad are legal for such
+ *  transform.
+ *
+ *  BEFORE
+ *                    |
+ *           [CircleTransposeConv]
+ *                    |
+ *               [CircleSlice]
+ *                    |
+ *
+ *  AFTER
+ *                    |
+ *            [CircleTransposeConv] (with m.b. changed padding, output shape, and filter/bias)
+ *                    |
+ *
+ */
+
+bool fuse_slice_with_tconv(luci::CircleSlice *slice)
+{
+  // NOTE: assume NHWC layout
+  auto tconv = dynamic_cast<luci::CircleTransposeConv *>(slice->input());
+  RETURN_FALSE_UNLESS(tconv != nullptr);
+
+  // offset
+  auto begin = dynamic_cast<luci::CircleConst *>(slice->begin());
+  // sanity check
+  RETURN_FALSE_UNLESS(begin != nullptr && begin->dtype() == loco::DataType::S32 &&
+                      begin->rank() == 1);
+
+  // output shape
+  auto out_shape = dynamic_cast<luci::CircleConst *>(slice->size());
+  // sanity check
+  RETURN_FALSE_UNLESS(out_shape != nullptr && out_shape->dtype() == loco::DataType::S32 &&
+                      out_shape->rank() == 1);
+
+  // output shape of tconv
+  auto tconv_shape = dynamic_cast<luci::CircleConst *>(tconv->inputSizes());
+  // sanity check
+  RETURN_FALSE_UNLESS(tconv_shape != nullptr && tconv_shape->dtype() == loco::DataType::S32 &&
+                      tconv_shape->rank() == 1);
+
+  // no update if batch dimension is processed in slice
+  RETURN_FALSE_UNLESS(begin->at<loco::DataType::S32>(0) == 0 &&
+                      out_shape->at<loco::DataType::S32>(0) ==
+                        tconv_shape->at<loco::DataType::S32>(0));
+
+  // filter
+  auto const tconv_filter = dynamic_cast<luci::CircleConst *>(tconv->filter());
+  // sanity check
+  RETURN_FALSE_UNLESS(tconv_filter != nullptr && tconv_filter->rank() == 4 &&
+                      tconv_filter->dtype() == loco::DataType::FLOAT32);
+
+  // bias
+  auto const tconv_bias = dynamic_cast<luci::CircleConst *>(tconv->bias());
+  // Only support const bias
+  // TODO Support non-const bias
+  RETURN_FALSE_UNLESS(tconv_bias != nullptr && tconv_bias->rank() == 1 &&
+                      tconv_bias->dtype() == loco::DataType::FLOAT32);
+
+  auto const out_height = out_shape->at<loco::DataType::S32>(1);
+  auto const out_width = out_shape->at<loco::DataType::S32>(2);
+
+  auto const pad_top = begin->at<loco::DataType::S32>(1);
+  auto const pad_left = begin->at<loco::DataType::S32>(2);
+
+  // As there is no option to set numerical values of pad explicitly for CircleTransposeConv
+  // we need to be sure that interpretation of PADDING + OUTPUT_SHAPE will produce
+  // the pad values, defined by slice. If possible compute_padding will return correct
+  // padding value, otherwise it will return UNDEFINED
+  auto const padding = compute_padding(tconv, out_height, out_width, pad_top, pad_left);
+  if (padding == luci::Padding::UNDEFINED)
+    return false; // impossible to fuse
+
+  auto const out_channels = out_shape->at<loco::DataType::S32>(3);
+  // update filter and bias in case it's needed
+  loco::Node *fused_filter = tconv->filter();
+  loco::Node *fused_bias = tconv->bias();
+  // Channel-direction slice
+  // Corresponding weights/bias of TConv is sliced.
+  if (begin->at<loco::DataType::S32>(3) != 0 ||
+      out_channels != tconv_shape->at<loco::DataType::S32>(3))
+  {
+    // fused filter
+    auto const in_channels = tconv_filter->dim(3).value();
+
+    luci::CircleConst *fused_tconv_filter = luci::clone(tconv_filter);
+    fused_tconv_filter->dim(0).set(out_channels); // out_channels
+    // update size due to channels change
+    fused_tconv_filter->size<loco::DataType::FLOAT32>(out_channels * tconv_filter->dim(1).value() *
+                                                      tconv_filter->dim(2).value() * in_channels);
+    auto const ch_offset = begin->at<loco::DataType::S32>(3);
+    // set reduced filter values
+    for (uint32_t out_chan = 0; out_chan < fused_tconv_filter->dim(0).value(); out_chan++)
+    {
+      for (uint32_t out_height = 0; out_height < fused_tconv_filter->dim(1).value(); out_height++)
+      {
+        for (uint32_t out_width = 0; out_width < fused_tconv_filter->dim(2).value(); out_width++)
+        {
+          for (uint32_t in_chan = 0; in_chan < fused_tconv_filter->dim(3).value(); in_chan++)
+          {
+            uint32_t indices[4] = {out_chan, out_height, out_width, in_chan};
+            uint32_t old_indices[4] = {out_chan + ch_offset, out_height, out_width, in_chan};
+            auto const data =
+              tconv_filter->at<loco::DataType::FLOAT32>(cal_offset(tconv_filter, old_indices));
+            fused_tconv_filter->at<loco::DataType::FLOAT32>(
+              cal_offset(fused_tconv_filter, indices)) = data;
+          }
+        }
+      }
+    }
+    fused_tconv_filter->name(tconv_filter->name() + "/FusedSlice");
+    luci::add_origin(fused_tconv_filter, luci::get_origin(tconv_shape));
+    fused_filter = fused_tconv_filter;
+
+    // fused bias
+    luci::CircleConst *fused_tconv_bias = luci::clone(tconv_bias);
+    fused_tconv_bias->size<loco::DataType::FLOAT32>(out_channels);
+    fused_tconv_bias->dim(0).set(out_channels); // out_channels
+    // set reduced bias values
+    for (int32_t c = 0; c < out_channels; c++)
+    {
+      auto const data = tconv_bias->at<loco::DataType::FLOAT32>(c + ch_offset);
+      fused_tconv_bias->at<loco::DataType::FLOAT32>(c) = data;
+    }
+
+    fused_tconv_bias->name(tconv_bias->name() + "/FusedSlice");
+    luci::add_origin(fused_tconv_bias, luci::get_origin(tconv_bias));
+    fused_bias = fused_tconv_bias;
+  }
+
+  auto *fused_tconv_shape = luci::clone(tconv_shape);
+  // spatial dimensions
+  fused_tconv_shape->at<loco::DataType::S32>(1) = out_height;
+  fused_tconv_shape->at<loco::DataType::S32>(2) = out_width;
+  // channels
+  fused_tconv_shape->at<loco::DataType::S32>(3) = out_channels;
+  fused_tconv_shape->name(tconv_shape->name() + "/FusedSlice");
+  luci::add_origin(fused_tconv_shape, luci::get_origin(tconv_shape));
+
+  // Configure new CircleTransposeConv operation.
+  auto *fused_tconv =
+    loco::must_cast<luci::CircleTransposeConv *>(luci::clone_node(tconv, slice->graph()));
+  fused_tconv->inputSizes(fused_tconv_shape);
+  fused_tconv->outBackprop(tconv->outBackprop());
+  fused_tconv->filter(fused_filter);
+  fused_tconv->bias(fused_bias);
+  fused_tconv->padding(padding);
+  fused_tconv->name(tconv->name() + "/FusedSlice");
+  luci::add_origin(fused_tconv,
+                   luci::composite_origin({luci::get_origin(tconv), luci::get_origin(slice)}));
+
+  // Replace old slice operation with new fused_tconv with merged pad values
+  replace(slice).with(fused_tconv);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool FuseSliceWithTConvPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto slice = dynamic_cast<luci::CircleSlice *>(node);
+    if (not slice)
+      continue;
+
+    if (fuse_slice_with_tconv(slice))
+      changed = true;
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/FuseSliceWithTConvPass.test.cpp b/compiler/luci/pass/src/FuseSliceWithTConvPass.test.cpp
new file mode 100644 (file)
index 0000000..71372d8
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/FuseSliceWithTConvPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+/**
+ *  TConv->Slice graph for test
+ *
+ *        [CircleInput]
+ *              |
+ *              |
+ *     [CircleTransposeConv]
+ *              |
+ *              |
+ *        [CircleSlice]
+ *              |
+ *              |
+ *        [CircleOutput]
+ */
+struct TConvSliceGraph : public luci::test::TestIOGraph
+{
+  luci::CircleTransposeConv *_tconv = nullptr;
+  luci::CircleSlice *_slice = nullptr;
+  luci::CircleConst *_filter = nullptr;
+  luci::CircleConst *_bias = nullptr;
+  luci::CircleConst *_tconv_shape = nullptr;
+  luci::CircleConst *_slice_offset = nullptr;
+  luci::CircleConst *_slice_size = nullptr;
+
+  TConvSliceGraph(uint32_t h, uint32_t w, uint32_t pads[4])
+  {
+    // pads={pad_top, pad_bottom, pad_left, pad_right}
+    uint32_t channels = 32;
+    uint32_t k_h = 3, k_w = 3;
+    auto const tconv_h = (h - 1) * 2 + k_h;
+    auto const tconv_w = (w - 1) * 2 + k_w;
+    auto const out_h = tconv_h - pads[0] - pads[1];
+    auto const out_w = tconv_w - pads[2] - pads[3];
+
+    // graph input and output
+    TestIOGraph::init({1, h, w, channels}, {1, out_h, out_w, channels});
+
+    _filter = g()->nodes()->create<luci::CircleConst>();
+    _filter->dtype(loco::DataType::FLOAT32);
+    _filter->rank(4);
+    _filter->shape({channels, k_h, k_w, channels});
+    _filter->shape_status(luci::ShapeStatus::VALID);
+    _filter->size<loco::DataType::FLOAT32>(channels * k_h * k_w * channels);
+    _filter->name("filter");
+
+    _bias = g()->nodes()->create<luci::CircleConst>();
+    _bias->dtype(loco::DataType::FLOAT32);
+    _bias->rank(1);
+    _bias->shape({channels});
+    _bias->shape_status(luci::ShapeStatus::VALID);
+    _bias->size<loco::DataType::FLOAT32>(channels);
+    _bias->name("bias");
+
+    _tconv_shape = g()->nodes()->create<luci::CircleConst>();
+    _tconv_shape->dtype(loco::DataType::S32);
+    _tconv_shape->rank(1);
+    _tconv_shape->shape({4});
+    _tconv_shape->shape_status(luci::ShapeStatus::VALID);
+    _tconv_shape->size<loco::DataType::S32>(4);
+    _tconv_shape->at<loco::DataType::S32>(0) = 1;
+    _tconv_shape->at<loco::DataType::S32>(3) = channels;
+    _tconv_shape->at<loco::DataType::S32>(1) = tconv_h;
+    _tconv_shape->at<loco::DataType::S32>(2) = tconv_w;
+    _tconv_shape->name("tconv_shape");
+
+    _tconv = g()->nodes()->create<luci::CircleTransposeConv>();
+    _tconv->filter(_filter);
+    _tconv->bias(_bias);
+    _tconv->inputSizes(_tconv_shape);
+    _tconv->outBackprop(input());
+    _tconv->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _tconv->dtype(loco::DataType::FLOAT32);
+    _tconv->padding(luci::Padding::VALID);
+    _tconv->stride()->h(2);
+    _tconv->stride()->w(2);
+    _tconv->name("tconv");
+
+    // offset to be used in slice
+    _slice_offset = g()->nodes()->create<luci::CircleConst>();
+    _slice_offset->dtype(loco::DataType::S32);
+    _slice_offset->rank(1);
+    _slice_offset->shape({4});
+    _slice_offset->shape_status(luci::ShapeStatus::VALID);
+    _slice_offset->size<loco::DataType::S32>(4);
+    _slice_offset->at<loco::DataType::S32>(0) = 0;
+    _slice_offset->at<loco::DataType::S32>(3) = 0;
+    _slice_offset->at<loco::DataType::S32>(1) = pads[0];
+    _slice_offset->at<loco::DataType::S32>(2) = pads[2];
+    _slice_offset->name("slice_offset");
+
+    _slice_size = g()->nodes()->create<luci::CircleConst>();
+    _slice_size->dtype(loco::DataType::S32);
+    _slice_size->rank(1);
+    _slice_size->shape({4});
+    _slice_size->shape_status(luci::ShapeStatus::VALID);
+    _slice_size->size<loco::DataType::S32>(4);
+    _slice_size->at<loco::DataType::S32>(0) = 1;
+    _slice_size->at<loco::DataType::S32>(3) = channels;
+    _slice_size->at<loco::DataType::S32>(1) = out_h;
+    _slice_size->at<loco::DataType::S32>(2) = out_w;
+    _slice_size->name("slice_size");
+
+    _slice = g()->nodes()->create<luci::CircleSlice>();
+    _slice->begin(_slice_offset);
+    _slice->size(_slice_size);
+    _slice->input(_tconv);
+    _slice->name("slice");
+
+    output()->from(_slice);
+  }
+};
+
+} // namespace
+
+TEST(FuseSliceWithTConvPassTest, simple_test)
+{
+  /**
+   *  tests:
+   *    1) fusion pass has nonnull name
+   *    2) fusion runs successfully for float32 TConvSlice graph
+   *    3) resulting graph has the following structure:
+   *
+   *      [CircleTransposeConv] (with output_shape = shape_of_the_slice)
+   *              |
+   *              |
+   *           [Output]
+   */
+  luci::FuseSliceWithTConvPass pass;
+  uint32_t pads[4] = {0, 2, 0, 2};
+  uint32_t h = 8, w = 8;
+  TConvSliceGraph graph(h, w, pads);
+  auto const out_h = graph._slice_size->at<loco::DataType::S32>(1);
+  auto const out_w = graph._slice_size->at<loco::DataType::S32>(2);
+
+  auto const name = pass.name();
+  ASSERT_NE(nullptr, name);
+
+  auto ret = pass.run(graph.g());
+  EXPECT_TRUE(ret);
+
+  auto const fused_tconv = dynamic_cast<luci::CircleTransposeConv *>(graph.output()->from());
+  EXPECT_NE(nullptr, fused_tconv);
+
+  EXPECT_EQ(luci::Padding::VALID, fused_tconv->padding());
+
+  auto const out_size = dynamic_cast<luci::CircleConst *>(fused_tconv->inputSizes());
+  EXPECT_NE(nullptr, out_size);
+  EXPECT_EQ(out_h, out_size->at<loco::DataType::S32>(1)); // h
+  EXPECT_EQ(out_w, out_size->at<loco::DataType::S32>(2)); // 2
+}
+
+TEST(FuseSliceWithTConvPassTest, wrong_condition_NEG)
+{
+  luci::FuseSliceWithTConvPass pass;
+  uint32_t pads[4] = {3, 3, 3, 3}; // no fusion is possible with these pads
+  TConvSliceGraph graph(8, 8, pads);
+
+  auto ret = pass.run(graph.g());
+  EXPECT_FALSE(ret);
+}
diff --git a/compiler/luci/pass/src/InsertQuantizeOpOnDTypeMismatch.cpp b/compiler/luci/pass/src/InsertQuantizeOpOnDTypeMismatch.cpp
new file mode 100644 (file)
index 0000000..b10071b
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "InsertQuantizeOpOnDTypeMismatch.h"
+#include "QuantizationUtils.h"
+
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Log.h>
+
+#include <limits> // std::numeric_limits
+
+using namespace luci;
+
+namespace
+{
+
+// Update u8 node to i16
+// Qparam of i16 is inferred from the qparam of u8
+void update_u8_to_i16(luci::CircleNode *node)
+{
+  assert(node->dtype() == loco::DataType::U8); // FIX_CALLER_UNLESS
+
+  node->dtype(loco::DataType::S16);
+
+  auto qparam = node->quantparam();
+  assert(qparam);
+  assert(qparam->scale.size() == 1);
+  assert(qparam->zerop.size() == 1);
+
+  auto u8_scale = qparam->scale[0];
+  auto u8_zerop = qparam->zerop[0];
+
+  auto min = u8_scale * (-u8_zerop);
+  auto max = u8_scale * (255 - u8_zerop);
+
+  float s16_scale{0};
+  int64_t s16_zerop{0};
+  float nudged_min{0};
+  float nudged_max{0};
+
+  compute_sym_scale(min, max, s16_scale, nudged_min, nudged_max);
+
+  auto quantparam = std::make_unique<CircleQuantParam>();
+  quantparam->scale.push_back(s16_scale);
+  quantparam->zerop.push_back(s16_zerop);
+
+  node->quantparam(std::move(quantparam));
+}
+
+// Update i16 node to u8 node
+// Qparam of u8 is inferred from the qparam of i16
+void update_i16_to_u8(luci::CircleNode *node)
+{
+  assert(node->dtype() == loco::DataType::S16); // FIX_CALLER_UNLESS
+
+  node->dtype(loco::DataType::U8);
+
+  auto qparam = node->quantparam();
+  assert(qparam);
+  assert(qparam->scale.size() == 1);
+  assert(qparam->zerop.size() == 1);
+
+  auto s16_scale = qparam->scale[0];
+  assert(qparam->zerop[0] == 0);
+
+  auto max = s16_scale * std::numeric_limits<int16_t>::max();
+  auto min = -max;
+
+  float u8_scale{0};
+  int64_t u8_zerop{0};
+  float nudged_min{0};
+  float nudged_max{0};
+
+  compute_asym_scale_zp(min, max, u8_scale, u8_zerop, nudged_min, nudged_max);
+
+  auto quantparam = std::make_unique<CircleQuantParam>();
+  quantparam->scale.push_back(u8_scale);
+  quantparam->zerop.push_back(u8_zerop);
+
+  node->quantparam(std::move(quantparam));
+}
+
+// Create a Quantize Op which has the same
+// dtype, shape, and qparam with node
+luci::CircleQuantize *create_quantize_op(luci::CircleNode *node)
+{
+  auto quantize = node->graph()->nodes()->create<CircleQuantize>();
+  quantize->name(node->name() + "_Quantize");
+  quantize->dtype(node->dtype());
+  quantize->rank(node->rank());
+  for (uint32_t i = 0; i < node->rank(); i++)
+    quantize->dim(i).set(node->dim(i).value());
+
+  quantize->shape_status(luci::ShapeStatus::VALID);
+
+  assert(node->quantparam()); // FIX_CALLER_UNLESS
+  copy_quantparam(node, quantize);
+
+  luci::add_origin(quantize, luci::get_origin(node));
+
+  return quantize;
+}
+
+} // namespace
+
+namespace luci
+{
+
+void InsertQuantizeOpOnDTypeMismatch::visit(luci::CircleFullyConnected *node)
+{
+  auto input = loco::must_cast<luci::CircleNode *>(node->input());
+
+  // Input dtype == Output dtype. No problem
+  if (input->dtype() == node->dtype())
+    return;
+
+  // Skip if node has bias
+  if (dynamic_cast<luci::CircleOutputExclude *>(node->bias()) == nullptr)
+    return;
+
+  if (node->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return;
+
+  // Only cares quantized case
+  if (not is_quantized(input))
+    return;
+
+  if (not is_quantized(node))
+    return;
+
+  // Let's support limited case
+  // TODO Extend this to another dtype
+  if (input->dtype() != loco::DataType::U8)
+    return;
+
+  if (node->dtype() != loco::DataType::S16)
+    return;
+
+  // Create Quantize Op
+  auto quant_op = create_quantize_op(node);
+
+  // Insert Quantize Op after node
+  loco::replace(node).with(quant_op);
+  quant_op->input(node);
+
+  // Update node's dtype and qparam from i16 to u8
+  // NOTE This would severely degrade accuracy. It is
+  // important to mitigate this accuracy drop in backend.
+  update_i16_to_u8(node);
+}
+
+void InsertQuantizeOpOnDTypeMismatch::visit(luci::CircleMul *node)
+{
+  auto x = loco::must_cast<luci::CircleNode *>(node->x());
+  auto y = loco::must_cast<luci::CircleNode *>(node->y());
+
+  assert(x->dtype() == y->dtype()); // FIX_CALLER_UNLESS
+
+  // Ignore invalid dtype
+  if (x->dtype() != y->dtype())
+    return;
+
+  if (node->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return;
+
+  // Input dtype == Output dtype. No problem
+  if (x->dtype() == node->dtype())
+    return;
+
+  // Only cares quantized case
+  if (not is_quantized(x))
+    return;
+
+  if (not is_quantized(y))
+    return;
+
+  if (not is_quantized(node))
+    return;
+
+  // Let's support limited case
+  // TODO Extend this to another dtype
+  if (x->dtype() != loco::DataType::S16)
+    return;
+
+  if (node->dtype() != loco::DataType::U8)
+    return;
+
+  // Create Quantize Op
+  auto quant_op = create_quantize_op(node);
+
+  // Insert Quantize Op after node
+  loco::replace(node).with(quant_op);
+  quant_op->input(node);
+
+  // Update node's dtype and qparam from u8 to i16
+  update_u8_to_i16(node);
+}
+
+void InsertQuantizeOpOnDTypeMismatch::visit(luci::CircleBatchMatMul *node)
+{
+  auto x = loco::must_cast<luci::CircleNode *>(node->x());
+  auto y = loco::must_cast<luci::CircleNode *>(node->y());
+
+  assert(x->dtype() == y->dtype()); // FIX_CALLER_UNLESS
+
+  // Ignore invalid dtype
+  if (x->dtype() != y->dtype())
+    return;
+
+  if (node->adj_x() or node->adj_y())
+    return;
+
+  // Input dtype == Output dtype. No problem
+  if (x->dtype() == node->dtype())
+    return;
+
+  // Only cares quantized case
+  if (not is_quantized(x))
+    return;
+
+  if (not is_quantized(y))
+    return;
+
+  if (not is_quantized(node))
+    return;
+
+  // Let's support limited case
+  // TODO Extend this to another dtype
+  if (x->dtype() != loco::DataType::S16)
+    return;
+
+  if (node->dtype() != loco::DataType::U8)
+    return;
+
+  // Create Quantize Op
+  auto quant_op = create_quantize_op(node);
+
+  // Insert Quantize Op after node
+  loco::replace(node).with(quant_op);
+  quant_op->input(node);
+
+  // Update node's dtype and qparam from i16 to u8
+  update_u8_to_i16(node);
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/InsertQuantizeOpOnDTypeMismatch.h b/compiler/luci/pass/src/InsertQuantizeOpOnDTypeMismatch.h
new file mode 100644 (file)
index 0000000..e4fe231
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LUCI_INSERT_QUANTIZE_OP_ON_DTYPE_MISMATCH_H__
+#define __LUCI_INSERT_QUANTIZE_OP_ON_DTYPE_MISMATCH_H__
+
+#include <luci/IR/CircleNodeVisitor.h>
+
+namespace luci
+{
+
+struct InsertQuantizeOpOnDTypeMismatch final : public luci::CircleNodeMutableVisitor<void>
+{
+  InsertQuantizeOpOnDTypeMismatch() = default;
+
+private:
+  void visit(luci::CircleNode *) {}
+
+  void visit(luci::CircleFullyConnected *node);
+  void visit(luci::CircleMul *node);
+  void visit(luci::CircleBatchMatMul *node);
+
+  // TODO Support more operators
+};
+
+} // namespace luci
+
+#endif // __LUCI_INSERT_QUANTIZE_OP_ON_DTYPE_MISMATCH_H__
diff --git a/compiler/luci/pass/src/InsertQuantizeOpOnDTypeMismatch.test.cpp b/compiler/luci/pass/src/InsertQuantizeOpOnDTypeMismatch.test.cpp
new file mode 100644 (file)
index 0000000..0d2ec52
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "InsertQuantizeOpOnDTypeMismatch.h"
+#include "PassTestGraphs.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+std::unique_ptr<luci::CircleQuantParam> gen_qparam(float s, int64_t zp)
+{
+  auto qparam = std::make_unique<luci::CircleQuantParam>();
+  {
+    qparam->scale.push_back(s);
+    qparam->zerop.push_back(zp);
+  }
+
+  return std::move(qparam);
+}
+
+/**
+ *  Mul graph for test
+ *
+ * BEFORE
+ *
+ *   [Input(s16)]    [Const(s16)]
+ *             \      /
+ *            [Mul(u8)]
+ *                |
+ *           [Output(u8)]
+ *
+ * AFTER
+ *
+ *   [Input(s16)]    [Const(s16)]
+ *             \      /
+ *            [Mul(s16)]
+ *                |
+ *          [Quantize(u8)]
+ *                |
+ *           [Output(u8)]
+ */
+class MulGraphlet
+{
+public:
+  MulGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    _mul = g->nodes()->create<luci::CircleMul>();
+    _const = g->nodes()->create<luci::CircleConst>();
+
+    _mul->dtype(loco::DataType::U8);
+    _const->dtype(loco::DataType::S16);
+
+    _mul->quantparam(std::move(gen_qparam(1, 0)));
+    _const->quantparam(std::move(gen_qparam(1, 0)));
+
+    _mul->shape({2, 2, 2});
+
+    _mul->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+    _mul->name("mul");
+    _const->name("const");
+  }
+
+public:
+  luci::CircleMul *mul(void) { return _mul; }
+
+protected:
+  luci::CircleMul *_mul = nullptr;
+  luci::CircleConst *_const = nullptr;
+};
+
+class DtypeMisMatchMulTestGraph : public TestIOGraph, public MulGraphlet
+{
+public:
+  void init(void)
+  {
+    TestIOGraph::init({2, 2, 2}, {2, 2, 2});
+
+    input()->dtype(loco::DataType::S16);
+    output()->dtype(loco::DataType::U8);
+
+    input()->quantparam(std::move(gen_qparam(1, 0)));
+    output()->quantparam(std::move(gen_qparam(1, 0)));
+
+    MulGraphlet::init(g());
+
+    _mul->x(input());
+    _mul->y(_const);
+
+    output()->from(_mul);
+  }
+};
+
+} // namespace
+
+TEST(InsertQuantizeOpOnDTypeMismatchTest, mul)
+{
+  DtypeMisMatchMulTestGraph g;
+
+  luci::InsertQuantizeOpOnDTypeMismatch visitor;
+
+  g.init();
+
+  auto node = g.mul();
+  node->accept(&visitor);
+
+  // Quantize Op is created
+  EXPECT_NE(nullptr, dynamic_cast<luci::CircleQuantize *>(g.output()->from()));
+
+  // Mul's dtype is changed from U8 to S16
+  EXPECT_EQ(loco::DataType::S16, g.mul()->dtype());
+}
+
+TEST(InsertQuantizeOpOnDTypeMismatchTest, mul_dtype_match_NEG)
+{
+  DtypeMisMatchMulTestGraph g;
+
+  luci::InsertQuantizeOpOnDTypeMismatch visitor;
+
+  g.init();
+
+  auto node = g.mul();
+  node->dtype(loco::DataType::S16);
+
+  node->accept(&visitor);
+
+  // Quantize Op is not created
+  EXPECT_EQ(nullptr, dynamic_cast<luci::CircleQuantize *>(g.output()->from()));
+}
index f5ae24f..f0b0f4e 100644 (file)
@@ -20,6 +20,9 @@
 #include <loco.h>
 #include <luci/IR/CircleNodes.h>
 
+#include <luci/test/TestIOGraph.h>
+#include <luci/test/TestShape.h>
+
 namespace luci
 {
 
@@ -137,6 +140,44 @@ protected:
   luci::CircleAdd *_add = nullptr;
 };
 
+/**
+ *  CommonSubExpressionEliminationTestGraph is a base class for testing
+ *  common subexpression elimination pass. It creates Input and Output
+ *  in the below graph. Child classes must implement Expression.
+ *
+ *           [Input]
+ *           /     \
+ *  [Expression]    [Expression]
+ *         |              |
+ *    [Output 1]      [Output 2]
+ *
+ *    Expression should satisfy the below conditions
+ *    - Input type == Output type
+ *    - Input shape == Output shape
+ *    - Expression 1 and 2 are semantically equal
+ */
+class CommonSubExpressionEliminationTestGraph : public test::TestIsGraphlet<1>,
+                                                public test::TestOsGraphlet<2>
+{
+public:
+  virtual void init(const std::initializer_list<test::ShapeU32> shape_in,
+                    const std::initializer_list<test::ShapeU32> shape_out)
+  {
+    test::TestIsGraphlet<1>::init(g(), shape_in);
+    test::TestOsGraphlet<2>::init(g(), shape_out);
+
+    auto expr1 = createExpression(input(0), "expr1");
+    auto expr2 = createExpression(input(0), "expr2");
+
+    output(0)->from(expr1);
+    output(1)->from(expr2);
+  }
+
+  virtual ~CommonSubExpressionEliminationTestGraph() = default;
+
+  virtual loco::Node *createExpression(luci::CircleNode *ifm, const std::string &name) = 0;
+};
+
 } // namespace luci
 
 #endif // __LUCI_PASS_TEST_GRAPHS_H__
index aaadb28..b7c5ee2 100644 (file)
@@ -141,7 +141,7 @@ struct PropagateQParamForward final : public luci::CircleNodeMutableVisitor<bool
       case luci::ActivationQType::PreDefinedLogistic:
       case luci::ActivationQType::PreDefinedTanh:
       case luci::ActivationQType::PreDefinedSoftmax:
-        node->quantparam(luci::make_predefined_qparam(qtype, node->dtype()));
+        node->quantparam(luci::make_predefined_qparam(qtype, node->dtype(), node->quantparam()));
         break;
       case luci::ActivationQType::IntScale:
         luci::set_int_scale(node);
index 3e3cdde..33d75ce 100644 (file)
@@ -101,14 +101,26 @@ void symmetric_wquant_with_minmax_per_layer(CircleConst *node, float min, float
   }
 }
 
+int32_t max_for_sym_quant(const loco::DataType &type)
+{
+  if (type == loco::DataType::S4)
+    return std::numeric_limits<int8_t>::max() >> 4;
+  else if (type == loco::DataType::S8)
+    return std::numeric_limits<int8_t>::max();
+  else if (type == loco::DataType::S16)
+    return std::numeric_limits<int16_t>::max();
+  else
+    throw std::runtime_error("Unsupported dtype for symmetric quantization");
+};
+
 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);
+  assert(out_type == loco::DataType::S4 || out_type == loco::DataType::S8 ||
+         out_type == loco::DataType::S16);
 
-  const int32_t kMaxScale = (out_type == loco::DataType::S16) ? std::numeric_limits<int16_t>::max()
-                                                              : std::numeric_limits<int8_t>::max();
+  const int32_t kMaxScale = max_for_sym_quant(out_type);
   const int32_t kMinScale = -kMaxScale;
   const double qmin_double = kMinScale;
   const double qmax_double = kMaxScale;
@@ -343,13 +355,16 @@ ActivationQType activation_qtype(const CircleNode *node)
 }
 
 std::unique_ptr<CircleQuantParam> make_predefined_qparam(ActivationQType qtype,
-                                                         loco::DataType dtype)
+                                                         loco::DataType dtype,
+                                                         CircleQuantParam *old_quant_param)
 {
   auto qparam = std::make_unique<CircleQuantParam>();
 
-  auto set_qparam = [&qparam](float scale, int64_t zp) {
+  auto set_qparam = [&qparam, old_quant_param](float scale, int64_t zp) {
     qparam->scale.emplace_back(scale);
     qparam->zerop.emplace_back(zp);
+    qparam->min = old_quant_param->min;
+    qparam->max = old_quant_param->max;
   };
 
   switch (qtype)
@@ -435,6 +450,12 @@ void quant_const(luci::CircleConst *node, loco::DataType quant_type)
   auto quantparam = std::make_unique<luci::CircleQuantParam>();
   quantparam->scale.push_back(scaling_factor);
   quantparam->zerop.push_back(zp);
+  // Copy min and max values if it exists
+  if (node->quantparam())
+  {
+    quantparam->min = node->quantparam()->min;
+    quantparam->max = node->quantparam()->max;
+  }
   node->quantparam(std::move(quantparam));
 }
 
@@ -508,4 +529,32 @@ void warn_accuracy_with_range(luci::CircleNode *n)
   }
 }
 
+bool is_onnx_dequantize_linear(const luci::CircleCustom *node)
+{
+  if (node->numInputs() != 3)
+    return false;
+
+  if (node->numOutputs() != 1)
+    return false;
+
+  if (node->custom_code() != "ONNXDequantizeLinear")
+    return false;
+
+  return true;
+}
+
+bool is_onnx_quantize_linear(const luci::CircleCustom *node)
+{
+  if (node->numInputs() != 3)
+    return false;
+
+  if (node->numOutputs() != 1)
+    return false;
+
+  if (node->custom_code() != "ONNXQuantizeLinear")
+    return false;
+
+  return true;
+}
+
 } // namespace luci
index 93c4045..0bf3270 100644 (file)
@@ -23,6 +23,9 @@
 namespace luci
 {
 
+// Return the max value of dtype for symmetric quantization (int4/int8/int16)
+int32_t max_for_sym_quant(const loco::DataType &type);
+
 // 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);
@@ -77,7 +80,8 @@ ActivationQType activation_qtype(const CircleNode *node);
 // Create qparam with pre-defined values for speical operators
 std::unique_ptr<CircleQuantParam> make_predefined_qparam(CircleNode *node, loco::DataType dtype);
 std::unique_ptr<CircleQuantParam> make_predefined_qparam(ActivationQType qtype,
-                                                         loco::DataType dtype);
+                                                         loco::DataType dtype,
+                                                         CircleQuantParam *old_quant_param);
 
 // Update node's scale to a positive integer (for special Ops e.g., Floor, Ceil)
 void set_int_scale(luci::CircleNode *node);
@@ -89,6 +93,12 @@ void quant_const(luci::CircleConst *node, loco::DataType quant_type);
 // Emits warnings to log with WARN
 void warn_accuracy_with_range(luci::CircleNode *n);
 
+// Return true if the node is OnnxDequantizeLinear
+bool is_onnx_dequantize_linear(const luci::CircleCustom *node);
+
+// Return true if the node is OnnxQuantizeLinear
+bool is_onnx_quantize_linear(const luci::CircleCustom *node);
+
 } // namespace luci
 
 #endif // __LUCI_QUANTIZATION_UTILS_H__
index 9134500..8d95398 100644 (file)
@@ -110,26 +110,30 @@ void QuantizeSpecialActivation::visit(luci::CircleNode *node)
   auto fused_act_node = dynamic_cast<CircleNodeMixin<CircleNodeTrait::FusedActFunc> *>(node);
   if (fused_act_node != nullptr && fused_act_node->fusedActivationFunction() == FusedActFunc::TANH)
   {
-    auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedTanh, output_type);
+    auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedTanh, output_type,
+                                         node->quantparam());
     node->quantparam(std::move(qparam));
   }
 }
 
 void QuantizeSpecialActivation::visit(luci::CircleLogistic *node)
 {
-  auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedLogistic, output_type);
+  auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedLogistic, output_type,
+                                       node->quantparam());
   node->quantparam(std::move(qparam));
 }
 
 void QuantizeSpecialActivation::visit(luci::CircleTanh *node)
 {
-  auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedTanh, output_type);
+  auto qparam =
+    make_predefined_qparam(luci::ActivationQType::PreDefinedTanh, output_type, node->quantparam());
   node->quantparam(std::move(qparam));
 }
 
 void QuantizeSpecialActivation::visit(luci::CircleSoftmax *node)
 {
-  auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedSoftmax, output_type);
+  auto qparam = make_predefined_qparam(luci::ActivationQType::PreDefinedSoftmax, output_type,
+                                       node->quantparam());
   node->quantparam(std::move(qparam));
 }
 
@@ -271,6 +275,7 @@ QUANTIZE_TWO_CONST_INPUTS(luci::CircleMinimum, x, y)
 QUANTIZE_TWO_CONST_INPUTS(luci::CircleMul, x, y)
 QUANTIZE_TWO_CONST_INPUTS(luci::CircleNotEqual, x, y)
 QUANTIZE_TWO_CONST_INPUTS(luci::CirclePow, x, y)
+QUANTIZE_TWO_CONST_INPUTS(luci::CircleSelectV2, t, e)
 QUANTIZE_TWO_CONST_INPUTS(luci::CircleSub, x, y)
 
 // AddN has arbitrary number of inputs
index ba3bc59..162ec2c 100644 (file)
@@ -27,12 +27,8 @@ namespace luci
  */
 struct QuantizeActivation final : public luci::CircleNodeMutableVisitor<void>
 {
-  QuantizeActivation(loco::DataType input, loco::DataType output)
-    : input_type(input), output_type(output)
-  {
-  }
+  QuantizeActivation(loco::DataType output) : output_type(output) {}
 
-  loco::DataType input_type;
   loco::DataType output_type;
 
   // Quantize each node using recorded min/max
@@ -44,12 +40,8 @@ struct QuantizeActivation final : public luci::CircleNodeMutableVisitor<void>
  */
 struct QuantizeSpecialActivation final : public luci::CircleNodeMutableVisitor<void>
 {
-  QuantizeSpecialActivation(loco::DataType input, loco::DataType output)
-    : input_type(input), output_type(output)
-  {
-  }
+  QuantizeSpecialActivation(loco::DataType output) : output_type(output) {}
 
-  loco::DataType input_type;
   loco::DataType output_type;
 
   void visit(luci::CircleNode *node);
@@ -158,6 +150,7 @@ private:
   void visit(luci::CircleMul *node);
   void visit(luci::CircleNotEqual *node);
   void visit(luci::CirclePow *node);
+  void visit(luci::CircleSelectV2 *node);
   void visit(luci::CircleSub *node);
 
   // AddN has arbitrary number of inputs
diff --git a/compiler/luci/pass/src/QuantizeOnnxDequantizeLinearPass.cpp b/compiler/luci/pass/src/QuantizeOnnxDequantizeLinearPass.cpp
new file mode 100644 (file)
index 0000000..9194af0
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "QuantizeOnnxDequantizeLinearPass.h"
+#include "QuantizationUtils.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+#include <flatbuffers/flexbuffers.h>
+
+namespace
+{
+
+using namespace luci;
+
+// Return true if all values of node are within value_range
+// value_range: [min, max]
+template <loco::DataType DT>
+bool value_range(const luci::CircleConst *node, const std::pair<int64_t, int64_t> &value_range)
+{
+  const auto min = value_range.first;
+  const auto max = value_range.second;
+
+  auto size = node->size<DT>();
+  for (uint32_t i = 0; i < size; i++)
+  {
+    const auto val = static_cast<int64_t>(node->at<DT>(i));
+    if (val < min or val > max)
+      return false;
+  }
+
+  return true;
+}
+
+std::vector<float> get_scales(const luci::CircleConst *node)
+{
+  assert(node); // FIX_CALLER_UNLESS
+
+  const auto num_scales = node->size<loco::DataType::FLOAT32>();
+  std::vector<float> scales(num_scales);
+  for (uint32_t i = 0; i < num_scales; ++i)
+  {
+    scales[i] = node->at<loco::DataType::FLOAT32>(i);
+  }
+
+  return scales;
+}
+
+template <loco::DataType DT> std::vector<int64_t> get_zerops(const luci::CircleConst *node)
+{
+  assert(node); // FIX_CALLER_UNLESS
+
+  const auto num_zerops = node->size<DT>();
+  std::vector<int64_t> zerops(num_zerops);
+  for (uint32_t i = 0; i < num_zerops; ++i)
+  {
+    zerops[i] = node->at<DT>(i);
+  }
+
+  return zerops;
+}
+
+int32_t get_axis(const luci::CircleCustom *node)
+{
+  assert(node); // FIX_CALLER_UNLESS
+
+  const auto custom_options = node->custom_options();
+  const auto map = flexbuffers::GetRoot(custom_options).AsMap();
+
+  return map["axis"].IsNull() ? 0 : map["axis"].AsInt32();
+}
+
+class OnnxDequantizeLinearPattern final
+{
+public:
+  OnnxDequantizeLinearPattern(luci::CircleCustomOut *candidate) { custom_out = candidate; }
+
+public:
+  bool matched()
+  {
+    if (not custom_out)
+      return false;
+
+    dequantize = loco::must_cast<luci::CircleCustom *>(custom_out->input());
+    if (not is_onnx_dequantize_linear(dequantize))
+      return false;
+
+    input = dynamic_cast<luci::CircleConst *>(dequantize->inputs(0));
+    if (not input)
+      return false;
+
+    scale = dynamic_cast<luci::CircleConst *>(dequantize->inputs(1));
+    if (not scale)
+      return false;
+
+    zerop = dynamic_cast<luci::CircleConst *>(dequantize->inputs(2));
+    if (not zerop)
+      return false;
+
+    const auto input_dtype = input->dtype();
+    const auto scale_dtype = scale->dtype();
+    const auto zerop_dtype = zerop->dtype();
+
+    if (scale_dtype != loco::DataType::FLOAT32)
+      return false;
+
+    // Invariant from onnx DequantizeLinear operator
+    if (input_dtype != zerop_dtype)
+      return false;
+
+    return true;
+  }
+
+public:
+  luci::CircleCustomOut *custom_out = nullptr;
+  luci::CircleCustom *dequantize = nullptr;
+  luci::CircleConst *input = nullptr;
+  luci::CircleConst *scale = nullptr;
+  luci::CircleConst *zerop = nullptr;
+};
+
+class QuantizeOnnxDequantizeLinear final
+{
+public:
+  QuantizeOnnxDequantizeLinear(const OnnxDequantizeLinearPattern &p) : _p(p) {}
+
+public:
+  void apply(void)
+  {
+    // The final const's dtype is the same with input_dtype by default
+    auto const_dtype = _p.input->dtype();
+    if (const_dtype == loco::DataType::U8)
+    {
+      // Onnx does not support int4/uint4 as of writing. We assume uint8
+      // tensor is quantized in int4/uint4 if values are within [0,15]
+      if (value_range<loco::DataType::U8>(_p.input, {0, 15}))
+      {
+        if (value_range<loco::DataType::U8>(_p.zerop, {8, 8}))
+        {
+          const_dtype = loco::DataType::S4;
+        }
+        else if (value_range<loco::DataType::U8>(_p.zerop, {0, 15}))
+        {
+          const_dtype = loco::DataType::U4;
+        }
+      }
+    }
+
+    luci::CircleConst *quant_const = nullptr;
+    switch (const_dtype)
+    {
+      case loco::DataType::S4:
+        quant_const = gen_s4_quant();
+        break;
+      case loco::DataType::U4:
+        quant_const = gen_u4_quant();
+        break;
+      case loco::DataType::U8:
+        quant_const = gen_u8_quant();
+        break;
+      case loco::DataType::S16:
+        quant_const = gen_s16_quant();
+        break;
+      default:
+        throw std::runtime_error("Unsupported quantized dtype");
+    }
+
+    assert(quant_const); // FIX_ME_UNLESS
+
+    // set origin
+    std::vector<std::shared_ptr<luci::CircleNodeOrigin>> origin_vec{
+      luci::get_origin(_p.dequantize), luci::get_origin(_p.input), luci::get_origin(_p.scale),
+      luci::get_origin(_p.zerop)};
+
+    luci::add_origin(quant_const, luci::composite_origin(origin_vec));
+
+    replace(_p.custom_out).with(quant_const);
+  }
+
+private:
+  luci::CircleConst *gen_s4_quant(void)
+  {
+    assert(_p.input->dtype() == loco::DataType::U8);      // FIX_CALLER_UNLESS
+    assert(_p.scale->dtype() == loco::DataType::FLOAT32); // FIX_CALLER_UNLESS
+    assert(_p.zerop->dtype() == loco::DataType::U8);      // FIX_CALLER_UNLESS
+
+    auto quantized_node = _p.dequantize->graph()->nodes()->create<luci::CircleConst>();
+    quantized_node->dtype(loco::DataType::S4);
+    quantized_node->rank(_p.input->rank());
+    for (uint32_t i = 0; i < _p.input->rank(); ++i)
+    {
+      quantized_node->dim(i) = _p.input->dim(i);
+    }
+    quantized_node->shape_status(luci::ShapeStatus::VALID);
+
+    // Create S4 CircleConst
+    // NOTE S4 is saved as S8 in luci::CircleConst
+    const auto num_elems = _p.input->size<loco::DataType::U8>();
+    quantized_node->size<loco::DataType::S4>(num_elems);
+    for (uint32_t i = 0; i < num_elems; i++)
+    {
+      const uint8_t u8_val = _p.input->at<loco::DataType::U8>(i);
+      assert(u8_val <= 15); // FIX_CALLER_UNLESS
+      quantized_node->at<loco::DataType::S4>(i) = static_cast<int8_t>(u8_val) - 8;
+    }
+
+    auto qparam = std::make_unique<luci::CircleQuantParam>();
+    {
+      const std::vector<float> scale_vector = get_scales(_p.scale);
+      const std::vector<int64_t> zerop_vector = get_zerops<loco::DataType::U8>(_p.zerop);
+
+      if (scale_vector.size() != zerop_vector.size())
+        throw std::runtime_error("Scale/Zerop size mismatches in " + _p.dequantize->name());
+
+      const int32_t qdim = get_axis(_p.dequantize);
+
+      qparam->scale = scale_vector;
+      qparam->zerop = zerop_vector;
+      qparam->quantized_dimension = qdim;
+    }
+
+    quantized_node->quantparam(std::move(qparam));
+
+    quantized_node->name(_p.input->name());
+
+    return quantized_node;
+  }
+
+  luci::CircleConst *gen_u4_quant(void)
+  {
+    assert(_p.input->dtype() == loco::DataType::U8);      // FIX_CALLER_UNLESS
+    assert(_p.scale->dtype() == loco::DataType::FLOAT32); // FIX_CALLER_UNLESS
+    assert(_p.zerop->dtype() == loco::DataType::U8);      // FIX_CALLER_UNLESS
+
+    auto quantized_node = _p.dequantize->graph()->nodes()->create<luci::CircleConst>();
+    quantized_node->dtype(loco::DataType::U4);
+    quantized_node->rank(_p.input->rank());
+    for (uint32_t i = 0; i < _p.input->rank(); ++i)
+    {
+      quantized_node->dim(i) = _p.input->dim(i);
+    }
+    quantized_node->shape_status(luci::ShapeStatus::VALID);
+
+    // Create U4 CircleConst
+    // NOTE U4 is saved as U8 in luci::CircleConst
+    const auto num_elems = _p.input->size<loco::DataType::U8>();
+    quantized_node->size<loco::DataType::U4>(num_elems);
+    for (uint32_t i = 0; i < num_elems; i++)
+    {
+      const uint8_t u8_val = _p.input->at<loco::DataType::U8>(i);
+      assert(u8_val <= 15); // FIX_CALLER_UNLESS
+      quantized_node->at<loco::DataType::U4>(i) = u8_val;
+    }
+
+    auto qparam = std::make_unique<luci::CircleQuantParam>();
+    {
+      const std::vector<float> scale_vector = get_scales(_p.scale);
+      const std::vector<int64_t> zerop_vector = get_zerops<loco::DataType::U8>(_p.zerop);
+
+      if (scale_vector.size() != zerop_vector.size())
+        throw std::runtime_error("Scale/Zerop size mismatches in " + _p.dequantize->name());
+
+      const int32_t qdim = get_axis(_p.dequantize);
+
+      qparam->scale = scale_vector;
+      qparam->zerop = zerop_vector;
+      qparam->quantized_dimension = qdim;
+    }
+
+    quantized_node->quantparam(std::move(qparam));
+
+    quantized_node->name(_p.input->name());
+
+    return quantized_node;
+  }
+
+  luci::CircleConst *gen_u8_quant(void)
+  {
+    assert(_p.input->dtype() == loco::DataType::U8);      // FIX_CALLER_UNLESS
+    assert(_p.scale->dtype() == loco::DataType::FLOAT32); // FIX_CALLER_UNLESS
+    assert(_p.zerop->dtype() == loco::DataType::U8);      // FIX_CALLER_UNLESS
+
+    auto quantized_node = _p.dequantize->graph()->nodes()->create<luci::CircleConst>();
+    quantized_node->dtype(loco::DataType::U8);
+    quantized_node->rank(_p.input->rank());
+    for (uint32_t i = 0; i < _p.input->rank(); ++i)
+    {
+      quantized_node->dim(i) = _p.input->dim(i);
+    }
+    quantized_node->shape_status(luci::ShapeStatus::VALID);
+
+    // Create U8 CircleConst
+    const auto num_elems = _p.input->size<loco::DataType::U8>();
+    quantized_node->size<loco::DataType::U8>(num_elems);
+    for (uint32_t i = 0; i < num_elems; i++)
+    {
+      const uint8_t u8_val = _p.input->at<loco::DataType::U8>(i);
+      quantized_node->at<loco::DataType::U8>(i) = u8_val;
+    }
+
+    auto qparam = std::make_unique<luci::CircleQuantParam>();
+    {
+      const std::vector<float> scale_vector = get_scales(_p.scale);
+      const std::vector<int64_t> zerop_vector = get_zerops<loco::DataType::U8>(_p.zerop);
+
+      if (scale_vector.size() != zerop_vector.size())
+        throw std::runtime_error("Scale/Zerop size mismatches in " + _p.dequantize->name());
+
+      const int32_t qdim = get_axis(_p.dequantize);
+
+      qparam->scale = scale_vector;
+      qparam->zerop = zerop_vector;
+      qparam->quantized_dimension = qdim;
+    }
+
+    quantized_node->quantparam(std::move(qparam));
+
+    quantized_node->name(_p.input->name());
+
+    return quantized_node;
+  }
+
+  luci::CircleConst *gen_s16_quant(void)
+  {
+    assert(_p.input->dtype() == loco::DataType::S16);     // FIX_CALLER_UNLESS
+    assert(_p.scale->dtype() == loco::DataType::FLOAT32); // FIX_CALLER_UNLESS
+    assert(_p.zerop->dtype() == loco::DataType::S16);     // FIX_CALLER_UNLESS
+
+    auto quantized_node = _p.dequantize->graph()->nodes()->create<luci::CircleConst>();
+    quantized_node->dtype(loco::DataType::S16);
+    quantized_node->rank(_p.input->rank());
+    for (uint32_t i = 0; i < _p.input->rank(); ++i)
+    {
+      quantized_node->dim(i) = _p.input->dim(i);
+    }
+    quantized_node->shape_status(luci::ShapeStatus::VALID);
+
+    // Create S16 CircleConst
+    const auto num_elems = _p.input->size<loco::DataType::S16>();
+    quantized_node->size<loco::DataType::S16>(num_elems);
+    for (uint32_t i = 0; i < num_elems; i++)
+    {
+      const int16_t s16_val = _p.input->at<loco::DataType::S16>(i);
+      quantized_node->at<loco::DataType::S16>(i) = s16_val;
+    }
+
+    auto qparam = std::make_unique<luci::CircleQuantParam>();
+    {
+      const std::vector<float> scale_vector = get_scales(_p.scale);
+      const std::vector<int64_t> zerop_vector = get_zerops<loco::DataType::S16>(_p.zerop);
+
+      if (scale_vector.size() != zerop_vector.size())
+        throw std::runtime_error("Scale/Zerop size mismatches in " + _p.dequantize->name());
+
+      const int32_t qdim = get_axis(_p.dequantize);
+
+      qparam->scale = scale_vector;
+      qparam->zerop = zerop_vector;
+      qparam->quantized_dimension = qdim;
+    }
+
+    quantized_node->quantparam(std::move(qparam));
+
+    quantized_node->name(_p.input->name());
+
+    return quantized_node;
+  }
+
+private:
+  const OnnxDequantizeLinearPattern &_p;
+};
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ *
+ * Quantize pattern
+ *
+ * [Before]
+ *
+ *      [CircleConst(quantized)]
+ *                |
+ *   [CircleCustom(OnnxDequantizeLinear)]
+ *                |
+ *           [CircleNode]
+ *
+ * [After]
+ *
+ *         [CircleConst(quantized)]
+ *                |
+ *           [CircleNode]
+ */
+bool QuantizeOnnxDequantizeLinearPass::run(loco::Graph *g)
+{
+  bool changed = false;
+
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto circle_custom_out = dynamic_cast<luci::CircleCustomOut *>(node))
+    {
+      OnnxDequantizeLinearPattern p(circle_custom_out);
+      if (p.matched())
+      {
+        QuantizeOnnxDequantizeLinear quantize(p);
+        quantize.apply();
+        changed = true;
+      }
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/QuantizeOnnxDequantizeLinearPass.h b/compiler/luci/pass/src/QuantizeOnnxDequantizeLinearPass.h
new file mode 100644 (file)
index 0000000..1743667
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_ONNX_DEQUANTIZE_LINEAR_PASS_H__
+#define __LUCI_QUANTIZE_ONNX_DEQUANTIZE_LINEAR_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to quantize ONNXDequantizeLinear operator
+ *
+ */
+struct QuantizeOnnxDequantizeLinearPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::QuantizeOnnxDequantizeLinear"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_QUANTIZE_ONNX_DEQUANTIZE_LINEAR_PASS_H__
diff --git a/compiler/luci/pass/src/QuantizeOnnxDequantizeLinearPass.test.cpp b/compiler/luci/pass/src/QuantizeOnnxDequantizeLinearPass.test.cpp
new file mode 100644 (file)
index 0000000..bd409c9
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "QuantizeOnnxDequantizeLinearPass.h"
+#include "PassTestGraphs.h"
+
+#include <flatbuffers/flexbuffers.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+template <loco::DataType DT>
+class QuantizeOnnxDequantizeLinearTest : public luci::ConstantFoldingAddTestGraph,
+                                         public ::testing::Test
+{
+public:
+  QuantizeOnnxDequantizeLinearTest() : luci::ConstantFoldingAddTestGraph({2, 2, 2}, DT) {}
+
+  virtual void SetUp() { init(); }
+
+  loco::Node *createFoldedPattern() override
+  {
+    _dequantize = _g.nodes()->template create<luci::CircleCustom>(3, 1);
+    _dequantize_out = _g.nodes()->template create<luci::CircleCustomOut>();
+    _input = _g.nodes()->template create<luci::CircleConst>();
+    _scale = _g.nodes()->template create<luci::CircleConst>();
+    _zerop = _g.nodes()->template create<luci::CircleConst>();
+
+    _dequantize->dtype(loco::DataType::FLOAT32);
+    _dequantize_out->dtype(loco::DataType::FLOAT32);
+    _input->dtype(DT);
+    _scale->dtype(loco::DataType::FLOAT32);
+    _zerop->dtype(DT);
+
+    _input->shape({2, 2, 2});
+    _scale->shape({2});
+    _zerop->shape({2});
+
+    _input->size<DT>(8);
+
+    _scale->size<loco::DataType::FLOAT32>(2);
+    _scale->at<loco::DataType::FLOAT32>(0) = 5.0;
+    _scale->at<loco::DataType::FLOAT32>(1) = 10.0;
+
+    _zerop->size<DT>(2);
+
+    // custom option
+    auto flex_buffers = std::make_unique<flexbuffers::Builder>();
+    size_t map_start = flex_buffers->StartMap();
+    flex_buffers->Int("axis", 1);
+    flex_buffers->EndMap(map_start);
+    flex_buffers->Finish();
+
+    _dequantize->inputs(0, _input);
+    _dequantize->inputs(1, _scale);
+    _dequantize->inputs(2, _zerop);
+    _dequantize->custom_code("ONNXDequantizeLinear");
+    _dequantize->custom_options(flex_buffers->GetBuffer());
+
+    _dequantize_out->input(_dequantize);
+    _dequantize_out->index(0);
+
+    _input->name("input");
+    _dequantize->name("dequantize");
+    _dequantize_out->name("dequantize_out");
+
+    return _dequantize_out;
+  }
+
+  void createNotQuantizablePattern() { _input->dtype(loco::DataType::FLOAT32); }
+
+protected:
+  luci::CircleCustom *_dequantize = nullptr;
+  luci::CircleCustomOut *_dequantize_out = nullptr;
+  luci::CircleConst *_input = nullptr;
+  luci::CircleConst *_scale = nullptr;
+  luci::CircleConst *_zerop = nullptr;
+};
+
+class S4QuantizeOnnxDequantizeLinearTest
+  : public QuantizeOnnxDequantizeLinearTest<loco::DataType::U8>
+{
+  virtual void SetUp() override
+  {
+    init();
+
+    // Input range [0, 15]
+    for (uint32_t i = 0; i < _input->size<loco::DataType::U8>(); i++)
+    {
+      _input->at<loco::DataType::U8>(i) = 1;
+    }
+
+    // Zerop = 8
+    for (uint32_t i = 0; i < _zerop->size<loco::DataType::U8>(); i++)
+    {
+      _zerop->at<loco::DataType::U8>(i) = 8;
+    }
+  }
+};
+
+class U4QuantizeOnnxDequantizeLinearTest
+  : public QuantizeOnnxDequantizeLinearTest<loco::DataType::U8>
+{
+  virtual void SetUp() override
+  {
+    init();
+
+    // Input range [0, 15]
+    for (uint32_t i = 0; i < _input->size<loco::DataType::U8>(); i++)
+    {
+      _input->at<loco::DataType::U8>(i) = 1;
+    }
+
+    // Zerop = [0, 15]
+    for (uint32_t i = 0; i < _zerop->size<loco::DataType::U8>(); i++)
+    {
+      _zerop->at<loco::DataType::U8>(i) = 1;
+    }
+  }
+};
+
+class U8QuantizeOnnxDequantizeLinearTest
+  : public QuantizeOnnxDequantizeLinearTest<loco::DataType::U8>
+{
+  virtual void SetUp() override
+  {
+    init();
+
+    // Input range [0, 255]
+    for (uint32_t i = 0; i < _input->size<loco::DataType::U8>(); i++)
+    {
+      _input->at<loco::DataType::U8>(i) = 255;
+    }
+
+    // Zerop = [0, 255]
+    for (uint32_t i = 0; i < _zerop->size<loco::DataType::U8>(); i++)
+    {
+      _zerop->at<loco::DataType::U8>(i) = 128;
+    }
+  }
+};
+
+class S16QuantizeOnnxDequantizeLinearTest
+  : public QuantizeOnnxDequantizeLinearTest<loco::DataType::S16>
+{
+  virtual void SetUp() override
+  {
+    init();
+
+    for (uint32_t i = 0; i < _input->size<loco::DataType::S16>(); i++)
+    {
+      _input->at<loco::DataType::S16>(i) = 1024;
+    }
+
+    for (uint32_t i = 0; i < _zerop->size<loco::DataType::S16>(); i++)
+    {
+      _zerop->at<loco::DataType::S16>(i) = 0;
+    }
+  }
+};
+
+} // namespace
+
+TEST_F(S4QuantizeOnnxDequantizeLinearTest, quantize_onnx_dq_linear_basic)
+{
+  luci::QuantizeOnnxDequantizeLinearPass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  EXPECT_EQ(loco::DataType::S4, folded_const->dtype());
+}
+
+TEST_F(S4QuantizeOnnxDequantizeLinearTest, quantize_onnx_dq_linear_basic_NEG)
+{
+  createNotQuantizablePattern();
+
+  luci::QuantizeOnnxDequantizeLinearPass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(U4QuantizeOnnxDequantizeLinearTest, quantize_onnx_dq_linear_basic)
+{
+  luci::QuantizeOnnxDequantizeLinearPass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  EXPECT_EQ(loco::DataType::U4, folded_const->dtype());
+}
+
+TEST_F(U4QuantizeOnnxDequantizeLinearTest, quantize_onnx_dq_linear_basic_NEG)
+{
+  createNotQuantizablePattern();
+
+  luci::QuantizeOnnxDequantizeLinearPass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(U8QuantizeOnnxDequantizeLinearTest, quantize_onnx_dq_linear_basic)
+{
+  luci::QuantizeOnnxDequantizeLinearPass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  EXPECT_EQ(loco::DataType::U8, folded_const->dtype());
+}
+
+TEST_F(U8QuantizeOnnxDequantizeLinearTest, quantize_onnx_dq_linear_basic_NEG)
+{
+  createNotQuantizablePattern();
+
+  luci::QuantizeOnnxDequantizeLinearPass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_EQ(nullptr, folded_const);
+}
+
+TEST_F(S16QuantizeOnnxDequantizeLinearTest, quantize_onnx_dq_linear_basic)
+{
+  luci::QuantizeOnnxDequantizeLinearPass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  EXPECT_EQ(loco::DataType::S16, folded_const->dtype());
+}
+
+TEST_F(S16QuantizeOnnxDequantizeLinearTest, quantize_onnx_dq_linear_basic_NEG)
+{
+  createNotQuantizablePattern();
+
+  luci::QuantizeOnnxDequantizeLinearPass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_EQ(nullptr, folded_const);
+}
diff --git a/compiler/luci/pass/src/QuantizeOnnxFakeQuantModelPass.cpp b/compiler/luci/pass/src/QuantizeOnnxFakeQuantModelPass.cpp
new file mode 100644 (file)
index 0000000..face706
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/QuantizeOnnxFakeQuantModelPass.h"
+#include "QuantizeOnnxQDQPass.h"
+#include "QuantizeOnnxDequantizeLinearPass.h"
+#include "QuantizeWithPredecessorPass.h"
+#include "InsertQuantizeOpOnDTypeMismatch.h"
+#include "QuantizeActivation.h"
+#include "QuantizationUtils.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Service/Nodes/CircleConst.h>
+#include <luci/Log.h>
+
+namespace luci
+{
+
+/**
+ * How QuantizeOnnxFakeQuantModel works?
+ *
+ * 1. Activation is quantized as below.
+ *
+ * Before
+ *
+ * [node(fp32)] -> [OnnxQuantizeLinear] -> [OnnxDequantizeLinear]
+ *
+ * After
+ *
+ * [node(q)]
+ *
+ *
+ * 2. Weight(constant) are quantized as below.
+ *
+ * Before
+ *
+ * [Const(q w/o qparam)] -> [OnnxDequantizeLinear]
+ *
+ * After
+ *
+ * [Const(q)]
+ *
+ * 3. Quantize constant activations
+ *
+ * 4. Quantize with predecessors' qparams
+ *
+ * 5. Update qparams of special operators
+ *
+ * 6. Insert Quantize Op if an Op's input dtype and output dtype mismatch
+ */
+bool QuantizeOnnxFakeQuantModelPass::run(loco::Graph *g)
+{
+  LOGGER(l);
+  INFO(l) << "QuantizeOnnxFakeQuantModelPass Start" << std::endl;
+
+  // Quantize Onnx QuantizeLinear-DequantizeLinear pattern
+  {
+    QuantizeOnnxQDQPass pass;
+    pass.run(g);
+  }
+
+  // Quantize Onnx const-DequantizeLinear pattern
+  {
+    QuantizeOnnxDequantizeLinearPass pass;
+    pass.run(g);
+  }
+
+  // Quantize const input activation
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+
+    QuantizeConstInputActivation qcia(_ctx->default_activation_dtype);
+    circle_node->accept(&qcia);
+  }
+
+  // Quantize nodes using their predecessors' qparams
+  {
+    QuantizeWithPredecessorPass pass;
+    pass.run(g);
+  }
+
+  // Update qparam of output of special Ops
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+
+    if (is_quantized(circle_node))
+    {
+      QuantizeSpecialActivation qsa(circle_node->dtype());
+      circle_node->accept(&qsa);
+    }
+  }
+
+  // Insert QuantizeOp if input/output dtype does not match
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+
+    InsertQuantizeOpOnDTypeMismatch iqoodm;
+    circle_node->accept(&iqoodm);
+  }
+
+  // Update output dtype
+  auto graph_outputs = g->outputs();
+  for (auto node : loco::output_nodes(g))
+  {
+    auto circle_node = loco::must_cast<luci::CircleOutput *>(node);
+    auto from = loco::must_cast<luci::CircleNode *>(circle_node->from());
+    circle_node->dtype(from->dtype());
+
+    auto graph_output = graph_outputs->at(circle_node->index());
+    graph_output->dtype(circle_node->dtype());
+  }
+
+  INFO(l) << "QuantizeOnnxFakeQuantModelPass End" << std::endl;
+  return false; // one time run
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/QuantizeOnnxFakeQuantModelPass.test.cpp b/compiler/luci/pass/src/QuantizeOnnxFakeQuantModelPass.test.cpp
new file mode 100644 (file)
index 0000000..953f206
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/QuantizeOnnxFakeQuantModelPass.h"
+#include "PassTestGraphs.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class S16OnnxFakeQuantGraphlet
+{
+public:
+  S16OnnxFakeQuantGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    _quantize = g->nodes()->create<luci::CircleCustom>(3, 1);
+    _quantize_out = g->nodes()->create<luci::CircleCustomOut>();
+    _dequantize = g->nodes()->create<luci::CircleCustom>(3, 1);
+    _dequantize_out = g->nodes()->create<luci::CircleCustomOut>();
+    _scale = g->nodes()->create<luci::CircleConst>();
+    _zerop = g->nodes()->create<luci::CircleConst>();
+
+    _quantize->dtype(loco::DataType::S16);
+    _quantize_out->dtype(loco::DataType::S16);
+    _dequantize->dtype(loco::DataType::FLOAT32);
+    _dequantize_out->dtype(loco::DataType::FLOAT32);
+    _scale->dtype(loco::DataType::FLOAT32);
+    _zerop->dtype(loco::DataType::S16);
+
+    _scale->shape({1});
+    _zerop->shape({1});
+
+    _scale->size<loco::DataType::FLOAT32>(1);
+    _scale->at<loco::DataType::FLOAT32>(0) = 5.0;
+
+    _zerop->size<loco::DataType::S16>(1);
+    _zerop->at<loco::DataType::S16>(0) = 0;
+
+    _quantize->custom_code("ONNXQuantizeLinear");
+    _quantize_out->index(0);
+
+    _dequantize->custom_code("ONNXDequantizeLinear");
+    _dequantize_out->index(0);
+
+    _scale->name("scale");
+    _zerop->name("zerop");
+    _quantize->name("quantize");
+    _quantize_out->name("quantize_out");
+    _dequantize->name("dequantize");
+    _dequantize_out->name("dequantize_out");
+  }
+
+protected:
+  luci::CircleCustom *_quantize = nullptr;
+  luci::CircleCustomOut *_quantize_out = nullptr;
+  luci::CircleCustom *_dequantize = nullptr;
+  luci::CircleCustomOut *_dequantize_out = nullptr;
+  luci::CircleConst *_scale = nullptr;
+  luci::CircleConst *_zerop = nullptr;
+};
+
+class S16QuantizeOnnxFakeQuantModelTestGraph : public TestIOGraph, public S16OnnxFakeQuantGraphlet
+{
+public:
+  void init(void)
+  {
+    TestIOGraph::init({2, 2, 2}, {2, 2, 2});
+    S16OnnxFakeQuantGraphlet::init(g());
+
+    _quantize->inputs(0, input());
+    _quantize->inputs(1, _scale);
+    _quantize->inputs(2, _zerop);
+    _quantize_out->input(_quantize);
+    _dequantize->inputs(0, _quantize_out);
+    _dequantize->inputs(1, _scale);
+    _dequantize->inputs(2, _zerop);
+    _dequantize_out->input(_dequantize);
+
+    output()->from(_dequantize_out);
+  }
+};
+
+} // namespace
+
+TEST(QuantizeOnnxFakeQuantModelTest, s16_quantize_onnx_qdq)
+{
+  S16QuantizeOnnxFakeQuantModelTestGraph g;
+
+  auto ctx = std::make_unique<luci::QuantizeOnnxFakeQuantModelPass::Context>();
+  {
+    ctx->default_activation_dtype = loco::DataType::S16;
+  }
+
+  luci::QuantizeOnnxFakeQuantModelPass pass(std::move(ctx));
+
+  g.init();
+
+  // Always return false
+  EXPECT_FALSE(pass.run(g.g()));
+
+  EXPECT_EQ(loco::DataType::S16, g.input()->dtype());
+}
diff --git a/compiler/luci/pass/src/QuantizeOnnxQDQPass.cpp b/compiler/luci/pass/src/QuantizeOnnxQDQPass.cpp
new file mode 100644 (file)
index 0000000..efe8b59
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "QuantizeOnnxQDQPass.h"
+#include "QuantizationUtils.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Service/Nodes/CircleConst.h>
+
+#include <cmath>
+#include <limits>
+
+namespace
+{
+
+using namespace luci;
+
+struct OnnxQDQPattern final
+{
+public:
+  OnnxQDQPattern(luci::CircleCustomOut *candidate) { dq_out = candidate; }
+
+public:
+  bool matched()
+  {
+    if (not dq_out)
+      return false;
+
+    dq = loco::must_cast<luci::CircleCustom *>(dq_out->input());
+    if (not is_onnx_dequantize_linear(dq))
+      return false;
+
+    q_out = dynamic_cast<luci::CircleCustomOut *>(dq->inputs(0));
+    if (not q_out)
+      return false;
+
+    dq_scale = dynamic_cast<luci::CircleConst *>(dq->inputs(1));
+    if (not dq_scale)
+      return false;
+
+    dq_zerop = dynamic_cast<luci::CircleConst *>(dq->inputs(2));
+    if (not dq_zerop)
+      return false;
+
+    q = loco::must_cast<luci::CircleCustom *>(q_out->input());
+    if (not is_onnx_quantize_linear(q))
+      return false;
+
+    input = loco::must_cast<luci::CircleNode *>(q->inputs(0));
+    if (input->dtype() != loco::DataType::FLOAT32)
+      return false;
+
+    q_scale = dynamic_cast<luci::CircleConst *>(q->inputs(1));
+    if (not q_scale)
+      return false;
+
+    q_zerop = dynamic_cast<luci::CircleConst *>(q->inputs(2));
+    if (not q_zerop)
+      return false;
+
+    const auto q_dtype = q->dtype();
+    const auto q_scale_dtype = q_scale->dtype();
+    const auto q_zerop_dtype = q_zerop->dtype();
+    const auto dq_scale_dtype = dq_scale->dtype();
+    const auto dq_zerop_dtype = dq_zerop->dtype();
+
+    if (q_scale_dtype != loco::DataType::FLOAT32)
+      return false;
+
+    if (dq_scale_dtype != loco::DataType::FLOAT32)
+      return false;
+
+    // Invariant from onnx Quantize operator
+    if (q_dtype != q_zerop_dtype)
+      return false;
+
+    // Invariant from onnx Dequantize operator
+    if (q_dtype != dq_zerop_dtype)
+      return false;
+
+    // Check length of scale, zp = 1
+    if (q_scale->size<loco::DataType::FLOAT32>() != 1)
+      return false;
+
+    if (dq_scale->size<loco::DataType::FLOAT32>() != 1)
+      return false;
+
+    auto q_zerop_size = 0;
+    auto dq_zerop_size = 0;
+    switch (q_zerop_dtype)
+    {
+      case loco::DataType::S16:
+        q_zerop_size = q_zerop->size<loco::DataType::S16>();
+        dq_zerop_size = dq_zerop->size<loco::DataType::S16>();
+        break;
+      case loco::DataType::U8:
+        q_zerop_size = q_zerop->size<loco::DataType::U8>();
+        dq_zerop_size = dq_zerop->size<loco::DataType::U8>();
+        break;
+      default:
+        throw std::runtime_error("Unsupported zerop dtype in " + q_zerop->name());
+    }
+
+    if (q_zerop_size != 1)
+      return false;
+
+    if (dq_zerop_size != 1)
+      return false;
+
+    return true;
+  }
+
+public:
+  luci::CircleCustomOut *dq_out = nullptr;
+  luci::CircleCustom *dq = nullptr;
+  luci::CircleConst *dq_scale = nullptr;
+  luci::CircleConst *dq_zerop = nullptr;
+  luci::CircleCustomOut *q_out = nullptr;
+  luci::CircleCustom *q = nullptr;
+  luci::CircleConst *q_scale = nullptr;
+  luci::CircleConst *q_zerop = nullptr;
+  luci::CircleNode *input = nullptr;
+};
+
+class QuantizeOnnxQDQ final
+{
+public:
+  QuantizeOnnxQDQ(const OnnxQDQPattern &p) : _p(p) {}
+
+public:
+  void apply(void)
+  {
+    const auto quantized_dtype = _p.q->dtype();
+
+    // Get scale
+    assert(_p.q_scale->dtype() == loco::DataType::FLOAT32);   // FIX_CALLER_UNLESS
+    assert(_p.q_scale->size<loco::DataType::FLOAT32>() == 1); // FIX_CALLER_UNLESS
+    const float q_scale = _p.q_scale->at<loco::DataType::FLOAT32>(0);
+
+    assert(_p.dq_scale->dtype() == loco::DataType::FLOAT32);   // FIX_CALLER_UNLESS
+    assert(_p.dq_scale->size<loco::DataType::FLOAT32>() == 1); // FIX_CALLER_UNLESS
+    const float dq_scale = _p.dq_scale->at<loco::DataType::FLOAT32>(0);
+
+    if (q_scale != dq_scale)
+      throw std::runtime_error("Invalid scale value in " + _p.dq_scale->name());
+
+    // Get zerop
+    int64_t q_zerop = 0;
+    int64_t dq_zerop = 0;
+    switch (quantized_dtype)
+    {
+      case loco::DataType::S16:
+        assert(_p.q_zerop->size<loco::DataType::S16>() == 1);  // FIX_CALLER_UNLESS
+        assert(_p.dq_zerop->size<loco::DataType::S16>() == 1); // FIX_CALLER_UNLESS
+        q_zerop = _p.q_zerop->at<loco::DataType::S16>(0);
+        dq_zerop = _p.dq_zerop->at<loco::DataType::S16>(0);
+        break;
+      case loco::DataType::U8:
+        assert(_p.q_zerop->size<loco::DataType::U8>() == 1);  // FIX_CALLER_UNLESS
+        assert(_p.dq_zerop->size<loco::DataType::U8>() == 1); // FIX_CALLER_UNLESS
+        q_zerop = _p.q_zerop->at<loco::DataType::U8>(0);
+        dq_zerop = _p.dq_zerop->at<loco::DataType::U8>(0);
+        break;
+      default:
+        throw std::runtime_error("Unsupported zerop dtype in " + _p.q_zerop->name());
+    }
+
+    if (q_zerop != dq_zerop)
+      throw std::runtime_error("Invalid zerop value in " + _p.dq_zerop->name());
+
+    auto qparam = std::make_unique<luci::CircleQuantParam>();
+    {
+      qparam->scale.push_back(q_scale);
+      qparam->zerop.push_back(q_zerop);
+      qparam->quantized_dimension = 0;
+    }
+
+    if (auto const_input = dynamic_cast<luci::CircleConst *>(_p.input))
+    {
+      assert(const_input->dtype() == loco::DataType::FLOAT32); // FIX_ME_UNLESS
+      const auto num_elem = const_input->size<loco::DataType::FLOAT32>();
+
+      auto new_const = luci::clone(const_input);
+      new_const->name(new_const->name() + "_quant");
+      add_origin(new_const, luci::get_origin(const_input));
+
+      new_const->dtype(quantized_dtype);
+
+      // Quantize const
+      switch (quantized_dtype)
+      {
+        case loco::DataType::S16:
+        {
+          new_const->size<loco::DataType::S16>(num_elem);
+
+          const int64_t max_val = std::numeric_limits<int16_t>::max();
+          const int64_t min_val = -max_val;
+          for (uint32_t i = 0; i < num_elem; i++)
+          {
+            const float fp_val = const_input->at<loco::DataType::FLOAT32>(i);
+            const int64_t q_val = std::round(fp_val / q_scale) + q_zerop;
+            new_const->at<loco::DataType::S16>(i) = std::min(max_val, std::max(min_val, q_val));
+          }
+          break;
+        }
+        default:
+          throw std::runtime_error("Unsupported quantized_dtype");
+      }
+      new_const->quantparam(std::move(qparam));
+
+      replace(_p.dq_out).with(new_const);
+    }
+    else
+    {
+      // clang-format off
+    // NOTE We overwrite dtype and qparam to _p.input
+    // This can be problematic if a single tensor has
+    // multiple different qparams. Let's fix later.
+    _p.input->dtype(quantized_dtype);
+    _p.input->quantparam(std::move(qparam));
+
+    replace(_p.dq_out).with(_p.input);
+      // clang-format on
+    }
+  }
+
+private:
+  const OnnxQDQPattern &_p;
+};
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ *
+ * Quantize pattern
+ *
+ * [Before]
+ *
+ *        [CircleNode(fp32)]
+ *                |
+ *   [CircleCustom(OnnxQuantizeLinear)]
+ *                |
+ *   [CircleCustom(OnnxDequantizeLinear)]
+ *                |
+ *           [CircleNode]
+ *
+ * [After]
+ *
+ *        [CircleNode(quantized)]
+ *                |
+ *           [CircleNode]
+ */
+bool QuantizeOnnxQDQPass::run(loco::Graph *g)
+{
+  bool changed = false;
+
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto circle_custom_out = dynamic_cast<luci::CircleCustomOut *>(node))
+    {
+      OnnxQDQPattern p(circle_custom_out);
+      if (p.matched())
+      {
+        QuantizeOnnxQDQ quantize(p);
+        quantize.apply();
+        changed = true;
+      }
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/QuantizeOnnxQDQPass.h b/compiler/luci/pass/src/QuantizeOnnxQDQPass.h
new file mode 100644 (file)
index 0000000..ac61d9e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_ONNX_QDQ_PASS_H__
+#define __LUCI_QUANTIZE_ONNX_QDQ_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to quantize ONNX QuantizeLinear-DequantizeLinear operator
+ *
+ */
+struct QuantizeOnnxQDQPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::QuantizeOnnxQDQ"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_QUANTIZE_ONNX_QDQ_PASS_H__
diff --git a/compiler/luci/pass/src/QuantizeOnnxQDQPass.test.cpp b/compiler/luci/pass/src/QuantizeOnnxQDQPass.test.cpp
new file mode 100644 (file)
index 0000000..6053bdf
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "QuantizeOnnxQDQPass.h"
+#include "PassTestGraphs.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class U8OnnxQDQGraphlet
+{
+public:
+  U8OnnxQDQGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    _quantize = g->nodes()->create<luci::CircleCustom>(3, 1);
+    _quantize_out = g->nodes()->create<luci::CircleCustomOut>();
+    _dequantize = g->nodes()->create<luci::CircleCustom>(3, 1);
+    _dequantize_out = g->nodes()->create<luci::CircleCustomOut>();
+    _scale = g->nodes()->create<luci::CircleConst>();
+    _zerop = g->nodes()->create<luci::CircleConst>();
+
+    _quantize->dtype(loco::DataType::U8);
+    _quantize_out->dtype(loco::DataType::U8);
+    _dequantize->dtype(loco::DataType::FLOAT32);
+    _dequantize_out->dtype(loco::DataType::FLOAT32);
+    _scale->dtype(loco::DataType::FLOAT32);
+    _zerop->dtype(loco::DataType::U8);
+
+    _scale->shape({1});
+    _zerop->shape({1});
+
+    _scale->size<loco::DataType::FLOAT32>(1);
+    _scale->at<loco::DataType::FLOAT32>(0) = 5.0;
+
+    _zerop->size<loco::DataType::U8>(1);
+    _zerop->at<loco::DataType::U8>(0) = 0;
+
+    _quantize->custom_code("ONNXQuantizeLinear");
+    _quantize_out->index(0);
+
+    _dequantize->custom_code("ONNXDequantizeLinear");
+    _dequantize_out->index(0);
+
+    _scale->name("scale");
+    _zerop->name("zerop");
+    _quantize->name("quantize");
+    _quantize_out->name("quantize_out");
+    _dequantize->name("dequantize");
+    _dequantize_out->name("dequantize_out");
+  }
+
+protected:
+  luci::CircleCustom *_quantize = nullptr;
+  luci::CircleCustomOut *_quantize_out = nullptr;
+  luci::CircleCustom *_dequantize = nullptr;
+  luci::CircleCustomOut *_dequantize_out = nullptr;
+  luci::CircleConst *_scale = nullptr;
+  luci::CircleConst *_zerop = nullptr;
+};
+
+class U8QuantizeOnnxQDQTestGraph : public TestIOGraph, public U8OnnxQDQGraphlet
+{
+public:
+  void init(void)
+  {
+    TestIOGraph::init({2, 2, 2}, {2, 2, 2});
+    U8OnnxQDQGraphlet::init(g());
+
+    _quantize->inputs(0, input());
+    _quantize->inputs(1, _scale);
+    _quantize->inputs(2, _zerop);
+    _quantize_out->input(_quantize);
+    _dequantize->inputs(0, _quantize_out);
+    _dequantize->inputs(1, _scale);
+    _dequantize->inputs(2, _zerop);
+    _dequantize_out->input(_dequantize);
+
+    output()->from(_dequantize_out);
+  }
+};
+
+class S16OnnxQDQGraphlet
+{
+public:
+  S16OnnxQDQGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    _quantize = g->nodes()->create<luci::CircleCustom>(3, 1);
+    _quantize_out = g->nodes()->create<luci::CircleCustomOut>();
+    _dequantize = g->nodes()->create<luci::CircleCustom>(3, 1);
+    _dequantize_out = g->nodes()->create<luci::CircleCustomOut>();
+    _scale = g->nodes()->create<luci::CircleConst>();
+    _zerop = g->nodes()->create<luci::CircleConst>();
+
+    _quantize->dtype(loco::DataType::S16);
+    _quantize_out->dtype(loco::DataType::S16);
+    _dequantize->dtype(loco::DataType::FLOAT32);
+    _dequantize_out->dtype(loco::DataType::FLOAT32);
+    _scale->dtype(loco::DataType::FLOAT32);
+    _zerop->dtype(loco::DataType::S16);
+
+    _scale->shape({1});
+    _zerop->shape({1});
+
+    _scale->size<loco::DataType::FLOAT32>(1);
+    _scale->at<loco::DataType::FLOAT32>(0) = 5.0;
+
+    _zerop->size<loco::DataType::S16>(1);
+    _zerop->at<loco::DataType::S16>(0) = 0;
+
+    _quantize->custom_code("ONNXQuantizeLinear");
+    _quantize_out->index(0);
+
+    _dequantize->custom_code("ONNXDequantizeLinear");
+    _dequantize_out->index(0);
+
+    _scale->name("scale");
+    _zerop->name("zerop");
+    _quantize->name("quantize");
+    _quantize_out->name("quantize_out");
+    _dequantize->name("dequantize");
+    _dequantize_out->name("dequantize_out");
+  }
+
+protected:
+  luci::CircleCustom *_quantize = nullptr;
+  luci::CircleCustomOut *_quantize_out = nullptr;
+  luci::CircleCustom *_dequantize = nullptr;
+  luci::CircleCustomOut *_dequantize_out = nullptr;
+  luci::CircleConst *_scale = nullptr;
+  luci::CircleConst *_zerop = nullptr;
+};
+
+class S16QuantizeOnnxQDQTestGraph : public TestIOGraph, public S16OnnxQDQGraphlet
+{
+public:
+  void init(void)
+  {
+    TestIOGraph::init({2, 2, 2}, {2, 2, 2});
+    S16OnnxQDQGraphlet::init(g());
+
+    _quantize->inputs(0, input());
+    _quantize->inputs(1, _scale);
+    _quantize->inputs(2, _zerop);
+    _quantize_out->input(_quantize);
+    _dequantize->inputs(0, _quantize_out);
+    _dequantize->inputs(1, _scale);
+    _dequantize->inputs(2, _zerop);
+    _dequantize_out->input(_dequantize);
+
+    output()->from(_dequantize_out);
+  }
+};
+
+class S16ConstOnnxQDQTest : public luci::ConstantFoldingAddTestGraph, public ::testing::Test
+{
+public:
+  S16ConstOnnxQDQTest() : luci::ConstantFoldingAddTestGraph({2, 2, 2}, loco::DataType::S16) {}
+
+  virtual void SetUp() { init(); }
+
+  loco::Node *createFoldedPattern() override
+  {
+    _quantize = _g.nodes()->create<luci::CircleCustom>(3, 1);
+    _quantize_out = _g.nodes()->create<luci::CircleCustomOut>();
+    _dequantize = _g.nodes()->create<luci::CircleCustom>(3, 1);
+    _dequantize_out = _g.nodes()->create<luci::CircleCustomOut>();
+    _scale = _g.nodes()->create<luci::CircleConst>();
+    _zerop = _g.nodes()->create<luci::CircleConst>();
+    _input = _g.nodes()->create<luci::CircleConst>();
+
+    _quantize->dtype(loco::DataType::S16);
+    _quantize_out->dtype(loco::DataType::S16);
+    _dequantize->dtype(loco::DataType::FLOAT32);
+    _dequantize_out->dtype(loco::DataType::FLOAT32);
+    _scale->dtype(loco::DataType::FLOAT32);
+    _zerop->dtype(loco::DataType::S16);
+    _input->dtype(loco::DataType::FLOAT32);
+
+    _scale->shape({1});
+    _zerop->shape({1});
+    _input->shape({2, 2, 2});
+
+    _scale->size<loco::DataType::FLOAT32>(1);
+    _scale->at<loco::DataType::FLOAT32>(0) = 5.0;
+
+    _zerop->size<loco::DataType::S16>(1);
+    _zerop->at<loco::DataType::S16>(0) = 0;
+
+    _input->size<loco::DataType::FLOAT32>(8);
+    for (uint32_t i = 0; i < 8; i++)
+      _input->at<loco::DataType::FLOAT32>(i) = i;
+
+    _quantize->custom_code("ONNXQuantizeLinear");
+    _quantize_out->index(0);
+
+    _dequantize->custom_code("ONNXDequantizeLinear");
+    _dequantize_out->index(0);
+
+    _scale->name("scale");
+    _zerop->name("zerop");
+    _quantize->name("quantize");
+    _quantize_out->name("quantize_out");
+    _dequantize->name("dequantize");
+    _dequantize_out->name("dequantize_out");
+
+    _quantize->inputs(0, _input);
+    _quantize->inputs(1, _scale);
+    _quantize->inputs(2, _zerop);
+    _quantize_out->input(_quantize);
+    _dequantize->inputs(0, _quantize_out);
+    _dequantize->inputs(1, _scale);
+    _dequantize->inputs(2, _zerop);
+    _dequantize_out->input(_dequantize);
+
+    return _dequantize_out;
+  }
+
+protected:
+  luci::CircleCustom *_quantize = nullptr;
+  luci::CircleCustomOut *_quantize_out = nullptr;
+  luci::CircleCustom *_dequantize = nullptr;
+  luci::CircleCustomOut *_dequantize_out = nullptr;
+  luci::CircleConst *_scale = nullptr;
+  luci::CircleConst *_zerop = nullptr;
+  luci::CircleConst *_input = nullptr;
+};
+
+} // namespace
+
+TEST(QuantizeOnnxQDQTest, s16_quantize_onnx_qdq)
+{
+  S16QuantizeOnnxQDQTestGraph g;
+
+  luci::QuantizeOnnxQDQPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(QuantizeOnnxQDQTest, s16_quantize_onnx_qdq_NEG)
+{
+  S16QuantizeOnnxQDQTestGraph g;
+
+  luci::QuantizeOnnxQDQPass pass;
+
+  g.init();
+
+  g.input()->dtype(loco::DataType::S16);
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
+
+TEST(QuantizeOnnxQDQTest, u8_quantize_onnx_qdq)
+{
+  U8QuantizeOnnxQDQTestGraph g;
+
+  luci::QuantizeOnnxQDQPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(QuantizeOnnxQDQTest, u8_quantize_onnx_qdq_NEG)
+{
+  U8QuantizeOnnxQDQTestGraph g;
+
+  luci::QuantizeOnnxQDQPass pass;
+
+  g.init();
+
+  g.input()->dtype(loco::DataType::U8);
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
+
+TEST_F(S16ConstOnnxQDQTest, s16_const_qdq)
+{
+  luci::QuantizeOnnxQDQPass pass;
+  while (pass.run(graph()))
+    ;
+
+  auto folded_const = getFoldedPattern();
+  EXPECT_NE(nullptr, folded_const);
+
+  // Chec type, shape, values of folded const
+  EXPECT_EQ(loco::DataType::S16, folded_const->dtype());
+  EXPECT_EQ(3, folded_const->rank());
+  EXPECT_EQ(2, folded_const->dim(0).value());
+  EXPECT_EQ(2, folded_const->dim(1).value());
+  EXPECT_EQ(2, folded_const->dim(2).value());
+  EXPECT_EQ(0, folded_const->at<loco::DataType::S16>(0));
+  EXPECT_EQ(0, folded_const->at<loco::DataType::S16>(1));
+  EXPECT_EQ(0, folded_const->at<loco::DataType::S16>(2));
+  EXPECT_EQ(1, folded_const->at<loco::DataType::S16>(3));
+  EXPECT_EQ(1, folded_const->at<loco::DataType::S16>(4));
+  EXPECT_EQ(1, folded_const->at<loco::DataType::S16>(5));
+  EXPECT_EQ(1, folded_const->at<loco::DataType::S16>(6));
+  EXPECT_EQ(1, folded_const->at<loco::DataType::S16>(7));
+}
index 59329c1..17a887c 100644 (file)
@@ -407,8 +407,6 @@ void QuantizeWeights::quantize_weights(luci::CircleConst *weights)
     {
       sym_wquant_per_channel(weights, scaling_factor, channel_dim_index);
     }
-    quantparam->min.clear();
-    quantparam->max.clear();
     quantparam->quantized_dimension = channel_dim_index;
   }
   // Find min/max per layer-wise
@@ -449,8 +447,6 @@ void QuantizeWeights::quantize_weights(luci::CircleConst *weights)
     auto min = quantparam->min[0];
     auto scaling_factor = quantparam->scale[0];
     asym_wquant_per_layer(weights, min, scaling_factor);
-    quantparam->min.clear();
-    quantparam->max.clear();
   }
 }
 void QuantizeWeights::visit(luci::CircleConv2D *node)
index e69a7b6..edaf13e 100644 (file)
@@ -68,9 +68,10 @@ void sym_wquant_per_channel(CircleConst *node, std::vector<float> &min, std::vec
                             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();
+  assert(out_type == loco::DataType::S4 || out_type == loco::DataType::S8 ||
+         out_type == loco::DataType::S16);
+
+  const int32_t kMaxScale = max_for_sym_quant(out_type);
   const int32_t kMinScale = -kMaxScale;
 
   uint32_t size = node->size<loco::DataType::FLOAT32>();
@@ -163,7 +164,12 @@ void QuantizeWeightsOnly::quantize_weights(luci::CircleConst *weights)
       std::vector<float> scaling_factor(min.size());
       std::vector<int64_t> zp(min.size());
 
-      if (output_type == loco::DataType::S8)
+      if (output_type == loco::DataType::S4)
+      {
+        sym_wquant_per_channel<loco::DataType::S4>(weights, min, max, scaling_factor, nudged_min,
+                                                   nudged_max, channel_dim_index);
+      }
+      else 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);
@@ -205,6 +211,20 @@ void QuantizeWeightsOnly::visit(luci::CircleConv2D *node)
   }
 }
 
+void QuantizeWeightsOnly::visit(luci::CircleFullyConnected *node)
+{
+  LOGGER(l);
+  INFO(l) << "QuantizeWeightsOnly visit node: " << node->name() << std::endl;
+
+  auto weights = loco::must_cast<luci::CircleConst *>(node->weights());
+  if (!is_quantized(weights))
+  {
+    auto new_weights = luci::clone(weights);
+    node->weights(new_weights);
+    quantize_weights(new_weights);
+  }
+}
+
 void QuantizeWeightsOnly::visit(luci::CircleDepthwiseConv2D *node)
 {
   LOGGER(l);
index ff6ad32..8d1421f 100644 (file)
@@ -43,6 +43,7 @@ private:
 
   void visit(luci::CircleConv2D *node);
   void visit(luci::CircleDepthwiseConv2D *node);
+  void visit(luci::CircleFullyConnected *node);
   void visit(luci::CircleNode *);
 };
 
index 4f4edaf..bdb50d6 100644 (file)
@@ -78,7 +78,7 @@ luci::CircleQuantize *create_quantize_op(luci::CircleNode *node, loco::DataType
   auto qtype = luci::activation_qtype(node);
   if (use_predefined_values(qtype))
   {
-    quantize->quantparam(luci::make_predefined_qparam(qtype, out_type));
+    quantize->quantparam(luci::make_predefined_qparam(qtype, out_type, node->quantparam()));
     return quantize;
   }
 
@@ -232,16 +232,25 @@ private:
   }
 
 // INPUT_NAME1 and INPUT_NAME2 are the only activations of NODE
-#define INSERT_QUANTIZE_TO_BINARY_OP(NODE, INPUT_NAME1, INPUT_NAME2)       \
-  void visit(NODE *node)                                                   \
-  {                                                                        \
-    if (auto input1_quant = create_in_quantize(node->INPUT_NAME1(), node)) \
-      node->INPUT_NAME1(input1_quant);                                     \
-                                                                           \
-    if (auto input2_quant = create_in_quantize(node->INPUT_NAME2(), node)) \
-      node->INPUT_NAME2(input2_quant);                                     \
-                                                                           \
-    insert_out_quantize(node);                                             \
+#define INSERT_QUANTIZE_TO_BINARY_OP(NODE, INPUT_NAME1, INPUT_NAME2)         \
+  void visit(NODE *node)                                                     \
+  {                                                                          \
+    if (node->INPUT_NAME1() == node->INPUT_NAME2())                          \
+    {                                                                        \
+      if (auto input1_quant = create_in_quantize(node->INPUT_NAME1(), node)) \
+      {                                                                      \
+        node->INPUT_NAME1(input1_quant);                                     \
+        node->INPUT_NAME2(input1_quant);                                     \
+      }                                                                      \
+      return;                                                                \
+    }                                                                        \
+    if (auto input1_quant = create_in_quantize(node->INPUT_NAME1(), node))   \
+      node->INPUT_NAME1(input1_quant);                                       \
+                                                                             \
+    if (auto input2_quant = create_in_quantize(node->INPUT_NAME2(), node))   \
+      node->INPUT_NAME2(input2_quant);                                       \
+                                                                             \
+    insert_out_quantize(node);                                               \
   }
 
   // Default behavior (NYI)
@@ -584,7 +593,7 @@ bool QuantizeWithMinMaxPass::run(loco::Graph *g)
   for (auto node : loco::all_nodes(g))
   {
     auto circle_node = loco::must_cast<luci::CircleNode *>(node);
-    QuantizeActivation qa(_ctx->input_model_dtype, quantize_dtype(circle_node));
+    QuantizeActivation qa(quantize_dtype(circle_node));
     circle_node->accept(&qa);
   }
 
@@ -637,7 +646,7 @@ bool QuantizeWithMinMaxPass::run(loco::Graph *g)
     if (circle_node->quantparam() == nullptr)
       continue;
 
-    QuantizeSpecialActivation qsa(_ctx->input_model_dtype, quantize_dtype(circle_node));
+    QuantizeSpecialActivation qsa(quantize_dtype(circle_node));
     circle_node->accept(&qsa);
   }
 
@@ -700,15 +709,18 @@ bool QuantizeWithMinMaxPass::run(loco::Graph *g)
     phase_runner.run(phase);
   }
 
-  // Remove min/max values
-  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  if (not _ctx->save_min_max)
   {
-    auto circle_node = loco::must_cast<luci::CircleNode *>(node);
-    if (auto qparam = circle_node->quantparam())
+    // Remove min/max values
+    for (auto node : loco::all_nodes(g))
     {
-      warn_accuracy_with_range(circle_node);
-      qparam->min.clear();
-      qparam->max.clear();
+      auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+      if (auto qparam = circle_node->quantparam())
+      {
+        warn_accuracy_with_range(circle_node);
+        qparam->min.clear();
+        qparam->max.clear();
+      }
     }
   }
 
index 49c2d46..9e47165 100644 (file)
@@ -51,6 +51,51 @@ public:
   luci::CircleConst *input_2 = nullptr;
 };
 
+class SimpleConcatGraphWithMinMaxValues
+{
+public:
+  SimpleConcatGraphWithMinMaxValues(loco::DataType quant_type)
+  {
+    concat_node = g.nodes()->create<luci::CircleConcatenation>(2);
+    input_1 = g.nodes()->create<luci::CircleInput>();
+    input_2 = g.nodes()->create<luci::CircleInput>();
+
+    concat_node->dtype(quant_type);
+    concat_node->fusedActivationFunction(luci::FusedActFunc::NONE);
+    auto concat_node_quant_params = std::make_unique<luci::CircleQuantParam>();
+    concat_node_quant_params->min = {-1};
+    concat_node_quant_params->max = {1};
+    concat_node->quantparam(std::move(concat_node_quant_params));
+
+    input_1->dtype(quant_type);
+    auto input1_node_quant_params = std::make_unique<luci::CircleQuantParam>();
+    input1_node_quant_params->min = {-1};
+    input1_node_quant_params->max = {1};
+    input_1->quantparam(std::move(input1_node_quant_params));
+
+    input_2->dtype(quant_type);
+    auto input2_node_quant_params = std::make_unique<luci::CircleQuantParam>();
+    input2_node_quant_params->min = {-1};
+    input2_node_quant_params->max = {1};
+    input_2->quantparam(std::move(input2_node_quant_params));
+
+    concat_node->values(0, input_1);
+    concat_node->values(1, input_2);
+  }
+
+  ~SimpleConcatGraphWithMinMaxValues()
+  {
+    concat_node->values(0, nullptr);
+    concat_node->values(1, nullptr);
+  }
+
+public:
+  loco::Graph g;
+  luci::CircleConcatenation *concat_node = nullptr;
+  luci::CircleInput *input_1 = nullptr;
+  luci::CircleInput *input_2 = nullptr;
+};
+
 TEST(QuantizeWithMinMaxPassTest, name)
 {
   auto ctx = std::make_unique<luci::QuantizeWithMinMaxPass::Context>();
@@ -105,3 +150,30 @@ TEST(QuantizeWithMinMaxPassTest, inactive_input)
 
   EXPECT_NO_THROW(qwmm.run(&g.g));
 }
+
+// Test saving min max
+TEST(QuantizeWithMinMaxPassTest, save_min_max_test)
+{
+  SimpleConcatGraphWithMinMaxValues g(loco::DataType::FLOAT32);
+
+  auto ctx = std::make_unique<luci::QuantizeWithMinMaxPass::Context>();
+  {
+    ctx->input_model_dtype = loco::DataType::FLOAT32;
+    ctx->output_model_dtype = loco::DataType::U8;
+    ctx->granularity = luci::QuantizationGranularity::LayerWise;
+    ctx->save_min_max = true;
+  }
+
+  luci::QuantizeWithMinMaxPass qwmm(std::move(ctx));
+
+  qwmm.run(&g.g);
+
+  EXPECT_NE(0, g.input_1->quantparam()->min.size());
+  EXPECT_NE(0, g.input_1->quantparam()->max.size());
+
+  EXPECT_NE(0, g.input_2->quantparam()->min.size());
+  EXPECT_NE(0, g.input_2->quantparam()->max.size());
+
+  EXPECT_NE(0, g.concat_node->quantparam()->min.size());
+  EXPECT_NE(0, g.concat_node->quantparam()->max.size());
+}
diff --git a/compiler/luci/pass/src/QuantizeWithPredecessorPass.cpp b/compiler/luci/pass/src/QuantizeWithPredecessorPass.cpp
new file mode 100644 (file)
index 0000000..352653b
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "QuantizeWithPredecessorPass.h"
+
+#include "QuantizationUtils.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeVisitor.h>
+#include <luci/Log.h>
+
+#include <limits>
+
+namespace
+{
+
+// Quantize dst node using src node's qparam
+// Return true if dst node is quantized with src
+// Return false otherwise
+bool quantize_with_same_qparam(luci::CircleNode *src, luci::CircleNode *dst)
+{
+  // src node is not quantized. Skip this case.
+  auto src_qparam = src->quantparam();
+  if (not src_qparam)
+    return false;
+
+  auto dst_qparam = dst->quantparam();
+  // dst node is already quantized. Skip this case.
+  if (dst_qparam)
+    return false;
+
+  luci::copy_quantparam(src, dst);
+
+  dst->dtype(src->dtype());
+
+  return true;
+}
+
+//  Visitor to quantize nodes using predecessors qparams
+struct QuantizeWithPredecessor final : public luci::CircleNodeMutableVisitor<bool>
+{
+  QuantizeWithPredecessor() = default;
+
+  bool visit(luci::CircleNode *) { return false; }
+
+  bool visit(luci::CircleReshape *node)
+  {
+    auto input_node = loco::must_cast<luci::CircleNode *>(node->tensor());
+    return quantize_with_same_qparam(input_node, node);
+  }
+
+  bool visit(luci::CircleTranspose *node)
+  {
+    auto input_node = loco::must_cast<luci::CircleNode *>(node->a());
+    return quantize_with_same_qparam(input_node, node);
+  }
+
+  bool visit(luci::CircleStridedSlice *node)
+  {
+    auto input_node = loco::must_cast<luci::CircleNode *>(node->input());
+    return quantize_with_same_qparam(input_node, node);
+  }
+
+  bool visit(luci::CircleSqueeze *node)
+  {
+    auto input_node = loco::must_cast<luci::CircleNode *>(node->input());
+    return quantize_with_same_qparam(input_node, node);
+  }
+
+  bool visit(luci::CircleGather *node)
+  {
+    auto input_node = loco::must_cast<luci::CircleNode *>(node->params());
+    return quantize_with_same_qparam(input_node, node);
+  }
+
+  bool visit(luci::CircleMul *node)
+  {
+    // Skip if node is already quantized
+    if (luci::is_quantized(node))
+      return false;
+
+    auto x = loco::must_cast<luci::CircleNode *>(node->x());
+    auto y = loco::must_cast<luci::CircleNode *>(node->y());
+
+    // Only support square for now
+    if (x != y)
+      return false;
+
+    // Only support S16 for now
+    if (x->dtype() != loco::DataType::S16)
+      return false;
+
+    const auto input_qparam = x->quantparam();
+    if (not input_qparam)
+      return false;
+
+    if (input_qparam->scale.size() != 1)
+      return false;
+
+    const auto input_scale = input_qparam->scale.at(0);
+
+    const auto s16_max = std::numeric_limits<int16_t>::max();
+    // How to determine a new scale of x^2?
+    // x's scale would have been determined by its max or min
+    //
+    // Max value of x^2 = (s * s16_max)^2
+    // Min value of x^2 = 0
+    // New scale = (s * s16_max)^2 / s16_max = s^2 * s16_max
+    //
+    // NOTE s16_max = -s16_min (symmetric quantization)
+    const auto output_scale = input_scale * input_scale * s16_max;
+
+    auto new_qparam = std::make_unique<luci::CircleQuantParam>();
+    {
+      new_qparam->scale.push_back(output_scale);
+      new_qparam->zerop.push_back(0);
+    }
+
+    node->quantparam(std::move(new_qparam));
+    node->dtype(x->dtype());
+
+    return true;
+  }
+
+  bool visit(luci::CircleNeg *node)
+  {
+    auto input_node = loco::must_cast<luci::CircleNode *>(node->x());
+    // Only support S16 for now
+    if (input_node->dtype() != loco::DataType::S16)
+      return false;
+
+    return quantize_with_same_qparam(input_node, node);
+  }
+
+  bool visit(luci::CircleConcatenation *node)
+  {
+    const auto num_inputs = node->numValues();
+
+    for (uint32_t i = 0; i < num_inputs; i++)
+    {
+      auto input = loco::must_cast<luci::CircleNode *>(node->values(i));
+      // Only support S16 for now
+      if (input->dtype() != loco::DataType::S16)
+        return false;
+
+      if (input->quantparam() == nullptr)
+        return false;
+
+      if (input->quantparam()->scale.size() != 1)
+        return false;
+    }
+
+    luci::CircleNode *max_scale_node = nullptr;
+    float max_scale = 0.0;
+    for (uint32_t i = 0; i < num_inputs; i++)
+    {
+      auto input = loco::must_cast<luci::CircleNode *>(node->values(i));
+      auto qparam = input->quantparam();
+      auto scale = qparam->scale.at(0);
+      if (max_scale < scale)
+      {
+        max_scale = scale;
+        max_scale_node = input;
+      }
+    }
+
+    if (max_scale_node == nullptr)
+    {
+      throw std::runtime_error{"Invalid max_scale_node"};
+    }
+
+    return quantize_with_same_qparam(max_scale_node, node);
+  }
+};
+
+} // namespace
+
+namespace luci
+{
+
+bool QuantizeWithPredecessorPass::run(loco::Graph *g)
+{
+  bool changed = false;
+
+  LOGGER(l);
+
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+    INFO(l) << "QuantizeWithPredecessorPass visit node: " << circle_node->name() << std::endl;
+
+    QuantizeWithPredecessor qwp;
+    if (circle_node->accept(&qwp))
+    {
+      changed = true;
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/QuantizeWithPredecessorPass.h b/compiler/luci/pass/src/QuantizeWithPredecessorPass.h
new file mode 100644 (file)
index 0000000..e182c79
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_WITH_PREDECESSOR_PASS_H__
+#define __LUCI_QUANTIZE_WITH_PREDECESSOR_PASS_H__
+
+#include <logo/Pass.h>
+
+namespace luci
+{
+
+/**
+ * @brief  Class to quantize nodes using their predecessors' qparam
+ *
+ */
+struct QuantizeWithPredecessorPass final : public logo::Pass
+{
+  const char *name(void) const final { return "luci::QuantizeWithPredecessor"; }
+
+  bool run(loco::Graph *g) final;
+};
+
+} // namespace luci
+
+#endif // __LUCI_QUANTIZE_WITH_PREDECESSOR_PASS_H__
diff --git a/compiler/luci/pass/src/QuantizeWithPredecessorPass.test.cpp b/compiler/luci/pass/src/QuantizeWithPredecessorPass.test.cpp
new file mode 100644 (file)
index 0000000..20d4f90
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "QuantizeWithPredecessorPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+void addQuantParam(luci::CircleNode *node, const std::vector<float> &scale,
+                   const std::vector<int64_t> &zp)
+{
+  assert(node->quantparam() == nullptr);
+
+  auto quantparam = std::make_unique<luci::CircleQuantParam>();
+  quantparam->scale = scale;
+  quantparam->zerop = zp;
+  node->quantparam(std::move(quantparam));
+}
+
+/**
+ *  Simple graph for test
+ *
+ *  BEFORE
+ *
+ *        [Conv] (int16)
+ *           |
+ *       [Reshape] (fp32)
+ *
+ *  AFTER
+ *
+ *        [Conv] (int16)
+ *           |
+ *       [Reshape] (int16)
+ *
+ */
+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());
+
+    conv->dtype(loco::DataType::S16);
+    reshape->dtype(loco::DataType::FLOAT32);
+
+    addQuantParam(conv, {1.0}, {0});
+
+    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;
+};
+
+/**
+ *  Simple graph for test
+ *
+ *  BEFORE
+ *
+ *        [Conv] (int16)
+ *           |
+ *       [Squeeze] (fp32)
+ *
+ *  AFTER
+ *
+ *        [Conv] (int16)
+ *           |
+ *       [Squeeze] (int16)
+ *
+ */
+class ConvSqueezeGraph
+{
+public:
+  ConvSqueezeGraph()
+  {
+    input = g.nodes()->create<luci::CircleInput>();
+    conv = g.nodes()->create<luci::CircleConv2D>();
+    squeeze = g.nodes()->create<luci::CircleSqueeze>();
+    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());
+
+    conv->dtype(loco::DataType::S16);
+    squeeze->dtype(loco::DataType::FLOAT32);
+
+    addQuantParam(conv, {1.0}, {0});
+
+    squeeze->squeeze_dims({0});
+
+    conv->input(input);
+    squeeze->input(conv);
+    output->from(squeeze);
+  }
+
+public:
+  loco::Graph g;
+  luci::CircleInput *input = nullptr;
+  luci::CircleConv2D *conv = nullptr;
+  luci::CircleSqueeze *squeeze = nullptr;
+  luci::CircleOutput *output = nullptr;
+};
+
+/**
+ *  Simple graph for test
+ *
+ *  BEFORE
+ *
+ *        [Conv] (int16)
+ *           |
+ *         [Mul] (fp32)
+ *
+ *  AFTER
+ *
+ *        [Conv] (int16)
+ *           |
+ *         [Mul] (int16)
+ *
+ */
+class ConvMulGraph
+{
+public:
+  ConvMulGraph()
+  {
+    input = g.nodes()->create<luci::CircleInput>();
+    conv = g.nodes()->create<luci::CircleConv2D>();
+    mul = g.nodes()->create<luci::CircleMul>();
+    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());
+
+    conv->dtype(loco::DataType::S16);
+    mul->dtype(loco::DataType::FLOAT32);
+
+    addQuantParam(conv, {1.0}, {0});
+
+    conv->input(input);
+    mul->x(conv);
+    mul->y(conv);
+    output->from(mul);
+  }
+
+public:
+  loco::Graph g;
+  luci::CircleInput *input = nullptr;
+  luci::CircleConv2D *conv = nullptr;
+  luci::CircleMul *mul = nullptr;
+  luci::CircleOutput *output = nullptr;
+};
+
+} // namespace
+
+TEST(QuantizeWithPredecessor, reshape)
+{
+  ConvReshapeGraph g;
+
+  luci::QuantizeWithPredecessorPass pass;
+  while (pass.run(&g.g))
+    ;
+
+  EXPECT_NE(nullptr, g.reshape->quantparam());
+  EXPECT_FLOAT_EQ(1.0, g.reshape->quantparam()->scale[0]);
+  EXPECT_EQ(0, g.reshape->quantparam()->zerop[0]);
+}
+
+TEST(QuantizeWithPredecessor, reshape_NEG)
+{
+  ConvReshapeGraph g;
+  g.conv->quantparam(nullptr);
+
+  luci::QuantizeWithPredecessorPass pass;
+  EXPECT_FALSE(pass.run(&g.g));
+}
+
+TEST(QuantizeWithPredecessor, squeeze)
+{
+  ConvSqueezeGraph g;
+
+  luci::QuantizeWithPredecessorPass pass;
+  while (pass.run(&g.g))
+    ;
+
+  EXPECT_NE(nullptr, g.squeeze->quantparam());
+  EXPECT_FLOAT_EQ(1.0, g.squeeze->quantparam()->scale[0]);
+  EXPECT_EQ(0, g.squeeze->quantparam()->zerop[0]);
+}
+
+TEST(QuantizeWithPredecessor, squeeze_NEG)
+{
+  ConvSqueezeGraph g;
+  g.conv->quantparam(nullptr);
+
+  luci::QuantizeWithPredecessorPass pass;
+  EXPECT_FALSE(pass.run(&g.g));
+}
+
+TEST(QuantizeWithPredecessor, mul)
+{
+  ConvMulGraph g;
+
+  luci::QuantizeWithPredecessorPass pass;
+  while (pass.run(&g.g))
+    ;
+
+  EXPECT_NE(nullptr, g.mul->quantparam());
+  EXPECT_FLOAT_EQ(32767, g.mul->quantparam()->scale[0]);
+  EXPECT_EQ(0, g.mul->quantparam()->zerop[0]);
+}
+
+TEST(QuantizeWithPredecessor, mul_NEG)
+{
+  ConvMulGraph g;
+  g.conv->quantparam(nullptr);
+
+  luci::QuantizeWithPredecessorPass pass;
+  EXPECT_FALSE(pass.run(&g.g));
+}
index e50dda9..bec9119 100644 (file)
@@ -122,9 +122,15 @@ bool RemoveDuplicateConstPass::remove_duplicate_const()
           case loco::DataType::S8:
             is_equal = is_equal_consts<loco::DataType::S8>(reference_const, cur_const);
             break;
+          case loco::DataType::S4:
+            is_equal = is_equal_consts<loco::DataType::S4>(reference_const, cur_const);
+            break;
           case loco::DataType::U8:
             is_equal = is_equal_consts<loco::DataType::U8>(reference_const, cur_const);
             break;
+          case loco::DataType::U4:
+            is_equal = is_equal_consts<loco::DataType::U4>(reference_const, cur_const);
+            break;
           default:
             continue;
         }
@@ -211,9 +217,15 @@ bool RemoveDuplicateConstPass::run(loco::Graph *g)
       case loco::DataType::S8:
         add_to_map<loco::DataType::S8>(const_node);
         break;
+      case loco::DataType::S4:
+        add_to_map<loco::DataType::S4>(const_node);
+        break;
       case loco::DataType::U8:
         add_to_map<loco::DataType::U8>(const_node);
         break;
+      case loco::DataType::U4:
+        add_to_map<loco::DataType::U4>(const_node);
+        break;
       default:
         continue;
     }
diff --git a/compiler/luci/pass/src/RemoveGatherGuardPass.cpp b/compiler/luci/pass/src/RemoveGatherGuardPass.cpp
new file mode 100644 (file)
index 0000000..920595c
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/RemoveGatherGuardPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <climits>
+
+namespace
+{
+
+/*
+ * BEFORE
+ *
+ *   [CircleNode]  [CircleNode]
+ *         |            |
+ *         |       [CircleAdd]
+ *         |            |
+ *         |     [CircleFloorMod]
+ *         |        /
+ *      [CircleGather]
+ *            |
+ *       [CircleNode]
+ *
+ * AFTER
+ *
+ *   [CircleNode]  [CircleNode]
+ *         |          |    \
+ *         |          |   [CircleAdd]
+ *         |          /        |
+ *         |         /    [CircleFloorMod]
+ *         |        /
+ *      [CircleGather]
+ *            |
+ *       [CircleNode]
+ */
+
+bool is_single_value_equal(const loco::Node *node, int32_t value)
+{
+  assert(node);
+
+  auto const cnode = dynamic_cast<const luci::CircleConst *>(node);
+  if (cnode == nullptr)
+    return false;
+  if (not(cnode->rank() == 0 || (cnode->rank() == 1 && cnode->dim(0).value() == 1)))
+    return false;
+
+  if (cnode->dtype() == loco::DataType::S32)
+    return cnode->at<loco::DataType::S32>(0) == value;
+  else if (cnode->dtype() == loco::DataType::S64)
+    return cnode->at<loco::DataType::S64>(0) == static_cast<int64_t>(value);
+
+  return false;
+}
+
+bool remove_guards(luci::CircleGather *gather)
+{
+  assert(gather);
+  // check if sequence is Add+FloorMod
+  auto floormod = dynamic_cast<luci::CircleFloorMod *>(gather->indices());
+  if (floormod == nullptr)
+    return false;
+  auto add = dynamic_cast<luci::CircleAdd *>(floormod->x());
+  if (add == nullptr)
+    return false;
+
+  if (add->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return false;
+
+  // check if gather axis is 0 for now
+  // TODO support other axis
+  if (gather->axis() != 0)
+    return false;
+  // check if RHS of Add and FloorMod is Const and is scalar/single element and
+  // the value is same as gather.params.dim(0)
+  luci::CircleNode *params = loco::must_cast<luci::CircleNode *>(gather->params());
+  if (params->shape_status() != luci::ShapeStatus::VALID || params->rank() == 0)
+    return false;
+  // safe range check
+  if (params->dim(gather->axis()).value() >= INT_MAX)
+    return false;
+  int32_t params_axis_dim = static_cast<int32_t>(params->dim(gather->axis()).value());
+  if (not is_single_value_equal(add->y(), params_axis_dim))
+    return false;
+  if (not is_single_value_equal(floormod->y(), params_axis_dim))
+    return false;
+
+  // disconnect Add+FloorMod
+  gather->indices(add->x());
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool RemoveGatherGuardPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto gather = dynamic_cast<luci::CircleGather *>(node))
+    {
+      if (remove_guards(gather))
+        changed = true;
+    }
+  }
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/RemoveGatherGuardPass.test.cpp b/compiler/luci/pass/src/RemoveGatherGuardPass.test.cpp
new file mode 100644 (file)
index 0000000..6de51dd
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/RemoveGatherGuardPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class GatherGuardGraphlet
+{
+public:
+  GatherGuardGraphlet() = default;
+
+public:
+  void init(loco::Graph *g, const ShapeU32 params_s, const ShapeU32 indices_s,
+            const ShapeU32 output_s)
+  {
+    std::vector<uint32_t> params_shape{params_s};
+
+    _add_y = g->nodes()->create<luci::CircleConst>();
+    _add_y->rank(0);
+    _add_y->shape_status(luci::ShapeStatus::VALID);
+    _add_y->dtype(loco::DataType::S32);
+    _add_y->size<loco::DataType::S32>(1);
+    _add_y->at<loco::DataType::S32>(0) = params_shape[0];
+
+    _add = g->nodes()->create<luci::CircleAdd>();
+    _add->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _add->dtype(loco::DataType::S32);
+    _add->shape(indices_s);
+    _add->shape_status(luci::ShapeStatus::VALID);
+
+    _fm_y = g->nodes()->create<luci::CircleConst>();
+    _fm_y->rank(0);
+    _fm_y->shape_status(luci::ShapeStatus::VALID);
+    _fm_y->dtype(loco::DataType::S32);
+    _fm_y->size<loco::DataType::S32>(1);
+    _fm_y->at<loco::DataType::S32>(0) = params_shape[0];
+
+    _fm = g->nodes()->create<luci::CircleFloorMod>();
+    _fm->dtype(loco::DataType::S32);
+    _fm->shape(indices_s);
+    _fm->shape_status(luci::ShapeStatus::VALID);
+
+    _gather = g->nodes()->create<luci::CircleGather>();
+    _gather->axis(0);
+    _gather->dtype(loco::DataType::FLOAT32);
+    _gather->shape(output_s);
+    _gather->shape_status(luci::ShapeStatus::VALID);
+  }
+
+protected:
+  luci::CircleAdd *_add = nullptr;
+  luci::CircleConst *_add_y = nullptr;
+  luci::CircleFloorMod *_fm = nullptr;
+  luci::CircleConst *_fm_y = nullptr;
+  luci::CircleGather *_gather = nullptr;
+};
+
+class GatherGuardGraph : public TestIsGraphlet<2>, public TestOGraphlet, public GatherGuardGraphlet
+{
+public:
+  GatherGuardGraph() = default;
+
+public:
+  void init(const ShapeU32 params_s, const ShapeU32 indices_s, const ShapeU32 output_s)
+  {
+    TestIsGraphlet<2>::init(g(), {params_s, indices_s});
+    TestOGraphlet::init(g(), output_s);
+    GatherGuardGraphlet::init(g(), params_s, indices_s, output_s);
+
+    // connect graph
+    _add->x(input(1));
+    _add->y(_add_y);
+    _fm->x(_add);
+    _fm->y(_fm_y);
+    _gather->params(input(0));
+    _gather->indices(_fm);
+    output()->from(_gather);
+  }
+};
+
+class GatherGuardGraphTest : public ::testing::Test, public GatherGuardGraph
+{
+protected:
+  luci::RemoveGatherGuardPass _pass;
+
+  ShapeU32 _input_s0 = {10, 3};
+  ShapeU32 _input_s1 = {5, 4};
+  ShapeU32 _output_s = {5, 4, 3};
+};
+
+} // namespace
+
+TEST_F(GatherGuardGraphTest, name)
+{
+  auto const name = _pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST_F(GatherGuardGraphTest, removed)
+{
+  // test to check pass is working as expected
+
+  init(_input_s0, _input_s1, _output_s);
+
+  auto *indices_before = loco::must_cast<luci::CircleNode *>(_gather->indices());
+  EXPECT_NE(input(1), indices_before);
+
+  EXPECT_TRUE(_pass.run(g()));
+
+  auto *indices_after = loco::must_cast<luci::CircleNode *>(_gather->indices());
+  EXPECT_EQ(input(1), indices_after);
+}
+
+TEST_F(GatherGuardGraphTest, axis_value_NEG)
+{
+  // test if fails when gather->params->dim(0) != add/floormod rhs value
+
+  init(_input_s0, _input_s1, _output_s);
+
+  _add_y->at<loco::DataType::S32>(0) = 11;
+  EXPECT_FALSE(_pass.run(g()));
+  _add_y->at<loco::DataType::S32>(0) = 10;
+
+  _fm_y->at<loco::DataType::S32>(0) = 11;
+  EXPECT_FALSE(_pass.run(g()));
+}
+
+TEST_F(GatherGuardGraphTest, add_act_not_none_NEG)
+{
+  // test if fails when add activation function is not none
+
+  init(_input_s0, _input_s1, _output_s);
+
+  _add->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+  EXPECT_FALSE(_pass.run(g()));
+}
diff --git a/compiler/luci/pass/src/RemoveQDQForMixedPrecisionOpPass.cpp b/compiler/luci/pass/src/RemoveQDQForMixedPrecisionOpPass.cpp
new file mode 100644 (file)
index 0000000..1f796cd
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/RemoveQDQForMixedPrecisionOpPass.h"
+
+#include <luci/IR/CircleNode.h>
+
+/**
+ *  Remove Quantize-Dequantize pattern for backends with mixed-precision operator.
+ *
+ *  BEFORE
+ *                                          [CircleNode_1]
+ *                                                |
+ *                             [CircleQuantize, dtype_1, scale_1, zero_point_1]
+ *                                                |
+ *                                       [CircleDequantize]
+ *                                                |
+ *                             [CircleQuantize, dtype_2, scale_2, zero_point_2]
+ *                                                |
+ *                                       [CircleDequantize]
+ *                                                |
+ *                                         [CircleNode_2]
+ *
+ *  AFTER
+ *
+ *                                          [CircleNode_1]
+ *                                                |
+ *                             [CircleQuantize, dtype_2, scale_2, zero_point_2]
+ *                                                |
+ *                                       [CircleDequantize]
+ *                                                |
+ *                                         [CircleNode_2]
+ *
+ */
+
+namespace
+{
+
+bool remove_qdq_for_mpo(luci::CircleDequantize *node)
+{
+  auto prev = dynamic_cast<luci::CircleQuantize *>(node->input());
+  if (not prev)
+    return false;
+
+  auto prev_prev = dynamic_cast<luci::CircleDequantize *>(prev->input());
+  if (not prev_prev)
+    return false;
+
+  auto prev_prev_prev = dynamic_cast<luci::CircleQuantize *>(prev_prev->input());
+  if (not prev_prev_prev)
+    return false;
+
+  auto input = loco::must_cast<luci::CircleNode *>(prev_prev_prev->input());
+
+  const static std::set<luci::CircleOpcode> supported_ops{luci::CircleOpcode::FULLY_CONNECTED,
+                                                          luci::CircleOpcode::BATCH_MATMUL};
+
+  if (supported_ops.find(input->opcode()) == supported_ops.end())
+    return false;
+
+  prev->input(input);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool RemoveQDQForMixedPrecisionOpPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::postorder_traversal(loco::output_nodes(g)))
+  {
+    if (auto dq = dynamic_cast<luci::CircleDequantize *>(node))
+    {
+      if (remove_qdq_for_mpo(dq))
+        changed = true;
+    }
+  }
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/RemoveQDQForMixedPrecisionOpPass.test.cpp b/compiler/luci/pass/src/RemoveQDQForMixedPrecisionOpPass.test.cpp
new file mode 100644 (file)
index 0000000..69e18da
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/RemoveQDQForMixedPrecisionOpPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class QuantDequantGraphlet
+{
+public:
+  QuantDequantGraphlet() = default;
+
+public:
+  void init(loco::Graph *g)
+  {
+    _fc = g->nodes()->create<luci::CircleFullyConnected>();
+    _fc->name("fc");
+
+    _qu = g->nodes()->create<luci::CircleQuantize>();
+    _qu->name("qu");
+
+    _de = g->nodes()->create<luci::CircleDequantize>();
+    _de->name("de");
+
+    _qu_2 = g->nodes()->create<luci::CircleQuantize>();
+    _qu_2->name("qu");
+
+    _de_2 = g->nodes()->create<luci::CircleDequantize>();
+    _de_2->name("de");
+  }
+
+public:
+  luci::CircleFullyConnected *fc(void) { return _fc; }
+  luci::CircleQuantize *qu(void) { return _qu; }
+  luci::CircleQuantize *qu_2(void) { return _qu_2; }
+
+protected:
+  luci::CircleFullyConnected *_fc = nullptr;
+  luci::CircleQuantize *_qu = nullptr;
+  luci::CircleDequantize *_de = nullptr;
+  luci::CircleQuantize *_qu_2 = nullptr;
+  luci::CircleDequantize *_de_2 = nullptr;
+};
+
+class QuantDequantGraph : public TestIOGraph, public QuantDequantGraphlet
+{
+public:
+  QuantDequantGraph() = default;
+
+public:
+  void init(void)
+  {
+    TestIOGraph::init({1}, {1});
+    QuantDequantGraphlet::init(g());
+
+    _fc->input(input());
+    _qu->input(_fc);
+    _de->input(_qu);
+    _qu_2->input(_de);
+    _de_2->input(_qu_2);
+
+    output()->from(_de_2);
+  }
+};
+
+} // namespace
+
+TEST(RemoveQDQForMixedPrecisionOpPass, remove_qdq_FC)
+{
+  QuantDequantGraph g;
+  luci::RemoveQDQForMixedPrecisionOpPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+
+  EXPECT_EQ(g.fc(), g.qu_2()->input());
+}
+
+TEST(RemoveQDQForMixedPrecisionOpPass, remove_qdq_wrong_op_NEG)
+{
+  QuantDequantGraph g;
+  luci::RemoveQDQForMixedPrecisionOpPass pass;
+
+  g.init();
+
+  g.qu()->input(g.input());
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
diff --git a/compiler/luci/pass/src/RemoveUnnecessaryAddPass.cpp b/compiler/luci/pass/src/RemoveUnnecessaryAddPass.cpp
new file mode 100644 (file)
index 0000000..93887cc
--- /dev/null
@@ -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 "luci/Pass/RemoveUnnecessaryAddPass.h"
+
+#include "helpers/NodeFiller.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <limits> // std::numeric_limits
+
+namespace
+{
+
+bool remove_no_effect_add(luci::CircleNode *node)
+{
+  auto target_node = dynamic_cast<luci::CircleAdd *>(node);
+  if (target_node == nullptr || target_node->dtype() != loco::DataType::FLOAT32)
+    return false;
+
+  //  NOTE for general activation function A: Act(A + 0) != A
+  if (target_node->fusedActivationFunction() != luci::FusedActFunc::NONE)
+    return false;
+
+  luci::CircleConst *const_operand = nullptr;
+  luci::CircleNode *nonconst_operand = nullptr;
+  if (not luci::fill(&const_operand, &nonconst_operand).with_commutative_args_of(target_node))
+    return false;
+
+  if (dynamic_cast<luci::CircleConst *>(nonconst_operand) != nullptr)
+  {
+    // NOTE this is degenerated '(const1 + const2)' case
+    return false;
+  }
+
+  // check const_operand is zero
+
+  // NOTE we assume graph is valid, so no need to check shape.
+  // just check that const operand is zero
+  auto const size = const_operand->size<loco::DataType::FLOAT32>();
+  for (uint32_t index = 0; index < size; index++)
+  {
+    auto const value = const_operand->at<loco::DataType::FLOAT32>(index);
+    if (std::abs(value) > std::numeric_limits<float>::min())
+    {
+      // at least one value is not zero
+      return false;
+    }
+  }
+
+  replace(target_node).with(nonconst_operand);
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * BEFORE
+ *
+ *      [CircleNode]
+ *            |
+ *            |      [CircleConst(=0)]
+ *            |     /
+ *            |    /
+ *       [CircleAdd] (no activation)
+ *            |
+ *      [CircleNode]
+ *
+ * AFTER
+ *
+ *      [CircleNode]
+ *            |
+ *            |
+ *      [CircleNode]
+ *
+ **/
+bool RemoveUnnecessaryAddPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+    if (remove_no_effect_add(circle_node))
+    {
+      changed = true;
+    }
+  }
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/RemoveUnnecessaryAddPass.test.cpp b/compiler/luci/pass/src/RemoveUnnecessaryAddPass.test.cpp
new file mode 100644 (file)
index 0000000..c2b2640
--- /dev/null
@@ -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/RemoveUnnecessaryAddPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class AddGraphlet
+{
+public:
+  AddGraphlet() = default;
+
+public:
+  void init(loco::Graph *g, const ShapeU32 input_shape, bool fill_with_zeros, bool activation)
+  {
+    // zero Create.
+    _zero = g->nodes()->create<luci::CircleConst>();
+    _zero->rank(1);
+    _zero->dim(0).set(input_shape.size());
+    _zero->shape_status(luci::ShapeStatus::VALID);
+    _zero->dtype(loco::DataType::FLOAT32);
+    _zero->size<loco::DataType::FLOAT32>(input_shape.size());
+    for (int i = 0; i < input_shape.size(); ++i)
+      _zero->at<loco::DataType::FLOAT32>(i) = fill_with_zeros ? 0 : 1;
+    _zero->name("begin");
+
+    // Add Create.
+    _add = g->nodes()->create<luci::CircleAdd>();
+    _add->y(_zero);
+    if (activation)
+    {
+      _add->fusedActivationFunction(luci::FusedActFunc::RELU);
+    }
+    else
+    {
+      _add->fusedActivationFunction(luci::FusedActFunc::NONE);
+    }
+    _add->dtype(loco::DataType::FLOAT32);
+    _add->shape(input_shape);
+    _add->name("add");
+  }
+
+protected:
+  luci::CircleAdd *_add = nullptr;
+  luci::CircleConst *_zero = nullptr;
+};
+
+class AddGraph : public TestIOGraph, public AddGraphlet
+{
+public:
+  AddGraph() = default;
+
+public:
+  void init(const ShapeU32 shape, bool fill_with_zeros, bool activation)
+  {
+    TestIOGraph::init(shape, shape);
+    AddGraphlet::init(g(), shape, fill_with_zeros, activation);
+
+    _add->x(input());
+    output()->from(_add);
+  }
+};
+
+} // namespace
+
+TEST(RemoveUnnecessaryAddPass, name_test)
+{
+  luci::RemoveUnnecessaryAddPass pass;
+  auto const name = pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST(RemoveUnnecessaryAddPass, simple_test)
+{
+  luci::RemoveUnnecessaryAddPass pass;
+
+  AddGraph g;
+  g.init({1, 14, 21, 32}, true, false);
+
+  ASSERT_TRUE(pass.run(g.g()));
+
+  // check Add is removed
+  int count = 0;
+  for (auto node : loco::active_nodes(loco::output_nodes(g.g())))
+  {
+    if (auto add = dynamic_cast<luci::CircleAdd *>(node))
+      count++;
+  }
+  ASSERT_EQ(0, count);
+}
+
+TEST(RemoveUnnecessaryAddPass, not_removed_NEG)
+{
+  luci::RemoveUnnecessaryAddPass pass;
+  AddGraph g;
+  g.init({1, 14, 21, 32}, false, false);
+
+  ASSERT_FALSE(pass.run(g.g()));
+
+  // check Add is not removed
+  int count = 0;
+  for (auto node : loco::active_nodes(loco::output_nodes(g.g())))
+  {
+    if (auto add = dynamic_cast<luci::CircleAdd *>(node))
+      count++;
+  }
+  ASSERT_EQ(1, count);
+}
+
+TEST(RemoveUnnecessaryAddPass, activation_blocks_removal_NEG)
+{
+  luci::RemoveUnnecessaryAddPass pass;
+  AddGraph g;
+  g.init({1, 14, 21, 32}, true, true);
+
+  ASSERT_FALSE(pass.run(g.g()));
+
+  // check Add is not removed
+  int count = 0;
+  for (auto node : loco::active_nodes(loco::output_nodes(g.g())))
+  {
+    if (auto add = dynamic_cast<luci::CircleAdd *>(node))
+      count++;
+  }
+  ASSERT_EQ(1, count);
+}
diff --git a/compiler/luci/pass/src/RemoveUnnecessaryTransposeNetPass.cpp b/compiler/luci/pass/src/RemoveUnnecessaryTransposeNetPass.cpp
new file mode 100644 (file)
index 0000000..f9e0bf9
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/RemoveUnnecessaryTransposeNetPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+#include <vector>
+
+namespace
+{
+
+class TaggedShapeAnalyzer final
+{
+public:
+  /**
+   * @brief check 'Transpose-Reshape-Transpose' can be replaced by one 'Reshape'.
+   *
+   * @example
+   *  Let's explain how analyzer check Transpose-Reshape-Transpose pattern with an exact example.
+   *
+   *  Let's assume under pattern is given :
+   *
+   *      Input(1, 7, 7, 448)
+   *            |
+   *      Transpose(perm=(0, 3, 1, 2))
+   *            |
+   *      Resahape(shape=(1, 448, 49))
+   *            |
+   *      Transpose(perm=(0, 2, 1))
+   *            |
+   *      Output(1, 49, 448)
+   *
+   *  It simulates how each dimension of the tensor's shape are transformed/moved
+   *  using a member variable named '_shape'.
+   *  'tags' in _shape record the initial order of each dimension.
+   *
+   *   TIMELINE              |   _shape states :
+   *                         |
+   *   init_shape_with_tag   |    - value :   (1)   (7)   (7)   (448)
+   *                         |    - tags  :   (-)   (0)   (1)   (2)
+   *                         |
+   *   analyze_transpose     |    - value :   (1)   (448)  (7)  (7)
+   *                         |    - tags  :   (-)   (2)    (0)  (1)
+   *                         |
+   *   analyze_reshape       |    - value :   (1)   (448)   (49)
+   *                         |    - tags  :   (-)   (2)     (0, 1)
+   *                         |
+   *   anaylze_transpose     |    - value  :   (1)   (49)    (448)
+   *                         |    - tags   :   (-)   (0, 1)  (2)
+   *
+   *  After all simulation done, if tags are in same order as initial _shape,
+   *  Transpose has no effect in final shape, which they can be removed as
+   *  unnecessary Ops.
+   */
+  template <loco::DataType DType>
+  bool can_remove_transposes(const luci::CircleTranspose *f_tr, const luci::CircleReshape *m_rs,
+                             const luci::CircleTranspose *b_tr);
+
+private:
+  void init_shape_with_tag(const luci::CircleNode *);
+
+  template <loco::DataType PermType> void analyze_transpose(const luci::CircleTranspose *);
+
+  template <loco::DataType ShapeType> bool analyze_reshape(const luci::CircleReshape *);
+
+  bool verify_tag() const;
+
+  struct Dim final
+  {
+    int32_t value;
+    std::vector<uint8_t> tags;
+  };
+
+  const uint8_t START_TAG = 0;
+
+  using Shape = std::vector<Dim>;
+  Shape _shape;
+
+  int32_t flatsize(const Shape &shape) const;
+  bool inference_incomplete_shape(const Shape &src, Shape &dst);
+};
+
+int32_t TaggedShapeAnalyzer::flatsize(const Shape &shape) const
+{
+  int32_t size = 1;
+  for (const auto &dim : shape)
+  {
+    if (dim.value >= 1)
+      size *= dim.value;
+  }
+  return size;
+}
+
+/**
+ * @brief if 'dst' has -1 valued dim, replace -1 with inferenced value
+ *
+ * @return  ture, if successfully replace -1 value
+ *          false, otherwise
+ */
+bool TaggedShapeAnalyzer::inference_incomplete_shape(const Shape &src, Shape &dst)
+{
+  std::vector<size_t> incomplete_indexes;
+  for (size_t i = 0; i < dst.size(); i++)
+  {
+    if (dst[i].value == -1)
+      incomplete_indexes.push_back(i);
+  }
+
+  if (incomplete_indexes.size() == 0)
+    return true;
+  else if (incomplete_indexes.size() == 1)
+  {
+    if (flatsize(src) % flatsize(dst) == 0)
+      dst[incomplete_indexes[0]].value = flatsize(src) / flatsize(dst);
+    else
+      return false;
+  }
+  else // incomplete_indexes.size() >= 2
+    return false;
+
+  return true;
+}
+
+/**
+ * @brief initalize _shape with input tensor named in_tensor
+ *
+ * @note 'tags' are attached to non-1 valued dimension.
+ */
+void TaggedShapeAnalyzer::init_shape_with_tag(const luci::CircleNode *in_tensor)
+{
+  _shape.clear();
+  uint8_t tag = START_TAG;
+
+  for (uint32_t i = 0; i < in_tensor->rank(); i++)
+  {
+    TaggedShapeAnalyzer::Dim dim;
+    {
+      dim.value = in_tensor->dim(i).value();
+      if (dim.value != 1)
+        dim.tags.push_back(tag++);
+    }
+    _shape.push_back(dim);
+  }
+}
+
+/**
+ * @brief update _shape based on 'Transpose' permutation value
+ *
+ * @example Let's assume Transpose(perm=0, 3, 1, 2) is given to [before] _shape.
+ *
+ *  This function reordered the Dims' order based on permutaiton value.
+ *
+ *  [before]  _shape :
+ *              - value :   (1)   (7)   (7)   (448)
+ *              - tags  :   (-)   (0)   (1)   (2)
+ *
+ *  [after]  _shape :
+ *              - value :   (1)   (448)  (7)  (7)
+ *              - tags  :   (-)   (2)    (0)  (1)
+ */
+template <loco::DataType PermType>
+void TaggedShapeAnalyzer::analyze_transpose(const luci::CircleTranspose *transpose_node)
+{
+  const luci::CircleConst *perm_node = loco::must_cast<luci::CircleConst *>(transpose_node->perm());
+  assert(perm_node->dtype() == PermType);
+
+  TaggedShapeAnalyzer::Shape new_shape;
+  const auto size = perm_node->size<PermType>();
+  for (uint32_t i = 0; i < size; i++)
+  {
+    auto perm_idx = perm_node->at<PermType>(i);
+    new_shape.push_back(_shape.at(perm_idx));
+  }
+  _shape = new_shape;
+}
+
+/**
+ * @brief update _shape based on 'Reshape' shape value
+ *
+ * @return False, if it determined that removing transposes is impossible
+ *
+ * @example Let's assume Reshape(shape=1, 448, 49) is given to [before] _shape.
+ *
+ *  [before]  _shape :
+ *              - value :   (1)   (448)  (7)   (7)
+ *              - tags  :   (-)   (2)    (0)   (1)
+ *
+ *  [after]  _shape :
+ *              - value :   (1)   (448)  (49)
+ *              - tags  :   (-)   (2)    (0, 1)
+ */
+template <loco::DataType ReshapeType>
+bool TaggedShapeAnalyzer::analyze_reshape(const luci::CircleReshape *reshape_node)
+{
+  const luci::CircleConst *shape_node = loco::must_cast<luci::CircleConst *>(reshape_node->shape());
+  assert(shape_node->dtype() == ReshapeType);
+
+  // At least one element must be in reshape's output-tensor.
+  if (shape_node->size<ReshapeType>() <= 0)
+    return false;
+
+  // Create new_shape based on reshape_node/shape
+  Shape new_shape;
+  for (uint32_t i = 0; i < shape_node->size<ReshapeType>(); i++)
+  {
+    TaggedShapeAnalyzer::Dim dim;
+    dim.value = shape_node->at<ReshapeType>(i);
+
+    new_shape.push_back(dim);
+  }
+
+  // inference new_shape dim with -1 value
+  if (inference_incomplete_shape(_shape, new_shape) == false)
+    return false;
+
+  // indexing for _shape [old_shape_start_idx, old_shape_end_idx)
+  uint32_t old_shape_start_idx = 0;
+  uint32_t old_shape_end_idx = 1;
+  auto old_shape_product = _shape[old_shape_start_idx].value;
+
+  auto expand_range = [&]() -> bool {
+    if (old_shape_end_idx >= _shape.size())
+      return false;
+
+    old_shape_product *= _shape[old_shape_end_idx].value;
+    old_shape_end_idx++;
+    return true;
+  };
+
+  auto move_to_next_range = [&]() -> bool {
+    if (old_shape_end_idx >= _shape.size())
+      return false;
+
+    old_shape_start_idx = old_shape_end_idx;
+    old_shape_end_idx++;
+    old_shape_product = _shape[old_shape_start_idx].value;
+    return true;
+  };
+
+  // Add tags from '_shape' to the 'new_shape'
+  uint32_t new_shape_idx = 0;
+  while (new_shape_idx < new_shape.size())
+  {
+    Dim &target_dim = new_shape[new_shape_idx];
+
+    // Ignore dim == 1
+    if (target_dim.value == 1)
+    {
+      new_shape_idx++;
+      continue;
+    }
+
+    while (old_shape_product < target_dim.value)
+    {
+      if (expand_range() == false)
+        break;
+    }
+
+    if (old_shape_product != target_dim.value)
+      return false;
+
+    assert(old_shape_product == target_dim.value);
+    for (uint32_t idx = old_shape_start_idx; idx < old_shape_end_idx; idx++)
+    {
+      const auto &old_tags = _shape[idx].tags;
+      target_dim.tags.insert(target_dim.tags.end(), old_tags.begin(), old_tags.end());
+    }
+
+    new_shape_idx++;
+    move_to_next_range();
+  }
+  _shape = new_shape;
+  return true;
+}
+
+bool TaggedShapeAnalyzer::verify_tag() const
+{
+  // check whether tags in _shape are incremental
+  uint8_t tag = START_TAG;
+  for (const auto &dim : _shape)
+  {
+    for (const auto &t : dim.tags)
+    {
+      if (t == tag)
+        tag++;
+      else
+        return false;
+    }
+  }
+  return true;
+}
+
+// For implementation details, please refer the comment with declaration.
+template <loco::DataType DType>
+bool TaggedShapeAnalyzer::can_remove_transposes(const luci::CircleTranspose *f_tr,
+                                                const luci::CircleReshape *m_rs,
+                                                const luci::CircleTranspose *b_tr)
+{
+  assert(loco::must_cast<luci::CircleConst *>(f_tr->perm())->dtype() == DType);
+  assert(loco::must_cast<luci::CircleConst *>(m_rs->shape())->dtype() == DType);
+  assert(loco::must_cast<luci::CircleConst *>(b_tr->perm())->dtype() == DType);
+
+  const luci::CircleNode *in_tensor = loco::must_cast<luci::CircleNode *>(f_tr->a());
+
+  init_shape_with_tag(in_tensor);
+
+  analyze_transpose<DType>(f_tr);
+
+  if (not analyze_reshape<DType>(m_rs))
+    return false;
+
+  analyze_transpose<DType>(b_tr);
+
+  if (not verify_tag())
+    return false;
+
+  return true;
+}
+
+/**
+ * @brief create CircleReshape node that reshapes 'front_transpose input tensor shape' into
+ * 'back_transposes output tensor shape'
+ */
+template <loco::DataType ShapeType>
+luci::CircleReshape *create_reshape_node(loco::Graph *graph,
+                                         const luci::CircleTranspose *front_transpose,
+                                         const luci::CircleReshape *mid_reshape,
+                                         const luci::CircleTranspose *back_transpose)
+{
+  std::string composed_name =
+    front_transpose->name() + ";" + mid_reshape->name() + ";" + back_transpose->name();
+
+  std::vector<std::shared_ptr<luci::CircleNodeOrigin>> src_origin{luci::get_origin(front_transpose),
+                                                                  luci::get_origin(mid_reshape),
+                                                                  luci::get_origin(back_transpose)};
+  auto const composed_origin = luci::composite_origin(src_origin);
+
+  auto shape_node = graph->nodes()->create<luci::CircleConst>();
+  {
+    shape_node->dtype(ShapeType);
+    shape_node->rank(1);
+    shape_node->dim(0).set(back_transpose->rank());
+
+    shape_node->size<ShapeType>(back_transpose->rank());
+    for (uint32_t i = 0; i < back_transpose->rank(); i++)
+    {
+      shape_node->at<ShapeType>(i) = back_transpose->dim(i).value();
+    }
+    shape_node->shape_status(luci::ShapeStatus::VALID);
+    shape_node->name(composed_name + "/shape");
+    luci::add_origin(shape_node, composed_origin);
+  }
+
+  auto reshape_node = graph->nodes()->create<luci::CircleReshape>();
+  {
+    reshape_node->name(composed_name);
+    reshape_node->tensor(front_transpose->a());
+    reshape_node->shape(shape_node);
+    luci::add_origin(reshape_node, composed_origin);
+  }
+  return reshape_node;
+}
+
+bool remove_unnecessary_transpose(luci::CircleTranspose *node)
+{
+  // find 'front_transpose - mid_reshape - back_transpose' pattern
+  const auto back_transpose = node;
+  const auto mid_reshape = dynamic_cast<luci::CircleReshape *>(back_transpose->a());
+  {
+    if (mid_reshape == nullptr)
+      return false;
+  }
+  const auto front_transpose = dynamic_cast<luci::CircleTranspose *>(mid_reshape->tensor());
+  {
+    if (not front_transpose)
+      return false;
+  }
+
+  // check perm and shape are CircleConst node and its' datatype is S32
+  const auto back_perm = dynamic_cast<luci::CircleConst *>(back_transpose->perm());
+  {
+    if (back_perm == nullptr)
+      return false;
+
+    if (back_perm->dtype() != loco::DataType::S32)
+      return false;
+  }
+  const auto shape = dynamic_cast<luci::CircleConst *>(mid_reshape->shape());
+  {
+    if (shape == nullptr)
+      return false;
+
+    if (shape->dtype() != loco::DataType::S32)
+      return false;
+  }
+  const auto front_perm = dynamic_cast<luci::CircleConst *>(front_transpose->perm());
+  {
+    if (front_perm == nullptr)
+      return false;
+
+    if (front_perm->dtype() != loco::DataType::S32)
+      return false;
+  }
+
+  // for now, handle only rank reduction equal (not expansion) cases
+  const auto output_rank = back_transpose->rank();
+  const auto input_rank = front_transpose->rank();
+  if (input_rank < output_rank)
+    return false;
+
+  // analyze pattern to check this pass is applicable
+  TaggedShapeAnalyzer analyzer;
+  if (not analyzer.can_remove_transposes<loco::DataType::S32>(front_transpose, mid_reshape,
+                                                              back_transpose))
+    return false;
+
+  // repalce with new_node
+  luci::CircleReshape *new_node = create_reshape_node<loco::DataType::S32>(
+    node->graph(), front_transpose, mid_reshape, back_transpose);
+
+  replace(node).with(new_node);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+/**
+ * BEFORE
+ *
+ * Current pass only targets below cases:
+ *  - in.rank() >= out.rank()
+ *  - 'Reshape' used to reduce N dimension into one (e.g. A x B x C => A x BC)
+ *
+ *
+ *     [CircleNode]      [CircleConst]
+ *    (in)               (perm)
+ *         \              /
+ *       [CircleTranspose]    [CircleConst]
+ *            \               (shape)
+ *             \             /
+ *             [CircleReshape]      [CircleConst]
+ *               \                  (perm)
+ *                \                /
+ *                 [CircleTranspose]
+ *                  \
+ *                   \
+ *                    [CircleNode]
+ *                    (out)
+ *
+ * AFTER
+ *
+ *    [CircleNode]        [CircleConst]
+ *     (in)                (shape)
+ *        \               /
+ *        [CircleReshape]
+ *         (new)
+ *          \
+ *          [CircleNode]
+ *          (out)
+ *
+ */
+
+bool RemoveUnnecessaryTransposeNetPass::run(loco::Graph *g)
+{
+  bool changed = false;
+
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto transpose_node = dynamic_cast<luci::CircleTranspose *>(node))
+    {
+      if (remove_unnecessary_transpose(transpose_node))
+        changed = true;
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/RemoveUnnecessaryTransposeNetPass.test.cpp b/compiler/luci/pass/src/RemoveUnnecessaryTransposeNetPass.test.cpp
new file mode 100644 (file)
index 0000000..5d0a965
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/RemoveUnnecessaryTransposeNetPass.h"
+
+#include <luci/IR/CircleNode.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class TransposeReshapeTransposeGraph : public TestIOGraph
+{
+
+public:
+  // create input-transpose-reshape-transpose-output graph
+  void init_whole_graph(ShapeU32 in_shape, ShapeU32 front_perm, ShapeI32 mid_shape,
+                        ShapeU32 back_perm, ShapeU32 out_shape)
+  {
+    TestIOGraph::init(in_shape, out_shape);
+
+    _front_perm = g()->nodes()->create<luci::CircleConst>();
+    {
+      _front_perm->name("front_transpose/perm");
+      init_circle_const(_front_perm, front_perm);
+    }
+
+    _front_transpose = g()->nodes()->create<luci::CircleTranspose>();
+    {
+      _front_transpose->a(input());
+      _front_transpose->name("front_transpose");
+      _front_transpose->perm(_front_perm);
+    }
+
+    _mid_shape = g()->nodes()->create<luci::CircleConst>();
+    {
+      _mid_shape->name("mid_reshpae/shape");
+      init_circle_const(_mid_shape, mid_shape);
+    }
+
+    _mid_reshape = g()->nodes()->create<luci::CircleReshape>();
+    {
+      _mid_reshape->name("mid_reshape");
+      _mid_reshape->tensor(_front_transpose);
+      _mid_reshape->shape(_mid_shape);
+    }
+
+    _back_perm = g()->nodes()->create<luci::CircleConst>();
+    {
+      _back_perm->name("back_transpose/perm");
+      init_circle_const(_back_perm, back_perm);
+    }
+
+    _back_transpose = g()->nodes()->create<luci::CircleTranspose>();
+    {
+      _back_transpose->name("back_transpose");
+      _back_transpose->a(_mid_reshape);
+      _back_transpose->perm(_back_perm);
+    }
+
+    output()->from(_back_transpose);
+  }
+
+  // create input-transpose-transpose-output graph
+  void init_transpose_only(ShapeU32 in_shape, ShapeU32 front_perm, ShapeU32 back_perm,
+                           ShapeU32 out_shape)
+  {
+    TestIOGraph::init(in_shape, out_shape);
+
+    _front_perm = g()->nodes()->create<luci::CircleConst>();
+    {
+      _front_perm->name("front_transpose/perm");
+      init_circle_const(_front_perm, front_perm);
+    }
+
+    _front_transpose = g()->nodes()->create<luci::CircleTranspose>();
+    {
+      _front_transpose->a(input());
+      _front_transpose->name("front_transpose");
+      _front_transpose->perm(_front_perm);
+    }
+
+    _back_perm = g()->nodes()->create<luci::CircleConst>();
+    {
+      _back_perm->name("back_transpose/perm");
+      init_circle_const(_back_perm, back_perm);
+    }
+
+    _back_transpose = g()->nodes()->create<luci::CircleTranspose>();
+    {
+      _back_transpose->name("back_transpose");
+      _back_transpose->a(_front_transpose);
+      _back_transpose->perm(_back_perm);
+    }
+
+    output()->from(_back_transpose);
+  }
+
+private:
+  void init_circle_const(luci::CircleConst *const_node, ShapeU32 shape)
+  {
+    const_node->dtype(loco::DataType::S32);
+    const_node->size<loco::DataType::S32>(shape.size());
+    uint32_t i = 0;
+    for (auto v : shape)
+    {
+      const_node->at<loco::DataType::S32>(i++) = v;
+    }
+  }
+
+  void init_circle_const(luci::CircleConst *const_node, ShapeI32 shape)
+  {
+    const_node->dtype(loco::DataType::S32);
+    const_node->size<loco::DataType::S32>(shape.size());
+    uint32_t i = 0;
+    for (auto v : shape)
+    {
+      const_node->at<loco::DataType::S32>(i++) = v;
+    }
+  }
+
+  luci::CircleTranspose *_front_transpose = nullptr;
+  luci::CircleConst *_front_perm = nullptr;
+
+  luci::CircleReshape *_mid_reshape = nullptr;
+  luci::CircleConst *_mid_shape = nullptr;
+
+  luci::CircleTranspose *_back_transpose = nullptr;
+  luci::CircleConst *_back_perm = nullptr;
+};
+
+bool is_transpose_removed(loco::Graph *g)
+{
+  bool transpose_exist = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (dynamic_cast<luci::CircleTranspose *>(node))
+    {
+      transpose_exist = true;
+      break;
+    }
+  }
+  return not transpose_exist;
+}
+
+} // namespace
+
+TEST(RemoveUnnecessaryTransposeNetPass, rank_reduction_pattern1)
+{
+  TransposeReshapeTransposeGraph g;
+  luci::RemoveUnnecessaryTransposeNetPass pass;
+
+  /**
+   * (1, 14, 14, 192)
+   *      |
+   * (1, 192, 14, 14)
+   *      |
+   * (1, 192, 196)
+   *      |
+   * (1, 196, 192)
+   */
+  g.init_whole_graph(/*in*/ {1, 14, 14, 192}, /*perm*/ {0, 3, 1, 2}, /*reshape*/ {1, 192, 196},
+                     /*perm*/ {0, 2, 1}, /*out*/ {1, 196, 192});
+
+  EXPECT_TRUE(pass.run(g.g()));
+  EXPECT_TRUE(is_transpose_removed(g.g()));
+}
+
+TEST(RemoveUnnecessaryTransposeNetPass, rank_reduction_pattern2)
+{
+  TransposeReshapeTransposeGraph g;
+  luci::RemoveUnnecessaryTransposeNetPass pass;
+
+  /**
+   * (1, 100, 10, 12)
+   *        |
+   * (1, 10, 12, 100)
+   *        |
+   *    (120, 100)
+   *        |
+   *    (100, 120)
+   */
+  g.init_whole_graph(/*in*/ {1, 100, 10, 12}, /*perm*/ {0, 2, 3, 1}, /*reshape*/ {120, 100},
+                     /*perm*/ {1, 0},
+                     /*out*/ {100, 120});
+
+  EXPECT_TRUE(pass.run(g.g()));
+  EXPECT_TRUE(is_transpose_removed(g.g()));
+}
+
+TEST(RemoveUnnecessaryTransposeNetPass, identity_pattern)
+{
+  TransposeReshapeTransposeGraph g;
+  luci::RemoveUnnecessaryTransposeNetPass pass;
+
+  /**
+   * (1, 2, 3)
+   *     |
+   * (1, 2, 3)
+   *      |
+   * (1, 2, 3)
+   *      |
+   * (1, 2, 3)
+   */
+  g.init_whole_graph(/*in*/ {1, 2, 3}, /*perm*/ {0, 1, 2}, /*reshape*/ {1, 2, 3},
+                     /*perm*/ {0, 1, 2},
+                     /*out*/ {1, 2, 3});
+
+  EXPECT_TRUE(pass.run(g.g()));
+  EXPECT_TRUE(is_transpose_removed(g.g()));
+}
+
+TEST(RemoveUnnecessaryTransposeNetPass, incomplete_reshape_pattern)
+{
+  TransposeReshapeTransposeGraph g;
+  luci::RemoveUnnecessaryTransposeNetPass pass;
+
+  /**
+   * (1, 7, 7, 448)
+   *     |
+   * (1, 448, 7, 7)
+   *      |
+   * (1, 448, -1)
+   *      |
+   * (1, 49, 448)
+   */
+  g.init_whole_graph(/*in*/ {1, 7, 7, 448}, /*perm*/ {0, 3, 1, 2}, /*reshape*/ {1, 448, -1},
+                     /*perm*/ {0, 2, 1}, /*out*/ {1, 49, 448});
+
+  EXPECT_TRUE(pass.run(g.g()));
+  EXPECT_TRUE(is_transpose_removed(g.g()));
+}
+
+TEST(RemoveUnnecessaryTransposeNetPass, basic_pattern1_NEG)
+{
+  TransposeReshapeTransposeGraph g;
+  luci::RemoveUnnecessaryTransposeNetPass pass;
+
+  /**
+   * (1, 2, 4, 6)
+   *      |
+   * (1, 2, 6, 4)
+   *      |
+   * (1, 12, 4)
+   *      |
+   * (1, 4, 12)
+   */
+  g.init_whole_graph(/*in*/ {1, 2, 4, 6}, /*perm*/ {0, 1, 3, 2}, /*reshape*/ {1, 12, 4},
+                     /*perm*/ {0, 2, 1},
+                     /*out*/ {1, 4, 12});
+
+  EXPECT_FALSE(pass.run(g.g()));
+  EXPECT_FALSE(is_transpose_removed(g.g()));
+}
+
+TEST(RemoveUnnecessaryTransposeNetPass, basic_pattern2_NEG)
+{
+  TransposeReshapeTransposeGraph g;
+  luci::RemoveUnnecessaryTransposeNetPass pass;
+
+  /**
+   * (15, 10, 10)
+   *      |
+   * (10, 10, 15)
+   *      |
+   * (1, 1, 1500)
+   *      |
+   * (1500, 1, 1)
+   */
+  g.init_whole_graph(/*in*/ {15, 10, 10}, /*perm*/ {1, 2, 0}, /*reshape*/ {1, 1, 1500},
+                     /*perm*/ {2, 0, 1},
+                     /*out*/ {1500, 1, 1});
+
+  EXPECT_FALSE(pass.run(g.g()));
+  EXPECT_FALSE(is_transpose_removed(g.g()));
+}
+
+TEST(RemoveUnnecessaryTransposeNetPass, basic_pattern3_NEG)
+{
+  TransposeReshapeTransposeGraph g;
+  luci::RemoveUnnecessaryTransposeNetPass pass;
+
+  /**
+   *  (1, 2, 3, 4)
+   *       |
+   * perm (0, 3, 1, 2)
+   *      |
+   *   (1, 4, 2, 3)
+   *      |
+   *  perm (0, 2, 3, 1)
+   *      |
+   *   (1, 2, 3, 4)
+   */
+  g.init_transpose_only(/*in*/ {1, 2, 3, 4}, /*perm*/ {0, 3, 1, 2}, /*perm*/ {0, 2, 3, 1},
+                        /*out*/ {1, 2, 3, 4});
+
+  EXPECT_FALSE(pass.run(g.g()));
+  EXPECT_FALSE(is_transpose_removed(g.g()));
+}
+
+TEST(RemoveUnnecessaryTransposeNetPass, incomplete_reshape_pattern1_NEG)
+{
+  TransposeReshapeTransposeGraph g;
+  luci::RemoveUnnecessaryTransposeNetPass pass;
+
+  /**
+   * (1, 10, 10, 14)
+   *     |
+   * (1, 14, 10, 10)
+   *      |
+   * (1, 14, 2, -1)  #(1, 14, 2, 50)
+   *      |
+   * (1, 14, 50, 2)
+   */
+  g.init_whole_graph(/*in*/ {1, 10, 10, 14}, /*perm*/ {0, 3, 1, 2}, /*reshape*/ {1, 14, 2, -1},
+                     /*perm*/ {0, 1, 3, 2}, /*out*/ {1, 14, 50, 2});
+
+  EXPECT_FALSE(pass.run(g.g()));
+  EXPECT_FALSE(is_transpose_removed(g.g()));
+}
+
+TEST(RemoveUnnecessaryTransposeNetPass, incomplete_reshape_pattern2_NEG)
+{
+  TransposeReshapeTransposeGraph g;
+  luci::RemoveUnnecessaryTransposeNetPass pass;
+
+  /**
+   * (1, 10, 10, 14)
+   *     |
+   * (1, 14, 10, 10)
+   *      |
+   * (1, 14, -1, -1)  # unexpected shape
+   *      |
+   * (1, 14, 50, 2)
+   */
+  g.init_whole_graph(/*in*/ {1, 10, 10, 14}, /*perm*/ {0, 3, 1, 2}, /*reshape*/ {1, 14, -1, -1},
+                     /*perm*/ {0, 1, 3, 2}, /*out*/ {1, 14, 50, 2});
+
+  EXPECT_FALSE(pass.run(g.g()));
+  EXPECT_FALSE(is_transpose_removed(g.g()));
+}
index 07457c1..a1ff82f 100644 (file)
@@ -138,6 +138,11 @@ bool replace_fc_with_matmul(luci::CircleFullyConnected *fc)
   if (dynamic_cast<luci::CircleConst *>(fc->weights()))
     return false; // NonConst
 
+  // NOTE For const inputs, it is possible to block this conversion,
+  // because we can make transposed FC rather than matmul to improve
+  // accuracy of quantized models by sacrificing latency.
+  // See https://github.com/Samsung/ONE/discussions/11941 for more details.
+
   if ((ty = dynamic_cast<luci::CircleTranspose *>(fc->weights()))) // is y a transpose?
   {
     adj_y = false;
diff --git a/compiler/luci/pass/src/ReplaceWithFCGeluFCPass.cpp b/compiler/luci/pass/src/ReplaceWithFCGeluFCPass.cpp
new file mode 100644 (file)
index 0000000..a9288a3
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/ReplaceWithFCGeluFCPass.h"
+#include "helpers/NodeFiller.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+#include <luci/Service/CircleNodeClone.h>
+#include <luci/Service/Nodes/CircleConst.h>
+
+#include <cmath>
+#include <cassert>
+
+namespace
+{
+
+// Float comparison
+bool same(float a, float b) { return fabs(a - b) < 1e-5; }
+
+luci::CircleConst *multiply_const(luci::CircleConst *node, float multiplier)
+{
+  auto cloned = luci::clone(node);
+
+  assert(node->dtype() == loco::DataType::FLOAT32);   // FIX_CALLER_UNLESS
+  assert(cloned->dtype() == loco::DataType::FLOAT32); // FIX_CALLER_UNLESS
+
+  for (uint32_t i = 0; i < cloned->size<loco::DataType::FLOAT32>(); i++)
+  {
+    cloned->at<loco::DataType::FLOAT32>(i) *= multiplier;
+  }
+
+  luci::add_origin(cloned, luci::get_origin(node));
+
+  return cloned;
+}
+
+/**
+ * Below diagram shows the target pattern.
+ * - The pattern will be converted to FC (front) -> Gelu -> FC (back).
+ * - FC (front) has the same weights with fc1
+ * - FC (back)'s weights is twice of fc3's weights
+ *
+ *     +---- [In]
+ *     |      |
+ *     |      V
+ *     |     fc2 (w = w of fc1 * sqrt(0.5). bias as well) -> const folded
+ *     |      |
+ *    fc1     V
+ *     |     erf
+ *     |      |
+ *     |      V
+ *     |   add_one (1.0)
+ *     |      |
+ *     |      V
+ *     +---> mul
+ *            |
+ *            V
+ *           fc3
+ *            |
+ *            V
+ *          [Out]
+ *
+ */
+class FCGeluFCPattern final
+{
+public:
+  FCGeluFCPattern(luci::CircleFullyConnected *cand)
+  {
+    assert(cand);
+    _fc3 = cand;
+  }
+
+public:
+  bool matched();
+
+public:
+  luci::CircleNode *_ifm = nullptr;
+  luci::CircleFullyConnected *_fc1 = nullptr;
+  luci::CircleFullyConnected *_fc2 = nullptr;
+  luci::CircleFullyConnected *_fc3 = nullptr;
+  luci::CircleCustom *_erf = nullptr;
+  luci::CircleCustomOut *_erf_out = nullptr;
+  luci::CircleAdd *_add_one = nullptr;
+  luci::CircleMul *_mul = nullptr;
+  luci::CircleConst *_const_one = nullptr;
+  luci::CircleConst *_fc1_w = nullptr;
+  luci::CircleConst *_fc2_w = nullptr;
+  luci::CircleConst *_fc3_w = nullptr;
+  luci::CircleConst *_fc1_b = nullptr;
+  luci::CircleConst *_fc2_b = nullptr;
+  luci::CircleConst *_fc3_b = nullptr;
+};
+
+#define CHECK_OR_FALSE(condition) \
+  if (not(condition))             \
+    return false;
+
+bool FCGeluFCPattern::matched()
+{
+  // check pattern
+  _fc3_w = dynamic_cast<luci::CircleConst *>(_fc3->weights());
+  CHECK_OR_FALSE(_fc3_w != nullptr);
+
+  _mul = dynamic_cast<luci::CircleMul *>(_fc3->input());
+  CHECK_OR_FALSE(_mul != nullptr);
+
+  CHECK_OR_FALSE(luci::fill(&_fc1, &_add_one).with_commutative_args_of(_mul));
+
+  _fc1_w = dynamic_cast<luci::CircleConst *>(_fc1->weights());
+  CHECK_OR_FALSE(_fc1_w != nullptr);
+
+  CHECK_OR_FALSE(_fc1->weights_format() == luci::CircleFullyConnected::WeightsFormat::DEFAULT);
+
+  _ifm = loco::must_cast<luci::CircleNode *>(_fc1->input());
+
+  CHECK_OR_FALSE(luci::fill(&_erf_out, &_const_one).with_commutative_args_of(_add_one));
+
+  _erf = dynamic_cast<luci::CircleCustom *>(_erf_out->input());
+  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);
+
+  _fc2 = dynamic_cast<luci::CircleFullyConnected *>(_erf->inputs(0));
+  CHECK_OR_FALSE(_fc2 != nullptr);
+  _fc2_w = dynamic_cast<luci::CircleConst *>(_fc2->weights());
+  CHECK_OR_FALSE(_fc2_w != nullptr);
+
+  CHECK_OR_FALSE(_fc2->weights_format() == luci::CircleFullyConnected::WeightsFormat::DEFAULT);
+  CHECK_OR_FALSE(_ifm == _fc2->input());
+
+  // Check Activation to be NONE
+  CHECK_OR_FALSE(_mul->fusedActivationFunction() == luci::FusedActFunc::NONE);
+  CHECK_OR_FALSE(_add_one->fusedActivationFunction() == luci::FusedActFunc::NONE);
+  CHECK_OR_FALSE(_fc1->fusedActivationFunction() == luci::FusedActFunc::NONE);
+  CHECK_OR_FALSE(_fc2->fusedActivationFunction() == luci::FusedActFunc::NONE);
+  // fc3 can have activation
+
+  // Check dtype
+  CHECK_OR_FALSE(_fc1->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(_fc2->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(_fc3->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(_erf->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(_erf_out->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(_add_one->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(_mul->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(_fc1_w->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(_fc2_w->dtype() == loco::DataType::FLOAT32);
+  CHECK_OR_FALSE(_fc3_w->dtype() == loco::DataType::FLOAT32);
+
+  // 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);
+
+  // Check fc2_w = fc1_w * sqrt(0.5)
+  CHECK_OR_FALSE(_fc1_w->size<loco::DataType::FLOAT32>() ==
+                 _fc2_w->size<loco::DataType::FLOAT32>());
+  for (uint32_t i = 0; i < _fc1_w->size<loco::DataType::FLOAT32>(); i++)
+  {
+    const auto fc1_val = _fc1_w->at<loco::DataType::FLOAT32>(i);
+    const auto fc2_val = _fc2_w->at<loco::DataType::FLOAT32>(i);
+    CHECK_OR_FALSE(::same(fc1_val * sqrtf(0.5f), fc2_val));
+  }
+
+  // Start to check bias
+  _fc1_b = dynamic_cast<luci::CircleConst *>(_fc1->bias());
+  _fc2_b = dynamic_cast<luci::CircleConst *>(_fc2->bias());
+  _fc3_b = dynamic_cast<luci::CircleConst *>(_fc3->bias());
+
+  // Check there is no non-constant bias
+  if (_fc1_b == nullptr)
+    CHECK_OR_FALSE(dynamic_cast<luci::CircleOutputExclude *>(_fc1->bias()) != nullptr);
+
+  if (_fc2_b == nullptr)
+    CHECK_OR_FALSE(dynamic_cast<luci::CircleOutputExclude *>(_fc2->bias()) != nullptr);
+
+  if (_fc3_b == nullptr)
+    CHECK_OR_FALSE(dynamic_cast<luci::CircleOutputExclude *>(_fc3->bias()) != nullptr);
+
+  // Check both fc1 and fc2 have biases, or both have no bias
+  CHECK_OR_FALSE((_fc1_b == nullptr and _fc2_b == nullptr) or
+                 (_fc1_b != nullptr and _fc2_b != nullptr));
+
+  // Check values of fc1 and fc2 bias (if bias exists)
+  if (_fc1_b != nullptr and _fc2_b != nullptr)
+  {
+    CHECK_OR_FALSE(_fc1_b->size<loco::DataType::FLOAT32>() ==
+                   _fc2_b->size<loco::DataType::FLOAT32>());
+    for (uint32_t i = 0; i < _fc1_b->size<loco::DataType::FLOAT32>(); i++)
+    {
+      const auto fc1_val = _fc1_b->at<loco::DataType::FLOAT32>(i);
+      const auto fc2_val = _fc2_b->at<loco::DataType::FLOAT32>(i);
+
+      // fc2_b = fc1_b * sqrt(0.5)
+      CHECK_OR_FALSE(::same(fc1_val * sqrtf(0.5f), fc2_val));
+    }
+  }
+
+  return true;
+}
+
+#undef CHECK_OR_FALSE
+
+class ReplaceWithFCGeluFC final
+{
+public:
+  ReplaceWithFCGeluFC(const FCGeluFCPattern *p) : _p(p) {}
+
+public:
+  void apply(void);
+
+private:
+  // Create FC -> Gelu -> FC pattern and set front/back
+  void create_fc_gelu_fc(luci::CircleFullyConnected *&front, luci::CircleFullyConnected *&back);
+
+private:
+  const FCGeluFCPattern *_p;
+};
+
+void ReplaceWithFCGeluFC::create_fc_gelu_fc(luci::CircleFullyConnected *&front,
+                                            luci::CircleFullyConnected *&back)
+{
+  auto graph = _p->_fc1->graph();
+  assert(graph);
+
+  front = loco::must_cast<luci::CircleFullyConnected *>(luci::clone_node(_p->_fc1, graph));
+  front->weights(_p->_fc1->weights());
+  front->bias(_p->_fc1->bias());
+  luci::add_origin(front, luci::get_origin(_p->_fc1));
+
+  auto gelu = graph->nodes()->create<luci::CircleGelu>();
+  gelu->features(front);
+  // TODO Support approximate = True pattern
+  gelu->approximate(false);
+  gelu->name(_p->_erf->name() + "_gelu");
+  std::vector<std::shared_ptr<luci::CircleNodeOrigin>> origin_vec{
+    luci::get_origin(_p->_fc2), luci::get_origin(_p->_erf), luci::get_origin(_p->_add_one),
+    luci::get_origin(_p->_mul)};
+  luci::add_origin(gelu, luci::composite_origin(origin_vec));
+
+  back = loco::must_cast<luci::CircleFullyConnected *>(luci::clone_node(_p->_fc3, graph));
+  back->input(gelu);
+  back->weights(multiply_const(_p->_fc3_w, 2.0f /* multiplier */));
+  back->bias(_p->_fc3->bias());
+  luci::add_origin(back, luci::get_origin(_p->_fc3));
+}
+
+void ReplaceWithFCGeluFC::apply()
+{
+  luci::CircleFullyConnected *front = nullptr;
+  luci::CircleFullyConnected *back = nullptr;
+  create_fc_gelu_fc(front, back);
+
+  assert(front); // FIX_ME_UNLESS
+  assert(back);  // FIX_ME_UNLESS
+
+  front->input(_p->_ifm);
+
+  replace(_p->_fc3).with(back);
+}
+
+bool replace_fc_gelu_fc(luci::CircleFullyConnected *fc)
+{
+  assert(fc);
+
+  FCGeluFCPattern pattern(fc);
+  if (pattern.matched())
+  {
+    ReplaceWithFCGeluFC replace(&pattern);
+    replace.apply();
+    return true;
+  }
+
+  return false;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool ReplaceWithFCGeluFCPass::run(loco::Graph *g)
+{
+  bool changed = false;
+
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto fc = dynamic_cast<luci::CircleFullyConnected *>(node);
+    if (not fc)
+      continue;
+
+    if (replace_fc_gelu_fc(fc))
+      changed = true;
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/ReplaceWithFCGeluFCPass.test.cpp b/compiler/luci/pass/src/ReplaceWithFCGeluFCPass.test.cpp
new file mode 100644 (file)
index 0000000..4b82bfd
--- /dev/null
@@ -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 "luci/Pass/ReplaceWithFCGeluFCPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+
+#include <cmath>
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class FCGeluFCGraphlet
+{
+public:
+  FCGeluFCGraphlet() = default;
+
+  virtual ~FCGeluFCGraphlet() = default;
+
+  void init(loco::Graph *g)
+  {
+    _fc1 = g->nodes()->create<luci::CircleFullyConnected>();
+    _fc2 = g->nodes()->create<luci::CircleFullyConnected>();
+    _fc3 = g->nodes()->create<luci::CircleFullyConnected>();
+    _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>();
+    _const_one = g->nodes()->create<luci::CircleConst>();
+    _fc1_w = g->nodes()->create<luci::CircleConst>();
+    _fc2_w = g->nodes()->create<luci::CircleConst>();
+    _fc3_w = g->nodes()->create<luci::CircleConst>();
+    auto no_bias = g->nodes()->create<luci::CircleOutputExclude>();
+
+    _mul->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _add_one->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _fc1->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _fc2->fusedActivationFunction(luci::FusedActFunc::NONE);
+    _fc3->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+    _fc1->name("fc1");
+    _fc2->name("fc2");
+    _fc3->name("fc3");
+    _erf->name("erf");
+    _erf_out->name("erf_out");
+    _add_one->name("add_one");
+    _mul->name("mul");
+    _const_one->name("const_one");
+    _fc1_w->name("fc1_w");
+    _fc2_w->name("fc2_w");
+    _fc3_w->name("fc3_w");
+
+    _erf->custom_code("Erf");
+
+    _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);
+
+    _fc1_w->dtype(loco::DataType::FLOAT32);
+    _fc1_w->size<loco::DataType::FLOAT32>(16);
+    _fc1_w->shape({4, 4});
+    for (uint32_t i = 0; i < 16; i++)
+      _fc1_w->at<loco::DataType::FLOAT32>(i) = 1.0;
+    _fc1_w->shape_status(luci::ShapeStatus::VALID);
+
+    _fc2_w->dtype(loco::DataType::FLOAT32);
+    _fc2_w->size<loco::DataType::FLOAT32>(16);
+    _fc2_w->shape({4, 4});
+    for (uint32_t i = 0; i < 16; i++)
+      _fc2_w->at<loco::DataType::FLOAT32>(i) = sqrtf(0.5);
+    _fc2_w->shape_status(luci::ShapeStatus::VALID);
+
+    _fc3_w->dtype(loco::DataType::FLOAT32);
+    _fc3_w->size<loco::DataType::FLOAT32>(16);
+    _fc3_w->shape({4, 4});
+    for (uint32_t i = 0; i < 16; i++)
+      _fc3_w->at<loco::DataType::FLOAT32>(i) = 1.0;
+    _fc3_w->shape_status(luci::ShapeStatus::VALID);
+
+    _fc1->dtype(loco::DataType::FLOAT32);
+    _fc2->dtype(loco::DataType::FLOAT32);
+    _fc3->dtype(loco::DataType::FLOAT32);
+    _erf->dtype(loco::DataType::FLOAT32);
+    _erf_out->dtype(loco::DataType::FLOAT32);
+    _add_one->dtype(loco::DataType::FLOAT32);
+    _mul->dtype(loco::DataType::FLOAT32);
+
+    // Connect nodes
+    _fc1->weights(_fc1_w);
+    _fc1->bias(no_bias);
+    _fc2->weights(_fc2_w);
+    _fc2->bias(no_bias);
+    _erf->inputs(0, _fc2);
+    _erf_out->input(_erf);
+    _add_one->x(_erf_out);
+    _add_one->y(_const_one);
+    _mul->x(_fc1);
+    _mul->y(_add_one);
+    _fc3->input(_mul);
+    _fc3->weights(_fc3_w);
+    _fc3->bias(no_bias);
+  }
+
+protected:
+  luci::CircleFullyConnected *_fc1 = nullptr;
+  luci::CircleFullyConnected *_fc2 = nullptr;
+  luci::CircleFullyConnected *_fc3 = nullptr;
+  luci::CircleCustom *_erf = nullptr;
+  luci::CircleCustomOut *_erf_out = nullptr;
+  luci::CircleAdd *_add_one = nullptr;
+  luci::CircleMul *_mul = nullptr;
+  luci::CircleConst *_const_one = nullptr;
+  luci::CircleConst *_fc1_w = nullptr;
+  luci::CircleConst *_fc2_w = nullptr;
+  luci::CircleConst *_fc3_w = nullptr;
+};
+
+class FCGeluFCGraphletWithBias : public FCGeluFCGraphlet
+{
+public:
+  FCGeluFCGraphletWithBias() = default;
+
+  virtual ~FCGeluFCGraphletWithBias() = default;
+
+  void init(loco::Graph *g)
+  {
+    // Create graphlet without bias
+    FCGeluFCGraphlet::init(g);
+
+    // Set bias
+    _fc1_b = g->nodes()->create<luci::CircleConst>();
+    _fc2_b = g->nodes()->create<luci::CircleConst>();
+    _fc3_b = g->nodes()->create<luci::CircleConst>();
+
+    _fc1_b->name("fc1_b");
+    _fc2_b->name("fc2_b");
+    _fc3_b->name("fc3_b");
+
+    _fc1_b->dtype(loco::DataType::FLOAT32);
+    _fc1_b->size<loco::DataType::FLOAT32>(4);
+    _fc1_b->shape({4});
+    for (uint32_t i = 0; i < 4; i++)
+      _fc1_b->at<loco::DataType::FLOAT32>(i) = 1.0;
+    _fc1_b->shape_status(luci::ShapeStatus::VALID);
+
+    _fc2_b->dtype(loco::DataType::FLOAT32);
+    _fc2_b->size<loco::DataType::FLOAT32>(4);
+    _fc2_b->shape({4});
+    for (uint32_t i = 0; i < 4; i++)
+      _fc2_b->at<loco::DataType::FLOAT32>(i) = sqrtf(0.5);
+    _fc2_b->shape_status(luci::ShapeStatus::VALID);
+
+    _fc3_b->dtype(loco::DataType::FLOAT32);
+    _fc3_b->size<loco::DataType::FLOAT32>(4);
+    _fc3_b->shape({4});
+    for (uint32_t i = 0; i < 4; i++)
+      _fc3_b->at<loco::DataType::FLOAT32>(i) = 1.0;
+    _fc3_b->shape_status(luci::ShapeStatus::VALID);
+
+    // Connect nodes
+    _fc1->bias(_fc1_b);
+    _fc2->bias(_fc2_b);
+    _fc3->bias(_fc3_b);
+  }
+
+protected:
+  luci::CircleConst *_fc1_b = nullptr;
+  luci::CircleConst *_fc2_b = nullptr;
+  luci::CircleConst *_fc3_b = nullptr;
+};
+
+class ReplaceWithFCGeluFCTestGraph : public TestIOGraph, public FCGeluFCGraphlet
+{
+public:
+  ReplaceWithFCGeluFCTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({1, 4, 4}, {1, 4, 4});
+    FCGeluFCGraphlet::init(g());
+
+    _fc1->input(input());
+    _fc2->input(input());
+
+    output()->from(_fc3);
+  }
+};
+
+class ReplaceWithFCGeluFCTestNegGraph : public TestIOGraph, public FCGeluFCGraphlet
+{
+public:
+  ReplaceWithFCGeluFCTestNegGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({1, 4, 4}, {1, 4, 4});
+    FCGeluFCGraphlet::init(g());
+    _fc1->input(input());
+    _fc2->input(_fc1);
+
+    output()->from(_fc3);
+  }
+};
+
+class ReplaceWithFCGeluFCWithBiasTestGraph : public TestIOGraph, public FCGeluFCGraphletWithBias
+{
+public:
+  ReplaceWithFCGeluFCWithBiasTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({1, 4, 4}, {1, 4, 4});
+    FCGeluFCGraphletWithBias::init(g());
+
+    _fc1->input(input());
+    _fc2->input(input());
+
+    output()->from(_fc3);
+  }
+};
+
+class ReplaceWithFCGeluFCWithBiasNegTestGraph : public TestIOGraph, public FCGeluFCGraphletWithBias
+{
+public:
+  ReplaceWithFCGeluFCWithBiasNegTestGraph() = default;
+
+  void init(void)
+  {
+    TestIOGraph::init({1, 4, 4}, {1, 4, 4});
+    FCGeluFCGraphletWithBias::init(g());
+
+    _fc1->input(input());
+    _fc2->input(_fc1);
+
+    output()->from(_fc3);
+  }
+};
+
+} // namespace
+
+TEST(ReplaceWithFCGeluFCPassTest, basic)
+{
+  ReplaceWithFCGeluFCTestGraph g;
+  luci::ReplaceWithFCGeluFCPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(ReplaceWithFCGeluFCPassTest, wrong_pattern_NEG)
+{
+  ReplaceWithFCGeluFCTestNegGraph g;
+  luci::ReplaceWithFCGeluFCPass pass;
+
+  g.init();
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
+
+TEST(ReplaceWithFCGeluFCPassTest, with_bias)
+{
+  ReplaceWithFCGeluFCWithBiasTestGraph g;
+  luci::ReplaceWithFCGeluFCPass pass;
+
+  g.init();
+
+  EXPECT_TRUE(pass.run(g.g()));
+}
+
+TEST(ReplaceWithFCGeluFCPassTest, with_bias_wrong_pattern_NEG)
+{
+  ReplaceWithFCGeluFCWithBiasNegTestGraph g;
+  luci::ReplaceWithFCGeluFCPass pass;
+
+  g.init();
+
+  EXPECT_FALSE(pass.run(g.g()));
+}
index 77c5532..75e7e6a 100644 (file)
@@ -145,6 +145,26 @@ bool RequantizePass::run(loco::Graph *g)
     return false;
   }
 
+  // Fix wrong quantized_dimension
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+
+    auto qparam = circle_node->quantparam();
+    if (not qparam)
+      continue;
+
+    if (circle_node->rank() != 1)
+      continue;
+
+    if (qparam->quantized_dimension == 0)
+      continue;
+
+    // For rank 1 node, quantized_dimension should be 0
+    qparam->quantized_dimension = 0;
+    WARN(l) << "Wrong quantized_dimension is fixed (" << circle_node->name() << ")" << std::endl;
+  }
+
   // Update output dtype
   auto graph_outputs = g->outputs();
   for (auto node : loco::output_nodes(g))
index 9f7e2f1..730543c 100644 (file)
 namespace
 {
 
+/// @brief Returns the number of BroadcastTo among node's inputs
+int32_t num_of_broadcast_to(const luci::CircleNode *node)
+{
+  int32_t bt_cnt = 0;
+  for (uint32_t idx = 0; idx < node->arity(); idx++)
+  {
+    auto input = loco::must_cast<const luci::CircleNode *>(node->arg(idx));
+    switch (input->opcode())
+    {
+      case luci::CircleOpcode::CIRCLECUSTOMOUT:
+      {
+        auto inputOut = loco::must_cast<const luci::CircleCustomOut *>(input);
+        auto custom = loco::must_cast<luci::CircleCustom *>(inputOut->input());
+        if (custom->custom_code() == "BroadcastTo")
+          ++bt_cnt;
+        break;
+      }
+      case luci::CircleOpcode::BROADCAST_TO:
+      {
+        ++bt_cnt;
+        break;
+      }
+      default:
+        break;
+    }
+  }
+  return bt_cnt;
+}
+
 /// @brief Returns the index of BroadcastTo node among cop's inputs.
 // NOTE This function assumes there is only one BroadcastTo node among its inputs.
 int32_t get_broadcastTo_index_among_inputs_of(luci::CircleCustom *cop)
 {
+  if (num_of_broadcast_to(cop) != 1)
+    return -1;
+
   for (uint32_t idx = 0; idx < cop->numInputs(); idx++)
   {
     auto input = dynamic_cast<const luci::CircleCustomOut *>(cop->inputs(idx));
@@ -38,12 +70,38 @@ int32_t get_broadcastTo_index_among_inputs_of(luci::CircleCustom *cop)
       if (broadcastTo->custom_code() == "BroadcastTo")
         return idx;
     }
+    else
+    {
+      auto broadcastTo = dynamic_cast<luci::CircleBroadcastTo *>(cop->inputs(idx));
+      if (broadcastTo)
+        return idx;
+    }
   }
 
   return -1;
 }
 
-/** BEFORE
+// NOTE Broadcasting of input `Const` is skipped cause `Add` will do the broadcasting.
+// TODO Implement broadcasting to the `Const` input.
+/**
+ * [Pattern1]
+ *  BEFORE
+ *                                  [CircleConst]
+ *                                        |
+ *        [CircleNode]         [BroadcastTo(Builtin)]
+ *              \                       /
+ *               \                     /
+ *                \                   /
+ *               [AddV2(CircleCustom)]
+ *  AFTER
+ *
+ *         [CircleConst]         [CircleNode]
+ *                   \           /
+ *                    \         /
+ *                    [CircleAdd]
+ *
+ * [Pattern2]
+ *  BEFORE
  *                                  [CircleConst]
  *                                        |
  *        [CircleNode]         [BroadcastTo(CircleCustom)]
@@ -65,19 +123,41 @@ bool resolve_with_BroadcastTo(luci::CircleCustom *addv2)
   if (broadcastTo_idx == -1)
     return false;
 
-  auto input = loco::must_cast<const luci::CircleCustomOut *>(addv2->inputs(broadcastTo_idx));
-  auto broadcastTo = loco::must_cast<luci::CircleCustom *>(input->input());
-
   auto name = addv2->name();
   assert(name.length() > 0);
 
+  auto input = loco::must_cast<const luci::CircleNode *>(addv2->inputs(broadcastTo_idx));
+  luci::CircleNode *bc = nullptr;
+  loco::Node *bc_input = nullptr;
+
+  switch (input->opcode())
+  {
+    case luci::CircleOpcode::BROADCAST_TO:
+    {
+      auto broadcastTo = loco::must_cast<luci::CircleBroadcastTo *>(addv2->inputs(broadcastTo_idx));
+      bc = broadcastTo;
+      bc_input = broadcastTo->input();
+      break;
+    }
+    case luci::CircleOpcode::CIRCLECUSTOMOUT:
+    {
+      auto inputOut =
+        loco::must_cast<const luci::CircleCustomOut *>(addv2->inputs(broadcastTo_idx));
+      auto braodcastTo = loco::must_cast<luci::CircleCustom *>(inputOut->input());
+      bc = braodcastTo;
+      bc_input = braodcastTo->inputs(0);
+      break;
+    }
+    default:
+      return false;
+  }
+
   auto add = addv2->graph()->nodes()->create<luci::CircleAdd>();
   add->fusedActivationFunction(luci::FusedActFunc::NONE);
   add->x(addv2->inputs(1 - broadcastTo_idx));
-  add->y(broadcastTo->inputs(0));
+  add->y(bc_input);
   add->name(name + "/Add");
-  luci::add_origin(
-    add, luci::composite_origin({luci::get_origin(broadcastTo), luci::get_origin(addv2)}));
+  luci::add_origin(add, luci::composite_origin({luci::get_origin(bc), luci::get_origin(addv2)}));
 
   auto customOut = loco::succs(addv2);
   assert(customOut.size() == 1);
@@ -103,7 +183,9 @@ bool resolve_custom_op(luci::CircleCustom *addv2)
     auto input = loco::must_cast<luci::CircleNode *>(addv2->inputs(i));
     switch (input->dtype())
     {
+      case loco::DataType::U4:
       case loco::DataType::U8:
+      case loco::DataType::S4:
       case loco::DataType::S8:
       case loco::DataType::S16:
       case loco::DataType::S32:
index 31c245b..2e59146 100644 (file)
 #include "luci/Pass/ResolveCustomOpAddPass.h"
 
 #include <gtest/gtest.h>
+#include <luci/test/TestIOGraph.h>
 
-TEST(ResolveCustomOpAddPassTest, name)
+#include <luci/IR/CircleNodes.h>
+
+using namespace luci::test;
+
+namespace
+{
+
+/**
+ *   Test graph with Custom(AddV2) to resolve
+ *
+ * [Pattern 1]
+ *        [Input]   [BroadcastTo]
+ *             \         /
+ *           [Custom(AddV2)]
+ *                  |
+ *             [CustomOut]
+ *                  |
+ *               [Output]
+ *
+ * [Pattern 2]
+ *        [Input]   [Custom(BroadcastTo)]
+ *             \         /
+ *           [Custom(AddV2)]
+ *                  |
+ *             [CustomOut]
+ *                  |
+ *               [Output]
+ */
+class BroadcastToAddGraphlet
 {
-  luci::ResolveCustomOpAddPass pass;
-  auto const name = pass.name();
+public:
+  BroadcastToAddGraphlet() = default;
+
+public:
+  void init(loco::Graph *g)
+  {
+    _addV2 = g->nodes()->create<luci::CircleCustom>(2, 1);
+    _addV2->custom_code("AddV2");
+    _addV2->shape({2, 3});
+    _addV2->dtype(loco::DataType::FLOAT32);
+    _addV2->name("addV2");
+
+    // Const as BroadcastTo input
+    _broadcastTo_input = g->nodes()->create<luci::CircleConst>();
+    _broadcastTo_input->dtype(loco::DataType::FLOAT32);
+    _broadcastTo_input->shape({1, 3});
+    _broadcastTo_input->size<loco::DataType::FLOAT32>(3);
+    _broadcastTo_input->at<loco::DataType::FLOAT32>(0) = 1;
+    _broadcastTo_input->at<loco::DataType::FLOAT32>(1) = 2;
+    _broadcastTo_input->at<loco::DataType::FLOAT32>(2) = 3;
+
+    // Const as BroadcastTo shape
+    auto broadcastTo_shape = g->nodes()->create<luci::CircleConst>();
+    broadcastTo_shape->dtype(loco::DataType::S32);
+    broadcastTo_shape->shape({2});
+    broadcastTo_shape->size<loco::DataType::S32>(2);
+    broadcastTo_shape->at<loco::DataType::S32>(0) = 2;
+    broadcastTo_shape->at<loco::DataType::S32>(1) = 3;
+
+    _custom_broadcastTo = g->nodes()->create<luci::CircleCustom>(2, 1);
+    _custom_broadcastTo->custom_code("BroadcastTo");
+    _custom_broadcastTo->dtype(loco::DataType::FLOAT32);
+    _custom_broadcastTo->shape({2, 3});
+    _custom_broadcastTo->name("BroadcastTo");
+
+    _custom_broadcastTo->inputs(0, _broadcastTo_input);
+    _custom_broadcastTo->inputs(1, broadcastTo_shape);
+
+    _custom_broadcastTo_out = g->nodes()->create<luci::CircleCustomOut>();
+    _custom_broadcastTo->custom_code("BroadcastTo");
+    _custom_broadcastTo_out->shape({2, 3});
+    _custom_broadcastTo_out->dtype(loco::DataType::FLOAT32);
+    _custom_broadcastTo_out->index(0);
+    _custom_broadcastTo_out->input(_custom_broadcastTo);
+
+    _builtin_broadcastTo = g->nodes()->create<luci::CircleBroadcastTo>();
+    _builtin_broadcastTo->dtype(loco::DataType::FLOAT32);
+    _builtin_broadcastTo->name("BroadcastTo");
+
+    _builtin_broadcastTo->input(_broadcastTo_input);
+    _builtin_broadcastTo->shape(broadcastTo_shape);
+
+    _addV2_out = g->nodes()->create<luci::CircleCustomOut>();
+    _addV2_out->shape({2, 3});
+    _addV2_out->dtype(loco::DataType::FLOAT32);
+    _addV2_out->index(0);
+    _addV2_out->input(_addV2);
+  }
+
+public:
+  luci::CircleCustom *addV2() { return _addV2; }
+  luci::CircleBroadcastTo *builtin_broadcastTo() { return _builtin_broadcastTo; }
+
+protected:
+  luci::CircleCustom *_addV2 = nullptr;
+  luci::CircleCustomOut *_addV2_out = nullptr;
+  luci::CircleCustom *_custom_broadcastTo = nullptr;
+  luci::CircleBroadcastTo *_builtin_broadcastTo = nullptr;
+  luci::CircleCustomOut *_custom_broadcastTo_out = nullptr;
+  luci::CircleConst *_broadcastTo_input = nullptr;
+};
+
+class BroadcastToAddV2Graph : public TestIGraphlet,
+                              public TestOsGraphlet<1>,
+                              public BroadcastToAddGraphlet
+{
+public:
+  BroadcastToAddV2Graph() = default;
+
+  void init(const bool &isCustomBroadcastTo)
+  {
+    TestIGraphlet::init(g(), {2, 3});
+    TestOsGraphlet<1>::init(g(), {{2, 3}});
+    BroadcastToAddGraphlet::init(g());
+
+    // connect Input and Output to test graph
+    _addV2->inputs(0, input());
+
+    if (isCustomBroadcastTo)
+      _addV2->inputs(1, _custom_broadcastTo_out);
+    else
+      _addV2->inputs(1, _builtin_broadcastTo);
+
+    _addV2_out->input(_addV2);
+    output(0)->from(_addV2_out);
+  }
+};
+
+class ResolveCustomOpAddPassTest : public ::testing::Test
+{
+public:
+  BroadcastToAddV2Graph _g;
+  luci::ResolveCustomOpAddPass _pass;
+};
+
+} // namespace
+
+TEST_F(ResolveCustomOpAddPassTest, name)
+{
+  auto const name = _pass.name();
   ASSERT_NE(nullptr, name);
 }
+
+TEST_F(ResolveCustomOpAddPassTest, simple_test_CustomBroadcastTo)
+{
+  _g.init(true);
+
+  // check if Custom(AddV2) exists before the pass
+  auto addV2_out = dynamic_cast<luci::CircleCustomOut *>(_g.output(0)->from());
+  EXPECT_NE(nullptr, addV2_out);
+  auto addV2 = dynamic_cast<luci::CircleCustom *>(addV2_out->input());
+  EXPECT_NE(nullptr, addV2);
+  EXPECT_TRUE("AddV2" == addV2->custom_code());
+
+  auto ret = _pass.run(_g.g());
+  EXPECT_EQ(true, ret);
+
+  // check if Custom(AddV2) is converted to Add
+  auto add = dynamic_cast<luci::CircleAdd *>(_g.output(0)->from());
+  EXPECT_NE(nullptr, add);
+
+  // check if Custom(BroadcastTo) is removed
+  auto input_y = dynamic_cast<luci::CircleConst *>(add->y());
+  EXPECT_NE(nullptr, input_y);
+}
+
+TEST_F(ResolveCustomOpAddPassTest, simple_test_BuiltinBroadcastTo)
+{
+  _g.init(false);
+
+  // check if Custom(AddV2) exists before the pass
+  auto addV2_out = dynamic_cast<luci::CircleCustomOut *>(_g.output(0)->from());
+  EXPECT_NE(nullptr, addV2_out);
+  auto addV2 = dynamic_cast<luci::CircleCustom *>(addV2_out->input());
+  EXPECT_NE(nullptr, addV2);
+  EXPECT_TRUE("AddV2" == addV2->custom_code());
+
+  auto ret = _pass.run(_g.g());
+  EXPECT_EQ(true, ret);
+
+  // check if Custom(AddV2) is converted to Add
+  auto add = dynamic_cast<luci::CircleAdd *>(_g.output(0)->from());
+  EXPECT_NE(nullptr, add);
+
+  // check if BroadcastTo is removed
+  auto input_y = dynamic_cast<luci::CircleConst *>(add->y());
+  EXPECT_NE(nullptr, input_y);
+}
+
+TEST_F(ResolveCustomOpAddPassTest, wrong_custom_code_NEG)
+{
+  _g.init(false);
+
+  _g.addV2()->custom_code("UNSUPORTED_CUSTOM_CODE");
+
+  auto ret = _pass.run(_g.g());
+  EXPECT_EQ(false, ret);
+}
+
+TEST_F(ResolveCustomOpAddPassTest, wrong_input_type_NEG)
+{
+  _g.init(false);
+
+  _g.builtin_broadcastTo()->dtype(loco::DataType::BOOL);
+
+  auto ret = _pass.run(_g.g());
+  EXPECT_EQ(false, ret);
+}
diff --git a/compiler/luci/pass/src/ResolveFormerCustomOpPass.cpp b/compiler/luci/pass/src/ResolveFormerCustomOpPass.cpp
new file mode 100644 (file)
index 0000000..75e74bb
--- /dev/null
@@ -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 "luci/Pass/ResolveFormerCustomOpPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/AttrFusedActFunc.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+#include <flatbuffers/flexbuffers.h>
+
+namespace
+{
+
+bool resolve_with_BroadcastTo(luci::CircleCustom *node)
+{
+  // check if the number of inputs is 2.
+  if (node->numInputs() != 2)
+    return false;
+
+  auto input = loco::must_cast<luci::CircleNode *>(node->inputs(0));
+
+  // check if shape are support data types
+  auto shape = loco::must_cast<luci::CircleNode *>(node->inputs(1));
+  if (shape->dtype() != loco::DataType::S32 && shape->dtype() != loco::DataType::S64)
+    return false;
+
+  auto customOut = loco::succs(node);
+  assert(customOut.size() == 1);
+
+  // check if the data type of output is same with the one of the input feature map.
+  auto output = loco::must_cast<luci::CircleNode *>(*customOut.begin());
+  if (input->dtype() != output->dtype())
+    return false;
+
+  auto name = node->name();
+  assert(name.length() > 0);
+
+  auto broadcastTo = node->graph()->nodes()->create<luci::CircleBroadcastTo>();
+  broadcastTo->input(input);
+  broadcastTo->shape(shape);
+  broadcastTo->name(name);
+  luci::add_origin(broadcastTo, luci::get_origin(node));
+
+  replace(*customOut.begin()).with(broadcastTo);
+
+  return true;
+}
+
+bool resolve_custom_op(luci::CircleCustom *node)
+{
+  const std::string custom_code = node->custom_code();
+
+  if (custom_code == "BroadcastTo")
+  {
+    return resolve_with_BroadcastTo(node);
+  }
+  // TODO add more custom codes
+
+  return false;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool ResolveFormerCustomOpPass::run(loco::Graph *g)
+{
+  bool changed = false;
+
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto cop = dynamic_cast<luci::CircleCustom *>(node);
+    if (not cop)
+      continue;
+
+    if (resolve_custom_op(cop))
+      changed = true;
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/ResolveFormerCustomOpPass.test.cpp b/compiler/luci/pass/src/ResolveFormerCustomOpPass.test.cpp
new file mode 100644 (file)
index 0000000..dc8cc7e
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Pass/ResolveFormerCustomOpPass.h"
+
+#include <luci/test/TestIOGraph.h>
+
+#include <luci/IR/CircleNodes.h>
+#include <gtest/gtest.h>
+
+using namespace luci::test;
+
+namespace
+{
+
+/**
+ *  graph having Custom operator BroadcastTo
+ *
+ *     [Const(Input)] [Const(Shape)]
+ *             \         /
+ *         [Custom(BroadcastTo)]
+ *                  |
+ *             [CustomOut]
+ *                  |
+ *              [Output]
+ */
+class CustomBroadcastToGraphlet
+{
+public:
+  CustomBroadcastToGraphlet() = default;
+
+public:
+  void init(loco::Graph *g)
+  {
+    // CircleCustom(BroadcastTo)
+    _broadcastTo = g->nodes()->create<luci::CircleCustom>(2, 1);
+    _broadcastTo->custom_code("BroadcastTo");
+    _broadcastTo->dtype(loco::DataType::FLOAT32);
+    _broadcastTo->shape({2, 3});
+    _broadcastTo->name("BroadcastTo");
+
+    // CircleConst(BroadcastTo-input)
+    _input = g->nodes()->create<luci::CircleConst>();
+    _input->dtype(loco::DataType::FLOAT32);
+    _input->shape({1, 3});
+    _input->size<loco::DataType::FLOAT32>(3);
+    _input->at<loco::DataType::FLOAT32>(0) = 1;
+    _input->at<loco::DataType::FLOAT32>(1) = 2;
+    _input->at<loco::DataType::FLOAT32>(2) = 3;
+
+    // CircleConst(BroadcastTo-shape)
+    _shape = g->nodes()->create<luci::CircleConst>();
+    _shape->dtype(loco::DataType::S32);
+    _shape->shape({2});
+    _shape->size<loco::DataType::S32>(2);
+    _shape->at<loco::DataType::S32>(0) = 2;
+    _shape->at<loco::DataType::S32>(1) = 3;
+
+    _broadcastTo->inputs(0, _input);
+    _broadcastTo->inputs(1, _shape);
+
+    // CircleCustomOut
+    _broadcastTo_out = g->nodes()->create<luci::CircleCustomOut>();
+    _broadcastTo_out->shape({2, 3});
+    _broadcastTo_out->dtype(loco::DataType::FLOAT32);
+    _broadcastTo_out->index(0);
+    _broadcastTo_out->input(_broadcastTo);
+  }
+
+public:
+  luci::CircleCustom *broadcastTo() { return _broadcastTo; }
+  luci::CircleConst *shape() { return _shape; }
+  luci::CircleCustomOut *broadcastTo_out() { return _broadcastTo_out; }
+
+protected:
+  luci::CircleCustom *_broadcastTo = nullptr;
+  luci::CircleCustomOut *_broadcastTo_out = nullptr;
+  luci::CircleConst *_input = nullptr;
+  luci::CircleConst *_shape = nullptr;
+};
+
+class BroadcastToGraph : public TestIGraphlet,
+                         public TestOsGraphlet<1>,
+                         public CustomBroadcastToGraphlet
+{
+public:
+  BroadcastToGraph() = default;
+
+  void init(void)
+  {
+    TestOsGraphlet<1>::init(g(), {{1, 2, 3, 1, 2, 3}});
+    CustomBroadcastToGraphlet::init(g());
+
+    output(0)->from(_broadcastTo_out);
+  }
+};
+
+class FormerCustomOpGraphTest : public ::testing::Test
+{
+public:
+  BroadcastToGraph _g;
+  luci::ResolveFormerCustomOpPass _pass;
+};
+
+} // namespace
+
+TEST(ResolveFormerCustomOpPassTest, name)
+{
+  luci::ResolveFormerCustomOpPass pass;
+  auto const name = pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST_F(FormerCustomOpGraphTest, simple_test_BroadcastTo)
+{
+  _g.init();
+
+  auto ret = _pass.run(_g.g());
+  EXPECT_EQ(true, ret);
+
+  auto broadcastTo = dynamic_cast<luci::CircleBroadcastTo *>(_g.output(0)->from());
+  EXPECT_NE(nullptr, broadcastTo);
+
+  auto input = dynamic_cast<luci::CircleConst *>(broadcastTo->input());
+  EXPECT_NE(nullptr, input);
+  EXPECT_EQ(1, input->at<loco::DataType::FLOAT32>(0));
+  EXPECT_EQ(2, input->at<loco::DataType::FLOAT32>(1));
+  EXPECT_EQ(3, input->at<loco::DataType::FLOAT32>(2));
+
+  auto shape = dynamic_cast<luci::CircleConst *>(broadcastTo->shape());
+  EXPECT_NE(nullptr, shape);
+  EXPECT_EQ(true, (shape->dtype() == loco::DataType::S32));
+  EXPECT_EQ(2, shape->at<loco::DataType::S32>(0));
+  EXPECT_EQ(3, shape->at<loco::DataType::S32>(1));
+}
+
+TEST_F(FormerCustomOpGraphTest, wrong_op_NEG)
+{
+  _g.init();
+
+  _g.broadcastTo()->custom_code("UNSUPORTED_CUSTOM_CODE");
+
+  auto ret = _pass.run(_g.g());
+  EXPECT_EQ(false, ret);
+}
+
+TEST_F(FormerCustomOpGraphTest, wrong_shape_type_NEG)
+{
+  // the data type of shape should be S32 or S64.
+  _g.init();
+
+  _g.shape()->dtype(loco::DataType::FLOAT32);
+
+  auto ret = _pass.run(_g.g());
+  EXPECT_EQ(false, ret);
+}
+
+TEST_F(FormerCustomOpGraphTest, unequal_input_output_type_NEG)
+{
+  _g.init();
+
+  _g.broadcastTo_out()->dtype(loco::DataType::S32);
+
+  auto ret = _pass.run(_g.g());
+  EXPECT_EQ(false, ret);
+}
index 549ed22..d756d91 100644 (file)
@@ -215,9 +215,9 @@ bool positive_or_zero(loco::Node *ifm)
   // Since Relu.output[i] >= 0
   if (dynamic_cast<luci::CircleRelu *>(ifm))
     return true;
-  if (auto conv = dynamic_cast<luci::CircleConv2D *>(ifm))
+  if (auto node = dynamic_cast<luci::CircleNodeMixin<luci::CircleNodeTrait::FusedActFunc> *>(ifm))
   {
-    if (conv->fusedActivationFunction() == luci::FusedActFunc::RELU)
+    if (node->fusedActivationFunction() == luci::FusedActFunc::RELU)
       return true;
     // Add more FusedActFunc
   }
index df7266d..9bc764f 100644 (file)
@@ -119,7 +119,7 @@ bool substitute_squeeze_to_reshape(luci::CircleSqueeze *squeeze)
   if (squeeze->shape_status() != luci::ShapeStatus::VALID)
     return false;
 
-  auto squeeze_dims = squeeze->squeeze_dims();
+  auto &squeeze_dims = squeeze->squeeze_dims();
   if (not is_valid_input(input, squeeze_dims))
     throw std::runtime_error("Invalid values in squeeze_dims: " + squeeze->name());
 
index 9d1dfc1..d196c59 100644 (file)
@@ -17,7 +17,6 @@
 #include "luci/Pass/TransformMinMaxToRelu6Pass.h"
 
 #include "helpers/NodeFiller.h"
-#include "helpers/TypeMapper.h"
 
 #include <luci/IR/CircleNodes.h>
 #include <luci/Profile/CircleNodeOrigin.h>
index cccc013..f5ec3df 100644 (file)
@@ -17,7 +17,6 @@
 #include "luci/Pass/TransformMinReluToRelu6Pass.h"
 
 #include "helpers/NodeFiller.h"
-#include "helpers/TypeMapper.h"
 
 #include <luci/IR/CircleNodes.h>
 #include <luci/Profile/CircleNodeOrigin.h>
diff --git a/compiler/luci/pass/src/TransformSqrtDivToRsqrtMulPass.cpp b/compiler/luci/pass/src/TransformSqrtDivToRsqrtMulPass.cpp
new file mode 100644 (file)
index 0000000..c21319d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/TransformSqrtDivToRsqrtMulPass.h"
+
+#include "helpers/NodeFiller.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace
+{
+
+/**
+ *  BEFORE
+ *        [CircleNode] [CircleNode]
+ *              |           |
+ *              |      [CircleSqrt]
+ *              |       |
+ *             [CircleDiv]
+ *                  |
+ *             [CircleNode]
+ *
+ *  AFTER
+ *        [CircleNode] [CircleNode]
+ *              |           |
+ *              |      [CircleRsqrt]   [CircleSqrt]
+ *              |       |                   |
+ *             [CircleMul]             [CircleDiv]
+ *                  |
+ *             [CircleNode]
+ *
+ */
+
+bool transform_sqrtdiv_to_rsqrtmul(luci::CircleDiv *div)
+{
+  assert(div != nullptr);
+
+  // skip if x is const, for FuseRsqrtPass
+  auto *const_node = dynamic_cast<luci::CircleConst *>(div->x());
+  if (const_node != nullptr)
+    return false;
+
+  auto *sqrt = dynamic_cast<luci::CircleSqrt *>(div->y());
+  if (sqrt == nullptr)
+    return false;
+
+  auto *graph = div->graph();
+
+  auto *rsqrt = graph->nodes()->create<luci::CircleRsqrt>();
+  rsqrt->x(sqrt->x());
+  rsqrt->name(sqrt->name() + "_rsqrt");
+  luci::add_origin(rsqrt, luci::get_origin(sqrt));
+
+  auto *mul = graph->nodes()->create<luci::CircleMul>();
+  mul->x(div->x());
+  mul->y(rsqrt);
+  mul->fusedActivationFunction(div->fusedActivationFunction());
+  mul->name(div->name() + "_mul");
+  luci::add_origin(mul, luci::get_origin(div));
+
+  replace(div).with(mul);
+
+  return true;
+}
+
+} // namespace
+
+namespace luci
+{
+
+bool TransformSqrtDivToRsqrtMulPass::run(loco::Graph *g)
+{
+  bool changed = false;
+
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    if (auto div = dynamic_cast<luci::CircleDiv *>(node))
+    {
+      if (transform_sqrtdiv_to_rsqrtmul(div))
+        changed = true;
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/TransformSqrtDivToRsqrtMulPass.test.cpp b/compiler/luci/pass/src/TransformSqrtDivToRsqrtMulPass.test.cpp
new file mode 100644 (file)
index 0000000..4f3bc2c
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/TransformSqrtDivToRsqrtMulPass.h"
+
+#include <luci/test/TestIOGraph.h>
+
+#include <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class SqrtDivGraphlet
+{
+public:
+  SqrtDivGraphlet() = default;
+
+public:
+  void init(loco::Graph *g)
+  {
+    _div = g->nodes()->create<luci::CircleDiv>();
+    _div->name("div");
+
+    _sqrt = g->nodes()->create<luci::CircleSqrt>();
+    _sqrt->name("sqrt");
+  }
+
+protected:
+  luci::CircleDiv *_div = nullptr;
+  luci::CircleSqrt *_sqrt = nullptr;
+};
+
+class SqrtDivGraph : public TestIOGraph, public SqrtDivGraphlet
+{
+public:
+  SqrtDivGraph() = default;
+
+public:
+  void init(void)
+  {
+    TestIOGraph::init({1, 2, 3}, {1, 2, 3});
+    SqrtDivGraphlet::init(g());
+
+    _div->x(input());
+    _div->y(_sqrt);
+
+    _sqrt->x(input());
+
+    output()->from(_div);
+  }
+};
+
+// For negative test: Div input order does not match
+class SqrtDivOrderGraph : public TestIOGraph, public SqrtDivGraphlet
+{
+public:
+  SqrtDivOrderGraph() = default;
+
+public:
+  void init(void)
+  {
+    TestIOGraph::init({1, 2, 3}, {1, 2, 3});
+    SqrtDivGraphlet::init(g());
+
+    _div->x(_sqrt);
+    _div->y(input());
+
+    _sqrt->x(input());
+
+    output()->from(_div);
+  }
+};
+
+// For negative test: Div input x is Const
+class SqrtDivConstGraph : public TestIOGraph, public SqrtDivGraphlet
+{
+public:
+  SqrtDivConstGraph() = default;
+
+public:
+  void init(void)
+  {
+    TestIOGraph::init({1, 2, 3}, {1, 2, 3});
+    SqrtDivGraphlet::init(g());
+
+    _const = g()->nodes()->create<luci::CircleConst>();
+    _const->name("const");
+
+    _div->x(_const);
+    _div->y(_sqrt);
+
+    _sqrt->x(input());
+
+    output()->from(_div);
+  }
+
+protected:
+  luci::CircleConst *_const = nullptr;
+};
+
+class TransformSqrtDivToRsqrtMulPassTest : public ::testing::Test
+{
+protected:
+  luci::TransformSqrtDivToRsqrtMulPass _pass;
+};
+
+} // namespace
+
+TEST_F(TransformSqrtDivToRsqrtMulPassTest, name)
+{
+  auto const name = _pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST_F(TransformSqrtDivToRsqrtMulPassTest, simple_run)
+{
+  SqrtDivGraph graph;
+  graph.init();
+
+  EXPECT_TRUE(_pass.run(graph.g()));
+
+  // success pass will transform Div to Mul
+  auto mul_node = dynamic_cast<luci::CircleMul *>(graph.output()->from());
+  ASSERT_NE(nullptr, mul_node);
+}
+
+TEST_F(TransformSqrtDivToRsqrtMulPassTest, div_input_order_NEG)
+{
+  SqrtDivOrderGraph graph;
+  graph.init();
+
+  EXPECT_FALSE(_pass.run(graph.g()));
+}
+
+TEST_F(TransformSqrtDivToRsqrtMulPassTest, div_input_const_NEG)
+{
+  SqrtDivConstGraph graph;
+  graph.init();
+
+  EXPECT_FALSE(_pass.run(graph.g()));
+}
index b73efaf..0b736e7 100644 (file)
@@ -16,9 +16,6 @@
 
 #include "luci/Pass/UnrollUnidirectionalSequenceLSTMPass.h"
 
-#include "helpers/NodeFiller.h"
-#include "helpers/TypeMapper.h"
-
 #include <luci/IR/CircleNodes.h>
 #include <luci/Profile/CircleNodeOrigin.h>
 
diff --git a/compiler/luci/pass/src/XpSepActFromTransposeConvPass.cpp b/compiler/luci/pass/src/XpSepActFromTransposeConvPass.cpp
new file mode 100644 (file)
index 0000000..74f5535
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Pass/XpSepActFromTransposeConvPass.h"
+
+#include <luci/IR/CircleNodes.h>
+#include <luci/IR/CircleNodeMixins.h>
+#include <luci/Profile/CircleNodeOrigin.h>
+
+namespace luci
+{
+
+/**
+ * XpSepActFromTransposeConvPass
+ * - Experimental Separate Activation From TransposeConv
+ * - This pass exist temporary to separate activation function from
+ * - TransposeConv to support backends that don't support this.
+ * - This pass will be removed when all backends support fused activation.
+ *
+ *  BEFORE
+ *       [Node]
+ *         |
+ *   [TransposeConv] (w/ Act)
+ *         |
+ *       [Node]
+ *
+ *  AFTER
+ *
+ *       [Node]
+ *         |
+ *   [TransposeConv]
+ *         |
+ *   [ReLU/ReLU6/...]
+ *         |
+ *       [Node]
+ *
+ */
+
+namespace
+{
+
+bool separate_activation_fuction(luci::CircleTransposeConv *trconv)
+{
+  // cannot separate for quantized state: support F32 for now
+  // TODO revise this to better way
+  if (trconv->dtype() != loco::DataType::FLOAT32)
+    return false;
+
+  auto fused_act = trconv->fusedActivationFunction();
+  if (fused_act == luci::FusedActFunc::NONE)
+    return false;
+  if (fused_act == luci::FusedActFunc::UNDEFINED)
+    throw std::runtime_error("XpSepActFromTransposeConvPass Activation is undefined");
+
+  // NOTE features() is call after replace().with();
+  //      calling loco::replace(trconv).with(actnode) will also update actnode
+  //      itself which will make totally wrong result with actnode input being
+  //      itself. this happends as TransposeConv is re-used, not replaced with
+  //      a new one.
+
+  auto name = trconv->name();
+  luci::CircleNode *actnode = nullptr;
+  switch (fused_act)
+  {
+    case luci::FusedActFunc::RELU:
+    {
+      auto af = trconv->graph()->nodes()->create<luci::CircleRelu>();
+      loco::replace(trconv).with(af);
+      af->features(trconv);
+      af->name(name + "/Relu");
+      actnode = af;
+    }
+    break;
+    case luci::FusedActFunc::RELU6:
+    {
+      auto af = trconv->graph()->nodes()->create<luci::CircleRelu6>();
+      loco::replace(trconv).with(af);
+      af->features(trconv);
+      af->name(name + "/Relu6");
+      actnode = af;
+    }
+    break;
+    // TODO support more
+    default:
+      return false;
+  }
+  assert(actnode != nullptr);
+  actnode->dtype(trconv->dtype());
+  luci::add_origin(actnode, luci::get_origin(trconv));
+
+  trconv->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+  return true;
+}
+
+} // namespace
+
+bool XpSepActFromTransposeConvPass::run(loco::Graph *g)
+{
+  bool changed = false;
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto trconv = dynamic_cast<luci::CircleTransposeConv *>(node);
+    if (trconv != nullptr)
+    {
+      if (separate_activation_fuction(trconv))
+        changed = true;
+    }
+  }
+
+  return changed;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/XpSepActFromTransposeConvPass.test.cpp b/compiler/luci/pass/src/XpSepActFromTransposeConvPass.test.cpp
new file mode 100644 (file)
index 0000000..73824ba
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/XpSepActFromTransposeConvPass.h"
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci/test/TestIOGraph.h>
+#include "test/TestFirstNode.h"
+
+#include <gtest/gtest.h>
+
+namespace
+{
+
+using namespace luci::test;
+
+class TrConvGraphlet
+{
+public:
+  TrConvGraphlet() = default;
+
+public:
+  void init(loco::Graph *g, ShapeU32 wshape)
+  {
+    const uint32_t elements_num = num_elements(wshape);
+
+    // trconv inputSizes
+    auto wshape_size = static_cast<uint32_t>(wshape.size());
+    _inpsize = g->nodes()->create<luci::CircleConst>();
+    _inpsize->dtype(loco::DataType::S32);
+    _inpsize->shape({wshape_size});
+    _inpsize->size<loco::DataType::S32>(wshape_size);
+    auto wsp = wshape.begin();
+    for (uint32_t idx = 0; idx < wshape_size; idx++)
+    {
+      _inpsize->at<loco::DataType::S32>(idx) = int32_t(*wsp++);
+    }
+    _inpsize->name("inpsize");
+
+    // trconv filter
+    _filter = g->nodes()->create<luci::CircleConst>();
+    _filter->dtype(loco::DataType::FLOAT32);
+    _filter->shape(wshape);
+    _filter->size<loco::DataType::FLOAT32>(elements_num);
+    for (uint32_t idx = 0; idx < elements_num; idx++)
+    {
+      _filter->at<loco::DataType::FLOAT32>(idx) = float(idx);
+    }
+    _filter->name("filter");
+
+    // trconv
+    _tc = g->nodes()->create<luci::CircleTransposeConv>();
+    _tc->dtype(loco::DataType::FLOAT32);
+    _tc->name("trconv");
+  }
+
+protected:
+  luci::CircleTransposeConv *_tc = nullptr;
+  luci::CircleConst *_filter = nullptr;
+  luci::CircleConst *_inpsize = nullptr;
+};
+
+class TrConvGraph : public TestIGraphlet, public TestOGraphlet, public TrConvGraphlet
+{
+public:
+  TrConvGraph() = default;
+
+  void init(const ShapeU32 shape)
+  {
+    TestIGraphlet::init(g(), shape);
+    TestOGraphlet::init(g(), shape);
+    TrConvGraphlet::init(g(), shape);
+
+    // connect graph
+    _tc->inputSizes(_inpsize);
+    _tc->filter(_filter);
+    _tc->outBackprop(input());
+
+    output()->from(_tc);
+  }
+};
+
+} // namespace
+
+TEST(XpSepActFromTransposeConvPassTest, name)
+{
+  luci::XpSepActFromTransposeConvPass pass;
+  auto const name = pass.name();
+  ASSERT_NE(nullptr, name);
+}
+
+TEST(XpSepActFromTransposeConvPassTest, separation_ok)
+{
+  TrConvGraph g;
+
+  g.init({1, 4, 4, 3});
+
+  auto tc_node = luci::test::first_node<luci::CircleTransposeConv>(g.g());
+  ASSERT_NE(tc_node, nullptr);
+  tc_node->fusedActivationFunction(luci::FusedActFunc::RELU);
+
+  luci::XpSepActFromTransposeConvPass pass;
+  EXPECT_EQ(pass.run(g.g()), true);
+
+  auto la_node = dynamic_cast<luci::CircleRelu *>(g.output()->from());
+  ASSERT_NE(la_node, nullptr);
+  auto la_tc_node = dynamic_cast<luci::CircleTransposeConv *>(la_node->features());
+  ASSERT_NE(la_tc_node, nullptr);
+  ASSERT_EQ(la_tc_node->fusedActivationFunction(), luci::FusedActFunc::NONE);
+}
+
+TEST(XpSepActFromTransposeConvPassTest, none_act_NEG)
+{
+  TrConvGraph g;
+
+  g.init({1, 4, 4, 3});
+
+  auto tc_node = luci::test::first_node<luci::CircleTransposeConv>(g.g());
+  ASSERT_NE(tc_node, nullptr);
+  tc_node->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+  luci::XpSepActFromTransposeConvPass pass;
+  EXPECT_NE(pass.run(g.g()), true);
+}
+
+TEST(XpSepActFromTransposeConvPassTest, invalid_act_NEG)
+{
+  TrConvGraph g;
+
+  g.init({1, 4, 4, 3});
+
+  auto tc_node = luci::test::first_node<luci::CircleTransposeConv>(g.g());
+  ASSERT_NE(tc_node, nullptr);
+  // leave activation as undefined
+
+  luci::XpSepActFromTransposeConvPass pass;
+  EXPECT_ANY_THROW(pass.run(g.g()));
+}
+
+TEST(XpSepActFromTransposeConvPassTest, invalid_dtype_NEG)
+{
+  TrConvGraph g;
+
+  g.init({1, 4, 4, 3});
+
+  auto tc_node = luci::test::first_node<luci::CircleTransposeConv>(g.g());
+  ASSERT_NE(tc_node, nullptr);
+  tc_node->dtype(loco::DataType::S16);
+
+  luci::XpSepActFromTransposeConvPass pass;
+  EXPECT_NE(pass.run(g.g()), true);
+}
diff --git a/compiler/luci/pass/src/helpers/Compute.cpp b/compiler/luci/pass/src/helpers/Compute.cpp
new file mode 100644 (file)
index 0000000..6c9e855
--- /dev/null
@@ -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.
+ */
+
+#include "Compute.h"
+
+namespace luci
+{
+
+bool to_compute(const Padding padding, compute::PaddingType &padding_type)
+{
+  switch (padding)
+  {
+    case Padding::SAME:
+      padding_type = compute::PaddingType::kSame;
+      break;
+
+    case Padding::VALID:
+      padding_type = compute::PaddingType::kValid;
+      break;
+
+    default:
+      return false;
+  }
+  return true;
+}
+
+bool to_compute(const FusedActFunc act, compute::FusedActFunc &act_func)
+{
+  switch (act)
+  {
+    case FusedActFunc::NONE:
+      act_func = compute::FusedActFunc::NONE;
+      break;
+
+    case FusedActFunc::TANH:
+      act_func = compute::FusedActFunc::TANH;
+      break;
+
+    case FusedActFunc::RELU:
+      act_func = compute::FusedActFunc::RELU;
+      break;
+
+    case FusedActFunc::RELU_N1_TO_1:
+      act_func = compute::FusedActFunc::RELU_N1_TO_1;
+      break;
+
+    case FusedActFunc::RELU6:
+      act_func = compute::FusedActFunc::RELU6;
+      break;
+
+    default:
+      return false;
+  }
+  return true;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/helpers/Compute.h b/compiler/luci/pass/src/helpers/Compute.h
new file mode 100644 (file)
index 0000000..9034adf
--- /dev/null
@@ -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 __LUCI_PASS_HELPERS_COMPUTE_H__
+#define __LUCI_PASS_HELPERS_COMPUTE_H__
+
+#include <luci/IR/CircleNodes.h>
+
+#include <luci_compute/Types.h>
+
+namespace luci
+{
+
+// Convert luci::XX to luci::compute::XX
+// Return true if conversion is valid.
+// Return false otherwise (undefined behavior).
+bool to_compute(const Padding padding, compute::PaddingType &padding_type);
+bool to_compute(const FusedActFunc act, compute::FusedActFunc &act_func);
+
+} // namespace luci
+
+#endif // __LUCI_PASS_HELPERS_COMPUTE_H__
diff --git a/compiler/luci/pass/src/helpers/ExpressionCache.cpp b/compiler/luci/pass/src/helpers/ExpressionCache.cpp
new file mode 100644 (file)
index 0000000..b51f1bb
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ExpressionCache.h"
+
+namespace
+{
+
+#define RETURN_FALSE_UNLESS(cond) \
+  if (not(cond))                  \
+    return false;
+
+// Check common (non-op-specific) attributes of lhs and rhs
+bool same_common_attributes(const luci::CircleNode *lhs, const luci::CircleNode *rhs)
+{
+  // Opcode
+  if (lhs->opcode() != rhs->opcode())
+    return false;
+
+  // Shape
+  if (lhs->rank() != rhs->rank())
+    return false;
+
+  for (uint32_t i = 0; i < lhs->rank(); i++)
+  {
+    if (lhs->dim(i).known() != rhs->dim(i).known())
+      return false;
+
+    if (lhs->dim(i).value() != rhs->dim(i).value())
+      return false;
+  }
+
+  // Data type
+  if (lhs->dtype() != rhs->dtype())
+    return false;
+
+  // Op version
+  if (lhs->op_version() != rhs->op_version())
+    return false;
+
+  // QuantParam
+  const auto lhs_qparam = lhs->quantparam();
+  const auto rhs_qparam = rhs->quantparam();
+
+  if (lhs_qparam == nullptr and rhs_qparam != nullptr)
+    return false;
+
+  if (lhs_qparam != nullptr and rhs_qparam == nullptr)
+    return false;
+
+  if (lhs_qparam)
+  {
+    assert(rhs_qparam); // FIX_ME_UNLESS
+
+    if (lhs_qparam->scale != rhs_qparam->scale)
+      return false;
+
+    if (lhs_qparam->zerop != rhs_qparam->zerop)
+      return false;
+
+    if (lhs_qparam->min != rhs_qparam->min)
+      return false;
+
+    if (lhs_qparam->max != rhs_qparam->max)
+      return false;
+  }
+
+  return true;
+}
+
+// Return true if two constants are the same
+bool same_const(const luci::CircleConst *x, const luci::CircleConst *y)
+{
+  assert(x != nullptr); // FIX_CALLER_UNLESS
+  assert(y != nullptr); // FIX_CALLER_UNLESS
+
+  RETURN_FALSE_UNLESS(same_common_attributes(x, y));
+
+  switch (x->dtype())
+  {
+    case loco::DataType::S32:
+    {
+      const auto size_x = x->size<loco::DataType::S32>();
+      const auto size_y = y->size<loco::DataType::S32>();
+      RETURN_FALSE_UNLESS(size_x == size_y);
+
+      for (uint32_t i = 0; i < size_x; i++)
+      {
+        RETURN_FALSE_UNLESS(x->at<loco::DataType::S32>(i) == y->at<loco::DataType::S32>(i));
+      }
+      return true;
+    }
+    // TODO Support more dtypes
+    default:
+      // Simply return false
+      return false;
+  }
+
+  return true;
+}
+
+// Return true if x and y are semantically equal
+bool same_attributes(const luci::CircleTranspose *x, luci::CircleTranspose *y)
+{
+  assert(x != nullptr); // FIX_CALLER_UNLESS
+  assert(y != nullptr); // FIX_CALLER_UNLESS
+
+  assert(same_common_attributes(x, y)); // FIX_CALLER_UNLESS
+
+  const auto perm_x = dynamic_cast<luci::CircleConst *>(x->perm());
+  const auto perm_y = dynamic_cast<luci::CircleConst *>(y->perm());
+
+  RETURN_FALSE_UNLESS(perm_x);
+  RETURN_FALSE_UNLESS(perm_y);
+
+  // Check perm_x and perm_y are the same
+  RETURN_FALSE_UNLESS(same_const(perm_x, perm_y));
+
+  return true;
+}
+
+// Use a similar approach as boost's hash_combine
+template <class T> inline void hash_combine(std::size_t &s, const T v)
+{
+  std::hash<T> h;
+  s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
+}
+
+template <> inline void hash_combine(std::size_t &s, luci::CircleNode *node)
+{
+  // Shape
+  hash_combine(s, node->rank());
+  for (uint32_t i = 0; i < node->rank(); i++)
+    hash_combine(s, node->dim(i).value());
+
+  // Data type
+  hash_combine(s, static_cast<std::size_t>(node->dtype()));
+
+  // Op version
+  hash_combine(s, node->op_version());
+
+  // Op code
+  hash_combine(s, node->opcode());
+
+  // QuantParam
+  // Let's skip quantparam to reduce burden of hash function
+}
+
+} // namespace
+
+namespace luci
+{
+namespace pass
+{
+
+Expression Expression::build(luci::CircleNode *node)
+{
+  if (node == nullptr)
+    throw std::invalid_argument("node");
+
+  Expression key;
+  {
+    switch (node->opcode())
+    {
+      case luci::CircleOpcode::QUANTIZE:
+      case luci::CircleOpcode::TRANSPOSE:
+        key.inputs.emplace_back(node->arg(0));
+        break;
+      // TODO Add more Ops
+      default:
+        // NYI. Return invalid expression
+        key.op = nullptr;
+        return key;
+    }
+
+    key.op = node;
+  }
+
+  return key;
+}
+
+bool operator==(const Expression &x, const Expression &y)
+{
+  if (x.inputs != y.inputs)
+    return false;
+
+  // Check general (non-op-specific) attributes
+  if (not same_common_attributes(x.op, y.op))
+    return false;
+
+  assert(x.op->opcode() == y.op->opcode()); // FIX_ME_UNLESS
+
+  // Check op-specific attributes
+  switch (x.op->opcode())
+  {
+    case luci::CircleOpcode::QUANTIZE:
+    {
+      // This Op has no op-specific attribute.
+      // same_common_attributes is enough.
+      return true;
+    }
+    case luci::CircleOpcode::TRANSPOSE:
+    {
+      const auto trans_x = loco::must_cast<luci::CircleTranspose *>(x.op);
+      const auto trans_y = loco::must_cast<luci::CircleTranspose *>(y.op);
+
+      return same_attributes(trans_x, trans_y);
+    }
+    // TODO Implement more operators
+    default:
+      // NYI: Unsupported operators
+      return false;
+  }
+
+  return true;
+}
+
+std::size_t Expression::Hash::call(const Expression &k) const noexcept
+{
+  std::size_t res = 0;
+  for (const auto input : k.inputs)
+    hash_combine(res, input);
+
+  hash_combine(res, k.op);
+
+  return res;
+}
+
+} // namespace pass
+} // namespace luci
diff --git a/compiler/luci/pass/src/helpers/ExpressionCache.h b/compiler/luci/pass/src/helpers/ExpressionCache.h
new file mode 100644 (file)
index 0000000..bf94608
--- /dev/null
@@ -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_PASS_HELPERS_EXPRESSION_CACHE_H__
+#define __LUCI_PASS_HELPERS_EXPRESSION_CACHE_H__
+
+#include <luci/IR/CircleNodes.h>
+
+#include <vector>
+#include <unordered_map>
+
+namespace luci
+{
+namespace pass
+{
+
+// Expression is defined as a circle node (operator) and its input feature maps
+struct Expression final
+{
+private:
+  // Prevent default ctor
+  Expression() = default;
+
+public:
+  // Input feature maps
+  std::vector<loco::Node *> inputs;
+  luci::CircleNode *op = nullptr;
+
+  // Hash function for Expression (used for std::unordered_map)
+  struct Hash final
+  {
+    std::size_t call(const Expression &k) const noexcept;
+    std::size_t operator()(const Expression &k) const noexcept { return call(k); }
+  };
+
+  // Build expression from a circle node
+  // Returned Expression.op == nullptr if Expression is invalid
+  static Expression build(luci::CircleNode *node);
+};
+
+// Return true if two expressions are the same
+// This is a core logic for common subexpression elimination
+bool operator==(const Expression &x, const Expression &y);
+
+// Cache for Expression object
+class ExpressionCache final
+{
+public:
+  using Key = Expression;
+  using Value = luci::CircleNode *;
+
+private:
+  std::unordered_map<Key, Value, Key::Hash> _content;
+
+public:
+  // Return value for the corresponding key
+  // Return nullptr if there is no item with the key
+  Value get(const Key &k) const
+  {
+    auto item = _content.find(k);
+    if (item == _content.end())
+      return nullptr;
+
+    return item->second;
+  }
+
+  // Save circle node for the corresponding key
+  void put(const Key &k, const Value v) { _content[k] = v; }
+};
+
+} // namespace pass
+} // namespace luci
+
+#endif // __LUCI_PASS_HELPERS_EXPRESSION_CACHE_H__
diff --git a/compiler/luci/pass/src/helpers/ExpressionCache.test.cpp b/compiler/luci/pass/src/helpers/ExpressionCache.test.cpp
new file mode 100644 (file)
index 0000000..308324b
--- /dev/null
@@ -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 <luci/IR/CircleNodes.h>
+
+#include <gtest/gtest.h>
+
+#include "ExpressionCache.h"
+
+using namespace luci::pass;
+
+TEST(ExpressionCacheTest, simple_test)
+{
+  luci::CircleInput in;
+  luci::CircleQuantize node;
+  node.input(&in);
+
+  auto expr = Expression::build(&node);
+
+  ExpressionCache cache;
+
+  cache.put(expr, &node);
+
+  EXPECT_NE(nullptr, cache.get(expr));
+}
+
+TEST(ExpressionCacheTest, null_expr_NEG) { EXPECT_ANY_THROW(Expression::build(nullptr)); }
+
+TEST(ExpressionCacheTest, invalid_expr_NEG)
+{
+  luci::CircleInput in;
+
+  auto expr = Expression::build(&in);
+
+  // Input is a virtual Op, thus return invalid expr
+  EXPECT_EQ(nullptr, expr.op);
+}
index ac07f9e..37d8e18 100644 (file)
@@ -145,7 +145,7 @@ LayerInfoMap layer_info_map(loco::Graph *g, std::vector<LayerInfo> &layers_info)
 
   for (auto &&info : layers_info)
   {
-    auto name = info.name;
+    auto &name = info.name;
     bool found = false;
     for (auto node : loco::active_nodes(loco::output_nodes(g)))
     {
diff --git a/compiler/luci/pass/src/helpers/Shape.cpp b/compiler/luci/pass/src/helpers/Shape.cpp
new file mode 100644 (file)
index 0000000..76b7188
--- /dev/null
@@ -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.
+ */
+
+#include "Shape.h"
+
+namespace luci
+{
+
+bool is_same_shape(const luci::CircleNode *node, const loco::TensorShape &shape)
+{
+  if (node == nullptr)
+    return false;
+
+  if (node->shape_status() != luci::ShapeStatus::VALID)
+    return false;
+
+  if (node->rank() != shape.rank())
+    return false;
+
+  for (uint32_t i = 0; i < node->rank(); ++i)
+  {
+    if (node->dim(i).known() != shape.dim(i).known())
+      return false;
+
+    if (node->dim(i).value() != shape.dim(i).value())
+      return false;
+  }
+
+  return true;
+}
+
+bool is_same_shape(const luci::CircleNode *node, const std::initializer_list<uint32_t> shape)
+{
+  if (node == nullptr)
+    return false;
+
+  if (node->rank() != shape.size())
+    return false;
+
+  uint32_t i = 0;
+  for (auto it = shape.begin(); it != shape.end(); ++it, ++i)
+  {
+    if (node->dim(i).value() != *it)
+      return false;
+  }
+  return true;
+}
+
+bool has_dynamic_shape(const loco::Node *node)
+{
+  const auto circle_node = loco::must_cast<const luci::CircleNode *>(node);
+  for (uint32_t i = 0; i < circle_node->rank(); ++i)
+    if (!circle_node->dim(i).known())
+      return true;
+  return false;
+}
+
+} // namespace luci
diff --git a/compiler/luci/pass/src/helpers/Shape.h b/compiler/luci/pass/src/helpers/Shape.h
new file mode 100644 (file)
index 0000000..69ea50e
--- /dev/null
@@ -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.
+ */
+
+#ifndef __LUCI_PASS_HELPERS_SHAPE_H__
+#define __LUCI_PASS_HELPERS_SHAPE_H__
+
+#include <luci/IR/CircleNodes.h>
+
+namespace luci
+{
+
+bool is_same_shape(const luci::CircleNode *node, const loco::TensorShape &shape);
+bool is_same_shape(const luci::CircleNode *node, const std::initializer_list<uint32_t> shape);
+
+bool has_dynamic_shape(const loco::Node *node);
+
+} // namespace luci
+
+#endif // __LUCI_PASS_HELPERS_SHAPE_H__
index 72b7d60..c15df2a 100644 (file)
@@ -38,7 +38,9 @@ uint64_t GetFlattenedIndex(const std::vector<int> &indices, const std::vector<in
   int sub_elements = 1;
   for (int i = shape.size() - 1; i >= 0; i--)
   {
-    index += indices[i] * sub_elements;
+    assert(indices[i] >= 0);
+    assert(sub_elements >= 0);
+    index += static_cast<uint64_t>(indices[i]) * static_cast<uint64_t>(sub_elements);
     sub_elements *= shape[i];
   }
   return index;
index 2628726..cb7f8a1 100644 (file)
@@ -46,6 +46,8 @@ std::string to_lower_case(std::string s)
 
 loco::DataType str_to_dtype(const std::string &str)
 {
+  if (to_lower_case(str).compare("uint4") == 0)
+    return loco::DataType::U4;
   if (to_lower_case(str).compare("uint8") == 0)
     return loco::DataType::U8;
   if (to_lower_case(str).compare("uint16") == 0)
@@ -55,6 +57,8 @@ loco::DataType str_to_dtype(const std::string &str)
   if (to_lower_case(str).compare("uint64") == 0)
     return loco::DataType::U64;
 
+  if (to_lower_case(str).compare("int4") == 0)
+    return loco::DataType::S4;
   if (to_lower_case(str).compare("int8") == 0)
     return loco::DataType::S8;
   if (to_lower_case(str).compare("int16") == 0)
index 6d854ad..a8423aa 100644 (file)
 
 TEST(StringsTest, str_to_dtype)
 {
+  ASSERT_EQ(loco::DataType::U4, luci::str_to_dtype("uint4"));
   ASSERT_EQ(loco::DataType::U8, luci::str_to_dtype("uint8"));
   ASSERT_EQ(loco::DataType::U16, luci::str_to_dtype("uint16"));
   ASSERT_EQ(loco::DataType::U32, luci::str_to_dtype("uint32"));
   ASSERT_EQ(loco::DataType::U64, luci::str_to_dtype("uint64"));
 
+  ASSERT_EQ(loco::DataType::S4, luci::str_to_dtype("int4"));
   ASSERT_EQ(loco::DataType::S8, luci::str_to_dtype("int8"));
   ASSERT_EQ(loco::DataType::S16, luci::str_to_dtype("int16"));
   ASSERT_EQ(loco::DataType::S32, luci::str_to_dtype("int32"));
index a71d448..7fd58df 100644 (file)
@@ -4,7 +4,7 @@ require("loco")
 require("locop")
 require("logo")
 require("logo-core")
-require("mio-circle06")
+require("mio-circle08")
 require("luci-compute")
 require("oops")
 require("hermes")
index 92c5fb0..e8c7266 100644 (file)
@@ -119,6 +119,7 @@ public:
   // loco::TensorShape visit(const luci::CircleReduceMin *node) final;
   // loco::TensorShape visit(const luci::CircleReduceProd *node) final;
   // loco::TensorShape visit(const luci::CircleRelu *node) final;
+  // loco::TensorShape visit(const luci::CircleRelu0To1 *node) final;
   // loco::TensorShape visit(const luci::CircleRelu6 *node) final;
   // loco::TensorShape visit(const luci::CircleReluN1To1 *node) final;
   // loco::TensorShape visit(const luci::CircleReshape *node) final;
index 4f4ab0f..e725722 100644 (file)
@@ -118,6 +118,7 @@ public:
   // loco::DataType visit(const luci::CircleReduceMin *node) final;
   // loco::DataType visit(const luci::CircleReduceProd *node) final;
   // loco::DataType visit(const luci::CircleRelu *node) final;
+  // loco::DataType visit(const luci::CircleRelu0To1 *node) final;
   // loco::DataType visit(const luci::CircleRelu6 *node) final;
   // loco::DataType visit(const luci::CircleReluN1To1 *node) final;
   // loco::DataType visit(const luci::CircleReshape *node) final;
index 1f80000..6517553 100644 (file)
@@ -72,7 +72,7 @@ void change_outputs(loco::Graph *graph, const std::vector<std::string> &new_outp
     auto output = luci::output_node(graph, out); // output is CircleOutput
     assert(output != nullptr);
 
-    auto node_name = new_outputs.at(out);
+    auto &node_name = new_outputs.at(out);
     auto node = named_nodes[node_name];
     assert(node != nullptr);
 
index e0b4dbc..e2f61e1 100644 (file)
@@ -52,12 +52,14 @@ public:
   luci::CircleNode *visit(const luci::CircleAveragePool2D *) final;
   luci::CircleNode *visit(const luci::CircleBatchMatMul *) final;
   luci::CircleNode *visit(const luci::CircleBatchToSpaceND *) final;
+  luci::CircleNode *visit(const luci::CircleBroadcastTo *) final;
   luci::CircleNode *visit(const luci::CircleCast *) final;
   luci::CircleNode *visit(const luci::CircleCeil *) final;
   luci::CircleNode *visit(const luci::CircleConcatenation *) final;
   luci::CircleNode *visit(const luci::CircleConst *) final;
   luci::CircleNode *visit(const luci::CircleConv2D *) final;
   luci::CircleNode *visit(const luci::CircleCos *) final;
+  luci::CircleNode *visit(const luci::CircleCumSum *) final;
   luci::CircleNode *visit(const luci::CircleCustom *) final;
 
   luci::CircleNode *visit(const luci::CircleNode *) final { return nullptr; }
@@ -171,6 +173,7 @@ public:
   luci::CircleNode *visit(const luci::CircleReduceMin *) final;
   luci::CircleNode *visit(const luci::CircleReduceProd *) final;
   luci::CircleNode *visit(const luci::CircleRelu *) final;
+  luci::CircleNode *visit(const luci::CircleRelu0To1 *) final;
   luci::CircleNode *visit(const luci::CircleRelu6 *) final;
   luci::CircleNode *visit(const luci::CircleReluN1To1 *) final;
   luci::CircleNode *visit(const luci::CircleReshape *) final;
@@ -255,6 +258,7 @@ public:
   luci::CircleNode *visit(const luci::CircleBCQFullyConnected *) final;
   luci::CircleNode *visit(const luci::CircleBCQGather *) final;
   luci::CircleNode *visit(const luci::CircleInstanceNorm *) final;
+  luci::CircleNode *visit(const luci::CircleGRU *) final;
 
   // NOTE CircleInput and CircleOutput are not handled here as these need
   //      link with graph I/O
index d56886c..e8febc5 100644 (file)
@@ -492,6 +492,36 @@ loco::NodeShape infer_batchmatmul_shape(const loco::TensorShape &x_shape,
   return loco::NodeShape{output_shape};
 }
 
+loco::NodeShape infer_broadcast_to(const luci::CircleBroadcastTo *node)
+{
+  const loco::DataType S32 = loco::DataType::S32;
+
+  loco::TensorShape shape_by_input;
+  {
+    LUCI_ASSERT(node->shape(), "2nd input shape() should not be nullptr");
+
+    // Only support node's shape() is CircleConst with S32
+    auto const_shape_node = dynamic_cast<luci::CircleConst *>(node->shape());
+    if (const_shape_node != nullptr)
+    {
+      LUCI_ASSERT(const_shape_node->dtype() == S32, "Only support int32 CircleConst");
+
+      shape_by_input.rank(const_shape_node->size<S32>());
+      for (uint32_t axis = 0; axis < shape_by_input.rank(); ++axis)
+      {
+        shape_by_input.dim(axis) = const_shape_node->at<S32>(axis);
+      }
+    }
+    else
+    {
+      // We use shape from the node itself
+      shape_by_input = own_shape(node);
+    }
+  }
+
+  return loco::NodeShape{shape_by_input};
+}
+
 loco::NodeShape infer_concatenation(const luci::CircleConcatenation *node)
 {
   // TODO Support when CircleConcatenation has 0 input
@@ -514,6 +544,8 @@ loco::NodeShape infer_concatenation(const luci::CircleConcatenation *node)
   for (uint32_t i = 1; i < node->numValues(); ++i)
   {
     auto input_shape = luci::shape_get(node->values(i)).as<loco::TensorShape>();
+    if (input_shape.rank() != output_shape.rank())
+      INTERNAL_EXN_V("Input has incompatible shape", node->name());
 
     for (uint32_t j = 0; j < output_shape.rank(); ++j)
     {
@@ -1575,7 +1607,9 @@ loco::NodeShape infer_transpose(const luci::CircleTranspose *node)
 loco::NodeShape infer_transpose_conv(const luci::CircleTransposeConv *node)
 {
   // TransposeConv's output shape is written in its 'inputSizes' argument
-  auto input_sizes_const = loco::must_cast<luci::CircleConst *>(node->inputSizes());
+  auto input_sizes_const = dynamic_cast<luci::CircleConst *>(node->inputSizes());
+  if (not input_sizes_const)
+    return use_own(node);
   // TODO support non-const type
   LUCI_ASSERT(input_sizes_const->dtype() == loco::DataType::S32, "Only support S32 dtype")
   LUCI_ASSERT(input_sizes_const->rank() == 1 && input_sizes_const->dim(0).value() == 4,
@@ -1710,6 +1744,28 @@ loco::NodeShape infer_bcq_gather(const luci::CircleBCQGather *node)
   return loco::NodeShape{output_shape};
 }
 
+loco::NodeShape infer_circle_gru(const luci::CircleGRU *node)
+{
+  loco::TensorShape output_shape;
+
+  const auto input_shape = luci::shape_get(node->input()).as<loco::TensorShape>();
+  const auto state_shape = luci::shape_get(node->state()).as<loco::TensorShape>();
+
+  auto rank = input_shape.rank();
+  assert(rank > 1);
+  output_shape.rank(rank);
+  for (uint32_t i = 0; i < rank - 1; i++)
+  {
+    output_shape.dim(i) = input_shape.dim(i);
+  }
+  output_shape.dim(rank - 1) = state_shape.dim(1);
+
+  if (not node->returnSequences())
+    output_shape.dim(0) = 1;
+
+  return loco::NodeShape{output_shape};
+}
+
 // Virtual
 loco::NodeShape infer_input(const luci::CircleInput *node)
 {
@@ -1966,7 +2022,7 @@ loco::NodeShape infer_while_out(const luci::CircleWhileOut *node)
   auto cond_graph_inputs = cond_graph->inputs();
   auto cond_graph_input = cond_graph_inputs->at(cond_in->index());
 
-  auto cond_graph_input_shape = *cond_graph_input->shape();
+  const auto &cond_graph_input_shape = *cond_graph_input->shape();
   auto this_shape = own_shape(node);
 
   if (!(this_shape == cond_graph_input_shape))
@@ -2015,6 +2071,11 @@ public:
     return infer_batch_to_space_nd(node);
   }
 
+  loco::NodeShape visit(const luci::CircleBroadcastTo *node) final
+  {
+    return infer_broadcast_to(node);
+  }
+
   loco::NodeShape visit(const luci::CircleCast *node) final { return use_x(node); }
 
   loco::NodeShape visit(const luci::CircleCeil *node) final { return use_x(node); }
@@ -2030,6 +2091,8 @@ public:
 
   loco::NodeShape visit(const luci::CircleCos *node) final { return use_x(node); }
 
+  loco::NodeShape visit(const luci::CircleCumSum *node) final { return use_input(node); }
+
   loco::NodeShape visit(const luci::CircleCustom *node) final { return use_own(node); }
 
   loco::NodeShape visit(const luci::CircleDensify *node) final { return use_input(node); }
@@ -2252,6 +2315,13 @@ public:
     return loco::NodeShape{input_shape};
   }
 
+  loco::NodeShape visit(const luci::CircleRelu0To1 *node) final
+  {
+    auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>();
+
+    return loco::NodeShape{input_shape};
+  }
+
   loco::NodeShape visit(const luci::CircleRelu6 *node) final
   {
     auto input_shape = luci::shape_get(node->features()).as<loco::TensorShape>();
@@ -2439,6 +2509,8 @@ public:
     return loco::NodeShape{input_shape};
   }
 
+  loco::NodeShape visit(const luci::CircleGRU *node) final { return infer_circle_gru(node); }
+
   // Virtual
   loco::NodeShape visit(const luci::CircleInput *node) final { return infer_input(node); }
 
index bd3feb9..78dde10 100644 (file)
@@ -69,6 +69,11 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
     return luci::dtype_get(node->input());
   }
 
+  loco::DataType visit(const luci::CircleBroadcastTo *node) final
+  {
+    return luci::dtype_get(node->input());
+  }
+
   loco::DataType visit(const luci::CircleCast *node) final { return node->dtype(); }
 
   loco::DataType visit(const luci::CircleCeil *node) final { return luci::dtype_get(node->x()); }
@@ -93,6 +98,11 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
 
   loco::DataType visit(const luci::CircleCos *node) final { return luci::dtype_get(node->x()); }
 
+  loco::DataType visit(const luci::CircleCumSum *node) final
+  {
+    return luci::dtype_get(node->input());
+  }
+
   loco::DataType visit(const luci::CircleCustom *node) final
   {
     if (node->custom_code() == "BatchMatMulV2")
@@ -186,6 +196,8 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
     return luci::dtype_get(node->features());
   }
 
+  loco::DataType visit(const luci::CircleGRU *node) final { return luci::dtype_get(node->input()); }
+
   loco::DataType visit(const luci::CircleIf *node) final
   {
     // Type of If is not used. Just use input 0
@@ -370,6 +382,11 @@ struct TypeInferenceAlgorithm final : public luci::CircleNodeVisitor<loco::DataT
     return luci::dtype_get(node->features());
   }
 
+  loco::DataType visit(const luci::CircleRelu0To1 *node) final
+  {
+    return luci::dtype_get(node->features());
+  }
+
   loco::DataType visit(const luci::CircleRelu6 *node) final
   {
     return luci::dtype_get(node->features());
diff --git a/compiler/luci/service/src/Nodes/CircleBroadcastTo.cpp b/compiler/luci/service/src/Nodes/CircleBroadcastTo.cpp
new file mode 100644 (file)
index 0000000..ca07025
--- /dev/null
@@ -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::ABC>::visit(const luci::CircleBroadcastTo *)
+{
+  return _graph->nodes()->create<luci::CircleBroadcastTo>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleBroadcastTo.test.cpp b/compiler/luci/service/src/Nodes/CircleBroadcastTo.test.cpp
new file mode 100644 (file)
index 0000000..07ff7de
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_BroadcastTo)
+{
+  auto g = loco::make_graph();
+  auto node_broadcastTo = g->nodes()->create<luci::CircleBroadcastTo>();
+
+  auto gc = loco::make_graph();
+  auto cloned = luci::clone_node(node_broadcastTo, gc.get());
+  ASSERT_NE(nullptr, cloned);
+  ASSERT_EQ(gc.get(), cloned->graph());
+
+  auto cloned_broadcastTo = dynamic_cast<luci::CircleBroadcastTo *>(cloned);
+  ASSERT_NE(nullptr, cloned_broadcastTo);
+}
index 017dcc8..c8f43c4 100644 (file)
@@ -59,10 +59,18 @@ luci::CircleConst *clone_circleconst(const luci::CircleConst *node, loco::Graph
         copy_values<loco::DataType::FLOAT32>(node, cloned);
         break;
 
+      case loco::DataType::U4:
+        copy_values<loco::DataType::U4>(node, cloned);
+        break;
+
       case loco::DataType::U8:
         copy_values<loco::DataType::U8>(node, cloned);
         break;
 
+      case loco::DataType::S4:
+        copy_values<loco::DataType::S4>(node, cloned);
+        break;
+
       case loco::DataType::S8:
         copy_values<loco::DataType::S8>(node, cloned);
         break;
index 5d94798..3d9acd9 100644 (file)
@@ -98,6 +98,20 @@ TEST(CircleConstTest, clone)
   ASSERT_NE(nullptr, const_cloned->sparsityparam());
 }
 
+TEST(CircleConstTest, clone_U4)
+{
+  auto g = loco::make_graph();
+
+  // prepare source CircleConst
+  auto circle_const = new_empty_const<loco::DataType::U4>(g.get());
+
+  // make a clone
+  auto const_cloned = luci::clone(circle_const);
+
+  // check attributes
+  ASSERT_EQ(loco::DataType::U4, const_cloned->dtype());
+}
+
 TEST(CircleConstTest, clone_U8)
 {
   auto g = loco::make_graph();
@@ -112,6 +126,20 @@ TEST(CircleConstTest, clone_U8)
   ASSERT_EQ(loco::DataType::U8, const_cloned->dtype());
 }
 
+TEST(CircleConstTest, clone_S4)
+{
+  auto g = loco::make_graph();
+
+  // prepare source CircleConst
+  auto circle_const = new_empty_const<loco::DataType::S4>(g.get());
+
+  // make a clone
+  auto const_cloned = luci::clone(circle_const);
+
+  // check attributes
+  ASSERT_EQ(loco::DataType::S4, const_cloned->dtype());
+}
+
 TEST(CircleConstTest, clone_S8)
 {
   auto g = loco::make_graph();
diff --git a/compiler/luci/service/src/Nodes/CircleCumSum.cpp b/compiler/luci/service/src/Nodes/CircleCumSum.cpp
new file mode 100644 (file)
index 0000000..5f8e6f0
--- /dev/null
@@ -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.
+ */
+
+#include "CircleCloneNode.h"
+
+namespace luci
+{
+
+luci::CircleNode *CloneNodeLet<CN::ABC>::visit(const luci::CircleCumSum *node)
+{
+  auto cloned = _graph->nodes()->create<luci::CircleCumSum>();
+  assert(cloned);
+  cloned->exclusive(node->exclusive());
+  cloned->reverse(node->reverse());
+  return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleCumSum.test.cpp b/compiler/luci/service/src/Nodes/CircleCumSum.test.cpp
new file mode 100644 (file)
index 0000000..66601e8
--- /dev/null
@@ -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.
+ */
+
+#include "luci/Service/CircleNodeClone.h"
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_CumSum)
+{
+  auto g = loco::make_graph();
+  auto node_cumsum = g->nodes()->create<luci::CircleCumSum>();
+  node_cumsum->exclusive(false);
+  node_cumsum->reverse(false);
+
+  auto gc = loco::make_graph();
+  auto cloned = luci::clone_node(node_cumsum, gc.get());
+  ASSERT_NE(nullptr, cloned);
+  ASSERT_EQ(gc.get(), cloned->graph());
+
+  auto cloned_cumsum = dynamic_cast<luci::CircleCumSum *>(cloned);
+  ASSERT_NE(nullptr, cloned_cumsum);
+  ASSERT_EQ(node_cumsum->exclusive(), cloned_cumsum->exclusive());
+  ASSERT_EQ(node_cumsum->reverse(), cloned_cumsum->reverse());
+}
diff --git a/compiler/luci/service/src/Nodes/CircleGRU.cpp b/compiler/luci/service/src/Nodes/CircleGRU.cpp
new file mode 100644 (file)
index 0000000..f39e4aa
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 *CloneNode::visit(const luci::CircleGRU *node)
+{
+  if (node->fusedActivationFunction() == luci::FusedActFunc::UNDEFINED)
+    return nullptr;
+
+  auto *cloned = _graph->nodes()->create<luci::CircleGRU>();
+  if (cloned != nullptr)
+  {
+    cloned->fusedActivationFunction(node->fusedActivationFunction());
+    cloned->returnSequences(node->returnSequences());
+    cloned->timeMajor(node->timeMajor());
+  }
+  return cloned;
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleGRU.test.cpp b/compiler/luci/service/src/Nodes/CircleGRU.test.cpp
new file mode 100644 (file)
index 0000000..ae684d9
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_circle_gru)
+{
+  luci::CircleInput input;
+  luci::CircleConst hidden_hidden;
+  luci::CircleConst hidden_hidden_bias;
+  luci::CircleConst hidden_input;
+  luci::CircleConst hidden_input_bias;
+  luci::CircleConst state;
+  luci::CircleGRU circle_gru;
+
+  input.shape({10, 1, 4});
+  input.shape_status(luci::ShapeStatus::VALID);
+
+  hidden_hidden.shape({7, 32});
+  hidden_hidden.shape_status(luci::ShapeStatus::VALID);
+
+  hidden_hidden_bias.shape({7});
+  hidden_hidden_bias.shape_status(luci::ShapeStatus::VALID);
+
+  hidden_input.shape({7, 4});
+  hidden_input.shape_status(luci::ShapeStatus::VALID);
+
+  hidden_input_bias.shape({7});
+  hidden_input_bias.shape_status(luci::ShapeStatus::VALID);
+
+  state.shape({1, 32});
+  state.shape_status(luci::ShapeStatus::VALID);
+
+  circle_gru.input(&input);
+  circle_gru.hidden_hidden(&hidden_hidden);
+  circle_gru.hidden_hidden_bias(&hidden_hidden_bias);
+  circle_gru.hidden_input(&hidden_input);
+  circle_gru.hidden_input_bias(&hidden_input_bias);
+  circle_gru.state(&state);
+
+  loco::TensorShape shape;
+  luci::sinf::Rule shape_inf_rule;
+
+  ASSERT_TRUE(shape_inf_rule.infer(&circle_gru, shape));
+  ASSERT_EQ(3, shape.rank());
+  ASSERT_EQ(1, shape.dim(0).value());
+  ASSERT_EQ(1, shape.dim(1).value());
+  ASSERT_EQ(32, shape.dim(2).value());
+}
+
+TEST(DataTypeRuleTest, simple_circle_gru)
+{
+  luci::CircleInput input;
+  luci::CircleConst hidden_hidden;
+  luci::CircleConst hidden_hidden_bias;
+  luci::CircleConst hidden_input;
+  luci::CircleConst hidden_input_bias;
+  luci::CircleConst state;
+  luci::CircleGRU circle_gru;
+
+  input.dtype(loco::DataType::FLOAT32);
+  hidden_hidden.dtype(loco::DataType::FLOAT32);
+  hidden_hidden_bias.dtype(loco::DataType::FLOAT32);
+  hidden_input.dtype(loco::DataType::FLOAT32);
+  hidden_input_bias.dtype(loco::DataType::FLOAT32);
+  state.dtype(loco::DataType::FLOAT32);
+
+  circle_gru.input(&input);
+  circle_gru.hidden_hidden(&hidden_hidden);
+  circle_gru.hidden_hidden_bias(&hidden_hidden_bias);
+  circle_gru.hidden_input(&hidden_input);
+  circle_gru.hidden_input_bias(&hidden_input_bias);
+  circle_gru.state(&state);
+
+  loco::DataType dtype;
+  luci::tinf::Rule type_inf_rule;
+
+  ASSERT_TRUE(type_inf_rule.infer(&circle_gru, dtype));
+  ASSERT_EQ(loco::DataType::FLOAT32, dtype);
+}
+
+TEST(CloneNodeTest, clone_circel_gru)
+{
+  auto g = loco::make_graph();
+  auto node_circle_gru = g->nodes()->create<luci::CircleGRU>();
+  node_circle_gru->fusedActivationFunction(luci::FusedActFunc::NONE);
+
+  auto gc = loco::make_graph();
+  auto cloned = luci::clone_node(node_circle_gru, gc.get());
+  ASSERT_NE(nullptr, cloned);
+  ASSERT_EQ(gc.get(), cloned->graph());
+
+  auto cloned_circle_gru = dynamic_cast<luci::CircleGRU *>(cloned);
+  ASSERT_NE(nullptr, cloned_circle_gru);
+}
diff --git a/compiler/luci/service/src/Nodes/CircleRelu0To1.cpp b/compiler/luci/service/src/Nodes/CircleRelu0To1.cpp
new file mode 100644 (file)
index 0000000..bdc3201
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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::OPQR>::visit(const luci::CircleRelu0To1 *)
+{
+  return _graph->nodes()->create<luci::CircleRelu0To1>();
+}
+
+} // namespace luci
diff --git a/compiler/luci/service/src/Nodes/CircleRelu0To1.test.cpp b/compiler/luci/service/src/Nodes/CircleRelu0To1.test.cpp
new file mode 100644 (file)
index 0000000..9bda584
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <loco/IR/TensorShape.h>
+
+#include <gtest/gtest.h>
+
+TEST(CloneNodeTest, clone_Relu0To1)
+{
+  auto g = loco::make_graph();
+  auto node_relu6 = g->nodes()->create<luci::CircleRelu0To1>();
+
+  auto gc = loco::make_graph();
+  auto cloned = luci::clone_node(node_relu6, gc.get());
+  ASSERT_NE(nullptr, cloned);
+  ASSERT_EQ(gc.get(), cloned->graph());
+
+  auto cloned_relu0to1 = dynamic_cast<luci::CircleRelu0To1 *>(cloned);
+  ASSERT_NE(nullptr, cloned_relu0to1);
+}
index bdd2773..5a22da3 100644 (file)
@@ -124,7 +124,7 @@ inline int64_t StartForAxis(const StridedSliceParams &params, const loco::Tensor
   int64_t start = start_indices[axis];
 
   // begin_mask override
-  if (begin_mask & (1 << axis))
+  if (begin_mask & (1LL << axis))
   {
     if (strides[axis] > 0)
     {
@@ -180,7 +180,7 @@ inline int64_t StopForAxis(const StridedSliceParams &params, const loco::TensorS
   }
 
   // Begin with the specified index
-  const bool shrink_axis = shrink_axis_mask & (1 << axis);
+  const bool shrink_axis = shrink_axis_mask & (1LL << axis);
   int64_t stop = stop_indices[axis];
 
   // When shrinking an axis, the end position does not matter (and can be
@@ -193,7 +193,7 @@ inline int64_t StopForAxis(const StridedSliceParams &params, const loco::TensorS
   }
 
   // end_mask override
-  if (end_mask & (1 << axis))
+  if (end_mask & (1LL << axis))
   {
     if (strides[axis] > 0)
     {
@@ -249,8 +249,8 @@ StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
   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))
+    if (!((1LL << i) & op_context->params.ellipsis_mask) &&
+        ((1LL << i) & op_context->params.new_axis_mask))
     {
       num_add_axis++;
     }
@@ -268,7 +268,7 @@ StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
   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)
+    if ((1LL << i) & op_context->params.ellipsis_mask)
     {
       ellipsis_start_idx = i;
       int64_t ellipsis_end_idx =
@@ -279,14 +279,14 @@ StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
       // Set bit for effective_ellipsis_mask.
       for (; i < ellipsis_end_idx; ++i)
       {
-        effective_ellipsis_mask |= (1 << i);
+        effective_ellipsis_mask |= (1LL << i);
       }
       continue;
     }
 
-    if ((1 << (i - expanded_ellipsis)) & op_context->params.new_axis_mask)
+    if ((1LL << (i - expanded_ellipsis)) & op_context->params.new_axis_mask)
     {
-      effective_new_axis_mask |= (1 << i);
+      effective_new_axis_mask |= (1LL << i);
     }
     ++i;
   }
@@ -298,17 +298,17 @@ StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
 
   for (int64_t i = 0; i < effective_dims; ++i)
   {
-    if ((1 << i) & effective_ellipsis_mask)
+    if ((1LL << i) & effective_ellipsis_mask)
     {
       // If ellipsis_mask, set the begin_mask and end_mask at that index.
       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.begin_mask |= (1LL << i);
+      op_params.end_mask |= (1LL << i);
       op_params.strides[i] = 1;
       op_context->effective_input_shape.dim(i) = input_shape.dim(i - added_axises);
     }
-    else if ((1 << i) & effective_new_axis_mask)
+    else if ((1LL << i) & effective_new_axis_mask)
     {
       // If new_axis_mask is set, it is equivalent to adding a new dim of 1 to
       // input tensor. Store added shape to effective_input_shape.
@@ -324,8 +324,8 @@ StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
       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_params.begin_mask |= (1LL << i);
+      op_params.end_mask |= (1LL << i);
       op_context->effective_input_shape.dim(i) = input_shape.dim(i - added_axises);
     }
     else
@@ -334,20 +334,20 @@ StridedSliceParams BuildStridedSliceParams(StridedSliceContext *op_context)
       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))
+      if (op_context->params.begin_mask & (1LL << orig_idx))
       {
         assert(i < 16);
-        op_params.begin_mask |= (1 << i);
+        op_params.begin_mask |= (1LL << i);
       }
-      if (op_context->params.end_mask & (1 << orig_idx))
+      if (op_context->params.end_mask & (1LL << orig_idx))
       {
         assert(i < 16);
-        op_params.end_mask |= (1 << i);
+        op_params.end_mask |= (1LL << i);
       }
-      if (op_context->params.shrink_axis_mask & (1 << orig_idx))
+      if (op_context->params.shrink_axis_mask & (1LL << orig_idx))
       {
         assert(i < 16);
-        op_params.shrink_axis_mask |= (1 << i);
+        op_params.shrink_axis_mask |= (1LL << i);
       }
       op_context->effective_input_shape.dim(i) = input_shape.dim(i - added_axises);
     }
@@ -398,7 +398,7 @@ 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;
+  auto &effective_input_shape = op_context.effective_input_shape;
   std::vector<int64_t> output_shape_vector;
 
   for (int32_t idx = effective_input_shape.rank() - 1; idx >= 0; --idx)
index a88661d..a9ded24 100644 (file)
@@ -27,6 +27,7 @@ addread(BatchMatMul_000)
 addread(BatchMatMulV2_000)
 addread(BatchMatMulV2_001)
 addread(BatchToSpaceND_000)
+addread(BroadcastTo_001)
 addread(Cast_000)
 addread(Cast_001)
 addread(Ceil_000)
@@ -39,6 +40,7 @@ addread(Conv2D_003)
 addread(Conv2D_U8_000)
 addread(Conv2D_U8_001)
 addread(Cos_000)
+addread(CumSum_000)
 addread(Densify_000)
 addread(DepthToSpace_000)
 addread(DepthwiseConv2D_000)
@@ -134,6 +136,7 @@ addread(ReduceProd_001)
 addread(ReduceProd_002)
 addread(ReduceProd_003)
 addread(ReLU_000)
+addread(ReLU0To1_000)
 addread(ReLU6_000)
 addread(ReLUN1To1_000)
 addread(Reshape_000)
@@ -257,6 +260,7 @@ addwrite(BatchMatMul_000)
 addwrite(BatchMatMulV2_000)
 addwrite(BatchMatMulV2_001)
 addwrite(BatchToSpaceND_000)
+addwrite(BroadcastTo_001)
 addwrite(Cast_000)
 addwrite(Cast_001)
 addwrite(Ceil_000)
@@ -269,6 +273,7 @@ addwrite(Conv2D_003)
 addwrite(Conv2D_U8_000)
 addwrite(Conv2D_U8_001)
 addwrite(Cos_000)
+addwrite(CumSum_000)
 addwrite(Densify_000)
 addwrite(DepthToSpace_000)
 addwrite(DepthwiseConv2D_000)
@@ -363,6 +368,7 @@ addwrite(ReduceProd_001)
 addwrite(ReduceProd_002)
 addwrite(ReduceProd_003)
 addwrite(ReLU_000)
+addwrite(ReLU0To1_000)
 addwrite(ReLU6_000)
 addwrite(ReLUN1To1_000)
 addwrite(Reshape_000)
diff --git a/compiler/minmax-embedder-value-test/CMakeLists.txt b/compiler/minmax-embedder-value-test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f97034f
--- /dev/null
@@ -0,0 +1,53 @@
+if(NOT ENABLE_TEST)
+    return()
+endif(NOT ENABLE_TEST)
+
+# Disable test if minmax-embedder does not exist
+if (NOT TARGET minmax_embedder)
+    message(STATUS "minmax-embedder-test is disabled as minmax-embedder was not built.")
+    return()
+endif(NOT TARGET minmax_embedder)
+
+add_subdirectory(gen)
+
+# Add tests
+unset(MINMAX_EMBEDDER_VALUE_TESTS)
+
+macro(addTest NAME)
+  list(APPEND MINMAX_EMBEDDER_VALUE_TESTS ${NAME})
+endmacro(addTest)
+
+include("test.lst")
+include("test.local.lst" OPTIONAL)
+
+unset(TEST_DEPS)
+
+# Generate test.config
+set(TEST_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/test.config")
+
+add_custom_command(
+  OUTPUT ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E remove -f ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'ARTIFACTS_PATH=\"$<TARGET_FILE_DIR:testDataGenerator>\"' >> ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'MINMAX_DATA_GEN=\"$<TARGET_FILE:minmax_data_gen>\"' >> ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'MINMAX_EMBEDDER=\"$<TARGET_FILE:minmax_embedder_driver>\"' >> ${TEST_CONFIG}
+  COMMAND ${CMAKE_COMMAND} -E echo 'CIRCLEDUMP=\"$<TARGET_FILE:circledump>\"' >> ${TEST_CONFIG}
+  DEPENDS testDataGenerator
+  DEPENDS minmax_data_gen
+  DEPENDS minmax_embedder_driver
+  DEPENDS circledump
+  COMMENT "Generate test configuration"
+)
+
+list(APPEND TEST_DEPS "${TEST_CONFIG}")
+
+# This enforces CMake to generate all the dependencies during "build" phase
+add_custom_target(minmax_embedder_value_test_deps ALL DEPENDS ${TEST_DEPS})
+
+# Run tests
+add_test(
+  NAME minmax_embedder_value_test
+        COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/testall.sh"
+        "${TEST_CONFIG}"
+        ${MINMAX_EMBEDDER_VALUE_TESTS}
+)
diff --git a/compiler/minmax-embedder-value-test/README.md b/compiler/minmax-embedder-value-test/README.md
new file mode 100644 (file)
index 0000000..dcf5b1c
--- /dev/null
@@ -0,0 +1,30 @@
+## minmax-embedder-value-test
+
+minmax-embedder-value-test aims to test minmax-embedder tool.
+
+It generates minmax data (encoded min and max from run idx, op/input index).
+
+Then, it checks whether it is correctly embedded into circle.
+
+minmax-embedder is supposed to be executed in a device.
+
+Thus, test is also implemented so that it can be run on a device (especially
+on Tizen device. For example, It does not use Python.
+
+### minmax-data-gen
+
+`minmax-data-gen` generates minmax-data for test.
+
+#### Usage
+
+```
+Usage: ./minmax-data-gen [-h] [--num_inputs NUM_INPUTS] [--num_ops NUM_OPS] minmax
+
+[Positional argument]
+minmax         path to generated minmax data
+
+[Optional argument]
+-h, --help     Show help message and exit
+--num_inputs   number of input layers (default:1)
+--num_ops      number of operators (default:1)
+```
diff --git a/compiler/minmax-embedder-value-test/gen/CMakeLists.txt b/compiler/minmax-embedder-value-test/gen/CMakeLists.txt
new file mode 100644 (file)
index 0000000..79e70a5
--- /dev/null
@@ -0,0 +1,16 @@
+# Build minmax-data-gen
+nnas_find_package(HDF5 COMPONENTS STATIC QUIET)
+
+if(NOT HDF5_FOUND)
+  message(STATUS "Build minmax-datagen: FAILED (missing HDF5)")
+  return()
+endif(NOT HDF5_FOUND)
+
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+
+add_executable(minmax_data_gen "${SOURCES}")
+target_include_directories(minmax_data_gen PUBLIC ${HDF5_INCLUDE_DIRS})
+
+target_link_libraries(minmax_data_gen ${HDF5_CXX_LIBRARIES})
+target_link_libraries(minmax_data_gen safemain)
+target_link_libraries(minmax_data_gen arser)
diff --git a/compiler/minmax-embedder-value-test/gen/src/Cast.h b/compiler/minmax-embedder-value-test/gen/src/Cast.h
new file mode 100644 (file)
index 0000000..8885cc9
--- /dev/null
@@ -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.
+ */
+
+#ifndef __MINMAX_EMBEDDER_TEST_CAST_H__
+#define __MINMAX_EMBEDDER_TEST_CAST_H__
+
+#include <cstdint>
+#include <stdexcept>
+
+namespace minmax_embedder_test
+{
+uint32_t to_u32(uint64_t v)
+{
+  if (v > UINT32_MAX)
+    throw std::overflow_error("to_u32 gets a value bigger than uint32 max.");
+  return static_cast<uint32_t>(v);
+}
+
+} // end of namespace minmax_embedder_test
+
+#endif // __MINMAX_EMBEDDER_TEST_CAST_H__
diff --git a/compiler/minmax-embedder-value-test/gen/src/DataGen.cpp b/compiler/minmax-embedder-value-test/gen/src/DataGen.cpp
new file mode 100644 (file)
index 0000000..c1cef89
--- /dev/null
@@ -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.
+ */
+
+#include "DataGen.h"
+
+namespace minmax_embedder_test
+{
+MinMax DataGen::operator()(uint32_t run, uint32_t obj) const
+{
+  MinMax r;
+  r.min() = (run * 10'000) + (obj * 10);
+  r.max() = (run * 10'000) + (obj * 10) + 7;
+  return r;
+}
+} // namespace minmax_embedder_test
diff --git a/compiler/minmax-embedder-value-test/gen/src/DataGen.h b/compiler/minmax-embedder-value-test/gen/src/DataGen.h
new file mode 100644 (file)
index 0000000..731ae91
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MINMAX_EMBEDDER_TEST_DATA_GEN_H__
+#define __MINMAX_EMBEDDER_TEST_DATA_GEN_H__
+
+#include <cstdint>
+
+namespace minmax_embedder_test
+{
+class MinMax
+{
+public:
+  float &min() { return v[0]; }
+  float &max() { return v[1]; }
+  float *data() { return &v[0]; }
+
+private:
+  float v[2];
+};
+
+/**
+ * generates (min,max) for obj (= model input or op output) index at run
+ */
+class DataGen
+{
+public:
+  MinMax operator()(uint32_t run, uint32_t obj) const;
+};
+} // end of namespace minmax_embedder_test
+
+#endif // __MINMAX_EMBEDDER_TEST_DATA_GEN_H__
diff --git a/compiler/minmax-embedder-value-test/gen/src/Driver.cpp b/compiler/minmax-embedder-value-test/gen/src/Driver.cpp
new file mode 100644 (file)
index 0000000..479a568
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "H5Writer.h"
+
+#include <arser/arser.h>
+
+using namespace minmax_embedder_test;
+
+int entry(const int argc, char **argv)
+{
+  arser::Arser arser("Generate min/max data to test minmax-embedder");
+  arser.add_argument("--num_inputs")
+    .type(arser::DataType::INT32)
+    .default_value(1)
+    .help("number of input layers (default:1)");
+  arser.add_argument("--num_ops")
+    .type(arser::DataType::INT32)
+    .default_value(1)
+    .help("number of operators (default:1)");
+  arser.add_argument("minmax").help("path to generated minmax data");
+
+  try
+  {
+    arser.parse(argc, argv);
+  }
+  catch (const std::runtime_error &err)
+  {
+    std::cout << err.what() << std::endl;
+    std::cout << arser;
+    return 255;
+  }
+
+  auto num_inputs = arser.get<int>("--num_inputs");
+  auto num_ops = arser.get<int>("--num_ops");
+  auto data_output_path = arser.get<std::string>("minmax");
+
+  ModelSpec mspec;
+  {
+    if (num_inputs <= 0 || num_ops <= 0)
+    {
+      std::cout << "num_inputs and num_ops must be positive integers." << std::endl;
+      return 255;
+    }
+    mspec.n_inputs = num_inputs;
+    mspec.n_ops = num_ops;
+  }
+  H5Writer writer(mspec, data_output_path);
+  writer.dump();
+
+  return EXIT_SUCCESS;
+}
diff --git a/compiler/minmax-embedder-value-test/gen/src/H5Writer.cpp b/compiler/minmax-embedder-value-test/gen/src/H5Writer.cpp
new file mode 100644 (file)
index 0000000..bf83ef1
--- /dev/null
@@ -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 "H5Writer.h"
+#include "Cast.h"
+
+#include <algorithm>
+#include <iostream>
+#include <stdexcept>
+#include <H5Cpp.h>
+
+namespace minmax_embedder_test
+{
+/*
+ * ensure grp_name exists in parent
+ */
+H5::Group ensureGroup(H5::Group parent, const std::string &child)
+{
+  H5::Exception::dontPrint();
+  try
+  {
+    return parent.openGroup(child.c_str());
+  }
+  catch (H5::Exception &e)
+  {
+    return parent.createGroup(child.c_str());
+  }
+}
+
+static const char *h5_value_grpname = "value";
+
+H5Writer::H5Writer(const ModelSpec &md_spec, const std::string &filepath)
+  : _md_spec{md_spec}, _filepath{filepath}
+{
+}
+
+void H5Writer::dump()
+{
+  // NOTE: H5Writer
+  H5::H5File h5file{_filepath, H5F_ACC_CREAT | H5F_ACC_RDWR};
+  auto root_grp = h5file.openGroup("/");
+  ensureGroup(root_grp, h5_value_grpname);
+  auto val_grp = h5file.openGroup(h5_value_grpname);
+  // NOTE: Writer
+  uint32_t num_run = to_u32(val_grp.getNumObjs());
+  auto run_grp = val_grp.createGroup(("run_") + std::to_string(num_run));
+  // Assumption: single subgraph
+  auto model_grp = ensureGroup(run_grp, std::string("model_") + "0");
+  hsize_t dims[] = {2};
+  H5::DataSpace dspace(1, dims); // rank=1, dim(0)=2, {min, max}
+  DataGen gen;
+  // dump input minmax
+  for (uint32_t i = 0; i < _md_spec.n_inputs; ++i)
+  {
+    const auto subg_idx = 0;
+    auto subg_grp = ensureGroup(model_grp, std::string("subg_") + std::to_string(subg_idx).c_str());
+    auto input_dset = subg_grp.createDataSet(std::string("input_") + std::to_string(i),
+                                             H5::PredType::IEEE_F32BE, dspace);
+    auto minmax = gen(num_run, i);
+    input_dset.write(gen(num_run, i).data(), H5::PredType::NATIVE_FLOAT);
+  }
+  // dump op minmax
+  for (uint32_t op = 0; op < _md_spec.n_ops; ++op)
+  {
+    const auto subg_idx = 0;
+    auto subg_grp = ensureGroup(model_grp, std::string("subg_") + std::to_string(subg_idx).c_str());
+    auto op_dset = subg_grp.createDataSet(std::string("op_") + std::to_string(op),
+                                          H5::PredType::IEEE_F32BE, dspace);
+    op_dset.write(gen(num_run, op).data(), H5::PredType::NATIVE_FLOAT);
+  }
+}
+} // end of namespace minmax_embedder_test
diff --git a/compiler/minmax-embedder-value-test/gen/src/H5Writer.h b/compiler/minmax-embedder-value-test/gen/src/H5Writer.h
new file mode 100644 (file)
index 0000000..bef679a
--- /dev/null
@@ -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 __MINMAX_EMBEDDER_TEST_H5WRITER_H__
+#define __MINMAX_EMBEDDER_TEST_H5WRITER_H__
+
+#include "ModelSpec.h"
+#include "DataGen.h"
+
+#include <string>
+
+namespace minmax_embedder_test
+{
+// It must be same to onert/core/src/dumper/h5/MinMaxDumper.h
+//
+// GROUP /
+//   GROUP value
+//     â””── GROUP run_{idx}
+//           â””── GROUP model_{idx}
+//                 â””── GROUP subg_{idx}
+//                       â”œâ”€â”€ DATASET op_{idx}
+//                       â”‚      DATATYPE Float32
+//                       â”‚      DATASPACE (2)
+//                       â”‚      DATA { min, max }
+//                       â””── DATASET input_{idx}
+//                              DATATYPE Float32
+//                              DATASPACE (2)
+//                              DATA { min, max }
+class H5Writer
+{
+public:
+  H5Writer(const ModelSpec &md_spec, const std::string &filepath);
+  void dump();
+
+private:
+  ModelSpec _md_spec;
+  std::string _filepath;
+};
+} // namespace minmax_embedder_test
+
+#endif // __MINMAX_EMBEDDER_TEST_H5WRITER_H__
diff --git a/compiler/minmax-embedder-value-test/gen/src/ModelSpec.h b/compiler/minmax-embedder-value-test/gen/src/ModelSpec.h
new file mode 100644 (file)
index 0000000..10cd17a
--- /dev/null
@@ -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 __MINMAX_EMBEDDER_TEST_MODEL_SPEC_H__
+#define __MINMAX_EMBEDDER_TEST_MODEL_SPEC_H__
+
+#include <cstdint>
+
+namespace minmax_embedder_test
+{
+struct ModelSpec
+{
+  /** number of model inputs */
+  uint32_t n_inputs;
+  /** number of operators*/
+  uint32_t n_ops;
+};
+} // end of namespace minmax_embedder_test
+
+#endif // __MINMAX_EMBEDDER_TEST_MODEL_SPEC_H__
diff --git a/compiler/minmax-embedder-value-test/requires.cmake b/compiler/minmax-embedder-value-test/requires.cmake
new file mode 100644 (file)
index 0000000..87c107e
--- /dev/null
@@ -0,0 +1,2 @@
+require("common-artifacts")
+require("minmax-embedder")
diff --git a/compiler/minmax-embedder-value-test/test.lst b/compiler/minmax-embedder-value-test/test.lst
new file mode 100644 (file)
index 0000000..dcdf942
--- /dev/null
@@ -0,0 +1,3 @@
+addTest(Abs_000)             # input: 1, op: 1, output: 1
+addTest(Add_000)             # input: 2, op: 1, output: 1
+addTest(Net_Conv_Relu6_000)  # input: 1, op: 3, output: 1
diff --git a/compiler/minmax-embedder-value-test/testall.sh b/compiler/minmax-embedder-value-test/testall.sh
new file mode 100755 (executable)
index 0000000..80a529f
--- /dev/null
@@ -0,0 +1,161 @@
+#!/bin/bash
+
+# This script tests the parallel behavior of minmax-embedder
+#
+# HOW TO USE
+#
+# ./testall.sh <test.config> <TEST_1> <TEST_2> ...
+#
+# test.config must contains the following variables:
+#  - ARTIFACTS_PATH: path to test models
+#  - MINMAX_DATA_GEN: path to minmax_data_gen
+#  - MINMAX_EMBEDDER: path to minmax_embedder_driver
+#  - CIRCLEDUMP: path to circledump
+
+# <TEST_N> is the name of model under ARTIFACTS_PATH
+
+CONFIG_PATH="$1"; shift; source "${CONFIG_PATH}"
+WORK_DIR=$(dirname "${CONFIG_PATH}") # For temporary and report outputs
+
+echo "-- Found ARTIFACTS_PATH: ${ARTIFACTS_PATH}"
+echo "-- Found MINMAX_DATA_GEN: ${MINMAX_DATA_GEN}"
+echo "-- Found MINMAX_EMBEDDER: ${MINMAX_EMBEDDER}"
+echo "-- Found CIRCLEDUMP: ${CIRCLEDUMP}"
+echo "-- Found CONFIG_PATH: ${CONFIG_PATH}"
+
+TESTED=()
+PASSED=()
+FAILED=()
+
+pushd "${WORK_DIR}"
+for TESTCASE in "$@"; do
+  TESTED+=("${TESTCASE}")
+
+  TESTCASE_FILE="${ARTIFACTS_PATH}/${TESTCASE}"
+
+  PASSED_TAG="${WORK_DIR}/${TESTCASE}.passed"
+  rm -f "${PASSED_TAG}"
+
+  cat > "${WORK_DIR}/${TESTCASE}.log" <(
+    exec 2>&1
+    set -ex
+
+    # Get model input tensor names
+    INPUT_NAMES=( $("${CIRCLEDUMP}" "${TESTCASE_FILE}.circle" | grep -aP '^I T' | grep -oE '[^ ]+$') )
+    if [[ $? -ne 0 ]]; then
+      echo "FAILED TO GET MODEL INPUT TENSOR INDEX"
+      continue
+    fi
+
+    # Get op output tensor names
+    OP_OUT_NAMES=( $("${CIRCLEDUMP}" "${TESTCASE_FILE}.circle" | grep -aP ' O T\(\d+:' | grep -oE '[^ ]+$') )
+    if [[ $? -ne 0 ]]; then
+      echo "FAILED TO GET OP OUTPUT TENSOR INDEX"
+      continue
+    fi
+
+    # Run minmax-embedder-data-gen
+    RUNS=2
+    for (( RUN=1; RUN<=RUNS; RUN++ )); do
+      "${MINMAX_DATA_GEN}" --num_inputs ${#INPUT_NAMES[@]} --num_ops ${#OP_OUT_NAMES[@]} "${TESTCASE}.minmax"
+      if [[ $? -ne 0 ]]; then
+        echo "FAILED TO GENERATE MINMAX DATA"
+        continue
+      fi
+    done
+
+    # Run minmax-embedder
+    "${MINMAX_EMBEDDER}" \
+      --min_percentile 0 --max_percentile 100 \
+      -o "${TESTCASE}.circle+minmax" \
+      "${TESTCASE_FILE}.circle" \
+      "${TESTCASE}.minmax"
+    if [[ $? -ne 0 ]]; then
+      echo "FAILED TO EMBED MINMAX INTO CIRCLE"
+      continue
+    fi
+
+    rm -f "${TESTCASE}.minmax"
+
+    # Read min/max from circle+minmax
+    MD_MIN=()
+    MD_MAX=()
+    for NAME in "${INPUT_NAMES[@]}"; do 
+      MD_MIN+=( $("${CIRCLEDUMP}" "${TESTCASE}.circle+minmax" | grep -aP "^T.*${NAME}$" -A 1 | tail -1 | grep -oP '(?<=min\()[+-]?[\d]+') )
+      if [[ $? -ne 0 ]]; then
+        echo "FAILED TO PARSE MODEL INPUT MIN FROM CIRCLE"
+        continue
+      fi
+      MD_MAX+=( $("${CIRCLEDUMP}" "${TESTCASE}.circle+minmax" | grep -aP "^T.*${NAME}$" -A 1 | tail -1 | grep -oP '(?<=max\()[+-]?[\d]+') )
+      if [[ $? -ne 0 ]]; then
+        echo "FAILED TO PARSE MODEL INPUT MAX FROM CIRCLE"
+        continue
+      fi
+    done
+
+    OP_MIN=()
+    OP_MAX=()
+    for NAME in "${OP_OUT_NAMES[@]}"; do 
+      OP_MIN+=( $("${CIRCLEDUMP}" "${TESTCASE}.circle+minmax" | grep -aP "^T.*${NAME}$" -A 1 | tail -1 | grep -oP '(?<=min\()[+-]?[\d]+') )
+      if [[ $? -ne 0 ]]; then
+        echo "FAILED TO PARSE OP MIN FROM CIRCLE"
+        continue
+      fi
+      OP_MAX+=( $("${CIRCLEDUMP}" "${TESTCASE}.circle+minmax" | grep -aP "^T.*${NAME}$" -A 1 | tail -1 | grep -oP '(?<=max\()[+-]?[\d]+') )
+      if [[ $? -ne 0 ]]; then
+        echo "FAILED TO PARSE OP MAX FROM CIRCLE"
+        continue
+      fi
+    done
+
+    # check model input 
+    for i in "${!MD_MIN[@]}"; do
+      # Be sure it is synced with minmax-embedder-data-gen
+      EXPECTED_MIN=$((i*10))
+      EXPECTED_MAX=$(((RUNS-1)*10000+i*10+7))
+      if [[ "${MD_MIN[i]}" != "$EXPECTED_MIN" ]]; then
+        echo "Min at model input $i does not equal."
+        continue
+      fi
+      if [[ "${MD_MAX[i]}" != "$EXPECTED_MAX" ]]; then
+        echo "Max at model input $i does not equal."
+        continue
+      fi
+    done
+
+    # check op output
+    for i in "${!OP_MIN[@]}"; do
+      # Be sure it is synced with minmax-embedder-data-gen
+      EXPECTED_MIN=$((i*10))
+      EXPECTED_MAX=$(((RUNS-1)*10000+i*10+7))
+      if [[ "${OP_MIN[i]}" != "$EXPECTED_MIN" ]]; then
+        echo "Min at op $i does not equal."
+        continue
+      fi
+      if [[ "${OP_MAX[i]}" != "$EXPECTED_MAX" ]]; then
+        echo "Max at op $i does not equal."
+        continue
+      fi
+    done
+    touch "${PASSED_TAG}"
+  )
+
+  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/minmax-embedder/CMakeLists.txt b/compiler/minmax-embedder/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3fd3bc7
--- /dev/null
@@ -0,0 +1,56 @@
+nnas_find_package(HDF5 COMPONENTS STATIC QUIET)
+
+if(NOT HDF5_FOUND)
+  message(STATUS "Build minmax_embedder: FAILED (missing HDF5)")
+  return()
+endif(NOT HDF5_FOUND)
+
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE DRIVER "driver/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${DRIVER})
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+#
+# Library
+#
+add_library(minmax_embedder "${SOURCES}")
+target_include_directories(minmax_embedder PUBLIC ${HDF5_INCLUDE_DIRS})
+target_include_directories(minmax_embedder PRIVATE include)
+
+target_link_libraries(minmax_embedder ${HDF5_CXX_LIBRARIES})
+target_link_libraries(minmax_embedder loco)
+target_link_libraries(minmax_embedder luci_import)
+target_link_libraries(minmax_embedder luci_service)
+target_link_libraries(minmax_embedder luci_pass)
+target_link_libraries(minmax_embedder luci_export)
+target_link_libraries(minmax_embedder luci_env)
+
+install(TARGETS minmax_embedder DESTINATION lib)
+install(DIRECTORY include/ DESTINATION include
+        FILES_MATCHING PATTERN "*.h")
+#
+# GTest
+#
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(minmax_embedder_test ${TESTS})
+target_include_directories(minmax_embedder_test PRIVATE include)
+target_link_libraries(minmax_embedder_test minmax_embedder)
+
+#
+# Driver
+#
+add_executable(minmax_embedder_driver "${DRIVER}")
+target_link_libraries(minmax_embedder_driver minmax_embedder)
+target_link_libraries(minmax_embedder_driver arser)
+target_link_libraries(minmax_embedder_driver safemain)
+target_link_libraries(minmax_embedder_driver vconone)
+target_include_directories(minmax_embedder_driver PRIVATE include)
+set_target_properties(minmax_embedder_driver PROPERTIES OUTPUT_NAME minmax_embedder)
+
+install(TARGETS minmax_embedder_driver DESTINATION bin)
diff --git a/compiler/minmax-embedder/README.md b/compiler/minmax-embedder/README.md
new file mode 100644 (file)
index 0000000..ddd7878
--- /dev/null
@@ -0,0 +1,19 @@
+# minmax-embedder
+
+_minmax-embedder_ embeds minmax to circle.
+
+### Usage
+```
+Usage: ./minmax_embedder [-h] [--version] [--min_percentile MIN_PERCENTILE] [--max_percentile MAX_PERCENTILE] [-o O] circle minmax
+
+[Positional argument]
+circle                  Path to input circle model
+minmax                  Path to minmax data in hdf5
+
+[Optional argument]
+-h, --help              Show help message and exit
+--version               Show version information and exit
+--min_percentile        Set min percentile (default: 1)
+--max_percentile        Set max percentile (default: 99)
+-o                      Path to output circle model
+```
diff --git a/compiler/minmax-embedder/driver/Driver.cpp b/compiler/minmax-embedder/driver/Driver.cpp
new file mode 100644 (file)
index 0000000..a3e03de
--- /dev/null
@@ -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 "minmax-embedder/Embedder.h"
+
+#include <arser/arser.h>
+#include <vconone/vconone.h>
+
+#include <stdlib.h>
+
+using namespace minmax_embedder;
+
+void print_version(void)
+{
+  std::cout << "minmax-embedder version " << vconone::get_string() << std::endl;
+  std::cout << vconone::get_copyright() << std::endl;
+}
+
+int entry(const int argc, char **argv)
+{
+  arser::Arser arser("minmax-embedder embeds given minmax into circle");
+  arser::Helper::add_version(arser, print_version);
+  // named args
+  arser.add_argument("--min_percentile")
+    .type(arser::DataType::FLOAT)
+    .default_value(1.f)
+    .help("Set min percentile (default: 1)");
+  arser.add_argument("--max_percentile")
+    .type(arser::DataType::FLOAT)
+    .default_value(99.f)
+    .help("Set max percentile (default: 99)");
+  arser.add_argument("-o").default_value("out.circle").help("Path to output circle model");
+  // positional args: minmax(h5), input(circle)
+  arser.add_argument("circle").help("Path to input circle model");
+  arser.add_argument("minmax").help("Path to minmax data in hdf5");
+  try
+  {
+    arser.parse(argc, argv);
+  }
+  catch (const std::runtime_error &err)
+  {
+    std::cout << err.what() << std::endl;
+    std::cout << arser;
+    return EXIT_FAILURE;
+  }
+
+  std::string minmax_path = arser.get<std::string>("minmax");
+  std::string circle_path = arser.get<std::string>("circle");
+  std::string output_path = arser.get<std::string>("-o");
+  float min_percentile = arser.get<float>("--min_percentile");
+  float max_percentile = arser.get<float>("--max_percentile");
+
+  EmbedderOptions opt{min_percentile, max_percentile};
+  try
+  {
+    Embedder().embed(output_path, circle_path, minmax_path, opt);
+  }
+  catch (const std::runtime_error &err)
+  {
+    std::cout << err.what() << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  return EXIT_SUCCESS;
+}
diff --git a/compiler/minmax-embedder/include/minmax-embedder/Embedder.h b/compiler/minmax-embedder/include/minmax-embedder/Embedder.h
new file mode 100644 (file)
index 0000000..316148a
--- /dev/null
@@ -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 __MINMAX_EMBEDDER_EMBEDDER_H__
+#define __MINMAX_EMBEDDER_EMBEDDER_H__
+
+#include <string>
+
+namespace minmax_embedder
+{
+
+struct EmbedderOptions
+{
+  float min_percentile = 0.0f; // dummy initial value to make SE tool happy
+  float max_percentile = 0.0f; // dummy initial value To make SE tool happy
+};
+
+class Embedder
+{
+public:
+  void embed(const std::string &output_path, const std::string &input_path,
+             const std::string &minmax_path, const EmbedderOptions &);
+};
+} // namespace minmax_embedder
+
+#endif // __MINMAX_EMBEDDER_EMBEDDER_H__
diff --git a/compiler/minmax-embedder/requires.cmake b/compiler/minmax-embedder/requires.cmake
new file mode 100644 (file)
index 0000000..186f966
--- /dev/null
@@ -0,0 +1,5 @@
+require("arser")
+require("loco")
+require("luci")
+require("safemain")
+require("vconone")
diff --git a/compiler/minmax-embedder/src/Embedder.cpp b/compiler/minmax-embedder/src/Embedder.cpp
new file mode 100644 (file)
index 0000000..46734ff
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "minmax-embedder/Embedder.h"
+
+#include <luci/CircleExporter.h>
+#include <luci/CircleFileExpContract.h>
+#include <luci/ImporterEx.h>
+#include <luci/IR/CircleNode.h>
+#include <luci/IR/CircleQuantParam.h>
+#include <luci/Profile/CircleNodeID.h>
+#include <luci/Service/Validate.h>
+
+#include "h5/Reader.h"
+
+#include <cassert>
+#include <cmath> // for std::floor
+#include <iostream>
+#include <string>
+
+namespace
+{
+
+/* NOTE: getNthPercentile is copied from compiler/record-minmax/include/RecordFunction.h */
+/**
+ * @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;
+}
+
+} // namespace
+
+namespace minmax_embedder
+{
+
+void Embedder::embed(const std::string &output_path, const std::string &input_path,
+                     const std::string &minmax_path, const EmbedderOptions &opt)
+{
+  // Load model from the file
+  luci::ImporterEx importerex;
+  auto module = importerex.importVerifyModule(input_path);
+  if (module.get() == nullptr)
+    throw std::runtime_error{"Input circle is invalid"};
+
+  h5::Reader mmr{minmax_path};
+
+  for (size_t idx = 0; idx < module->size(); ++idx)
+  {
+    auto graph = module->graph(idx);
+
+    /* read subgraph inputs */
+    const auto input_nodes = loco::input_nodes(graph);
+    const auto n_inputs = input_nodes.size();
+    for (size_t input_idx = 0; input_idx < n_inputs; ++input_idx)
+    {
+      const auto *circle_input = loco::must_cast<const luci::CircleInput *>(input_nodes[input_idx]);
+      if (circle_input->index() != input_idx)
+        throw std::runtime_error("Input order in minmax recording does not match to circle");
+
+      auto minmax = mmr.read_input(0, idx, input_idx);
+      auto min = getNthPercentile(minmax.min_vector, opt.min_percentile);
+      auto max = getNthPercentile(minmax.max_vector, opt.max_percentile);
+      auto quantparam = std::make_unique<luci::CircleQuantParam>();
+      quantparam->min.push_back(min);
+      quantparam->max.push_back(max);
+      const auto *circle_node = loco::must_cast<const luci::CircleNode *>(input_nodes[input_idx]);
+      auto mutable_node = const_cast<luci::CircleNode *>(circle_node);
+      mutable_node->quantparam(std::move(quantparam));
+    }
+
+    /* read op outputs */
+    uint32_t n_nodes = graph->nodes()->size();
+    for (uint32_t i = 0; i < n_nodes; ++i)
+    {
+      auto node = loco::must_cast<luci::CircleNode *>(graph->nodes()->at(i));
+      if (not luci::has_node_id(node)) // Skip non-op nodes (e.g. input/const/output)
+        continue;
+      auto op_idx = luci::get_node_id(node);
+      auto minmax = mmr.read(0, idx, op_idx);
+      auto min = getNthPercentile(minmax.min_vector, opt.min_percentile);
+      auto max = getNthPercentile(minmax.max_vector, opt.max_percentile);
+      auto quantparam = std::make_unique<luci::CircleQuantParam>();
+      quantparam->min.push_back(min);
+      quantparam->max.push_back(max);
+      auto mutable_node = const_cast<luci::CircleNode *>(node);
+      mutable_node->quantparam(std::move(quantparam));
+    }
+
+    if (!luci::validate(graph))
+      throw std::runtime_error{"Circle after embedding minmax is invalid"};
+  }
+
+  // Export to output Circle file
+  luci::CircleExporter exporter;
+
+  luci::CircleFileExpContract contract(module.get(), output_path);
+
+  if (!exporter.invoke(&contract))
+    throw std::runtime_error{"Failed to export circle"};
+}
+
+} // namespace minmax_embedder
diff --git a/compiler/minmax-embedder/src/Embedder.test.cpp b/compiler/minmax-embedder/src/Embedder.test.cpp
new file mode 100644 (file)
index 0000000..c747e2c
--- /dev/null
@@ -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 "minmax-embedder/Embedder.h"
+
+#include <gtest/gtest.h>
+
+using namespace minmax_embedder;
+
+namespace
+{
+struct MinMaxEmbedderTest : public ::testing::Test
+{
+  EmbedderOptions _opt{0, 100};
+};
+
+} // namespace
+
+TEST_F(MinMaxEmbedderTest, invalid_input_NEG)
+{
+  Embedder embedder;
+  EXPECT_THROW(embedder.embed("", "not_existing", "", _opt), std::runtime_error);
+}
diff --git a/compiler/minmax-embedder/src/h5/Reader.cpp b/compiler/minmax-embedder/src/h5/Reader.cpp
new file mode 100644 (file)
index 0000000..b0bb8c3
--- /dev/null
@@ -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.
+ */
+
+#include "Reader.h"
+
+#include <cstdio>
+#include <stdexcept>
+
+namespace
+{
+bool exists(hid_t id, const char *path) { return H5Lexists(id, path, H5P_DEFAULT) > 0; }
+} // namespace
+
+namespace minmax_embedder
+{
+namespace h5
+{
+static const char *h5_value_grpname = "value";
+
+Reader::Reader(const std::string &filepath) : _file(filepath, H5F_ACC_RDONLY)
+{
+  _val_grp = _file.openGroup(h5_value_grpname);
+}
+
+// TODO: Handle multiple output
+MinMaxVectors Reader::read(int model_idx, int subg_idx, int op_idx) const
+{
+  MinMaxVectors mmv;
+  float minmax[2];
+  auto num_run = _val_grp.getNumObjs();
+  for (uint32_t r = 0; r < num_run; ++r)
+  {
+    // check whether minmax exists
+    char path[128]; // 128 is enough to print "/value/run_%d/model_%d/subg_%d/op_%d" + null
+    snprintf(path, 128, "/value/run_%d/model_%d/subg_%d/op_%d", r, model_idx, subg_idx, op_idx);
+    if (!exists(_file.getId(), path))
+      continue;
+    auto run_grp = _val_grp.openGroup(std::string("run_") + std::to_string(r));
+    auto model_grp = run_grp.openGroup(std::string("model_") + std::to_string(model_idx));
+    auto subg_grp = model_grp.openGroup(std::string("subg_") + std::to_string(subg_idx));
+    auto op_dset = subg_grp.openDataSet(std::string("op_") + std::to_string(op_idx));
+    H5::DataType dtype = op_dset.getDataType();
+    if (not(dtype == H5::PredType::IEEE_F32BE || dtype == H5::PredType::IEEE_F32LE))
+      throw std::runtime_error{"dtype of min, max in h5 is not float."};
+    op_dset.read(minmax, H5::PredType::NATIVE_FLOAT);
+    mmv.min_vector.emplace_back(minmax[0]);
+    mmv.max_vector.emplace_back(minmax[1]);
+  }
+  return mmv;
+}
+
+MinMaxVectors Reader::read_input(int model_idx, int subg_idx, int input_idx) const
+{
+  MinMaxVectors mmv;
+  float minmax[2];
+  auto num_run = _val_grp.getNumObjs();
+  for (uint32_t r = 0; r < num_run; ++r)
+  {
+    // check whether minmax exists
+    char path[128]; // 128 is enough to print "/value/run_%d/model_%d/subg_%d/input_%d" + null
+    snprintf(path, 128, "/value/run_%d/model_%d/subg_%d/input_%d", r, model_idx, subg_idx,
+             input_idx);
+    if (!exists(_file.getId(), path))
+      continue;
+    auto run_grp = _val_grp.openGroup(std::string("run_") + std::to_string(r));
+    auto model_grp = run_grp.openGroup(std::string("model_") + std::to_string(model_idx));
+    auto subg_grp = model_grp.openGroup(std::string("subg_") + std::to_string(subg_idx));
+    auto op_dset = subg_grp.openDataSet(std::string("input_") + std::to_string(input_idx));
+
+    H5::DataType dtype = op_dset.getDataType();
+    if (not(dtype == H5::PredType::IEEE_F32BE || dtype == H5::PredType::IEEE_F32LE))
+      throw std::runtime_error{"dtype of min, max in h5 is not float."};
+    op_dset.read(minmax, H5::PredType::NATIVE_FLOAT);
+    mmv.min_vector.emplace_back(minmax[0]);
+    mmv.max_vector.emplace_back(minmax[1]);
+  }
+  return mmv;
+}
+
+} // namespace h5
+} // namespace minmax_embedder
diff --git a/compiler/minmax-embedder/src/h5/Reader.h b/compiler/minmax-embedder/src/h5/Reader.h
new file mode 100644 (file)
index 0000000..600a387
--- /dev/null
@@ -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 __MINMAX_EMBEDDER_H5_READER_H__
+#define __MINMAX_EMBEDDER_H5_READER_H__
+
+#include <H5Cpp.h>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace minmax_embedder
+{
+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 }
+//                       â””── DATASET input_{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 { "op/name"}
+//                       â””── ATTRIBUTE input_{idx}
+//                              DATATYPE String
+//                              DATA { "input/name"}
+struct MinMaxVectors
+{
+  std::vector<float> min_vector;
+  std::vector<float> max_vector;
+};
+
+class Reader
+{
+public:
+  Reader(const std::string &filepath);
+  /**
+   * @brief Returns minmax recording for op {model_idx, subg_idx, op_idx}
+   *
+   * @return MinMaxVectors
+   */
+  MinMaxVectors read(int model_idx, int subg_idx, int op_idx) const;
+  /**
+   * @brief Returns minmax recording for input {model_idx, subg_idx, input_idx}
+   *
+   * @return MinMaxVectors
+   */
+  MinMaxVectors read_input(int model_idx, int subg_idx, int input_idx) const;
+
+private:
+  H5::H5File _file;
+  H5::Group _val_grp;
+};
+
+} // namespace h5
+} // namespace minmax_embedder
+
+#endif // __MINMAX_EMBEDDER_H5_READER_H__
index d247173..d2a037e 100644 (file)
@@ -1,7 +1,7 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 
 if(NOT FlatBuffers_FOUND)
-  message(STATUS "mio-circle skip: FlatBuffers 2.0 NOT FOUND")
+  message(STATUS "mio-circle skip: FlatBuffers 23.5.26 NOT FOUND")
   return()
 endif(NOT FlatBuffers_FOUND)
 
diff --git a/compiler/mio-circle/exclude.me b/compiler/mio-circle/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 8ee6da4..cf93f2b 100644 (file)
@@ -1,7 +1,7 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 
 if(NOT FlatBuffers_FOUND)
-  message(STATUS "mio-circle04 skip: FlatBuffers 2.0 NOT FOUND")
+  message(STATUS "mio-circle04 skip: FlatBuffers 23.5.26 NOT FOUND")
   return()
 endif(NOT FlatBuffers_FOUND)
 
diff --git a/compiler/mio-circle04/exclude.me b/compiler/mio-circle04/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index dfd359e..a1211e1 100644 (file)
@@ -1,7 +1,7 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 
 if(NOT FlatBuffers_FOUND)
-  message(STATUS "mio-circle05 skip: FlatBuffers 2.0 NOT FOUND")
+  message(STATUS "mio-circle05 skip: FlatBuffers 23.5.26 NOT FOUND")
   return()
 endif(NOT FlatBuffers_FOUND)
 
diff --git a/compiler/mio-circle05/exclude.me b/compiler/mio-circle05/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 2ccd805..d4f6a4d 100644 (file)
@@ -1,7 +1,7 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 
 if(NOT FlatBuffers_FOUND)
-  message(STATUS "mio-circle06 skip: FlatBuffers 2.0 NOT FOUND")
+  message(STATUS "mio-circle06 skip: FlatBuffers 23.5.26 NOT FOUND")
   return()
 endif(NOT FlatBuffers_FOUND)
 
diff --git a/compiler/mio-circle06/exclude.me b/compiler/mio-circle06/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/mio-circle07/CMakeLists.txt b/compiler/mio-circle07/CMakeLists.txt
new file mode 100644 (file)
index 0000000..aee9ef6
--- /dev/null
@@ -0,0 +1,52 @@
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
+
+if(NOT FlatBuffers_FOUND)
+  message(STATUS "mio-circle07 skip: FlatBuffers 23.5.26 NOT FOUND")
+  return()
+endif(NOT FlatBuffers_FOUND)
+
+message(STATUS "Build mio-circle07: 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.7/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_circle07
+  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-circle07" library
+add_executable(mio_circle07_example example.cpp)
+target_link_libraries(mio_circle07_example mio_circle07)
+
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(mio_circle07_helper STATIC ${SOURCES})
+set_target_properties(mio_circle07_helper PROPERTIES POSITION_INDEPENDENT_CODE ON)
+target_include_directories(mio_circle07_helper PRIVATE src)
+target_include_directories(mio_circle07_helper PUBLIC include)
+target_link_libraries(mio_circle07_helper mio_circle07)
+
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(mio_circle07_helper_test ${TESTS})
+target_include_directories(mio_circle07_helper_test PRIVATE src)
+target_link_libraries(mio_circle07_helper_test mio_circle07)
+target_link_libraries(mio_circle07_helper_test mio_circle07_helper)
diff --git a/compiler/mio-circle07/README.md b/compiler/mio-circle07/README.md
new file mode 100644 (file)
index 0000000..2152ad7
--- /dev/null
@@ -0,0 +1,3 @@
+# mio-circle07
+
+Let's make it easy to read and write Circle models.
diff --git a/compiler/mio-circle07/example.cpp b/compiler/mio-circle07/example.cpp
new file mode 100644 (file)
index 0000000..f524fb3
--- /dev/null
@@ -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-circle07"
+//
+#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-circle07/exclude.me b/compiler/mio-circle07/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/mio-circle07/include/mio_circle/Helper.h b/compiler/mio-circle07/include/mio_circle/Helper.h
new file mode 100644 (file)
index 0000000..d44a6c1
--- /dev/null
@@ -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_CIRCLE07_HELPER_H__
+#define __MIO_CIRCLE07_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->size());
+  for (uint32_t i = 0; i < flat_array->size(); i++)
+  {
+    ret[i] = flat_array->Get(i);
+  }
+  return ret;
+}
+
+} // namespace circle
+} // namespace mio
+
+#endif // __MIO_CIRCLE07_HELPER_H__
diff --git a/compiler/mio-circle07/include/mio_circle/Reader.h b/compiler/mio-circle07/include/mio_circle/Reader.h
new file mode 100644 (file)
index 0000000..4411579
--- /dev/null
@@ -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 __MIO_CIRCLE07_READER_H__
+#define __MIO_CIRCLE07_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 CircleMetadata_t *metadata() const { return _metadata; }
+  const CircleSignatureDef_t *signature_defs() const { return _signature_defs; }
+
+  uint32_t num_subgraph() const { return _subgraphs->size(); }
+
+  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;
+};
+
+} // namespace circle
+} // namespace mio
+
+#endif // __MIO_CIRCLE07_READER_H__
diff --git a/compiler/mio-circle07/src/Helper.cpp b/compiler/mio-circle07/src/Helper.cpp
new file mode 100644 (file)
index 0000000..bbfa204
--- /dev/null
@@ -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-circle07/src/Helper.test.cpp b/compiler/mio-circle07/src/Helper.test.cpp
new file mode 100644 (file)
index 0000000..687fb03
--- /dev/null
@@ -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_circle07_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_circle07_helper_test, v07)
+{
+  // 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_circle07_helper_test, v07_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_circle07_helper_test, v07_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_circle07_helper_test, v07_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_circle07_helper_test, v07_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_circle07_helper_test, v07_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_circle07_helper_test, v07_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_circle07_helper_test, v07_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_circle07_helper_test, v07_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-circle07/src/Reader.cpp b/compiler/mio-circle07/src/Reader.cpp
new file mode 100644 (file)
index 0000000..114eaf6
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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->size() <= 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();
+
+  _inputs = as_index_vector(subgraph->inputs());
+  _outputs = as_index_vector(subgraph->outputs());
+
+  return true;
+}
+
+} // namespace circle
+} // namespace mio
diff --git a/compiler/mio-circle07/src/Reader.test.cpp b/compiler/mio-circle07/src/Reader.test.cpp
new file mode 100644 (file)
index 0000000..132da01
--- /dev/null
@@ -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_circle07_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_circle07_reader_test, null_Model_NEG)
+{
+  EXPECT_THROW(mio::circle::Reader reader(nullptr), std::runtime_error);
+}
+
+TEST_F(mio_circle07_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-circle08/CMakeLists.txt b/compiler/mio-circle08/CMakeLists.txt
new file mode 100644 (file)
index 0000000..03e449d
--- /dev/null
@@ -0,0 +1,52 @@
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
+
+if(NOT FlatBuffers_FOUND)
+  message(STATUS "mio-circle08 skip: FlatBuffers 23.5.26 NOT FOUND")
+  return()
+endif(NOT FlatBuffers_FOUND)
+
+message(STATUS "Build mio-circle08: 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.8/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_circle08
+  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-circle08" library
+add_executable(mio_circle08_example example.cpp)
+target_link_libraries(mio_circle08_example mio_circle08)
+
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(mio_circle08_helper STATIC ${SOURCES})
+set_target_properties(mio_circle08_helper PROPERTIES POSITION_INDEPENDENT_CODE ON)
+target_include_directories(mio_circle08_helper PRIVATE src)
+target_include_directories(mio_circle08_helper PUBLIC include)
+target_link_libraries(mio_circle08_helper mio_circle08)
+
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+GTest_AddTest(mio_circle08_helper_test ${TESTS})
+target_include_directories(mio_circle08_helper_test PRIVATE src)
+target_link_libraries(mio_circle08_helper_test mio_circle08)
+target_link_libraries(mio_circle08_helper_test mio_circle08_helper)
diff --git a/compiler/mio-circle08/README.md b/compiler/mio-circle08/README.md
new file mode 100644 (file)
index 0000000..a12fce8
--- /dev/null
@@ -0,0 +1,3 @@
+# mio-circle08
+
+Let's make it easy to read and write Circle models.
diff --git a/compiler/mio-circle08/example.cpp b/compiler/mio-circle08/example.cpp
new file mode 100644 (file)
index 0000000..99fa866
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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-circle08"
+//
+#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-circle08/include/mio_circle/Helper.h b/compiler/mio-circle08/include/mio_circle/Helper.h
new file mode 100644 (file)
index 0000000..ce6bb01
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CIRCLE08_HELPER_H__
+#define __MIO_CIRCLE08_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->size());
+  for (uint32_t i = 0; i < flat_array->size(); i++)
+  {
+    ret[i] = flat_array->Get(i);
+  }
+  return ret;
+}
+
+} // namespace circle
+} // namespace mio
+
+#endif // __MIO_CIRCLE08_HELPER_H__
diff --git a/compiler/mio-circle08/include/mio_circle/Reader.h b/compiler/mio-circle08/include/mio_circle/Reader.h
new file mode 100644 (file)
index 0000000..723668f
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CIRCLE08_READER_H__
+#define __MIO_CIRCLE08_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 CircleMetadata_t *metadata() const { return _metadata; }
+  const CircleSignatureDef_t *signature_defs() const { return _signature_defs; }
+
+  uint32_t num_subgraph() const { return _subgraphs->size(); }
+
+  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;
+};
+
+} // namespace circle
+} // namespace mio
+
+#endif // __MIO_CIRCLE08_READER_H__
diff --git a/compiler/mio-circle08/src/Helper.cpp b/compiler/mio-circle08/src/Helper.cpp
new file mode 100644 (file)
index 0000000..a7bbd23
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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-circle08/src/Helper.test.cpp b/compiler/mio-circle08/src/Helper.test.cpp
new file mode 100644 (file)
index 0000000..57e78c0
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_circle08_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_circle08_helper_test, v08)
+{
+  // 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_circle08_helper_test, v08_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_circle08_helper_test, v08_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_circle08_helper_test, v08_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_circle08_helper_test, v08_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_circle08_helper_test, v08_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_circle08_helper_test, v08_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_circle08_helper_test, v08_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_circle08_helper_test, v08_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-circle08/src/Reader.cpp b/compiler/mio-circle08/src/Reader.cpp
new file mode 100644 (file)
index 0000000..e4df6d0
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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->size() <= 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();
+
+  _inputs = as_index_vector(subgraph->inputs());
+  _outputs = as_index_vector(subgraph->outputs());
+
+  return true;
+}
+
+} // namespace circle
+} // namespace mio
diff --git a/compiler/mio-circle08/src/Reader.test.cpp b/compiler/mio-circle08/src/Reader.test.cpp
new file mode 100644 (file)
index 0000000..7ead63e
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_circle08_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_circle08_reader_test, null_Model_NEG)
+{
+  EXPECT_THROW(mio::circle::Reader reader(nullptr), std::runtime_error);
+}
+
+TEST_F(mio_circle08_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-tf/exclude.me b/compiler/mio-tf/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 90187b0..a5f9d44 100644 (file)
@@ -1,4 +1,4 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 
 if(NOT FlatBuffers_FOUND)
   message(STATUS "Build mio-tflite: FAILED (missing Flatbuffers)")
diff --git a/compiler/mio-tflite/exclude.me b/compiler/mio-tflite/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 1ca8e75..371118b 100644 (file)
@@ -1,7 +1,7 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 
 if(NOT FlatBuffers_FOUND)
-  message(STATUS "Build mio-tflite2121: FAILED (missing Flatbuffers 2.0)")
+  message(STATUS "Build mio-tflite2121: FAILED (missing Flatbuffers 23.5.26)")
   return()
 endif(NOT FlatBuffers_FOUND)
 
index f2cfeaf..d34d6cc 100644 (file)
@@ -1,7 +1,7 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 
 if(NOT FlatBuffers_FOUND)
-  message(STATUS "Build mio-tflite260: FAILED (missing Flatbuffers 2.0)")
+  message(STATUS "Build mio-tflite260: FAILED (missing Flatbuffers 23.5.26)")
   return()
 endif(NOT FlatBuffers_FOUND)
 
diff --git a/compiler/mio-tflite260/exclude.me b/compiler/mio-tflite260/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index edf75f4..7c5d328 100644 (file)
@@ -1,7 +1,7 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 
 if(NOT FlatBuffers_FOUND)
-  message(STATUS "Build mio-tflite280: FAILED (missing Flatbuffers 2.0)")
+  message(STATUS "Build mio-tflite280: FAILED (missing Flatbuffers 23.5.26)")
   return()
 endif(NOT FlatBuffers_FOUND)
 
diff --git a/compiler/mio-tflite280/exclude.me b/compiler/mio-tflite280/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/mir-interpreter/exclude.me b/compiler/mir-interpreter/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 4333621..f7edf44 100644 (file)
@@ -27,7 +27,7 @@ namespace mir_interpreter
 {
 
 template <template <typename> class F, typename... Args>
-void dispatch(mir::DataType dt, Args &&... args)
+void dispatch(mir::DataType dt, Args &&...args)
 {
   switch (dt)
   {
diff --git a/compiler/mir/exclude.me b/compiler/mir/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 37bfdb3..48a4825 100644 (file)
@@ -38,7 +38,7 @@ public:
 
   virtual ~Graph();
 
-  template <typename T, typename... Args> Operation *create(Args &&... args)
+  template <typename T, typename... Args> Operation *create(Args &&...args)
   {
     auto op = new T(std::forward<Args>(args)...);
     op->setId(_last_node_id++);
index 2b29378..025cb54 100644 (file)
@@ -103,11 +103,11 @@ public:
 private:
   mir::Graph *_graph = nullptr;
 
-  template <typename OpType, typename... Types> mir::Operation *createOp(Types &&... args);
+  template <typename OpType, typename... Types> mir::Operation *createOp(Types &&...args);
 };
 
 template <typename OpType, typename... Types>
-mir::Operation *Caffe2OpCreator::createOp(Types &&... args)
+mir::Operation *Caffe2OpCreator::createOp(Types &&...args)
 {
   return _graph->create<OpType>(std::forward<Types>(args)...);
 }
index 721bb90..11a4dfc 100644 (file)
@@ -132,11 +132,11 @@ private:
 
   mir::TensorVariant convertBlob(const caffe::BlobProto &blob);
 
-  template <typename OpType, typename... Types> mir::Operation *createOp(Types &&... args);
+  template <typename OpType, typename... Types> mir::Operation *createOp(Types &&...args);
 };
 
 template <typename OpType, typename... Types>
-mir::Operation *CaffeOpCreator::createOp(Types &&... args)
+mir::Operation *CaffeOpCreator::createOp(Types &&...args)
 {
   return _graph->create<OpType>(std::forward<Types>(args)...);
 }
index 04c2205..7c407fa 100644 (file)
@@ -9,6 +9,12 @@ if (NOT Protobuf_FOUND)
     return()
 endif ()
 
+if (ENABLE_EXCLUDE_ME)
+    if (NOT TARGET mir_interpreter)
+        return()
+    endif ()
+endif ()
+
 Protobuf_Generate(MIR_ONNX_PROTO
         ${CMAKE_CURRENT_BINARY_DIR}/generated
         ${ONNXSource_DIR}
index 1367ab8..3b644ca 100644 (file)
@@ -38,7 +38,7 @@ mir::TensorVariant createTensor(const onnx::TensorProto *tensor);
 mir::Operation *foldConstants(mir::Graph *graph, mir::Operation *op);
 
 template <typename OpType, typename... Types>
-mir::Operation *createOp(mir::Graph *graph, Types &&... args)
+mir::Operation *createOp(mir::Graph *graph, Types &&...args)
 {
   auto op = graph->create<OpType>(std::forward<Types>(args)...);
   op = foldConstants(graph, op);
index 6c6c28a..7525f23 100644 (file)
@@ -1,4 +1,4 @@
-nnas_find_package(FlatBuffers EXACT 2.0 REQUIRED)
+nnas_find_package(FlatBuffers EXACT 23.5.26 REQUIRED)
 
 if (NOT FlatBuffers_FOUND)
     return()
index 820436f..c5bc4f6 100644 (file)
@@ -149,11 +149,11 @@ private:
   mir::Operation::Output *addFusedActivation(mir::Operation::Output *input,
                                              tflite::ActivationFunctionType activation_type);
 
-  template <typename OpType, typename... Types> mir::Operation *createOp(Types &&... args);
+  template <typename OpType, typename... Types> mir::Operation *createOp(Types &&...args);
 };
 
 template <typename OpType, typename... Types>
-mir::Operation *TFLiteOpCreator::createOp(Types &&... args)
+mir::Operation *TFLiteOpCreator::createOp(Types &&...args)
 {
   return _graph->create<OpType>(std::forward<Types>(args)...);
 }
index 91b1be7..d3d33b1 100644 (file)
@@ -28,7 +28,7 @@ struct ParamType
   Shape shape;
 
   template <typename... Args>
-  explicit ParamType(int32_t actual_len, Args &&... args)
+  explicit ParamType(int32_t actual_len, Args &&...args)
     : actual_length(actual_len), shape({static_cast<int32_t>(args)...})
   {
   }
diff --git a/compiler/mir2loco/exclude.me b/compiler/mir2loco/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/moco-log/exclude.me b/compiler/moco-log/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/moco-tf/exclude.me b/compiler/moco-tf/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/moco-value-pbtxt-test/exclude.me b/compiler/moco-value-pbtxt-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/moco/exclude.me b/compiler/moco/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 7e09afa..8987755 100644 (file)
@@ -27,7 +27,7 @@ class Closure
 {
 public:
   template <typename... Args>
-  Closure(const DomainID &id, Args &&... indices) : _id{id}, _sub{std::forward<Args>(indices)...}
+  Closure(const DomainID &id, Args &&...indices) : _id{id}, _sub{std::forward<Args>(indices)...}
   {
     // DO NOTHING
   }
index 8d809e2..8c497b6 100644 (file)
@@ -37,7 +37,7 @@ public:
   Domain(const Domain &) = default;
 
 public:
-  template <typename... Args> Closure operator()(Args &&... indices)
+  template <typename... Args> Closure operator()(Args &&...indices)
   {
     return Closure{_id, std::forward<Args>(indices)...};
   }
index 8e3cc56..1080918 100644 (file)
@@ -30,8 +30,7 @@ class DerefNode final : public Node
 {
 public:
   template <typename... Args>
-  DerefNode(const DomainID &id, Args &&... indicies)
-    : _id{id}, _sub{std::forward<Args>(indicies)...}
+  DerefNode(const DomainID &id, Args &&...indicies) : _id{id}, _sub{std::forward<Args>(indicies)...}
   {
     // DO NOTHING
   }
diff --git a/compiler/nest/exclude.me b/compiler/nest/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/nike/exclude.me b/compiler/nike/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index cad05cc..8cfe537 100644 (file)
@@ -18,8 +18,7 @@
 #include "AclCppOpGenerator.h"
 #include "backends/acl_soft_backend/AclCppException.h"
 
-#include <boost/filesystem.hpp>
-
+#include <filesystem>
 #include <fstream>
 #include <utility>
 
@@ -27,7 +26,7 @@ namespace nnc
 {
 
 using namespace std;
-namespace fs = boost::filesystem;
+namespace fs = std::filesystem;
 
 AclCppCodeGenerator::AclCppCodeGenerator(string output_dir, string artifact_name)
   : _output_dir(std::move(output_dir)), _artifact_name(std::move(artifact_name))
index 8f55303..f769a58 100644 (file)
@@ -1,5 +1,3 @@
-nnas_find_package(Boost REQUIRED COMPONENTS filesystem)
-
 set(ACL_SOFT_BACKEND_CPP_SOURCES AclCppGenerator.cpp AclCppOpGenerator.cpp
     ArtifactGeneratorCppCode.cpp ArtifactGeneratorCppDecl.cpp ArtifactModel.cpp)
 
@@ -7,8 +5,11 @@ file(GLOB_RECURSE ACL_IN_SOURCES "*.in")
 nnc_make_generated_sources("${ACL_IN_SOURCES}" ${CMAKE_CURRENT_BINARY_DIR} ACL_GENERATED_SOURCES)
 
 nnc_add_library(acl_soft_backend_cpp SHARED ${ACL_SOFT_BACKEND_CPP_SOURCES} ${ACL_GENERATED_SOURCES})
-target_include_directories(acl_soft_backend_cpp PRIVATE ${Boost_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
-target_link_libraries(acl_soft_backend_cpp PRIVATE mir ${Boost_LIBRARIES})
+target_include_directories(acl_soft_backend_cpp PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+target_link_libraries(acl_soft_backend_cpp PRIVATE mir)
+if(ONE_UBUNTU_CODENAME_BIONIC)
+    target_link_libraries(acl_soft_backend_cpp PRIVATE stdc++fs)
+endif()
 
 # install soft backend c++ library
 nnc_install_library(acl_soft_backend_cpp)
index ea0cd1a..0d8be77 100644 (file)
@@ -1,5 +1,3 @@
-nnas_find_package(Boost REQUIRED COMPONENTS filesystem)
-
 set(SOFT_BACKEND_CPP_SOURCES CPPGenerator.cpp ModelAnalyzer.cpp SBSerializer.cpp SequencedIR.cpp)
 
 file(GLOB_RECURSE SOFT_DEF_SOURCES "*.def")
@@ -7,8 +5,11 @@ file(GLOB_RECURSE SOFT_DEF_SOURCES "*.def")
 nnc_make_generated_sources("${SOFT_DEF_SOURCES}" ${CMAKE_CURRENT_BINARY_DIR} SOFT_GENERATED_SOURCES)
 
 nnc_add_library(soft_backend_cpp SHARED ${SOFT_BACKEND_CPP_SOURCES} ${SOFT_GENERATED_SOURCES})
-target_include_directories(soft_backend_cpp PRIVATE ${Boost_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
-target_link_libraries(soft_backend_cpp PRIVATE mir ${Boost_LIBRARIES})
+target_include_directories(soft_backend_cpp PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+target_link_libraries(soft_backend_cpp PRIVATE mir)
+if(ONE_UBUNTU_CODENAME_BIONIC)
+    target_link_libraries(soft_backend_cpp PRIVATE stdc++fs)
+endif()
 
 # install soft backend c++ library
 nnc_install_library(soft_backend_cpp)
index 0971228..69100a0 100644 (file)
@@ -50,9 +50,8 @@
 #include "cpp_gather.generated.h"
 #include "cpp_broadcast.generated.h"
 
-#include <boost/filesystem.hpp>
-
 #include <cstring>
+#include <filesystem>
 #include <fstream>
 #include <stdexcept>
 #include <utility>
@@ -62,7 +61,7 @@ namespace nnc
 
 using namespace sir;
 using namespace std;
-namespace fs = boost::filesystem;
+namespace fs = std::filesystem;
 
 /**
  * @brief Creates pointer to some output stream to encapsulate resource management into deleter
diff --git a/compiler/nnc/exclude.me b/compiler/nnc/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index e593333..cf5d0ac 100644 (file)
@@ -228,7 +228,7 @@ mir::TensorVariant getReferenceTensor(mir::Graph &g, mir::Operation *op)
  * @brief Run selected operation, used to make code in tests more compact and fit getReferenceTensor
  * format
  */
-template <typename Operation, typename... Args> Tensor run(Operation op, const Args &... args)
+template <typename Operation, typename... Args> Tensor run(Operation op, const Args &...args)
 {
   Tensor output;
   op(output, args...);
@@ -308,7 +308,7 @@ void createAndRunTestGraph(
   function<mir::Operation *(mir::Graph &, const std::vector<mir::Operation::Output *> &inputs)>
     op_generator,
   TestFunc artifactOperation, const vector<unique_ptr<mir::TensorVariant>> &input_ntensors,
-  Args &... input_atensors)
+  Args &...input_atensors)
 {
   mir::Graph g;
   mir::Operation *actual_operation = fillGraph(g, op_generator, input_ntensors);
diff --git a/compiler/nnkit-caffe/exclude.me b/compiler/nnkit-caffe/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/nnkit-intf/exclude.me b/compiler/nnkit-intf/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/nnkit-misc/exclude.me b/compiler/nnkit-misc/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/nnkit-mocotf/exclude.me b/compiler/nnkit-mocotf/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/nnkit-onnxrt/exclude.me b/compiler/nnkit-onnxrt/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/nnkit-tf/exclude.me b/compiler/nnkit-tf/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/nnkit-tflite/exclude.me b/compiler/nnkit-tflite/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/nnkit/exclude.me b/compiler/nnkit/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/nnop/exclude.me b/compiler/nnop/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 20c4238..d5471c6 100644 (file)
@@ -35,8 +35,8 @@ public:
   TestModel(const std::string &ifm_name, const feature::Shape &ifm_shape,
             const std::string &ofm_name, const feature::Shape &ofm_shape,
             const kernel::Shape &ker_shape, const kernel::Layout &ker_layout, float *ker_data)
-    : _ifm_name(ifm_name), _ifm_shape(ifm_shape), _ofm_name(ofm_name),
-      _ofm_shape(ofm_shape), _ker{ker_shape, ker_layout, ker_data}
+    : _ifm_name(ifm_name), _ifm_shape(ifm_shape), _ofm_name(ofm_name), _ofm_shape(ofm_shape),
+      _ker{ker_shape, ker_layout, ker_data}
   {
     // DO NOTHING
   }
index 98ac78f..bf1f1dc 100644 (file)
@@ -38,8 +38,8 @@ public:
   TestModel(const std::string &ifm_name, const feature::Shape &ifm_shape,
             const std::string &ofm_name, const feature::Shape &ofm_shape,
             const kernel::Shape &ker_shape, const kernel::Layout &ker_layout, float *ker_data)
-    : _ifm_name(ifm_name), _ifm_shape(ifm_shape), _ofm_name(ofm_name),
-      _ofm_shape(ofm_shape), _ker{ker_shape, ker_layout, ker_data}
+    : _ifm_name(ifm_name), _ifm_shape(ifm_shape), _ofm_name(ofm_name), _ofm_shape(ofm_shape),
+      _ker{ker_shape, ker_layout, ker_data}
   {
     // DO NOTHING
   }
diff --git a/compiler/nnsuite/exclude.me b/compiler/nnsuite/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 917bbda..10cd5fc 100644 (file)
@@ -20,6 +20,7 @@ endif()
 #      below code will remove extension when copy and install.
 set(ONE_COMMAND_FILES
     one-build
+    one-create-quant-dataset
     one-import
     one-import-bcq
     one-import-tf
@@ -119,11 +120,13 @@ install(FILES ${MODEL2NNPKG}
               RENAME "model2nnpkg")
 
 # make python directory
-set(ONE_PYTHON_FILES backends.py
+set(ONE_PYTHON_FILES argumentparse.py
+                     backends.py
                      constant.py
                      export_constant.py
                      make_cmd.py
                      CfgRunner.py
+                     Command.py
                      OptionBuilder.py
                      TopologicalSortHelper.py
                      WorkflowRunner.py
@@ -159,6 +162,7 @@ foreach(ONE_PYTHON_FILE IN ITEMS ${ONE_PYTHON_FILES})
 endforeach(ONE_PYTHON_FILE)
 
 set(CONSTANT_EXPORTING_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/${ONE_PYTHON_DIR}/export_constant.py")
+set(CONSTANT_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/${ONE_PYTHON_DIR}/constant.py")
 set(O1_OPTION "O1")
 set(O1_CFG_FILE "${O1_OPTION}.cfg")
 set(O1_CFG_FILE_BIN "${CMAKE_CURRENT_BINARY_DIR}/${ONE_PYTHON_DIR}/${O1_CFG_FILE}")
@@ -168,7 +172,7 @@ add_custom_command(OUTPUT ${O1_CFG_FILE_BIN}
           --constant ${O1_OPTION}
           --format cfg
           --output_path ${O1_CFG_FILE_BIN}
-  DEPENDS ${CONSTANT_EXPORTING_SCRIPT}
+  DEPENDS ${CONSTANT_EXPORTING_SCRIPT} ${CONSTANT_SCRIPT}
   COMMENT "Generate ${O1_CFG_FILE}"
 )
 
index 55ef96c..1398923 100644 (file)
@@ -1,4 +1,5 @@
 # dummy driver for interface test
+set(DUMMY_COMPILER_SRC src/dummy-compiler.cpp)
 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)
@@ -12,6 +13,10 @@ 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)
 
+# Note that `dummy-compiler` is differnet from `dummy-compile`.
+# Without command schema, codegen drivers have "-compile" suffix in their names.
+# Such restriction can be relieved with the command schema.
+add_executable(dummy-compiler ${DUMMY_COMPILER_SRC})
 add_executable(dummy-compile ${DUMMY_DRIVER_SRC})
 add_executable(dummyV2-compile ${DUMMY_V2_DRIVER_SRC})
 add_executable(help-compile ${HELP_DRIVER_SRC})
@@ -25,6 +30,7 @@ add_executable(help-profile ${HELP_PROFILE_SRC})
 add_executable(dummyEnv-compile ${DUMMY_ENV_SRC})
 add_executable(dummy-onnx-ext ${DUMMY_ONNX_EXT})
 
+set(DUMMY_COMPILER "${CMAKE_CURRENT_BINARY_DIR}/dummy-compiler")
 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")
@@ -38,6 +44,11 @@ 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_COMPILER}
+        PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
+                    GROUP_READ GROUP_EXECUTE
+                    WORLD_READ WORLD_EXECUTE
+        DESTINATION test)
 install(FILES ${DUMMY_DRIVER}
         PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
                     GROUP_READ GROUP_EXECUTE
index 2ad09a3..93b2ab5 100644 (file)
@@ -17,7 +17,9 @@
 /**
  * dummy-compile only tests its interface rather than its functionality.
  *
+ * ./dummy-compile -h
  * ./dummy-compile -o ${OUTPUT_NAME} ${INPUT_NAME}
+ * ./dummy-compile --target {TARGET_NAME} -o ${OUTPUT_NAME} ${INPUT_NAME}
  *
  * NOTE argv[3](INPUT_NAME) is not used here.
  */
 
 int main(int argc, char **argv)
 {
-  if (argc != 4)
+  if (argc != 2 and argc != 4 and argc != 6)
     return EXIT_FAILURE;
 
-  std::string opt_o{"-o"};
-  std::string argv_1{argv[1]};
+  if (argc == 2)
+  {
+    std::string help_o{"-h"};
+    std::string argv_1{argv[1]};
+    if (help_o != argv_1)
+      return EXIT_FAILURE;
 
-  if (opt_o != argv_1)
-    return EXIT_FAILURE;
+    std::cout << "HELP MESSAGE!!" << std::endl;
+    return EXIT_SUCCESS;
+  }
+  if (argc == 4)
+  {
+    std::string opt_o{"-o"};
+    std::string argv_1{argv[1]};
+    if (opt_o != argv_1)
+      return EXIT_FAILURE;
 
-  std::string output_name{argv[2]};
-  std::ofstream outfile(output_name);
+    std::string output_name{argv[2]};
+    std::ofstream outfile(output_name);
+    outfile << "dummy-compile dummy output!!" << std::endl;
+    outfile.close();
+  }
+  if (argc == 6)
+  {
+    std::string opt_T{"--target"};
+    std::string argv_1{argv[1]};
+    if (opt_T != argv_1)
+      return EXIT_FAILURE;
+    std::string target_name{argv[2]};
 
-  outfile << "dummy-compile dummy output!!" << std::endl;
+    std::string opt_o{"-o"};
+    std::string argv_3{argv[3]};
+    if (opt_o != argv_3)
+      return EXIT_FAILURE;
 
-  outfile.close();
+    std::string output_name{argv[4]};
+    std::ofstream outfile(output_name);
+    outfile << "dummy-compile with " << target_name << " target" << std::endl;
+    outfile.close();
+  }
 
   return EXIT_SUCCESS;
 }
diff --git a/compiler/one-cmds/dummy-driver/src/dummy-compiler.cpp b/compiler/one-cmds/dummy-driver/src/dummy-compiler.cpp
new file mode 100644 (file)
index 0000000..6ca4226
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * dummy-compiler only tests its interface rather than its functionality.
+ *
+ * ./dummy-compiler --target ${TARGET_NAME} --verbose ${INPUT_NAME} ${OUTPUT_NAME}
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+int main(int argc, char **argv)
+{
+  if (argc != 2 and argc != 6)
+    return EXIT_FAILURE;
+  if (argc == 2)
+  {
+    std::string help_o{"-h"};
+    std::string argv_1{argv[1]};
+    if (help_o != argv_1)
+      return EXIT_FAILURE;
+
+    std::cout << "HELP MESSAGE!!" << std::endl;
+    return EXIT_SUCCESS;
+  }
+  std::string target_name{argv[2]};
+  std::string output_name{argv[5]};
+
+  std::ofstream outfile(output_name);
+
+  outfile << "dummy-compiler with " << target_name << " target" << std::endl;
+
+  return EXIT_SUCCESS;
+}
index b997e05..f30a67a 100644 (file)
@@ -18,7 +18,7 @@
  * dummy-profile only tests its interface rather than its functionality.
  *
  * ./dummy-profile ${INPUT_NAME}
- * dummy-profile dummy output!!!
+ * ./dummy-profile --target ${TARGET_NAME} ${INPUT_NAME}
  */
 
 #include <iostream>
 
 int main(int argc, char **argv)
 {
-  if (argc != 2)
+  if (argc != 2 and argc != 4)
     return EXIT_FAILURE;
 
-  std::cout << "dummy-profile dummy output!!!" << std::endl;
+  if (argc == 2)
+  {
+    std::cout << "dummy-profile dummy output!!!" << std::endl;
+  }
+  if (argc == 4)
+  {
+    std::string opt_T{"--target"};
+    std::string argv_1{argv[1]};
+    if (opt_T != argv_1)
+      return EXIT_FAILURE;
+    std::string target_name{argv[2]};
+
+    std::cout << "dummy-profile with " << target_name << " target" << std::endl;
+  }
 
   return EXIT_SUCCESS;
 }
index 028cde4..fefbabf 100644 (file)
@@ -149,6 +149,9 @@ one-optimize
 one-optimize provides network or operator transformation shown below.
 
 Current transformation options are
+- common_subexpression_elimination : This will perform common subexpression elimination.
+- decompose_hardswish : This will decompose hardswish operator to Add, Mul and Relu6 operators.
+- decompose_softmax : This will decompose softmax into multiple operators for special backends.
 - disable_validation : This will turn off operator validations.
 - expand_broadcast_const : This will expand broadcastable constant node inputs
 - fold_add_v2 : This removes AddV2 operation which can be folded
@@ -157,13 +160,21 @@ Current transformation options are
 - fold_dequantize : This removes Dequantize operation which can be folded
 - fold_dwconv : This folds Depthwise Convolution operation which can be folded
 - fold_gather : This removes Gather operation which can be folded
+- fold_mul : This removes Mul operation which can be folded
+- fold_shape : This removes Shape operation which can be folded
 - fold_sparse_to_dense : This removes SparseToDense operation which can be folded
 - forward_reshape_to_unaryop: This will move Reshape after UnaryOp for centain condition
+- fuse_add_to_fullyconnected_bias: This fuses Add operator to following FullyConnected operator bias
+- fuse_add_with_conv: This fuses Add operator with the preceding Convolution operator if possible
 - fuse_add_with_fully_connected: This fuses Add operator with the preceding FullyConnected operator if possible
 - fuse_add_with_tconv: This fuses Add operator with the preceding TConv operator if possible
 - fuse_batchnorm_with_conv : This fuses BatchNorm operator to convolution operator
 - fuse_batchnorm_with_dwconv : This fuses BatchNorm operator to depthwise convolution operator
 - fuse_batchnorm_with_tconv : This fuses BatchNorm operator to transpose convolution operator
+- fuse_mul_to_fullyconnected_weights : This fuses Mul operator to following FullyConnected operator weights
+- fuse_mul_with_conv: This fuses Mul with a preceding Convolution op if possible.
+- fuse_mul_with_div: This fuses Mul and Div op as Div.
+- fuse_slice_with_tconv: This fuses Slice with a preceding TConv if possible.
 - fuse_bcq: This enables Binary-Coded-bases Quantized DNNs
    - read https://arxiv.org/abs/2005.09904 for detailed information
 - fuse_instnorm: This will convert instance normalization related operators to
@@ -174,20 +185,25 @@ Current transformation options are
 - fuse_activation_function: This fuses Activation function to a preceding operator.
 - fuse_mean_with_mean: This fuses two consecutive ReduceMean operations into one.
 - fuse_transpose_with_mean: This fuses ReduceMean with a preceding Transpose under certain conditions.
+- fuse_horizontal_fc_layers: This fuses horizontal FullyConnected layers under certain conditions.
 - make_batchnorm_gamma_positive: This makes negative gamma of batch normalization into a small positive value (1e-10).
   Note that this pass can change the execution result of the model.
   So, use it only when the impact is known to be acceptable.
 - mute_warnings : This will turn off warning messages.
 - generate_profile_data : This will turn on profiling data generation.
 - remove_fakequant : This will remove all fakequant operators.
+- remove_gather_guard : This will remove Add/FloorMod guards of Gather indices with certain conditions.
+  CAUTION: user must guarantee that indices are all non-negative values.
 - remove_quantdequant : This will remove all Quantize-Dequantize sequence.
 - remove_redundant_quantize : This removes redundant quantize operators.
 - remove_redundant_reshape : This fuses or removes redundant reshape operators.
 - remove_redundant_transpose : This fuses or removes redundant transpose operators.
+- remove_unnecessary_add : This removes unnecessary add operators.
 - remove_unnecessary_reshape : This removes unnecessary reshape operators.
 - remove_unnecessary_slice : This removes unnecessary slice operators.
 - remove_unnecessary_strided_slice : This removes unnecessary strided slice operators.
 - remove_unnecessary_split : This removes unnecessary split operators.
+- remove_unnecessary_transpose: This removes unnecessary transpose operators.
 - replace_cw_mul_add_with_depthwise_conv: This will replace channel-wise Mul/Add with DepthwiseConv2D.
 - resolve_customop_add: This will convert Custom(Add) to normal Add operator
 - resolve_customop_batchmatmul: This will convert Custom(BatchMatMul) to
@@ -206,6 +222,7 @@ Current transformation options are
 - substitute_transpose_to_reshape : This will convert certain condition Transpose to Reshape.
 - transform_min_max_to_relu6: This will transform Minimum-Maximum pattern to Relu6 operator.
 - transform_min_relu_to_relu6: This will transform Minimum(6)-Relu pattern to Relu6 operator.
+- transform_sqrt_div_to_rsqrt_mul: This will transform Sqrt-Div pattern to Rsqrt-Mul operators.
 
 
 one-quantize
index b21a162..556a8f8 100644 (file)
@@ -20,7 +20,6 @@
 # limitations under the License.
 
 import argparse
-import configparser
 import os
 import sys
 
@@ -89,8 +88,7 @@ def _get_driver_name(driver_name):
 
 
 def parse_cfg(args):
-    config = configparser.ConfigParser()
-    config.optionxform = str
+    config = oneutils.get_config_parser()
     parsed = config.read(os.path.expanduser(getattr(args, 'config')))
     if not parsed:
         raise FileNotFoundError('Not found given configuration file')
@@ -122,8 +120,7 @@ def _verify_cfg(driver_list, config):
 # verify given optimization option file
 def _verify_opt(args):
     if oneutils.is_valid_attr(args, 'O'):
-        config = configparser.ConfigParser()
-        config.optionxform = str
+        config = oneutils.get_config_parser()
         opt_name_path_dic = dict(
             zip(oneutils.get_optimization_list(get_name=True),
                 oneutils.get_optimization_list()))
index a956a63..1081146 100644 (file)
@@ -37,7 +37,7 @@ sys.tracebacklimit = 0
 
 
 def _get_parser(backends_list):
-    codegen_usage = 'one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND] [--] [COMMANDS FOR BACKEND]'
+    codegen_usage = 'one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND | -T TARGET] [--] [COMMANDS FOR BACKEND]'
     parser = argparse.ArgumentParser(
         description='command line tool for code generation', usage=codegen_usage)
 
@@ -52,20 +52,38 @@ def _get_parser(backends_list):
             backends_name) + ')'
     backend_help_message = 'backend name to use ' + backends_name_message
     parser.add_argument('-b', '--backend', type=str, help=backend_help_message)
+    parser.add_argument(
+        '-T', '--target', type=str, help='run with specific target of the backend')
 
     return parser
 
 
-def _verify_arg(parser, args, cfg_args, backend_args, unknown_args):
+def _verify_arg(parser, args, cfg_args, cfg_target_args, backend_args, unknown_args):
     """verify given arguments"""
     cmd_backend_exist = oneutils.is_valid_attr(args, 'backend')
+    cmd_target_exist = oneutils.is_valid_attr(args, 'target')
+    if cmd_backend_exist and cmd_target_exist:
+        parser.error(
+            '\'backend\' option and \'target\' option cannot be used simultaneously.')
     cfg_backend_exist = oneutils.is_valid_attr(cfg_args, 'backend')
     cfg_backends_exist = oneutils.is_valid_attr(cfg_args, 'backends')
+    target_exist = cmd_target_exist or oneutils.is_valid_attr(cfg_target_args, 'target')
 
     # check if required arguments is given
     missing = []
     if not cmd_backend_exist and not cfg_backend_exist and not cfg_backends_exist:
-        missing.append('-b/--backend')
+        if target_exist:
+            target_to_run = None
+            if oneutils.is_valid_attr(cfg_target_args, 'target'):
+                target_to_run = getattr(cfg_target_args, 'target')
+            # overwrite the value if it exists as command line option has higher priority.
+            if oneutils.is_valid_attr(args, 'target'):
+                target_to_run = args.target
+            given_backend = backends.get_backend_from_target_conf(target_to_run)
+            if not given_backend:
+                parser.error(f'Not found {target_to_run} target.')
+        else:
+            missing.append('[-b/--backend | -T/--target]')
     if len(missing):
         parser.error('the following arguments are required: ' + ' '.join(missing))
 
@@ -110,11 +128,11 @@ def _parse_arg(parser):
     if len(args) == 0:
         codegen_args = parser.parse_args(codegen_args)
     # one-codegen has two interfaces
-    # 1. one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND] [COMMANDS FOR BACKEND]
+    # 1. one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND | -T TARGET] [COMMANDS FOR BACKEND]
     if len(args) == 1:
         codegen_args = args[0]
         codegen_args, unknown_args = parser.parse_known_args(codegen_args)
-    # 2. one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND] -- [COMMANDS FOR BACKEND]
+    # 2. one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND | -T TARGET] -- [COMMANDS FOR BACKEND]
     if len(args) == 2:
         codegen_args = args[0]
         backend_args = args[1]
@@ -128,7 +146,7 @@ def _parse_arg(parser):
 
 def main():
     # get backend list
-    backends_list = backends.get_list('compile')
+    backends_list = backends.get_list('*-compile')
 
     # parse arguments
     parser = _get_parser(backends_list)
@@ -137,12 +155,14 @@ def main():
     # parse configuration file
     cfg_args = SimpleNamespace()
     oneutils.parse_cfg(args.config, 'one-codegen', cfg_args)
+    cfg_target_args = SimpleNamespace()
+    oneutils.parse_cfg(args.config, 'backend', cfg_target_args, quiet=True)
 
     # 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, cfg_args, backend_args, unknown_args)
+    _verify_arg(parser, args, cfg_args, cfg_target_args, backend_args, unknown_args)
     '''
     one-codegen defines its behavior for below cases.
 
@@ -158,10 +178,26 @@ def main():
     [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)
+    [11] one-codegen -C {cfg} (w/ target, w/ command schema)
+    [12] one-codegen -C {cfg} (w/ target, w/o command schema)
+    [13] one-codegen -C {cfg} -T {target} (w/ command schema)
+    [14] one-codegen -C {cfg} -T {target} (w/o command schema)
+    [15] one-codegen -T {target} ${command} (ignore command schema)
+    [16] one-codegen -T {target} -- ${command} (ignore command schema)
 
     All other cases are not allowed or an undefined behavior.
     '''
+    # decide target
+    target_to_run = None
+    if oneutils.is_valid_attr(cfg_target_args, 'target'):
+        target_to_run = getattr(cfg_target_args, 'target')
+    # overwrite the value if it exists as command line option has higher priority.
+    if oneutils.is_valid_attr(args, 'target'):
+        target_to_run = args.target
+
     cmd_overwrite = False
+    parser = None
+    # decide which backend to run
     if oneutils.is_valid_attr(args, 'config'):
         # [9], [10]
         if backend_args and not unknown_args:
@@ -175,42 +211,80 @@ def main():
                     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]
+                # get backend information
+                given_backend = backends.get_backend_from_target_conf(target_to_run)
+                # check if command schema for the backend exists
+                # 1. if it exists, run the command according to the schema.
+                # 2. if it doesn't exist, insert "--target ${TARGET}" at the beginning of the given command.
+                parser = oneutils.get_arg_parser(
+                    given_backend, cmd="codegen", target=target_to_run)
+                # [11], [13]
+                if target_to_run and parser:
+                    if oneutils.is_valid_attr(cfg_args, 'command'):
+                        given_backends = [given_backend]
+                        setattr(cfg_args, given_backend, cfg_args.command)
+                        # If "command" key exists with target option, command schema is not used. ${BACKEND}-compile will be run as before.
+                        print(
+                            "WARNING: 'command' key in the [one-codegen] will be deprecated as of September 1, 2025."
+                        )
+                    else:
+                        # DO NOTHING
+                        pass
+                # [12], [14]
+                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(',')
     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()
+        # [5], [6]
+        if oneutils.is_valid_attr(args, 'backend'):
+            given_backends = [args.backend]
+        # [15], [16]
         else:
-            codegen_cmd += backend_args
-            codegen_cmd += unknown_args
+            assert oneutils.is_valid_attr(args, 'target')
+            given_backends = [backends.get_backend_from_target_conf(target_to_run)]
 
+    # make commands
+    # 1. if command schema exists
+    if parser and not oneutils.is_valid_attr(cfg_args, 'command'):
+        codegen_cmd = parser.make_cmd(cfg_args)
         # run backend driver
-        oneutils.run(codegen_cmd, err_prefix=backend_base)
+        oneutils.run(codegen_cmd, err_prefix=parser.driver)
+    # 2. if command schema doesn't exist
+    else:
+        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]
+            # "--target" option is intentionally inserted at the beginning of the command.
+            # It would match the command of backends' tool.
+            if target_to_run:
+                codegen_cmd += ['--target', target_to_run]
+            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-create-quant-dataset b/compiler/one-cmds/one-create-quant-dataset
new file mode 100644 (file)
index 0000000..00a3244
--- /dev/null
@@ -0,0 +1,128 @@
+#!/usr/bin/env bash
+''''export SCRIPT_PATH="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)" # '''
+''''export PY_PATH=${SCRIPT_PATH}/venv/bin/python                                       # '''
+''''test -f ${PY_PATH} && exec ${PY_PATH} "$0" "$@"                                     # '''
+''''echo "Error: Virtual environment not found. Please run 'one-prepare-venv' command." # '''
+''''exit 255                                                                            # '''
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 h5py as h5
+import numpy as np
+import argparse
+import glob
+import os
+import onelib.utils as oneutils
+
+
+def get_parser():
+    """Create and return given the argument parser"""
+    parser = argparse.ArgumentParser(
+        description='command line tool to convert data files to hdf5 file')
+    parser.add_argument(
+        "-i",
+        "--input_data_format",
+        type=str,
+        help="Input data format of either rawdata or numpy",
+        choices=['rawdata', 'numpy'],
+        required=True)
+    parser.add_argument(
+        "-l",
+        "--data_list",
+        type=str,
+        help=
+        "Path to a text file which contains a list of absolute paths to data files. " + \
+        "For a multi-input model, input data files for the same inference call " + \
+        "have to be separated by space in the same line.",
+        required=True)
+    parser.add_argument(
+        "-p", "--output_path", type=str, help="Path to the output file.", required=True)
+    return parser
+
+
+def create_hdf5(input_data_format, data_list, output_path):
+    """Create the hdf5 file using given input data files listed in the data_list file"""
+    if not os.path.isfile(data_list):
+        raise FileNotFoundError("No such file. " + data_list)
+
+    h5_file = h5.File(output_path, 'w')
+    group = h5_file.create_group("value")
+
+    if input_data_format == 'rawdata':
+        # We assume the raw input data have the correct type/shape for the corresponding model
+        # If this flag is set in the hdf5 file, record-minmax will skip type/shape check
+        group.attrs['rawData'] = '1'
+
+    num_converted = 0
+
+    # Data list
+    datalist = []
+    with open(data_list, 'r') as f:
+        lines = f.readlines()
+        for line in lines:
+            if line.strip():
+                filenames = line.strip().split(' ')
+                # A single input can indicate multiple files (multi-input)
+                for filename in filenames:
+                    if not os.path.isfile(filename):
+                        raise FileNotFoundError("No such file. " + filename)
+                datalist.append(filenames)
+
+    # Input files
+    for input_files in datalist:
+        sample = group.create_group(str(num_converted))
+        for idx, input_file in enumerate(input_files):
+            if input_data_format == 'rawdata':  # rawdata2hdf5
+                with open(input_file, 'rb') as f:
+                    raw_data = bytearray(f.read())
+                    sample.create_dataset(str(idx), data=raw_data)
+            elif input_data_format == "numpy":  # numpy2hdf5
+                try:
+                    numpy_data = np.load(input_file)
+                    sample.create_dataset(str(idx), data=numpy_data)
+                except:
+                    raise RuntimeError(
+                        f"{input_file} is not loadable by np.load. Please check it is a numpy file."
+                    )
+            else:
+                raise RuntimeError("Unsupported input data format")
+
+        sample.attrs['desc'] = ','.join(
+            list(map(lambda x: os.path.basename(x), input_files)))
+        num_converted += 1
+
+    h5_file.close()
+
+    if input_data_format == 'rawdata':  # rawdata2hdf5
+        print("Raw data have been packaged to " + output_path)
+    elif input_data_format == 'numpy':  # numpy2hdf5
+        print("Numpy data have been packaged to " + output_path)
+    else:
+        raise RuntimeError("Unsupported input data format")
+
+    print("Number of packaged data: " + str(num_converted))
+
+
+def main():
+    # parse arguments
+    parser = get_parser()
+    args = parser.parse_args()
+
+    # Currently, we are only supporting the conversion to the form of hdf5.
+    create_hdf5(args.input_data_format, args.data_list, args.output_path)
+
+
+if __name__ == '__main__':
+    oneutils.safemain(main, __file__)
index b9c773b..c440e92 100644 (file)
@@ -70,21 +70,21 @@ class TidyIONames:
         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():
+                if '.' in name or ':' 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
+                    name_alt = name_alt.replace('/', '_')
+                    name_alt = 'a_' + name_alt  # prevent start with digit or _
                     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():
+            if '.' in name or ':' 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
+                name_alt = name_alt.replace('/', '_')
+                name_alt = 'a_' + name_alt
                 self.remap_outputs.append(name_alt)
 
     def update(self):
@@ -169,6 +169,12 @@ def _get_parser():
         'Ensure generated circle model preserves the I/O order of the original onnx model.'
     )
 
+    # force use onnx-tf for one-import-onnx-ext is installed
+    parser.add_argument(
+        '--disable_ext',
+        action='store_true',
+        help='Disable one-import-onnx-ext and use legacy onnx-tf package')
+
     # save intermediate file(s)
     parser.add_argument(
         '--save_intermediate',
@@ -218,7 +224,7 @@ 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
+# 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):
@@ -238,7 +244,12 @@ def _remap_io_names(onnx_model):
     remapper.update()
 
 
-def _check_ext():
+def _check_ext(args):
+    if oneutils.is_valid_attr(args, 'disable_ext'):
+        return None
+    env_disable_ext = os.getenv('ONE_IMPORT_ONNX_EXT_DISABLE')
+    if env_disable_ext == '1' or env_disable_ext == 'Y':
+        return None
     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)):
@@ -252,7 +263,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()
+    ext_path = _check_ext(args)
 
     with open(logfile_path, 'wb') as f, tempfile.TemporaryDirectory() as tmpdir:
         # save intermediate
index f2ddc78..63ce3db 100644 (file)
@@ -310,7 +310,7 @@ def _get_model_type(parser, args):
 
 def main():
     # get backend list
-    backends_list = backends.get_list('init')
+    backends_list = backends.get_list('*-init')
 
     # parse arguments
     parser = _get_parser(backends_list)
index a456a6b..6d40fd0 100644 (file)
@@ -34,10 +34,11 @@ fi
 # - 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=1.16.0
+VER_ONNXRUNTIME=1.18.0
 VER_ONNX_TF=1.10.0
 VER_PYDOT=1.4.2
+VER_TORCH="2.1.2+cpu"
 
 # Install tensorflow
 
@@ -69,16 +70,14 @@ ${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.
-#      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}"
+# NOTE set ONE_PREPVENV_TORCH_SOURCE to override options for source URL.
+TORCH_SOURCE_OPTION="-f https://download.pytorch.org/whl/torch_stable.html"
+if [[ ! -z "$ONE_PREPVENV_TORCH_SOURCE" ]]; then
+  TORCH_SOURCE_OPTION="${ONE_PREPVENV_TORCH_SOURCE}"
 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+cpu -f ${TORCH_STABLE_URL}
+echo "Torch from '${ONE_PREPVENV_TORCH_SOURCE}' -> '${TORCH_SOURCE_OPTION}'"
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install torch==${VER_TORCH} ${TORCH_SOURCE_OPTION}
 
 ${VENV_PYTHON} -m pip ${PIP_OPTIONS} install onnx==${VER_ONNX}
 
index c8850df..6edc8f5 100644 (file)
@@ -34,10 +34,11 @@ fi
 # - 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=1.16.0
+VER_ONNXRUNTIME=1.18.0
 VER_ONNX_TF=1.10.0
 VER_PYDOT=1.4.2
+VER_TORCH="2.1.2+cpu"
 
 # Install tensorflow
 
@@ -110,16 +111,14 @@ 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}"
+# NOTE set ONE_PREPVENV_TORCH_SOURCE to override options for source URL.
+TORCH_SOURCE_OPTION="-f https://download.pytorch.org/whl/torch_stable.html"
+if [[ ! -z "$ONE_PREPVENV_TORCH_SOURCE" ]]; then
+  TORCH_SOURCE_OPTION="${ONE_PREPVENV_TORCH_SOURCE}"
 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}
+echo "Torch from '${ONE_PREPVENV_TORCH_SOURCE}' -> '${TORCH_SOURCE_OPTION}'"
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install torch==${VER_TORCH} ${TORCH_SOURCE_OPTION}
 
 ${VENV_PYTHON} -m pip ${PIP_OPTIONS} install onnx==${VER_ONNX}
 
index 55c79c6..2be3b02 100644 (file)
@@ -34,10 +34,11 @@ fi
 # - 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=1.16.0
+VER_ONNXRUNTIME=1.18.0
 VER_ONNX_TF=1.10.0
 VER_PYDOT=1.4.2
+VER_TORCH="2.1.2+cpu"
 
 # Install tensorflow
 
@@ -69,16 +70,14 @@ ${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.
-#      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}"
+# NOTE set ONE_PREPVENV_TORCH_SOURCE to override options for source URL.
+TORCH_SOURCE_OPTION="-f https://download.pytorch.org/whl/torch_stable.html"
+if [[ ! -z "$ONE_PREPVENV_TORCH_SOURCE" ]]; then
+  TORCH_SOURCE_OPTION="${ONE_PREPVENV_TORCH_SOURCE}"
 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+cpu -f ${TORCH_STABLE_URL}
+echo "Torch from '${ONE_PREPVENV_TORCH_SOURCE}' -> '${TORCH_SOURCE_OPTION}'"
+${VENV_PYTHON} -m pip ${PIP_OPTIONS} install torch==${VER_TORCH} ${TORCH_SOURCE_OPTION}
 
 ${VENV_PYTHON} -m pip ${PIP_OPTIONS} install onnx==${VER_ONNX}
 
index bc5338d..9296e51 100644 (file)
@@ -26,8 +26,10 @@ import itertools
 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
@@ -74,7 +76,7 @@ def _get_backends_list():
 
 
 def _get_parser(backends_list):
-    profile_usage = 'one-profile [-h] [-v] [-C CONFIG] [-b BACKEND] [--] [COMMANDS FOR BACKEND]'
+    profile_usage = 'one-profile [-h] [-v] [-C CONFIG] [-b BACKEND | -T TARGET] [--] [COMMANDS FOR BACKEND]'
     parser = argparse.ArgumentParser(
         description='command line tool for profiling backend model', usage=profile_usage)
 
@@ -89,20 +91,38 @@ def _get_parser(backends_list):
             backends_name) + ')'
     backend_help_message = 'backend name to use ' + backends_name_message
     parser.add_argument('-b', '--backend', type=str, help=backend_help_message)
+    parser.add_argument(
+        '-T', '--target', type=str, help='run with specific target of the backend')
 
     return parser
 
 
-def _verify_arg(parser, args, cfg_args, backend_args, unknown_args):
+def _verify_arg(parser, args, cfg_args, cfg_target_args, backend_args, unknown_args):
     """verify given arguments"""
     cmd_backend_exist = oneutils.is_valid_attr(args, 'backend')
+    cmd_target_exist = oneutils.is_valid_attr(args, 'target')
+    if cmd_backend_exist and cmd_target_exist:
+        parser.error(
+            '\'backend\' option and \'target\' option cannot be used simultaneously.')
     cfg_backend_exist = oneutils.is_valid_attr(cfg_args, 'backend')
     cfg_backends_exist = oneutils.is_valid_attr(cfg_args, 'backends')
+    target_exist = cmd_target_exist or oneutils.is_valid_attr(cfg_target_args, 'target')
 
     # check if required arguments is given
     missing = []
     if not cmd_backend_exist and not cfg_backend_exist and not cfg_backends_exist:
-        missing.append('-b/--backend')
+        if target_exist:
+            target_to_run = None
+            if oneutils.is_valid_attr(cfg_target_args, 'target'):
+                target_to_run = getattr(cfg_target_args, 'target')
+            # overwrite the value if it exists as command line option has higher priority.
+            if oneutils.is_valid_attr(args, 'target'):
+                target_to_run = args.target
+            given_backend = backends.get_backend_from_target_conf(target_to_run)
+            if not given_backend:
+                parser.error(f'Not found {target_to_run} target.')
+        else:
+            missing.append('[-b/--backend | -T/--target]')
     if len(missing):
         parser.error('the following arguments are required: ' + ' '.join(missing))
 
@@ -146,11 +166,11 @@ def _parse_arg(parser):
     if len(args) == 0:
         profile_args = parser.parse_args(profile_args)
     # one-profile has two interfaces
-    # 1. one-profile [-h] [-v] [-C CONFIG] [-b BACKEND] [COMMANDS FOR BACKEND]
+    # 1. one-profile [-h] [-v] [-C CONFIG] [-b BACKEND | -T TARGET] [COMMANDS FOR BACKEND]
     if len(args) == 1:
         profile_args = args[0]
         profile_args, unknown_args = parser.parse_known_args(profile_args)
-    # 2. one-profile [-h] [-v] [-C CONFIG] [-b BACKEND] -- [COMMANDS FOR BACKEND]
+    # 2. one-profile [-h] [-v] [-C CONFIG] [-b BACKEND | -T TARGET] -- [COMMANDS FOR BACKEND]
     if len(args) == 2:
         profile_args = args[0]
         backend_args = args[1]
@@ -173,9 +193,11 @@ def main():
     # parse configuration file
     cfg_args = SimpleNamespace()
     oneutils.parse_cfg(args.config, 'one-profile', cfg_args)
+    cfg_target_args = SimpleNamespace()
+    oneutils.parse_cfg(args.config, 'backend', cfg_target_args, quiet=True)
 
     # verify arguments
-    _verify_arg(parser, args, cfg_args, backend_args, unknown_args)
+    _verify_arg(parser, args, cfg_args, cfg_target_args, backend_args, unknown_args)
     '''
     one-profile defines its behavior for below cases.
 
@@ -191,10 +213,26 @@ def main():
     [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)
+    [11] one-profile -C {cfg} (w/ target, w/ command schema)
+    [12] one-profile -C {cfg} (w/ target, w/o command schema)
+    [13] one-profile -C {cfg} -T {target} (w/ command schema)
+    [14] one-profile -C {cfg} -T {target} (w/o command schema)
+    [15] one-profile -T {target} ${command}
+    [16] one-profile -T {target} -- ${command}
 
     All other cases are not allowed or an undefined behavior.
     '''
+    # decide target
+    target_to_run = None
+    if oneutils.is_valid_attr(cfg_target_args, 'target'):
+        target_to_run = getattr(cfg_target_args, 'target')
+    # overwrite the value if it exists as command line option has higher priority.
+    if oneutils.is_valid_attr(args, 'target'):
+        target_to_run = args.target
+
     cmd_overwrite = False
+    parser = None
+    # decide which backend to run
     if oneutils.is_valid_attr(args, 'config'):
         # [9], [10]
         if backend_args and not unknown_args:
@@ -208,38 +246,77 @@ def main():
                     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]
+                # get backend information
+                given_backend = backends.get_backend_from_target_conf(target_to_run)
+                # check if command schema exists
+                # 1. if it exists, run the command according to the schema.
+                # 2. if it doesn't exist, insert "--target ${TARGET}" at the beginning of the given command.
+                parser = oneutils.get_arg_parser(
+                    given_backend, cmd="profile", target=target_to_run)
+                # [11], [13]
+                if target_to_run and parser:
+                    if oneutils.is_valid_attr(cfg_args, 'command'):
+                        given_backends = [given_backend]
+                        setattr(cfg_args, given_backend, cfg_args.command)
+                        # If "command" key exists with target option, command schema is not used. ${BACKEND}-profile will be run as before.
+                        print(
+                            "WARNING: 'command' key in the [one-profile] will be deprecated as of September 1, 2025."
+                        )
+                    else:
+                        # DO NOTHING
+                        pass
+                # [12], [14]
+                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(',')
     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()
+        # [5], [6]
+        if oneutils.is_valid_attr(args, 'backend'):
+            given_backends = [args.backend]
+        # [15], [16]
         else:
-            profile_cmd += backend_args
-            profile_cmd += unknown_args
+            assert oneutils.is_valid_attr(args, 'target')
+            given_backends = [backends.get_backend_from_target_conf(target_to_run)]
+
+    # make commands
+    # 1. if command schema exists
+    if parser and not oneutils.is_valid_attr(cfg_args, 'command'):
+        profile_cmd = parser.make_cmd(cfg_args)
 
         # run backend driver
-        oneutils.run(profile_cmd, err_prefix=backend_base)
+        oneutils.run(profile_cmd, err_prefix=parser.driver)
+    # 2. if command schema doesn't exist
+    else:
+        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]
+            # "--target" option is intentionally inserted at the beginning of the command.
+            # It would match the command of backends' tool.
+            if target_to_run:
+                profile_cmd += ['--target', target_to_run]
+            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__':
index f686aad..a7dc591 100644 (file)
@@ -45,16 +45,16 @@ def _get_parser():
         '-d',
         '--input_data',
         type=str,
-        help=
-        'full filepath of the input data used for post-training quantization. if not specified, run with random input data.'
-    )
+        help="""full filepath of the input data used for post-training quantization. if not
+        specified, run with random input data.""")
     parser.add_argument(
         '-f',
         '--input_data_format',
         type=str,
         help=
-        'file format of input data. h5/hdf5 (default), list/filelist (a text file where a file path of input data is written in each line), or dir/directory (a directory where input data are saved)'
-    )
+        """file format of input data. h5/hdf5 (default), list/filelist (a text file where
+        a file path of input data is written in each line), or dir/directory (a directory
+        where input data are saved)""")
     parser.add_argument(
         '-o',
         '--output_path',
@@ -80,9 +80,8 @@ def _get_parser():
     quantization_group.add_argument(
         '--input_dtype',
         type=str,
-        help=
-        'input model data type (supported: float32, default=float32). Deprecated (Use input_model_dtype)'
-    )
+        help="""input model data type (supported: float32, default=float32).
+        Deprecated (Use input_model_dtype)""")
     quantization_group.add_argument(
         '--input_model_dtype',
         type=str,
@@ -95,83 +94,91 @@ def _get_parser():
     quantization_group.add_argument(
         '--granularity',
         type=str,
-        help='quantization granularity (supported: layer, channel, default=layer)')
+        help="""weight quantization granularity (supported: layer, channel, default=layer).
+        Activation is quantized per layer.""")
     quantization_group.add_argument(
         '--input_type',
         type=str,
-        help=
-        'data type of inputs of quantized model (supported: uint8, int16, float32, default=quantized_dtype). QUANTIZE Op will be inserted at the beginning of the quantized model if input_type is different from quantized_dtype.'
-    )
+        help="""data type of inputs of quantized model (supported: uint8, int16, float32,
+        default=quantized_dtype). QUANTIZE Op will be inserted at the beginning of
+        the quantized model if input_type is different from quantized_dtype.""")
     quantization_group.add_argument(
         '--output_type',
         type=str,
-        help=
-        'data type of outputs of quantized model (supported: uint8, int16, float32, default=quantized_dtype). QUANTIZE Op will be inserted at the end of the quantized model if output_type is different from quantized_dtype.'
-    )
+        help="""data type of outputs of quantized model (supported: uint8, int16, float32,
+        default=quantized_dtype). QUANTIZE Op will be inserted at the end of the
+        quantized model if output_type is different from quantized_dtype.""")
     quantization_group.add_argument(
         '--min_percentile',
         type=str,
         help=
-        'minimum percentile (0.0~100.0, default=1.0). Algorithm parameter for calibration. This is valid when calibration algorithm is percentile.'
-    )
+        """minimum percentile (0.0~100.0, default=1.0). Algorithm parameter for calibration.
+        This is valid when calibration algorithm is percentile.""")
     quantization_group.add_argument(
         '--max_percentile',
         type=str,
         help=
-        'maximum percentile (0.0~100.0, default=99.0). Algorithm parameter for calibration. This is valid when calibration algorithm is percentile.'
-    )
+        """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.'
-    )
+        """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.'
-    )
+        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=
-        "calibration algorithm for post-training quantization (supported: percentile/moving_average, default=percentile). 'percentile' mode uses the n-th percentiles as min/max values. 'moving_average' mode records the moving average of min/max."
-    )
+        help="""calibration algorithm for post-training quantization (supported:
+        percentile/moving_average, default=percentile). 'percentile' mode uses the n-th
+        percentiles as min/max values. 'moving_average' mode records the moving average
+        of min/max.""")
     quantization_group.add_argument(
         '--TF-style_maxpool',
         action='store_true',
         help=
-        "Force MaxPool Op to have the same input/output quantparams. NOTE: This option can degrade accuracy of some models.)"
-    )
+        """Force MaxPool Op to have the same input/output quantparams. NOTE: This option can
+        degrade accuracy of some models.)""")
+    quantization_group.add_argument(
+        '--save_min_max',
+        action='store_true',
+        help="""Save min/max of each tensor. NOTE: Min/max valuse are clipped according to
+        calibration algorithms, such as percentile or moving average. Nudge adjustment is
+        not applied.""")
     quantization_group.add_argument(
         '--quant_config', type=str, help="Path to the quantization configuration file.")
     quantization_group.add_argument(
         '--evaluate_result',
         action='store_true',
         help=
-        "Evaluate accuracy of quantized model. Run inference for both fp32 model and the quantized model, and compare the inference results."
-    )
+        """Evaluate accuracy of quantized model. Run inference for both fp32 model and the
+        quantized model, and compare the inference results.""")
     quantization_group.add_argument(
         '--test_data', type=str, help="Path to the test data used for evaluation.")
     quantization_group.add_argument(
         '--print_mae',
         action='store_true',
         help=
-        "Print MAE (Mean Absolute Error) of inference results between quantized model and fp32 model."
-    )
+        """Print MAE (Mean Absolute Error) of inference results between quantized model and
+        fp32 model.""")
     quantization_group.add_argument(
         '--print_mape',
         action='store_true',
         help=
-        "Print MAPE (Mean Absolute Percentage Error) of inference results between quantized model and fp32 model."
-    )
+        """Print MAPE (Mean Absolute Percentage Error) of inference results between quantized
+        model and fp32 model.""")
     quantization_group.add_argument(
         '--print_mpeir',
         action='store_true',
         help=
-        "Print MPEIR (Mean Peak Error to Interval Ratio) of inference results between quantized model and fp32 model."
-    )
+        """Print MPEIR (Mean Peak Error to Interval Ratio) of inference results between quantized
+        model and fp32 model.""")
     quantization_group.add_argument(
         '--print_top1_match',
         action='store_true',
@@ -250,11 +257,21 @@ def _get_parser():
 
     # ampq_algorithm
     ampq_quant_group.add_argument(
-        '--ampq_algorithm', type=str, help='type of algorithm (bisection)')
+        '--ampq_algorithm', type=str, help='type of algorithm (bisection, pattern)')
 
     ampq_quant_group.add_argument(
         '--bisection_type', type=str, help="one of 'auto', 'i16_front', 'i16_back'")
 
+    ampq_quant_group.add_argument(
+        '--u8_layernorm_with_s16_variance',
+        action='store_true',
+        help='Use int16 for computing variance in uint8 layer normalization')
+
+    ampq_quant_group.add_argument(
+        '--u8_softmax_with_s16_sub_exp',
+        action='store_true',
+        help='Use int16 for computing Sub and Exp nodes in uint8 Softmax')
+
     # ampq_bisection_visq
     ampq_quant_group.add_argument(
         '--ampq_bisection_visq',
@@ -508,6 +525,8 @@ def _quantize(args):
             circle_quantizer_cmd.append(getattr(args, 'granularity'))
         if oneutils.is_valid_attr(args, 'TF-style_maxpool'):
             circle_quantizer_cmd.append('--TF-style_maxpool')
+        if oneutils.is_valid_attr(args, 'save_min_max'):
+            circle_quantizer_cmd.append('--save_min_max')
         if oneutils.is_valid_attr(args, 'input_type'):
             circle_quantizer_cmd.append('--input_type')
             circle_quantizer_cmd.append(getattr(args, 'input_type'))
@@ -783,6 +802,12 @@ def _ampq_solve(args):
                         ampq_quantize_cmd.extend(['--bisection', 'true'])
                     elif bisection_type == 'i16_back':
                         ampq_quantize_cmd.extend(['--bisection', 'false'])
+            elif algorithm == 'pattern':
+                ampq_quantize_cmd.append('--patterns')
+                if oneutils.is_valid_attr(args, 'u8_layernorm_with_s16_variance'):
+                    ampq_quantize_cmd.append('--u8_layernorm_with_s16_variance')
+                if oneutils.is_valid_attr(args, 'u8_softmax_with_s16_sub_exp'):
+                    ampq_quantize_cmd.append('--u8_softmax_with_s16_sub_exp')
 
         # recorded model as input
         ampq_quantize_cmd.extend(['--input_model', tmp_minmax_recorded_path])
@@ -799,6 +824,26 @@ def _ampq_solve(args):
         if oneutils.is_valid_attr(args, 'output_path'):
             ampq_quantize_cmd.extend(['--output_model', getattr(args, 'output_path')])
 
+        # quantized model dtype
+        if oneutils.is_valid_attr(args, 'quantized_dtype'):
+            ampq_quantize_cmd.extend(
+                ['--quantized_dtype',
+                 getattr(args, 'quantized_dtype')])
+
+        # granularity
+        if oneutils.is_valid_attr(args, 'granularity'):
+            ampq_quantize_cmd.extend(['--granularity', getattr(args, 'granularity')])
+
+        # TF-style_maxpool
+        if oneutils.is_valid_attr(args, 'TF-style_maxpool'):
+            ampq_quantize_cmd.append('--TF-style_maxpool')
+
+        # save_min_max
+        if oneutils.is_valid_attr(args, 'save_min_max'):
+            ampq_quantize_cmd.append('--save_min_max')
+
+        # TODO Add config
+
         # visq_file
         if not (visq_file is None):
             ampq_quantize_cmd.extend(['--visq_file', visq_file])
index c7a76c5..dbbd4d0 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import argparse
-import configparser
+from argparse import ArgumentParser
+from configparser import ConfigParser
 import os
-import subprocess
 import sys
 from types import SimpleNamespace
+from typing import List
 
 from onelib.CfgRunner import CfgRunner
 from onelib.WorkflowRunner import WorkflowRunner
@@ -33,48 +33,37 @@ import onelib.utils as oneutils
 # TODO Find better way to suppress trackback on error
 sys.tracebacklimit = 0
 
-subtool_list = {
-    'compile': {
-        'import': 'Convert given model to circle',
-        'optimize': 'Optimize circle model',
-        'quantize': 'Quantize circle model',
-    },
-    'package': {
-        'pack': 'Package circle and metadata into nnpackage',
-    },
-    'backend': {
-        'codegen': 'Code generation tool',
-        'profile': 'Profile backend model file',
-        'infer': 'Infer backend model file'
-    },
-}
-
-
-def _call_driver(driver_name, options):
-    dir_path = os.path.dirname(os.path.realpath(__file__))
-    driver_path = os.path.join(dir_path, driver_name)
-    cmd = [driver_path] + options
-    oneutils.run(cmd)
-
-
-def _check_subtool_exists():
-    """verify given arguments"""
-    subtool_keys = [n for k, v in subtool_list.items() for n in v.keys()]
-    if len(sys.argv) > 1 and sys.argv[1] in subtool_keys:
-        driver_name = 'one-' + sys.argv[1]
-        options = sys.argv[2:]
-        _call_driver(driver_name, options)
-        sys.exit(0)
-
-
-def _get_parser():
-    onecc_usage = 'onecc [-h] [-v] [-C CONFIG] [-b BACKEND] [-W WORKFLOW] [-O OPTIMIZATION] [COMMAND <args>]'
+
+def run_subtools():
+    """
+    Run one-cmds tools directly.
+
+    _onecc_ allows users to run one-cmds tools directly as well as using configuraiton files.
+
+    E.g. $ onecc -C ${CFG_FILE}
+         $ onecc import tflite -i ${INPUT} -o ${OUTPUT} ## HERE
+        
+    Please refer to above `subtool_list` for the support list of sub-tools.
+    
+    This function checks if given sub-tool exists and run it directly.
+    """
+    subtool_keys: List[str] = oneutils.one_cmd_list()
+    if len(sys.argv) > 1:
+        one_cmd = sys.argv[1]
+        options: List[str] = sys.argv[2:]
+        if one_cmd in subtool_keys:
+            oneutils.run(options, one_cmd=one_cmd)
+            sys.exit(0)
+
+
+def get_parser():
+    onecc_usage = 'onecc [-h] [-v] [-C CONFIG | -W WORKFLOW] [-b BACKEND | -T TARGET] [-O OPTIMIZATION] [COMMAND <args>]'
     onecc_desc = 'Run ONE driver via several commands or configuration file'
-    parser = argparse.ArgumentParser(description=onecc_desc, usage=onecc_usage)
+    parser = ArgumentParser(description=onecc_desc, usage=onecc_usage)
 
     oneutils.add_default_arg(parser)
 
-    opt_name_list = oneutils.get_optimization_list(get_name=True)
+    opt_name_list: List[str] = oneutils.get_optimization_list(get_name=True)
     opt_name_list = ['-' + s for s in opt_name_list]
     if not opt_name_list:
         opt_help_message = '(No available optimization options)'
@@ -90,23 +79,32 @@ def _get_parser():
     parser.add_argument(
         '-b', '--backend', type=str, help='generate code for given backend')
 
+    target_name_list: List[str] = oneutils.get_target_list(get_name=True)
+    if not target_name_list:
+        target_help_message = '(No available target)'
+    else:
+        target_help_message = '(Available target: ' + ', '.join(target_name_list) + ')'
+    target_help_message = 'run with specific target of the backend ' + target_help_message
+    parser.add_argument('-T', '--target', type=str, help=target_help_message)
+
     # just for help message
     compile_group = parser.add_argument_group('compile to circle model')
-    for tool, desc in subtool_list['compile'].items():
+    ONE_CMD = oneutils.ONE_CMD
+    for tool, desc in ONE_CMD['compile'].items():
         compile_group.add_argument(tool, action='store_true', help=desc)
 
     package_group = parser.add_argument_group('package circle model')
-    for tool, desc in subtool_list['package'].items():
+    for tool, desc in ONE_CMD['package'].items():
         package_group.add_argument(tool, action='store_true', help=desc)
 
     backend_group = parser.add_argument_group('run backend tools')
-    for tool, desc in subtool_list['backend'].items():
+    for tool, desc in ONE_CMD['backend'].items():
         backend_group.add_argument(tool, action='store_true', help=desc)
 
     return parser
 
 
-def _parse_arg(parser):
+def parse_arg(parser: ArgumentParser):
     args = parser.parse_args()
     # print version
     if args.version:
@@ -115,14 +113,11 @@ def _parse_arg(parser):
     return args
 
 
-def _verify_backend_args(parser, args):
+def verify_backend_args(parser: ArgumentParser, args):
     """
-    verify one-profile, one-codegen arguments
-
-    This verification logic comes from each drivers' codes.
+    Verify arguments for backend tools.
     """
-    cfgparser = configparser.ConfigParser()
-    cfgparser.optionxform = str
+    cfgparser: ConfigParser = oneutils.get_config_parser()
     cfgparser.read(args.config)
 
     for driver in ['one-profile', 'one-codegen']:
@@ -157,14 +152,14 @@ def _verify_backend_args(parser, args):
                     parser.error('Not found the command of given backend')
 
 
-def _verify_arg(parser, args):
-    """verify given arguments"""
+def verify_arg(parser: ArgumentParser, args):
+    """Verify given arguments"""
     # check if required arguments is given
     if not oneutils.is_valid_attr(args, 'config') and not oneutils.is_valid_attr(
             args, 'workflow'):
         parser.error('-C/--config or -W/--workflow argument is required')
     # check if given optimization option exists
-    opt_name_list = oneutils.get_optimization_list(get_name=True)
+    opt_name_list: List[str] = oneutils.get_optimization_list(get_name=True)
     opt_name_list = [oneutils.remove_prefix(s, 'O') for s in opt_name_list]
     if oneutils.is_valid_attr(args, 'O'):
         if ' ' in getattr(args, 'O'):
@@ -175,38 +170,29 @@ def _verify_arg(parser, args):
     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') and oneutils.is_valid_attr(args, 'target'):
+        parser.error(
+            '\'backend\' and \'target\' are mutually exclusive option. \'target\' option automatically set a backend.'
+        )
 
     if oneutils.is_valid_attr(args, 'backend'):
-        _verify_backend_args(parser, args)
+        verify_backend_args(parser, args)
 
 
 def main():
-    # check if there is subtool argument
-    # if true, it executes subtool with argv
-    # NOTE:
-    # Why call subtool directly without using Argparse?
-    # Because if Argparse is used, options equivalent to onecc including
-    # '--help', '-C' are processed directly onecc itself.
-    # So options cannot be delivered to subtool.
-    _check_subtool_exists()
-
-    # parse arguments
-    # since the configuration file path is required first,
-    # parsing of the configuration file proceeds after this.
-    parser = _get_parser()
-    args = _parse_arg(parser)
-
-    # verify arguments
-    _verify_arg(parser, args)
+    run_subtools()
+
+    parser: ArgumentParser = get_parser()
+    args = parse_arg(parser)
+    verify_arg(parser, args)
 
     bin_dir = os.path.dirname(os.path.realpath(__file__))
     if oneutils.is_valid_attr(args, 'config'):
         runner = CfgRunner(args.config)
         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.add_opt(getattr(args, 'O', None))
+        runner.set_backend(getattr(args, 'backend', None))
+        runner.set_target(getattr(args, 'target', None))
         runner.run(bin_dir)
     elif oneutils.is_valid_attr(args, 'workflow'):
         runner = WorkflowRunner(args.workflow)
index c9968b4..8bc1e2a 100644 (file)
@@ -2,6 +2,10 @@
 [Environment]
 ONECC_ENV="ONECC"
 
+[backend]
+; codename of the target
+target=
+
 ; To activate a step (or task),
 ; set True for the step in [onecc] section and fill options in the corresponding section
 [onecc]
index 3a7b5fc..1327252 100644 (file)
@@ -14,8 +14,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import configparser
 import os
+from typing import Optional
 import warnings
 
 import onelib.utils as oneutils
@@ -34,9 +34,7 @@ class CfgRunner:
     def __init__(self, path):
         self.path = path
         self.optparser = None
-        self.cfgparser = configparser.ConfigParser()
-        # make option names case sensitive
-        self.cfgparser.optionxform = str
+        self.cfgparser = oneutils.get_config_parser()
         parsed = self.cfgparser.read(os.path.expanduser(path))
         if not parsed:
             raise FileNotFoundError('Not found given configuration file')
@@ -57,6 +55,10 @@ class CfgRunner:
                 self.add_opt(o[1:])
 
         self.backend = None
+        self.target = None
+        if self.cfgparser.has_section('backend'):
+            if 'target' in self.cfgparser['backend']:
+                self.target = self.cfgparser['backend']['target']
 
     def _verify_cfg(self, cfgparser):
         if not cfgparser.has_section('onecc'):
@@ -73,10 +75,10 @@ class CfgRunner:
             'onecc', driver)) or (self.cfgparser.has_option('one-build', driver)
                                   and self.cfgparser.getboolean('one-build', driver))
 
-    def add_opt(self, opt):
-        self.optparser = configparser.ConfigParser()
-        # make option names case sensitive
-        self.optparser.optionxform = str
+    def add_opt(self, opt: Optional[str]):
+        if not opt:
+            return
+        self.optparser = oneutils.get_config_parser()
         opt_book = dict(
             zip(oneutils.get_optimization_list(get_name=True),
                 oneutils.get_optimization_list()))
@@ -90,9 +92,12 @@ class CfgRunner:
             )
         self.opt = opt
 
-    def set_backend(self, backend: str):
+    def set_backend(self, backend: Optional[str]):
         self.backend = backend
 
+    def set_target(self, target: Optional[str]):
+        self.target = target
+
     def detect_import_drivers(self, dir):
         self.import_drivers = list(oneutils.detect_one_import_drivers(dir).keys())
 
@@ -116,6 +121,8 @@ class CfgRunner:
                 options.append('--verbose')
             if (section == 'one-codegen' or section == 'one-profile') and self.backend:
                 options += ['-b', self.backend]
+            if (section == 'one-codegen' or section == 'one-profile') and self.target:
+                options += ['-T', self.target]
             driver_path = os.path.join(working_dir, section)
             cmd = [driver_path] + options
             oneutils.run(cmd)
diff --git a/compiler/one-cmds/onelib/argumentparse.py b/compiler/one-cmds/onelib/argumentparse.py
new file mode 100644 (file)
index 0000000..f140061
--- /dev/null
@@ -0,0 +1,233 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 is for the command schema feature.
+
+_one-cmds_ has lots of tools such as one-import, one-optimize, etc.
+They have their own section in the configuration file and users can 
+ give arguments with key-value pairs.
+But, backend tools such as one-codegen and one-profile hasn't the same
+ mechanism. Rather, they should pass all the arguments with `command` key
+ because _onecc_ can't know the backends' interface in advance.
+
+The command schema has been introduced for resolving these difficulties.
+If users provide _onecc_ with the command schema that describes the interface 
+ of the backend, users can give arguments with key-value paris like other tools.
+
+NOTE. Command schema feature works only when target option is given.
+
+[AS-IS]
+
+# example.cfg
+[backend]
+target=my_target
+
+[one-codegen]
+backend=my_backend
+commnad=--output sample.tvn sample.circle
+
+[TO-BE]
+
+# /usr/share/one/backends/command/my_backend/codegen.py
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("my_backend-compile", action=DriverName)
+    parser.add_argument("--output", action=NormalOption)
+    parser.add_argument("input", action=NormalOption)
+
+    return parser
+
+# /usr/share/one/target/my_target.ini
+TARGET=my_target
+BACKEND=my_backend
+
+# example.cfg
+[one-codegen]
+output=sample.tvn
+input=sample.circle
+
+
+---
+
+Command schema file should define `command_schema` function. And, you can add
+ arguments by calling `add_argument`. You should specify an action according to
+the option category.
+
+[Action List]
+- DriverName: the name of backend driver
+- TargetOption: the target option of the drvier.
+- NormalOption: the option of the driver. Starting with dash('-') implies the option
+ is optional rather than positional one.
+"""
+
+import ntpath
+from types import SimpleNamespace
+from typing import List, Tuple, Union, Type
+import shutil
+
+import onelib.backends as backends
+import onelib.utils as oneutils
+
+
+class Action():
+    pass
+
+
+class DriverName(Action):
+    pass
+
+
+class NormalOption(Action):
+    pass
+
+
+class TargetOption(Action):
+    pass
+
+
+class Option():
+    pass
+
+
+class Positional(Option):
+    pass
+
+
+class Optional(Option):
+    pass
+
+
+class ArgumentParser():
+    _SUPPORTED_ACTION_TYPE = [DriverName, NormalOption, TargetOption]
+
+    def __init__(self):
+        # List[args, action type, data type, option type]
+        self._actions: List[Tuple[Tuple[str], Action, Union[Type[str], Type[
+            bool]]]] = list()
+        self.driver: str = None
+        self.target: str = None
+
+    def print_help(self):
+        backends_list = backends.get_list(self.driver)
+        driver_path = None
+        for cand in backends_list:
+            if ntpath.basename(cand) == self.driver:
+                driver_path = cand
+        if not driver_path:
+            driver_path = shutil.which(self.driver)
+
+        if not driver_path:
+            raise FileNotFoundError(self.driver + ' not found')
+
+        oneutils.run([driver_path, '-h'], err_prefix=self.driver)
+
+    def check_if_valid_option_name(self, *args, **kwargs):
+        if not 'action' in kwargs:
+            raise RuntimeError('"action" keyword argument is required')
+
+        action = kwargs['action']
+        if not action in self._SUPPORTED_ACTION_TYPE:
+            raise RuntimeError('Invalid action')
+        if not args:
+            raise RuntimeError('Invalid option name')
+        if action == DriverName and len(args) >= 2:
+            raise RuntimeError('onecc doesn\'t support multiple driver name')
+
+        dtype = kwargs.get('dtype', str)
+        if dtype == bool and action != NormalOption:
+            raise RuntimeError('Only normal option can be boolean type')
+        if dtype == bool and not all(a.startswith('-') for a in args):
+            raise RuntimeError('Boolean type option should start with dash("-")')
+
+    def add_argument(self, *args, **kwargs):
+        self.check_if_valid_option_name(*args, **kwargs)
+
+        action = kwargs['action']
+        dtype = kwargs.get('dtype', str)
+        if action == DriverName:
+            assert len(args) == 1
+            self.driver = args[0]
+        else:
+            if all(a.startswith('-') for a in args):
+                otype = Optional
+            elif all(not a.startswith('-') for a in args):
+                otype = Positional
+            else:
+                raise RuntimeError(
+                    'Invalid option names. Only either of option type is allowed: positional or optional'
+                )
+            self._actions.append((args, kwargs['action'], dtype, otype))
+
+    def make_cmd(self, cfg_args: SimpleNamespace) -> List:
+        assert self.target, "Target should be set before making commands"
+        assert self.driver, "Driver should be set before making commands"
+        # find driver path
+        driver_name = self.driver
+        driver_list = backends.get_list(driver_name)
+        if not driver_list:
+            driver_list = [shutil.which(driver_name)]
+            if not driver_list:
+                raise FileNotFoundError(f'{driver_name} not found')
+        # use first driver
+        driver_path = driver_list[0]
+        cmd: List = [driver_path]
+        invalid_options = list(cfg_args.__dict__.keys())
+        # traverse the action in order and make commands
+        for action in self._actions:
+            args, act, dtype, otype = action
+            assert act in [NormalOption, TargetOption]
+            if otype == Optional:
+                option_names = []
+                for arg in args:
+                    if arg.startswith('--'):
+                        option_names.append(arg[len('--'):])
+                    elif arg.startswith('-'):
+                        option_names.append(arg[len('-'):])
+            elif otype == Positional:
+                option_names = args
+            else:
+                assert False
+
+            given_option = None
+            if act == NormalOption:
+                for option_name in option_names:
+                    if oneutils.is_valid_attr(cfg_args, option_name):
+                        given_option = option_name
+                        break
+                if not given_option:
+                    continue
+                if dtype == bool and given_option.lower() == "false":
+                    continue
+            if otype == Optional:
+                # use first option
+                cmd += [args[0]]
+            if act == TargetOption:
+                cmd += [self.target]
+            else:
+                assert act == NormalOption
+                if dtype == str:
+                    cmd += [getattr(cfg_args, given_option)]
+                invalid_options.remove(given_option)
+
+        if len(invalid_options):
+            print(f'WARNING: there are invalid options {invalid_options}')
+            self.print_help()
+        return cmd
index 9d7dad1..362c8e8 100644 (file)
@@ -17,6 +17,8 @@
 import glob
 import ntpath
 import os
+
+import onelib.utils as oneutils
 """
 [one hierarchy]
 one
@@ -42,11 +44,10 @@ def get_list(cmdname):
     backend_set = set()
 
     # bin folder
-    files = [f for f in glob.glob(dir_path + '/../*-' + cmdname)]
+    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)
+        f for f in glob.glob(dir_path + '/../../backends/**/' + cmdname, recursive=True)
     ]
     # TODO find backends in `$PATH`
 
@@ -61,6 +62,28 @@ def get_list(cmdname):
     return backends_list
 
 
+def get_backend_from_target_conf(target: str):
+    dir_path = os.path.dirname(os.path.realpath(__file__))
+    target_conf_path = dir_path + f'/../../target/{target}.ini'
+    if not os.path.isfile(target_conf_path):
+        return None
+
+    # target config doesn't have section.
+    # but, configparser needs configs to have one or more sections.
+    DUMMY_SECTION = 'dummy_section'
+    with open(target_conf_path, 'r') as f:
+        config_str = f'[{DUMMY_SECTION}]\n' + f.read()
+    parser = oneutils.get_config_parser()
+    parser.read_string(config_str)
+    assert parser.has_section(DUMMY_SECTION)
+
+    BACKEND_KEY = 'BACKEND'
+    if BACKEND_KEY in parser[DUMMY_SECTION]:
+        return parser[DUMMY_SECTION][BACKEND_KEY]
+
+    return None
+
+
 def search_driver(driver):
     dir_path = os.path.dirname(os.path.realpath(__file__))
 
index 90109ef..8c5de1b 100644 (file)
@@ -29,30 +29,45 @@ class CONSTANT:
         'fold_dwconv',
         'fold_fully_connected',
         'fold_gather',
+        'fold_mul',
+        'fold_reshape',
+        'fold_shape',
         'fold_sparse_to_dense',
+        'fold_squeeze',
 
         # Operator fusion
+        'fuse_add_to_fullyconnected_bias',
+        'fuse_add_with_conv',
         'fuse_add_with_tconv',
         'fuse_add_with_fully_connected',
         'fuse_batchnorm_with_conv',
         'fuse_batchnorm_with_dwconv',
         'fuse_batchnorm_with_tconv',
         'fuse_activation_function',
+        'fuse_mul_to_fullyconnected_weights',
         'fuse_instnorm',
         'fuse_prelu',
         'fuse_gelu',
+        'fuse_rsqrt',
         'fuse_mean_with_mean',
+        'fuse_mul_with_conv',
+        'fuse_mul_with_div',
         'fuse_transpose_with_mean',
+        'fuse_slice_with_tconv',
+        'fuse_horizontal_fc_layers',
         'transform_min_max_to_relu6',
         'transform_min_relu_to_relu6',
 
         # Remove redundant operators
         'remove_redundant_reshape',
         'remove_redundant_transpose',
+        'remove_unnecessary_add',
         'remove_unnecessary_reshape',
         'remove_unnecessary_slice',
         'remove_unnecessary_strided_slice',
         'remove_unnecessary_split',
+        'remove_unnecessary_transpose',
+        'common_subexpression_elimination',
 
         # Canonicalization
         # (passes to help further optimization)
@@ -70,6 +85,8 @@ class CONSTANT:
         'forward_reshape_to_unaryop',
         'forward_transpose_op',
         'replace_non_const_fc_with_batch_matmul',  # For quantization
+        'replace_with_fc_gelu_fc',
+        'transform_sqrt_div_to_rsqrt_mul',
     )
 
     OPTIMIZATION_OPTS = (
@@ -77,6 +94,7 @@ class CONSTANT:
         ('convert_nchw_to_nhwc',
          'Experimental: This will convert NCHW operators to NHWC under the assumption that input model is NCHW.'
          ),
+        ('common_subexpression_elimination', 'perform common subexpression elimination'),
         ('expand_broadcast_const', 'expand broadcastable constant node inputs'),
         ('nchw_to_nhwc_input_shape',
          'convert the input shape of the model (argument for convert_nchw_to_nhwc)'),
@@ -89,20 +107,34 @@ class CONSTANT:
         ('fold_dwconv', 'fold Depthwise Convolution op with constant inputs'),
         ('fold_fully_connected', 'fold FullyConnected op with constant inputs'),
         ('fold_gather', 'fold Gather op'),
+        ('fold_mul', 'fold Mul Op'),
+        ('fold_reshape', 'fold Reshape op'),
+        ('fold_shape', 'fold Shape op'),
         ('fold_sparse_to_dense', 'fold SparseToDense op'),
+        ('fold_squeeze', 'fold Squeeze op'),
         ('forward_reshape_to_unaryop', 'Forward Reshape op'),
         ('forward_transpose_op', 'Forward Transpose op'),
+        ('fuse_add_to_fullyconnected_bias',
+         'Fuse Add op to following FullyConnected op bias'),
+        ('fuse_add_with_conv', 'fuse Add op to Convolution op'),
         ('fuse_add_with_tconv', 'fuse Add op to Transposed'),
         ('fuse_add_with_fully_connected', 'fuse Add op to FullyConnected op'),
         ('fuse_batchnorm_with_conv', 'fuse BatchNorm op to Convolution op'),
         ('fuse_batchnorm_with_dwconv', 'fuse BatchNorm op to Depthwise Convolution op'),
         ('fuse_batchnorm_with_tconv', 'fuse BatchNorm op to Transposed Convolution op'),
+        ('fuse_mul_to_fullyconnected_weights',
+         'fuse Mul op to following FullyConnected op weights'),
+        ('fuse_slice_with_tconv', 'fuse Slice op to Transposed Convolution op'),
         ('fuse_bcq', 'apply Binary Coded Quantization'),
         ('fuse_preactivation_batchnorm',
          'fuse BatchNorm operators of pre-activations to Convolution op'),
         ('fuse_mean_with_mean', 'fuse two consecutive Mean ops'),
+        ('fuse_mul_with_conv', 'fuse Mul op to Convolution op'),
+        ('fuse_mul_with_div', 'fuse Mul with Div as Div'),
         ('fuse_transpose_with_mean',
          'fuse Mean with a preceding Transpose under certain conditions'),
+        ('fuse_horizontal_fc_layers',
+         'fuse horizontal FullyConnected layers under certain conditions'),
         ('make_batchnorm_gamma_positive',
          'make negative gamma of BatchNorm to a small positive value (1e-10).'
          ' Note that this pass can change the execution result of the model.'
@@ -111,20 +143,27 @@ class CONSTANT:
         ('fuse_instnorm', 'fuse ops to InstanceNorm operator'),
         ('fuse_prelu', 'fuse ops to PReLU operator'),
         ('fuse_gelu', 'fuse ops to GeLU operator'),
+        ('fuse_rsqrt', 'fuse ops to Rsqrt operator'),
         ('replace_cw_mul_add_with_depthwise_conv',
          'replace channel-wise Mul/Add with DepthwiseConv2D'),
         ('remove_fakequant', 'remove FakeQuant ops'),
+        ('remove_gather_guard',
+         'remove Add/FloorMod guards of Gather indices with certain conditions. '
+         'CAUTION: user must guarantee that indices are all non-negative values.'),
         ('remove_quantdequant', 'remove Quantize-Dequantize sequence'),
         ('remove_redundant_quantize', 'remove redundant Quantize ops'),
         ('remove_redundant_reshape', 'fuse or remove subsequent Reshape ops'),
         ('remove_redundant_transpose', 'fuse or remove subsequent Transpose ops'),
+        ('remove_unnecessary_add', 'remove unnecessary add ops'),
         ('remove_unnecessary_reshape', 'remove unnecessary reshape ops'),
         ('remove_unnecessary_slice', 'remove unnecessary slice ops'),
         ('remove_unnecessary_strided_slice', 'remove unnecessary strided slice ops'),
         ('remove_unnecessary_split', 'remove unnecessary split ops'),
+        ('remove_unnecessary_transpose', 'remove unnecessary transpose ops'),
         ('replace_non_const_fc_with_batch_matmul',
          'replace FullyConnected op with non-const weights to BatchMatMul op'),
         ('replace_sub_with_add', 'replace Sub op with Add op'),
+        ('replace_with_fc_gelu_fc', 'replace a certain pattern with FC-Gelu-FC ops'),
         ('resolve_customop_add', 'convert Custom(Add) op to Add op'),
         ('resolve_customop_batchmatmul',
          'convert Custom(BatchMatmul) op to BatchMatmul op'),
@@ -145,7 +184,11 @@ 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'),
+        ('transform_sqrt_div_to_rsqrt_mul',
+         'transform Sqrt-Div pattern to Rsqrt-Mul ops'),
         ('decompose_hardswish', 'decompose the HardSwish op to Add, Mul and Relu6 ops'),
+        ('decompose_softmax',
+         'decompose the Softmax op to Max, Sub, Exp, Sum, Div and optionally Mul ops'),
         ('unroll_unidirseqlstm', 'unroll UnidirectionalSequenceLSTM op'),
         ('dynamic_batch_to_single_batch',
          'convert dynamic batch size (first dimension) of inputs to 1'))
index f7a1a96..da1faff 100644 (file)
@@ -24,9 +24,37 @@ import os
 import subprocess
 import sys
 
-from typing import Union
-
-import onelib.constant as _constant
+from typing import Union, Optional
+
+from onelib.argumentparse import ArgumentParser
+"""
+Support commands in the one-cmds.
+
+{ 
+  ${GROUP} : {
+    ${CMD} : EXPLANATIONS
+  }
+}
+"""
+ONE_CMD = {
+    'compile': {
+        'import': 'Convert given model to circle',
+        'optimize': 'Optimize circle model',
+        'quantize': 'Quantize circle model',
+    },
+    'package': {
+        'pack': 'Package circle and metadata into nnpackage',
+    },
+    'backend': {
+        'codegen': 'Code generation tool',
+        'profile': 'Profile backend model file',
+        'infer': 'Infer backend model file'
+    },
+}
+
+
+def one_cmd_list():
+    return [cmd for group, cmds in ONE_CMD.items() for cmd in cmds.keys()]
 
 
 def add_default_arg(parser):
@@ -84,21 +112,39 @@ def is_valid_attr(args, attr):
     return hasattr(args, attr) and getattr(args, attr)
 
 
-def parse_cfg(config_path: Union[str, None], section_to_parse: str, args):
+def get_config_parser() -> configparser.ConfigParser:
+    """
+    Initialize configparser and set default option
+
+    This funciton has been introduced for all the one-cmds tools having same parsing option.
+    """
+    parser = configparser.ConfigParser(inline_comment_prefixes=('#', ';'))
+    parser.optionxform = str
+
+    return parser
+
+
+def parse_cfg(config_path: Union[str, None],
+              section_to_parse: str,
+              args,
+              quiet: bool = False):
     """
     parse configuration file and store the information to args
     
     :param config_path: path to configuration file
     :param section_to_parse: section name to parse
     :param args: object to store the parsed information
+    :param quiet: raise no error when given section doesn't exist
     """
     if config_path is None:
         return
 
-    parser = configparser.ConfigParser()
-    parser.optionxform = str
+    parser = get_config_parser()
     parser.read(config_path)
 
+    if not parser.has_section(section_to_parse) and quiet:
+        return
+
     if not parser.has_section(section_to_parse):
         raise AssertionError('configuration file must have \'' + section_to_parse +
                              '\' section')
@@ -135,14 +181,22 @@ def safemain(main, mainpath):
         sys.exit(255)
 
 
-def run(cmd, err_prefix=None, logfile=None):
+def run(cmd, *, one_cmd: str = None, err_prefix=None, logfile=None):
     """Execute command in subprocess
 
     Args:
+        one_cmd: subtool name to execute with given `cmd`
         cmd: command to be executed in subprocess
         err_prefix: prefix to be put before every stderr lines
         logfile: file stream to which both of stdout and stderr lines will be written
     """
+    if one_cmd:
+        assert one_cmd in one_cmd_list(), f'Invalid ONE COMMAND: {one_cmd}'
+        dir_path = os.path.dirname(os.path.dirname(
+            os.path.realpath(__file__)))  # bin = onelib/../
+        driver_path = os.path.join(dir_path, f'one-{one_cmd}')
+        cmd = [driver_path] + cmd
+
     with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as p:
         import select
         inputs = set([p.stdout, p.stderr])
@@ -220,6 +274,68 @@ def get_optimization_list(get_name=False):
     return opt_list
 
 
+def get_target_list(get_name=False):
+    """
+    returns a list of targets. If `get_name` is True,
+    only basename without extension is returned rather than full file path.
+
+    [one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test
+
+    Target configuration files must be placed in `target` folder
+    """
+    dir_path = os.path.dirname(os.path.realpath(__file__))
+
+    # target folder
+    files = [f for f in glob.glob(dir_path + '/../../target/*.ini', recursive=True)]
+    # exclude if the name has space
+    files = [s for s in files if not ' ' in s]
+
+    target_list = []
+    for cand in files:
+        if os.path.isfile(cand) and os.access(cand, os.R_OK):
+            target_list.append(cand)
+
+    if get_name == True:
+        target_list = [ntpath.basename(f) for f in target_list]
+        target_list = [remove_suffix(s, '.ini') for s in target_list]
+
+    return target_list
+
+
+def get_arg_parser(backend: Optional[str], cmd: str,
+                   target: Optional[str]) -> Optional[ArgumentParser]:
+    if not backend:
+        return None
+
+    dir_path = os.path.dirname(os.path.realpath(__file__))
+    # for python module naming convention
+    command_schema_path = dir_path + f'/../../backends/command/{backend}/{cmd}.py'
+    if not os.path.isfile(command_schema_path):
+        return None
+
+    # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
+    spec = importlib.util.spec_from_file_location(cmd, command_schema_path)
+    module = importlib.util.module_from_spec(spec)
+    sys.modules[cmd] = module
+    spec.loader.exec_module(module)
+
+    if not hasattr(module, "command_schema"):
+        raise RuntimeError('You must implement "command_schema" function')
+
+    parser: ArgumentParser = module.command_schema()
+    parser.target = target
+    return parser
+
+
 def detect_one_import_drivers(search_path):
     """Looks for import drivers in given directory
 
index 8c006c1..9f343a9 100644 (file)
@@ -6,6 +6,8 @@ file(GLOB CONFIGITEMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "./*.cfg")
 file(GLOB QCONFIGITEMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "./*.qconf.json")
 file(GLOB PYSCRIPTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "./*.py")
 file(GLOB WORKFLOWITEMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "./*.workflow.json")
+file(GLOB PYTHONITEMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "./*.py")
+file(GLOB TARGETCONFITEMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "./*.ini")
 
 # Create a script to run the tests at installation folder
 set(DRIVER_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/runtestall.sh")
@@ -57,6 +59,16 @@ foreach(WORKFLOWITEM IN ITEMS ${WORKFLOWITEMS})
   install(FILES ${WORKFLOWITEM} DESTINATION test)
 endforeach(WORKFLOWITEM)
 
+foreach(PYTHONITEM IN ITEMS ${PYTHONITEMS})
+  get_filename_component(ITEM_PREFIX ${PYTHONITEM} NAME_WE)
+  install(FILES ${PYTHONITEM} DESTINATION test)
+endforeach(PYTHONITEM)
+
+foreach(TARGETCONFITEM IN ITEMS ${TARGETCONFITEMS})
+  get_filename_component(ITEM_PREFIX ${TARGETCONFITEM} NAME_WE)
+  install(FILES ${TARGETCONFITEM} DESTINATION test)
+endforeach(TARGETCONFITEM)
+
 file(APPEND "${DRIVER_SCRIPT}" "popd > /dev/null\n\n")
 
 file(APPEND "${DRIVER_SCRIPT}"
@@ -70,6 +82,7 @@ fi\n
 
 set(PREPARE_TEST_MATERIALS_SH "${CMAKE_CURRENT_SOURCE_DIR}/prepare_test_materials.sh")
 set(PREPROCESS_IMAGES_PY "${CMAKE_CURRENT_SOURCE_DIR}/preprocess_images.py")
+set(PREPROCESS_IMAGES_NUMPY_PY "${CMAKE_CURRENT_SOURCE_DIR}/preprocess_images_numpy.py")
 set(ONNX_LEGALIZE_RUN_COMPARE "${CMAKE_CURRENT_SOURCE_DIR}/onnx_legalize_run_compare.py")
 set(PRINT_ONNX_MODEL "${CMAKE_CURRENT_SOURCE_DIR}/print_onnx_model.py")
 
@@ -91,6 +104,12 @@ install(FILES ${PREPROCESS_IMAGES_PY}
                     WORLD_READ
         DESTINATION test)
 
+install(FILES ${PREPROCESS_IMAGES_NUMPY_PY}
+        PERMISSIONS OWNER_WRITE OWNER_READ
+                    GROUP_READ
+                    WORLD_READ
+        DESTINATION test)
+        
 install(FILES ${ONNX_LEGALIZE_RUN_COMPARE}
         PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
         GROUP_READ GROUP_EXECUTE
@@ -116,6 +135,7 @@ endif(ENABLE_ONE_IMPORT_PYTORCH)
 get_filename_component(ONE_CMDS_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
 set(ONE_PYTHON_DIR "onelib")
 set(CONSTANT_EXPORTING_SCRIPT "${ONE_CMDS_DIR}/${ONE_PYTHON_DIR}/export_constant.py")
+set(CONSTANT_SCRIPT "${ONE_CMDS_DIR}/${ONE_PYTHON_DIR}/constant.py")
 set(O1_OPTION "O1")
 set(O1_TXT_FILE "${O1_OPTION}.list")
 set(O1_TXT_FILE_BIN "${CMAKE_CURRENT_BINARY_DIR}/${O1_TXT_FILE}")
@@ -125,7 +145,7 @@ set(NON_O1_TXT_FILE_BIN "${CMAKE_CURRENT_BINARY_DIR}/${NON_O1_TXT_FILE}")
 add_custom_command(OUTPUT ${O1_TXT_FILE_BIN}
   COMMAND ${PYTHON_EXECUTABLE} ${CONSTANT_EXPORTING_SCRIPT} --constant ${O1_OPTION}
                                     --format txt --output_path ${O1_TXT_FILE_BIN}
-  DEPENDS ${CONSTANT_EXPORTING_SCRIPT}
+  DEPENDS ${CONSTANT_EXPORTING_SCRIPT} ${CONSTANT_SCRIPT}
   COMMENT "Generate ${O1_TXT_FILE}"
 )
 
@@ -133,7 +153,7 @@ add_custom_command(OUTPUT ${NON_O1_TXT_FILE_BIN}
   COMMAND ${PYTHON_EXECUTABLE} ${CONSTANT_EXPORTING_SCRIPT} --constant ${O1_OPTION}
                                     --format txt --output_path ${NON_O1_TXT_FILE_BIN}
                                     --exclusive
-  DEPENDS ${CONSTANT_EXPORTING_SCRIPT}
+  DEPENDS ${CONSTANT_EXPORTING_SCRIPT} ${CONSTANT_SCRIPT}
   COMMENT "Generate ${NON_O1_TXT_FILE}"
 )
 
diff --git a/compiler/one-cmds/tests/OONE-BUILD_014.cfg b/compiler/one-cmds/tests/OONE-BUILD_014.cfg
deleted file mode 100644 (file)
index a39aae0..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-[one-optimize]
-make_batchnorm_gamma_positive=True
diff --git a/compiler/one-cmds/tests/one-build_001.cfg b/compiler/one-cmds/tests/one-build_001.cfg
deleted file mode 100644 (file)
index b022ba7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=True
-one-quantize=False
-one-pack=False
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v2
-
-[one-optimize]
-input_path=inception_v3.circle
-output_path=inception_v3.opt.circle
diff --git a/compiler/one-cmds/tests/one-build_001.test b/compiler/one-cmds/tests/one-build_001.test
deleted file mode 100644 (file)
index e6c6ee7..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tf -> one-optimize
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_001.cfg"
-outputfile="inception_v3.opt.circle"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-
-# run test
-one-build -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/one-build_002.cfg b/compiler/one-cmds/tests/one-build_002.cfg
deleted file mode 100644 (file)
index bbf0915..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=True
-one-quantize=False
-one-pack=True
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v2
-
-[one-optimize]
-input_path=inception_v3.circle
-output_path=inception_v3.opt.circle
-
-[one-pack]
-input_path=inception_v3.opt.circle
-output_path=inception_v3_pkg
diff --git a/compiler/one-cmds/tests/one-build_002.test b/compiler/one-cmds/tests/one-build_002.test
deleted file mode 100644 (file)
index c29d422..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tf -> one-optimize -> one-pack
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_002.cfg"
-outputfile="inception_v3_pkg"
-
-rm -f ${filename}.log
-rm -rf ${outputfile}
-
-# run test
-one-build -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/one-build_003.cfg b/compiler/one-cmds/tests/one-build_003.cfg
deleted file mode 100644 (file)
index 6aec3ca..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=False
-one-quantize=True
-one-pack=False
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v1
-
-[one-quantize]
-input_path=inception_v3.circle
-output_path=inception_v3.quantized.circle
-input_data=inception_v3_test_data.h5
diff --git a/compiler/one-cmds/tests/one-build_003.test b/compiler/one-cmds/tests/one-build_003.test
deleted file mode 100644 (file)
index 6337b50..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tf -> one-quantize
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_003.cfg"
-outputfile="inception_v3.quantized.circle"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-
-# run test
-one-build -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/one-build_004.cfg b/compiler/one-cmds/tests/one-build_004.cfg
deleted file mode 100644 (file)
index c23405b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=False
-one-quantize=False
-one-pack=False
-one-codegen=True
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v1
-
-[one-codegen]
-backend=dummy
-command=-o sample.tvn inception_v3.circle
diff --git a/compiler/one-cmds/tests/one-build_004.test b/compiler/one-cmds/tests/one-build_004.test
deleted file mode 100644 (file)
index 5406355..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tf -> one-codegen
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  rm -rf ../bin/dummy-compile
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_004.cfg"
-outputfile="sample.tvn"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-
-# copy dummy-compile to bin folder
-cp dummy-compile ../bin/dummy-compile
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-if [[ ! -s "${outputfile}" ]]; then
-  trap_err_onexit
-fi
-
-rm -rf ../bin/dummy-compile
-
-echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_005.cfg b/compiler/one-cmds/tests/one-build_005.cfg
deleted file mode 100644 (file)
index 841b372..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-[one-build]
-one-import-tf=False
-one-import-tflite=True
-one-import-bcq=False
-one-optimize=True
-one-quantize=False
-one-pack=False
-one-codegen=True
-
-[one-import-tflite]
-input_path=inception_v3.tflite
-output_path=inception_v3.circle
-
-[one-optimize]
-input_path=inception_v3.circle
-output_path=inception_v3.opt.circle
-
-[one-codegen]
-backend=dummy
-command=-o sample.tvn inception_v3.opt.circle
diff --git a/compiler/one-cmds/tests/one-build_005.test b/compiler/one-cmds/tests/one-build_005.test
deleted file mode 100644 (file)
index f003be5..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tflite -> one-optimize -> one-codgen
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  rm -rf ../bin/dummy-compile
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_005.cfg"
-outputfile="sample.tvn"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-
-# copy dummy-compile to bin folder
-cp dummy-compile ../bin/dummy-compile
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-if [[ ! -s "${outputfile}" ]]; then
-  trap_err_onexit
-fi
-
-rm -rf ../bin/dummy-compile
-
-echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_006.cfg b/compiler/one-cmds/tests/one-build_006.cfg
deleted file mode 100644 (file)
index e754bde..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=True
-one-quantize=True
-one-pack=False
-one-codegen=True
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v1
-
-[one-optimize]
-input_path=inception_v3.circle
-output_path=inception_v3.opt.circle
-
-[one-quantize]
-input_path=inception_v3.opt.circle
-output_path=inception_v3.quantized.circle
-input_data=inception_v3_test_data.h5
-
-[one-codegen]
-backend=dummy
-command=-o sample.tvn inception_v3.quantized.circle
diff --git a/compiler/one-cmds/tests/one-build_006.test b/compiler/one-cmds/tests/one-build_006.test
deleted file mode 100644 (file)
index 0777015..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tf -> one-optimize -> one-quantize -> one-codegen
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  rm -rf ../bin/dummy-compile
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_006.cfg"
-outputfile="sample.tvn"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-
-# copy dummy-compile to bin folder
-cp dummy-compile ../bin/dummy-compile
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-if [[ ! -s "${outputfile}" ]]; then
-  trap_err_onexit
-fi
-
-rm -rf ../bin/dummy-compile
-
-echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_007.cfg b/compiler/one-cmds/tests/one-build_007.cfg
deleted file mode 100644 (file)
index 5261075..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=False
-one-quantize=True
-one-pack=True
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v1
-
-[one-optimize]
-input_path=inception_v3.circle
-output_path=inception_v3.opt.circle
-
-[one-quantize]
-input_path=inception_v3.opt.circle
-output_path=inception_v3.quantized.circle
-input_data=inception_v3_test_data.h5
-
-[one-pack]
-input_path=inception_v3.quantized.circle
-output_path=inception_v3_pkg
diff --git a/compiler/one-cmds/tests/one-build_007.test b/compiler/one-cmds/tests/one-build_007.test
deleted file mode 100644 (file)
index 4fd6a2a..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tf -> one-optimize -> one-quantize -> one-pack
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_007.cfg"
-outputfile="inception_v3_pkg"
-
-rm -f ${filename}.log
-rm -rf ${outputfile}
-
-# run test
-one-build -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/one-build_008.cfg b/compiler/one-cmds/tests/one-build_008.cfg
deleted file mode 100644 (file)
index 8c777f6..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-[one-build]
-one-import-tf=False
-one-import-tflite=False
-one-import-bcq=False
-one-import-onnx=True
-one-optimize=True
-one-quantize=False
-one-pack=False
-one-codegen=True
-
-[one-import-onnx]
-input_path=test_onnx_model.onnx
-output_path=test_onnx_model.circle
-
-[one-optimize]
-input_path=test_onnx_model.circle
-output_path=test_onnx_model.opt.circle
-remove_redundant_transpose=True
-
-[one-codegen]
-backend=dummy
-command=-o test_onnx_model.bin test_onnx_model.opt.circle
diff --git a/compiler/one-cmds/tests/one-build_008.test b/compiler/one-cmds/tests/one-build_008.test
deleted file mode 100644 (file)
index d19b95f..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tf -> one-optimize -> one-quantize -> one-codegen
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  rm -rf ../bin/dummy-compile
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_008.cfg"
-outputfile="test_onnx_model.bin"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-
-# copy dummy-compile to bin folder
-cp dummy-compile ../bin/dummy-compile
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-if [[ ! -s "${outputfile}" ]]; then
-  trap_err_onexit
-fi
-
-rm -rf ../bin/dummy-compile
-
-echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_009.cfg b/compiler/one-cmds/tests/one-build_009.cfg
deleted file mode 100644 (file)
index b5a35dd..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-[one-build]
-one-import-tf=False
-one-import-tflite=False
-one-import-bcq=False
-one-import-onnx=True
-one-optimize=True
-one-quantize=False
-one-pack=False
-one-codegen=True
-
-[one-import-onnx]
-input_path=onnx_conv2d_conv2d.onnx
-output_path=onnx_conv2d_conv2d.circle
-
-[one-optimize]
-input_path=onnx_conv2d_conv2d.circle
-output_path=onnx_conv2d_conv2d.opt.circle
-remove_redundant_transpose=True
-convert_nchw_to_nhwc=True
-
-[one-codegen]
-backend=dummy
-command=-o onnx_conv2d_conv2d.bin onnx_conv2d_conv2d.opt.circle
diff --git a/compiler/one-cmds/tests/one-build_009.test b/compiler/one-cmds/tests/one-build_009.test
deleted file mode 100644 (file)
index ae53519..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-onnx -> one-optimize -> one-codegen
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  rm -rf ../bin/dummy-compile
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_009.cfg"
-outputfile="onnx_conv2d_conv2d.bin"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-
-# copy dummy-compile to bin folder
-cp dummy-compile ../bin/dummy-compile
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-if [[ ! -s "${outputfile}" ]]; then
-  trap_err_onexit
-fi
-
-rm -rf ../bin/dummy-compile
-
-echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_010.cfg b/compiler/one-cmds/tests/one-build_010.cfg
deleted file mode 100644 (file)
index 3be9ed3..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=False
-one-quantize=False
-one-pack=False
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.alt.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v1
-save_intermediate=True
diff --git a/compiler/one-cmds/tests/one-build_010.test b/compiler/one-cmds/tests/one-build_010.test
deleted file mode 100644 (file)
index b76e81c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tf: intermediate file should exist
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_010.cfg"
-outputfile="inception_v3.alt.circle"
-intermfile="inception_v3.alt.tflite"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-rm -f ${intermfile}
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-if [[ ! -s "${outputfile}" ]]; then
-  trap_err_onexit
-fi
-if [[ ! -s "${intermfile}" ]]; then
-  trap_err_onexit
-fi
-
-echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_011.cfg b/compiler/one-cmds/tests/one-build_011.cfg
deleted file mode 100644 (file)
index 15d2c10..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-[one-build]
-one-import-tf=False
-one-import-tflite=False
-one-import-bcq=False
-one-import-onnx=True
-one-optimize=False
-one-quantize=False
-one-pack=False
-one-codegen=False
-
-[one-import-onnx]
-input_path=test_onnx_model.onnx
-output_path=test_onnx_model.circle
-save_intermediate=True
diff --git a/compiler/one-cmds/tests/one-build_011.test b/compiler/one-cmds/tests/one-build_011.test
deleted file mode 100644 (file)
index efd7143..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-onnx
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_011.cfg"
-outputfile="test_onnx_model.circle"
-intermfile="test_onnx_model.tflite"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-rm -f ${intermfile}
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-if [[ ! -s "${outputfile}" ]]; then
-  trap_err_onexit
-fi
-if [[ ! -s "${intermfile}" ]]; then
-  trap_err_onexit
-fi
-
-echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_012.cfg b/compiler/one-cmds/tests/one-build_012.cfg
deleted file mode 100644 (file)
index 74b0a0c..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=False
-one-quantize=True
-one-pack=False
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v1
-
-[one-quantize]
-input_path=inception_v3.circle
-output_path=inception_v3.list.quantized.circle
-input_data=datalist.txt
-input_data_format=list
diff --git a/compiler/one-cmds/tests/one-build_012.test b/compiler/one-cmds/tests/one-build_012.test
deleted file mode 100644 (file)
index 5f123cd..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tf -> one-quantize
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_012.cfg"
-outputfile="inception_v3.list.quantized.circle"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-
-# run test
-one-build -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/one-build_013.cfg b/compiler/one-cmds/tests/one-build_013.cfg
deleted file mode 100644 (file)
index 8e9e40e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=False
-one-quantize=True
-one-pack=False
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v1
-
-[one-quantize]
-input_path=inception_v3.circle
-output_path=inception_v3.dir.quantized.circle
-input_data=raw_files
-input_data_format=directory
diff --git a/compiler/one-cmds/tests/one-build_013.test b/compiler/one-cmds/tests/one-build_013.test
deleted file mode 100644 (file)
index 9a71f02..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# one-import-tf -> one-quantize
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_013.cfg"
-outputfile="inception_v3.dir.quantized.circle"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-
-# run test
-one-build -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/one-build_014.cfg b/compiler/one-cmds/tests/one-build_014.cfg
deleted file mode 100644 (file)
index f09145e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-import-onnx=False
-one-optimize=True
-one-quantize=False
-one-pack=False
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v1
-
-[one-optimize]
-input_path=inception_v3.circle
-output_path=inception_v3.opt.circle
-make_batchnorm_gamma_positive=False
diff --git a/compiler/one-cmds/tests/one-build_014.test b/compiler/one-cmds/tests/one-build_014.test
deleted file mode 100644 (file)
index 10e6cc6..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# Use `OONE-BUILD_014` optimization option
-
-: '
-This test assumes below directories.
-
-[one hierarchy]
-    one
-    â”œâ”€â”€ backends
-    â”œâ”€â”€ bin
-    â”œâ”€â”€ doc
-    â”œâ”€â”€ include
-    â”œâ”€â”€ lib
-    â”œâ”€â”€ optimization
-    â””── test # pwd
-'
-
-OPT_ALREADY_EXIST=true
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-clean_envir()
-{
-  rm -rf ../optimization/OONE-BUILD_014.cfg
-  if [ "$OPT_ALREADY_EXIST" = false ]; then
-    rm -rf ../optimization
-  fi
-}
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  clean_envir
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_014.cfg"
-outputfile="inception_v3.opt.circle"
-
-rm -f ${filename}.log
-rm -f ${outputfile}
-
-if [ ! -d "../optimization" ]; then
-  mkdir -p ../optimization
-  OPT_ALREADY_EXIST=false
-fi
-
-cp OONE-BUILD_014.cfg ../optimization
-
-# run test
-LUCI_LOG=5 one-build -C ${configfile} -OONE-BUILD_014 > ${filename}.log 2>&1
-
-clean_envir
-
-if ! grep -q "MakeBatchNormGammaPositivePass" "${filename}.log"; then
-    echo "${filename_ext} SUCCESS"
-    exit 0
-fi
-
-trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-build_neg_001.test b/compiler/one-cmds/tests/one-build_neg_001.test
deleted file mode 100644 (file)
index 2ea26d2..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# negative usage with missing configuration file
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  if grep -q "Not found given 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-build_neg_001.cfg"
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-echo "${filename_ext} FAILED"
-exit 255
diff --git a/compiler/one-cmds/tests/one-build_neg_002.cfg b/compiler/one-cmds/tests/one-build_neg_002.cfg
deleted file mode 100644 (file)
index 99db966..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=True
-one-quantize=False
-one-pack=True
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v2
-
-[one-optimize]
-input_path=inception_v3.circle
-output_path=inception_v3.opt.circle
diff --git a/compiler/one-cmds/tests/one-build_neg_002.test b/compiler/one-cmds/tests/one-build_neg_002.test
deleted file mode 100644 (file)
index dece9c0..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# negative usage with missing one-pack section in configuration file
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  if grep -q "configuration file must have 'one-pack' section" "${filename}.log"; then
-    echo "${filename_ext} SUCCESS"
-    exit 0
-  fi
-
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_neg_002.cfg"
-
-rm -f ${filename}.log
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-echo "${filename_ext} FAILED"
-exit 255
diff --git a/compiler/one-cmds/tests/one-build_neg_003.cfg b/compiler/one-cmds/tests/one-build_neg_003.cfg
deleted file mode 100644 (file)
index fa027cb..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v2
-
-[one-optimize]
-input_path=inception_v3.circle
-output_path=inception_v3.opt.circle
-
-[one-pack]
-input_path=inception_v3.opt.circle
-output_path=inception_v3_pkg
diff --git a/compiler/one-cmds/tests/one-build_neg_003.test b/compiler/one-cmds/tests/one-build_neg_003.test
deleted file mode 100644 (file)
index c793d13..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# negative usage with missing one-build section in configuration file
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  if grep -q "\[one-build\] section is required in configuraion file" "${filename}.log"; then
-    echo "${filename_ext} SUCCESS"
-    exit 0
-  fi
-
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_neg_003.cfg"
-
-rm -f ${filename}.log
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-echo "${filename_ext} FAILED"
-exit 255
diff --git a/compiler/one-cmds/tests/one-build_neg_004.cfg b/compiler/one-cmds/tests/one-build_neg_004.cfg
deleted file mode 100644 (file)
index 571077b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=True
-one-quantize=False
-one-pack=False
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v2
-
-[one-optimize]
-input_path=inception_v3.circle
-output_path=inception_v3.opt.circle
-
-[one-optimize]
-input_path=inception_v4.circle
-output_path=inception_v4.opt.circle
diff --git a/compiler/one-cmds/tests/one-build_neg_004.test b/compiler/one-cmds/tests/one-build_neg_004.test
deleted file mode 100644 (file)
index b0d4e61..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# negative usage with duplicate section
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  if grep -q "section 'one-optimize' already exists" "${filename}.log"; then
-    echo "${filename_ext} SUCCESS"
-    exit 0
-  fi
-
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_neg_004.cfg"
-
-rm -f ${filename}.log
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-echo "${filename_ext} FAILED"
-exit 255
diff --git a/compiler/one-cmds/tests/one-build_neg_005.cfg b/compiler/one-cmds/tests/one-build_neg_005.cfg
deleted file mode 100644 (file)
index ad9efbc..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-[one-build]
-one-import-tf=True
-one-import-tflite=False
-one-import-bcq=False
-one-optimize=False
-one-quantize=False
-one-pack=False
-one-codegen=False
-
-[one-import-tf]
-input_path=inception_v3.pb
-output_path=inception_v3.alt.circle
-input_arrays=input
-input_shapes=1,299,299,3
-output_arrays=InceptionV3/Predictions/Reshape_1
-converter_version=v2
diff --git a/compiler/one-cmds/tests/one-build_neg_005.test b/compiler/one-cmds/tests/one-build_neg_005.test
deleted file mode 100644 (file)
index 9b25111..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# negative one-import-tf intermediate file should not exist
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_neg_005.cfg"
-outputfile="inception_v3.alt.circle"
-intermfile="inception_v3.alt.tflite"
-
-rm -rf ${outputfile}
-rm -rf ${intermfile}
-rm -f ${filename}.log
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-# output should exist
-if [[ ! -s "${outputfile}" ]]; then
-  trap_err_onexit
-fi
-# intermediate file should not exist
-if [[ -f "${intermfile}" ]]; then
-  trap_err_onexit
-fi
-
-echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_neg_006.cfg b/compiler/one-cmds/tests/one-build_neg_006.cfg
deleted file mode 100644 (file)
index abe4c7d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-[one-build]
-one-import-tf=False
-one-import-tflite=False
-one-import-bcq=False
-one-import-onnx=True
-one-optimize=False
-one-quantize=False
-one-pack=False
-one-codegen=False
-
-[one-import-onnx]
-input_path=test_onnx_model.onnx
-output_path=test_onnx_model.circle
diff --git a/compiler/one-cmds/tests/one-build_neg_006.test b/compiler/one-cmds/tests/one-build_neg_006.test
deleted file mode 100644 (file)
index d228f8f..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# negative one-import-tf intermediate file should not exist
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile="one-build_neg_006.cfg"
-outputfile="test_onnx_model.circle"
-intermfile="test_onnx_model.tflite"
-
-rm -rf ${outputfile}
-rm -rf ${intermfile}
-rm -f ${filename}.log
-
-# run test
-one-build -C ${configfile} > ${filename}.log 2>&1
-
-# output should exist
-if [[ ! -s "${outputfile}" ]]; then
-  trap_err_onexit
-fi
-# intermediate file should not exist
-if [[ -f "${intermfile}" ]]; then
-  trap_err_onexit
-fi
-
-echo "${filename_ext} SUCCESS"
diff --git a/compiler/one-cmds/tests/one-build_neg_007.test b/compiler/one-cmds/tests/one-build_neg_007.test
deleted file mode 100644 (file)
index 59a5d25..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# Valid optimization option but invalid configuration file path
-
-: '
-This test assumes below directories.
-
-[one hierarchy]
-    one
-    â”œâ”€â”€ backends
-    â”œâ”€â”€ bin
-    â”œâ”€â”€ doc
-    â”œâ”€â”€ include
-    â”œâ”€â”€ lib
-    â”œâ”€â”€ optimization
-    â””── test # pwd
-'
-
-OPT_ALREADY_EXIST=true
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  rm -rf ../optimization/OONE_BUILD_NEG_007.cfg
-  if [ "$OPT_ALREADY_EXIST" = false ]; then
-    rm -rf ../optimization
-  fi
-  if grep -q "Not found given configuration file" "${filename}.log"; then
-    echo "${filename_ext} SUCCESS"
-    exit 0
-  fi
-
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-if [ ! -d "../optimization" ]; then
-  mkdir -p ../optimization
-  OPT_ALREADY_EXIST=false
-fi
-
-
-touch ../optimization/OONE_BUILD_NEG_007.cfg
-
-configfile=".."
-
-rm -f ${filename}.log
-
-# run test
-one-build -C ${configfile} -OONE_BUILD_NEG_007 > ${filename}.log 2>&1
-
-echo "${filename_ext} FAILED"
-exit 255
diff --git a/compiler/one-cmds/tests/one-build_neg_008.test b/compiler/one-cmds/tests/one-build_neg_008.test
deleted file mode 100644 (file)
index 2b41222..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# Invalid optimization option
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  if grep -q "Invalid optimization option" "${filename}.log"; then
-    echo "${filename_ext} SUCCESS"
-    exit 0
-  fi
-
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile=".."
-
-rm -f ${filename}.log
-
-# run test
-one-build -C ${configfile} -OONE_BUILD_NEG_008 > ${filename}.log 2>&1
-
-echo "${filename_ext} FAILED"
-exit 255
diff --git a/compiler/one-cmds/tests/one-build_neg_009.test b/compiler/one-cmds/tests/one-build_neg_009.test
deleted file mode 100644 (file)
index 5e3698d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-# Have space in the optimization name
-
-filename_ext="$(basename -- $0)"
-filename="${filename_ext%.*}"
-
-trap_err_onexit()
-{
-  if grep -q "Not allowed to have space in the optimization name" "${filename}.log"; then
-    echo "${filename_ext} SUCCESS"
-    exit 0
-  fi
-
-  echo "${filename_ext} FAILED"
-  exit 255
-}
-
-trap trap_err_onexit ERR
-
-configfile=".."
-
-rm -f ${filename}.log
-
-# run test
-one-build -C ${configfile} "-O SPACE OPTION" > ${filename}.log 2>&1
-
-echo "${filename_ext} FAILED"
-exit 255
diff --git a/compiler/one-cmds/tests/one-codegen_005.cfg b/compiler/one-cmds/tests/one-codegen_005.cfg
new file mode 100644 (file)
index 0000000..60de50f
--- /dev/null
@@ -0,0 +1,10 @@
+[onecc]
+one-codegen=True
+
+# target is given in the command line
+#[backend]
+#target=
+
+[one-codegen]
+backend=dummy
+command=-o one-codegen_005.tvn one-codegen_005.circle
diff --git a/compiler/one-cmds/tests/one-codegen_005.ini b/compiler/one-cmds/tests/one-codegen_005.ini
new file mode 100644 (file)
index 0000000..0889207
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-codegen_005
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-codegen_005.test b/compiler/one-cmds/tests/one-codegen_005.test
new file mode 100644 (file)
index 0000000..aa5a9cd
--- /dev/null
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# run dummy-compile drvier with given target in the command line
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-codegen_005.cfg"
+outputfile="one-codegen_005.tvn"
+targetfile="one-codegen_005.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-compile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -rf ${outputfile}
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp ${targetfile} ../target/
+
+# run test
+one-codegen -C ${configfile} -T one-codegen_005 > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with one-codegen_005 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-codegen_006.cfg b/compiler/one-cmds/tests/one-codegen_006.cfg
new file mode 100644 (file)
index 0000000..4328b39
--- /dev/null
@@ -0,0 +1,9 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=one-codegen_006
+
+[one-codegen]
+backend=dummy
+command=-o one-codegen_006.tvn one-codegen_006.circle
diff --git a/compiler/one-cmds/tests/one-codegen_006.ini b/compiler/one-cmds/tests/one-codegen_006.ini
new file mode 100644 (file)
index 0000000..4902f0d
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-codegen_006
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-codegen_006.test b/compiler/one-cmds/tests/one-codegen_006.test
new file mode 100644 (file)
index 0000000..d5e3dc8
--- /dev/null
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# run dummy-compile drvier with given target in the cfg file
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-codegen_006.cfg"
+outputfile="one-codegen_006.tvn"
+targetfile="one-codegen_006.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-compile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  rm -rf ../bin/dummy-compile
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -rf ${outputfile}
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp ${targetfile} ../target/
+
+# run test
+one-codegen -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with one-codegen_006 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-codegen_007.cfg b/compiler/one-cmds/tests/one-codegen_007.cfg
new file mode 100644 (file)
index 0000000..498fc9b
--- /dev/null
@@ -0,0 +1,9 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=sunflower
+
+[one-codegen]
+backend=dummy
+command=-o one-codegen_007.tvn one-codegen_007.circle
diff --git a/compiler/one-cmds/tests/one-codegen_007.ini b/compiler/one-cmds/tests/one-codegen_007.ini
new file mode 100644 (file)
index 0000000..f8b58ff
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-codegen_007
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-codegen_007.test b/compiler/one-cmds/tests/one-codegen_007.test
new file mode 100644 (file)
index 0000000..73ef685
--- /dev/null
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# run dummy-compile drvier with given target overwrited from the command line
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── dummy
+    â”‚           â””── codegen.py
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-codegen_007.cfg"
+outputfile="one-codegen_007.tvn"
+targetfile="one-codegen_007.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-compile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -rf ${outputfile}
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp ${targetfile} ../target/
+
+# run test
+one-codegen -C ${configfile} -T one-codegen_007 > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with one-codegen_007 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-codegen_008.cfg b/compiler/one-cmds/tests/one-codegen_008.cfg
new file mode 100644 (file)
index 0000000..99bb2b2
--- /dev/null
@@ -0,0 +1,9 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=one-codegen_008
+
+[one-codegen]
+o=one-codegen_008.tvn
+input=sample.circle
diff --git a/compiler/one-cmds/tests/one-codegen_008.ini b/compiler/one-cmds/tests/one-codegen_008.ini
new file mode 100644 (file)
index 0000000..98b100b
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-codegen_008
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-codegen_008.py b/compiler/one-cmds/tests/one-codegen_008.py
new file mode 100644 (file)
index 0000000..ba44e83
--- /dev/null
@@ -0,0 +1,13 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-compile", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    parser.add_argument("--DSP-quota", action=NormalOption)
+    parser.add_argument("-o", action=NormalOption)
+    parser.add_argument("input", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/one-codegen_008.test b/compiler/one-cmds/tests/one-codegen_008.test
new file mode 100644 (file)
index 0000000..20f93a0
--- /dev/null
@@ -0,0 +1,115 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# run dummy-compile drvier with given target and command schema
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── dummy
+    â”‚           â””── codegen.py
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-codegen_008.cfg"
+outputfile="one-codegen_008.tvn"
+targetfile="one-codegen_008.ini"
+commandschema="one-codegen_008.py"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-compile
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/codegen.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp ${targetfile} ../target/
+cp ${commandschema} "../backends/command/${BACKEND_NAME}/codegen.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with one-codegen_008 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-codegen_009.cfg b/compiler/one-cmds/tests/one-codegen_009.cfg
new file mode 100644 (file)
index 0000000..0170d03
--- /dev/null
@@ -0,0 +1,10 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=one-codegen_009
+
+[one-codegen]
+; o=one-codegen_009.tvn
+; input=one-codegen_009.circle
+command=-o one-codegen_009.tvn one-codegen_009.circle
diff --git a/compiler/one-cmds/tests/one-codegen_009.ini b/compiler/one-cmds/tests/one-codegen_009.ini
new file mode 100644 (file)
index 0000000..5af1c17
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-codegen_009
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-codegen_009.py b/compiler/one-cmds/tests/one-codegen_009.py
new file mode 100644 (file)
index 0000000..ba44e83
--- /dev/null
@@ -0,0 +1,13 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-compile", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    parser.add_argument("--DSP-quota", action=NormalOption)
+    parser.add_argument("-o", action=NormalOption)
+    parser.add_argument("input", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/one-codegen_009.test b/compiler/one-cmds/tests/one-codegen_009.test
new file mode 100644 (file)
index 0000000..a395940
--- /dev/null
@@ -0,0 +1,116 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 command key in `one-codegen` section in configuration file
+# TODO deprecate this test
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── dummy
+    â”‚           â””── codegen.py
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-codegen_009.cfg"
+outputfile="one-codegen_009.tvn"
+targetfile="one-codegen_009.ini"
+commandschema="one-codegen_009.py"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-compile
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/codegen.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp ${targetfile} ../target/
+cp ${commandschema} "../backends/command/${BACKEND_NAME}/codegen.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with one-codegen_009 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-codegen_010.ini b/compiler/one-cmds/tests/one-codegen_010.ini
new file mode 100644 (file)
index 0000000..3a99b89
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-codegen_010
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-codegen_010.test b/compiler/one-cmds/tests/one-codegen_010.test
new file mode 100644 (file)
index 0000000..a81310e
--- /dev/null
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 -T {target} ${command}
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+inputfile="one-codegen_010.circle"
+outputfile="one-codegen_010.tvn"
+targetfile="one-codegen_010.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-compile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  rm -rf ../bin/dummy-compile
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -rf ${outputfile}
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp ${targetfile} ../target/
+
+# run test
+one-codegen -T one-codegen_010 -o ${outputfile} ${inputfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with one-codegen_010 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-codegen_011.ini b/compiler/one-cmds/tests/one-codegen_011.ini
new file mode 100644 (file)
index 0000000..d514a46
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-codegen_011
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-codegen_011.test b/compiler/one-cmds/tests/one-codegen_011.test
new file mode 100644 (file)
index 0000000..0b7f917
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 -T {target} -- ${command}
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-codegen_011.cfg"
+inputfile="one-codegen_011.circle"
+outputfile="one-codegen_011.tvn"
+targetfile="one-codegen_011.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-compile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  rm -rf ../bin/dummy-compile
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -rf ${outputfile}
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy-compile to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp ${targetfile} ../target/
+
+# run test
+one-codegen -T one-codegen_011 -- -o ${outputfile} ${inputfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with one-codegen_011 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
index 137a3f9..e5c1865 100644 (file)
@@ -21,7 +21,7 @@ filename="${filename_ext%.*}"
 
 trap_err_onexit()
 {
-  if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
+  if grep -q "error: the following arguments are required: \[-b/--backend | -T/--target\]" "${filename}.log"; then
     echo "${filename_ext} SUCCESS"
     exit 0
   fi
index 28dfa92..f54f3eb 100644 (file)
@@ -21,7 +21,7 @@ filename="${filename_ext%.*}"
 
 trap_err_onexit()
 {
-  if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
+  if grep -q "error: the following arguments are required: \[-b/--backend | -T/--target\]" "${filename}.log"; then
     echo "${filename_ext} SUCCESS"
     exit 0
   fi
index 0622b6a..015b726 100644 (file)
@@ -21,7 +21,7 @@ filename="${filename_ext%.*}"
 
 trap_err_onexit()
 {
-  if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
+  if grep -q "error: the following arguments are required: \[-b/--backend | -T/--target\]" "${filename}.log"; then
     echo "${filename_ext} SUCCESS"
     exit 0
   fi
diff --git a/compiler/one-cmds/tests/one-create-quant-dataset_001.test b/compiler/one-cmds/tests/one-create-quant-dataset_001.test
new file mode 100644 (file)
index 0000000..5526df9
--- /dev/null
@@ -0,0 +1,44 @@
+#!/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.
+
+# run test with rawdata2hdf5
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+outputfile="./output_one-create-quant-dataset_testdata_001.h5"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+one-create-quant-dataset \
+--input_data_format rawdata \
+--data_list datalist.txt \
+--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-create-quant-dataset_002.test b/compiler/one-cmds/tests/one-create-quant-dataset_002.test
new file mode 100644 (file)
index 0000000..07e6109
--- /dev/null
@@ -0,0 +1,44 @@
+#!/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.
+
+# run test with numpy2hdf5 
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+outputfile="./output_one-create-quant-dataset_testdata_002.h5"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+one-create-quant-dataset \
+--input_data_format numpy \
+--data_list datalist_numpy.txt \
+--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-create-quant-dataset_neg_001.test b/compiler/one-cmds/tests/one-create-quant-dataset_neg_001.test
new file mode 100644 (file)
index 0000000..bc2377d
--- /dev/null
@@ -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.
+
+# negative usage with non-existing input file
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  if grep -q "No such file" "${filename}.log"; then
+    echo "${filename_ext} SUCCESS"
+    exit 0
+  fi
+
+  echo "${filename_ext} FAILED"
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./wronglist.txt"
+outputfile="./output_testdata.h5"
+
+rm -rf ${inputfile}
+rm -f ${filename}.log
+
+touch ${inputfile}
+echo "non-existing-file.data" >> ${inputfile}
+
+# run test
+one-create-quant-dataset \
+--input_data_format rawdata \
+--data_list ${inputfile} \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-create-quant-dataset_neg_002.test b/compiler/one-cmds/tests/one-create-quant-dataset_neg_002.test
new file mode 100644 (file)
index 0000000..449fca8
--- /dev/null
@@ -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.
+
+# negative usage with invalid input file 
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  if grep -q "UnicodeDecodeError" "${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="./output_testdata.h5"
+
+rm -f ${filename}.log
+
+# run test
+one-create-quant-dataset \
+--input_data_format numpy \
+--data_list ${inputfile} \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-create-quant-dataset_neg_003.test b/compiler/one-cmds/tests/one-create-quant-dataset_neg_003.test
new file mode 100644 (file)
index 0000000..d58aac8
--- /dev/null
@@ -0,0 +1,45 @@
+#!/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.
+
+# negative usage with missing -l/--data_list arguments
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  if grep -q "the following arguments are required: -l/--data_list" "${filename}.log"; then
+    echo "${filename_ext} SUCCESS"
+    exit 0
+  fi
+
+  echo "${filename_ext} FAILED"
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+outputfile="./output_testdata.h5"
+
+rm -f ${filename}.log
+
+# run test
+one-create-quant-dataset \
+--input_data_format numpy \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-create-quant-dataset_neg_004.test b/compiler/one-cmds/tests/one-create-quant-dataset_neg_004.test
new file mode 100644 (file)
index 0000000..ed2313d
--- /dev/null
@@ -0,0 +1,45 @@
+#!/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.
+
+# negative usage with missing -i/--input_data_format arguments
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  if grep -q "the following arguments are required: -i/--input_data_format" "${filename}.log"; then
+    echo "${filename_ext} SUCCESS"
+    exit 0
+  fi
+
+  echo "${filename_ext} FAILED"
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+outputfile="./output_testdata.h5"
+
+rm -f ${filename}.log
+
+# run test
+one-create-quant-dataset \
+--data_list datalist_numpy.txt \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-create-quant-dataset_neg_005.test b/compiler/one-cmds/tests/one-create-quant-dataset_neg_005.test
new file mode 100644 (file)
index 0000000..ced5e4e
--- /dev/null
@@ -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.
+
+# negative usage with invalid input_data_format (test without choosing between rawdata and numpy)
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  if grep -q "argument -i/--input_data_format: invalid choice:" "${filename}.log"; then
+    echo "${filename_ext} SUCCESS"
+    exit 0
+  fi
+
+  echo "${filename_ext} FAILED"
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+outputfile="./output_testdata.h5"
+
+rm -f ${filename}.log
+
+# run test
+one-create-quant-dataset \
+--input_data_format raw \
+--data_list datalist.txt \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/one-profile_005.cfg b/compiler/one-cmds/tests/one-profile_005.cfg
new file mode 100644 (file)
index 0000000..71ddcd8
--- /dev/null
@@ -0,0 +1,6 @@
+[onecc]
+one-profile=True
+
+[one-profile]
+backend=dummy
+command=one-profile_005.tvn
diff --git a/compiler/one-cmds/tests/one-profile_005.ini b/compiler/one-cmds/tests/one-profile_005.ini
new file mode 100644 (file)
index 0000000..4962295
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-profile_005
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-profile_005.test b/compiler/one-cmds/tests/one-profile_005.test
new file mode 100644 (file)
index 0000000..66dc35c
--- /dev/null
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# run dummy-profile driver with given target
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-profile_005.cfg"
+targetfile="one-profile_005.ini"
+# not used
+inputfile="one-profile_005.tvn"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-profile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy-profile to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp ${targetfile} ../target/
+
+# run test
+one-profile -C ${configfile} -T one-profile_005 ${inputfile} > ${filename}.log
+
+clean_envir
+
+if grep -q "dummy-profile with one-profile_005 target" "${filename}.log"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-profile_006.cfg b/compiler/one-cmds/tests/one-profile_006.cfg
new file mode 100644 (file)
index 0000000..38f0353
--- /dev/null
@@ -0,0 +1,9 @@
+[onecc]
+one-profile=True
+
+[backend]
+target=one-profile_006
+
+[one-profile]
+backend=dummy
+command=sample.tvn
diff --git a/compiler/one-cmds/tests/one-profile_006.ini b/compiler/one-cmds/tests/one-profile_006.ini
new file mode 100644 (file)
index 0000000..351232f
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-profile_006
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-profile_006.test b/compiler/one-cmds/tests/one-profile_006.test
new file mode 100644 (file)
index 0000000..3afb575
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# run dummy-profile drvier with given target in the cfg file
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-profile_006.cfg"
+outputfile="one-profile_006.tvn"
+targetfile="one-profile_006.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-profile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  rm -rf ../bin/dummy-profile
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="one-profile_006.cfg"
+
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy-profile to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp ${targetfile} ../target/
+
+# run test
+one-profile -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-profile with one-profile_006 target" "${filename}.log"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-profile_007.cfg b/compiler/one-cmds/tests/one-profile_007.cfg
new file mode 100644 (file)
index 0000000..33e187b
--- /dev/null
@@ -0,0 +1,9 @@
+[onecc]
+one-profile=True
+
+[backend]
+target=rose
+
+[one-profile]
+backend=dummy
+command=one-profile_007.tvn
diff --git a/compiler/one-cmds/tests/one-profile_007.ini b/compiler/one-cmds/tests/one-profile_007.ini
new file mode 100644 (file)
index 0000000..663a957
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-profile_007
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-profile_007.test b/compiler/one-cmds/tests/one-profile_007.test
new file mode 100644 (file)
index 0000000..aa51f5c
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# run dummy-profile drvier with given target overwrited from the command line
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-profile_007.cfg"
+targetfile="one-profile_007.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-profile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy-profile to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp ${targetfile} ../target/
+
+# run test
+one-profile -C ${configfile} -T one-profile_007 > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-profile with one-profile_007 target" "${filename}.log"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-profile_008.cfg b/compiler/one-cmds/tests/one-profile_008.cfg
new file mode 100644 (file)
index 0000000..edca616
--- /dev/null
@@ -0,0 +1,8 @@
+[onecc]
+one-profile=True
+
+[backend]
+target=one-profile_008
+
+[one-profile]
+input=one-profile_008.tvn
diff --git a/compiler/one-cmds/tests/one-profile_008.ini b/compiler/one-cmds/tests/one-profile_008.ini
new file mode 100644 (file)
index 0000000..66d0389
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-profile_008
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-profile_008.py b/compiler/one-cmds/tests/one-profile_008.py
new file mode 100644 (file)
index 0000000..25f91d9
--- /dev/null
@@ -0,0 +1,11 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-profile", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    parser.add_argument("input", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/one-profile_008.test b/compiler/one-cmds/tests/one-profile_008.test
new file mode 100644 (file)
index 0000000..d935b65
--- /dev/null
@@ -0,0 +1,113 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# run dummy-profile drvier with given target and command schema
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── dummy
+    â”‚           â””── profile.py
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-profile_008.cfg"
+targetfile="one-profile_008.ini"
+commandschema="one-profile_008.py"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-profile
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/profile.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp ${targetfile} ../target/
+cp ${commandschema} "../backends/command/${BACKEND_NAME}/profile.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-profile with one-profile_008 target" "${filename}.log"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-profile_009.cfg b/compiler/one-cmds/tests/one-profile_009.cfg
new file mode 100644 (file)
index 0000000..9166318
--- /dev/null
@@ -0,0 +1,9 @@
+[onecc]
+one-profile=True
+
+[backend]
+target=one-profile_009
+
+[one-profile]
+; input=one-profile_009.tvn
+command=one-profile_009.tvn
diff --git a/compiler/one-cmds/tests/one-profile_009.ini b/compiler/one-cmds/tests/one-profile_009.ini
new file mode 100644 (file)
index 0000000..dca05c8
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-profile_009
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-profile_009.py b/compiler/one-cmds/tests/one-profile_009.py
new file mode 100644 (file)
index 0000000..25f91d9
--- /dev/null
@@ -0,0 +1,11 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-profile", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    parser.add_argument("input", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/one-profile_009.test b/compiler/one-cmds/tests/one-profile_009.test
new file mode 100644 (file)
index 0000000..3a65da8
--- /dev/null
@@ -0,0 +1,114 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 command key in `one-codegen` section in configuration file
+# TODO deprecate this test
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── dummy
+    â”‚           â””── profile.py
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-profile_009.cfg"
+targetfile="one-profile_009.ini"
+commandschema="one-profile_009.py"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-profile
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/profile.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp ${targetfile} ../target/
+cp ${commandschema} "../backends/command/${BACKEND_NAME}/profile.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-profile with one-profile_009 target" "${filename}.log"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-profile_010.ini b/compiler/one-cmds/tests/one-profile_010.ini
new file mode 100644 (file)
index 0000000..22ae64a
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-profile_010
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-profile_010.test b/compiler/one-cmds/tests/one-profile_010.test
new file mode 100644 (file)
index 0000000..681b9d6
--- /dev/null
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 -T {target} ${command}
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-profile_010.cfg"
+inputfile="one-profile_010.tvn"
+targetfile="one-profile_010.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-profile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  rm -rf ../bin/dummy-profile
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy-profile to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp ${targetfile} ../target/
+
+# run test
+one-profile -T one-profile_010 ${inputfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-profile with one-profile_010 target" "${filename}.log"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/one-profile_011.ini b/compiler/one-cmds/tests/one-profile_011.ini
new file mode 100644 (file)
index 0000000..ccb146d
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=one-profile_011
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/one-profile_011.test b/compiler/one-cmds/tests/one-profile_011.test
new file mode 100644 (file)
index 0000000..db2e1c8
--- /dev/null
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 -T {target} -- ${command}
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="one-profile_011.cfg"
+inputfile="one-profile_011.tvn"
+targetfile="one-profile_011.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-profile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  rm -rf ../bin/dummy-profile
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy-profile to bin folder
+cp dummy-profile ../bin/dummy-profile
+cp ${targetfile} ../target/
+
+# run test
+one-profile -T one-profile_011 -- ${inputfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-profile with one-profile_011 target" "${filename}.log"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
index f5b2dce..59a089f 100644 (file)
@@ -21,7 +21,7 @@ filename="${filename_ext%.*}"
 
 trap_err_onexit()
 {
-  if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
+  if grep -q "error: the following arguments are required: \[-b/--backend | -T/--target\]" "${filename}.log"; then
     echo "${filename_ext} SUCCESS"
     exit 0
   fi
index 6964312..6afbbe2 100644 (file)
@@ -21,7 +21,7 @@ filename="${filename_ext%.*}"
 
 trap_err_onexit()
 {
-  if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
+  if grep -q "error: the following arguments are required: \[-b/--backend | -T/--target\]" "${filename}.log"; then
     echo "${filename_ext} SUCCESS"
     exit 0
   fi
index a002154..4efac34 100644 (file)
@@ -21,7 +21,7 @@ filename="${filename_ext%.*}"
 
 trap_err_onexit()
 {
-  if grep -q "error: the following arguments are required: -b/--backend" "${filename}.log"; then
+  if grep -q "error: the following arguments are required: \[-b/--backend | -T/--target\]" "${filename}.log"; then
     echo "${filename_ext} SUCCESS"
     exit 0
   fi
diff --git a/compiler/one-cmds/tests/one-quantize_022.cfg b/compiler/one-cmds/tests/one-quantize_022.cfg
new file mode 100644 (file)
index 0000000..f9dc6a9
--- /dev/null
@@ -0,0 +1,19 @@
+[onecc]
+one-import-onnx=True
+one-optimize=True
+one-quantize=True
+include=O1
+
+[one-import-onnx]
+input_path=onnx_conv2d_conv2d_split.onnx
+output_path=one-quantize_022.circle
+
+[one-optimize]
+input_path=one-quantize_022.circle
+output_path=one-quantize_022.opt.circle
+convert_nchw_to_nhwc=True
+
+[one-quantize]
+input_path=one-quantize_022.opt.circle
+output_path=one-quantize_022.opt.qm.circle
+quant_config=one-quantize_022.qconf.json
diff --git a/compiler/one-cmds/tests/one-quantize_022.qconf.json b/compiler/one-cmds/tests/one-quantize_022.qconf.json
new file mode 100644 (file)
index 0000000..acc8cf7
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "default_quantization_dtype" : "uint8",
+  "default_granularity" : "layer",
+  "layers" : [
+    {
+      "names" : [
+        "onnx_tf_prefix_Relu_1;Add;convolution;Const_1"
+      ],
+      "alternate": {
+        "tf2121": [
+          "onnx_tf_prefix_/relu1/Relu;Add;convolution;Const_2"
+        ],
+        "o2c": [
+          "/conv1/Conv;/relu1/Relu"
+        ]
+      },
+      "dtype" : "int16",
+      "granularity" : "channel"
+    }
+  ]
+}
diff --git a/compiler/one-cmds/tests/one-quantize_022.test b/compiler/one-cmds/tests/one-quantize_022.test
new file mode 100644 (file)
index 0000000..d809b21
--- /dev/null
@@ -0,0 +1,44 @@
+#!/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.
+
+# Check "alternate" of qconf.json
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./onnx_conv2d_conv2d_split.onnx"
+outputfile="./${filename}.opt.qm.circle"
+configfile="${filename}.cfg"
+
+rm -f ${filename}.log
+rm -f ${outputfile}
+
+# test one-quantize through onecc
+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/one-quantize_023.test b/compiler/one-cmds/tests/one-quantize_023.test
new file mode 100644 (file)
index 0000000..e503b01
--- /dev/null
@@ -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.
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./Add_000.circle"
+outputfile="./Add_000.one-quantize_023.circle"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+# Test space-delimitered list format (Add_000.inputs.txt)
+# Content of Add_000.inputs.txt is as follows.
+# Add_000.circle.input0 Add_000.circle.input1
+one-quantize \
+--input_dtype float32 \
+--quantized_dtype uint8 \
+--input_path ${inputfile} \
+--input_data ./Add_000.inputs.txt \
+--input_data_format list \
+--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_024.test b/compiler/one-cmds/tests/one-quantize_024.test
new file mode 100644 (file)
index 0000000..88e66cb
--- /dev/null
@@ -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="./inception_v3.circle"
+outputfile="./inception_v3.one-quantize_024.circle"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+# run test without input data
+one-quantize \
+--quantized_dtype uint8 \
+--granularity channel \
+--save_min_max \
+--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_neg_024.test b/compiler/one-cmds/tests/one-quantize_neg_024.test
new file mode 100644 (file)
index 0000000..df425eb
--- /dev/null
@@ -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.
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  if grep -q "Wrong number of inputs" "${filename}.log"; then
+    echo "${filename_ext} SUCCESS"
+    exit 0
+  fi
+
+  echo "${filename_ext} FAILED"
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+inputfile="./Add_000.circle"
+outputfile="./Add_000.one-quantize_neg_024.circle"
+
+rm -f ${filename}.log
+
+# Test with wrong number of intputs in list file
+# Model has two inputs, but list file has three inputs
+# Add_000.circle.input0 Add_000.circle.input1 Add_000.circle.input2
+one-quantize \
+--input_dtype float32 \
+--quantized_dtype uint8 \
+--input_path ${inputfile} \
+--input_data ./Add_000.wrong_inputs.txt \
+--input_data_format list \
+--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/onecc_059.cfg b/compiler/one-cmds/tests/onecc_059.cfg
new file mode 100644 (file)
index 0000000..9a118d6
--- /dev/null
@@ -0,0 +1,23 @@
+[onecc]
+one-import-tf=True
+one-import-tflite=False
+one-import-bcq=False
+one-optimize=True
+one-quantize=False
+one-pack=False
+one-codegen=False
+
+[one-import-tf]
+input_path=inception_v3.pb # comment test
+output_path=inception_v3.onecc_059.circle #comment test
+input_arrays=input ; comment test
+input_shapes=1,299,299,3 ;comment test
+output_arrays=InceptionV3/Predictions/Reshape_1     ## test
+converter_version=v2       ## test
+# comment test
+[one-optimize]
+input_path=inception_v3.onecc_059.circle
+output_path=inception_v3.onecc_059.opt.circle
+
+# Note. there must be one or more space between the value and the comment
+# e.g. input_path=inception_v3.pb#THIS IS NOT ALLOWED
diff --git a/compiler/one-cmds/tests/onecc_059.test b/compiler/one-cmds/tests/onecc_059.test
new file mode 100644 (file)
index 0000000..411e5ea
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 if writing comments are allowed in the configuration file.
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+configfile="onecc_059.cfg"
+outputfile="inception_v3.onecc_059.opt.circle"
+
+rm -f ${filename}.log
+rm -f ${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_060.cfg b/compiler/one-cmds/tests/onecc_060.cfg
new file mode 100644 (file)
index 0000000..4847567
--- /dev/null
@@ -0,0 +1,9 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=onecc_060
+
+[one-codegen]
+backend=dummy
+command=-o onecc_060.tvn onecc_060.circle
diff --git a/compiler/one-cmds/tests/onecc_060.ini b/compiler/one-cmds/tests/onecc_060.ini
new file mode 100644 (file)
index 0000000..6d3a9ac
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=rose
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_060.test b/compiler/one-cmds/tests/onecc_060.test
new file mode 100644 (file)
index 0000000..345a0ec
--- /dev/null
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 'target' option
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="onecc_060.cfg"
+outputfile="onecc_060.tvn"
+targetfile="onecc_060.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-compile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp ${targetfile} ../target/
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with onecc_060 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/onecc_061.cfg b/compiler/one-cmds/tests/onecc_061.cfg
new file mode 100644 (file)
index 0000000..db83216
--- /dev/null
@@ -0,0 +1,9 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=rose
+
+[one-codegen]
+backend=dummy
+command=-o onecc_061.tvn inception_v3.onecc_061.circle
diff --git a/compiler/one-cmds/tests/onecc_061.ini b/compiler/one-cmds/tests/onecc_061.ini
new file mode 100644 (file)
index 0000000..66721b1
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=onecc_061
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_061.test b/compiler/one-cmds/tests/onecc_061.test
new file mode 100644 (file)
index 0000000..966a81f
--- /dev/null
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 'target' option
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+TARGET_ALREADY_EXIST=true
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="onecc_061.cfg"
+outputfile="onecc_061.tvn"
+targetfile="onecc_061.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/dummy-compile
+  rm -rf ../target/${targetfile}
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp dummy-compile ../bin/dummy-compile
+cp ${targetfile} ../target/
+
+# run test
+onecc -C ${configfile} -T onecc_061 > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with onecc_061 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/onecc_062.cfg b/compiler/one-cmds/tests/onecc_062.cfg
new file mode 100644 (file)
index 0000000..ba1c91c
--- /dev/null
@@ -0,0 +1,9 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=onecc_062
+
+[one-codegen]
+o=onecc_062.tvn
+input=inception_v3.onecc_062.circle
diff --git a/compiler/one-cmds/tests/onecc_062.ini b/compiler/one-cmds/tests/onecc_062.ini
new file mode 100644 (file)
index 0000000..ee85c32
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=onecc_062
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_062.py b/compiler/one-cmds/tests/onecc_062.py
new file mode 100644 (file)
index 0000000..ba44e83
--- /dev/null
@@ -0,0 +1,13 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-compile", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    parser.add_argument("--DSP-quota", action=NormalOption)
+    parser.add_argument("-o", action=NormalOption)
+    parser.add_argument("input", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/onecc_062.test b/compiler/one-cmds/tests/onecc_062.test
new file mode 100644 (file)
index 0000000..6ade2c1
--- /dev/null
@@ -0,0 +1,114 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 command schema of codegen
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── dummy (backend name)
+    â”‚           â””── codegen.py
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="onecc_062.cfg"
+outputfile="onecc_062.tvn"
+targetfile="onecc_062.ini"
+
+clean_envir()
+{
+  rm -rf "../bin/${BACKEND_NAME}-compile"
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/codegen.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp ${BACKEND_NAME}-compile ../bin/
+cp ${targetfile} ../target/
+cp onecc_062.py "../backends/command/${BACKEND_NAME}/codegen.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with onecc_062 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/onecc_063.cfg b/compiler/one-cmds/tests/onecc_063.cfg
new file mode 100644 (file)
index 0000000..2e11e6b
--- /dev/null
@@ -0,0 +1,8 @@
+[onecc]
+one-profile=True
+
+[backend]
+target=onecc_063
+
+[one-profile]
+input=onecc_063.tvn
diff --git a/compiler/one-cmds/tests/onecc_063.ini b/compiler/one-cmds/tests/onecc_063.ini
new file mode 100644 (file)
index 0000000..21c929b
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=onecc_063
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_063.py b/compiler/one-cmds/tests/onecc_063.py
new file mode 100644 (file)
index 0000000..25f91d9
--- /dev/null
@@ -0,0 +1,11 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-profile", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    parser.add_argument("input", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/onecc_063.test b/compiler/one-cmds/tests/onecc_063.test
new file mode 100644 (file)
index 0000000..a1995e3
--- /dev/null
@@ -0,0 +1,113 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 command schema of profile
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── dummy (backend name)
+    â”‚           â””── profile.py
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="onecc_063.cfg"
+outputfile="onecc_063.tvn"
+targetfile="onecc_063.ini"
+
+clean_envir()
+{
+  rm -rf "../bin/${BACKEND_NAME}-profile"
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/profile.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp ${BACKEND_NAME}-profile ../bin/
+cp ${targetfile} ../target/
+cp onecc_063.py "../backends/command/${BACKEND_NAME}/profile.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-profile with onecc_063 target" "${filename}.log"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/onecc_064.cfg b/compiler/one-cmds/tests/onecc_064.cfg
new file mode 100644 (file)
index 0000000..2a22ae4
--- /dev/null
@@ -0,0 +1,10 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=onecc_064
+
+[one-codegen]
+verbose=True
+input=onecc_064.circle
+output=onecc_064.tvn
diff --git a/compiler/one-cmds/tests/onecc_064.ini b/compiler/one-cmds/tests/onecc_064.ini
new file mode 100644 (file)
index 0000000..f357c46
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=onecc_064
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_064.py b/compiler/one-cmds/tests/onecc_064.py
new file mode 100644 (file)
index 0000000..50cbc3b
--- /dev/null
@@ -0,0 +1,13 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-compiler", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    parser.add_argument("--verbose", action=NormalOption, dtype=bool)
+    parser.add_argument("input", action=NormalOption)
+    parser.add_argument("output", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/onecc_064.test b/compiler/one-cmds/tests/onecc_064.test
new file mode 100644 (file)
index 0000000..426ad6b
--- /dev/null
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 command schema with customized driver name instead of "*-compile"
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── dummy
+    â”‚           â””── codegen.py
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+driver_name="dummy-compiler"
+configfile="onecc_064.cfg"
+outputfile="onecc_064.tvn"
+targetfile="onecc_064.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/${driver_name}
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/codegen.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp ${driver_name} ../bin/
+cp ${targetfile} ../target/
+cp onecc_064.py "../backends/command/${BACKEND_NAME}/codegen.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "${driver_name} with onecc_064 target" "${outputfile}"; then
+  if ! grep -q "HELP MESSAGE!!" "${filename}.log"; then
+    echo "${filename_ext} SUCCESS"
+    exit 0
+  fi
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/onecc_065.cfg b/compiler/one-cmds/tests/onecc_065.cfg
new file mode 100644 (file)
index 0000000..6f6c63f
--- /dev/null
@@ -0,0 +1,10 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=onecc_065
+
+[one-codegen]
+; input=onecc_065.circle
+; output=onecc_065.tvn
+command=-o onecc_065.tvn onecc_065.circle
diff --git a/compiler/one-cmds/tests/onecc_065.ini b/compiler/one-cmds/tests/onecc_065.ini
new file mode 100644 (file)
index 0000000..dabc9c7
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=onecc_065
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_065.py b/compiler/one-cmds/tests/onecc_065.py
new file mode 100644 (file)
index 0000000..50cbc3b
--- /dev/null
@@ -0,0 +1,13 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-compiler", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    parser.add_argument("--verbose", action=NormalOption, dtype=bool)
+    parser.add_argument("input", action=NormalOption)
+    parser.add_argument("output", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/onecc_065.test b/compiler/one-cmds/tests/onecc_065.test
new file mode 100644 (file)
index 0000000..1bb8a3d
--- /dev/null
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 command key in `one-codegen` section in configuration file
+# TODO deprecate this test
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── codegen
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+driver_name="dummy-compile"
+configfile="onecc_065.cfg"
+outputfile="onecc_065.tvn"
+targetfile="onecc_065.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/${driver_name}
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/codegen.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp ${driver_name} ../bin/
+cp ${targetfile} ../target/
+cp onecc_065.py "../backends/command/${BACKEND_NAME}/codegen.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "${driver_name} with onecc_065 target" "${outputfile}"; then
+  if ! grep -q "HELP MESSAGE!!" "${filename}.log"; then
+    echo "${filename_ext} SUCCESS"
+    exit 0
+  fi
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/onecc_066.cfg b/compiler/one-cmds/tests/onecc_066.cfg
new file mode 100644 (file)
index 0000000..f62a32d
--- /dev/null
@@ -0,0 +1,11 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=onecc_066
+
+[one-codegen]
+invalid_option=onecc_066
+verbose=True
+input=onecc_066.circle
+output=onecc_066.tvn
diff --git a/compiler/one-cmds/tests/onecc_066.ini b/compiler/one-cmds/tests/onecc_066.ini
new file mode 100644 (file)
index 0000000..2da9372
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=onecc_066
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_066.py b/compiler/one-cmds/tests/onecc_066.py
new file mode 100644 (file)
index 0000000..50cbc3b
--- /dev/null
@@ -0,0 +1,13 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-compiler", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    parser.add_argument("--verbose", action=NormalOption, dtype=bool)
+    parser.add_argument("input", action=NormalOption)
+    parser.add_argument("output", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/onecc_066.test b/compiler/one-cmds/tests/onecc_066.test
new file mode 100644 (file)
index 0000000..355a04f
--- /dev/null
@@ -0,0 +1,116 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Have invalid options in the [one-codegen]
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── codegen
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+driver_name="dummy-compiler"
+configfile="onecc_066.cfg"
+outputfile="onecc_066.tvn"
+targetfile="onecc_066.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/${driver_name}
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/codegen.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp ${driver_name} ../bin/
+cp ${targetfile} ../target/
+cp onecc_066.py "../backends/command/${BACKEND_NAME}/codegen.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "${driver_name} with onecc_066 target" "${outputfile}"; then
+  if grep -q "HELP MESSAGE!!" "${filename}.log"; then
+    echo "${filename_ext} SUCCESS"
+    exit 0
+  fi
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/onecc_067.cfg b/compiler/one-cmds/tests/onecc_067.cfg
new file mode 100644 (file)
index 0000000..97395fd
--- /dev/null
@@ -0,0 +1,18 @@
+[onecc]
+one-import-tf=True
+one-codegen=True
+
+[backend]
+target=onecc_067
+
+[one-import-tf]
+input_path=inception_v3.pb
+output_path=inception_v3.onecc_067.circle
+input_arrays=input
+input_shapes=1,299,299,3
+output_arrays=InceptionV3/Predictions/Reshape_1
+converter_version=v2
+
+[one-codegen]
+o=onecc_067.tvn
+input=inception_v3.onecc_067.circle
diff --git a/compiler/one-cmds/tests/onecc_067.ini b/compiler/one-cmds/tests/onecc_067.ini
new file mode 100644 (file)
index 0000000..4abeb6f
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=onecc_067
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_067.py b/compiler/one-cmds/tests/onecc_067.py
new file mode 100644 (file)
index 0000000..ba44e83
--- /dev/null
@@ -0,0 +1,13 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-compile", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    parser.add_argument("--DSP-quota", action=NormalOption)
+    parser.add_argument("-o", action=NormalOption)
+    parser.add_argument("input", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/onecc_067.test b/compiler/one-cmds/tests/onecc_067.test
new file mode 100644 (file)
index 0000000..4ea173d
--- /dev/null
@@ -0,0 +1,114 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 command schema of codegen
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── dummy (backend name)
+    â”‚           â””── codegen.py
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="onecc_067.cfg"
+outputfile="onecc_067.tvn"
+targetfile="onecc_067.ini"
+
+clean_envir()
+{
+  rm -rf "../bin/${BACKEND_NAME}-compile"
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/codegen.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp ${BACKEND_NAME}-compile ../bin/
+cp ${targetfile} ../target/
+cp onecc_067.py "../backends/command/${BACKEND_NAME}/codegen.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with onecc_067 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/onecc_068.cfg b/compiler/one-cmds/tests/onecc_068.cfg
new file mode 100644 (file)
index 0000000..1e4169c
--- /dev/null
@@ -0,0 +1,18 @@
+[onecc]
+one-import-tf=True
+one-codegen=True
+
+[backend]
+target=onecc_068
+
+[one-import-tf]
+input_path=inception_v3.pb
+output_path=inception_v3.onecc_068.circle
+input_arrays=input
+input_shapes=1,299,299,3
+output_arrays=InceptionV3/Predictions/Reshape_1
+converter_version=v2
+
+[one-codegen]
+output_path=onecc_068.tvn
+input=inception_v3.onecc_068.circle
diff --git a/compiler/one-cmds/tests/onecc_068.ini b/compiler/one-cmds/tests/onecc_068.ini
new file mode 100644 (file)
index 0000000..9ecfa13
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=onecc_068
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_068.py b/compiler/one-cmds/tests/onecc_068.py
new file mode 100644 (file)
index 0000000..aec0dd6
--- /dev/null
@@ -0,0 +1,13 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-compile", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    # multiple option names
+    parser.add_argument("-o", "--output_path", action=NormalOption)
+    parser.add_argument("input", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/onecc_068.test b/compiler/one-cmds/tests/onecc_068.test
new file mode 100644 (file)
index 0000000..d1abbd1
--- /dev/null
@@ -0,0 +1,114 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Support multiple option names in command schema
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── dummy (backend name)
+    â”‚           â””── codegen.py
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+configfile="onecc_068.cfg"
+outputfile="onecc_068.tvn"
+targetfile="onecc_068.ini"
+
+clean_envir()
+{
+  rm -rf "../bin/${BACKEND_NAME}-compile"
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/codegen.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp ${BACKEND_NAME}-compile ../bin/
+cp ${targetfile} ../target/
+cp onecc_068.py "../backends/command/${BACKEND_NAME}/codegen.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "dummy-compile with onecc_068 target" "${outputfile}"; then
+  echo "${filename_ext} SUCCESS"
+  exit 0
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/onecc_069.cfg b/compiler/one-cmds/tests/onecc_069.cfg
new file mode 100644 (file)
index 0000000..9f500b6
--- /dev/null
@@ -0,0 +1,10 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=onecc_069
+
+[one-codegen]
+v=True
+input=onecc_069.circle
+output=onecc_069.tvn
diff --git a/compiler/one-cmds/tests/onecc_069.ini b/compiler/one-cmds/tests/onecc_069.ini
new file mode 100644 (file)
index 0000000..2e7cc83
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=onecc_069
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_069.py b/compiler/one-cmds/tests/onecc_069.py
new file mode 100644 (file)
index 0000000..d839019
--- /dev/null
@@ -0,0 +1,14 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-compiler", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    # multiple options
+    parser.add_argument("--verbose", "-v", action=NormalOption, dtype=bool)
+    parser.add_argument("input", action=NormalOption)
+    parser.add_argument("output", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/onecc_069.test b/compiler/one-cmds/tests/onecc_069.test
new file mode 100644 (file)
index 0000000..03eb5c6
--- /dev/null
@@ -0,0 +1,116 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Boolean type option has multiple options. 
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── codegen
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+driver_name="dummy-compiler"
+configfile="onecc_069.cfg"
+outputfile="onecc_069.tvn"
+targetfile="onecc_069.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/${driver_name}
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/codegen.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  echo "${filename_ext} FAILED"
+  clean_envir
+  exit 255
+}
+
+trap trap_err_onexit ERR
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp ${driver_name} ../bin/
+cp ${targetfile} ../target/
+cp onecc_069.py "../backends/command/${BACKEND_NAME}/codegen.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+clean_envir
+
+if grep -q "${driver_name} with onecc_069 target" "${outputfile}"; then
+  if ! grep -q "HELP MESSAGE!!" "${filename}.log"; then
+    echo "${filename_ext} SUCCESS"
+    exit 0
+  fi
+fi
+
+trap_err_onexit
diff --git a/compiler/one-cmds/tests/onecc_neg_037.test b/compiler/one-cmds/tests/onecc_neg_037.test
new file mode 100644 (file)
index 0000000..219bbd1
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 'target' option simultaneously
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+trap_err_onexit()
+{
+  if grep -q "'backend' and 'target' are mutually exclusive option. 'target' option automatically set a 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
+onecc -C "dummy_cfg" -b "dummy_backend" -T "dummy_target" > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
diff --git a/compiler/one-cmds/tests/onecc_neg_038.cfg b/compiler/one-cmds/tests/onecc_neg_038.cfg
new file mode 100644 (file)
index 0000000..17ab809
--- /dev/null
@@ -0,0 +1,10 @@
+[onecc]
+one-codegen=True
+
+[backend]
+target=onecc_neg_038
+
+[one-codegen]
+v=True
+input=onecc_neg_038.circle
+output=onecc_neg_038.tvn
diff --git a/compiler/one-cmds/tests/onecc_neg_038.ini b/compiler/one-cmds/tests/onecc_neg_038.ini
new file mode 100644 (file)
index 0000000..9881e62
--- /dev/null
@@ -0,0 +1,2 @@
+TARGET=onecc_neg_038
+BACKEND=dummy
diff --git a/compiler/one-cmds/tests/onecc_neg_038.py b/compiler/one-cmds/tests/onecc_neg_038.py
new file mode 100644 (file)
index 0000000..bafb305
--- /dev/null
@@ -0,0 +1,14 @@
+from onelib import argumentparse
+from onelib.argumentparse import DriverName, NormalOption, TargetOption
+
+
+def command_schema():
+    parser = argumentparse.ArgumentParser()
+    parser.add_argument("dummy-compiler", action=DriverName)
+    parser.add_argument("--target", action=TargetOption)
+    # Invalid opiton: positional and optional options are mixed
+    parser.add_argument("verbose", "-v", action=NormalOption)
+    parser.add_argument("input", action=NormalOption)
+    parser.add_argument("output", action=NormalOption)
+
+    return parser
diff --git a/compiler/one-cmds/tests/onecc_neg_038.test b/compiler/one-cmds/tests/onecc_neg_038.test
new file mode 100644 (file)
index 0000000..13c7d75
--- /dev/null
@@ -0,0 +1,112 @@
+#!/bin/bash
+
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Boolean type option has multiple options. 
+
+: '
+This test assumes below directories.
+
+[one hierarchy]
+    one
+    â”œâ”€â”€ backends
+    â”‚   â””── command
+    â”‚       â””── codegen
+    â”œâ”€â”€ bin
+    â”œâ”€â”€ doc
+    â”œâ”€â”€ include
+    â”œâ”€â”€ lib
+    â”œâ”€â”€ optimization
+    â”œâ”€â”€ target
+    â””── test # pwd
+'
+
+BACKENDS_ALREADY_EXIST=true
+CMD_ALREADY_EXIST=true
+DUMMY_ALREADY_EXIST=true
+TARGET_ALREADY_EXIST=true
+
+BACKEND_NAME="dummy"
+
+filename_ext="$(basename -- $0)"
+filename="${filename_ext%.*}"
+
+driver_name="dummy-compiler"
+configfile="onecc_neg_038.cfg"
+outputfile="onecc_neg_038.tvn"
+targetfile="onecc_neg_038.ini"
+
+clean_envir()
+{
+  rm -rf ../bin/${driver_name}
+  rm -rf ../target/${targetfile}
+  rm -rf "../backends/command/${BACKEND_NAME}/codegen.py"
+  if [ "$TARGET_ALREADY_EXIST" = false ]; then
+    rm -rf ../target/
+  fi
+  if [ "$DUMMY_ALREADY_EXIST" = false ]; then
+    rm -rf "../backends/command/${BACKEND_NAME}/"
+  fi
+  if [ "$CMD_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/command/
+  fi
+  if [ "$BACKENDS_ALREADY_EXIST" = false ]; then
+    rm -rf ../backends/
+  fi
+}
+
+trap_err_onexit()
+{
+  if grep -q "Only either of option type is allowed: positional or optional" "${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
+rm -rf ${outputfile}
+
+if [ ! -d "../target/" ]; then
+  mkdir -p ../target/
+  TARGET_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/" ]; then
+  mkdir -p ../backends/
+  BACKENDS_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/" ]; then
+  mkdir -p ../backends/command/
+  CMD_ALREADY_EXIST=false
+fi
+if [ ! -d "../backends/command/${BACKEND_NAME}/" ]; then
+  mkdir -p ../backends/command/${BACKEND_NAME}/
+  DUMMY_ALREADY_EXIST=false
+fi
+
+# copy dummy tools to bin folder
+cp ${driver_name} ../bin/
+cp ${targetfile} ../target/
+cp onecc_neg_038.py "../backends/command/${BACKEND_NAME}/codegen.py"
+
+# run test
+onecc -C ${configfile} > ${filename}.log 2>&1
+
+echo "${filename_ext} FAILED"
+exit 255
index 9b02b74..b6bcb73 100644 (file)
@@ -52,7 +52,14 @@ def _run_model(model, inputs):
         list of numpy.ndarray: inference outputs
     """
     output_names = list(map(lambda output: output.name, model.graph.output))
-    session = rt.InferenceSession(model.SerializeToString())
+    options = rt.SessionOptions()
+    # NOTE this is needed for U18.04
+    # referenced: https://github.com/microsoft/onnxruntime/issues/10113
+    options.intra_op_num_threads = 4
+    # NOTE set `providers` for https://github.com/microsoft/onnxruntime/issues/17631
+    providers = rt.get_available_providers()
+    session = rt.InferenceSession(
+        model.SerializeToString(), sess_options=options, providers=providers)
     outputs = session.run(output_names, inputs)
     return outputs
 
index 915beff..e701b4c 100644 (file)
@@ -57,10 +57,14 @@ if [[ ! -s "img_files" ]]; then
     # https://github.com/Samsung/ONE/issues/3213#issuecomment-722757499
 fi
 
-if [ ! -d "raw_files" ] || [ ! -s "datalist.txt" ]; then
+if [ ! -d "raw_files" ] || [ ! -s "datalist.txt" ] || [ ! -d "numpy_files" ] || [ ! -s "datalist_numpy.txt" ]; then
     ../bin/venv/bin/python preprocess_images.py
 fi
 
+if [ ! -d "numpy_files" ] || [ ! -s "datalist_numpy.txt" ]; then
+    ../bin/venv/bin/python preprocess_images_numpy.py
+fi
+
 if [[ ! -s "inception_v3_test_data.h5" ]]; then
   ../bin/venv/bin/python ../bin/rawdata2hdf5 \
   --data_list datalist.txt \
@@ -124,6 +128,24 @@ if [[ ! -s "UnidirSeqLSTM.tflite" ]]; then
     # https://github.com/Samsung/ONE/issues/9940#issuecomment-1293282484
 fi
 
+if [[ ! -s "onnx_conv2d_conv2d_split.onnx" ]]; then
+    rm -rf onnx_conv2d_conv2d_split.zip
+    wget -nv https://github.com/Samsung/ONE/files/12711381/onnx_conv2d_conv2d_split.zip
+    unzip onnx_conv2d_conv2d_split.zip
+    # https://github.com/Samsung/ONE/issues/11280#issuecomment-1732852295
+fi
+
+if [[ ! -s "Add_000.inputs.txt" ]]; then
+    rm -rf Add_000.inputs.txt
+    echo "Add_000.circle.input0 Add_000.circle.input1" >> Add_000.inputs.txt
+fi
+
+# List file with wrong number of inputs (for negative test)
+if [[ ! -s "Add_000.wrong_inputs.txt" ]]; then
+    rm -rf Add_000.wrong_inputs.txt
+    echo "Add_000.circle.input0 Add_000.circle.input1 Add_000.circle.input2" >> Add_000.wrong_inputs.txt
+fi
+
 function files_missing() {
     condition="test "
 
@@ -157,6 +179,15 @@ if files_missing "${NEG_TEST_RECCURENT_MODELS[@]}"; then
     # https://github.com/Samsung/ONE/issues/8395#issuecomment-1050364375
 fi
 
+declare -a ADD_000_MODEL_AND_INPUTS=("Add_000.circle" "Add_000.circle.input0" "Add_000.circle.input1")
+
+if files_missing "${ADD_000_MODEL_AND_INPUTS}"; then
+    rm -rf Add_000.zip
+    wget -nv https://github.com/Samsung/ONE/files/13211993/Add_000.zip
+    unzip Add_000.zip
+    # https://github.com/Samsung/ONE/issues/11724#issuecomment-1786420834
+fi
+
 # prepare 'inception_v3.circle' file used for quantization test
 inputfile="./inception_v3.pb"
 outputfile="./inception_v3.circle"
index ced6e3a..3cbefd5 100644 (file)
 import os, shutil, PIL.Image, numpy as np
 
 input_dir = 'img_files'
-output_dir = 'raw_files'
-list_file = 'datalist.txt'
+raw_output_dir = 'raw_files'
+raw_list_file = 'datalist.txt'
+numpy_output_dir = 'numpy_files'
+numpy_list_file = 'datalist_numpy.txt'
 
-if os.path.exists(output_dir):
-    shutil.rmtree(output_dir, ignore_errors=True)
-os.makedirs(output_dir)
+if os.path.exists(raw_output_dir):
+    shutil.rmtree(raw_output_dir, ignore_errors=True)
+os.makedirs(raw_output_dir)
+
+if os.path.exists(numpy_output_dir):
+    shutil.rmtree(numpy_output_dir, ignore_errors=True)
+os.makedirs(numpy_output_dir)
 
 for (root, _, files) in os.walk(input_dir):
-    datalist = open(list_file, 'w')
+    raw_datalist = open(raw_list_file, 'w')
+    numpy_datalist = open(numpy_list_file, 'w')
     for f in files:
         with PIL.Image.open(root + '/' + f) as image:
             # To handle ANTIALIAS deprecation
@@ -32,7 +39,15 @@ for (root, _, files) in os.walk(input_dir):
 
             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)
-            datalist.writelines(os.path.abspath(output_file) + '\n')
-    datalist.close()
+            # To save in numpy format
+            output_numpy_file = numpy_output_dir + '/' + f.replace('jpg', 'npy')
+            np.save('./' + output_numpy_file, img)
+            numpy_datalist.writelines(os.path.abspath(output_numpy_file) + '\n')
+
+            # To save in raw data format
+            output_raw_file = raw_output_dir + '/' + f.replace('jpg', 'data')
+            img.tofile(output_raw_file)
+            raw_datalist.writelines(os.path.abspath(output_raw_file) + '\n')
+
+    raw_datalist.close()
+    numpy_datalist.close()
diff --git a/compiler/one-cmds/tests/preprocess_images_numpy.py b/compiler/one-cmds/tests/preprocess_images_numpy.py
new file mode 100644 (file)
index 0000000..3593109
--- /dev/null
@@ -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.
+
+import os, shutil, PIL.Image, numpy as np
+
+input_dir = 'img_files'
+output_dir = 'numpy_files'
+list_file = 'datalist_numpy.txt'
+
+if os.path.exists(output_dir):
+    shutil.rmtree(output_dir, ignore_errors=True)
+os.makedirs(output_dir)
+
+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:
+            # To handle ANTIALIAS deprecation
+            ANTIALIAS = PIL.Image.Resampling.LANCZOS if hasattr(
+                PIL.Image, "Resampling") else PIL.Image.ANTIALIAS
+
+            # To save in numpy format
+            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', 'npy')
+            np.save('./' + output_file, img)
+            datalist.writelines(os.path.abspath(output_file) + '\n')
+    datalist.close()
diff --git a/compiler/one-cmds/tests/rawdata2hdf5_002.test b/compiler/one-cmds/tests/rawdata2hdf5_002.test
new file mode 100644 (file)
index 0000000..d7b36cd
--- /dev/null
@@ -0,0 +1,42 @@
+#!/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
+
+outputfile="./rawdata2hdf5_002.h5"
+
+rm -f ${filename}.log
+rm -rf ${outputfile}
+
+# run test
+rawdata2hdf5 \
+--data_list Add_000.inputs.txt \
+--output_path ${outputfile} > ${filename}.log 2>&1
+
+if [[ ! -s "${outputfile}" ]]; then
+  trap_err_onexit
+fi
+
+echo "${filename_ext} SUCCESS"
index df06201..1691517 100644 (file)
@@ -19,7 +19,7 @@ filename="${filename_ext%.*}"
 
 trap_err_onexit()
 {
-  if grep -q "Unable to create file" "${filename}.log"; then
+  if grep -q "FileNotFoundError" "${filename}.log"; then
     echo "${filename_ext} SUCCESS"
     exit 0
   fi
index eac2f6d..28217e4 100644 (file)
@@ -64,7 +64,14 @@ class OnnxRunner:
     def load(self):
         model = onnx.load(self.filepath)
         onnx.checker.check_model(model)
-        self.session = ort.InferenceSession(self.filepath)
+        options = ort.SessionOptions()
+        # NOTE this is needed for U18.04
+        # referenced: https://github.com/microsoft/onnxruntime/issues/10113
+        options.intra_op_num_threads = 4
+        # NOTE set `providers` for https://github.com/microsoft/onnxruntime/issues/17631
+        providers = ort.get_available_providers()
+        self.session = ort.InferenceSession(
+            self.filepath, sess_options=options, providers=providers)
 
     def feed_random_inputs(self):
         self.inputs = self.session.get_inputs()
index 3d7aa89..36200e8 100644 (file)
@@ -4,8 +4,8 @@ _onecc-docker_ broadens ONE tools to be used in other platforms.
 
 ## Description
 
-For now, ONE tools only support Ubuntu 18.04 and 20.04(not officially).
-So, it is difficult for people in different environments to use our tools without using ubuntu 18.04.
+For now, ONE tools only support Ubuntu 18.04 and 20.04.
+So, it is difficult for people in different environments to use our tools without using ubuntu 20.04.
 
 To overcome this limitation, we provide _onecc-docker_ that runs using a Docker so that users can use ONE tools more widely.
 
@@ -21,8 +21,8 @@ This tool aims at the following objectives.
     - Requires root privileges.
            - _onecc-docker_ requires the current `user ID` to be included in the `Docker group` because it requires the Docker-related commands to be executed without `sudo` privileges.
              - See "[Post-installation steps for Linux](https://docs.docker.com/engine/install/linux-postinstall/)"
-- Python 3.8
-  - requests
+- Python 3
+  - Requires for __onecc-docker__ command
 
 ## Note
 
index 4687d10..6e7329d 100644 (file)
@@ -9,5 +9,5 @@ Homepage: https://github.com/Samsung/ONE
 Package: onecc-docker
 Architecture: amd64
 Multi-Arch: foreign
-Depends: ${misc:Depends}, ${shlibs:Depends}, python3.8
+Depends: ${misc:Depends}, ${shlibs:Depends}, python3
 Description: On-device Neural Engine docker package
index ae91279..effa588 100644 (file)
@@ -1,26 +1,26 @@
-# 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 
+# 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
 
-FROM ubuntu:18.04 
+FROM ubuntu:20.04
 
 ARG VERSION
 
-RUN apt-get update && apt-get install -qqy --no-install-recommends \ 
+RUN apt-get update && apt-get install -qqy --no-install-recommends \
     wget \
-    ca-certificates \ 
-    && 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/* 
+    ca-certificates \
+    && wget --no-check-certificate https://github.com/Samsung/ONE/releases/download/${VERSION}/one-compiler-focal_${VERSION}_amd64.deb \
+    && apt-get install -y ./one-compiler-focal_${VERSION}_amd64.deb \
+    && rm -rf /var/lib/apt/lists/*
+
 ENTRYPOINT ["onecc"]
index c68c7f1..10c72f0 100644 (file)
@@ -44,14 +44,15 @@ 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
+
+    for release_item in response.json():
+        # Return the latest version containing one-compiler-focal_{version}_amd64.deb in assets
+        version = release_item["tag_name"]
+        for asset in release_item["assets"]:
+            if bool(
+                    re.match(r'one-compiler-focal_\d+\.\d+\.\d_amd64.deb',
+                             asset["name"])):
+                return version
 
     raise SystemExit('[onecc-docker] Failed to get latest onecc version')
 
diff --git a/compiler/oneco-value-pbtxt-test/exclude.me b/compiler/oneco-value-pbtxt-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/oneco/exclude.me b/compiler/oneco/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/onnx2circle/exclude.me b/compiler/onnx2circle/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/onnx2tflite-integration-test/exclude.me b/compiler/onnx2tflite-integration-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/onnx2tflite/exclude.me b/compiler/onnx2tflite/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/onnxkit/exclude.me b/compiler/onnxkit/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 84a6b81..af4526c 100644 (file)
@@ -43,7 +43,7 @@ class UserExn : public std::exception
 public:
   UserExn() = delete;
 
-  template <typename... Info> UserExn(const std::string &msg, Info &&... args)
+  template <typename... Info> UserExn(const std::string &msg, Info &&...args)
   {
     std::stringstream out;
 
@@ -58,7 +58,7 @@ public:
 
 private:
   template <typename Attr, typename Val, typename... AttsVals>
-  void build_info(std::stringstream &out, Attr &attr, Val &val, AttsVals &... args)
+  void build_info(std::stringstream &out, Attr &attr, Val &val, AttsVals &...args)
   {
     out << pepper::str(attr, " = ", val);
     out << ", ";
diff --git a/compiler/pepper-assert/exclude.me b/compiler/pepper-assert/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/pepper-env/exclude.me b/compiler/pepper-env/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 0c74aa8..9b33f33 100644 (file)
@@ -27,7 +27,7 @@ namespace pepper
 namespace details
 {
 
-template <typename... Arg> void str_impl(std::ostream &os, Arg &&... args);
+template <typename... Arg> void str_impl(std::ostream &os, Arg &&...args);
 
 template <> inline void str_impl(std::ostream &)
 {
@@ -41,7 +41,7 @@ template <typename Arg> inline void str_impl(std::ostream &os, Arg &&arg)
 }
 
 template <typename Arg, typename... Args>
-inline void str_impl(std::ostream &os, Arg &&arg, Args &&... args)
+inline void str_impl(std::ostream &os, Arg &&arg, Args &&...args)
 {
   str_impl(os, std::forward<Arg>(arg));
   str_impl(os, std::forward<Args>(args)...);
@@ -53,7 +53,7 @@ inline void str_impl(std::ostream &os, Arg &&arg, Args &&... args)
 namespace pepper
 {
 
-template <typename... Args> static inline std::string str(Args &&... args)
+template <typename... Args> static inline std::string str(Args &&...args)
 {
   std::stringstream ss;
   details::str_impl(ss, std::forward<Args>(args)...);
index 053d6a0..a6f955a 100644 (file)
@@ -1,4 +1,4 @@
-nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
+nnas_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 if(NOT FlatBuffers_FOUND)
   message(STATUS "Configure pics: FAILED (missing FlatBuffers)")
   return()
@@ -11,7 +11,7 @@ unset(PICS_DEPS)
 ###
 set(CIRCLE_SCHEMA_PYTHON_DIR "${CMAKE_CURRENT_BINARY_DIR}/circle")
 
-get_target_property(SCHEMA_BIN_PATH mio_circle06 BINARY_DIR)
+get_target_property(SCHEMA_BIN_PATH mio_circle08 BINARY_DIR)
 
 add_custom_command(
   OUTPUT ${CIRCLE_SCHEMA_PYTHON_DIR}
index 1b77457..b1d3260 100644 (file)
@@ -1 +1 @@
-require("mio-circle06")
+require("mio-circle08")
diff --git a/compiler/plier-tf/exclude.me b/compiler/plier-tf/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index ec86fd9..059f2c8 100644 (file)
@@ -31,8 +31,8 @@ unset(TEST_DEPS)
 
 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)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/gen_h5_explicit_inputs_all.py"
+               "${CMAKE_CURRENT_BINARY_DIR}/gen_h5_explicit_inputs_all.py" COPYONLY)
 
 set(VIRTUALENV "${NNCC_OVERLAY_DIR}/venv_2_12_1")
 
@@ -66,6 +66,7 @@ list(APPEND TEST_DEPS "${TEST_CONFIG}" "${CMAKE_CURRENT_BINARY_DIR}/circle")
 add_custom_target(pota_quantization_value_test_deps ALL DEPENDS ${TEST_DEPS})
 
 # Run tests
+# NOTE. The order of the test matters as some tests depend on previous tests.
 add_test(
   NAME pota_fake_wquant_test
   COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/test_fake_wquant.sh"
diff --git a/compiler/pota-quantization-value-test/compare_tensors.py b/compiler/pota-quantization-value-test/compare_tensors.py
deleted file mode 100755 (executable)
index fceeba5..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/env python3
-import h5py as h5
-import numpy as np
-import argparse
-import os.path
-import json
-import sys
-
-#
-# This script checks if the min/max values recorded in the circle model are the same with the expected values
-#
-# Basic usage:
-#   compare_tensors.py --input_h5 <path/to/iput/h5> --expect_dir <path/to/expect/dir> --mode <compare_mode>
-#   ex: compare_minmax.py --input_h5 Add_000.h5 --expect_dir expected_outputs/Add_000 --mode fake_quantization
-
-parser = argparse.ArgumentParser()
-parser.add_argument('--input_h5', type=str, required=True)
-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", "weights_only_quantization"
-]
-
-model = args.input_h5
-expect_dir = args.expect_dir
-mode = args.mode
-
-failed_cases = 0
-
-if mode not in supported_modes:
-    raise SystemExit("Unsupported mode. --mode should be one of " + str(supported_modes))
-
-
-def compare_fake_quantization(tensor, tensor_name, expect_dir):
-    global failed_cases
-    with open(expect_dir + "/" + tensor_name + ".json", "r") as expect_file:
-        json_load = json.load(expect_file)
-    expected_weights = np.array(json_load["weights"])
-    input_weights = tensor["weights"][:]
-    if np.allclose(input_weights, expected_weights, rtol=1.e-5, atol=1.e-5) == False:
-        print("Fake-quantized weights of " + tensor_name + " (" + str(input_weights) +
-              ") do not match with expected value (" + str(expected_weights) + ").")
-        failed_cases += 1
-
-
-def compare_record_minmax(tensor, tensor_name, expect_dir):
-    global failed_cases
-    with open(expect_dir + "/" + tensor_name + ".json", "r") as expect_file:
-        json_load = json.load(expect_file)
-    expected_min = np.array(json_load["min"])
-    expected_max = np.array(json_load["max"])
-    input_min = tensor["min"][:]
-    input_max = tensor["max"][:]
-    if np.allclose(input_min, expected_min, rtol=1.e-5, atol=1.e-5) == False:
-        print("Recorded min of " + tensor_name + " (" + str(input_min) +
-              ") does not match with expected value (" + str(expected_min) + ").")
-        failed_cases += 1
-    if np.allclose(input_max, expected_max, rtol=1.e-5, atol=1.e-5) == False:
-        print("Recorded max of " + tensor_name + " (" + str(input_max) +
-              ") does not match with expected value (" + str(expected_max) + ").")
-        failed_cases += 1
-
-
-def compare_quantization(tensor, tensor_name, expect_dir):
-    global failed_cases
-    with open(expect_dir + "/" + tensor_name + ".json", "r") as expect_file:
-        json_load = json.load(expect_file)
-    for key in json_load:
-        if key == "weights":
-            expected_weights = np.array(json_load["weights"])
-            input_weights = tensor["weights"][()]
-            abs_tolerance = 1
-            # We use higher tolerance for int64 data (bias of int16-quantized model)
-            if tensor["weights"].dtype == 'int64':
-                abs_tolerance = 5
-
-            if np.allclose(
-                    input_weights, expected_weights, rtol=0, atol=abs_tolerance) == False:
-                print("Quantized weights of " + tensor_name + " (" + str(input_weights) +
-                      ") do not match with expected value (" + str(expected_weights) +
-                      ").")
-                failed_cases += 1
-
-        if key == "scale":
-            expected_scale = np.array(json_load["scale"])
-            input_scale = tensor["scale"][:]
-            if np.allclose(input_scale, expected_scale, rtol=1.e-5, atol=1.e-5) == False:
-                print("Quantized scale of " + tensor_name + " (" + str(input_scale) +
-                      ") do not match with expected value (" + str(expected_scale) + ").")
-                failed_cases += 1
-
-        if key == "zero_point":
-            expected_zero_point = np.array(json_load["zero_point"])
-            input_zero_point = tensor["zero_point"][:]
-            if np.allclose(
-                    input_zero_point, expected_zero_point, rtol=0, atol=1) == False:
-                print("Quantized zero_point of " + tensor_name + " (" +
-                      str(input_zero_point) + ") do not match with expected value (" +
-                      str(expected_zero_point) + ").")
-                failed_cases += 1
-
-
-with h5.File(model, "r") as input:
-    for tensor_name in input.keys():
-        # We only check the given golden data
-        if os.path.isfile(expect_dir + "/" + tensor_name + ".json"):
-            print("Compare " + tensor_name)
-            if mode == "fake_quantization":
-                compare_fake_quantization(input[tensor_name], tensor_name, expect_dir)
-            elif mode == "record_minmax":
-                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.")
-
-sys.exit(failed_cases)
diff --git a/compiler/pota-quantization-value-test/compare_tensors_all.py b/compiler/pota-quantization-value-test/compare_tensors_all.py
new file mode 100644 (file)
index 0000000..98fe1d0
--- /dev/null
@@ -0,0 +1,203 @@
+#!/usr/bin/env python3
+import h5py as h5
+import numpy as np
+import argparse
+from io import StringIO
+import os.path
+import json
+import logging
+import sys
+
+#
+# This script checks if the min/max values recorded in the circle model are the same with the expected values
+#
+parser = argparse.ArgumentParser()
+parser.add_argument(
+    '--test_param',
+    type=str,
+    required=True,
+    nargs='+',
+    help=
+    'All the param list to test. e.g. ${RECIPE_NAME_0} ${GRANULARITY_0} ${DTYPE_0} ${RECIPE_NAME_1} ${GRANULARITY_1} ${DTYPE_1}..'
+)
+parser.add_argument(
+    '--bin_dir',
+    type=str,
+    required=True,
+    help='Directory path wehre test files are generated')
+parser.add_argument(
+    '--source_dir',
+    type=str,
+    required=True,
+    help='Directory path where expected outputs exist')
+parser.add_argument('--mode', type=str, required=True, help='Mode to test')
+args = parser.parse_args()
+
+modes_to_expected_folder = {
+    'fake_quantization': 'fake_quantization',
+    'mixed_fake_quantization': 'fake_quantization',
+    'record_minmax': 'record_minmax',
+    'parallel_record_minmax': 'record_minmax',
+    'quantization': 'quantization',
+    'mixed_quantization': 'quantization',
+    'weights_only_quantization': 'wo_quantization'
+}
+modes_to_input_h5_suffix = {
+    'fake_quantization': 'fake_quantized.circle.h5',
+    'mixed_fake_quantization': 'fake_quantized.mixed.circle.h5',
+    'record_minmax': 'minmax_recorded.circle.h5',
+    'parallel_record_minmax': 'parallel_minmax_recorded.circle.h5',
+    'quantization': 'quantized.circle.h5',
+    'mixed_quantization': 'quantized.mixed.circle.h5',
+    'weights_only_quantization': 'wo_quantized.circle.h5'
+}
+
+test_param = args.test_param
+bin_dir = args.bin_dir
+source_dir = args.source_dir
+mode = args.mode
+
+if mode in ['mixed_fake_quantization', 'parallel_record_minmax', 'mixed_quantization']:
+    source_dir += '_config'
+
+log_format = '%(levelname)s: %(message)s'
+formatter = logging.Formatter(log_format)
+streamer = StringIO()
+stream_handler = logging.StreamHandler(stream=streamer)
+stream_handler.setFormatter(formatter)
+logging.basicConfig(handlers=[stream_handler])
+
+if mode not in modes_to_expected_folder.keys():
+    raise SystemExit("Unsupported mode. --mode should be one of " +
+                     str(modes_to_expected_folder.keys()))
+
+
+def compare_fake_quantization(tensor, tensor_name, expect_dir):
+    with open(expect_dir + "/" + tensor_name + ".json", "r") as expect_file:
+        json_load = json.load(expect_file)
+    expected_weights = np.array(json_load["weights"])
+    input_weights = tensor["weights"][:]
+    if np.allclose(input_weights, expected_weights, rtol=1.e-5, atol=1.e-5) == False:
+        logging.error("Fake-quantized weights of " + tensor_name + " (" +
+                      str(input_weights) + ") do not match with expected value (" +
+                      str(expected_weights) + ").")
+        return False
+    return True
+
+
+def compare_record_minmax(tensor, tensor_name, expect_dir):
+    test_result = True
+    with open(expect_dir + "/" + tensor_name + ".json", "r") as expect_file:
+        json_load = json.load(expect_file)
+    expected_min = np.array(json_load["min"])
+    expected_max = np.array(json_load["max"])
+    input_min = tensor["min"][:]
+    input_max = tensor["max"][:]
+    if np.allclose(input_min, expected_min, rtol=1.e-5, atol=1.e-5) == False:
+        logging.error("Recorded min of " + tensor_name + " (" + str(input_min) +
+                      ") does not match with expected value (" + str(expected_min) + ").")
+        test_result = False
+    if np.allclose(input_max, expected_max, rtol=1.e-5, atol=1.e-5) == False:
+        logging.error("Recorded max of " + tensor_name + " (" + str(input_max) +
+                      ") does not match with expected value (" + str(expected_max) + ").")
+        test_result = False
+    return test_result
+
+
+def compare_quantization(tensor, tensor_name, expect_dir):
+    test_result = True
+    with open(expect_dir + "/" + tensor_name + ".json", "r") as expect_file:
+        json_load = json.load(expect_file)
+    for key in json_load:
+        if key == "weights":
+            expected_weights = np.array(json_load["weights"])
+            input_weights = tensor["weights"][()]
+            abs_tolerance = 1
+            # We use higher tolerance for int64 data (bias of int16-quantized model)
+            if tensor["weights"].dtype == 'int64':
+                abs_tolerance = 5
+
+            if np.allclose(
+                    input_weights, expected_weights, rtol=0, atol=abs_tolerance) == False:
+                logging.error(
+                    "Quantized weights of " + tensor_name + " (" + str(input_weights) +
+                    ") do not match with expected value (" + str(expected_weights) + ").")
+                test_result = False
+
+        if key == "scale":
+            expected_scale = np.array(json_load["scale"])
+            input_scale = tensor["scale"][:]
+            if np.allclose(input_scale, expected_scale, rtol=1.e-5, atol=1.e-5) == False:
+                logging.error("Quantized scale of " + tensor_name + " (" +
+                              str(input_scale) + ") do not match with expected value (" +
+                              str(expected_scale) + ").")
+                test_result = False
+
+        if key == "zero_point":
+            expected_zero_point = np.array(json_load["zero_point"])
+            input_zero_point = tensor["zero_point"][:]
+            if np.allclose(
+                    input_zero_point, expected_zero_point, rtol=0, atol=1) == False:
+                logging.error("Quantized zero_point of " + tensor_name + " (" +
+                              str(input_zero_point) +
+                              ") do not match with expected value (" +
+                              str(expected_zero_point) + ").")
+                test_result = False
+    return test_result
+
+
+def chunks(lst, n):
+    """Yield successive n-sized chunks from the list"""
+    for i in range(0, len(lst), n):
+        yield lst[i:i + n]
+
+
+failed_log = dict()
+inputs = test_param[0].split()
+PARAM_SET_SIZE = 3
+assert (len(inputs) % PARAM_SET_SIZE) == 0
+inputs = list(chunks(inputs, PARAM_SET_SIZE))
+for idx in range(len(inputs)):
+    model_name = inputs[idx][0]
+    granularity = inputs[idx][1]
+    dtype = inputs[idx][2]
+
+    testcase = f'{model_name}.{granularity}.{dtype}'
+    test_result_file = os.path.join(bin_dir, testcase)
+    input_h5 = f'{test_result_file}.{modes_to_input_h5_suffix[mode]}'
+    with h5.File(input_h5, 'r') as input:
+        for tensor_name in input.keys():
+            expect_dir = f'{source_dir}/expected_outputs/{model_name}/{granularity}/{dtype}/{modes_to_expected_folder[mode]}'
+            if os.path.isfile(expect_dir + "/" + tensor_name + ".json"):
+                test_result = False
+                if mode in ["fake_quantization", "mixed_fake_quantization"]:
+                    test_result = compare_fake_quantization(input[tensor_name],
+                                                            tensor_name, expect_dir)
+                elif mode in ["record_minmax", "parallel_record_minmax"]:
+                    test_result = compare_record_minmax(input[tensor_name], tensor_name,
+                                                        expect_dir)
+                elif mode in ["quantization", "mixed_quantization"]:
+                    test_result = compare_quantization(input[tensor_name], tensor_name,
+                                                       expect_dir)
+                elif mode == "weights_only_quantization":
+                    # Assume weights have name "ker"
+                    if tensor_name == "ker":
+                        test_result = compare_quantization(input[tensor_name],
+                                                           tensor_name, expect_dir)
+                else:
+                    raise SystemExit("Unsupproted mode.")
+
+                if not test_result:
+                    failed_log[testcase] = streamer.getvalue().rstrip()
+                    # Clean log
+                    streamer = StringIO()
+                    stream_handler.setStream(streamer)
+
+failed_number = len(failed_log)
+if failed_number != 0:
+    print('FAILED')
+    for testcase in failed_log:
+        print(f'- {testcase}')
+        print(failed_log[testcase])
+
+sys.exit(failed_number)
diff --git a/compiler/pota-quantization-value-test/gen_h5_explicit_inputs.py b/compiler/pota-quantization-value-test/gen_h5_explicit_inputs.py
deleted file mode 100755 (executable)
index a00cbeb..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python3
-import h5py as h5
-import numpy as np
-from circle.Model import Model
-from circle.TensorType import TensorType
-import argparse
-import glob
-
-#
-# This script generates a pack of random input data (.h5) expected by the input circle model
-#
-# Basic usage:
-#   gen_h5_explicit_inputs.py --model <path/to/model/file> --input <path/to/input/directory> --output <path/to/output/file>
-#   ex: gen_h5_explicit_inputs.py --model Add_000.circle --input Add_000 --output Add_000.input.h5
-#   (This will create Add_000.input.h5)
-#
-# The input directory should be organized as follows
-# <input_directory>/
-#   -> <record_index>.txt
-#     ...
-# Each txt file has the explicit values of inputs
-# Example. if the model has two inputs whose shapes are both (1, 3),
-# the first record file name is 0.txt, and its contents is something like below
-# 1, 2, 3
-# 4, 5, 6
-#
-parser = argparse.ArgumentParser()
-parser.add_argument('--model', type=str, required=True)
-parser.add_argument('--input', type=str, required=True)
-parser.add_argument('--output', type=str, required=True)
-args = parser.parse_args()
-
-model = args.model
-input = args.input
-output = args.output
-
-with open(model, 'rb') as f:
-    buf = f.read()
-    circle_model = Model.GetRootAsModel(buf, 0)
-
-# Assume one subgraph
-assert (circle_model.SubgraphsLength() == 1)
-graph = circle_model.Subgraphs(0)
-inputs = graph.InputsAsNumpy()
-
-# Create h5 file
-h5_file = h5.File(output, 'w')
-group = h5_file.create_group("value")
-group.attrs['desc'] = "Input data for " + model
-
-
-def toNumpyType(circle_type):
-    if circle_type == TensorType.UINT8:
-        return np.uint8
-    if circle_type == TensorType.FLOAT32:
-        return np.float32
-    if circle_type == TensorType.INT16:
-        return np.int16
-
-
-# Input files
-records = sorted(glob.glob(input + "/*.txt"))
-for i, record in enumerate(records):
-    sample = group.create_group(str(i))
-    sample.attrs['desc'] = "Input data " + str(i)
-    with open(record, 'r') as f:
-        lines = f.readlines()
-        for j, line in enumerate(lines):
-            data = np.array(line.split(','))
-            input_index = inputs[j]
-            tensor = graph.Tensors(input_index)
-            np_type = toNumpyType(tensor.Type())
-            input_data = np.array(data.reshape(tensor.ShapeAsNumpy()), np_type)
-            sample.create_dataset(str(j), data=input_data)
-
-h5_file.close()
diff --git a/compiler/pota-quantization-value-test/gen_h5_explicit_inputs_all.py b/compiler/pota-quantization-value-test/gen_h5_explicit_inputs_all.py
new file mode 100644 (file)
index 0000000..c14a54e
--- /dev/null
@@ -0,0 +1,126 @@
+#!/usr/bin/env python3
+import h5py as h5
+import numpy as np
+from circle.Model import Model
+from circle.TensorType import TensorType
+import argparse
+import glob
+import os
+
+
+def chunks(lst, n):
+    """Yield successive n-sized chunks from the list"""
+    for i in range(0, len(lst), n):
+        yield lst[i:i + n]
+
+
+def toNumpyType(circle_type):
+    if circle_type == TensorType.UINT8:
+        return np.uint8
+    if circle_type == TensorType.FLOAT32:
+        return np.float32
+    if circle_type == TensorType.INT16:
+        return np.int16
+
+
+#
+# This script generates a pack of random input data (.h5) expected by the input circle models
+#
+# The input directory should be organized as follows
+# <input_directory>/
+#   -> <record_index>.txt
+#     ...
+# Each txt file has the explicit values of inputs
+# Example. if the model has two inputs whose shapes are both (1, 3),
+# the first record file name is 0.txt, and its contents is something like below
+# 1, 2, 3
+# 4, 5, 6
+#
+parser = argparse.ArgumentParser()
+parser.add_argument(
+    '--output_dir',
+    type=str,
+    required=True,
+    help='Output directory where the inputs are generated')
+parser.add_argument(
+    '--artifact_dir',
+    type=str,
+    required=True,
+    help='Artifact directory where test files exist')
+parser.add_argument(
+    '--input_dir',
+    type=str,
+    required=True,
+    help='Input directory where input text files exist')
+parser.add_argument(
+    '--test_param',
+    type=str,
+    required=True,
+    nargs='+',
+    help=
+    'All the param list to test. e.g. ${RECIPE_NAME_0} ${GRANULARITY_0} ${DTYPE_0} ${RECIPE_NAME_1} ${GRANULARITY_1} ${DTYPE_1}..'
+)
+parser.add_argument('--config', action='store_true', help='Generate inputs with config')
+parser.add_argument('--mode', type=str, default='default', help='Mode to test')
+args = parser.parse_args()
+
+output_dir = args.output_dir
+artifact_dir = args.artifact_dir
+input_dir = args.input_dir
+test_param = args.test_param
+config = args.config
+mode = args.mode
+
+modes_to_input_h5_suffix = {
+    'default': 'input.h5',
+    'mixed_quantization': 'mixed.input.h5',
+}
+
+test_params = test_param[0].split()
+PARAM_SET_SIZE = 3
+assert (len(test_params) % PARAM_SET_SIZE) == 0
+test_params = list(chunks(test_params, PARAM_SET_SIZE))
+for idx in range(len(test_params)):
+    model_name = test_params[idx][0]
+    granularity = test_params[idx][1]
+    dtype = test_params[idx][2]
+
+    model = os.path.join(artifact_dir, model_name + '.circle')
+    with open(model, 'rb') as f:
+        buf = f.read()
+        circle_model = Model.GetRootAsModel(buf, 0)
+
+    # Assume one subgraph
+    assert (circle_model.SubgraphsLength() == 1)
+    graph = circle_model.Subgraphs(0)
+    inputs = graph.InputsAsNumpy()
+
+    testcase = f'{model_name}.{granularity}.{dtype}'
+    output = os.path.join(output_dir, f'{testcase}.{modes_to_input_h5_suffix[mode]}')
+
+    # Create h5 file
+    h5_file = h5.File(output, 'w')
+    group = h5_file.create_group("value")
+    group.attrs['desc'] = "Input data for " + model
+
+    if config:
+        input_text_dir = os.path.join(input_dir,
+                                      f'{model_name}_config/{granularity}/{dtype}')
+    else:
+        input_text_dir = os.path.join(input_dir, f'{model_name}/{granularity}/{dtype}')
+    # Input files
+    records = sorted(glob.glob(input_text_dir + "/*.txt"))
+    for i, record in enumerate(records):
+        sample = group.create_group(str(i))
+        sample.attrs['desc'] = "Input data " + str(i)
+        with open(record, 'r') as f:
+            lines = f.readlines()
+            for j, line in enumerate(lines):
+                data = np.array(line.split(','))
+                input_index = inputs[j]
+                tensor = graph.Tensors(input_index)
+                np_type = toNumpyType(tensor.Type())
+                input_data = np.array(data.reshape(tensor.ShapeAsNumpy()), np_type)
+                sample.create_dataset(str(j), data=input_data)
+
+    h5_file.close()
index 1331703..607c3a6 100755 (executable)
@@ -9,7 +9,7 @@
 # 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"
+COMPARE_SCRIPT_PATH="${SOURCE_PATH}/compare_tensors_all.py"
 CONFIG_PATH="$1"; shift
 BIN_PATH=$(dirname "${CONFIG_PATH}")
 TEST_INPUT_PATH="${SOURCE_PATH}/test_inputs"
@@ -25,6 +25,8 @@ TESTED=()
 PASSED=()
 FAILED=()
 
+TEST_PARAMS="$@"
+
 pushd "${WORKDIR}"
 while [ "$1" != "" ]; do  
   MODELNAME=$1; shift
@@ -54,32 +56,18 @@ while [ "$1" != "" ]; do
     "${CIRCLE_TENSORDUMP_PATH}" \
       "${TEST_RESULT_FILE}.fake_quantized.circle" \
       --tensors_to_hdf5 "${TEST_RESULT_FILE}.fake_quantized.circle.h5"
-
-    # Compare result
-    "${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
-      --input_h5 "${TEST_RESULT_FILE}.fake_quantized.circle.h5" \
-      --expect_dir "${SOURCE_PATH}/expected_outputs/${MODELNAME}/${GRANULARITY}/${DTYPE}/fake_quantization" \
-      --mode fake_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
+# Compare result
+"${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
+  --test_param "${TEST_PARAMS}" \
+  --bin_dir ${BIN_PATH} \
+  --source_dir ${SOURCE_PATH} \
+  --mode fake_quantization
+
+if [[ $? -ne 0 ]]; then
   exit 255
 fi
 
index 070b273..815ab4c 100755 (executable)
@@ -9,7 +9,7 @@
 # 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"
+COMPARE_SCRIPT_PATH="${SOURCE_PATH}/compare_tensors_all.py"
 CONFIG_PATH="$1"; shift
 BIN_PATH=$(dirname "${CONFIG_PATH}")
 WORKDIR="$1"; shift
@@ -24,6 +24,8 @@ TESTED=()
 PASSED=()
 FAILED=()
 
+TEST_PARAMS="$@"
+
 pushd "${WORKDIR}"
 while [ "$1" != "" ]; do  
   MODELNAME=$1; shift
@@ -54,32 +56,18 @@ while [ "$1" != "" ]; do
     "${CIRCLE_TENSORDUMP_PATH}" \
       "${TEST_RESULT_FILE}.fake_quantized.mixed.circle" \
       --tensors_to_hdf5 "${TEST_RESULT_FILE}.fake_quantized.mixed.circle.h5"
-
-    # Compare result
-    "${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
-      --input_h5 "${TEST_RESULT_FILE}.fake_quantized.mixed.circle.h5" \
-      --expect_dir "${SOURCE_PATH}/expected_outputs/${MODELNAME}_config/${GRANULARITY}/${DTYPE}/fake_quantization" \
-      --mode fake_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
+# Compare result
+"${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
+  --test_param "${TEST_PARAMS}" \
+  --bin_dir ${BIN_PATH} \
+  --source_dir ${SOURCE_PATH} \
+  --mode mixed_fake_quantization
+
+if [[ $? -ne 0 ]]; then
   exit 255
 fi
 
index 0af2c01..612215d 100755 (executable)
@@ -9,11 +9,11 @@
 # 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"
+COMPARE_SCRIPT_PATH="${SOURCE_PATH}/compare_tensors_all.py"
 CONFIG_PATH="$1"; shift
 BIN_PATH=$(dirname "${CONFIG_PATH}")
 TEST_INPUT_PATH="${SOURCE_PATH}/test_inputs"
-GEN_SCRIPT_PATH="${BIN_PATH}/gen_h5_explicit_inputs.py"
+GEN_SCRIPT_PATH="${BIN_PATH}/gen_h5_explicit_inputs_all.py"
 WORKDIR="$1"; shift
 
 source "${CONFIG_PATH}"
@@ -26,6 +26,21 @@ TESTED=()
 PASSED=()
 FAILED=()
 
+TEST_PARAMS="$@"
+
+# Generate h5 input data
+source "${VIRTUALENV}/bin/activate"
+"${VIRTUALENV}/bin/python" "${GEN_SCRIPT_PATH}" \
+  --output_dir ${BIN_PATH} \
+  --artifact_dir ${WORKDIR} \
+  --input_dir ${TEST_INPUT_PATH} \
+  --test_param "$TEST_PARAMS"
+
+if [[ $? -ne 0 ]]; then
+  echo "FAILED TO GENERATE INPUT"
+  exit 255
+fi
+
 pushd "${WORKDIR}"
 while [ "$1" != "" ]; do
   MODELNAME=$1; shift
@@ -44,50 +59,29 @@ while [ "$1" != "" ]; do
   cat > "${TEST_RESULT_FILE}_parallel_record_minmax.log" <(
     exec 2>&1
     set -ex
-    # Generate h5 input data
-    source "${VIRTUALENV}/bin/activate"
-    "${VIRTUALENV}/bin/python" "${GEN_SCRIPT_PATH}" \
-      --model "${WORKDIR}/${MODELNAME}.circle" \
-      --input "${TEST_INPUT_PATH}/${MODELNAME}/${GRANULARITY}/${DTYPE}" \
-      --output "${TESTCASE_FILE}.input.h5"
-    if [[ $? -ne 0 ]]; then
-      echo "FAILED TO GENERATE INPUT"
-      continue
-    fi
+
     # Run parallel record-minmax
     "${RECORD_MINMAX_PATH}" \
       --input_model "${TEST_RESULT_FILE}.fake_quantized.circle" \
-      --input_data "${TESTCASE_FILE}.input.h5" \
+      --input_data "${TEST_RESULT_FILE}.input.h5" \
       --output_model "${TEST_RESULT_FILE}.parallel_minmax_recorded.circle" \
       --num_threads 4
     # Dump min/max values (circle-tensordump)
     "${CIRCLE_TENSORDUMP_PATH}" \
       "${TEST_RESULT_FILE}.parallel_minmax_recorded.circle" \
       --tensors_to_hdf5 "${TEST_RESULT_FILE}.parallel_minmax_recorded.circle.h5"
-    # Compare result
-    "${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
-      --input_h5 "${TEST_RESULT_FILE}.parallel_minmax_recorded.circle.h5" \
-      --expect_dir "${SOURCE_PATH}/expected_outputs/${MODELNAME}/${GRANULARITY}/${DTYPE}/record_minmax" \
-      --mode record_minmax
-    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
+# Compare result
+"${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
+  --test_param "${TEST_PARAMS}" \
+  --bin_dir ${BIN_PATH} \
+  --source_dir ${SOURCE_PATH} \
+  --mode parallel_record_minmax
+
+if [[ $? -ne 0 ]]; then
   exit 255
 fi
 
index 5ebd726..708bf29 100755 (executable)
@@ -9,7 +9,7 @@
 # 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"
+COMPARE_SCRIPT_PATH="${SOURCE_PATH}/compare_tensors_all.py"
 CONFIG_PATH="$1"; shift
 BIN_PATH=$(dirname "${CONFIG_PATH}")
 TEST_INPUT_PATH="${SOURCE_PATH}/test_inputs"
@@ -25,6 +25,8 @@ TESTED=()
 PASSED=()
 FAILED=()
 
+TEST_PARAMS="$@"
+
 pushd "${WORKDIR}"
 while [ "$1" != "" ]; do  
   MODELNAME=$1; shift
@@ -54,32 +56,18 @@ while [ "$1" != "" ]; do
     "${CIRCLE_TENSORDUMP_PATH}" \
       "${TEST_RESULT_FILE}.quantized.circle" \
       --tensors_to_hdf5 "${TEST_RESULT_FILE}.quantized.circle.h5"
-
-    # Compare result
-    "${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
-      --input_h5 "${TEST_RESULT_FILE}.quantized.circle.h5" \
-      --expect_dir "${SOURCE_PATH}/expected_outputs/${MODELNAME}/${GRANULARITY}/${DTYPE}/quantization" \
-      --mode 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
+# Compare result
+"${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
+  --test_param "${TEST_PARAMS}" \
+  --bin_dir ${BIN_PATH} \
+  --source_dir ${SOURCE_PATH} \
+  --mode quantization
+
+if [[ $? -ne 0 ]]; then
   exit 255
 fi
 
index 1364dfb..e56f0fd 100755 (executable)
@@ -9,11 +9,11 @@
 # 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"
+COMPARE_SCRIPT_PATH="${SOURCE_PATH}/compare_tensors_all.py"
 CONFIG_PATH="$1"; shift
 BIN_PATH=$(dirname "${CONFIG_PATH}")
 TEST_INPUT_PATH="${SOURCE_PATH}/test_inputs"
-GEN_SCRIPT_PATH="${BIN_PATH}/gen_h5_explicit_inputs.py"
+GEN_SCRIPT_PATH="${BIN_PATH}/gen_h5_explicit_inputs_all.py"
 WORKDIR="$1"; shift
 
 source "${CONFIG_PATH}"
@@ -26,6 +26,23 @@ TESTED=()
 PASSED=()
 FAILED=()
 
+TEST_PARAMS="$@"
+
+# Generate h5 input data
+source "${VIRTUALENV}/bin/activate"
+"${VIRTUALENV}/bin/python" "${GEN_SCRIPT_PATH}" \
+  --output_dir ${BIN_PATH} \
+  --artifact_dir ${WORKDIR} \
+  --input_dir ${TEST_INPUT_PATH} \
+  --test_param "$TEST_PARAMS" \
+  --config \
+  --mode 'mixed_quantization'
+
+if [[ $? -ne 0 ]]; then
+  echo "FAILED TO GENERATE INPUT"
+  exit 255
+fi
+
 pushd "${WORKDIR}"
 while [ "$1" != "" ]; do  
   MODELNAME=$1; shift
@@ -45,24 +62,12 @@ while [ "$1" != "" ]; do
     exec 2>&1
     set -ex
 
-    # Generate h5 input data
-    source "${VIRTUALENV}/bin/activate"
-    "${VIRTUALENV}/bin/python" "${GEN_SCRIPT_PATH}" \
-      --model "${WORKDIR}/${MODELNAME}.circle" \
-      --input "${TEST_INPUT_PATH}/${MODELNAME}_config/${GRANULARITY}/${DTYPE}" \
-      --output "${TESTCASE_FILE}.mixed.input.h5"
-
-    if [[ $? -ne 0 ]]; then
-      echo "FAILED TO GENERATE INPUT"
-      continue
-    fi
-
     # Run record-minmax
     # NOTE There is no '_with_config' test for record-minmax, because it does not
     # use quantization config file.
     "${RECORD_MINMAX_PATH}" \
       --input_model "${TEST_RESULT_FILE}.fake_quantized.mixed.circle" \
-      --input_data "${TESTCASE_FILE}.mixed.input.h5" \
+      --input_data "${TEST_RESULT_FILE}.mixed.input.h5" \
       --output_model "${TEST_RESULT_FILE}.minmax_recorded.mixed.circle" 
 
     # Run circle-quantizer with --quantize_with_minmax
@@ -76,32 +81,18 @@ while [ "$1" != "" ]; do
     "${CIRCLE_TENSORDUMP_PATH}" \
       "${TEST_RESULT_FILE}.quantized.mixed.circle" \
       --tensors_to_hdf5 "${TEST_RESULT_FILE}.quantized.mixed.circle.h5"
-
-    # Compare result
-    "${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
-      --input_h5 "${TEST_RESULT_FILE}.quantized.mixed.circle.h5" \
-      --expect_dir "${SOURCE_PATH}/expected_outputs/${MODELNAME}_config/${GRANULARITY}/${DTYPE}/quantization" \
-      --mode 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
+# Compare result
+"${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
+  --test_param "${TEST_PARAMS}" \
+  --bin_dir ${BIN_PATH} \
+  --source_dir ${SOURCE_PATH} \
+  --mode mixed_quantization
+
+if [[ $? -ne 0 ]]; then
   exit 255
 fi
 
index fa8f506..f4609b3 100755 (executable)
@@ -9,11 +9,11 @@
 # 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"
+COMPARE_SCRIPT_PATH="${SOURCE_PATH}/compare_tensors_all.py"
 CONFIG_PATH="$1"; shift
 BIN_PATH=$(dirname "${CONFIG_PATH}")
 TEST_INPUT_PATH="${SOURCE_PATH}/test_inputs"
-GEN_SCRIPT_PATH="${BIN_PATH}/gen_h5_explicit_inputs.py"
+GEN_SCRIPT_PATH="${BIN_PATH}/gen_h5_explicit_inputs_all.py"
 WORKDIR="$1"; shift
 
 source "${CONFIG_PATH}"
@@ -26,6 +26,21 @@ TESTED=()
 PASSED=()
 FAILED=()
 
+TEST_PARAMS="$@"
+
+# Generate h5 all the input data
+source "${VIRTUALENV}/bin/activate"
+"${VIRTUALENV}/bin/python" "${GEN_SCRIPT_PATH}" \
+  --output_dir ${BIN_PATH} \
+  --artifact_dir ${WORKDIR} \
+  --input_dir ${TEST_INPUT_PATH} \
+  --test_param "$TEST_PARAMS"
+
+if [[ $? -ne 0 ]]; then
+  echo "FAILED TO GENERATE INPUT"
+  exit 255
+fi
+
 pushd "${WORKDIR}"
 while [ "$1" != "" ]; do  
   MODELNAME=$1; shift
@@ -45,54 +60,28 @@ while [ "$1" != "" ]; do
     exec 2>&1
     set -ex
 
-    # Generate h5 input data
-    source "${VIRTUALENV}/bin/activate"
-    "${VIRTUALENV}/bin/python" "${GEN_SCRIPT_PATH}" \
-      --model "${WORKDIR}/${MODELNAME}.circle" \
-      --input "${TEST_INPUT_PATH}/${MODELNAME}/${GRANULARITY}/${DTYPE}" \
-      --output "${TESTCASE_FILE}.input.h5"
-
-    if [[ $? -ne 0 ]]; then
-      echo "FAILED TO GENERATE INPUT"
-      continue
-    fi
-
     # Run record-minmax
     "${RECORD_MINMAX_PATH}" \
       --input_model "${TEST_RESULT_FILE}.fake_quantized.circle" \
-      --input_data "${TESTCASE_FILE}.input.h5" \
+      --input_data "${TEST_RESULT_FILE}.input.h5" \
       --output_model "${TEST_RESULT_FILE}.minmax_recorded.circle" 
 
     # Dump min/max values (circle-tensordump)
     "${CIRCLE_TENSORDUMP_PATH}" \
       "${TEST_RESULT_FILE}.minmax_recorded.circle" \
       --tensors_to_hdf5 "${TEST_RESULT_FILE}.minmax_recorded.circle.h5"
-
-    # Compare result
-    "${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
-      --input_h5 "${TEST_RESULT_FILE}.minmax_recorded.circle.h5" \
-      --expect_dir "${SOURCE_PATH}/expected_outputs/${MODELNAME}/${GRANULARITY}/${DTYPE}/record_minmax" \
-      --mode record_minmax
-
-    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
+# Compare result
+"${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
+  --test_param "${TEST_PARAMS}" \
+  --bin_dir ${BIN_PATH} \
+  --source_dir ${SOURCE_PATH} \
+  --mode record_minmax
+
+if [[ $? -ne 0 ]]; then
   exit 255
 fi
 
index 18c85fe..2d5aa45 100755 (executable)
@@ -9,7 +9,7 @@
 # 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"
+COMPARE_SCRIPT_PATH="${SOURCE_PATH}/compare_tensors_all.py"
 CONFIG_PATH="$1"; shift
 BIN_PATH=$(dirname "${CONFIG_PATH}")
 TEST_INPUT_PATH="${SOURCE_PATH}/test_inputs"
@@ -25,6 +25,8 @@ TESTED=()
 PASSED=()
 FAILED=()
 
+TEST_PARAMS="$@"
+
 pushd "${WORKDIR}"
 while [ "$1" != "" ]; do
   MODELNAME=$1; shift
@@ -54,32 +56,18 @@ while [ "$1" != "" ]; do
     "${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
+# Compare result
+"${VIRTUALENV}/bin/python" "${COMPARE_SCRIPT_PATH}" \
+  --test_param "${TEST_PARAMS}" \
+  --bin_dir ${BIN_PATH} \
+  --source_dir ${SOURCE_PATH} \
+  --mode weights_only_quantization
+
+if [[ $? -ne 0 ]]; then
   exit 255
 fi
 
index 68c1d6c..18ad031 100644 (file)
@@ -25,13 +25,13 @@ namespace pp
 
 template <typename Arg> static inline void _fmt(std::ostream &os, const Arg &arg) { os << arg; }
 template <typename Arg, typename... Args>
-static inline void _fmt(std::ostream &os, const Arg &arg, const Args &... args)
+static inline void _fmt(std::ostream &os, const Arg &arg, const Args &...args)
 {
   _fmt(os, arg);
   _fmt(os, args...);
 }
 
-template <typename... Args> static inline std::string fmt(const Args &... args)
+template <typename... Args> static inline std::string fmt(const Args &...args)
 {
   std::stringstream ss;
   _fmt(ss, args...);
index 2655aff..9bb8124 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "pp/Format.h"
 
+#include <cstdint>
+
 namespace pp
 {
 
@@ -38,10 +40,7 @@ public:
   std::string build(const std::string &content);
 
 public:
-  template <typename... Args> std::string build(const Args &... args)
-  {
-    return build(fmt(args...));
-  }
+  template <typename... Args> std::string build(const Args &...args) { return build(fmt(args...)); }
 
 private:
   uint32_t _level;
index f9abd89..1f2c49c 100644 (file)
@@ -70,7 +70,7 @@ public:
     }
   }
 
-  template <typename... Args> void append(const Args &... args) { append(fmt(args...)); }
+  template <typename... Args> void append(const Args &...args) { append(fmt(args...)); }
 
 public:
   void append(const LinearDocument &doc);
diff --git a/compiler/q-implant-qparam-test/CMakeLists.txt b/compiler/q-implant-qparam-test/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e007bbd
--- /dev/null
@@ -0,0 +1,23 @@
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+unset(Q_IMPLANT_TESTS)
+
+macro(addeval NAME)
+  list(APPEND Q_IMPLANT_TESTS ${NAME})
+endmacro(addeval)
+
+include("test.lst")
+
+get_target_property(ARTIFACTS_BIN_PATH testDataGenerator BINARY_DIR)
+
+add_test(NAME q-implant-qparam-test
+  COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/q_implant_qparam_test.sh"
+          "${CMAKE_CURRENT_BINARY_DIR}"
+          "${ARTIFACTS_BIN_PATH}"
+          "${NNCC_OVERLAY_DIR}/venv_2_12_1"
+          "$<TARGET_FILE:q-implant>"
+          "$<TARGET_FILE:circle-tensordump>"
+          ${Q_IMPLANT_TESTS}
+)
diff --git a/compiler/q-implant-qparam-test/README.md b/compiler/q-implant-qparam-test/README.md
new file mode 100644 (file)
index 0000000..05f09d1
--- /dev/null
@@ -0,0 +1,61 @@
+# q-implant-qparam-test
+
+`q-implant-qparam-test` validates that q-implant supports common used operators.
+
+The test proceeds as follows
+
+Step 1: Generate qparam file(.json) and numpy array(.npy) through the operator python file.
+```
+operator file -> qparam file, numpy array
+```
+
+Step 2: Generate output.circle to use q-implant
+```
+"circle file" + "qparam.json" -> q-implant -> "quant circle file"
+```
+
+Step 3: Dump output.circle to output.h5.
+```
+"output.circle" -> circle-tensordump -> "output.h5"
+```
+
+Step 4: And compare tensor values of h5 file with numpy arrays due to validate q-implant.
+
+how to make qparam file
+
+step 1: Choose the recipe in 'res/TensorFlowLiteRecipes' and get name of recipe.
+
+step 2: Create folder in qparam that name is recipe name
+
+step 3: Create `__init__.py` follow this sample.
+
+``` python
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class recipe_name_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate operand_name
+        json_content['operand_name'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (3, 3, 3, 3)) # value_shape ( such as weight, bias )
+
+         ...
+
+        return json_content
+
+
+_name_ = 'recipe_name_000_Q8'
+
+_test_case_ = recipe_name_000_Q8()
+
+```
diff --git a/compiler/q-implant-qparam-test/q_implant_qparam_test.py b/compiler/q-implant-qparam-test/q_implant_qparam_test.py
new file mode 100644 (file)
index 0000000..fad271b
--- /dev/null
@@ -0,0 +1,97 @@
+#!/usr/bin/env python3
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 argparse
+import subprocess
+import os
+import importlib
+
+from test_utils import TestRunner
+from q_implant_validator import validate
+
+parser = argparse.ArgumentParser()
+parser.add_argument('--input_dir', type=str, required=True)
+parser.add_argument('--output_dir', type=str, required=True)
+parser.add_argument('--driver', type=str, required=True)
+parser.add_argument('--dump', type=str, required=True)
+parser.add_argument('--model', type=str, required=True)
+args = parser.parse_args()
+
+input_dir = args.input_dir
+output_dir = args.output_dir
+driver = args.driver
+dump = args.dump
+model = args.model
+
+module = importlib.import_module('qparam.' + model)
+
+input_circle = input_dir + '.circle'
+output_circle = output_dir + f'/{module._name_}/output.circle'
+qparam_dir = output_dir + f'/{module._name_}/qparam.json'
+h5_path = output_dir + f'/{module._name_}/output.h5'
+
+if not os.path.exists(input_circle):
+    print('fail to load input circle')
+    quit(255)
+
+# if the previous test dummy file exist, remove it.
+if os.path.exists(output_circle):
+    os.remove(output_circle)
+
+if os.path.exists(h5_path):
+    os.remove(h5_path)
+
+# generate qparam.json and numpys
+test_runner = TestRunner(output_dir)
+
+test_runner.register(module._test_case_)
+
+test_runner.run()
+
+if not os.path.exists(qparam_dir):
+    print('qparam generate fail')
+    quit(255)
+
+# run q-implant
+process = subprocess.run([driver, input_circle, qparam_dir, output_circle], check=True)
+
+try:
+    process.check_returncode()
+except:
+    print('q-implant run failed')
+    quit(255)
+
+if not os.path.exists(output_circle):
+    print('output circle generate fail')
+    quit(255)
+
+# dump circle to h5
+process = subprocess.run([dump, '--tensors_to_hdf5', h5_path, output_circle], check=True)
+
+try:
+    process.check_returncode()
+except:
+    print('circle-tensordump run failed')
+    quit(255)
+
+if not os.path.exists(h5_path):
+    print('h5 dump failed')
+    quit(255)
+
+if not validate(h5_path, output_dir + f'/{module._name_}', qparam_dir):
+    quit(255)
+
+quit(0)
diff --git a/compiler/q-implant-qparam-test/q_implant_qparam_test.sh b/compiler/q-implant-qparam-test/q_implant_qparam_test.sh
new file mode 100755 (executable)
index 0000000..fff4e60
--- /dev/null
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+VERIFY_SOURCE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+VERIFY_SCRIPT_PATH="${VERIFY_SOURCE_PATH}/q_implant_qparam_test.py"
+BINDIR="$1"; shift
+WORKDIR="$1"; shift
+VIRTUALENV="$1"; shift
+INTERPRETER_DRIVER_PATH="$1"; shift
+H5_DUMP_PATH="$1"; shift
+
+TESTED=()
+PASSED=()
+FAILED=()
+
+for TESTCASE in "$@"; do
+  TESTED+=("${TESTCASE}")
+
+  TESTCASE_FILE="${WORKDIR}/${TESTCASE}"
+  TEST_RESULT_FILE="${BINDIR}/${TESTCASE}"
+
+  PASSED_TAG="${TEST_RESULT_FILE}.passed"
+  rm -f "${PASSED_TAG}"
+
+  cat > "${TEST_RESULT_FILE}.log" <(
+    exec 2>&1
+    set -ex
+
+    source "${VIRTUALENV}/bin/activate"
+    "${VIRTUALENV}/bin/python" "${VERIFY_SCRIPT_PATH}" \
+    --model "${TESTCASE}" \
+    --driver "${INTERPRETER_DRIVER_PATH}" \
+    --dump "${H5_DUMP_PATH}" \
+    --output_dir "${BINDIR}" \
+    --input_dir "${TESTCASE_FILE}"
+
+    if [[ $? -eq 0 ]]; then
+      touch "${PASSED_TAG}"
+    fi
+  )
+
+  if [[ -f "${PASSED_TAG}" ]]; then
+    PASSED+=("${TESTCASE}")
+  else
+    FAILED+=("${TESTCASE}")
+  fi
+done
+
+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/q-implant-qparam-test/q_implant_validator.py b/compiler/q-implant-qparam-test/q_implant_validator.py
new file mode 100644 (file)
index 0000000..1f3d8b6
--- /dev/null
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+
+# Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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 h5py as h5
+import numpy as np
+import json
+
+
+def validate(h5_path, qparam_dir, qparam_json):
+    valid = True
+    with open(qparam_json, "r") as qparams:
+        json_load = json.load(qparams)
+    with h5.File(h5_path, "r") as model:
+        for node_name in model.keys():
+            # not quantized node exists (reshape, pad...)
+            if not json_load.get(node_name):
+                continue
+
+            for tensor_name in json_load[node_name]:
+                np_path = f"{qparam_dir}/{json_load[node_name][tensor_name]}"
+                if tensor_name == "value":
+                    expected_weights = np.load(np_path)
+                    h5_weights = model[node_name]["weights"][:]
+                    if np.allclose(
+                            h5_weights, expected_weights, rtol=1.e-5,
+                            atol=1.e-5) == False:
+                        print("Implanted weights of " + node_name + "." + tensor_name +
+                              " (" + str(h5_weights) +
+                              ") do not match with expected value (" +
+                              str(expected_weights) + ").")
+                        valid = False
+
+                if tensor_name == "scale":
+                    expected_scale = np.load(np_path)
+                    h5_scale = model[node_name]["scale"][:]
+                    if np.allclose(
+                            h5_scale, expected_scale, rtol=1.e-5, atol=1.e-5) == False:
+                        print("Implanted scale of " + node_name + "." + tensor_name +
+                              " (" + str(h5_scale) +
+                              ") do not match with expected value (" +
+                              str(expected_scale) + ").")
+                        valid = False
+
+                if tensor_name == "zerop":
+                    expected_zerop = np.load(np_path)
+                    input_zerop = model[node_name]["zero_point"][:]
+                    if np.allclose(input_zerop, expected_zerop, rtol=0, atol=1) == False:
+                        print("Implanted zero point of " + tensor_name + " (" +
+                              str(input_zerop) + ") do not match with expected value (" +
+                              str(expected_zerop) + ").")
+                        valid = False
+
+    return valid
diff --git a/compiler/q-implant-qparam-test/qparam/Add_000/__init__.py b/compiler/q-implant-qparam-test/qparam/Add_000/__init__.py
new file mode 100644 (file)
index 0000000..e53136d
--- /dev/null
@@ -0,0 +1,38 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Add_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm1
+        json_content['ifm1'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ifm2
+        json_content['ifm2'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Add_000_Q8'
+
+_test_case_ = Add_000_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Add_001/__init__.py b/compiler/q-implant-qparam-test/qparam/Add_001/__init__.py
new file mode 100644 (file)
index 0000000..6636e2b
--- /dev/null
@@ -0,0 +1,39 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Add_001_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm1
+        json_content['ifm1'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ifm2
+        json_content['ifm2'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1, 0, 1))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Add_001_Q8'
+
+_test_case_ = Add_001_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Add_002/__init__.py b/compiler/q-implant-qparam-test/qparam/Add_002/__init__.py
new file mode 100644 (file)
index 0000000..9a51506
--- /dev/null
@@ -0,0 +1,39 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Add_002_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm1
+        json_content['ifm1'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ifm2
+        json_content['ifm2'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1, 2, 2, 3))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Add_002_Q8'
+
+_test_case_ = Add_002_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/AveragePool2D_000/__init__.py b/compiler/q-implant-qparam-test/qparam/AveragePool2D_000/__init__.py
new file mode 100644 (file)
index 0000000..6b57bb2
--- /dev/null
@@ -0,0 +1,31 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class AveragePool2D_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'AveragePool2D_000_Q8'
+
+_test_case_ = AveragePool2D_000_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Concatenation_000/__init__.py b/compiler/q-implant-qparam-test/qparam/Concatenation_000/__init__.py
new file mode 100644 (file)
index 0000000..a33f9f8
--- /dev/null
@@ -0,0 +1,38 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Concatenation_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm1
+        json_content['ifm1'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ifm2
+        json_content['ifm2'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Concatenation_000_Q8'
+
+_test_case_ = Concatenation_000_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Conv2D_000/__init__.py b/compiler/q-implant-qparam-test/qparam/Conv2D_000/__init__.py
new file mode 100644 (file)
index 0000000..08b8ba8
--- /dev/null
@@ -0,0 +1,47 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Conv2D_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ker
+        json_content['ker'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1, 1, 1, 2))  # value_shape (OHWI)
+
+        # Generate bias
+        json_content['bias'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Conv2D_000_Q8'
+
+_test_case_ = Conv2D_000_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Conv2D_001/__init__.py b/compiler/q-implant-qparam-test/qparam/Conv2D_001/__init__.py
new file mode 100644 (file)
index 0000000..7463e18
--- /dev/null
@@ -0,0 +1,47 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Conv2D_001_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ker
+        json_content['ker'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1, 1, 1, 2))  # value_shape (OHWI)
+
+        # Generate bias
+        json_content['bias'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Conv2D_001_Q8'
+
+_test_case_ = Conv2D_001_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Conv2D_002/__init__.py b/compiler/q-implant-qparam-test/qparam/Conv2D_002/__init__.py
new file mode 100644 (file)
index 0000000..235bd5e
--- /dev/null
@@ -0,0 +1,47 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Conv2D_002_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ker
+        json_content['ker'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1, 1, 1, 1))  # value_shape (OHWI)
+
+        # Generate bias
+        json_content['bias'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Conv2D_002_Q8'
+
+_test_case_ = Conv2D_002_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Conv2D_003/__init__.py b/compiler/q-implant-qparam-test/qparam/Conv2D_003/__init__.py
new file mode 100644 (file)
index 0000000..9595424
--- /dev/null
@@ -0,0 +1,47 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Conv2D_003_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ker
+        json_content['ker'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1, 3, 3, 1))  # value_shape (OHWI)
+
+        # Generate bias
+        json_content['bias'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Conv2D_003_Q8'
+
+_test_case_ = Conv2D_003_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Conv2D_004/__init__.py b/compiler/q-implant-qparam-test/qparam/Conv2D_004/__init__.py
new file mode 100644 (file)
index 0000000..c90c51b
--- /dev/null
@@ -0,0 +1,47 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Conv2D_004_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ker
+        json_content['ker'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (2, 2, 2, 2))  # value_shape (OHWI)
+
+        # Generate bias
+        json_content['bias'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (2))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Conv2D_004_Q8'
+
+_test_case_ = Conv2D_004_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Conv2D_005/__init__.py b/compiler/q-implant-qparam-test/qparam/Conv2D_005/__init__.py
new file mode 100644 (file)
index 0000000..8e18c5e
--- /dev/null
@@ -0,0 +1,39 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Conv2D_005_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ker
+        json_content['ker'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1, 1, 1, 2))  # value_shape (OHWI)
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Conv2D_005_Q8'
+
+_test_case_ = Conv2D_005_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_000/__init__.py b/compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_000/__init__.py
new file mode 100644 (file)
index 0000000..4aaf51e
--- /dev/null
@@ -0,0 +1,46 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class DepthwiseConv2D_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ker
+        json_content['ker'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate bias
+        json_content['bias'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (8))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'DepthwiseConv2D_000_Q8'
+
+_test_case_ = DepthwiseConv2D_000_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_001/__init__.py b/compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_001/__init__.py
new file mode 100644 (file)
index 0000000..02d856e
--- /dev/null
@@ -0,0 +1,46 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class DepthwiseConv2D_001_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ker
+        json_content['ker'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate bias
+        json_content['bias'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (8))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'DepthwiseConv2D_001_Q8'
+
+_test_case_ = DepthwiseConv2D_001_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_002/__init__.py b/compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_002/__init__.py
new file mode 100644 (file)
index 0000000..db7c145
--- /dev/null
@@ -0,0 +1,46 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class DepthwiseConv2D_002_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ker
+        json_content['ker'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate bias
+        json_content['bias'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (4))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'DepthwiseConv2D_002_Q8'
+
+_test_case_ = DepthwiseConv2D_002_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_003/__init__.py b/compiler/q-implant-qparam-test/qparam/DepthwiseConv2D_003/__init__.py
new file mode 100644 (file)
index 0000000..77e00ce
--- /dev/null
@@ -0,0 +1,46 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class DepthwiseConv2D_003_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ker
+        json_content['ker'] = gen_random_tensor(
+            "uint8",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate bias
+        json_content['bias'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (25))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'DepthwiseConv2D_003_Q8'
+
+_test_case_ = DepthwiseConv2D_003_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/MaxPool2D_000/__init__.py b/compiler/q-implant-qparam-test/qparam/MaxPool2D_000/__init__.py
new file mode 100644 (file)
index 0000000..615816c
--- /dev/null
@@ -0,0 +1,31 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class MaxPool2D_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'MaxPool2D_000_Q8'
+
+_test_case_ = MaxPool2D_000_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Mean_000/__init__.py b/compiler/q-implant-qparam-test/qparam/Mean_000/__init__.py
new file mode 100644 (file)
index 0000000..08d9faa
--- /dev/null
@@ -0,0 +1,31 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Mean_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Mean_000_Q8'
+
+_test_case_ = Mean_000_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Mul_000/__init__.py b/compiler/q-implant-qparam-test/qparam/Mul_000/__init__.py
new file mode 100644 (file)
index 0000000..454b238
--- /dev/null
@@ -0,0 +1,38 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Mul_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm1
+        json_content['ifm1'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ifm2
+        json_content['ifm2'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Mul_000_Q8'
+
+_test_case_ = Mul_000_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Mul_001/__init__.py b/compiler/q-implant-qparam-test/qparam/Mul_001/__init__.py
new file mode 100644 (file)
index 0000000..263cbf4
--- /dev/null
@@ -0,0 +1,39 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Mul_001_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm1
+        json_content['ifm1'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ifm2
+        json_content['ifm2'] = gen_random_tensor(
+            "int32",  #dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0,  # quantized_dimension
+            (1, 2, 2, 3))  # value_shape
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Mul_001_Q8'
+
+_test_case_ = Mul_001_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Pad_000/__init__.py b/compiler/q-implant-qparam-test/qparam/Pad_000/__init__.py
new file mode 100644 (file)
index 0000000..b1e239f
--- /dev/null
@@ -0,0 +1,31 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Pad_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Pad_000_Q8'
+
+_test_case_ = Pad_000_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Reshape_000/__init__.py b/compiler/q-implant-qparam-test/qparam/Reshape_000/__init__.py
new file mode 100644 (file)
index 0000000..13d4d55
--- /dev/null
@@ -0,0 +1,31 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Reshape_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Reshape_000_Q8'
+
+_test_case_ = Reshape_000_Q8()
diff --git a/compiler/q-implant-qparam-test/qparam/Softmax_000/__init__.py b/compiler/q-implant-qparam-test/qparam/Softmax_000/__init__.py
new file mode 100644 (file)
index 0000000..fffe4b9
--- /dev/null
@@ -0,0 +1,31 @@
+from test_utils import TestCase
+from test_utils import gen_random_tensor
+
+
+class Softmax_000_Q8(TestCase):
+    def __init__(self):
+        self.name = _name_
+
+    def generate(self) -> dict:
+        json_content = dict()
+
+        # Generate ifm
+        json_content['ifm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        # Generate ofm
+        json_content['ofm'] = gen_random_tensor(
+            "uint8",  # dtype_str
+            (1),  # scale_shape
+            (1),  # zerop_shape
+            0)  # quantized_dimension
+
+        return json_content
+
+
+_name_ = 'Softmax_000_Q8'
+
+_test_case_ = Softmax_000_Q8()
diff --git a/compiler/q-implant-qparam-test/requires.cmake b/compiler/q-implant-qparam-test/requires.cmake
new file mode 100644 (file)
index 0000000..2e4349c
--- /dev/null
@@ -0,0 +1,2 @@
+require("common-artifacts")
+require("q-implant")
diff --git a/compiler/q-implant-qparam-test/test.lst b/compiler/q-implant-qparam-test/test.lst
new file mode 100644 (file)
index 0000000..1bd06da
--- /dev/null
@@ -0,0 +1,22 @@
+addeval(Conv2D_000)
+addeval(Conv2D_001)
+addeval(Conv2D_002)
+addeval(Conv2D_003)
+addeval(Conv2D_004)
+addeval(Conv2D_005)
+addeval(Reshape_000)
+addeval(Softmax_000)
+addeval(AveragePool2D_000)
+addeval(DepthwiseConv2D_000)
+addeval(DepthwiseConv2D_001)
+addeval(DepthwiseConv2D_002)
+addeval(DepthwiseConv2D_003)
+addeval(Add_000)
+addeval(Add_001)
+addeval(Add_002)
+addeval(MaxPool2D_000)
+addeval(Mul_000)
+addeval(Mul_001)
+addeval(Concatenation_000)
+addeval(Mean_000)
+addeval(Pad_000)
diff --git a/compiler/q-implant-qparam-test/test_utils.py b/compiler/q-implant-qparam-test/test_utils.py
new file mode 100644 (file)
index 0000000..5fabd22
--- /dev/null
@@ -0,0 +1,92 @@
+import json
+import typing
+import numpy as np
+import os
+
+
+def _dump_npy_included_json(output_dir: str, json_content: dict):
+    """
+    Dump json and npy files to output_dir
+    """
+    # Create output_dir if not exists
+    if not os.path.exists(output_dir):
+        os.makedirs(output_dir)
+
+    # file name for npy data (ex: 0.npy, 1.npy, ...)
+    _index = 0
+    _index_to_value = dict()
+
+    # Replace npy to the path to the npy file
+    for tensor_name, qparam in json_content.items():
+        assert type(tensor_name) == str
+        assert type(qparam) == dict
+        for field, value in qparam.items():
+            if isinstance(value, np.ndarray):
+                npy_name = str(_index) + '.npy'
+
+                # Save npy file
+                np.save(os.path.join(output_dir, npy_name), value)
+
+                # Replace to the path to the npy file
+                json_content[tensor_name][field] = npy_name
+
+                # Save the mapping from index to tensor name
+                _index_to_value[_index] = tensor_name + "_" + field
+                _index += 1
+
+    # Dump json
+    with open(os.path.join(output_dir, 'qparam.json'), 'w') as f:
+        json.dump(json_content, f, indent=2)
+
+
+def _str_to_npy_dtype(dtype_str: str):
+    if dtype_str == "uint8":
+        return np.uint8
+    if dtype_str == "int16":
+        return np.int16
+    if dtype_str == "int32":
+        return np.int32
+    if dtype_str == "int64":
+        return np.int64
+    raise SystemExit("Unsupported npy dtype", dtype_str)
+
+
+def gen_random_tensor(dtype_str: str,
+                      scale_shape: typing.Tuple[int],
+                      zerop_shape: typing.Tuple[int],
+                      quantized_dimension: int,
+                      value_shape: typing.Optional[typing.Tuple[int]] = None) -> dict:
+    content = dict()
+    content['dtype'] = dtype_str
+    content['scale'] = np.random.rand(scale_shape).astype(np.float32)
+    # Why 256? To ensure the smallest dtype (uint8) range [0, 256)
+    content['zerop'] = np.random.randint(256, size=zerop_shape, dtype=np.int64)
+    content['quantized_dimension'] = quantized_dimension
+
+    if value_shape != None:
+        dtype = _str_to_npy_dtype(dtype_str)
+        content['value'] = np.random.randint(256, size=value_shape, dtype=dtype)
+    return content
+
+
+class TestCase:
+    def __init__(self):
+        pass
+
+    def generate(self) -> dict:
+        pass
+
+
+class TestRunner:
+    def __init__(self, output_dir: str):
+        self.test_cases = list()
+        self.output_dir = output_dir
+
+    def register(self, test_case: TestCase):
+        self.test_cases.append(test_case)
+
+    def run(self):
+        for test_case in self.test_cases:
+            print("Generate test case: " + test_case.name)
+            _dump_npy_included_json(self.output_dir + '/' + test_case.name,
+                                    test_case.generate())
diff --git a/compiler/q-implant/CMakeLists.txt b/compiler/q-implant/CMakeLists.txt
new file mode 100644 (file)
index 0000000..60c238e
--- /dev/null
@@ -0,0 +1,32 @@
+nnas_find_package(Jsoncpp)
+if(NOT Jsoncpp_FOUND)
+  message(STATUS "q-implant: Jsoncpp NOT FOUND")
+  return()
+endif(NOT Jsoncpp_FOUND)
+
+nnas_find_package(LibnpySource QUIET)
+if(NOT LibnpySource_FOUND)
+  message(STATUS "q-implant: LibnpySource NOT FOUND")
+  return()
+endif(NOT LibnpySource_FOUND)
+
+set(DRIVER "driver/Driver.cpp")
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+
+add_executable(q-implant ${DRIVER} ${SOURCES})
+target_include_directories(q-implant PRIVATE ${Jsoncpp_INCLUDE_DIRS})
+target_include_directories(q-implant PRIVATE ${LibnpySource_DIR}/include)
+target_include_directories(q-implant PRIVATE include)
+
+target_link_libraries(q-implant ${Jsoncpp_STATIC_LIB})
+target_link_libraries(q-implant safemain)
+target_link_libraries(q-implant loco)
+target_link_libraries(q-implant luci_import)
+target_link_libraries(q-implant luci_service)
+target_link_libraries(q-implant luci_pass)
+target_link_libraries(q-implant luci_export)
+target_link_libraries(q-implant luci_env)
+target_link_libraries(q-implant arser)
+target_link_libraries(q-implant vconone)
+
+install(TARGETS q-implant DESTINATION bin)
diff --git a/compiler/q-implant/README.md b/compiler/q-implant/README.md
new file mode 100644 (file)
index 0000000..40f24c2
--- /dev/null
@@ -0,0 +1,105 @@
+# q-implant
+
+_q-implant_ implants quantization parameters and weights 
+(given as .json and .npy files) to a circle model.
+
+## Format of input files (`.json` and `.npy`)
+
+The main input file is a `.json` file, which is a dictionary.
+The dictionary's key is a tensor name, and its value is quantization parameters
+and values(if exists).
+
+The `.npy` file is a NumPy file that can be generated with `numpy.save` function. 
+
+The content of the json file is as below.
+
+```
+{
+  <tensor_name>: {
+    "dtype": <dtype>,
+    "scale": <path/to/scale_npy>,
+    "zerop": <path/to/zerop_npy>,
+    "quantized_dimension": <dim>,
+    "value": <path/to/value_npy>
+  },
+  ...
+}
+```
+`<tensor_name>`: String (target tensor name)
+
+`<dtype>`: String (data type of the target tensor. ex: "uint8" or "int16")
+
+`<path/to/scale_npy>`: String (path to the .npy file that contains scale. 
+The npy file has to be 1d array of fp32.)
+
+`<path/to/zerop_npy>`: String (path to the .npy file that contains zerop. 
+The npy file has to be 1d array of int64.)
+
+`<dim>`: Integer (quantized dimension)
+
+`<path/to/value_npy>`: String (path to the .npy file that contains zerop. 
+The npy file should have the same shape/dtype with the target tensor.)
+
+NOTE "value" is an optional attribute. It is only necessary for weights.
+
+NOTE `.npy` files have to be placed in the same directory with `qparam.json`.
+
+## Example
+
+```sh
+q-implant input.circle qparam.json output.circle
+```
+
+Let's assume a circle model with a single Conv layer. 
+It has four tensors: `ifm`, `ker`, `bias`, and `ofm`.
+
+For the model, `qparam.json` and `*.npy` can be defined as follows.
+(`*.npy` internal values are random values for testing)
+
+- qparam.json
+
+```json
+{
+  "ifm": {
+    "dtype": "uint8",
+    "scale": "0.npy",
+    "zerop": "1.npy",
+    "quantized_dimension": 0
+  },
+  "ker": {
+    "dtype": "uint8",
+    "scale": "2.npy",
+    "zerop": "3.npy",
+    "quantized_dimension": 0,
+    "value": "4.npy"
+  },
+  "bias": {
+    "dtype": "int32",
+    "scale": "5.npy",
+    "zerop": "6.npy",
+    "quantized_dimension": 0,
+    "value": "7.npy"
+  },
+  "ofm": {
+    "dtype": "uint8",
+    "scale": "8.npy",
+    "zerop": "9.npy",
+    "quantized_dimension": 0
+  }
+}
+```
+
+- \*.npy
+
+```
+0.npy : [0.27102426]
+1.npy : [216]
+2.npy : [0.44855267]
+3.npy : [103]
+4.npy : [[[[237 157]]]]
+5.npy : [0.03877867]
+6.npy : [97]
+7.npy : [88]
+8.npy : [0.83054835]
+9.npy : [7]
+```
diff --git a/compiler/q-implant/driver/Driver.cpp b/compiler/q-implant/driver/Driver.cpp
new file mode 100644 (file)
index 0000000..3eee192
--- /dev/null
@@ -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 <luci/ImporterEx.h>
+#include <luci/CircleQuantizer.h>
+#include <luci/Service/Validate.h>
+#include <luci/CircleExporter.h>
+#include <luci/CircleFileExpContract.h>
+#include <luci/UserSettings.h>
+
+#include <arser/arser.h>
+
+#include "QImplant.h"
+
+#include <iostream>
+#include <string>
+
+using namespace q_implant;
+
+int entry(int argc, char **argv)
+{
+  arser::Arser arser("q-implant provides circle model quantization");
+
+  arser::Helper::add_verbose(arser);
+
+  arser.add_argument("input").help("Input circle model");
+  arser.add_argument("qparam").help("Quantization parameter file (.json)");
+  arser.add_argument("output").help("Output circle model");
+
+  try
+  {
+    arser.parse(argc, argv);
+  }
+  catch (const std::runtime_error &err)
+  {
+    std::cerr << err.what() << std::endl;
+    std::cout << arser;
+    return EXIT_FAILURE;
+  }
+
+  if (arser.get<bool>("--verbose"))
+  {
+    // The third parameter of setenv means REPLACE.
+    // If REPLACE is zero, it does not overwrite an existing value.
+    setenv("LUCI_LOG", "100", 0);
+  }
+
+  const std::string input_path = arser.get<std::string>("input");
+  const std::string qparam_path = arser.get<std::string>("qparam");
+  const std::string output_path = arser.get<std::string>("output");
+
+  // Load model from the file
+  luci::ImporterEx importerex;
+  auto module = importerex.importVerifyModule(input_path);
+  if (module.get() == nullptr)
+    return EXIT_FAILURE;
+
+  QImplant writer(qparam_path);
+
+  if (module->size() != 1)
+  {
+    std::cerr << "ERROR: Only a single subgraph is supported" << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  for (size_t idx = 0; idx < module->size(); ++idx)
+  {
+    auto graph = module->graph(idx);
+
+    writer.write(graph);
+
+    if (!luci::validate(graph))
+    {
+      std::cerr << "ERROR: Quantized graph is invalid" << std::endl;
+      return EXIT_FAILURE;
+    }
+  }
+
+  // Export to output Circle file
+  luci::CircleExporter exporter;
+
+  luci::CircleFileExpContract contract(module.get(), output_path);
+
+  if (!exporter.invoke(&contract))
+  {
+    std::cerr << "ERROR: Failed to export '" << output_path << "'" << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  return 0;
+}
diff --git a/compiler/q-implant/include/QImplant.h b/compiler/q-implant/include/QImplant.h
new file mode 100644 (file)
index 0000000..75467c6
--- /dev/null
@@ -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 __Q_IMPLANT_H__
+#define __Q_IMPLANT_H__
+
+#include <loco.h>
+
+#include <string>
+
+namespace q_implant
+{
+
+class QImplant final
+{
+public:
+  QImplant(const std::string &path) : _path(path) {}
+
+  void write(loco::Graph *g);
+
+private:
+  void forward_qparam(loco::Graph *g);
+
+private:
+  const std::string &_path;
+};
+
+} // namespace q_implant
+
+#endif // __Q_IMPLANT_H__
diff --git a/compiler/q-implant/requires.cmake b/compiler/q-implant/requires.cmake
new file mode 100644 (file)
index 0000000..1018f2d
--- /dev/null
@@ -0,0 +1,5 @@
+require("loco")
+require("locop")
+require("safemain")
+require("luci")
+require("arser")
diff --git a/compiler/q-implant/src/QImplant.cpp b/compiler/q-implant/src/QImplant.cpp
new file mode 100644 (file)
index 0000000..60a652c
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "QImplant.h"
+
+#include <loco.h>
+#include <luci/IR/CircleNode.h>
+
+#include <npy.hpp>
+#include <json.h>
+#include <fstream>
+#include <unordered_map>
+
+using namespace q_implant;
+
+#define THROW_UNLESS(cond) \
+  if (not(cond))           \
+    throw std::runtime_error{#cond};
+
+namespace
+{
+
+// Return directory path of given file path
+// TODO Find a platform-independent way to do this
+std::string directory_path(const std::string &file_path)
+{
+  const auto pos = file_path.find_last_of("/");
+  if (std::string::npos == pos)
+    return "";
+
+  return file_path.substr(0, pos);
+}
+
+loco::DataType str_to_dtype(const std::string &str)
+{
+  auto lower_case_str = str;
+  std::transform(lower_case_str.begin(), lower_case_str.end(), lower_case_str.begin(),
+                 [](unsigned char c) { return std::tolower(c); });
+
+  if (lower_case_str.compare("int8") == 0)
+    return loco::DataType::S8;
+  if (lower_case_str.compare("uint8") == 0)
+    return loco::DataType::U8;
+  if (lower_case_str.compare("int16") == 0)
+    return loco::DataType::S16;
+  if (lower_case_str.compare("int32") == 0)
+    return loco::DataType::S32;
+  if (lower_case_str.compare("int64") == 0)
+    return loco::DataType::S64;
+
+  throw std::runtime_error("Invalid dtype detected. " + str);
+}
+
+// Throw an exception if tensor has any invalid field.
+void verify_tensor(const Json::Value &tensor)
+{
+  THROW_UNLESS(tensor.isMember("scale"));
+  THROW_UNLESS(tensor["scale"].isString());
+  THROW_UNLESS(tensor.isMember("zerop"));
+  THROW_UNLESS(tensor["zerop"].isString());
+  THROW_UNLESS(tensor.isMember("quantized_dimension"));
+  THROW_UNLESS(tensor["quantized_dimension"].isUInt());
+  THROW_UNLESS(tensor.isMember("dtype"));
+  THROW_UNLESS(tensor["dtype"].isString());
+
+  if (tensor.isMember("value"))
+  {
+    THROW_UNLESS(tensor["value"].isString());
+  }
+}
+
+Json::Value load_json(const std::string &path)
+{
+  Json::Value root;
+  std::ifstream ifs(path);
+
+  // Failed to open cfg file
+  if (not ifs.is_open())
+    throw std::runtime_error("Cannot open config file. " + path);
+
+  Json::CharReaderBuilder builder;
+  JSONCPP_STRING errs;
+
+  // Failed to parse
+  if (not parseFromStream(builder, ifs, &root, &errs))
+    throw std::runtime_error("Cannot parse config file (json format). " + errs);
+
+  return root;
+}
+
+void set_dtype(luci::CircleNode *node, loco::DataType dtype) { node->dtype(dtype); }
+
+void copy_dtype(const luci::CircleNode *src, luci::CircleNode *dest) { dest->dtype(src->dtype()); }
+
+void set_scale(luci::CircleNode *node, const std::string &scale_path)
+{
+  assert(node);               // FIX CALLER UNLESS
+  assert(node->quantparam()); // FIX CALLER UNLESS
+
+  std::vector<unsigned long> shape;
+  bool fortran_order;
+  std::vector<float> scale;
+  npy::LoadArrayFromNumpy(scale_path, shape, fortran_order, scale);
+
+  THROW_UNLESS(shape.size() == 1);
+  THROW_UNLESS(fortran_order == false);
+
+  node->quantparam()->scale = scale;
+}
+
+void set_zerop(luci::CircleNode *node, const std::string &zerop_path)
+{
+  assert(node);               // FIX CALLER UNLESS
+  assert(node->quantparam()); // FIX CALLER UNLESS
+
+  std::vector<unsigned long> shape;
+  bool fortran_order;
+  std::vector<int64_t> zerop;
+  npy::LoadArrayFromNumpy(zerop_path, shape, fortran_order, zerop);
+
+  THROW_UNLESS(shape.size() == 1);
+  THROW_UNLESS(fortran_order == false);
+
+  node->quantparam()->zerop = zerop;
+}
+
+void set_quantized_dimension(luci::CircleNode *node, const uint32_t quantized_dimension)
+{
+  assert(node);               // FIX CALLER UNLESS
+  assert(node->quantparam()); // FIX CALLER UNLESS
+
+  node->quantparam()->quantized_dimension = quantized_dimension;
+}
+
+template <loco::DataType DT> void set_value(luci::CircleConst *node, const std::string &value_path)
+{
+  assert(node);                // FIX CALLER UNLESS
+  assert(node->dtype() == DT); // FIX CALLER UNLESS
+
+  std::vector<unsigned long> shape;
+  bool fortran_order;
+  std::vector<typename loco::DataTypeImpl<DT>::Type> values;
+  npy::LoadArrayFromNumpy(value_path, shape, fortran_order, values);
+
+  THROW_UNLESS(shape.size() == node->rank());
+  THROW_UNLESS(fortran_order == false);
+
+  uint32_t value_size = 1;
+  for (uint32_t i = 0; i < node->rank(); i++)
+  {
+    THROW_UNLESS(node->dim(i).known());
+    THROW_UNLESS(node->dim(i).value() == shape[i]);
+
+    value_size *= node->dim(i).value();
+  }
+
+  node->size<DT>(value_size);
+  for (uint32_t i = 0; i < value_size; i++)
+  {
+    node->at<DT>(i) = values.at(i);
+  }
+}
+
+void set_value(luci::CircleConst *const_node, const std::string &value_path, loco::DataType dtype)
+{
+  assert(const_node); // FIX CALLER UNLESS
+
+  switch (dtype)
+  {
+    case loco::DataType::S8:
+      set_value<loco::DataType::S8>(const_node, value_path);
+      break;
+    case loco::DataType::U8:
+      set_value<loco::DataType::U8>(const_node, value_path);
+      break;
+    case loco::DataType::S16:
+      set_value<loco::DataType::S16>(const_node, value_path);
+      break;
+    case loco::DataType::S32:
+      set_value<loco::DataType::S32>(const_node, value_path);
+      break;
+    case loco::DataType::S64:
+      set_value<loco::DataType::S64>(const_node, value_path);
+      break;
+    default:
+      throw std::runtime_error("Invalid value dtype detected. ");
+  }
+}
+
+} // namespace
+
+void QImplant::write(loco::Graph *g)
+{
+  const auto root = load_json(_path);
+  const auto dir_path = directory_path(_path);
+
+  std::unordered_map<std::string, luci::CircleNode *> name_to_node;
+  for (auto node : loco::all_nodes(g))
+  {
+    auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+    if (circle_node->opcode() == luci::CircleOpcode::CIRCLEOUTPUT)
+    {
+      continue;
+    }
+
+    name_to_node[circle_node->name()] = circle_node;
+  }
+
+  THROW_UNLESS(root.isObject());
+
+  for (const auto tensor_name : root.getMemberNames())
+  {
+    const auto tensor = root[tensor_name];
+
+    verify_tensor(tensor);
+
+    const auto scale_path = dir_path + '/' + tensor["scale"].asString();
+    const auto zerop_path = dir_path + '/' + tensor["zerop"].asString();
+    const auto quantized_dimension = tensor["quantized_dimension"].asUInt();
+    const auto dtype = str_to_dtype(tensor["dtype"].asString());
+
+    auto node = name_to_node.at(tensor_name);
+
+    // Node must be fp32
+    THROW_UNLESS(node->dtype() == loco::DataType::FLOAT32);
+
+    node->quantparam(std::make_unique<luci::CircleQuantParam>());
+
+    set_dtype(node, dtype);
+    set_scale(node, scale_path);
+    set_zerop(node, zerop_path);
+    set_quantized_dimension(node, quantized_dimension);
+
+    if (tensor.isMember("value"))
+    {
+      auto const_node = loco::must_cast<luci::CircleConst *>(node);
+      const auto value_path = dir_path + '/' + tensor["value"].asString();
+
+      set_value(const_node, value_path, dtype);
+    }
+  }
+
+  forward_qparam(g);
+
+  // Update output nodes
+  auto graph_outputs = g->outputs();
+  assert(graph_outputs); // FIX_CALLER_UNLESS
+  for (auto node : loco::output_nodes(g))
+  {
+    auto out_node = loco::must_cast<luci::CircleOutput *>(node);
+    auto from_node = loco::must_cast<luci::CircleNode *>(out_node->from());
+
+    THROW_UNLESS(from_node->quantparam());
+
+    out_node->quantparam(std::make_unique<luci::CircleQuantParam>());
+    out_node->quantparam()->scale = from_node->quantparam()->scale;
+    out_node->quantparam()->zerop = from_node->quantparam()->zerop;
+    out_node->quantparam()->quantized_dimension = from_node->quantparam()->quantized_dimension;
+    out_node->dtype(from_node->dtype());
+
+    auto graph_output = graph_outputs->at(out_node->index());
+    graph_output->dtype(out_node->dtype());
+  }
+
+  // Verify quantized model
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+
+    // Throw an exception if dtype is not float32
+    // TODO Operator-level verification (ex: using QuantizedModelVerifier)
+    THROW_UNLESS(circle_node->dtype() != loco::DataType::FLOAT32);
+  }
+}
+
+void QImplant::forward_qparam(loco::Graph *g)
+{
+  /*
+   * TODO: add comment about how to add to the set
+   *
+   * If the operator doesn't change input tensor value,
+   * (Operator don't change input quantization parameter to output tensor)
+   * the operator's quantization parameter can be forwarded
+   */
+  std::set<luci::CircleOpcode> forwardable_opcode;
+  forwardable_opcode.emplace(luci::CircleOpcode::RESHAPE);
+  forwardable_opcode.emplace(luci::CircleOpcode::SPLIT);
+  forwardable_opcode.emplace(luci::CircleOpcode::CIRCLESPLITOUT);
+  forwardable_opcode.emplace(luci::CircleOpcode::TRANSPOSE);
+  // TODO add more Ops
+
+  auto forwardable = [&forwardable_opcode](luci::CircleOpcode opcode) {
+    return forwardable_opcode.find(opcode) != forwardable_opcode.end();
+  };
+
+  for (auto node : loco::active_nodes(loco::output_nodes(g)))
+  {
+    auto circle_node = loco::must_cast<luci::CircleNode *>(node);
+
+    auto quantparam = circle_node->quantparam();
+    if (quantparam == nullptr)
+      continue;
+
+    for (auto successor : loco::succs(node))
+    {
+      auto successor_node = loco::must_cast<luci::CircleNode *>(successor);
+      if (successor_node->quantparam() == nullptr)
+      {
+        if (!forwardable(successor_node->opcode()))
+          continue;
+        copy_quantparam(circle_node, successor_node);
+        copy_dtype(circle_node, successor_node);
+      }
+    }
+  }
+}
+
+#undef THROW_UNLESS
index bb46d3a..292666f 100644 (file)
@@ -24,6 +24,7 @@ import numpy as np
 import argparse
 import glob
 import os
+import warnings
 
 
 def get_parser():
@@ -79,23 +80,24 @@ def create_hdf5(data_list, output_path):
         lines = f.readlines()
         for line in lines:
             if line.strip():
-                filename = line.rstrip()
-                if os.path.isfile(filename):
-                    datalist.append(filename)
-                else:
-                    raise FileNotFoundError("No such file. " + filename)
+                filenames = line.rstrip().split(' ')
+                # A single line can indicate multiple files (multi-input)
+                for filename in filenames:
+                    if not os.path.isfile(filename):
+                        raise FileNotFoundError("No such file. " + filename)
+                datalist.append(filenames)
 
     # Input files
     num_converted = 0
-    for rawdata in datalist:
-        with open(rawdata, 'rb') as f:
-            sample = group.create_group(str(num_converted))
-            num_converted += 1
-            filename = os.path.basename(rawdata)
-            sample.attrs['desc'] = filename
-            raw_data = bytearray(f.read())
-            # The target model is DNN with one input data
-            sample.create_dataset('0', data=raw_data)
+    for input_files in datalist:
+        sample = group.create_group(str(num_converted))
+        for idx, input_file in enumerate(input_files):
+            with open(input_file, 'rb') as f:
+                raw_data = bytearray(f.read())
+                sample.create_dataset(str(idx), data=raw_data)
+        sample.attrs['desc'] = ','.join(
+            list(map(lambda x: os.path.basename(x), input_files)))
+        num_converted += 1
 
     h5_file.close()
 
@@ -104,6 +106,7 @@ def create_hdf5(data_list, output_path):
 
 
 def main():
+    warnings.warn("rawdata2hdf5 will be deprecated. Please use one-create-quant-dataset.");
     parser = get_parser()
 
     args = parser.parse_args()
diff --git a/compiler/record-minmax-conversion-test/gen_h5_random_inputs.py b/compiler/record-minmax-conversion-test/gen_h5_random_inputs.py
deleted file mode 100755 (executable)
index d57289a..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python3
-import h5py as h5
-import numpy as np
-import tensorflow as tf
-import argparse
-
-#
-# This script generates a pack of random input data (.h5) expected by the input tflite model
-#
-# Basic usage:
-#   gen_h5_inputs.py --model <path/to/tflite/model> --num_data <number/of/data> --output <path/to/output/data>
-#   ex: gen_h5_inputs.py --model add.tflite --num_data 3 --output add.tflite.input.h5
-#   (This will create add.tflite.input.h5 composed of three random inputs in the same directory as the model)
-parser = argparse.ArgumentParser()
-parser.add_argument('--model', type=str, required=True)
-parser.add_argument('--num_data', type=int, required=True)
-parser.add_argument('--output', type=str, required=True)
-args = parser.parse_args()
-
-model = args.model
-
-num_data = args.num_data
-
-output_path = args.output
-
-# Build TFLite interpreter. (to get the information of model input)
-interpreter = tf.lite.Interpreter(model)
-input_details = interpreter.get_input_details()
-
-# Create h5 file
-h5_file = h5.File(output_path, 'w')
-group = h5_file.create_group("value")
-group.attrs['desc'] = "Input data for " + model
-
-# Generate random data
-for i in range(num_data):
-    sample = group.create_group(str(i))
-    sample.attrs['desc'] = "Input data " + str(i)
-
-    for j in range(len(input_details)):
-        input_detail = input_details[j]
-        print(input_detail["dtype"])
-        if input_detail["dtype"] == np.bool_:
-            # Generate random bool [0, 1]
-            input_data = np.array(
-                np.random.random_integers(0, 1, input_detail["shape"]),
-                input_detail["dtype"])
-        elif input_detail["dtype"] == np.float32:
-            # Generate random input [-5, 5)
-            input_data = np.array(10 * np.random.random_sample(input_detail["shape"]) - 5,
-                                  input_detail["dtype"])
-        sample.create_dataset(str(j), data=input_data)
-
-h5_file.close()
diff --git a/compiler/record-minmax-conversion-test/gen_h5_random_inputs_all.py b/compiler/record-minmax-conversion-test/gen_h5_random_inputs_all.py
new file mode 100644 (file)
index 0000000..f3c49eb
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+import h5py as h5
+import numpy as np
+import tensorflow as tf
+import argparse
+import os
+
+#
+# This script generates a pack of random input data (.h5) expected by the input tflite models
+#
+parser = argparse.ArgumentParser()
+parser.add_argument('--num_data', type=int, required=True)
+parser.add_argument('--output_dir', type=str, required=True)
+parser.add_argument('--artifact_dir', type=str, required=True)
+parser.add_argument('--model', type=str, required=True, nargs='+')
+args = parser.parse_args()
+
+num_data = args.num_data
+output_dir = args.output_dir
+artifact_dir = args.artifact_dir
+model_list = args.model
+
+for model_name in model_list:
+    model_path = os.path.join(artifact_dir, model_name + '.tflite')
+    h5_path = os.path.join(output_dir, model_name + '.tflite.input.h5')
+    # Build TFLite interpreter. (to get the information of model input)
+    interpreter = tf.lite.Interpreter(model_path)
+    input_details = interpreter.get_input_details()
+
+    # Create h5 file
+    h5_file = h5.File(h5_path, 'w')
+    group = h5_file.create_group("value")
+    group.attrs['desc'] = "Input data for " + model_path
+
+    # Generate random data
+    for i in range(num_data):
+        sample = group.create_group(str(i))
+        sample.attrs['desc'] = "Input data " + str(i)
+
+        for j in range(len(input_details)):
+            input_detail = input_details[j]
+            print(input_detail["dtype"])
+            if input_detail["dtype"] == np.bool_:
+                # Generate random bool [0, 1]
+                input_data = np.array(
+                    np.random.random_integers(0, 1, input_detail["shape"]),
+                    input_detail["dtype"])
+            elif input_detail["dtype"] == np.float32:
+                # Generate random input [-5, 5)
+                input_data = np.array(
+                    10 * np.random.random_sample(input_detail["shape"]) - 5,
+                    input_detail["dtype"])
+            sample.create_dataset(str(j), data=input_data)
+
+    h5_file.close()
index d7fc1de..71f186f 100755 (executable)
@@ -9,7 +9,7 @@
 # work_dir : build directory of record-minmax-conversion-test (ex: build/compiler/record-minmax-conversion-test)
 
 GEN_SOURCE_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-GEN_SCRIPT_PATH="${GEN_SOURCE_PATH}/gen_h5_random_inputs.py"
+GEN_SCRIPT_PATH="${GEN_SOURCE_PATH}/gen_h5_random_inputs_all.py"
 CONFIG_PATH="$1"; shift
 BIN_PATH=$(dirname "$CONFIG_PATH")
 WORKDIR="$1"; shift
@@ -25,6 +25,20 @@ PASSED=()
 FAILED=()
 
 pushd "${WORKDIR}"
+
+# Generate h5 input data
+source "${VIRTUALENV}/bin/activate"
+  "${VIRTUALENV}/bin/python" "${GEN_SCRIPT_PATH}" \
+  --num_data 3 \
+  --output_dir "${BIN_PATH}" \
+  --artifact_dir ${WORKDIR} \
+  --model "$@"
+
+if [[ $? -ne 0 ]]; then
+  echo "FAILED TO GENERATE INPUT"
+  exit 255
+fi
+
 for TESTCASE in "$@"; do
   TESTED+=("${TESTCASE}")
 
@@ -37,18 +51,6 @@ for TESTCASE in "$@"; do
     exec 2>&1
     set -ex
 
-    # Generate h5 input data
-    source "${VIRTUALENV}/bin/activate"
-    "${VIRTUALENV}/bin/python" "${GEN_SCRIPT_PATH}" \
-    --model "${TESTCASE_FILE}.tflite" \
-    --num_data 3 \
-    --output "${BIN_PATH}/${TESTCASE}.tflite.input.h5"
-
-    if [[ $? -ne 0 ]]; then
-      echo "FAILED TO GENERATE INPUT"
-      continue
-    fi
-
     # Run record-minmax
     "${RECORD_MINMAX_PATH}" \
       --input_model "${TESTCASE_FILE}.circle" \
index d96b79c..43d0323 100644 (file)
@@ -17,6 +17,7 @@
 #include "RecordMinMax.h"
 #include "MinMaxObserver.h"
 
+#include <luci/IR/DataTypeHelper.h>
 #include <luci/Importer.h>
 #include <luci/CircleExporter.h>
 #include <luci/CircleFileExpContract.h>
@@ -39,6 +40,36 @@ using DataType = loco::DataType;
 namespace
 {
 
+// Return a string with no whitespace from both ends
+std::string trim(std::string s)
+{
+  // Trim left side
+  s.erase(s.begin(),
+          std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
+
+  // Trim right side
+  s.erase(
+    std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(),
+    s.end());
+
+  return s;
+}
+
+std::vector<std::string> parse_line(const std::string &line)
+{
+  auto trimmed = trim(line);
+  std::stringstream ss(trimmed);
+
+  std::vector<std::string> res;
+
+  std::string filename;
+  while (getline(ss, filename, ' '))
+  {
+    res.emplace_back(filename);
+  }
+  return res;
+}
+
 // Max h5 file size for parallel recording in bytes = 1 GB
 const long h5_max_size_bytes = 1000000000;
 
@@ -117,7 +148,7 @@ std::vector<T> genRandomIntData(std::mt19937 &gen, uint32_t num_elements, T min,
  */
 template <typename NodeT> size_t getTensorSize(const NodeT *node)
 {
-  uint32_t tensor_size = loco::size(node->dtype());
+  uint32_t tensor_size = luci::size(node->dtype());
   for (uint32_t i = 0; i < node->rank(); ++i)
     tensor_size *= node->dim(i).value();
   return tensor_size;
@@ -294,6 +325,40 @@ void RecordMinMax::profileRawData(const std::string &input_data_path)
   {
     std::cout << "Recording " << num_records << "'th data" << std::endl;
 
+    auto file_names = parse_line(record);
+
+    // Have multiple files in one line
+    if (file_names.size() == input_nodes.size())
+    {
+      std::vector<std::vector<char>> input_data;
+      for (uint32_t i = 0; i < file_names.size(); i++)
+      {
+        const auto file_name = file_names[i];
+        const auto input_node = loco::must_cast<const luci::CircleInput *>(input_nodes[i]);
+        const auto input_size = getTensorSize(input_node);
+
+        input_data.emplace_back(input_size);
+
+        // Read data from file
+        readDataFromFile(file_name, input_data[i], input_size);
+
+        // Write data from buffer to interpreter
+        getInterpreter()->writeInputTensor(input_node, input_data[i].data(), input_size);
+      }
+
+      getInterpreter()->interpret();
+
+      num_records++;
+    }
+    else
+    {
+      // Must have a single file in one line (inputs are concatenated)
+      if (file_names.size() != 1)
+        throw std::runtime_error(
+          "Wrong number of inputs are given. Model has " + std::to_string(input_nodes.size()) +
+          " inputs, but list file gives " + std::to_string(file_names.size()) + " inputs.");
+
+      // clang-format off
     // Read data from file to buffer
     // Assumption: For a multi-input model, the binary file should have inputs concatenated in the
     // same order with the input index.
@@ -314,6 +379,8 @@ void RecordMinMax::profileRawData(const std::string &input_data_path)
     getInterpreter()->interpret();
 
     num_records++;
+      // clang-format on
+    }
   }
 
   if (num_records == 0)
index 6bb7bba..6a6e646 100644 (file)
@@ -20,6 +20,8 @@
 #include "souschef/DataChef.h"
 #include "souschef/LexicalCast.h"
 
+#include <stdexcept>
+
 namespace souschef
 {
 
@@ -62,6 +64,89 @@ template <typename T> struct ConstantDataChefFactory : public DataChefFactory
   }
 };
 
+class ConstantInt4DataChef final : public DataChef
+{
+public:
+  ConstantInt4DataChef(const int8_t &value) : _value{value}
+  {
+    // DO NOTHING
+  }
+
+public:
+  // int4 constant is saved as int8 (extra 4 bits are filled with sign bits).
+  // Callers must cast each element to int8 before using it.
+  // Example)
+  //   ConstInt4DataChef chef(-5)
+  //   auto values = chef.generate(3);
+  //   for (uint8_t value: values) {
+  //     int8_t real_value = static_cast<int8_t>(value);
+  //     assert(value == 251 and real_value == -5);
+  std::vector<uint8_t> generate(int32_t count) const override
+  {
+    std::vector<uint8_t> res;
+
+    if (_value < -8 || 7 < _value)
+      throw std::runtime_error("Constant value out of range.");
+
+    for (uint32_t n = 0; n < count; ++n)
+    {
+      const uint8_t data = static_cast<const uint8_t>(_value);
+      res.emplace_back(data);
+    }
+
+    return res;
+  }
+
+private:
+  int8_t _value;
+};
+
+struct ConstantInt4DataChefFactory : public DataChefFactory
+{
+  std::unique_ptr<DataChef> create(const Arguments &args) const
+  {
+    auto const value = to_number<int8_t>(args.value(0));
+    return std::unique_ptr<DataChef>{new ConstantInt4DataChef{value}};
+  }
+};
+
+class ConstantUint4DataChef final : public DataChef
+{
+public:
+  ConstantUint4DataChef(const uint8_t &value) : _value{value}
+  {
+    // DO NOTHING
+  }
+
+public:
+  std::vector<uint8_t> generate(int32_t count) const override
+  {
+    std::vector<uint8_t> res;
+
+    if (15 < _value)
+      throw std::runtime_error("Constant value out of range.");
+
+    for (uint32_t n = 0; n < count; ++n)
+    {
+      res.emplace_back(_value);
+    }
+
+    return res;
+  }
+
+private:
+  uint8_t _value;
+};
+
+struct ConstantUint4DataChefFactory : public DataChefFactory
+{
+  std::unique_ptr<DataChef> create(const Arguments &args) const
+  {
+    auto const value = to_number<uint8_t>(args.value(0));
+    return std::unique_ptr<DataChef>{new ConstantUint4DataChef{value}};
+  }
+};
+
 } // namespace souschef
 
 #endif // __SOUSCHEF_DATA_CONSTANT_H__
index 434d0ec..6791998 100644 (file)
@@ -131,6 +131,74 @@ struct ExplicitFloat16DataChefFactory : public DataChefFactory
   }
 };
 
+class ExplicitInt4DataChef final : public DataChef
+{
+public:
+  ExplicitInt4DataChef()
+  {
+    // DO NOTHING
+  }
+
+public:
+  std::vector<uint8_t> generate(int32_t count) const override;
+
+public:
+  void insert(const int8_t &value) { _values.emplace_back(value); }
+
+private:
+  std::vector<int8_t> _values;
+};
+
+struct ExplicitInt4DataChefFactory : public DataChefFactory
+{
+  std::unique_ptr<DataChef> create(const Arguments &args) const
+  {
+    std::unique_ptr<ExplicitInt4DataChef> res{new ExplicitInt4DataChef};
+
+    for (uint32_t n = 0; n < args.count(); ++n)
+    {
+      auto const data = to_number<int8_t>(args.value(n));
+      res->insert(data);
+    }
+
+    return std::move(res);
+  }
+};
+
+class ExplicitUint4DataChef final : public DataChef
+{
+public:
+  ExplicitUint4DataChef()
+  {
+    // DO NOTHING
+  }
+
+public:
+  std::vector<uint8_t> generate(int32_t count) const override;
+
+public:
+  void insert(const uint8_t &value) { _values.emplace_back(value); }
+
+private:
+  std::vector<uint8_t> _values;
+};
+
+struct ExplicitUint4DataChefFactory : public DataChefFactory
+{
+  std::unique_ptr<DataChef> create(const Arguments &args) const
+  {
+    std::unique_ptr<ExplicitUint4DataChef> res{new ExplicitUint4DataChef};
+
+    for (uint32_t n = 0; n < args.count(); ++n)
+    {
+      auto const data = to_number<uint8_t>(args.value(n));
+      res->insert(data);
+    }
+
+    return std::move(res);
+  }
+};
+
 } // namespace souschef
 
 #endif // __SOUSCHEF_DATA_EXPLICIT_H__
index 1d87f13..38d9b0e 100644 (file)
@@ -85,6 +85,12 @@ public:
     return false;
   }
 
+  void clear_tensor_filler() { _tensor_filler.clear(); }
+
+  void clear_tensor_filler_vint32() { _tensor_filler_vint32.clear(); }
+
+  void clear_tensor_filler_vfloat() { _tensor_filler_vfloat.clear(); }
+
 private:
   std::map<uint32_t, bool> _tensor_filler{};
   std::map<uint32_t, std::vector<int32_t>> _tensor_filler_vint32{};
index 3278ae3..06c76c4 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "souschef/Data/Explicit.h"
 
+#include <stdexcept>
 #include <string>
 #include <vector>
 
@@ -95,4 +96,37 @@ std::vector<uint8_t> ExplicitFloat16DataChef::generate(int32_t count) const
   return res;
 }
 
+std::vector<uint8_t> ExplicitInt4DataChef::generate(int32_t count) const
+{
+  std::vector<uint8_t> res;
+
+  for (uint32_t n = 0; n < count; ++n)
+  {
+    int8_t const value = (n < _values.size()) ? _values.at(n) : 0;
+    if (value < -8 || 7 < value)
+      throw std::runtime_error("Explicit value out of range.");
+
+    const uint8_t data = static_cast<const uint8_t>(value);
+    res.emplace_back(data);
+  }
+
+  return res;
+}
+
+std::vector<uint8_t> ExplicitUint4DataChef::generate(int32_t count) const
+{
+  std::vector<uint8_t> res;
+
+  for (uint32_t n = 0; n < count; ++n)
+  {
+    uint8_t const value = (n < _values.size()) ? _values.at(n) : 0;
+    if (15 < value)
+      throw std::runtime_error("Explicit value out of range.");
+
+    res.emplace_back(value);
+  }
+
+  return res;
+}
+
 } // namespace souschef
diff --git a/compiler/tf2circle-conversion-test/exclude.me b/compiler/tf2circle-conversion-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2circle-dredd-pb-test/exclude.me b/compiler/tf2circle-dredd-pb-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2circle-dredd-pbtxt-test/exclude.me b/compiler/tf2circle-dredd-pbtxt-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2circle-model-test/exclude.me b/compiler/tf2circle-model-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2circle-ui-check/exclude.me b/compiler/tf2circle-ui-check/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2circle-value-pbtxt-remote-test/exclude.me b/compiler/tf2circle-value-pbtxt-remote-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2circle/exclude.me b/compiler/tf2circle/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2tflite-dredd-pb-test/exclude.me b/compiler/tf2tflite-dredd-pb-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2tflite-dredd-pbtxt-test/exclude.me b/compiler/tf2tflite-dredd-pbtxt-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2tflite-value-pb-test/exclude.me b/compiler/tf2tflite-value-pb-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2tflite-value-pbtxt-test/exclude.me b/compiler/tf2tflite-value-pbtxt-test/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tf2tflite/exclude.me b/compiler/tf2tflite/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tfinfo-v2/exclude.me b/compiler/tfinfo-v2/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/compiler/tfkit/exclude.me b/compiler/tfkit/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index 78e7700..820e721 100644 (file)
@@ -36,7 +36,7 @@ void DumpOperators::run(std::ostream &os, const tflite::Model *model)
     auto ops = reader.operators();
 
     // dump operators
-    for (uint32_t i = 0; i < ops->Length(); ++i)
+    for (uint32_t i = 0; i < ops->size(); ++i)
     {
       const auto op = ops->Get(i);
 
@@ -56,7 +56,7 @@ const tflite::Operator *operator_match_output(tflinspect::Reader &reader, const
 {
   auto ops = reader.operators();
 
-  for (uint32_t i = 0; i < ops->Length(); ++i)
+  for (uint32_t i = 0; i < ops->size(); ++i)
   {
     const auto op = ops->Get(i);
 
@@ -75,7 +75,7 @@ size_t tensor_buffer_size(tflinspect::Reader &reader, const int32_t tensor_id)
 {
   auto tensors = reader.tensors();
 
-  if (tensor_id < 0 || tensor_id >= tensors->Length())
+  if (tensor_id < 0 || tensor_id >= tensors->size())
   {
     throw std::runtime_error("Invalid Tensor ID");
   }
@@ -105,7 +105,7 @@ void DumpConv2DWeight::run(std::ostream &os, const tflite::Model *model)
     auto ops = reader.operators();
 
     // dump Conv2D, DepthwiseConv2D and its weight input operator
-    for (uint32_t i = 0; i < ops->Length(); ++i)
+    for (uint32_t i = 0; i < ops->size(); ++i)
     {
       const auto op = ops->Get(i);
       auto bc = reader.builtin_code(op);
@@ -159,7 +159,7 @@ void DumpOperatorVersion::run(std::ostream &os, const tflite::Model *model)
     auto ops = reader.operators();
 
     // dump Conv2D, DepthwiseConv2D and its weight input operator
-    for (uint32_t i = 0; i < ops->Length(); ++i)
+    for (uint32_t i = 0; i < ops->size(); ++i)
     {
       const auto op = ops->Get(i);
 
index 1ae2e47..7821bb9 100644 (file)
@@ -98,7 +98,7 @@ bool Reader::select_subgraph(uint32_t sgindex)
   _inputs.clear();
   _outputs.clear();
 
-  if (_subgraphs->Length() <= sgindex)
+  if (_subgraphs->size() <= sgindex)
   {
     assert(false);
     return false;
index 98554cf..efb0de2 100644 (file)
@@ -28,8 +28,8 @@ namespace tflinspect
 
 template <typename T> std::vector<T> as_index_vector(const flatbuffers::Vector<T> *flat_array)
 {
-  std::vector<T> ret(flat_array->Length());
-  for (uint32_t i = 0; i < flat_array->Length(); i++)
+  std::vector<T> ret(flat_array->size());
+  for (uint32_t i = 0; i < flat_array->size(); i++)
   {
     ret[i] = flat_array->Get(i);
   }
@@ -60,7 +60,7 @@ public:
   const std::vector<int32_t> &inputs() const { return _inputs; }
   const std::vector<int32_t> &outputs() const { return _outputs; }
 
-  uint32_t num_subgraph() const { return _subgraphs->Length(); }
+  uint32_t num_subgraph() const { return _subgraphs->size(); }
 
   size_t buffer_info(uint32_t buf_idx, const uint8_t **buff_data);
   tflite::BuiltinOperator builtin_code(const tflite::Operator *op) const;
index d1babf0..3b699b3 100644 (file)
@@ -79,6 +79,8 @@ tflite::TensorType as_tflite_tensortype(const tflchef::TensorType &value)
       return tflite::TensorType_INT16;
     case tflchef::INT8:
       return tflite::TensorType_INT8;
+    case tflchef::INT4:
+      return tflite::TensorType_INT4;
     default:
       break;
   }
index 557c20b..f3d0b5e 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "AddV2.h"
+#include "OpUtils.h"
 
 #include <flatbuffers/flexbuffers.h>
 
@@ -29,7 +30,7 @@ AddV2Chef::custom_value(flatbuffers::FlatBufferBuilder &fbb) const
 {
   auto &operation = (*_operation);
 
-  assert(operation.type() == "AddV2");
+  check_custom_op_value(operation, "AddV2");
 
   /**
    * REGISTER_OP("AddV2")
index bbef5ec..4af447d 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "All.h"
+#include "OpUtils.h"
 
 #include <flatbuffers/flexbuffers.h>
 
@@ -29,7 +30,7 @@ AllChef::custom_value(flatbuffers::FlatBufferBuilder &fbb) const
 {
   auto &operation = (*_operation);
 
-  assert(operation.type() == "All");
+  check_custom_op_value(operation, "All");
 
   /**
    * REGISTER_OP("All")
index 6d2c5b1..f7ce490 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "BatchMatMulV2.h"
+#include "OpUtils.h"
 
 #include <flatbuffers/flexbuffers.h>
 
@@ -29,7 +30,7 @@ BatchMatMulV2Chef::custom_value(flatbuffers::FlatBufferBuilder &fbb) const
 {
   auto &operation = (*_operation);
 
-  assert(operation.type() == "BatchMatMulV2");
+  check_custom_op_value(operation, "BatchMatMulV2");
 
   /**
    * REGISTER_OP("BatchMatMulV2")
index dd458b3..4ce8207 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "BroadcastTo.h"
+#include "OpUtils.h"
 
 #include <flatbuffers/flexbuffers.h>
 
@@ -29,7 +30,7 @@ BroadcastToChef::custom_value(flatbuffers::FlatBufferBuilder &fbb) const
 {
   auto &operation = (*_operation);
 
-  assert(operation.type() == "BroadcastTo");
+  check_custom_op_value(operation, "BroadcastTo");
 
   /**
    * REGISTER_OP("BroadcastTo")
index f611b68..ac2e9b3 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "Erf.h"
+#include "OpUtils.h"
 
 #include <flatbuffers/flexbuffers.h>
 
@@ -29,7 +30,7 @@ ErfChef::custom_value(flatbuffers::FlatBufferBuilder &fbb) const
 {
   auto &operation = (*_operation);
 
-  assert(operation.type() == "Erf");
+  check_custom_op_value(operation, "Erf");
 
   /**
    * REGISTER_OP("Erf")
index e7c707d..d8282f7 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "MatMul.h"
+#include "OpUtils.h"
 
 #include <flatbuffers/flexbuffers.h>
 
@@ -29,7 +30,7 @@ MatMulChef::custom_value(flatbuffers::FlatBufferBuilder &fbb) const
 {
   auto &operation = (*_operation);
 
-  assert(operation.type() == "MatMul");
+  check_custom_op_value(operation, "MatMul");
 
   /**
    * REGISTER_OP("MatMul")
index b250032..1c7987a 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "MatrixBandPart.h"
+#include "OpUtils.h"
 
 #include <flatbuffers/flexbuffers.h>
 
@@ -29,7 +30,7 @@ MatrixBandPartChef::custom_value(flatbuffers::FlatBufferBuilder &fbb) const
 {
   auto &operation = (*_operation);
 
-  assert(operation.type() == "MatrixBandPart");
+  check_custom_op_value(operation, "MatrixBandPart");
 
   /**
    * REGISTER_OP("MatrixBandPart")
index 290d3c2..64c1a6c 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "MaxPoolWithArgmax.h"
+#include "OpUtils.h"
 
 #include <flatbuffers/flexbuffers.h>
 
@@ -29,7 +30,7 @@ MaxPoolWithArgmaxChef::custom_value(flatbuffers::FlatBufferBuilder &fbb) const
 {
   auto &operation = (*_operation);
 
-  assert(operation.type() == "MaxPoolWithArgmax");
+  check_custom_op_value(operation, "MaxPoolWithArgmax");
 
   /**
    * REGISTER_OP("MaxPoolWithArgmax")
index abe6426..ed10628 100644 (file)
@@ -25,6 +25,10 @@ DATA_CHEF(INT16, gaussian, GaussianInt16DataChefFactory)
 DATA_CHEF(INT8, gaussian, GaussianInt8DataChefFactory)
 DATA_CHEF(UINT8, gaussian, GaussianUint8DataChefFactory)
 
+// INT4 support only for constant, explicit as int8_t
+DATA_CHEF(INT4, constant, ConstantInt4DataChefFactory)
+DATA_CHEF(INT4, explicit, ExplicitInt4DataChefFactory)
+
 // FLOAT16 support for only gaussian, explicit for now
 DATA_CHEF(FLOAT16, explicit, ExplicitFloat16DataChefFactory)
 DATA_CHEF(FLOAT16, gaussian, GaussianFloat16DataChefFactory)
index 3afcd23..4025ed2 100644 (file)
@@ -94,6 +94,7 @@ DataChefRegistry &data_chef_registry(const tflchef::TensorType &type)
   static DataChefRegistry s16;
   static DataChefRegistry fp16;
   static DataChefRegistry s8;
+  static DataChefRegistry s4;
 
   switch (type)
   {
@@ -115,6 +116,8 @@ DataChefRegistry &data_chef_registry(const tflchef::TensorType &type)
       return s16;
     case tflchef::INT8:
       return s8;
+    case tflchef::INT4:
+      return s4;
     default:
       break;
   }
@@ -141,10 +144,10 @@ gather_builtincode_map(const ::tflchef::ModelRecipe &model_recipe)
 
   for (const auto &operation : model_recipe.operation())
   {
-    auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
-    if (op_chef->code() == tflite::BuiltinOperator_CUSTOM)
+    if (operation.type() == "Custom")
       continue;
 
+    auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
     // Various operation version is unified as the highest version among them
     if (builtin_map.find(op_chef->code()) == builtin_map.end() ||
         builtin_map[op_chef->code()] < operation.version())
@@ -157,10 +160,10 @@ gather_builtincode_map(const ::tflchef::ModelRecipe &model_recipe)
     const auto &graph = model_recipe.graph(g);
     for (const auto &operation : graph.operation())
     {
-      auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
-      if (op_chef->code() == tflite::BuiltinOperator_CUSTOM)
+      if (operation.type() == "Custom")
         continue;
 
+      auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
       // Various operation version is unified as the highest version among them
       if (builtin_map.find(op_chef->code()) == builtin_map.end() ||
           builtin_map[op_chef->code()] < operation.version())
@@ -177,9 +180,11 @@ std::set<std::string> gather_customcode_set(const ::tflchef::ModelRecipe &model_
   std::set<std::string> customcode_set;
   for (const auto &operation : model_recipe.operation())
   {
-    auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
-    if (op_chef->code() == tflite::BuiltinOperator_CUSTOM)
-      customcode_set.insert(operation.type());
+    if (operation.type() == "Custom")
+    {
+      assert(not operation.custom_code().empty());
+      customcode_set.insert(operation.custom_code());
+    }
   }
 
   // Add ops used in Graphs(subgraphs)
@@ -188,9 +193,11 @@ std::set<std::string> gather_customcode_set(const ::tflchef::ModelRecipe &model_
     const auto &graph = model_recipe.graph(g);
     for (const auto &operation : graph.operation())
     {
-      auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
-      if (op_chef->code() == tflite::BuiltinOperator_CUSTOM)
-        customcode_set.insert(operation.type());
+      if (operation.type() == "Custom")
+      {
+        assert(not operation.custom_code().empty());
+        customcode_set.insert(operation.custom_code());
+      }
     }
   }
 
@@ -346,6 +353,7 @@ template <typename T> std::map<std::string, int32_t> cook_graph(const T &graph,
       {
         assert(not operand.has_sparsity());
         assert(operand.has_shape());
+        assert(operand.type() != tflchef::TensorType::INT4);
 
         const int32_t dims_count = dims.size();
         std::vector<int> traversal_order_vec;
@@ -449,6 +457,21 @@ template <typename T> std::map<std::string, int32_t> cook_graph(const T &graph,
       }
       else
       {
+        // pack for INT4 and replace data_vec
+        if (operand.type() == tflchef::TensorType::INT4)
+        {
+          uint32_t packed = (count + 1) / 2;
+          std::vector<uint8_t> data_packed(packed);
+          for (uint32_t idx = 0; idx < packed; ++idx)
+          {
+            uint32_t sidx = idx * 2;
+            data_packed[idx] = data_vec[sidx++] & 0x0f;
+            if (sidx < count)
+              data_packed[idx] |= data_vec[sidx] << 4;
+          }
+          data_vec = data_packed;
+        }
+
         auto data = flatbuffer_builder->CreateVector(data_vec);
 
         // Create Buffer
@@ -619,7 +642,11 @@ template <typename T> std::map<std::string, int32_t> cook_graph(const T &graph,
   {
     assert(operation.has_type());
 
-    auto op_chef = op_chef_registry().lookup(operation.type()).create(&operation);
+    std::string op_type = operation.type();
+    if (not operation.custom_code().empty())
+      op_type = operation.custom_code();
+
+    auto op_chef = op_chef_registry().lookup(op_type).create(&operation);
 
     // Create 'inputs'
     std::vector<int32_t> input_vec = as_dataset(operation.input()).map(lookup).vectorize();
@@ -650,7 +677,9 @@ template <typename T> std::map<std::string, int32_t> cook_graph(const T &graph,
     // custom operator
     else
     {
-      auto op_it = std::find(custom_code_vec.begin(), custom_code_vec.end(), operation.type());
+      assert(not operation.custom_code().empty());
+      auto custom_code = operation.custom_code();
+      auto op_it = std::find(custom_code_vec.begin(), custom_code_vec.end(), custom_code);
       assert(op_it != custom_code_vec.end());
       opcode_index = builtin_code_map.size();
       opcode_index += std::distance(custom_code_vec.begin(), op_it);
diff --git a/compiler/tflchef/core/src/Op/BroadcastTo.cpp b/compiler/tflchef/core/src/Op/BroadcastTo.cpp
new file mode 100644 (file)
index 0000000..820964d
--- /dev/null
@@ -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.
+ */
+
+#include "BroadcastTo.h"
+
+flatbuffers::Offset<void> BroadcastToChef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+  tflite::BroadcastToOptionsBuilder options_builder{fbb};
+
+  return options_builder.Finish().Union();
+}
+
+std::unique_ptr<OpChef> BroadcastToChefFactory::create(const tflchef::Operation *operation) const
+{
+  return std::unique_ptr<OpChef>{new BroadcastToChef{operation}};
+}
diff --git a/compiler/tflchef/core/src/Op/BroadcastTo.h b/compiler/tflchef/core/src/Op/BroadcastTo.h
new file mode 100644 (file)
index 0000000..cdd863b
--- /dev/null
@@ -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_BROADCASTTO_H__
+#define __OP_BROADCASTTO_H__
+
+#include "OpChef.h"
+
+class BroadcastToChef final : public OpChef
+{
+public:
+  explicit BroadcastToChef(const tflchef::Operation *operation) : _operation{operation}
+  {
+    // DO NOTHING
+  }
+
+public:
+  tflite::BuiltinOperator code(void) const override { return tflite::BuiltinOperator_BROADCAST_TO; }
+
+  tflite::BuiltinOptions type(void) const override
+  {
+    return tflite::BuiltinOptions_BroadcastToOptions;
+  }
+
+  flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+  const tflchef::Operation *_operation;
+};
+
+struct BroadcastToChefFactory final : public OpChefFactory
+{
+  std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_BROADCAST_TO_H__
diff --git a/compiler/tflchef/core/src/Op/CumSum.cpp b/compiler/tflchef/core/src/Op/CumSum.cpp
new file mode 100644 (file)
index 0000000..93d3fa0
--- /dev/null
@@ -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 "CumSum.h"
+
+flatbuffers::Offset<void> CumSumChef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+  auto &operation = (*_operation);
+
+  assert(operation.has_cumsum_options());
+
+  auto exclusive = operation.cumsum_options().exclusive();
+  auto reverse = operation.cumsum_options().reverse();
+
+  tflite::CumsumOptionsBuilder cumsum_options_builder{fbb};
+  cumsum_options_builder.add_exclusive(exclusive);
+  cumsum_options_builder.add_reverse(reverse);
+
+  return cumsum_options_builder.Finish().Union();
+}
+
+std::unique_ptr<OpChef> CumSumChefFactory::create(const tflchef::Operation *operation) const
+{
+  return std::unique_ptr<OpChef>{new CumSumChef{operation}};
+}
diff --git a/compiler/tflchef/core/src/Op/CumSum.h b/compiler/tflchef/core/src/Op/CumSum.h
new file mode 100644 (file)
index 0000000..4fe89eb
--- /dev/null
@@ -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_CUMSUM_H__
+#define __OP_CUMSUM_H__
+
+#include "OpChef.h"
+
+class CumSumChef final : public OpChef
+{
+public:
+  explicit CumSumChef(const tflchef::Operation *operation) : _operation{operation}
+  {
+    // DO NOTHING
+  }
+
+public:
+  tflite::BuiltinOperator code(void) const override { return tflite::BuiltinOperator_CUMSUM; }
+
+  tflite::BuiltinOptions type(void) const override { return tflite::BuiltinOptions_CumsumOptions; }
+
+  flatbuffers::Offset<void> value(flatbuffers::FlatBufferBuilder &fbb) const override;
+
+private:
+  const tflchef::Operation *_operation;
+};
+
+struct CumSumChefFactory final : public OpChefFactory
+{
+  std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_CUMSUM_H__
diff --git a/compiler/tflchef/core/src/Op/ReLU0To1.cpp b/compiler/tflchef/core/src/Op/ReLU0To1.cpp
new file mode 100644 (file)
index 0000000..4176427
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ReLU0To1.h"
+
+flatbuffers::Offset<void> ReLU0To1Chef::value(flatbuffers::FlatBufferBuilder &fbb) const
+{
+  return flatbuffers::Offset<void>();
+}
+
+std::unique_ptr<OpChef> ReLU0To1ChefFactory::create(const tflchef::Operation *operation) const
+{
+  return std::unique_ptr<OpChef>{new ReLU0To1Chef{operation}};
+}
diff --git a/compiler/tflchef/core/src/Op/ReLU0To1.h b/compiler/tflchef/core/src/Op/ReLU0To1.h
new file mode 100644 (file)
index 0000000..dc93710
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_RELU_0_TO_1_H__
+#define __OP_RELU_0_TO_1_H__
+
+#include "OpChef.h"
+
+class ReLU0To1Chef final : public OpChef
+{
+public:
+  explicit ReLU0To1Chef(const tflchef::Operation *operation) : _operation{operation}
+  {
+    // DO NOTHING
+  }
+
+public:
+  tflite::BuiltinOperator code(void) const override { return tflite::BuiltinOperator_RELU_0_TO_1; }
+
+  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 ReLU0To1ChefFactory final : public OpChefFactory
+{
+  std::unique_ptr<OpChef> create(const tflchef::Operation *operation) const override;
+};
+
+#endif // __OP_RELU_0_TO_1_H__
index 9a21646..8881451 100644 (file)
@@ -13,11 +13,13 @@ OP_CHEF(AveragePool2D, AveragePool2DChefFactory)
 OP_CHEF(BatchMatMul, BatchMatMulChefFactory)
 OP_CHEF(BatchToSpaceND, BatchToSpaceNDChefFactory)
 OP_CHEF(BidirectionalSequenceLSTM, BidirectionalSequenceLSTMChefFactory)
+OP_CHEF(BroadcastTo, BroadcastToChefFactory)
 OP_CHEF(Cast, CastChefFactory)
 OP_CHEF(Ceil, CeilChefFactory)
 OP_CHEF(Concatenation, ConcatenationChefFactory)
 OP_CHEF(Conv2D, Conv2DChefFactory)
 OP_CHEF(Cos, CosChefFactory)
+OP_CHEF(CumSum, CumSumChefFactory)
 OP_CHEF(Densify, DensifyChefFactory)
 OP_CHEF(DepthToSpace, DepthToSpaceChefFactory)
 OP_CHEF(DepthwiseConv2D, DepthwiseConv2DChefFactory)
@@ -78,6 +80,7 @@ OP_CHEF(ReduceMax, ReduceMaxChefFactory)
 OP_CHEF(ReduceMin, ReduceMinChefFactory)
 OP_CHEF(ReduceProd, ReduceProdChefFactory)
 OP_CHEF(ReLU, ReLUChefFactory)
+OP_CHEF(ReLU0To1, ReLU0To1ChefFactory)
 OP_CHEF(ReLU6, ReLU6ChefFactory)
 OP_CHEF(ReLUN1To1, ReLUN1To1ChefFactory)
 OP_CHEF(Reshape, ReshapeChefFactory)
index ba2b175..2c2b9be 100644 (file)
 #include "Op/BatchMatMul.h"
 #include "Op/BatchToSpaceND.h"
 #include "Op/BidirectionalSequenceLSTM.h"
+#include "Op/BroadcastTo.h"
 #include "Op/Cast.h"
 #include "Op/Ceil.h"
 #include "Op/Concatenation.h"
 #include "Op/Conv2D.h"
 #include "Op/Cos.h"
+#include "Op/CumSum.h"
 #include "Op/Densify.h"
 #include "Op/DepthToSpace.h"
 #include "Op/DepthwiseConv2D.h"
@@ -90,6 +92,7 @@
 #include "Op/ReduceMin.h"
 #include "Op/ReduceProd.h"
 #include "Op/ReLU.h"
+#include "Op/ReLU0To1.h"
 #include "Op/ReLU6.h"
 #include "Op/ReLUN1To1.h"
 #include "Op/Reshape.h"
diff --git a/compiler/tflchef/core/src/OpUtils.cpp b/compiler/tflchef/core/src/OpUtils.cpp
new file mode 100644 (file)
index 0000000..8f65e52
--- /dev/null
@@ -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 "OpUtils.h"
+
+#include <stdexcept>
+
+void check_custom_op_value(const tflchef::Operation &operation, const std::string &op_type)
+{
+  if (operation.type() == "Custom")
+  {
+    assert(operation.custom_code() == op_type);
+  }
+}
diff --git a/compiler/tflchef/core/src/OpUtils.h b/compiler/tflchef/core/src/OpUtils.h
new file mode 100644 (file)
index 0000000..2183fdf
--- /dev/null
@@ -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.
+ */
+
+/**
+ * @file  OpUtils.h
+ * @brief This header declares various op_utils functions
+ */
+#ifndef __OPUTILS_H__
+#define __OPUTILS_H__
+
+#include <tflchef.pb.h>
+
+void check_custom_op_value(const tflchef::Operation &operation, const std::string &op_type);
+
+#endif // __OPUTILS_H__
index 98ae2b2..e4ae5d9 100644 (file)
@@ -23,6 +23,7 @@ enum TensorType {
   BOOL = 6;
   INT16 = 7;
   INT8 = 9;
+  INT4 = 17;
 }
 
 enum DimensionType {
@@ -274,6 +275,11 @@ message CosOptions {
   // None
 }
 
+message CumSumOptions {
+  optional bool exclusive = 1 [ default = false ];
+  optional bool reverse = 2 [ default = false ];
+}
+
 message EqualOptions {
   // None
 }
@@ -286,6 +292,10 @@ message BatchToSpaceNDOptions {
   // None
 }
 
+message BroadcastToOptions {
+  // None
+}
+
 message SpaceToBatchNDOptions {
   // None
 }
@@ -556,6 +566,7 @@ message Operation {
   repeated string input = 2;
   repeated string output = 3;
   optional int32 version = 4 [default = 1];
+  optional string custom_code = 5;
 
   optional Conv2DOptions conv2d_options = 100;
   optional Pool2DOptions averagepool2d_options = 101;
@@ -669,6 +680,7 @@ message Operation {
   optional MaxPoolWithArgmaxOptions max_pool_with_argmax_options = 209;
   optional DensifyOptions densify_options = 210;
   optional GeluOptions gelu_options = 211;
+  optional CumSumOptions cumsum_options = 212;
   // NOTE if there are more than two options with same type of Options
   // use the number not listed in the above reserve list
 }
index 8d86632..9bcc047 100644 (file)
@@ -1,5 +1,4 @@
 require("arser")
-require("nnkit")
 require("cwrap")
 require("mio-tflite2121")
 require("safemain")
index ab093a3..8877b0e 100644 (file)
@@ -9,9 +9,10 @@ operand {
   shape { dim: 1 dim: 3 dim: 3 dim: 2 }
 }
 operation {
-  type: "Erf"
+  type: "Custom"
   input: "ifm"
   output: "ofm"
+  custom_code: "Erf"
 }
 input: "ifm"
 output: "ofm"
diff --git a/compiler/tflchef/tests/short_int4/test.recipe b/compiler/tflchef/tests/short_int4/test.recipe
new file mode 100644 (file)
index 0000000..e9c990f
--- /dev/null
@@ -0,0 +1,44 @@
+operand {
+  name: "ifm"
+  type: INT4
+  shape { dim: 1 dim: 5 dim: 5 dim: 1 }
+}
+operand {
+  name: "ker"
+  type: INT4
+  shape { dim: 1 dim: 3 dim: 3 dim: 1 }
+  filler {
+    tag: "explicit"
+    arg: "-1" arg: "0" arg: "1"
+    arg: "1" arg: "2" arg: "3"
+    arg: "-1" arg: "-2" arg: "-3"
+  }
+}
+operand {
+  name: "bias"
+  type: INT4
+  shape { dim: 1 }
+  filler {
+    tag: "constant"
+    arg: "1"
+  }
+}
+operand {
+  name: "ofm"
+  type: INT4
+  shape { dim: 1 dim: 3 dim: 3 dim: 1 }
+}
+operation {
+  type: "Conv2D"
+  conv2d_options {
+    padding: VALID
+    stride_w: 1
+    stride_h: 1
+  }
+  input: "ifm"
+  input: "ker"
+  input: "bias"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/compiler/tflchef/tests/short_int4_quant/test.recipe b/compiler/tflchef/tests/short_int4_quant/test.recipe
new file mode 100644 (file)
index 0000000..c6d4471
--- /dev/null
@@ -0,0 +1,46 @@
+operand {
+  name: "ifm"
+  type: INT4
+  shape { dim: 1 dim: 5 dim: 5 dim: 1 }
+}
+operand {
+  name: "ker"
+  type: INT4
+  shape { dim: 1 dim: 3 dim: 3 dim: 1 }
+  filler {
+    tag: "explicit"
+    arg: "-1" arg: "0" arg: "1"
+    arg: "1" arg: "2" arg: "3"
+    arg: "-1" arg: "-2" arg: "-3"
+  }
+  quant { min: -0.5 max: 0.5 zero_point: 0 }
+}
+operand {
+  name: "bias"
+  type: INT4
+  shape { dim: 1 }
+  filler {
+    tag: "constant"
+    arg: "1"
+  }
+  quant { min: -0.5 max: 0.5 zero_point: 0 }
+}
+operand {
+  name: "ofm"
+  type: INT4
+  shape { dim: 1 dim: 3 dim: 3 dim: 1 }
+}
+operation {
+  type: "Conv2D"
+  conv2d_options {
+    padding: VALID
+    stride_w: 1
+    stride_h: 1
+  }
+  input: "ifm"
+  input: "ker"
+  input: "bias"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
index cf0c615..fb72c16 100644 (file)
@@ -46,8 +46,8 @@ template <typename DT> std::vector<DT> extract_buffer(const tflite::Buffer *buff
 
 template <typename T> std::vector<T> as_index_vector(const flatbuffers::Vector<T> *flat_array)
 {
-  std::vector<T> ret(flat_array->Length());
-  for (uint32_t i = 0; i < flat_array->Length(); i++)
+  std::vector<T> ret(flat_array->size());
+  for (uint32_t i = 0; i < flat_array->size(); i++)
   {
     ret[i] = flat_array->Get(i);
   }
index 7d769e3..55b218e 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpAbs::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpAbs::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpAbs::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Abs");
 
index 23d3606..f17bb6f 100644 (file)
@@ -30,14 +30,14 @@ void TFliteOpAdd::filler(const tflite::Operator *op, TFliteImport *import,
   fill_two_inputs(op, import);
 }
 
-tflchef::Operation *TFliteOpAdd::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpAdd::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_AddOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Add");
 
   auto op_options = operation->mutable_add_options();
index aeb3803..96a2c9e 100644 (file)
@@ -33,10 +33,10 @@ void TFliteOpAddN::filler(const tflite::Operator *op, TFliteImport *import,
     fill_tensor_to_import(inputs[idx], import);
 }
 
-tflchef::Operation *TFliteOpAddN::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpAddN::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("AddN");
 
index f4d1c5e..0116495 100644 (file)
@@ -34,14 +34,14 @@ void TFliteOpArgMax::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpArgMax::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpArgMax::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_ArgMaxOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("ArgMax");
 
   auto op_options = operation->mutable_argmax_options();
index faab0b8..c69c738 100644 (file)
@@ -34,14 +34,14 @@ void TFliteOpArgMin::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpArgMin::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpArgMin::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_ArgMinOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("ArgMin");
 
   auto op_options = operation->mutable_argmin_options();
index 1f269e4..450d11f 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpAveragePool2D::filler(const tflite::Operator *op, TFliteImport *imp
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpAveragePool2D::build(const tflite::Operator *op, TFliteImport *import,
-                                                 tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpAveragePool2D::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_Pool2DOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("AveragePool2D");
 
   auto op_options = operation->mutable_averagepool2d_options();
index 598e58c..a72ee10 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpBatchMatMul::filler(const tflite::Operator *op, TFliteImport *impor
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpBatchMatMul::build(const tflite::Operator *op, TFliteImport *import,
-                                               tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpBatchMatMul::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("BatchMatMul");
 
index d5d9606..5eee1cf 100644 (file)
@@ -40,10 +40,10 @@ void TFliteOpBatchToSpaceND::filler(const tflite::Operator *op, TFliteImport *im
   import->set_tensor_filler(inputs[2], vec);
 }
 
-tflchef::Operation *TFliteOpBatchToSpaceND::build(const tflite::Operator *op, TFliteImport *import,
-                                                  tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpBatchToSpaceND::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("BatchToSpaceND");
 
index 3254824..4d8866b 100644 (file)
@@ -41,15 +41,14 @@ void TFliteOpBidirectionalSequenceLSTM::filler(const tflite::Operator *op, TFlit
   }
 }
 
-tflchef::Operation *
-TFliteOpBidirectionalSequenceLSTM::build(const tflite::Operator *op, TFliteImport *import,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpBidirectionalSequenceLSTM::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_BidirectionalSequenceLSTMOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("BidirectionalSequenceLSTM");
 
   auto op_options = operation->mutable_bidirectional_sequence_lstm_options();
diff --git a/compiler/tflchef/tflite/src/Op/BroadcastTo.cpp b/compiler/tflchef/tflite/src/Op/BroadcastTo.cpp
new file mode 100644 (file)
index 0000000..c5f3f08
--- /dev/null
@@ -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 "BroadcastTo.h"
+
+#include "Convert.h"
+#include "FillerHelper.h"
+
+namespace tflchef
+{
+
+void TFliteOpBroadcastTo::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);
+  fill_tensor_to_import(inputs[1], import);
+}
+
+tflchef::Operation *TFliteOpBroadcastTo::build(RecipeChefContext *ctx) const
+{
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
+  operation->set_type("BroadcastTo");
+
+  return operation;
+}
+
+} // namespace tflchef
index 393bb4b..e923c5d 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpCast::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpCast::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpCast::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_CastOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Cast");
 
   auto op_options = operation->mutable_cast_options();
index d3ef3ad..7723689 100644 (file)
@@ -26,10 +26,10 @@ void TFliteOpCeil::filler(const tflite::Operator *, TFliteImport *, tflchef::Mod
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpCeil::build(const tflite::Operator *, TFliteImport *,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpCeil::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Ceil");
 
index 126402f..c431952 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpConcatenation::filler(const tflite::Operator *op, TFliteImport *imp
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpConcatenation::build(const tflite::Operator *op, TFliteImport *import,
-                                                 tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpConcatenation::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_ConcatenationOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Concatenation");
 
   auto op_options = operation->mutable_concatenation_options();
index 57abd46..d3220b6 100644 (file)
@@ -34,14 +34,14 @@ void TFliteOpConv2D::filler(const tflite::Operator *op, TFliteImport *import,
     import->set_tensor_filler(inputs.at(2)); // bias
 }
 
-tflchef::Operation *TFliteOpConv2D::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpConv2D::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_Conv2DOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Conv2D");
 
   auto op_options = operation->mutable_conv2d_options();
index 9f2c49d..ca0df91 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpCos::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpCos::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpCos::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Cos");
 
diff --git a/compiler/tflchef/tflite/src/Op/CumSum.cpp b/compiler/tflchef/tflite/src/Op/CumSum.cpp
new file mode 100644 (file)
index 0000000..1f93bf8
--- /dev/null
@@ -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 "CumSum.h"
+
+#include "Convert.h"
+
+namespace tflchef
+{
+
+void TFliteOpCumsum::filler(const tflite::Operator *op, TFliteImport *import,
+                            tflchef::ModelRecipe *model_recipe) const
+{
+  const auto &inputs = *op->inputs();
+
+  const tflite::Tensor *tensor = import->tensors()->Get(inputs[1]);
+  assert(tensor->type() == tflite::TensorType::TensorType_INT32);
+  const tflite::Buffer *buffer = import->buffers()->Get(tensor->buffer());
+  auto vec = extract_buffer<int32_t>(buffer);
+  import->set_tensor_filler(inputs[1], vec);
+}
+
+tflchef::Operation *TFliteOpCumsum::build(RecipeChefContext *ctx) const
+{
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
+  auto op_params = op->builtin_options_as_CumsumOptions();
+  assert(op_params != nullptr);
+
+  operation->set_type("CumSum");
+  auto op_options = operation->mutable_cumsum_options();
+
+  op_options->set_exclusive(op_params->exclusive());
+  op_options->set_reverse(op_params->reverse());
+
+  return operation;
+}
+
+} // namespace tflchef
index 1a0917e..5832fdf 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpDepthToSpace::filler(const tflite::Operator *op, TFliteImport *impo
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpDepthToSpace::build(const tflite::Operator *op, TFliteImport *import,
-                                                tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpDepthToSpace::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("DepthToSpace");
 
index 5fed335..5f48495 100644 (file)
@@ -34,14 +34,14 @@ void TFliteOpDepthwiseConv2D::filler(const tflite::Operator *op, TFliteImport *i
     import->set_tensor_filler(inputs.at(2)); // bias
 }
 
-tflchef::Operation *TFliteOpDepthwiseConv2D::build(const tflite::Operator *op, TFliteImport *import,
-                                                   tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpDepthwiseConv2D::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_DepthwiseConv2DOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("DepthwiseConv2D");
 
   auto op_options = operation->mutable_depthwiseconv2d_options();
index 436a0db..3a1ec50 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpDequantize::filler(const tflite::Operator *op, TFliteImport *import
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpDequantize::build(const tflite::Operator *, TFliteImport *import,
-                                              tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpDequantize::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Dequantize");
 
index 0fd87dc..c7fecad 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpDiv::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpDiv::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpDiv::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_DivOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Div");
 
   auto op_options = operation->mutable_div_options();
index cb4b61d..5bcc671 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpELU::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpELU::build(const tflite::Operator *, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpELU::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("ELU");
 
index a515862..74565ec 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpEqual::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpEqual::build(const tflite::Operator *op, TFliteImport *import,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpEqual::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Equal");
 
index f715da6..aad09fc 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpExp::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpExp::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpExp::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Exp");
 
index e30e8db..0df174d 100644 (file)
@@ -34,10 +34,10 @@ void TFliteOpExpandDims::filler(const tflite::Operator *op, TFliteImport *import
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpExpandDims::build(const tflite::Operator *op, TFliteImport *import,
-                                              tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpExpandDims::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("ExpandDims");
 
index f44b854..9c6212a 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpFakeQuant::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpFakeQuant::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpFakeQuant::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_FakeQuantOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("FakeQuant");
 
   auto op_options = operation->mutable_fakequant_options();
index 08b695f..5a83ffb 100644 (file)
@@ -33,10 +33,10 @@ void TFliteOpFill::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[0], vec);
 }
 
-tflchef::Operation *TFliteOpFill::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpFill::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
   operation->set_type("Fill");
 
   // FillOptions are empty
index 373c69f..774cb53 100644 (file)
@@ -26,10 +26,10 @@ void TFliteOpFloor::filler(const tflite::Operator *, TFliteImport *, tflchef::Mo
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpFloor::build(const tflite::Operator *, TFliteImport *,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpFloor::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Floor");
 
index 492c694..da37a6b 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpFloorDiv::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpFloorDiv::build(const tflite::Operator *op, TFliteImport *import,
-                                            tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpFloorDiv::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("FloorDiv");
 
index 997d826..ce75745 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpFloorMod::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpFloorMod::build(const tflite::Operator *op, TFliteImport *import,
-                                            tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpFloorMod::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("FloorMod");
 
index bbc749f..7eb8fa1 100644 (file)
@@ -35,14 +35,14 @@ void TFliteOpFullyConnected::filler(const tflite::Operator *op, TFliteImport *im
   }
 }
 
-tflchef::Operation *TFliteOpFullyConnected::build(const tflite::Operator *op, TFliteImport *import,
-                                                  tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpFullyConnected::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_FullyConnectedOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("FullyConnected");
 
   auto op_options = operation->mutable_fullyconnected_options();
index 98da3ec..858296c 100644 (file)
@@ -39,14 +39,14 @@ void TFliteOpGather::filler(const tflite::Operator *op, TFliteImport *import,
   }
 }
 
-tflchef::Operation *TFliteOpGather::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpGather::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_GatherOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Gather");
 
   auto op_options = operation->mutable_gather_options();
index 0ff5a0b..01a9a57 100644 (file)
@@ -38,10 +38,10 @@ void TFliteOpGatherNd::filler(const tflite::Operator *op, TFliteImport *import,
   }
 }
 
-tflchef::Operation *TFliteOpGatherNd::build(const tflite::Operator *op, TFliteImport *import,
-                                            tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpGatherNd::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
   operation->set_type("GatherNd");
 
   return operation;
index 23cee07..69da8cb 100644 (file)
@@ -27,12 +27,12 @@ void TFliteOpGelu::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpGelu::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpGelu::build(RecipeChefContext *ctx) const
 {
-  auto op_params = op->builtin_options_as_GeluOptions();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
-  auto operation = model_recipe->add_operation();
+  auto op_params = op->builtin_options_as_GeluOptions();
 
   operation->set_type("Gelu");
 
index 4e41efb..26840e7 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpGreater::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpGreater::build(const tflite::Operator *op, TFliteImport *import,
-                                           tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpGreater::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Greater");
 
index aead30e..d861889 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpGreaterEqual::filler(const tflite::Operator *op, TFliteImport *impo
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpGreaterEqual::build(const tflite::Operator *op, TFliteImport *import,
-                                                tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpGreaterEqual::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("GreaterEqual");
 
index 2282ff9..75d6cab 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpHardSwish::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpHardSwish::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpHardSwish::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("HardSwish");
 
index 0a89084..f92f6bf 100644 (file)
@@ -27,11 +27,12 @@ void TFliteOpL2Normalize::filler(const tflite::Operator *op, TFliteImport *impor
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpL2Normalize::build(const tflite::Operator *op, TFliteImport *import,
-                                               tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpL2Normalize::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_L2NormOptions();
-  auto operation = model_recipe->add_operation();
 
   operation->set_type("L2Normalize");
 
index 8db4b02..7acd065 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpL2Pool2D::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpL2Pool2D::build(const tflite::Operator *op, TFliteImport *import,
-                                            tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpL2Pool2D::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_Pool2DOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("L2Pool2D");
 
   auto op_options = operation->mutable_l2pool2d_options();
index bf9cb2f..4679e2b 100644 (file)
@@ -27,12 +27,12 @@ void TFliteOpLeakyRelu::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpLeakyRelu::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpLeakyRelu::build(RecipeChefContext *ctx) const
 {
-  auto op_params = op->builtin_options_as_LeakyReluOptions();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
-  auto operation = model_recipe->add_operation();
+  auto op_params = op->builtin_options_as_LeakyReluOptions();
 
   operation->set_type("LeakyRelu");
 
index 0360317..e69db74 100644 (file)
@@ -17,6 +17,7 @@
 #include "Less.h"
 
 #include "Convert.h"
+#include "FillerHelper.h"
 
 namespace tflchef
 {
@@ -24,13 +25,18 @@ namespace tflchef
 void TFliteOpLess::filler(const tflite::Operator *op, TFliteImport *import,
                           tflchef::ModelRecipe *model_recipe) const
 {
-  // Nothing to do with filler
+  const auto &inputs = *op->inputs();
+
+  for (int input : inputs)
+  {
+    fill_tensor_to_import(input, import);
+  }
 }
 
-tflchef::Operation *TFliteOpLess::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpLess::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Less");
 
index b8c42e8..4e059ec 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpLessEqual::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpLessEqual::build(const tflite::Operator *, TFliteImport *,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpLessEqual::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("LessEqual");
 
index 8bebd9e..82302eb 100644 (file)
@@ -27,15 +27,14 @@ void TFliteOpLocalResponseNormalization::filler(const tflite::Operator *op, TFli
   // Nothing to do with filler
 }
 
-tflchef::Operation *
-TFliteOpLocalResponseNormalization::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpLocalResponseNormalization::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_LocalResponseNormalizationOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("LocalResponseNormalization");
 
   auto op_options = operation->mutable_local_response_normalization_options();
index a68dc9a..b3e91da 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpLog::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpLog::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpLog::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Log");
 
index 8f0e1a9..c2bd677 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpLogSoftmax::filler(const tflite::Operator *op, TFliteImport *import
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpLogSoftmax::build(const tflite::Operator *op, TFliteImport *import,
-                                              tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpLogSoftmax::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("LogSoftmax");
 
index 2cc4864..04f76f4 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpLogicalAnd::filler(const tflite::Operator *op, TFliteImport *import
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpLogicalAnd::build(const tflite::Operator *op, TFliteImport *import,
-                                              tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpLogicalAnd::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("LogicalAnd");
 
index ecd5b90..3fbd8a0 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpLogicalNot::filler(const tflite::Operator *op, TFliteImport *import
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpLogicalNot::build(const tflite::Operator *op, TFliteImport *import,
-                                              tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpLogicalNot::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("LogicalNot");
 
index b91f4cf..a773500 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpLogicalOr::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpLogicalOr::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpLogicalOr::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("LogicalOr");
 
index 18b3b5c..ea97f66 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpLogistic::filler(const tflite::Operator *, TFliteImport *,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpLogistic::build(const tflite::Operator *, TFliteImport *,
-                                            tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpLogistic::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Logistic");
 
index ca84c49..5d71818 100644 (file)
@@ -25,10 +25,10 @@ void TFliteOpMatrixDiag::filler(const tflite::Operator *op, TFliteImport *import
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpMatrixDiag::build(const tflite::Operator *op, TFliteImport *import,
-                                              tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpMatrixDiag::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("MatrixDiag");
 
index 97c7de4..d473e8c 100644 (file)
@@ -25,10 +25,10 @@ void TFliteOpMatrixSetDiag::filler(const tflite::Operator *, TFliteImport *,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpMatrixSetDiag::build(const tflite::Operator *, TFliteImport *,
-                                                 tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpMatrixSetDiag::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("MatrixSetDiag");
 
index 1366366..0874389 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpMaxPool2D::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpMaxPool2D::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpMaxPool2D::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_Pool2DOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("MaxPool2D");
 
   auto op_options = operation->mutable_maxpool2d_options();
index 65e4c2c..4def381 100644 (file)
@@ -28,10 +28,10 @@ void TFliteOpMaximum::filler(const tflite::Operator *op, TFliteImport *import,
   fill_two_inputs(op, import);
 }
 
-tflchef::Operation *TFliteOpMaximum::build(const tflite::Operator *op, TFliteImport *import,
-                                           tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpMaximum::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Maximum");
 
index 1c29757..885b1da 100644 (file)
@@ -34,14 +34,14 @@ void TFliteOpMean::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpMean::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpMean::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_ReducerOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Mean");
 
   auto op_options = operation->mutable_mean_options();
index b4d255c..faadf20 100644 (file)
@@ -28,10 +28,10 @@ void TFliteOpMinimum::filler(const tflite::Operator *op, TFliteImport *import,
   fill_two_inputs(op, import);
 }
 
-tflchef::Operation *TFliteOpMinimum::build(const tflite::Operator *op, TFliteImport *import,
-                                           tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpMinimum::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Minimum");
 
index c688552..6c8a389 100644 (file)
@@ -34,10 +34,10 @@ void TFliteOpMirrorPad::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpMirrorPad::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpMirrorPad::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
   operation->set_type("MirrorPad");
 
   auto op_options = operation->mutable_mirrorpad_options();
index 1145ff7..ec6ee1a 100644 (file)
@@ -30,10 +30,10 @@ void TFliteOpMul::filler(const tflite::Operator *op, TFliteImport *import,
   fill_two_inputs(op, import);
 }
 
-tflchef::Operation *TFliteOpMul::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpMul::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Mul");
 
index c691390..c8179a8 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpNeg::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpNeg::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpNeg::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Neg");
 
index 4f096ce..2b3891d 100644 (file)
@@ -42,11 +42,10 @@ void TFliteOpNonMaxSuppressionV4::filler(const tflite::Operator *op, TFliteImpor
   }
 }
 
-tflchef::Operation *TFliteOpNonMaxSuppressionV4::build(const tflite::Operator *op,
-                                                       TFliteImport *import,
-                                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpNonMaxSuppressionV4::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("NonMaxSuppressionV4");
 
index 332cba0..a6817be 100644 (file)
@@ -45,11 +45,10 @@ void TFliteOpNonMaxSuppressionV5::filler(const tflite::Operator *op, TFliteImpor
   }
 }
 
-tflchef::Operation *TFliteOpNonMaxSuppressionV5::build(const tflite::Operator *op,
-                                                       TFliteImport *import,
-                                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpNonMaxSuppressionV5::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("NonMaxSuppressionV5");
 
index c2275db..42494b6 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpNotEqual::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpNotEqual::build(const tflite::Operator *op, TFliteImport *import,
-                                            tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpNotEqual::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("NotEqual");
 
index f26ed3e..fadd7ab 100644 (file)
@@ -67,14 +67,14 @@ void TFliteOpOneHot::filler(const tflite::Operator *op, TFliteImport *import,
   }
 }
 
-tflchef::Operation *TFliteOpOneHot::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpOneHot::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_OneHotOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("OneHot");
 
   auto op_options = operation->mutable_onehot_options();
index 1a1a84b..cf6929f 100644 (file)
@@ -31,10 +31,10 @@ void TFliteOpPRelu::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs.at(1)); // alpha
 }
 
-tflchef::Operation *TFliteOpPRelu::build(const tflite::Operator *op, TFliteImport *import,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpPRelu::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
   operation->set_type("PRelu");
 
   // PReluOptions are empty
index ddf8c7d..5418b81 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpPack::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpPack::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpPack::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_PackOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Pack");
 
   auto op_options = operation->mutable_pack_options();
index 2978e44..f22089a 100644 (file)
@@ -34,10 +34,10 @@ void TFliteOpPad::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpPad::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpPad::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Pad");
 
index a6b657f..78deae8 100644 (file)
@@ -32,10 +32,10 @@ void TFliteOpPadV2::filler(const tflite::Operator *op, TFliteImport *import,
   fill_tensor_to_import(inputs[2], import);
 }
 
-tflchef::Operation *TFliteOpPadV2::build(const tflite::Operator *op, TFliteImport *import,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpPadV2::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("PadV2");
 
index fe8e8ac..f1f35a0 100644 (file)
@@ -26,10 +26,10 @@ void TFliteOpPow::filler(const tflite::Operator *op, TFliteImport *import,
 {
 }
 
-tflchef::Operation *TFliteOpPow::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpPow::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
   operation->set_type("Pow");
 
   // PowOptions are empty
index 0808b9c..9b1e354 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpQuantize::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpQuantize::build(const tflite::Operator *, TFliteImport *import,
-                                            tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpQuantize::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Quantize");
 
index 2958b9c..131ab8b 100644 (file)
@@ -48,10 +48,10 @@ void TFliteOpRange::filler(const tflite::Operator *op, TFliteImport *import,
   }
 }
 
-tflchef::Operation *TFliteOpRange::build(const tflite::Operator *op, TFliteImport *import,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpRange::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Range");
 
index 184c8e4..83a08b6 100644 (file)
@@ -25,10 +25,10 @@ void TFliteOpRank::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpRank::build(const tflite::Operator *, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpRank::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Rank");
 
index e4474b6..d7e6167 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpReLU::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpReLU::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpReLU::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("ReLU");
 
diff --git a/compiler/tflchef/tflite/src/Op/ReLU0To1.cpp b/compiler/tflchef/tflite/src/Op/ReLU0To1.cpp
new file mode 100644 (file)
index 0000000..e5353c3
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ReLU0To1.h"
+
+#include "Convert.h"
+
+namespace tflchef
+{
+
+void TFliteOpReLU0To1::filler(const tflite::Operator *op, TFliteImport *import,
+                              tflchef::ModelRecipe *model_recipe) const
+{
+  // Nothing to do with filler
+}
+
+tflchef::Operation *TFliteOpReLU0To1::build(RecipeChefContext *ctx) const
+{
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
+  operation->set_type("ReLU0To1");
+
+  return operation;
+}
+
+} // namespace tflchef
index 1437188..66b1481 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpReLU6::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpReLU6::build(const tflite::Operator *op, TFliteImport *import,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpReLU6::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("ReLU6");
 
index 4cc8dbd..1d2d66e 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpReLUN1To1::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpReLUN1To1::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpReLUN1To1::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("ReLUN1To1");
 
index e0cc503..b682ffb 100644 (file)
@@ -34,10 +34,10 @@ void TFliteOpReduceAny::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpReduceAny::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpReduceAny::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
   operation->set_type("ReduceAny");
 
   auto op_params = op->builtin_options_as_ReducerOptions();
index 499f585..0fd0701 100644 (file)
@@ -34,14 +34,14 @@ void TFliteOpReduceMax::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpReduceMax::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpReduceMax::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_ReducerOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("ReduceMax");
 
   auto op_options = operation->mutable_reduce_max_options();
index 09e2e13..3c7de06 100644 (file)
@@ -34,14 +34,14 @@ void TFliteOpReduceMin::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpReduceMin::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpReduceMin::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_ReducerOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("ReduceMin");
 
   auto op_options = operation->mutable_reduce_min_options();
index e2d9897..eb71d7e 100644 (file)
@@ -34,10 +34,10 @@ void TFliteOpReduceProd::filler(const tflite::Operator *op, TFliteImport *import
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpReduceProd::build(const tflite::Operator *op, TFliteImport *import,
-                                              tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpReduceProd::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
   operation->set_type("ReduceProd");
 
   auto op_params = op->builtin_options_as_ReducerOptions();
index 0094d5d..0dfecb0 100644 (file)
@@ -34,10 +34,10 @@ void TFliteOpReshape::filler(const tflite::Operator *op, TFliteImport *import,
   }
 }
 
-tflchef::Operation *TFliteOpReshape::build(const tflite::Operator *op, TFliteImport *import,
-                                           tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpReshape::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Reshape");
 
index 0f6db1f..5e5ff8b 100644 (file)
@@ -38,14 +38,14 @@ void TFliteOpResizeBilinear::filler(const tflite::Operator *op, TFliteImport *im
   }
 }
 
-tflchef::Operation *TFliteOpResizeBilinear::build(const tflite::Operator *op, TFliteImport *import,
-                                                  tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpResizeBilinear::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_ResizeBilinearOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("ResizeBilinear");
 
   auto op_options = operation->mutable_resize_bilinear_options();
index f3dd8fe..316a215 100644 (file)
@@ -38,15 +38,14 @@ void TFliteOpResizeNearestNeighbor::filler(const tflite::Operator *op, TFliteImp
   }
 }
 
-tflchef::Operation *TFliteOpResizeNearestNeighbor::build(const tflite::Operator *op,
-                                                         TFliteImport *import,
-                                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpResizeNearestNeighbor::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_ResizeNearestNeighborOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("ResizeNearestNeighbor");
 
   auto op_options = operation->mutable_resize_nearest_neighbor_options();
index 6ef6c23..8fd8ae0 100644 (file)
@@ -31,10 +31,10 @@ void TFliteOpReverseSequence::filler(const tflite::Operator *op, TFliteImport *i
   fill_tensor_to_import(inputs[1], import);
 }
 
-tflchef::Operation *TFliteOpReverseSequence::build(const tflite::Operator *op, TFliteImport *,
-                                                   tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpReverseSequence::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("ReverseSequence");
 
index c59d975..ce7901f 100644 (file)
@@ -31,10 +31,10 @@ void TFliteOpReverseV2::filler(const tflite::Operator *op, TFliteImport *import,
   fill_tensor_to_import(inputs[1], import);
 }
 
-tflchef::Operation *TFliteOpReverseV2::build(const tflite::Operator *, TFliteImport *,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpReverseV2::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("ReverseV2");
 
index c3f6bf6..537975d 100644 (file)
@@ -24,10 +24,10 @@ void TFliteOpRound::filler(const tflite::Operator *, TFliteImport *, tflchef::Mo
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpRound::build(const tflite::Operator *, TFliteImport *,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpRound::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Round");
 
index 1639214..19b9614 100644 (file)
@@ -26,10 +26,10 @@ void TFliteOpRsqrt::filler(const tflite::Operator *, TFliteImport *, tflchef::Mo
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpRsqrt::build(const tflite::Operator *, TFliteImport *,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpRsqrt::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Rsqrt");
 
index 015f968..8518f73 100644 (file)
@@ -37,14 +37,14 @@ void TFliteOpSVDF::filler(const tflite::Operator *op, TFliteImport *import,
     import->set_tensor_filler(inputs.at(3));
 }
 
-tflchef::Operation *TFliteOpSVDF::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSVDF::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   const auto op_params = op->builtin_options_as_SVDFOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("SVDF");
 
   auto op_options = operation->mutable_svdf_options();
index ec09a69..4ab3139 100644 (file)
@@ -32,10 +32,10 @@ void TFliteOpScatterNd::filler(const tflite::Operator *op, TFliteImport *import,
   fill_tensor_to_import(inputs[2], import);
 }
 
-tflchef::Operation *TFliteOpScatterNd::build(const tflite::Operator *, TFliteImport *,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpScatterNd::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("ScatterNd");
 
index bc45a94..dd0eab2 100644 (file)
@@ -31,10 +31,10 @@ void TFliteOpSegmentSum::filler(const tflite::Operator *op, TFliteImport *import
   fill_tensor_to_import(inputs[1], import);
 }
 
-tflchef::Operation *TFliteOpSegmentSum::build(const tflite::Operator *op, TFliteImport *import,
-                                              tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSegmentSum::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("SegmentSum");
 
index 741ffb8..c7aca80 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpSelect::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpSelect::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSelect::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Select");
 
index 0ddabb4..8637324 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpSelectV2::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpSelectV2::build(const tflite::Operator *op, TFliteImport *import,
-                                            tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSelectV2::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("SelectV2");
 
index d6e490d..6ec3dfa 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpShape::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpShape::build(const tflite::Operator *op, TFliteImport *import,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpShape::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
   operation->set_type("Shape");
 
   auto op_params = op->builtin_options_as_ShapeOptions();
index 8c063f4..f963599 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpSin::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpSin::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSin::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Sin");
 
index f0c44da..7e099e5 100644 (file)
@@ -37,10 +37,10 @@ void TFliteOpSlice::filler(const tflite::Operator *op, TFliteImport *import,
   }
 }
 
-tflchef::Operation *TFliteOpSlice::build(const tflite::Operator *op, TFliteImport *import,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSlice::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Slice");
 
index 5b5c94f..77ac2cc 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpSoftmax::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpSoftmax::build(const tflite::Operator *op, TFliteImport *import,
-                                           tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSoftmax::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_SoftmaxOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Softmax");
 
   auto op_options = operation->mutable_softmax_options();
index 9de0775..da90221 100644 (file)
@@ -40,10 +40,10 @@ void TFliteOpSpaceToBatchND::filler(const tflite::Operator *op, TFliteImport *im
   import->set_tensor_filler(inputs[2], vec);
 }
 
-tflchef::Operation *TFliteOpSpaceToBatchND::build(const tflite::Operator *op, TFliteImport *import,
-                                                  tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSpaceToBatchND::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("SpaceToBatchND");
 
index e5718b5..2f1c118 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpSpaceToDepth::filler(const tflite::Operator *op, TFliteImport *impo
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpSpaceToDepth::build(const tflite::Operator *op, TFliteImport *import,
-                                                tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSpaceToDepth::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("SpaceToDepth");
 
index 9e4f0a0..a1290f6 100644 (file)
@@ -34,14 +34,14 @@ void TFliteOpSparseToDense::filler(const tflite::Operator *op, TFliteImport *imp
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpSparseToDense::build(const tflite::Operator *op, TFliteImport *import,
-                                                 tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSparseToDense::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_SparseToDenseOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("SparseToDense");
 
   auto op_options = operation->mutable_sparse_to_dense_options();
index 49f9aa2..492f42c 100644 (file)
@@ -35,10 +35,10 @@ void TFliteOpSplit::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[0], vec);
 }
 
-tflchef::Operation *TFliteOpSplit::build(const tflite::Operator *op, TFliteImport *import,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSplit::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Split");
 
index 18035e6..b91436f 100644 (file)
@@ -37,10 +37,10 @@ void TFliteOpSplitV::filler(const tflite::Operator *op, TFliteImport *import,
   }
 }
 
-tflchef::Operation *TFliteOpSplitV::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSplitV::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("SplitV");
 
index dd6bfca..148a763 100644 (file)
@@ -40,10 +40,10 @@ void TFliteOpSqrt::filler(const tflite::Operator *op, TFliteImport *import,
   }
 }
 
-tflchef::Operation *TFliteOpSqrt::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSqrt::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Sqrt");
 
index d380328..953872c 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpSquare::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpSquare::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSquare::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Square");
 
index 1ee536e..61ea9bf 100644 (file)
@@ -27,11 +27,10 @@ void TFliteOpSquaredDifference::filler(const tflite::Operator *op, TFliteImport
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpSquaredDifference::build(const tflite::Operator *op,
-                                                     TFliteImport *import,
-                                                     tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSquaredDifference::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("SquaredDifference");
 
index 7983fc6..8cbc65e 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpSqueeze::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpSqueeze::build(const tflite::Operator *op, TFliteImport *import,
-                                           tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSqueeze::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_SqueezeOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Squeeze");
 
   auto op_options = operation->mutable_squeeze_options();
index c770236..b142f43 100644 (file)
@@ -37,14 +37,14 @@ void TFliteOpStridedSlice::filler(const tflite::Operator *op, TFliteImport *impo
   }
 }
 
-tflchef::Operation *TFliteOpStridedSlice::build(const tflite::Operator *op, TFliteImport *import,
-                                                tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpStridedSlice::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_StridedSliceOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("StridedSlice");
 
   auto op_options = operation->mutable_strided_slice_options();
index 584be0a..0b38c93 100644 (file)
@@ -30,14 +30,14 @@ void TFliteOpSub::filler(const tflite::Operator *op, TFliteImport *import,
   fill_two_inputs(op, import);
 }
 
-tflchef::Operation *TFliteOpSub::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSub::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_SubOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Sub");
 
   auto op_options = operation->mutable_sub_options();
index 9f3133e..c0a9355 100644 (file)
@@ -34,14 +34,14 @@ void TFliteOpSum::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpSum::build(const tflite::Operator *op, TFliteImport *import,
-                                       tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpSum::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_ReducerOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Sum");
 
   auto op_options = operation->mutable_sum_options();
index cab8ca4..87c3355 100644 (file)
@@ -26,10 +26,10 @@ void TFliteOpTanh::filler(const tflite::Operator *, TFliteImport *, tflchef::Mod
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpTanh::build(const tflite::Operator *, TFliteImport *,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpTanh::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Tanh");
 
index 14e6513..02fc268 100644 (file)
@@ -35,10 +35,10 @@ void TFliteOpTile::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpTile::build(const tflite::Operator *op, TFliteImport *import,
-                                        tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpTile::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Tile");
 
index 461456a..2aa73d4 100644 (file)
@@ -35,10 +35,10 @@ void TFliteOpTopKV2::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpTopKV2::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpTopKV2::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("TopKV2");
 
index a997bb0..5ab7def 100644 (file)
@@ -33,10 +33,10 @@ void TFliteOpTranspose::filler(const tflite::Operator *op, TFliteImport *import,
   import->set_tensor_filler(inputs[1], vec);
 }
 
-tflchef::Operation *TFliteOpTranspose::build(const tflite::Operator *op, TFliteImport *import,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpTranspose::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Transpose");
 
index 875ccb5..281ddf5 100644 (file)
@@ -41,15 +41,15 @@ void TFliteOpTransposeConv::filler(const tflite::Operator *op, TFliteImport *imp
   import->set_tensor_filler(inputs[1]);
 }
 
-tflchef::Operation *TFliteOpTransposeConv::build(const tflite::Operator *op, TFliteImport *import,
-                                                 tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpTransposeConv::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_TransposeConvOptions();
 
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("TransposeConv");
 
   auto op_options = operation->mutable_transpose_conv_options();
index b2bc1ac..eb7c733 100644 (file)
@@ -41,15 +41,14 @@ void TFliteOpUnidirectionalSequenceLSTM::filler(const tflite::Operator *op, TFli
   }
 }
 
-tflchef::Operation *
-TFliteOpUnidirectionalSequenceLSTM::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpUnidirectionalSequenceLSTM::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_UnidirectionalSequenceLSTMOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("UnidirectionalSequenceLSTM");
 
   auto op_options = operation->mutable_unidirectional_sequence_lstm_options();
index e3f77f4..3729de4 100644 (file)
@@ -27,14 +27,14 @@ void TFliteOpUnique::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpUnique::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpUnique::build(RecipeChefContext *ctx) const
 {
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
   auto op_params = op->builtin_options_as_UniqueOptions();
   assert(op_params != nullptr);
 
-  auto operation = model_recipe->add_operation();
-
   operation->set_type("Unique");
 
   auto op_options = operation->mutable_unique_options();
index a51ef84..3dfecba 100644 (file)
@@ -25,10 +25,10 @@ void TFliteOpUnpack::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with filler
 }
 
-tflchef::Operation *TFliteOpUnpack::build(const tflite::Operator *op, TFliteImport *import,
-                                          tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpUnpack::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
 
   operation->set_type("Unpack");
 
index e42de37..2434b20 100644 (file)
@@ -24,10 +24,10 @@ void TFliteOpWhere::filler(const tflite::Operator *, TFliteImport *, tflchef::Mo
   // Nothing to do with fillers here
 }
 
-tflchef::Operation *TFliteOpWhere::build(const tflite::Operator *, TFliteImport *,
-                                         tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpWhere::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
   operation->set_type("Where");
 
   return operation;
diff --git a/compiler/tflchef/tflite/src/Op/While.cpp b/compiler/tflchef/tflite/src/Op/While.cpp
new file mode 100644 (file)
index 0000000..96c00eb
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "While.h"
+
+#include "Convert.h"
+#include "FillerHelper.h"
+
+namespace tflchef
+{
+
+void TFliteOpWhile::filler(const tflite::Operator *op, TFliteImport *import,
+                           tflchef::ModelRecipe *model_recipe) const
+{
+  const auto &inputs = *op->inputs();
+
+  for (int input : inputs)
+  {
+    fill_tensor_to_import(input, import);
+  }
+}
+
+tflchef::Operation *TFliteOpWhile::build(RecipeChefContext *ctx) const
+{
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
+
+  auto op_params = op->builtin_options_as_WhileOptions();
+  assert(op_params != nullptr);
+
+  operation->set_type("While");
+
+  auto op_options = operation->mutable_while_options();
+
+  op_options->set_body_subgraph_index(op_params->body_subgraph_index());
+  op_options->set_cond_subgraph_index(op_params->cond_subgraph_index());
+
+  return operation;
+}
+
+} // namespace tflchef
index a56b6bd..b927900 100644 (file)
@@ -27,10 +27,10 @@ void TFliteOpZerosLike::filler(const tflite::Operator *op, TFliteImport *import,
   // Nothing to do with fillers here
 }
 
-tflchef::Operation *TFliteOpZerosLike::build(const tflite::Operator *op, TFliteImport *,
-                                             tflchef::ModelRecipe *model_recipe) const
+tflchef::Operation *TFliteOpZerosLike::build(RecipeChefContext *ctx) const
 {
-  auto operation = model_recipe->add_operation();
+  tflchef::Operation *operation = ctx->chefop;
+  const tflite::Operator *op = ctx->tflop;
   operation->set_type("ZerosLike");
 
   auto op_options = operation->mutable_zeros_like_options();
index d99b0d5..45333a3 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpAbs : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 49d945f..bcc279d 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpAdd : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 4387aa0..ec88172 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpAddN : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 30068ec..9e9f3c9 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpArgMax : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 83c643c..03f1e3e 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpArgMin : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index f9e9fb2..63f6fc8 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpAveragePool2D : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 6eb4c6e..af12f46 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpBatchMatMul : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index ae2114c..5ec22c7 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpBatchToSpaceND : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 333f542..353045e 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpBidirectionalSequenceLSTM : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
diff --git a/compiler/tflchef/tflite/src/Op/include/BroadcastTo.h b/compiler/tflchef/tflite/src/Op/include/BroadcastTo.h
new file mode 100644 (file)
index 0000000..952290e
--- /dev/null
@@ -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 __TFLITE_OP_BROADCAST_TO_H__
+#define __TFLITE_OP_BROADCAST_TO_H__
+
+#include "TFliteOpChef.h"
+
+namespace tflchef
+{
+
+/**
+ * @brief tflchef operator builder for BroadcastTo
+ */
+class TFliteOpBroadcastTo : public TFliteOpChef
+{
+public:
+  void filler(const tflite::Operator *op, TFliteImport *import,
+              tflchef::ModelRecipe *mode_recipe) const override;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
+};
+
+} // namespace tflchef
+
+#endif // __TFLITE_OP_BROADCAST_H__
index 29c126c..8a77609 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpCast : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 44df207..5cfdfce 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpCeil : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 4a7ea57..febdbf1 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpConcatenation : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 0216e9c..af2580e 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpConv2D : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 8f3dbe3..dd84479 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpCos : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
diff --git a/compiler/tflchef/tflite/src/Op/include/CumSum.h b/compiler/tflchef/tflite/src/Op/include/CumSum.h
new file mode 100644 (file)
index 0000000..7680aae
--- /dev/null
@@ -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 __TFLITE_OP_CUMSUM_H__
+#define __TFLITE_OP_CUMSUM_H__
+
+#include "TFliteOpChef.h"
+
+namespace tflchef
+{
+
+/**
+ * @brief tflchef operator builder for CumSum
+ */
+class TFliteOpCumsum : public TFliteOpChef
+{
+public:
+  void filler(const tflite::Operator *op, TFliteImport *import,
+              tflchef::ModelRecipe *model_recipe) const override;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
+};
+
+} // namespace tflchef
+
+#endif // __TFLITE_OP_CUMSUM_H__
index b5852ac..435fe04 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpDepthToSpace : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index c172536..abdde29 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpDepthwiseConv2D : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index df1c7bb..a2d0018 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpDequantize : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 254a4cd..9ac9904 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpDiv : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 490c9fd..a3db9dc 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpELU : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index fd4b400..909920e 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpEqual : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 5ff3ddc..b31b9f2 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpExp : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index e2f3e4e..c174fe7 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpExpandDims : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index f36e615..289dfb8 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpFakeQuant : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 4f46f62..9441b37 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpFill : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index f0f8ef3..4f0869b 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpFloor : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 5d049a6..62ed8f1 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpFloorDiv : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index f36dfe8..b4f4272 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpFloorMod : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 8fbe1f3..c0de426 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpFullyConnected : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index e01276b..68111b8 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpGather : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 112f23d..e8d4150 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpGatherNd : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 0c51a51..05a45f1 100644 (file)
@@ -30,8 +30,7 @@ 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 3ab2d1a..3a08c20 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpGreater : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 96b0af7..4e71d66 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpGreaterEqual : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index d9b5a53..d9b0411 100644 (file)
@@ -30,8 +30,7 @@ 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index a73eae6..405c670 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpL2Normalize : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 0463534..b1b3a24 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpL2Pool2D : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 28e63e0..3d90672 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpLeakyRelu : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 1316cb6..14d0303 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpLess : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 81c710f..cea744d 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpLessEqual : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index c0eb3f2..a1b8d18 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpLocalResponseNormalization : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 9d17e2f..4d08695 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpLog : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index efd81f3..aa5b9dd 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpLogSoftmax : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 1f7a964..6db5c1f 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpLogicalAnd : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index b75d335..0f0552a 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpLogicalNot : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 5331a0d..02efd6e 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpLogicalOr : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index a75bf49..839f498 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpLogistic : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 4074f2c..f9d8452 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpMatrixDiag : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 0e7ec7f..8339177 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpMatrixSetDiag : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 36533f8..951331e 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpMaxPool2D : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index acafec3..73ba060 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpMaximum : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 532c40c..7e7d820 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpMean : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 5db5b79..f0f1219 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpMinimum : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index c9acdd4..43a615b 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpMirrorPad : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index fd009d2..ecdf5da 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpMul : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index c77ab7e..96eaa76 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpNeg : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 114a2ad..0aef56d 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpNonMaxSuppressionV4 : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index c948043..228f8dd 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpNonMaxSuppressionV5 : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index b1febdc..7326111 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpNotEqual : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 50bbed0..d060c40 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpOneHot : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index b35c6e7..385a123 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpPRelu : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 7779f64..d377739 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpPack : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 99998d4..4d90740 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpPad : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 3aa474b..61d755f 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpPadV2 : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 20e8473..1e6403d 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpPow : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 256ed5a..9058621 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpQuantize : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index ad10dc5..705c35a 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpRange : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 003d9d3..5fbbe87 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpRank : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index be10902..93d2a0a 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpReLU : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
diff --git a/compiler/tflchef/tflite/src/Op/include/ReLU0To1.h b/compiler/tflchef/tflite/src/Op/include/ReLU0To1.h
new file mode 100644 (file)
index 0000000..6543f32
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_RELU_0_TO_1_H__
+#define __TFLITE_OP_RELU_0_TO_1_H__
+
+#include "TFliteOpChef.h"
+
+namespace tflchef
+{
+
+/**
+ * @brief tflchef operator builder for RELU_0_TO_1
+ */
+class TFliteOpReLU0To1 : public TFliteOpChef
+{
+public:
+  void filler(const tflite::Operator *op, TFliteImport *import,
+              tflchef::ModelRecipe *model_recipe) const override;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
+};
+
+} // namespace tflchef
+
+#endif // __TFLITE_OP_RELU_0_TO_1_H__
index 64ddb6a..1cc15b4 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpReLU6 : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 0767006..cbac399 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpReLUN1To1 : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index dd5e361..b6a21f0 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpReduceAny : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 8e65cf4..cf70850 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpReduceMax : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 88cba6f..66c9df2 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpReduceMin : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index e776684..8869fbb 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpReduceProd : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index be9fdac..d7b8bfa 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpReshape : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 98c49c5..4417d5e 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpResizeBilinear : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 5090bb9..8588301 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpResizeNearestNeighbor : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 8c8c811..469f460 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpReverseSequence : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 6a8a75e..22cc2fe 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpReverseV2 : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index df0da3f..01c43a9 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpRound : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 5d68344..c2246c7 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpRsqrt : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index a59ca54..35b4c21 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSVDF : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 76362d7..616a80b 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpScatterNd : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index d20e63b..33d0182 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSegmentSum : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index bf8e57d..a6cd79a 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSelect : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index ff03341..5278a98 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSelectV2 : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index ebe1bef..6dbe3b8 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpShape : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 51eabce..7b97067 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSin : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 6ca6724..31327a9 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSlice : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index cf168bd..1e2162c 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSoftmax : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 9d7bc44..1900bea 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSpaceToBatchND : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 784ad94..72f5973 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSpaceToDepth : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 5ffe478..351de34 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSparseToDense : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index af247a1..6ea60bb 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSplit : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 3f715b5..b1748f6 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSplitV : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 9f0ad04..13dc43e 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSqrt : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 9c008fe..69a4bb0 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSquare : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 58c2ed4..743d112 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSquaredDifference : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index b6c89f7..ea8f553 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSqueeze : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 98054b9..de9181e 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpStridedSlice : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 2168e5e..b78744a 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSub : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 38eeb08..d1537d8 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpSum : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 7339e41..480a387 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpTanh : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 640f52a..9635bb4 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpTile : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index b2b74cc..6d94369 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpTopKV2 : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index f0d944b..89501ec 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpTranspose : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index c79cdab..4ad9bf9 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpTransposeConv : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index cc4e5fb..912f808 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpUnidirectionalSequenceLSTM : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index fae037c..fd34630 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpUnique : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 1036bdc..f16a7ee 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpUnpack : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 00cdc4b..e1c78d1 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpWhere : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
diff --git a/compiler/tflchef/tflite/src/Op/include/While.h b/compiler/tflchef/tflite/src/Op/include/While.h
new file mode 100644 (file)
index 0000000..532f023
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_WHILE_H__
+#define __TFLITE_OP_WHILE_H__
+
+#include "TFliteOpChef.h"
+
+namespace tflchef
+{
+
+/**
+ * @brief tflchef operator builder for While
+ */
+class TFliteOpWhile : public TFliteOpChef
+{
+public:
+  void filler(const tflite::Operator *op, TFliteImport *import,
+              tflchef::ModelRecipe *model_recipe) const override;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
+};
+
+} // namespace tflchef
+
+#endif // __TFLITE_OP_WHILE_H__
index 163c1fa..ec1dc48 100644 (file)
@@ -30,8 +30,7 @@ class TFliteOpZerosLike : 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;
+  tflchef::Operation *build(RecipeChefContext *ctx) const override;
 };
 
 } // namespace tflchef
index 2203f59..116b03c 100644 (file)
@@ -74,254 +74,276 @@ std::unique_ptr<ModelRecipe> generate_recipe(const tflite::Model *model)
 
   TFliteImport tflite_import(model);
 
-  assert(tflite_import.num_subgraph() == 1);
-  tflite_import.select_sub_graph(0);
+  auto const num_subgraph = tflite_import.num_subgraph();
 
-  auto tensors = tflite_import.tensors();
-  auto buffers = tflite_import.buffers();
-  auto operators = tflite_import.operators();
-
-  // operand fillers for adding all operators
-  for (uint32_t i = 0; i < operators->Length(); ++i)
-  {
-    const auto *op = operators->Get(i);
-    tflite::BuiltinOperator builtincode = tflite_import.builtin_code(op);
-
-    if (const auto *graph_builder = TFliteOpRegistry::get().lookup(builtincode))
-    {
-      graph_builder->filler(op, &tflite_import, model_recipe.get());
-    }
-    else
-    {
-      std::string opcodename = tflite_import.opcode_name(op);
-      throw std::runtime_error{"Not supported: " + opcodename};
-    }
-  }
-
-  // add all operands(tensors)
-  for (uint32_t i = 0; i < tensors->Length(); ++i)
+  RecipeChefContext ctx;
+  for (uint32_t n = 0; n < num_subgraph; ++n)
   {
-    auto tensor = tensors->Get(i);
-
-    // check buffer
-    if (tensor->buffer() >= buffers->size())
-      throw std::runtime_error{"file load failed"};
+    tflite_import.select_sub_graph(n);
 
-    ::tflchef::Operand *operand = model_recipe->add_operand();
+    auto tensors = tflite_import.tensors();
+    auto buffers = tflite_import.buffers();
+    auto operators = tflite_import.operators();
 
-    operand->set_name(mio::tflite::tensor_name(tensor));
-    operand->set_type(as_tflchef_type(tensor->type()));
-    operand->set_is_variable(tensor->is_variable());
+    tflchef::Graph *graph = nullptr;
+    if (n != 0)
+      graph = model_recipe->add_graph();
 
-    if (tensor->shape())
+    // operand fillers for adding all operators
+    for (uint32_t i = 0; i < operators->size(); ++i)
     {
-      std::vector<int32_t> dims = as_index_vector(tensor->shape());
-      ::tflchef::TensorShape *shape = operand->mutable_shape();
-      for (auto dim : dims)
-      {
-        shape->add_dim(dim);
-      }
-    }
+      const auto *op = operators->Get(i);
+      tflite::BuiltinOperator builtincode = tflite_import.builtin_code(op);
 
-    // filler for weights, bias and so on
-    std::vector<int32_t> expvalues;
-    std::vector<float> expfvalues;
-    if (tflite_import.get_tensor_filler(i))
-    {
-      tflchef::TensorFiller *filler = operand->mutable_filler();
-      // Note: it is OK to use random weights for functionality validation
-      filler->set_tag("gaussian");
-      filler->add_arg("0.0"); // average
-      filler->add_arg("0.1"); // standard deviation
-    }
-    else if (tflite_import.get_tensor_filler(i, expvalues))
-    {
-      tflchef::TensorFiller *filler = operand->mutable_filler();
-      filler->set_tag("explicit");
-      for (auto value : expvalues)
+      if (const auto *graph_builder = TFliteOpRegistry::get().lookup(builtincode))
       {
-        std::ostringstream ss;
-        ss << value;
-        filler->add_arg(ss.str());
+        graph_builder->filler(op, &tflite_import, model_recipe.get());
       }
-    }
-    else if (tflite_import.get_tensor_filler(i, expfvalues))
-    {
-      tflchef::TensorFiller *filler = operand->mutable_filler();
-      filler->set_tag("explicit");
-      for (auto value : expfvalues)
+      else
       {
-        std::ostringstream ss;
-        ss << value;
-        filler->add_arg(ss.str());
+        std::string opcodename = tflite_import.opcode_name(op);
+        throw std::runtime_error{"Not supported: " + opcodename};
       }
     }
 
-    auto quant = tensor->quantization();
-    if (quant != nullptr)
+    // add all operands(tensors)
+    for (uint32_t i = 0; i < tensors->size(); ++i)
     {
-      // Note: Calling 'operand->mutable_quant()' will create empty 'quant' node
-      // in the recipe file. We want this only when valid parameter exist.
-      if (quant->min() != nullptr && quant->min()->size() > 0)
+      auto tensor = tensors->Get(i);
+
+      // check buffer
+      if (tensor->buffer() >= buffers->size())
+        throw std::runtime_error{"file load failed"};
+
+      ::tflchef::Operand *operand;
+      if (graph != nullptr)
+        operand = graph->add_operand();
+      else
+        operand = model_recipe->add_operand();
+      operand->set_name(mio::tflite::tensor_name(tensor));
+      operand->set_type(as_tflchef_type(tensor->type()));
+      operand->set_is_variable(tensor->is_variable());
+
+      if (tensor->shape())
       {
-        tflchef::TensorQuantization *chef_quant = operand->mutable_quant();
-        for (uint32_t idx = 0; idx < quant->min()->size(); ++idx)
-          chef_quant->add_min(quant->min()->Get(idx));
+        std::vector<int32_t> dims = as_index_vector(tensor->shape());
+        ::tflchef::TensorShape *shape = operand->mutable_shape();
+        for (auto dim : dims)
+        {
+          shape->add_dim(dim);
+        }
       }
-      if (quant->max() != nullptr && quant->max()->size() > 0)
+
+      // filler for weights, bias and so on
+      std::vector<int32_t> expvalues;
+      std::vector<float> expfvalues;
+      if (tflite_import.get_tensor_filler(i))
       {
-        tflchef::TensorQuantization *chef_quant = operand->mutable_quant();
-        for (uint32_t idx = 0; idx < quant->max()->size(); idx++)
-          chef_quant->add_max(quant->max()->Get(idx));
+        tflchef::TensorFiller *filler = operand->mutable_filler();
+        // Note: it is OK to use random weights for functionality validation
+        filler->set_tag("gaussian");
+        filler->add_arg("0.0"); // average
+        filler->add_arg("0.1"); // standard deviation
       }
-      if (quant->scale() != nullptr && quant->scale()->size() > 0)
+      else if (tflite_import.get_tensor_filler(i, expvalues))
       {
-        tflchef::TensorQuantization *chef_quant = operand->mutable_quant();
-        for (uint32_t idx = 0; idx < quant->scale()->size(); ++idx)
-          chef_quant->add_scale(quant->scale()->Get(idx));
+        tflchef::TensorFiller *filler = operand->mutable_filler();
+        filler->set_tag("explicit");
+        for (auto value : expvalues)
+        {
+          std::ostringstream ss;
+          ss << value;
+          filler->add_arg(ss.str());
+        }
       }
-      if (quant->zero_point() != nullptr && quant->zero_point()->size() > 0)
+      else if (tflite_import.get_tensor_filler(i, expfvalues))
       {
-        tflchef::TensorQuantization *chef_quant = operand->mutable_quant();
-        for (uint32_t idx = 0; idx < quant->zero_point()->size(); ++idx)
-          chef_quant->add_zero_point(quant->zero_point()->Get(idx));
+        tflchef::TensorFiller *filler = operand->mutable_filler();
+        filler->set_tag("explicit");
+        for (auto value : expfvalues)
+        {
+          std::ostringstream ss;
+          ss << value;
+          filler->add_arg(ss.str());
+        }
       }
-      tflchef::TensorQuantization *chef_quant = operand->mutable_quant();
-      chef_quant->set_quantized_dimension(quant->quantized_dimension());
-    }
 
-    auto sparsity = tensor->sparsity();
-    if (sparsity != nullptr)
-    {
-      tflchef::TensorSparsity *chef_sparsity = operand->mutable_sparsity();
-      // traversal_order
-      auto chef_traversal_order = chef_sparsity->mutable_traversal_order();
-      for (const auto &to : *(sparsity->traversal_order()))
+      auto quant = tensor->quantization();
+      if (quant != nullptr)
       {
-        chef_traversal_order->add_dim(to);
-      }
-      // block_map
-      auto chef_block_map = chef_sparsity->mutable_block_map();
-      for (const auto &bm : *(sparsity->block_map()))
-      {
-        chef_block_map->add_dim(bm);
+        // Note: Calling 'operand->mutable_quant()' will create empty 'quant' node
+        // in the recipe file. We want this only when valid parameter exist.
+        if (quant->min() != nullptr && quant->min()->size() > 0)
+        {
+          tflchef::TensorQuantization *chef_quant = operand->mutable_quant();
+          for (uint32_t idx = 0; idx < quant->min()->size(); ++idx)
+            chef_quant->add_min(quant->min()->Get(idx));
+        }
+        if (quant->max() != nullptr && quant->max()->size() > 0)
+        {
+          tflchef::TensorQuantization *chef_quant = operand->mutable_quant();
+          for (uint32_t idx = 0; idx < quant->max()->size(); idx++)
+            chef_quant->add_max(quant->max()->Get(idx));
+        }
+        if (quant->scale() != nullptr && quant->scale()->size() > 0)
+        {
+          tflchef::TensorQuantization *chef_quant = operand->mutable_quant();
+          for (uint32_t idx = 0; idx < quant->scale()->size(); ++idx)
+            chef_quant->add_scale(quant->scale()->Get(idx));
+        }
+        if (quant->zero_point() != nullptr && quant->zero_point()->size() > 0)
+        {
+          tflchef::TensorQuantization *chef_quant = operand->mutable_quant();
+          for (uint32_t idx = 0; idx < quant->zero_point()->size(); ++idx)
+            chef_quant->add_zero_point(quant->zero_point()->Get(idx));
+        }
+        tflchef::TensorQuantization *chef_quant = operand->mutable_quant();
+        chef_quant->set_quantized_dimension(quant->quantized_dimension());
       }
-      // dim_metadata
-      for (const auto &dm : *(sparsity->dim_metadata()))
+
+      auto sparsity = tensor->sparsity();
+      if (sparsity != nullptr)
       {
-        auto chef_dm = chef_sparsity->add_dim_metadata();
-        // format
-        chef_dm->set_format(as_tflchef_sparse_dim_type(dm->format()));
-        // dense_size
-        chef_dm->set_dense_size(dm->dense_size());
-        // array_segments
-        auto chef_array_segments = chef_dm->mutable_array_segments();
-        switch (dm->array_segments_type())
+        tflchef::TensorSparsity *chef_sparsity = operand->mutable_sparsity();
+        // traversal_order
+        auto chef_traversal_order = chef_sparsity->mutable_traversal_order();
+        for (const auto &to : *(sparsity->traversal_order()))
+        {
+          chef_traversal_order->add_dim(to);
+        }
+        // block_map
+        auto chef_block_map = chef_sparsity->mutable_block_map();
+        for (const auto &bm : *(sparsity->block_map()))
         {
-          case tflite::SparseIndexVector_NONE:
-            // DO NOTHING
-            break;
-          case tflite::SparseIndexVector_Int32Vector:
-            for (const auto &as : *(dm->array_segments_as_Int32Vector()->values()))
-            {
-              chef_array_segments->add_dim(as);
-            }
-            break;
-          case tflite::SparseIndexVector_Uint16Vector:
-            for (const auto &as : *(dm->array_segments_as_Uint16Vector()->values()))
-            {
-              chef_array_segments->add_dim(as);
-            }
-            break;
-          case tflite::SparseIndexVector_Uint8Vector:
-            for (const auto &as : *(dm->array_segments_as_Uint8Vector()->values()))
-            {
-              chef_array_segments->add_dim(as);
-            }
-            break;
-          default:
-            throw std::runtime_error("unsupported sparse index vector type");
+          chef_block_map->add_dim(bm);
         }
-        // array_indices
-        auto chef_array_indices = chef_dm->mutable_array_indices();
-        switch (dm->array_indices_type())
+        // dim_metadata
+        for (const auto &dm : *(sparsity->dim_metadata()))
         {
-          case tflite::SparseIndexVector_NONE:
-            // DO NOTHING
-            break;
-          case tflite::SparseIndexVector_Int32Vector:
-            for (const auto &as : *(dm->array_indices_as_Int32Vector()->values()))
-            {
-              chef_array_indices->add_dim(as);
-            }
-            break;
-          case tflite::SparseIndexVector_Uint16Vector:
-            for (const auto &as : *(dm->array_indices_as_Uint16Vector()->values()))
-            {
-              chef_array_indices->add_dim(as);
-            }
-            break;
-          case tflite::SparseIndexVector_Uint8Vector:
-            for (const auto &as : *(dm->array_indices_as_Uint8Vector()->values()))
-            {
-              chef_array_indices->add_dim(as);
-            }
-            break;
-          default:
-            throw std::runtime_error("unsupported sparse index vector type");
+          auto chef_dm = chef_sparsity->add_dim_metadata();
+          // format
+          chef_dm->set_format(as_tflchef_sparse_dim_type(dm->format()));
+          // dense_size
+          chef_dm->set_dense_size(dm->dense_size());
+          // array_segments
+          auto chef_array_segments = chef_dm->mutable_array_segments();
+          switch (dm->array_segments_type())
+          {
+            case tflite::SparseIndexVector_NONE:
+              // DO NOTHING
+              break;
+            case tflite::SparseIndexVector_Int32Vector:
+              for (const auto &as : *(dm->array_segments_as_Int32Vector()->values()))
+              {
+                chef_array_segments->add_dim(as);
+              }
+              break;
+            case tflite::SparseIndexVector_Uint16Vector:
+              for (const auto &as : *(dm->array_segments_as_Uint16Vector()->values()))
+              {
+                chef_array_segments->add_dim(as);
+              }
+              break;
+            case tflite::SparseIndexVector_Uint8Vector:
+              for (const auto &as : *(dm->array_segments_as_Uint8Vector()->values()))
+              {
+                chef_array_segments->add_dim(as);
+              }
+              break;
+            default:
+              throw std::runtime_error("unsupported sparse index vector type");
+          }
+          // array_indices
+          auto chef_array_indices = chef_dm->mutable_array_indices();
+          switch (dm->array_indices_type())
+          {
+            case tflite::SparseIndexVector_NONE:
+              // DO NOTHING
+              break;
+            case tflite::SparseIndexVector_Int32Vector:
+              for (const auto &as : *(dm->array_indices_as_Int32Vector()->values()))
+              {
+                chef_array_indices->add_dim(as);
+              }
+              break;
+            case tflite::SparseIndexVector_Uint16Vector:
+              for (const auto &as : *(dm->array_indices_as_Uint16Vector()->values()))
+              {
+                chef_array_indices->add_dim(as);
+              }
+              break;
+            case tflite::SparseIndexVector_Uint8Vector:
+              for (const auto &as : *(dm->array_indices_as_Uint8Vector()->values()))
+              {
+                chef_array_indices->add_dim(as);
+              }
+              break;
+            default:
+              throw std::runtime_error("unsupported sparse index vector type");
+          }
+        }
+      }
+
+      auto shape_signature = tensor->shape_signature();
+      if (shape_signature != nullptr)
+      {
+        tflchef::ShapeSignature *chef_shape_signature = operand->mutable_shape_signature();
+        for (uint32_t j = 0; j < shape_signature->size(); ++j)
+        {
+          chef_shape_signature->add_dim(shape_signature->Get(j));
         }
       }
     }
 
-    auto shape_signature = tensor->shape_signature();
-    if (shape_signature != nullptr)
+    // add all operators
+    for (uint32_t i = 0; i < operators->size(); ++i)
     {
-      tflchef::ShapeSignature *chef_shape_signature = operand->mutable_shape_signature();
-      for (uint32_t i = 0; i < shape_signature->size(); ++i)
+      const auto *op = operators->Get(i);
+      tflite::BuiltinOperator builtincode = tflite_import.builtin_code(op);
+
+      if (const auto *graph_builder = TFliteOpRegistry::get().lookup(builtincode))
+      {
+        tflchef::Operation *operation =
+          graph ? graph->add_operation() : model_recipe->add_operation();
+        ctx.tflop = op;
+        ctx.chefop = operation;
+        graph_builder->build(&ctx);
+
+        // common for all operators: inputs, outputs
+        set_inputs(&tflite_import, operation, op);
+        set_outputs(&tflite_import, operation, op);
+      }
+      else
       {
-        chef_shape_signature->add_dim(shape_signature->Get(i));
+        std::string opcodename = tflite_import.opcode_name(op);
+        throw std::runtime_error{"Not supported: " + opcodename};
       }
     }
-  }
 
-  // add all operators
-  for (uint32_t i = 0; i < operators->Length(); ++i)
-  {
-    const auto *op = operators->Get(i);
-    tflite::BuiltinOperator builtincode = tflite_import.builtin_code(op);
+    // network inputs/outputs
+    const std::vector<int32_t> &inputs = tflite_import.inputs();
+    const std::vector<int32_t> &outputs = tflite_import.outputs();
 
-    if (const auto *graph_builder = TFliteOpRegistry::get().lookup(builtincode))
+    for (const auto input : inputs)
     {
-      auto operation = graph_builder->build(op, &tflite_import, model_recipe.get());
+      auto tensor = tensors->Get(input);
+      std::string name = mio::tflite::tensor_name(tensor);
 
-      // common for all operators: inputs, outputs
-      set_inputs(&tflite_import, operation, op);
-      set_outputs(&tflite_import, operation, op);
+      if (graph != nullptr)
+        graph->add_input(name);
+      else
+        model_recipe->add_input(name);
     }
-    else
+    for (const auto output : outputs)
     {
-      std::string opcodename = tflite_import.opcode_name(op);
-      throw std::runtime_error{"Not supported: " + opcodename};
-    }
-  }
-
-  // network inputs/outputs
-  const std::vector<int32_t> &inputs = tflite_import.inputs();
-  const std::vector<int32_t> &outputs = tflite_import.outputs();
-
-  for (const auto input : inputs)
-  {
-    auto tensor = tensors->Get(input);
-    std::string name = mio::tflite::tensor_name(tensor);
-
-    model_recipe->add_input(name);
-  }
-  for (const auto output : outputs)
-  {
-    auto tensor = tensors->Get(output);
-    std::string name = mio::tflite::tensor_name(tensor);
+      auto tensor = tensors->Get(output);
+      std::string name = mio::tflite::tensor_name(tensor);
 
-    model_recipe->add_output(name);
+      if (graph != nullptr)
+        graph->add_output(name);
+      else
+        model_recipe->add_output(name);
+    }
   }
 
   return std::move(model_recipe);
index 9abec9a..cdb0815 100644 (file)
@@ -43,8 +43,11 @@ bool TFliteImport::select_sub_graph(uint32_t sgindex)
   _operators = nullptr;
   _inputs.clear();
   _outputs.clear();
+  clear_tensor_filler();
+  clear_tensor_filler_vint32();
+  clear_tensor_filler_vfloat();
 
-  if (_subgraphs->Length() <= sgindex)
+  if (_subgraphs->size() <= sgindex)
   {
     assert(false);
     return false;
index e6722e4..6fcb128 100644 (file)
@@ -54,7 +54,7 @@ public:
   const std::vector<int32_t> &inputs() const { return _inputs; }
   const std::vector<int32_t> &outputs() const { return _outputs; }
 
-  uint32_t num_subgraph() const { return _subgraphs->Length(); }
+  uint32_t num_subgraph() const { return _subgraphs->size(); }
 
   tflite::BuiltinOperator builtin_code(const tflite::Operator *op) const;
   std::string opcode_name(const tflite::Operator *op) const;
index 9856429..6113df4 100644 (file)
 namespace tflchef
 {
 
+struct RecipeChefContext
+{
+  const tflite::Operator *tflop = nullptr;
+  tflchef::Operation *chefop = nullptr;
+  // add more if needed
+};
+
 /**
  * @brief Interface for each operators to build tflchef
  */
@@ -34,8 +41,7 @@ class TFliteOpChef
 public:
   virtual void filler(const tflite::Operator *op, TFliteImport *import,
                       tflchef::ModelRecipe *model_recipe) const = 0;
-  virtual ::tflchef::Operation *build(const tflite::Operator *op, TFliteImport *import,
-                                      tflchef::ModelRecipe *model_recipe) const = 0;
+  virtual ::tflchef::Operation *build(RecipeChefContext *ctx) const = 0;
   virtual ~TFliteOpChef() {}
 };
 
index 34cb1ba..94e2ad2 100644 (file)
 #include "Op/include/BatchMatMul.h"
 #include "Op/include/BatchToSpaceND.h"
 #include "Op/include/BidirectionalSequenceLSTM.h"
+#include "Op/include/BroadcastTo.h"
 #include "Op/include/Cast.h"
 #include "Op/include/Ceil.h"
 #include "Op/include/Concatenation.h"
 #include "Op/include/Conv2D.h"
 #include "Op/include/Cos.h"
+#include "Op/include/CumSum.h"
 #include "Op/include/DepthToSpace.h"
 #include "Op/include/DepthwiseConv2D.h"
 #include "Op/include/Dequantize.h"
@@ -90,6 +92,7 @@
 #include "Op/include/ReduceMin.h"
 #include "Op/include/ReduceProd.h"
 #include "Op/include/ReLU.h"
+#include "Op/include/ReLU0To1.h"
 #include "Op/include/ReLU6.h"
 #include "Op/include/ReLUN1To1.h"
 #include "Op/include/Reshape.h"
 #include "Op/include/Unique.h"
 #include "Op/include/Unpack.h"
 #include "Op/include/Where.h"
+#include "Op/include/While.h"
 #include "Op/include/ZerosLike.h"
 
 #endif // __TFLITE_OP_CHEFS_H__
index a37f15c..43d526d 100644 (file)
@@ -64,11 +64,13 @@ private:
     REG_TFL_OP(BATCH_MATMUL, TFliteOpBatchMatMul);
     REG_TFL_OP(BATCH_TO_SPACE_ND, TFliteOpBatchToSpaceND);
     REG_TFL_OP(BIDIRECTIONAL_SEQUENCE_LSTM, TFliteOpBidirectionalSequenceLSTM);
+    REG_TFL_OP(BROADCAST_TO, TFliteOpBroadcastTo);
     REG_TFL_OP(CAST, TFliteOpCast);
     REG_TFL_OP(CEIL, TFliteOpCeil);
     REG_TFL_OP(CONCATENATION, TFliteOpConcatenation);
     REG_TFL_OP(CONV_2D, TFliteOpConv2D);
     REG_TFL_OP(COS, TFliteOpCos);
+    REG_TFL_OP(CUMSUM, TFliteOpCumsum);
     REG_TFL_OP(DEPTH_TO_SPACE, TFliteOpDepthToSpace);
     REG_TFL_OP(DEPTHWISE_CONV_2D, TFliteOpDepthwiseConv2D);
     REG_TFL_OP(DEQUANTIZE, TFliteOpDequantize);
@@ -127,6 +129,7 @@ private:
     REG_TFL_OP(REDUCE_MIN, TFliteOpReduceMin);
     REG_TFL_OP(REDUCE_PROD, TFliteOpReduceProd);
     REG_TFL_OP(RELU, TFliteOpReLU);
+    REG_TFL_OP(RELU_0_TO_1, TFliteOpReLU0To1);
     REG_TFL_OP(RELU6, TFliteOpReLU6);
     REG_TFL_OP(RELU_N1_TO_1, TFliteOpReLUN1To1);
     REG_TFL_OP(RESHAPE, TFliteOpReshape);
@@ -166,6 +169,7 @@ private:
     REG_TFL_OP(UNIQUE, TFliteOpUnique);
     REG_TFL_OP(UNPACK, TFliteOpUnpack);
     REG_TFL_OP(WHERE, TFliteOpWhere);
+    REG_TFL_OP(WHILE, TFliteOpWhile);
     REG_TFL_OP(ZEROS_LIKE, TFliteOpZerosLike);
 
 #undef REG_TFL_OP
index a345039..7139f9c 100644 (file)
@@ -129,7 +129,7 @@ void dump_sub_graph(std::ostream &os, tflread::Reader &reader)
   // dump operands(tensors)
   os << "Operands: T(subgraph index : tensor index) TYPE (shape) (shape_signature) "
      << "B(buffer index) (variable) OperandName" << std::endl;
-  for (uint32_t i = 0; i < tensors->Length(); ++i)
+  for (uint32_t i = 0; i < tensors->size(); ++i)
   {
     // TODO refactor to some better structure
     auto tensor = tensors->Get(i);
@@ -280,7 +280,7 @@ void dump_sub_graph(std::ostream &os, tflread::Reader &reader)
   os << "    Option(values) ... <-- depending on OpCode" << std::endl;
   os << "    I T(tensor index) OperandName <-- as input" << std::endl;
   os << "    O T(tensor index) OperandName <-- as output" << std::endl;
-  for (uint32_t i = 0; i < operators->Length(); ++i)
+  for (uint32_t i = 0; i < operators->size(); ++i)
   {
     const auto op = operators->Get(i);
     tflite::BuiltinOperator builtincode = reader.builtin_code(op);
@@ -377,7 +377,7 @@ void dump_model(std::ostream &os, const tflite::Model *model)
 
   // dump buffer
   os << "Buffers: B(index) (length) values, if any" << std::endl;
-  for (uint32_t i = 0; i < buffers->Length(); ++i)
+  for (uint32_t i = 0; i < buffers->size(); ++i)
   {
     const uint8_t *buff_data;
     size_t size = reader.buffer_info(i, &buff_data);
@@ -395,7 +395,7 @@ void dump_model(std::ostream &os, const tflite::Model *model)
   if (metadata != nullptr)
   {
     os << "metadata : B(index) name" << std::endl;
-    for (uint32_t i = 0; i < metadata->Length(); ++i)
+    for (uint32_t i = 0; i < metadata->size(); ++i)
     {
       os << "B(" << metadata->Get(i)->buffer() << ") " << metadata->Get(i)->name()->c_str()
          << std::endl;
@@ -407,14 +407,14 @@ void dump_model(std::ostream &os, const tflite::Model *model)
   if (signaturedefs != nullptr)
   {
     os << "SignatureDef" << std::endl;
-    for (uint32_t i = 0; i < signaturedefs->Length(); ++i)
+    for (uint32_t i = 0; i < signaturedefs->size(); ++i)
     {
       auto sign_i = signaturedefs->Get(i);
       os << "S(" << i << ") signature_key(" << sign_i->signature_key()->c_str() << "), sub_graph("
          << sign_i->subgraph_index() << ")" << std::endl;
 
       auto inputs_i = sign_i->inputs();
-      for (uint32_t t = 0; t < inputs_i->Length(); ++t)
+      for (uint32_t t = 0; t < inputs_i->size(); ++t)
       {
         auto inputs_i_t = inputs_i->Get(t);
         os << "    I(" << t << ")"
@@ -423,7 +423,7 @@ void dump_model(std::ostream &os, const tflite::Model *model)
       }
 
       auto outputs_i = sign_i->outputs();
-      for (uint32_t t = 0; t < outputs_i->Length(); ++t)
+      for (uint32_t t = 0; t < outputs_i->size(); ++t)
       {
         auto outputs_i_t = outputs_i->Get(t);
         os << "    O(" << t << ")"
index f8777fa..fd8fd08 100644 (file)
@@ -117,7 +117,7 @@ public:
     if (auto conv_params = op->builtin_options_as_Conv2DOptions())
     {
       os << "    ";
-      os << "Padding(" << conv_params->padding() << ") ";
+      os << "Padding(" << EnumNamePadding(conv_params->padding()) << ") ";
       os << "Stride.W(" << conv_params->stride_w() << ") ";
       os << "Stride.H(" << conv_params->stride_h() << ") ";
       os << "Dilation.W(" << conv_params->dilation_w_factor() << ") ";
@@ -152,7 +152,7 @@ public:
     if (auto pool_params = op->builtin_options_as_Pool2DOptions())
     {
       os << "    ";
-      os << "Padding(" << pool_params->padding() << ") ";
+      os << "Padding(" << EnumNamePadding(pool_params->padding()) << ") ";
       os << "Stride.W(" << pool_params->stride_w() << ") ";
       os << "Stride.H(" << pool_params->stride_h() << ") ";
       os << "Filter.W(" << pool_params->filter_width() << ") ";
@@ -294,7 +294,7 @@ public:
     if (auto conv_params = op->builtin_options_as_DepthwiseConv2DOptions())
     {
       os << "    ";
-      os << "Padding(" << conv_params->padding() << ") ";
+      os << "Padding(" << EnumNamePadding(conv_params->padding()) << ") ";
       os << "Stride.W(" << conv_params->stride_w() << ") ";
       os << "Stride.H(" << conv_params->stride_h() << ") ";
       os << "DepthMultiplier(" << conv_params->depth_multiplier() << ") ";
@@ -640,7 +640,7 @@ public:
     if (auto *params = op->builtin_options_as_TransposeConvOptions())
     {
       os << "    ";
-      os << "Padding(" << params->padding() << ") ";
+      os << "Padding(" << EnumNamePadding(params->padding()) << ") ";
       os << "Stride.W(" << params->stride_w() << ") ";
       os << "Stride.H(" << params->stride_h() << ") ";
       os << "Activation(" << EnumNameActivationFunctionType(params->fused_activation_function())
@@ -784,6 +784,7 @@ OpPrinterRegistry::OpPrinterRegistry()
   // There is no Option for PRELU
   // There is no Option for RELU
   // There is no Option for RELU6
+  // There is no Option for RELU_0_TO_1
   // There is no Option for RELU_N1_TO_1
   _op_map[tflite::BuiltinOperator_REDUCE_ANY] = make_unique<ReducerPrinter>();
   _op_map[tflite::BuiltinOperator_REDUCE_MAX] = make_unique<ReducerPrinter>();
index 7fa3d81..f55d86d 100644 (file)
@@ -95,7 +95,7 @@ bool Reader::select_subgraph(uint32_t sgindex)
   _inputs.clear();
   _outputs.clear();
 
-  if (_subgraphs->Length() <= sgindex)
+  if (_subgraphs->size() <= sgindex)
   {
     assert(false);
     return false;
index 1ae6387..fb4d330 100644 (file)
@@ -28,8 +28,8 @@ namespace tflread
 
 template <typename T> std::vector<T> as_index_vector(const flatbuffers::Vector<T> *flat_array)
 {
-  std::vector<T> ret(flat_array->Length());
-  for (uint32_t i = 0; i < flat_array->Length(); i++)
+  std::vector<T> ret(flat_array->size());
+  for (uint32_t i = 0; i < flat_array->size(); i++)
   {
     ret[i] = flat_array->Get(i);
   }
@@ -66,7 +66,7 @@ public:
   const TFliteMetadata_t *metadata() const { return _metadata; }
   const TFliteSignatureDef_t *signaturedefs() const { return _signaturedefs; }
 
-  uint32_t num_subgraph() const { return _subgraphs->Length(); }
+  uint32_t num_subgraph() const { return _subgraphs->size(); }
 
   size_t buffer_info(uint32_t buf_idx, const uint8_t **buff_data);
   tflite::BuiltinOperator builtin_code(const tflite::Operator *op) const;
index 73639f3..35aad32 100644 (file)
@@ -2,7 +2,7 @@ nnas_include(TargetRequire)
 
 unset(REQUIRED_TARGETS)
 list(APPEND REQUIRED_TARGETS mio_tflite2121)
-list(APPEND REQUIRED_TARGETS mio_circle06)
+list(APPEND REQUIRED_TARGETS mio_circle08)
 TargetRequire_Return(${REQUIRED_TARGETS})
 
 set(DRIVER "driver/Driver.cpp")
@@ -15,7 +15,7 @@ target_link_libraries(tflite2circle foder)
 target_link_libraries(tflite2circle safemain)
 target_link_libraries(tflite2circle mio_tflite2121)
 target_link_libraries(tflite2circle mio_tflite2121_helper)
-target_link_libraries(tflite2circle mio_circle06)
+target_link_libraries(tflite2circle mio_circle08)
 target_link_libraries(tflite2circle vconone)
 target_link_libraries(tflite2circle nncc_coverage)
 
index c5528c2..cf770df 100644 (file)
@@ -1,6 +1,6 @@
 require("arser")
 require("foder")
 require("mio-tflite2121")
-require("mio-circle06")
+require("mio-circle08")
 require("safemain")
 require("vconone")
index 5ed88ce..8f3bfb9 100644 (file)
 #include "BuildBuiltinOptions/BatchMatMulOptions.h"
 #include "BuildBuiltinOptions/BatchToSpaceNDOptions.h"
 #include "BuildBuiltinOptions/BidirectionalSequenceLSTMOptions.h"
+#include "BuildBuiltinOptions/BroadcastToOptions.h"
 #include "BuildBuiltinOptions/CastOptions.h"
 #include "BuildBuiltinOptions/ConcatenationOptions.h"
 #include "BuildBuiltinOptions/Conv2DOptions.h"
 #include "BuildBuiltinOptions/CosOptions.h"
+#include "BuildBuiltinOptions/CumSumOptions.h"
 #include "BuildBuiltinOptions/DensifyOptions.h"
 #include "BuildBuiltinOptions/DepthToSpaceOptions.h"
 #include "BuildBuiltinOptions/DepthwiseConv2DOptions.h"
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/BroadcastToOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/BroadcastToOptions.cpp
new file mode 100644 (file)
index 0000000..4b15c6e
--- /dev/null
@@ -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.
+ */
+
+#include "BroadcastToOptions.h"
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::BroadcastToOptions>
+build_circle_BroadcastToOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Operator *op)
+{
+  auto *tflite_builtin_options = op->builtin_options_as_BroadcastToOptions();
+  assert(tflite_builtin_options);
+  circle::BroadcastToOptionsBuilder builtin_options_builder{fb};
+  return builtin_options_builder.Finish();
+}
+
+} // namespace tflite2circle
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/BroadcastToOptions.h b/compiler/tflite2circle/src/BuildBuiltinOptions/BroadcastToOptions.h
new file mode 100644 (file)
index 0000000..816fbd3
--- /dev/null
@@ -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_BROADCAST_TO_OPTIONS_H__
+#define __BBO_BROADCAST_TO_OPTIONS_H__
+
+#include <mio/tflite/schema_generated.h>
+#include <mio/circle/schema_generated.h>
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::BroadcastToOptions>
+build_circle_BroadcastToOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Operator *op);
+
+} // namespace tflite2circle
+
+#endif // __BBO_BROADCAST_TO_OPTIONS_H__
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/CumSumOptions.cpp b/compiler/tflite2circle/src/BuildBuiltinOptions/CumSumOptions.cpp
new file mode 100644 (file)
index 0000000..a52aa7b
--- /dev/null
@@ -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 "CumSumOptions.h"
+
+#include <cassert>
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::CumsumOptions>
+build_circle_CumsumOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Operator *op)
+{
+  auto tflite_builtin_options = op->builtin_options_as_CumsumOptions();
+  assert(tflite_builtin_options);
+  circle::CumsumOptionsBuilder cumsum_options_builder{fb};
+  cumsum_options_builder.add_exclusive(tflite_builtin_options->exclusive());
+  cumsum_options_builder.add_reverse(tflite_builtin_options->reverse());
+  return cumsum_options_builder.Finish();
+}
+
+} // namespace tflite2circle
diff --git a/compiler/tflite2circle/src/BuildBuiltinOptions/CumSumOptions.h b/compiler/tflite2circle/src/BuildBuiltinOptions/CumSumOptions.h
new file mode 100644 (file)
index 0000000..02716f1
--- /dev/null
@@ -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_CUMSUM_OPTIONS_H__
+#define __BBO_CUMSUM_OPTIONS_H__
+
+#include <mio/tflite/schema_generated.h>
+#include <mio/circle/schema_generated.h>
+
+namespace tflite2circle
+{
+
+flatbuffers::Offset<circle::CumsumOptions>
+build_circle_CumsumOptions(flatbuffers::FlatBufferBuilder &fb, const tflite::Operator *op);
+
+} // namespace tflite2circle
+
+#endif // __BBO_CUMSUM_OPTIONS_H__
index 899bc84..c9465a0 100644 (file)
@@ -323,7 +323,6 @@ template <> void Offset<SubGraphLink>::build(const TFLFlatBufVec *tflite_flatbuf
     circle_subgraph_builder.add_outputs(circle_outputs);
     circle_subgraph_builder.add_operators(circle_operators);
     circle_subgraph_builder.add_name(subgraphs_name);
-    circle_subgraph_builder.add_data_format(circle::DataFormat_CHANNELS_LAST);
 
     auto circle_subgraph = circle_subgraph_builder.Finish();
     subgprahs_vec.emplace_back(circle_subgraph);
index c16e601..9f3e694 100644 (file)
@@ -30,7 +30,11 @@ circle::BuiltinOperator get_circle_builtin_code(tflite::BuiltinOperator tfl_bop)
 #include "TFLOperator.lst"
 #undef TFL_OPERATOR
     default:
-      throw std::runtime_error("tflite2circle: wrong op");
+    {
+      std::string msg = "tflite2circle: Unsupported op ";
+      msg = msg + tflite::EnumNameBuiltinOperator(tfl_bop);
+      throw std::runtime_error(msg.c_str());
+    }
   }
 }
 
@@ -53,7 +57,11 @@ int32_t get_circle_builtin_code(int32_t tfl_bop_i32)
     case tflite::BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES:
       return static_cast<int32_t>(circle::BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES);
     default:
-      throw std::runtime_error("tflite2circle: wrong op");
+    {
+      std::string msg = "tflite2circle: Unsupported op ";
+      msg = msg + tflite::EnumNameBuiltinOperator(tfl_bop);
+      throw std::runtime_error(msg.c_str());
+    }
   }
 }
 
index ac77c9a..8f49205 100644 (file)
@@ -108,3 +108,5 @@ TFL_BUILTIN_OPTIONS(ScatterNdOptions)
 TFL_BUILTIN_OPTIONS(SegmentSumOptions)
 TFL_BUILTIN_OPTIONS(BatchMatMulOptions)
 TFL_BUILTIN_OPTIONS(DensifyOptions)
+TFL_BUILTIN_OPTIONS(CumsumOptions)
+TFL_BUILTIN_OPTIONS(BroadcastToOptions)
index b7db49b..cbe171e 100644 (file)
@@ -152,3 +152,4 @@ TFL_OPERATOR(ASSIGN_VARIABLE)
 TFL_OPERATOR(BROADCAST_ARGS)
 TFL_OPERATOR(RANDOM_STANDARD_NORMAL)
 TFL_OPERATOR(GELU)
+TFL_OPERATOR(RELU_0_TO_1)
index 968153a..213ad15 100644 (file)
@@ -14,3 +14,8 @@ TFL_TENSORTYPE(BOOL)
 TFL_TENSORTYPE(INT16)
 TFL_TENSORTYPE(COMPLEX64)
 TFL_TENSORTYPE(INT8)
+TFL_TENSORTYPE(FLOAT64)
+TFL_TENSORTYPE(UINT64)
+TFL_TENSORTYPE(UINT32)
+TFL_TENSORTYPE(UINT16)
+TFL_TENSORTYPE(INT4)
diff --git a/compiler/tfts/exclude.me b/compiler/tfts/exclude.me
new file mode 100644 (file)
index 0000000..e69de29
index c5c9be2..0c1263d 100644 (file)
@@ -1,5 +1,5 @@
 if (NOT VCONONE_VERSION)
-  set(VCONONE_VERSION 0x0000000000190001)
+  set(VCONONE_VERSION 0x00000000001c0001)
   # 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/compute/ARMComputeEx/arm_compute/core/NEON/NEElementwiseOperationFuncs.h b/compute/ARMComputeEx/arm_compute/core/NEON/NEElementwiseOperationFuncs.h
deleted file mode 100644 (file)
index 933d876..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Copyright (c) 2016-2018 ARM Limited.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __ARM_COMPUTE_NEELEMENTWISEOPERATIONFUNCS_H__
-#define __ARM_COMPUTE_NEELEMENTWISEOPERATIONFUNCS_H__
-
-#include <arm_neon.h>
-
-namespace arm_compute
-{
-class ITensor;
-class Window;
-class QuantizationInfo;
-} // namespace arm_compute
-
-namespace arm_compute
-{
-
-void elementwise_op(const ITensor *in1, const ITensor *in2, ITensor *out, const Window &window,
-                    float (*scalar_func)(const float &, const float &),
-                    int (*broadcast_func)(int, int, int, const float *, const float &, float *,
-                                          const bool),
-                    int (*neon_func)(int, int, int, const float *, const float *, float *));
-
-void elementwise_op(const ITensor *in1, const ITensor *in2, ITensor *out, const Window &window,
-                    uint8_t (*scalar_func)(const uint8_t &, const uint8_t &),
-                    int (*broadcast_func)(int, int, int, const uint8_t *, const uint8_t &,
-                                          uint8_t *, const bool),
-                    int (*neon_func)(int, int, int, const uint8_t *, const uint8_t *, uint8_t *));
-} // namespace arm_compute
-#endif // __ARM_COMPUTE_NEELEMENTWISEOPERATIONFUNCS_H__
diff --git a/compute/ARMComputeEx/arm_compute/core/NEON/kernels/NEBinaryLogicalOperationKernel.h b/compute/ARMComputeEx/arm_compute/core/NEON/kernels/NEBinaryLogicalOperationKernel.h
deleted file mode 100644 (file)
index c46b261..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Copyright (c) 2018-2019 ARM Limited.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __ARM_COMPUTE_NEBINARYLOGICALOPERATIONKERNEL_H__
-#define __ARM_COMPUTE_NEBINARYLOGICALOPERATIONKERNEL_H__
-
-#include "arm_compute/core/TypesEx.h"
-
-#include "src/core/cpu/kernels/CpuElementwiseKernel.h"
-
-namespace arm_compute
-{
-
-class NEBinaryLogicalOperationKernel : public cpu::kernels::CpuComparisonKernel
-{
-public:
-  const char *name() const override { return "NEBinaryLogicalOperationKernel"; }
-
-  NEBinaryLogicalOperationKernel() = default;
-  /** Default destructor */
-  ~NEBinaryLogicalOperationKernel() = default;
-
-  /** Static function to check if given info will lead to a valid configuration of @ref
-   * NEBinaryLogicalOperationKernel
-   *
-   * @param[in] op     Binary logical operation to be executed.
-   * @param[in] input1 First tensor input. Data types supported: QASYMM8/U8.
-   * @param[in] input2 Second tensor input. Data types supported: Same as @p input1.
-   * @param[in] output Output tensor. Data types supported: Same as @p input1.
-   */
-  void configure(BinaryLogicalOperation op, const ITensor *input1, const ITensor *input2,
-                 ITensor *output);
-
-  /** Static function to check if given info will lead to a valid configuration of @ref
-   * NEBinaryLogicalOperationKernel
-   *
-   * @param[in] op     Binary logical operation to be executed.
-   * @param[in] input1 First tensor input info. Data types supported: QASYMM8/U8.
-   * @param[in] input2 Second tensor input info. Data types supported: Same as @p input1.
-   * @param[in] output Output tensor info. Data types supported: Same as @p input1.
-   *
-   * @return a Status
-   */
-  static Status validate(BinaryLogicalOperation op, const ITensorInfo *input1,
-                         const ITensorInfo *input2, const ITensorInfo *output);
-
-protected:
-  // Inherited methods overridden:
-  static Status validate_arguments(const ITensorInfo &input1, const ITensorInfo &input2,
-                                   const ITensorInfo &output);
-
-  std::function<void(const ITensor *input1, const ITensor *input2, ITensor *output,
-                     const Window &window)>
-    _function;
-};
-} // namespace arm_compute
-#endif /* __ARM_COMPUTE_NEBINARYLOGICALOPERATIONKERNEL_H__ */
diff --git a/compute/ARMComputeEx/arm_compute/runtime/NEON/functions/NEBinaryLogicalOperation.h b/compute/ARMComputeEx/arm_compute/runtime/NEON/functions/NEBinaryLogicalOperation.h
deleted file mode 100644 (file)
index 8d931f0..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Copyright (c) 2018-2019 ARM Limited.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __ARM_COMPUTE_NEBINARYLOGICALOPERATION_H__
-#define __ARM_COMPUTE_NEBINARYLOGICALOPERATION_H__
-
-#include "arm_compute/core/Error.h"
-#include "arm_compute/core/TypesEx.h"
-#include "arm_compute/runtime/NEON/INESimpleFunction.h"
-#include "arm_compute/core/ITensorInfo.h"
-
-namespace arm_compute
-{
-class ITensor;
-
-/** Basic function to run @ref NEBinaryLogicalOperationKernel.
- *
- * @note The tensor data type for the inputs must be QASYMM8/U8.
- * @note The function performs a binary logical operation between two tensors.
- */
-class NEBinaryLogicalOperation : public INESimpleFunction
-{
-public:
-  /** Initialise the kernel's inputs, output and conversion policy.
-   *
-   * @param[in, out] input1 First tensor input. Data types supported: QASYMM8/U8.
-   * @param[in, out] input2 Second tensor input. Data types supported: Same as @p input1.
-   * @param[out]     output Output tensor. Data types supported: Same as @p input1.
-   * @param[in]      op     Binary Logical Operation to be performed.
-   */
-  void configure(ITensor *input1, ITensor *input2, ITensor *output, BinaryLogicalOperation op);
-  /** Static function to check if given info will lead to a valid configuration of @ref
-   * NEBinaryLogicalOperationKernel
-   *
-   * @param[in] input1 First tensor input info. Data types supported: QASYMM8/U8.
-   * @param[in] input2 Second tensor input info. Data types supported: Same as @p input1.
-   * @param[in] output Output tensor info. Data types supported: Same as @p input1.
-   * @param[in] op     Binary Logical Operation to be performed.
-   *
-   * @return a status
-   */
-  static Status validate(const ITensorInfo *input1, const ITensorInfo *input2,
-                         const ITensorInfo *output, BinaryLogicalOperation op);
-};
-
-/** Basic function to run @ref NEBinaryLogicalOperationKernel
- *
- * @note The tensor data type for the inputs must be QASYMM8/U8.
- * @note The function performs a binary logical operation between two tensors.
- */
-template <BinaryLogicalOperation op> class NEBinaryLogicalOperationStatic : public INESimpleFunction
-{
-public:
-  /** Initialise the kernel's inputs, output and conversion policy.
-   *
-   * @param[in, out] input1 First tensor input. Data types supported: QASYMM8/U8
-   * @param[in, out] input2 Second tensor input. Data types supported: Same as @p input1.
-   * @param[out]     output Output tensor. Data types supported: Same as @p input1.
-   */
-  void configure(ITensor *input1, ITensor *input2, ITensor *output);
-  /** Static function to check if given info will lead to a valid configuration of @ref
-   * NEBinaryLogicalOperationKernel
-   *
-   * @param[in] input1 First tensor input info. Data types supported: QASYMM8/U8
-   * @param[in] input2 Second tensor input info. Data types supported: Same as @p input1.
-   * @param[in] output Output tensor info. Data types supported: Same as @p input1.
-   *
-   * @return a status
-   */
-  static Status validate(const ITensorInfo *input1, const ITensorInfo *input2,
-                         const ITensorInfo *output);
-};
-
-/** Basic function to run equal comparison. */
-using NELogicalAnd = NEBinaryLogicalOperationStatic<BinaryLogicalOperation::AND>;
-/** Basic function to run not equal comparison. */
-using NELogicalOr = NEBinaryLogicalOperationStatic<BinaryLogicalOperation::OR>;
-} // namespace arm_compute
-#endif /* __ARM_COMPUTE_NEBINARYLOGICALOPERATION_H__ */
index 2d9acc7..c19766c 100644 (file)
@@ -2141,26 +2141,26 @@ __kernel void gemmlowp_offset_contribution_quantize_down(TENSOR3D_DECLARATION(mm
  * element in the output shifts vector
  */
 __kernel void
-  gemmlowp_offset_contribution_quantize_down_fixedpoint(TENSOR3D_DECLARATION(mm_result)
+gemmlowp_offset_contribution_quantize_down_fixedpoint(TENSOR3D_DECLARATION(mm_result)
 #if defined(A_OFFSET)
-                                                          ,
-                                                        IMAGE_DECLARATION(sum_col)
+                                                        ,
+                                                      IMAGE_DECLARATION(sum_col)
 #endif // defined(A_OFFSET)
 #if defined(B_OFFSET)
-                                                          ,
-                                                        IMAGE_DECLARATION(sum_row)
+                                                        ,
+                                                      IMAGE_DECLARATION(sum_row)
 #endif // defined(B_OFFSET)
-                                                          ,
+                                                        ,
 #if defined(ADD_BIAS)
-                                                        VECTOR_DECLARATION(biases),
+                                                      VECTOR_DECLARATION(biases),
 #endif // defined(ADD_BIAS)
-                                                        TENSOR3D_DECLARATION(dst)
+                                                      TENSOR3D_DECLARATION(dst)
 #if defined(PER_CHANNEL_QUANTIZATION)
-                                                          ,
-                                                        VECTOR_DECLARATION(result_multipliers),
-                                                        VECTOR_DECLARATION(result_shifts)
+                                                        ,
+                                                      VECTOR_DECLARATION(result_multipliers),
+                                                      VECTOR_DECLARATION(result_shifts)
 #endif // defined(PER_CHANNEL_QUANTIZATION)
-  )
+)
 {
   const int x = get_global_id(0) * 4;
   const int y = get_global_id(1);
diff --git a/compute/ARMComputeEx/src/core/NEON/NEElementwiseOperationFuncs.cpp b/compute/ARMComputeEx/src/core/NEON/NEElementwiseOperationFuncs.cpp
deleted file mode 100644 (file)
index 1d4d33a..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Copyright (c) 2016-2018 ARM Limited.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "arm_compute/core/NEON/NEElementwiseOperationFuncs.h"
-
-#include <algorithm>
-#include "arm_compute/core/Types.h"
-#include "src/core/NEON/NEAsymm.h"
-#include "arm_compute/core/ITensor.h"
-#include "arm_compute/core/Helpers.h"
-#include "arm_compute/core/Window.h"
-
-namespace
-{
-
-using namespace arm_compute;
-template <typename InputScalarType, typename OutputScalarType, typename InputVectorType>
-void elementwise_op_templ(
-  const ITensor *in1, const ITensor *in2, ITensor *out, const Window &window,
-  OutputScalarType (*scalar_func)(const InputScalarType &, const InputScalarType &),
-  int (*broadcast_func)(int, int, int, const InputScalarType *, const InputScalarType &,
-                        OutputScalarType *, const bool),
-  int (*neon_func)(int, int, int, const InputScalarType *, const InputScalarType *,
-                   OutputScalarType *))
-{
-  // Create input windows
-  Window input1_win = window.broadcast_if_dimension_le_one(in1->info()->tensor_shape());
-  Window input2_win = window.broadcast_if_dimension_le_one(in2->info()->tensor_shape());
-
-  // Clear X Dimension on execution window as we handle manually
-  Window win = window;
-  win.set(Window::DimX, Window::Dimension(0, 1, 1));
-
-  const int window_step_x = std::min(16 / static_cast<int>(sizeof(OutputScalarType)), 8);
-  const auto window_start_x = static_cast<int>(window.x().start());
-  const auto window_end_x = static_cast<int>(window.x().end());
-  const bool is_broadcast_across_x = (input1_win.x().step() == 0) || (input2_win.x().step() == 0);
-
-  if (is_broadcast_across_x)
-  {
-    const bool is_broadcast_input_2 = input2_win.x().step() == 0;
-    Window broadcast_win = is_broadcast_input_2 ? input2_win : input1_win;
-    Window non_broadcast_win = !is_broadcast_input_2 ? input2_win : input1_win;
-    const ITensor *broadcast_tensor = is_broadcast_input_2 ? in2 : in1;
-    const ITensor *non_broadcast_tensor = !is_broadcast_input_2 ? in2 : in1;
-
-    // Clear X Dimension on execution window as we handle manually
-    non_broadcast_win.set(Window::DimX, Window::Dimension(0, 1, 1));
-
-    Iterator broadcast_input(broadcast_tensor, broadcast_win);
-    Iterator non_broadcast_input(non_broadcast_tensor, non_broadcast_win);
-    Iterator output(out, win);
-
-    execute_window_loop(
-      win,
-      [&](const Coordinates &) {
-        auto output_ptr = reinterpret_cast<OutputScalarType *>(output.ptr());
-        const auto non_broadcast_input_ptr =
-          reinterpret_cast<const InputScalarType *>(non_broadcast_input.ptr());
-        const InputScalarType broadcast_value =
-          *reinterpret_cast<const InputScalarType *>(broadcast_input.ptr());
-
-        int x =
-          (*broadcast_func)(window_start_x, window_end_x, window_step_x, non_broadcast_input_ptr,
-                            broadcast_value, output_ptr, !is_broadcast_input_2);
-        for (; x < window_end_x; ++x)
-        {
-          const auto a = *(non_broadcast_input_ptr + x);
-          *(output_ptr + x) = (*scalar_func)(!is_broadcast_input_2 ? broadcast_value : a,
-                                             !is_broadcast_input_2 ? a : broadcast_value);
-        }
-      },
-      broadcast_input, non_broadcast_input, output);
-  }
-  else
-  {
-    // Clear X Dimension on execution window as we handle manually
-    input1_win.set(Window::DimX, Window::Dimension(0, 1, 1));
-    input2_win.set(Window::DimX, Window::Dimension(0, 1, 1));
-
-    Iterator input1(in1, input1_win);
-    Iterator input2(in2, input2_win);
-    Iterator output(out, win);
-
-    execute_window_loop(
-      win,
-      [&](const Coordinates &) {
-        auto output_ptr = reinterpret_cast<OutputScalarType *>(output.ptr());
-        const auto input1_ptr = reinterpret_cast<const InputScalarType *>(input1.ptr());
-        const auto input2_ptr = reinterpret_cast<const InputScalarType *>(input2.ptr());
-
-        int x = (*neon_func)(window_start_x, window_end_x, window_step_x, input1_ptr, input2_ptr,
-                             output_ptr);
-        for (; x < window_end_x; ++x)
-        {
-          const auto a = *(input1_ptr + x);
-          const auto b = *(input2_ptr + x);
-          *(output_ptr + x) = (*scalar_func)(a, b);
-        }
-      },
-      input1, input2, output);
-  }
-}
-
-} // namespace
-
-namespace arm_compute
-{
-
-void elementwise_op(const ITensor *in1, const ITensor *in2, ITensor *out, const Window &window,
-                    float (*scalar_func)(const float &, const float &),
-                    int (*broadcast_func)(int, int, int, const float *, const float &, float *,
-                                          const bool),
-                    int (*neon_func)(int, int, int, const float *, const float *, float *))
-{
-  elementwise_op_templ<float, float, float32x4_t>(in1, in2, out, window, scalar_func,
-                                                  broadcast_func, neon_func);
-}
-
-void elementwise_op(const ITensor *in1, const ITensor *in2, ITensor *out, const Window &window,
-                    uint8_t (*scalar_func)(const uint8_t &, const uint8_t &),
-                    int (*broadcast_func)(int, int, int, const uint8_t *, const uint8_t &,
-                                          uint8_t *, const bool),
-                    int (*neon_func)(int, int, int, const uint8_t *, const uint8_t *, uint8_t *))
-{
-  elementwise_op_templ<uint8_t, uint8_t, uint8x16_t>(in1, in2, out, window, scalar_func,
-                                                     broadcast_func, neon_func);
-}
-} // namespace arm_compute
diff --git a/compute/ARMComputeEx/src/core/NEON/kernels/NEBinaryLogicalOperationKernel.cpp b/compute/ARMComputeEx/src/core/NEON/kernels/NEBinaryLogicalOperationKernel.cpp
deleted file mode 100644 (file)
index 0551fc7..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Copyright (c) 2018-2019 ARM Limited.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "arm_compute/core/NEON/kernels/NEBinaryLogicalOperationKernel.h"
-
-#include "arm_compute/core/Error.h"
-#include "arm_compute/core/Helpers.h"
-#include "arm_compute/core/ITensor.h"
-#include "arm_compute/core/NEON/NEElementwiseOperationFuncs.h"
-#include "arm_compute/core/TensorInfo.h"
-#include "arm_compute/core/Validate.h"
-#include "src/core/NEON/wrapper/wrapper.h"
-
-#include <algorithm>
-#include <arm_neon.h>
-#include <map>
-#include <string>
-
-namespace arm_compute
-{
-class Coordinates;
-} // namespace arm_compute
-
-namespace arm_compute
-{
-
-template <BinaryLogicalOperation op, typename ScalarType>
-inline ScalarType elementwise_logic_op_scalar(const ScalarType &a, const ScalarType &b)
-{
-  auto res = ScalarType(0);
-
-  switch (op)
-  {
-    case BinaryLogicalOperation::AND:
-      res = a & b;
-      break;
-    case BinaryLogicalOperation::OR:
-      res = a | b;
-      break;
-    default:
-      ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
-  }
-  return res;
-}
-
-template <BinaryLogicalOperation op, typename VectorType>
-inline VectorType elementwise_logic_op(const VectorType &a, const VectorType &b)
-{
-  VectorType res = {0, 0, 0, 0};
-
-  switch (op)
-  {
-    case BinaryLogicalOperation::AND:
-      res = wrapper::vand(a, b);
-      break;
-    case BinaryLogicalOperation::OR:
-      res = wrapper::vorr(a, b);
-      break;
-    default:
-      ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
-  }
-  return res;
-}
-
-template <BinaryLogicalOperation op>
-inline uint8x16x4_t elementwise_logic_op(const uint8x16x4_t &a, const uint8x16x4_t &b)
-{
-  uint8x16x4_t out = {{
-    elementwise_logic_op<op>(a.val[0], b.val[0]),
-    elementwise_logic_op<op>(a.val[1], b.val[1]),
-    elementwise_logic_op<op>(a.val[2], b.val[2]),
-    elementwise_logic_op<op>(a.val[3], b.val[3]),
-  }};
-  return out;
-}
-
-template <BinaryLogicalOperation op, typename ScalarType, typename VectorType>
-inline VectorType elementwise_logic_op_broadcast(const VectorType &a,
-                                                 const ScalarType &broadcast_value,
-                                                 const bool reorder)
-{
-  VectorType broadcast_vector = wrapper::vdup_n(broadcast_value, wrapper::traits::vector_128_tag());
-  return elementwise_logic_op<op>(reorder ? broadcast_vector : a, reorder ? a : broadcast_vector);
-}
-
-template <BinaryLogicalOperation op, typename ScalarType, typename VectorType>
-inline int elementwise_logic_op_loop(int window_start_x, int window_end_x, int window_step_x,
-                                     const ScalarType *input1_ptr, const ScalarType *input2_ptr,
-                                     ScalarType *output_ptr)
-{
-  int x = window_start_x;
-  for (; x <= (window_end_x - window_step_x); x += window_step_x)
-  {
-    const auto a = wrapper::vloadq(input1_ptr + x);
-    const auto b = wrapper::vloadq(input2_ptr + x);
-    wrapper::vstore(output_ptr + x, elementwise_logic_op<op>(a, b));
-  }
-  return x;
-}
-
-template <BinaryLogicalOperation op, typename ScalarType, typename VectorType>
-inline int elementwise_logic_op_broadcast_loop(int window_start_x, int window_end_x,
-                                               int window_step_x,
-                                               const ScalarType *non_broadcast_input_ptr,
-                                               const ScalarType &broadcast_value,
-                                               ScalarType *output_ptr, const bool reorder)
-{
-  int x = window_start_x;
-  for (; x <= (window_end_x - window_step_x); x += window_step_x)
-  {
-    const auto a = wrapper::vloadq((non_broadcast_input_ptr + x));
-    wrapper::vstore(output_ptr + x,
-                    elementwise_logic_op_broadcast<op>(a, broadcast_value, reorder));
-  }
-  return x;
-}
-
-template <BinaryLogicalOperation op, typename ScalarType, typename VectorType>
-void elementwise_logic_op(const ITensor *in1, const ITensor *in2, ITensor *out,
-                          const Window &window)
-{
-  elementwise_op(in1, in2, out, window, &elementwise_logic_op_scalar<op, ScalarType>,
-                 &elementwise_logic_op_broadcast_loop<op, ScalarType, VectorType>,
-                 &elementwise_logic_op_loop<op, ScalarType, VectorType>);
-}
-
-std::function<void(const ITensor *, const ITensor *, ITensor *, const Window &)> configure_func(
-  const ITensor *input1, const ITensor *input2, ITensor *output,
-  std::map<std::string, cpu::kernels::CpuElementwiseKernel::ElementwiseFunction *> map_function)
-{
-  std::string function_to_call("op_");
-  function_to_call += string_from_data_type(input1->info()->data_type()) + "_";
-  function_to_call += string_from_data_type(input2->info()->data_type()) + "_";
-  function_to_call += string_from_data_type(output->info()->data_type());
-
-  auto it = map_function.find(function_to_call);
-
-  if (it != map_function.end())
-  {
-    auto func = it->second;
-    return [func](const ITensor *input1, const ITensor *input2, ITensor *output,
-                  const Window &window) { func(input1, input2, output, window); };
-  }
-  return nullptr;
-}
-
-template <BinaryLogicalOperation op>
-std::function<void(const ITensor *, const ITensor *, ITensor *, const Window &)>
-configure_logic_func(const ITensor *input1, const ITensor *input2, ITensor *output)
-{
-  static std::map<std::string, cpu::kernels::CpuElementwiseKernel::ElementwiseFunction *>
-    map_function = {{"op_U8_U8_U8", &elementwise_logic_op<op, uint8_t, uint8x16_t>},
-                    {"op_QASYMM8_QASYMM8_QASYMM8", &elementwise_logic_op<op, uint8_t, uint8x16_t>}};
-
-  return configure_func(input1, input2, output, map_function);
-}
-
-void NEBinaryLogicalOperationKernel::configure(BinaryLogicalOperation op, const ITensor *input1,
-                                               const ITensor *input2, ITensor *output)
-{
-  ARM_COMPUTE_ERROR_THROW_ON(validate_arguments(*input1->info(), *input2->info(), *output->info()));
-  configure_common(input1->info(), input2->info(), output->info());
-  switch (op)
-  {
-    case BinaryLogicalOperation::AND:
-      _function = configure_logic_func<BinaryLogicalOperation::AND>(input1, input2, output);
-      break;
-    case BinaryLogicalOperation::OR:
-      _function = configure_logic_func<BinaryLogicalOperation::OR>(input1, input2, output);
-      break;
-    default:
-      ARM_COMPUTE_ERROR("NOT_SUPPORTED!");
-  }
-}
-
-Status NEBinaryLogicalOperationKernel::validate_arguments(const ITensorInfo &input1,
-                                                          const ITensorInfo &input2,
-                                                          const ITensorInfo &output)
-{
-  // Validate in case of configured output
-  if (output.total_size() > 0)
-  {
-    ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&output, 1, DataType::U8,
-                                                         DataType::QASYMM8);
-  }
-  ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input1, 1, DataType::U8, DataType::QASYMM8);
-  ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(&input2, 1, DataType::U8, DataType::QASYMM8);
-  ARM_COMPUTE_RETURN_ERROR_ON_MISMATCHING_DATA_TYPES(&input1, &input2);
-
-  const TensorShape out_shape =
-    TensorShape::broadcast_shape(input1.tensor_shape(), input2.tensor_shape());
-
-  ARM_COMPUTE_RETURN_ERROR_ON_MSG(out_shape.total_size() == 0,
-                                  "Inputs are not broadcast compatible");
-
-  // Validate in case of configured output
-  if (output.total_size() > 0)
-  {
-    ARM_COMPUTE_RETURN_ERROR_ON_MSG(
-      detail::have_different_dimensions(out_shape, output.tensor_shape(), 0),
-      "Wrong shape for output");
-  }
-
-  return Status{};
-}
-
-Status NEBinaryLogicalOperationKernel::validate(BinaryLogicalOperation op,
-                                                const ITensorInfo *input1,
-                                                const ITensorInfo *input2,
-                                                const ITensorInfo *output)
-{
-  ARM_COMPUTE_UNUSED(op);
-  ARM_COMPUTE_RETURN_ERROR_ON_NULLPTR(input1, input2, output);
-  ARM_COMPUTE_RETURN_ON_ERROR(validate_arguments(*input1, *input2, *output));
-  return Status{};
-}
-} // namespace arm_compute
index e56fbf7..04eb407 100644 (file)
@@ -105,8 +105,8 @@ bool isOnValue(U index, U depth)
 } // namespace
 
 NEOneHotKernel::NEOneHotKernel()
-  : _indices{nullptr}, _depth{nullptr}, _on_value{nullptr},
-    _off_value{nullptr}, _axis{-1}, _output{nullptr}, _func{}
+  : _indices{nullptr}, _depth{nullptr}, _on_value{nullptr}, _off_value{nullptr}, _axis{-1},
+    _output{nullptr}, _func{}
 {
 }
 
diff --git a/compute/ARMComputeEx/src/runtime/NEON/functions/NEBinaryLogicalOperation.cpp b/compute/ARMComputeEx/src/runtime/NEON/functions/NEBinaryLogicalOperation.cpp
deleted file mode 100644 (file)
index e6b7329..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Copyright (c) 2018-2019 ARM Limited.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <arm_compute/core/NEON/kernels/NEBinaryLogicalOperationKernel.h>
-#include "arm_compute/runtime/NEON/functions/NEBinaryLogicalOperation.h"
-
-#include "arm_compute/core/ITensor.h"
-
-#include <utility>
-
-namespace arm_compute
-{
-
-template <BinaryLogicalOperation COP>
-void NEBinaryLogicalOperationStatic<COP>::configure(ITensor *input1, ITensor *input2,
-                                                    ITensor *output)
-{
-  auto k = std::make_unique<NEBinaryLogicalOperationKernel>();
-  k->configure(COP, input1, input2, output);
-  _kernel = std::move(k);
-}
-
-template <BinaryLogicalOperation COP>
-Status NEBinaryLogicalOperationStatic<COP>::validate(const ITensorInfo *input1,
-                                                     const ITensorInfo *input2,
-                                                     const ITensorInfo *output)
-{
-  return NEBinaryLogicalOperationKernel::validate(COP, input1, input2, output);
-}
-
-void NEBinaryLogicalOperation::configure(ITensor *input1, ITensor *input2, ITensor *output,
-                                         BinaryLogicalOperation op)
-{
-  auto k = std::make_unique<NEBinaryLogicalOperationKernel>();
-  k->configure(op, input1, input2, output);
-  _kernel = std::move(k);
-}
-
-Status NEBinaryLogicalOperation::validate(const ITensorInfo *input1, const ITensorInfo *input2,
-                                          const ITensorInfo *output, BinaryLogicalOperation op)
-{
-  return NEBinaryLogicalOperationKernel::validate(op, input1, input2, output);
-}
-
-// Supported Specializations
-template class NEBinaryLogicalOperationStatic<BinaryLogicalOperation::AND>;
-template class NEBinaryLogicalOperationStatic<BinaryLogicalOperation::OR>;
-} // namespace arm_compute
index d464dcc..da7f37d 100644 (file)
@@ -22,6 +22,9 @@ target_include_directories(nnfw_lib_cker INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/i
 # TODO Resolve warning
 target_compile_options(nnfw_lib_cker INTERFACE -Wno-attributes)
 
+# Set EIGEN_NEON_GEBP_NR for arm 64bit
+target_compile_definitions(eigen INTERFACE EIGEN_NEON_GEBP_NR=4)
+
 if(NOT ENABLE_TEST)
   return()
 endif(NOT ENABLE_TEST)
index 45ad969..e4aecd0 100644 (file)
@@ -157,11 +157,11 @@ inline const int8_t *ShuffleVectors(const int8_t *vectors, const int n_batch, co
         "st4 {v0.s, v1.s, v2.s, v3.s}[2], [%[shuffled_vectors_ptr]], #16\n"
         "st4 {v0.s, v1.s, v2.s, v3.s}[3], [%[shuffled_vectors_ptr]], #16\n"
 
-        : [ unshuffled_vec0_ptr ] "+r"(unshuffled_vec0_ptr),
-          [ unshuffled_vec1_ptr ] "+r"(unshuffled_vec1_ptr),
-          [ unshuffled_vec2_ptr ] "+r"(unshuffled_vec2_ptr),
-          [ unshuffled_vec3_ptr ] "+r"(unshuffled_vec3_ptr),
-          [ shuffled_vectors_ptr ] "+r"(shuffled_vectors_ptr)
+        : [unshuffled_vec0_ptr] "+r"(unshuffled_vec0_ptr),
+          [unshuffled_vec1_ptr] "+r"(unshuffled_vec1_ptr),
+          [unshuffled_vec2_ptr] "+r"(unshuffled_vec2_ptr),
+          [unshuffled_vec3_ptr] "+r"(unshuffled_vec3_ptr),
+          [shuffled_vectors_ptr] "+r"(shuffled_vectors_ptr)
         :
         : "v0", "v1", "v2", "v3", "cc", "memory");
     }
@@ -296,10 +296,10 @@ static void DotprodMatrixBatchFourVectorMultiplyAccumulate(const int8_t *__restr
         "st2 {v9.s, v10.s}[1], [%[result_ptr]], %[wide_rows]\n"
         "st2 {v9.s, v10.s}[2], [%[result_ptr]], %[wide_rows]\n"
         "st2 {v9.s, v10.s}[3], [%[result_ptr]], %[wide_rows]\n"
-        : [ mat_ptr0 ] "+r"(mat_ptr0), [ mat_ptr1 ] "+r"(mat_ptr1), [ vec_ptr ] "+r"(vec_ptr),
-          [ result_ptr ] "+r"(result_ptr), [ mat_ptr2 ] "+r"(mat_ptr2), [ mat_ptr3 ] "+r"(mat_ptr3)
-        : [ mat_ptr0_end ] "r"(mat_ptr0_end), [ scaling_factors_ptr ] "r"(scaling_factors_ptr),
-          [ wide_rows ] "r"(wide_rows)
+        : [mat_ptr0] "+r"(mat_ptr0), [mat_ptr1] "+r"(mat_ptr1), [vec_ptr] "+r"(vec_ptr),
+          [result_ptr] "+r"(result_ptr), [mat_ptr2] "+r"(mat_ptr2), [mat_ptr3] "+r"(mat_ptr3)
+        : [mat_ptr0_end] "r"(mat_ptr0_end), [scaling_factors_ptr] "r"(scaling_factors_ptr),
+          [wide_rows] "r"(wide_rows)
         : "x0", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v12",
           "v13", "cc", "memory");
     }
@@ -419,13 +419,13 @@ static void DotprodMatrixBatchFourVectorMultiplyAccumulate(
         "st2 {v9.s, v10.s}[1], [%[result_ptr]], %[wide_rows]\n"
         "st2 {v9.s, v10.s}[2], [%[result_ptr]], %[wide_rows]\n"
         "st2 {v9.s, v10.s}[3], [%[result_ptr]], %[wide_rows]\n"
-        : [ mat_ptr0 ] "+r"(mat_ptr0), [ mat_ptr1 ] "+r"(mat_ptr1), [ vec_ptr ] "+r"(vec_ptr),
-          [ result_ptr ] "+r"(result_ptr), [ row_sums_ptr ] "+r"(row_sums_ptr)
-        : [ mat_ptr0_end ] "r"(mat_ptr0_end), [ scaling_factors_ptr ] "r"(scaling_factors_ptr),
-          [ wide_rows ] "r"(wide_rows), [ channel_scales_ptr ] "r"(channel_scales_ptr),
-          [ batch_offsets_ptr ] "r"(batch_offsets_ptr),
-          [ is_channel_scale_nullptr ] "r"(is_channel_scale_nullptr),
-          [ is_row_sums_nullptr ] "r"(is_row_sums_nullptr)
+        : [mat_ptr0] "+r"(mat_ptr0), [mat_ptr1] "+r"(mat_ptr1), [vec_ptr] "+r"(vec_ptr),
+          [result_ptr] "+r"(result_ptr), [row_sums_ptr] "+r"(row_sums_ptr)
+        : [mat_ptr0_end] "r"(mat_ptr0_end), [scaling_factors_ptr] "r"(scaling_factors_ptr),
+          [wide_rows] "r"(wide_rows), [channel_scales_ptr] "r"(channel_scales_ptr),
+          [batch_offsets_ptr] "r"(batch_offsets_ptr),
+          [is_channel_scale_nullptr] "r"(is_channel_scale_nullptr),
+          [is_row_sums_nullptr] "r"(is_row_sums_nullptr)
         : "x0", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11", "v12",
           "v13", "v14", "v15", "v16", "v17", "w0", "w1", "cc", "memory");
     }
index 3fd0cf5..35a5366 100644 (file)
@@ -80,17 +80,17 @@ enum class BroadcastableOpCategory : uint8_t
 
 struct PoolParams
 {
-  PaddingValues padding_values;
-  int stride_height;
-  int stride_width;
-  int filter_height;
-  int filter_width;
+  PaddingValues padding_values{0, 0};
+  int stride_height{0};
+  int stride_width{0};
+  int filter_height{0};
+  int filter_width{0};
   // uint8, etc, activation params.
-  int32_t quantized_activation_min;
-  int32_t quantized_activation_max;
+  int32_t quantized_activation_min{0};
+  int32_t quantized_activation_max{0};
   // float activation params.
-  float float_activation_min;
-  float float_activation_max;
+  float float_activation_min{0.0f};
+  float float_activation_max{0.0f};
 };
 
 struct SoftmaxParams
@@ -397,6 +397,12 @@ struct LeakyReluParams
   float alpha;
 };
 
+struct PadParams
+{
+  int32_t data[8];
+  int32_t rank;
+};
+
 enum class Order
 {
   kColMajor,
index e3b1099..5497f1e 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef __NNFW_CKER_EIGEN_EIGEN_SUPPORT_H__
 #define __NNFW_CKER_EIGEN_EIGEN_SUPPORT_H__
 
-//#if defined(CKER_OPTIMIZED_EIGEN)
+// #if defined(CKER_OPTIMIZED_EIGEN)
 
 #include <Eigen/Core>
 #include <thread>
@@ -117,6 +117,6 @@ inline const Eigen::ThreadPoolDevice *GetThreadPoolDevice()
 } // namespace cker
 } // namespace nnfw
 
-//#endif // defined(CKER_OPTIMIZED_EIGEN)
+// #endif // defined(CKER_OPTIMIZED_EIGEN)
 
 #endif // __NNFW_CKER_EIGEN_EIGEN_SUPPORT_H__
diff --git a/compute/cker/include/cker/eigen/depthwise_conv_op.h b/compute/cker/include/cker/eigen/depthwise_conv_op.h
new file mode 100644 (file)
index 0000000..d99ace0
--- /dev/null
@@ -0,0 +1,955 @@
+/*
+ * Copyright (c) 2024 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.
+ */
+
+#ifndef __NNFW_CKER_EIGEN_DEPTHWISE_CONV_OP_H__
+#define __NNFW_CKER_EIGEN_DEPTHWISE_CONV_OP_H__
+
+// From tensorflow/core/kernels/depthwise_conv_grad_op.cc
+#define EIGEN_USE_THREADS
+
+#include <thread>
+#include "unsupported/Eigen/CXX11/Tensor"
+#include "cker/operation/Helper/Tensor.h"
+
+// From tensorflow/core/kernels/depthwise_conv_op.h
+namespace nnfw
+{
+namespace cker
+{
+namespace depthwise_conv_op
+{
+
+template <typename Device, typename T> struct LaunchDepthwiseConvBackpropInputOp
+{
+  void operator()(int batch, int in_rows, int in_cols, int in_depth, int filter_rows,
+                  int filter_cols, int depth_multiplier, int stride, int pad_rows, int pad_cols,
+                  int out_rows, int out_cols, int out_depth, const T *out_backprop, const T *filter,
+                  T *in_backprop);
+};
+
+template <typename Device, typename T> struct LaunchDepthwiseConvBackpropFilterOp
+{
+  void operator()(int batch, int in_rows, int in_cols, int in_depth, int filter_rows,
+                  int filter_cols, int depth_multiplier, int stride, int pad_rows, int pad_cols,
+                  int out_rows, int out_cols, int out_depth, const T *out_backprop, const T *input,
+                  T *filter_backprop);
+};
+
+namespace functor
+{
+
+// Pads 'filter' to vector-register boundary along its inner dimension:
+//   filter_inner_dim_size = in_depth * depth_multiplier
+// Requires 'filter' to have the following storage order:
+//   [filter_rows, filter_cols, in_depth, depth_multiplier]
+// Returns zero-padded filter in 'padded_filter'.
+//
+// EX:
+//   in_depth = 3, depth_multiplier = 2, filter [2, 2], register_width = 4
+//   So we have a total of 3 * 2 = 6 filters, each of spatial size 2 x 2.
+//
+//   filter [rows, cols, in_depth, depth_multiplier]
+//     [u0, v0, w0, x0] [y0, z0, u1, v1] [w1, x1, y1, z1]
+//     [u2, v2, w2, x2] [y2, z2, u3, v3] [w3, x3, y3, z3]
+//
+//   padded_filter [rows, cols, in_depth, depth_multiplier]
+//     [u0, v0, w0, x0] [y0, z0, 0, 0] [u1, v1, w1, x1] [y1, z1, 0, 0]
+//     [u2, v2, w2, x2] [y2, z2, 0, 0] [u3, v3, w3, x3] [y3, z3, 0, 0]
+
+template <typename T> struct DepthwiseFilterPadOp
+{
+  void operator()(int, int, int, int, int filter_rows, int filter_cols, int, int, int, int, int,
+                  int, int out_depth, const T *filter, T *padded_filter)
+  {
+    typedef typename Eigen::internal::packet_traits<T>::type Packet;
+    static const int64_t kPacketSize = (sizeof(Packet) / sizeof(T));
+
+    // Calculate vectorized and scalar lengths of filter's inner dimension.
+    const int64_t filter_inner_dim_size = out_depth;
+    const int64_t vectorized_size = (filter_inner_dim_size / kPacketSize) * kPacketSize;
+    const int64_t scalar_size = filter_inner_dim_size - vectorized_size;
+    // Calculate required padding and padded output buffer stride.
+    const int64_t pad_size = scalar_size > 0 ? kPacketSize - scalar_size : 0;
+    const int64_t padded_filter_stride = vectorized_size + kPacketSize;
+
+    const int64_t filter_spatial_size = filter_rows * filter_cols;
+    for (int64_t i = 0; i < filter_spatial_size; ++i)
+    {
+      const int64_t input_base = i * filter_inner_dim_size;
+      const int64_t output_base = i * padded_filter_stride;
+      // Write vectorized length of filter's inner dimension to output.
+      for (int64_t j = 0; j < vectorized_size; j += kPacketSize)
+      {
+        const auto v = Eigen::internal::ploadu<Packet>(filter + input_base + j);
+        Eigen::internal::pstoreu<T>(padded_filter + output_base + j, v);
+      }
+      // Write scalar length of filter's inner dimension to output.
+      for (int64_t j = 0; j < scalar_size; ++j)
+      {
+        padded_filter[output_base + vectorized_size + j] = filter[input_base + vectorized_size + j];
+      }
+      // Pad the remainder of output to vector-register boundary.
+      for (int64_t j = 0; j < pad_size; ++j)
+      {
+        padded_filter[output_base + vectorized_size + scalar_size + j] = static_cast<T>(0);
+      }
+    }
+  }
+};
+
+// Copies data from local region in 'input' specified by 'out_r' and 'out_'c'
+// to 'input_buffer'. The copied data is replicated by factor
+// 'depth_multiplier', and padded to vector register-width boundaries so
+// that it is aligned for efficient traversal and vector multiply-add by the
+// depthwise kernel.
+//
+// EX:
+//   in_depth = 3, depth_multiplier = 2, filter [2, 2], register_width = 4
+//
+//   input: [batch, in_rows, in_cols, in_depth]
+//
+//     [a0, a1, a2, b0, b1, b2, ..., e0, e1, e2, f0, f1, f2, ...]
+//
+//   input_buffer (register boundaries shown):
+//     [a0, a0, a1, a1] [a2, a2, 0, 0]   in_row = 0, in_col = 0
+//     [b0, b0, b1, b1] [b2, b2, 0, 0]   in_row = 0, in_col = 1
+//     [e0, e0, e1, e1] [e2, e2, 0, 0]   in_row = 1, in_col = 0
+//     [f0, f0, f1, f1] [f2, f2, 0, 0]   in_row = 1, in_col = 1
+//
+// Returns replicated and padded data from specified input region in
+// 'input_buffer'.
+
+template <typename T> struct DepthwiseInputCopyOp
+{
+  void operator()(int, int in_rows, int in_cols, int in_depth, int filter_rows, int filter_cols,
+                  int depth_multiplier, int stride, int pad_rows, int pad_cols, int, int,
+                  int out_depth, const int64_t padded_filter_inner_dim_size, const int64_t out_r,
+                  const int64_t out_c, const T *input, T *input_buffer)
+  {
+    typedef typename Eigen::internal::packet_traits<T>::type Packet;
+    static const int64_t kPacketSize = Eigen::internal::packet_traits<T>::size;
+
+    const int64_t kDepth = depth_multiplier;
+    // Calculate vectorized and scalar (residual) lengths for 'in_depth'.
+    const int64_t input_vectorized_size = (in_depth / kPacketSize) * kPacketSize;
+    const int64_t input_scalar_size = in_depth - input_vectorized_size;
+
+    // Calculate output padding length.
+    const int64_t output_scalar_size = out_depth % kPacketSize;
+    const int64_t output_pad_size = output_scalar_size > 0 ? kPacketSize - output_scalar_size : 0;
+
+    // Iterate through all rows x cols reading 'in_depth' from 'input' and
+    // replicating by 'depth_multiplier' into 'input_buffer' (otherwise
+    // zero-padding input buffer as needed).
+    auto *in_buf = input_buffer;
+    const int64_t in_r_start = out_r * stride - pad_rows;
+    const int64_t in_c_start = out_c * stride - pad_cols;
+
+    // TODO: add a ploaddup variant for depth == 2 if needed.
+    if (kDepth > 1 && kDepth <= kPacketSize)
+    {
+      for (int64_t f_r = 0; f_r < filter_rows; ++f_r)
+      {
+        const int64_t in_r = in_r_start + f_r;
+
+        for (int64_t f_c = 0; f_c < filter_cols; ++f_c)
+        {
+          const int64_t in_c = in_c_start + f_c;
+
+          if (in_r >= 0 && in_r < in_rows && in_c >= 0 && in_c < in_cols)
+          {
+            const auto *in = input + (in_r * in_cols + in_c) * in_depth;
+            int64_t limit = in_depth;
+            // This will overwrite up to kPacketSize next elements,
+            // this is ok on all iterations except the last one, since
+            // we will write correct values on a next iteration.
+            if (f_c == filter_cols - 1)
+            {
+              limit -= (kPacketSize - kDepth) / kDepth + 1;
+              if (limit < 0)
+              {
+                limit = 0;
+              }
+            }
+            // Copy vectorized portion of inner dimension.
+            for (int64_t d = 0; d < limit; d++)
+            {
+              const auto p = Eigen::internal::pset1<Packet>(in[d]);
+              Eigen::internal::pstoreu<T>(in_buf, p);
+              in_buf += kDepth;
+            }
+
+            // Copy the scalar portion.
+            for (int64_t d = limit; d < in_depth; d++)
+            {
+              const auto value = in[d];
+              for (int64_t dm = 0; dm < kDepth; dm++)
+              {
+                in_buf[dm] = value;
+              }
+              in_buf += kDepth;
+            }
+
+            // Pad the remainder of the output to vector register boundary.
+            for (int64_t d = 0; d < output_pad_size; ++d)
+            {
+              in_buf[d] = static_cast<T>(0);
+            }
+            in_buf += output_pad_size;
+          }
+          else
+          {
+            // Zero pad.
+            memset(in_buf, 0, sizeof(T) * padded_filter_inner_dim_size);
+            in_buf += padded_filter_inner_dim_size;
+          }
+        }
+      }
+    }
+    else if (kDepth > kPacketSize)
+    {
+      // Calculate vectorized and scalar (residual) lengths for
+      // 'depth_multiplier'. This is used to efficiently replicate data for
+      // when 'depth_multiplier' > kPacketSize.
+      const int64_t dm_vectorized_size = (kDepth / kPacketSize) * kPacketSize;
+
+      for (int64_t f_r = 0; f_r < filter_rows; ++f_r)
+      {
+        const int64_t in_r = in_r_start + f_r;
+
+        for (int64_t f_c = 0; f_c < filter_cols; ++f_c)
+        {
+          const int64_t in_c = in_c_start + f_c;
+
+          if (in_r >= 0 && in_r < in_rows && in_c >= 0 && in_c < in_cols)
+          {
+            const auto *in = input + (in_r * in_cols + in_c) * in_depth;
+            // Copy vectorized portion of inner dimension.
+            for (int64_t d = 0; d < in_depth; d++)
+            {
+              const auto p = Eigen::internal::pset1<Packet>(in[d]);
+              for (int64_t dm = 0; dm < dm_vectorized_size; dm += kPacketSize)
+              {
+                Eigen::internal::pstoreu<T>(in_buf + dm, p);
+              }
+              // Overlapping store for the remainder.
+              Eigen::internal::pstoreu<T>(in_buf + kDepth - kPacketSize, p);
+              in_buf += kDepth;
+            }
+            // Pad the remainder of the output to vector register boundary.
+            for (int64_t d = 0; d < output_pad_size; ++d)
+            {
+              in_buf[d] = static_cast<T>(0);
+            }
+            in_buf += output_pad_size;
+          }
+          else
+          {
+            // Zero pad.
+            memset(in_buf, 0, sizeof(T) * padded_filter_inner_dim_size);
+            in_buf += padded_filter_inner_dim_size;
+          }
+        }
+      }
+    }
+    else if (kDepth == 1)
+    {
+      for (int64_t f_r = 0; f_r < filter_rows; ++f_r)
+      {
+        const int64_t in_r = in_r_start + f_r;
+
+        for (int64_t f_c = 0; f_c < filter_cols; ++f_c)
+        {
+          const int64_t in_c = in_c_start + f_c;
+
+          if (in_r >= 0 && in_r < in_rows && in_c >= 0 && in_c < in_cols)
+          {
+            const auto *in = input + (in_r * in_cols + in_c) * in_depth;
+            for (int64_t d = 0; d < input_vectorized_size; d += kPacketSize)
+            {
+              const auto p = Eigen::internal::ploadu<Packet>(in + d);
+              Eigen::internal::pstoreu<T>(in_buf, p);
+              in_buf += kPacketSize;
+            }
+            for (int64_t d = 0; d < input_scalar_size; ++d)
+            {
+              T v = in[input_vectorized_size + d];
+              in_buf[d] = v;
+            }
+            in_buf += input_scalar_size;
+
+            // Pad the remainder of the output to vector register boundary.
+            for (int64_t d = 0; d < output_pad_size; ++d)
+            {
+              in_buf[d] = static_cast<T>(0);
+            }
+            in_buf += output_pad_size;
+          }
+          else
+          {
+            // Zero pad.
+            memset(in_buf, 0, sizeof(T) * padded_filter_inner_dim_size);
+            in_buf += padded_filter_inner_dim_size;
+          }
+        }
+      }
+    }
+  }
+};
+
+} // namespace functor
+} // namespace depthwise_conv_op
+} // namespace cker
+} // namespace nnfw
+
+// From tensorflow/core/kernels/depthwise_conv_grad_op.cc
+namespace nnfw
+{
+namespace cker
+{
+namespace depthwise_conv_op
+{
+
+// Enable CPUDevice only for depthwise_conv_op
+using CPUDevice = Eigen::ThreadPoolDevice;
+
+// Copies data from local region in 'out_backprop' into 'buffer'.
+// The local region coordinates are calculated as the set of output points which
+// used the input point ('in_r', 'in_'c') as input during the forward pass.
+// Rather than spatially reversing the filter, the input is reversed during
+// the copy. The copied data is padded to vector register-width boundaries so
+// that it is aligned for efficient traversal and vector multiply-add by the
+// depthwise input kernel.
+//
+// EX:
+//   in_depth = 3, depth_multiplier = 2, filter [2, 2], register_width = 4
+//
+//   'out_backprop': [batch, out_rows, out_cols, out_depth]
+//
+//     [a00, a01, a10, a11] [a20, a21, b00, b01]
+//     [b10, b11, b20, b21] [...]
+//     [e00, e01, e10, e11] [e20, e21, f00, f01]
+//     [f10, f11, f20, f21] [...]
+//
+//   'buffer' (register boundaries shown):
+//
+//     [f00, f01, f10, f11] [f20, f21, 0, 0]   in_row = 0, in_col = 0
+//     [e00, e01, e10, e11] [e20, e21, 0, 0]   in_row = 0, in_col = 1
+//     [b00, b01, b10, b11] [b20, b21, 0, 0]   in_row = 1, in_col = 0
+//     [a00, a01, a10, a11] [a20, a21, 0, 0]   in_row = 1, in_col = 1
+//
+template <typename T>
+void CopyOutputBackpropRegion(int, int, int, int, int filter_rows_, int filter_cols_, int,
+                              int stride_, int pad_rows_, int pad_cols_, int out_rows_,
+                              int out_cols_, int out_depth,
+                              const int64_t padded_filter_inner_dim_size, const int64_t in_r,
+                              const int64_t in_c, const T *out_backprop, T *buffer)
+{
+  typedef typename Eigen::internal::packet_traits<T>::type Packet;
+  static const int64_t kPacketSize = (sizeof(Packet) / sizeof(T));
+
+  const int64_t stride = stride_;
+  const int64_t filter_rows = filter_rows_;
+  const int64_t filter_cols = filter_cols_;
+  const int64_t pad_rows = pad_rows_;
+  const int64_t pad_cols = pad_cols_;
+  const int64_t out_rows = out_rows_;
+  const int64_t out_cols = out_cols_;
+
+  // Calculate the output spatial region which used point (in_r, in_c) as input.
+  const int64_t out_r_start =
+    std::max(static_cast<int64_t>(0), (in_r - filter_rows + pad_rows + stride) / stride);
+  const int64_t out_r_end = std::min(out_rows - 1, (in_r + pad_rows) / stride);
+  const int64_t out_c_start =
+    std::max(static_cast<int64_t>(0), (in_c - filter_cols + pad_cols + stride) / stride);
+  const int64_t out_c_end = std::min(out_cols - 1, (in_c + pad_cols) / stride);
+
+  // Zero-pad 'buffer' if output region is smaller than filter spatial size.
+  const int64_t filter_spatial_size = filter_rows * filter_cols;
+  if ((out_r_end - out_r_start + 1) < filter_rows || (out_c_end - out_c_start + 1) < filter_cols)
+  {
+    memset(buffer, 0, filter_spatial_size * padded_filter_inner_dim_size * sizeof(T));
+  }
+
+  // Calculate vectorized and scalar (residual) lengths for 'in_depth'.
+  const int64_t vectorized_size = (out_depth / kPacketSize) * kPacketSize;
+  const int64_t scalar_size = out_depth % kPacketSize;
+  const int64_t pad_size = scalar_size > 0 ? kPacketSize - scalar_size : 0;
+
+  for (int out_r = out_r_start; out_r <= out_r_end; ++out_r)
+  {
+    const int64_t f_r = in_r + pad_rows - out_r * stride;
+    for (int out_c = out_c_start; out_c <= out_c_end; ++out_c)
+    {
+      const int64_t f_c = in_c + pad_cols - out_c * stride;
+      const int64_t buf_base = (f_r * filter_cols + f_c) * padded_filter_inner_dim_size;
+      // Calculate index into 'out_backprop' for coordinate (out_r, out_c).
+      auto *out_bprop = out_backprop + (out_r * out_cols + out_c) * out_depth;
+
+      // Copy vectorized portion of inner dimension into 'buffer'.
+      for (int64_t d = 0; d < vectorized_size; d += kPacketSize)
+      {
+        auto v = Eigen::internal::ploadu<Packet>(out_bprop + d);
+        Eigen::internal::pstoreu<T>(buffer + buf_base + d, v);
+      }
+      // Copy scalar portion of out_bprop to 'buffer'
+      for (int64_t d = 0; d < scalar_size; ++d)
+      {
+        buffer[buf_base + vectorized_size + d] = out_bprop[vectorized_size + d];
+      }
+      // Pad to vector-register width (if needed).
+      for (int64_t d = 0; d < pad_size; ++d)
+      {
+        buffer[buf_base + vectorized_size + scalar_size + d] = static_cast<T>(0);
+      }
+    }
+  }
+}
+
+// Computes the vectorized product of 'buffer' and 'filter' and stores
+// result in 'output' at location computed from 'in_r' and 'in_c'.
+// If depth_multiplier is > 1, the intermediate output is reduced along
+// the depth_multiplier dimension.
+//
+// EX:
+//   in_depth = 3, depth_multiplier = 2, filter [2, 2], register_width = 4
+//   Both 'input_buffer' and 'filter' are padded to register-width boundaries.
+//
+//   'buffer' [rows, cols, in_depth, depth_multiplier]
+//
+//     [f00, f01, f10, f11] [f20, f21, 0, 0]   in_row = 0, in_col = 0
+//     [e00, e01, e10, e11] [e20, e21, 0, 0]   in_row = 0, in_col = 1
+//     [b00, b01, b10, b11] [b20, b21, 0, 0]   in_row = 1, in_col = 0
+//     [a00, a01, a10, a11] [a20, a21, 0, 0]   in_row = 1, in_col = 1
+//
+//   filter [rows, cols, in_depth, depth_multiplier]
+//     [u0, v0, w0, x0] [y0, z0, 0, 0] [u1, v1, w1, x1] [y1, z1, 0, 0]
+//     [u2, v2, w2, x2] [y2, z2, 0, 0] [u3, v3, w3, x3] [y3, z3, 0, 0]
+//
+//   First output register [in_depth, depth_multiplier]
+//     [q00, q01, q10, q11] = ([f00, f01, f10, f11] x [u0, v0, w0, x0]) +
+//                            ([e00, e01, e10, e11] x [u1, v1, w1, x1]) +
+//                            ([b00, b01, b10, b11] x [u2, v2, w2, x2]) +
+//                            ([a00, a01, a10, a11] x [u3, v3, w3, x3])
+//
+//   Reduction step along depth-multiplier dimension:
+//
+//     [q00, q01, q10, q11] [q20, q21, 0, 0] -> [r0, r1, r2, 0]
+//
+
+template <typename T>
+void ComputeBackpropInput(int, int, int in_cols, int in_depth_, int filter_rows, int filter_cols,
+                          int depth_multiplier_, int, int, int, int, int, int out_depth_,
+                          const int64_t padded_filter_inner_dim_size, const int64_t in_r,
+                          const int64_t in_c, const T *filter, const T *buffer, T *out_buffer,
+                          T *output)
+{
+  typedef typename Eigen::internal::packet_traits<T>::type Packet;
+  static const int64_t kPacketSize = (sizeof(Packet) / sizeof(T));
+
+  const int64_t in_depth = in_depth_;
+  const int64_t depth_multiplier = depth_multiplier_;
+  const int64_t out_depth = out_depth_;
+  const int64_t filter_spatial_size = filter_rows * filter_cols;
+
+  // Calculate vectorized and scalar lengths of 'out_depth'.
+  const int64_t output_vectorized_size = (out_depth / kPacketSize) * kPacketSize;
+  const int64_t output_scalar_size = out_depth % kPacketSize;
+
+  // Calculate base index at which to begin writing output.
+  const int64_t base_output_index = (in_r * in_cols + in_c) * in_depth;
+
+  // Calculate vectorized and scalar lengths for 'depth_multiplier'. This is
+  // used to efficiently reduce output when 'depth_multiplier' > kPacketSize.
+  const int64_t dm_vectorized_size = (depth_multiplier / kPacketSize) * kPacketSize;
+  const int64_t dm_scalar_size = depth_multiplier % kPacketSize;
+
+  for (int i = 0; i < output_vectorized_size; i += kPacketSize)
+  {
+    // Reset accumulator.
+    auto vaccum = Eigen::internal::pset1<Packet>(static_cast<T>(0));
+    for (int j = 0; j < filter_spatial_size; ++j)
+    {
+      // Calculate index.
+      const int64_t index = i + j * padded_filter_inner_dim_size;
+      // Load filter.
+      const auto filter_block = Eigen::internal::ploadu<Packet>(filter + index);
+      // Load input.
+      const auto data_block = Eigen::internal::ploadu<Packet>(buffer + index);
+      // Vector multiply-add.
+      vaccum = Eigen::internal::pmadd<Packet>(filter_block, data_block, vaccum);
+    }
+    if (depth_multiplier == 1)
+    {
+      // Write directly to the output.
+      Eigen::internal::pstoreu<T>(output + base_output_index + i, vaccum);
+    }
+    else
+    {
+      // Buffer output for subsequent reduction step.
+      Eigen::internal::pstoreu<T>(out_buffer + i, vaccum);
+    }
+  }
+
+  if (output_scalar_size > 0)
+  {
+    auto vaccum = Eigen::internal::pset1<Packet>(static_cast<T>(0));
+    for (int j = 0; j < filter_spatial_size; ++j)
+    {
+      const int64_t index = output_vectorized_size + j * padded_filter_inner_dim_size;
+      const auto filter_block = Eigen::internal::ploadu<Packet>(filter + index);
+      const auto data_block = Eigen::internal::ploadu<Packet>(buffer + index);
+      vaccum = Eigen::internal::pmadd<Packet>(filter_block, data_block, vaccum);
+    }
+    // Load accumulator into an array and loop through output.
+    T out_buf[kPacketSize];
+    Eigen::internal::pstoreu<T>(out_buf, vaccum);
+    if (depth_multiplier == 1)
+    {
+      // Write directly to the output.
+      for (int j = 0; j < output_scalar_size; ++j)
+      {
+        output[base_output_index + output_vectorized_size + j] = out_buf[j];
+      }
+    }
+    else
+    {
+      // Buffer output for subsequent reduction step.
+      for (int j = 0; j < output_scalar_size; ++j)
+      {
+        out_buffer[output_vectorized_size + j] = out_buf[j];
+      }
+    }
+  }
+
+  // Iterate over 'in_depth', reduce over 'depth_multiplier', write 'output'.
+  if (depth_multiplier > 1)
+  {
+    for (int64_t d = 0; d < in_depth; ++d)
+    {
+      const int64_t index = d * depth_multiplier;
+      T accum = static_cast<T>(0);
+      for (int64_t dm = 0; dm < dm_vectorized_size; dm += kPacketSize)
+      {
+        const auto v = Eigen::internal::ploadu<Packet>(out_buffer + index + dm);
+        accum += Eigen::internal::predux(v);
+      }
+      // Copy scalar portion of replicated output.
+      for (int64_t dm = 0; dm < dm_scalar_size; ++dm)
+      {
+        accum += out_buffer[index + dm_vectorized_size + dm];
+      }
+      // Copy to output.
+      output[base_output_index + d] = accum;
+    }
+  }
+}
+
+// Computes the depthwise conv2d backprop input of 'out_backprop' by
+// 'depthwise_filter' and stores the result in 'in_backprop'.
+template <typename T> struct LaunchDepthwiseConvBackpropInputOp<CPUDevice, T>
+{
+  typedef typename Eigen::internal::packet_traits<T>::type Packet;
+
+  void operator()(int batch, int in_rows, int in_cols, int in_depth, int filter_rows,
+                  int filter_cols, int depth_multiplier, int stride, int pad_rows, int pad_cols,
+                  int out_rows, int out_cols, int out_depth, const T *out_backprop,
+                  const T *depthwise_filter, T *padded_filter_data, T *in_backprop, bool pad_filter,
+                  T *out_bprop, T *in_bprop)
+  {
+    const Eigen::ThreadPoolDevice &d = *eigen_support::GetThreadPoolDevice();
+
+    // Pad 'depthwise_filter' to vector register width (if needed).
+    if (pad_filter)
+    {
+      // Write out padded filter.
+      functor::DepthwiseFilterPadOp<T>()(
+        batch, in_rows, in_cols, in_depth, filter_rows, filter_cols, depth_multiplier, stride,
+        pad_rows, pad_cols, out_rows, out_cols, out_depth, depthwise_filter, padded_filter_data);
+    }
+    const T *filter_data = pad_filter ? padded_filter_data : depthwise_filter;
+
+    // Computes one shard of depthwise conv2d backprop input.
+    auto shard = [d, in_rows, in_cols, in_depth, out_rows, out_cols, out_depth, batch, filter_rows,
+                  filter_cols, depth_multiplier, stride, pad_rows, pad_cols, out_backprop,
+                  filter_data, in_backprop, out_bprop, in_bprop](int64_t start, int64_t limit) {
+      static const int64_t kPacketSize = (sizeof(Packet) / sizeof(T));
+
+      const int64_t input_image_size = in_rows * in_cols * in_depth;
+      const int64_t output_image_size = out_rows * out_cols * out_depth;
+      const int64_t filter_spatial_size = filter_rows * filter_cols;
+      const int64_t padded_filter_inner_dim_size =
+        ((out_depth + kPacketSize - 1) / kPacketSize) * kPacketSize;
+      const int64_t out_bprop_size = filter_spatial_size * padded_filter_inner_dim_size;
+
+      int cur_id = d.currentThreadId() + 1;
+      assert(cur_id >= 0 && cur_id < d.numThreads() + 1);
+
+      // Use out_bprop buffer to copy regions from 'out_backprop'.
+      T *out_bprop_buf = out_bprop + cur_id * out_bprop_size;
+
+      // Use in_bprop buffer for intermediate results.
+      T *in_bprop_buf = in_bprop + cur_id * padded_filter_inner_dim_size;
+
+      for (int64_t b = start; b < limit; ++b)
+      {
+        for (int64_t in_r = 0; in_r < in_rows; ++in_r)
+        {
+          for (int64_t in_c = 0; in_c < in_cols; ++in_c)
+          {
+            // Populate 'out_bprop_buf' from local 'out_backprop' region.
+            CopyOutputBackpropRegion<T>(batch, in_rows, in_cols, in_depth, filter_rows, filter_cols,
+                                        depth_multiplier, stride, pad_rows, pad_cols, out_rows,
+                                        out_cols, out_depth, padded_filter_inner_dim_size, in_r,
+                                        in_c, out_backprop + b * output_image_size, out_bprop_buf);
+
+            // Compute depthwise backprop input.
+            ComputeBackpropInput<T>(
+              batch, in_rows, in_cols, in_depth, filter_rows, filter_cols, depth_multiplier, stride,
+              pad_rows, pad_cols, out_rows, out_cols, out_depth, padded_filter_inner_dim_size, in_r,
+              in_c, filter_data, out_bprop_buf, in_bprop_buf, in_backprop + b * input_image_size);
+          }
+        }
+      }
+    };
+
+    const int64_t input_bytes = out_rows * out_cols * out_depth * sizeof(T);
+    const int64_t output_bytes = in_rows * in_cols * in_depth * sizeof(T);
+    const int64_t compute_cycles = in_rows * in_cols * out_depth * batch;
+    const Eigen::TensorOpCost cost(input_bytes, output_bytes, compute_cycles);
+    d.parallelFor(batch, cost, shard);
+  }
+};
+
+template <typename T>
+void DepthwiseConvBackpropInputReference(int batch, int in_rows, int in_cols, int in_depth,
+                                         int out_rows, int out_cols, int out_depth, int stride,
+                                         int depth_multiplier, int filter_rows, int filter_cols,
+                                         int pad_rows, int pad_cols, const T *out_backprop,
+                                         const T *filter, T *in_backprop)
+{
+  // Naive for loop as a reference point without concerns about performance.
+  for (int b = 0; b < batch; ++b)
+  {
+    for (int in_r = 0; in_r < in_rows; ++in_r)
+    {
+      for (int in_c = 0; in_c < in_cols; ++in_c)
+      {
+        for (int in_d = 0; in_d < in_depth; ++in_d)
+        {
+          T sum = 0;
+          const int out_d_start = in_d * depth_multiplier;
+          const int out_d_end = out_d_start + depth_multiplier;
+
+          for (int out_d = out_d_start; out_d < out_d_end; ++out_d)
+          {
+            const int out_r_start = std::max(0, (in_r - filter_rows + pad_rows + stride) / stride);
+            const int out_r_end = std::min(out_rows - 1, (in_r + pad_rows) / stride);
+
+            for (int out_r = out_r_start; out_r <= out_r_end; ++out_r)
+            {
+              const int out_c_start =
+                std::max(0, (in_c - filter_cols + pad_cols + stride) / stride);
+              const int out_c_end = std::min(out_cols - 1, (in_c + pad_cols) / stride);
+
+              for (int out_c = out_c_start; out_c <= out_c_end; ++out_c)
+              {
+                int f_r = in_r + pad_rows - out_r * stride;
+                int f_c = in_c + pad_cols - out_c * stride;
+                int filter_dm = out_d - out_d_start;
+                int out_backprop_offset =
+                  out_d + out_depth * (out_c + out_cols * (out_r + out_rows * b));
+                int filter_offset =
+                  filter_dm + depth_multiplier * (in_d + in_depth * (f_c + filter_cols * f_r));
+                sum += out_backprop[out_backprop_offset] * filter[filter_offset];
+              }
+            }
+          }
+
+          int in_backprop_offset = in_d + in_depth * (in_c + in_cols * (in_r + in_rows * b));
+          in_backprop[in_backprop_offset] = sum;
+        }
+      }
+    }
+  }
+}
+
+// Kernels to compute the gradients of the filters for depthwise convolution.
+
+// Computes filter backprop using 'out_backprop' and 'input_buffer', storing the
+// result in 'output_buffer' at an index computed from 'out_r' and 'out_c'.
+//
+// EX:
+//   in_depth = 3, depth_multiplier = 2, filter [2, 2], register_width = 4
+//   Both 'input_buffer' and 'filter' are padded to register-width boundaries.
+//
+//   'input_buffer' [rows, cols, in_depth, depth_multiplier]
+//
+//     [f00, f01, f10, f11] [f20, f21, 0, 0]   in_row = 0, in_col = 0
+//     [e00, e01, e10, e11] [e20, e21, 0, 0]   in_row = 0, in_col = 1
+//     [b00, b01, b10, b11] [b20, b21, 0, 0]   in_row = 1, in_col = 0
+//     [a00, a01, a10, a11] [a20, a21, 0, 0]   in_row = 1, in_col = 1
+//
+//   'out_backprop' [out_rows, out_cols, in_depth, depth_multiplier]
+//
+//     [q00, q01, q10, q11] [q20, q21, r00, r01]
+//     [r10, r11, r20, r21] [s00, s01, s10, s11]
+//     [s20, s21, t00, t01] [t10, t11, t20, a21]
+//
+//   First output register of 'filter_backprop'
+//     [u0, v0, w0, x0] += ([f00, f01, f10, f11] x [q00, q01, q10, q11])
+//
+template <typename T>
+void ComputeBackpropFilter(int, int, int, int, int filter_rows, int filter_cols, int, int, int, int,
+                           int out_rows, int out_cols, int out_depth_,
+                           const int64_t padded_out_depth_size, const int64_t out_r,
+                           const int64_t out_c, const T *out_backprop, const T *input_buffer,
+                           T *output_buffer)
+{
+  typedef typename Eigen::internal::packet_traits<T>::type Packet;
+  static const int64_t kPacketSize = (sizeof(Packet) / sizeof(T));
+  // Calculate vectorized size of 'padded_out_depth_size'.
+  const int64_t out_depth = out_depth_;
+  const int64_t filter_spatial_size = filter_rows * filter_cols;
+  const int64_t output_vectorized_size = (padded_out_depth_size / kPacketSize) * kPacketSize;
+  const int64_t base_output_index = (out_r * out_cols + out_c) * out_depth;
+  // Determine whether we can execute fast or slow code path.
+  const int64_t output_image_size = out_rows * out_cols * out_depth;
+  const int64_t output_last_vector_index =
+    output_image_size - (filter_spatial_size * padded_out_depth_size);
+  const bool fast_path = base_output_index <= output_last_vector_index;
+
+  if (fast_path)
+  {
+    // TODO(andydavis) Process multiple inputs in 'input_buffer' so we can
+    // amortize the cost of 'output_buffer' load store in the loop below.
+    for (int i = 0; i < output_vectorized_size; i += kPacketSize)
+    {
+      // Load vector register from 'out_backprop'.
+      const auto out_bprop_block =
+        Eigen::internal::ploadu<Packet>(out_backprop + base_output_index + i);
+      for (int j = 0; j < filter_spatial_size; ++j)
+      {
+        const int64_t index = i + j * padded_out_depth_size;
+        // Load vector register from 'input_buffer'.
+        const auto input_block = Eigen::internal::ploadu<Packet>(input_buffer + index);
+        // Load output block into vector register.
+        auto out_block_data = output_buffer + index;
+        auto out_block = Eigen::internal::ploadu<Packet>(out_block_data);
+        // Vector multiply-add.
+        out_block = Eigen::internal::pmadd<Packet>(out_bprop_block, input_block, out_block);
+        // Store 'out_block' back to memory.
+        Eigen::internal::pstoreu<T>(out_block_data, out_block);
+      }
+    }
+  }
+  else
+  {
+    // Slow path (cant do vector reads from non-padded 'out_backprop'.
+    for (int i = 0; i < output_vectorized_size; i += kPacketSize)
+    {
+      // Calculate safe read size from 'out_backprop'.
+      const int64_t out_bprop_index = base_output_index + i;
+      const int64_t out_bprop_limit = std::min(output_image_size, out_bprop_index + kPacketSize);
+      T out_buf[kPacketSize];
+      memset(&out_buf, 0, kPacketSize * sizeof(T));
+      const int64_t scalar_size = out_bprop_limit - out_bprop_index;
+      for (int64_t j = 0; j < scalar_size; ++j)
+      {
+        out_buf[j] = out_backprop[out_bprop_index + j];
+      }
+      // Load vector register from 'out_buf'.
+      const auto out_bprop_block = Eigen::internal::ploadu<Packet>(out_buf);
+      for (int j = 0; j < filter_spatial_size; ++j)
+      {
+        const int64_t index = i + j * padded_out_depth_size;
+        // Load vector register from 'input_buffer'.
+        const auto input_block = Eigen::internal::ploadu<Packet>(input_buffer + index);
+        // Load output block into vector register.
+        auto out_block_data = output_buffer + index;
+        auto out_block = Eigen::internal::ploadu<Packet>(out_block_data);
+        // Vector multiply-add.
+        out_block = Eigen::internal::pmadd<Packet>(out_bprop_block, input_block, out_block);
+        // Store 'out_block' back to memory.
+        Eigen::internal::pstoreu<T>(out_block_data, out_block);
+      }
+    }
+  }
+}
+
+template <typename T> struct LaunchDepthwiseConvBackpropFilterOp<CPUDevice, T>
+{
+  typedef typename Eigen::internal::packet_traits<T>::type Packet;
+
+  void operator()(int batch, int in_rows, int in_cols, int in_depth, int filter_rows,
+                  int filter_cols, int depth_multiplier, int stride, int pad_rows, int pad_cols,
+                  int out_rows, int out_cols, int out_depth, const T *out_backprop, const T *input,
+                  T *filter_backprop, T *padded_filter_data, T *in_bprop)
+  {
+    const Eigen::ThreadPoolDevice &d = *eigen_support::GetThreadPoolDevice();
+
+    static const int64_t kPacketSize = (sizeof(Packet) / sizeof(T));
+
+    const int64_t filter_spatial_size = filter_rows * filter_cols;
+    const int64_t padded_out_depth_size =
+      ((out_depth + kPacketSize - 1) / kPacketSize) * kPacketSize;
+
+    T *output_buffer_data = padded_filter_data;
+
+    // Computes one shard of depthwise conv2d backprop filter.
+    // auto shard = [&ctx, &args, &out_backprop, &input, &output_buffer_data](
+    auto shard = [&](int64_t start, int64_t limit) {
+      static const int64_t kPacketSize = (sizeof(Packet) / sizeof(T));
+      const int64_t filter_spatial_size = filter_rows * filter_cols;
+      const int64_t padded_out_depth_size =
+        ((out_depth + kPacketSize - 1) / kPacketSize) * kPacketSize;
+
+      int cur_id = d.currentThreadId() + 1;
+      assert(cur_id >= 0 && cur_id < d.numThreads() + 1);
+
+      const int64_t input_image_size = in_rows * in_cols * in_depth;
+      const int64_t output_image_size = out_rows * out_cols * out_depth;
+      const int64_t padded_filter_size = filter_spatial_size * padded_out_depth_size;
+
+      T *input_buffer_data = in_bprop + cur_id * padded_filter_size;
+
+      for (int b = start; b < limit; ++b)
+      {
+        // Initialize 'output_buffer' for 'b'.
+        auto *output_buffer = output_buffer_data + b * padded_filter_size;
+        memset(output_buffer, 0, padded_filter_size * sizeof(T));
+
+        for (int out_r = 0; out_r < out_rows; ++out_r)
+        {
+          for (int out_c = 0; out_c < out_cols; ++out_c)
+          {
+            // Populate 'input_buffer_data' with data from local input region.
+            functor::DepthwiseInputCopyOp<T>()(
+              batch, in_rows, in_cols, in_depth, filter_rows, filter_cols, depth_multiplier, stride,
+              pad_rows, pad_cols, out_rows, out_cols, out_depth, padded_out_depth_size, out_r,
+              out_c, input + b * input_image_size, input_buffer_data);
+            // Compute depthwise backprop filter.
+            ComputeBackpropFilter(
+              batch, in_rows, in_cols, in_depth, filter_rows, filter_cols, depth_multiplier, stride,
+              pad_rows, pad_cols, out_rows, out_cols, out_depth, padded_out_depth_size, out_r,
+              out_c, out_backprop + b * output_image_size, input_buffer_data, output_buffer);
+          }
+        }
+      }
+    };
+
+    const int64_t input_bytes = in_rows * in_cols * in_depth * sizeof(T);
+    const int64_t output_bytes = out_rows * out_cols * out_depth * sizeof(T);
+    const int64_t compute_cycles = out_rows * out_cols * out_depth * batch;
+    const Eigen::TensorOpCost cost(input_bytes, output_bytes, compute_cycles);
+    d.parallelFor(batch, cost, shard);
+
+    // Accumulate 'output_buffer' from each shard into 'output'.
+    // const int64_t out_depth = out_depth;
+    const int64_t vectorized_size = (out_depth / kPacketSize) * kPacketSize;
+    const int64_t scalar_size = out_depth - vectorized_size;
+    const int64_t padded_filter_size = filter_spatial_size * padded_out_depth_size;
+    memset(filter_backprop, 0, filter_spatial_size * out_depth * sizeof(T));
+
+    for (int64_t i = 0; i < filter_spatial_size; ++i)
+    {
+      const int64_t buffer_base = i * padded_out_depth_size;
+      const int64_t output_base = i * out_depth;
+      // Write vectorized length of filter's inner dimension to output.
+      for (int64_t j = 0; j < vectorized_size; j += kPacketSize)
+      {
+        // Load data from 'filter_backprop' into vector register.
+        auto out_block_data = filter_backprop + output_base + j;
+        auto out_block = Eigen::internal::ploadu<Packet>(out_block_data);
+        for (int b = 0; b < batch; ++b)
+        {
+          // Load data from 'output_buffer' for 'b'.
+          const auto *output_buffer = output_buffer_data + b * padded_filter_size;
+          const auto v = Eigen::internal::ploadu<Packet>(output_buffer + buffer_base + j);
+          // Add 'v' to 'out_block'.
+          out_block = Eigen::internal::padd<Packet>(out_block, v);
+        }
+        // Store 'out_block' back to memory.
+        Eigen::internal::pstoreu<T>(out_block_data, out_block);
+      }
+      // Write scalar length of filter's inner dimension to output.
+      for (int64_t j = 0; j < scalar_size; ++j)
+      {
+        for (int b = 0; b < batch; ++b)
+        {
+          const auto *output_buffer = output_buffer_data + b * padded_filter_size;
+          filter_backprop[output_base + vectorized_size + j] +=
+            output_buffer[buffer_base + vectorized_size + j];
+        }
+      }
+    }
+  }
+};
+
+template <typename T>
+void DepthwiseConvBackpropFilterReference(int batch, int in_rows, int in_cols, int in_depth,
+                                          int out_rows, int out_cols, int out_depth, int stride,
+                                          int depth_multiplier, int filter_rows, int filter_cols,
+                                          int pad_rows, int pad_cols, const T *out_backprop,
+                                          const T *input, T *filter_backprop)
+{
+  int num_filter_backprop = filter_rows * filter_cols * in_depth * depth_multiplier;
+  memset(filter_backprop, 0, num_filter_backprop * sizeof(T));
+  // Naive for loop as a reference point without concerns about performance.
+  for (int b = 0; b < batch; ++b)
+  {
+    for (int out_r = 0; out_r < out_rows; ++out_r)
+    {
+      for (int out_c = 0; out_c < out_cols; ++out_c)
+      {
+        for (int out_d = 0; out_d < out_depth; ++out_d)
+        {
+          const int in_d = out_d / depth_multiplier;
+          const int dm = out_d % depth_multiplier;
+          const int in_r_start = out_r * stride - pad_rows;
+          const int in_c_start = out_c * stride - pad_cols;
+
+          for (int f_r = 0; f_r < filter_rows; ++f_r)
+          {
+            for (int f_c = 0; f_c < filter_cols; ++f_c)
+            {
+              const int in_r = in_r_start + f_r;
+              const int in_c = in_c_start + f_c;
+
+              if (in_r >= 0 && in_r < in_rows && in_c >= 0 && in_c < in_cols)
+              {
+                int out_backprop_offset =
+                  out_d + out_depth * (out_c + out_cols * (out_r + out_rows * b));
+                int input_offset = in_d + in_depth * (in_c + in_cols * (in_r + in_rows * b));
+                int filter_backprop_offset =
+                  dm + depth_multiplier * (in_d + in_depth * (f_c + filter_cols * f_r));
+                filter_backprop[filter_backprop_offset] +=
+                  input[input_offset] * out_backprop[out_backprop_offset];
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+} // namespace depthwise_conv_op
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_EIGEN_DEPTHWISE_CONV_OP_H__
diff --git a/compute/cker/include/cker/eigen/eigen_backward_spatial_convolutions.h b/compute/cker/include/cker/eigen/eigen_backward_spatial_convolutions.h
new file mode 100644 (file)
index 0000000..163c4db
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * 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.
+ */
+
+#ifndef __NNFW_CKER_EGIEN_EIGEN_BACKWARD_SPATIAL_CONVOLUTIONS_H__
+#define __NNFW_CKER_EGIEN_EIGEN_BACKWARD_SPATIAL_CONVOLUTIONS_H__
+
+#include "unsupported/Eigen/CXX11/Tensor"
+#include "eigen_spatial_convolutions.h"
+
+namespace Eigen
+{
+
+/** SpatialConvolutionBackwardInput
+ * \ingroup CXX11_NeuralNetworks_Module
+ *
+ * \brief Computes the backprop for the input of a 2D convolution.
+ *
+ * The output_backward parameter is expected to be a tensor with a rank of 3 or
+ * more (channels, height, width, and optionally others)
+ * The kernel parameter is expected to be a 4D tensor (filters, channels,
+ * kernel_height, kernel_width)
+ * The output_backward and the kernel must both be in col-major layout. The
+ * result will also be in col-major layout.
+ *
+ * If row_in_stride, col_in_stride > 1, then applies convolution with holes
+ * (aka atrous convolution), sampling every row_in_stride, col_in_stride input
+ * pixels.
+ *
+ * The result can be assigned to a tensor of rank equal to the rank of the
+ * output_backward. The dimensions of the result will be filters, height, width
+ * (and others if applicable).
+ *
+ * It is possible to swap the order of the width and height dimensions provided
+ * that the same order is used in the input, the kernel, and the output.
+ *
+ */
+typedef IndexList<type2index<0>, type2index<0>, type2index<1>, type2index<1>> ReverseColMajor;
+typedef IndexList<type2index<1>, type2index<1>, type2index<0>, type2index<0>> ReverseRowMajor;
+
+template <typename OutputBackward, typename Kernel>
+EIGEN_ALWAYS_INLINE static const std::conditional_t<
+  internal::traits<OutputBackward>::Layout == ColMajor,
+  TensorReshapingOp<
+    const DSizes<typename internal::traits<OutputBackward>::Index,
+                 internal::traits<OutputBackward>::NumDimensions>,
+    const TensorContractionOp<
+      const array<IndexPair<typename internal::traits<OutputBackward>::Index>, 1>,
+      const TensorReshapingOp<const DSizes<typename internal::traits<OutputBackward>::Index, 2>,
+                              const Eigen::TensorForcedEvalOp<const TensorShufflingOp<
+                                const array<typename internal::traits<OutputBackward>::Index, 4>,
+                                const Eigen::TensorForcedEvalOp<
+                                  const TensorReverseOp<const ReverseColMajor, const Kernel>>>>>,
+      const TensorReshapingOp<const DSizes<typename internal::traits<OutputBackward>::Index, 2>,
+                              const TensorImagePatchOp<Dynamic, Dynamic, const OutputBackward>>>>,
+  TensorReshapingOp<
+
+    const DSizes<typename internal::traits<OutputBackward>::Index,
+                 internal::traits<OutputBackward>::NumDimensions>,
+    const TensorContractionOp<
+      const array<IndexPair<typename internal::traits<OutputBackward>::Index>, 1>,
+      const TensorReshapingOp<const DSizes<typename internal::traits<OutputBackward>::Index, 2>,
+                              const TensorImagePatchOp<Dynamic, Dynamic, const OutputBackward>>,
+      const TensorReshapingOp<const DSizes<typename internal::traits<OutputBackward>::Index, 2>,
+                              const Eigen::TensorForcedEvalOp<const TensorShufflingOp<
+                                const array<typename internal::traits<OutputBackward>::Index, 4>,
+                                const Eigen::TensorForcedEvalOp<
+                                  const TensorReverseOp<const ReverseRowMajor, const Kernel>>>>>>>>
+SpatialConvolutionBackwardInput(const Kernel &kernel, const OutputBackward &output_backward,
+                                typename internal::traits<OutputBackward>::Index inputRows,
+                                typename internal::traits<OutputBackward>::Index inputCols,
+                                const DenseIndex row_stride = 1, const DenseIndex col_stride = 1,
+                                const DenseIndex row_in_stride = 1,
+                                const DenseIndex col_in_stride = 1)
+{
+  typedef typename internal::traits<OutputBackward>::Index TensorIndex;
+  typedef typename internal::traits<OutputBackward>::Scalar OutScalar;
+  TensorRef<
+    Tensor<typename internal::traits<Kernel>::Scalar, internal::traits<Kernel>::NumDimensions,
+           internal::traits<Kernel>::Layout, TensorIndex>>
+    kern(kernel);
+  TensorRef<Tensor<OutScalar, internal::traits<OutputBackward>::NumDimensions,
+                   internal::traits<OutputBackward>::Layout, TensorIndex>>
+    out(output_backward);
+
+  EIGEN_STATIC_ASSERT(internal::traits<Kernel>::Layout == internal::traits<OutputBackward>::Layout,
+                      YOU_MADE_A_PROGRAMMING_MISTAKE);
+
+  static const bool isColMajor = (internal::traits<OutputBackward>::Layout == ColMajor);
+
+  static const int NumDims = internal::traits<OutputBackward>::NumDimensions;
+
+  // Number of filters to apply. This is the same as the output depth of the
+  // result
+  const TensorIndex kernelFilters = isColMajor ? kern.dimensions()[0] : kern.dimensions()[3];
+  // Number of channels. This is the same as the input depth.
+  const TensorIndex kernelChannels = isColMajor ? kern.dimensions()[1] : kern.dimensions()[2];
+  const TensorIndex kernelRows = isColMajor ? kern.dimensions()[2] : kern.dimensions()[1];
+  const TensorIndex kernelCols = isColMajor ? kern.dimensions()[3] : kern.dimensions()[0];
+
+  // This is the effective kernel size, taking into account the (*_in_stride -
+  // 1) zero-values
+  // inserted between consecutive kernel elements in atrous convolution
+  const TensorIndex kernelRowsEff = kernelRows + (kernelRows - 1) * (row_in_stride - 1);
+  const TensorIndex kernelColsEff = kernelCols + (kernelCols - 1) * (col_in_stride - 1);
+
+  const TensorIndex outputRows =
+    isColMajor ? output_backward.dimension(1) : output_backward.dimension(NumDims - 2);
+  const TensorIndex outputCols =
+    isColMajor ? output_backward.dimension(2) : output_backward.dimension(NumDims - 3);
+
+  // Computing the forward padding
+  const TensorIndex forward_pad_top =
+    numext::maxi<Index>(0, ((outputRows - 1) * row_stride + kernelRowsEff - inputRows) / 2);
+  const TensorIndex forward_pad_left =
+    numext::maxi<Index>(0, ((outputCols - 1) * col_stride + kernelColsEff - inputCols) / 2);
+  const TensorIndex padding_top = kernelRowsEff - 1 - forward_pad_top;
+  const TensorIndex padding_left = kernelColsEff - 1 - forward_pad_left;
+
+  const TensorIndex padding_bottom =
+    inputRows - (outputRows - 1) * row_stride - 2 - padding_top + kernelRowsEff;
+  const TensorIndex padding_right =
+    inputCols - (outputCols - 1) * col_stride - 2 - padding_left + kernelColsEff;
+
+  eigen_assert(padding_top >= 0);
+  eigen_assert(padding_left >= 0);
+  eigen_assert(padding_bottom >= 0);
+  eigen_assert(padding_right >= 0);
+
+  // The kernel has dimensions filters X channels X patch_rows X patch_cols
+  // We need to reverse the kernel along dimensions corresponding to rows and
+  // cols.
+  // TODO(yangke): we can make things slightly faster by collapsing the
+  // dimensions
+  // where we don't reverse. Try that once we have a faster compiler.
+  typedef std::conditional_t<isColMajor, ReverseColMajor, ReverseRowMajor> Reverse;
+  Reverse kernel_reverse;
+  // Reorder the dimensions to:
+  //   filters x patch_rows x patch_cols x channels
+  array<TensorIndex, 4> kernel_shuffle;
+  if (isColMajor)
+  {
+    //  From: filters x channels x rows x cols
+    //  To:   filters x rows x cols x channels
+    kernel_shuffle[0] = 0;
+    kernel_shuffle[1] = 2;
+    kernel_shuffle[2] = 3;
+    kernel_shuffle[3] = 1;
+  }
+  else
+  {
+    //  From: cols x rows x channels x filters
+    //  To:   channels x cols x rows x filters
+    kernel_shuffle[0] = 2;
+    kernel_shuffle[1] = 0;
+    kernel_shuffle[2] = 1;
+    kernel_shuffle[3] = 3;
+  }
+
+  // Collapse the dims
+  DSizes<TensorIndex, 2> kernel_dims;
+  if (isColMajor)
+  {
+    kernel_dims[0] = kernelFilters * kernelRows * kernelCols;
+    kernel_dims[1] = kernelChannels;
+  }
+  else
+  {
+    kernel_dims[1] = kernelFilters * kernelRows * kernelCols;
+    kernel_dims[0] = kernelChannels;
+  }
+
+  // The output_backward has dimensions out_depth X out_rows X out_cols X OTHERS
+  // When we extract the image patches from output_backward, it will have
+  // dimensions
+  //   out_depth X (patch_rows * patch_cols) X (input_rows * input_cols *
+  //   OTHERS)
+  DSizes<TensorIndex, 2> pre_contract_dims;
+  if (isColMajor)
+  {
+    pre_contract_dims[0] = kernelFilters * kernelRows * kernelCols;
+    pre_contract_dims[1] = inputRows * inputCols;
+    for (int i = 3; i < NumDims; ++i)
+    {
+      pre_contract_dims[1] *= out.dimension(i);
+    }
+  }
+  else
+  {
+    pre_contract_dims[1] = kernelFilters * kernelRows * kernelCols;
+    pre_contract_dims[0] = inputRows * inputCols;
+    for (int i = 0; i < NumDims - 3; ++i)
+    {
+      pre_contract_dims[0] *= out.dimension(i);
+    }
+  }
+
+  // We will contract along the collapsed dimension that contains the
+  // kernelFilters, the kernelRows and the kernelCols.
+  array<IndexPair<TensorIndex>, 1> contract_dims;
+  if (isColMajor)
+  {
+    // col-major: kernel.contract(output.patches)
+    contract_dims[0] = IndexPair<TensorIndex>(0, 0);
+  }
+  else
+  {
+    // row-major: output.patches.contract(kernel)
+    contract_dims[0] = IndexPair<TensorIndex>(1, 1);
+  }
+
+  // Post contraction, the dimensions of the input_backprop is
+  //  channels X input_rows X input_cols X OTHERS
+  DSizes<TensorIndex, NumDims> post_contract_dims;
+  if (isColMajor)
+  {
+    post_contract_dims[0] = kernelChannels;
+    post_contract_dims[1] = inputRows;
+    post_contract_dims[2] = inputCols;
+    for (int i = 3; i < NumDims; ++i)
+    {
+      post_contract_dims[i] = out.dimension(i);
+    }
+  }
+  else
+  {
+    post_contract_dims[NumDims - 1] = kernelChannels;
+    post_contract_dims[NumDims - 2] = inputRows;
+    post_contract_dims[NumDims - 3] = inputCols;
+    for (int i = 0; i < NumDims - 3; ++i)
+    {
+      post_contract_dims[i] = out.dimension(i);
+    }
+  }
+
+  // NOTE(ezhulenev): We do eval after reverse and shuffle, because tiled
+  // evaluation of these ops does not compose. Doing explicit eval is ~8x
+  // faster in micro benchmarks.
+
+  return choose(
+    Cond<internal::traits<OutputBackward>::Layout == ColMajor>(),
+    kernel.reverse(kernel_reverse)
+      .eval()
+      .shuffle(kernel_shuffle)
+      .eval()
+      .reshape(kernel_dims)
+      .contract(output_backward
+                  .extract_image_patches(kernelRows, kernelCols, 1, 1, row_in_stride, col_in_stride,
+                                         row_stride, col_stride, padding_top, padding_bottom,
+                                         padding_left, padding_right, OutScalar(0))
+                  .reshape(pre_contract_dims),
+                contract_dims)
+      .reshape(post_contract_dims),
+    output_backward
+      .extract_image_patches(kernelRows, kernelCols, 1, 1, row_in_stride, col_in_stride, row_stride,
+                             col_stride, padding_top, padding_bottom, padding_left, padding_right,
+                             OutScalar(0))
+      .reshape(pre_contract_dims)
+      .contract(
+        kernel.reverse(kernel_reverse).eval().shuffle(kernel_shuffle).eval().reshape(kernel_dims),
+        contract_dims)
+      .reshape(post_contract_dims));
+}
+
+/** SpatialConvolutionBackwardKernel
+ * \ingroup CXX11_NeuralNetworks_Module
+ *
+ * \brief Computes the backprop for the filter of a 2D convolution.
+ *
+ * The output_backward parameter is expected to be a tensor with a rank of 3 or
+ * more (channels, height, width, and optionally others)
+ * The kernel parameter is expected to be a 4D tensor (filters, channels,
+ * kernel_height, kernel_width)
+ * The output_backward and the kernel must both be in col-major layout. The
+ * result will also be in col-major layout.
+ *
+ * If row_in_stride, col_stride > 1, then applies convolution with holes (aka
+ * atrous convolution), sampling every row_in_stride, col_in_stride input
+ * pixels.
+ *
+ * The result can be assigned to a tensor of rank equal to the rank of the
+ * output_backward. The dimensions of the result will be filters, height, width
+ * (and others if applicable).
+ *
+ * It is possible to swap the order of the width and height dimensions provided
+ * that the same order is used in the input, the kernel, and the output.
+ *
+ */
+
+template <typename OutputBackward, typename Input>
+EIGEN_ALWAYS_INLINE static const std::conditional_t<
+  internal::traits<Input>::Layout == ColMajor,
+  const TensorReverseOp<
+    const Eigen::array<typename internal::traits<Input>::Index,
+                       internal::traits<Input>::NumDimensions>,
+    const Eigen::TensorForcedEvalOp<const Eigen::TensorShufflingOp<
+      const Eigen::array<typename internal::traits<Input>::Index,
+                         internal::traits<Input>::NumDimensions>,
+      const Eigen::TensorReshapingOp<
+        const Eigen::DSizes<typename internal::traits<Input>::Index,
+                            internal::traits<Input>::NumDimensions>,
+        const TensorContractionOp<
+          const array<IndexPair<typename internal::traits<Input>::Index>, 1>,
+          const TensorReshapingOp<const DSizes<typename internal::traits<Input>::Index, 2>,
+                                  const Eigen::TensorForcedEvalOp<const Eigen::TensorShufflingOp<
+                                    const Eigen::array<typename internal::traits<Input>::Index,
+                                                       internal::traits<Input>::NumDimensions>,
+                                    const Input>>>,
+          const TensorReshapingOp<
+            const DSizes<typename internal::traits<Input>::Index, 2>,
+            const TensorImagePatchOp<Dynamic, Dynamic,
+                                     const Eigen::TensorForcedEvalOp<const Eigen::TensorShufflingOp<
+                                       const Eigen::array<typename internal::traits<Input>::Index,
+                                                          internal::traits<Input>::NumDimensions>,
+                                       const OutputBackward>>>>>>>>>,
+  const TensorReverseOp<
+    const Eigen::array<typename internal::traits<Input>::Index,
+                       internal::traits<Input>::NumDimensions>,
+    const Eigen::TensorForcedEvalOp<const Eigen::TensorShufflingOp<
+      const Eigen::array<typename internal::traits<Input>::Index,
+                         internal::traits<Input>::NumDimensions>,
+      const Eigen::TensorReshapingOp<
+        const Eigen::DSizes<typename internal::traits<Input>::Index,
+                            internal::traits<Input>::NumDimensions>,
+        const TensorContractionOp<
+          const array<IndexPair<typename internal::traits<Input>::Index>, 1>,
+          const TensorReshapingOp<
+            const DSizes<typename internal::traits<Input>::Index, 2>,
+            const TensorImagePatchOp<Dynamic, Dynamic,
+                                     const Eigen::TensorForcedEvalOp<const Eigen::TensorShufflingOp<
+                                       const Eigen::array<typename internal::traits<Input>::Index,
+                                                          internal::traits<Input>::NumDimensions>,
+                                       const OutputBackward>>>>,
+          const TensorReshapingOp<const DSizes<typename internal::traits<Input>::Index, 2>,
+                                  const Eigen::TensorForcedEvalOp<const Eigen::TensorShufflingOp<
+                                    const Eigen::array<typename internal::traits<Input>::Index,
+                                                       internal::traits<Input>::NumDimensions>,
+                                    const Input>>>>>>>>>
+SpatialConvolutionBackwardKernel(const Input &input, const OutputBackward &output_backward,
+                                 typename internal::traits<Input>::Index kernelRows,
+                                 typename internal::traits<Input>::Index kernelCols,
+                                 const DenseIndex row_stride = 1, const DenseIndex col_stride = 1,
+                                 const DenseIndex row_in_stride = 1,
+                                 const DenseIndex col_in_stride = 1)
+{
+  typedef typename internal::traits<Input>::Index TensorIndex;
+  typedef typename internal::traits<OutputBackward>::Scalar OutScalar;
+  TensorRef<Tensor<typename internal::traits<Input>::Scalar, internal::traits<Input>::NumDimensions,
+                   internal::traits<Input>::Layout, TensorIndex>>
+    in(input);
+  TensorRef<Tensor<OutScalar, internal::traits<OutputBackward>::NumDimensions,
+                   internal::traits<OutputBackward>::Layout, TensorIndex>>
+    out(output_backward);
+
+  EIGEN_STATIC_ASSERT(internal::traits<Input>::Layout == internal::traits<OutputBackward>::Layout,
+                      YOU_MADE_A_PROGRAMMING_MISTAKE);
+
+  // stride and in_stride cannot both be larger than 1
+  eigen_assert(!(row_stride > 1 && row_in_stride > 1));
+  eigen_assert(!(col_stride > 1 && col_in_stride > 1));
+
+  static const bool isColMajor = (internal::traits<Input>::Layout == ColMajor);
+
+  static const int NumDims = internal::traits<Input>::NumDimensions;
+  EIGEN_STATIC_ASSERT(internal::traits<Input>::NumDimensions ==
+                        internal::traits<OutputBackward>::NumDimensions,
+                      YOU_MADE_A_PROGRAMMING_MISTAKE);
+  EIGEN_STATIC_ASSERT(NumDims == 4, YOU_MADE_A_PROGRAMMING_MISTAKE);
+
+  const TensorIndex inputRows = isColMajor ? in.dimension(1) : in.dimension(NumDims - 2);
+  const TensorIndex inputCols = isColMajor ? in.dimension(2) : in.dimension(NumDims - 3);
+
+  const TensorIndex outputRows =
+    isColMajor ? output_backward.dimension(1) : output_backward.dimension(NumDims - 2);
+  const TensorIndex outputCols =
+    isColMajor ? output_backward.dimension(2) : output_backward.dimension(NumDims - 3);
+
+  // Number of filters to apply. This is the same as the output depth of the
+  // result
+  const TensorIndex kernelFilters =
+    isColMajor ? out.dimensions()[0] : out.dimensions()[NumDims - 1];
+
+  // Number of channels. This is the same as the input depth.
+  const TensorIndex kernelChannels = isColMajor ? in.dimensions()[0] : in.dimensions()[NumDims - 1];
+
+  // This is the effective kernel size, taking into account the
+  // (*_in_stride - 1) zero-values inserted between consecutive kernel
+  // elements in atrous convolution
+  const TensorIndex kernelRowsEff = kernelRows + (kernelRows - 1) * (row_in_stride - 1);
+  const TensorIndex kernelColsEff = kernelCols + (kernelCols - 1) * (col_in_stride - 1);
+
+  // Number of batches (and other dimensions) in the input tensor.
+  TensorIndex batch = 1;
+  for (int d = 3; d < NumDims; ++d)
+  {
+    batch *= isColMajor ? in.dimension(d) : in.dimension(NumDims - d - 1);
+  }
+
+  // Computing the forward padding
+  const TensorIndex padRows =
+    numext::maxi<Index>(0, (outputRows - 1) * row_stride + kernelRowsEff - inputRows);
+  const TensorIndex padCols =
+    numext::maxi<Index>(0, (outputCols - 1) * col_stride + kernelColsEff - inputCols);
+
+  TensorIndex padding_top = padRows / 2;
+  TensorIndex padding_left = padCols / 2;
+
+  // Compute paddings for output_backward before extracting patches.
+  const TensorIndex expanded_out_rows = (outputRows - 1) * row_stride + 1;
+  const TensorIndex expanded_out_cols = (outputCols - 1) * col_stride + 1;
+
+  const TensorIndex padded_out_rows = inputRows + kernelRowsEff - 1;
+  const TensorIndex padded_out_cols = inputCols + kernelColsEff - 1;
+
+  const TensorIndex top_pad_rows = kernelRowsEff - 1 - padding_top;
+  const TensorIndex left_pad_cols = kernelColsEff - 1 - padding_left;
+
+  const TensorIndex bottom_pad_rows = padded_out_rows - expanded_out_rows - top_pad_rows;
+  const TensorIndex right_pad_cols = padded_out_cols - expanded_out_cols - left_pad_cols;
+
+  // Reorder output_backward dimensions.
+  array<TensorIndex, 4> output_backward_shuffle;
+  if (isColMajor)
+  {
+    // From: [out_depth, out_rows, out_cols, batch]
+    // To:   [batch, out_rows, out_cols, out_depth]
+    output_backward_shuffle = {3, 1, 2, 0};
+  }
+  else
+  {
+    // From: [batch, out_cols, out_rows, out_depth]
+    // To:   [out_depth, out_cols, out_rows, batch]
+    output_backward_shuffle = {3, 1, 2, 0};
+  }
+
+  // Reorder input dimensions.
+  array<TensorIndex, 4> input_shuffle;
+  if (isColMajor)
+  {
+    // From: [in_depth, in_rows, in_cols, batch]
+    // To:   [in_depth, batch, in_rows, in_cols]
+    input_shuffle = {0, 3, 1, 2};
+  }
+  else
+  {
+    // From: [batch, in_cols, in_rows, in_depth]
+    // To:   [in_cols, in_rows, batch, in_depth]
+    input_shuffle = {1, 2, 0, 3};
+  }
+
+  // Input is playing the role of a "kernel" in this convolution.
+  DSizes<TensorIndex, 2> input_dims;
+  if (isColMajor)
+  {
+    input_dims[0] = kernelChannels;
+    input_dims[1] = batch * inputRows * inputCols;
+  }
+  else
+  {
+    input_dims[1] = kernelChannels;
+    input_dims[0] = inputCols * inputRows * batch;
+  }
+
+  // Molds the output of the patch extraction result into a 2D tensor:
+  // - the first dimension (dims[0]): the patch values to be multiplied with the
+  // kernels
+  // - the second dimension (dims[1]): everything else
+  DSizes<TensorIndex, 2> pre_contract_dims;
+  if (isColMajor)
+  {
+    pre_contract_dims[0] = batch * inputRows * inputCols;
+    pre_contract_dims[1] = kernelRows * kernelCols * kernelFilters;
+  }
+  else
+  {
+    pre_contract_dims[1] = inputCols * inputRows * batch;
+    pre_contract_dims[0] = kernelFilters * kernelCols * kernelRows;
+  }
+
+  // We will contract along the collapsed dimension that contains the
+  // batch, inputRows and inputCols.
+  array<IndexPair<TensorIndex>, 1> contract_dims;
+  contract_dims[0] = IndexPair<TensorIndex>(1, 0);
+
+  // Dimensions after contraction.
+  DSizes<TensorIndex, NumDims> post_contract_dims;
+  if (isColMajor)
+  {
+    post_contract_dims[0] = kernelChannels;
+    post_contract_dims[1] = kernelRows;
+    post_contract_dims[2] = kernelCols;
+    post_contract_dims[3] = kernelFilters;
+  }
+  else
+  {
+    post_contract_dims[0] = kernelFilters;
+    post_contract_dims[1] = kernelCols;
+    post_contract_dims[2] = kernelRows;
+    post_contract_dims[3] = kernelChannels;
+  }
+
+  // Reorder output of contraction to a valid filter shape.
+  array<TensorIndex, 4> kernel_shuffle;
+  if (isColMajor)
+  {
+    // From: [in_depth, kernel_rows, kernel_cols, out_depth]
+    // To:   [out_depth, in_depth, kernel_rows, kernel_cols]
+    kernel_shuffle = {3, 0, 1, 2};
+  }
+  else
+  {
+    // From: [out_depth, kernel_cols, kernel_rows, in_depth]
+    // To:   [kernel_cols, kernel_rows, in_depth, out_depth]
+    kernel_shuffle = {1, 2, 3, 0};
+  }
+
+  // Reverse kernel backprop dimensions.
+  array<TensorIndex, 4> kernel_reverse;
+  if (isColMajor)
+  {
+    kernel_reverse = {false, false, true, true};
+  }
+  else
+  {
+    kernel_reverse = {true, true, false, false};
+  }
+
+  // Create convolution input (aka source of patches) from output backward
+  // tensor by shuffling dimensions.
+  const auto output_backward_shuffled = output_backward.shuffle(output_backward_shuffle).eval();
+
+  // Create convolution kernel (aka filter) from input by shuffling and
+  // reshaping.
+  const auto input_shuffled = input.shuffle(input_shuffle).eval().reshape(input_dims);
+
+  return choose(Cond<internal::traits<OutputBackward>::Layout == ColMajor>(),
+                input_shuffled.contract(
+                  output_backward_shuffled
+                    .extract_image_patches(inputRows, inputCols, row_in_stride, col_in_stride, 1, 1,
+                                           row_stride, col_stride, top_pad_rows, bottom_pad_rows,
+                                           left_pad_cols, right_pad_cols, OutScalar(0))
+                    .reshape(pre_contract_dims),
+                  contract_dims),
+                output_backward_shuffled
+                  .extract_image_patches(inputRows, inputCols, row_in_stride, col_in_stride, 1, 1,
+                                         row_stride, col_stride, top_pad_rows, bottom_pad_rows,
+                                         left_pad_cols, right_pad_cols, OutScalar(0))
+                  .reshape(pre_contract_dims)
+                  .contract(input_shuffled, contract_dims))
+    .reshape(post_contract_dims)
+    .shuffle(kernel_shuffle)
+    .eval()
+    .reverse(kernel_reverse);
+}
+
+} // end namespace Eigen
+
+#endif // __NNFW_CKER_EGIEN_EIGEN_BACKWARD_SPATIAL_CONVOLUTIONS_H__
index 9d4fd2e..856ae78 100644 (file)
@@ -60,8 +60,8 @@ public:
   template <typename TensorEvaluatorT, typename PacketT, typename IndexT>
   static auto functionExistsSfinae(...) -> std::false_type;
 
-  typedef decltype(
-    functionExistsSfinae<TensorEvaluatorType, PacketType, IndexType>(nullptr)) status;
+  typedef decltype(functionExistsSfinae<TensorEvaluatorType, PacketType, IndexType>(
+    nullptr)) status;
 
   static constexpr bool value = status::value;
 };
index c931ac5..3808695 100644 (file)
@@ -400,7 +400,7 @@ private:
       // span[1]+1 : packetSize-1 - Zeross will be loaded for these indices
       const Index packetSize = internal::unpacket_traits<Packet>::size;
       EIGEN_ALIGN_MAX
-      typename internal::remove_const<Scalar>::type values[packetSize];
+      std::remove_const_t<Scalar> values[packetSize];
       for (int i = 0; i < span[0]; ++i)
         values[i] = Scalar(0);
       for (int i = span[0]; i < span[1] + 1; ++i)
@@ -610,7 +610,7 @@ private:
   {
     const int packetSize = internal::unpacket_traits<Packet>::size;
     EIGEN_ALIGN_MAX
-    typename internal::remove_const<Scalar>::type values[packetSize];
+    std::remove_const_t<Scalar> values[packetSize];
     for (int i = 0; i < packetSize; ++i)
     {
       values[i] = loadCoeff(patchId + i, rowIndex, colIndex, otherIndex);
@@ -1567,7 +1567,7 @@ struct gemm_pack_rhs<
  *
  */
 template <typename Input, typename Kernel, typename OutputKernel = const NoOpOutputKernel>
-EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static const typename internal::conditional<
+EIGEN_ALWAYS_INLINE static const std::conditional_t<
   internal::traits<Input>::Layout == ColMajor,
   TensorReshapingOp<
     const DSizes<typename internal::traits<Input>::Index, internal::traits<Input>::NumDimensions>,
@@ -1586,7 +1586,7 @@ EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE static const typename internal::conditiona
                               const TensorImagePatchOp<Dynamic, Dynamic, const Input>>,
       const TensorReshapingOp<const DSizes<typename internal::traits<Input>::Index, 2>,
                               const Kernel>,
-      const OutputKernel>>>::type
+      const OutputKernel>>>
 SpatialConvolution(const Input &input, const Kernel &kernel, const Index row_stride = 1,
                    const Index col_stride = 1, const PaddingType padding_type = PADDING_SAME,
                    const Index row_in_stride = 1, const Index col_in_stride = 1,
@@ -1594,7 +1594,8 @@ SpatialConvolution(const Input &input, const Kernel &kernel, const Index row_str
                    Index padding_bottom = 0, Index padding_left = 0, Index padding_right = 0)
 {
   typedef typename internal::traits<Input>::Index TensorIndex;
-  TensorRef<Tensor<typename internal::traits<Input>::Scalar, internal::traits<Input>::NumDimensions,
+  typedef typename internal::traits<Input>::Scalar InputScalar;
+  TensorRef<Tensor<InputScalar, internal::traits<Input>::NumDimensions,
                    internal::traits<Input>::Layout, TensorIndex>>
     in(input);
   TensorRef<
@@ -1719,28 +1720,28 @@ SpatialConvolution(const Input &input, const Kernel &kernel, const Index row_str
   }
   if (padding_explicit)
   {
-    return choose(Cond<internal::traits<Input>::Layout == ColMajor>(),
-                  kernel.reshape(kernel_dims)
-                    .contract(input
-                                .extract_image_patches(kernelRows, kernelCols, row_stride,
-                                                       col_stride, row_in_stride, col_in_stride,
-                                                       /*row_inflate_stride=*/1,
-                                                       /*col_inflate_stride=*/1, padding_top,
-                                                       padding_bottom, padding_left, padding_right,
-                                                       /*padding_value=*/0)
-                                .reshape(pre_contract_dims),
-                              contract_dims, output_kernel)
-                    .reshape(post_contract_dims),
-                  input
+    return choose(
+      Cond<internal::traits<Input>::Layout == ColMajor>(),
+      kernel.reshape(kernel_dims)
+        .contract(input
                     .extract_image_patches(kernelRows, kernelCols, row_stride, col_stride,
                                            row_in_stride, col_in_stride,
                                            /*row_inflate_stride=*/1,
                                            /*col_inflate_stride=*/1, padding_top, padding_bottom,
                                            padding_left, padding_right,
-                                           /*padding_value=*/0)
-                    .reshape(pre_contract_dims)
-                    .contract(kernel.reshape(kernel_dims), contract_dims, output_kernel)
-                    .reshape(post_contract_dims));
+                                           /*padding_value=*/static_cast<InputScalar>(0))
+                    .reshape(pre_contract_dims),
+                  contract_dims, output_kernel)
+        .reshape(post_contract_dims),
+      input
+        .extract_image_patches(
+          kernelRows, kernelCols, row_stride, col_stride, row_in_stride, col_in_stride,
+          /*row_inflate_stride=*/1,
+          /*col_inflate_stride=*/1, padding_top, padding_bottom, padding_left, padding_right,
+          /*padding_value=*/static_cast<InputScalar>(0))
+        .reshape(pre_contract_dims)
+        .contract(kernel.reshape(kernel_dims), contract_dims, output_kernel)
+        .reshape(post_contract_dims));
   }
   else
   {
index c6f1e2e..70d3718 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef __NNFW_CKER_EGIEN_EIGEN_SPATIAL_CONVOLUTIONS_H__
 #define __NNFW_CKER_EGIEN_EIGEN_SPATIAL_CONVOLUTIONS_H__
 
-//#define EIGEN_USE_CUSTOM_THREAD_POOL
+// #define EIGEN_USE_CUSTOM_THREAD_POOL
 #define EIGEN_USE_THREADS
 #include "unsupported/Eigen/CXX11/Tensor"
 
diff --git a/compute/cker/include/cker/eigen/redux_functor.h b/compute/cker/include/cker/eigen/redux_functor.h
new file mode 100644 (file)
index 0000000..40af74f
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EIGEN_REDUX_FUNCTOR_H__
+#define __NNFW_CKER_EIGEN_REDUX_FUNCTOR_H__
+
+#include <cker/operation/Helper/Tensor.h>
+
+// From tensorflow/core/kernels/redux_functor.h
+namespace nnfw
+{
+namespace cker
+{
+namespace functor
+{
+
+// Compute reduction over outer dimensions.
+// Example:
+//   input: [D1, D2, ... , DN]
+//   ->
+//   output: [Di, ... , DN] where i belongs to set [1,N]
+template <typename Device, typename InputT, typename AccumT, typename OutputT,
+          typename BinaryFunctor>
+struct ReduceOuterDimensions
+{
+  ReduceOuterDimensions() {}
+
+  template <int num_dims>
+  void operator()(const Device &device, const Eigen::DSizes<Eigen::Index, num_dims> &input_dims,
+                  const Tensor &input, Tensor *output) const
+  {
+    // Compute inner and outer dim after reshaping into 2d tensor.
+    const int num_output_dims = output->shape.DimensionsCount();
+    auto output_dims = output->template flat<OutputT>().dimensions();
+
+    Eigen::Index inner_dim = 1, outer_dim = 1;
+    for (int i = 0; i < num_dims - num_output_dims; ++i)
+      outer_dim *= input_dims[i];
+    for (int i = num_dims - num_output_dims; i < num_dims; ++i)
+      inner_dim *= input_dims[i];
+
+    if (1 == outer_dim)
+    {
+      // Nothing to do but passing input to output.
+      output->template flat<OutputT>() =
+        input.template flat<InputT>().template cast<OutputT>().reshape(output_dims);
+      return;
+    }
+
+    // Get device thread num.
+    const Eigen::Index num_threads = device.numThreads();
+
+    // If the inner dim parallelism is large enough
+    // TODO(ezhulenev): There seems to be no benefits in going this route. Check
+    // if this can be improved, or use better heuristic?
+    if (inner_dim > num_threads * 32)
+    {
+      // Do not create more blocks than there are threads in a pool.
+      const Eigen::Index num_blocks = num_threads;
+
+      // Block size along the outer dimension.
+      const Eigen::Index inner_block_size = Eigen::divup(inner_dim, num_blocks);
+      const InputT *input_data = input.template flat<InputT>().data();
+
+      // Allocate temporary buffer for partial reductions.
+      Eigen::Tensor<AccumT, 1, Eigen::RowMajor, Eigen::Index> buffer({inner_dim});
+      buffer.setZero();
+      AccumT *buffer_data = buffer.data();
+
+      using Buffer =
+        Eigen::TensorMap<Eigen::Tensor<AccumT, 1, Eigen::RowMajor, Eigen::Index>, Eigen::Unaligned>;
+
+      using Input = Eigen::TensorMap<Eigen::Tensor<const InputT, 1, Eigen::RowMajor, Eigen::Index>,
+                                     Eigen::Unaligned>;
+
+      const auto compute = [inner_dim, outer_dim, inner_block_size, input_data,
+                            buffer_data](Eigen::Index start, Eigen::Index limit) -> void {
+        Eigen::Index inner_dim_start = start * inner_block_size;
+        Eigen::Index inner_dim_limit = limit * inner_block_size;
+        inner_dim_limit = std::min(inner_dim, inner_dim_limit);
+        Eigen::Index my_job_len = inner_dim_limit - inner_dim_start;
+
+        const InputT *my_job_start = input_data + inner_dim_start;
+        Buffer buf(buffer_data + inner_dim_start, my_job_len);
+
+        for (Eigen::Index i = 0; i < outer_dim; ++i)
+        {
+          auto in = Input(my_job_start + i * inner_dim, my_job_len);
+          auto cast = in.template cast<AccumT>();
+          buf =
+            Eigen::TensorCwiseBinaryOp<BinaryFunctor, const decltype(buf), const decltype(cast)>(
+              buf, cast);
+        }
+      };
+
+      // Compute cost of reducing a single block.
+      const Eigen::Index compute_size = outer_dim * inner_block_size;
+      const Eigen::Index compute_input_bytes = compute_size * sizeof(InputT);
+      const Eigen::TensorOpCost cost(compute_input_bytes,
+                                     0, // We'll be mostly writing to L1, assume store cost is 0
+                                     compute_size *
+                                       Eigen::internal::functor_traits<BinaryFunctor>::Cost);
+
+      device.parallelFor(num_blocks, cost, compute);
+
+      // Write final result to the output.
+      output->template flat<OutputT>() = buffer.template cast<OutputT>().reshape(output_dims);
+    }
+    else
+    {
+      // Compute block size along the outer dimension for efficiency.
+      const Eigen::Index parallel_cell_size = inner_dim;
+      const Eigen::Index total_workload = outer_dim * inner_dim;
+      const Eigen::Index max_parallelism = total_workload / parallel_cell_size;
+
+      const Eigen::Index min_block_workload = 2000;
+      const Eigen::Index min_block_size = Eigen::divup(min_block_workload, parallel_cell_size);
+      const Eigen::Index max_num_blocks =
+        std::min(max_parallelism, Eigen::divup(total_workload, min_block_size));
+
+      // Do not create more blocks than there are threads in a pool.
+      const Eigen::Index num_blocks = std::min(max_num_blocks, num_threads);
+
+      // Block size along the outer dimension.
+      const Eigen::Index outer_block_size = Eigen::divup(outer_dim, num_blocks);
+
+      const InputT *input_data = input.template flat<InputT>().data();
+
+      // Allocate temporary buffer for partial reductions.
+      std::vector<AccumT> buffer(num_blocks * inner_dim);
+      AccumT *buffer_data = buffer.data();
+
+      using Buffer =
+        Eigen::TensorMap<Eigen::Tensor<AccumT, 1, Eigen::RowMajor, Eigen::Index>, Eigen::Unaligned>;
+
+      using Input = Eigen::TensorMap<Eigen::Tensor<const InputT, 1, Eigen::RowMajor, Eigen::Index>,
+                                     Eigen::Unaligned>;
+
+      const auto compute = [inner_dim, outer_block_size, buffer_data, input_data,
+                            outer_dim](Eigen::Index start, Eigen::Index limit) -> void {
+        Eigen::Index outer_dim_start = start * outer_block_size;
+        Eigen::Index outer_dim_limit = limit * outer_block_size;
+        outer_dim_limit = std::min(outer_dim, outer_dim_limit);
+
+        Buffer buf(buffer_data + start * inner_dim, inner_dim);
+        for (Eigen::Index i = outer_dim_start; i < outer_dim_limit; ++i)
+        {
+          auto in = Input(input_data + i * inner_dim, inner_dim);
+          auto cast = in.template cast<AccumT>();
+          buf =
+            Eigen::TensorCwiseBinaryOp<BinaryFunctor, const decltype(buf), const decltype(cast)>(
+              buf, cast);
+        }
+      };
+
+      // Compute cost of reducing a single block.
+      const Eigen::Index compute_size = outer_block_size * inner_dim;
+      const Eigen::Index compute_input_bytes = compute_size * sizeof(InputT);
+      const Eigen::TensorOpCost cost(compute_input_bytes,
+                                     0, // We'll be mostly writing to L1, assume store cost is 0
+                                     compute_size *
+                                       Eigen::internal::functor_traits<BinaryFunctor>::Cost);
+
+      device.parallelFor(num_blocks, cost, compute);
+
+      // Aggregate partial results from temporary buffer into first block.
+      auto buf0 = Buffer(buffer_data, inner_dim);
+      // Just sum the buffer up, as inner dimensions is not large in this case.
+      for (int i = 1; i < num_blocks; ++i)
+      {
+        auto buf = Buffer(buffer_data + i * inner_dim, inner_dim);
+        buf0 = Eigen::TensorCwiseBinaryOp<BinaryFunctor, const decltype(buf0), const decltype(buf)>(
+          buf0, buf);
+      }
+      // Write final result to the output.
+      output->template flat<OutputT>() = buf0.template cast<OutputT>().reshape(output_dims);
+    }
+  }
+};
+
+void biasReductionHelper(float *input_backprop_buffer, const Shape &input_backprop_shape,
+                         float *bias_grad_buffer, const Shape &bias_grad_shape)
+{
+  assert(input_backprop_buffer);
+  assert(bias_grad_buffer);
+
+  const nnfw::cker::functor::ReduceOuterDimensions<Eigen::ThreadPoolDevice, float, float, float,
+                                                   Eigen::internal::scalar_sum_op<float>>
+    redux;
+
+  const Tensor input_backprop_t{input_backprop_shape, static_cast<void *>(input_backprop_buffer)};
+
+  Tensor bias_grad_t{bias_grad_shape, bias_grad_buffer};
+
+  int outer = 1;
+  for (int i = 0; i < input_backprop_shape.DimensionsCount() - 1; ++i)
+    outer *= input_backprop_shape.Dims(i);
+  int inner = input_backprop_shape.Dims(input_backprop_shape.DimensionsCount() - 1);
+
+  redux(*eigen_support::GetThreadPoolDevice(), Eigen::DSizes<Eigen::Index, 2>{outer, inner},
+        input_backprop_t, &bias_grad_t);
+}
+
+} // namespace functor
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_EIGEN_REDUX_FUNCTOR_H__
diff --git a/compute/cker/include/cker/eigen/training_ops.h b/compute/cker/include/cker/eigen/training_ops.h
new file mode 100644 (file)
index 0000000..dff8726
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2016 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EIGEN_TRAINING_OPS_H__
+#define __NNFW_CKER_EIGEN_TRAINING_OPS_H__
+
+// From tensorflow/core/kernels/training_ops.cc
+#define EIGEN_USE_THREADS
+
+#include "unsupported/Eigen/CXX11/Tensor"
+#include "cker/operation/Helper/Tensor.h"
+
+// From tensorflow/core/kernels/training_ops.h
+namespace nnfw
+{
+namespace cker
+{
+namespace training_ops
+{
+namespace functor
+{
+
+template <typename Device, typename T> struct ApplyAdam
+{
+  void operator()(const Device &d, typename TTypes<T>::Flat var, typename TTypes<T>::Flat m,
+                  typename TTypes<T>::Flat v, typename TTypes<T>::ConstScalar beta1_power,
+                  typename TTypes<T>::ConstScalar beta2_power, typename TTypes<T>::ConstScalar lr,
+                  typename TTypes<T>::ConstScalar beta1, typename TTypes<T>::ConstScalar beta2,
+                  typename TTypes<T>::ConstScalar epsilon, typename TTypes<T>::ConstFlat grad,
+                  bool use_nesterov);
+};
+
+// Each training algorithm has a ApplyXYZ functor struct declared in
+// this header file. They are specialized for different devices
+// (CPUDevice in training_ops.cc or GPUDevice in training_ops_gpu.cc).
+template <typename Device, typename T> struct ApplyGradientDescent
+{
+  void operator()(const Device &d, typename TTypes<T>::Flat var,
+                  typename TTypes<T>::ConstScalar alpha, typename TTypes<T>::ConstFlat delta);
+};
+
+} // namespace functor
+} // namespace training_ops
+} // namespace cker
+} // namespace nnfw
+
+// From tensorflow/core/kernels/training_ops.cc
+namespace nnfw
+{
+namespace cker
+{
+namespace training_ops
+{
+
+// Enable CPUDevice only for training_ops
+using CPUDevice = Eigen::ThreadPoolDevice;
+using Index = Eigen::Index;
+
+namespace functor
+{
+
+template <typename Device, typename T> struct ApplyAdamNonCuda
+{
+  void operator()(const Device &d, typename TTypes<T>::Flat var, typename TTypes<T>::Flat m,
+                  typename TTypes<T>::Flat v, typename TTypes<T>::ConstScalar beta1_power,
+                  typename TTypes<T>::ConstScalar beta2_power, typename TTypes<T>::ConstScalar lr,
+                  typename TTypes<T>::ConstScalar beta1, typename TTypes<T>::ConstScalar beta2,
+                  typename TTypes<T>::ConstScalar epsilon, typename TTypes<T>::ConstFlat grad,
+                  bool use_nesterov)
+  {
+    // Get params length and check if they can be vectorized by packet size.
+    Index length = var.size();
+    Index packet_size = Eigen::internal::packet_traits<T>::size;
+    if (length % packet_size == 0)
+    {
+      length = length / packet_size;
+    }
+    else
+    {
+      packet_size = 1;
+    }
+
+    T *var_ptr = var.data();
+    T *m_ptr = m.data();
+    T *v_ptr = v.data();
+    const T *g_ptr = grad.data();
+    const T alpha = lr() * Eigen::numext::sqrt(T(1) - beta2_power()) / (T(1) - beta1_power());
+    // beta1 == Î¼
+    // beta2 == Î½
+    // v     == n
+    // var   == Î¸
+
+    auto shard = [var_ptr, m_ptr, v_ptr, g_ptr, alpha, beta1, beta2, epsilon, use_nesterov,
+                  packet_size](int begin, int end) {
+      int t_size = (end - begin) * packet_size;
+      begin = begin * packet_size;
+      auto var = typename TTypes<T>::UnalignedTensor(var_ptr + begin, t_size);
+      auto m = typename TTypes<T>::UnalignedTensor(m_ptr + begin, t_size);
+      auto v = typename TTypes<T>::UnalignedTensor(v_ptr + begin, t_size);
+      auto g = typename TTypes<T>::UnalignedConstTensor(g_ptr + begin, t_size);
+
+      if (use_nesterov)
+      {
+        m += (g - m) * (T(1) - beta1());
+        v += (g.square() - v) * (T(1) - beta2());
+        var -= ((g * (T(1) - beta1()) + beta1() * m) * alpha) / (v.sqrt() + epsilon());
+      }
+      else
+      {
+        m += (g - m) * (T(1) - beta1());
+        v += (g.square() - v) * (T(1) - beta2());
+        var -= (m * alpha) / (v.sqrt() + epsilon());
+      }
+    };
+
+    // Input data: var, v, m, grad.
+    // Output data: var, v, m.
+    const int input_bytes = length * packet_size * sizeof(T) * 4;
+    const int output_bytes = length * packet_size * sizeof(T) * 3;
+    const int compute_cycles =
+      // Consider Sub as Add
+      (Eigen::TensorOpCost::AddCost<int>() * 5 + Eigen::TensorOpCost::MulCost<int>() * 2 +
+       Eigen::TensorOpCost::AddCost<T>() * 10 + Eigen::TensorOpCost::MulCost<T>() * 6 +
+       Eigen::TensorOpCost::DivCost<T>()) *
+      length;
+    const Eigen::TensorOpCost cost(input_bytes, output_bytes, compute_cycles);
+
+    // Eigen device must update 3 variables with 3 different expressions,
+    // which is bad for cache locality on CPU. Here use ParallelFor instead of
+    // "regular" tensor expressions to get better performance.
+    d.parallelFor(length, cost, shard);
+  }
+};
+
+template <typename T> struct ApplyAdam<CPUDevice, T> : ApplyAdamNonCuda<CPUDevice, T>
+{
+};
+
+template <typename T> struct ApplyGradientDescent<CPUDevice, T>
+{
+  void operator()(const CPUDevice &d, typename TTypes<T>::Flat var,
+                  typename TTypes<T>::ConstScalar lr, typename TTypes<T>::ConstFlat grad)
+  {
+    var.device(d) -= grad * lr();
+  }
+};
+
+} // namespace functor
+} // namespace training_ops
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_EIGEN_TRAINING_OPS_H__
index c787849..6c6e01c 100644 (file)
@@ -19,6 +19,7 @@
 #define __NNFW_CKER_BINARY_ARITHMETIC_OPS_H__
 
 #include <functional>
+#include <stdexcept>
 #include "cker/operation/optimized/BinaryArithmeticOps.h"
 #include "cker/operation/reference/BinaryArithmeticOps.h"
 #include "cker/Shape.h"
@@ -32,7 +33,8 @@ namespace cker
 
 namespace
 {
-template <BinaryArithmeticOpType op_type, typename T>
+template <BinaryArithmeticOpType op_type, typename T,
+          typename std::enable_if_t<!std::is_same<T, bool>::value, bool> = true>
 const std::function<T(const T &, const T &)> GetBinaryArtithmeticFn()
 {
   switch (op_type)
@@ -71,6 +73,23 @@ const std::function<T(const T &, const T &)> GetBinaryArtithmeticFn()
     }
   }
 }
+
+template <BinaryArithmeticOpType op_type, typename T,
+          typename std::enable_if_t<std::is_same<T, bool>::value, bool> = true>
+const std::function<T(const bool &, const bool &)> GetBinaryArtithmeticFn()
+{
+  switch (op_type)
+  {
+    case BinaryArithmeticOpType::MUL:
+    {
+      return [](const bool &a, const bool &b) -> bool { return a && b; };
+    }
+    default:
+    {
+      throw std::runtime_error("GetBinaryArtithmeticFn: Unsupported OpType with Bool8");
+    }
+  }
+}
 } // namespace
 
 // Consolidates dimensions in broadcast inputs, checks for five-fold pattern.
@@ -190,7 +209,17 @@ inline bool ProcessBroadcastShapes(const Shape &shape0, const Shape &shape1,
 }
 
 template <BinaryArithmeticOpType op_type, typename T>
-inline typename std::enable_if_t<!is_quant8<T>::value>
+inline typename std::enable_if_t<!is_quant8<T>::value && !std::is_same<T, bool>::value>
+BinaryArithmeticOp(const BinaryArithmeticOpParam &params, const Shape &input1_shape,
+                   const T *input1_data, const Shape &input2_shape, const T *input2_data,
+                   const Shape &output_shape, T *output_data)
+{
+  reference::BinaryArithmeticOp(params, input1_shape, input1_data, input2_shape, input2_data,
+                                output_shape, output_data, GetBinaryArtithmeticFn<op_type, T>());
+}
+
+template <BinaryArithmeticOpType op_type, typename T>
+inline typename std::enable_if_t<!is_quant8<T>::value && std::is_same<T, bool>::value>
 BinaryArithmeticOp(const BinaryArithmeticOpParam &params, const Shape &input1_shape,
                    const T *input1_data, const Shape &input2_shape, const T *input2_data,
                    const Shape &output_shape, T *output_data)
@@ -298,6 +327,11 @@ inline void BroadcastBinaryArithmeticOp(BinaryArithmeticOpParam &params, const S
                                         const float *input2_data, const Shape &output_shape,
                                         float *output_data)
 {
+  if (output_shape.DimensionsCount() > 4)
+    throw std::runtime_error(
+      std::string("cker::BroadcastBinaryArithmeticOp: Unsupported rank size : ") +
+      std::to_string(output_shape.DimensionsCount()));
+
   // Supported type is only float now
   switch (op_type)
   {
index 9aaca00..b73fa5c 100644 (file)
@@ -54,6 +54,7 @@ inline void Concatenation(const ConcatenationParams &params, const Shape *const
     concat_size += input_shapes[i]->Dims(axis);
   }
   assert(concat_size == output_shape.Dims(axis));
+  UNUSED_RELEASE(concat_size);
   int64_t outer_size = 1;
   for (int i = 0; i < axis; ++i)
   {
@@ -110,6 +111,7 @@ inline void ConcatenationWithScaling(const ConcatenationParams &params,
     concat_size += input_shapes[i]->Dims(axis);
   }
   assert(concat_size == output_shape.Dims(axis));
+  UNUSED_RELEASE(concat_size);
   int64_t outer_size = 1;
   for (int i = 0; i < axis; ++i)
   {
diff --git a/compute/cker/include/cker/operation/FloorMod.h b/compute/cker/include/cker/operation/FloorMod.h
new file mode 100644 (file)
index 0000000..f40b573
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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 __NNFW_CKER_FLOOR_MOD_H__
+#define __NNFW_CKER_FLOOR_MOD_H__
+
+#include "cker/Shape.h"
+#include "cker/Utils.h"
+
+#include <functional>
+#include <stdexcept>
+#include <string>
+
+namespace nnfw
+{
+namespace cker
+{
+
+template <typename T>
+inline void FloorModBroadcast(const Shape &unextended_input1_shape, const T *input1_data,
+                              const Shape &unextended_input2_shape, const T *input2_data,
+                              const Shape &unextended_output_shape, T *output_data)
+{
+  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;
+
+  if (unextended_output_shape.DimensionsCount() > 4)
+    throw std::runtime_error(std::string("cker::FloorModBroadcast: Unsupported rank size : ") +
+                             std::to_string(unextended_output_shape.DimensionsCount()));
+  const Shape output_shape = Shape::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];
+
+          ModFunc mod_func;
+          T trunc_mod = mod_func(in1_val, in2_val);
+          output_data[out_idx] = (trunc_mod != 0) && ((in2_val < 0) != (trunc_mod < 0))
+                                   ? (trunc_mod + in2_val)
+                                   : trunc_mod;
+        }
+      }
+    }
+  }
+}
+
+template <typename T>
+inline void FloorModElementwise(const Shape &shape, const T *input1_data, const T *input2_data,
+                                T *output_data)
+{
+  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;
+
+  int num_elements = shape.FlatSize();
+  for (int t = 0; t < num_elements; t++)
+  {
+    ModFunc mod_func;
+    auto in1_val = input1_data[t];
+    auto in2_val = input2_data[t];
+    T trunc_mod = mod_func(in1_val, in2_val);
+    output_data[t] =
+      (trunc_mod != 0) && ((in2_val < 0) != (trunc_mod < 0)) ? (trunc_mod + in2_val) : trunc_mod;
+  }
+}
+
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_FLOOR_MOD_H__
index b80ccc0..b7d6394 100644 (file)
@@ -62,13 +62,13 @@ public:
     if (!_batch_bcast->IsValid())
       return;
 
-    auto x_reshaped = _batch_bcast->x_reshape();
-    auto y_reshaped = _batch_bcast->y_reshape();
+    const auto &x_reshaped = _batch_bcast->x_reshape();
+    const auto &y_reshaped = _batch_bcast->y_reshape();
     auto output_shape = _batch_bcast->output_shape();
 
     _x_batch_size = std::accumulate(x_reshaped.cbegin(), x_reshaped.cend(), INT32_C(1),
                                     std::multiplies<int32_t>());
-    _y_batch_size = std::accumulate(x_reshaped.cbegin(), x_reshaped.cend(), INT32_C(1),
+    _y_batch_size = std::accumulate(y_reshaped.cbegin(), y_reshaped.cend(), INT32_C(1),
                                     std::multiplies<int32_t>());
     _output_shape.ReplaceWith(output_shape.size(), output_shape.data());
     _output_batch_size = _output_shape.FlatSize();
index c99f697..06a8587 100644 (file)
@@ -147,9 +147,9 @@ template <class Distribution> struct FillPhiloxRandomTask<Distribution, true>
 // Partial specialization for CPU to fill the entire region with randoms
 // It splits the work into several tasks and run them in parallel
 template <class Distribution>
-void FillPhiloxRandom<CPUDevice, Distribution>::
-operator()(random::PhiloxRandom gen, typename Distribution::ResultElementType *data, int64_t size,
-           Distribution dist)
+void FillPhiloxRandom<CPUDevice, Distribution>::operator()(
+  random::PhiloxRandom gen, typename Distribution::ResultElementType *data, int64_t size,
+  Distribution dist)
 {
   FillPhiloxRandomTask<Distribution, Distribution::kVariableSamplesPerOutput>::Run(gen, data, size,
                                                                                    dist);
index e990772..daa549d 100644 (file)
@@ -29,39 +29,13 @@ namespace nnfw
 namespace cker
 {
 
-/**
- * @brief Internal scalar_logistic_op operation struct
- *
- * @note  Recent Eigen3 scalar_logistic_op return invalid value on ARM32 if
- *        input value is float type 88 (expected: 1, actual: 0)
- *        As a workaround, we use old version scalar_logistic_op internal struct
- *        TODO Remove this workaround
- */
-template <typename T> struct scalar_logistic_op
-{
-  EIGEN_EMPTY_STRUCT_CTOR(scalar_logistic_op)
-  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T operator()(const T &x) const
-  {
-    const T one = T(1);
-    return one / (one + Eigen::numext::exp(-x));
-  }
-
-  template <typename Packet>
-  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet packetOp(const Packet &x) const
-  {
-    const Packet one = Eigen::internal::pset1<Packet>(T(1));
-    return pdiv(one, padd(one, pexp(pnegate(x))));
-  }
-};
-
 inline void Logistic(const Shape &input_shape, const float *input_data, const Shape &output_shape,
                      float *output_data)
 {
   auto input_map = MapAsVector(input_data, input_shape);
   auto output_map = MapAsVector(output_data, output_shape);
 
-  // Use old version scalar_logistic_op
-  output_map.array() = input_map.array().unaryExpr(nnfw::cker::scalar_logistic_op<float>());
+  output_map.array() = input_map.array().unaryExpr(Eigen::internal::scalar_logistic_op<float>());
 }
 
 } // namespace cker
index 9e46f4b..533fcc3 100644 (file)
@@ -34,8 +34,6 @@ void SplitV(const SplitVParams &params, const Shape &input_shape, const Scalar *
   int axis = params.axis < 0 ? params.axis + split_dimensions : params.axis;
   int outputs_count = params.num_split;
 
-  int64_t split_size = 0;
-
   for (int i = 0; i < outputs_count; i++)
   {
     // TFLITE_DCHECK_EQ(output_shapes[i]->DimensionsCount(), split_dimensions);
@@ -46,7 +44,6 @@ void SplitV(const SplitVParams &params, const Shape &input_shape, const Scalar *
         MatchingDim(output_shapes[i], j, input_shape, j);
       }
     }
-    split_size += output_shapes[i].Dims(axis);
   }
 
   int64_t outer_size = 1;
index 2f10895..ecb587d 100644 (file)
@@ -254,6 +254,7 @@ void checkOutputSize(const StridedSliceParams &op_params, const Shape &input_sha
   }
 
   assert(output_shape.DimensionsCount() == shape_size);
+  UNUSED_RELEASE(shape_size);
 }
 
 template <typename T>
index 96e1d91..0a030f7 100644 (file)
@@ -61,6 +61,20 @@ inline void BinaryArithmeticOp(const BinaryArithmeticOpParam &params, const Shap
   }
 }
 
+template <>
+inline void BinaryArithmeticOp(const BinaryArithmeticOpParam &, const Shape &input1_shape,
+                               const bool *input1_data, const Shape &input2_shape,
+                               const bool *input2_data, const Shape &output_shape,
+                               bool *output_data,
+                               const std::function<bool(const bool &, const bool &)> &fn)
+{
+  const int size = MatchingElementsSize(input1_shape, input2_shape, output_shape);
+  for (int i = 0; i < size; i++)
+  {
+    output_data[i] = fn(input1_data[i], input2_data[i]);
+  }
+}
+
 template <typename T>
 inline typename std::enable_if_t<is_quant8<T>::value> BroadcastBinaryArithmeticOpSlow(
   const BinaryArithmeticOpParam &params, const Shape &input1_shape, const T *input1_data,
@@ -174,6 +188,34 @@ inline void BroadcastBinaryArithmeticOpSlow(
   }
 }
 
+template <>
+inline void BroadcastBinaryArithmeticOpSlow(
+  const BinaryArithmeticOpParam &, const Shape &input1_shape, const bool *input1_data,
+  const Shape &input2_shape, const bool *input2_data, const Shape &output_shape, bool *output_data,
+  const std::function<bool(const bool &, const bool &)> &fn)
+{
+  NdArrayDesc<4> desc1;
+  NdArrayDesc<4> desc2;
+  NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, &desc2);
+  const Shape extended_output_shape = Shape::ExtendedShape(4, output_shape);
+
+  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)
+        {
+          output_data[Offset(extended_output_shape, b, y, x, c)] =
+            fn(input1_data[SubscriptToIndex(desc1, b, y, x, c)],
+               input2_data[SubscriptToIndex(desc2, b, y, x, c)]);
+        }
+      }
+    }
+  }
+}
+
 } // namespace reference
 } // namespace cker
 } // namespace nnfw
diff --git a/compute/cker/include/cker/train/operation/BinaryArithmetic.h b/compute/cker/include/cker/train/operation/BinaryArithmetic.h
new file mode 100644 (file)
index 0000000..d312d45
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_BINARYARITHMETIC_H__
+#define __NNFW_CKER_TRAIN_OPERATION_BINARYARITHMETIC_H__
+
+#include "cker/Shape.h"
+#include "cker/eigen/Utils.h"
+#include "cker/operation/BroadcastTo.h"
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+enum class ArithmeticType
+{
+  kAdd,
+  kSub,
+  kMul,
+  kDiv,
+};
+
+template <typename T>
+void BinaryArithmeticGrad(const Shape &lhs_shape, const T *lhs_data, const Shape &rhs_shape,
+                          const T *rhs_data, const Shape &incoming_shape, const T *incoming_data,
+                          const Shape &lhs_grad_shape, T *lhs_grad_data,
+                          const Shape &rhs_grad_shape, T *rhs_grad_data,
+                          ArithmeticType arithmetic_type)
+{
+  if (!(lhs_shape == rhs_shape && rhs_shape == incoming_shape && incoming_shape == lhs_grad_shape &&
+        lhs_grad_shape == rhs_grad_shape))
+    throw std::runtime_error{"Shape of lhs, rhs, incoming, lhs_grad, and rhs_grad must match"};
+
+  switch (arithmetic_type)
+  {
+    case ArithmeticType::kAdd:
+    {
+      BroadcastTo(incoming_shape, const_cast<T *>(incoming_data), lhs_grad_shape, lhs_grad_data);
+      BroadcastTo(incoming_shape, const_cast<T *>(incoming_data), rhs_grad_shape, rhs_grad_data);
+    }
+    break;
+
+    case ArithmeticType::kSub:
+    {
+      BroadcastTo(incoming_shape, const_cast<T *>(incoming_data), lhs_grad_shape, lhs_grad_data);
+
+      auto const in_map = MapAsVector(incoming_data, incoming_shape);
+      auto rhs_grad_map = MapAsVector(rhs_grad_data, rhs_grad_shape);
+      rhs_grad_map = -in_map;
+    }
+    break;
+
+    case ArithmeticType::kMul:
+    {
+      auto const in_map = MapAsVector(incoming_data, incoming_shape);
+      auto const lhs_map = MapAsVector(lhs_data, lhs_shape);
+      auto const rhs_map = MapAsVector(rhs_data, rhs_shape);
+      auto lhs_grad_map = MapAsVector(lhs_grad_data, lhs_grad_shape);
+      auto rhs_grad_map = MapAsVector(rhs_grad_data, rhs_grad_shape);
+
+      lhs_grad_map = in_map.array() * rhs_map.array();
+      rhs_grad_map = in_map.array() * lhs_map.array();
+    }
+    break;
+
+    case ArithmeticType::kDiv:
+    default:
+      throw std::runtime_error{"Unsupported Binary Arithmetic Operation"};
+  }
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPERATION_BINARYARITHMETIC_H__
diff --git a/compute/cker/include/cker/train/operation/Conv.h b/compute/cker/include/cker/train/operation/Conv.h
new file mode 100644 (file)
index 0000000..640352e
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * 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.
+ */
+
+#ifndef __NNFW_CKER_TRAIN_OPERATION_CONV_H__
+#define __NNFW_CKER_TRAIN_OPERATION_CONV_H__
+
+#include "cker/operation/Helper/Tensor.h"
+#include "cker/eigen/eigen_backward_spatial_convolutions.h"
+#include "cker/eigen/EigenSupport.h"
+#include "cker/eigen/Utils.h"
+#include "cker/Shape.h"
+#include "cker/Types.h"
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+// From tensorflow/core/kernels/conv_2d.h
+namespace functor
+{
+
+template <typename Device, typename T> struct SpatialConvolutionBackwardInputFunc
+{
+  void operator()(const Device &d, typename TTypes<T, 4>::Tensor input_backward,
+                  typename TTypes<T, 4>::ConstTensor filter,
+                  typename TTypes<T, 4>::ConstTensor output_backward, Eigen::DenseIndex col_stride,
+                  Eigen::DenseIndex row_stride, Eigen::DenseIndex col_dilation,
+                  Eigen::DenseIndex row_dilation)
+  {
+    input_backward.device(d) = Eigen::SpatialConvolutionBackwardInput(
+      filter, output_backward, input_backward.dimension(2), input_backward.dimension(1), col_stride,
+      row_stride, col_dilation, row_dilation);
+  }
+};
+
+template <typename Device, typename T> struct SpatialConvolutionBackwardInputWithExplicitPaddingFunc
+{
+  void operator()(const Device &d, typename TTypes<T, 4>::Tensor input_backward,
+                  typename TTypes<T, 4>::ConstTensor filter,
+                  typename TTypes<T, 4>::ConstTensor output_backward, Eigen::DenseIndex padded_cols,
+                  Eigen::DenseIndex padded_rows, Eigen::DenseIndex col_stride,
+                  Eigen::DenseIndex row_stride, Eigen::DenseIndex col_dilation,
+                  Eigen::DenseIndex row_dilation, Eigen::DenseIndex pad_left,
+                  Eigen::DenseIndex pad_top)
+  {
+    // We have to slice the result of a spatial convolution backward
+    // input, before assigning it to the `input_backward` to remove padding.
+    //
+    // TODO(ezhulenev): Pass explicit paddings to Eigen and do not materialize
+    // intermediate result in memory before slicing.
+    input_backward.device(d) =
+      Eigen::SpatialConvolutionBackwardInput(filter, output_backward, padded_cols, padded_rows,
+                                             col_stride, row_stride, col_dilation, row_dilation)
+        .eval()
+        .slice(Eigen::DSizes<Eigen::DenseIndex, 4>{0, pad_left, pad_top, 0},
+               input_backward.dimensions());
+  }
+};
+
+} // namespace functor
+
+// From tensorflow/core/kernels/conv_grad_input_ops.h
+// Computes backprop input using Eigen::SpatialConvolutionBackwardInput on CPU
+// and GPU (for int32 only).
+template <typename Device, typename T> struct LaunchConv2DBackpropInputOpImpl
+{
+  void operator()(const Device &d, const T *out_backprop_data, int batches, int out_backprop_height,
+                  int out_backprop_width, int output_depth, const T *filter_data, int filter_height,
+                  int filter_width, int row_dilation, int col_dilation, int row_stride /* H */,
+                  int col_stride /* W */, const PaddingType &padding_type, int padding_top,
+                  int padding_bottom, int padding_left, int padding_right, T *in_backprop_data,
+                  int in_backprop_height, int in_backprop_width, int input_depth)
+  {
+    // WARNING: Need to swap row/col, padding_top/padding_left, and
+    // padding_bottom/padding_right when calling Eigen. Eigen expects tensors
+    // in NWHC format, but Tensorflow uses NHWC.
+
+    eigen_support::EigenTensor in_backprop_t(in_backprop_data, batches, in_backprop_height,
+                                             in_backprop_width, input_depth);
+    eigen_support::ConstEigenTensor filter_t(filter_data, filter_height, filter_width, input_depth,
+                                             output_depth);
+    eigen_support::ConstEigenTensor out_backprop_t(out_backprop_data, batches, out_backprop_height,
+                                                   out_backprop_width, output_depth);
+
+    if (padding_type != PaddingType::kNone /* EXPLICIT */)
+    {
+      // If padding was not explicitly defined, Eigen spatial convolution
+      // backward input will infer correct forward paddings from input tensors.
+      functor::SpatialConvolutionBackwardInputFunc<Device, T>()(
+        d, in_backprop_t, filter_t, out_backprop_t, col_stride, row_stride, col_dilation,
+        row_dilation);
+    }
+    else
+    {
+      functor::SpatialConvolutionBackwardInputWithExplicitPaddingFunc<Device, T>()(
+        d, in_backprop_t, filter_t, out_backprop_t,
+        in_backprop_t.dimension(2) + (padding_left + padding_right),
+        in_backprop_t.dimension(1) + (padding_top + padding_bottom), col_stride, row_stride,
+        col_dilation, row_dilation, padding_top, padding_left);
+    }
+  }
+};
+
+// Computes backprop input using Eigen::SpatialConvolutionBackwardInput on CPU.
+template <typename T> struct LaunchConv2DBackpropInputOp
+{
+  void operator()(const T *out_backprop_data, int batches, int out_backprop_height,
+                  int out_backprop_width, int output_depth, const T *filter_data, int filter_height,
+                  int filter_width, int row_dilation, int col_dilation, int row_stride /* H */,
+                  int col_stride /* W */, const PaddingType &padding_type, int padding_top,
+                  int padding_bottom, int padding_left, int padding_right, T *in_backprop_data,
+                  int in_backprop_height, int in_backprop_width, int input_depth)
+  {
+    LaunchConv2DBackpropInputOpImpl<Eigen::ThreadPoolDevice, T> launcher;
+    launcher(*eigen_support::GetThreadPoolDevice(), out_backprop_data, batches, out_backprop_height,
+             out_backprop_width, output_depth, filter_data, filter_height, filter_width,
+             row_dilation, col_dilation, row_stride, col_stride, padding_type, padding_top,
+             padding_bottom, padding_left, padding_right, in_backprop_data, in_backprop_height,
+             in_backprop_width, input_depth);
+  }
+};
+
+// From tensorflow/core/kernels/conv_grad_filter_ops.cc
+template <typename T> struct LaunchConv2DBackpropFilterOp
+{
+  void operator()(const T *out_backprop_data, int batches, int out_backprop_height,
+                  int out_backprop_width, int output_depth, const T *input_data, int input_height,
+                  int input_width, int input_depth, int row_dilation, int col_dilation,
+                  int row_stride /* H */, int col_stride /* W */, const PaddingType &padding_type,
+                  int padding_top, int padding_bottom, int padding_left, int padding_right,
+                  T *filter_backprop_data, int filter_backprop_height, int filter_backprop_width)
+  {
+    eigen_support::EigenTensor filter_backprop_t(filter_backprop_data, filter_backprop_height,
+                                                 filter_backprop_width, input_depth, output_depth);
+    eigen_support::ConstEigenTensor input_t(input_data, batches, input_height, input_width,
+                                            input_depth);
+    eigen_support::ConstEigenTensor out_backprop_t(out_backprop_data, batches, out_backprop_height,
+                                                   out_backprop_width, output_depth);
+
+    const Eigen::ThreadPoolDevice &d = *eigen_support::GetThreadPoolDevice();
+
+    if (padding_type != PaddingType::kNone /* EXPLICIT */)
+    {
+      // If padding was not explicitly defined, Eigen spatial convolution
+      // backward filter will infer correct forward paddings from input tensors.
+      filter_backprop_t.device(d) = Eigen::SpatialConvolutionBackwardKernel(
+        input_t, out_backprop_t, filter_backprop_t.dimension(1), filter_backprop_t.dimension(0),
+        col_stride, row_stride, col_dilation, row_dilation);
+    }
+    else
+    {
+      // Otherwise we have to explicitly pad the input, before passing it to
+      // spatial convolution backward filter.
+      Eigen::array<std::pair<int, int>, 4> paddings;
+      paddings[0] = {0, 0};
+      paddings[1] = {padding_top, padding_bottom};
+      paddings[2] = {padding_left, padding_right};
+      paddings[3] = {0, 0};
+
+      auto padded_t = input_t.pad(paddings, T(0));
+
+      // TODO(ezhulenev): Pass explicit paddings to Eigen spatial backward
+      // convolution and do not rely on tensor padding expression.
+      filter_backprop_t.device(d) = Eigen::SpatialConvolutionBackwardKernel(
+        padded_t, out_backprop_t, filter_backprop_t.dimension(1), filter_backprop_t.dimension(0),
+        col_stride, row_stride, col_dilation, row_dilation);
+    }
+  }
+};
+
+inline void ConvInputGrad(const ConvParams &params, const Shape &incoming_shape,
+                          const float *incoming_data, const Shape &filter_shape,
+                          const float *filter_data, const int padding_bottom,
+                          const int padding_right, const Shape &grad_shape, float *grad_data)
+{
+  const int stride_rows = params.stride_height;
+  const int stride_cols = params.stride_width;
+  const PaddingType padding = params.padding_type;
+  const int padding_top = params.padding_values.height;
+  const int padding_left = params.padding_values.width;
+  assert(padding_top >= 0);
+  assert(padding_bottom >= 0);
+  assert(padding_left >= 0);
+  assert(padding_right >= 0);
+  const int dilation_rows = params.dilation_height_factor;
+  const int dilation_cols = params.dilation_width_factor;
+
+  const int batches = MatchingDim(grad_shape, 0, incoming_shape, 0);
+  const int input_depth = MatchingDim(filter_shape, 2, grad_shape, 3);
+  const int output_depth = MatchingDim(filter_shape, 3, incoming_shape, 3);
+  const int grad_height = grad_shape.Dims(1);
+  const int grad_width = grad_shape.Dims(2);
+  const int filter_height = filter_shape.Dims(0);
+  const int filter_width = filter_shape.Dims(1);
+  const int incoming_height = incoming_shape.Dims(1);
+  const int incoming_width = incoming_shape.Dims(2);
+
+  if (dilation_rows != 1 || dilation_cols != 1)
+    throw std::runtime_error("cker::ConvFilterGrad: not yet support dilation rates larger than 1.");
+
+  LaunchConv2DBackpropInputOp<float>()(
+    incoming_data, batches, incoming_height, incoming_width, output_depth, filter_data,
+    filter_height, filter_width, dilation_rows, dilation_cols, stride_rows, stride_cols, padding,
+    padding_top, padding_bottom, padding_left, padding_right, grad_data, grad_height, grad_width,
+    input_depth);
+}
+
+inline void ConvFilterGrad(const ConvParams &params, const Shape &incoming_shape,
+                           const float *incoming_data, const Shape &input_shape,
+                           const float *input_data, const int padding_bottom,
+                           const int padding_right, const Shape &filter_backprop_shape,
+                           float *filter_backprop_data)
+{
+  const int stride_rows = params.stride_height;
+  const int stride_cols = params.stride_width;
+  const PaddingType padding = params.padding_type;
+  const int padding_top = params.padding_values.height;
+  const int padding_left = params.padding_values.width;
+  assert(padding_top >= 0);
+  assert(padding_bottom >= 0);
+  assert(padding_left >= 0);
+  assert(padding_right >= 0);
+  const int dilation_rows = params.dilation_height_factor;
+  const int dilation_cols = params.dilation_width_factor;
+
+  const int batches = MatchingDim(input_shape, 0, incoming_shape, 0);
+  const int input_depth = MatchingDim(filter_backprop_shape, 2, input_shape, 3);
+  const int output_depth = MatchingDim(filter_backprop_shape, 3, incoming_shape, 3);
+  const int input_height = input_shape.Dims(1);
+  const int input_width = input_shape.Dims(2);
+  const int filter_backprop_height = filter_backprop_shape.Dims(0);
+  const int filter_backprop_width = filter_backprop_shape.Dims(1);
+  const int incoming_height = incoming_shape.Dims(1);
+  const int incoming_width = incoming_shape.Dims(2);
+
+  if (dilation_rows != 1 || dilation_cols != 1)
+    throw std::runtime_error("cker::ConvFilterGrad: not yet support dilation rates larger than 1.");
+
+  LaunchConv2DBackpropFilterOp<float>()(
+    incoming_data, batches, incoming_height, incoming_width, output_depth, input_data, input_height,
+    input_width, input_depth, dilation_rows, dilation_cols, stride_rows, stride_cols, padding,
+    padding_top, padding_bottom, padding_left, padding_right, filter_backprop_data,
+    filter_backprop_height, filter_backprop_width);
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPERATION_RELU_H__
diff --git a/compute/cker/include/cker/train/operation/DepthwiseConv.h b/compute/cker/include/cker/train/operation/DepthwiseConv.h
new file mode 100644 (file)
index 0000000..b9fab25
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_DEPTHWISECONV_H__
+#define __NNFW_CKER_TRAIN_OPERATION_DEPTHWISECONV_H__
+
+#include "cker/eigen/depthwise_conv_op.h"
+#include "cker/Shape.h"
+#include "cker/Types.h"
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+class DepthwiseConv
+{
+public:
+  DepthwiseConv() = default;
+
+  template <typename T> int64_t kPacketSize() const
+  {
+    typedef typename Eigen::internal::packet_traits<T>::type Packet;
+    return sizeof(Packet) / sizeof(T);
+  }
+
+  int getThreadCount() const
+  {
+    // NOTE The Eigen library uses both main thread as well as a thread pool.
+    // Therefore, it needs to add an additional memory buffer for main thread.
+    const Eigen::ThreadPoolDevice &d = *eigen_support::GetThreadPoolDevice();
+    return d.numThreads() + 1;
+  }
+
+  template <typename T>
+  void backpropInput(const DepthwiseConvParams &params, const Shape &incoming_shape,
+                     const T *incoming_data, const Shape &filter_shape, const T *filter_data,
+                     T *padded_filter_data, const Shape &grad_shape, T *grad_data, bool pad_filter,
+                     T *filter_buffers_data, T *filter_dim_buffers_data)
+  {
+    if (params.stride_height != params.stride_width)
+      throw std::runtime_error("Not support different length strides");
+
+    const int batch = MatchingDim(incoming_shape, 0, grad_shape, 0);
+    const int input_depth = grad_shape.Dims(3);
+    const int output_depth = incoming_shape.Dims(3);
+    const int incoming_height = incoming_shape.Dims(1);
+    const int incoming_width = incoming_shape.Dims(2);
+    const int grad_height = grad_shape.Dims(1);
+    const int grad_width = grad_shape.Dims(2);
+    const int stride = params.stride_height;
+    const int depth_multiplier = params.depth_multiplier;
+    const int filter_height = filter_shape.Dims(1);
+    const int filter_width = filter_shape.Dims(2);
+    const int pad_height = params.padding_values.height;
+    const int pad_width = params.padding_values.width;
+
+    depthwise_conv_op::LaunchDepthwiseConvBackpropInputOp<Eigen::ThreadPoolDevice, T>()(
+      batch, grad_height, grad_width, input_depth, filter_height, filter_width, depth_multiplier,
+      stride, pad_height, pad_width, incoming_height, incoming_width, output_depth, incoming_data,
+      filter_data, padded_filter_data, grad_data, pad_filter, filter_buffers_data,
+      filter_dim_buffers_data);
+  }
+
+  template <typename T>
+  void backpropFilter(const DepthwiseConvParams &params, const Shape &incoming_shape,
+                      const T *incoming_data, const Shape &input_shape, const T *input_data,
+                      const Shape &filter_grad_shape, T *filter_grad_data, T *padded_filter_data,
+                      T *filter_buffers_data)
+  {
+    if (params.stride_height != params.stride_width)
+      throw std::runtime_error("Not support different length strides");
+
+    const int batch = MatchingDim(incoming_shape, 0, input_shape, 0);
+    const int input_depth = input_shape.Dims(3);
+    const int output_depth = incoming_shape.Dims(3);
+    const int incoming_height = incoming_shape.Dims(1);
+    const int incoming_width = incoming_shape.Dims(2);
+    const int input_height = input_shape.Dims(1);
+    const int input_width = input_shape.Dims(2);
+    const int stride = params.stride_height;
+    const int depth_multiplier = params.depth_multiplier;
+    const int filter_height = filter_grad_shape.Dims(1);
+    const int filter_width = filter_grad_shape.Dims(2);
+    const int pad_height = params.padding_values.height;
+    const int pad_width = params.padding_values.width;
+
+    depthwise_conv_op::LaunchDepthwiseConvBackpropFilterOp<Eigen::ThreadPoolDevice, T>()(
+      batch, input_height, input_width, input_depth, filter_height, filter_width, depth_multiplier,
+      stride, pad_height, pad_width, incoming_height, incoming_width, output_depth, incoming_data,
+      input_data, filter_grad_data, padded_filter_data, filter_buffers_data);
+  }
+};
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPERATION_DEPTHWISECONV_H__
index 94f49ff..70f54ad 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef __NNFW_CKER_TRAIN_OPERATION_LOSS_H__
 #define __NNFW_CKER_TRAIN_OPERATION_LOSS_H__
 
+#include <numeric>
+
 #include "cker/Shape.h"
 #include "cker/eigen/Utils.h"
 
@@ -27,31 +29,32 @@ namespace cker
 namespace train
 {
 
+template <typename T> inline T square(T value) { return value * value; }
+template <typename T> inline T log_threshold() { return static_cast<T>(1e-20); }
+
 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 (output_shape.DimensionsCount() != 1)
+    throw std::runtime_error("cker::MSE: output dimension count should be 1");
+  if (output_shape.Dims(0) != y_pred_shape.Dims(0))
+    throw std::runtime_error("cker::MSE: output and y_pred do not have the same batch");
   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);
+  const auto batch = y_pred_shape.Dims(0);
+  const auto size = FlatSizeSkipDim(y_pred_shape, 0);
 
-  double squared_sum = 0.0f;
-  for (size_t c = 0; c < (size_t)y_pred.cols(); ++c)
+  for (int b = 0; b < batch; ++b)
   {
-    for (size_t r = 0; r < (size_t)y_pred.rows(); ++r)
+    float sum = 0.f;
+    for (int i = 0; i < size; ++i)
     {
-      double error = y_pred.coeff(r, c) - y_true.coeff(r, c);
-      squared_sum += (error * error);
+      sum += square(y_pred_data[b * size + i] - y_true_data[b * size + i]);
     }
+    output_data[b] = static_cast<T>(sum / size);
   }
-
-  auto size = y_pred.cols() * y_pred.rows();
-  output_data[0] = (T)(squared_sum / size);
 }
 
 template <typename T>
@@ -70,6 +73,46 @@ inline void MSEGrad(const Shape &y_pred_shape, const T *y_pred_data, const Shape
   }
 }
 
+template <typename T>
+inline void CategoricalCrossEntropy(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)
+{
+  if (output_shape.DimensionsCount() != 1)
+    throw std::runtime_error("cker::CategoricalCrossEntropy: output dimension count should be 1");
+  if (y_pred_shape != y_true_shape)
+    throw std::runtime_error(
+      "cker::CategoricalCrossEntropy: y_pred and y_true do not have the same shape");
+  if (output_shape.Dims(0) != y_pred_shape.Dims(0))
+    throw std::runtime_error(
+      "cker::CategoricalCrossEntropy: output and y_pred do not have the same batch");
+
+  const auto y_pred = MapAsMatrixWithLastDimAsRows(y_pred_data, y_pred_shape);
+  const auto y_true = MapAsMatrixWithLastDimAsRows(y_true_data, y_true_shape);
+  auto output = MapAsVector(output_data, output_shape);
+
+  output = -(y_true.array() * y_pred.array().cwiseMax(log_threshold<T>()).log()).colwise().sum();
+}
+
+template <typename T>
+inline void CategoricalCrossEntropyGrad(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::CategoricalCrossEntropyGrad: y_pred and y_true do not have the same shape");
+  if (y_pred_shape != grad_shape)
+    throw std::runtime_error(
+      "cker::CategoricalCrossEntropyGrad: y_pred and grad do not have the same shape");
+
+  const auto y_pred = MapAsMatrixWithLastDimAsRows(y_pred_data, y_pred_shape);
+  const auto y_true = MapAsMatrixWithLastDimAsRows(y_true_data, y_true_shape);
+  auto grad = MapAsMatrixWithLastDimAsRows(grad_data, grad_shape);
+
+  grad = -(y_true.array() / y_pred.array().cwiseMax(log_threshold<T>()));
+}
+
 } // namespace train
 } // namespace cker
 } // namespace nnfw
diff --git a/compute/cker/include/cker/train/operation/MaxPool.h b/compute/cker/include/cker/train/operation/MaxPool.h
new file mode 100644 (file)
index 0000000..cfe4a34
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_MAXPOOL_H__
+#define __NNFW_CKER_TRAIN_OPERATION_MAXPOOL_H__
+
+#include "cker/Shape.h"
+#include "cker/Utils.h"
+#include "cker/eigen/Utils.h"
+
+#include <Eigen/Core>
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+// Most of the logic except 'arg_max_index' related is copy-paste from
+// https://github.com/Samsung/ONE/blob/a380292/compute/cker/include/cker/operation/MaxPool.h#L42-L88
+// 'arg_max_index' is to record max-arguments' index to apply gradient later.
+inline void MaxPool2D(const PoolParams &params, const Shape &input_shape, const float *input_data,
+                      const Shape &output_shape, float *output_data, int *arg_max_index)
+{
+  assert(input_shape.DimensionsCount() == 4);
+  assert(output_shape.DimensionsCount() == 4);
+  assert(input_shape.Dims(0) == output_shape.Dims(0)); // MaxPool2D doesn't change batch
+  assert(input_shape.Dims(3) == output_shape.Dims(3)); // MaxPool2D doesn't change depth
+
+  const int batches = MatchingDim(input_shape, 0, output_shape, 0);
+  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 filter_height = params.filter_height;
+  const int filter_width = params.filter_width;
+  const int pad_height = params.padding_values.height;
+  const int pad_width = params.padding_values.width;
+  const int stride_height = params.stride_height;
+  const int stride_width = params.stride_width;
+
+  const auto in_mat = MapAsMatrixWithLastDimAsRows(input_data, input_shape);
+  auto out_mat = MapAsMatrixWithLastDimAsRows(output_data, output_shape);
+  auto arg_max_index_mat = MapAsMatrixWithLastDimAsRows(arg_max_index, output_shape);
+
+  // initialize output area
+  std::fill(output_data, output_data + output_shape.FlatSize(), 0.0);
+  std::fill(arg_max_index, arg_max_index + output_shape.FlatSize(), -1);
+
+  // initialize projected area with lowest float
+  const int h_start =
+    (pad_height < filter_height) ? 0 : (pad_height - filter_height) / stride_height + 1;
+  const int h_end = std::min((input_height + pad_height - 1) / stride_height + 1, output_height);
+
+  const int w_start =
+    (pad_width < filter_width) ? 0 : (pad_width - filter_width) / stride_width + 1;
+  const int w_end = std::min((input_width + pad_width - 1) / stride_width + 1, output_width);
+
+  for (int b = 0; b < batches; ++b)
+  {
+    for (int h_idx = h_start; h_idx < h_end; h_idx++)
+    {
+      for (int w_idx = w_start; w_idx < w_end; w_idx++)
+      {
+        const int offset = NodeOffset(b, h_idx, w_idx, output_height, output_width);
+        out_mat.col(offset).setConstant(std::numeric_limits<float>::lowest());
+      }
+    }
+  }
+
+  for (int b = 0; b < batches; ++b)
+  {
+    for (int h = 0; h < input_height; ++h)
+    {
+      for (int w = 0; w < input_width; ++w)
+      {
+        // (h_start, h_end) * (w_start, w_end) is the range that the input
+        // vector projects to.
+        int hpad = h + pad_height;
+        int wpad = w + pad_width;
+
+        int h_start = (hpad < filter_height) ? 0 : (hpad - filter_height) / stride_height + 1;
+        int h_end = std::min(hpad / stride_height + 1, output_height);
+
+        int w_start = (wpad < filter_width) ? 0 : (wpad - filter_width) / stride_width + 1;
+        int w_end = std::min(wpad / stride_width + 1, output_width);
+
+        // compute elementwise sum
+        for (int ph = h_start; ph < h_end; ++ph)
+        {
+          for (int pw = w_start; pw < w_end; ++pw)
+          {
+            const int out_offset = NodeOffset(b, ph, pw, output_height, output_width);
+            const int in_offset = NodeOffset(b, h, w, input_height, input_width);
+
+            const auto out_vector = out_mat.col(out_offset);
+            const auto in_vector = in_mat.col(in_offset);
+
+            // update arg_max_index_mat
+            arg_max_index_mat.col(out_offset) =
+              (out_vector.array() < in_vector.array())
+                .select(in_offset, arg_max_index_mat.col(out_offset));
+
+            // update out_mat
+            out_mat.col(out_offset) = out_vector.cwiseMax(in_vector);
+          }
+        }
+      }
+    }
+  }
+
+  out_mat.cwiseMin(params.float_activation_min).cwiseMax(params.float_activation_max);
+}
+
+inline void MaxPool2DGrad(const Shape &incoming_shape, const float *incoming_data,
+                          const int *arg_max_index, const Shape &grad_shape, float *grad_data)
+{
+  assert(grad_shape.DimensionsCount() == 4);
+  assert(incoming_shape.DimensionsCount() == 4);
+
+  // initialize grad_data
+  std::fill(grad_data, grad_data + grad_shape.FlatSize(), 0.0);
+
+  const int depth = MatchingDim(grad_shape, 3, incoming_shape, 3);
+  const auto incoming_mat = MapAsMatrixWithLastDimAsRows(incoming_data, incoming_shape);
+  auto arg_max_index_mat = MapAsMatrixWithLastDimAsRows(arg_max_index, incoming_shape);
+  auto grad_mat = MapAsMatrixWithLastDimAsRows(grad_data, grad_shape);
+
+  for (int col_index = 0; col_index < incoming_mat.cols(); col_index++)
+  {
+    auto arg_indices = arg_max_index_mat.col(col_index);
+    for (int d = 0; d < depth; d++)
+    {
+      // output value is from padding, so nothing to propagate
+      if (arg_indices(d) == -1)
+        continue;
+
+      grad_mat(d, arg_indices(d)) += incoming_mat(d, col_index);
+    }
+  }
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPERATION_MAXPOOL_H__
diff --git a/compute/cker/include/cker/train/operation/Pad.h b/compute/cker/include/cker/train/operation/Pad.h
new file mode 100644 (file)
index 0000000..f3f4a93
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_PAD_H__
+#define __NNFW_CKER_TRAIN_OPERATION_PAD_H__
+
+#include "cker/operation/Pad.h"
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+/*
+ * input_data will be transformed by PAD operation with padding options(such as constant C) to
+ * output_data
+ *
+ * input_data  ->  output_data
+ *   [0,1]     ->    [C,C,C,C]
+ *   [2,3]     ->    [C,0,1,C]
+ *             ->    [C,2,3,C]
+ *             ->    [C,C,C,C]
+ */
+/*
+ * input_data(backward_output_data) will be transformed by backward of PAD operation (Depad) with
+ * padding options to output_data(backward_input_data)
+ *
+ * input_data(backward_output_data)  ->  output_data(backward_input_data)
+ *   [C,C,C,C]                       ->    [0,1]
+ *   [C,0,1,C]                       ->    [2,3]
+ *   [C,2,3,C]                       ->
+ *   [C,C,C,C]                       ->
+ */
+template <typename T>
+inline void Depad(const int32_t *padding_data, int32_t pad_rank, const Shape &input_shape,
+                  const T *input_data, const Shape &output_shape, T *output_data)
+{
+  using PaddingInfo = std::pair<int32_t, int32_t>;
+  using PaddingList = std::vector<PaddingInfo>;
+
+  assert(output_shape.DimensionsCount() == input_shape.DimensionsCount());
+  assert(output_shape.DimensionsCount() == pad_rank);
+
+  PaddingList padding_list(pad_rank);
+  for (int32_t n = 0; n < pad_rank; ++n)
+  {
+    const int32_t *from = padding_data + (n * 2);
+    assert(from[0] >= 0 && from[1] >= 0);
+    padding_list[n] = {from[0], from[1]};
+  }
+  for (int32_t i = 0; i < pad_rank; ++i)
+  {
+    assert(output_shape.Dims(i) ==
+           input_shape.Dims(i) - padding_list[i].first - padding_list[i].second);
+  }
+
+  // logical axis: row -> col -> plain -> cube
+  switch (pad_rank)
+  {
+    case 0:
+    case 1:
+    {
+      const int32_t out_row_len = output_shape.Dims(0);
+      const int32_t padding_left = padding_list[0].first;
+      std::memcpy(output_data, input_data + padding_left, out_row_len * sizeof(T));
+      break;
+    }
+    case 2: // HW
+    {
+      const int32_t out_col_len = output_shape.Dims(0);
+      const int32_t out_row_len = output_shape.Dims(1);
+      const int32_t in_row_len = input_shape.Dims(1);
+      const int32_t padding_top = padding_list[0].first;
+      const int32_t padding_left = padding_list[1].first;
+      for (auto i = 0; i < out_col_len; ++i)
+      {
+        const auto in_offset = (i + padding_top) * in_row_len + padding_left;
+        const auto out_offset = i * out_row_len;
+        // copy a row of input data to output data
+        std::memcpy(output_data + out_offset, input_data + in_offset, out_row_len * sizeof(T));
+      }
+      break;
+    }
+    case 3: // HWC
+    {
+      const int32_t out_plain_len = output_shape.Dims(0);
+      const int32_t out_col_len = output_shape.Dims(1);
+      const int32_t out_row_len = output_shape.Dims(2);
+      const int32_t out_plain_size = out_col_len * out_row_len;
+      const int32_t in_col_len = input_shape.Dims(1);
+      const int32_t in_row_len = input_shape.Dims(2);
+      const int32_t in_plain_size = in_col_len * in_row_len;
+      const int32_t padding_depth = padding_list[0].first;
+      const int32_t padding_top = padding_list[1].first;
+      const int32_t padding_left = padding_list[2].first;
+      for (auto d = 0; d < out_plain_len; ++d)
+      {
+        for (auto h = 0; h < out_col_len; ++h)
+        {
+          const auto in_offset =
+            (d + padding_depth) * in_plain_size + (h + padding_top) * in_row_len + (padding_left);
+          const auto out_offset = (d * out_plain_size) + (h * out_row_len);
+          // copy a row of input data to output data
+          std::memcpy(output_data + out_offset, input_data + in_offset, out_row_len * sizeof(T));
+        }
+      }
+      break;
+    }
+    case 4: // NHWC
+    {
+      const int32_t out_cube_len = output_shape.Dims(0);
+      const int32_t out_plain_len = output_shape.Dims(1);
+      const int32_t out_col_len = output_shape.Dims(2);
+      const int32_t out_row_len = output_shape.Dims(3);
+      const int32_t out_plain_size = out_col_len * out_row_len;
+      const int32_t out_cube_size = out_plain_len * out_plain_size;
+      const int32_t in_plain_len = input_shape.Dims(1);
+      const int32_t in_col_len = input_shape.Dims(2);
+      const int32_t in_row_len = input_shape.Dims(3);
+      const int32_t in_plain_size = in_col_len * in_row_len;
+      const int32_t in_cube_size = in_plain_len * in_plain_size;
+      const int32_t padding_cube = padding_list[0].first;
+      const int32_t padding_depth = padding_list[1].first;
+      const int32_t padding_top = padding_list[2].first;
+      const int32_t padding_left = padding_list[3].first;
+      for (auto c = 0; c < out_cube_len; ++c)
+      {
+        for (auto d = 0; d < out_plain_len; ++d)
+        {
+          for (auto h = 0; h < out_col_len; ++h)
+          {
+            const auto in_offset = (c + padding_cube) * in_cube_size +
+                                   (d + padding_depth) * in_plain_size +
+                                   (h + padding_top) * in_row_len + (padding_left);
+            const auto out_offset = (c * out_cube_size) + (d * out_plain_size) + (h * out_row_len);
+            // copy a row of input data to output data
+            std::memcpy(output_data + out_offset, input_data + in_offset, out_row_len * sizeof(T));
+          }
+        }
+      }
+      break;
+    }
+    default:
+      throw std::runtime_error("Padding for rank > 4 NYI");
+      break;
+  }
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPERATION_PAD_H__
diff --git a/compute/cker/include/cker/train/operation/ReLU6.h b/compute/cker/include/cker/train/operation/ReLU6.h
new file mode 100644 (file)
index 0000000..3016a03
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_RELU6_H__
+#define __NNFW_CKER_TRAIN_OPERATION_RELU6_H__
+
+#include "cker/Shape.h"
+#include "cker/eigen/Utils.h"
+#include <Eigen/Core>
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+inline void ReLU6Grad(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)
+    throw std::runtime_error{"cker::ReLU6Grad: Unsupported shape"};
+
+  grad_map.array() =
+    incoming_map.array() *
+    (0.0f < output_map.array() && output_map.array() < 6.0f).template cast<float>();
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPERATION_RELU6_H__
diff --git a/compute/cker/include/cker/train/operation/ReduceMean.h b/compute/cker/include/cker/train/operation/ReduceMean.h
new file mode 100644 (file)
index 0000000..27011cf
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_REDUCEMEAN_H__
+#define __NNFW_CKER_TRAIN_OPERATION_REDUCEMEAN_H__
+
+#include "cker/Shape.h"
+#include "cker/eigen/Utils.h"
+#include "cker/operation/BroadcastTo.h"
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+template <typename T>
+void MeanGrad(const Shape &incoming_shape, const T *incoming_data, const Shape &grad_shape,
+              T *grad_data)
+{
+  BroadcastTo(incoming_shape, const_cast<T *>(incoming_data), grad_shape, grad_data);
+  const auto incoming = MapAsMatrixWithLastDimAsRows(incoming_data, incoming_shape);
+  auto grad = MapAsMatrixWithLastDimAsRows(grad_data, grad_shape);
+  grad /= (grad.size() / incoming.size());
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPERATION_REDUCEMEAN_H__
diff --git a/compute/cker/include/cker/train/operation/SoftMax.h b/compute/cker/include/cker/train/operation/SoftMax.h
new file mode 100644 (file)
index 0000000..540dcf5
--- /dev/null
@@ -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 __NNFW_CKER_TRAIN_SOFTMAX_H__
+#define __NNFW_CKER_TRAIN_SOFTMAX_H__
+
+#include "cker/Shape.h"
+#include "cker/eigen/Utils.h"
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+inline void SoftMaxGrad(const Shape &output_shape, const float *output_data,
+                        const Shape &incoming_shape, const float *incoming_data,
+                        const Shape &grad_shape, float *grad_data)
+{
+  // TODO Support 4dim softmax gradient
+  assert(incoming_shape.DimensionsCount() == 2);
+  MatchingFlatSize(output_shape, incoming_shape, grad_shape);
+
+  const int batches = incoming_shape.Dims(0);
+  const int width = incoming_shape.Dims(1);
+
+  for (int b = 0; b < batches; ++b)
+  {
+    int b_offset = b * width;
+    for (int w1 = 0; w1 < width; ++w1)
+    {
+      float sum = 0.0f;
+      for (int w2 = 0; w2 < width; ++w2)
+      {
+        float val;
+        if (w1 == w2)
+        {
+          val = output_data[b_offset + w2] * (1.f - output_data[b_offset + w2]);
+        }
+        else
+        {
+          val = -output_data[b_offset + w2] * output_data[b_offset + w1];
+        }
+        val *= incoming_data[b_offset + w2];
+        sum += val;
+      }
+      grad_data[b_offset + w1] = sum;
+    }
+  }
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_SOFTMAX_H__
diff --git a/compute/cker/include/cker/train/optimizer/Adam.h b/compute/cker/include/cker/train/optimizer/Adam.h
new file mode 100644 (file)
index 0000000..e5fd9eb
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2016 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_OPTIMIZER_ADAM_H__
+#define __NNFW_CKER_TRAIN_OPTIMIZER_ADAM_H__
+
+#include "cker/eigen/training_ops.h"
+#include "cker/eigen/EigenSupport.h"
+
+#include <vector>
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+inline void Adam(const Shape &trainable_shape, float *trainable_data, const Shape &grad_shape,
+                 const float *grad_data, const Shape &m_shape, float *m_data, const Shape &v_shape,
+                 float *v_data, float beta1_power, float beta2_power, float learning_rate,
+                 float beta1, float beta2, float epsilon, bool use_nesterov)
+{
+  Tensor trainable_tensor;
+  Tensor grad_tensor;
+  Tensor m_tensor;
+  Tensor v_tensor;
+  Tensor beta1_power_tensor;
+  Tensor beta2_power_tensor;
+  Tensor lr_tensor;
+  Tensor beta1_tensor;
+  Tensor beta2_tensor;
+  Tensor epsilon_tensor;
+
+  trainable_tensor.shape.ReplaceWith(trainable_shape.DimensionsCount(), trainable_shape.DimsData());
+  trainable_tensor.buffer = trainable_data;
+
+  grad_tensor.shape.ReplaceWith(grad_shape.DimensionsCount(), grad_shape.DimsData());
+  grad_tensor.buffer = const_cast<float *>(grad_data);
+
+  m_tensor.shape.ReplaceWith(m_shape.DimensionsCount(), m_shape.DimsData());
+  m_tensor.buffer = m_data;
+
+  v_tensor.shape.ReplaceWith(v_shape.DimensionsCount(), v_shape.DimsData());
+  v_tensor.buffer = v_data;
+
+  std::vector<float> beta1_power_vec{beta1_power};
+  beta1_power_tensor.buffer = beta1_power_vec.data();
+
+  std::vector<float> beta2_power_vec{beta2_power};
+  beta2_power_tensor.buffer = beta2_power_vec.data();
+
+  std::vector<float> lr_vec{learning_rate};
+  lr_tensor.buffer = lr_vec.data();
+
+  std::vector<float> beta1_vec{beta1};
+  beta1_tensor.buffer = beta1_vec.data();
+
+  std::vector<float> beta2_vec{beta2};
+  beta2_tensor.buffer = beta2_vec.data();
+
+  std::vector<float> epsilon_vec{epsilon};
+  epsilon_tensor.buffer = epsilon_vec.data();
+
+  if (trainable_shape != m_shape)
+    throw std::runtime_error("cker::Adam: output and m do not have the same shape");
+
+  if (trainable_shape != v_shape)
+    throw std::runtime_error("cker::Adam: output and v do not have the same shape");
+
+  if (trainable_shape != grad_shape)
+    throw std::runtime_error("cker::Adam: output and gradient do not have the same shape");
+
+  const training_ops::CPUDevice &device = *eigen_support::GetThreadPoolDevice();
+  training_ops::functor::ApplyAdam<training_ops::CPUDevice, float>()(
+    device, trainable_tensor.flat<float>(), m_tensor.flat<float>(), v_tensor.flat<float>(),
+    beta1_power_tensor.scalar<float>(), beta2_power_tensor.scalar<float>(),
+    lr_tensor.scalar<float>(), beta1_tensor.scalar<float>(), beta2_tensor.scalar<float>(),
+    epsilon_tensor.scalar<float>(), static_cast<const Tensor &>(grad_tensor).flat<float>(),
+    use_nesterov);
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPTIMIZER_ADAM_H__
diff --git a/compute/cker/include/cker/train/optimizer/SGD.h b/compute/cker/include/cker/train/optimizer/SGD.h
new file mode 100644 (file)
index 0000000..5bc1223
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2016 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_OPTIMIZER_SGD_H__
+#define __NNFW_CKER_TRAIN_OPTIMIZER_SGD_H__
+
+#include "cker/eigen/training_ops.h"
+#include "cker/eigen/EigenSupport.h"
+
+#include <vector>
+
+namespace nnfw
+{
+namespace cker
+{
+namespace train
+{
+
+inline void GradientDescent(const Shape &output_shape, float *output_data, const Shape &grad_shape,
+                            const float *grad_data, float learning_rate)
+{
+  Tensor output_tensor;
+  Tensor grad_tensor;
+  Tensor lr_tensor;
+
+  output_tensor.shape.ReplaceWith(output_shape.DimensionsCount(), output_shape.DimsData());
+  output_tensor.buffer = output_data;
+
+  grad_tensor.shape.ReplaceWith(grad_shape.DimensionsCount(), grad_shape.DimsData());
+  grad_tensor.buffer = const_cast<float *>(grad_data);
+
+  std::vector<float> lr_vec{learning_rate};
+  lr_tensor.buffer = lr_vec.data();
+
+  if (output_shape != grad_shape)
+    throw std::runtime_error(
+      "cker::GradientDescent: output and gradient do not have the same shape");
+
+  const training_ops::CPUDevice &device = *eigen_support::GetThreadPoolDevice();
+  training_ops::functor::ApplyGradientDescent<training_ops::CPUDevice, float>()(
+    device, output_tensor.flat<float>(), lr_tensor.scalar<float>(),
+    static_cast<const Tensor &>(grad_tensor).flat<float>());
+}
+
+} // namespace train
+} // namespace cker
+} // namespace nnfw
+
+#endif // __NNFW_CKER_TRAIN_OPTIMIZER_SGD_H__
diff --git a/compute/cker/src/FloorMod.test.cc b/compute/cker/src/FloorMod.test.cc
new file mode 100644 (file)
index 0000000..16105bb
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * 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 <cker/operation/FloorMod.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+TEST(CKer_Operation, FloorMod)
+{
+  // Simple
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<int32_t> input1 = {10, 9, 11, 3};
+    // Shape: {1, 2, 2, 1}
+    std::vector<int32_t> input2 = {2, 2, 3, 4};
+    std::vector<int32_t> expected_output = {0, 1, 2, 3};
+    std::vector<int32_t> output(4);
+
+    nnfw::cker::FloorModElementwise(nnfw::cker::Shape{1, 2, 2, 1}, input1.data(), input2.data(),
+                                    output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      ASSERT_EQ(output[i], expected_output[i]);
+  }
+
+  // Negative Value
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<int32_t> input1 = {10, -9, -11, 7};
+    // Shape: {1, 2, 2, 1}
+    std::vector<int32_t> input2 = {2, 2, -3, -4};
+    std::vector<int32_t> expected_output = {0, 1, -2, -1};
+    std::vector<int32_t> output(4);
+
+    nnfw::cker::FloorModElementwise(nnfw::cker::Shape{1, 2, 2, 1}, input1.data(), input2.data(),
+                                    output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      ASSERT_EQ(output[i], expected_output[i]);
+  }
+
+  // Broadcast
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<int32_t> input1 = {10, -9, -11, 7};
+    // Shape: {1}
+    std::vector<int32_t> input2 = {-3};
+    std::vector<int32_t> expected_output = {-2, 0, -2, -2};
+    std::vector<int32_t> output(4);
+
+    nnfw::cker::FloorModBroadcast(nnfw::cker::Shape{1, 2, 2, 1}, input1.data(),
+                                  nnfw::cker::Shape{1}, input2.data(),
+                                  nnfw::cker::Shape{1, 2, 2, 1}, output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      ASSERT_EQ(output[i], expected_output[i]);
+  }
+
+  // Broadcast Int64
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<int64_t> input1 = {10, -9, -11, (1LL << 34) + 9};
+    // Shape: {1}
+    std::vector<int64_t> input2 = {-(1LL << 33)};
+    std::vector<int64_t> expected_output = {-8589934582, -9, -11, -8589934583};
+    std::vector<int64_t> output(4);
+
+    nnfw::cker::FloorModBroadcast(nnfw::cker::Shape{1, 2, 2, 1}, input1.data(),
+                                  nnfw::cker::Shape{1}, input2.data(),
+                                  nnfw::cker::Shape{1, 2, 2, 1}, output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      ASSERT_EQ(output[i], expected_output[i]);
+  }
+
+  // Simple Float
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<float> input1 = {10, 9, 11, 3};
+    // Shape: {1, 2, 2, 1}
+    std::vector<float> input2 = {2, 2, 3, 4};
+    std::vector<float> expected_output = {0, 1, 2, 3};
+    std::vector<float> output(4);
+
+    nnfw::cker::FloorModElementwise(nnfw::cker::Shape{1, 2, 2, 1}, input1.data(), input2.data(),
+                                    output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      ASSERT_EQ(output[i], expected_output[i]);
+  }
+
+  // Negative Value Float
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<float> input1 = {10, -9, -11, 7};
+    // Shape: {1, 2, 2, 1}
+    std::vector<float> input2 = {2, 2, -3, -4};
+    std::vector<float> expected_output = {0, 1, -2, -1};
+    std::vector<float> output(4);
+
+    nnfw::cker::FloorModElementwise(nnfw::cker::Shape{1, 2, 2, 1}, input1.data(), input2.data(),
+                                    output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      ASSERT_EQ(output[i], expected_output[i]);
+  }
+
+  // Broadcast
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<float> input1 = {10, -9, -11, 7};
+    // Shape: {1}
+    std::vector<float> input2 = {-3};
+    std::vector<float> expected_output = {-2, 0, -2, -2};
+    std::vector<float> output(4);
+
+    nnfw::cker::FloorModBroadcast(nnfw::cker::Shape{1, 2, 2, 1}, input1.data(),
+                                  nnfw::cker::Shape{1}, input2.data(),
+                                  nnfw::cker::Shape{1, 2, 2, 1}, output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      ASSERT_EQ(output[i], expected_output[i]);
+  }
+}
+
+TEST(CKer_Operation, neg_FloorModUnsupportedBroadcastRank)
+{
+  // Unsupported rank
+  {
+    // Shape: {1, 2, 2, 1, 1}
+    std::vector<float> input1 = {10, -9, -11, 7};
+    // Shape: {1}
+    std::vector<float> input2 = {-3};
+    std::vector<float> output(4);
+
+    EXPECT_ANY_THROW(nnfw::cker::FloorModBroadcast(
+      nnfw::cker::Shape{1, 2, 2, 1, 1}, input1.data(), nnfw::cker::Shape{1}, input2.data(),
+      nnfw::cker::Shape{1, 2, 2, 1, 1}, output.data()));
+  }
+}
diff --git a/compute/cker/src/Mul.test.cc b/compute/cker/src/Mul.test.cc
new file mode 100644 (file)
index 0000000..92b14b5
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/BinaryArithmeticOps.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+TEST(CKer_Operation, Mul)
+{
+  // Simple
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<int32_t> input1 = {10, 9, 11, 3};
+    // Shape: {1, 2, 2, 1}
+    std::vector<int32_t> input2 = {2, 2, 3, 4};
+    std::vector<int32_t> expected_output = {20, 18, 33, 12};
+    std::vector<int32_t> output(4);
+
+    nnfw::cker::BinaryArithmeticOpParam param;
+    param.quantized_activation_min = std::numeric_limits<int32_t>::lowest();
+    param.quantized_activation_max = std::numeric_limits<int32_t>::max();
+    nnfw::cker::Shape shape{1, 2, 2, 1};
+
+    nnfw::cker::BinaryArithmeticOp<nnfw::cker::BinaryArithmeticOpType::MUL>(
+      param, shape, input1.data(), shape, input2.data(), shape, output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      EXPECT_EQ(output[i], expected_output[i]);
+  }
+
+  // Negative Value
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<int32_t> input1 = {10, -9, -11, 7};
+    // Shape: {1, 2, 2, 1}
+    std::vector<int32_t> input2 = {2, 2, -3, -4};
+    std::vector<int32_t> expected_output = {20, -18, 33, -28};
+    std::vector<int32_t> output(4);
+
+    nnfw::cker::BinaryArithmeticOpParam param;
+    param.quantized_activation_min = std::numeric_limits<int32_t>::lowest();
+    param.quantized_activation_max = std::numeric_limits<int32_t>::max();
+    nnfw::cker::Shape shape{1, 2, 2, 1};
+
+    nnfw::cker::BinaryArithmeticOp<nnfw::cker::BinaryArithmeticOpType::MUL>(
+      param, shape, input1.data(), shape, input2.data(), shape, output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      EXPECT_EQ(output[i], expected_output[i]);
+  }
+
+  // Broadcast
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<int32_t> input1 = {10, -9, -11, 7};
+    // Shape: {1}
+    std::vector<int32_t> input2 = {-3};
+    std::vector<int32_t> expected_output = {-30, 27, 33, -21};
+    std::vector<int32_t> output(4);
+
+    nnfw::cker::BinaryArithmeticOpParam param;
+    param.broadcast_category = nnfw::cker::BroadcastableOpCategory::kGenericBroadcast;
+    param.quantized_activation_min = std::numeric_limits<int32_t>::lowest();
+    param.quantized_activation_max = std::numeric_limits<int32_t>::max();
+
+    nnfw::cker::BroadcastBinaryArithmeticOp<nnfw::cker::BinaryArithmeticOpType::MUL>(
+      param, nnfw::cker::Shape{1, 2, 2, 1}, input1.data(), nnfw::cker::Shape{1}, input2.data(),
+      nnfw::cker::Shape{1, 2, 2, 1}, output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      EXPECT_EQ(output[i], expected_output[i]);
+  }
+
+  // Simple Float
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<float> input1 = {10, 9, -11.1, 3};
+    // Shape: {1, 2, 2, 1}
+    std::vector<float> input2 = {2, -2.2, -3.3, 4};
+    std::vector<float> expected_output = {20, -19.8, 36.63, 12};
+    std::vector<float> output(4);
+
+    nnfw::cker::BinaryArithmeticOpParam param;
+    param.float_activation_min = std::numeric_limits<float>::lowest();
+    param.float_activation_max = std::numeric_limits<float>::max();
+    nnfw::cker::Shape shape{1, 2, 2, 1};
+
+    nnfw::cker::BinaryArithmeticOp<nnfw::cker::BinaryArithmeticOpType::MUL>(
+      param, shape, input1.data(), shape, input2.data(), shape, output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      EXPECT_NEAR(output[i], expected_output[i], 1e-5f);
+  }
+
+  // Float Relu
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<float> input1 = {10, 9, -11.1, 3};
+    // Shape: {1, 2, 2, 1}
+    std::vector<float> input2 = {2, -2.2, -3.3, 4};
+    std::vector<float> expected_output = {20, 0, 36.63, 12};
+    std::vector<float> output(4);
+
+    nnfw::cker::BinaryArithmeticOpParam param;
+    param.float_activation_min = 0;
+    param.float_activation_max = std::numeric_limits<float>::max();
+    nnfw::cker::Shape shape{1, 2, 2, 1};
+
+    nnfw::cker::BinaryArithmeticOp<nnfw::cker::BinaryArithmeticOpType::MUL>(
+      param, shape, input1.data(), shape, input2.data(), shape, output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      EXPECT_NEAR(output[i], expected_output[i], 1e-5f);
+  }
+
+  // Broadcast
+  {
+    // Shape: {1, 2, 2, 1}
+    std::vector<float> input1 = {10, 9, -11.1, 3};
+    // Shape: {1}
+    std::vector<float> input2 = {-3};
+    std::vector<float> expected_output = {-30, -27, 33.3, -9};
+    std::vector<float> output(4);
+
+    nnfw::cker::BinaryArithmeticOpParam param;
+    param.broadcast_category = nnfw::cker::BroadcastableOpCategory::kGenericBroadcast;
+    param.float_activation_min = std::numeric_limits<float>::lowest();
+    param.float_activation_max = std::numeric_limits<float>::max();
+
+    nnfw::cker::BroadcastBinaryArithmeticOp<nnfw::cker::BinaryArithmeticOpType::MUL>(
+      param, nnfw::cker::Shape{1, 2, 2, 1}, input1.data(), nnfw::cker::Shape{1}, input2.data(),
+      nnfw::cker::Shape{1, 2, 2, 1}, output.data());
+
+    for (size_t i = 0; i < expected_output.size(); ++i)
+      EXPECT_NEAR(output[i], expected_output[i], 1e-5f);
+  }
+
+  // Bool8
+  {
+    // Shape: {1, 2, 2, 1}
+    bool input1[4] = {true, true, false, false};
+    // Shape: {1, 2, 2, 1}
+    bool input2[4] = {true, false, true, false};
+    bool expected_output[4] = {true, false, false, false};
+    bool output[4];
+
+    nnfw::cker::BinaryArithmeticOpParam param;
+    nnfw::cker::Shape shape{1, 2, 2, 1};
+
+    nnfw::cker::BinaryArithmeticOp<nnfw::cker::BinaryArithmeticOpType::MUL, bool>(
+      param, shape, input1, shape, input2, shape, output);
+
+    for (size_t i = 0; i < 4; ++i)
+      EXPECT_EQ(output[i], expected_output[i]);
+  }
+
+  // Broadcast Bool8
+  {
+    // Shape: {1, 2, 2, 1}
+    bool input1[4] = {true, true, false, false};
+    // Shape: {1, 2, 2, 1}
+    bool input2[1] = {true};
+    bool expected_output[4] = {true, true, false, false};
+    bool output[4];
+
+    nnfw::cker::BinaryArithmeticOpParam param;
+
+    nnfw::cker::BroadcastBinaryArithmeticOp<nnfw::cker::BinaryArithmeticOpType::MUL, bool>(
+      param, nnfw::cker::Shape{1, 2, 2, 1}, input1, nnfw::cker::Shape{1}, input2,
+      nnfw::cker::Shape{1, 2, 2, 1}, output);
+
+    for (size_t i = 0; i < 4; ++i)
+      EXPECT_EQ(output[i], expected_output[i]);
+  }
+
+  // TODO Add other types
+}
+
+TEST(CKer_Operation, neg_MulUnsupportedBroadcastRank)
+{
+  // Unsupported rank
+  {
+    // Shape: {1, 2, 2, 1, 1}
+    std::vector<float> input1 = {10, -9, -11, 7};
+    // Shape: {1}
+    std::vector<float> input2 = {-3};
+    std::vector<float> output(4);
+
+    nnfw::cker::BinaryArithmeticOpParam param;
+
+    EXPECT_ANY_THROW(
+      nnfw::cker::BroadcastBinaryArithmeticOp<nnfw::cker::BinaryArithmeticOpType::MUL>(
+        param, nnfw::cker::Shape{1, 2, 2, 1, 1}, input1.data(), nnfw::cker::Shape{1}, input2.data(),
+        nnfw::cker::Shape{1, 2, 2, 1, 1}, output.data()));
+  }
+}
diff --git a/compute/cker/src/train/Adam.test.cc b/compute/cker/src/train/Adam.test.cc
new file mode 100644 (file)
index 0000000..0d0effe
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/optimizer/Adam.h>
+
+#include <algorithm>
+#include <cmath>
+#include <gtest/gtest.h>
+#include <vector>
+
+// TODO Add tests that verifies result values
+template <typename T> class AdamOptimizerVerifier
+{
+public:
+  AdamOptimizerVerifier(const std::vector<T> &trainable, const std::vector<T> &gradient,
+                        const std::vector<T> &m, const std::vector<T> &v, float learning_rate,
+                        float beta1, float beta2, float epsilon, bool use_nesterov,
+                        uint32_t nums_step)
+    : _trainable{trainable}, _gradient{gradient}, _m{m}, _v{v}, _learning_rate{learning_rate},
+      _beta1{beta1}, _beta2{beta2}, _epsilon{epsilon}, _use_nesterov{use_nesterov},
+      _nums_step{nums_step}
+  {
+    EXPECT_TRUE(trainable.size() == gradient.size());
+    EXPECT_TRUE(trainable.size() == m.size());
+    EXPECT_TRUE(trainable.size() == v.size());
+
+    _expected.resize(trainable.size());
+    std::copy(trainable.begin(), trainable.end(), _expected.begin());
+  }
+
+public:
+  void verify()
+  {
+    for (uint32_t step = 0; step < _nums_step; ++step)
+    {
+      const T beta1_power = std::pow(_beta1, step + 1);
+      const T beta2_power = std::pow(_beta2, step + 1);
+
+      calculateExpected(beta1_power, beta2_power);
+
+      nnfw::cker::train::Adam(
+        nnfw::cker::Shape{static_cast<int>(_trainable.size())}, _trainable.data(),
+        nnfw::cker::Shape{static_cast<int>(_gradient.size())}, _gradient.data(),
+        nnfw::cker::Shape{static_cast<int>(_m.size())}, _m.data(),
+        nnfw::cker::Shape{static_cast<int>(_v.size())}, _v.data(), beta1_power, beta2_power,
+        _learning_rate, _beta1, _beta2, _epsilon, _use_nesterov);
+
+      for (size_t i = 0; i < _trainable.size(); ++i)
+        EXPECT_NEAR(_trainable[i], _expected[i], 1e-5f);
+    }
+  }
+
+private:
+  void calculateExpected(const float beta1_power, const float beta2_power)
+  {
+    assert(_expected.size() == _m.size());
+    assert(_expected.size() == _v.size());
+    assert(_expected.size() == _gradient.size());
+
+    const T alpha = _learning_rate * std::sqrt(static_cast<T>(1) - beta2_power) /
+                    (static_cast<T>(1) - beta1_power);
+    for (int i = 0; i < _expected.size(); ++i)
+    {
+      T m = _m.at(i);
+      T v = _v.at(i);
+      T g = _gradient.at(i);
+      T &var = _expected.at(i);
+
+      if (_use_nesterov)
+      {
+        m += (g - m) * (static_cast<T>(1) - _beta1);
+        v += (std::pow(g, 2) - v) * (static_cast<T>(1) - _beta2);
+        var -=
+          ((g * (static_cast<T>(1) - _beta1) + _beta1 * m) * alpha) / (std::sqrt(v) + _epsilon);
+      }
+      else
+      {
+        m += (g - m) * (static_cast<T>(1) - _beta1);
+        v += (std::pow(g, 2) - v) * (static_cast<T>(1) - _beta2);
+        var -= (m * alpha) / (std::sqrt(v) + _epsilon);
+      }
+    }
+  }
+
+private:
+  std::vector<T> _trainable;
+  std::vector<T> _gradient;
+  std::vector<T> _m;
+  std::vector<T> _v;
+  float _learning_rate;
+  float _beta1;
+  float _beta2;
+  float _epsilon;
+  bool _use_nesterov;
+  uint32_t _nums_step;
+  std::vector<T> _expected;
+};
+
+TEST(CKer_Optimizer, AdamSimple)
+{
+  // Unmatched shape
+  {
+    std::vector<float> trainable = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient = {-1, 2, -3, 4, 5, -6, 7, 8, 9};
+    std::vector<float> m = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> v = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    float lr = 0.001;
+    float beta1 = 0.9;
+    float beta2 = 0.999;
+    float epsilon = 1e-07;
+    bool use_nesterov = true;
+    uint32_t training_steps = 10;
+
+    AdamOptimizerVerifier<float>{trainable,    gradient,      m, v, lr, beta1, beta2, epsilon,
+                                 use_nesterov, training_steps}
+      .verify();
+  }
+}
+
+TEST(CKer_Optimizer, AdamSteps1e5)
+{
+  // Unmatched shape
+  {
+    std::vector<float> trainable = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> m = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> v = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    float lr = 0.001;
+    float beta1 = 0.9;
+    float beta2 = 0.999;
+    float epsilon = 1e-07;
+    bool use_nesterov = false;
+    uint32_t training_steps = 10000;
+
+    AdamOptimizerVerifier<float>{trainable,    gradient,      m, v, lr, beta1, beta2, epsilon,
+                                 use_nesterov, training_steps}
+      .verify();
+  }
+}
+
+TEST(CKer_Optimizer, neg_AdamUnmatchedGradientShape)
+{
+  // Unmatched shape
+  {
+    std::vector<float> trainable = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient = {-1, 2, -3, 4, 5, -6, 7, 8};
+    std::vector<float> m = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> v = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    float lr = 0.001;
+    float beta1 = 0.9;
+    float beta2 = 0.999;
+    float epsilon = 1e-07;
+    bool use_nesterov = false;
+    float beta1_power = std::pow(beta1, 1);
+    float beta2_power = std::pow(beta2, 1);
+
+    EXPECT_ANY_THROW(nnfw::cker::train::Adam(
+      nnfw::cker::Shape{static_cast<int>(trainable.size())}, trainable.data(),
+      nnfw::cker::Shape{static_cast<int>(gradient.size())}, gradient.data(),
+      nnfw::cker::Shape{static_cast<int>(m.size())}, m.data(),
+      nnfw::cker::Shape{static_cast<int>(v.size())}, v.data(), beta1_power, beta2_power, lr, beta1,
+      beta2, epsilon, use_nesterov));
+  }
+}
+
+TEST(CKer_Optimizer, neg_AdamUnmatchedEMAShape1)
+{
+  // Unmatched shape
+  {
+    std::vector<float> trainable = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient = {-1, 2, -3, 4, 5, -6, 7, 8, 9};
+    std::vector<float> m = {0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> v = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    float lr = 0.001;
+    float beta1 = 0.9;
+    float beta2 = 0.999;
+    float epsilon = 1e-07;
+    bool use_nesterov = false;
+    float beta1_power = std::pow(beta1, 1);
+    float beta2_power = std::pow(beta2, 1);
+
+    EXPECT_ANY_THROW(nnfw::cker::train::Adam(
+      nnfw::cker::Shape{static_cast<int>(trainable.size())}, trainable.data(),
+      nnfw::cker::Shape{static_cast<int>(gradient.size())}, gradient.data(),
+      nnfw::cker::Shape{static_cast<int>(m.size())}, m.data(),
+      nnfw::cker::Shape{static_cast<int>(v.size())}, v.data(), beta1_power, beta2_power, lr, beta1,
+      beta2, epsilon, use_nesterov));
+  }
+}
+
+TEST(CKer_Optimizer, neg_AdamUnmatchedEMAShape2)
+{
+  // Unmatched shape
+  {
+    std::vector<float> trainable = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient = {-1, 2, -3, 4, 5, -6, 7, 8, 9};
+    std::vector<float> m = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> v = {0, 0, 0, 0, 0, 0, 0, 0};
+    float lr = 0.001;
+    float beta1 = 0.9;
+    float beta2 = 0.999;
+    float epsilon = 1e-07;
+    bool use_nesterov = false;
+    float beta1_power = std::pow(beta1, 1);
+    float beta2_power = std::pow(beta2, 1);
+
+    EXPECT_ANY_THROW(nnfw::cker::train::Adam(
+      nnfw::cker::Shape{static_cast<int>(trainable.size())}, trainable.data(),
+      nnfw::cker::Shape{static_cast<int>(gradient.size())}, gradient.data(),
+      nnfw::cker::Shape{static_cast<int>(m.size())}, m.data(),
+      nnfw::cker::Shape{static_cast<int>(v.size())}, v.data(), beta1_power, beta2_power, lr, beta1,
+      beta2, epsilon, use_nesterov));
+  }
+}
diff --git a/compute/cker/src/train/BinaryArithmetic.test.cc b/compute/cker/src/train/BinaryArithmetic.test.cc
new file mode 100644 (file)
index 0000000..3a20ba1
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/BinaryArithmetic.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+TEST(CKer_Operation, AddGrad)
+{
+  {
+    // Shape: {2, 3}
+    std::vector<float> lhs(6); // Does not matter
+    std::vector<float> rhs(6); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7};
+    std::vector<float> expected_lhs_backward = incoming_backward;
+    std::vector<float> expected_rhs_backward = incoming_backward;
+    std::vector<float> lhs_backward(6);
+    std::vector<float> rhs_backward(6);
+
+    nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 3}, lhs.data(), nnfw::cker::Shape{2, 3}, rhs.data(),
+      nnfw::cker::Shape{2, 3}, incoming_backward.data(), nnfw::cker::Shape{2, 3},
+      lhs_backward.data(), nnfw::cker::Shape{2, 3}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kAdd);
+
+    for (size_t i = 0; i < lhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(lhs_backward[i], expected_lhs_backward[i]);
+    for (size_t i = 0; i < rhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(rhs_backward[i], expected_rhs_backward[i]);
+  }
+  {
+    // Shape: {4, 3}
+    std::vector<float> lhs(12); // Does not matter
+    std::vector<float> rhs(12); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13};
+    std::vector<float> expected_lhs_backward = incoming_backward;
+    std::vector<float> expected_rhs_backward = incoming_backward;
+    std::vector<float> lhs_backward(12);
+    std::vector<float> rhs_backward(12);
+
+    nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{4, 3}, lhs.data(), nnfw::cker::Shape{4, 3}, rhs.data(),
+      nnfw::cker::Shape{4, 3}, incoming_backward.data(), nnfw::cker::Shape{4, 3},
+      lhs_backward.data(), nnfw::cker::Shape{4, 3}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kAdd);
+
+    for (size_t i = 0; i < lhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(lhs_backward[i], expected_lhs_backward[i]);
+    for (size_t i = 0; i < rhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(rhs_backward[i], expected_rhs_backward[i]);
+  }
+}
+
+TEST(CKer_Operation, SubGrad)
+{
+  {
+    // Shape: {2, 3}
+    std::vector<float> lhs(6); // Does not matter
+    std::vector<float> rhs(6); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7};
+    std::vector<float> expected_lhs_backward = incoming_backward;
+    std::vector<float> expected_rhs_backward = incoming_backward;
+    std::vector<float> lhs_backward(6);
+    std::vector<float> rhs_backward(6);
+
+    nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 3}, lhs.data(), nnfw::cker::Shape{2, 3}, rhs.data(),
+      nnfw::cker::Shape{2, 3}, incoming_backward.data(), nnfw::cker::Shape{2, 3},
+      lhs_backward.data(), nnfw::cker::Shape{2, 3}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kSub);
+
+    for (size_t i = 0; i < lhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(lhs_backward[i], expected_lhs_backward[i]);
+    for (size_t i = 0; i < rhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(rhs_backward[i], -expected_rhs_backward[i]);
+  }
+  {
+    // Shape: {4, 3}
+    std::vector<float> lhs(12); // Does not matter
+    std::vector<float> rhs(12); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13};
+    std::vector<float> expected_lhs_backward = incoming_backward;
+    std::vector<float> expected_rhs_backward = incoming_backward;
+    std::vector<float> lhs_backward(12);
+    std::vector<float> rhs_backward(12);
+
+    nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{4, 3}, lhs.data(), nnfw::cker::Shape{4, 3}, rhs.data(),
+      nnfw::cker::Shape{4, 3}, incoming_backward.data(), nnfw::cker::Shape{4, 3},
+      lhs_backward.data(), nnfw::cker::Shape{4, 3}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kSub);
+
+    for (size_t i = 0; i < lhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(lhs_backward[i], expected_lhs_backward[i]);
+    for (size_t i = 0; i < rhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(rhs_backward[i], -expected_rhs_backward[i]);
+  }
+  {
+    // Shape: {2, 2, 2}
+    std::vector<float> lhs(8); // Does not matter
+    std::vector<float> rhs(8); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7, -8, 9};
+    std::vector<float> expected_lhs_backward = incoming_backward;
+    std::vector<float> expected_rhs_backward = incoming_backward;
+    std::vector<float> lhs_backward(8);
+    std::vector<float> rhs_backward(8);
+
+    nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 2, 2}, lhs.data(), nnfw::cker::Shape{2, 2, 2}, rhs.data(),
+      nnfw::cker::Shape{2, 2, 2}, incoming_backward.data(), nnfw::cker::Shape{2, 2, 2},
+      lhs_backward.data(), nnfw::cker::Shape{2, 2, 2}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kSub);
+
+    for (size_t i = 0; i < lhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(lhs_backward[i], expected_lhs_backward[i]);
+    for (size_t i = 0; i < rhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(rhs_backward[i], -expected_rhs_backward[i]);
+  }
+}
+
+TEST(CKer_Operation, MulGrad)
+{
+  {
+    // Shape: {2, 3}
+    std::vector<float> lhs = {-8, 9, -10, 11, -12, 13};
+    std::vector<float> rhs = {-14, 15, -16, 17, -18, 19};
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7};
+    std::vector<float> expected_lhs_backward(6);
+    std::vector<float> expected_rhs_backward(6);
+    std::vector<float> lhs_backward(6);
+    std::vector<float> rhs_backward(6);
+
+    for (uint32_t i = 0; i < 6; ++i)
+    {
+      expected_lhs_backward[i] = incoming_backward[i] * rhs[i];
+      expected_rhs_backward[i] = incoming_backward[i] * lhs[i];
+    }
+
+    nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 3}, lhs.data(), nnfw::cker::Shape{2, 3}, rhs.data(),
+      nnfw::cker::Shape{2, 3}, incoming_backward.data(), nnfw::cker::Shape{2, 3},
+      lhs_backward.data(), nnfw::cker::Shape{2, 3}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kMul);
+
+    for (size_t i = 0; i < lhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(lhs_backward[i], expected_lhs_backward[i]);
+    for (size_t i = 0; i < rhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(rhs_backward[i], expected_rhs_backward[i]);
+  }
+  {
+    // Shape: {4, 3}
+    std::vector<float> lhs = {-14, 15, -16, 17, -18, 19, -20, 21, -22, 23, -24, 25};
+    std::vector<float> rhs = {-26, 27, -28, 29, -30, 31, -32, 33, -34, 35, -36, 37};
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13};
+    std::vector<float> expected_lhs_backward(12);
+    std::vector<float> expected_rhs_backward(12);
+    std::vector<float> lhs_backward(12);
+    std::vector<float> rhs_backward(12);
+
+    for (uint32_t i = 0; i < 12; ++i)
+    {
+      expected_lhs_backward[i] = incoming_backward[i] * rhs[i];
+      expected_rhs_backward[i] = incoming_backward[i] * lhs[i];
+    }
+
+    nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{4, 3}, lhs.data(), nnfw::cker::Shape{4, 3}, rhs.data(),
+      nnfw::cker::Shape{4, 3}, incoming_backward.data(), nnfw::cker::Shape{4, 3},
+      lhs_backward.data(), nnfw::cker::Shape{4, 3}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kMul);
+
+    for (size_t i = 0; i < lhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(lhs_backward[i], expected_lhs_backward[i]);
+    for (size_t i = 0; i < rhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(rhs_backward[i], expected_rhs_backward[i]);
+  }
+  {
+    // Shape: {2, 2, 2}
+    std::vector<float> lhs = {-10, 11, -12, 13, -14, 15, -16, 17};
+    std::vector<float> rhs = {-18, 19, -20, 21, -22, 23, -24, 25};
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7, -8, 9};
+    std::vector<float> expected_lhs_backward = incoming_backward;
+    std::vector<float> expected_rhs_backward = incoming_backward;
+    std::vector<float> lhs_backward(8);
+    std::vector<float> rhs_backward(8);
+
+    for (uint32_t i = 0; i < 8; ++i)
+    {
+      expected_lhs_backward[i] = incoming_backward[i] * rhs[i];
+      expected_rhs_backward[i] = incoming_backward[i] * lhs[i];
+    }
+
+    nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 2, 2}, lhs.data(), nnfw::cker::Shape{2, 2, 2}, rhs.data(),
+      nnfw::cker::Shape{2, 2, 2}, incoming_backward.data(), nnfw::cker::Shape{2, 2, 2},
+      lhs_backward.data(), nnfw::cker::Shape{2, 2, 2}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kMul);
+
+    for (size_t i = 0; i < lhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(lhs_backward[i], expected_lhs_backward[i]);
+    for (size_t i = 0; i < rhs_backward.size(); ++i)
+      EXPECT_FLOAT_EQ(rhs_backward[i], expected_rhs_backward[i]);
+  }
+}
+
+TEST(CKer_Operation, neg_BinaryArithmeticDistinctShape)
+{
+  {
+    // all but lhs have the same shape
+    std::vector<float> lhs(8); // Does not matter
+    std::vector<float> rhs(6); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7};
+    std::vector<float> lhs_backward(6);
+    std::vector<float> rhs_backward(6);
+
+    EXPECT_ANY_THROW(nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 2, 2}, lhs.data(), nnfw::cker::Shape{2, 3}, rhs.data(),
+      nnfw::cker::Shape{2, 3}, incoming_backward.data(), nnfw::cker::Shape{2, 3},
+      lhs_backward.data(), nnfw::cker::Shape{2, 3}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kAdd));
+  }
+  {
+    // all but rhs have the same shape
+    std::vector<float> lhs(6); // Does not matter
+    std::vector<float> rhs(8); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7};
+    std::vector<float> lhs_backward(6);
+    std::vector<float> rhs_backward(6);
+
+    EXPECT_ANY_THROW(nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 3}, lhs.data(), nnfw::cker::Shape{2, 2, 2}, rhs.data(),
+      nnfw::cker::Shape{2, 3}, incoming_backward.data(), nnfw::cker::Shape{2, 3},
+      lhs_backward.data(), nnfw::cker::Shape{2, 3}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kAdd));
+  }
+  {
+    // all but incoming_backward have the same shape
+    std::vector<float> lhs(6); // Does not matter
+    std::vector<float> rhs(6); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7, -8, 9};
+    std::vector<float> lhs_backward(6);
+    std::vector<float> rhs_backward(6);
+
+    EXPECT_ANY_THROW(nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 3}, lhs.data(), nnfw::cker::Shape{2, 3}, rhs.data(),
+      nnfw::cker::Shape{2, 2, 2}, incoming_backward.data(), nnfw::cker::Shape{2, 3},
+      lhs_backward.data(), nnfw::cker::Shape{2, 3}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kAdd));
+  }
+  {
+    // all but lhs_backward have the same shape
+    std::vector<float> lhs(6); // Does not matter
+    std::vector<float> rhs(6); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7};
+    std::vector<float> lhs_backward(8);
+    std::vector<float> rhs_backward(6);
+
+    EXPECT_ANY_THROW(nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 3}, lhs.data(), nnfw::cker::Shape{2, 3}, rhs.data(),
+      nnfw::cker::Shape{2, 3}, incoming_backward.data(), nnfw::cker::Shape{2, 2, 2},
+      lhs_backward.data(), nnfw::cker::Shape{2, 3}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kAdd));
+  }
+  {
+    // all but rhs_backward have the same shape
+    std::vector<float> lhs(6); // Does not matter
+    std::vector<float> rhs(6); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7};
+    std::vector<float> lhs_backward(6);
+    std::vector<float> rhs_backward(8);
+
+    EXPECT_ANY_THROW(nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 3}, lhs.data(), nnfw::cker::Shape{2, 3}, rhs.data(),
+      nnfw::cker::Shape{2, 3}, incoming_backward.data(), nnfw::cker::Shape{2, 3},
+      lhs_backward.data(), nnfw::cker::Shape{2, 2, 2}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kAdd));
+  }
+  {
+    std::vector<float> lhs(8); // Does not matter
+    std::vector<float> rhs(8); // Does not matter
+    std::vector<float> incoming_backward = {-2, 3, -4, 5, -6, 7};
+    std::vector<float> lhs_backward(6);
+    std::vector<float> rhs_backward(8);
+
+    EXPECT_ANY_THROW(nnfw::cker::train::BinaryArithmeticGrad(
+      nnfw::cker::Shape{2, 2, 2}, lhs.data(), nnfw::cker::Shape{2, 2, 2}, rhs.data(),
+      nnfw::cker::Shape{2, 3}, incoming_backward.data(), nnfw::cker::Shape{2, 3},
+      lhs_backward.data(), nnfw::cker::Shape{2, 2, 2}, rhs_backward.data(),
+      nnfw::cker::train::ArithmeticType::kAdd));
+  }
+}
diff --git a/compute/cker/src/train/Conv.test.cc b/compute/cker/src/train/Conv.test.cc
new file mode 100644 (file)
index 0000000..c7bf34e
--- /dev/null
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/Conv.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+namespace
+{
+
+template <typename T> class ConvVerifier
+{
+public:
+  static void verifyFilterGradExpected(const nnfw::cker::ConvParams &params,
+                                       const nnfw::cker::Shape &incoming_shape,
+                                       const T *incoming_data, const nnfw::cker::Shape &input_shape,
+                                       const T *input_data, int padding_bottom, int padding_right,
+                                       const nnfw::cker::Shape &filter_shape)
+  {
+    std::vector<T> gradient(filter_shape.FlatSize(), static_cast<T>(0));
+    std::vector<T> expected(filter_shape.FlatSize(), static_cast<T>(0));
+
+    calculateFilterGradExpected(params, incoming_shape, incoming_data, input_shape, input_data,
+                                filter_shape, expected.data());
+
+    nnfw::cker::train::ConvFilterGrad(params, incoming_shape, incoming_data, input_shape,
+                                      input_data, padding_bottom, padding_right, filter_shape,
+                                      gradient.data());
+
+    for (size_t i = 0; i < gradient.size(); ++i)
+      EXPECT_NEAR(gradient[i], expected[i], 1e-4f);
+  }
+
+  static void verifyInputGradExpected(const nnfw::cker::ConvParams &params,
+                                      const nnfw::cker::Shape &incoming_shape,
+                                      const T *incoming_data, const nnfw::cker::Shape &filter_shape,
+                                      const T *filter_data, int padding_bottom, int padding_right,
+                                      const nnfw::cker::Shape &input_shape)
+  {
+    std::vector<T> gradient(input_shape.FlatSize(), static_cast<T>(0));
+    std::vector<T> expected(input_shape.FlatSize(), static_cast<T>(0));
+
+    calculateInputGradExpected(params, incoming_shape, incoming_data, filter_shape, filter_data,
+                               input_shape, expected.data());
+
+    nnfw::cker::train::ConvInputGrad(params, incoming_shape, incoming_data, filter_shape,
+                                     filter_data, padding_bottom, padding_right, input_shape,
+                                     gradient.data());
+
+    for (size_t i = 0; i < gradient.size(); ++i)
+      EXPECT_NEAR(gradient[i], expected[i], 1e-4f);
+  }
+
+private:
+  static void calculateFilterGradExpected(const nnfw::cker::ConvParams &params,
+                                          const nnfw::cker::Shape &incoming_shape,
+                                          const T *incoming_data,
+                                          const nnfw::cker::Shape &input_shape, const T *input_data,
+                                          const nnfw::cker::Shape &filter_shape, T *expected)
+  {
+    assert(incoming_shape.DimensionsCount() == 4);
+    assert(input_shape.DimensionsCount() == 4);
+    assert(filter_shape.DimensionsCount() == 4);
+
+    const int batches = MatchingDim(incoming_shape, 0, input_shape, 0);
+    const int input_channel = MatchingDim(filter_shape, 2, input_shape, 3);
+    const int output_channel = MatchingDim(filter_shape, 3, incoming_shape, 3);
+    const int input_height = input_shape.Dims(1);
+    const int input_width = input_shape.Dims(2);
+    const int filter_height = filter_shape.Dims(0);
+    const int filter_width = filter_shape.Dims(1);
+    const int incoming_height = incoming_shape.Dims(1);
+    const int incoming_width = incoming_shape.Dims(2);
+
+    int pad_top = params.padding_values.height;
+    int pad_left = params.padding_values.width;
+    const int stride_height = params.stride_height;
+    const int stride_width = params.stride_width;
+
+    if (params.padding_type == nnfw::cker::PaddingType::kValid)
+    {
+      pad_top = 0;
+      pad_left = 0;
+    }
+    else if (params.padding_type == nnfw::cker::PaddingType::kSame)
+    {
+      pad_top = ((incoming_height - 1) * stride_height + filter_height - input_height) / 2;
+      pad_left = ((incoming_width - 1) * stride_width + filter_width - input_width) / 2;
+    }
+
+    assert(pad_top >= 0);
+    assert(pad_left >= 0);
+    assert(stride_height > 0);
+    assert(stride_width > 0);
+
+    for (int m = 0; m < batches; ++m)
+    {
+      for (int i = 0; i < incoming_height; ++i)
+      {
+        for (int j = 0; j < incoming_width; ++j)
+        {
+          for (int a = 0; a < filter_height; ++a)
+          {
+            for (int b = 0; b < filter_width; ++b)
+            {
+              for (int c = 0; c < input_channel; ++c)
+              {
+                for (int k = 0; k < output_channel; ++k)
+                {
+                  const auto input_i = stride_height * i + a - pad_top;
+                  const auto input_j = stride_width * j + b - pad_left;
+                  if (input_i < 0 || input_i >= input_height || input_j < 0 ||
+                      input_j >= input_width)
+                    continue;
+
+                  const auto filter_offset = Offset(filter_shape, a, b, c, k);
+                  const auto incoming_offset = Offset(incoming_shape, m, i, j, k);
+                  const auto input_offset = Offset(input_shape, m, input_i, input_j, c);
+
+                  expected[filter_offset] +=
+                    incoming_data[incoming_offset] * input_data[input_offset];
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  static void calculateInputGradExpected(const nnfw::cker::ConvParams &params,
+                                         const nnfw::cker::Shape &incoming_shape,
+                                         const T *incoming_data,
+                                         const nnfw::cker::Shape &filter_shape,
+                                         const T *filter_data, const nnfw::cker::Shape &input_shape,
+                                         T *expected)
+  {
+    assert(incoming_shape.DimensionsCount() == 4);
+    assert(filter_shape.DimensionsCount() == 4);
+    assert(input_shape.DimensionsCount() == 4);
+
+    const int batches = MatchingDim(incoming_shape, 0, input_shape, 0);
+    const int input_channel = MatchingDim(filter_shape, 2, input_shape, 3);
+    const int output_channel = MatchingDim(filter_shape, 3, incoming_shape, 3);
+    const int input_height = input_shape.Dims(1);
+    const int input_width = input_shape.Dims(2);
+    const int filter_height = filter_shape.Dims(0);
+    const int filter_width = filter_shape.Dims(1);
+    const int incoming_height = incoming_shape.Dims(1);
+    const int incoming_width = incoming_shape.Dims(2);
+
+    int pad_top = params.padding_values.height;
+    int pad_left = params.padding_values.width;
+    const int stride_height = params.stride_height;
+    const int stride_width = params.stride_width;
+
+    if (params.padding_type == nnfw::cker::PaddingType::kValid)
+    {
+      pad_top = 0;
+      pad_left = 0;
+    }
+    else if (params.padding_type == nnfw::cker::PaddingType::kSame)
+    {
+      pad_top = ((incoming_height - 1) * stride_height + filter_height - input_height) / 2;
+      pad_left = ((incoming_width - 1) * stride_width + filter_width - input_width) / 2;
+    }
+
+    assert(pad_top >= 0);
+    assert(pad_left >= 0);
+    assert(stride_height > 0);
+    assert(stride_width > 0);
+
+    for (int m = 0; m < batches; ++m)
+    {
+      for (int i = 0; i < incoming_height; ++i)
+      {
+        for (int j = 0; j < incoming_width; ++j)
+        {
+          for (int a = 0; a < filter_height; ++a)
+          {
+            for (int b = 0; b < filter_width; ++b)
+            {
+              for (int c = 0; c < input_channel; ++c)
+              {
+                for (int k = 0; k < output_channel; ++k)
+                {
+                  const auto input_i = stride_height * i + a - pad_top;
+                  const auto input_j = stride_width * j + b - pad_left;
+                  if (input_i < 0 || input_i >= input_height || input_j < 0 ||
+                      input_j >= input_width)
+                    continue;
+
+                  const auto filter_offset = Offset(filter_shape, a, b, c, k);
+                  const auto incoming_offset = Offset(incoming_shape, m, i, j, k);
+                  const auto input_offset = Offset(input_shape, m, input_i, input_j, c);
+
+                  expected[input_offset] +=
+                    incoming_data[incoming_offset] * filter_data[filter_offset];
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+};
+
+} // namespace
+
+TEST(CKer_Operation, ConvGrad)
+{
+  // No pad, No stride
+  {
+    nnfw::cker::ConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kNone;
+    params.padding_values.width = 0;
+    params.padding_values.height = 0;
+    params.stride_width = 1;
+    params.stride_height = 1;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+
+    nnfw::cker::Shape incoming_shape{1, 2, 2, 3}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2, -0.3, 0.4,  0.5, -0.6,
+                                   -0.7, 0.8, 0.9,  -1.0, 1.1, -1.2};
+    nnfw::cker::Shape filter_shape{2, 2, 2, 3}; // h, w, i, o
+    std::vector<float> filter = {-1,  2,  -3,  4,  5,  -6,  -7,  8,  9,   -10, -11, 12,
+                                 -13, 14, -15, 16, 17, -18, -19, 20, -21, 22,  23,  -24};
+    nnfw::cker::Shape input_shape{1, 3, 3, 2}; // n, h, w, c
+    std::vector<float> input = {-1,  2,  -3,  4,  5,   -6, -7,  8,   -9,
+                                -10, 11, -12, 13, -14, 15, -16, -17, 18};
+
+    const auto padding_bottom = 0;
+    const auto padding_right = 0;
+
+    ConvVerifier<float>::verifyFilterGradExpected(params, incoming_shape, incoming.data(),
+                                                  input_shape, input.data(), padding_bottom,
+                                                  padding_right, filter_shape);
+    ConvVerifier<float>::verifyInputGradExpected(params, incoming_shape, incoming.data(),
+                                                 filter_shape, filter.data(), padding_bottom,
+                                                 padding_right, input_shape);
+  }
+
+  // pad top 1, pad left 1, No stride
+  {
+    nnfw::cker::ConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kNone;
+    params.padding_values.width = 1;
+    params.padding_values.height = 1;
+    params.stride_width = 1;
+    params.stride_height = 1;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+
+    nnfw::cker::Shape incoming_shape{1, 3, 3, 3}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2, -0.3, 0.4, 0.5,  -0.6, -0.7, 0.8,  0.9,
+                                   -1.0, 1.1, -1.2, 1.3, -1.4, 1.5,  -1.6, 1.7,  -1.8,
+                                   -1.9, 2.0, -2.1, 2.2, 2.3,  -2.4, 2.5,  -2.6, -2.7};
+    nnfw::cker::Shape filter_shape{2, 2, 2, 3}; // h, w, i, o
+    std::vector<float> filter = {-1,  2,  -3,  4,  5,  -6,  -7,  8,  9,   -10, -11, 12,
+                                 -13, 14, -15, 16, 17, -18, -19, 20, -21, 22,  23,  -24};
+    nnfw::cker::Shape input_shape{1, 3, 3, 2}; // n, h, w, c
+    std::vector<float> input = {-1,  2,  -3,  4,  5,   -6, -7,  8,   -9,
+                                -10, 11, -12, 13, -14, 15, -16, -17, 18};
+
+    const auto padding_bottom = 0;
+    const auto padding_right = 0;
+
+    ConvVerifier<float>::verifyFilterGradExpected(params, incoming_shape, incoming.data(),
+                                                  input_shape, input.data(), padding_bottom,
+                                                  padding_right, filter_shape);
+    ConvVerifier<float>::verifyInputGradExpected(params, incoming_shape, incoming.data(),
+                                                 filter_shape, filter.data(), padding_bottom,
+                                                 padding_right, input_shape);
+  }
+
+  // pad top 1, pad left 1, pad bottom 2, pad right 2, stride 2
+  {
+    nnfw::cker::ConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kNone;
+    params.padding_values.width = 1;
+    params.padding_values.height = 1;
+    params.stride_width = 2;
+    params.stride_height = 2;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+
+    nnfw::cker::Shape incoming_shape{1, 3, 3, 3}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2, -0.3, 0.4, 0.5,  -0.6, -0.7, 0.8,  0.9,
+                                   -1.0, 1.1, -1.2, 1.3, -1.4, -1.5, 1.6,  1.7,  -1.8,
+                                   1.9,  2.0, -2.1, 2.2, -2.3, 2.4,  2.5,  -2.6, -2.7};
+    nnfw::cker::Shape filter_shape{3, 3, 2, 3}; // h, w, i, o
+    std::vector<float> filter = {
+      -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};
+    nnfw::cker::Shape input_shape{1, 3, 3, 2}; // n, h, w, c
+    std::vector<float> input = {-1,  2,  -3,  4,  5,   -6, -7,  8,   -9,
+                                -10, 11, -12, 13, -14, 15, -16, -17, 18};
+
+    const auto padding_bottom = 2;
+    const auto padding_right = 2;
+
+    ConvVerifier<float>::verifyFilterGradExpected(params, incoming_shape, incoming.data(),
+                                                  input_shape, input.data(), padding_bottom,
+                                                  padding_right, filter_shape);
+    ConvVerifier<float>::verifyInputGradExpected(params, incoming_shape, incoming.data(),
+                                                 filter_shape, filter.data(), padding_bottom,
+                                                 padding_right, input_shape);
+  }
+
+  // pad same, stride 2
+  {
+    nnfw::cker::ConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kSame;
+    params.stride_width = 2;
+    params.stride_height = 2;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+
+    nnfw::cker::Shape incoming_shape{1, 3, 3, 3}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2, -0.3, 0.4, 0.5,  -0.6, -0.7, 0.8,  0.9,
+                                   -1.0, 1.1, -1.2, 1.3, -1.4, -1.5, 1.6,  1.7,  -1.8,
+                                   1.9,  2.0, -2.1, 2.2, -2.3, 2.4,  2.5,  -2.6, -2.7};
+    nnfw::cker::Shape filter_shape{3, 3, 2, 3}; // h, w, i, o
+    std::vector<float> filter = {
+      -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};
+    nnfw::cker::Shape input_shape{1, 3, 3, 2}; // n, h, w, c
+    std::vector<float> input = {-1,  2,  -3,  4,  5,   -6, -7,  8,   -9,
+                                -10, 11, -12, 13, -14, 15, -16, -17, 18};
+
+    const auto padding_bottom = 0;
+    const auto padding_right = 0;
+
+    ConvVerifier<float>::verifyFilterGradExpected(params, incoming_shape, incoming.data(),
+                                                  input_shape, input.data(), padding_bottom,
+                                                  padding_right, filter_shape);
+    ConvVerifier<float>::verifyInputGradExpected(params, incoming_shape, incoming.data(),
+                                                 filter_shape, filter.data(), padding_bottom,
+                                                 padding_right, input_shape);
+  }
+
+  // pad valid, stride 2
+  {
+    nnfw::cker::ConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kValid;
+    params.stride_width = 2;
+    params.stride_height = 2;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+
+    nnfw::cker::Shape incoming_shape{1, 1, 1, 3}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2, -0.3};
+    nnfw::cker::Shape filter_shape{2, 2, 2, 3}; // h, w, i, o
+    std::vector<float> filter = {-1,  2,  -3,  4,  5,  -6,  -7,  8,  9,   -10, -11, 12,
+                                 -13, 14, -15, 16, 17, -18, -19, 20, -21, 22,  23,  -24};
+    nnfw::cker::Shape input_shape{1, 3, 3, 2}; // n, h, w, c
+    std::vector<float> input = {-1,  2,  -3,  4,  5,   -6, -7,  8,   -9,
+                                -10, 11, -12, 13, -14, 15, -16, -17, 18};
+
+    const auto padding_bottom = 0;
+    const auto padding_right = 0;
+
+    ConvVerifier<float>::verifyFilterGradExpected(params, incoming_shape, incoming.data(),
+                                                  input_shape, input.data(), padding_bottom,
+                                                  padding_right, filter_shape);
+    ConvVerifier<float>::verifyInputGradExpected(params, incoming_shape, incoming.data(),
+                                                 filter_shape, filter.data(), padding_bottom,
+                                                 padding_right, input_shape);
+
+    SUCCEED();
+  }
+}
+
+TEST(CKer_Operation, neg_ConvGradUnsupportedDilation)
+{
+  // Unsupported dilation
+  {
+    nnfw::cker::ConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kNone;
+    params.padding_values.width = 0;
+    params.padding_values.height = 0;
+    params.stride_width = 1;
+    params.stride_height = 1;
+    params.dilation_width_factor = 2;
+    params.dilation_height_factor = 2;
+
+    nnfw::cker::Shape incoming_shape{1, 2, 2, 3}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2, -0.3, 0.4,  0.5, -0.6,
+                                   -0.7, 0.8, 0.9,  -1.0, 1.1, -1.2};
+    nnfw::cker::Shape filter_shape{2, 2, 2, 3}; // h, w, i, o
+    std::vector<float> filter = {-1,  2,  -3,  4,  5,  -6,  -7,  8,  9,   -10, -11, 12,
+                                 -13, 14, -15, 16, 17, -18, -19, 20, -21, 22,  23,  -24};
+    nnfw::cker::Shape input_shape{1, 3, 3, 2}; // n, h, w, c
+    std::vector<float> input = {-1,  2,  -3,  4,  5,   -6, -7,  8,   -9,
+                                -10, 11, -12, 13, -14, 15, -16, -17, 18};
+
+    EXPECT_ANY_THROW(nnfw::cker::train::ConvFilterGrad(params, incoming_shape, incoming.data(),
+                                                       input_shape, input.data(), 0, 0,
+                                                       filter_shape, filter.data()));
+
+    EXPECT_ANY_THROW(nnfw::cker::train::ConvInputGrad(params, incoming_shape, incoming.data(),
+                                                      filter_shape, filter.data(), 0, 0,
+                                                      input_shape, input.data()));
+  }
+}
diff --git a/compute/cker/src/train/DepthwiseConv.test.cc b/compute/cker/src/train/DepthwiseConv.test.cc
new file mode 100644 (file)
index 0000000..3451373
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/DepthwiseConv.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+namespace
+{
+
+template <typename T> class DepthwiseConvVerifier
+{
+public:
+  DepthwiseConvVerifier() : _dconv_kernel{new nnfw::cker::train::DepthwiseConv()}
+  {
+    _dconv_kernel = std::make_unique<nnfw::cker::train::DepthwiseConv>();
+  }
+
+  void prepare(const nnfw::cker::Shape &incoming_shape, const nnfw::cker::Shape &filter_shape)
+  {
+    const int k_packet_size = _dconv_kernel->kPacketSize<T>();
+    const int batch = incoming_shape.Dims(0);
+    const int out_depth = incoming_shape.Dims(3);
+    const int filter_rows = filter_shape.Dims(1);
+    const int filter_cols = filter_shape.Dims(2);
+    const int filter_spatial_size = filter_rows * filter_cols;
+    const int padded_filter_inner_dim_size =
+      ((out_depth + k_packet_size - 1) / k_packet_size) * k_packet_size;
+
+    _use_padded_filter = (out_depth % k_packet_size) == 0 ? false : true;
+    {
+      nnfw::cker::Shape padded_filter_shape(
+        {batch, filter_spatial_size, padded_filter_inner_dim_size});
+      _padded_filter.resize(padded_filter_shape.FlatSize());
+    }
+
+    {
+      const int thread_count = _dconv_kernel->getThreadCount();
+
+      nnfw::cker::Shape filter_buffer_shape(
+        {thread_count, filter_spatial_size, padded_filter_inner_dim_size});
+      _filter_buffers.resize(filter_buffer_shape.FlatSize());
+
+      nnfw::cker::Shape filter_dim_buffer_shape({thread_count, padded_filter_inner_dim_size});
+      _filter_dim_buffers.resize(filter_dim_buffer_shape.FlatSize());
+    }
+  }
+
+  void verifyInputGradExpected(const nnfw::cker::DepthwiseConvParams &params,
+                               const nnfw::cker::Shape &incoming_shape, const T *incoming_data,
+                               const nnfw::cker::Shape &filter_shape, const T *filter_data,
+                               const nnfw::cker::Shape &grad_shape)
+  {
+    std::vector<T> gradient(grad_shape.FlatSize(), static_cast<T>(0));
+    std::vector<T> expected(grad_shape.FlatSize(), static_cast<T>(0));
+
+    calculateInputGradExpected(params, incoming_shape, incoming_data, filter_shape, filter_data,
+                               grad_shape, expected.data());
+
+    _dconv_kernel->backpropInput(params, incoming_shape, incoming_data, filter_shape, filter_data,
+                                 _padded_filter.data(), grad_shape, gradient.data(),
+                                 _use_padded_filter, _filter_buffers.data(),
+                                 _filter_dim_buffers.data());
+
+    for (size_t i = 0; i < gradient.size(); ++i)
+      EXPECT_NEAR(gradient[i], expected[i], 1e-3f);
+  }
+
+  void throwInputGradExpected(const nnfw::cker::DepthwiseConvParams &params,
+                              const nnfw::cker::Shape &incoming_shape, const T *incoming_data,
+                              const nnfw::cker::Shape &filter_shape, const T *filter_data,
+                              const nnfw::cker::Shape &grad_shape)
+  {
+    std::vector<T> gradient(grad_shape.FlatSize(), static_cast<T>(0));
+
+    EXPECT_ANY_THROW(_dconv_kernel->backpropInput(
+      params, incoming_shape, incoming_data, filter_shape, filter_data, _padded_filter.data(),
+      grad_shape, gradient.data(), _use_padded_filter, _filter_buffers.data(),
+      _filter_dim_buffers.data()));
+  }
+
+  void verifyFilterGradExpected(const nnfw::cker::DepthwiseConvParams &params,
+                                const nnfw::cker::Shape &incoming_shape, const T *incoming_data,
+                                const nnfw::cker::Shape &input_shape, const T *input_data,
+                                const nnfw::cker::Shape &filter_grad_shape)
+  {
+    std::vector<T> gradient(filter_grad_shape.FlatSize(), static_cast<T>(0));
+    std::vector<T> expected(filter_grad_shape.FlatSize(), static_cast<T>(0));
+
+    calculateFilterGradExpected(params, incoming_shape, incoming_data, input_shape, input_data,
+                                filter_grad_shape, expected.data());
+
+    _dconv_kernel->backpropFilter(params, incoming_shape, incoming_data, input_shape, input_data,
+                                  filter_grad_shape, gradient.data(), _padded_filter.data(),
+                                  _filter_buffers.data());
+
+    for (size_t i = 0; i < gradient.size(); ++i)
+      EXPECT_NEAR(gradient[i], expected[i], 1e-3f);
+  }
+
+  void throwFilterGradExpected(const nnfw::cker::DepthwiseConvParams &params,
+                               const nnfw::cker::Shape &incoming_shape, const T *incoming_data,
+                               const nnfw::cker::Shape &input_shape, const T *input_data,
+                               const nnfw::cker::Shape &filter_grad_shape)
+  {
+    std::vector<T> gradient(filter_grad_shape.FlatSize(), static_cast<T>(0));
+
+    EXPECT_ANY_THROW(_dconv_kernel->backpropFilter(
+      params, incoming_shape, incoming_data, input_shape, input_data, filter_grad_shape,
+      gradient.data(), _padded_filter.data(), _filter_buffers.data()));
+  }
+
+private:
+  void calculateInputGradExpected(const nnfw::cker::DepthwiseConvParams &params,
+                                  const nnfw::cker::Shape &incoming_shape, const T *incoming_data,
+                                  const nnfw::cker::Shape &filter_shape, const T *filter_data,
+                                  const nnfw::cker::Shape &grad_shape, T *expected)
+  {
+    assert(incoming_shape.DimensionsCount() == 4);
+    assert(filter_shape.DimensionsCount() == 4);
+    assert(grad_shape.DimensionsCount() == 4);
+    assert(params.stride_height == params.stride_width);
+
+    const int batch = MatchingDim(incoming_shape, 0, grad_shape, 0);
+    const int input_depth = grad_shape.Dims(3);
+    const int output_depth = incoming_shape.Dims(3);
+    const int incoming_height = incoming_shape.Dims(1);
+    const int incoming_width = incoming_shape.Dims(2);
+    const int grad_height = grad_shape.Dims(1);
+    const int grad_width = grad_shape.Dims(2);
+    const int stride = params.stride_height;
+    const int depth_multiplier = params.depth_multiplier;
+    const int filter_height = filter_shape.Dims(1);
+    const int filter_width = filter_shape.Dims(2);
+    const int pad_height = params.padding_values.height;
+    const int pad_width = params.padding_values.width;
+
+    nnfw::cker::depthwise_conv_op::DepthwiseConvBackpropInputReference<T>(
+      batch, grad_height, grad_width, input_depth, incoming_height, incoming_width, output_depth,
+      stride, depth_multiplier, filter_height, filter_width, pad_height, pad_width, incoming_data,
+      filter_data, expected);
+  }
+
+  void calculateFilterGradExpected(const nnfw::cker::DepthwiseConvParams &params,
+                                   const nnfw::cker::Shape &incoming_shape, const T *incoming_data,
+                                   const nnfw::cker::Shape &input_shape, const T *input_data,
+                                   const nnfw::cker::Shape &filter_grad_shape, T *expected)
+  {
+    assert(incoming_shape.DimensionsCount() == 4);
+    assert(input_shape.DimensionsCount() == 4);
+    assert(filter_grad_shape.DimensionsCount() == 4);
+    assert(params.stride_height == params.stride_width);
+
+    const int batch = MatchingDim(incoming_shape, 0, input_shape, 0);
+    const int input_depth = input_shape.Dims(3);
+    const int output_depth = incoming_shape.Dims(3);
+    const int incoming_height = incoming_shape.Dims(1);
+    const int incoming_width = incoming_shape.Dims(2);
+    const int input_height = input_shape.Dims(1);
+    const int input_width = input_shape.Dims(2);
+    const int stride = params.stride_height;
+    const int depth_multiplier = params.depth_multiplier;
+    const int filter_height = filter_grad_shape.Dims(1);
+    const int filter_width = filter_grad_shape.Dims(2);
+    const int pad_height = params.padding_values.height;
+    const int pad_width = params.padding_values.width;
+
+    nnfw::cker::depthwise_conv_op::DepthwiseConvBackpropFilterReference<T>(
+      batch, input_height, input_width, input_depth, incoming_height, incoming_width, output_depth,
+      stride, depth_multiplier, filter_height, filter_width, pad_height, pad_width, incoming_data,
+      input_data, expected);
+  }
+
+private:
+  std::unique_ptr<nnfw::cker::train::DepthwiseConv> _dconv_kernel;
+  bool _use_padded_filter;
+  std::vector<T> _padded_filter;
+  std::vector<T> _filter_buffers;
+  std::vector<T> _filter_dim_buffers;
+};
+
+} // namespace
+
+TEST(CKer_Operation, DepthwiseConvGrad)
+{
+  // No pad, No stride
+  {
+    nnfw::cker::DepthwiseConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kNone;
+    params.padding_values.width = 0;
+    params.padding_values.height = 0;
+    params.stride_width = 1;
+    params.stride_height = 1;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+    params.depth_multiplier = 1;
+
+    nnfw::cker::Shape incoming_shape{1, 2, 2, 3}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2, -0.3, 0.4,  0.5, -0.6,
+                                   -0.7, 0.8, 0.9,  -1.0, 1.1, -1.2};
+    nnfw::cker::Shape filter_shape{1, 2, 2, 3}; // 1, h, w, c
+    std::vector<float> filter = {-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12};
+    nnfw::cker::Shape input_shape{1, 3, 3, 3}; // n, h, w, c
+    std::vector<float> input = {-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};
+
+    DepthwiseConvVerifier<float> verifier;
+    verifier.prepare(incoming_shape, filter_shape);
+    verifier.verifyInputGradExpected(params, incoming_shape, incoming.data(), filter_shape,
+                                     filter.data(), input_shape);
+    verifier.verifyFilterGradExpected(params, incoming_shape, incoming.data(), input_shape,
+                                      input.data(), filter_shape);
+  }
+
+  // 2 depth_multiplier, use_padded_filter false
+  {
+    nnfw::cker::DepthwiseConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kNone;
+    params.padding_values.width = 0;
+    params.padding_values.height = 0;
+    params.stride_width = 1;
+    params.stride_height = 1;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+    params.depth_multiplier = 2;
+
+    nnfw::cker::Shape incoming_shape{1, 2, 2, 4}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2, -0.3, 0.4, -0.5, 0.6, -0.7, 0.8,
+                                   -0.1, 0.2, -0.3, 0.4, -0.5, 0.6, -0.7, 0.8};
+    nnfw::cker::Shape filter_shape{1, 2, 2, 4}; // 1, h, w, c * depth_multiplier
+    std::vector<float> filter = {-1, 2, -3, 4, 5, -6, 7, -8, 9, -10, -11, 12, -13, 14, -15, 16};
+    nnfw::cker::Shape input_shape{1, 3, 3, 2}; // n, h, w, c
+    std::vector<float> input = {-1,  2,  -3,  4,  5,   -6, -7,  8,   -9,
+                                -10, 11, -12, 13, -14, 15, -16, -17, 18};
+
+    DepthwiseConvVerifier<float> verifier;
+    verifier.prepare(incoming_shape, filter_shape);
+    verifier.verifyInputGradExpected(params, incoming_shape, incoming.data(), filter_shape,
+                                     filter.data(), input_shape);
+    verifier.verifyFilterGradExpected(params, incoming_shape, incoming.data(), input_shape,
+                                      input.data(), filter_shape);
+  }
+
+  // pad valid, stride 2
+  {
+    nnfw::cker::DepthwiseConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kValid;
+    params.stride_width = 2;
+    params.stride_height = 2;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+    params.depth_multiplier = 1;
+
+    nnfw::cker::Shape incoming_shape{1, 3, 3, 2}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2, -0.3, 0.4, 0.5,  -0.6, -0.7, 0.8, 0.9,
+                                   -1.0, 1.1, -1.2, 1.3, -1.4, -1.5, 1.6,  1.7, -1.8};
+    nnfw::cker::Shape filter_shape{1, 3, 3, 2}; // 1, h, w, c
+    std::vector<float> filter = {-1,  2,   -3, 4,   5,  -6,  -7, 8,  9,
+                                 -10, -11, 12, -13, 14, -15, 16, 17, -18};
+    nnfw::cker::Shape input_shape{1, 3, 3, 2}; // n, h, w, c
+    std::vector<float> input = {-1,  2,  -3,  4,  5,   -6, -7,  8,   -9,
+                                -10, 11, -12, 13, -14, 15, -16, -17, 18};
+
+    DepthwiseConvVerifier<float> verifier;
+    verifier.prepare(incoming_shape, filter_shape);
+    verifier.verifyInputGradExpected(params, incoming_shape, incoming.data(), filter_shape,
+                                     filter.data(), input_shape);
+    verifier.verifyFilterGradExpected(params, incoming_shape, incoming.data(), input_shape,
+                                      input.data(), filter_shape);
+  }
+
+  // pad same, stride 2
+  {
+    nnfw::cker::DepthwiseConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kSame;
+    params.stride_width = 2;
+    params.stride_height = 2;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+    params.depth_multiplier = 1;
+
+    nnfw::cker::Shape incoming_shape{1, 1, 1, 2}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2};
+    nnfw::cker::Shape filter_shape{1, 2, 2, 2}; // 1, h, w, c
+    std::vector<float> filter = {-1, 2, -3, 4, 5, -6, -7, 8};
+    nnfw::cker::Shape input_shape{1, 3, 3, 2}; // n, h, w, c
+    std::vector<float> input = {-1,  2,  -3,  4,  5,   -6, -7,  8,   -9,
+                                -10, 11, -12, 13, -14, 15, -16, -17, 18};
+
+    DepthwiseConvVerifier<float> verifier;
+    verifier.prepare(incoming_shape, filter_shape);
+    verifier.verifyInputGradExpected(params, incoming_shape, incoming.data(), filter_shape,
+                                     filter.data(), input_shape);
+    verifier.verifyFilterGradExpected(params, incoming_shape, incoming.data(), input_shape,
+                                      input.data(), filter_shape);
+  }
+
+  // multi thread case
+  {
+    nnfw::cker::DepthwiseConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kNone;
+    params.padding_values.width = 0;
+    params.padding_values.height = 0;
+    params.stride_width = 1;
+    params.stride_height = 1;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+    params.depth_multiplier = 1;
+
+    nnfw::cker::Shape incoming_shape{10, 112, 112, 32}; // n, h, w, c
+    std::vector<float> incoming;
+    for (int i = 0; i < incoming_shape.FlatSize(); ++i)
+    {
+      incoming.push_back(static_cast<float>(i) / static_cast<float>(RAND_MAX));
+    }
+    nnfw::cker::Shape filter_shape{1, 3, 3, 32}; // 1, h, w, c
+    std::vector<float> filter;
+    for (int i = 0; i < filter_shape.FlatSize(); ++i)
+    {
+      filter.push_back(static_cast<float>(i) / static_cast<float>(RAND_MAX));
+    }
+    nnfw::cker::Shape input_shape{10, 112, 112, 32}; // n, h, w, c
+    std::vector<float> input;
+    const int input_size = input_shape.FlatSize();
+    for (int i = 0; i < input_size; ++i)
+    {
+      input.push_back(static_cast<float>(input_size - i) * 0.001f / static_cast<float>(RAND_MAX));
+    }
+
+    DepthwiseConvVerifier<float> verifier;
+    verifier.prepare(incoming_shape, filter_shape);
+    verifier.verifyInputGradExpected(params, incoming_shape, incoming.data(), filter_shape,
+                                     filter.data(), input_shape);
+    verifier.verifyFilterGradExpected(params, incoming_shape, incoming.data(), input_shape,
+                                      input.data(), filter_shape);
+  }
+}
+
+TEST(CKer_Operation, neg_DepthwiseConvGrad)
+{
+  // Not matched stride, InputGrad test case
+  {
+    nnfw::cker::DepthwiseConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kNone;
+    params.padding_values.width = 0;
+    params.padding_values.height = 0;
+    params.stride_width = 1;
+    params.stride_height = 2;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+    params.depth_multiplier = 1;
+
+    nnfw::cker::Shape incoming_shape{1, 2, 2, 4}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2,  -0.3, 0.4,  0.5,  -0.6, -0.7, 0.8,
+                                   0.9,  -1.0, 1.1,  -1.2, -1.3, 1.4,  1.5,  -1.6};
+    nnfw::cker::Shape filter_shape{1, 2, 2, 4}; // 1, h, w, c
+    std::vector<float> filter = {-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12};
+    nnfw::cker::Shape input_shape{1, 3, 3, 4}; // n, h, w, c
+    std::vector<float> input = {-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};
+
+    DepthwiseConvVerifier<float> verifier;
+    verifier.prepare(incoming_shape, filter_shape);
+    verifier.throwInputGradExpected(params, incoming_shape, incoming.data(), filter_shape,
+                                    filter.data(), input_shape);
+  }
+
+  // Not matched stride, FilterGrad test case
+  {
+    nnfw::cker::DepthwiseConvParams params;
+    params.padding_type = nnfw::cker::PaddingType::kNone;
+    params.padding_values.width = 0;
+    params.padding_values.height = 0;
+    params.stride_width = 1;
+    params.stride_height = 2;
+    params.dilation_width_factor = 1;
+    params.dilation_height_factor = 1;
+    params.depth_multiplier = 1;
+
+    nnfw::cker::Shape incoming_shape{1, 2, 2, 4}; // n, h, w, c
+    std::vector<float> incoming = {-0.1, 0.2,  -0.3, 0.4,  0.5,  -0.6, -0.7, 0.8,
+                                   0.9,  -1.0, 1.1,  -1.2, -1.3, 1.4,  1.5,  -1.6};
+    nnfw::cker::Shape filter_shape{1, 2, 2, 4}; // 1, h, w, c
+    std::vector<float> filter = {-1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12};
+    nnfw::cker::Shape input_shape{1, 3, 3, 4}; // n, h, w, c
+    std::vector<float> input = {-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};
+
+    DepthwiseConvVerifier<float> verifier;
+    verifier.prepare(incoming_shape, filter_shape);
+    verifier.throwFilterGradExpected(params, incoming_shape, incoming.data(), filter_shape,
+                                     filter.data(), input_shape);
+  }
+}
index 98568f4..034d07c 100644 (file)
 #include <gtest/gtest.h>
 #include <vector>
 
+namespace
+{
+using namespace nnfw::cker;
+
+template <typename T> class LossCCEVerifier
+{
+public:
+  LossCCEVerifier(const Shape &in_shape, const Shape &out_shape)
+    : _in_shape{in_shape}, _out_shape{out_shape}
+  {
+  }
+
+  void verifyForward(const std::vector<T> &y_pred, const std::vector<T> &y_true,
+                     const std::vector<T> &expected)
+  {
+    assert(y_pred.size() == y_true.size());
+
+    std::vector<T> output(_out_shape.FlatSize());
+    const int N = _in_shape.Dims(0);
+    const int D = _in_shape.FlatSize() / N;
+
+    nnfw::cker::train::CategoricalCrossEntropy(_in_shape, y_pred.data(), _in_shape, y_true.data(),
+                                               _out_shape, output.data());
+
+    // Don't be panic when it fails after kernel implementation or input is changed.
+    // CrossEntropy formula can be calculated slightly differently depending on the environment
+    // because it involes calculations such as log or exp.
+    for (int i = 0; i < output.size(); ++i)
+    {
+      EXPECT_NEAR(output[i], expected[i], 1e-3f);
+    }
+  }
+
+  void throwForward(const std::vector<T> &y_pred, const std::vector<T> &y_true,
+                    const std::vector<T> &expected)
+  {
+    assert(y_pred.size() == y_true.size());
+
+    std::vector<T> output(_out_shape.FlatSize());
+    const int N = _in_shape.Dims(0);
+    const int D = _in_shape.FlatSize() / N;
+
+    EXPECT_ANY_THROW(nnfw::cker::train::CategoricalCrossEntropy(
+      _in_shape, y_pred.data(), _in_shape, y_true.data(), _out_shape, output.data()));
+  }
+
+  void verifyBackward(const std::vector<T> &y_pred, const std::vector<T> &y_true,
+                      const std::vector<T> &expected)
+  {
+    assert(y_pred.size() == y_true.size());
+
+    std::vector<T> output(_in_shape.FlatSize());
+    const int N = _in_shape.Dims(0);
+    const int D = _in_shape.FlatSize() / N;
+
+    nnfw::cker::train::CategoricalCrossEntropyGrad(_in_shape, y_pred.data(), _in_shape,
+                                                   y_true.data(), _out_shape, output.data());
+
+    // Don't be panic when it fails after kernel implementation or input is changed.
+    // CrossEntropy Gradient formula can be calculated slightly differently depending on the
+    // environment because it involes calculations such as log or exp.
+    for (int i = 0; i < output.size(); ++i)
+    {
+      EXPECT_NEAR(output[i], expected[i], 1e-3f);
+    }
+  }
+
+  void throwBackward(const std::vector<T> &y_pred, const std::vector<T> &y_true,
+                     const std::vector<T> &expected)
+  {
+    assert(y_pred.size() == y_true.size());
+
+    std::vector<T> output(_out_shape.FlatSize());
+    const int N = _in_shape.Dims(0);
+    const int D = _in_shape.FlatSize() / N;
+
+    EXPECT_ANY_THROW(nnfw::cker::train::CategoricalCrossEntropyGrad(
+      _in_shape, y_pred.data(), _in_shape, y_true.data(), _out_shape, output.data()));
+  }
+
+private:
+  const Shape _in_shape;
+  const Shape _out_shape;
+};
+} // namespace
+
 TEST(CKer_Operation, LossMSE)
 {
   {
@@ -51,13 +137,16 @@ TEST(CKer_Operation, LossMSE)
     // 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};
+    std::vector<float> output(2);
+    std::vector<float> expected = {193.9667, 26.033342};
 
     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());
+                           y_true.data(), nnfw::cker::Shape{2}, output.data());
 
-    EXPECT_FLOAT_EQ(output[0], expected[0]);
+    for (int i = 0; i < output.size(); ++i)
+    {
+      EXPECT_FLOAT_EQ(output[i], expected[i]);
+    }
   }
 
   {
@@ -66,13 +155,16 @@ TEST(CKer_Operation, LossMSE)
                                  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};
+    std::vector<float> output(2);
+    std::vector<float> expected = {2.1666667, 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());
+                           y_true.data(), nnfw::cker::Shape{2}, output.data());
 
-    EXPECT_FLOAT_EQ(output[0], expected[0]);
+    for (int i = 0; i < output.size(); ++i)
+    {
+      EXPECT_FLOAT_EQ(output[i], expected[i]);
+    }
   }
 }
 
@@ -82,13 +174,16 @@ 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};
+    std::vector<float> output(2);
+    std::vector<float> expected = {0.0, 0.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());
+    nnfw::cker::train::MSE(nnfw::cker::Shape{2, 5}, y_pred.data(), nnfw::cker::Shape{2, 5},
+                           y_true.data(), nnfw::cker::Shape{2}, output.data());
 
-    EXPECT_NE(output[0], expected[0]);
+    for (int i = 0; i < output.size(); ++i)
+    {
+      EXPECT_NE(output[i], expected[i]);
+    }
   }
 
   {
@@ -96,10 +191,10 @@ TEST(CKer_Operation, neg_LossMSE)
     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};
+    std::vector<float> expected = {1.0, 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(),
+    EXPECT_ANY_THROW(nnfw::cker::train::MSE(nnfw::cker::Shape{2, 5}, y_pred.data(),
+                                            nnfw::cker::Shape{2, 5}, y_true.data(),
                                             nnfw::cker::Shape{3}, output.data()));
   }
 
@@ -107,12 +202,12 @@ TEST(CKer_Operation, neg_LossMSE)
     // 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};
+    std::vector<float> output(2);
+    std::vector<float> expected = {1.0, 1.0};
 
-    EXPECT_ANY_THROW(nnfw::cker::train::MSE(nnfw::cker::Shape{2, 3, 4}, y_pred.data(),
+    EXPECT_ANY_THROW(nnfw::cker::train::MSE(nnfw::cker::Shape{2, 5}, y_pred.data(),
                                             nnfw::cker::Shape{2, 3}, y_true.data(),
-                                            nnfw::cker::Shape{1}, output.data()));
+                                            nnfw::cker::Shape{2}, output.data()));
   }
 }
 
@@ -199,3 +294,96 @@ TEST(CKer_Operation, neg_LossMSEGrad)
                                                 nnfw::cker::Shape{2, 3}, deriv_y_pred.data()));
   }
 }
+
+TEST(CKer_Operation, LossCategoricalCrossEntropy)
+{
+  // single batch
+  {
+    nnfw::cker::Shape in_shape{1, 10};
+    nnfw::cker::Shape out_shape{1};
+
+    std::vector<float> y_pred = {2.86E-12, 2.82E-13, 0.99999845, 2.36E-07, 2.91E-16,
+                                 2.10E-07, 1.69E-14, 1.21E-17,   1.08E-06, 6.23E-18};
+    std::vector<float> y_true = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+    std::vector<float> expected = {39.617155};
+
+    LossCCEVerifier<float> verifier(in_shape, out_shape);
+    verifier.verifyForward(y_pred, y_true, expected);
+  }
+
+  // multiple batch
+  {
+    nnfw::cker::Shape in_shape{2, 10};
+    nnfw::cker::Shape out_shape{2};
+
+    std::vector<float> y_pred = {0.01, 0.03, 0.05, 0.35,  0.04,  0.05,  0.28,  0.09,  0.04,  0.06,
+                                 0.89, 0.03, 0.04, 0.005, 0.023, 0.001, 0.004, 0.005, 0.001, 0.001};
+    std::vector<float> y_true = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> expected = {2.813410, 0.116533};
+
+    LossCCEVerifier<float> verifier(in_shape, out_shape);
+    verifier.verifyForward(y_pred, y_true, expected);
+  }
+}
+
+TEST(CKer_Operation, neg_LossCategoricalCrossEntropy)
+{
+  // Invalid output shape
+  {
+    nnfw::cker::Shape in_shape{1, 10};
+    nnfw::cker::Shape out_shape{1, 1};
+
+    std::vector<float> y_pred = {-2.86E-12, 2.82E-13, 0.99999845, 2.36E-07, 2.91E-16,
+                                 2.10E-07,  1.69E-14, 1.21E-17,   1.08E-06, 6.23E-18};
+    std::vector<float> y_true = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+    std::vector<float> expected = {39.617155};
+
+    LossCCEVerifier<float> verifier(in_shape, out_shape);
+    verifier.throwForward(y_pred, y_true, expected);
+  }
+}
+
+TEST(CKer_Operation, LossCategoricalCrossEntropyGrad)
+{
+  {
+    nnfw::cker::Shape in_shape{1, 10};
+    nnfw::cker::Shape grad_shape{1, 10};
+
+    std::vector<float> y_pred = {0.01, 0.03, 0.05, 0.35, 0.04, 0.05, 0.28, 0.09, 0.04, 0.06};
+    std::vector<float> y_true = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+    std::vector<float> expected = {0, 0, 0, 0, 0, 0, 0, 0, 0, -16.66666667};
+
+    LossCCEVerifier<float> verifier(in_shape, grad_shape);
+    verifier.verifyBackward(y_pred, y_true, expected);
+  }
+
+  {
+    nnfw::cker::Shape in_shape{2, 10};
+    nnfw::cker::Shape grad_shape{2, 10};
+
+    std::vector<float> y_pred = {0.01, 0.03, 0.05, 0.35,  0.04,  0.05,  0.28,  0.09,  0.04,  0.06,
+                                 0.89, 0.03, 0.04, 0.005, 0.023, 0.001, 0.004, 0.005, 0.001, 0.001};
+    std::vector<float> y_true = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> expected = {0, 0, 0, 0, 0, 0, 0, 0, 0, -16.66666667, -1.123595506,
+                                   0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+    LossCCEVerifier<float> verifier(in_shape, grad_shape);
+    verifier.verifyBackward(y_pred, y_true, expected);
+  }
+}
+
+TEST(CKer_Operation, neg_LossCategoricalCrossEntropyGrad)
+{
+  // Invalid grad shape
+  {
+    nnfw::cker::Shape in_shape{1, 10};
+    nnfw::cker::Shape grad_shape{1, 1};
+
+    std::vector<float> y_pred = {0.01, 0.03, 0.05, 0.35, 0.04, 0.05, 0.28, 0.09, 0.04, 0.06};
+    std::vector<float> y_true = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+    std::vector<float> expected = {0, 0, 0, 0, 0, 0, 0, 0, 0, -16.66666667};
+
+    LossCCEVerifier<float> verifier(in_shape, grad_shape);
+    verifier.throwBackward(y_pred, y_true, expected);
+  }
+}
diff --git a/compute/cker/src/train/MaxPool.test.cc b/compute/cker/src/train/MaxPool.test.cc
new file mode 100644 (file)
index 0000000..a510d22
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/eigen/Utils.h>
+#include <cker/operation/MaxPool.h>
+#include <cker/train/operation/MaxPool.h>
+#include <cker/Shape.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+namespace
+{
+using namespace nnfw::cker;
+
+template <typename T> class MaxPoolOpVerifier
+{
+private:
+  const PoolParams _op_params;
+  const Shape _in_shape;
+  const Shape _out_shape;
+  std::vector<int> _arg_max_index;
+
+public:
+  MaxPoolOpVerifier(const nnfw::cker::PoolParams &op_params, const Shape &in_shape,
+                    const Shape &out_shape)
+    : _op_params(op_params), _in_shape(in_shape), _out_shape(out_shape)
+  {
+    _arg_max_index.reserve(_out_shape.FlatSize());
+  }
+
+public:
+  void verifyForward(const std::vector<T> input, const std::vector<T> expected_output,
+                     bool expect_eq = true)
+  {
+    assert(input.size() == _in_shape.FlatSize());
+    assert(expected_output.size() == _out_shape.FlatSize());
+
+    std::vector<T> cacluated_output(_out_shape.FlatSize());
+    nnfw::cker::train::MaxPool2D(_op_params, _in_shape, input.data(), _out_shape,
+                                 cacluated_output.data(), _arg_max_index.data());
+
+    if (expect_eq)
+      EXPECT_EQ(expected_output, cacluated_output);
+    else
+      EXPECT_NE(expected_output, cacluated_output);
+  }
+
+  void verifyBackward(const std::vector<T> incoming_data, const std::vector<T> expected_grad_data,
+                      bool expect_eq = true)
+  {
+    assert(incoming_data.size() == _out_shape.FlatSize());
+    assert(expected_grad_data.size() == _in_shape.FlatSize());
+
+    std::vector<T> calcuated_grad(_in_shape.FlatSize());
+    nnfw::cker::train::MaxPool2DGrad(_out_shape, incoming_data.data(), _arg_max_index.data(),
+                                     _in_shape, calcuated_grad.data());
+
+    if (expect_eq)
+      EXPECT_EQ(expected_grad_data, calcuated_grad);
+    else
+      EXPECT_NE(expected_grad_data, calcuated_grad);
+  }
+};
+
+} // namespace
+
+TEST(CKer_Operation, MaxPool2D)
+{
+  // Depth 1 case
+  {
+    nnfw::cker::PoolParams op_param;
+    {
+      op_param.stride_height = 1;
+      op_param.stride_width = 1;
+      op_param.filter_height = 2;
+      op_param.filter_width = 2;
+      op_param.padding_values.height = 0;
+      op_param.padding_values.width = 0;
+    }
+    nnfw::cker::Shape in = {1, 3, 3, 1};
+    nnfw::cker::Shape out = {1, 2, 2, 1};
+
+    MaxPoolOpVerifier<float> verifier(op_param, in, out);
+
+    /**
+     *  input(index) :                         output(arg-index):
+     *
+     *  10(0)  15(1)   2(2)
+     *   7(3)   8(4)   9(5)   - (forward) ->   15(1)  15(1)
+     *  10(6)   1(7)   0(8)                    10(6)   9(5)
+     */
+
+    std::vector<float> input = {10, 15, 2, 7, 8, 9, 10, 1, 0};
+    std::vector<float> expected_output = {15, 15, 10, 9};
+    verifier.verifyForward(input, expected_output);
+
+    /**
+     *  output_deriv:                     input_deriv:
+     * (randomly filled)
+     *
+     *   0.1   0.2                        0     0.3   0
+     *   0.3   0.4     - (backward) ->    0     0     0.4
+     *                                    0.3   0     0
+     */
+
+    std::vector<float> output_deriv = {0.1, 0.2, 0.3, 0.4};
+    std::vector<float> expected_input_deriv = {0, 0.3, 0, 0, 0, 0.4, 0.3, 0, 0};
+    verifier.verifyBackward(output_deriv, expected_input_deriv);
+  }
+
+  // Depth 2 case
+  {
+    nnfw::cker::PoolParams op_param;
+    {
+      op_param.stride_height = 1;
+      op_param.stride_width = 1;
+      op_param.filter_height = 3;
+      op_param.filter_width = 3;
+      op_param.padding_values.height = 0;
+      op_param.padding_values.width = 0;
+    }
+    nnfw::cker::Shape in = {1, 3, 3, 2};
+    nnfw::cker::Shape out = {1, 1, 1, 2};
+
+    MaxPoolOpVerifier<float> verifier(op_param, in, out);
+
+    /**
+     *  depth[0]
+     *  input(index) :                     output(arg-index):
+     *
+     *  10(0)  15(1)  2(2)
+     *  10(3)  12(4)  17(5)   -(forward)->     50(6)
+     *  50(6)  34(7)  -2(8)
+     *
+     *
+     *  depth[1]
+     *  input(index):                      output(arg-index):
+     *
+     *  -1(0)  2(1)  3(2)
+     *  8(3)   9(4)  2(5)    -(forward)->       9(4)
+     *  4(6)   2(7)  1(8)
+     */
+
+    std::vector<float> input(in.FlatSize());
+    auto input_mat = MapAsMatrixWithLastDimAsRows(input.data(), in);
+    input_mat << /* depth0 */ 10, 15, 2, 10, 12, 17, 50, 34, -2,
+      /* depth1 */ -1, 2, 3, 8, 9, 2, 4, 2, 1;
+    std::vector<float> expected_output = {50, 9};
+    verifier.verifyForward(input, expected_output);
+
+    /**
+     * depth[0]
+     * ouput_deriv:                 input_deriv:
+     *
+     *                              0   0   0
+     *    0.5     -(backward)->     0   0   0
+     *                             0.5  0   0
+     *
+     *
+     * depth[1]
+     * output_deriv:                input_deriv:
+     *                              0   0   0
+     *    0.9     -(backward)->     0  0.9  0
+     *                              0   0   0
+     */
+
+    std::vector<float> output_deriv = {0.5, 0.9};
+    std::vector<float> expected_input_deriv(in.FlatSize());
+    auto input_deriv_mat = MapAsMatrixWithLastDimAsRows(expected_input_deriv.data(), in);
+    input_deriv_mat << /* depth0 */ 0, 0, 0, 0, 0, 0, 0.5, 0, 0,
+      /* depth1 */ 0, 0, 0, 0, 0.9, 0, 0, 0, 0;
+    verifier.verifyBackward(output_deriv, expected_input_deriv);
+  }
+
+  // with padding case
+  {
+    nnfw::cker::PoolParams op_param;
+    {
+      op_param.stride_height = 2;
+      op_param.stride_width = 2;
+      op_param.filter_height = 2;
+      op_param.filter_width = 2;
+      op_param.padding_values.height = 2;
+      op_param.padding_values.width = 2;
+    }
+    nnfw::cker::Shape in = {1, 2, 2, 1};
+    nnfw::cker::Shape out = {1, 3, 3, 1};
+
+    MaxPoolOpVerifier<float> verifier(op_param, in, out);
+
+    /**
+     * input_with_padding:             expected_output:
+     *
+     *    4   8                              0  0  0
+     *    9   2            -(forward)->      0  9  0
+     *                                       0  0  0
+     */
+
+    std::vector<float> input = {4, 8, 9, 2};
+    std::vector<float> expected_output = {0, 0, 0, 0, 9, 0, 0, 0, 0};
+    verifier.verifyForward(input, expected_output);
+
+    /**
+     * output_deriv:                    input_deriv:
+     *
+     *  0.1   0.1   0.1                     0     0
+     *  0.1   0.2   0.3   -(backward)->     0.2   0
+     *  0.5   0.1   0.1
+     */
+    std::vector<float> output_deriv = {0.1, 0.1, 0.1, 0.1, 0.2, 0.3, 0.5, 0.1, 0.1};
+    std::vector<float> expected_input_deriv = {0, 0, 0.2, 0};
+    verifier.verifyBackward(output_deriv, expected_input_deriv);
+  }
+}
+
+TEST(CKer_Operation, neg_MaxPool)
+{
+  // Invalid expected value
+  {
+    nnfw::cker::PoolParams op_param;
+    {
+      op_param.stride_height = 1;
+      op_param.stride_width = 1;
+      op_param.filter_height = 2;
+      op_param.filter_width = 2;
+      op_param.padding_values.height = 0;
+      op_param.padding_values.width = 0;
+    }
+    nnfw::cker::Shape in = {1, 2, 2, 1};
+    nnfw::cker::Shape out = {1, 1, 1, 1};
+
+    MaxPoolOpVerifier<float> verifier(op_param, in, out);
+
+    std::vector<float> input = {0, 0, 0, 0};
+    std::vector<float> expected_output = {-1};
+
+    verifier.verifyForward(input, expected_output, false);
+  }
+
+  // Invalid expected value
+  {
+    nnfw::cker::PoolParams op_param;
+    {
+      op_param.stride_height = 2;
+      op_param.stride_width = 2;
+      op_param.filter_height = 2;
+      op_param.filter_width = 2;
+      op_param.padding_values.height = 1;
+      op_param.padding_values.width = 1;
+    }
+
+    nnfw::cker::Shape in = {1, 2, 2, 1};
+    nnfw::cker::Shape out = {1, 2, 2, 1};
+
+    MaxPoolOpVerifier<float> verifier(op_param, in, out);
+
+    std::vector<float> input = {0, 0, 0, 0};
+    std::vector<float> expected_output = {0, 0, 0, 0};
+    verifier.verifyForward(input, expected_output);
+
+    std::vector<float> output_deriv = {0.1, 0.1, 0.1, 0.2};
+    std::vector<float> expected_input_deriv = {0.1, 0.1, 0.1, 0.1};
+    verifier.verifyBackward(output_deriv, expected_input_deriv, false);
+  }
+}
diff --git a/compute/cker/src/train/Pad.test.cc b/compute/cker/src/train/Pad.test.cc
new file mode 100644 (file)
index 0000000..269534f
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/eigen/Utils.h>
+#include <cker/train/operation/Pad.h>
+#include <cker/Shape.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+namespace
+{
+using namespace nnfw::cker;
+
+template <typename T> class PadOpVerifier
+{
+private:
+  const PadParams _op_params;
+  const Shape _in_shape;
+  const Shape _out_shape;
+  T _constant_value;
+
+public:
+  PadOpVerifier(const PadParams &op_params, const Shape &in_shape, const Shape &out_shape,
+                T constant_value)
+    : _op_params(op_params), _in_shape(in_shape), _out_shape(out_shape),
+      _constant_value(constant_value)
+  {
+    // DO NOTHING
+  }
+
+public:
+  void verifyForward(const std::vector<T> input, const std::vector<T> expected_output,
+                     bool expect_eq = true)
+  {
+    assert(input.size() == _in_shape.FlatSize());
+    assert(expected_output.size() == _out_shape.FlatSize());
+
+    std::vector<T> cacluated_output(_out_shape.FlatSize());
+    nnfw::cker::Pad(_op_params.data, _op_params.rank, _in_shape, input.data(), _out_shape,
+                    cacluated_output.data(), &_constant_value);
+
+    if (expect_eq)
+      EXPECT_EQ(expected_output, cacluated_output);
+    else
+      EXPECT_NE(expected_output, cacluated_output);
+  }
+
+  void verifyBackward(const std::vector<T> backward_output,
+                      const std::vector<T> expected_backward_input, bool expect_eq = true)
+  {
+    assert(backward_output.size() == _out_shape.FlatSize());
+    assert(expected_backward_input.size() == _in_shape.FlatSize());
+
+    std::vector<T> backward_input(_in_shape.FlatSize());
+    nnfw::cker::train::Depad(_op_params.data, _op_params.rank, _out_shape, backward_output.data(),
+                             _in_shape, backward_input.data());
+
+    if (expect_eq)
+      EXPECT_EQ(expected_backward_input, backward_input);
+    else
+      EXPECT_NE(expected_backward_input, backward_input);
+  }
+};
+
+} // namespace
+
+TEST(CKer_Operation, Pad)
+{
+  // NOTE:
+  // Since the pad operation is an operation that only copies memory
+  // (precisely where to copy memory), each input and output of forward/backward
+  // can be used as each other's output and input.
+
+  // Pad rank 1
+  {
+    nnfw::cker::PadParams op_param;
+    {
+      op_param.rank = 1;
+      op_param.data[0] = 1;
+      op_param.data[1] = 1;
+    }
+    float constant_value = 3.f;
+
+    nnfw::cker::Shape in = {1};
+    nnfw::cker::Shape out = {3};
+
+    PadOpVerifier<float> verifier(op_param, in, out, constant_value);
+
+    std::vector<float> input = {1.f};
+    std::vector<float> expected_output = {3.f, 1.f, 3.f};
+    verifier.verifyForward(input, expected_output);
+    verifier.verifyBackward(expected_output, input);
+  }
+  {
+    nnfw::cker::PadParams op_param;
+    {
+      op_param.rank = 1;
+      op_param.data[0] = 2;
+      op_param.data[1] = 2;
+    }
+    float constant_value = 1.f;
+
+    nnfw::cker::Shape in = {3};
+    nnfw::cker::Shape out = {7};
+
+    PadOpVerifier<float> verifier(op_param, in, out, constant_value);
+
+    std::vector<float> input = {2.f, 3.f, 4.f};
+    std::vector<float> expected_output = {1.f, 1.f, 2.f, 3.f, 4.f, 1.f, 1.f};
+    verifier.verifyForward(input, expected_output);
+    verifier.verifyBackward(expected_output, input);
+  }
+
+  // Pad rank 2: HW
+  {
+    nnfw::cker::PadParams op_param;
+    {
+      op_param.rank = 2;
+      op_param.data[0] = 1;
+      op_param.data[1] = 1;
+      op_param.data[2] = 1;
+      op_param.data[3] = 1;
+    }
+    float constant_value = 3.f;
+
+    nnfw::cker::Shape in = {1, 1};
+    nnfw::cker::Shape out = {3, 3};
+
+    PadOpVerifier<float> verifier(op_param, in, out, constant_value);
+
+    float init_value = 1.f;
+    std::vector<float> input = {init_value};
+    std::vector<float> expected_output(3 * 3, constant_value);
+    expected_output[expected_output.size() / 2] = init_value;
+    verifier.verifyForward(input, expected_output);
+    verifier.verifyBackward(expected_output, input);
+  }
+  {
+    nnfw::cker::PadParams op_param;
+    {
+      op_param.rank = 2;
+      op_param.data[0] = 3;
+      op_param.data[1] = 3;
+      op_param.data[2] = 3;
+      op_param.data[3] = 3;
+    }
+    float constant_value = 1.f;
+
+    nnfw::cker::Shape in = {3, 3};
+    nnfw::cker::Shape out = {9, 9};
+
+    PadOpVerifier<float> verifier(op_param, in, out, constant_value);
+
+    float init_value = 1.f;
+    std::vector<float> input(3 * 3, init_value);
+    std::vector<float> expected_output(9 * 9, constant_value);
+    for (auto i = -1; i <= 1; ++i)
+    {
+      for (auto j = -1; j <= 1; ++j)
+      {
+        size_t ind = (9 * i) + (expected_output.size() / 2 + j);
+        expected_output[ind] = init_value;
+      }
+    }
+    verifier.verifyForward(input, expected_output);
+    verifier.verifyBackward(expected_output, input);
+  }
+
+  // Pad rank 3: HWC
+  {
+    nnfw::cker::PadParams op_param;
+    {
+      op_param.rank = 3;
+      op_param.data[0] = 1;
+      op_param.data[1] = 1;
+      op_param.data[2] = 1;
+      op_param.data[3] = 1;
+      op_param.data[4] = 1;
+      op_param.data[5] = 1;
+    }
+    float constant_value = 3.f;
+
+    nnfw::cker::Shape in = {1, 1, 1};
+    nnfw::cker::Shape out = {3, 3, 3};
+
+    PadOpVerifier<float> verifier(op_param, in, out, constant_value);
+
+    float init_value = 1.f;
+    std::vector<float> input = {init_value};
+    std::vector<float> expected_output(3 * 3 * 3, constant_value);
+    expected_output[expected_output.size() / 2] = init_value;
+    verifier.verifyForward(input, expected_output);
+    verifier.verifyBackward(expected_output, input);
+  }
+  {
+    nnfw::cker::PadParams op_param;
+    {
+      op_param.rank = 3;
+      op_param.data[0] = 5;
+      op_param.data[1] = 5;
+      op_param.data[2] = 5;
+      op_param.data[3] = 5;
+      op_param.data[4] = 5;
+      op_param.data[5] = 5;
+    }
+    float constant_value = 7.f;
+
+    nnfw::cker::Shape in = {3, 3, 3};
+    nnfw::cker::Shape out = {13, 13, 13};
+
+    PadOpVerifier<float> verifier(op_param, in, out, constant_value);
+
+    float init_value = 5.f;
+    std::vector<float> input(3 * 3 * 3, init_value);
+    std::vector<float> expected_output(13 * 13 * 13, constant_value);
+    for (auto i = -1; i <= 1; ++i)
+    {
+      for (auto j = -1; j <= 1; ++j)
+      {
+        for (auto k = -1; k <= 1; ++k)
+        {
+          size_t ind = (13 * 13 * i) + (13 * j) + (expected_output.size() / 2 + k);
+          expected_output[ind] = init_value;
+        }
+      }
+    }
+    verifier.verifyForward(input, expected_output);
+    verifier.verifyBackward(expected_output, input);
+  }
+
+  // Pad rank 4
+  {
+    nnfw::cker::PadParams op_param;
+    {
+      op_param.rank = 4;
+      op_param.data[0] = 1;
+      op_param.data[1] = 1;
+      op_param.data[2] = 1;
+      op_param.data[3] = 1;
+      op_param.data[4] = 1;
+      op_param.data[5] = 1;
+      op_param.data[6] = 1;
+      op_param.data[7] = 1;
+    }
+    float constant_value = 3.f;
+
+    nnfw::cker::Shape in = {1, 1, 1, 1};
+    nnfw::cker::Shape out = {3, 3, 3, 3};
+
+    PadOpVerifier<float> verifier(op_param, in, out, constant_value);
+
+    float init_value = 1.f;
+    std::vector<float> input = {init_value};
+    std::vector<float> expected_output(3 * 3 * 3 * 3, constant_value);
+    expected_output[expected_output.size() / 2] = init_value;
+    verifier.verifyForward(input, expected_output);
+    verifier.verifyBackward(expected_output, input);
+  }
+  {
+    nnfw::cker::PadParams op_param;
+    {
+      op_param.rank = 4;
+      op_param.data[0] = 7;
+      op_param.data[1] = 7;
+      op_param.data[2] = 7;
+      op_param.data[3] = 7;
+      op_param.data[4] = 7;
+      op_param.data[5] = 7;
+      op_param.data[6] = 7;
+      op_param.data[7] = 7;
+    }
+    float constant_value = 9.f;
+
+    nnfw::cker::Shape in = {5, 5, 5, 5};
+    nnfw::cker::Shape out = {19, 19, 19, 19};
+
+    PadOpVerifier<float> verifier(op_param, in, out, constant_value);
+
+    float init_value = 2.f;
+    std::vector<float> input(5 * 5 * 5 * 5, init_value);
+    std::vector<float> expected_output(19 * 19 * 19 * 19, constant_value);
+    for (auto i = -2; i <= 2; ++i)
+    {
+      for (auto j = -2; j <= 2; ++j)
+      {
+        for (auto k = -2; k <= 2; ++k)
+        {
+          for (auto l = -2; l <= 2; ++l)
+          {
+            size_t ind =
+              (19 * 19 * 19 * i) + (19 * 19 * j) + (19 * k) + (expected_output.size() / 2 + l);
+            expected_output[ind] = init_value;
+          }
+        }
+      }
+    }
+    verifier.verifyForward(input, expected_output);
+    verifier.verifyBackward(expected_output, input);
+  }
+
+  // TODO: Add tests for more complex padding options
+}
+
+// TODO: neg_Pad
diff --git a/compute/cker/src/train/ReduceMean.test.cc b/compute/cker/src/train/ReduceMean.test.cc
new file mode 100644 (file)
index 0000000..856f6e9
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/ReduceMean.h>
+#include <cker/train/operation/ReduceMean.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+namespace
+{
+using namespace nnfw::cker;
+
+template <typename T> class ReduceMeanVerifier
+{
+public:
+  ReduceMeanVerifier(const Shape &in_shape, const Shape &out_shape,
+                     const std::vector<int32_t> &axes, bool keep_dims)
+    : _in_shape{in_shape}, _out_shape{out_shape}, _axes{axes}, _keep_dims{keep_dims},
+      _axis_is_1_and_2{false}
+  {
+    _axis_is_1_and_2 = _keep_dims && _in_shape.DimensionsCount() == 4 && _axes.size() == 2 &&
+                       ((_axes[0] == 1 && _axes[1] == 2) || (_axes[0] == 2 && _axes[1] == 1));
+  }
+
+  void verifyForward(const std::vector<T> &input, const std::vector<T> &expected,
+                     bool expect_eq = true)
+  {
+    assert(input.size() == _in_shape.FlatSize());
+    assert(expected.size() == _out_shape.FlatSize());
+
+    std::vector<T> output(_out_shape.FlatSize());
+
+    if (_axis_is_1_and_2)
+    {
+      nnfw::cker::MeanAxis1And2(_in_shape, input.data(), _out_shape, output.data());
+    }
+    else
+    {
+      nnfw::cker::Mean(_in_shape, input.data(), _out_shape, output.data(), _axes);
+    }
+
+    if (expect_eq)
+      EXPECT_EQ(output, expected);
+    else
+      EXPECT_NE(output, expected);
+  }
+
+  void verifyBackward(const std::vector<T> &incoming, const std::vector<T> &expected,
+                      bool expect_eq = true)
+  {
+    std::vector<T> grad(_in_shape.FlatSize());
+
+    nnfw::cker::train::MeanGrad(_out_shape, incoming.data(), _in_shape, grad.data());
+
+    if (expect_eq)
+    {
+      // consider the floating point error
+      for (int i = 0; i < grad.size(); ++i)
+      {
+        EXPECT_NEAR(grad[i], expected[i], 1e-3f);
+      }
+    }
+    else
+      EXPECT_NE(grad, expected);
+  }
+
+private:
+  const Shape _in_shape;
+  const Shape _out_shape;
+  const std::vector<int32_t> _axes;
+  const bool _keep_dims;
+  bool _axis_is_1_and_2;
+};
+
+} // namespace
+
+TEST(CKer_Operation, ReduceMean)
+{
+  // axis = 0
+  {
+    nnfw::cker::Shape in_shape = nnfw::cker::Shape{2, 2};
+    std::vector<float> in_data = {1., 1., 2., 2.};
+    nnfw::cker::Shape out_shape = nnfw::cker::Shape{1, 2};
+    std::vector<float> expected_data = {1.5, 1.5};
+    std::vector<int32_t> axes = {0};
+
+    ReduceMeanVerifier<float> verifier(in_shape, out_shape, axes, false /*keep_dims*/);
+    verifier.verifyForward(in_data, expected_data);
+  }
+
+  // axis = 1
+  {
+    nnfw::cker::Shape in_shape = nnfw::cker::Shape{2, 2};
+    std::vector<float> in_data = {1., 1., 2., 2.};
+    nnfw::cker::Shape out_shape = nnfw::cker::Shape{2, 1};
+    std::vector<float> expected_data = {1., 2.};
+    std::vector<int32_t> axes = {1};
+
+    ReduceMeanVerifier<float> verifier(in_shape, out_shape, axes, false /*keep_dims*/);
+    verifier.verifyForward(in_data, expected_data);
+  }
+}
+
+TEST(CKer_Operation, neg_ReduceMean)
+{
+  // wrong axis
+  {
+    nnfw::cker::Shape in_shape = nnfw::cker::Shape{2, 2};
+    std::vector<float> in_data = {1., 1., 2., 2.};
+    nnfw::cker::Shape out_shape = nnfw::cker::Shape{1, 2};
+    std::vector<float> expected_data = {1., 2.};
+    std::vector<int32_t> axes = {0};
+
+    ReduceMeanVerifier<float> verifier(in_shape, out_shape, axes, false /*keep_dims*/);
+    verifier.verifyForward(in_data, expected_data, false);
+  }
+}
+
+TEST(CKer_Operation, ReduceMeanGrad)
+{
+  // axis = 0
+  {
+    nnfw::cker::Shape in_shape = nnfw::cker::Shape{2, 2};
+    nnfw::cker::Shape out_shape = nnfw::cker::Shape{1, 2};
+    // nnfw::cker::Shape incoming_shape = out_shape;
+    std::vector<float> incoming_data = {1., 2.};
+    // nnfw::cker::Shape grad_shape = in_shape;
+    std::vector<float> expected_grad_data = {0.5, 1, 0.5, 1.};
+    std::vector<int32_t> axes = {0};
+
+    ReduceMeanVerifier<float> verifier(in_shape, out_shape, axes, false /*keep_dims*/);
+    verifier.verifyBackward(incoming_data, expected_grad_data);
+  }
+  // axis = 1
+  {
+    nnfw::cker::Shape in_shape = nnfw::cker::Shape{2, 2};
+    nnfw::cker::Shape out_shape = nnfw::cker::Shape{2, 1};
+    // nnfw::cker::Shape incoming_shape = out_shape;
+    std::vector<float> incoming_data = {1., 2.};
+    // nnfw::cker::Shape grad_shape = in_shape;
+    std::vector<float> expected_grad_data = {0.5, 0.5, 1., 1.};
+    std::vector<int32_t> axes = {1};
+
+    ReduceMeanVerifier<float> verifier(in_shape, out_shape, axes, false /*keep_dims*/);
+    verifier.verifyBackward(incoming_data, expected_grad_data);
+  }
+}
+
+TEST(CKer_Operation, neg_ReduceMeanGrad)
+{
+  // wrong axis
+  {
+    nnfw::cker::Shape in_shape = nnfw::cker::Shape{2, 2};
+    nnfw::cker::Shape out_shape = nnfw::cker::Shape{1, 2};
+    // nnfw::cker::Shape incoming_shape = out_shape;
+    std::vector<float> incoming_data = {1., 2.};
+    // nnfw::cker::Shape grad_shape = in_shape;
+    std::vector<float> expected_grad_data = {0.5, 0.5, 1., 1.};
+    std::vector<int32_t> axes = {0};
+
+    ReduceMeanVerifier<float> verifier(in_shape, out_shape, axes, false /*keep_dims*/);
+    verifier.verifyBackward(incoming_data, expected_grad_data, false);
+  }
+}
diff --git a/compute/cker/src/train/Relu6.test.cc b/compute/cker/src/train/Relu6.test.cc
new file mode 100644 (file)
index 0000000..ca8a3fc
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/ReLU6.h>
+#include <cker/train/operation/ReLU6.h>
+
+#include <gtest/gtest.h>
+#include <gtest/gtest-spi.h>
+#include <vector>
+
+namespace
+{
+
+using namespace nnfw::cker;
+
+template <typename T> class Relu6OpVerifier
+{
+public:
+  void verifyBackward(const std::vector<T> &output, const std::vector<T> &input_bwd,
+                      const std::vector<T> &expected_output_bwd, bool expect_eq = true)
+  {
+    std::vector<T> calc_output_bwd(input_bwd.size()); // calculated output backward
+    train::ReLU6Grad(Shape{static_cast<int>(output.size())}, output.data(),
+                     Shape{static_cast<int>(input_bwd.size())}, input_bwd.data(),
+                     Shape{static_cast<int>(calc_output_bwd.size())}, calc_output_bwd.data());
+
+    if (expect_eq)
+      EXPECT_EQ(expected_output_bwd, calc_output_bwd);
+    else
+      EXPECT_NE(expected_output_bwd, calc_output_bwd);
+  }
+};
+
+} // namespace
+
+TEST(CKer_Operation, ReLU6)
+{
+  {
+    Relu6OpVerifier<float> verifier;
+
+    // clang-format off
+    // std::vector<float> input_fwd         = {-2.0,  -1.0,  2.0,  3.0,  6.0,  7.0};
+    std::vector<float> output_fwd           = { 0.0,   0.0,  2.0,  3.0,  6.0,  6.0};  
+    std::vector<float> input_bwd            = {-0.1,  -0.2,  0.3,  0.4, -0.1,  0.5};
+    std::vector<float> expected_output_bwd  = { 0.0,   0.0,  0.3,  0.4,  0.0,  0.0};
+    // clang-format on
+
+    verifier.verifyBackward(output_fwd, input_bwd, expected_output_bwd);
+  }
+
+  {
+    Relu6OpVerifier<float> verifier;
+
+    // clang-format off
+    // std::vector<float> input_fwd         = { 7.0,   8.0,  4.0, -4.0, -5.0, 10.0};
+    std::vector<float> output_fwd           = { 6.0,   6.0,  4.0,  0.0,  0.0,  6.0};  
+    std::vector<float> input_bwd            = {-6.1,  -3.3,  7.0,  8.4, -9.2,  0.0};
+    std::vector<float> expected_output_bwd  = { 0.0,   0.0,  7.0,  0.0,  0.0,  0.0};
+    // clang-format on
+
+    verifier.verifyBackward(output_fwd, input_bwd, expected_output_bwd);
+  }
+}
+
+TEST(CKer_Operation, neg_ReLU6)
+{
+  {
+    Relu6OpVerifier<float> verifier;
+
+    // clang-format off
+    // std::vector<float> input_fwd         = { 0.0,   2.0,  4.0,  6.0,  8.0, 10.0};
+    std::vector<float> output_fwd           = { 0.0,   2.0,  4.0,  6.0,  6.0,  6.0};  
+    std::vector<float> input_bwd            = { 0.1,   0.2,  0.3,  0.4,  0.5,  0.6};
+    std::vector<float> expected_output_bwd  = { 0.1,   0.2,  0.3,  0.4,  0.5,  0.6};  // wrong value
+    // clang-format on
+
+    verifier.verifyBackward(output_fwd, input_bwd, expected_output_bwd, false);
+  }
+
+  {
+    Relu6OpVerifier<float> verifier;
+
+    // clang-format off
+    // std::vector<float> input_fwd         = { 0.0,   2.0,  4.0,  6.0,  8.0, 10.0};
+    std::vector<float> output_fwd           = { 0.0,   2.0,  4.0,  6.0,  6.0,  6.0};  
+    std::vector<float> input_bwd            = { 0.1,   0.2,  0.3,  0.4};  // size mismatch
+    std::vector<float> expected_output_bwd  = { 0.0,   0.2,  0.3,  0.4};
+    // clang-format on
+
+    EXPECT_ANY_THROW(verifier.verifyBackward(output_fwd, input_bwd, expected_output_bwd, false));
+  }
+}
diff --git a/compute/cker/src/train/SGD.test.cc b/compute/cker/src/train/SGD.test.cc
new file mode 100644 (file)
index 0000000..0a819b3
--- /dev/null
@@ -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.
+ */
+
+#include <cker/train/optimizer/SGD.h>
+
+#include <gtest/gtest.h>
+#include <vector>
+
+// TODO Add tests that verifies result values
+template <typename T> class SGDOptimizerVerifier
+{
+public:
+  SGDOptimizerVerifier(const std::vector<T> &trainable, const std::vector<T> &gradient,
+                       float learning_rate, uint32_t nums_step)
+    : _trainable{trainable}, _gradient{gradient}, _learning_rate{learning_rate},
+      _nums_step{nums_step}
+  {
+    EXPECT_TRUE(trainable.size() == gradient.size());
+
+    _expected.resize(trainable.size());
+    std::copy(trainable.begin(), trainable.end(), _expected.begin());
+  }
+
+public:
+  void verify()
+  {
+    for (uint32_t step = 0; step < _nums_step; ++step)
+    {
+      calculateExpected();
+
+      nnfw::cker::train::GradientDescent(
+        nnfw::cker::Shape{static_cast<int>(_trainable.size())}, _trainable.data(),
+        nnfw::cker::Shape{static_cast<int>(_gradient.size())}, _gradient.data(), _learning_rate);
+
+      for (size_t i = 0; i < _trainable.size(); ++i)
+        EXPECT_NEAR(_trainable[i], _expected[i], 1e-5f);
+    }
+  }
+
+private:
+  void calculateExpected()
+  {
+    assert(_expected.size() == _gradient.size());
+
+    for (int i = 0; i < _expected.size(); ++i)
+    {
+      T g = _gradient.at(i);
+      T &var = _expected.at(i);
+
+      var -= g * _learning_rate;
+    }
+  }
+
+private:
+  std::vector<T> _trainable;
+  std::vector<T> _gradient;
+  float _learning_rate;
+  uint32_t _nums_step;
+  std::vector<T> _expected;
+};
+
+TEST(CKer_Optimizer, SGDSimple)
+{
+  {
+    std::vector<float> trainable = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient = {-1, 2, -3, 4, 5, -6, 7, 8, 9};
+    std::vector<float> m = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> v = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    float lr = 0.001;
+    uint32_t training_steps = 10000;
+
+    SGDOptimizerVerifier<float>{trainable, gradient, lr, training_steps}.verify();
+  }
+}
+
+TEST(CKer_Optimizer, neg_SGDUnmatchedGradientShape)
+{
+  // Unmatched shape
+  {
+    std::vector<float> trainable = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient = {-1, 2, -3, 4, 5, -6, 7, 8};
+    std::vector<float> m = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> v = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    float lr = 0.001;
+
+    EXPECT_ANY_THROW(nnfw::cker::train::GradientDescent(
+      nnfw::cker::Shape{static_cast<int>(trainable.size())}, trainable.data(),
+      nnfw::cker::Shape{static_cast<int>(gradient.size())}, gradient.data(), lr));
+  }
+}
diff --git a/compute/cker/src/train/SoftMax.test.cc b/compute/cker/src/train/SoftMax.test.cc
new file mode 100644 (file)
index 0000000..5f3a777
--- /dev/null
@@ -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.
+ */
+
+#include <cker/train/operation/SoftMax.h>
+
+#include <algorithm>
+#include <cmath>
+#include <gtest/gtest.h>
+#include <vector>
+
+// TODO Add tests that verifies result values
+TEST(CKer_Operation, SoftMaxGrad)
+{
+  // Unmatched shape
+  {
+    // Dim 1x10
+    nnfw::cker::Shape shape{1, 10};
+    std::vector<float> softmax = {2.86195412e-12, 2.81944090e-13, 9.99998474e-01, 2.35859203e-07,
+                                  2.90586864e-16, 2.09893085e-07, 1.68954109e-14, 1.21487884e-17,
+                                  1.08008625e-06, 6.22994465e-18};
+    std::vector<float> incoming = {5.72000000e-13, 5.64000000e-14, 1.99999690e-01, 4.72000000e-08,
+                                   5.81000000e-17, 4.20000000e-08, 3.38000000e-15, 2.43000000e-18,
+                                   2.16000000e-07, -2.00000003e-01};
+    std::vector<float> expected = {
+      -5.72389063e-13, -5.63886446e-14, 3.05167149e-07,  -4.71716844e-08, -5.81171941e-17,
+      -4.19784790e-08, -3.37907178e-15, -2.42975021e-18, -2.16016353e-07, -2.49197405e-18};
+    std::vector<float> grad(10);
+
+    nnfw::cker::train::SoftMaxGrad(shape, softmax.data(), shape, incoming.data(), shape,
+                                   grad.data());
+
+    // TODO Use EXPECT_FLOAT_EQUAL
+    for (size_t i = 0; i < grad.size(); ++i)
+      EXPECT_NEAR(grad[i], expected[i], 0.01);
+  }
+
+  {
+    // Dim 2x10
+    nnfw::cker::Shape shape{2, 10};
+    std::vector<float> softmax = {6.80841727e-08, 2.31582313e-11, 5.66484244e-05, 4.50472506e-01,
+                                  7.77810687e-13, 4.52301134e-04, 5.41837231e-01, 1.54489112e-07,
+                                  7.18104184e-03, 4.84659012e-08, 1.51924287e-03, 7.48874448e-04,
+                                  5.43233175e-02, 1.10145863e-01, 6.17917826e-10, 5.09775521e-04,
+                                  8.27892599e-01, 3.03146885e-05, 4.25460567e-03, 5.75406837e-04};
+    std::vector<float> incoming = {
+      -1.99999988e-01, 4.63000000e-12, 1.13000000e-05, 9.00945070e-02, 1.56000000e-13,
+      9.05000000e-05,  1.08367443e-01, 3.09000000e-08, 1.43620800e-03, 9.69000000e-09,
+      -1.99999988e-01, 4.63000000e-12, 1.13000000e-05, 9.00945070e-02, 1.56000000e-13,
+      9.05000000e-05,  1.08367443e-01, 3.09000000e-08, 1.43620800e-03, 9.69000000e-09};
+    std::vector<float> expected = {
+      -2.03784741e-08, -2.29991239e-12, -5.62528230e-06, -4.15265741e-03, -7.72466778e-14,
+      -4.48784290e-05, 4.90605867e-03,  -1.53427655e-08, -7.02857016e-04, -4.81329140e-09,
+      -5.15774553e-04, -1.04579225e-04, -7.00410377e-03, -1.29717840e-02, -8.63838721e-11,
+      -7.12137857e-05, 2.13432343e-02,  -4.23775872e-06, -5.91166379e-04, -8.03746891e-05};
+    std::vector<float> grad(20);
+
+    nnfw::cker::train::SoftMaxGrad(shape, softmax.data(), shape, incoming.data(), shape,
+                                   grad.data());
+
+    // TODO Use EXPECT_FLOAT_EQUAL
+    for (size_t i = 0; i < grad.size(); ++i)
+      EXPECT_NEAR(grad[i], expected[i], 0.1);
+  }
+}
+
+TEST(CKer_Operation, neg_SoftMaxGrad)
+{
+  // Invalid expected value
+  {
+    // Dim 1x10
+    nnfw::cker::Shape shape{1, 10};
+    std::vector<float> softmax = {7.96183250e-06, 1.73761995e-05, 9.35646649e-03, 5.53923216e-01,
+                                  7.15798787e-13, 1.46669847e-02, 4.21307124e-01, 2.77163556e-07,
+                                  4.36947878e-04, 2.83646234e-04};
+    std::vector<float> incoming = {1.5900000e-06, 3.4800000e-06, 1.8712930e-03, -8.9215361e-02,
+                                   1.4300000e-13, 2.9333970e-03, 8.4261417e-02, 5.5400000e-08,
+                                   8.7400000e-05, 5.6700000e-05};
+    std::vector<float> expected = {0.001, 0.002, 0.003, 0.001, 0.002,
+                                   0.003, 0.001, 0.002, 0.003, 0.001};
+    std::vector<float> grad(10);
+
+    nnfw::cker::train::SoftMaxGrad(shape, softmax.data(), shape, incoming.data(), shape,
+                                   grad.data());
+
+    for (size_t i = 0; i < grad.size(); ++i)
+      EXPECT_NE(grad[i], expected[i]);
+  }
+}
index 5025671..9d80491 100644 (file)
@@ -21,7 +21,7 @@ copyright = '2020, Samsung Research & contributors'
 author = 'Samsung Research & contributors'
 
 # The full version, including alpha/beta/rc tags
-release = '1.25.0'
+release = '1.28.0'
 
 # -- General configuration ---------------------------------------------------
 
index 3a96386..1f31f72 100644 (file)
@@ -197,11 +197,14 @@ python3 -m pip install numpy
 You can also run unit tests in ARM32 Ubuntu device with cross build results.
 First you need to run the test in host to prepare files that are currently
 complicated in target device.
+For value test with python, separate venv is requried. make target `test_venv`
+will prepare this.
 ```
 # run this in x86-64 host
 make -f infra/nncc/Makefile.arm32 test_prep
 
 # run this in ARM32 target device
+make -f infra/nncc/Makefile.arm32 test_venv
 make -f infra/nncc/Makefile.arm32 test
 ```
 
index 3e27057..77579d4 100644 (file)
@@ -16,7 +16,7 @@ Use `install_rootfs.sh` script to prepare Root File System. You should have `sud
 $ sudo ./tools/cross/install_rootfs.sh aarch64
 ```
 - supports `arm`(default) and `aarch64` architecutre for now
-- supports `bionic`(default) and `focal` release
+- supports `focal`, `jammy`, and `noble` release
 
 To see the options,
 ```
@@ -27,16 +27,18 @@ RootFS will be prepared at `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"
 ```
 
+`install_rootfs.sh` will select development system code name as default.
+
 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).
 
 ### Prepare RootFS at alternative folder
index 13984a0..dcc3130 100644 (file)
@@ -1,2 +1,41 @@
 # How to Cross-build Runtime for Android
 
+**Note: To set up a basic build environment on your development PC, please read the [how-to-build-runtime.md](how-to-build-runtime.md) document first. The cross build covered in this document assumes that you have an environment in which the native build operates normally without problems.**
+
+Supported Architecture : AARCH64 only (ARM32 is not supported yet)
+
+## Prepare Android NDK
+
+Use `tools/cross/install_android_ndk.sh` script to prepare Android NDK. This is recommended way to build Android NDK.
+
+Or you can use `tools/cross/install_android_sdk.sh` script to prepare Android SDK including NDK. You can find NDK in `{android-sdk-dir}/ndk/{ndk-version}` directory.
+
+## Build
+
+### Host Environment Requirements
+
+CMake 3.6.0 or later is required for Android NDK r26d CMake support.
+So if you want to use Docker, please use `infra/docker/android-sdk/Dockerfile`.
+
+```
+$ ./nnas build-docker-image --codename android-sdk -t nnfw/one-devtools:android-sdk
+```
+
+
+### Build and install the runtime
+
+Some tools/libs are still not supported and those are not built by default - mostly due to dependency on HDF5 library.
+Please refer to `infra/nnfw/cmake/options/options_aarch64-android.cmake` for details.
+
+Different from cross build for linux,
+
+- `NDK_DIR` is required
+
+Here is an example of using Makefile.
+
+```bash
+TARGET_OS=android \
+CROSS_BUILD=1 \
+NDK_DIR=/path/android-sdk/ndk/{ndk-version}/ \
+make -f Makefile.template install
+```
index 2db4d56..954218c 100644 (file)
@@ -14,7 +14,7 @@ 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 `aarch64` architecutre for now
-- supports `focal`(default), `bionic`, and `jammy` release
+- supports `focal`,`jammy`, and `noble` release
 
 To see the options,
 ```
@@ -35,6 +35,8 @@ DISTRIB_CODENAME=jammy
 DISTRIB_DESCRIPTION="Ubuntu 22.04.3 LTS"
 ```
 
+`install_rootfs.sh` will select development system code name as default.
+
 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).
 
 ### Prepare RootFS at alternative folder
index 9ab4987..fd1faf2 100644 (file)
@@ -243,7 +243,7 @@ This module generates IR from a model. There are two kinds of frontend: Loader a
 This is where the common parts of loaders are implemented.
 
 1. Add to base_loader to load new operation and to generate IR from it
-- [base_loader](/runtime/onert/frontend/base_loader/include/base_loader.h)
+- [base_loader](/runtime/onert/core/src/loader/base_loader.h)
 
 ```cpp
     case BuiltinOperator::BuiltinOperator_SELECT:
@@ -278,7 +278,7 @@ If you want new operation to be loaded on only Circle Loader, you only need to i
 ### NNAPI
 
 1. Add to the OperationFactory to generate IR of new operation
-- [OperationFactory](/runtime/onert/frontend/nnapi/wrapper/OperationFactory.cc)
+- [OperationFactory](/runtime/onert/api/nnapi/wrapper/OperationFactory.cc)
 
 ```cpp
   _map[ANEURALNETWORKS_SELECT] = [](const OperationFactory::Param &init_param, Operands &) {
@@ -470,4 +470,3 @@ void ConstantInitializer::visit(const ir::operation::Conv2D &node)
 - `Select` operation
   - Simple explanation : `Output[i] = Condition[i] ? input1[i] : input2[i]`
   - PR : https://github.com/Samsung/ONE/pull/XXX
-
index ade4e7b..7c6858a 100644 (file)
@@ -1,5 +1,5 @@
 # How to Use NNAPI Binding
 
-Runtime supports [Android Neural Networks API](https://developer.android.com/ndk/guides/neuralnetworks) as a frontend. We provide the whole `NeuralNetworks.h` implementation. Its source code is located at `runtime/onert/frontend/nnapi`.
+Runtime supports [Android Neural Networks API](https://developer.android.com/ndk/guides/neuralnetworks) as a frontend. We provide the whole `NeuralNetworks.h` implementation. Its source code is located at `runtime/onert/api/nnapi`.
 
 So users can just use NN API in the same way as [the official guide](https://developer.android.com/ndk/guides/neuralnetworks), but should watch the version of `NeuralNetworks.h`. It may not be the latest. There is a copy of the file is located at `runtime/nnapi-header/include/NeuralNetworks.h`.
index 1198a31..1f72039 100644 (file)
@@ -21,11 +21,11 @@ nnfw_create_session(&session);
 ``` c
 nnfw_load_model_from_file(session, nnpackage_path);
 ```
-3) (Optional) Assign a specific backend to operations
+3) (Optional) Assign a specific backend
 ``` c
-  // Use 'acl_neon' backend for CONV_2D and 'cpu' for otherwise.
+  // Use 'acl_neon' backend only
   // Note that defalut backend is 'cpu'.
-  nnfw_set_op_backend(session, "CONV_2D", "acl_neon");
+  nnfw_set_available_backends(session, "acl_neon");
 ```
 
 4) Compilation
diff --git a/docs/howto/how-to-use-nnfw-python-api.md b/docs/howto/how-to-use-nnfw-python-api.md
new file mode 100644 (file)
index 0000000..5d5b839
--- /dev/null
@@ -0,0 +1,50 @@
+# How to Use NNFW PYTHON API
+
+## CAUTION
+
+This Python API is experimental yet. It can be changed later.
+
+## Prepare nnpackage
+
+### Use nnpackage examples
+
+Use the [nnpackage examples](https://github.com/Samsung/ONE/tree/master/nnpackage/examples/v1.0.0) to run tutorial code.
+
+## Install nnfw python API
+
+Please see [nnfw python api](https://github.com/SAMSUNG/ONE/tree/master/infra/nnfw/python) for installing nnfw python api.
+
+1. Initialize nnfw_session
+
+```python
+# Create session and load nnpackage
+# operations is optional to assign a specific backends to each operation.
+# The default value of backends is "cpu".
+if operations:
+    session = nnfw_session(nnpackage_path, backends, operations)
+else:
+    session = nnfw_session(nnpackage_path, backends)
+```
+
+2. Prepare Input
+
+```python
+# Prepare input. Here we just allocate dummy input arrays.
+input_size = session.input_size()
+session.set_inputs(input_size)
+```
+
+3. Inference
+
+```python
+# Do inference
+outputs = session.inference()
+```
+
+## Run Inference with app on the target devices
+
+reference app : [minimal-python app](https://github.com/Samsung/ONE/blob/master/runtime/onert/sample/minimal-python)
+
+```
+$ python3 minimal.py path_to_nnpackage_directory
+```
index a839777..5aee349 100644 (file)
@@ -9,9 +9,6 @@ ONE runtime has many ways to use specific backend during inference
 - For each backend string, `libbackend_{backend}.so` will be dynamically loaded during nnfw_prepare.
 - Among the multiple backends, the 1st element is used as the default backend.
 
-### [nnfw_set_op_backend](https://github.com/Samsung/ONE/blob/c46ddc04abdb58323fbd38389e6927f003bfaea1/runtime/onert/api/include/nnfw.h#L476)
-- The backend for op has higher priority than available backends specified by nnfw_set_available_backends.
-
 ## Using Environment Variable
 
 ### 1. BACKENDS
@@ -22,7 +19,6 @@ BACKENDS=cpu ./Product/out/bin/onert_run ...
 ```
 
 ### 2. OP_BACKEND_[OP_TYPE]
-- Same as `nnfw_set_op_backend`
 - Set backend for specific operator type
 - Example
   - Execute `Conv2D` operator on ruy backend and others on cpu backend
diff --git a/docs/nnfw/howto/CrossBuildForAndroid.md b/docs/nnfw/howto/CrossBuildForAndroid.md
deleted file mode 100644 (file)
index 08d5fd6..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-# Cross building for Android
-
-**Note: To set up a basic build environment on your development PC, please read the [howto.md](../howto.md) document first. The cross build covered in this document assumes that you have an environment in which the native build operates normally without problems.**
-
-Supported Architecture : AARCH64 only (ARM32 is not supported yet)
-
-## Prepare Android NDK
-
-Use `tools/cross/install_android_ndk.sh` script to prepare Android NDK. This is recommended way to build Android NDK.
-You may download it yourself from the offical Android NDK website, but the script does a little more than just downloading and unzipping.
-
-## Build
-
-### Host Environment Requirements
-
-With Ubuntu 16.04, everything is fine except one. CMake 3.6.0 or later is required for Android NDK CMake support.
-So if you want to use Docker, please use `infra/docker/Dockerfile.1804` which is based on Ubuntu 18.04. It has CMake 3.10.2.
-
-```bash
-docker build --network host -t nnas1804 -f infra/docker/Dockerfile.1804 infra/docker
-```
-
-### Get prebuilt ARM Compute Library
-
-Download prebuilt binary from [github](https://github.com/ARM-software/ComputeLibrary/releases). Check the version we support and platform(Android).
-
-Then extract the tarball to the folder indicated as EXT_ACL_FOLDER in the example below. We will use the following file in `lib/android-arm64-v8a-neon-cl`.
-
-```
-libarm_compute_core.so
-libarm_compute_graph.so
-libarm_compute.so
-```
-
-### Build and install the runtime
-
-Some tools/libs are still not supported and those are not built by default - mostly due to dependency on Boost library.
-Please refer to `infra/nnfw/cmake/options/options_aarch64-android.cmake` for details.
-
-Different from cross build for linux,
-
-- `NDK_DIR` is required
-
-Here is an example of using Makefile.
-
-```bash
-TARGET_OS=android \
-CROSS_BUILD=1 \
-NDK_DIR=/path/android-tools/r20/ndk \
-EXT_ACL_FOLDER=/path/arm_compute-v19.11.1-bin-android/lib/android-arm64-v8a-neon-cl \
-make -f Makefile.template install
-```
index c4b21d4..80896d1 100644 (file)
@@ -4,25 +4,25 @@ Artificial intelligence (AI) techniques are getting popular and utilized in vari
 services. While the cloud-based AI techniques have been used to perform compute/memory intensive
 inferences because of the powerful servers on cloud, on-device AI technologies are recently drawing
 attention from the mobile industry for response time reduction, privacy protection, and
-connection-less AI service. Big mobile players are investing their research effort on the on-device
-AI technologies and already announced hardware and software on-device AI solutions. We are not
-leading this trend currently, but since on-device AI area is just started and still in the initial
-state, there are still opportunities and possibilities to reduce the gap between pioneers and us. We
-believe on-device AI will become a key differentiator for mobile phone, TV, and other home
-appliances, and thus developing on-device AI software stack is of paramount importance in order to
+connection-less AI service. Big mobile players are investing their research effort in the on-device
+AI technologies and have already announced hardware and software on-device AI solutions. We are not
+leading this trend currently, but since on-device AI area has just started and remains in the initial
+stage, there are still opportunities and possibilities to reduce the gap between pioneers and us. We
+believe that on-device AI will become a key differentiator for mobile phones, TV, and other home
+appliances. Therefore, developing on-device AI software stack is of paramount importance in order to
 take leadership in the on-device AI technology.
 
 Although the vision of on-device AI is promising, enabling on-device AI involves unique technical
 challenges compared to traditional cloud-based approach. This is because on-device AI tries to
 conduct inference tasks solely on device without connecting to cloud resources. Specifically,
-hardware resources on device, such as processor performance, memory capacity, and power budget, are
-very scarce and limit the compute capability, which is typically required to execute complicated
+hardware resources on device, such as processor performance, memory capacity and power budget are
+very scarce and limit the compute capability, which is typically required to execute complex
 neural network (NN) models. For example, in one product requirement, a mobile device should consume
-less than 1.2W and could use at most 2W only for 10 minutes due to thermal issue. Next, on-device AI
+less than 1.2W and could use at most 2W only for 10 minutes due to thermal constraints. On-device AI
 software stack needs to support diverse device environments, since embedded platforms may consist of
 heterogeneous compute devices, such as CPU, GPU, DSP, or neural processing unit (NPU), and use
-different OS platforms, such as Tizen, Android, or various Linux.
+different OS platforms, such as Tizen, Android, or various Linux systems.
 
-To tackle the challenges above and to have the leadership on on-device AI technology, this project,
+To tackle the challenges above and to have the leadership in on-device AI technology, this project,
 as the first step, aims at developing a neural network inference framework specialized and optimized
 for on-device AI.
index 06833df..64f5281 100644 (file)
@@ -1,17 +1,17 @@
 # Roadmap
 
-This document describes roadmap of **ONE** project.
+This document describes the roadmap of the **ONE** project.
 
-This project **ONE** aims at providing a high-performance, on-device neural network (NN) inference
+Project **ONE** aims at providing a high-performance, on-device neural network (NN) inference
 framework that performs inference of a given NN model on processors, such as CPU, GPU, DSP, or NPU, 
-in the target platform, such as Tizen, Android, and Ubuntu. 
+on the target platform, such as Tizen, Android and Ubuntu. 
 
 ## Progress
 
 Until last year, we already saw significant gains in accelerating with a single CPU or GPU backend.
 We have seen better performance improvements, not only when using a single backend, but even when
-mixing CPUs or GPUs considering the characteristics of individual operations. It could give us an
-opportunity to have a high degree of freedom in terms of operator coverage, and possibly provide
+mixing CPUs or GPUs, considering the characteristics of individual operations. It could give us an
+opportunity to have a high degree of freedom in terms of operator coverage and possibly provide
 better performance compared to single backend acceleration.
 
 On the other hand, we introduced the compiler as a front-end. This will support a variety of deep
@@ -27,7 +27,7 @@ model. From this year, now we start working on the voice model. The runtime requ
 voice model will be different from those of the vision model. There will be new requirements that
 we do not recognize yet, along with some already recognized elements such as control flow and
 dynamic tensor. In addition, recent studies on voice models require efficient support for specific
-architectures such as attention, transformer, and BERT. Also, depending on the characteristics of
+architectures such as attention, transformer and BERT. Also, depending on the characteristics of
 most voice models with large memory bandwidth, we will have to put more effort into optimizing the
 memory bandwidth at runtime.
 
@@ -44,7 +44,7 @@ memory bandwidth at runtime.
   + Completion and application of _circle2circle_ pass
     - _circle-quantizer_ for UINT8 and INT16
     - _circle-optimizer_
-  + Grphical _circle_ model viewer
+  + Graphical _circle_ model viewer
 
 ## Milestones
 
@@ -52,7 +52,7 @@ memory bandwidth at runtime.
 
 ## Workgroups (WGs)
 
-- We organize WGs for major topics, and each WG will be working on its own major topic by breaking
-  it into small tasks/issues, performing them inside WG, and collaborating between WGs.
+- We organize WGs for major topics and each WG will be working on its own major topic by breaking
+  it into small tasks/issues, performing them inside WG and collaborating between WGs.
 - The WG information can be found [here](workgroup.md).
 
diff --git a/docs/release/1.26/index.rst b/docs/release/1.26/index.rst
new file mode 100644 (file)
index 0000000..e39a253
--- /dev/null
@@ -0,0 +1,13 @@
+.. ONE documentation master file, created by
+   sphinx-quickstart on Thu Dec 19 14:10:15 2023.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+1.26
+====
+
+.. toctree::
+   :maxdepth: 2
+   :caption: Contents:
+
+  ./release-note-1.26.0.md
diff --git a/docs/release/1.26/release-note-1.26.0.md b/docs/release/1.26/release-note-1.26.0.md
new file mode 100644 (file)
index 0000000..8749143
--- /dev/null
@@ -0,0 +1,15 @@
+# Release Note 1.26.0
+
+## ONE Compiler
+
+- Support more Op(s): HardSwish, CumSum, BroadcastTo
+- Support more optimization option(s): `decompose_softmax`, `decompose_hardswish`, `fuse_slice_with_tconv`,
+    `fuse_mul_with_conv`, `remove_unnecessary_add`, `fuse_horizontal_fc_layers`, `common_subexpression_elimination`,
+    `remove_unnecessary_transpose`
+- _one-quantize_ supports more option
+  - Requantization option to convert TF2-quantized int8 model to uint8 model (--requantize)
+  - A new option to automatically find mixed-precision configuration (--ampq)
+  - A new option to save calibrated min/max values (--save_min_max)
+  - Add new parameters for moving average calibration (--moving_avg_batch, --moving_avg_const)
+- Introduce _q-implant_ that writes quantization parameters and weights into the circle model
+- Introduce _minmax-embedder_ that embeds min/max values into the circle model
diff --git a/docs/release/1.27/index.rst b/docs/release/1.27/index.rst
new file mode 100644 (file)
index 0000000..cf43202
--- /dev/null
@@ -0,0 +1,15 @@
+.. ONE documentation master file, created by
+   sphinx-quickstart on Thu Jun 19 09:10:15 2024.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+1.27
+====
+
+.. toctree::
+   :maxdepth: 2
+   :caption: Contents:
+
+  ./release-note-1.27.0.md
+  ./release-note-1.27.1.md
+  ./release-note-1.27.2.md
diff --git a/docs/release/1.27/release-note-1.27.0.md b/docs/release/1.27/release-note-1.27.0.md
new file mode 100644 (file)
index 0000000..9377e0b
--- /dev/null
@@ -0,0 +1,12 @@
+# Release Note 1.27.0
+
+## ONE Compiler
+
+- Support more Op(s): CircleGRU, CircleRelu0To1
+- Support more optimization option(s): `resolve_former_customop`, `--forward_transpose_op`, 
+    `fold_shape`, `remove_gather_guard`, `fuse_add_with_conv`, `fold_squeeze`, `fuse_rsqrt`
+- Support INT4, UINT4 data types
+- Support 4bit quantization of ONNX fake quantize model
+- Introduce global configuration target feature
+- Introduce command schema feature
+- Use C++17
diff --git a/docs/release/1.27/release-note-1.27.1.md b/docs/release/1.27/release-note-1.27.1.md
new file mode 100644 (file)
index 0000000..20e3464
--- /dev/null
@@ -0,0 +1,6 @@
+# Release Note 1.27.1
+
+## ONE Compiler
+
+- Command schema supports multiple names.
+- Fix invalid warning on boolean type option in _onecc_.
diff --git a/docs/release/1.27/release-note-1.27.2.md b/docs/release/1.27/release-note-1.27.2.md
new file mode 100644 (file)
index 0000000..661d5c2
--- /dev/null
@@ -0,0 +1,6 @@
+# Release Note 1.27.2
+
+## ONE Compiler
+
+- Support target option with command args in `one-profile`, `one-codegen`.
+- Update man pages of `one-cmds` tools.
diff --git a/docs/release/1.28/index.rst b/docs/release/1.28/index.rst
new file mode 100644 (file)
index 0000000..cc92efe
--- /dev/null
@@ -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.28
+====
+
+.. toctree::
+   :maxdepth: 2
+   :caption: Contents:
+
+  ./release-note-1.28.0.md
diff --git a/docs/release/1.28/release-note_1.28.0.md b/docs/release/1.28/release-note_1.28.0.md
new file mode 100644 (file)
index 0000000..adabcf6
--- /dev/null
@@ -0,0 +1,43 @@
+# Release Note 1.28.0
+
+## ONE Runtime
+
+### Python API
+
+- Support experimental python API
+  - Refer howto document for more details
+
+### On-device Training
+
+- Support on-device training with circle model
+  - Training parameter can be passed to _onert_ via _onert_`s experimental API or loading new model format including training information: _circle_plus_
+  - Trained model can be exported to _circle_ model via experimental API `nnfw_train_export_circle`
+  - Supporting Transfer learning from a pre-trained circle model
+- Introduce _circle_plus_gen_ tool
+  - Generates a _circle_plus_ model file with a given training hyperparameters
+  - Shows a _circle_plus model details
+
+### Runtime configuration API
+- _onert_ supports runtime configuration API for prepare and execution phase via experimental APIs
+  - `nnfw_set_prepare_config` sets configuration for prepare phase, and `nnfw_reset_prepare_config` resets it to default value
+  - `nnfw_set_execution_config` sets configuration for execution phase, and `nnfw_reset_execution_config` resets it to default value
+  - Supporting prepare phase configuration: prepare execution time profile
+  - Supporting execution phase configuration: dump minmax data, dump execution trace, dump execution time
+- Introduce new API to set _onert_ workspace directory: `nnfw_set_workspace`
+  - _onert_ workspace directory is used to store intermediate files during prepare and execution phase
+
+### Minmax Recorder
+- Now _onert_'s minmax recorder dumps raw file format instead of HDF5 format
+- _onert_ dumps minmax data into workspace directory
+
+### On-device Compilation
+- _onert_ supports full quantization of uint8/int16 type weight and activation.
+  - To quantize activation, _onert_ requires minmax data of activation.
+- _onert_ supports on-device code generation for special backend requiring special binary format such as DSP, NPU.
+  - Introduce new experimental API for code generation: `nnfw_codegen`
+
+### Type-aware model I/O usage
+- If loaded model is quantized model, _onert_ allows float type I/O buffer
+  - _onert_ converts float type input buffer to quantized type internally
+  - _onert_ fills float type output buffers by converting quantized type output data to float type internally
+- On multimodel package, _onert_ allows edges between quantized model and float type model
diff --git a/docs/release/onert-micro/2.0/release-note-2.0.0-pre.md b/docs/release/onert-micro/2.0/release-note-2.0.0-pre.md
new file mode 100644 (file)
index 0000000..cca0382
--- /dev/null
@@ -0,0 +1,14 @@
+## Release Notes for onert-micro 2.0.0-pre 
+
+### Overall Structure Refactored
+
+- c++ api has been changed : [onert-micro c++ api](https://github.com/samsung/ONE/blob/master/onert-micro/onert-micro/include/OMInterpreter.h)
+- 60 ops supported : Abs, Add, AddN, AveragePool2D, ArgMax, ArgMin, Concatenation, BatchToSpaceD, Cos, Div, DepthwiseCov2D, Dequatize, FullyCoected, Cov2D, Logistic, Log, Gather, GatherD, Exp, Greater, GreaterEqual, ExpadDims, Equal, Floor, FloorDiv, FloorMod, Pad, Reshape, ReLU, ReLU6, Roud, Less, L2ormalize, L2Pool2D, LessEqual, LeakyReLU, LogSoftmax, Mul, Maximum, MaxPool2D, Miimum, otEqual, Si, SquaredDifferece, Slice, Sub, Split, SpaceToBatchD, StridedSlice, Square, Sqrt, SpaceToDepth, Tah, Traspose, TrasposeCov, Softmax, While, Rsqrt, Upack
+
+### onert-micro supports on-device training feature
+
+- Trainable Operations : 5 operations ( Conv2D, FullyConnected, MaxPool2D, Reshape, Softmax )
+- Loss : MSE, Categorical Cross Entropy
+- Optimizer : ADAM, SGD
+- C api for training feature : [onert-micro c api header](https://github.com/samsung/ONE/blob/master/onert-micro/onert-micro/include/onert-micro.h)
+- limitation : For now, you can train topologically linear model
index 54ef870..cc0cb6b 100644 (file)
@@ -4,13 +4,13 @@ Backend API is defined by One Runtime. It is about actual computation of operati
 
 ## How backends are loaded
 
-When a backend ID is given to a session, the compiler module tries to load `libbackend_{BACKEND_ID}.so`. If it is successful, the runtime looks up for C API functions in it, and make use of those.
+When a backend ID is given to a session, the compiler module tries to load `libbackend_{BACKEND_ID}.so`. If it is successful, the runtime looks up for C API functions in it and makes use of those.
 
 ## C and C++ API
 
 ### C API
 
-We have 2 C API functions which are used as the entrypoint and the exitpoint. Here are the definitions of those.
+We have two C API functions which are used as the entrypoint and the exitpoint. Here are the definitions of those.
 
 ```c
 onert::backend::Backend *onert_backend_create();
@@ -23,16 +23,16 @@ What they do is creating a C++ object and destroying it, respectively. These two
 
 > **NOTE** C++ API is subject to change so it may change in every release
 
-C API above is just an entrypoint and it delegates core stuff to C++ API.
+C API above is just an entrypoint and it delegates core stuff to the C++ API.
 
-Here are major classes are described below. One must implement these classes(and some more classes) to create a backend.
+Major classes are described below. One must implement these classes (and some more classes) to create a backend.
 
-- `Backend` : Responsible to create a backend context which is a set of backend components
-- `BackendContext` : Holds data for the current session and also responsible to create tensor objects and kernels
-  - `BackendContext::genTensors` : Create tensor objects
-  - `BackendContext::genKernels` : Create kernels
-- `IConfig` : Configurations and miscellaneous stuff (not session based, global)
-- `ITensorRegistry` : A set of tensor(`ITensor`) objects that are used by the current backend
+- `Backend` : Responsible for creating a backend context which is a set of backend components
+- `BackendContext` : Holds data for the current session and also responsible for creation of tensor objects and kernels
+  - `BackendContext::genTensors` : Creates tensor objects
+  - `BackendContext::genKernels` : Creates kernels
+- `IConfig` : Configurations and miscellaneous stuff (global, not session based)
+- `ITensorRegistry` : A set of tensor (`ITensor`) objects that are used by the current backend
 
 Please refer to each class document for details. You may refer to [Bundle Backends](#bundle-backends) for actual implementation samples.
 
@@ -42,24 +42,24 @@ We provide some backends along with the runtime. There is the special backend `b
 
 ## `builtin` Backend
 
-`builtin` is a special backend that is always loaded(statically linked, part of runtime core). It is implemented just like other backends, but there are some things that it does exclusively.
+`builtin` is a special backend that is always loaded (statically linked, part of runtime core). It is implemented just like other backends, but there are some things that it does exclusively.
 
-- Has kernels for If, While and Permute operations (Kernels from other backends are never be used)
+- Has kernels for If, While and Permute operations (Kernels from other backends are never used)
 - The runtime core directly creates `builtin`'s tensor objects to accept user-given input and output buffers
-- The runtime core gives the executor context to `builtin` backend which allows control flow ops can change execution flow properly
+- The runtime core gives the executor a context to `builtin` backend which lets control flow ops properly change the execution flow
 
 ## Bundle Backends
 
-Without actual implmentation of backends, we cannot run any models. So we provide 3 bundle backends which support dozens of operations.
+Without actual implementation of backends, we cannot run any model. So we provide 3 bundle backends which support dozens of operations.
 
 ### cpu
 
-This backend is written in C++ and all the computation is done with CPU only.
+This backend is written in C++ and all the computation is done exclusively on a CPU.
 
 ### acl_neon
 
-`acl_neon` is a backend that is an adaptation layer of [ARM ComputeLibrary](https://github.com/ARM-software/ComputeLibrary) NE(NEON) part. So it basically only uses CPU too, but worksonly on ARM.
+`acl_neon` is a backend that is an adaptation layer of [ARM ComputeLibrary](https://github.com/ARM-software/ComputeLibrary) NE (NEON) part. So it's CPU-only and restricted to ARM.
 
 ### acl_cl
 
-`acl_cl` is a backend that is an adaptation layer of [ARM ComputeLibrary](https://github.com/ARM-software/ComputeLibrary) CL(OpenCL) part. OpenCL support(`libOpenCL.so`) is also necessary in the running environment to be able to use this backend. Also, it works only on ARM.
+`acl_cl` is a backend that is an adaptation layer of [ARM ComputeLibrary](https://github.com/ARM-software/ComputeLibrary) CL (OpenCL) part. OpenCL support (`libOpenCL.so`) is also necessary in the running environment to be able to use this backend. Also, it works only on ARM.
index 857a589..8427fa9 100644 (file)
@@ -10,4 +10,4 @@ The code structure looks just like ComputeLibrary's. Some of the code could be c
 
 ## cker
 
-"cker" stands for Cpu KERnel. It is a port of Tensorflow lite's operation kernels and possibly there are some own code. It is used by `cpu` backend.
+"cker" stands for Cpu KERnel. It is a port of Tensorflow lite's operation kernels with some additions. It is used by the `cpu` backend.
index 8c456b2..527e358 100644 (file)
@@ -1,22 +1,22 @@
 # Controlflow Operations
 
-We call `If` and `While` operations "Controlflow operations". These operations are different from the others. They are not for computing data, they are used to invoke another subgraph and return back which is to make conditional/iterations work in dataflow models.
+We call the `If` and `While` operations "Controlflow operations". These operations are special. Instead of computing data, they are used to invoke another subgraph and return back which constitutes conditional/iterations work in dataflow models.
 
 ## Defining controlflow operations
 
-As we use Tensorflow Lite schema(or Circle which is based on TF Lite), the runtime follows the way TF Lite does. The details are stated in [Control Flow in TensorFlow Lite](https://github.com/tensorflow/community/blob/master/rfcs/20190315-tflite-control-flow.md) RFC document.
+As we use Tensorflow Lite schema (or Circle which is based on TF Lite), the runtime follows the way TF Lite does. The details are stated in the [Control Flow in TensorFlow Lite](https://github.com/tensorflow/community/blob/master/rfcs/20190315-tflite-control-flow.md) RFC document.
 
-Controlflow operations from NN API is not yet supported. But we expect that it can be enabled in the similar way.
+Controlflow operations from NN API are not yet supported. But we expect that they can be enabled in a similar way.
 
 ## Implementation
 
 ### Graph representation
 
-`onert` internally has its representation for controlflow operations and subgraphs. It is pretty much straightforward as it is pretty much isomorphic with the schema. The `onert`'s in-memory model contains multiple subgraphs and the controlflow operations have same parameters(subgraph indices) just like TF Lite schema has.
+`onert` internally has its representation for controlflow operations and subgraphs. It is straightforward as it is pretty much isomorphic with the schema. The `onert`'s in-memory model contains multiple subgraphs and the controlflow operations have same parameters (subgraph indices), just like TF Lite schema has.
 
 ### Execution
 
-`controlflow` backend is a built-in backend to support these controlflow operations. This backend is special as it has access to `onert` core's executor manager(`ExecutorMap`) so it can invoke/return a subgraph. This backend has implementation for `If` and `While` operation and they make use of the access to executor manager.
+The `controlflow` backend is a built-in backend to support these controlflow operations. This backend is special as it has access to `onert` core's executor manager (`ExecutorMap`) so it can invoke/return a subgraph. This backend has implementations for `If` and `While` operations and they make use of the access to executor manager.
 
 An `Executor` has two different ways to execute depending on if it is the initial execution or invoking a subgraph from a controlflow operation.
 
@@ -28,13 +28,13 @@ An `Executor` has two different ways to execute depending on if it is the initia
 
 #### Kernel Implementation
 
-Here is brief explanation what the kernels do, which is quoted from [Control Flow in TensorFlow Lite](https://github.com/tensorflow/community/blob/master/rfcs/20190315-tflite-control-flow.md).
+Here is brief explanation what the kernels do, which is quoted from [Control Flow in TensorFlow Lite](https://github.com/tensorflow/community/blob/master/rfcs/20190315-tflite-control-flow.md).
 
 > * `If` : Check the condition input and invoke one of the 2 subgraphs.
 > * `While` :
->     * Invoke the condition subgraph. Break out the loop if result is false.
+>     * Invoke the condition subgraph. Break out the loop if the result is false.
 >     * Invoke the body subgraph, use the output as the input of the next iteration.
 
 Invoking a subgraph needs to pass the operation's inputs to the subgraph inputs. And Returning back needs to pass the subgraph outputs to the operation outputs.
 
-When invoking a subgraph and returning back, the current kernel implementation performs literally copy all the subgraph inputs and outputs. This is going to be optimized to minimize redundant copies.
+When invoking a subgraph and returning back, the current kernel implementation makes a copy of all the subgraph inputs and outputs. This is going to be optimized to minimize redundant copies.
index 64a6c62..d9936fd 100644 (file)
@@ -66,21 +66,21 @@ Let's say we have some functions written in a certain programming language. Then
 
 #### 5. Create Executor
 
-With generated tensors and kernels, the compiler creates executor objects. There are 3 types of executors are supported - Linear, Dataflow, and Parallel. Linear executor is the default executor and Dataflow Executor and Parallel Executor are experimental.
+With generated tensors and kernels, the compiler creates executor objects. There are 3 types of executors: Linear, Dataflow, and Parallel. Linear executor is the default executor and Dataflow Executor and Parallel Executor are experimental.
 
-For more about executors, please refer to [Executors](executors.md) document.
+For more about executors, please refer to the [Executors](executors.md) document.
 
 ### Module `exec`
 
-`exec` stands for 'execution'. As a result of the compilation, `Execution` class is created. This class manages the actual execution of the model inference. Here is a typical usage of using this class.
+`exec` stands for 'execution'. As a result of the compilation, `Execution` class is created. This class manages the actual execution of the model inference. Here is a typical usage of this class.
 
 1. Resize input size if needed
 2. Provide input and output buffers
-3. Run the inference in either synchronous/asynchronous mode
+3. Run the inference in either synchronous or asynchronous mode
 4. Check out the results which are stored in output buffers provided earlier
 
 ### Module `backend`
 
-Backends are plugins and they are loaded dynamically(via `dlopen`). So this module is a set of interface classes for backend implementation. `compiler` can compile with a variety of backends without knowing specific backend implementation.
+Backends are plugins and they are loaded dynamically (via `dlopen`). So this module is a set of interface classes for backend implementation. `compiler` can compile with a variety of backends without knowing specific backend implementation.
 
-Backend interface classes are mostly about memory management and kernel generation. For more, please refer to [Backend API](backend-api.md) document.
+Backend interface classes are mostly about memory management and kernel generation. For more, please refer to the [Backend API](backend-api.md) document.
index c777e0c..0d57d7d 100644 (file)
@@ -1,10 +1,10 @@
 # Executors
 
-Executor(`IExecutor`) is a execution engine of a subgraph that can execute inference for the subgraph. It is the result of `Subgraph` compilation. If we would compare it with most of common programming language tools, it is just like an interpreter with code to execute.
+Executor (`IExecutor`) is an execution engine of a subgraph that can execute inference for the subgraph. It is the result of a `Subgraph` compilation. Compared to common programming language tools, it is like an interpreter with code to execute.
 
 ## Understanding models
 
-We can think of a NNPackage model as a set of tasks with dependencies. In other words, it is a form of [DAG](https://en.wikipedia.org/wiki/Directed_acyclic_graph)(more precisely, it is a set of DAGs as we need multiple subgraphs to support control flow operations). And that is exactly the same concept with [Dataflow programming](https://en.wikipedia.org/wiki/Dataflow_programming).
+We can think of an NNPackage model as a set of tasks with dependencies. In other words, it is a form of [DAG](https://en.wikipedia.org/wiki/Directed_acyclic_graph) (more precisely, it is a set of DAGs, as we need multiple subgraphs to support control flow operations). And that is exactly the same concept with [Dataflow programming](https://en.wikipedia.org/wiki/Dataflow_programming).
 
 That is, there are some input tensors that must be ready to run a operation. And the execution must be done in topological order. Here's the workflow for execution.
 
@@ -15,20 +15,20 @@ That is, there are some input tensors that must be ready to run a operation. And
 5. Check if there are some operations ready
     1. If yes, Go to 3
     2. Otherwise, Finish execution
-6. User uses data of model output tensors
+6. User consumes data of model output tensors
 
-We have 3 different types of executors in our codebase and they all are based on the explation above. However only `LinearExecutor` is official and the other two are experimental.
+We have 3 different types of executors in our codebase and they all are based on the above explanation. However, only `LinearExecutor` is official and the other two are experimental.
 
 ## Linear Executor
 
-`LinearExecutor` is the main executor. As we know the model to run and the model graph does not change at runtime, we do not have to do step 3-5 above at runtime. During the compilation for Linear Executor, it sorts operations in topological order so we can just execute in that fixed order which means that it cannot perform the operations in parallel.
+`LinearExecutor` is the main executor. As we know the model to run and the model graph does not change at runtime, we do not need to do the above steps 3-5 at runtime. During the compilation for Linear Executor, it sorts operations in topological order so we can just execute in that fixed order which means that it cannot perform the operations in parallel.
 
 If the tensors are static, it also can analyze the lifetimes of the tensors and pre-allocate tensor memory with reusing memory between the tensors whose lifetimes do not overlap.
 
 ## Dataflow Executor (experimental)
 
-Unlike `LinearExecutor`, `DataflowExecutor` does step 3-5 at runtime. By doing it we can know which operations are available at a specific point. However this executor still executes the operations one at a time. Just choose any operation that is ready then execute. And wait for it to finish then repeat that. So there may be no advantage compared to `LinearExecutor` but `DataflowExecutor` is the parent class of `ParallelExecutor`. And `DataflowExecutor` can be used for profiling executions for the heterogeneous scheduler.
+Unlike `LinearExecutor`, `DataflowExecutor` does steps 3-5 at runtime. By doing it we can know which operations are available at a specific point. However this executor still executes the operations one at a time. Just choose any operation that is ready then execute, wait for it to finish then repeat. So there may be no advantage compared to `LinearExecutor` but `DataflowExecutor` is the parent class of `ParallelExecutor`. And `DataflowExecutor` can be used for profiling executions for the heterogeneous scheduler.
 
 ## Parallel Executor (experimental)
 
-Just like `DataflowExecutor`, `ParallelExecutor` does step 3-5 at runtime. One big difference is that it creates a `ThreadPool` for each backend for parallel execution(`ThreadPool` is supposed to have multiple threads, however for now, it can have only one thread). As we know that there may be multiple operations ready to execute, and those can be executed in different backends at the same time which could lead some performance gain.
+Just like `DataflowExecutor`, `ParallelExecutor` does steps 3-5 at runtime. One big difference is that it creates a `ThreadPool` for each backend for parallel execution (`ThreadPool` is supposed to have multiple threads, however for now, it can have only one thread). Multiple operations ready to execute can be executed in different backends at the same time, which could lead to some performance gain.
index e7a5e27..bcef6ba 100644 (file)
@@ -1,8 +1,8 @@
 # Heterogeneous Execution
 
-A big feature of ONE Runtime is that it can perform inference for a neural network model with different backends(computation libraries). This is called "Heterogenous Execution".
+A major feature of ONE Runtime is that it can perform inference for a neural network model with different backends (computation libraries). This is called "Heterogenous Execution".
 
-A neural network model consists of operations and each operation can be computed by a variety of backends. Then we can choose the faster one for that operation for computation. Let's say we have a model that has two operations in sequence.
+A neural network model consists of operations and each operation can be computed by a variety of backends. Then we can choose the faster one for a given computation. Let's say we have a model that has two operations in sequence.
 
 ![Add-Conv model](heterogeneous-execution-add-conv-model.png)
 
@@ -12,11 +12,11 @@ Here is another case. Let's say we have a model that is not sequential so there
 
 ![Add-3Conv model](heterogeneous-execution-add-3-conv-model.png)
 
-Say we have 3 backends that are based on CPU, GPU and NPU(Neural Processing Unit) respectively. After executing Add, 3 Conv2D operations are ready to run. We may utilize those backends with [Parallel Executor (experimental)](executors.md#parallel-executor-experimental). For this case we may get performance gain regardless of kernels' speed as those are run in parallel independently.
+Say we have 3 backends that are based on CPU, GPU and NPU (Neural Processing Unit) respectively. After executing Add, 3 Conv2D operations are ready to run. We may utilize those backends with [Parallel Executor (experimental)](executors.md#parallel-executor-experimental). For this case we may get performance gain regardless of kernels' speed as those are run in parallel independently.
 
 ## Graph Transformation
 
-Unfortunately it is not that simple to get performance gain. As each backend has its own memory management module, a copy must be done between backend boundaries. Plus, it may require layout changes so "Permute" operations are added from  `PermutationInsertionPass`. This process is done from [Lowering](core.md#1-lowering) phase of compilation.
+Unfortunately, it is not that simple to get a performance gain. As each backend has its own memory management module, a copy must be done between backend boundaries. Plus, it may require layout changes so "Permute" operations are added from  `PermutationInsertionPass`. This process is done from the [Lowering](core.md#1-lowering) phase of compilation.
 
 Here is an example of that. Let's say we have assigned different backends for Add and Conv2D. So a Permute operation is inserted between them.
 
@@ -30,6 +30,6 @@ Sometime later, we are going to introduce a concept of compatible backends and t
 
 Now we know that it could be useful to have a lot of backends, but one might wonder how we can schedule backends effectively. When a model is large, it is not trivial to do it manually by a user.
 
-There is a [profiling-based automatic scheduler](/runtime/onert/core/src/compiler/HEScheduler.h)(experimental). It first runs every operation in sequence with every backend it has. And it records the duration of the execution for each. Then that data can be used to schedule. The scheduler assigns backends according to a certain algorithm with the given data. And the user can execute it with Parallel Scheduler.
+There is a [profiling-based automatic scheduler](/runtime/onert/core/src/compiler/HEScheduler.h) (experimental). It first runs every operation in sequence with every backend it has. And it records the duration of the execution for each. Then that data can be used to schedule. The scheduler assigns backends according to a certain algorithm with the given data. And the user can execute it with Parallel Scheduler.
 
 There were actually some performance gain with the model Inception V3 and two backends - acl_neon(GPU) and acl_cl(GPU). Note that this model contains operations that can be run at the same time.
diff --git a/docs/runtime/transfer_learning.md b/docs/runtime/transfer_learning.md
new file mode 100644 (file)
index 0000000..fffec51
--- /dev/null
@@ -0,0 +1,197 @@
+# Transfer Learning
+
+Let's classify dogs and cats using the pre-trained model. It will be `mobilenet v2` in our case.
+
+## Preparing dataset
+The first step is conversion dataset (input data and expected outputs) to the binary format accepted by `ONE`. Note, that for many cases it can be achieved via [tf_dataset_converter](https://github.com/Samsung/ONE/tree/master/tools/generate_datafile/tf_dataset_converter).
+
+```python
+import os
+import tensorflow as tf
+import pathlib
+import numpy as np
+
+_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'
+path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=_URL, extract=True)
+PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered')
+
+train_dir = os.path.join(PATH, 'train')
+validation_dir = os.path.join(PATH, 'validation')
+
+BATCH_SIZE = 32
+IMG_SIZE = (160, 160)
+
+def label_to_array(label):
+    arr = np.zeros(2, dtype=float)
+    arr[label] = 1.
+    tensor = tf.convert_to_tensor(arr, tf.float32)
+    return tensor
+
+train_dataset = tf.keras.preprocessing.image_dataset_from_directory(train_dir,
+                                                            shuffle=True,
+                                                            batch_size=BATCH_SIZE,
+                                                            image_size=IMG_SIZE)
+
+current_dir = pathlib.Path(__file__).parent
+with open(current_dir/'cats_and_dogs.input.bin', 'wb') as in_stream:
+    with open(current_dir/'cats_and_dogs.output.bin', 'wb') as out_stream:
+        for image,label in train_dataset:
+            in_stream.write(image.numpy().astype(np.float32).tobytes())
+            out_stream.write(label.numpy().astype(np.float32).tobytes())
+```
+
+## Prepare model for fine-tuning
+The first step to align the model to our problem is inserting custom operations on the top of the model. The base (with unchanged weights) remains the same.
+
+```python
+import tensorflow as tf
+import numpy as np
+
+BATCH_SIZE = 32
+IMG_SIZE = (160, 160)
+IMG_SHAPE = IMG_SIZE + (3,)
+
+base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
+                                               include_top=False,
+                                               weights='imagenet')
+
+base_model.trainable = False
+image_batch = tf.zeros([32, 160, 160, 3])
+feature_batch = base_model(image_batch)
+
+# define custom classification layers
+global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
+prediction_layer = tf.keras.layers.Dense(1, activation='relu')
+
+# applying preprocessing
+preprocess_input = tf.keras.applications.mobilenet_v2.preprocess_input
+
+inputs = tf.keras.Input(shape=(160, 160, 3))
+x = preprocess_input(inputs)
+x = base_model(x, training=False)
+
+# add additional layers on the top
+x = global_average_layer(x)
+outputs = prediction_layer(x)
+model = tf.keras.Model(inputs, outputs)
+
+# Convert to tflite
+converter = tf.lite.TFLiteConverter.from_keras_model(model)
+tflite_model = converter.convert()
+
+# Save tflite model model.
+with open('customized_mobilenetv2.tflite', 'wb') as f:
+  f.write(tflite_model)
+```
+For more information about feature extraction and fine tuning, please refer to [transfer learning tutorial](https://www.tensorflow.org/tutorials/images/transfer_learning).
+
+## Convert tflite model to circle model
+In the moment of writing, the `circle+` format is developed but it will the other possibility to handle model training.
+Note that `one-import` can be found in the installation directory (determined by `-DCMAKE_INSTALL_PREFIX` cmake flag which can be added to `./nnfw configure` command).
+```bash
+one-import tflite -i customized_mobilenetv2.tflite -o customized_mobilenetv2.circle
+```
+
+## Run training
+Let's train the model using `onert_train`. In this case we want to test only 2 last layers: `Mean` and `FullyConnected` (created from `GlobalAveragePooling2D` and `Dense` in TensorFlow). Note that the other possibility is using `circle+` capabilities.
+The crucial here is proper choosing value of `num_of_trainable_ops` to achieve tradeoff between training time and accuracy. It determines how many operations from the back of the graph will be trained. In our case, these are additionally added `Dense` with `Relu` activation, `GlobalAveragePooling` and some previous operations.
+
+```bash
+onert_train \
+--modelfile customized_mobilenetv2.circle \
+--epoch 5 \
+--loss 1 \                # mean squared error
+--loss_reduction_type 1 \ # sum over batch size
+--optimizer 2 \           # adam
+--learning_rate 0.0001 \
+--batch_size 32 \
+--num_of_trainable_ops 5 \
+--load_expected:raw cats_and_dogs.output.bin \
+--load_input:raw cats_and_dogs.input.bin \
+--export_path customized_mobilenetv2_trained.circle
+```
+The result of training:
+```
+Model Expected Filename cats_and_dogs.output.bin
+Model Input Filename cats_and_dogs.input.bin
+Model Filename customized_mobilenetv2.circle
+== training parameter ==
+- learning_rate        = 0.0001
+- batch_size           = 32
+- loss_info            = {loss = mean squared error, reduction = sum over batch size}
+- optimizer            = adam
+- num_of_trainable_ops = 10
+========================
+Epoch 1/5 - time: 532.378ms/step - loss: [0] 0.1567
+Epoch 2/5 - time: 531.966ms/step - loss: [0] 0.0417
+Epoch 3/5 - time: 532.795ms/step - loss: [0] 0.0104
+Epoch 4/5 - time: 532.607ms/step - loss: [0] 0.0053
+Epoch 5/5 - time: 532.567ms/step - loss: [0] 0.0049
+===================================
+MODEL_LOAD   takes 4.3720 ms
+PREPARE      takes 192.9690 ms
+EXECUTE      takes 165537.7600 ms
+- Epoch 1      takes 33007.4380 ms
+- Epoch 2      takes 32981.8970 ms
+- Epoch 3      takes 33033.2690 ms
+- Epoch 4      takes 33021.6380 ms
+- Epoch 5      takes 33019.1300 ms
+===================================
+```
+## Test inference
+In this tutorial the inference will be launched via `Python API`.
+### Convert the trained model to nnpackage format
+The current version of `Python API` expect models in Python `nnpackge` format. The conversion can be done with `tools/nnpackage_tool/model2nnpkg/model2nnpkg.py` script.
+```bash
+python model2nnpkg.py -m customized_mobilenetv2_trained.circle -o mobilenet_package_dir
+```
+### Run inference via Python API
+PRE: Install `nnfwapi` package
+```
+pip install -i https://test.pypi.org/simple/ nnfwapi==0.1.1
+```
+```python
+from nnfwapi.libnnfw_api_pybind import *
+
+import matplotlib.pyplot as plt
+import os
+import tensorflow as tf
+
+nnpackage_path = '{mobilenet_package_dir}/customized_mobilenetv2_trained'
+session = nnfw_session(nnpackage_path, 'cpu')
+
+_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'
+path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=_URL, extract=True)
+PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered')
+
+validation_dir = os.path.join(PATH, 'validation')
+
+BATCH_SIZE = 1 # we take only a single image per inference
+IMG_SIZE = (160, 160)
+
+validation_dataset = tf.keras.utils.image_dataset_from_directory(validation_dir,
+                                                                 shuffle=True,
+                                                                 batch_size=BATCH_SIZE,
+                                                                 image_size=IMG_SIZE)
+
+test_image,labels = next(x for x in validation_dataset)
+test_image = test_image.numpy()
+inputs = []
+inputs.append(test_image)
+input_size = session.input_size()
+
+session.set_inputs(input_size, inputs)
+outputs = session.inference()
+
+# Note that the last layer of our model is Relu (which means "0" value for cats detection)
+plt.title("dogs" if outputs[0] > 0.01 else "cats")
+plt.axis("off")
+plt.imshow(test_image.squeeze().astype("uint8"))
+plt.savefig('transfer_learning_result.png')
+```
+
+Example output<br/>
+![An example result of inference](transfer_learning_result.png)
+
+## References
+- [Transfer learning Tensorflow tutorial](https://www.tensorflow.org/tutorials/images/transfer_learning)
diff --git a/docs/runtime/transfer_learning_result.png b/docs/runtime/transfer_learning_result.png
new file mode 100644 (file)
index 0000000..2b990f2
Binary files /dev/null and b/docs/runtime/transfer_learning_result.png differ
diff --git a/infra/3rdparty/.gitignore b/infra/3rdparty/.gitignore
deleted file mode 100644 (file)
index c3d773e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-URL.local
diff --git a/infra/3rdparty/Eigen/fd6845384b86/URL.default b/infra/3rdparty/Eigen/fd6845384b86/URL.default
deleted file mode 100644 (file)
index 76b000a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-https://mirror.bazel.build/bitbucket.org/eigen/eigen/get/fd6845384b86.tar.gz
diff --git a/infra/3rdparty/Eigen/fd6845384b86/URL.info b/infra/3rdparty/Eigen/fd6845384b86/URL.info
deleted file mode 100644 (file)
index 8e7a3c2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-This URL originates from TensorFlow 1.12
-
-Please check https://github.com/tensorflow/tensorflow/blob/v1.12.0/tensorflow/workspace.bzl#L121
diff --git a/infra/buildtool/CMakeLists.txt b/infra/buildtool/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c6332b2
--- /dev/null
@@ -0,0 +1,57 @@
+cmake_minimum_required(VERSION 3.16.3)
+
+project(nnas_buildtool)
+
+set(NNAS_PROJECT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." CACHE
+  INTERNAL "Where to find nnas top-level source directory"
+)
+set(NNAS_EXTERNALS_DIR
+  "${NNAS_PROJECT_SOURCE_DIR}/externals" CACHE
+  INTERNAL "Where to download external dependencies"
+)
+
+if(NOT DEFINED BUILDTOOL_PATH)
+  message(FATAL_ERROR "BUILDTOOL_PATH is not defined")
+endif()
+
+macro(nnas_include PREFIX)
+  include("${NNAS_PROJECT_SOURCE_DIR}/infra/cmake/modules/${PREFIX}.cmake")
+endmacro(nnas_include)
+
+nnas_include(OptionTools)
+envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+# Sync with traditional external download tool: server login
+# TODO Migrate external download tool
+envoption(EXTERNAL_SERVER_USERPWD "")
+if(EXTERNAL_SERVER_USERPWD)
+  string(REGEX MATCH "^[^:]*" EXTERNAL_SERVER_USERNAME ${EXTERNAL_SERVER_USERPWD})
+  string(REGEX MATCH "[^:]*$" EXTERNAL_SERVER_PASSWORD ${EXTERNAL_SERVER_USERPWD})
+else()
+  envoption(EXTERNAL_SERVER_USERNAME "")
+  envoption(EXTERNAL_SERVER_PASSWORD "")
+endif()
+
+set(FLATBUFFERS_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/flatbuffers/archive/v23.5.26.tar.gz)
+
+# Download and build Flatbuffers 23.5.26
+include(ExternalProject)
+ExternalProject_Add(flatbuffers-23.5.26
+  URL ${FLATBUFFERS_URL}
+  HTTP_USERNAME ${EXTERNAL_SERVER_USERNAME}
+  HTTP_PASSWORD ${EXTERNAL_SERVER_PASSWORD}
+  PREFIX  ${CMAKE_CURRENT_BINARY_DIR}/flatbuffers
+  SOURCE_DIR  ${NNAS_EXTERNALS_DIR}/FLATBUFFERS-23.5.26
+  STAMP_DIR ${NNAS_EXTERNALS_DIR}/external-stamp
+  INSTALL_DIR ${BUILDTOOL_PATH}
+  CMAKE_ARGS  -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${BUILDTOOL_PATH}
+              -DFLATBUFFERS_BUILD_TESTS=OFF -DFLATBUFFERS_BUILD_FLATLIB=OFF -DFLATBUFFERS_BUILD_FLATHASH=OFF
+)
+
+# Sync with traditional external download tool - stamp
+# TODO Migrate external download tool
+nnas_include(StampTools)
+set(STAMP_PATH "${NNAS_EXTERNALS_DIR}/FLATBUFFERS-23.5.26.stamp")
+Stamp_Check(URL_CHECK "${STAMP_PATH}" "${FLATBUFFERS_URL}")
+if(NOT URL_CHECK)
+  file(WRITE "${STAMP_PATH}" "${FLATBUFFERS_URL}")
+endif(NOT URL_CHECK)
index 0240611..ebaaace 100644 (file)
@@ -45,6 +45,8 @@ elseif("${HOST_ARCH}" STREQUAL "aarch64")
   set(HOST_ARCH_BASE "aarch64")
 elseif("${HOST_ARCH}" STREQUAL "i686")
   set(HOST_ARCH_BASE "i686")
+elseif("${HOST_ARCH}" STREQUAL "riscv64")
+  set(HOST_ARCH_BASE "riscv64")
 else()
   message(FATAL_ERROR "'${HOST_ARCH}' architecture is not supported")
 endif()
@@ -65,6 +67,8 @@ elseif("${TARGET_ARCH}" STREQUAL "aarch64")
   set(TARGET_ARCH_BASE "aarch64")
 elseif("${TARGET_ARCH}" STREQUAL "i686")
   set(TARGET_ARCH_BASE "i686")
+elseif("${TARGET_ARCH}" STREQUAL "riscv64")
+  set(TARGET_ARCH_BASE "riscv64")
 else()
   message(FATAL_ERROR "'${TARGET_ARCH}' architecture is not supported")
 endif()
index 8d0c779..7d9a075 100644 (file)
@@ -7,13 +7,12 @@ function(_AbseilSource_import)
   nnas_include(ExternalSourceTools)
   nnas_include(OptionTools)
 
-  # NOTE GCC 13 requires abseil 20230125.3
+  # NOTE TensorFlow 2.16.1 downloads abseil from the following URL
   envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
-  envoption(ABSEIL_URL ${EXTERNAL_DOWNLOAD_SERVER}/abseil/abseil-cpp/archive/20230125.3.tar.gz)
+  envoption(ABSEIL_URL ${EXTERNAL_DOWNLOAD_SERVER}/abseil/abseil-cpp/archive/fb3621f4f897824c0dbe0615fa94543df6192f30.tar.gz)
   ExternalSource_Download(ABSEIL
     DIRNAME ABSEIL
-    URL ${ABSEIL_URL}
-    CHECKSUM MD5=9b6dae642c4bd92f007ab2c148bc0498)
+    URL ${ABSEIL_URL})
 
   set(AbseilSource_DIR ${ABSEIL_SOURCE_DIR} PARENT_SCOPE)
   set(AbseilSource_FOUND TRUE PARENT_SCOPE)
index 2477a48..e1559db 100644 (file)
@@ -9,7 +9,7 @@ function(_BoostSource_import)
 
   # EXTERNAL_DOWNLOAD_SERVER will be overwritten by CI server to use mirror server.
   envoption(EXTERNAL_DOWNLOAD_SERVER "http://sourceforge.net")
-  envoption(BOOST_URL ${EXTERNAL_DOWNLOAD_SERVER}/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.gz)
+  envoption(BOOST_URL ${EXTERNAL_DOWNLOAD_SERVER}/projects/boost/files/boost/1.84.0/boost_1_84_0.tar.gz)
   ExternalSource_Download(BOOST ${BOOST_URL})
 
   set(BoostSource_DIR ${BOOST_SOURCE_DIR} PARENT_SCOPE)
index b93a6a2..f555623 100644 (file)
@@ -8,8 +8,8 @@ function(_CpuInfoSource_import)
   nnas_include(OptionTools)
 
   envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
-  # CPUINFO commit from tflite v2.8
-  envoption(CPUINFO_URL ${EXTERNAL_DOWNLOAD_SERVER}/pytorch/cpuinfo/archive/5916273f79a21551890fd3d56fc5375a78d1598d.tar.gz)
+  # CPUINFO commit for RISC-V bug fix
+  envoption(CPUINFO_URL ${EXTERNAL_DOWNLOAD_SERVER}/pytorch/cpuinfo/archive/6543fec09b2f04ac4a666882998b534afc9c1349.tar.gz)
   ExternalSource_Download(CPUINFO
     DIRNAME CPUINFO
     URL ${CPUINFO_URL})
diff --git a/infra/cmake/packages/Eigen-fd6845384b86Config.cmake b/infra/cmake/packages/Eigen-fd6845384b86Config.cmake
deleted file mode 100644 (file)
index e98856a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-# NOTE TensorFlow 1.12 uses eigen commit ID fd6845384b86
-
-# find_package rejects version with commit number. Commit ID is appended to the package name
-# as a workaround.
-#
-# TODO Find a better way
-function(_Eigen_import)
-  nnas_find_package(EigenSource-fd6845384b86 QUIET)
-
-  if(NOT EigenSource-fd6845384b86_FOUND)
-    set(Eigen-fd6845384b86_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT EigenSource-fd6845384b86_FOUND)
-
-  if(NOT TARGET eigen-fd6845384b86)
-    add_library(eigen-fd6845384b86 INTERFACE)
-    target_include_directories(eigen-fd6845384b86 INTERFACE "${EigenSource_DIR}")
-    # Add EIGEN_MPL2_ONLY to remove license issue posibility
-    target_compile_definitions(eigen-fd6845384b86 INTERFACE EIGEN_MPL2_ONLY)
-  endif(NOT TARGET eigen-fd6845384b86)
-
-  set(Eigen-fd6845384b86_FOUND TRUE PARENT_SCOPE)
-endfunction(_Eigen_import)
-
-_Eigen_import()
diff --git a/infra/cmake/packages/EigenSource-fd6845384b86Config.cmake b/infra/cmake/packages/EigenSource-fd6845384b86Config.cmake
deleted file mode 100644 (file)
index 4a854e7..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-# find_package rejects version with commit number. Commit ID is appended to the package name
-# as a workaround.
-#
-# TODO Find a better way
-function(_import)
-  if(NOT DOWNLOAD_EIGEN)
-    set(EigenSource_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT DOWNLOAD_EIGEN)
-
-  nnas_include(ExternalSourceTools)
-  nnas_include(ThirdPartyTools)
-
-  # NOTE TensorFlow 1.12 downloads eigen from the following URL
-  ThirdParty_URL(EIGEN_URL PACKAGE Eigen VERSION fd6845384b86)
-
-  ExternalSource_Download(EIGEN
-    DIRNAME EIGEN-fd6845384b86
-    CHECKSUM MD5=4c884968ede816a84c70e2cd2c81de8d
-    ${EIGEN_URL}
-  )
-
-  set(EigenSource_DIR ${EIGEN_SOURCE_DIR} PARENT_SCOPE)
-  set(EigenSource-fd6845384b86_FOUND TRUE PARENT_SCOPE)
-endfunction(_import)
-
-_import()
index fa1867c..d81eef1 100644 (file)
@@ -7,13 +7,11 @@ function(_FarmhashSource_import)
   nnas_include(ExternalSourceTools)
   nnas_include(OptionTools)
 
-  # NOTE TensorFlow 1.12 downloads farmhash from the following URL
-  #      TensorFlow 1.13.1 downloads farmhash from the following URL
-  #      TensorFlow 2.3.0 downloads farmhash from the following URL
+  # NOTE TensorFlow 2.16.1 downloads farmhash from the following URL
   envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
-  envoption(FARMHASH_1_12_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/farmhash/archive/816a4ae622e964763ca0862d9dbd19324a1eaf45.tar.gz)
+  envoption(FARMHASH_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/farmhash/archive/0d859a811870d10f53a594927d0d0b97573ad06d.tar.gz)
 
-  ExternalSource_Download(FARMHASH ${FARMHASH_1_12_URL})
+  ExternalSource_Download(FARMHASH ${FARMHASH_URL})
 
   set(FarmhashSource_DIR ${FARMHASH_SOURCE_DIR} PARENT_SCOPE)
   set(FarmhashSource_FOUND TRUE PARENT_SCOPE)
index b7ae666..99db050 100644 (file)
@@ -1,6 +1,5 @@
-# TODO Remove other Flatbuffers versions
 function(_FlatBuffers_import)
-  find_package(Flatbuffers 2.0 QUIET)
+  find_package(Flatbuffers 2.0 EXACT QUIET PATHS ${EXT_OVERLAY_DIR}/FLATBUFFERS-2.0)
   set(FlatBuffers_FOUND ${Flatbuffers_FOUND} PARENT_SCOPE)
 endfunction(_FlatBuffers_import)
 
@@ -22,11 +21,14 @@ function(_FlatBuffers_build)
   if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0)
     set(ADDITIONAL_CXX_FLAGS "-Wno-error=class-memaccess")
   endif()
+  if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12.0)
+    set(ADDITIONAL_CXX_FLAGS "-Wno-error=stringop-overflow")
+  endif()
 
   nnas_include(ExternalBuildTools)
   ExternalBuild_CMake(CMAKE_DIR   ${FlatBuffersSource_DIR}
                       BUILD_DIR   ${CMAKE_BINARY_DIR}/externals/FLATBUFFERS-2.0/build
-                      INSTALL_DIR ${EXT_OVERLAY_DIR}
+                      INSTALL_DIR ${EXT_OVERLAY_DIR}/FLATBUFFERS-2.0
                       BUILD_FLAGS ${ADDITIONAL_CXX_FLAGS}
                       IDENTIFIER  "2.0"
                       EXTRA_OPTS  "-DFLATBUFFERS_BUILD_TESTS:BOOL=OFF"
@@ -44,7 +46,7 @@ _FlatBuffers_import()
 set(FLATC_PATH "$<TARGET_FILE:flatbuffers::flatc>")
 
 if(DEFINED ENV{BUILD_HOST_EXEC})
-  set(FLATC_PATH $ENV{BUILD_HOST_EXEC}/overlay/bin/flatc)
+  set(FLATC_PATH $ENV{BUILD_HOST_EXEC}/overlay/FLATBUFFERS-2.0/bin/flatc)
 endif(DEFINED ENV{BUILD_HOST_EXEC})
 if(DEFINED ENV{EXTERNAL_FLATC})
   set(FLATC_PATH $ENV{EXTERNAL_FLATC})
diff --git a/infra/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfig.cmake b/infra/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfig.cmake
new file mode 100644 (file)
index 0000000..d98882a
--- /dev/null
@@ -0,0 +1,135 @@
+# TODO Remove other Flatbuffers versions
+function(_FlatBuffers_import)
+  find_package(Flatbuffers 23.5.26 QUIET)
+  set(FlatBuffers_FOUND ${Flatbuffers_FOUND} PARENT_SCOPE)
+endfunction(_FlatBuffers_import)
+
+function(_FlatBuffers_build)
+  if(NOT BUILD_FLATBUFFERS)
+    message(STATUS "FlatBuffersConfig !BUILD_FLATBUFFERS")
+    return()
+  endif(NOT BUILD_FLATBUFFERS)
+
+  nnas_find_package(FlatBuffersSource EXACT 23.5.26 QUIET)
+
+  if(NOT FlatBuffersSource_FOUND)
+    # Source is not available
+    message(STATUS "FlatBuffersConfig !FlatBuffersSource_FOUND")
+    return()
+  endif(NOT FlatBuffersSource_FOUND)
+
+  set(ADDITIONAL_CXX_FLAGS "")
+  if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0)
+    set(ADDITIONAL_CXX_FLAGS "-Wno-error=class-memaccess")
+  endif()
+  if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 12.0)
+    set(ADDITIONAL_CXX_FLAGS "-Wno-error=stringop-overflow")
+  endif()
+
+  nnas_include(ExternalBuildTools)
+  ExternalBuild_CMake(CMAKE_DIR   ${FlatBuffersSource_DIR}
+                      BUILD_DIR   ${CMAKE_BINARY_DIR}/externals/FLATBUFFERS-23.5.26/build
+                      INSTALL_DIR ${EXT_OVERLAY_DIR}
+                      BUILD_FLAGS ${ADDITIONAL_CXX_FLAGS}
+                      IDENTIFIER  "23.5.26"
+                      EXTRA_OPTS  "-DFLATBUFFERS_BUILD_TESTS:BOOL=OFF"
+                                  "-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON"
+                      PKG_NAME    "FLATBUFFERS-23.5.26")
+
+endfunction(_FlatBuffers_build)
+
+_FlatBuffers_build()
+_FlatBuffers_import()
+
+# for cross compilation BUILD_HOST_EXEC should be set for host flatc executable
+# flatc should exist as ${BUILD_HOST_EXEC}/overlay/bin/flatc.
+# and then if EXTERNAL_FLATC is set then use ${EXTERNAL_FLATC} file.
+set(FLATC_PATH "$<TARGET_FILE:flatbuffers::flatc>")
+
+if(DEFINED ENV{BUILD_HOST_EXEC})
+  set(FLATC_PATH $ENV{BUILD_HOST_EXEC}/overlay/bin/flatc)
+endif(DEFINED ENV{BUILD_HOST_EXEC})
+if(DEFINED ENV{EXTERNAL_FLATC})
+  set(FLATC_PATH $ENV{EXTERNAL_FLATC})
+endif(DEFINED ENV{EXTERNAL_FLATC})
+
+if(FlatBuffers_FOUND)
+  if(NOT TARGET flatbuffers-23.5.26)
+    add_library(flatbuffers-23.5.26 INTERFACE)
+    target_link_libraries(flatbuffers-23.5.26 INTERFACE flatbuffers::flatbuffers)
+    message(STATUS "Found flatbuffers-23.5.26: TRUE")
+  endif(NOT TARGET flatbuffers-23.5.26)
+
+  function(FlatBuffers_Generate PREFIX OUTPUT_DIR SCHEMA_DIR)
+    get_filename_component(abs_output_dir ${OUTPUT_DIR} ABSOLUTE)
+    get_filename_component(abs_schema_dir ${SCHEMA_DIR} ABSOLUTE)
+
+    foreach(schema ${ARGN})
+      get_filename_component(schema_fn "${schema}" NAME)
+      get_filename_component(dir "${schema}" DIRECTORY)
+
+      get_filename_component(schema_fn_we "${schema_fn}" NAME_WE)
+
+      list(APPEND SCHEMA_FILES "${abs_schema_dir}/${schema}")
+      list(APPEND OUTPUT_FILES "${abs_output_dir}/${schema_fn_we}_generated.h")
+    endforeach()
+
+    add_custom_command(OUTPUT ${OUTPUT_FILES}
+                       COMMAND ${CMAKE_COMMAND} -E make_directory "${abs_output_dir}"
+                       COMMAND "${FLATC_PATH}" -c --no-includes
+                       --no-union-value-namespacing
+                       --gen-object-api -o "${abs_output_dir}"
+                       ${SCHEMA_FILES}
+                       DEPENDS flatbuffers::flatc)
+
+    set(${PREFIX}_SOURCES ${OUTPUT_FILES} PARENT_SCOPE)
+    set(${PREFIX}_INCLUDE_DIRS ${abs_output_dir} PARENT_SCOPE)
+  endfunction(FlatBuffers_Generate)
+
+  function(FlatBuffers_Target TGT)
+    set(oneValueArgs OUTPUT_DIR SCHEMA_DIR INCLUDE_DIR)
+    set(multiValueArgs SCHEMA_FILES)
+    cmake_parse_arguments(ARG "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+    # Use OUTPUT_DIR as INCLUDE_DIR if INCLUDE_DIR is not specified
+    if(NOT ARG_INCLUDE_DIR)
+      set(ARG_INCLUDE_DIR ${ARG_OUTPUT_DIR})
+    endif(NOT ARG_INCLUDE_DIR)
+
+    get_filename_component(abs_output_dir ${ARG_OUTPUT_DIR} ABSOLUTE)
+    get_filename_component(abs_include_dir ${ARG_INCLUDE_DIR} ABSOLUTE)
+    get_filename_component(abs_schema_dir ${ARG_SCHEMA_DIR} ABSOLUTE)
+
+    # Let's reset list variables before using them
+    # NOTE THIS DOES NOT AFFECT parent scope
+    unset(SCHEMA_FILES)
+    unset(OUTPUT_FILES)
+
+    foreach(schema ${ARG_SCHEMA_FILES})
+      get_filename_component(schema_fn "${schema}" NAME)
+      get_filename_component(dir "${schema}" DIRECTORY)
+
+      get_filename_component(schema_fn_we "${schema_fn}" NAME_WE)
+
+      list(APPEND SCHEMA_FILES "${abs_schema_dir}/${schema}")
+      list(APPEND OUTPUT_FILES "${abs_output_dir}/${schema_fn_we}_generated.h")
+    endforeach()
+
+    # Generate headers
+    add_custom_command(OUTPUT ${OUTPUT_FILES}
+                       COMMAND ${CMAKE_COMMAND} -E make_directory "${abs_output_dir}"
+                       COMMAND "${FLATC_PATH}" -c --no-includes
+                               --no-union-value-namespacing
+                               --gen-object-api -o "${abs_output_dir}"
+                               ${SCHEMA_FILES}
+                       DEPENDS ${SCHEMA_FILES}
+                       COMMENT "Generate '${TGT}' headers")
+
+    # NOTE This header-only library is deliberately declared as STATIC library
+    #      to avoid possible scope issues related with generated files
+    add_library(${TGT} STATIC ${OUTPUT_FILES})
+    set_target_properties(${TGT} PROPERTIES LINKER_LANGUAGE CXX)
+    target_include_directories(${TGT} PUBLIC "${ARG_INCLUDE_DIR}")
+    target_link_libraries(${TGT} PUBLIC flatbuffers-23.5.26)
+  endfunction(FlatBuffers_Target)
+endif(FlatBuffers_FOUND)
diff --git a/infra/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfigVersion.cmake b/infra/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfigVersion.cmake
new file mode 100644 (file)
index 0000000..f8b165c
--- /dev/null
@@ -0,0 +1,10 @@
+set(PACKAGE_VERSION "23.5.26")
+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/FlatBuffersSource-23.5.26/FlatBuffersSourceConfig.cmake b/infra/cmake/packages/FlatBuffersSource-23.5.26/FlatBuffersSourceConfig.cmake
new file mode 100644 (file)
index 0000000..9725f3c
--- /dev/null
@@ -0,0 +1,22 @@
+function(_FlatBuffersSource_import)
+  if(NOT DOWNLOAD_FLATBUFFERS)
+    set(FlatBuffersSource_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT DOWNLOAD_FLATBUFFERS)
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+  envoption(FLATBUFFERS_23_5_26_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/flatbuffers/archive/v23.5.26.tar.gz)
+  ExternalSource_Download(FLATBUFFERS
+    DIRNAME FLATBUFFERS-23.5.26
+    CHECKSUM MD5=2ef00eaaa86ab5e9ad5eafe09c2e7b60
+    URL ${FLATBUFFERS_23_5_26_URL}
+  )
+
+  set(FlatBuffersSource_DIR ${FLATBUFFERS_SOURCE_DIR} PARENT_SCOPE)
+  set(FlatBuffersSource_FOUND TRUE PARENT_SCOPE)
+endfunction(_FlatBuffersSource_import)
+
+_FlatBuffersSource_import()
diff --git a/infra/cmake/packages/FlatBuffersSource-23.5.26/FlatBuffersSourceConfigVersion.cmake b/infra/cmake/packages/FlatBuffersSource-23.5.26/FlatBuffersSourceConfigVersion.cmake
new file mode 100644 (file)
index 0000000..f8b165c
--- /dev/null
@@ -0,0 +1,10 @@
+set(PACKAGE_VERSION "23.5.26")
+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)
index 3df4e4c..eced9fd 100644 (file)
@@ -8,8 +8,8 @@ function(_Fp16Source_import)
   nnas_include(OptionTools)
 
   envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
-  # fp16 commit in xnnpack 8b283aa30a31
-  envoption(FP16_URL ${EXTERNAL_DOWNLOAD_SERVER}/Maratyszcza/FP16/archive/4dfe081cf6bcd15db339cf2680b9281b8451eeb3.tar.gz)
+  # fp16 commit in xnnpack (tflite v2.16.1)
+  envoption(FP16_URL ${EXTERNAL_DOWNLOAD_SERVER}/Maratyszcza/FP16/archive/0a92994d729ff76a58f692d3028ca1b64b145d91.tar.gz)
   ExternalSource_Download(FP16
     DIRNAME FP16
     URL ${FP16_URL})
index 4427bf2..4d8ff43 100644 (file)
@@ -8,8 +8,8 @@ function(_FxdivSource_import)
   nnas_include(OptionTools)
 
   envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
-  # fxdiv commit in xnnpack 8b283aa30a31
-  envoption(FXDIV_URL ${EXTERNAL_DOWNLOAD_SERVER}/Maratyszcza/FXdiv/archive/f8c5354679ec2597792bc70a9e06eff50c508b9a.tar.gz)
+  # fxdiv commit in tflite v2.16.1
+  envoption(FXDIV_URL ${EXTERNAL_DOWNLOAD_SERVER}/Maratyszcza/FXdiv/archive/63058eff77e11aa15bf531df5dd34395ec3017c8.tar.gz)
   ExternalSource_Download(FXDIV
     DIRNAME FXDIV
     URL ${FXDIV_URL})
index 643c3d1..dc050a0 100644 (file)
@@ -8,7 +8,7 @@ function(_GTestSource_import)
   nnas_include(OptionTools)
 
   envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
-  envoption(GTEST_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/googletest/archive/release-1.11.0.tar.gz)
+  envoption(GTEST_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/googletest/archive/release-1.12.1.tar.gz)
 
   ExternalSource_Download(GTEST ${GTEST_URL})
 
diff --git a/infra/cmake/packages/LibnpySourceConfig.cmake b/infra/cmake/packages/LibnpySourceConfig.cmake
new file mode 100644 (file)
index 0000000..17a0fea
--- /dev/null
@@ -0,0 +1,20 @@
+function(_LibnpySource_import)
+  if(NOT ${DOWNLOAD_LIBNPY})
+    set(LibnpySource_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT ${DOWNLOAD_LIBNPY})
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+  envoption(LIBNPY_URL ${EXTERNAL_DOWNLOAD_SERVER}/llohse/libnpy/archive/refs/tags/v0.1.0.tar.gz)
+
+  ExternalSource_Download(LIBNPY ${LIBNPY_URL})
+
+  set(LibnpySource_DIR ${LIBNPY_SOURCE_DIR} PARENT_SCOPE)
+  set(LibnpySource_FOUND TRUE PARENT_SCOPE)
+endfunction(_LibnpySource_import)
+
+_LibnpySource_import()
+
diff --git a/infra/cmake/packages/MLDtypesSourceConfig.cmake b/infra/cmake/packages/MLDtypesSourceConfig.cmake
new file mode 100644 (file)
index 0000000..adffb26
--- /dev/null
@@ -0,0 +1,19 @@
+function(_MLDtypesSource_import)
+  if(NOT DOWNLOAD_MLDTYPES)
+    set(MLDtypesSource_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT DOWNLOAD_MLDTYPES)
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+  envoption(MLDTYPES_URL ${EXTERNAL_DOWNLOAD_SERVER}/jax-ml/ml_dtypes/archive/2ca30a2b3c0744625ae3d6988f5596740080bbd0/ml_dtypes-2ca30a2b3c0744625ae3d6988f5596740080bbd0.tar.gz)
+
+  ExternalSource_Download(MLDTYPES ${MLDTYPES_URL})
+
+  set(MLDtypesSource_DIR ${MLDTYPES_SOURCE_DIR} PARENT_SCOPE)
+  set(MLDtypesSource_FOUND TRUE PARENT_SCOPE)
+endfunction(_MLDtypesSource_import)
+
+_MLDtypesSource_import()
index 82c71e2..0614ae6 100644 (file)
@@ -7,11 +7,9 @@ function(_NEON2SSESource_import)
   nnas_include(ExternalSourceTools)
   nnas_include(OptionTools)
 
-  # NOTE TensorFlow 1.13.1 downloads NEON2SSE from the following URL
-  # NOTE TensorFlow 2.8.0 downloads NEON2SSE from the following URL
-  # NOTE commit c12f8932c3be5aebaf35562d699f645686c4e2c3 will resolve build fail on debug build
+  # NOTE TensorFlow 2.16.1 downloads NEON2SSE from the following URL
   envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
-  envoption(NEON2SSE_URL ${EXTERNAL_DOWNLOAD_SERVER}/intel/ARM_NEON_2_x86_SSE/archive/1200fe90bb174a6224a525ee60148671a786a71f.tar.gz)
+  envoption(NEON2SSE_URL ${EXTERNAL_DOWNLOAD_SERVER}/intel/ARM_NEON_2_x86_SSE/archive/a15b489e1222b2087007546b4912e21293ea86ff.tar.gz)
 
   ExternalSource_Download(NEON2SSE ${NEON2SSE_URL})
 
index 17965f1..96b144a 100644 (file)
@@ -16,7 +16,7 @@ function(_NoniusSource_import)
     # This header file is modified to show the html summary view according to the layer in kbenchmark.
     execute_process(COMMAND ${CMAKE_COMMAND} -E copy
                     "${CMAKE_CURRENT_LIST_DIR}/Nonius/html_report_template.g.h++"
-                    "${NoniusSource_DIR}/include/nonius/detail")
+                    "${Nonius_Source_DIR}/include/nonius/detail")
   endif(BUILD_KBENCHMARK)
 
   set(NoniusSource_DIR ${NONIUS_SOURCE_DIR} PARENT_SCOPE)
index 4e1910a..e21d32b 100644 (file)
@@ -8,8 +8,8 @@ function(_PthreadpoolSource_import)
   nnas_include(OptionTools)
 
   envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
-  # pthreadpool commit in xnnpack 8b283aa30a31
-  envoption(PTHREADPOOL_URL ${EXTERNAL_DOWNLOAD_SERVER}/Maratyszcza/pthreadpool/archive/029c88620802e1361ccf41d1970bd5b07fd6b7bb.tar.gz)
+  # pthreadpool commit in xnnpack (tflite v2.16.1)
+  envoption(PTHREADPOOL_URL ${EXTERNAL_DOWNLOAD_SERVER}/Maratyszcza/pthreadpool/archive/4fe0e1e183925bf8cfa6aae24237e724a96479b8.tar.gz)
   ExternalSource_Download(PTHREADPOOL
     DIRNAME PTHREADPOOL
     URL ${PTHREADPOOL_URL})
index 2f64253..26367f3 100644 (file)
@@ -8,7 +8,7 @@ function(_Pybind11Source_import)
   nnas_include(OptionTools)
 
   envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
-  envoption(PYBIND11_URL ${EXTERNAL_DOWNLOAD_SERVER}/pybind/pybind11/archive/v2.5.0.tar.gz)
+  envoption(PYBIND11_URL ${EXTERNAL_DOWNLOAD_SERVER}/pybind/pybind11/archive/v2.11.1.tar.gz)
 
   ExternalSource_Download(PYBIND11 ${PYBIND11_URL})
 
diff --git a/infra/cmake/packages/TensorFlowConfig.cmake b/infra/cmake/packages/TensorFlowConfig.cmake
deleted file mode 100644 (file)
index 14d2fdf..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-set(TENSORFLOW_PREFIX "/usr" CACHE PATH "The location of pre-installed TensorFlow library")
-set(TENSORFLOW_VERSION_REQUIRED "1.12.0")
-
-# TODO Build TensorFlow from the (downloaded) source
-
-function(_TensorFlow_import)
-  # Find the header & lib
-  find_library(TensorFlow_LIB NAMES tensorflow PATHS "${TENSORFLOW_PREFIX}/lib")
-  find_path(TensorFlow_INCLUDE_DIR NAMES tensorflow/c/c_api.h PATHS "${TENSORFLOW_PREFIX}/include")
-
-  if(NOT TensorFlow_LIB OR NOT TensorFlow_INCLUDE_DIR)
-    message(STATUS "Found TensorFlow: FALSE")
-
-    set(TensorFlow_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT TensorFlow_LIB OR NOT TensorFlow_INCLUDE_DIR)
-
-  # Check TensorFlow version
-  try_run(RUN_RESULT_VAR COMPILE_RESULT_VAR
-    ${CMAKE_BINARY_DIR}
-    ${CMAKE_CURRENT_LIST_DIR}/TensorFlowVersionChecker.c
-    COMPILE_DEFINITIONS -I${TensorFlow_INCLUDE_DIR}
-    LINK_LIBRARIES ${TensorFlow_LIB}
-    ARGS ${TENSORFLOW_VERSION_REQUIRED})
-
-  if(NOT COMPILE_RESULT_VAR)
-    message(STATUS "Failed to build TensorFlowVersionChecker. Your libtensorflow may be built on different version of Ubuntu.")
-    message(STATUS "Found TensorFlow: FALSE")
-    set(TensorFlow_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT COMPILE_RESULT_VAR)
-
-  if(NOT RUN_RESULT_VAR EQUAL 0)
-    message(STATUS "you need tensorflow version ${TENSORFLOW_VERSION_REQUIRED}")
-    message(STATUS "Found TensorFlow: FALSE")
-    set(TensorFlow_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT RUN_RESULT_VAR EQUAL 0)
-
-  # Add tensorflow target (if necessary)
-  if(NOT TARGET tensorflow)
-    message(STATUS "Found TensorFlow (include: ${TensorFlow_INCLUDE_DIR}, library: ${TensorFlow_LIB})")
-
-    # NOTE IMPORTED target may be more appropriate for this case
-    add_library(tensorflow INTERFACE)
-    target_link_libraries(tensorflow INTERFACE ${TensorFlow_LIB})
-    target_include_directories(tensorflow INTERFACE ${TensorFlow_INCLUDE_DIR})
-  endif(NOT TARGET tensorflow)
-
-  set(TensorFlow_FOUND TRUE PARENT_SCOPE)
-endfunction(_TensorFlow_import)
-
-_TensorFlow_import()
diff --git a/infra/cmake/packages/TensorFlowEigenSource-2.12.1/TensorFlowEigenSourceConfig.cmake b/infra/cmake/packages/TensorFlowEigenSource-2.12.1/TensorFlowEigenSourceConfig.cmake
new file mode 100644 (file)
index 0000000..69646d3
--- /dev/null
@@ -0,0 +1,21 @@
+function(_TensorFlowEigenSource_import)
+  if(NOT DOWNLOAD_EIGEN)
+    set(TensorFlowEigenSource_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT DOWNLOAD_EIGEN)
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  # Exact version used by TensorFlow v2.12.1.
+  # See tensorflow/third_party/eigen3/workspace.bzl.
+  envoption(EXTERNAL_DOWNLOAD_SERVER "https://gitlab.com")
+  envoption(TENSORFLOW_2_12_1_EIGEN_URL ${EXTERNAL_DOWNLOAD_SERVER}/libeigen/eigen/-/archive/3460f3558e7b469efb8a225894e21929c8c77629/eigen-3460f3558e7b469efb8a225894e21929c8c77629.tar.gz)
+
+  ExternalSource_Download(EIGEN DIRNAME TENSORFLOW-2.12.1-EIGEN ${TENSORFLOW_2_12_1_EIGEN_URL})
+
+  set(TensorFlowEigenSource_DIR ${EIGEN_SOURCE_DIR} PARENT_SCOPE)
+  set(TensorFlowEigenSource_FOUND TRUE PARENT_SCOPE)
+endfunction(_TensorFlowEigenSource_import)
+
+_TensorFlowEigenSource_import()
diff --git a/infra/cmake/packages/TensorFlowEigenSource-2.12.1/TensorFlowEigenSourceConfigVersion.cmake b/infra/cmake/packages/TensorFlowEigenSource-2.12.1/TensorFlowEigenSourceConfigVersion.cmake
new file mode 100644 (file)
index 0000000..8566d08
--- /dev/null
@@ -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/cmake/packages/TensorFlowEigenSource-2.16.1/TensorFlowEigenSourceConfig.cmake b/infra/cmake/packages/TensorFlowEigenSource-2.16.1/TensorFlowEigenSourceConfig.cmake
new file mode 100644 (file)
index 0000000..df58ce3
--- /dev/null
@@ -0,0 +1,21 @@
+function(_TensorFlowEigenSource_import)
+  if(NOT DOWNLOAD_EIGEN)
+    set(TensorFlowEigenSource_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT DOWNLOAD_EIGEN)
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  # Exact version used by TensorFlow v2.16.1.
+  # See tensorflow/third_party/eigen3/workspace.bzl.
+  envoption(EXTERNAL_DOWNLOAD_SERVER "https://gitlab.com")
+  envoption(TENSORFLOW_2_16_1_EIGEN_URL ${EXTERNAL_DOWNLOAD_SERVER}/libeigen/eigen/-/archive/aa6964bf3a34fd607837dd8123bc42465185c4f8/eigen-aa6964bf3a34fd607837dd8123bc42465185c4f8.tar.gz)
+
+  ExternalSource_Download(EIGEN DIRNAME TENSORFLOW-2.16.1-EIGEN ${TENSORFLOW_2_16_1_EIGEN_URL})
+
+  set(TensorFlowEigenSource_DIR ${EIGEN_SOURCE_DIR} PARENT_SCOPE)
+  set(TensorFlowEigenSource_FOUND TRUE PARENT_SCOPE)
+endfunction(_TensorFlowEigenSource_import)
+
+_TensorFlowEigenSource_import()
diff --git a/infra/cmake/packages/TensorFlowEigenSource-2.16.1/TensorFlowEigenSourceConfigVersion.cmake b/infra/cmake/packages/TensorFlowEigenSource-2.16.1/TensorFlowEigenSourceConfigVersion.cmake
new file mode 100644 (file)
index 0000000..1090931
--- /dev/null
@@ -0,0 +1,10 @@
+set(PACKAGE_VERSION "2.16.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/cmake/packages/TensorFlowGEMMLowpSource-2.12.1/TensorFlowGEMMLowpSourceConfig.cmake b/infra/cmake/packages/TensorFlowGEMMLowpSource-2.12.1/TensorFlowGEMMLowpSourceConfig.cmake
new file mode 100644 (file)
index 0000000..3c2ffac
--- /dev/null
@@ -0,0 +1,21 @@
+function(_TensorFlowGEMMLowpSource_import)
+  if(NOT DOWNLOAD_GEMMLOWP)
+    set(TensorFlowGEMMLowpSource_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT DOWNLOAD_GEMMLOWP)
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  # Exact version used by TensorFlow v2.12.1.
+  # See tensorflow/third_party/gemmlowp/workspace.bzl.
+  envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+  envoption(TENSORFLOW_2_12_1_GEMMLOWP_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/gemmlowp/archive/e844ffd17118c1e17d94e1ba4354c075a4577b88.zip)
+
+  ExternalSource_Download(GEMMLOWP DIRNAME TENSORFLOW-2.12.1-GEMMLOWP ${TENSORFLOW_2_12_1_GEMMLOWP_URL})
+
+  set(TensorFlowGEMMLowpSource_DIR ${GEMMLOWP_SOURCE_DIR} PARENT_SCOPE)
+  set(TensorFlowGEMMLowpSource_FOUND TRUE PARENT_SCOPE)
+endfunction(_TensorFlowGEMMLowpSource_import)
+
+_TensorFlowGEMMLowpSource_import()
diff --git a/infra/cmake/packages/TensorFlowGEMMLowpSource-2.12.1/TensorFlowGEMMLowpSourceConfigVersion.cmake b/infra/cmake/packages/TensorFlowGEMMLowpSource-2.12.1/TensorFlowGEMMLowpSourceConfigVersion.cmake
new file mode 100644 (file)
index 0000000..8566d08
--- /dev/null
@@ -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/cmake/packages/TensorFlowGEMMLowpSource-2.16.1/TensorFlowGEMMLowpSourceConfig.cmake b/infra/cmake/packages/TensorFlowGEMMLowpSource-2.16.1/TensorFlowGEMMLowpSourceConfig.cmake
new file mode 100644 (file)
index 0000000..baa53cb
--- /dev/null
@@ -0,0 +1,21 @@
+function(_TensorFlowGEMMLowpSource_import)
+  if(NOT DOWNLOAD_GEMMLOWP)
+    set(TensorFlowGEMMLowpSource_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT DOWNLOAD_GEMMLOWP)
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  # Exact version used by TensorFlow v2.16.1.
+  # See tensorflow/third_party/gemmlowp/workspace.bzl.
+  envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+  envoption(TENSORFLOW_2_16_1_GEMMLOWP_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/gemmlowp/archive/16e8662c34917be0065110bfcd9cc27d30f52fdf.zip)
+
+  ExternalSource_Download(GEMMLOWP DIRNAME TENSORFLOW-2.16.1-GEMMLOWP ${TENSORFLOW_2_16_1_GEMMLOWP_URL})
+
+  set(TensorFlowGEMMLowpSource_DIR ${GEMMLOWP_SOURCE_DIR} PARENT_SCOPE)
+  set(TensorFlowGEMMLowpSource_FOUND TRUE PARENT_SCOPE)
+endfunction(_TensorFlowGEMMLowpSource_import)
+
+_TensorFlowGEMMLowpSource_import()
diff --git a/infra/cmake/packages/TensorFlowGEMMLowpSource-2.16.1/TensorFlowGEMMLowpSourceConfigVersion.cmake b/infra/cmake/packages/TensorFlowGEMMLowpSource-2.16.1/TensorFlowGEMMLowpSourceConfigVersion.cmake
new file mode 100644 (file)
index 0000000..1090931
--- /dev/null
@@ -0,0 +1,10 @@
+set(PACKAGE_VERSION "2.16.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/cmake/packages/TensorFlowLite-1.13.1/Lite/CMakeLists.txt b/infra/cmake/packages/TensorFlowLite-1.13.1/Lite/CMakeLists.txt
deleted file mode 100644 (file)
index a57d7f4..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-# NOTE The followings SHOULD be defined before using this CMakeLists.txt
-# NOTE TensorFlow 1.13.1 uses flatbuffers-1.10
-#      but we use flatbuffers-2.0 to match with all other modules flatbuffers version.
-#
-#  'TensorFlowSource_DIR' variable
-#  'flatbuffers-2.0' target
-#  'eigen' target
-#  'gemmlowp' target
-#  'neon2sse' target
-#  'farmhash' target
-#  'abseil' target
-#
-message(STATUS "Build TensorFlow Lite from ${TensorFlowSource_DIR}")
-
-set(TensorFlowLiteSource_DIR ${TensorFlowSource_DIR}/tensorflow/lite)
-
-file(GLOB CORE_SRCS
-  "${TensorFlowLiteSource_DIR}/*.c"
-  "${TensorFlowLiteSource_DIR}/*.cc"
-  "${TensorFlowLiteSource_DIR}/c/*.c"
-  "${TensorFlowLiteSource_DIR}/core/*.cc"
-  "${TensorFlowLiteSource_DIR}/core/api/*.cc")
-file(GLOB_RECURSE CORE_TESTS "${TensorFlowLiteSource_DIR}/*test*.cc")
-list(REMOVE_ITEM CORE_SRCS ${CORE_TESTS})
-
-file(GLOB_RECURSE KERNEL_SRCS "${TensorFlowLiteSource_DIR}/kernels/*.cc")
-file(GLOB_RECURSE KERNEL_TESTS "${TensorFlowLiteSource_DIR}/kernels/*test*.cc")
-list(REMOVE_ITEM KERNEL_SRCS ${KERNEL_TESTS})
-# Exclude buggy kernel(s) from the build
-#list(REMOVE_ITEM KERNEL_SRCS "${TensorFlowLiteSource_DIR}/kernels/internal/spectrogram.cc")
-
-list(APPEND SRCS ${CORE_SRCS})
-list(APPEND SRCS ${KERNEL_SRCS})
-
-include(CheckCXXCompilerFlag)
-
-CHECK_CXX_COMPILER_FLAG(-Wno-extern-c-compat COMPILER_SUPPORT_EXTERN_C_COMPAT_WARNING)
-
-add_library(tensorflowlite-1.13.1 ${SRCS})
-set_target_properties(tensorflowlite-1.13.1 PROPERTIES POSITION_INDEPENDENT_CODE ON)
-target_include_directories(tensorflowlite-1.13.1 PUBLIC ${TensorFlowSource_DIR})
-target_compile_options(tensorflowlite-1.13.1 PUBLIC -Wno-ignored-attributes)
-if(COMPILER_SUPPORT_EXTERN_C_COMPAT_WARNING)
-  target_compile_options(tensorflowlite-1.13.1 PUBLIC -Wno-extern-c-compat)
-endif(COMPILER_SUPPORT_EXTERN_C_COMPAT_WARNING)
-target_compile_definitions(tensorflowlite-1.13.1 PUBLIC "GEMMLOWP_ALLOW_SLOW_SCALAR_FALLBACK")
-target_link_libraries(tensorflowlite-1.13.1 flatbuffers-2.0 eigen gemmlowp neon2sse farmhash abseil dl)
diff --git a/infra/cmake/packages/TensorFlowLite-1.13.1/TensorFlowLiteConfig.cmake b/infra/cmake/packages/TensorFlowLite-1.13.1/TensorFlowLiteConfig.cmake
deleted file mode 100644 (file)
index ea20658..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-function(_TensorFlowLite_import)
-  nnas_find_package(TensorFlowSource EXACT 1.13.1 QUIET)
-
-  if(NOT TensorFlowSource_FOUND)
-    set(TensorFlowLite_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT TensorFlowSource_FOUND)
-
-  nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
-
-  if(NOT FlatBuffers_FOUND)
-    set(TensorFlowLite_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT FlatBuffers_FOUND)
-
-  nnas_find_package(Farmhash QUIET)
-
-  if(NOT Farmhash_FOUND)
-    set(TensorFlowLite_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT Farmhash_FOUND)
-
-  nnas_find_package(Eigen QUIET)
-
-  if(NOT Eigen_FOUND)
-    set(TensorFlowLite_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT Eigen_FOUND)
-
-  nnas_find_package(GEMMLowp QUIET)
-
-  if(NOT GEMMLowp_FOUND)
-    set(TensorFlowLite_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT GEMMLowp_FOUND)
-
-  nnas_find_package(NEON2SSE QUIET)
-
-  if(NOT NEON2SSE_FOUND)
-    set(TensorFlowLite_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT NEON2SSE_FOUND)
-
-  nnas_find_package(Abseil QUIET)
-
-  if(NOT Abseil_FOUND)
-    set(TensorFlowLite_FOUND FALSE PARENT_SCOPE)
-    return()
-  endif(NOT Abseil_FOUND)
-
-  if(NOT TARGET tensorflowlite-1.13.1)
-    nnas_include(ExternalProjectTools)
-    add_extdirectory("${CMAKE_CURRENT_LIST_DIR}/Lite" tflite-1.13.1)
-  endif(NOT TARGET tensorflowlite-1.13.1)
-
-  set(TensorFlowLite_FOUND TRUE PARENT_SCOPE)
-endfunction(_TensorFlowLite_import)
-
-_TensorFlowLite_import()
diff --git a/infra/cmake/packages/TensorFlowLite-1.13.1/TensorFlowLiteConfigVersion.cmake b/infra/cmake/packages/TensorFlowLite-1.13.1/TensorFlowLiteConfigVersion.cmake
deleted file mode 100644 (file)
index ed79ecd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-set(PACKAGE_VERSION "1.13.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_UNSUITABLE FALSE)
-endif(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
diff --git a/infra/cmake/packages/TensorFlowRuySource-2.12.1/TensorFlowRuySourceConfig.cmake b/infra/cmake/packages/TensorFlowRuySource-2.12.1/TensorFlowRuySourceConfig.cmake
new file mode 100644 (file)
index 0000000..6c11844
--- /dev/null
@@ -0,0 +1,21 @@
+function(_TensorFlowRuySource_import)
+  if(NOT DOWNLOAD_RUY)
+    set(TensorFlowRuySource_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT DOWNLOAD_RUY)
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  # Exact version used by TensorFlow v2.12.1.
+  # See tensorflow/third_party/ruy/workspace.bzl
+  envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+  envoption(TENSORFLOW_2_12_1_RUY_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/ruy/archive/3286a34cc8de6149ac6844107dfdffac91531e72.zip)
+
+  ExternalSource_Download(RUY DIRNAME TENSORFLOW-2.12.1-RUY ${TENSORFLOW_2_12_1_RUY_URL})
+
+  set(TensorFlowRuySource_DIR ${RUY_SOURCE_DIR} PARENT_SCOPE)
+  set(TensorFlowRuySource_FOUND TRUE PARENT_SCOPE)
+endfunction(_TensorFlowRuySource_import)
+
+_TensorFlowRuySource_import()
diff --git a/infra/cmake/packages/TensorFlowRuySource-2.12.1/TensorFlowRuySourceConfigVersion.cmake b/infra/cmake/packages/TensorFlowRuySource-2.12.1/TensorFlowRuySourceConfigVersion.cmake
new file mode 100644 (file)
index 0000000..8566d08
--- /dev/null
@@ -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/cmake/packages/TensorFlowRuySource-2.16.1/TensorFlowRuySourceConfig.cmake b/infra/cmake/packages/TensorFlowRuySource-2.16.1/TensorFlowRuySourceConfig.cmake
new file mode 100644 (file)
index 0000000..3310b7e
--- /dev/null
@@ -0,0 +1,21 @@
+function(_TensorFlowRuySource_import)
+  if(NOT DOWNLOAD_RUY)
+    set(TensorFlowRuySource_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT DOWNLOAD_RUY)
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  # Exact version used by TensorFlow v2.16.1.
+  # See tensorflow/third_party/ruy/workspace.bzl
+  envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+  envoption(TENSORFLOW_2_16_1_RUY_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/ruy/archive/3286a34cc8de6149ac6844107dfdffac91531e72.zip)
+
+  ExternalSource_Download(RUY DIRNAME TENSORFLOW-2.16.1-RUY ${TENSORFLOW_2_16_1_RUY_URL})
+
+  set(TensorFlowRuySource_DIR ${RUY_SOURCE_DIR} PARENT_SCOPE)
+  set(TensorFlowRuySource_FOUND TRUE PARENT_SCOPE)
+endfunction(_TensorFlowRuySource_import)
+
+_TensorFlowRuySource_import()
diff --git a/infra/cmake/packages/TensorFlowRuySource-2.16.1/TensorFlowRuySourceConfigVersion.cmake b/infra/cmake/packages/TensorFlowRuySource-2.16.1/TensorFlowRuySourceConfigVersion.cmake
new file mode 100644 (file)
index 0000000..1090931
--- /dev/null
@@ -0,0 +1,10 @@
+set(PACKAGE_VERSION "2.16.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/cmake/packages/TensorFlowSource-2.16.1/TensorFlowSourceConfig.cmake b/infra/cmake/packages/TensorFlowSource-2.16.1/TensorFlowSourceConfig.cmake
new file mode 100644 (file)
index 0000000..cc8879a
--- /dev/null
@@ -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_16_1_URL ${EXTERNAL_DOWNLOAD_SERVER}/tensorflow/tensorflow/archive/v2.16.1.tar.gz)
+
+  ExternalSource_Download(TENSORFLOW DIRNAME TENSORFLOW-2.16.1 ${TENSORFLOW_2_16_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.16.1/TensorFlowSourceConfigVersion.cmake b/infra/cmake/packages/TensorFlowSource-2.16.1/TensorFlowSourceConfigVersion.cmake
new file mode 100644 (file)
index 0000000..1090931
--- /dev/null
@@ -0,0 +1,10 @@
+set(PACKAGE_VERSION "2.16.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/cmake/packages/TensorFlowThreadpoolSource-2.12.1/TensorFlowThreadpoolSourceConfig.cmake b/infra/cmake/packages/TensorFlowThreadpoolSource-2.12.1/TensorFlowThreadpoolSourceConfig.cmake
new file mode 100644 (file)
index 0000000..2bbf958
--- /dev/null
@@ -0,0 +1,21 @@
+function(_TensorFlowThreadpoolSource_import)
+  if(NOT DOWNLOAD_THREADPOOL)
+    set(TensorFlowThreadpoolSource_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT DOWNLOAD_THREADPOOL)
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  # Exact version used by TensorFlow v2.12.1.
+  # See tensorflow/workspace2.bzl
+  envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
+  envoption(TENSORFLOW_2_12_1_THREADPOOL_URL ${EXTERNAL_DOWNLOAD_SERVER}/Maratyszcza/pthreadpool/archive/b8374f80e42010941bda6c85b0e3f1a1bd77a1e0.zip)
+
+  ExternalSource_Download(THREADPOOL DIRNAME TENSORFLOW-2.12.1-THREADPOOL ${TENSORFLOW_2_12_1_THREADPOOL_URL})
+
+  set(TensorFlowThreadpoolSource_DIR ${THREADPOOL_SOURCE_DIR} PARENT_SCOPE)
+  set(TensorFlowThreadpoolSource_FOUND TRUE PARENT_SCOPE)
+endfunction(_TensorFlowThreadpoolSource_import)
+
+_TensorFlowThreadpoolSource_import()
diff --git a/infra/cmake/packages/TensorFlowThreadpoolSource-2.12.1/TensorFlowThreadpoolSourceConfigVersion.cmake b/infra/cmake/packages/TensorFlowThreadpoolSource-2.12.1/TensorFlowThreadpoolSourceConfigVersion.cmake
new file mode 100644 (file)
index 0000000..8566d08
--- /dev/null
@@ -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/cmake/packages/XnnpackSource.patch b/infra/cmake/packages/XnnpackSource.patch
new file mode 100644 (file)
index 0000000..d7aff90
--- /dev/null
@@ -0,0 +1,52 @@
+--- a/src/configs/dwconv-config.c
++++ b/src/configs/dwconv-config.c
+@@ -688,6 +688,7 @@
+     const struct xnn_hardware_config* hardware_config = xnn_init_hardware_config();
+     assert(hardware_config != NULL);
+     if (hardware_config->use_arm_neon) {
++#if defined(XNN_ENABLE_ASSEMBLY) && XNN_ENABLE_ASSEMBLY
+       if (hardware_config->use_arm_neon_v8) {
+         qs8_qc8w_dwconv_config[0].minmax.unipass = (xnn_dwconv_unipass_ukernel_fn) xnn_qs8_qc8w_dwconv_minmax_fp32_ukernel_3p16c__asm_aarch32_neonv8_mla8_cortex_a35;
+         qs8_qc8w_dwconv_config[0].init.qs8_qc8w = xnn_init_qs8_qc8w_conv_minmax_fp32_neonv8_params;
+@@ -708,6 +709,9 @@
+         qs8_qc8w_dwconv_config[2].channel_round = 1;
+         qs8_qc8w_dwconv_config[2].primary_tile = 25;
+       } else {
++#else
++      {
++#endif
+         qs8_qc8w_dwconv_config[0].minmax.unipass = (xnn_dwconv_unipass_ukernel_fn) xnn_qs8_qc8w_dwconv_minmax_fp32_ukernel_3p16c__neon_mla8_ld128;
+         qs8_qc8w_dwconv_config[0].init.qs8_qc8w = xnn_init_qs8_qc8w_conv_minmax_fp32_neon_params;
+         qs8_qc8w_dwconv_config[0].channel_tile = 16;
+--- a/src/configs/hardware-config.c
++++ b/src/configs/hardware-config.c
+@@ -99,7 +99,11 @@
+     hardware_config.use_arm_neon = cpuinfo_has_arm_neon();
+     hardware_config.use_arm_neon_fp16 = cpuinfo_has_arm_neon_fp16();
+     hardware_config.use_arm_neon_fma = cpuinfo_has_arm_neon_fma();
++#if defined(XNN_ENABLE_ASSEMBLY) && XNN_ENABLE_ASSEMBLY
+     hardware_config.use_arm_neon_v8 = cpuinfo_has_arm_neon_v8();
++#else
++    hardware_config.use_arm_neon_v8 = false;
++#endif
+   #endif
+
+   #if XNN_ARCH_ARM64
+--- a/src/configs/unary-elementwise-config.c
++++ b/src/configs/unary-elementwise-config.c
+@@ -1806,11 +1806,15 @@
+   #if XNN_ARCH_ARM
+     const struct xnn_hardware_config* hardware_config = xnn_init_hardware_config();
+     assert(hardware_config != NULL);
++#if defined(XNN_ENABLE_ASSEMBLY) && XNN_ENABLE_ASSEMBLY
+     if (hardware_config->use_arm_neon) {
+       qs16_to_qs8_cvt_config.ukernel = (xnn_vunary_ukernel_fn) xnn_qs16_qs8_vcvt_ukernel__asm_aarch32_neon_u16;
+       qs16_to_qs8_cvt_config.init.qs16_qs8_cvt = xnn_init_qs16_qs8_cvt_neon_params;
+       qs16_to_qs8_cvt_config.element_tile = 16;
+     } else if (!XNN_PLATFORM_MOBILE) {
++#else
++    if (!XNN_PLATFORM_MOBILE) {
++#endif
+       qs16_to_qs8_cvt_config.ukernel = (xnn_vunary_ukernel_fn) xnn_qs16_qs8_vcvt_ukernel__scalar_u4;
+       qs16_to_qs8_cvt_config.init.qs16_qs8_cvt = xnn_init_qs16_qs8_cvt_scalar_params;
+       qs16_to_qs8_cvt_config.element_tile = 4;
index 36a9204..d4a3d30 100644 (file)
@@ -8,11 +8,14 @@ function(_XnnpackSource_import)
   nnas_include(OptionTools)
 
   envoption(EXTERNAL_DOWNLOAD_SERVER "https://github.com")
-  # xnnpack commit in tflite v2.3
-  envoption(XNNPACK_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/XNNPACK/archive/8b283aa30a3186c6e640aed520543e9c067132d.tar.gz)
+  # xnnpack latest commit (2024.05.20)
+  # xnnpack in tflite v2.16.1 is not stable on armv7l gbs and linux cross build process (assembly microkernel build issue)
+  # Patch: workaround to resolve build fail by forcing disable using armv8 feature on gbs build and arm linux cross build under gcc 10
+  envoption(XNNPACK_URL ${EXTERNAL_DOWNLOAD_SERVER}/google/XNNPACK/archive/fcb36699c67201ceff7358df42730809e8f2c9cc.tar.gz)
   ExternalSource_Download(XNNPACK
     DIRNAME XNNPACK
-    URL ${XNNPACK_URL})
+    URL ${XNNPACK_URL}
+    PATCH ${CMAKE_CURRENT_LIST_DIR}/XnnpackSource.patch)
 
   set(XnnpackSource_DIR ${XNNPACK_SOURCE_DIR} PARENT_SCOPE)
   set(XnnpackSource_FOUND TRUE PARENT_SCOPE)
index f4e2069..95f6ab6 100644 (file)
@@ -5,7 +5,8 @@ function Usage()
   echo "Usage: $0 $(basename ${BASH_SOURCE[0]}) [OPTIONS]"
   echo ""
   echo "Options:"
-  echo "      --codename                ubuntu codename, default image name is nnfw/one-devtools:[codename]"
+  echo "      --codename    ubuntu codename, default: ${UBUNTU_CODENAME}"
+  echo "                    default image name is nnfw/one-devtools:[codename]"
   echo "Options can use as docker build option:"
   docker build --help
 }
@@ -14,8 +15,7 @@ DOCKER_FILE_RPATH_BASE="infra/docker"
 DOCKER_BUILD_ARGS=()
 
 # Default setting
-UBUNTU_CODENAME="bionic"
-DOCKER_TAG="latest"
+UBUNTU_CODENAME="focal"
 
 while [[ $# -gt 0 ]]
 do
@@ -29,7 +29,6 @@ do
       ;;
     --codename)
       UBUNTU_CODENAME=$2
-      DOCKER_TAG=$2
       shift 2
       ;;
     -t|--tag)
@@ -43,7 +42,7 @@ do
   esac
 done
 
-DOCKER_IMAGE_NAME=${DOCKER_IMAGE_NAME:-nnfw/one-devtools:$DOCKER_TAG}
+DOCKER_IMAGE_NAME=${DOCKER_IMAGE_NAME:-nnfw/one-devtools:$UBUNTU_CODENAME}
 DOCKER_FILE_RPATH=$DOCKER_FILE_RPATH_BASE/$UBUNTU_CODENAME/Dockerfile
 
 HOST_ARCH=$(uname -m)
index 9a186b3..5a9fa8d 100644 (file)
@@ -1,19 +1,15 @@
 #!/bin/bash
 
 import "docker.configuration"
-USER_MODE=0
 
+# Use host user ID if --user option is given
+# It is useful if host userID is different from docker userID 1000
 if [[ $1 == '--user' ]]; then
   DOCKER_RUN_OPTS+=" -u $(stat -c "%u" $NNAS_PROJECT_PATH):$(stat -c "%g" $NNAS_PROJECT_PATH)"
-  USER_MODE=1
   shift
 fi
 
 docker run ${DOCKER_RUN_OPTS} ${DOCKER_ENV_VARS} ${DOCKER_VOLUMES} ${DOCKER_IMAGE_NAME} "$@"
 EXITCODE=$?
 
-if [ $USER_MODE -eq 0 ]; then
-  docker_cleanup
-fi
-
 exit ${EXITCODE}
diff --git a/infra/command/docker-shell b/infra/command/docker-shell
new file mode 100644 (file)
index 0000000..27e3e2f
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+import "docker.configuration"
+
+DOCKER_RUN_OPTS+=" -it"
+docker run $DOCKER_RUN_OPTS $DOCKER_ENV_VARS $DOCKER_VOLUMES $DOCKER_IMAGE_NAME "/bin/bash"
+EXITCODE=$?
+
+if [ $EXITCODE -ne 0 ]; then
+  exit $EXITCODE
+fi
index 461da6f..1e6f6ad 100644 (file)
@@ -4,8 +4,8 @@ INVALID_EXIT=0
 FILES_TO_CHECK=()
 DIRECTORIES_TO_BE_TESTED=()
 DIRECTORIES_NOT_TO_BE_TESTED=()
-DEFAULT_CLANG_FORMAT="clang-format-8"
-CLANG_FORMAT_CANDIDATES=()
+DEFAULT_CLANG_VERSION="16"
+CLANG_FORMAT_CANDIDATE=clang-format-$DEFAULT_CLANG_VERSION
 PATCH_FILE=format.patch
 CHECK_DIFF_ONLY="0"
 CHECK_STAGED_ONLY="0"
@@ -17,9 +17,10 @@ function Usage()
   echo "If <file>s are given, it reformats the files"
   echo ""
   echo "Options:"
-  echo "      --clang-format <TOOL>     clang format bin (default: $DEFAULT_CLANG_FORMAT)"
-  echo "      --diff-only               check diff files with master"
-  echo "      --staged-only             check git staged files"
+  echo "      --clang-format-version <version>  clang format version (default: ${DEFAULT_CLANG_VERSION})"
+  echo "      --clang-format <TOOL>             clang format bin (default: $DEFAULT_CLANG_FORMAT) (will be deprecated)"
+  echo "      --diff-only                       check diff files with master"
+  echo "      --staged-only                     check git staged files"
 }
 
 while [[ $# -gt 0 ]]
@@ -31,13 +32,18 @@ do
       exit 0
       ;;
     --clang-format)
-      CLANG_FORMAT_CANDIDATES=($2)
+      CLANG_FORMAT_CANDIDATE=$2
       shift 2
       ;;
     --clang-format=*)
-      CLANG_FORMAT_CANDIDATES=(${1#*=})
+      CLANG_FORMAT_CANDIDATE=${1#*=}
       shift
       ;;
+    --clang-format-version)
+      CLANG_FORMAT_CANDIDATE=clang-format-$2
+      CLANG_STYLE_FILE=.clang-format.$2
+      shift 2
+      ;;
     --staged-only)
       CHECK_STAGED_ONLY="1"
       CHECK_DIFF_ONLY="1"
@@ -104,18 +110,15 @@ function check_cpp_files() {
     return
   fi
 
-  CLANG_FORMAT_CANDIDATES+=($DEFAULT_CLANG_FORMAT)
-  for CLANG_FORMAT_CANDIDATE in ${CLANG_FORMAT_CANDIDATES[@]}; do
-    if command_exists ${CLANG_FORMAT_CANDIDATE} ; then
-      CLANG_FORMAT="${CLANG_FORMAT_CANDIDATE}"
-      break
-    fi
-  done
+  if command_exists $CLANG_FORMAT_CANDIDATE ; then
+    CLANG_FORMAT=$CLANG_FORMAT_CANDIDATE
+  fi
 
-  if [[ -z ${CLANG_FORMAT}  ]]; then
-    echo "[ERROR] $CLANG_FORMAT is unavailable"
+  if [[ -z "${CLANG_FORMAT}" ]]; then
+    echo "[ERROR] $CLANG_FORMAT_CANDIDATE is unavailable"
     echo
-    echo "        Please install $DEFAULT_CLANG_FORMAT before running format check"
+    echo "        Please install $CLANG_FORMAT_MIGRATE before running format check (refer https://github.com/Samsung/ONE/issues/12311#issuecomment-1857503157)"
+    echo "        If you use docker for format checking, please pull or build latest version"
     exit 1
   fi
 
@@ -129,7 +132,6 @@ function check_cpp_files() {
   # Skip by '.FORMATDENY' file
   for s in ${DIRECTORIES_NOT_TO_BE_TESTED[@]}; do
     FILES_TO_CHECK_CPP=(${FILES_TO_CHECK_CPP[*]/$s*/})
-    FILES_TO_CHECK_CPP_BY_CLANG_FORMAT_8=(${FILES_TO_CHECK_CPP_BY_CLANG_FORMAT_8[*]/$s*/})
   done
 
   if [[ ${#FILES_TO_CHECK_CPP} -ne 0 ]]; then
@@ -248,7 +250,7 @@ if [[ -s ${PATCH_FILE} ]]; then
 fi
 
 if [[ ${INVALID_EXIT} -ne 0 ]]; then
-  echo "[[FAILED] Invalid format checker exit."
+  echo "[FAILED] Invalid format checker exit."
 fi
 
 exit 1
index c841dc0..3a64dfc 100644 (file)
@@ -69,7 +69,7 @@ done
 # Exclude test files from coverage report
 # Exclude flatbuffer generated files from coverage report
 "${LCOV_PATH}" -r "${EXTRACTED_COVERAGE_INFO_PATH}" -o "${EXCLUDED_COVERAGE_INFO_PATH}" \
-  '*.test.cpp' '*.test.cc' '*/test/*' '*/tests/*' '*_schema_generated.h'
+  '*.test.cpp' '*.test.cc' '*/test/*' '*/tests/*' '*_generated.h' '.test.h' '*/test_models/*'
 
 # Final coverage data
 cp -v ${EXCLUDED_COVERAGE_INFO_PATH} ${COVERAGE_INFO_PATH}
index 2e00137..c551ebf 100644 (file)
@@ -3,7 +3,7 @@
 # Don't run this script
 [[ "${BASH_SOURCE[0]}" == "${0}" ]] && echo "Please don't execute ${BASH_SOURCE[0]}" && exit 1
 
-DOCKER_IMAGE_NAME=${DOCKER_IMAGE_NAME:-nnfw/one-devtools}
+DOCKER_IMAGE_NAME=${DOCKER_IMAGE_NAME:-nnfw/one-devtools:focal}
 echo "Using docker image ${DOCKER_IMAGE_NAME}"
 
 if [ -z "`docker images ${DOCKER_IMAGE_NAME}`" ]; then
@@ -32,21 +32,10 @@ DOCKER_ENV_VARS+=" -e GIT_SSL_NO_VERIFY"
 DOCKER_ENV_VARS+=" -e NNAS_WORKSPACE"
 DOCKER_ENV_VARS+=" -e NNCC_WORKSPACE"
 DOCKER_ENV_VARS+=" -e NNFW_WORKSPACE"
+DOCKER_ENV_VARS+=" -e EXTERNAL_DOWNLOAD_SERVER"
+DOCKER_ENV_VARS+=" -e EXTERNAL_SERVER_USERPWD"
+DOCKER_ENV_VARS+=" -e MODELFILE_SERVER"
 
 DOCKER_RUN_OPTS="${DOCKER_OPTS}"
 DOCKER_RUN_OPTS+=" --rm"
 DOCKER_RUN_OPTS+=" -w ${DOCKER_PATH}"
-
-function docker_cleanup()
-{
-  # Newly created files during during docker run can have different ownership.
-  # This may cause some problems, for example, some jenkins slaves or developers
-  # can't remove built files due to lack of permission.
-  # To address this issue, let's change owner of all files
-  # in nncc to owner of nncc.
-  NNFW_OWNER_UID=$(stat -c "%u" ${HOST_PATH})
-  NNFW_OWNER_GID=$(stat -c "%g" ${HOST_PATH})
-
-  CMD="chown -R ${NNFW_OWNER_UID}:${NNFW_OWNER_GID} ${DOCKER_PATH}"
-  docker run ${DOCKER_RUN_OPTS} ${DOCKER_ENV_VARS} ${DOCKER_VOLUMES} ${DOCKER_IMAGE_NAME} ${CMD}
-}
index c4d3584..f2d5917 100644 (file)
@@ -1,3 +1,39 @@
+one (1.27.1) bionic focal; urgency=medium
+
+  * Command schema supports multiple names.
+  * Fix invalid warning on boolean type option in _onecc_.
+
+ -- seongwoo <mhs4670go@naver.com>  Wed, 10 Jul 2024 16:18:33 +0900
+
+one (1.27.0) bionic focal; urgency=medium
+
+  * Support more Op(s): CircleGRU, CircleRelu0To1
+  *  Support more optimization option(s): `resolve_former_customop`, `--forward_transpose_op`,
+    `fold_shape`, `remove_gather_guard`, `fuse_add_with_conv`, `fold_squeeze`, `fuse_rsqrt`
+  * Support INT4, UINT4 data types
+  * Support 4bit quantization of ONNX fake quantize model
+  * Introduce global configuration target feature
+  * Introduce command schema feature
+  * Use C++17
+
+ -- seongwoo <seongwoo@sw>  Thu, 27 Jun 2024 10:44:00 +0900
+
+one (1.26.0) bionic; urgency=medium
+
+  * Support more Op(s): HardSwish, CumSum, BroadcastTo
+  * Support more optimization option(s): `decompose_softmax`, `decompose_hardswish`, `fuse_slice_with_tconv`,
+    `fuse_mul_with_conv`, `remove_unnecessary_add`, `fuse_horizontal_fc_layers`, `common_subexpression_elimination`,
+    `remove_unnecessary_transpose`
+  * _one-quantize_ supports more option
+    - Requantization option to convert TF2-quantized int8 model to uint8 model (--requantize)
+    - A new option to automatically find mixed-precision configuration (--ampq)
+    - A new option to save calibrated min/max values (--save_min_max)
+    - Add new parameters for moving average calibration (--moving_avg_batch, --moving_avg_const)
+  * Introduce _q-implant_ that writes quantization parameters and weights into the circle model
+  * Introduce _minmax-embedder_ that embeds min/max values into the circle model
+
+ -- seongwoo <mhs4670go@naver.com>  Thu, 21 Dec 2023 08:20:28 +0900
+
 one (1.24.0) bionic; urgency=medium
 
   * Introduce _one-import-onnx_ extension interface
index b5296a0..db35f6d 100644 (file)
@@ -1,8 +1,8 @@
-.TH ONE-CODEGEN "1" "August 2021" "one-codegen version 1.17.0" "User Commands"
+.TH ONE-CODEGEN "1" "July 2024" "one-codegen version 1.28.0" "User Commands"
 .SH NAME
 one-codegen \- geneate codes
 .SH DESCRIPTION
-usage: one\-codegen [\-h] [\-v] [\-C CONFIG] [\-b BACKEND] [\-\-] [COMMANDS FOR BACKEND]
+usage: one\-codegen [\-h] [\-v] [\-C CONFIG] [\-b BACKEND | \-T TARGET] [\-\-] [COMMANDS FOR BACKEND]
 .PP
 \fBone\-codegen\fR is a command line tool for code generation.
 .SH OPTIONS
@@ -21,8 +21,11 @@ run with configuation file
 .TP
 \fB\-b\fR BACKEND, \fB\-\-backend\fR BACKEND
 backend name to use
+.TP
+\fB\-T\fR TARGET, \fB\-\-target\fR TARGET
+run with specific target of the backend
 .SH COPYRIGHT
-Copyright \(co 2020\-2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index b8a85ce..a350b76 100644 (file)
@@ -1,4 +1,4 @@
-.TH ONE-IMPORT-BCQ "1" "August 2021" "one-import-bcq version 1.17.0" "User Commands"
+.TH ONE-IMPORT-BCQ "1" "July 2024" "one-import-bcq version 1.28.0" "User Commands"
 .SH NAME
 one-import-bcq \- convert TensorFlow with BCQ to circle
 .SH DESCRIPTION
@@ -44,7 +44,7 @@ shapes corresponding to \fB\-\-input_arrays\fR, colon\-separated (ex:"1,4,4,3:1,
 \fB\-O\fR OUTPUT_ARRAYS, \fB\-\-output_arrays\fR OUTPUT_ARRAYS
 names of the output arrays, comma\-separated
 .SH COPYRIGHT
-Copyright \(co 2020\-2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index 1953544..5974c5b 100644 (file)
@@ -1,4 +1,4 @@
-.TH ONE-IMPORT-ONNX "1" "August 2021" "one-import-onnx version 1.17.0" "User Commands"
+.TH ONE-IMPORT-ONNX "1" "July 2024" "one-import-onnx version 1.28.0" "User Commands"
 .SH NAME
 one-import-onnx \- convert ONNX to circle
 .SH DESCRIPTION
@@ -8,12 +8,16 @@ usage: one\-import\-onnx [\-h] [\-v] [\-V] [\-C CONFIG] [\-i INPUT_PATH]
 .br
 [\-\-model_format MODEL_FORMAT]
 .br
-[\-\-converter_version CONVERTER_VERSION]
+[\-\-converter_version CONVERTER_VERSION] [\-\-unroll_rnn]
+.br
+[\-\-unroll_lstm] [\-\-keep_io_order] [\-\-disable_ext]
 .br
 [\-\-save_intermediate]
+.br
+[\-\-experimental_disable_batchmatmul_unfold]
 .PP
 \fBone\-import\-onnx\fR is a command line tool to convert ONNX to circle.
-.SH OPTIONS
+.SS "options:"
 .TP
 \fB\-h\fR, \fB\-\-help\fR
 show this help message and exit
@@ -27,9 +31,27 @@ output additional information to stdout or stderr
 \fB\-C\fR CONFIG, \fB\-\-config\fR CONFIG
 run with configuation file
 .TP
+\fB\-\-unroll_rnn\fR
+Unroll RNN operators
+.TP
+\fB\-\-unroll_lstm\fR
+Unroll LSTM operators
+.TP
+\fB\-\-keep_io_order\fR
+Ensure generated circle model preserves the I/O order
+of the original onnx model.
+.TP
+\fB\-\-disable_ext\fR
+Disable one\-import\-onnx\-ext and use legacy onnx\-tf
+package
+.TP
 \fB\-\-save_intermediate\fR
 Save intermediate files to output folder
 .TP
+\fB\-\-experimental_disable_batchmatmul_unfold\fR
+Experimental disable BatchMatMul unfold
+.SS "converter arguments:"
+.TP
 \fB\-i\fR INPUT_PATH, \fB\-\-input_path\fR INPUT_PATH
 full filepath of the input file
 .TP
@@ -46,7 +68,7 @@ names of the output arrays, comma\-separated
 .HP
 \fB\-\-converter_version\fR CONVERTER_VERSION
 .SH COPYRIGHT
-Copyright \(co 2020\-2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index 9f05a88..7b4c4cd 100644 (file)
@@ -1,19 +1,21 @@
-.TH ONE-IMPORT-TF "1" "August 2021" "one-import-tf version 1.17.0" "User Commands"
+.TH ONE-IMPORT-TF "1" "July 2024" "one-import-tf version 1.28.0" "User Commands"
 .SH NAME
 one-import-tf \- convert TensorFlow to circle
 .SH DESCRIPTION
 usage: one\-import\-tf [\-h] [\-v] [\-V] [\-C CONFIG] [\-\-v1 | \-\-v2]
 .br
-[\-\-graph_def | \-\-saved_model | \-\-keras_model]
+[\fB\-\-graph_def | \fB\-\-saved_model\fR | \fB\-\-keras_model]\fR
 .br
 [\-i INPUT_PATH] [\-o OUTPUT_PATH] [\-I INPUT_ARRAYS]
 .br
 [\-s INPUT_SHAPES] [\-O OUTPUT_ARRAYS]
 .br
 [\-\-save_intermediate]
+.br
+[\-\-experimental_disable_batchmatmul_unfold]
 .PP
 \fBone\-import\-tf\fR is a command line tool to convert TensorFlow model to circle.
-.SH OPTIONS
+.SS "options:"
 .TP
 \fB\-h\fR, \fB\-\-help\fR
 show this help message and exit
@@ -30,6 +32,10 @@ run with configuation file
 \fB\-\-save_intermediate\fR
 Save intermediate files to output folder
 .TP
+\fB\-\-experimental_disable_batchmatmul_unfold\fR
+Experimental disable BatchMatMul unfold
+.SS "converter arguments:"
+.TP
 \fB\-\-v1\fR
 use TensorFlow Lite Converter 1.x
 .TP
@@ -55,12 +61,12 @@ full filepath of the output file
 names of the input arrays, comma\-separated
 .TP
 \fB\-s\fR INPUT_SHAPES, \fB\-\-input_shapes\fR INPUT_SHAPES
-shapes corresponding to \fB\-\-input_arrays\fR, colon\-separated (ex:"1,4,4,3:1,20,20,3")
+shapes corresponding to \fB\-\-input_arrays\fR, colonseparated (ex:"1,4,4,3:1,20,20,3")
 .TP
 \fB\-O\fR OUTPUT_ARRAYS, \fB\-\-output_arrays\fR OUTPUT_ARRAYS
 names of the output arrays, comma\-separated
 .SH COPYRIGHT
-Copyright \(co 2020\-2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index ef63146..fbf8715 100644 (file)
@@ -1,4 +1,4 @@
-.TH ONE-IMPORT-TFLITE "1" "August 2021" "one-import-tflite version 1.17.0" "User Commands"
+.TH ONE-IMPORT-TFLITE "1" "July 2024" "one-import-tflite version 1.28.0" "User Commands"
 .SH NAME
 one-import-tflite \- convert TensorFlow lite to circle
 .SH DESCRIPTION
@@ -27,7 +27,7 @@ full filepath of the input file
 \fB\-o\fR OUTPUT_PATH, \fB\-\-output_path\fR OUTPUT_PATH
 full filepath of the output file
 .SH COPYRIGHT
-Copyright \(co 2020\-2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index 674e9ad..168cce6 100644 (file)
@@ -1,4 +1,4 @@
-.TH ONE-IMPORT "1" "August 2021" "one-import version 1.17.0" "User Commands"
+.TH ONE-IMPORT "1" "July 2024" "one-import version 1.28.0" "User Commands"
 .SH NAME
 one-import \- convert various format to circle
 .SH SYNOPSIS
@@ -18,7 +18,7 @@ run with configuation file
 .TP
 \fBdriver\fR driver name to run (supported: tf, tflite, bcq, onnx)
 .SH COPYRIGHT
-Copyright \(co 2020\-2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index a1bafbb..0bdd351 100644 (file)
@@ -1,6 +1,6 @@
-.TH ONE-INFER "1" "July 2022" "one-infer version 1.21.0" "User Commands"
+.TH ONE-INFER "1" "July 2024" "one-infer version 1.28.0" "User Commands"
 .SH NAME
-one-infer \- manual page for one-infer version 1.21.0
+one-infer \- infer backend binary file
 .SH DESCRIPTION
 usage: one\-infer [\-h] [\-v] [\-C CONFIG] [\-d DRIVER | \fB\-b\fR BACKEND] [\-\-post\-process POST_PROCESS] [\-\-] [COMMANDS FOR BACKEND DRIVER]
 .PP
@@ -29,7 +29,7 @@ backend name to use
 post processing script to convert I/O data to standard
 format
 .SH COPYRIGHT
-Copyright \(co 2020\-2022 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index 58b2c60..bd6eb98 100644 (file)
@@ -1,4 +1,4 @@
-.TH ONE-OPTIMIZE "1" "August 2021" "one-optimize version 1.17.0" "User Commands"
+.TH ONE-OPTIMIZE "1" "July 2024" "one-optimize version 1.28.0" "User Commands"
 .SH NAME
 one-optimize \- optimize circle model
 .SH DESCRIPTION
@@ -6,33 +6,55 @@ usage: one\-optimize [\-h] [\-v] [\-V] [\-C CONFIG] [\-p]
 .br
 [\-\-change_outputs CHANGE_OUTPUTS] [\-i INPUT_PATH]
 .br
-[\-o OUTPUT_PATH] [\-\-O1] [\-\-convert_nchw_to_nhwc]
+[\-o OUTPUT_PATH] [\-\-convert_nchw_to_nhwc]
 .br
-[\-\-nchw_to_nhwc_input_shape] [\-\-nchw_to_nhwc_output_shape]
+[\-\-common_subexpression_elimination]
 .br
-[\-\-fold_add_v2] [\-\-fold_cast] [\-\-fold_dequantize]
+[\-\-expand_broadcast_const] [\-\-nchw_to_nhwc_input_shape]
 .br
-[\-\-fold_sparse_to_dense] [\-\-forward_reshape_to_unaryop]
+[\-\-nchw_to_nhwc_output_shape] [\-\-fold_add_v2]
 .br
-[\-\-fuse_add_with_tconv] [\-\-fuse_batchnorm_with_conv]
+[\-\-fold_cast] [\-\-fold_densify] [\-\-fold_dequantize]
+.br
+[\-\-fold_dwconv] [\-\-fold_fully_connected] [\-\-fold_gather]
+.br
+[\-\-fold_reshape] [\-\-fold_shape] [\-\-fold_sparse_to_dense]
+.br
+[\-\-fold_squeeze] [\-\-forward_reshape_to_unaryop]
+.br
+[\-\-forward_transpose_op] [\-\-fuse_add_with_conv]
+.br
+[\-\-fuse_add_with_tconv] [\-\-fuse_add_with_fully_connected]
+.br
+[\-\-fuse_batchnorm_with_conv]
 .br
 [\-\-fuse_batchnorm_with_dwconv]
 .br
-[\-\-fuse_batchnorm_with_tconv] [\-\-fuse_bcq]
+[\-\-fuse_batchnorm_with_tconv] [\-\-fuse_slice_with_tconv]
+.br
+[\-\-fuse_bcq] [\-\-fuse_preactivation_batchnorm]
+.br
+[\-\-fuse_mean_with_mean] [\-\-fuse_mul_with_conv]
 .br
-[\-\-fuse_preactivation_batchnorm]
+[\-\-fuse_mul_with_div] [\-\-fuse_transpose_with_mean]
+.br
+[\-\-fuse_horizontal_fc_layers]
 .br
 [\-\-make_batchnorm_gamma_positive]
 .br
 [\-\-fuse_activation_function] [\-\-fuse_instnorm]
 .br
+[\-\-fuse_prelu] [\-\-fuse_gelu] [\-\-fuse_rsqrt]
+.br
 [\-\-replace_cw_mul_add_with_depthwise_conv]
 .br
-[\-\-remove_fakequant] [\-\-remove_quantdequant]
+[\-\-remove_fakequant] [\-\-remove_gather_guard]
+.br
+[\-\-remove_quantdequant] [\-\-remove_redundant_quantize]
 .br
 [\-\-remove_redundant_reshape]
 .br
-[\-\-remove_redundant_transpose]
+[\-\-remove_redundant_transpose] [\-\-remove_unnecessary_add]
 .br
 [\-\-remove_unnecessary_reshape]
 .br
@@ -40,26 +62,46 @@ usage: one\-optimize [\-h] [\-v] [\-V] [\-C CONFIG] [\-p]
 .br
 [\-\-remove_unnecessary_strided_slice]
 .br
-[\-\-remove_unnecessary_split] [\-\-resolve_customop_add]
+[\-\-remove_unnecessary_split]
+.br
+[\-\-remove_unnecessary_transpose]
 .br
-[\-\-resolve_customop_batchmatmul]
+[\-\-replace_non_const_fc_with_batch_matmul]
+.br
+[\-\-replace_sub_with_add] [\-\-replace_with_fc_gelu_fc]
+.br
+[\-\-resolve_customop_add] [\-\-resolve_customop_batchmatmul]
 .br
 [\-\-resolve_customop_matmul]
 .br
+[\-\-resolve_customop_max_pool_with_argmax]
+.br
+[\-\-resolve_customop_splitv]
+.br
 [\-\-shuffle_weight_to_16x1float32]
 .br
-[\-\-substitute_pack_to_reshape]
+[\-\-substitute_pack_to_reshape] [\-\-substitute_padv2_to_pad]
+.br
+[\-\-substitute_splitv_to_split]
 .br
 [\-\-substitute_squeeze_to_reshape]
 .br
+[\-\-substitute_strided_slice_to_reshape]
+.br
 [\-\-substitute_transpose_to_reshape]
 .br
 [\-\-transform_min_max_to_relu6]
 .br
 [\-\-transform_min_relu_to_relu6]
+.br
+[\-\-transform_sqrt_div_to_rsqrt_mul]
+.br
+[\-\-decompose_hardswish] [\-\-decompose_softmax]
+.br
+[\-\-unroll_unidirseqlstm] [\-\-dynamic_batch_to_single_batch]
 .PP
 \fBone\-optimize\fR is a command line tool to optimize circle model.
-.SH OPTIONS
+.SS "options:"
 .TP
 \fB\-h\fR, \fB\-\-help\fR
 show this help message and exit
@@ -88,13 +130,16 @@ full filepath of the input file
 \fB\-o\fR OUTPUT_PATH, \fB\-\-output_path\fR OUTPUT_PATH
 full filepath of the output file
 .TP
-\fB\-\-O1\fR
-enable O1 optimization pass
-.TP
 \fB\-\-convert_nchw_to_nhwc\fR
 Experimental: This will convert NCHW operators to NHWC
 under the assumption that input model is NCHW.
 .TP
+\fB\-\-common_subexpression_elimination\fR
+perform common subexpression elimination
+.TP
+\fB\-\-expand_broadcast_const\fR
+expand broadcastable constant node inputs
+.TP
 \fB\-\-nchw_to_nhwc_input_shape\fR
 convert the input shape of the model (argument for
 convert_nchw_to_nhwc)
@@ -109,17 +154,47 @@ fold AddV2 op with constant inputs
 \fB\-\-fold_cast\fR
 fold Cast op with constant input
 .TP
+\fB\-\-fold_densify\fR
+fold Densify op with sparse constant input
+.TP
 \fB\-\-fold_dequantize\fR
 fold Dequantize op
 .TP
+\fB\-\-fold_dwconv\fR
+fold Depthwise Convolution op with constant inputs
+.TP
+\fB\-\-fold_fully_connected\fR
+fold FullyConnected op with constant inputs
+.TP
+\fB\-\-fold_gather\fR
+fold Gather op
+.TP
+\fB\-\-fold_reshape\fR
+fold Reshape op
+.TP
+\fB\-\-fold_shape\fR
+fold Shape op
+.TP
 \fB\-\-fold_sparse_to_dense\fR
 fold SparseToDense op
 .TP
+\fB\-\-fold_squeeze\fR
+fold Squeeze op
+.TP
 \fB\-\-forward_reshape_to_unaryop\fR
 Forward Reshape op
 .TP
+\fB\-\-forward_transpose_op\fR
+Forward Transpose op
+.TP
+\fB\-\-fuse_add_with_conv\fR
+fuse Add op to Convolution op
+.TP
 \fB\-\-fuse_add_with_tconv\fR
-fuse Add op to Transposed Convolution op
+fuse Add op to Transposed
+.TP
+\fB\-\-fuse_add_with_fully_connected\fR
+fuse Add op to FullyConnected op
 .TP
 \fB\-\-fuse_batchnorm_with_conv\fR
 fuse BatchNorm op to Convolution op
@@ -130,6 +205,9 @@ fuse BatchNorm op to Depthwise Convolution op
 \fB\-\-fuse_batchnorm_with_tconv\fR
 fuse BatchNorm op to Transposed Convolution op
 .TP
+\fB\-\-fuse_slice_with_tconv\fR
+fuse Slice op to Transposed Convolution op
+.TP
 \fB\-\-fuse_bcq\fR
 apply Binary Coded Quantization
 .TP
@@ -137,6 +215,23 @@ apply Binary Coded Quantization
 fuse BatchNorm operators of pre\-activations to
 Convolution op
 .TP
+\fB\-\-fuse_mean_with_mean\fR
+fuse two consecutive Mean ops
+.TP
+\fB\-\-fuse_mul_with_conv\fR
+fuse Mul op to Convolution op
+.TP
+\fB\-\-fuse_mul_with_div\fR
+fuse Mul with Div as Div
+.TP
+\fB\-\-fuse_transpose_with_mean\fR
+fuse Mean with a preceding Transpose under certain
+conditions
+.TP
+\fB\-\-fuse_horizontal_fc_layers\fR
+fuse horizontal FullyConnected layers under certain
+conditions
+.TP
 \fB\-\-make_batchnorm_gamma_positive\fR
 make negative gamma of BatchNorm to a small positive
 value (1e\-10). Note that this pass can change the
@@ -149,21 +244,41 @@ fuse Activation function to a preceding operator
 \fB\-\-fuse_instnorm\fR
 fuse ops to InstanceNorm operator
 .TP
+\fB\-\-fuse_prelu\fR
+fuse ops to PReLU operator
+.TP
+\fB\-\-fuse_gelu\fR
+fuse ops to GeLU operator
+.TP
+\fB\-\-fuse_rsqrt\fR
+fuse ops to Rsqrt operator
+.TP
 \fB\-\-replace_cw_mul_add_with_depthwise_conv\fR
 replace channel\-wise Mul/Add with DepthwiseConv2D
 .TP
 \fB\-\-remove_fakequant\fR
 remove FakeQuant ops
 .TP
+\fB\-\-remove_gather_guard\fR
+remove Add/FloorMod guards of Gather indices with
+certain conditions. CAUTION: user must guarantee that
+indices are all non\-negative values.
+.TP
 \fB\-\-remove_quantdequant\fR
 remove Quantize\-Dequantize sequence
 .TP
+\fB\-\-remove_redundant_quantize\fR
+remove redundant Quantize ops
+.TP
 \fB\-\-remove_redundant_reshape\fR
 fuse or remove subsequent Reshape ops
 .TP
 \fB\-\-remove_redundant_transpose\fR
 fuse or remove subsequent Transpose ops
 .TP
+\fB\-\-remove_unnecessary_add\fR
+remove unnecessary add ops
+.TP
 \fB\-\-remove_unnecessary_reshape\fR
 remove unnecessary reshape ops
 .TP
@@ -176,6 +291,19 @@ remove unnecessary strided slice ops
 \fB\-\-remove_unnecessary_split\fR
 remove unnecessary split ops
 .TP
+\fB\-\-remove_unnecessary_transpose\fR
+remove unnecessary transpose ops
+.TP
+\fB\-\-replace_non_const_fc_with_batch_matmul\fR
+replace FullyConnected op with non\-const weights to
+BatchMatMul op
+.TP
+\fB\-\-replace_sub_with_add\fR
+replace Sub op with Add op
+.TP
+\fB\-\-replace_with_fc_gelu_fc\fR
+replace a certain pattern with FC\-Gelu\-FC ops
+.TP
 \fB\-\-resolve_customop_add\fR
 convert Custom(Add) op to Add op
 .TP
@@ -185,6 +313,13 @@ convert Custom(BatchMatmul) op to BatchMatmul op
 \fB\-\-resolve_customop_matmul\fR
 convert Custom(Matmul) op to Matmul op
 .TP
+\fB\-\-resolve_customop_max_pool_with_argmax\fR
+convert Custom(MaxPoolWithArgmax) to net of builtin
+operators
+.TP
+\fB\-\-resolve_customop_splitv\fR
+convert Custom(SplitV) op to SplitV op
+.TP
 \fB\-\-shuffle_weight_to_16x1float32\fR
 convert weight format of FullyConnected op to
 SHUFFLED16x1FLOAT32. Note that it only converts
@@ -193,9 +328,18 @@ weights whose row is a multiple of 16
 \fB\-\-substitute_pack_to_reshape\fR
 convert single input Pack op to Reshape op
 .TP
+\fB\-\-substitute_padv2_to_pad\fR
+convert certain condition PadV2 to Pad
+.TP
+\fB\-\-substitute_splitv_to_split\fR
+convert certain condition SplitV to Split
+.TP
 \fB\-\-substitute_squeeze_to_reshape\fR
 convert certain condition Squeeze to Reshape
 .TP
+\fB\-\-substitute_strided_slice_to_reshape\fR
+convert certain condition StridedSlice to Reshape
+.TP
 \fB\-\-substitute_transpose_to_reshape\fR
 convert certain condition Transpose to Reshape
 .TP
@@ -204,8 +348,25 @@ transform Minimum\-Maximum pattern to Relu6 op
 .TP
 \fB\-\-transform_min_relu_to_relu6\fR
 transform Minimum(6)\-Relu pattern to Relu6 op
+.TP
+\fB\-\-transform_sqrt_div_to_rsqrt_mul\fR
+transform Sqrt\-Div pattern to Rsqrt\-Mul ops
+.TP
+\fB\-\-decompose_hardswish\fR
+decompose the HardSwish op to Add, Mul and Relu6 ops
+.TP
+\fB\-\-decompose_softmax\fR
+decompose the Softmax op to Max, Sub, Exp, Sum, Div
+and optionally Mul ops
+.TP
+\fB\-\-unroll_unidirseqlstm\fR
+unroll UnidirectionalSequenceLSTM op
+.TP
+\fB\-\-dynamic_batch_to_single_batch\fR
+convert dynamic batch size (first dimension) of inputs
+to 1
 .SH COPYRIGHT
-Copyright \(co 2020\-2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index dd04221..dca8a1f 100644 (file)
@@ -1,4 +1,4 @@
-.TH ONE-PACK "1" "August 2021" "one-pack version 1.17.0" "User Commands"
+.TH ONE-PACK "1" "July 2024" "one-pack version 1.28.0" "User Commands"
 .SH NAME
 one-pack \- package circle and metadata into nnpackage
 .SH DESCRIPTION
@@ -25,7 +25,7 @@ full filepath of the input file
 \fB\-o\fR OUTPUT_PATH, \fB\-\-output_path\fR OUTPUT_PATH
 full filepath of the output file
 .SH COPYRIGHT
-Copyright \(co 2020\-2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index 5b6fe93..3bd8169 100644 (file)
@@ -1,11 +1,12 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.47.6.
-.TH ONE-PARTITION "1" "June 2022" "one-partition version 1.21.0" "User Commands"
+.TH ONE-PARTITION "1" "July 2024" "one-partition version 1.28.0" "User Commands"
 .SH NAME
-one-partition \- manual page for one-partition version 1.21.0
+one-partition \- partition circle model by multiple backends
 .SH DESCRIPTION
 usage: one\-partition [\-h] [\-v] [\-V] [\-C CONFIG] [\-\-backends BACKENDS]
-.TP
+.br
 [\-\-default DEFAULT] [\-\-part_file PART_FILE]
+.br
 [\-\-input_file INPUT_FILE] [\-\-work_path WORK_PATH]
 .PP
 command line tool to partition circle model by multiple backends
@@ -39,7 +40,7 @@ input circle model filename
 work path of partition, input files exist and output
 files are produced
 .SH COPYRIGHT
-Copyright \(co 2020\-2022 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index 3952c44..011a0b4 100644 (file)
@@ -1,8 +1,8 @@
-.TH ONE-PROFILE "1" "August 2021" "one-profile version 1.17.0" "User Commands"
+.TH ONE-PROFILE "1" "July 2024" "one-profile version 1.28.0" "User Commands"
 .SH NAME
 one-profile \- profile backend model file
 .SH DESCRIPTION
-usage: one\-profile [\-h] [\-v] [\-V] [\-C CONFIG] [\-b BACKEND] [\-\-] [COMMANDS FOR BACKEND]
+usage: one\-profile [\-h] [\-v] [\-C CONFIG] [\-b BACKEND | \-T TARGET] [\-\-] [COMMANDS FOR BACKEND]
 .PP
 \fBone\-profile\fR is a command line tool for profiling backend model.
 .SH OPTIONS
@@ -21,8 +21,11 @@ run with configuation file
 .TP
 \fB\-b\fR BACKEND, \fB\-\-backend\fR BACKEND
 backend name to use
+.TP
+\fB\-T\fR TARGET, \fB\-\-target\fR TARGET
+run with specific target of the backend
 .SH COPYRIGHT
-Copyright \(co 2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2021\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index 43c4c03..8d34e87 100644 (file)
@@ -1,4 +1,4 @@
-.TH ONE-QUANTIZE "1" "August 2021" "one-quantize version 1.17.0" "User Commands"
+.TH ONE-QUANTIZE "1" "July 2024" "one-quantize version 1.28.0" "User Commands"
 .SH NAME
 one-quantize \- quantize circle model
 .SH DESCRIPTION
@@ -6,18 +6,58 @@ usage: one\-quantize [\-h] [\-v] [\-V] [\-C CONFIG] [\-i INPUT_PATH] [\-d INPUT_
 .br
 [\-f INPUT_DATA_FORMAT] [\-o OUTPUT_PATH] [\-p]
 .br
-[\-\-input_dtype INPUT_DTYPE]
+[\-\-save_intermediate] [\-\-input_dtype INPUT_DTYPE]
+.br
+[\-\-input_model_dtype INPUT_MODEL_DTYPE]
 .br
 [\-\-quantized_dtype QUANTIZED_DTYPE]
 .br
-[\-\-granularity GRANULARITY]
+[\-\-granularity GRANULARITY] [\-\-input_type INPUT_TYPE]
+.br
+[\-\-output_type OUTPUT_TYPE]
 .br
 [\-\-min_percentile MIN_PERCENTILE]
 .br
-[\-\-max_percentile MAX_PERCENTILE] [\-\-mode MODE]
+[\-\-max_percentile MAX_PERCENTILE]
+.br
+[\-\-moving_avg_batch MOVING_AVG_BATCH]
+.br
+[\-\-moving_avg_const MOVING_AVG_CONST] [\-\-mode MODE]
+.br
+[\-\-TF\-style_maxpool] [\-\-save_min_max]
+.br
+[\-\-quant_config QUANT_CONFIG] [\-\-evaluate_result]
+.br
+[\-\-test_data TEST_DATA] [\-\-print_mae] [\-\-print_mape]
+.br
+[\-\-print_mpeir] [\-\-print_top1_match] [\-\-print_top5_match]
+.br
+[\-\-print_mse] [\-\-force_quantparam]
+.br
+[\-\-tensor_name TENSOR_NAME] [\-\-scale SCALE]
+.br
+[\-\-zero_point ZERO_POINT] [\-\-copy_quantparam]
+.br
+[\-\-src_tensor_name SRC_TENSOR_NAME]
+.br
+[\-\-dst_tensor_name DST_TENSOR_NAME] [\-\-fake_quantize]
+.br
+[\-\-requantize] [\-\-ampq]
+.br
+[\-\-ampq_qerror_ratio AMPQ_QERROR_RATIO]
+.br
+[\-\-ampq_algorithm AMPQ_ALGORITHM]
+.br
+[\-\-bisection_type BISECTION_TYPE]
+.br
+[\-\-u8_layernorm_with_s16_variance]
+.br
+[\-\-u8_softmax_with_s16_sub_exp]
+.br
+[\-\-ampq_bisection_visq AMPQ_BISECTION_VISQ]
 .PP
 \fBone\-quantize\fR is a command line tool to quantize circle model.
-.SH OPTIONS
+.SS "options:"
 .TP
 \fB\-h\fR, \fB\-\-help\fR
 show this help message and exit
@@ -32,41 +72,194 @@ output additional information to stdout or stderr
 run with configuation file
 .TP
 \fB\-i\fR INPUT_PATH, \fB\-\-input_path\fR INPUT_PATH
-full filepath of the input file
+full filepath of the input circle model
 .TP
 \fB\-d\fR INPUT_DATA, \fB\-\-input_data\fR INPUT_DATA
-full filepath of the input data file. if not
-specified, run with random input data.
+full filepath of the input data used for post\-training
+quantization. if not specified, run with random input
+data.
+.TP
+\fB\-f\fR INPUT_DATA_FORMAT, \fB\-\-input_data_format\fR INPUT_DATA_FORMAT
+file format of input data. h5/hdf5 (default),
+list/filelist (a text file where a file path of input
+data is written in each line), or dir/directory (a
+directory where input data are saved)
 .TP
 \fB\-o\fR OUTPUT_PATH, \fB\-\-output_path\fR OUTPUT_PATH
-full filepath of the output file
+full filepath of the output quantized model
 .TP
 \fB\-p\fR, \fB\-\-generate_profile_data\fR
 generate profiling data
+.TP
+\fB\-\-save_intermediate\fR
+Save intermediate files to output folder
 .SS "arguments for quantization:"
 .TP
 \fB\-\-input_dtype\fR INPUT_DTYPE
-input data type (supported: float32, default=float32)
+input model data type (supported: float32,
+default=float32). Deprecated (Use input_model_dtype)
+.TP
+\fB\-\-input_model_dtype\fR INPUT_MODEL_DTYPE
+input model data type (supported: float32,
+default=float32)
 .TP
 \fB\-\-quantized_dtype\fR QUANTIZED_DTYPE
-output quantized data type (supported: uint8, int16,
-default=uint8)
+data type of output quantized model (supported: uint8,
+int16, default=uint8)
 .TP
 \fB\-\-granularity\fR GRANULARITY
-quantize granularity (supported: layer, channel,
-default=layer)
+weight quantization granularity (supported: layer,
+channel, default=layer). Activation is quantized per
+layer.
+.TP
+\fB\-\-input_type\fR INPUT_TYPE
+data type of inputs of quantized model (supported:
+uint8, int16, float32, default=quantized_dtype).
+QUANTIZE Op will be inserted at the beginning of the
+quantized model if input_type is different from
+quantized_dtype.
+.TP
+\fB\-\-output_type\fR OUTPUT_TYPE
+data type of outputs of quantized model (supported:
+uint8, int16, float32, default=quantized_dtype).
+QUANTIZE Op will be inserted at the end of the
+quantized model if output_type is different from
+quantized_dtype.
 .TP
 \fB\-\-min_percentile\fR MIN_PERCENTILE
-minimum percentile (0.0~100.0, default=1.0)
+minimum percentile (0.0~100.0, default=1.0). Algorithm
+parameter for calibration. This is valid when
+calibration algorithm is percentile.
 .TP
 \fB\-\-max_percentile\fR MAX_PERCENTILE
-maximum percentile (0.0~100.0, default=99.0)
+maximum percentile (0.0~100.0, default=99.0).
+Algorithm parameter for calibration. This is valid
+when calibration algorithm is percentile.
+.TP
+\fB\-\-moving_avg_batch\fR MOVING_AVG_BATCH
+batch size of moving average (default=16). This is
+valid when calibration algorithm is moving_average.
+.TP
+\fB\-\-moving_avg_const\fR MOVING_AVG_CONST
+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.
 .TP
 \fB\-\-mode\fR MODE
-record mode (supported: percentile/moving_average,
-default=percentile)
+calibration algorithm for post\-training quantization
+(supported: percentile/moving_average,
+default=percentile). 'percentile' mode uses the n\-th
+percentiles as min/max values. 'moving_average' mode
+records the moving average of min/max.
+.TP
+\fB\-\-TF\-style_maxpool\fR
+Force MaxPool Op to have the same input/output
+quantparams. NOTE: This option can degrade accuracy of
+some models.)
+.TP
+\fB\-\-save_min_max\fR
+Save min/max of each tensor. NOTE: Min/max valuse are
+clipped according to calibration algorithms, such as
+percentile or moving average. Nudge adjustment is not
+applied.
+.TP
+\fB\-\-quant_config\fR QUANT_CONFIG
+Path to the quantization configuration file.
+.TP
+\fB\-\-evaluate_result\fR
+Evaluate accuracy of quantized model. Run inference
+for both fp32 model and the quantized model, and
+compare the inference results.
+.TP
+\fB\-\-test_data\fR TEST_DATA
+Path to the test data used for evaluation.
+.TP
+\fB\-\-print_mae\fR
+Print MAE (Mean Absolute Error) of inference results
+between quantized model and fp32 model.
+.TP
+\fB\-\-print_mape\fR
+Print MAPE (Mean Absolute Percentage Error) of
+inference results between quantized model and fp32
+model.
+.TP
+\fB\-\-print_mpeir\fR
+Print MPEIR (Mean Peak Error to Interval Ratio) of
+inference results between quantized model and fp32
+model.
+.TP
+\fB\-\-print_top1_match\fR
+Print Top\-1 match ratio of inference results between
+quantized model and fp32 model.
+.TP
+\fB\-\-print_top5_match\fR
+Print Top\-5 match ratio of inference results between
+quantized model and fp32 model.
+.TP
+\fB\-\-print_mse\fR
+Print MSE (Mean Squared Error) of inference results
+between quantized model and fp32 model.
+.SS "arguments for force_quantparam option:"
+.TP
+\fB\-\-force_quantparam\fR
+overwrite quantparam (scale, zero_point) to the
+specified tensor in the quantized model.
+.TP
+\fB\-\-tensor_name\fR TENSOR_NAME
+tensor name (string)
+.TP
+\fB\-\-scale\fR SCALE
+scale (float)
+.TP
+\fB\-\-zero_point\fR ZERO_POINT
+zero point (int)
+.SS "arguments for copy_quantparam option:"
+.TP
+\fB\-\-copy_quantparam\fR
+copy quantparam (scale, zero_point) of a tensor to
+another tensor.
+.TP
+\fB\-\-src_tensor_name\fR SRC_TENSOR_NAME
+tensor name (string)
+.TP
+\fB\-\-dst_tensor_name\fR DST_TENSOR_NAME
+tensor name (string)
+.SS "arguments for fake_quantize option:"
+.TP
+\fB\-\-fake_quantize\fR
+convert quantized model to fake\-quantized fp32 model.
+.SS "arguments for requantize option:"
+.TP
+\fB\-\-requantize\fR
+convert quantized model to another\-typed quantized
+model (ex: int8 \-> uin8).
+.SS "arguments for ampq option:"
+.TP
+\fB\-\-ampq\fR
+quantize model using ampq solver.
+.TP
+\fB\-\-ampq_qerror_ratio\fR AMPQ_QERROR_RATIO
+quantization error ratio ([0, 1])
+.TP
+\fB\-\-ampq_algorithm\fR AMPQ_ALGORITHM
+type of algorithm (bisection, pattern)
+.TP
+\fB\-\-bisection_type\fR BISECTION_TYPE
+one of 'auto', 'i16_front', 'i16_back'
+.TP
+\fB\-\-u8_layernorm_with_s16_variance\fR
+Use int16 for computing variance in uint8 layer
+normalization
+.TP
+\fB\-\-u8_softmax_with_s16_sub_exp\fR
+Use int16 for computing Sub and Exp nodes in uint8
+Softmax
+.TP
+\fB\-\-ampq_bisection_visq\fR AMPQ_BISECTION_VISQ
+\&.visq.json file path with quantization errors
 .SH COPYRIGHT
-Copyright \(co 2020\-2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index 352b30a..4c20241 100644 (file)
@@ -1,10 +1,10 @@
 .\" Manpage for onecc.
 .\" Contact nnfw@samsung.com to correct errors or typos.
-.TH ONECC "1" "August 2021" "onecc version 1.17.0" "User Commands"
+.TH ONECC "1" "July 2024" "onecc version 1.28.0" "User Commands"
 .SH NAME
 onecc \- run ONE driver via several commands or configuration file
 .SH SYNOPSIS
-\fBonecc\fR [\-h] [\-v] [\-C CONFIG] [COMMAND <args>]
+\fBonecc\fR [\-h] [\-v] [\-C CONFIG | \-W WORKFLOW] [\-b BACKEND | \-T TARGET] [\-O OPTIMIZATION] [COMMAND <args>]
 .SH DESCRIPTION
 \fBonecc\fR is a command line tool to execute ONE driver via several commands or configuration file.
 .SS "Configuration file:"
@@ -24,6 +24,18 @@ output additional information to stdout or stderr
 .TP
 \fB\-C\fR CONFIG, \fB\-\-config\fR CONFIG
 run with configuation file
+.TP
+\fB\-O\fR OPTIMIZATION
+optimization name to use
+.TP
+\fB\-W\fR WORKFLOW, \fB\-\-workflow\fR CONFIG
+run with workflow file
+.TP
+\fB\-B\fR BACKEND, \fB\-\-backend\fR CONFIG
+generate code for given backend
+.TP
+\fB\-T\fR TARGET, \fB\-\-target\fR CONFIG
+run with specific target of the backend
 .SS compile to circle model
 .TP
 \fBimport\fR
@@ -45,6 +57,9 @@ Code generation tool. See one-codegen(1) for details.
 .TP
 \fBprofile\fR
 Profile backend model file. See one-profile(1) for details.
+.TP
+\fBinfer\fR
+Infer backend model file. See one-infer(1) for details.
 .SH EXAMPLES
 .SS Use command line interface
 .TP
@@ -71,6 +86,9 @@ generate backend code
 .TP
 \fBonecc profile -b\fR \fIbackend\fR \fB--\fR \fIbackends_arguments\fR
 profile backend model
+.TP
+\fBonecc infer -b\fR \fIbackend\fR \fB--\fR \fIbackends_arguments\fR
+infer backend model
 .PP
 .SS Use configuration file
 .PP
@@ -95,6 +113,8 @@ one-pack=True
 one-codegen=True
 .br
 one-profile=True
+.br
+one-infer=True
 .IP
 [one-import-tf]
 .br
@@ -145,6 +165,12 @@ command=-o sample.out inception_v3.quantized.circle
 backend=dummy
 .br
 command=sample.out
+.IP
+[one-infer]
+.br
+backend=dummy
+.br
+command=sample.out
 .TP
 \fBonecc -C\fR \fIconfiguration file\fR
 Run ONE driver according to configuration section parameter
@@ -152,7 +178,7 @@ Run ONE driver according to configuration section parameter
 \fBonecc\fR section decides whether to use each driver or not.
 If the value is False, even if the corresponding section exists, the driver won't be executed.
 .SH COPYRIGHT
-Copyright \(co 2020\-2021 Samsung Electronics Co., Ltd. All Rights Reserved
+Copyright \(co 2020\-2024 Samsung Electronics Co., Ltd. All Rights Reserved
 Licensed under the Apache License, Version 2.0
 https://github.com/Samsung/ONE
 .SH "SEE ALSO"
index 700cc2d..5b16967 100644 (file)
@@ -16,6 +16,7 @@ usr/bin/onecc.template.cfg usr/share/one/bin/
 usr/bin/one-build usr/share/one/bin/
 usr/bin/one-build.template.cfg usr/share/one/bin/
 usr/bin/one-codegen usr/share/one/bin/
+usr/bin/one-create-quant-dataset usr/share/one/bin/
 usr/bin/one-import usr/share/one/bin/
 usr/bin/one-import-bcq usr/share/one/bin/
 usr/bin/one-import-onnx usr/share/one/bin/
@@ -29,6 +30,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/argumentparse.py usr/share/one/bin/onelib/
 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/
index 9e46435..56a40bf 100644 (file)
@@ -3,6 +3,7 @@ usr/share/one/bin/one-build usr/bin/one-build
 usr/share/one/bin/onecc usr/bin/onecc
 # lib
 usr/share/one/lib/libloco.so usr/lib/libloco.so
+usr/share/one/lib/libluci_compute.so usr/lib/libluci_compute.so
 usr/share/one/lib/libluci_env.so usr/lib/libluci_env.so
 usr/share/one/lib/libluci_export.so usr/lib/libluci_export.so
 usr/share/one/lib/libluci_import.so usr/lib/libluci_import.so
index d84e8e0..74245df 100644 (file)
@@ -5,8 +5,15 @@
 
 set -e
 
-# This script is invoked as root except environmental variables,
+# `postinst` script is invoked as root except given environmental variables specified in the w option,
 # which causes invalid permission problem.
 # e.g. When `pip` installs user packages, it proceeds based on $HOME.
 # To proper installation, $HOME should be root.
-su - $(whoami) -p -c '/usr/share/one/bin/one-prepare-venv' # $(whoami) = root
+CODENAME=$(awk -F "=" '/UBUNTU_CODENAME/ {print $2}' /etc/os-release)
+if [[ $CODENAME == "bionic" ]]; then
+  # Ubuntu 18.04 doesn't support w option.
+  su - $(whoami) -p -c '/usr/share/one/bin/one-prepare-venv' # $(whoami) = root
+else
+  su - $(whoami) -w ONE_PREPVENV_TORCH_SOURCE -c '/usr/share/one/bin/one-prepare-venv' # $(whoami) = root
+fi
+
index e83680d..fb5ddb3 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/make -f
 export DH_VERBOSE = 1
 export NNAS_BUILD_PREFIX = build
-export PRESET = 20230413
+export PRESET = 20230907
 export _DESTDIR = debian/tmp/usr
 
 %:
index 20543ba..c231a55 100644 (file)
@@ -2,7 +2,7 @@ Source: one
 Section: devel
 Priority: extra
 Maintainer: Neural Network Acceleration Solution Developers <nnfw@samsung.com>
-Build-Depends: cmake, debhelper (>=9), dh-python, python3-all
+Build-Depends: cmake, debhelper (>=9), dh-python, python3-all, libboost-all-dev, libhdf5-dev
 Standards-Version: 3.9.8
 Homepage: https://github.com/Samsung/ONE
 
@@ -17,3 +17,9 @@ Architecture: amd64
 Multi-Arch: same
 Depends: nnfw, ${shlibs:Depends}, ${misc:Depends}
 Description: one-runtime development package
+
+Package: nnfw-plugin-dev
+Architecture: amd64
+Multi-Arch: same
+Depends: nnfw, nnfw-dev, ${shlibs:Depends}, ${misc:Depends}
+Description: one-runtime development package
diff --git a/infra/debian/runtime/nnfw-plugin-dev.install b/infra/debian/runtime/nnfw-plugin-dev.install
new file mode 100644 (file)
index 0000000..1f19e54
--- /dev/null
@@ -0,0 +1,3 @@
+# {FILES_TO_INSTALL} {DEST_DIR}
+usr/include/onert usr/include/
+usr/lib/pkgconfig/nnfw-plugin.pc usr/lib/pkgconfig/
index 44be07c..ede8cf7 100644 (file)
@@ -1,3 +1,6 @@
 # {FILES_TO_INSTALL} {DEST_DIR}
 # lib
 usr/lib/*.so usr/lib/
+usr/lib/nnfw/backend/*.so usr/lib/nnfw/backend/
+# tvn loader debian build is not supported yet
+#usr/lib/nnfw/loader/*.so usr/lib/nnfw/loader/
index a228196..47a6d51 100755 (executable)
@@ -1,22 +1,36 @@
 #!/usr/bin/make -f
+
+# x64 only
+# TODO: Support more architectures
 DEBVER := $(shell dpkg-parsechangelog -SVersion)
+NPROC ?= $(shell nproc)
+
 export DH_VERBOSE = 1
-export _DESTDIR = debian/tmp/
-export BUILD_TYPE=release
-export OPTIONS=-DBUILD_LOGGING=0 -DBUILD_TFLITE_COMPARATOR_TEST_TOOL=0 -DBUILD_ONERT_RUN=0 -DBUILD_TFLITE_RUN=0 -DBUILD_RUNTIME_NNAPI_TEST=0 -DBUILD_TFLITE_VANILLA_RUN=0 -DBUILD_TENSORFLOW_LITE_2_8_0=0 -DBUILD_TENSORFLOW_LITE=0
-export DEBIAN_BUILD=1
-export INSTALL_PATH=debian/tmp/usr/
+export NNFW_WORKSPACE = build/onert
+export NNFW_INSTALL_PREFIX = $(CURDIR)/debian/tmp/usr/
+
 %:
        dh $@
 
 override_dh_auto_build:
-       make -f Makefile.template
+       test -d externals || mkdir -p externals
+       find packaging/ -type f -name "*.tar.gz" | xargs -i tar xf {} -C externals
+       mkdir -p $(NNFW_WORKSPACE)
+       ./nnfw configure -DCMAKE_BUILD_TYPE=Release -DEXTERNALS_BUILD_THREADS=$(NPROC) \
+         -DBUILD_LOGGING=OFF -DDOWNLOAD_GTEST=OFF -DENABLE_TEST=OFF \
+               -DBUILD_PYTHON_BINDING=OFF
+       ./nnfw build -j$(NPROC)
 override_dh_auto_install:
-       make -f Makefile.template install
+       ./nnfw install --prefix $(NNFW_INSTALL_PREFIX) --strip
 override_dh_install:
-       install -d debian/tmp/usr/lib/pkgconfig
+       install -d $(NNFW_INSTALL_PREFIX)/lib/pkgconfig
        sed -i 's:@libdir@:\/usr\/lib:g' ./packaging/nnfw.pc.in
        sed -i 's:@includedir@:\/usr\/include:g' ./packaging/nnfw.pc.in
        sed -i 's:@version@:${DEBVER}:g' ./packaging/nnfw.pc.in
-       install -m 0644 packaging/nnfw.pc.in -T debian/tmp/usr/lib/pkgconfig/nnfw.pc
+       sed -i 's:@libdir@:\/usr\/lib:g' ./packaging/nnfw-plugin.pc.in
+       sed -i 's:@includedir@:\/usr\/include:g' ./packaging/nnfw-plugin.pc.in
+       sed -i 's:@version@:${DEBVER}:g' ./packaging/nnfw-plugin.pc.in
+
+       install -m 0644 packaging/nnfw.pc.in -T $(NNFW_INSTALL_PREFIX)/lib/pkgconfig/nnfw.pc
+       install -m 0644 packaging/nnfw-plugin.pc.in -T $(NNFW_INSTALL_PREFIX)/lib/pkgconfig/nnfw-plugin.pc
        dh_install
diff --git a/infra/docker/android-sdk/Dockerfile b/infra/docker/android-sdk/Dockerfile
new file mode 100644 (file)
index 0000000..12abf58
--- /dev/null
@@ -0,0 +1,89 @@
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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
+
+# 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
+
+# Additonal tools
+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 clang-format
+RUN apt-get install -qqy gnupg2
+RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
+RUN add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main"
+RUN apt-get update && apt-get install -qqy clang-format-16
+
+# Install java for gradle and android sdk (and file for NDK internally used)
+ARG OPENJDK_VERSION=11
+RUN apt-get install -y openjdk-${OPENJDK_VERSION}-jdk file
+ENV JAVA_HOME /usr/lib/jvm/java-${OPENJDK_VERSION}-openjdk-amd64
+
+# 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}
+WORKDIR /home/ubuntu
+
+# download and install Gradle
+# https://services.gradle.org/distributions/
+ARG GRADLE_VERSION=6.4.1
+ARG GRADLE_DIST=bin
+RUN 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
+ENV ANDROID_HOME /home/ubuntu/android-sdk
+RUN wget -q -O commandlinetools.zip https://dl.google.com/android/repository/commandlinetools-linux-6514223_latest.zip
+
+# Unzip bootstrap cmdline-tools (old version) to tmp dir and install cmdline-tools (latest openjdk supporting version)
+# accept the license agreements of the SDK components
+ARG CMDTOOLS_VERSION=10.0
+RUN unzip -d tmp commandlinetools.zip && rm commandlinetools.zip
+RUN yes | tmp/tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} --licenses > /dev/null
+RUN tmp/tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} "cmdline-tools;${CMDTOOLS_VERSION}"
+RUN rm -rf tmp
+
+# Install android ndk and tools (other packages will be installed by gradle build)
+ARG NDK_VERSION=26.3.11579264
+RUN ${ANDROID_HOME}/cmdline-tools/${CMDTOOLS_VERSION}/bin/sdkmanager --sdk_root=${ANDROID_HOME} "ndk;${NDK_VERSION}"
+RUN ${ANDROID_HOME}/cmdline-tools/${CMDTOOLS_VERSION}/bin/sdkmanager --sdk_root=${ANDROID_HOME} "platform-tools"
+
+# Env variable for android build (ndk, gradle)
+ENV NDK_DIR ${ANDROID_HOME}/ndk/${NDK_VERSION}
+ENV GRADLE_HOME /home/ubuntu/gradle
+ENV PATH ${PATH}:${GRADLE_HOME}/bin:${ANDROID_HOME}/cmdline-tools/${CMDTOOLS_VERSION}/bin:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools
+
+# setup adb server
+EXPOSE 5037
index 383fddc..3fb41cc 100644 (file)
@@ -41,13 +41,16 @@ 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
+    apt-get -qqy install doxygen graphviz wget zip unzip 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
 
+# Skip clang-format-16 install
+# Cannot install clang-formart-16
+
 # Install google test (source)
 RUN apt-get update && apt-get -qqy install libgtest-dev
 
@@ -84,47 +87,10 @@ RUN rm -rf gtest
 # Install gbs & sdb
 RUN echo 'deb [trusted=yes] http://download.tizen.org/tools/latest-release/Ubuntu_18.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_3.1.4_ubuntu-64.zip -O sdb.zip
+RUN wget http://download.tizen.org/sdk/tizenstudio/official/binary/sdb_4.2.25_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/*
 
-# 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"
 
index 0c6c582..b2cc05d 100644 (file)
@@ -14,8 +14,6 @@
 
 FROM ubuntu:20.04
 
-ARG UBUNTU_MIRROR
-
 # Install 'add-apt-repository'
 RUN apt-get update && apt-get -qqy install software-properties-common
 
@@ -34,65 +32,19 @@ 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
+    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
+# Install clang-format
+RUN apt-get install -qqy gnupg2
+RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
+RUN add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-16 main"
+RUN apt-get update && apt-get install -qqy clang-format-16
 
-# Install gbs & sdb
+# Install gbs
 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/*
-
-# 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
@@ -106,3 +58,4 @@ RUN apt-get clean -y
 
 # Set user to the one we just created
 USER ${USER_ID}
+WORKDIR /home/ubuntu
index b63bbb1..00b445c 100644 (file)
@@ -34,10 +34,16 @@ 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
+    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 clang-format
+RUN apt-get install -qqy gnupg2
+RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
+RUN add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-16 main"
+RUN apt-get update && apt-get install -qqy clang-format-16
+
 # Install google test (source)
 RUN apt-get update && apt-get -qqy install libgtest-dev
 
index aa500b0..f35653f 100644 (file)
@@ -14,8 +14,6 @@
 
 FROM ubuntu:jammy
 
-ARG UBUNTU_MIRROR
-
 # Install 'add-apt-repository'
 RUN apt-get update && apt-get -qqy install software-properties-common
 
@@ -32,18 +30,21 @@ RUN apt-get update && apt-get -qqy install libboost-all-dev libgflags-dev libgoo
 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
+# Install clang-format
+RUN apt-get install -qqy gnupg2
+RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
+RUN add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main"
+RUN apt-get update && apt-get install -qqy clang-format-16
 
-# TODO: Install gbs & sdb
-# gbs & sdb are not support ubuntu jammy yet
+# Install gbs
+RUN echo 'deb [trusted=yes] http://download.tizen.org/tools/latest-release/Ubuntu_22.04/ /' | cat >> /etc/apt/sources.list
+RUN apt-get update && apt-get -qqy install gbs
 
 # Setup user to match host user, and give superuser permissions
 ARG USER_ID=1000
index a6a449d..8abff4e 100644 (file)
@@ -39,6 +39,12 @@ RUN apt-get update && \
 RUN python3 -m pip install --upgrade pip
 RUN python3 -m pip install yapf==0.22.0 numpy flatbuffers
 
+# Install clang-format
+RUN apt-get install -qqy gnupg2
+RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
+RUN add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main"
+RUN apt-get update && apt-get install -qqy clang-format-16
+
 # Install google test (source)
 RUN apt-get update && apt-get -qqy install libgtest-dev
 
diff --git a/infra/docker/noble/Dockerfile b/infra/docker/noble/Dockerfile
new file mode 100644 (file)
index 0000000..0dd20d4
--- /dev/null
@@ -0,0 +1,55 @@
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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:noble
+
+# Install 'add-apt-repository'
+RUN apt-get update && apt-get -qqy install software-properties-common
+
+# Install tzdata without user input
+RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get -qqy install tzdata
+
+# Build tool
+RUN apt-get update && apt-get -qqy install build-essential cmake scons git lcov g++-arm-linux-gnueabihf g++-aarch64-linux-gnu
+
+# 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
+
+# Additonal tools
+RUN apt-get update && \
+    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 yapf==0.22.0 --break-system-packages
+
+# Install clang-format
+RUN apt-get update && apt-get -qqy install clang-format-16
+
+# TODO: Install gbs & sdb
+# gbs & sdb are not support ubuntu noble yet
+
+# Setup user ubuntu: give superuser permissions without password
+RUN apt-get update && apt-get -qqy install sudo
+RUN usermod -aG sudo ubuntu
+RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+# Clean archives (to reduce image size)
+RUN apt-get clean -y
+
+# Set user to ubuntu(1000)
+USER ubuntu
+WORKDIR /home/ubuntu
+RUN python3 -m venv ~/.local
+ENV PATH=~/.local/bin:$PATH
diff --git a/infra/docker/noble/Dockerfile.aarch64 b/infra/docker/noble/Dockerfile.aarch64
new file mode 100644 (file)
index 0000000..b355b3f
--- /dev/null
@@ -0,0 +1,55 @@
+# Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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:noble
+
+# Install tzdata without user input
+RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -qqy install tzdata
+
+# 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
+
+# Additonal tools
+RUN apt-get update && \
+    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 yapf==0.22.0 --break-system-packages
+
+# Install clang-format
+RUN apt-get update && apt-get -qqy install clang-format-16
+
+# TODO: Install gbs & sdb
+# gbs & sdb are not support ubuntu jammy yet
+
+# Setup user ubuntu: give superuser permissions without password
+RUN apt-get update && apt-get -qqy install sudo
+RUN usermod -aG sudo ubuntu
+RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
+
+# Clean archives (to reduce image size)
+RUN apt-get clean -y
+
+# Set user to ubuntu(1000)
+USER ubuntu
+WORKDIR /home/ubuntu
+RUN python3 -m venv ~/.local
+ENV PATH=~/.local/bin:$PATH
index bd53c33..cba480e 100644 (file)
@@ -4,7 +4,7 @@ project(nncc)
 
 enable_testing()
 
-set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD 17)
 
 set(CMAKE_SKIP_BUILD_RPATH FALSE)
 set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
index 9ba57dd..0d344a0 100644 (file)
@@ -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-circle05;mio-tflite280;mio-circle06;mio-tflite2121
+ARM32_BUILD_ITEMS+=;safemain;mio-circle08;mio-tflite2121
 ARM32_BUILD_ITEMS+=;dio-hdf5
 ARM32_BUILD_ITEMS+=;luci-compute
 ARM32_BUILD_ITEMS+=;foder;circle-verify;souschef;arser;vconone
@@ -35,7 +35,7 @@ ARM32_BUILD_ITEMS+=;luci-interpreter
 ARM32_BUILD_ITEMS+=;tflite2circle
 ARM32_BUILD_ITEMS+=;tflchef;circlechef
 ARM32_BUILD_ITEMS+=;circle2circle;record-minmax;circle-quantizer
-ARM32_BUILD_ITEMS+=;luci-eval-driver;luci-value-test
+ARM32_BUILD_ITEMS+=;luci-eval-driver;luci-value-py-test
 
 ARM32_TOOLCHAIN_FILE=cmake/buildtool/cross/toolchain_armv7l-linux.cmake
 
@@ -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-circle05;mio-tflite280;mio-circle06;mio-tflite2121
+ARM32_HOST_ITEMS+=;safemain;mio-circle08;mio-tflite2121
 ARM32_HOST_ITEMS+=;luci-compute
 ARM32_HOST_ITEMS+=;foder;circle-verify;souschef;arser;vconone
 ARM32_HOST_ITEMS+=;luci
@@ -54,7 +54,7 @@ ARM32_HOST_ITEMS+=;tflchef;circlechef
 ARM32_HOST_ITEMS+=;circle-tensordump
 ARM32_HOST_ITEMS+=;circle2circle
 ARM32_HOST_ITEMS+=;common-artifacts
-ARM32_HOST_ITEMS+=;luci-eval-driver;luci-value-test
+ARM32_HOST_ITEMS+=;luci-eval-driver;luci-value-py-test
 
 
 _EMPTY_:=
@@ -132,6 +132,16 @@ int_test_arm32_host:
        NNCC_WORKSPACE=$(BUILD_ARM32_HOST) ./nncc test
 
 #
+# prepare python venv in target for testing
+# NOTE sync package versions with compiler/common-artifacts
+#
+int_prep_venv_arm32:
+       python3 -m venv $(BUILD_ARM32_FOLDER)/overlay/venv_2_12_1
+       $(BUILD_ARM32_FOLDER)/overlay/venv_2_12_1/bin/python3 -m pip install --upgrade pip setuptools
+       $(BUILD_ARM32_FOLDER)/overlay/venv_2_12_1/bin/python3 -m pip install --upgrade tensorflow==2.12.1 \
+               flatbuffers==23.5.26 protobuf==4.23.3 pydot==1.4.2 pytest==7.4.3
+
+#
 # tests: run in ARM32 Ubuntu 18.04 device
 #
 int_test:
@@ -148,5 +158,8 @@ debug: int_build_arm32
 # NOTE before run test in ARM32, run test in host is required to prepare test data
 test_prep: int_test_arm32_host
 
+# NOTE before run test in ARM32, prepare python venv in ARM32
+test_venv: int_prep_venv_arm32
+
 # NOTE run test in ARM32 Ubuntu 18.04 device
 test: int_test
index 773a1f7..48eaa95 100644 (file)
@@ -14,6 +14,7 @@ option(DOWNLOAD_EIGEN "Download Eigen source" ON)
 option(DOWNLOAD_FARMHASH "Download farmhash source" ON)
 option(DOWNLOAD_GEMMLOWP "Download GEMM low precesion library source" ON)
 option(DOWNLOAD_RUY "Download ruy source" ON)
+option(DOWNLOAD_THREADPOOL "Download Threadpool source" ON)
 option(DOWNLOAD_NEON2SSE "Download NEON2SSE library source" ON)
 option(DOWNLOAD_GFLAGS "Download GFlags source" OFF)
 option(DOWNLOAD_FLATBUFFERS "Download FlatBuffers source" ON)
@@ -26,6 +27,7 @@ option(DOWNLOAD_ABSEIL "Download Abseil-cpp source" ON)
 option(DOWNLOAD_OPENCL_HEADERS "Download OpenCl Header source" ON)
 option(DOWNLOAD_PYBIND11 "Download Pybind11 source" ON)
 option(DOWNLOAD_JSONCPP "Download Jsoncpp source" ON)
+option(DOWNLOAD_LIBNPY "Download Libnpy source" ON)
 
 option(DOWNLOAD_GTEST "Download Google Test source" ON)
 option(BUILD_GTEST "Build Google Test from the downloaded source" ON)
@@ -56,3 +58,7 @@ option(NNCC_LIBRARY_NO_PIC "Disable PIC option for libraries" OFF)
 # This option enables installation of one-import-pytorch utility and
 # generation of related testsuite.
 option(ENABLE_ONE_IMPORT_PYTORCH "Enable deploy of one-cmds pytoch importer and related tests" OFF)
+
+# Enable exclusion of a module in compiler with exclude.me file
+# This option is ignored when BUILD_WHITELIST is given
+option(ENABLE_EXCLUDE_ME "Exclude compiler module with exclude.me" ON)
diff --git a/infra/nncc/cmake/buildtool/cross/toolchain_aarch64-linux.cmake b/infra/nncc/cmake/buildtool/cross/toolchain_aarch64-linux.cmake
new file mode 100644 (file)
index 0000000..04528d3
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# config for aarch64-linux
+#
+include(CMakeForceCompiler)
+
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_PROCESSOR aarch64)
+
+set(CMAKE_C_COMPILER   aarch64-linux-gnu-gcc)
+set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
+
+# where is the target environment
+set(NNAS_PROJECT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../../..")
+set(ROOTFS_AARCH64 "${NNAS_PROJECT_SOURCE_DIR}/tools/cross/rootfs/aarch64")
+include("${NNAS_PROJECT_SOURCE_DIR}/infra/cmake/modules/OptionTools.cmake")
+
+envoption(ROOTFS_DIR ${ROOTFS_AARCH64})
+if(NOT EXISTS "${ROOTFS_DIR}/lib/aarch64-linux-gnu")
+  message(FATAL_ERROR "Please prepare RootFS for AARCH64")
+endif()
+
+set(CMAKE_SYSROOT ${ROOTFS_DIR})
+set(CMAKE_SHARED_LINKER_FLAGS
+    "${CMAKE_SHARED_LINKER_FLAGS} --sysroot=${ROOTFS_DIR}"
+    CACHE INTERNAL "" FORCE)
+set(CMAKE_EXE_LINKER_FLAGS
+    "${CMAKE_EXE_LINKER_FLAGS} --sysroot=${ROOTFS_DIR}"
+    CACHE INTERNAL "" FORCE)
+
+# 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)
diff --git a/infra/nncc/cmake/options/options_riscv64-tizen.cmake b/infra/nncc/cmake/options/options_riscv64-tizen.cmake
new file mode 100644 (file)
index 0000000..d26d034
--- /dev/null
@@ -0,0 +1,3 @@
+#
+# riscv64 tizen cmake options
+#
diff --git a/infra/nncc/command/docker-nncc b/infra/nncc/command/docker-nncc
deleted file mode 100644 (file)
index 0eea016..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-import "docker.configuration"
-
-docker run $DOCKER_RUN_OPTS $DOCKER_ENV_VARS $DOCKER_VOLUMES $DOCKER_IMAGE_NAME ./nncc "$@"
-EXITCODE=$?
-
-docker_cleanup
-
-exit $EXITCODE
diff --git a/infra/nncc/command/docker-run b/infra/nncc/command/docker-run
deleted file mode 100644 (file)
index 863b2b8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-import "docker.configuration"
-
-docker run $DOCKER_RUN_OPTS $DOCKER_ENV_VARS $DOCKER_VOLUMES $DOCKER_IMAGE_NAME "$@"
-EXITCODE=$?
-
-docker_cleanup
-
-exit $EXITCODE
diff --git a/infra/nncc/command/docker-shell b/infra/nncc/command/docker-shell
deleted file mode 100644 (file)
index 7f84498..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-import "docker.configuration"
-
-DOCKER_RUN_OPTS+=" -it"
-docker run $DOCKER_RUN_OPTS $DOCKER_ENV_VARS $DOCKER_VOLUMES $DOCKER_IMAGE_NAME /bin/bash
-EXITCODE=$?
-
-docker_cleanup
-
-exit $EXITCODE
diff --git a/infra/nncc/command/install b/infra/nncc/command/install
new file mode 100644 (file)
index 0000000..d7ed3d7
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+import "build.configuration"
+
+BUILD_WORKSPACE_PATH="${NNCC_PROJECT_PATH}/${BUILD_WORKSPACE_RPATH}"
+
+if [[ ! -d "${BUILD_WORKSPACE_PATH}" ]]; then
+  echo "'${BUILD_WORKSPACE_RPATH}' does not exist. Please run 'configure' first"
+  exit 255
+fi
+
+# Check version
+# TODO Remove version check when we does not support 18.04 anymore
+cmp=3.15.0
+ver=$(cmake --version | head -1 | cut -f3 -d" ")
+
+mapfile -t sorted < <(printf "%s\n" "$ver" "$cmp" | sort -V)
+
+if [[ ${sorted[0]} == "$ver" ]]; then
+  echo "This command requires cmake version $cmp or upper."
+  exit 255
+fi
+
+cmake --install ${BUILD_WORKSPACE_PATH} "$@"
index 65aea8b..004fee5 100644 (file)
@@ -1,4 +1,5 @@
 #!/bin/bash
+# NOTE this file is not used and not updated anymore but left for any future referennce.
 
 import "build.configuration"
 
diff --git a/infra/nncc/config/docker.configuration b/infra/nncc/config/docker.configuration
deleted file mode 100644 (file)
index 2765c36..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-DOCKER_IMAGE_NAME=${DOCKER_IMAGE_NAME:-nnfw/one-devtools}
-echo "Using docker image ${DOCKER_IMAGE_NAME}"
-
-if [ -z "`docker images ${DOCKER_IMAGE_NAME}`" ]; then
-  echo "Need docker image!"
-  exit 1
-fi
-
-HOST_PATH="$NNCC_PROJECT_PATH"
-DOCKER_PATH="$NNCC_PROJECT_PATH"
-
-export GIT_SSL_NO_VERIFY=1
-
-DOCKER_VOLUMES+=" -v $HOST_PATH:$DOCKER_PATH"
-
-DOCKER_ENV_VARS+=" -e http_proxy"
-DOCKER_ENV_VARS+=" -e no_proxy"
-DOCKER_ENV_VARS+=" -e GIT_SSL_NO_VERIFY"
-DOCKER_ENV_VARS+=" -e CAFFE_URL"
-DOCKER_ENV_VARS+=" -e GTEST_URL"
-DOCKER_ENV_VARS+=" -e EIGEN_URL"
-DOCKER_ENV_VARS+=" -e GEMMLOWP_URL"
-DOCKER_ENV_VARS+=" -e FLATBUFFERS_URL"
-DOCKER_ENV_VARS+=" -e FARMHASH_URL"
-DOCKER_ENV_VARS+=" -e NEON2SSE_URL"
-DOCKER_ENV_VARS+=" -e TENSORFLOW_URL"
-
-DOCKER_ENV_VARS+=" -e NNCC_WORKSPACE"
-
-DOCKER_RUN_OPTS="${DOCKER_OPTS}"
-DOCKER_RUN_OPTS+=" --rm"
-DOCKER_RUN_OPTS+=" -w $DOCKER_PATH"
-
-function docker_cleanup()
-{
-  # Newly created files during during docker run can have different ownership.
-  # This may cause some problems, for example, some jenkins slaves or developers
-  # can't remove built files due to lack of permission.
-  # To address this issue, let's change owner of all files
-  # in nncc to owner of nncc.
-  NNCC_OWNER_UID=$(stat -c "%u" $HOST_PATH)
-  NNCC_OWNER_GID=$(stat -c "%g" $HOST_PATH)
-
-  CMD="chown -R $NNCC_OWNER_UID:$NNCC_OWNER_GID $DOCKER_PATH"
-  docker run $DOCKER_RUN_OPTS $DOCKER_ENV_VARS $DOCKER_VOLUMES $DOCKER_IMAGE_NAME $CMD
-}
index 857c15b..de1ca76 100644 (file)
@@ -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/../lib/nnfw/odc:$ORIGIN/")
+set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib/:$ORIGIN/")
 set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
 
 ### CMAKE_BUILD_TYPE_LC: Build type lower case
@@ -26,8 +26,9 @@ set(NNFW_OVERLAY_DIR "${CMAKE_BINARY_DIR}/overlay" CACHE
 # Share package build script with compiler
 set(EXT_OVERLAY_DIR ${NNFW_OVERLAY_DIR})
 
-# This allows find_package to access configurations installed inside overlay
-list(APPEND CMAKE_PREFIX_PATH "${EXT_OVERLAY_DIR}")
+# This allows find_package configurations, find_library, and find_path to access installed inside overlay
+# EXT_OVERLAY_DIR is higher priority than ROOTFS_DIR on cross build
+list(INSERT CMAKE_FIND_ROOT_PATH 0 "${EXT_OVERLAY_DIR}")
 
 macro(nnas_include PREFIX)
   include("${NNAS_PROJECT_SOURCE_DIR}/infra/cmake/modules/${PREFIX}.cmake")
@@ -116,6 +117,13 @@ endif(ENABLE_COVERAGE)
 
 nnas_include(AddSubdirectories)
 
+# Add arser for test driver
+# TODO: Better way to handle this
+if(ENABLE_TEST)
+  add_library(arser INTERFACE)
+  target_include_directories(arser INTERFACE ${NNAS_PROJECT_SOURCE_DIR}/compiler/arser/include/)
+endif(ENABLE_TEST)
+
 add_subdirectory(${NNAS_PROJECT_SOURCE_DIR}/compute compute)
 add_subdirectory(${NNAS_PROJECT_SOURCE_DIR}/runtime runtime)
 add_subdirectory(${NNAS_PROJECT_SOURCE_DIR}/tests tests)
index 8d37cf2..041817d 100644 (file)
@@ -29,11 +29,9 @@ option(BUILD_WITH_HDF5 "Build test tool with HDF5 library" ON)
 option(GENERATE_RUNTIME_NNAPI_TESTS "Generate NNAPI operation gtest" ON)
 option(ENVVAR_ONERT_CONFIG "Use environment variable for onert configuration" ON)
 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)
+option(BUILD_MINMAX_H5DUMPER "Build minmax h5dumper" OFF)
 #
 # Default build configuration for contrib
 #
@@ -47,6 +45,8 @@ option(BUILD_TFLITE_TEST "Build tensorflow lite test" OFF)
 option(BUILD_TFLITE_CLASSIFY_APP "Build tflite_classify app" OFF)
 option(BUILD_UBEN "Build micro-benchmark (uben) suite" OFF)
 option(BUILD_MLAPSE "Build mlapse benchmark toolkit" OFF)
+option(BUILD_GPU_CL "Build gpu_cl backend" OFF)
+option(BUILD_TENSORFLOW_LITE_GPU "Build TensorFlow Lite GPU delegate from the downloaded source" OFF)
 #
 # Default build configuration for tools
 #
@@ -58,7 +58,6 @@ option(BUILD_TFLITE_ACCURACY "Build tflite accuracy tool" OFF)
 #
 option(DOWNLOAD_TENSORFLOW "Download Tensorflow source" ON)
 option(DOWNLOAD_ABSEIL "Download Abseil source" ON)
-option(DOWNLOAD_OPENCL_HEADERS "Download Opencl_headers source" OFF)
 option(DOWNLOAD_EIGEN "Download Eigen source" ON)
 option(DOWNLOAD_FARMHASH "Download farmhash source" ON)
 option(DOWNLOAD_GEMMLOWP "Download GEMM low precesion library source" ON)
@@ -70,10 +69,10 @@ option(DOWNLOAD_BOOST "Download boost source" OFF)
 option(DOWNLOAD_RUY "Download ruy source" ON)
 option(DOWNLOAD_CPUINFO "Download cpuinfo source" ON)
 option(DOWNLOAD_OOURAFFT "Download Ooura FFT source" ON)
+option(DOWNLOAD_MLDTYPES "Download ml_dtypes source" ON)
 option(DOWNLOAD_GTEST "Download Google Test source and build Google Test" ON)
 option(BUILD_BOOST "Build boost source" OFF)
 option(BUILD_TENSORFLOW_LITE "Build TensorFlow Lite from the downloaded source" ON)
-option(BUILD_TENSORFLOW_LITE_GPU "Build TensorFlow Lite GPU delegate from the downloaded source" OFF)
 option(BUILD_ARMCOMPUTE "Build ARM Compute from the downloaded source" ON)
 option(DEBUG_ARMCOMPUTE "Build ARM Compute as debug type" OFF)
 option(BUILD_RUY "Build ruy library from the downloaded source" ON)
@@ -89,7 +88,10 @@ option(DOWNLOAD_FP16 "Download fp16 source" ON)
 option(BUILD_FP16 "Build fp16 library from the source" ON)
 option(DOWNLOAD_FXDIV "Download fxdiv source" ON)
 option(BUILD_FXDIV "Build fxdiv library from the source" ON)
-
+option(DOWNLOAD_PYBIND11 "Download Pybind11 source" OFF)
+option(BUILD_PYTHON_BINDING "Build python binding" OFF)
+option(HDF5_USE_STATIC_LIBRARIES "Determine whether or not static linking for HDF5" ON)
+option(Boost_USE_STATIC_LIBS "Determine whether or not static linking for Boost" ON)
 
 #
 ## Default sample build configuration
index dec1b4a..363a3e8 100644 (file)
@@ -14,7 +14,8 @@ include("cmake/buildtool/config/config_linux.cmake")
 
 # addition for arm-linux
 set(FLAGS_COMMON ${FLAGS_COMMON}
-    "-mtune=cortex-a8"
+    "-march=armv7-a"
+    "-mtune=cortex-a15.cortex-a7"
     "-mfloat-abi=hard"
     "-mfpu=neon-vfpv4"
     "-funsafe-math-optimizations"
index 8963f30..f3c52d7 100644 (file)
@@ -9,7 +9,8 @@ include("${CMAKE_CURRENT_LIST_DIR}/config_linux.cmake")
 
 # addition for arm-linux
 set(FLAGS_COMMON ${FLAGS_COMMON}
-    "-mcpu=cortex-a7"
+    "-march=armv7-a"
+    "-mtune=cortex-a15.cortex-a7"
     "-mfloat-abi=hard"
     "-mfpu=neon-vfpv4"
     "-ftree-vectorize"
index fa12ecb..a43f9e0 100644 (file)
@@ -14,7 +14,8 @@ include("cmake/buildtool/config/config_linux.cmake")
 
 # addition for arm-linux
 set(FLAGS_COMMON ${FLAGS_COMMON}
-    "-mtune=cortex-a8"
+    "-march=armv7-a"
+    "-mtune=cortex-a15.cortex-a7"
     "-mfloat-abi=softfp"
     "-mfpu=neon-vfpv4"
     "-funsafe-math-optimizations"
diff --git a/infra/nnfw/cmake/buildtool/config/config_riscv64-tizen.cmake b/infra/nnfw/cmake/buildtool/config/config_riscv64-tizen.cmake
new file mode 100644 (file)
index 0000000..d45510e
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# riscv64 tizen compile options
+#
+
+message(STATUS "Building for RISC-V 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 riscv64-tizen
+set(FLAGS_COMMON ${FLAGS_COMMON}
+    )
index 99cc32a..95f075b 100644 (file)
@@ -14,16 +14,16 @@ set(ANDROID_ABI arm64-v8a)
 set(ANDROID_API_LEVEL 29)
 set(ANDROID_PLATFORM android-${ANDROID_API_LEVEL})
 set(ANDROID_STL c++_shared)
-set(ANDROID_STL_LIB "${NDK_DIR}/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so")
 
 # Find package in the host. `nnfw_find_package` won't work without this
+# Others (library, path) will follow android.toolchain.cmake settings
 set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER)
-# Find library in the host. Necessary for `add_library` searching in `out/lib` dir.
-set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
 
 # Use the toolchain file that NDK provides
 include(${NDK_DIR}/build/cmake/android.toolchain.cmake)
 
+find_library(ANDROID_STL_LIB c++_shared PATHS /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE})
+
 # Install libc++_shared.so to lib folder
 install(FILES ${ANDROID_STL_LIB} DESTINATION lib)
 
index 5de2be3..117810b 100644 (file)
@@ -6,13 +6,3 @@ option(DOWNLOAD_NEON2SSE "Download NEON2SSE library source" OFF)
 option(DOWNLOAD_BOOST "Download boost source" ON)
 option(BUILD_BOOST "Build boost source" ON)
 option(BUILD_LOGGING "Build logging runtime" OFF)
-
-option(DOWNLOAD_OPENGL_HEADERS "Download Opengl_headers source" ON)
-option(DOWNLOAD_EGL_HEADERS "Download Egl_headers source" ON)
-option(DOWNLOAD_VULKAN "Download vulkan source" ON)
-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)
index 829711f..20fd9f4 100644 (file)
@@ -2,3 +2,5 @@
 # aarch64 linux cmake options
 #
 option(DOWNLOAD_NEON2SSE "Download NEON2SSE library source" OFF)
+option(DOWNLOAD_PYBIND11 "Download Pybind11 source" ON)
+option(BUILD_PYTHON_BINDING "Build python binding" ON)
index cccd77f..685f9ed 100644 (file)
@@ -11,9 +11,8 @@ option(BUILD_LOGGING "Build logging runtime" OFF)
 option(GENERATE_RUNTIME_NNAPI_TESTS "Generate NNAPI operation gtest" OFF)
 option(ENVVAR_ONERT_CONFIG "Use environment variable for onert configuration" OFF)
 
-option(BUILD_NPUD "Build NPU daemon" ON)
+option(BUILD_NPUD "Build NPU daemon" OFF)
 # 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)
+# Tizen boost package does not have static library
+option(Boost_USE_STATIC_LIBS "Determine whether or not static linking for Boost" OFF)
index 07dc040..f77a34d 100644 (file)
@@ -11,17 +11,8 @@ option(BUILD_LOGGING "Build logging runtime" OFF)
 option(GENERATE_RUNTIME_NNAPI_TESTS "Generate NNAPI operation gtest" OFF)
 option(ENVVAR_ONERT_CONFIG "Use environment variable for onert configuration" OFF)
 
-option(DOWNLOAD_OPENCL_HEADERS "Download Opencl_headers source" ON)
-option(DOWNLOAD_OPENGL_HEADERS "Download Opengl_headers source" ON)
-option(DOWNLOAD_EGL_HEADERS "Download Egl_headers source" ON)
-option(DOWNLOAD_VULKAN "Download vulkan 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_NPUD "Build NPU daemon" ON)
+option(BUILD_NPUD "Build NPU daemon" OFF)
 # 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)
+# Tizen boost package does not have static library
+option(Boost_USE_STATIC_LIBS "Determine whether or not static linking for Boost" OFF)
index c73a2be..59fbb8a 100644 (file)
@@ -4,9 +4,8 @@
 option(DOWNLOAD_NEON2SSE "Download NEON2SSE library source" OFF)
 option(BUILD_OPENCL_TOOL "Build OpenCL tool" ON)
 
-option(DOWNLOAD_OPENGL_HEADERS "Download Opengl_headers source" ON)
-option(DOWNLOAD_EGL_HEADERS "Download Egl_headers source" ON)
-option(DOWNLOAD_VULKAN "Download vulkan source" ON)
-option(DOWNLOAD_OPENCL_HEADERS "Download Opencl_headers 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(DOWNLOAD_PYBIND11 "Download Pybind11 source" ON)
+option(BUILD_PYTHON_BINDING "Build python binding" ON)
+
+# Under linux gcc 10.0, required header for xnnpack arm build is not supported
+cmake_dependent_option(BUILD_XNNPACK "Build xnnpack library from the downloaded source" OFF "CXX_COMPILER_VERSION VERSION_LESS 10.0" ON)
index 4fdcbc3..fa8aff8 100644 (file)
@@ -11,17 +11,8 @@ option(BUILD_LOGGING "Build logging runtime" OFF)
 option(GENERATE_RUNTIME_NNAPI_TESTS "Generate NNAPI operation gtest" OFF)
 option(ENVVAR_ONERT_CONFIG "Use environment variable for onert configuration" OFF)
 
-option(DOWNLOAD_OPENCL_HEADERS "Download Opencl_headers source" ON)
-option(DOWNLOAD_OPENGL_HEADERS "Download Opengl_headers source" ON)
-option(DOWNLOAD_EGL_HEADERS "Download Egl_headers source" ON)
-option(DOWNLOAD_VULKAN "Download vulkan 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_NPUD "Build NPU daemon" ON)
+option(BUILD_NPUD "Build NPU daemon" OFF)
 # 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)
+# Tizen boost package does not have static library
+option(Boost_USE_STATIC_LIBS "Determine whether or not static linking for Boost" OFF)
index e51f5ed..a86985f 100644 (file)
@@ -12,5 +12,6 @@ option(ENVVAR_ONERT_CONFIG "Use environment variable for onert configuration" OF
 
 option(BUILD_XNNPACK "Build XNNPACK" OFF)
 
-option(BUILD_MINMAX_H5DUMPER "Build minmax h5dumper" OFF)
-option(ENABLE_ONERT_TRAIN "Enable onert training feature" OFF)
+option(BUILD_NPUD "Build NPU daemon" OFF)
+# Do not allow to use CONFIG option on Tizen
+option(ENVVAR_NPUD_CONFIG "Use environment variable for npud configuration" OFF)
diff --git a/infra/nnfw/cmake/options/options_riscv64-tizen.cmake b/infra/nnfw/cmake/options/options_riscv64-tizen.cmake
new file mode 100644 (file)
index 0000000..6b34c2b
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# riscv64 tizen cmake options
+#
+option(BUILD_ARMCOMPUTE "Build ARM Compute from the downloaded source" OFF)
+option(BUILD_TENSORFLOW_LITE "Build TensorFlow Lite from the downloaded source" OFF)
+option(DOWNLOAD_ARMCOMPUTE "Download ARM Compute source" OFF)
+option(DOWNLOAD_GTEST "Download Google Test source and build Google Test" OFF)
+
+option(BUILD_LOGGING "Build logging runtime" OFF)
+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_NPUD "Build NPU daemon" OFF)
+# Do not allow to use CONFIG option on Tizen
+option(ENVVAR_NPUD_CONFIG "Use environment variable for npud configuration" OFF)
+# Tizen boost package does not have static library
+option(Boost_USE_STATIC_LIBS "Determine whether or not static linking for Boost" OFF)
index 1cb72d5..fb53fba 100644 (file)
@@ -4,3 +4,5 @@
 option(BUILD_ARMCOMPUTE "Build ARM Compute from the downloaded source" OFF)
 option(BUILD_XNNPACK "Build XNNPACK" OFF)
 option(DOWNLOAD_ARMCOMPUTE "Download ARM Compute source" OFF)
+option(DOWNLOAD_PYBIND11 "Download Pybind11 source" ON)
+option(BUILD_PYTHON_BINDING "Build python binding" ON)
index 70da68c..18c34f2 100644 (file)
@@ -11,11 +11,9 @@ 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(DOWNLOAD_OPENCL_HEADERS "Download opencl headers" OFF)
 
-option(BUILD_NPUD "Build NPU daemon" ON)
+option(BUILD_NPUD "Build NPU daemon" OFF)
 # 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)
+# Tizen boost package does not have static library
+option(Boost_USE_STATIC_LIBS "Determine whether or not static linking for Boost" OFF)
index acc244a..e55a0f4 100644 (file)
@@ -3,19 +3,17 @@ function(_ARMCompute_Import)
 
   list(APPEND ARMCompute_LIB_SEARCH_PATHS ${ARMCompute_PREFIX}/lib)
 
-  find_path(INCLUDE_DIR NAMES arm_compute/core/ITensor.h PATHS ${ARMCompute_INCLUDE_SEARCH_PATHS})
+  find_path(INCLUDE_DIR NAMES arm_compute/core/ITensor.h)
 
-  find_library(CORE_LIBRARY NAMES       arm_compute_core  PATHS ${ARMCompute_LIB_SEARCH_PATHS} CMAKE_FIND_ROOT_PATH_BOTH)
-  find_library(RUNTIME_LIBRARY NAMES arm_compute       PATHS ${ARMCompute_LIB_SEARCH_PATHS} CMAKE_FIND_ROOT_PATH_BOTH)
-  find_library(GRAPH_LIBRARY NAMES   arm_compute_graph PATHS ${ARMCompute_LIB_SEARCH_PATHS} CMAKE_FIND_ROOT_PATH_BOTH)
-
-  message(STATUS "Search acl in ${ARMCompute_LIB_SEARCH_PATHS}")
+  find_library(CORE_LIBRARY NAMES       arm_compute_core)
+  find_library(RUNTIME_LIBRARY NAMES arm_compute)
+  find_library(GRAPH_LIBRARY NAMES   arm_compute_graph)
 
   # ARMCompute v21.02 moves some headers into "src/".
   # And we cannot build armcompute-ex library without these headers.
   # So we need to download and use source code if our build root doesn't have headers in "src/" (tizen's devel package includes these headers).
   # TODO Don't use headers in "src/"
-  find_path(HEADER_SRC_DIR NAMES src/core/CL/ICLKernel.h PATHS ${ARMCompute_INCLUDE_SEARCH_PATHS})
+  find_path(HEADER_SRC_DIR NAMES src/core/CL/ICLKernel.h)
   if(NOT INCLUDE_DIR OR NOT HEADER_SRC_DIR)
     nnas_find_package(ARMComputeSource QUIET)
     if (NOT ARMComputeSource_FOUND)
@@ -165,13 +163,23 @@ function(_ARMCompute_Build ARMComputeInstall_DIR)
 
   set(SCONS_CC "gcc")
   set(SCONS_CXX "g++")
+  # Refer https://android.googlesource.com/platform/external/armnn/+/HEAD/BuildGuideAndroidNDK.md#build-arm-compute-library
   if(ANDROID)
-    list(APPEND SCONS_OPTIONS "toolchain_prefix=${ANDROID_TOOLCHAIN_PREFIX}")
+    if(ANDROID_NDK_MAJOR LESS 22)
+      # Use legacy toolchain
+      list(APPEND SCONS_OPTIONS "toolchain_prefix=${ANDROID_TOOLCHAIN_PREFIX}")
+    else(ANDROID_NDK_MAJOR LESS 22)
+      list(APPEND SCONS_OPTIONS "toolchain_prefix=${ANDROID_TOOLCHAIN_ROOT}/bin/llvm-")
+    endif(ANDROID_NDK_MAJOR LESS 22)
     list(APPEND SCONS_OPTIONS "compiler_prefix=${ANDROID_TOOLCHAIN_ROOT}/bin/aarch64-linux-android${ANDROID_API_LEVEL}-")
     set(SCONS_CC "clang")
     set(SCONS_CXX "clang++")
   endif(ANDROID)
 
+  if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10)
+    list(APPEND SCONS_OPTIONS "extra_cxx_flags=-Wno-deprecated-copy")
+  endif()
+
   message(STATUS "Build ARMCompute with ${SCONS_PATH} ('${SCONS_OPTIONS}'")
 
   # Build ARMCompute libraries with SCONS
index f2759f8..e2941f3 100644 (file)
@@ -19,7 +19,7 @@ function(_Boost_Build Boost_PREFIX)
   set(INSTALL_STAMP_PATH "${BoostInstall_DIR}/BOOST.stamp")
   set(BUILD_LOG_PATH "${BoostBuild_DIR}/BOOST.log")
   set(PKG_NAME "BOOST")
-  set(PKG_IDENTIFIER "1.58.0")
+  set(PKG_IDENTIFIER "1.84.0")
 
   if(EXISTS ${INSTALL_STAMP_PATH})
     file(READ ${INSTALL_STAMP_PATH} READ_IDENTIFIER)
@@ -32,10 +32,7 @@ function(_Boost_Build Boost_PREFIX)
 
   list(APPEND Boost_Options --build-dir=${BoostBuild_DIR})
   list(APPEND Boost_Options --prefix=${BoostInstall_DIR})
-  list(APPEND Boost_Options --with-log)
   list(APPEND Boost_Options --with-program_options)
-  list(APPEND Boost_Options --with-system)
-  list(APPEND Boost_Options --with-filesystem)
 
   if(DEFINED EXTERNALS_BUILD_THREADS)
     set(N ${EXTERNALS_BUILD_THREADS})
@@ -80,7 +77,7 @@ endfunction(_Boost_Build)
 if (NOT BUILD_BOOST)
   # BoostConfig.cmake does not honor QUIET argument at least till cmake 1.70.0.
   # Thus, don't try to find_package if you're not entirely sure you have boost.
-  find_package(Boost 1.58.0 QUIET COMPONENTS log program_options filesystem system)
+  find_package(Boost 1.58.0 QUIET COMPONENTS program_options)
   if(Boost_FOUND)
     return()
   endif()
@@ -99,5 +96,5 @@ if(BUILD_BOOST)
   set(Boost_USE_STATIC_LIBS ON)
 
   # We built boost library so update Boost variables.
-  find_package(Boost 1.58.0 QUIET COMPONENTS log program_options filesystem system)
+  find_package(Boost 1.58.0 QUIET COMPONENTS program_options)
 endif(BUILD_BOOST)
index 1537882..08e0d10 100644 (file)
@@ -1,5 +1,5 @@
 function(_Eigen_import)
-  nnas_find_package(TensorFlowEigenSource EXACT 2.8.0 QUIET)
+  nnas_find_package(TensorFlowEigenSource EXACT 2.16.1 QUIET)
 
   if(NOT TensorFlowEigenSource_FOUND)
     set(Eigen_FOUND FALSE PARENT_SCOPE)
@@ -11,6 +11,8 @@ function(_Eigen_import)
     target_include_directories(eigen SYSTEM INTERFACE "${TensorFlowEigenSource_DIR}")
     # Add EIGEN_MPL2_ONLY to remove license issue posibility
     target_compile_definitions(eigen INTERFACE EIGEN_MPL2_ONLY)
+    # Some used Eigen functions makes deprecated declarations warning
+    target_compile_options(eigen INTERFACE -Wno-deprecated-declarations)
   endif(NOT TARGET eigen)
 
   set(Eigen_FOUND TRUE PARENT_SCOPE)
diff --git a/infra/nnfw/cmake/packages/FlatBuffers-2.0/FlatBuffersConfigVersion.cmake b/infra/nnfw/cmake/packages/FlatBuffers-2.0/FlatBuffersConfigVersion.cmake
new file mode 100644 (file)
index 0000000..e4a87a7
--- /dev/null
@@ -0,0 +1,10 @@
+set(PACKAGE_VERSION "2.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/nnfw/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfig.cmake b/infra/nnfw/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfig.cmake
new file mode 100644 (file)
index 0000000..eefa203
--- /dev/null
@@ -0,0 +1,41 @@
+function(_FlatBuffers_import)
+
+    find_package(Flatbuffers QUIET)
+    if(Flatbuffers_FOUND)
+      set(FlatBuffers_FOUND TRUE PARENT_SCOPE)
+      return()
+    endif(Flatbuffers_FOUND)
+
+    nnas_find_package(FlatBuffersSource EXACT 23.5.26 QUIET)
+
+    if(NOT FlatBuffersSource_FOUND)
+      set(FlatBuffers_FOUND FALSE PARENT_SCOPE)
+      return()
+    endif(NOT FlatBuffersSource_FOUND)
+
+    # From FlatBuffers's CMakeLists.txt
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/annotated_binary_text_gen.cpp")
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/bfbs_gen_lua.cpp")
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/bfbs_gen_nim.cpp")
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/binary_annotator.cpp")
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/code_generators.cpp")
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/flatc.cpp")
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/idl_gen_fbs.cpp")
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/idl_gen_text.cpp")
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/idl_parser.cpp")
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/reflection.cpp")
+    list(APPEND FlatBuffers_Library_SRCS "${FlatBuffersSource_DIR}/src/util.cpp")
+
+    if(NOT TARGET flatbuffers::flatbuffers-23.5.26)
+      add_library(flatbuffers-23.5.26 ${FlatBuffers_Library_SRCS})
+      target_include_directories(flatbuffers-23.5.26 PUBLIC "${FlatBuffersSource_DIR}/include")
+      set_property(TARGET flatbuffers-23.5.26 PROPERTY POSITION_INDEPENDENT_CODE ON)
+      target_compile_options(flatbuffers-23.5.26 PUBLIC $<$<CONFIG:Debug>:-Wno-sign-compare>)
+
+      add_library(flatbuffers::flatbuffers-23.5.26 ALIAS flatbuffers-23.5.26)
+    endif(NOT TARGET flatbuffers::flatbuffers-23.5.26)
+
+    set(FlatBuffers_FOUND TRUE PARENT_SCOPE)
+  endfunction(_FlatBuffers_import)
+
+  _FlatBuffers_import()
diff --git a/infra/nnfw/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfigVersion.cmake b/infra/nnfw/cmake/packages/FlatBuffers-23.5.26/FlatBuffersConfigVersion.cmake
new file mode 100644 (file)
index 0000000..f8b165c
--- /dev/null
@@ -0,0 +1,10 @@
+set(PACKAGE_VERSION "23.5.26")
+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)
index b321961..ce6c021 100644 (file)
@@ -1,16 +1,16 @@
 function(_GEMMLowp_import)
-  nnas_find_package(GEMMLowpSource QUIET)
+  nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.16.1 QUIET)
 
-  if(NOT GEMMLowpSource_FOUND)
+  if(NOT TensorFlowGEMMLowpSource_FOUND)
     set(GEMMLowp_FOUND FALSE PARENT_SCOPE)
     return()
-  endif(NOT GEMMLowpSource_FOUND)
+  endif(NOT TensorFlowGEMMLowpSource_FOUND)
 
   if(NOT TARGET gemmlowp)
     find_package(Threads REQUIRED)
 
     add_library(gemmlowp INTERFACE)
-    target_include_directories(gemmlowp SYSTEM INTERFACE ${GEMMLowpSource_DIR})
+    target_include_directories(gemmlowp SYSTEM INTERFACE ${TensorFlowGEMMLowpSource_DIR})
     target_link_libraries(gemmlowp INTERFACE ${LIB_PTHREAD})
   endif(NOT TARGET gemmlowp)
 
index 05f1874..d0d64f4 100644 (file)
@@ -2,7 +2,7 @@ function(_GIO_UNIX_2_0_import)
   nnfw_find_package(Gio2.0 REQUIRED)
 
   find_path(GIO_UNIX_INCLUDE_DIR
-    NAMES gio/gunixfdlist.h
+    NAMES gio/gfiledescriptorbased.h
     PATH_SUFFIXES gio-unix-2.0)
 
   # The gio-unix-2.0 requires gio-2.0 and link the gio-2.0 library.
index 8c2badf..190e3ca 100644 (file)
@@ -1,4 +1,8 @@
 # Don't cache HDF5_*. Otherwise it will use the cached value without searching.
+if (HDF5_INCLUDE_DIRS AND HDF5_CXX_LIBRARIES AND HDF5_FOUND)
+  return()
+endif()
+
 unset(HDF5_DIR CACHE)
 unset(HDF5_INCLUDE_DIRS CACHE)
 unset(HDF5_CXX_LIBRARY_hdf5 CACHE)
@@ -38,11 +42,23 @@ else()
   endif()
 
   if(HDF5_USE_STATIC_LIBRARIES)
-    find_library(HDF5_CXX_LIBRARY_hdf5 libhdf5.a)
-    find_library(HDF5_CXX_LIBRARY_hdf5_cpp libhdf5_cpp.a)
+    find_library(HDF5_CXX_LIBRARY_hdf5
+      NAMES libhdf5.a
+      ONLY_CMAKE_FIND_ROOT_PATH
+      PATH_SUFFIXES hdf5/serial)
+    find_library(HDF5_CXX_LIBRARY_hdf5_cpp
+      NAMES libhdf5_cpp.a
+      ONLY_CMAKE_FIND_ROOT_PATH
+      PATH_SUFFIXES hdf5/serial)
   else(HDF5_USE_STATIC_LIBRARIES)
-    find_library(HDF5_CXX_LIBRARY_hdf5 libhdf5.so)
-    find_library(HDF5_CXX_LIBRARY_hdf5_cpp libhdf5_cpp.so)
+    find_library(HDF5_CXX_LIBRARY_hdf5
+      NAMES libhdf5.so
+      ONLY_CMAKE_FIND_ROOT_PATH
+      PATH_SUFFIXES hdf5/serial)
+    find_library(HDF5_CXX_LIBRARY_hdf5_cpp
+      NAMES libhdf5_cpp.so
+      ONLY_CMAKE_FIND_ROOT_PATH
+      PATH_SUFFIXES hdf5/serial)
   endif(HDF5_USE_STATIC_LIBRARIES)
 
   if (NOT (HDF5_CXX_LIBRARY_hdf5 AND HDF5_CXX_LIBRARY_hdf5_cpp))
@@ -50,11 +66,17 @@ else()
     return()
   endif()
 
-  # We can use "hdf5" and "hdf5_cpp" to use the same file founded with above.
-  list(APPEND HDF5_CXX_LIBRARIES "hdf5" "hdf5_cpp" "sz" "z" "dl" "m")
+  find_library(HDF5_DEP_sz NAMES sz ONLY_CMAKE_FIND_ROOT_PATH)
+  list(APPEND HDF5_CXX_LIBRARY_DEPS ${HDF5_DEP_sz})
+
+  find_library(HDF5_DEP_z NAMES z ONLY_CMAKE_FIND_ROOT_PATH)
+  list(APPEND HDF5_CXX_LIBRARY_DEPS ${HDF5_DEP_z})
+
+  find_library(HDF5_DEP_m NAMES m ONLY_CMAKE_FIND_ROOT_PATH)
+  list(APPEND HDF5_CXX_LIBRARY_DEPS ${HDF5_DEP_m})
 
-  # Append missing libaec which is required by libsz, which is required by libhdf5
-  list(APPEND HDF5_CXX_LIBRARIES "aec")
+  ### Caution: You must keep appending order for static linking
+  list(APPEND HDF5_CXX_LIBRARIES ${HDF5_CXX_LIBRARY_hdf5_cpp} ${HDF5_CXX_LIBRARY_hdf5} ${HDF5_CXX_LIBRARY_DEPS})
 
   set(HDF5_FOUND TRUE)
 endif()
index 426556b..3ace693 100644 (file)
@@ -2,13 +2,11 @@
 
 set(Luci_FOUND FALSE)
 
-find_path(LUCI_HEADERS
-    NAMES loco.h luci/IR/CircleNode.h
-    PATHS ${EXT_OVERLAY_DIR}/include)
+find_path(LUCI_HEADERS NAMES loco.h luci/IR/CircleNode.h)
 
 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)
+    find_library(LUCI_LIB_PATH_${LUCI_NAME} NAMES luci_${LUCI_NAME})
     if (NOT LUCI_LIB_PATH_${LUCI_NAME})
         return()
     endif()
@@ -32,7 +30,7 @@ _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)
+find_library(LOCO_LIB_PATH NAMES loco)
 if (NOT LOCO_LIB_PATH)
     return()
 endif()
diff --git a/infra/nnfw/cmake/packages/OouraFFTConfig.cmake b/infra/nnfw/cmake/packages/OouraFFTConfig.cmake
new file mode 100644 (file)
index 0000000..ad226a1
--- /dev/null
@@ -0,0 +1,21 @@
+function(_OouraFFT_build)
+  nnas_find_package(OouraFFTSource QUIET)
+
+  if(NOT OouraFFTSource_FOUND)
+    set(OouraFFT_FOUND FALSE PARENT_SCOPE)
+    return()
+  endif(NOT OouraFFTSource_FOUND)
+
+  # TFLite requires fft2d_fftsg2d (oourafft::fftsg2d)
+  if(NOT TARGET oourafft::fftsg2d)
+    add_library(fft2d_fftsg2d STATIC
+      ${OouraFFTSource_DIR}/fftsg2d.c
+      ${OouraFFTSource_DIR}/fftsg.c
+    )
+    add_library(oourafft::fftsg2d ALIAS fft2d_fftsg2d)
+  endif(NOT TARGET oourafft::fftsg2d)
+
+  set(OouraFFT_FOUND TRUE PARENT_SCOPE)
+endfunction(_OouraFFT_build)
+
+_OouraFFT_build()
diff --git a/infra/nnfw/cmake/packages/Pybind11Config.cmake b/infra/nnfw/cmake/packages/Pybind11Config.cmake
new file mode 100644 (file)
index 0000000..c099870
--- /dev/null
@@ -0,0 +1,22 @@
+function(_Pybind11_Build)
+  nnas_find_package(Pybind11Source QUIET)
+
+  if(NOT Pybind11Source_FOUND)
+    set(Pybind11_FOUND FALSE)
+    return()
+  endif(NOT Pybind11Source_FOUND)
+
+  if(NOT TARGET pybind11)
+    nnas_include(ExternalProjectTools)
+    add_extdirectory(${Pybind11Source_DIR} pybind11 EXCLUDE_FROM_ALL)
+  endif(NOT TARGET pybind11)
+
+  set(Pybind11_FOUND TRUE)
+  return()
+endfunction(_Pybind11_Build)
+
+if(BUILD_PYTHON_BINDING)
+  _Pybind11_Build()
+else()
+  set(Pybind11_FOUND FALSE)
+endif()
index 6f5f4b7..09b2806 100644 (file)
@@ -5,7 +5,7 @@ function(_Ruy_Build)
     return()
   endif(TARGET ruy)
 
-  nnas_find_package(TensorFlowRuySource EXACT 2.8 QUIET)
+  nnas_find_package(TensorFlowRuySource EXACT 2.16.1 QUIET)
   nnfw_find_package(CpuInfo QUIET)
 
   if(NOT TensorFlowRuySource_FOUND)
index dfc10eb..18afb06 100644 (file)
@@ -13,6 +13,13 @@ function(_TRIXEngine_import)
     PATHS "${TRIX_ENGINE_PREFIX}/include/npu-engine"
   )
 
+  # npubinfmt.h is in different path on version >=2.6.0
+  find_path(NPUBINFMT_INCLUDE_DIR
+    NAMES npubinfmt.h
+    HINTS "${TRIX_ENGINE_PREFIX}/include/npubin-fmt"
+          "${TRIX_ENGINE_PREFIX}/include/npu-engine"
+  )
+
   set(TRIXEngine_FOUND TRUE)
 
   if(NOT TRIXEngine_LIB)
@@ -23,6 +30,10 @@ function(_TRIXEngine_import)
     set(TRIXEngine_FOUND FALSE)
   endif(NOT TRIXEngine_INCLUDE_DIR)
 
+  if(NOT NPUBINFMT_INCLUDE_DIR)
+    set(TRIXEngine_FOUND FALSE)
+  endif(NOT NPUBINFMT_INCLUDE_DIR)
+
   if(NOT TRIXEngine_FOUND)
     message(STATUS "Failed to find TRIX Engine")
   else(NOT TRIXEngine_FOUND)
@@ -31,12 +42,12 @@ function(_TRIXEngine_import)
     if(NOT TARGET trix_engine)
       add_library(trix_engine INTERFACE)
       target_link_libraries(trix_engine INTERFACE ${TRIXEngine_LIB})
-      target_include_directories(trix_engine INTERFACE ${TRIXEngine_INCLUDE_DIR})
+      target_include_directories(trix_engine INTERFACE ${TRIXEngine_INCLUDE_DIR} ${NPUBINFMT_INCLUDE_DIR})
     endif(NOT TARGET trix_engine)
   endif(NOT TRIXEngine_FOUND)
 
   set(TRIXEngine_FOUND ${TRIXEngine_FOUND} PARENT_SCOPE)
-  set(TRIXEngine_INCLUDE_DIRS ${TRIXEngine_INCLUDE_DIR} PARENT_SCOPE)
+  set(TRIXEngine_INCLUDE_DIRS ${TRIXEngine_INCLUDE_DIR} ${NPUBINFMT_INCLUDE_DIR} PARENT_SCOPE)
 endfunction(_TRIXEngine_import)
 
 _TRIXEngine_import()
index 0e0a043..5ede1fb 100644 (file)
@@ -25,27 +25,37 @@ find_path(TRIXEngine_INCLUDE_DIR
   HINTS "${TRIX_ENGINE_PREFIX}/include/npu-engine"
 )
 
-if(NOT TRIXEngine_INCLUDE_DIR OR NOT TRIXEngine_LIB)
+# npubinfmt.h is in different path on version >=2.6.0
+find_path(NPUBINFMT_INCLUDE_DIR
+  NAMES npubinfmt.h
+  HINTS "${TRIX_ENGINE_PREFIX}/include/npubin-fmt"
+        "${TRIX_ENGINE_PREFIX}/include/npu-engine"
+)
+
+if(NOT TRIXEngine_INCLUDE_DIR OR NOT NPUBINFMT_INCLUDE_DIR OR NOT TRIXEngine_LIB)
+  message(STATUS "Fail to check TRIXEngine version")
   set(PACKAGE_VERSION_EXACT FALSE)
   set(PACKAGE_VERSION_COMPATIBLE FALSE)
   set(PACKAGE_VERSION_UNSUITABLE TRUE)
   return()
-endif(NOT TRIXEngine_INCLUDE_DIR OR NOT TRIXEngine_LIB)
+endif(NOT TRIXEngine_INCLUDE_DIR OR NOT NPUBINFMT_INCLUDE_DIR OR NOT TRIXEngine_LIB)
+
+set(TRYRUN_COMPILE_DEFINITIONS "-I${TRIXEngine_INCLUDE_DIR} -I${NPUBINFMT_INCLUDE_DIR}")
 
 # TODO Assert TRIX_ENGINE_PREFIX is directory
 
 # TODO Can we run this only once per configure?
 try_run(MAJOR_VER MAJOR_COMPILABLE "${CMAKE_BINARY_DIR}/TRIXEngineConfigVersion.major"
   SOURCES "${CMAKE_CURRENT_LIST_DIR}/TRIXEngineConfigVersion.major.cpp"
-  CMAKE_FLAGS
-  "-DINCLUDE_DIRECTORIES=${TRIXEngine_INCLUDE_DIR}"
-  "-DLINK_LIBRARIES=${TRIXEngine_LIB}"
+  COMPILE_DEFINITIONS "${TRYRUN_COMPILE_DEFINITIONS}"
+  LINK_LIBRARIES ${TRIXEngine_LIB}
 )
 
 if(NOT MAJOR_COMPILABLE)
   # This means VERSION < 2.2.7
   # `getVersion` API introduced from TRIX Engine 2.2.7
   if(PACKAGE_FIND_VERSION VERSION_GREATER_EQUAL 2.2.7)
+    message(STATUS "Fail to build TRIXEngine version checker")
     set(PACKAGE_VERSION_EXACT FALSE)
     set(PACKAGE_VERSION_COMPATIBLE FALSE)
     set(PACKAGE_VERSION_UNSUITABLE TRUE)
@@ -58,16 +68,14 @@ endif(NOT MAJOR_COMPILABLE)
 
 try_run(MINOR_VER MINOR_COMPILABLE "${CMAKE_BINARY_DIR}/TRIXEngineConfigVersion.minor"
   SOURCES "${CMAKE_CURRENT_LIST_DIR}/TRIXEngineConfigVersion.minor.cpp"
-  CMAKE_FLAGS
-  "-DINCLUDE_DIRECTORIES=${TRIXEngine_INCLUDE_DIR}"
-  "-DLINK_LIBRARIES=${TRIXEngine_LIB}"
+  COMPILE_DEFINITIONS "${TRYRUN_COMPILE_DEFINITIONS}"
+  LINK_LIBRARIES ${TRIXEngine_LIB}
 )
 
 try_run(EXTRA_VER EXTRA_COMPILABLE "${CMAKE_BINARY_DIR}/TRIXEngineConfigVersion.extra"
   SOURCES "${CMAKE_CURRENT_LIST_DIR}/TRIXEngineConfigVersion.extra.cpp"
-  CMAKE_FLAGS
-  "-DINCLUDE_DIRECTORIES=${TRIXEngine_INCLUDE_DIR}"
-  "-DLINK_LIBRARIES=${TRIXEngine_LIB}"
+  COMPILE_DEFINITIONS "${TRYRUN_COMPILE_DEFINITIONS}"
+  LINK_LIBRARIES ${TRIXEngine_LIB}
 )
 
 macro(assert)
@@ -87,8 +95,10 @@ assert(NOT MINOR_VER STREQUAL FAILED_TO_RUN)
 assert(NOT EXTRA_VER STREQUAL FAILED_TO_RUN)
 
 set(PACKAGE_VERSION ${MAJOR_VER}.${MINOR_VER}.${EXTRA_VER})
+message(STATUS "Found TRIXEngine: ${PACKAGE_VERSION}")
 
 if(PACKAGE_VERSION VERSION_EQUAL PACKAGE_FIND_VERSION)
+  message("Found TRIXEngine: ${PACKAGE_VERSION} exact match")
   set(PACKAGE_VERSION_EXACT TRUE)
 else()
   set(PACKAGE_VERSION_EXACT FALSE)
@@ -96,6 +106,7 @@ endif()
 
 # Assume TRIX Engine is backward compatible
 if(PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION)
+  message("Found TRIXEngine: ${PACKAGE_VERSION} compatible with ${PACKAGE_FIND_VERSION}")
   set(PACKAGE_VERSION_COMPATIBLE TRUE)
 else()
   set(PACKAGE_VERSION_COMPATIBLE FALSE)
index 5d20dd3..bfb709b 100644 (file)
@@ -17,24 +17,30 @@ function(_Build_TfliteGpuDelagate_)
   nnas_find_package(TensorFlowEigenSource EXACT 2.8.0 QUIET)
   return_unless(TensorFlowEigenSource_FOUND)
 
-  nnas_find_package(AbseilSource REQUIRED)
-  return_unless(AbseilSource_FOUND)
+  nnas_find_package(Abseil REQUIRED)
+  return_unless(Abseil_FOUND)
 
   nnas_find_package(Farmhash REQUIRED)
   return_unless(Farmhash_FOUND)
 
-  nnas_find_package(Fp16Source REQUIRED)
-  return_unless(Fp16Source_FOUND)
+  nnfw_find_package(Fp16 REQUIRED)
+  return_unless(Fp16_FOUND)
 
   nnas_find_package(VulkanSource QUIET)
   return_unless(VulkanSource_FOUND)
 
+  nnas_find_package(Opencl_HeadersSource QUIET)
+  return_unless(Opencl_HeadersSource_FOUND)
+
   nnas_find_package(Opengl_HeadersSource QUIET)
   return_unless(Opengl_HeadersSource_FOUND)
 
   nnas_find_package(Egl_HeadersSource QUIET)
   return_unless(Egl_HeadersSource_FOUND)
 
+  nnfw_find_package(FlatBuffers EXACT 2.0 QUIET)
+  return_unless(FlatBuffers_FOUND)
+
   if(NOT TARGET TensorFlowGpu)
     nnas_include(ExternalProjectTools)
     add_extdirectory("${CMAKE_CURRENT_LIST_DIR}/TensorFlowLiteGpu" TensorFlowLiteGpu)
diff --git a/infra/nnfw/cmake/packages/TensorFlowLite-2.16.1/TensorFlowLite/CMakeLists.txt b/infra/nnfw/cmake/packages/TensorFlowLite-2.16.1/TensorFlowLite/CMakeLists.txt
new file mode 100644 (file)
index 0000000..57eecc3
--- /dev/null
@@ -0,0 +1,252 @@
+# Reference: https://github.com/tensorflow/tensorflow/blob/v2.16.1/tensorflow/lite/CMakeLists.txt
+#
+# Tensorflow Lite library 2.16.1
+#
+set(TFLITE_SOURCE_DIR ${TensorFlowSource_DIR}/tensorflow/lite)
+set(TSL_SOURCE_DIR "${TensorFlowSource_DIR}/third_party/xla/third_party/tsl")
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Generate TensorFlow Lite FlatBuffer code.
+# We used to have an actual compilation logic with flatc but decided to use
+# schema_generated.h since flatc doesn't work with cross compilation.
+set(TFLITE_FLATBUFFERS_SCHEMA_DIR "${TFLITE_SOURCE_DIR}/schema")
+
+macro(populate_source_vars SOURCE_DIR SOURCES_VAR)
+  cmake_parse_arguments(ARGS "RECURSE" "" "FILTER" ${ARGN})
+  if(ARGS_RECURSE)
+    set(GLOB_OP GLOB_RECURSE)
+  else()
+    set(GLOB_OP GLOB)
+  endif()
+  set(DEFAULT_FILE_FILTER ".*(_test|test_util)\\.(c|cc|h)$")
+  file(${GLOB_OP} FOUND_SOURCES "${SOURCE_DIR}/*.*")
+  list(FILTER FOUND_SOURCES INCLUDE REGEX ".*\\.(c|cc|h)$")
+  list(FILTER FOUND_SOURCES EXCLUDE REGEX "${DEFAULT_FILE_FILTER}")
+  foreach(FILE_FILTER ${ARGS_FILTER})
+    list(FILTER FOUND_SOURCES EXCLUDE REGEX "${FILE_FILTER}")
+  endforeach()
+  list(APPEND ${SOURCES_VAR} ${FOUND_SOURCES})
+endmacro()
+# Simplifies inclusion of non-test sources and headers from a directory
+# relative to TFLITE_SOURCE_DIR. See populate_source_vars() for the
+# description of arguments including and following SOURCES_VAR.
+macro(populate_tflite_source_vars RELATIVE_DIR SOURCES_VAR)
+  populate_source_vars(
+    "${TFLITE_SOURCE_DIR}/${RELATIVE_DIR}" ${SOURCES_VAR} ${ARGN}
+  )
+endmacro()
+
+# Additional compiler flags used when compiling TF Lite.
+set(TFLITE_TARGET_PUBLIC_OPTIONS "-DEIGEN_NEON_GEBP_NR=4")
+
+# Build a list of source files to compile into the TF Lite library.
+populate_tflite_source_vars("." TFLITE_SRCS)
+
+# This particular file is excluded because the more explicit approach to enable
+# XNNPACK delegate is preferred to the weak-symbol one.
+list(FILTER TFLITE_SRCS EXCLUDE REGEX ".*tflite_with_xnnpack\\.cc$")
+
+# Exclude Flex related files.
+list(FILTER TFLITE_SRCS EXCLUDE REGEX ".*with_selected_ops\\.cc$")
+
+# Exclude tensorflow_profiler_logger files.
+list(FILTER TFLITE_SRCS EXCLUDE REGEX ".*tensorflow_profiler_logger\\.cc$")
+
+# Use MMAP
+list(FILTER TFLITE_SRCS EXCLUDE REGEX ".*mmap_allocation_disabled\\.cc$")
+
+# Handle TFLite logging source.
+list(FILTER TFLITE_SRCS EXCLUDE REGEX ".*minimal_logging_.*\\.cc$")
+if("${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
+  list(APPEND TFLITE_SRCS ${TFLITE_SOURCE_DIR}/minimal_logging_android.cc)
+elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "iOS")
+  list(APPEND TFLITE_SRCS ${TFLITE_SOURCE_DIR}/minimal_logging_ios.cc)
+else()
+  list(APPEND TFLITE_SRCS ${TFLITE_SOURCE_DIR}/minimal_logging_default.cc)
+endif()
+
+populate_tflite_source_vars("core" TFLITE_CORE_SRCS)
+populate_tflite_source_vars("core/acceleration/configuration" TFLITE_CORE_ACCELERATION_SRCS)
+populate_tflite_source_vars("core/api" TFLITE_CORE_API_SRCS)
+populate_tflite_source_vars("core/async" TFLITE_CORE_ASYNC_SRCS)
+populate_tflite_source_vars("core/async/c" TFLITE_CORE_ASYNC_C_SRCS)
+populate_tflite_source_vars("core/async/interop" TFLITE_CORE_ASYNC_INTEROP_SRCS)
+populate_tflite_source_vars("core/async/interop/c" TFLITE_CORE_ASYNC_INTEROP_C_SRCS)
+populate_tflite_source_vars("core/c" TFLITE_CORE_C_SRCS)
+populate_tflite_source_vars("core/experimental/acceleration/configuration" TFLITE_CORE_EXPERIMENTAL_SRCS)
+populate_tflite_source_vars("core/kernels" TFLITE_CORE_KERNELS_SRCS)
+populate_tflite_source_vars("core/tools" TFLITE_CORE_TOOLS_SRCS)
+populate_tflite_source_vars("c" TFLITE_C_SRCS)
+populate_tflite_source_vars("delegates" TFLITE_DELEGATES_SRCS)
+
+# Enable NNAPI
+populate_tflite_source_vars("delegates/nnapi"
+  TFLITE_DELEGATES_NNAPI_SRCS
+  FILTER "(_test_list|_disabled)\\.(cc|h)$"
+)
+populate_tflite_source_vars(
+  "nnapi" TFLITE_NNAPI_SRCS FILTER "(_disabled)\\.(cc|h)$"
+)
+list(APPEND TFLITE_NNAPI_SRCS
+  "${TFLITE_SOURCE_DIR}/nnapi/sl/SupportLibrary.cc"
+)
+
+# Enable experimental delegate
+populate_tflite_source_vars("delegates/external"
+  TFLITE_DELEGATES_EXTERNAL_SRCS
+  FILTER ".*(_test|_tester)\\.(cc|h)"
+)
+
+populate_tflite_source_vars("experimental/remat"
+  TFLITE_EXPERIMENTAL_REMAT_SRCS
+  FILTER ".*_test\\.(cc|h)$"
+)
+
+# Enable  experimental support for resource (need for build success)
+populate_tflite_source_vars("experimental/resource"
+TFLITE_EXPERIMENTAL_RESOURCE_SRCS
+)
+
+# Disable XNNPack
+
+populate_tflite_source_vars("experimental/ruy"
+  TFLITE_EXPERIMENTAL_RUY_SRCS
+  FILTER
+  ".*(test(_fast|_slow|_special_specs))\\.(cc|h)$"
+  ".*(benchmark|tune_tool|example)\\.(cc|h)$"
+)
+populate_tflite_source_vars("experimental/ruy/profiler"
+  TFLITE_EXPERIMENTAL_RUY_PROFILER_SRCS
+  FILTER ".*(test|test_instrumented_library)\\.(cc|h)$"
+)
+# Enable Ruy
+list(APPEND TFLITE_TARGET_PUBLIC_OPTIONS "-DTFLITE_WITH_RUY")
+
+populate_tflite_source_vars("kernels"
+  TFLITE_KERNEL_SRCS
+  FILTER "(.*_test_util_internal|test_.*|.*_ops_wrapper)\\.(cc|h)"
+)
+populate_tflite_source_vars("kernels/internal" TFLITE_KERNEL_INTERNAL_SRCS)
+populate_tflite_source_vars("kernels/internal/optimized"
+  TFLITE_KERNEL_INTERNAL_OPT_SRCS
+)
+populate_tflite_source_vars("kernels/internal/optimized/integer_ops"
+  TFLITE_KERNEL_INTERNAL_OPT_INTEGER_OPS_SRCS
+)
+populate_tflite_source_vars("kernels/internal/optimized/sparse_ops"
+  TFLITE_KERNEL_INTERNAL_OPT_SPARSE_OPS_SRCS
+)
+populate_tflite_source_vars("kernels/internal/reference"
+  TFLITE_KERNEL_INTERNAL_REF_SRCS
+)
+populate_tflite_source_vars("kernels/internal/reference/integer_ops"
+  TFLITE_KERNEL_INTERNAL_REF_INTEGER_OPS_SRCS
+)
+populate_tflite_source_vars("kernels/internal/reference/sparse_ops"
+  TFLITE_KERNEL_INTERNAL_REF_SPARSE_OPS_SRCS
+)
+populate_tflite_source_vars("kernels/internal/optimized/4bit"
+  TFLITE_KERNEL_INTERNAL_OPT_4BIT_SRCS
+  FILTER "(.*neon.*|.*sse.*)\\.(cc|h)"
+)
+set(TFLITE_PROFILER_SRCS
+  ${TFLITE_SOURCE_DIR}/profiling/platform_profiler.cc
+  ${TFLITE_SOURCE_DIR}/profiling/root_profiler.h
+  ${TFLITE_SOURCE_DIR}/profiling/root_profiler.cc
+  ${TFLITE_SOURCE_DIR}/profiling/telemetry/profiler.cc
+  ${TFLITE_SOURCE_DIR}/profiling/telemetry/profiler.h
+  ${TFLITE_SOURCE_DIR}/profiling/telemetry/telemetry.cc
+  ${TFLITE_SOURCE_DIR}/profiling/telemetry/c/telemetry_setting_internal.cc
+  ${TFLITE_SOURCE_DIR}/profiling/telemetry/c/telemetry_setting_internal.h
+  ${TFLITE_SOURCE_DIR}/profiling/telemetry/c/profiler.h
+  ${TFLITE_SOURCE_DIR}/profiling/telemetry/c/telemetry_setting.h
+  ${TFLITE_SOURCE_DIR}/profiling/telemetry/telemetry_status.h
+)
+if(CMAKE_SYSTEM_NAME MATCHES "Android")
+  list(APPEND TFLITE_PROFILER_SRCS
+    ${TFLITE_SOURCE_DIR}/profiling/atrace_profiler.cc
+  )
+endif()
+
+# include headers
+list(APPEND TFLITE_INCLUDE_DIRS "${TSL_SOURCE_DIR}")
+list(APPEND TFLITE_INCLUDE_DIRS "${TensorFlowSource_DIR}")
+list(APPEND TFLITE_INCLUDE_DIRS "${TensorFlowGEMMLowpSource_DIR}")
+list(APPEND TFLITE_INCLUDE_DIRS "${Fp16Source_DIR}/include")
+#list(APPEND TFLITE_INCLUDE_DIRS "${Pybind11Source_DIR}/include")
+list(APPEND TFLITE_INCLUDE_DIRS "${CpuInfoSource_DIR}")
+list(APPEND TFLITE_INCLUDE_DIRS "${MLDtypesSource_DIR}")
+
+if(NEON2SSESource_FOUND)
+  list(APPEND TFLITE_INCLUDE_DIRS "${NEON2SSESource_DIR}")
+endif(NEON2SSESource_FOUND)
+
+# TFLite library
+set(_ALL_TFLITE_SRCS
+  ${TFLITE_CORE_ACCELERATION_SRCS}
+  ${TFLITE_CORE_API_SRCS}
+  ${TFLITE_CORE_C_SRCS}
+  ${TFLITE_CORE_EXPERIMENTAL_SRCS}
+  ${TFLITE_CORE_KERNELS_SRCS}
+  ${TFLITE_CORE_SRCS}
+  ${TFLITE_CORE_ASYNC_SRCS}
+  ${TFLITE_CORE_ASYNC_C_SRCS}
+  ${TFLITE_CORE_ASYNC_INTEROP_SRCS}
+  ${TFLITE_CORE_ASYNC_INTEROP_C_SRCS}
+  ${TFLITE_CORE_TOOLS_SRCS}
+  ${TFLITE_C_SRCS}
+  ${TFLITE_DELEGATES_FLEX_SRCS}
+  ${TFLITE_DELEGATES_GPU_SRCS}
+  ${TFLITE_DELEGATES_NNAPI_SRCS}
+  ${TFLITE_DELEGATES_SRCS}
+  ${TFLITE_DELEGATES_XNNPACK_SRCS}
+  ${TFLITE_DELEGATES_EXTERNAL_SRCS}
+  ${TFLITE_EXPERIMENTAL_REMAT_SRCS}
+  ${TFLITE_EXPERIMENTAL_RESOURCE_SRCS}
+  ${TFLITE_EXPERIMENTAL_RUY_PROFILER_SRCS}
+  ${TFLITE_EXPERIMENTAL_RUY_SRCS}
+  ${TFLITE_KERNEL_INTERNAL_OPT_INTEGER_OPS_SRCS}
+  ${TFLITE_KERNEL_INTERNAL_OPT_SPARSE_OPS_SRCS}
+  ${TFLITE_KERNEL_INTERNAL_OPT_SRCS}
+  ${TFLITE_KERNEL_INTERNAL_OPT_4BIT_SRCS}
+  ${TFLITE_KERNEL_INTERNAL_REF_INTEGER_OPS_SRCS}
+  ${TFLITE_KERNEL_INTERNAL_REF_SPARSE_OPS_SRCS}
+  ${TFLITE_KERNEL_INTERNAL_REF_SRCS}
+  ${TFLITE_KERNEL_INTERNAL_SRCS}
+  ${TFLITE_KERNEL_SRCS}
+  ${TFLITE_NNAPI_SRCS}
+  ${TFLITE_SRCS}
+  ${TFLITE_PROFILER_SRCS}
+  ${TFLITE_SOURCE_DIR}/internal/signature_def.h
+  ${TFLITE_SOURCE_DIR}/kernels/internal/utils/sparsity_format_converter.cc
+  ${TFLITE_SOURCE_DIR}/schema/conversion_metadata_generated.h
+  ${TFLITE_SOURCE_DIR}/schema/schema_utils.cc
+  ${TFLITE_SOURCE_DIR}/schema/schema_generated.h
+)
+add_library(tensorflow-lite-2.16.1 STATIC
+  ${_ALL_TFLITE_SRCS}
+)
+target_include_directories(tensorflow-lite-2.16.1
+  SYSTEM PUBLIC
+    ${TFLITE_INCLUDE_DIRS}
+)
+
+target_compile_options(tensorflow-lite-2.16.1 PUBLIC ${TFLITE_TARGET_PUBLIC_OPTIONS})
+set_property(TARGET tensorflow-lite-2.16.1 PROPERTY POSITION_INDEPENDENT_CODE ON)
+target_link_libraries(tensorflow-lite-2.16.1 eigen flatbuffers::flatbuffers-23.5.26 ruy abseil farmhash oourafft::fftsg2d pthreadpool ${LIB_PTHREAD} dl)
+if(NOT ANDROID)
+  target_link_libraries(tensorflow-lite-2.16.1 rt)
+endif()
+
+# Define TF_LITE_DISABLE_X86_NEON for debug build
+# If we upgrade NEON2SSE version, we can remove below line
+if(NEON2SSESource_FOUND)
+  target_compile_definitions(tensorflow-lite-2.16.1 PRIVATE $<$<CONFIG:Debug>:TF_LITE_DISABLE_X86_NEON>)
+endif(NEON2SSESource_FOUND)
+
+if(ANDROID)
+  target_link_libraries(tensorflow-lite-2.16.1 log)
+  #target_include_directories(tensorflow-lite-2.16.1 PUBLIC "${NDK_DIR}/..")
+endif()
diff --git a/infra/nnfw/cmake/packages/TensorFlowLite-2.16.1/TensorFlowLiteConfig.cmake b/infra/nnfw/cmake/packages/TensorFlowLite-2.16.1/TensorFlowLiteConfig.cmake
new file mode 100644 (file)
index 0000000..d118249
--- /dev/null
@@ -0,0 +1,102 @@
+# NOTE This line prevents multiple definitions of tensorflow-lite target
+if(TARGET tensorflow-lite-2.16.1)
+  set(TensorFlowLite_FOUND TRUE)
+  return()
+endif(TARGET tensorflow-lite-2.16.1)
+
+if(BUILD_TENSORFLOW_LITE)
+  macro(return_unless VAR)
+  if(NOT ${VAR})
+    message("TFLite 2.16.1: ${VAR} NOT TRUE")
+    set(TensorFlowLite_FOUND FALSE)
+    return()
+  endif(NOT ${VAR})
+  endmacro(return_unless)
+
+  nnas_include(ExternalSourceTools)
+  nnas_include(OptionTools)
+
+  nnas_find_package(TensorFlowSource EXACT 2.16.1 QUIET)
+  return_unless(TensorFlowSource_FOUND)
+
+  # Below urls come from https://github.com/tensorflow/tensorflow/blob/v2.16.1/tensorflow/workspace2.bzl
+  nnas_find_package(Abseil QUIET)
+  return_unless(Abseil_FOUND)
+  nnfw_find_package(Eigen QUIET)
+  return_unless(Eigen_FOUND)
+  nnas_find_package(Farmhash QUIET)
+  return_unless(Farmhash_FOUND)
+  nnfw_find_package(FlatBuffers EXACT 23.5.26 QUIET)
+  return_unless(FlatBuffers_FOUND)
+  nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.16.1 QUIET)
+  return_unless(TensorFlowGEMMLowpSource_FOUND)
+  nnfw_find_package(OouraFFT QUIET)
+  return_unless(OouraFFT_FOUND)
+  nnfw_find_package(Ruy QUIET)
+  return_unless(Ruy_FOUND)
+  nnas_find_package(MLDtypesSource QUIET)
+  return_unless(MLDtypesSource_FOUND)
+
+  # TensorFlow Lite requires FP16 library's header only
+  nnas_find_package(Fp16Source QUIET)
+  return_unless(Fp16Source_FOUND)
+
+  # PThreadpool
+  nnfw_find_package(Pthreadpool QUIET)
+  return_unless(Pthreadpool_FOUND)
+
+  # TensorFlow Lite requires Pybind11 library's header only
+  # But Pybind11 requires python3-dev package
+  # TODO Enable below by installing package on build system
+  #nnas_find_package(Pybind11Source QUIET)
+  #return_unless(Pybind11Source_FOUND)
+
+  # Optional packages
+  nnas_find_package(NEON2SSESource QUIET)
+
+  nnas_include(ExternalProjectTools)
+  add_extdirectory("${CMAKE_CURRENT_LIST_DIR}/TensorFlowLite" tflite-2.16.1)
+
+  set(TensorFlowLite_FOUND TRUE)
+  return()
+endif()
+
+# Use pre-built TensorFlow Lite
+find_path(TFLITE_INCLUDE_DIR NAMES  tensorflow/lite/c/c_api.h)
+find_library(TFLITE_LIB NAMES       tensorflow2-lite)
+
+if(NOT TFLITE_INCLUDE_DIR)
+  # Tizen install TensorFlow Lite 2.16.1 headers in /usr/include/tensorflow2
+  find_path(TFLITE_INCLUDE_DIR NAMES tensorflow/lite/c/c_api.h PATHS "/usr/include/tensorflow2")
+  if(NOT TFLITE_INCLUDE_DIR)
+    set(TensorFlowLite_FOUND FALSE)
+    return()
+  endif(NOT TFLITE_INCLUDE_DIR)
+endif(NOT TFLITE_INCLUDE_DIR)
+
+if(NOT TFLITE_LIB)
+  set(TensorFlowLite_FOUND FALSE)
+  return()
+endif(NOT TFLITE_LIB)
+
+message(STATUS "Found TensorFlow Lite: TRUE (include: ${TFLITE_INCLUDE_DIR}, lib: ${TFLITE_LIB}")
+
+# TODO Use IMPORTED target
+add_library(tensorflow-lite-2.16.1 INTERFACE)
+target_include_directories(tensorflow-lite-2.16.1 SYSTEM INTERFACE ${TFLITE_INCLUDE_DIR})
+target_link_libraries(tensorflow-lite-2.16.1 INTERFACE ${TFLITE_LIB})
+find_package(Flatbuffers)
+if(Flatbuffers_FOUND)
+  target_link_libraries(tensorflow-lite-2.16.1 INTERFACE flatbuffers::flatbuffers)
+endif(Flatbuffers_FOUND)
+
+# Prefer -pthread to -lpthread
+set(THREADS_PREFER_PTHREAD_FLAG TRUE)
+set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+find_package(Threads QUIET)
+
+if(Threads_FOUND)
+  target_link_libraries(tensorflow-lite-2.16.1 INTERFACE ${CMAKE_THREAD_LIBS_INIT})
+endif(Threads_FOUND)
+
+set(TensorFlowLite_FOUND TRUE)
diff --git a/infra/nnfw/cmake/packages/TensorFlowLite-2.16.1/TensorFlowLiteConfigVersion.cmake b/infra/nnfw/cmake/packages/TensorFlowLite-2.16.1/TensorFlowLiteConfigVersion.cmake
new file mode 100644 (file)
index 0000000..e3cf0a9
--- /dev/null
@@ -0,0 +1,9 @@
+set(PACKAGE_VERSION "2.16.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_UNSUITABLE FALSE)
+endif(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
diff --git a/infra/nnfw/cmake/packages/TensorFlowLite-2.8.0/TensorFlowLite/CMakeLists.txt b/infra/nnfw/cmake/packages/TensorFlowLite-2.8.0/TensorFlowLite/CMakeLists.txt
deleted file mode 100644 (file)
index cbc10d2..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-# Reference: https://github.com/tensorflow/tensorflow/blob/v2.8.0/tensorflow/lite/CMakeLists.txt
-#
-# Tensorflow Lite library 2.8.0
-#
-set(TFLITE_SOURCE_DIR ${TensorFlowSource_DIR}/tensorflow/lite)
-
-# Generate TensorFlow Lite FlatBuffer code.
-# We used to have an actual compilation logic with flatc but decided to use
-# schema_generated.h since flatc doesn't work with cross compilation.
-set(TFLITE_FLATBUFFERS_SCHEMA_DIR "${TFLITE_SOURCE_DIR}/schema")
-
-macro(populate_source_vars SOURCE_DIR SOURCES_VAR)
-  cmake_parse_arguments(ARGS "RECURSE" "" "FILTER" ${ARGN})
-  if(ARGS_RECURSE)
-    set(GLOB_OP GLOB_RECURSE)
-  else()
-    set(GLOB_OP GLOB)
-  endif()
-  set(DEFAULT_FILE_FILTER ".*(_test|test_util)\\.(c|cc|h)$")
-  file(${GLOB_OP} FOUND_SOURCES "${SOURCE_DIR}/*.*")
-  list(FILTER FOUND_SOURCES INCLUDE REGEX ".*\\.(c|cc|h)$")
-  list(FILTER FOUND_SOURCES EXCLUDE REGEX "${DEFAULT_FILE_FILTER}")
-  foreach(FILE_FILTER ${ARGS_FILTER})
-    list(FILTER FOUND_SOURCES EXCLUDE REGEX "${FILE_FILTER}")
-  endforeach()
-  list(APPEND ${SOURCES_VAR} ${FOUND_SOURCES})
-endmacro()
-# Simplifies inclusion of non-test sources and headers from a directory
-# relative to TFLITE_SOURCE_DIR. See populate_source_vars() for the
-# description of arguments including and following SOURCES_VAR.
-macro(populate_tflite_source_vars RELATIVE_DIR SOURCES_VAR)
-  populate_source_vars(
-    "${TFLITE_SOURCE_DIR}/${RELATIVE_DIR}" ${SOURCES_VAR} ${ARGN}
-  )
-endmacro()
-
-# Build a list of source files to compile into the TF Lite library.
-populate_tflite_source_vars("." TFLITE_SRCS)
-
-# This particular file is excluded because the more explicit approach to enable
-# XNNPACK delegate is preferred to the weak-symbol one.
-list(FILTER TFLITE_SRCS EXCLUDE REGEX ".*tflite_with_xnnpack\\.cc$")
-
-# Exclude Flex related files.
-list(FILTER TFLITE_SRCS EXCLUDE REGEX ".*with_selected_ops\\.cc$")
-
-# Use MMAP
-list(FILTER TFLITE_SRCS EXCLUDE REGEX ".*mmap_allocation_disabled\\.cc$")
-
-if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
-  list(FILTER TFLITE_SRCS EXCLUDE REGEX ".*minimal_logging_android\\.cc$")
-endif()
-if(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "iOS")
-  list(FILTER TFLITE_SRCS EXCLUDE REGEX ".*minimal_logging_ios\\.cc$")
-endif()
-
-populate_tflite_source_vars("core" TFLITE_CORE_SRCS)
-populate_tflite_source_vars("core/api" TFLITE_CORE_API_SRCS)
-populate_tflite_source_vars("c" TFLITE_C_SRCS)
-populate_tflite_source_vars("delegates" TFLITE_DELEGATES_SRCS)
-
-# Enable NNAPI
-populate_tflite_source_vars("delegates/nnapi"
-TFLITE_DELEGATES_NNAPI_SRCS
-FILTER "(_test_list|_disabled)\\.(cc|h)$"
-)
-populate_tflite_source_vars(
-"nnapi" TFLITE_NNAPI_SRCS FILTER "(_disabled)\\.(cc|h)$"
-)
-
-# Disable XNNPack
-
-# Enable  experimental support for resource (need for build success)
-populate_tflite_source_vars("experimental/resource"
-TFLITE_EXPERIMENTAL_RESOURCE_SRCS
-)
-
-# Enable Ruy
-populate_tflite_source_vars("experimental/ruy"
-  TFLITE_EXPERIMENTAL_RUY_SRCS
-  FILTER
-  ".*(test(_fast|_slow|_special_specs))\\.(cc|h)$"
-  ".*(benchmark|tune_tool|example)\\.(cc|h)$"
-)
-populate_tflite_source_vars("experimental/ruy/profiler"
-  TFLITE_EXPERIMENTAL_RUY_PROFILER_SRCS
-  FILTER ".*(test|test_instrumented_library)\\.(cc|h)$"
-)
-list(APPEND TFLITE_TARGET_PUBLIC_OPTIONS "-DTFLITE_WITH_RUY")
-
-populate_tflite_source_vars("kernels"
-  TFLITE_KERNEL_SRCS
-  FILTER "(.*_test_util_internal|test_.*|.*_ops_wrapper)\\.(cc|h)"
-)
-populate_tflite_source_vars("kernels/internal" TFLITE_KERNEL_INTERNAL_SRCS)
-populate_tflite_source_vars("kernels/internal/optimized"
-  TFLITE_KERNEL_INTERNAL_OPT_SRCS
-)
-populate_tflite_source_vars("kernels/internal/optimized/integer_ops"
-  TFLITE_KERNEL_INTERNAL_OPT_INTEGER_OPS_SRCS
-)
-populate_tflite_source_vars("kernels/internal/optimized/sparse_ops"
-  TFLITE_KERNEL_INTERNAL_OPT_SPARSE_OPS_SRCS
-)
-populate_tflite_source_vars("kernels/internal/reference"
-  TFLITE_KERNEL_INTERNAL_REF_SRCS
-)
-populate_tflite_source_vars("kernels/internal/reference/integer_ops"
-  TFLITE_KERNEL_INTERNAL_REF_INTEGER_OPS_SRCS
-)
-populate_tflite_source_vars("kernels/internal/reference/sparse_ops"
-  TFLITE_KERNEL_INTERNAL_REF_SPARSE_OPS_SRCS
-)
-set(TFLITE_PROFILER_SRCS ${TFLITE_SOURCE_DIR}/profiling/platform_profiler.cc)
-if(CMAKE_SYSTEM_NAME MATCHES "Android")
-  list(APPEND TFLITE_PROFILER_SRCS
-    ${TFLITE_SOURCE_DIR}/profiling/atrace_profiler.cc
-  )
-endif()
-
-# Common include directories
-set(TFLITE_INCLUDE_DIRS
-  "${TENSORFLOW_SOURCE_DIR}"
-  "${TFLITE_FLATBUFFERS_SCHEMA_DIR}"
-)
-
-# include headers
-list(APPEND TFLITE_INCLUDE_DIRS "${TensorFlowSource_DIR}")
-list(APPEND TFLITE_INCLUDE_DIRS "${TensorFlowGEMMLowpSource_DIR}")
-list(APPEND TFLITE_INCLUDE_DIRS "${Fp16Source_DIR}/include")
-#list(APPEND TFLITE_INCLUDE_DIRS "${Pybind11Source_DIR}/include")
-list(APPEND TFLITE_INCLUDE_DIRS "${CpuInfoSource_DIR}")
-
-if(NEON2SSESource_FOUND)
-  list(APPEND TFLITE_INCLUDE_DIRS "${NEON2SSESource_DIR}")
-endif(NEON2SSESource_FOUND)
-
-# TFLite library
-add_library(tensorflow-lite-2.8.0 STATIC
-  ${TFLITE_CORE_API_SRCS}
-  ${TFLITE_CORE_SRCS}
-  ${TFLITE_C_SRCS}
-  ${TFLITE_DELEGATES_NNAPI_SRCS}
-  ${TFLITE_DELEGATES_SRCS}
-  ${TFLITE_EXPERIMENTAL_RESOURCE_SRCS}
-  ${TFLITE_EXPERIMENTAL_RUY_PROFILER_SRCS}
-  ${TFLITE_EXPERIMENTAL_RUY_SRCS}
-  ${TFLITE_KERNEL_INTERNAL_OPT_INTEGER_OPS_SRCS}
-  ${TFLITE_KERNEL_INTERNAL_OPT_SPARSE_OPS_SRCS}
-  ${TFLITE_KERNEL_INTERNAL_OPT_SRCS}
-  ${TFLITE_KERNEL_INTERNAL_REF_INTEGER_OPS_SRCS}
-  ${TFLITE_KERNEL_INTERNAL_REF_SPARSE_OPS_SRCS}
-  ${TFLITE_KERNEL_INTERNAL_REF_SRCS}
-  ${TFLITE_KERNEL_INTERNAL_SRCS}
-  ${TFLITE_KERNEL_SRCS}
-  ${TFLITE_NNAPI_SRCS}
-  ${TFLITE_SRCS}
-  ${TFLITE_PROFILER_SRCS}
-  ${TFLITE_SOURCE_DIR}/kernels/internal/utils/sparsity_format_converter.cc
-  ${TFLITE_SOURCE_DIR}/schema/schema_utils.cc
-  ${OouraFFTSource_DIR}/fftsg.c
-  ${OouraFFTSource_DIR}/fftsg2d.c
-)
-target_include_directories(tensorflow-lite-2.8.0
-  SYSTEM PUBLIC
-    ${TFLITE_INCLUDE_DIRS}
-)
-
-target_compile_definitions(tensorflow-lite-2.8.0 PUBLIC "GEMMLOWP_ALLOW_SLOW_SCALAR_FALLBACK -DTFLITE_WITH_RUY -DTFLITE_WITH_RUY_GEMV -DRUY_HAVE_CPUINFO -DNNAPI_VERBOSE_VALIDATION")
-set_property(TARGET tensorflow-lite-2.8.0 PROPERTY POSITION_INDEPENDENT_CODE ON)
-target_link_libraries(tensorflow-lite-2.8.0 eigen flatbuffers::flatbuffers ruy abseil farmhash ${LIB_PTHREAD} dl)
-if(NOT ANDROID)
-  target_link_libraries(tensorflow-lite-2.8.0 rt)
-endif()
-
-# Define TF_LITE_DISABLE_X86_NEON for debug build
-# If we upgrade NEON2SSE version, we can remove below line
-if(NEON2SSESource_FOUND)
-  target_compile_definitions(tensorflow-lite-2.8.0 PRIVATE $<$<CONFIG:Debug>:TF_LITE_DISABLE_X86_NEON>)
-endif(NEON2SSESource_FOUND)
-
-if(ANDROID)
-  target_link_libraries(tensorflow-lite-2.8.0 log)
-  #target_include_directories(tensorflow-lite-2.8.0 PUBLIC "${NDK_DIR}/..")
-endif()
diff --git a/infra/nnfw/cmake/packages/TensorFlowLite-2.8.0/TensorFlowLiteConfig.cmake b/infra/nnfw/cmake/packages/TensorFlowLite-2.8.0/TensorFlowLiteConfig.cmake
deleted file mode 100644 (file)
index 60f7f54..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-# NOTE This line prevents multiple definitions of tensorflow-lite target
-if(TARGET tensorflow-lite-2.8.0)
-  set(TensorFlowLite_FOUND TRUE)
-  return()
-endif(TARGET tensorflow-lite-2.8.0)
-
-if(BUILD_TENSORFLOW_LITE)
-  macro(return_unless VAR)
-  if(NOT ${VAR})
-    message("TFLite 2.8: ${VAR} NOT TRUE")
-    set(TensorFlowLite_FOUND FALSE)
-    return()
-  endif(NOT ${VAR})
-  endmacro(return_unless)
-
-  nnas_include(ExternalSourceTools)
-  nnas_include(OptionTools)
-
-  nnas_find_package(TensorFlowSource EXACT 2.8.0 QUIET)
-  return_unless(TensorFlowSource_FOUND)
-
-  # Below urls come from https://github.com/tensorflow/tensorflow/blob/v2.8.0/tensorflow/workspace2.bzl
-  nnas_find_package(Abseil QUIET)
-  return_unless(Abseil_FOUND)
-  nnfw_find_package(Eigen QUIET)
-  return_unless(Eigen_FOUND)
-  nnas_find_package(Farmhash QUIET)
-  return_unless(Farmhash_FOUND)
-  nnfw_find_package(FlatBuffers QUIET)
-  return_unless(FlatBuffers_FOUND)
-  nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.8.0 QUIET)
-  return_unless(TensorFlowGEMMLowpSource_FOUND)
-  nnas_find_package(OouraFFTSource QUIET)
-  return_unless(OouraFFTSource_FOUND)
-  nnfw_find_package(Ruy QUIET)
-  return_unless(Ruy_FOUND)
-
-  # TensorFlow Lite requires FP16 library's header only
-  nnas_find_package(Fp16Source QUIET)
-  return_unless(Fp16Source_FOUND)
-
-  # TensorFlow Lite requires Pybind11 library's header only
-  # But Pybind11 requires python3-dev package
-  # TODO Enable below by installing package on build system
-  #nnas_find_package(Pybind11Source QUIET)
-  #return_unless(Pybind11Source_FOUND)
-
-  # Optional packages
-  nnas_find_package(NEON2SSESource QUIET)
-
-  nnas_include(ExternalProjectTools)
-  add_extdirectory("${CMAKE_CURRENT_LIST_DIR}/TensorFlowLite" tflite-2.8.0)
-
-  set(TensorFlowLite_FOUND TRUE)
-  return()
-endif()
-
-# Use pre-built TensorFlow Lite
-find_path(TFLITE_INCLUDE_DIR NAMES  tensorflow/lite/c/c_api.h)
-find_library(TFLITE_LIB NAMES       tensorflow2-lite)
-
-if(NOT TFLITE_INCLUDE_DIR)
-  # Tizen install TensorFlow Lite 2.8 headers in /usr/include/tensorflow2
-  find_path(TFLITE_INCLUDE_DIR NAMES tensorflow/lite/c/c_api.h PATHS "/usr/include/tensorflow2")
-  if(NOT TFLITE_INCLUDE_DIR)
-    set(TensorFlowLite_FOUND FALSE)
-    return()
-  endif(NOT TFLITE_INCLUDE_DIR)
-endif(NOT TFLITE_INCLUDE_DIR)
-
-if(NOT TFLITE_LIB)
-  set(TensorFlowLite_FOUND FALSE)
-  return()
-endif(NOT TFLITE_LIB)
-
-message(STATUS "Found TensorFlow Lite: TRUE (include: ${TFLITE_INCLUDE_DIR}, lib: ${TFLITE_LIB}")
-
-# TODO Use IMPORTED target
-add_library(tensorflow-lite-2.8.0 INTERFACE)
-target_include_directories(tensorflow-lite-2.8.0 SYSTEM INTERFACE ${TFLITE_INCLUDE_DIR})
-target_link_libraries(tensorflow-lite-2.8.0 INTERFACE ${TFLITE_LIB})
-find_package(Flatbuffers)
-if(Flatbuffers_FOUND)
-  target_link_libraries(tensorflow-lite-2.8.0 INTERFACE flatbuffers::flatbuffers)
-endif(Flatbuffers_FOUND)
-
-# Prefer -pthread to -lpthread
-set(THREADS_PREFER_PTHREAD_FLAG TRUE)
-set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
-find_package(Threads QUIET)
-
-if(Threads_FOUND)
-  target_link_libraries(tensorflow-lite-2.8.0 INTERFACE ${CMAKE_THREAD_LIBS_INIT})
-endif(Threads_FOUND)
-
-set(TensorFlowLite_FOUND TRUE)
diff --git a/infra/nnfw/cmake/packages/TensorFlowLite-2.8.0/TensorFlowLiteConfigVersion.cmake b/infra/nnfw/cmake/packages/TensorFlowLite-2.8.0/TensorFlowLiteConfigVersion.cmake
deleted file mode 100644 (file)
index cd49d7b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-set(PACKAGE_VERSION "2.8.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_UNSUITABLE FALSE)
-endif(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
index 73264d1..bc63e11 100644 (file)
@@ -2,7 +2,7 @@
 # Tensorflow Lite GPU delegate library 2.8.0
 #
 
-set(LIB_TENSORFLOW_GPU_DELEGATE "TensorFlowGpu")
+set(LIB_TENSORFLOW_GPU_DELEGATE tflite-gpu-delegate)
 
 #TENSORFLOWGPU_SOURCE_DIR
 set(TENSORFLOWSOURCE_DIR ${TensorFlowSource_DIR})
@@ -49,20 +49,21 @@ list(APPEND TFLITE_GPU_SRCS ${GPU_CL_SRC_LIST})
 
 add_library(${LIB_TENSORFLOW_GPU_DELEGATE} STATIC ${TFLITE_GPU_SRCS})
 
-target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE "${Opencl_Headers_DIR}")
-target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE "${Fp16Source_DIR}/include")
-target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE "${TensorFlowSource_DIR}")
-target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE "${TensorFlowGEMMLowpSource_DIR}")
-target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE "${TensorFlowEigenSource_DIR}")
-target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE "${VulkanSource_DIR}/include")
-target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE "${Opengl_HeadersSource_DIR}/api")
-target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE "${Egl_HeadersSource_DIR}/api")
+target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PUBLIC "${Opencl_HeadersSource_DIR}")
+target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PUBLIC "${Fp16Source_DIR}/include")
+target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PUBLIC "${TensorFlowSource_DIR}")
+target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PUBLIC "${TensorFlowGEMMLowpSource_DIR}")
+target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PUBLIC "${TensorFlowEigenSource_DIR}")
+target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PUBLIC "${VulkanSource_DIR}/include")
+target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PUBLIC "${Opengl_HeadersSource_DIR}/api")
+target_include_directories(${LIB_TENSORFLOW_GPU_DELEGATE} PUBLIC "${Egl_HeadersSource_DIR}/api")
 
-target_link_libraries(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE abseil farmhash fp16 flatbuffers)
+target_link_libraries(${LIB_TENSORFLOW_GPU_DELEGATE} PUBLIC abseil farmhash fp16 flatbuffers::flatbuffers)
 
 # GL codes are not used on gpu_cl
-target_compile_options(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE "-DCL_DELEGATE_NO_GL")
-target_compile_options(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE "-DTFLITE_GPU_BINARY_RELEASE" "-DEGL_NO_X11")
+target_compile_definitions(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE CL_DELEGATE_NO_GL)
+target_compile_definitions(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE CL_TARGET_OPENCL_VERSION=220)
+target_compile_definitions(${LIB_TENSORFLOW_GPU_DELEGATE} PRIVATE TFLITE_GPU_BINARY_RELEASE EGL_NO_X11)
 
 # deprecated-copy warning on header (gcc 9.4.0)
 if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 9.4)
index 101d757..19742c2 100644 (file)
@@ -3,7 +3,6 @@ function(_Xnnpack_Build)
   nnfw_find_package(Fxdiv QUIET)
   nnfw_find_package(CpuInfo QUIET)
   nnfw_find_package(Pthreadpool QUIET)
-  nnfw_find_package(Psimd QUIET)
   nnfw_find_package(Fp16 QUIET)
 
   # NOTE This line prevents multiple definitions of cpuinfo target
@@ -19,12 +18,25 @@ function(_Xnnpack_Build)
     return()
   endif(NOT XnnpackSource_FOUND)
 
+  set(XNNPACK_LIBRARY_TYPE "static")
   set(XNNPACK_BUILD_TESTS OFF CACHE BOOL "Build XNNPACK unit tests")
   set(XNNPACK_BUILD_BENCHMARKS OFF CACHE BOOL "Build XNNPACK benchmarks")
   set(XNNPACK_USE_SYSTEM_LIBS ON CACHE BOOL "Use system-provided dependency libraries")
 
+  # microkernel build is not supported under gcc 9.x, clang, and tizen armv7l
+  # TODO Enable this
+if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0 OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
+  (TARGET_OS STREQUAL "tizen" AND TARGET_ARCH STREQUAL "armv7l"))
+  set(XNNPACK_ENABLE_ASSEMBLY OFF CACHE BOOL "Build XNNPACK with assembly micro-kernels")
+  set(XNNPACK_ENABLE_ARM_I8MM OFF CACHE BOOL "Build XNNPACK with ARM I8MM (8-bit integer matrix multiply accumulate) micro-kernels")
+  # Set definition: used on patched code
+  add_compile_definitions("XNN_ENABLE_ASSEMBLY=$<BOOL:${XNNPACK_ENABLE_ASSEMBLY}>")
+endif()
+
+  # Set -fPIC property to XNNPack and linked libraries
+  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
   add_extdirectory("${XnnpackSource_DIR}" XNNPACK EXCLUDE_FROM_ALL)
-  set_target_properties(XNNPACK PROPERTIES POSITION_INDEPENDENT_CODE ON)
   # Suppress warnings generated by xnnpack
   set_target_properties(XNNPACK PROPERTIES COMPILE_FLAGS "-Wno-deprecated-declarations")
   set(XnnpackSource_DIR ${XnnpackSource_DIR} PARENT_SCOPE)
index 4a3601e..8c1e7bc 100644 (file)
@@ -7,5 +7,4 @@ if [[ ! -d "${BUILD_PATH}" ]]; then
   exit 255
 fi
 
-cd ${BUILD_PATH}
-cmake --build . -- "$@"
+cmake --build ${BUILD_PATH} -- "$@"
index 98cad76..6883fba 100644 (file)
@@ -2,25 +2,5 @@
 
 import "build.configuration"
 
-INSTALL_PATH="${NNFW_INSTALL_PREFIX:-${WORKSPACE_PATH}/out}"
-# Normalize to absolute path
-if [[ "${INSTALL_PATH}" != /*  ]]; then
-    INSTALL_PATH=${NNFW_PROJECT_PATH}/${INSTALL_PATH}
-fi
-
-# Create "BUILD_PATH"
-mkdir -p "${BUILD_PATH}"
-
-if [ ! -d "${INSTALL_PATH}" ]; then
-  echo "[WARNING] Cannot find install directory '${INSTALL_PATH}'"
-  echo "          Try to make install directory"
-  mkdir -p "${INSTALL_PATH}"
-  if [ ! -d "${INSTALL_PATH}" ]; then
-    echo "[ERROR] Fail to make install directory '${INSTALL_PATH}'"
-    echo "        Please make '${INSTALL_PATH}' directory first"
-    exit 255
-  fi
-fi
-
-cd "${BUILD_PATH}"
-cmake "${NNFW_PROJECT_PATH}"/infra/nnfw -DCMAKE_INSTALL_PREFIX="${INSTALL_PATH}" "$@"
+# Require cmake version >= 3.13 to use '-S' & '-B' option
+cmake -S "${NNFW_PROJECT_PATH}"/infra/nnfw -B ${BUILD_PATH} "$@"
diff --git a/infra/nnfw/command/docker-run b/infra/nnfw/command/docker-run
deleted file mode 100644 (file)
index b523d61..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-import "docker.configuration"
-
-docker run $DOCKER_RUN_OPTS $DOCKER_ENV_VARS $DOCKER_VOLUMES $DOCKER_IMAGE_NAME "$@"
-EXITCODE=$?
-
-docker_cleanup
-
-if [ $EXITCODE -ne 0 ]; then
-  exit $EXITCODE
-fi
diff --git a/infra/nnfw/command/docker-run-user b/infra/nnfw/command/docker-run-user
deleted file mode 100644 (file)
index 3b5a961..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-import "docker.configuration"
-
-DOCKER_RUN_OPTS+=" -u $(id -u):$(id -g)"
-
-docker run $DOCKER_RUN_OPTS $DOCKER_ENV_VARS $DOCKER_VOLUMES $DOCKER_IMAGE_NAME "$@"
-EXITCODE=$?
-
-if [ $EXITCODE -ne 0 ]; then
-  exit $EXITCODE
-fi
diff --git a/infra/nnfw/command/docker-shell b/infra/nnfw/command/docker-shell
deleted file mode 100644 (file)
index 1413a7a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-import "docker.configuration"
-
-DOCKER_RUN_OPTS+=" -it"
-docker run $DOCKER_RUN_OPTS $DOCKER_ENV_VARS $DOCKER_VOLUMES $DOCKER_IMAGE_NAME "/bin/bash"
-EXITCODE=$?
-
-docker_cleanup
-
-if [ $EXITCODE -ne 0 ]; then
-  exit $EXITCODE
-fi
index 3bbb92e..8290b5e 100644 (file)
@@ -7,5 +7,5 @@ if [[ ! -d "${BUILD_PATH}" ]]; then
   exit 255
 fi
 
-cd ${BUILD_PATH}
-make install
+# Require cmake version >= 3.15
+cmake --install ${BUILD_PATH} "$@"
diff --git a/infra/nnfw/config/docker.configuration b/infra/nnfw/config/docker.configuration
deleted file mode 100644 (file)
index c61ab0f..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-
-DOCKER_IMAGE_NAME=${DOCKER_IMAGE_NAME:-nnfw/one-devtools}
-echo "Using docker image ${DOCKER_IMAGE_NAME}"
-
-if [ -z "`docker images ${DOCKER_IMAGE_NAME}`" ]; then
-  echo "Need docker image!"
-  exit 1
-fi
-
-HOST_PATH="$NNFW_PROJECT_PATH"
-DOCKER_PATH="$NNFW_PROJECT_PATH"
-
-export GIT_SSL_NO_VERIFY=1
-
-DOCKER_VOLUMES+=" -v $HOST_PATH:$DOCKER_PATH"
-
-if [[ ! -z $ENV_FILE ]]; then
-  DOCKER_ENV_VARS+=" --env-file ${ENV_FILE} "
-fi
-
-DOCKER_ENV_VARS+=" -e http_proxy"
-DOCKER_ENV_VARS+=" -e no_proxy"
-DOCKER_ENV_VARS+=" -e GIT_SSL_NO_VERIFY"
-DOCKER_ENV_VARS+=" -e EXTERNAL_DOWNLOAD_SERVER"
-DOCKER_ENV_VARS+=" -e NNFW_WORKSPACE"
-DOCKER_ENV_VARS+=" -e EXT_ACL_FOLDER"
-DOCKER_ENV_VARS+=" -e NDK_DIR"
-
-DOCKER_RUN_OPTS="${DOCKER_OPTS}"
-DOCKER_RUN_OPTS+=" --rm"
-DOCKER_RUN_OPTS+=" -w $DOCKER_PATH"
-
-function docker_cleanup()
-{
-  # Newly created files during during docker run can have different ownership.
-  # This may cause some problems, for example, some jenkins slaves or developers
-  # can't remove built files due to lack of permission.
-  # To address this issue, let's change owner of all files
-  # in nncc to owner of nncc.
-  NNFW_OWNER_UID=$(stat -c "%u" $HOST_PATH)
-  NNFW_OWNER_GID=$(stat -c "%g" $HOST_PATH)
-
-  CMD="chown -R $NNFW_OWNER_UID:$NNFW_OWNER_GID $DOCKER_PATH"
-  docker run $DOCKER_RUN_OPTS $DOCKER_ENV_VARS $DOCKER_VOLUMES $DOCKER_IMAGE_NAME $CMD
-}
index 23278bb..2b91252 100644 (file)
@@ -5,8 +5,44 @@ profile = profile.tizen
 [profile.tizen]
 repos = repo.base, repo.unified
 
+[profile.tizen_7]
+repos = repo.base_7, repo.unified_7
+
+[profile.tizen_8]
+repos = repo.base_8, repo.unified_8
+
+[profile.tizen-dev]
+repos = repo.base-dev, repo.unified-dev
+
+[profile.tizen-riscv]
+repos = repo.base-riscv, repo.unified-riscv
+
 [repo.unified]
-url = http://download.tizen.org/snapshots/TIZEN/Tizen-7.0/Tizen-7.0-Unified/latest/repos/standard/packages/
+url = http://download.tizen.org/snapshots/TIZEN/Tizen/Tizen-Unified/latest/repos/standard/packages/
 
 [repo.base]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen/Tizen-Base/latest/repos/standard/packages/
+
+[repo.unified_7]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen-7.0/Tizen-7.0-Unified/latest/repos/standard/packages/
+
+[repo.base_7]
 url = http://download.tizen.org/snapshots/TIZEN/Tizen-7.0/Tizen-7.0-Base/latest/repos/standard/packages/
+
+[repo.unified_8]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen-8.0/Tizen-8.0-Unified/latest/repos/standard/packages/
+
+[repo.base_8]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen-8.0/Tizen-8.0-Base/latest/repos/standard/packages/
+
+[repo.unified-dev]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen/Tizen-Unified-Dev/latest/repos/standard/packages/
+
+[repo.base-dev]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen/Tizen-Base-Dev/latest/repos/standard/packages/
+
+[repo.unified-riscv]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen/Tizen-Unified-RISCV/latest/repos/standard/packages/
+
+[repo.base-riscv]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen/Tizen-Base-RISCV/latest/repos/standard/packages/
diff --git a/infra/nnfw/python/.gitignore b/infra/nnfw/python/.gitignore
new file mode 100644 (file)
index 0000000..15d72de
--- /dev/null
@@ -0,0 +1,4 @@
+build/
+dist/
+nnfwapi/
+nnfwapi.egg-info/
diff --git a/infra/nnfw/python/README.md b/infra/nnfw/python/README.md
new file mode 100644 (file)
index 0000000..2a5942e
--- /dev/null
@@ -0,0 +1,55 @@
+# nnfwapi package
+
+`nnfwapi` is a package to run `nnpackage` with the nnfw python API.
+
+This package includes the nnfw python API module resulting from runtime build.
+
+It is provided separate package for each architecture(x86_64, armv7l, aarch64).
+
+It uses `nnfwapi/libnnfw_api_pybind.py` interface.
+
+## Packaging
+Execute this command, then the tasks such as copying modules, and packaging.
+
+```
+$ python3 setup.py sdist bdist_wheel --plat-name manylinux_x_y_arch
+```
+
+x_y is the glibc version of manylinux.
+
+arch is supported target architecture: aarch64, x86_64, armv7l
+
+## Publishing
+
+To publish the package, twine should be installed.
+
+```
+$ sudo apt install twine
+```
+This command is for TestPyPI only and it will be changed to PyPI.
+Additionally, a private token is required for publishing.
+
+```
+$ twine upload --repository-url https://test.pypi.org/legacy/ dist/*
+```
+
+
+## Usage
+
+You can install the package as follows:
+
+```
+$ pip install -i https://test.pypi.org/simple/ nnfwapi
+```
+
+By specifying the version, you can use a specific version of the package. (recommended)
+
+```
+$ pip install -i https://test.pypi.org/simple/ nnfwapi==0.1.1
+```
+
+This definition has to be set at the top of the script using nnfw python API.
+
+```
+from nnfwapi.libnnfw_api_pybind import *
+```
diff --git a/infra/nnfw/python/pack.sh b/infra/nnfw/python/pack.sh
new file mode 100644 (file)
index 0000000..01f1119
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# package
+python3 setup.py sdist bdist_wheel
+
+# deploy for TestPyPI
+twine upload --repository-url https://test.pypi.org/legacy/ dist/*
+
+# deploy for PyPI instead of TestPyPI
+#twine upload dist/*
diff --git a/infra/nnfw/python/setup.py b/infra/nnfw/python/setup.py
new file mode 100644 (file)
index 0000000..f4c68ce
--- /dev/null
@@ -0,0 +1,124 @@
+from setuptools import setup, find_packages
+import os
+import shutil
+import sys
+
+architecture_directory = ['x86_64', 'armv7l', 'aarch64']
+package_directory = 'nnfwapi'
+packaging_directory = ['build', package_directory + '.egg-info']
+THIS_FILE_DIR = os.path.dirname(os.path.abspath(__file__))
+so_list = []
+so_files = []
+target_arch = 'none'
+
+try:
+    # check argument "--plat-name" includes one of architecture_directory to find target architecture
+    for arg in sys.argv:
+        if arg.startswith('--plat-name'):
+            arg_split = arg.split('=')
+            arg_arch = ''
+            if len(arg_split) == 2:
+                arg_arch = arg_split[1]
+            else:
+                arch_idx = sys.argv.index('--plat-name')
+                arg_arch = sys.argv[arch_idx + 1]
+
+            for arch in architecture_directory:
+                if arch in arg_arch:
+                    target_arch = arch
+                    print(f"Target architecture: {target_arch}")
+            if target_arch == 'none':
+                print(f"Unsupported target platform: {target_arch}")
+                sys.exit(1)
+
+    if target_arch == 'none':
+        print(f"Need to set target platform by '--plat-name'")
+        sys.exit(1)
+
+    # remove packaging directory
+    for packaging_dir in packaging_directory:
+        if os.path.exists(packaging_dir):
+            print(f"Deleting existing directory '{packaging_dir}'...")
+            shutil.rmtree(packaging_dir)
+
+    # initialize package_directory
+    if os.path.exists(package_directory):
+        print(f"Deleting existing directory '{package_directory}'...")
+        shutil.rmtree(package_directory)
+    os.makedirs(package_directory)
+    print(f"Created directory '{package_directory}'...")
+
+    # copy *py files to package_directory
+    PY_DIR = os.path.join(THIS_FILE_DIR, '../../../runtime/onert/api/python/package')
+    for py_file in os.listdir(PY_DIR):
+        if py_file.endswith(".py"):
+            src_path = os.path.join(PY_DIR, py_file)
+            dest_path = os.path.join(THIS_FILE_DIR, package_directory)
+            shutil.copy(src_path, dest_path)
+            print(f"Copied '{src_path}' to '{dest_path}'")
+
+    # remove architecture directory
+    if os.path.exists(package_directory):
+        arch_path = os.path.join(package_directory, target_arch)
+        if os.path.exists(arch_path):
+            print(f"Deleting existing directory '{arch_path}'...")
+            shutil.rmtree(arch_path)
+
+        # make architecture_directory and copy .so files to the directories
+        arch_path = os.path.join(package_directory, 'onert')
+        os.makedirs(arch_path)
+        print(f"Created directory '{arch_path}'")
+
+        product_dir = os.path.join(THIS_FILE_DIR, '../../../Product')
+
+        # onert core library
+        so_core_dir = os.path.join(product_dir, target_arch + '-linux.release/out/lib')
+        for so in os.listdir(so_core_dir):
+            if so.endswith(".so"):
+                so_list.append('onert/' + so)
+                src_path = os.path.join(so_core_dir, so)
+                tgt_path = os.path.join(arch_path, so)
+                shutil.copy(src_path, tgt_path)
+                print(f"Copied {src_path} to {tgt_path}")
+
+        # onert backend library
+        so_backend_dir = os.path.join(so_core_dir, 'nnfw/backend')
+        if os.path.exists(so_backend_dir):
+            so_backend_tgt_dir = os.path.join(arch_path, 'nnfw/backend')
+            os.makedirs(so_backend_tgt_dir)
+            for so in os.listdir(so_backend_dir):
+                if so.endswith(".so"):
+                    so_list.append('onert/nnfw/backend/' + so)
+                    src_path = os.path.join(so_backend_dir, so)
+                    tgt_path = os.path.join(so_backend_tgt_dir, so)
+                    shutil.copy(src_path, tgt_path)
+                    print(f"Copied {src_path} to {tgt_path}")
+
+        # onert odc library
+        so_odc_dir = os.path.join(so_core_dir, 'nnfw/odc')
+        if os.path.exists(so_odc_dir):
+            so_odc_tgt_dir = os.path.join(arch_path, 'nnfw/odc')
+            os.makedirs(so_odc_tgt_dir)
+            for so in os.listdir(so_odc_dir):
+                if so.endswith(".so"):
+                    so_list.append('onert/nnfw/odc/' + so)
+                    src_path = os.path.join(so_odc_dir, so)
+                    tgt_path = os.path.join(so_odc_tgt_dir, so)
+                    shutil.copy(src_path, tgt_path)
+                    print(f"Copied {src_path} to {tgt_path}")
+
+    print("Operation completed successfully.")
+
+except Exception as e:
+    print(f"An error occurred: {str(e)}")
+
+# copy .so files to architecture directories
+
+setup(
+    name=package_directory,
+    version='0.1.0',
+    description='nnfw_api binding',
+    long_description='It provides nnfw Python api',
+    packages=[package_directory],
+    package_data={package_directory: so_list},
+)
index 16bce7e..e095f9d 100644 (file)
@@ -8,7 +8,7 @@ if [[ -z "${NNAS_PROJECT_PATH}" ]]; then
 fi
 
 # The default preset
-PRESET="20230413"
+PRESET="20230907"
 
 # Test is enabled by default
 DISABLE_TEST=false
index 44bc4e0..5834a59 100644 (file)
@@ -20,7 +20,7 @@ function preset_configure()
   # loco IR and related utilities
   REQUIRED_UNITS+=("loco" "locop" "locomotiv" "logo-core" "logo")
   # Flatbuffer I/O
-  REQUIRED_UNITS+=("mio-tflite2121" "mio-circle06")
+  REQUIRED_UNITS+=("mio-tflite2121" "mio-circle08")
   # Data I/O
   REQUIRED_UNITS+=("dio-hdf5")
   # Compute
index 5dcb36a..037e870 100644 (file)
@@ -17,7 +17,7 @@ function preset_configure()
   # loco IR and related utilities
   REQUIRED_UNITS+=("loco" "locop" "locomotiv" "logo-core" "logo")
   # Flatbuffer I/O
-  REQUIRED_UNITS+=("mio-tflite2121" "mio-circle06")
+  REQUIRED_UNITS+=("mio-tflite2121" "mio-circle08")
   # Data I/O
   REQUIRED_UNITS+=("dio-hdf5")
   # Compute
index 8b361a7..1f5310a 100644 (file)
@@ -1,7 +1,8 @@
 #!/bin/bash
 
 # NOTE this file is sourced from, for the purpose of
-# - configure_compiler_coverage.sh: to get test coverage for release criteria
+# - configure_compiler_coverage.sh (DEBUG_BUILD_ITEMS): to get test coverage for release criteria
+# - configure_collect_nnpkgs.sh (NNPKG_RES_ITEMS): to collect nnpkg resources for nnpackage test
 
 # Don't run this script
 [[ "${BASH_SOURCE[0]}" == "${0}" ]] && echo "Please don't execute ${BASH_SOURCE[0]}, source it" && return
@@ -11,12 +12,12 @@ 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-circle05;mio-tflite280;mio-circle06;mio-tflite2121;dio-hdf5"
+DEBUG_BUILD_ITEMS+=";safemain;mio-circle08;mio-tflite2121;dio-hdf5"
 DEBUG_BUILD_ITEMS+=";luci-compute"
 DEBUG_BUILD_ITEMS+=";tflite2circle"
 DEBUG_BUILD_ITEMS+=";luci"
 DEBUG_BUILD_ITEMS+=";luci-interpreter"
-DEBUG_BUILD_ITEMS+=";luci-eval-driver;luci-pass-value-test;luci-value-test"
+DEBUG_BUILD_ITEMS+=";luci-eval-driver;luci-pass-value-py-test;luci-value-py-test"
 DEBUG_BUILD_ITEMS+=";circle2circle;record-minmax;circle-quantizer"
 DEBUG_BUILD_ITEMS+=";circle-eval-diff"
 DEBUG_BUILD_ITEMS+=";circle-partitioner;circle-part-driver;circle-operator"
@@ -29,10 +30,29 @@ DEBUG_BUILD_ITEMS+=";record-minmax-conversion-test"
 DEBUG_BUILD_ITEMS+=";tf2tfliteV2;tf2tfliteV2-conversion-test"
 DEBUG_BUILD_ITEMS+=";tflite2circle-conversion-test"
 DEBUG_BUILD_ITEMS+=";pota-quantization-value-test;pics"
-DEBUG_BUILD_ITEMS+=";circle-part-value-test"
+DEBUG_BUILD_ITEMS+=";circle-part-value-py-test"
 DEBUG_BUILD_ITEMS+=";circle-quantizer-dredd-recipe-test"
 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"
+
+NNPKG_RES_ITEMS="angkor;cwrap;pepper-str;pepper-strcast;pp"
+NNPKG_RES_ITEMS+=";pepper-csv2vec"
+NNPKG_RES_ITEMS+=";oops;safemain;foder;crew;arser;vconone"
+# Hermes Logging Framework
+NNPKG_RES_ITEMS+=";hermes;hermes-std"
+# loco IR and related utilities
+NNPKG_RES_ITEMS+=";loco;locop;locomotiv;logo-core;logo"
+# Compute
+NNPKG_RES_ITEMS+=";luci-compute"
+# Circle compiler library (.circle -> .circle)
+NNPKG_RES_ITEMS+=";luci"
+# Flatbuffer I/O
+NNPKG_RES_ITEMS+=";mio-tflite2121;mio-circle08"
+# Tools
+NNPKG_RES_ITEMS+=";tflite2circle;circle2circle;luci-interpreter"
+NNPKG_RES_ITEMS+=";souschef;tflchef;circlechef;circle-verify"
+# common-artifacts
+NNPKG_RES_ITEMS+=";common-artifacts"
diff --git a/infra/scripts/configure_collect_nnpkgs.sh b/infra/scripts/configure_collect_nnpkgs.sh
new file mode 100755 (executable)
index 0000000..9040112
--- /dev/null
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+[[ "${BASH_SOURCE[0]}" != "${0}" ]] && echo "Please don't source ${BASH_SOURCE[0]}, execute it" && return
+
+set -eo pipefail
+
+CURRENT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_PATH="$CURRENT_PATH/../../"
+
+source ${CURRENT_PATH}/compiler_modules.sh
+
+NNCC_CFG_OPTION=" -DCMAKE_BUILD_TYPE=Release"
+NNCC_CFG_STRICT=" -DENABLE_STRICT_BUILD=ON"
+NNCC_COV_DEBUG=" -DBUILD_WHITELIST=$NNPKG_RES_ITEMS"
+
+if [ $# -ne 0 ]; then
+       echo "Additional cmake configuration: $@"
+fi
+
+# Reset whitelist to build all
+./nncc configure \
+       $NNCC_CFG_OPTION $NNCC_COV_DEBUG $NNCC_CFG_STRICT \
+       "$@"
diff --git a/infra/scripts/docker_build_nncc.sh b/infra/scripts/docker_build_nncc.sh
deleted file mode 100755 (executable)
index dd9d0bd..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/bash
-
-[[ "${BASH_SOURCE[0]}" != "${0}" ]] && echo "Please don't source ${BASH_SOURCE[0]}, execute it" && return
-
-unset RELEASE_VERSION
-# TODO need more better argument parsing
-RELEASE_VERSION="$1"
-
-CURRENT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-ROOT_PATH="$CURRENT_PATH/../../"
-
-CONFIG_OPTIONS=""
-# mount volume (or directory) for externals
-if [ -n "$EXTERNAL_VOLUME" ]; then
-  DOCKER_OPTS+=" -v $EXTERNAL_VOLUME:/externals"
-  CONFIG_OPTIONS+=" -DNNAS_EXTERNALS_DIR=/externals"
-else
-  echo "It will use default external path"
-fi
-
-# mount volume (or directory) for overlay
-if [ -n "$OVERLAY_VOLUME" ]; then
-  DOCKER_OPTS+=" -v $OVERLAY_VOLUME:/overlay"
-  CONFIG_OPTIONS+=" -DNNCC_OVERLAY_DIR=/overlay"
-else
-  echo "It will use default overlay path"
-fi
-
-# prepare tensorflow
-if [ -n "$TENSORFLOW_PREFIX" ]; then
-  DOCKER_OPTS+=" -v $TENSORFLOW_PREFIX:/opt/tensorflow"
-  CONFIG_OPTIONS+=" -DTENSORFLOW_PREFIX=/opt/tensorflow"
-fi
-
-# prepare onnx
-if [ -n "$ONNXRUNTIME_PREFIX" ]; then
-  DOCKER_OPTS+=" -v $ONNXRUNTIME_PREFIX:/opt/onnxruntime"
-  CONFIG_OPTIONS+=" -DONNXRUNTIME_PREFIX=/opt/onnxruntime"
-fi
-
-# docker image name
-# - for bionic, use DOCKER_IMAGE_NAME="nnfw/one-devtools:bionic"
-# - for focal, use DOCKER_IMAGE_NAME="nnfw/one-devtools:focal"
-if [[ -z $DOCKER_IMAGE_NAME ]]; then
-  echo "It will use default docker image name"
-fi
-
-NNAS_WORKSPACE=${NNAS_WORKSPACE:-build}
-NNCC_INSTALL_PREFIX=${NNAS_WORKSPACE}/out
-DOCKER_OPTS+=" -e NNAS_BUILD_PREFIX=${NNAS_WORKSPACE}"
-export DOCKER_OPTS
-if [[ -z "${ARCHIVE_PATH}" ]]; then
-  ARCHIVE_PATH=${NNAS_WORKSPACE}/archive
-fi
-
-set -e
-
-pushd $ROOT_PATH > /dev/null
-
-mkdir -p ${NNCC_INSTALL_PREFIX}
-./nncc docker-run ./nnas create-package --prefix "${PWD}/${NNCC_INSTALL_PREFIX}" -- "${CONFIG_OPTIONS}"
-
-mkdir -p ${ARCHIVE_PATH}
-tar -zcf ${ARCHIVE_PATH}/nncc-package.tar.gz -C ${NNCC_INSTALL_PREFIX} \
-    --exclude test --exclude tflchef* --exclude circle-tensordump --exclude circledump ./
-tar -zcf ${ARCHIVE_PATH}/nncc-test-package.tar.gz -C ${NNCC_INSTALL_PREFIX} ./test
-
-if [ -z ${RELEASE_VERSION} ] || [ ${RELEASE_VERSION} == "nightly" ]; then
-  ./nncc docker-run /bin/bash -c \
-         '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
-
-./nncc docker-run debuild --preserve-env --no-lintian -us -uc \
-        -b --buildinfo-option=-ubuild --changes-option=-ubuild
-
-popd > /dev/null
diff --git a/infra/scripts/docker_collect_nnpkg_resources.sh b/infra/scripts/docker_collect_nnpkg_resources.sh
deleted file mode 100755 (executable)
index 8a73dd3..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/bin/bash
-
-function join_by
-{
-  local IFS="$1"; shift; echo "$*"
-}
-
-[[ "${BASH_SOURCE[0]}" != "${0}" ]] && echo "Please don't source ${BASH_SOURCE[0]}, execute it" && return
-
-CURRENT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-ROOT_PATH="$CURRENT_PATH/../../"
-
-CONFIG_OPTIONS=""
-# mount volume (or directory) for externals
-if [ -n "$EXTERNAL_VOLUME" ]; then
-  DOCKER_OPTS+=" -v $EXTERNAL_VOLUME:/externals"
-  CONFIG_OPTIONS+=" -DNNAS_EXTERNALS_DIR=/externals"
-else
-  echo "It will use default external path"
-fi
-
-# mount volume (or directory) for overlay
-if [ -n "$OVERLAY_VOLUME" ]; then
-  DOCKER_OPTS+=" -v $OVERLAY_VOLUME:/overlay"
-  CONFIG_OPTIONS+=" -DNNCC_OVERLAY_DIR=/overlay"
-else
-  echo "It will use default overlay path"
-fi
-
-# prepare tensorflow
-if [ -n "$TENSORFLOW_PREFIX" ]; then
-  DOCKER_OPTS+=" -v $TENSORFLOW_PREFIX:/opt/tensorflow"
-  CONFIG_OPTIONS+=" -DTENSORFLOW_PREFIX=/opt/tensorflow"
-fi
-
-# prepare onnx
-if [ -n "$ONNXRUNTIME_PREFIX" ]; then
-  DOCKER_OPTS+=" -v $ONNXRUNTIME_PREFIX:/opt/onnxruntime"
-  CONFIG_OPTIONS+=" -DONNXRUNTIME_PREFIX=/opt/onnxruntime"
-fi
-
-# docker image name
-# - for bionic, use DOCKER_IMAGE_NAME="nnfw/one-devtools:bionic"
-# - for focal, use DOCKER_IMAGE_NAME="nnfw/one-devtools:focal"
-if [[ -z $DOCKER_IMAGE_NAME ]]; then
-  echo "It will use default docker image name"
-fi
-
-# Assume that build is already finished, and ready to test
-NNAS_WORKSPACE=${NNAS_WORKSPACE:-build}
-export NNCC_WORKSPACE=${NNAS_WORKSPACE}/nncc
-export DOCKER_OPTS
-
-if [[ -z "${ARCHIVE_PATH}" ]]; then
-  ARCHIVE_PATH=${NNAS_WORKSPACE}/archive
-fi
-
-set -e
-
-pushd $ROOT_PATH > /dev/null
-
-REQUIRED_UNITS=()
-# Common Libraries
-REQUIRED_UNITS+=("angkor" "cwrap" "pepper-str" "pepper-strcast" "pp")
-REQUIRED_UNITS+=("pepper-csv2vec")
-REQUIRED_UNITS+=("oops" "safemain" "foder" "crew" "arser" "vconone")
-# Hermes Logging Framework
-REQUIRED_UNITS+=("hermes" "hermes-std")
-# loco IR and related utilities
-REQUIRED_UNITS+=("loco" "locop" "locomotiv" "logo-core" "logo")
-# Compute
-REQUIRED_UNITS+=("luci-compute")
-# Circle compiler library (.circle -> .circle)
-REQUIRED_UNITS+=("luci")
-# Flatbuffer I/O
-REQUIRED_UNITS+=("mio-tflite280" "mio-circle05" "mio-tflite2121" "mio-circle06")
-# Tools
-REQUIRED_UNITS+=("tflite2circle" "circle2circle" "luci-interpreter")
-REQUIRED_UNITS+=("souschef" "tflchef" "circlechef" "circle-verify")
-# common-artifacts
-REQUIRED_UNITS+=("common-artifacts")
-
-# Reset whitelist to build all
-./nncc docker-run ./nncc configure -DENABLE_STRICT_BUILD=ON -DCMAKE_BUILD_TYPE=release \
-  -DBUILD_WHITELIST=$(join_by ";" "${REQUIRED_UNITS[@]}") \
-  $CONFIG_OPTIONS
-./nncc docker-run ./nncc build -j4
-
-mkdir -p ${ARCHIVE_PATH}
-TEMP_DIR=$(mktemp -d -t resXXXX)
-rm -f ${TEMP_DIR}/*
-mkdir -p ${TEMP_DIR}/nnpkg-tcs
-
-# Copy nnpakcage only if it has its test data
-for nnpkg in $NNCC_WORKSPACE/compiler/common-artifacts/*; do
-  if [ -d $nnpkg/metadata/tc ]; then
-    cp -r $nnpkg ${TEMP_DIR}/nnpkg-tcs
-  fi
-done
-
-tar -zcf ${ARCHIVE_PATH}/nnpkg-test-suite.tar.gz -C ${TEMP_DIR} ./
-rm -rf ${TEMP_DIR}
-
-echo "resouce generation end"
-popd > /dev/null
index 97043ce..8e78404 100755 (executable)
@@ -31,9 +31,9 @@ TENSOR_LOGGING=trace_log.txt ./infra/scripts/test_ubuntu_runtime.sh --backend ac
 # Enable all logs (mixed backend)
 ONERT_LOG_ENABLE=1 GRAPH_DOT_DUMP=1 ./infra/scripts/test_ubuntu_runtime_mixed.sh
 # Enable trace event (acl_cl default backend)
-export TRACE_FILEPATH=trace.json
+export TRACING_MODE=1
 TFLiteModelVerification "acl_cl" "Product/out/test/list/tflite_comparator.armv7l.acl_cl.list" "report/acl_cl/trace"
-unset TRACE_FILEPATH
+unset TRACING_MODE
 
 # nnpackage test suite
 if [[ -e ${ARCHIVE_PATH}/nnpkg-test-suite.tar.gz ]]; then
index cdc1036..460fa43 100644 (file)
@@ -31,6 +31,8 @@
 // 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.
+// Version 0.7: Base up to TensorFlow Lite v2.15.0 schema, deprecate data_format in Subgraph table
+// Version 0.8: GRU op is added. UINT4 is added.
 
 namespace circle;
 
@@ -44,6 +46,7 @@ file_extension "circle";
 
 // The type of data stored in a tensor.
 enum TensorType : byte {
+  UINT4 = -1,
   FLOAT32 = 0,
   FLOAT16 = 1,
   INT32 = 2,
@@ -84,8 +87,12 @@ table QuantizationParameters {
   // 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.
+  // NOTE min/max values are valid if
+  // 1. length of min/max == 0 or
+  // 2. length of min/max == length of scale/zero_point
+  // Otherwise, min/max are not valid (undefined behavior).
+  min:[float];
+  max:[float];
   scale:[float];  // For dequantizing the tensor's values.
   zero_point:[long];
 
@@ -242,8 +249,12 @@ table Tensor {
   // represented with -1.
   shape_signature:[int]; // Optional.
 
-  // If false, the rank or the number of tensor dimensions is unknown.
-  // If false, "shape" must be [].
+  // This field is added to distinguish between scalars and tensors of unknown
+  // ranks (both of which shape is []).
+  // For scalars (rank = 0), shape = [] and has_rank = true.
+  // For tensors with known rank (rank > 0) and shape, shape = [...] and
+  // has_rank = true.
+  // For tensors with unknown rank and shape, shape = [] and has_rank = false.
   has_rank: bool = false;
 
   // The nested Tensor types for VARIANT type. This is always empty for
@@ -259,6 +270,7 @@ table Tensor {
 // set of acceptable options.
 // LINT.IfChange
 enum BuiltinOperator : int32 {
+  GRU = -5,
   BCQ_GATHER = -4,
   BCQ_FULLY_CONNECTED = -3,
   INSTANCE_NORM = -2,
@@ -430,6 +442,52 @@ enum BuiltinOperator : int32 {
   BITCAST = 159,
   BITWISE_XOR = 160,
   RIGHT_SHIFT = 161,
+  // All Operators start with STABLEHLO_ prefixes are subject to change
+  // Many of the ops below can not be executed by runtime
+  STABLEHLO_LOGISTIC = 162, // WARNING: Do not have runtime support
+  STABLEHLO_ADD = 163, // WARNING: No runtime support yet
+  STABLEHLO_DIVIDE = 164, // WARNING: No runtime support yet
+  STABLEHLO_MULTIPLY = 165, // WARNING: No runtime support yet
+  STABLEHLO_MAXIMUM = 166, // WARNING: No runtime support yet
+  STABLEHLO_RESHAPE = 167, // WARNING: No runtime support yet
+  STABLEHLO_CLAMP = 168, // WARNING: No runtime support
+  STABLEHLO_CONCATENATE = 169, // WARNING: No runtime support
+  STABLEHLO_BROADCAST_IN_DIM = 170, // WARNING: No runtime support
+  STABLEHLO_CONVOLUTION = 171, // WARNING: No runtime support
+  STABLEHLO_SLICE = 172, // WARNING: No runtime support
+  STABLEHLO_CUSTOM_CALL = 173, // WARNING: No runtime support
+  STABLEHLO_REDUCE = 174, // WARNING: No runtime support
+  STABLEHLO_ABS = 175, // WARNING: No runtime support
+  STABLEHLO_AND = 176, // WARNING: No runtime support
+  STABLEHLO_COSINE = 177, // WARNING: No runtime support
+  STABLEHLO_EXPONENTIAL = 178, // WARNING: No runtime support
+  STABLEHLO_FLOOR = 179, // WARNING: No runtime support
+  STABLEHLO_LOG = 180, // WARNING: No runtime support
+  STABLEHLO_MINIMUM = 181, // WARNING: No runtime support
+  STABLEHLO_NEGATE = 182, // WARNING: No runtime support
+  STABLEHLO_OR = 183, // WARNING: No runtime support
+  STABLEHLO_POWER = 184, // WARNING: No runtime support
+  STABLEHLO_REMAINDER = 185, // WARNING: No runtime support
+  STABLEHLO_RSQRT = 186, // WARNING: No runtime support
+  STABLEHLO_SELECT = 187, // WARNING: No runtime support
+  STABLEHLO_SUBTRACT = 188, // WARNING: No runtime support
+  STABLEHLO_TANH = 189, // WARNING: No runtime support
+  STABLEHLO_SCATTER = 190,
+  STABLEHLO_COMPARE = 191, // WARNING: No runtime support
+  STABLEHLO_CONVERT = 192, // WARNING: No runtime support
+  STABLEHLO_DYNAMIC_SLICE = 193, // WARNING: No runtime support
+  STABLEHLO_DYNAMIC_UPDATE_SLICE = 194, // WARNING: No runtime support
+  STABLEHLO_PAD = 195, // WARNING: No runtime support
+  STABLEHLO_IOTA = 196, // WARNING: No runtime support
+  STABLEHLO_DOT_GENERAL = 197, // WARNING: No runtime support
+  STABLEHLO_REDUCE_WINDOW = 198, // WARNING: No runtime support
+  STABLEHLO_SORT = 199, // WARNING: No runtime support
+  STABLEHLO_WHILE = 200, // WARNING: No runtime support
+  STABLEHLO_GATHER = 201, // WARNING: No runtime support
+  STABLEHLO_TRANSPOSE = 202, // WARNING: No runtime support
+  DILATE = 203,
+  STABLEHLO_RNG_BIT_GENERATOR = 204,
+  REDUCE_WINDOW = 205,
 }
 // LINT.ThenChange(nnapi_linter/linter.proto)
 
@@ -561,13 +619,199 @@ union BuiltinOptions {
   BitcastOptions,
   BitwiseXorOptions,
   RightShiftOptions,
+  GRUOptions = 251,
   BCQGatherOptions = 252,
   BCQFullyConnectedOptions = 253,
   InstanceNormOptions = 254,
 }
 
+union BuiltinOptions2{
+  StablehloConcatenateOptions,
+  StablehloBroadcastInDimOptions,
+  StablehloSliceOptions,
+  StablehloConvolutionOptions,
+  StablehloCustomCallOptions,
+  StablehloReduceOptions,
+  StablehloScatterOptions,
+  StablehloCompareOptions,
+  StablehloDynamicSliceOptions,
+  StablehloPadOptions,
+  StablehloIotaOptions,
+  StablehloDotGeneralOptions,
+  StablehloReduceWindowOptions,
+  StablehloSortOptions,
+  StablehloWhileOptions,
+  StablehloGatherOptions,
+  StablehloTransposeOptions,
+  DilateOptions,
+  StablehloRngBitGeneratorOptions,
+  ReduceWindowOptions,
+}
+
+table StablehloGatherOptions{
+  offset_dims : [long];
+  collapsed_slice_dims : [long];
+  start_index_map : [long];
+  index_vector_dim : long;
+  slice_sizes : [long];
+  indices_are_sorted : bool;
+}
+
+table StablehloTransposeOptions{
+  permutation : [long];
+}
+
+enum StablehloPrecisionConfig : uint {
+  DEFAULT,
+  HIGH,
+  HIGHEST,
+}
+
+table StablehloDotGeneralOptions{
+  lhs_batching_dimensions : [long];
+  rhs_batching_dimensions : [long];
+  lhs_contracting_dimensions : [long];
+  rhs_contracting_dimensions : [long];
+  precision_config : [StablehloPrecisionConfig];
+}
+
+table StablehloReduceWindowOptions{
+  window_dimensions : [long];
+  window_strides : [long];
+  base_dilations : [long];
+  window_dilations : [long];
+  padding : [long];
+  body_subgraph_index : int;
+}
+
+table StablehloWhileOptions{
+  cond_subgraph_index : int;
+  body_subgraph_index : int;
+}
+
+table StablehloSortOptions{
+  dimension : long;
+  is_stable : bool;
+  comparator_subgraph_index : int;
+}
+
+table StablehloConcatenateOptions {
+  dimension : long;
+}
+
+table StablehloBroadcastInDimOptions{
+  broadcast_dimensions : [long];
+}
+
+enum StablehloComparisonDirection : uint {
+  STABLEHLO_COMPARISON_DIRECTION_EQ,
+  STABLEHLO_COMPARISON_DIRECTION_NE,
+  STABLEHLO_COMPARISON_DIRECTION_GE,
+  STABLEHLO_COMPARISON_DIRECTION_GT,
+  STABLEHLO_COMPARISON_DIRECTION_LE,
+  STABLEHLO_COMPARISON_DIRECTION_LT,
+
+}
+
+enum StablehloComparisonType : uint {
+  STABLEHLO_COMPARISON_TYPE_NOTYPE,
+  STABLEHLO_COMPARISON_TYPE_FLOAT,
+  STABLEHLO_COMPARISON_TYPE_FLOAT_TOTAL_ORDER,
+  STABLEHLO_COMPARISON_TYPE_SIGNED,
+  STABLEHLO_COMPARISON_TYPE_UNSIGNED,
+}
+
+table StablehloCompareOptions{
+  comparison_direction : StablehloComparisonDirection;
+  compare_type : StablehloComparisonType;
+}
+
+table StablehloDynamicSliceOptions{
+  slice_sizes : [long];
+}
+
+table StablehloPadOptions{
+  edge_padding_low : [long];
+  edge_padding_high : [long];
+  interior_padding : [long];
+}
+
+table StablehloIotaOptions{
+  iota_dimension : long;
+}
+
+table StablehloCustomCallOptions {
+  call_target_name : string;
+  has_side_effect : bool;
+  backend_config: string;
+  api_version : int; // will be decprecated
+  called_computations: [int]; // should point to subgraphs of the computations
+  custom_attributes : [ubyte];
+}
+
+table StablehloReduceOptions {
+  dimensions : [long];
+  body_subgraph_index : int;
+}
+
+table StablehloSliceOptions{
+  start_indices : [long];
+  limit_indices : [long];
+  strides : [long];
+}
+
+table StablehloConvolutionOptions{
+  window_strides : [long];
+  padding : [long];
+  lhs_dilation : [long];
+  rhs_dilation : [long];
+  window_reversal : [bool];
+  input_batch_dimension : long;
+  input_feature_dimension : long;
+  input_spatial_dimensions : [long];
+  kernel_input_feature_dimension : long;
+  kernel_output_feature_dimension : long;
+  kernel_spatial_dimensions : [long];
+  output_batch_dimension : long;
+  output_feature_dimension : long;
+  output_spatial_dimensions    : [long];
+  feature_group_count : long;
+  batch_group_count : long;
+  precision_config : [StablehloPrecisionConfig];
+}
+
+table StablehloScatterOptions {
+  indices_are_sorted: bool;
+  update_window_dims: [long];
+  inserted_window_dims: [long];
+  scatter_dims_to_operand_dims: [long];
+  index_vector_dim: long;
+  unique_indices: bool;
+  update_computation_subgraph_index: int;
+}
+
+enum RngAlgorithm : byte {
+  // An algorithm auto-selected by the system according to device type.
+  DEFAULT = 0,
+  // The Philox algorithm, as described in paper
+  // ['Parallel Random Numbers: As Easy as 1, 2, 3']
+  // (https://www.thesalmons.org/john/random123/papers/random123sc11.pdf)
+  PHILOX = 1,
+  // The ThreeFry algorithm, as described in paper
+  // ['Parallel Random Numbers: As Easy as 1, 2, 3']
+  // (https://www.thesalmons.org/john/random123/papers/random123sc11.pdf)
+  THREEFRY = 2,
+}
+
+table StablehloRngBitGeneratorOptions {
+  algorithm:RngAlgorithm;
+}
+
+// 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,
@@ -576,6 +820,7 @@ enum ActivationFunctionType : byte {
   TANH = 4,
   SIGN_BIT = 5,
 }
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
 
 table Conv2DOptions {
   padding:Padding;
@@ -584,6 +829,9 @@ table Conv2DOptions {
   fused_activation_function:ActivationFunctionType;
   dilation_w_factor:int = 1;
   dilation_h_factor:int = 1;
+  // Parameters for Conv2D version 8 or above.
+  // When set, quantized_bias_type defines the dtype for both bias and accumulator.
+  quantized_bias_type: TensorType;
 }
 
 // Options for both Conv3D and Conv3DTranspose.
@@ -667,11 +915,13 @@ table BidirectionalSequenceRNNOptions {
   asymmetric_quantize_inputs:bool;
 }
 
+// LINT.IfChange
 enum FullyConnectedOptionsWeightsFormat: byte {
   DEFAULT = 0,
   SHUFFLED4x16INT8 = 1,
   SHUFFLED16x1FLOAT32 = 127
 }
+// LINT.ThenChange(//tensorflow/compiler/mlir/lite/ir/tfl_op_enums.td)
 
 // An implementation of TensorFlow fully_connected (a.k.a Dense) layer.
 table FullyConnectedOptions {
@@ -690,6 +940,10 @@ table FullyConnectedOptions {
   // If set to true, then weights-only op will use asymmetric quantization for
   // inputs.
   asymmetric_quantize_inputs: bool;
+
+  // Parameters for FullyConnected version 11 or above.
+  // When set, quantized_bias_type defines the dtype for both bias and accumulator.
+  quantized_bias_type: TensorType;
 }
 
 table SoftmaxOptions {
@@ -724,12 +978,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 {
@@ -889,6 +1145,8 @@ table StridedSliceOptions {
   ellipsis_mask: int;
   new_axis_mask: int;
   shrink_axis_mask: int;
+  // If true, then the end tensor is an offset of the begin tensor.
+  offset: bool;
 }
 
 table LogSoftmaxOptions {
@@ -945,6 +1203,11 @@ table TransposeConvOptions {
 
   // Parameters supported by version 4:
   fused_activation_function:ActivationFunctionType = NONE;
+
+  // Parameters for TransposeConv version 5 or above.
+  // If set, use this for bias and accumulator.
+  // When set, quantized_bias_type defines the dtype for both bias and accumulator.
+  quantized_bias_type: TensorType;
 }
 
 table ExpandDimsOptions {
@@ -1036,12 +1299,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;
@@ -1200,6 +1465,29 @@ table BitwiseXorOptions {
 table RightShiftOptions {
 }
 
+table DilateOptions {
+}
+
+enum ReduceWindowFunction : int {
+  UNSUPPORTED,
+  ADD,
+  MUL,
+  MINIMUM,
+  MAXIMUM,
+  ALL,
+  ANY,
+}
+
+table ReduceWindowOptions{
+  reduce_function: ReduceWindowFunction;
+}
+
+table GRUOptions {
+  fused_activation_function:ActivationFunctionType;
+  return_sequences : bool;
+  time_major : bool;
+}
+
 table BCQGatherOptions {
   input_hidden_size: int;
   axis: int;
@@ -1283,6 +1571,18 @@ table Operator {
   // computation, which may require relevant metadata such as quantization
   // parameters.
   intermediates:[int];
+
+  // When an op is using custom_options in a model that is larger than 2GB, then
+  // we instead use the following attributes to find the buffer location which
+  // is stored outside of flatbuffers, the offset is calculated relative to the
+  // beginning of the file and is only valid if > 1
+  large_custom_options_offset: ulong;
+  large_custom_options_size: ulong;
+
+  // Flatbuffers union struct has a 128 elements limit in JAVA, so a second
+  // union is added, in the case of where BuitlinOptions2 runs out, a third
+  // one can be added
+  builtin_options_2 : BuiltinOptions2;
 }
 
 // The root type, defining a subgraph, which typically represents an entire
@@ -1306,14 +1606,21 @@ table SubGraph {
   // Name of this subgraph (used for debugging).
   name:string;
 
-  // Data format for input/output of SubGraph
-  data_format: DataFormat;
+  // Data format for input/output of SubGraph, deprecated
+  deprecated_data_format: DataFormat (deprecated);
 }
 
 // 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);
+
+  // In a model that is larger than 2GB, then buffers instead uses the following
+  // attributes to find stored data, which is outside of flatbuffers
+  // the offset is calculated relative to the beginning of the file and is only
+  // valid if > 1.
+  offset: ulong;
+  size: ulong;
 }
 
 table Metadata {
index 416281d..4aafa9e 100644 (file)
@@ -6,9 +6,13 @@ set(ARM_OBJCOPY "arm-none-eabi-objcopy")
 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)")
+    message(STATUS "Build onert-micro failed: ARM compiler is NOT FOUND")
+    return()
 endif ()
 
+set(OM_CIRCLE_SCHEMA onert_micro_circle_schema)
+set(OM_TRAININFO_SCHEMA onert_micro_traininfo_schema)
+
 if (NOT_BUILD_EXTERNALS)
     message(STATUS "USE LOCAL EXTERNAL")
 
@@ -25,13 +29,13 @@ else()
     nnas_find_package(FlatBuffers EXACT 2.0 QUIET)
 
     if (NOT FlatBuffers_FOUND)
-        message(STATUS "Build luci-micro: FALSE(FlatBuffers 2.0 NOT FOUND)")
+        message(STATUS "Build onert-micro failed: FlatBuffers 2.0 NOT FOUND")
         return()
     endif (NOT FlatBuffers_FOUND)
 
-    message(STATUS "Build luci-micro: TRUE")
+    message(STATUS "FOUND FlatBuffers")
 
-    set(SCHEMA_FILE "${NNAS_PROJECT_SOURCE_DIR}/res/CircleSchema/0.4/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"
@@ -40,57 +44,56 @@ else()
             DEPENDS "${SCHEMA_FILE}"
             )
 
-    FlatBuffers_Target(luci_micro_circle_schema
+    FlatBuffers_Target(${OM_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(SCHEMA_FILE "${NNAS_PROJECT_SOURCE_DIR}/runtime/libs/circle-schema/include/circle_traininfo.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}/traininfo.fbs"
+            COMMAND ${CMAKE_COMMAND} -E copy "${SCHEMA_FILE}" traininfo.fbs
+            WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+            DEPENDS "${SCHEMA_FILE}"
+            )
+
+    FlatBuffers_Target(${OM_TRAININFO_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 "traininfo.fbs"
+            )
+
     set(Flatbuffers_DIR "${CMAKE_CURRENT_BINARY_DIR}/../../overlay/lib/cmake/flatbuffers")
-    set (EXT_OVERLAY_DIR "${CMAKE_CURRENT_BINARY_DIR}/../../overlay")
+    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)
-
-# Choosing Kernel: reference mcu, optimized cmsisnn, optimized linux
+# Choosing Kernel: reference mcu, optimized cmsisnn
 if (NOT KERNELS)
     message(STATUS "KERNEL variable is not defined, default reference mcu kernels will be used")
-    set(LUCI_INTERPRETER_PAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/luci-interpreter/pal/mcu")
+    set(OM_PAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/onert-micro/include/pal/mcu")
 elseif("${KERNELS}" STREQUAL "mcu")
     message(STATUS "ONERT_MICRO will use reference mcu kernels")
-    set(LUCI_INTERPRETER_PAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/luci-interpreter/pal/mcu")
+    set(OM_PAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/onert-micro/include/pal/mcu")
 elseif("${KERNELS}" STREQUAL "cmsisnn")
     message(STATUS "ONERT_MICRO will use optimized cmsisnn kernels")
-    set(LUCI_INTERPRETER_PAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/luci-interpreter/pal/cmsisnn")
-elseif("${KERNELS}" STREQUAL "linux")
-    message(STATUS "ONERT_MICRO will use optimized linux kernels")
-    set(LUCI_INTERPRETER_PAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/luci-interpreter/pal/linux")
+    set(OM_PAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/onert-micro/include/pal/cmsisnn")
 else()
-    message(STATUS "Build onert-micro: FAILED (Non-existent kernel variable. Choose one of the following options: mcu, cmsisnn, linux)")
+    message(STATUS "Build onert-micro: FAILED (Non-existent kernel variable. Choose one of the following options: mcu, cmsisnn)")
     return()
 endif()
 
-if (USE_STATIC_ALLOC)
-    # TODO: enable it
-    message(STATUS "FAILED ONERT-MICRO is not support Static Memory Manager now")
-    return()
-else()
-    message(STATUS "USE_STATIC_ALLOC variable is not defined, default dynamic memory manager will be used")
-endif()
-
 set(CMAKE_ARM_OPTIONS
-        -DLUCI_INTERPRETER_STATIC=ON
-        -DLUCI_STATIC=ON
-        -DBUILD_CMSIS_NN_FUNCTIONS=ON
         -DTARGET_CPU=${TARGET_CPU}
         -DTARGET_ARCH=${TARGET_ARCH}
         "-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}"
+        "-DOM_PAL_DIR=${OM_PAL_DIR}"
         "-DNNAS_PROJECT_SOURCE_DIR=${NNAS_PROJECT_SOURCE_DIR}"
         "-DNNAS_EXTERNALS_DIR=${NNAS_EXTERNALS_DIR}"
         -DC_COMPILER=${ARM_C_COMPILER}
@@ -101,15 +104,9 @@ set(CMAKE_ARM_OPTIONS
         -DENABLE_TEST=OFF
         -DBUILD_GTEST=OFF
         "-DNNAS_ROOT=${NNAS_PROJECT_SOURCE_DIR}"
-        -DENABLE_STRICT_BUILD=OFF
         "-DGENERATED_INCLUDE_DIR=${GENERATED_INCLUDE_DIR}"
         )
 
-if (GENERATE_KERNELS_LIST_FROM)
-    set(GENERATED_KERNELS_LIST_PATH "${LUCI_INTERPRETER_PAL_DIR}/GeneratedKernelsToBuild.lst")
-    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()
@@ -121,6 +118,12 @@ if (ENABLE_ONERT_MICRO_TEST)
     list(APPEND CMAKE_ARM_OPTIONS "-DENABLE_TEST=ON")
 endif ()
 
+if (ENABLE_ONERT_MICRO_TRAINING)
+    message(STATUS "ENABLE TRAINING PART")
+    add_definitions(-DENABLE_TRAINING)
+    list(APPEND CMAKE_ARM_OPTIONS "-DENABLE_TRAINING=ON")
+endif ()
+
 if (DIS_QUANT)
     message(STATUS "ONERT-MICRO will not use part for QUANTIZED models")
     add_definitions(-DDIS_QUANT)
@@ -151,26 +154,7 @@ add_custom_command(
         VERBATIM
 )
 
-add_custom_target(luci_interpreter_micro_arm_cmake DEPENDS "${MICRO_ARM_BUILD_DEPENDENCY}")
-
-# Generate KernelsToBuild list from circle model
-if (GENERATE_KERNELS_LIST_FROM)
-    add_executable(generator_kernels_list_exec helpers/GenerateKernelsListHelper.cpp)
-
-    target_link_libraries(generator_kernels_list_exec luci_micro_circle_reader)
-    target_link_libraries(generator_kernels_list_exec luci_micro_circle_schema)
-
-    target_include_directories(generator_kernels_list_exec PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/luci-interpreter/include")
-
-    add_custom_target(
-            generate_kernels_list ALL
-            COMMAND generator_kernels_list_exec ${GENERATE_KERNELS_LIST_FROM} ${GENERATED_KERNELS_LIST_PATH}
-            COMMENT "Generating KernelsToBuild list"
-    )
-    add_dependencies(generate_kernels_list luci_micro_circle_reader)
-    add_dependencies(luci_interpreter_micro_arm_cmake generate_kernels_list)
-
-endif ()
+add_custom_target(onert_micro_arm_cmake DEPENDS "${MICRO_ARM_BUILD_DEPENDENCY}")
 
 # To remove GENERATE_KERNELS_LIST_FROM and KERNELS variable from cmake cache
 unset(GENERATE_KERNELS_LIST_FROM CACHE)
@@ -181,21 +165,25 @@ 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")
+set(MICRO_ARM_BINARY "${MICRO_ARM_BUILD_DIR}/onert_micro/src/libonert_micro_dev.a")
 
 add_custom_command(
         OUTPUT "${MICRO_ARM_BINARY}"
-        COMMAND "${CMAKE_MAKE_PROGRAM}" luci_interpreter_micro -j ${CPU_COUNT}
+        COMMAND "${CMAKE_MAKE_PROGRAM}" onert_micro_dev -j ${CPU_COUNT}
         WORKING_DIRECTORY "${MICRO_ARM_BUILD_DIR}"
-        DEPENDS luci_interpreter_micro_arm_cmake luci_micro_circle_schema
+        DEPENDS onert_micro_arm_cmake ${OM_CIRCLE_SCHEMA}
         VERBATIM
 )
 
-add_custom_target(luci_interpreter_micro_arm DEPENDS "${MICRO_ARM_BINARY}")
+add_custom_target(onert_micro_arm DEPENDS "${MICRO_ARM_BINARY}")
 
 add_subdirectory(eval-driver)
 
-if (NOT DEFINED BUILD_TEST)
+# Should be after add_subdirectory
+unset(ENABLE_ONERT_MICRO_TRAINING CACHE)
+
+# Example build
+if (NOT DEFINED BUILD_EXAMPLE)
     return()
 endif ()
 
@@ -207,7 +195,7 @@ if (NOT MbedOSSource_FOUND)
     return()
 endif ()
 
-set(MBED_OS_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/tests/mbed-os")
+set(MBED_OS_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/examples/speech_recognition/DISCO_F746/mbed-os")
 file(MAKE_DIRECTORY "${MBED_OS_BUILD_DIR}")
 
 set(MBED_OS_BUILD_DEPENDENCY "${MBED_OS_BUILD_DIR}/CMakeCache.txt")
@@ -216,13 +204,13 @@ set(ONERTMICRO_SRC_DIR "${NNAS_PROJECT_SOURCE_DIR}/onert-micro")
 
 add_custom_command(
         OUTPUT "${MBED_OS_BUILD_DEPENDENCY}"
-        COMMAND "${CMAKE_COMMAND}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/mbed-os"
+        COMMAND "${CMAKE_COMMAND}" "${CMAKE_CURRENT_SOURCE_DIR}/examples/speech_recognition/DISCO_F746/mbed-os"
         -DMICRO_ARM_BUILD_DIR=${MICRO_ARM_BUILD_DIR}
         -DMbedOSSource_DIR=${MbedOSSource_DIR}
         -DFlatBuffersSource_DIR=${FlatBuffersSource_DIR}
         -DONERTMICRO_SRC_DIR=${ONERTMICRO_SRC_DIR}
         WORKING_DIRECTORY "${MBED_OS_BUILD_DIR}"
-        DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/tests/mbed-os/CMakeLists.txt"
+        DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/examples/speech_recognition/DISCO_F746/mbed-os/CMakeLists.txt"
         VERBATIM
 )
 
@@ -240,13 +228,13 @@ add_custom_command(
 
 add_custom_target(mbed_os_arm DEPENDS "${MBED_OS_BINARY}")
 
-set(BUILD_TEST_BINARY "${MBED_OS_BUILD_DIR}/build_test.bin")
+set(BUILD_EXAMPLE_BINARY "${MBED_OS_BUILD_DIR}/example_speech_recognition.bin")
 
 add_custom_command(
-        OUTPUT "${BUILD_TEST_BINARY}"
-        COMMAND "${CMAKE_MAKE_PROGRAM}" build_test -j ${CPU_COUNT}
+        OUTPUT "${BUILD_EXAMPLE_BINARY}"
+        COMMAND "${CMAKE_MAKE_PROGRAM}" example_speech_recognition -j ${CPU_COUNT}
         WORKING_DIRECTORY "${MBED_OS_BUILD_DIR}"
-        DEPENDS mbed_os_arm "${CMAKE_CURRENT_SOURCE_DIR}/tests/mbed-os/main.cpp" ${MICRO_ARM_BINARY}
+        DEPENDS mbed_os_arm "${CMAKE_CURRENT_SOURCE_DIR}/examples/speech_recognition/DISCO_F746/mbed-os/main.cpp" ${MICRO_ARM_BINARY}
         VERBATIM
 )
-add_custom_target(onert_micro_build_test_arm DEPENDS "${BUILD_TEST_BINARY}")
+add_custom_target(onert_micro_build_example_arm DEPENDS "${BUILD_EXAMPLE_BINARY}")
index 2a1b73a..3b5b84e 100644 (file)
@@ -5,9 +5,25 @@ add_executable(onert_micro_eval_driver ${SRCS_EVAL_TESTER})
 # This variable is needed to separate standalone interpreter libraries from the libraries used in driver
 set(READER_SUFFIX "_driver")
 
-add_subdirectory(${NNAS_PROJECT_SOURCE_DIR}/onert-micro/luci-interpreter ${CMAKE_CURRENT_BINARY_DIR}/luci-interpreter)
+add_subdirectory(${NNAS_PROJECT_SOURCE_DIR}/onert-micro/onert-micro ${CMAKE_CURRENT_BINARY_DIR}/onert-micro)
 
-target_include_directories(onert_micro_eval_driver PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/luci-interpreter/include")
-target_link_libraries(onert_micro_eval_driver PUBLIC luci_interpreter_micro)
+target_include_directories(onert_micro_eval_driver PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/onert_micro/include")
+target_link_libraries(onert_micro_eval_driver PUBLIC onert_micro_interpreter)
 
 install(TARGETS onert_micro_eval_driver DESTINATION bin)
+
+message(STATUS "DONE eval driver")
+
+set(SRCS_EVAL_TRAINING_TESTER TrainingDriver.cpp)
+
+add_executable(onert_micro_training_eval_driver ${SRCS_EVAL_TRAINING_TESTER})
+
+# This variable is needed to separate standalone interpreter libraries from the libraries used in driver
+set(READER_SUFFIX "_driver")
+
+target_include_directories(onert_micro_training_eval_driver PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/onert_micro/include")
+target_link_libraries(onert_micro_training_eval_driver PUBLIC onert_micro_training_interpreter)
+
+install(TARGETS onert_micro_training_eval_driver DESTINATION bin)
+
+message(STATUS "DONE training eval driver")
index d29c41d..b4570e5 100644 (file)
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <luci_interpreter/Interpreter.h>
+#include "OMInterpreter.h"
 
 #include <stdexcept>
 #include <cstdlib>
@@ -94,7 +94,9 @@ int entry(int argc, char **argv)
   }
 
   // Create interpreter.
-  luci_interpreter::Interpreter interpreter(model_data.data(), true);
+  onert_micro::OMInterpreter interpreter;
+  onert_micro::OMConfig config;
+  interpreter.importModel(model_data.data(), config);
 
   // Set input.
   // Data for n'th input is read from ${input_prefix}n
@@ -102,28 +104,31 @@ int entry(int argc, char **argv)
   int num_inference = 1;
   for (int j = 0; j < num_inference; ++j)
   {
+    interpreter.reset();
+    interpreter.allocateInputs();
     for (int32_t i = 0; i < num_inputs; i++)
     {
-      auto input_data = reinterpret_cast<char *>(interpreter.allocateInputTensor(i));
+      auto input_data = reinterpret_cast<char *>(interpreter.getInputDataAt(i));
       readDataFromFile(std::string(input_prefix) + std::to_string(i), input_data,
-                       interpreter.getInputDataSizeByIndex(i));
+                       interpreter.getInputSizeAt(i) * sizeof(float));
     }
 
     // Do inference.
-    interpreter.interpret();
+    interpreter.run();
   }
 
   // Get output.
   int num_outputs = 1;
   for (int i = 0; i < num_outputs; i++)
   {
-    auto data = interpreter.readOutputTensor(i);
+    auto data = interpreter.getOutputDataAt(i);
 
     // Output data is written in ${output_file}
     // (ex: Add.circle.output0)
     writeDataToFile(std::string(output_file) + std::to_string(i), reinterpret_cast<char *>(data),
-                    interpreter.getOutputDataSizeByIndex(i));
+                    interpreter.getOutputSizeAt(i) * sizeof(float));
   }
+  interpreter.reset();
   return EXIT_SUCCESS;
 }
 
diff --git a/onert-micro/eval-driver/TrainingDriver.cpp b/onert-micro/eval-driver/TrainingDriver.cpp
new file mode 100644 (file)
index 0000000..706ad7e
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMTrainingInterpreter.h"
+#include <stdexcept>
+#include <cstdlib>
+#include <fstream>
+#include <vector>
+#include <string>
+#include <iostream>
+#include <numeric>
+
+#define MODEL_TYPE float
+
+#define CLASSIFICATION_TASK 1
+
+namespace
+{
+
+using DataBuffer = std::vector<char>;
+
+void readDataFromFile(const std::string &filename, char *data, size_t data_size,
+                      size_t start_position = 0)
+{
+  std::streampos start = start_position;
+
+  std::ifstream fs(filename, std::ifstream::binary);
+  if (fs.fail())
+    throw std::runtime_error("Cannot open file \"" + filename + "\".\n");
+
+  fs.seekg(start);
+
+  if (fs.read(data, data_size).fail())
+    throw std::runtime_error("Failed to read data from file \"" + filename + "\".\n");
+  fs.close();
+}
+
+void readDataFromFile(std::ifstream &fs, const std::string &filename, char *data, size_t data_size,
+                      size_t start_position = 0)
+{
+  std::streampos start = start_position;
+
+  fs.seekg(start);
+
+  if (fs.read(data, data_size).fail())
+    throw std::runtime_error("Failed to read data from file \"" + filename + "\".\n");
+}
+
+void writeDataToFile(const std::string &filename, const char *data, size_t data_size)
+{
+  std::ofstream fs(filename, std::ofstream::binary);
+  if (fs.fail())
+    throw std::runtime_error("Cannot open file \"" + filename + "\".\n");
+  if (fs.write(data, data_size).fail())
+  {
+    throw std::runtime_error("Failed to write data to file \"" + filename + "\".\n");
+  }
+}
+
+DataBuffer readFile(const char *path)
+{
+  std::ifstream file(path, std::ios::binary | std::ios::in);
+  if (!file.good())
+  {
+    std::string errmsg = "Failed to open file";
+    throw std::runtime_error(errmsg.c_str());
+  }
+
+  file.seekg(0, std::ios::end);
+  auto fileSize = file.tellg();
+  file.seekg(0, std::ios::beg);
+
+  // reserve capacity
+  DataBuffer model_data(fileSize);
+
+  // read the data
+  file.read(model_data.data(), fileSize);
+  if (file.fail())
+  {
+    std::string errmsg = "Failed to read file";
+    throw std::runtime_error(errmsg.c_str());
+  }
+
+  return model_data;
+}
+
+} // namespace
+
+/*
+ * @brief EvalDriver main
+ *
+ *  Driver for testing training onert micro
+ *  Current example for testing classification task
+ *
+ */
+int entry(int argc, char **argv)
+{
+  if (argc != 11 and argc != 10)
+  {
+    std::cerr << "Two variant of usage with and without wof file: " << argv[0]
+              << " <path/to/circle/model> "
+                 " optional(<path/to/wof/file>) <path/to/save/trained/model> "
+                 "<path/to/save/checkpoint> <path/to/input/train_data> "
+                 "<path/to/input/target_train_data> "
+                 "<path/to/input/test_data> <path/to/input/target_test_data> num_of_train_smpl "
+                 "num_of_test_smpl\n";
+    return EXIT_FAILURE;
+  }
+
+  const char *circle_model_path = nullptr;
+  const char *wof_file_path = nullptr;
+  const char *output_trained_file_path = nullptr;
+  const char *input_input_train_data_path = nullptr;
+  const char *input_target_train_data_path = nullptr;
+  const char *input_input_test_data_path = nullptr;
+  const char *input_target_test_data_path = nullptr;
+  const char *checkpoints_path = nullptr;
+  int32_t num_train_data_samples = 0;
+  int32_t num_test_data_samples = 0;
+
+  if (argc == 11)
+  {
+    circle_model_path = argv[1];
+    wof_file_path = argv[2];
+    output_trained_file_path = argv[3];
+    checkpoints_path = argv[4];
+    input_input_train_data_path = argv[5];
+    input_target_train_data_path = argv[6];
+    input_input_test_data_path = argv[7];
+    input_target_test_data_path = argv[8];
+    num_train_data_samples = atoi(argv[9]);
+    num_test_data_samples = atoi(argv[10]);
+  }
+  else if (argc == 10)
+  {
+    circle_model_path = argv[1];
+    output_trained_file_path = argv[2];
+    checkpoints_path = argv[3];
+    input_input_train_data_path = argv[4];
+    input_target_train_data_path = argv[5];
+    input_input_test_data_path = argv[6];
+    input_target_test_data_path = argv[7];
+    num_train_data_samples = atoi(argv[8]);
+    num_test_data_samples = atoi(argv[9]);
+  }
+  else
+  {
+    throw std::runtime_error("Unknown commands number\n");
+  }
+
+  DataBuffer circle_model = readFile(circle_model_path);
+  DataBuffer wof_data;
+  // If defined wof file
+  if (wof_file_path != nullptr)
+    wof_data = readFile(wof_file_path);
+
+  // Configure training mode
+  onert_micro::OMConfig config;
+
+  // Save model size and model ptr in config
+  config.model_size = circle_model.size();
+  config.model_ptr = circle_model.data();
+
+  // If defined wof file
+  if (wof_file_path != nullptr)
+    config.wof_ptr = nullptr;
+
+  // Set user defined training settings
+  const uint32_t training_epochs = 30;
+  const float lambda = 0.001f;
+  const uint32_t BATCH_SIZE = 32;
+  const uint32_t INPUT_SIZE = 180;
+  const uint32_t OUTPUT_SIZE = 4;
+  const uint32_t num_train_layers = 10;
+  const onert_micro::OMLoss loss = onert_micro::CROSS_ENTROPY;
+  const onert_micro::OMTrainOptimizer train_optim = onert_micro::ADAM;
+  const float beta = 0.9;
+  const float beta_squares = 0.999;
+  const float epsilon = 1e-07;
+
+  config.train_mode = true;
+  {
+    onert_micro::OMTrainingContext train_context;
+    train_context.batch_size = BATCH_SIZE;
+    train_context.num_of_train_layers = num_train_layers;
+    train_context.learning_rate = lambda;
+    train_context.loss = loss;
+    train_context.optimizer = train_optim;
+    train_context.beta = beta;
+    train_context.beta_squares = beta_squares;
+    train_context.epsilon = epsilon;
+    train_context.epochs = training_epochs;
+
+    config.training_context = train_context;
+  }
+
+  // Create training interpreter and import models
+  onert_micro::OMTrainingInterpreter train_interpreter;
+  train_interpreter.importTrainModel(circle_model.data(), config);
+
+  // Temporary buffer to read input data from file using BATCH_SIZE
+  float training_input[BATCH_SIZE * INPUT_SIZE];
+  float training_target[BATCH_SIZE * OUTPUT_SIZE];
+  // Note: here test size used with BATCH_SIZE = 1
+  float test_input[INPUT_SIZE];
+  float test_target[OUTPUT_SIZE];
+
+  std::vector<float> accuracy_v;
+  std::vector<float> cross_entropy_v;
+  std::vector<float> mse_v;
+  std::vector<float> mae_v;
+
+  float max_accuracy = std::numeric_limits<float>::min();
+  float min_mae = std::numeric_limits<float>::max();
+
+  for (uint32_t e = 0; e < training_epochs; ++e)
+  {
+    // Run train for current epoch
+    std::cout << "Run training for epoch: " << e + 1 << "/" << training_epochs << "\n";
+    config.training_context.num_epoch = e + 1;
+    uint32_t num_steps = num_train_data_samples / BATCH_SIZE;
+    for (int i = 0; i < num_steps; ++i)
+    {
+      uint32_t cur_batch_size = std::min(BATCH_SIZE, num_train_data_samples - BATCH_SIZE * i - 1);
+      cur_batch_size = std::max(1u, cur_batch_size);
+
+      config.training_context.batch_size = cur_batch_size;
+
+      // Read current input and target data
+      readDataFromFile(input_input_train_data_path, reinterpret_cast<char *>(training_input),
+                       sizeof(float) * INPUT_SIZE * cur_batch_size,
+                       i * sizeof(MODEL_TYPE) * INPUT_SIZE * BATCH_SIZE);
+
+      readDataFromFile(input_target_train_data_path, reinterpret_cast<char *>(training_target),
+                       sizeof(float) * OUTPUT_SIZE * cur_batch_size,
+                       i * sizeof(MODEL_TYPE) * OUTPUT_SIZE * BATCH_SIZE);
+
+      // Set input and target
+      train_interpreter.setInput(reinterpret_cast<uint8_t *>(training_input), 0);
+      train_interpreter.setTarget(reinterpret_cast<uint8_t *>(training_target), 0);
+
+      // Train with current batch size
+      train_interpreter.trainSingleStep(config);
+
+      float mse = 0.f;
+      float mae = 0.f;
+      float cross_entropy_metric = 0.f;
+      float accuracy = 0.f;
+
+      if (CLASSIFICATION_TASK)
+      {
+        // Evaluate cross_entropy and accuracy metrics
+        train_interpreter.evaluateMetric(onert_micro::CROSS_ENTROPY_METRICS,
+                                         reinterpret_cast<void *>(&cross_entropy_metric),
+                                         cur_batch_size);
+        train_interpreter.evaluateMetric(onert_micro::ACCURACY, reinterpret_cast<void *>(&accuracy),
+                                         cur_batch_size);
+
+        // Save them into vectors
+        accuracy_v.push_back(accuracy);
+        cross_entropy_v.push_back(cross_entropy_metric);
+      }
+      else
+      {
+        // Evaluate mse and mae metrics
+        train_interpreter.evaluateMetric(onert_micro::MSE_METRICS, reinterpret_cast<void *>(&mse),
+                                         cur_batch_size);
+        train_interpreter.evaluateMetric(onert_micro::MAE_METRICS, reinterpret_cast<void *>(&mae),
+                                         cur_batch_size);
+
+        // Save them into vectors
+        mse_v.push_back(mse);
+        mae_v.push_back(mae);
+      }
+    }
+
+    // Reset num step value
+    config.training_context.num_step = 0;
+
+    // Calculate and print average values
+    if (CLASSIFICATION_TASK)
+    {
+      float sum_acc = std::accumulate(accuracy_v.begin(), accuracy_v.end(), 0.f);
+      float sum_ent = std::accumulate(cross_entropy_v.begin(), cross_entropy_v.end(), 0.f);
+      std::cout << "Train Average ACCURACY = " << sum_acc / accuracy_v.size() << "\n";
+      std::cout << "Train Average CROSS ENTROPY = " << sum_ent / cross_entropy_v.size() << "\n";
+    }
+    else
+    {
+      float sum_mse = std::accumulate(mse_v.begin(), mse_v.end(), 0.f);
+      float sum_mae = std::accumulate(mae_v.begin(), mae_v.end(), 0.f);
+      std::cout << "Train Average MSE = " << sum_mse / mse_v.size() << "\n";
+      std::cout << "Train Average MAE = " << sum_mae / mae_v.size() << "\n";
+    }
+
+    // Run test for current epoch
+    std::cout << "Run test for epoch: " << e + 1 << "/" << training_epochs << "\n";
+    num_steps = num_test_data_samples;
+
+    accuracy_v.clear();
+    cross_entropy_v.clear();
+
+    for (int i = 0; i < num_steps; ++i)
+    {
+      uint32_t cur_batch_size = 1;
+      readDataFromFile(input_input_test_data_path, reinterpret_cast<char *>(test_input),
+                       sizeof(float) * INPUT_SIZE * cur_batch_size,
+                       i * sizeof(MODEL_TYPE) * INPUT_SIZE);
+
+      readDataFromFile(input_target_test_data_path, reinterpret_cast<char *>(test_target),
+                       sizeof(float) * OUTPUT_SIZE * cur_batch_size,
+                       i * sizeof(MODEL_TYPE) * OUTPUT_SIZE);
+
+      train_interpreter.setInput(reinterpret_cast<uint8_t *>(test_input), 0);
+      train_interpreter.setTarget(reinterpret_cast<uint8_t *>(test_target), 0);
+
+      float mse = 0.f;
+      float mae = 0.f;
+      float cross_entropy_metric = 0.f;
+      float accuracy = 0.f;
+
+      if (CLASSIFICATION_TASK)
+      {
+        // Evaluate cross_entropy and accuracy metrics
+        train_interpreter.evaluateMetric(onert_micro::CROSS_ENTROPY_METRICS,
+                                         reinterpret_cast<void *>(&cross_entropy_metric),
+                                         cur_batch_size);
+        train_interpreter.evaluateMetric(onert_micro::ACCURACY, reinterpret_cast<void *>(&accuracy),
+                                         cur_batch_size);
+
+        // Save them into vectors
+        accuracy_v.push_back(accuracy);
+        cross_entropy_v.push_back(cross_entropy_metric);
+      }
+      else
+      {
+        // Evaluate mse and mae metrics
+        train_interpreter.evaluateMetric(onert_micro::MSE_METRICS, reinterpret_cast<void *>(&mse),
+                                         cur_batch_size);
+        train_interpreter.evaluateMetric(onert_micro::MAE_METRICS, reinterpret_cast<void *>(&mae),
+                                         cur_batch_size);
+
+        // Save them into vectors
+        mse_v.push_back(mse);
+        mae_v.push_back(mae);
+      }
+    }
+    // Calculate and print average values
+    if (CLASSIFICATION_TASK)
+    {
+      float sum_acc = std::accumulate(accuracy_v.begin(), accuracy_v.end(), 0.f);
+      float sum_ent = std::accumulate(cross_entropy_v.begin(), cross_entropy_v.end(), 0.f);
+      std::cout << "Test Average ACCURACY = " << sum_acc / accuracy_v.size() << "\n";
+      std::cout << "Test Average CROSS ENTROPY = " << sum_ent / cross_entropy_v.size() << "\n";
+
+      // Best checkpoint part
+      float acc = sum_acc / accuracy_v.size();
+      if (acc > max_accuracy)
+      {
+        // Save best checkpoint
+        train_interpreter.saveCheckpoint(config, checkpoints_path);
+        max_accuracy = acc;
+        std::cout << "Found new max Test ACCURACY = " << max_accuracy << " in epoch = " << e + 1
+                  << " / " << training_epochs << "\n";
+      }
+    }
+    else
+    {
+      float sum_mse = std::accumulate(mse_v.begin(), mse_v.end(), 0.f);
+      float sum_mae = std::accumulate(mae_v.begin(), mae_v.end(), 0.f);
+      std::cout << "Test Average MSE = " << sum_mse / mse_v.size() << "\n";
+      std::cout << "Test Average MAE = " << sum_mae / mae_v.size() << "\n";
+
+      // Best checkpoint part
+      float acc = sum_mae / mae_v.size();
+      if (acc < min_mae)
+      {
+        // Save best checkpoint
+        train_interpreter.saveCheckpoint(config, checkpoints_path);
+        min_mae = acc;
+        std::cout << "Found new min Test MAE = " << min_mae << " in epoch = " << e + 1 << " / "
+                  << training_epochs << "\n";
+      }
+    }
+  }
+
+  // Load best model
+  train_interpreter.loadCheckpoint(config, checkpoints_path);
+
+  // Save training best result
+  train_interpreter.saveModel(config, output_trained_file_path);
+
+  return EXIT_SUCCESS;
+}
+
+int entry(int argc, char **argv);
+
+#ifdef NDEBUG
+int main(int argc, char **argv)
+{
+  try
+  {
+    return entry(argc, argv);
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "ERROR: " << e.what() << std::endl;
+  }
+
+  return 255;
+}
+#else  // NDEBUG
+int main(int argc, char **argv)
+{
+  // NOTE main does not catch internal exceptions for debug build to make it easy to
+  //      check the stacktrace with a debugger
+  return entry(argc, argv);
+}
+#endif // !NDEBUG
diff --git a/onert-micro/examples/README.md b/onert-micro/examples/README.md
new file mode 100644 (file)
index 0000000..97e93cf
--- /dev/null
@@ -0,0 +1,6 @@
+## How to build an example
+- Build ONE toolchain
+- Convert your tflite model to circle using tflite2circle from toolchain
+  e.g. `./tflite2circle ./speech_recognition_float.tflite ./speech_recognition_float.circle`
+- Convert model to C array: `xxd -i ./speech_recognition_float.circle ./speech_recognition_float.h`
+- Include C array with model to your project
diff --git a/onert-micro/examples/models/speech_recognition/speech_recognition_float.tflite b/onert-micro/examples/models/speech_recognition/speech_recognition_float.tflite
new file mode 100644 (file)
index 0000000..4245e2c
Binary files /dev/null and b/onert-micro/examples/models/speech_recognition/speech_recognition_float.tflite differ
diff --git a/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/CMakeLists.txt b/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/CMakeLists.txt
new file mode 100644 (file)
index 0000000..214f863
--- /dev/null
@@ -0,0 +1,147 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 3.9)
+SET(CMAKE_SYSTEM_NAME Generic)
+SET(CMAKE_CROSSCOMPILING TRUE)
+
+# force compiler settings
+SET(CMAKE_C_COMPILER_WORKS TRUE)
+SET(CMAKE_CXX_COMPILER_WORKS TRUE)
+
+# force cmake compilers
+SET(CMAKE_ASM_COMPILER "arm-none-eabi-gcc")
+SET(CMAKE_C_COMPILER "arm-none-eabi-gcc")
+SET(CMAKE_CXX_COMPILER "arm-none-eabi-g++")
+SET(ELF2BIN "arm-none-eabi-objcopy")
+
+
+# if the environment does not specify build type, set to Debug
+IF (NOT CMAKE_BUILD_TYPE)
+    set(CMAKE_BUILD_TYPE "Debug"
+            CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
+            FORCE)
+ENDIF ()
+
+# here starts the project
+PROJECT(example_speech_recognition C CXX ASM)
+
+# uncomment below to have a verbose build process
+#SET(CMAKE_VERBOSE_MAKEFILE ON)
+SET(LD_SYS_LIBS "-Wl,--start-group -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys  -Wl,--end-group")
+
+SET(CMAKE_C_FLAGS "-g3 -fno-pic -std=gnu11 -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fmessage-length=0 -fexceptions -ffunction-sections -fdata-sections -funsigned-char -MMD -fomit-frame-pointer -Og -DMBED_DEBUG -DMBED_TRAP_ERRORS_ENABLED=1 -DMBED_MINIMAL_PRINTF -mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=softfp -DMBED_ROM_START=0x8000000 -DMBED_ROM_SIZE=0x100000 -DMBED_ROM1_START=0x200000 -DMBED_ROM1_SIZE=0x100000 -DMBED_RAM_START=0x20010000 -DMBED_RAM_SIZE=0x40000 -DMBED_RAM1_START=0x20000000 -DMBED_RAM1_SIZE=0x10000 -include ${CMAKE_CURRENT_SOURCE_DIR}/mbed_config.h")
+SET(CMAKE_CXX_FLAGS "-g3 -fno-pic -std=gnu++14 -frtti -Wvla -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fmessage-length=0 -fexceptions -ffunction-sections -fdata-sections -funsigned-char -MMD -fomit-frame-pointer -Og -DMBED_DEBUG -DMBED_TRAP_ERRORS_ENABLED=1 -DMBED_MINIMAL_PRINTF -mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=softfp -DMBED_ROM_START=0x8000000 -DMBED_ROM_SIZE=0x100000 -DMBED_ROM1_START=0x200000 -DMBED_ROM1_SIZE=0x100000 -DMBED_RAM_START=0x20010000 -DMBED_RAM_SIZE=0x40000 -DMBED_RAM1_START=0x20000000 -DMBED_RAM1_SIZE=0x10000  -include ${CMAKE_CURRENT_SOURCE_DIR}/mbed_config.h")
+SET(CMAKE_ASM_FLAGS "-g3 -x assembler-with-cpp -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fmessage-length=0 -fexceptions -ffunction-sections -fdata-sections -funsigned-char -MMD -fomit-frame-pointer -Og -DMBED_DEBUG -DMBED_TRAP_ERRORS_ENABLED=1 -DMBED_MINIMAL_PRINTF -mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=softfp  -include ${CMAKE_CURRENT_SOURCE_DIR}/mbed_config.h")
+SET(CMAKE_CXX_LINK_FLAGS "-Wl,--gc-sections -Wl,--wrap,main -Wl,--wrap,__malloc_r -Wl,--wrap,__free_r -Wl,--wrap,__realloc_r -Wl,--wrap,__memalign_r -Wl,--wrap,__calloc_r -Wl,--wrap,exit -Wl,--wrap,atexit -Wl,-n -Wl,--wrap,printf -Wl,--wrap,sprintf -Wl,--wrap,snprintf -Wl,--wrap,vprintf -Wl,--wrap,vsprintf -Wl,--wrap,vsnprintf -Wl,--wrap,fprintf -Wl,--wrap,vfprintf -mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=softfp -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fmessage-length=0 -fexceptions -ffunction-sections -fdata-sections -funsigned-char -MMD -fomit-frame-pointer -Og -DMBED_DEBUG -DMBED_TRAP_ERRORS_ENABLED=1 -DMBED_MINIMAL_PRINTF -mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=softfp -DMBED_ROM_START=0x8000000 -DMBED_ROM_SIZE=0x100000 -DMBED_ROM1_START=0x200000 -DMBED_ROM1_SIZE=0x100000 -DMBED_RAM_START=0x20010000 -DMBED_RAM_SIZE=0x40000 -DMBED_RAM1_START=0x20000000 -DMBED_RAM1_SIZE=0x10000 -DMBED_BOOT_STACK_SIZE=1024 -DXIP_ENABLE=0 ")
+SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} ${LD_SYS_LIBS} -T ${CMAKE_BINARY_DIR}/example_speech_recognition_pp.link_script.ld")
+
+ADD_DEFINITIONS(
+        -DARM_MATH_CM7
+        -DCOMPONENT_FLASHIAP=1
+        -DCOMPONENT_QSPIF=1
+        -DDEVICE_ANALOGIN=1
+        -DDEVICE_ANALOGOUT=1
+        -DDEVICE_CAN=1
+        -DDEVICE_CRC=1
+        -DDEVICE_EMAC=1
+        -DDEVICE_FLASH=1
+        -DDEVICE_I2C=1
+        -DDEVICE_I2CSLAVE=1
+        -DDEVICE_I2C_ASYNCH=1
+        -DDEVICE_INTERRUPTIN=1
+        -DDEVICE_LPTICKER=1
+        -DDEVICE_MPU=1
+        -DDEVICE_PORTIN=1
+        -DDEVICE_PORTINOUT=1
+        -DDEVICE_PORTOUT=1
+        -DDEVICE_PWMOUT=1
+        -DDEVICE_QSPI=1
+        -DDEVICE_RESET_REASON=1
+        -DDEVICE_RTC=1
+        -DDEVICE_SERIAL=1
+        -DDEVICE_SERIAL_ASYNCH=1
+        -DDEVICE_SERIAL_FC=1
+        -DDEVICE_SLEEP=1
+        -DDEVICE_SPI=1
+        -DDEVICE_SPISLAVE=1
+        -DDEVICE_SPI_ASYNCH=1
+        -DDEVICE_STDIO_MESSAGES=1
+        -DDEVICE_TRNG=1
+        -DDEVICE_USBDEVICE=1
+        -DDEVICE_USTICKER=1
+        -DDEVICE_WATCHDOG=1
+        -DEXTRA_IDLE_STACK_REQUIRED
+        -DHSE_VALUE=25000000
+        -DMBED_BUILD_TIMESTAMP=1641868365.2
+        -DMBED_TICKLESS
+        -DSTM32F746xx
+        -DTARGET_CORTEX
+        -DTARGET_CORTEX_M
+        -DTARGET_DISCO_F746NG
+        -DTARGET_FF_ARDUINO_UNO
+        -DTARGET_LIKE_CORTEX_M7
+        -DTARGET_LIKE_MBED
+        -DTARGET_M7
+        -DTARGET_MCU_STM32
+        -DTARGET_MCU_STM32F7
+        -DTARGET_N25Q128A
+        -DTARGET_NAME=DISCO_F746NG
+        -DTARGET_RELEASE
+        -DTARGET_RTOS_M4_M7
+        -DTARGET_STM
+        -DTARGET_STM32F7
+        -DTARGET_STM32F746xG
+        -DTOOLCHAIN_GCC
+        -DTOOLCHAIN_GCC_ARM
+        -DTRANSACTION_QUEUE_SIZE_SPI=2
+        -DUSE_FULL_LL_DRIVER
+        -DUSE_HAL_DRIVER
+        -D__CMSIS_RTOS
+        -D__CORTEX_M7
+        -D__FPU_PRESENT=1
+        -D__MBED_CMSIS_RTOS_CM
+        -D__MBED__=1
+)
+
+include(mbed-sources.cmake)
+
+set_sources_mbed(${MbedOSSource_DIR})
+
+add_library(mbed_os STATIC ${SOURCES})
+
+target_include_directories_mbed(mbed_os ${MbedOSSource_DIR})
+
+
+SET_TARGET_PROPERTIES(mbed_os PROPERTIES ENABLE_EXPORTS 1)
+# add syslibs dependencies to create the correct linker order
+TARGET_LINK_LIBRARIES(mbed_os -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys)
+
+add_executable(example_speech_recognition main.cpp)
+
+target_link_libraries(example_speech_recognition PUBLIC mbed_os)
+target_include_directories_mbed(example_speech_recognition ${MbedOSSource_DIR})
+
+target_link_libraries(example_speech_recognition PUBLIC "${MICRO_ARM_BUILD_DIR}/luci-interpreter/src/libluci_interpreter_micro.a")
+target_link_libraries(example_speech_recognition PUBLIC "${MICRO_ARM_BUILD_DIR}/luci-interpreter/src/loader/libluci_interpreter_loader_micro.a")
+target_link_libraries(example_speech_recognition PUBLIC "${MICRO_ARM_BUILD_DIR}/luci-interpreter/src/core/libluci_interpreter_core_micro.a")
+target_link_libraries(example_speech_recognition PUBLIC "${MICRO_ARM_BUILD_DIR}/luci-interpreter/src/core/reader/libluci_micro_circle_reader.a")
+target_link_libraries(example_speech_recognition PUBLIC "${MICRO_ARM_BUILD_DIR}/luci-interpreter/src/memory_managers/libluci_interpreter_micro_memory_manager.a")
+target_link_libraries(example_speech_recognition PUBLIC "${MICRO_ARM_BUILD_DIR}/luci-interpreter/src/kernels/libluci_interpreter_kernels_micro.a")
+
+target_include_directories(example_speech_recognition PUBLIC
+        ${ONERTMICRO_SRC_DIR}/luci-interpreter/include
+        ${ONERTMICRO_SRC_DIR}/luci-interpreter/src
+        ${ONERTMICRO_SRC_DIR}/externals
+        ${ONERTMICRO_SRC_DIR}/externals/gen
+        ${CMAKE_CURRENT_SOURCE_DIR}
+        ${FlatBuffersSource_DIR}/include
+)
+
+add_custom_command(TARGET example_speech_recognition PRE_LINK
+        COMMAND "arm-none-eabi-cpp" -E -P -Wl,--gc-sections -Wl,--wrap,main -Wl,--wrap,_malloc_r -Wl,--wrap,_free_r -Wl,--wrap,_realloc_r -Wl,--wrap,_memalign_r -Wl,--wrap,_calloc_r -Wl,--wrap,exit -Wl,--wrap,atexit -Wl,-n -Wl,--wrap,printf -Wl,--wrap,sprintf -Wl,--wrap,snprintf -Wl,--wrap,vprintf -Wl,--wrap,vsprintf -Wl,--wrap,vsnprintf -Wl,--wrap,fprintf -Wl,--wrap,vfprintf -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=softfp -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fmessage-length=0 -fexceptions -ffunction-sections -fdata-sections -funsigned-char -MMD -fomit-frame-pointer -Og -DMBED_DEBUG -DMBED_TRAP_ERRORS_ENABLED=1 -DMBED_MINIMAL_PRINTF -mcpu=cortex-m7 -mthumb -mfpu=fpv5-d16 -mfloat-abi=softfp -DMBED_ROM_START=0x8000000 -DMBED_ROM_SIZE=0x100000 -DMBED_ROM1_START=0x200000 -DMBED_ROM1_SIZE=0x100000 -DMBED_RAM_START=0x20010000 -DMBED_RAM_SIZE=0x40000 -DMBED_RAM1_START=0x20000000 -DMBED_RAM1_SIZE=0x10000 -DMBED_BOOT_STACK_SIZE=1024 -DXIP_ENABLE=0 ${MbedOSSource_DIR}/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TOOLCHAIN_GCC_ARM/STM32F746xG.ld -o ${CMAKE_CURRENT_BINARY_DIR}/example_speech_recognition_pp.link_script.ld
+        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+        BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/example_speech_recognition_pp.link_script.ld"
+)
+
+add_custom_command(TARGET example_speech_recognition POST_BUILD
+        COMMAND ${ELF2BIN} -O binary $<TARGET_FILE:example_speech_recognition> $<TARGET_FILE:example_speech_recognition>.bin
+        COMMAND ${CMAKE_COMMAND} -E echo "-- built: $<TARGET_FILE:example_speech_recognition>.bin"
+)
diff --git a/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/main.cpp b/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/main.cpp
new file mode 100644 (file)
index 0000000..359e191
--- /dev/null
@@ -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_interpreter/Interpreter.h>
+#include <iostream>
+#include <vector>
+#include "mbed.h"
+#include "speech_recognition_float.circle.h"
+#include "test_data.h"
+
+static luci_interpreter::Interpreter interpreter(circle_model_raw, true);
+std::vector<float> infer()
+{
+  auto input_data = reinterpret_cast<float *>(interpreter.allocateInputTensor(0));
+  for (int i = 0; i < 1960; ++i)
+  {
+    *(input_data + i) = test_data[i];
+  }
+  interpreter.interpret();
+  auto data = interpreter.readOutputTensor(0);
+  std::vector<float> output;
+  for (int i = 0; i < 4; ++i)
+  {
+    output.push_back(*(reinterpret_cast<float *>(data) + i));
+  }
+  return output;
+}
+void print_float(float x)
+{
+  int tmp = x * 1000000 - static_cast<int>(x) * 1000000;
+  std::cout << (tmp >= 0 ? "" : "-") << static_cast<int>(x) << ".";
+  int zeros_to_add = 0;
+  for (int i = 100000; i >= 1; i = i / 10)
+  {
+    if (tmp / i != 0)
+      break;
+    zeros_to_add++;
+  }
+  for (int i = 0; i < zeros_to_add; ++i)
+  {
+    std::cout << "0";
+  }
+  std::cout << (tmp >= 0 ? tmp : -tmp) << "\n";
+}
+int main()
+{
+  Timer t;
+  t.start();
+  auto res = infer();
+  t.stop();
+  std::cout << "Executed in " << t.read_us() << "us\n";
+
+  // Predictions after inference with TFLite on PC:
+  std::cout << "CORRECT PREDICTION\n0.960639\n0.006082\n0.005203\n0.028074\n";
+
+  std::cout << "MODEL PREDICTION\n";
+  for (int i = 0; i < 4; ++i)
+    print_float(res[i]);
+  while (true)
+  {
+    ThisThread::sleep_for(100ms);
+  }
+}
diff --git a/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/mbed-sources.cmake b/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/mbed-sources.cmake
new file mode 100644 (file)
index 0000000..df3ee05
--- /dev/null
@@ -0,0 +1,1991 @@
+macro(set_sources_mbed)
+    set(SOURCES
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/Include/cmsis_os2.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/Include/os_tick.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config/RTX_Config.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config/RTX_Config.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_def.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_evr.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include/rtx_os.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include1/cmsis_os.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Library/cmsis_os1.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/TOOLCHAIN_GCC/TARGET_RTOS_M4_M7/irq_cm4f.S
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_c.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_ca.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_core_cm.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_delay.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_evflags.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_evr.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_kernel.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_lib.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_lib.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_memory.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mempool.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_msgqueue.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_mutex.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_semaphore.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_system.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_thread.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source/rtx_timer.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/Source/os_systick.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/RTOS2/Source/os_tick_ptim.c
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cachel1_armv7.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armcc.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armclang.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_armclang_ltm.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_compiler.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_gcc.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_iccarm.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/cmsis_version.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv81mml.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv8mbl.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_armv8mml.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm0.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm0plus.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm1.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm23.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm3.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm33.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm35p.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm4.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm55.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_cm7.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_sc000.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/core_sc300.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/mpu_armv7.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/mpu_armv8.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/pmu_armv8.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include/tz_context.h
+            ${ARGV0}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Source/mbed_tz_context.c
+            ${ARGV0}/cmsis/device/RTE/include/RTE_Components.h
+            ${ARGV0}/cmsis/device/mbed_cmsis_conf.h
+            ${ARGV0}/cmsis/device/rtos/TOOLCHAIN_GCC_ARM/mbed_boot_gcc_arm.c
+            ${ARGV0}/cmsis/device/rtos/include/mbed_boot.h
+            ${ARGV0}/cmsis/device/rtos/include/mbed_rtx_conf.h
+            ${ARGV0}/cmsis/device/rtos/include/mbed_rtx_storage.h
+            ${ARGV0}/cmsis/device/rtos/source/mbed_boot.c
+            ${ARGV0}/cmsis/device/rtos/source/mbed_rtos_rtx.c
+            ${ARGV0}/cmsis/device/rtos/source/mbed_rtx_handlers.c
+            ${ARGV0}/cmsis/device/rtos/source/mbed_rtx_idle.cpp
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/API/ATHandler.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/API/CellularContext.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/API/CellularDevice.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/API/CellularInformation.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/API/CellularNetwork.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/API/CellularSMS.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/AT/AT_CellularContext.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/AT/AT_CellularInformation.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/AT/AT_CellularNetwork.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/AT/AT_CellularSMS.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/AT/AT_CellularStack.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/AT/AT_ControlPlane_netif.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/common/APN_db.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/common/CellularCommon.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/common/CellularList.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/common/CellularLog.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/common/CellularUtil.h
+            ${ARGV0}/connectivity/cellular/include/cellular/framework/device/CellularStateMachine.h
+            ${ARGV0}/connectivity/cellular/source/framework/AT/AT_CellularContext.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/AT/AT_CellularInformation.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/AT/AT_CellularNetwork.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/AT/AT_CellularSMS.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/AT/AT_CellularStack.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/AT/AT_ControlPlane_netif.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/common/APN_db.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/common/CellularLog.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/common/CellularUtil.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/device/ATHandler.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/device/CellularContext.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/device/CellularDevice.cpp
+            ${ARGV0}/connectivity/cellular/source/framework/device/CellularStateMachine.cpp
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/atmel-rf-driver/atmel-rf-driver/NanostackRfPhyAtmel.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/atmel-rf-driver/source/AT86RF215Reg.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/atmel-rf-driver/source/AT86RFReg.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAT86RF215.cpp
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/atmel-rf-driver/source/NanostackRfPhyAtmel.cpp
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/atmel-rf-driver/source/at24mac.cpp
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/atmel-rf-driver/source/at24mac.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/atmel-rf-driver/source/rfbits.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/mcr20a-rf-driver/mcr20a-rf-driver/NanostackRfPhyMcr20a.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/mcr20a-rf-driver/source/MCR20Drv.c
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/mcr20a-rf-driver/source/MCR20Drv.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/mcr20a-rf-driver/source/MCR20Overwrites.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/mcr20a-rf-driver/source/MCR20Reg.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/mcr20a-rf-driver/source/NanostackRfPhyMcr20a.cpp
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/mcr20a-rf-driver/source/XcvrSpi.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/stm-s2lp-rf-driver/source/at24mac_s2lp.cpp
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/stm-s2lp-rf-driver/source/at24mac_s2lp.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/stm-s2lp-rf-driver/source/rf_configuration.c
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/stm-s2lp-rf-driver/source/rf_configuration.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/stm-s2lp-rf-driver/source/s2lpReg.h
+            ${ARGV0}/connectivity/drivers/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h
+            ${ARGV0}/connectivity/drivers/cellular/Altair/ALT1250/PPP/ALT1250_PPP.cpp
+            ${ARGV0}/connectivity/drivers/cellular/Altair/ALT1250/PPP/ALT1250_PPP.h
+            ${ARGV0}/connectivity/drivers/cellular/Altair/ALT1250/PPP/ALT1250_PPP_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/Altair/ALT1250/PPP/ALT1250_PPP_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/Altair/ALT1250/PPP/ALT1250_PPP_CellularNetwork.cpp
+            ${ARGV0}/connectivity/drivers/cellular/Altair/ALT1250/PPP/ALT1250_PPP_CellularNetwork.h
+            ${ARGV0}/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp
+            ${ARGV0}/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h
+            ${ARGV0}/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularInformation.cpp
+            ${ARGV0}/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularInformation.h
+            ${ARGV0}/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp
+            ${ARGV0}/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h
+            ${ARGV0}/connectivity/drivers/cellular/GENERIC/GENERIC_AT3GPP/GENERIC_AT3GPP.cpp
+            ${ARGV0}/connectivity/drivers/cellular/GENERIC/GENERIC_AT3GPP/GENERIC_AT3GPP.h
+            ${ARGV0}/connectivity/drivers/cellular/MultiTech/DragonflyNano/PPP/SARA4_PPP.cpp
+            ${ARGV0}/connectivity/drivers/cellular/MultiTech/DragonflyNano/PPP/SARA4_PPP.h
+            ${ARGV0}/connectivity/drivers/cellular/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularNetwork.cpp
+            ${ARGV0}/connectivity/drivers/cellular/MultiTech/DragonflyNano/PPP/SARA4_PPP_CellularNetwork.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularInformation.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularInformation.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularNetwork.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularNetwork.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularStack.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BC95/QUECTEL_BC95_CellularStack.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularInformation.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularInformation.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularNetwork.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularStack.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_CellularStack.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_ControlPlane_netif.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/BG96/QUECTEL_BG96_ControlPlane_netif.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/EC2X/QUECTEL_EC2X.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/EC2X/QUECTEL_EC2X.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/M26/QUECTEL_M26.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/M26/QUECTEL_M26.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/M26/QUECTEL_M26_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/M26/QUECTEL_M26_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/M26/QUECTEL_M26_CellularInformation.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/M26/QUECTEL_M26_CellularInformation.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/M26/QUECTEL_M26_CellularStack.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/M26/QUECTEL_M26_CellularStack.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/UG96/QUECTEL_UG96.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/UG96/QUECTEL_UG96.h
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/UG96/QUECTEL_UG96_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/QUECTEL/UG96/QUECTEL_UG96_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/RiotMicro/AT/RM1000_AT.cpp
+            ${ARGV0}/connectivity/drivers/cellular/RiotMicro/AT/RM1000_AT.h
+            ${ARGV0}/connectivity/drivers/cellular/RiotMicro/AT/RM1000_AT_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/RiotMicro/AT/RM1000_AT_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/RiotMicro/AT/RM1000_AT_CellularNetwork.cpp
+            ${ARGV0}/connectivity/drivers/cellular/RiotMicro/AT/RM1000_AT_CellularNetwork.h
+            ${ARGV0}/connectivity/drivers/cellular/RiotMicro/AT/RM1000_AT_CellularStack.cpp
+            ${ARGV0}/connectivity/drivers/cellular/RiotMicro/AT/RM1000_AT_CellularStack.h
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/HE910/TELIT_HE910.cpp
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/HE910/TELIT_HE910.h
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME310/TELIT_ME310.cpp
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME310/TELIT_ME310.h
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME310/TELIT_ME310_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME310/TELIT_ME310_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME310/TELIT_ME310_CellularNetwork.cpp
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME310/TELIT_ME310_CellularNetwork.h
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME310/TELIT_ME310_CellularStack.cpp
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME310/TELIT_ME310_CellularStack.h
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME910/TELIT_ME910.cpp
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME910/TELIT_ME910.h
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME910/TELIT_ME910_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME910/TELIT_ME910_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME910/TELIT_ME910_CellularNetwork.cpp
+            ${ARGV0}/connectivity/drivers/cellular/TELIT/ME910/TELIT_ME910_CellularNetwork.h
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/AT/UBLOX_AT.cpp
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/AT/UBLOX_AT.h
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/AT/UBLOX_AT_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/AT/UBLOX_AT_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/AT/UBLOX_AT_CellularNetwork.cpp
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/AT/UBLOX_AT_CellularNetwork.h
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/AT/UBLOX_AT_CellularStack.cpp
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/AT/UBLOX_AT_CellularStack.h
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/N2XX/UBLOX_N2XX.cpp
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/N2XX/UBLOX_N2XX.h
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/N2XX/UBLOX_N2XX_CellularContext.cpp
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/N2XX/UBLOX_N2XX_CellularContext.h
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/N2XX/UBLOX_N2XX_CellularNetwork.cpp
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/N2XX/UBLOX_N2XX_CellularNetwork.h
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/N2XX/UBLOX_N2XX_CellularSMS.cpp
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/N2XX/UBLOX_N2XX_CellularSMS.h
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/N2XX/UBLOX_N2XX_CellularStack.cpp
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/N2XX/UBLOX_N2XX_CellularStack.h
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/PPP/UBLOX_PPP.cpp
+            ${ARGV0}/connectivity/drivers/cellular/UBLOX/PPP/UBLOX_PPP.h
+            ${ARGV0}/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c
+            ${ARGV0}/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/stm32f7_eth_conf.c
+            ${ARGV0}/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/stm32xx_emac_config.h
+            ${ARGV0}/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp
+            ${ARGV0}/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.h
+            ${ARGV0}/connectivity/drivers/emac/TARGET_STM/stm32xx_eth_irq_callback.cpp
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/aes_alt.cpp
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/aes_alt.h
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/aes_alt_stm32l4.c
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/aes_alt_stm32l4.h
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/ccm_alt.cpp
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/ccm_alt.h
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/cryp_stm32.c
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/cryp_stm32.h
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/gcm_alt.cpp
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/gcm_alt.h
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/hash_stm32.c
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/hash_stm32.h
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/md5_alt.cpp
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/md5_alt.h
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/sha1_alt.cpp
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/sha1_alt.h
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/sha256_alt.cpp
+            ${ARGV0}/connectivity/drivers/mbedtls/TARGET_STM/sha256_alt.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512Driver.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512SPITransportDriver.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/include/nfc/controllers/PN512TransportDriver.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/PN512Driver.cpp
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/PN512SPITransportDriver.cpp
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/PN512TransportDriver.cpp
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512.c
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_callback.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_cmd.c
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_cmd.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_hw.c
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_hw.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_internal.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_irq.c
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_irq.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_poll.c
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_poll.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_registers.c
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_registers.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_rf.c
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_rf.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_timer.c
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_timer.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_transceive.c
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_transceive.h
+            ${ARGV0}/connectivity/drivers/nfc/PN512/source/transceiver/pn512_types.h
+            ${ARGV0}/connectivity/drivers/wifi/esp8266-driver/ESP8266/ESP8266.cpp
+            ${ARGV0}/connectivity/drivers/wifi/esp8266-driver/ESP8266/ESP8266.h
+            ${ARGV0}/connectivity/drivers/wifi/esp8266-driver/ESP8266Interface.cpp
+            ${ARGV0}/connectivity/drivers/wifi/esp8266-driver/ESP8266Interface.h
+            ${ARGV0}/connectivity/libraries/mbed-coap/mbed-coap/sn_coap_header.h
+            ${ARGV0}/connectivity/libraries/mbed-coap/mbed-coap/sn_coap_protocol.h
+            ${ARGV0}/connectivity/libraries/mbed-coap/mbed-coap/sn_config.h
+            ${ARGV0}/connectivity/libraries/mbed-coap/source/include/sn_coap_header_internal.h
+            ${ARGV0}/connectivity/libraries/mbed-coap/source/include/sn_coap_protocol_internal.h
+            ${ARGV0}/connectivity/libraries/mbed-coap/source/sn_coap_builder.c
+            ${ARGV0}/connectivity/libraries/mbed-coap/source/sn_coap_header_check.c
+            ${ARGV0}/connectivity/libraries/mbed-coap/source/sn_coap_parser.c
+            ${ARGV0}/connectivity/libraries/mbed-coap/source/sn_coap_protocol.c
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/common_functions.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/ip4string.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/ip6string.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/ip_fsc.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/ns_list.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/ns_nvm_helper.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/ns_types.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/nsdynmemLIB.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/nsdynmem_tracker.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/nsdynmem_tracker_lib.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/platform/arm_hal_interrupt.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/platform/arm_hal_nvm.h
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/source/IPv6_fcf_lib/ip_fsc.c
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/source/libBits/common_functions.c
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/source/libList/ns_list.c
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/source/libip4string/ip4tos.c
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/source/libip4string/stoip4.c
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/source/libip6string/ip6tos.c
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/source/libip6string/stoip6.c
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/source/nsdynmemLIB/nsdynmemLIB.c
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/source/nsdynmemtracker/nsdynmem_tracker_lib.c
+            ${ARGV0}/connectivity/libraries/nanostack-libservice/source/nvmHelper/ns_nvm_helper.c
+            ${ARGV0}/connectivity/libraries/ppp/include/polarssl/arc4.h
+            ${ARGV0}/connectivity/libraries/ppp/include/polarssl/des.h
+            ${ARGV0}/connectivity/libraries/ppp/include/polarssl/md4.h
+            ${ARGV0}/connectivity/libraries/ppp/include/polarssl/md5.h
+            ${ARGV0}/connectivity/libraries/ppp/include/polarssl/sha1.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/ccp.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/chap-md5.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/chap-new.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/chap_ms.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/eap.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/ecp.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/eui64.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/fsm.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/ipcp.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/ipv6cp.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/lcp.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/magic.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/mppe.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/ppp.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/ppp_impl.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/ppp_opts.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/ppp_service.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/ppp_service_if.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/pppapi.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/pppcrypt.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/pppdebug.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/pppoe.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/pppol2tp.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/pppos.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/upap.h
+            ${ARGV0}/connectivity/libraries/ppp/include/ppp/vj.h
+            ${ARGV0}/connectivity/libraries/ppp/source/auth.c
+            ${ARGV0}/connectivity/libraries/ppp/source/ccp.c
+            ${ARGV0}/connectivity/libraries/ppp/source/chap-md5.c
+            ${ARGV0}/connectivity/libraries/ppp/source/chap-new.c
+            ${ARGV0}/connectivity/libraries/ppp/source/chap_ms.c
+            ${ARGV0}/connectivity/libraries/ppp/source/demand.c
+            ${ARGV0}/connectivity/libraries/ppp/source/eap.c
+            ${ARGV0}/connectivity/libraries/ppp/source/eui64.c
+            ${ARGV0}/connectivity/libraries/ppp/source/fsm.c
+            ${ARGV0}/connectivity/libraries/ppp/source/ipcp.c
+            ${ARGV0}/connectivity/libraries/ppp/source/ipv6cp.c
+            ${ARGV0}/connectivity/libraries/ppp/source/lcp.c
+            ${ARGV0}/connectivity/libraries/ppp/source/magic.c
+            ${ARGV0}/connectivity/libraries/ppp/source/mppe.c
+            ${ARGV0}/connectivity/libraries/ppp/source/multilink.c
+            ${ARGV0}/connectivity/libraries/ppp/source/polarssl/ppp_arc4.c
+            ${ARGV0}/connectivity/libraries/ppp/source/polarssl/ppp_des.c
+            ${ARGV0}/connectivity/libraries/ppp/source/polarssl/ppp_md4.c
+            ${ARGV0}/connectivity/libraries/ppp/source/polarssl/ppp_md5.c
+            ${ARGV0}/connectivity/libraries/ppp/source/polarssl/ppp_sha1.c
+            ${ARGV0}/connectivity/libraries/ppp/source/ppp.c
+            ${ARGV0}/connectivity/libraries/ppp/source/ppp_ecp.c
+            ${ARGV0}/connectivity/libraries/ppp/source/ppp_service.cpp
+            ${ARGV0}/connectivity/libraries/ppp/source/ppp_service_if.cpp
+            ${ARGV0}/connectivity/libraries/ppp/source/pppapi.c
+            ${ARGV0}/connectivity/libraries/ppp/source/pppcrypt.c
+            ${ARGV0}/connectivity/libraries/ppp/source/pppoe.c
+            ${ARGV0}/connectivity/libraries/ppp/source/pppol2tp.c
+            ${ARGV0}/connectivity/libraries/ppp/source/pppos.cpp
+            ${ARGV0}/connectivity/libraries/ppp/source/upap.c
+            ${ARGV0}/connectivity/libraries/ppp/source/utils.c
+            ${ARGV0}/connectivity/libraries/ppp/source/vj.c
+            ${ARGV0}/connectivity/lorawan/include/lorawan/LoRaRadio.h
+            ${ARGV0}/connectivity/lorawan/include/lorawan/LoRaWANBase.h
+            ${ARGV0}/connectivity/lorawan/include/lorawan/LoRaWANInterface.h
+            ${ARGV0}/connectivity/lorawan/include/lorawan/LoRaWANStack.h
+            ${ARGV0}/connectivity/lorawan/include/lorawan/lorawan_types.h
+            ${ARGV0}/connectivity/lorawan/lorastack/mac/LoRaMac.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/mac/LoRaMac.h
+            ${ARGV0}/connectivity/lorawan/lorastack/mac/LoRaMacChannelPlan.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/mac/LoRaMacChannelPlan.h
+            ${ARGV0}/connectivity/lorawan/lorastack/mac/LoRaMacCommand.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/mac/LoRaMacCommand.h
+            ${ARGV0}/connectivity/lorawan/lorastack/mac/LoRaMacCrypto.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/mac/LoRaMacCrypto.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHY.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHY.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYAS923.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYAS923.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYAU915.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYAU915.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYCN470.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYCN470.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYCN779.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYCN779.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYEU433.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYEU433.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYEU868.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYEU868.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYIN865.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYIN865.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYKR920.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYKR920.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYUS915.cpp
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/LoRaPHYUS915.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/lora_phy_ds.h
+            ${ARGV0}/connectivity/lorawan/lorastack/phy/loraphy_target.h
+            ${ARGV0}/connectivity/lorawan/source/LoRaWANInterface.cpp
+            ${ARGV0}/connectivity/lorawan/source/LoRaWANStack.cpp
+            ${ARGV0}/connectivity/lorawan/system/LoRaWANTimer.cpp
+            ${ARGV0}/connectivity/lorawan/system/LoRaWANTimer.h
+            ${ARGV0}/connectivity/lorawan/system/lorawan_data_structures.h
+            ${ARGV0}/connectivity/lwipstack/include/lwipstack/LWIPMemoryManager.h
+            ${ARGV0}/connectivity/lwipstack/include/lwipstack/LWIPStack.h
+            ${ARGV0}/connectivity/lwipstack/include/lwipstack/lwip_tools.h
+            ${ARGV0}/connectivity/lwipstack/include/lwipstack/lwipopts.h
+            ${ARGV0}/connectivity/lwipstack/lwip-sys/arch/cc.h
+            ${ARGV0}/connectivity/lwipstack/lwip-sys/arch/lwip_checksum.c
+            ${ARGV0}/connectivity/lwipstack/lwip-sys/arch/lwip_memcpy.c
+            ${ARGV0}/connectivity/lwipstack/lwip-sys/arch/lwip_sys_arch.c
+            ${ARGV0}/connectivity/lwipstack/lwip-sys/arch/perf.h
+            ${ARGV0}/connectivity/lwipstack/lwip-sys/arch/sys_arch.h
+            ${ARGV0}/connectivity/lwipstack/lwip-sys/lwip_random.c
+            ${ARGV0}/connectivity/lwipstack/lwip-sys/lwip_random.h
+            ${ARGV0}/connectivity/lwipstack/lwip-sys/lwip_tcp_isn.c
+            ${ARGV0}/connectivity/lwipstack/lwip-sys/lwip_tcp_isn.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/api/lwip_api_lib.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/api/lwip_api_msg.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/api/lwip_err.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/api/lwip_if_api.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/api/lwip_netbuf.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/api/lwip_netdb.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/api/lwip_netifapi.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/api/lwip_sockets.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/api/lwip_tcpip.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv4/lwip_autoip.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv4/lwip_dhcp.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv4/lwip_etharp.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv4/lwip_icmp.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv4/lwip_igmp.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv4/lwip_ip4.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv4/lwip_ip4_addr.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv4/lwip_ip4_frag.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv6/lwip_dhcp6.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv6/lwip_ethip6.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv6/lwip_icmp6.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv6/lwip_inet6.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv6/lwip_ip6.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv6/lwip_ip6_addr.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv6/lwip_ip6_frag.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv6/lwip_mld6.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/ipv6/lwip_nd6.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_altcp.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_altcp_alloc.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_altcp_tcp.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_def.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_dns.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_inet_chksum.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_init.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_ip.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_mem.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_memp.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_netif.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_pbuf.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_raw.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_stats.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_sys.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_tcp.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_tcp_in.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_tcp_out.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_timeouts.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/core/lwip_udp.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/compat/posix/arpa/inet.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/compat/posix/net/if.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/compat/posix/netdb.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/compat/posix/sys/socket.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/altcp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/altcp_tcp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/altcp_tls.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/api.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/arch.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/autoip.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/debug.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/def.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/dhcp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/dhcp6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/dns.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/err.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/etharp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/ethip6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/icmp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/icmp6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/if_api.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/igmp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/inet.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/inet_chksum.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/init.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/ip.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/ip4.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/ip4_addr.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/ip4_frag.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/ip6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/ip6_addr.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/ip6_frag.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/ip6_zone.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/ip_addr.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/lwip_errno.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/mem.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/memp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/mld6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/nd6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/netbuf.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/netdb.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/netif.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/netifapi.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/opt.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/pbuf.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/priv/altcp_priv.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/priv/api_msg.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/priv/mem_priv.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/priv/memp_priv.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/priv/memp_std.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/priv/nd6_priv.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/priv/raw_priv.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/priv/sockets_priv.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/priv/tcp_priv.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/priv/tcpip_priv.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/autoip.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/dhcp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/dhcp6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/dns.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/etharp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/ethernet.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/iana.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/icmp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/icmp6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/ieee.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/igmp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/ip.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/ip4.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/ip6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/mld6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/nd6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/tcp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/prot/udp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/raw.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/sio.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/snmp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/sockets.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/stats.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/sys.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/tcp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/tcpbase.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/tcpip.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/timeouts.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/lwip/udp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/bridgeif.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/bridgeif_opts.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/etharp.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/ethernet.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/ieee802154.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/lowpan6.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/lowpan6_ble.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/lowpan6_common.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/lowpan6_opts.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/slipif.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/include/netif/zepif.h
+            ${ARGV0}/connectivity/lwipstack/lwip/src/netif/lwip_bridgeif.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/netif/lwip_bridgeif_fdb.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/netif/lwip_ethernet.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/netif/lwip_lowpan6.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/netif/lwip_lowpan6_ble.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/netif/lwip_lowpan6_common.c
+            ${ARGV0}/connectivity/lwipstack/lwip/src/netif/lwip_zepif.c
+            ${ARGV0}/connectivity/lwipstack/source/LWIPInterface.cpp
+            ${ARGV0}/connectivity/lwipstack/source/LWIPInterfaceEMAC.cpp
+            ${ARGV0}/connectivity/lwipstack/source/LWIPInterfaceL3IP.cpp
+            ${ARGV0}/connectivity/lwipstack/source/LWIPInterfacePPP.cpp
+            ${ARGV0}/connectivity/lwipstack/source/LWIPMemoryManager.cpp
+            ${ARGV0}/connectivity/lwipstack/source/LWIPStack.cpp
+            ${ARGV0}/connectivity/lwipstack/source/lwip_tools.cpp
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/aes.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/aesni.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/arc4.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/aria.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/asn1.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/asn1write.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/base64.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/bignum.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/blowfish.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/bn_mul.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/camellia.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ccm.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/certs.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/chacha20.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/chachapoly.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/check_config.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/cipher.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/cipher_internal.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/cmac.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/common.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/compat-1.3.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/config-no-entropy.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/config.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/config_psa.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ctr_drbg.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/debug.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/des.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/dhm.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ecdh.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ecdsa.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ecjpake.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ecp.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ecp_internal.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/entropy.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/entropy_poll.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/error.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/gcm.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/havege.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/hkdf.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/hmac_drbg.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/md.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/md2.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/md4.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/md5.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/md_internal.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/memory_buffer_alloc.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/net.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/net_sockets.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/nist_kw.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/oid.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/padlock.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/pem.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/pk.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/pk_internal.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/pkcs11.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/pkcs12.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/pkcs5.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/platform.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/platform_time.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/platform_util.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/poly1305.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/psa_util.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ripemd160.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/rsa.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/rsa_internal.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/sha1.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/sha256.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/sha512.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ssl.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ssl_cache.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ssl_ciphersuites.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ssl_cookie.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ssl_internal.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/ssl_ticket.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/threading.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/timing.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/version.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/x509.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/x509_crl.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/x509_crt.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/x509_csr.h
+            ${ARGV0}/connectivity/mbedtls/include/mbedtls/xtea.h
+            ${ARGV0}/connectivity/mbedtls/platform/inc/platform_alt.h
+            ${ARGV0}/connectivity/mbedtls/platform/inc/platform_mbed.h
+            ${ARGV0}/connectivity/mbedtls/platform/inc/shared_rng.h
+            ${ARGV0}/connectivity/mbedtls/platform/inc/timing_alt.h
+            ${ARGV0}/connectivity/mbedtls/platform/src/hash_wrappers.c
+            ${ARGV0}/connectivity/mbedtls/platform/src/mbed_trng.cpp
+            ${ARGV0}/connectivity/mbedtls/platform/src/platform_alt.cpp
+            ${ARGV0}/connectivity/mbedtls/platform/src/shared_rng.cpp
+            ${ARGV0}/connectivity/mbedtls/platform/src/timing_mbed.cpp
+            ${ARGV0}/connectivity/mbedtls/source/aes.c
+            ${ARGV0}/connectivity/mbedtls/source/aesni.c
+            ${ARGV0}/connectivity/mbedtls/source/arc4.c
+            ${ARGV0}/connectivity/mbedtls/source/aria.c
+            ${ARGV0}/connectivity/mbedtls/source/asn1parse.c
+            ${ARGV0}/connectivity/mbedtls/source/asn1write.c
+            ${ARGV0}/connectivity/mbedtls/source/base64.c
+            ${ARGV0}/connectivity/mbedtls/source/bignum.c
+            ${ARGV0}/connectivity/mbedtls/source/blowfish.c
+            ${ARGV0}/connectivity/mbedtls/source/camellia.c
+            ${ARGV0}/connectivity/mbedtls/source/ccm.c
+            ${ARGV0}/connectivity/mbedtls/source/certs.c
+            ${ARGV0}/connectivity/mbedtls/source/chacha20.c
+            ${ARGV0}/connectivity/mbedtls/source/chachapoly.c
+            ${ARGV0}/connectivity/mbedtls/source/check_crypto_config.h
+            ${ARGV0}/connectivity/mbedtls/source/cipher.c
+            ${ARGV0}/connectivity/mbedtls/source/cipher_wrap.c
+            ${ARGV0}/connectivity/mbedtls/source/cmac.c
+            ${ARGV0}/connectivity/mbedtls/source/ctr_drbg.c
+            ${ARGV0}/connectivity/mbedtls/source/debug.c
+            ${ARGV0}/connectivity/mbedtls/source/des.c
+            ${ARGV0}/connectivity/mbedtls/source/dhm.c
+            ${ARGV0}/connectivity/mbedtls/source/ecdh.c
+            ${ARGV0}/connectivity/mbedtls/source/ecdsa.c
+            ${ARGV0}/connectivity/mbedtls/source/ecjpake.c
+            ${ARGV0}/connectivity/mbedtls/source/ecp.c
+            ${ARGV0}/connectivity/mbedtls/source/ecp_curves.c
+            ${ARGV0}/connectivity/mbedtls/source/entropy.c
+            ${ARGV0}/connectivity/mbedtls/source/entropy_poll.c
+            ${ARGV0}/connectivity/mbedtls/source/error.c
+            ${ARGV0}/connectivity/mbedtls/source/gcm.c
+            ${ARGV0}/connectivity/mbedtls/source/havege.c
+            ${ARGV0}/connectivity/mbedtls/source/hkdf.c
+            ${ARGV0}/connectivity/mbedtls/source/hmac_drbg.c
+            ${ARGV0}/connectivity/mbedtls/source/md.c
+            ${ARGV0}/connectivity/mbedtls/source/md2.c
+            ${ARGV0}/connectivity/mbedtls/source/md4.c
+            ${ARGV0}/connectivity/mbedtls/source/md5.c
+            ${ARGV0}/connectivity/mbedtls/source/memory_buffer_alloc.c
+            ${ARGV0}/connectivity/mbedtls/source/net_sockets.c
+            ${ARGV0}/connectivity/mbedtls/source/nist_kw.c
+            ${ARGV0}/connectivity/mbedtls/source/oid.c
+            ${ARGV0}/connectivity/mbedtls/source/padlock.c
+            ${ARGV0}/connectivity/mbedtls/source/pem.c
+            ${ARGV0}/connectivity/mbedtls/source/pk.c
+            ${ARGV0}/connectivity/mbedtls/source/pk_wrap.c
+            ${ARGV0}/connectivity/mbedtls/source/pkcs11.c
+            ${ARGV0}/connectivity/mbedtls/source/pkcs12.c
+            ${ARGV0}/connectivity/mbedtls/source/pkcs5.c
+            ${ARGV0}/connectivity/mbedtls/source/pkparse.c
+            ${ARGV0}/connectivity/mbedtls/source/pkwrite.c
+            ${ARGV0}/connectivity/mbedtls/source/platform.c
+            ${ARGV0}/connectivity/mbedtls/source/platform_util.c
+            ${ARGV0}/connectivity/mbedtls/source/poly1305.c
+            ${ARGV0}/connectivity/mbedtls/source/ripemd160.c
+            ${ARGV0}/connectivity/mbedtls/source/rsa.c
+            ${ARGV0}/connectivity/mbedtls/source/rsa_internal.c
+            ${ARGV0}/connectivity/mbedtls/source/sha1.c
+            ${ARGV0}/connectivity/mbedtls/source/sha256.c
+            ${ARGV0}/connectivity/mbedtls/source/sha512.c
+            ${ARGV0}/connectivity/mbedtls/source/ssl_cache.c
+            ${ARGV0}/connectivity/mbedtls/source/ssl_ciphersuites.c
+            ${ARGV0}/connectivity/mbedtls/source/ssl_cli.c
+            ${ARGV0}/connectivity/mbedtls/source/ssl_cookie.c
+            ${ARGV0}/connectivity/mbedtls/source/ssl_invasive.h
+            ${ARGV0}/connectivity/mbedtls/source/ssl_msg.c
+            ${ARGV0}/connectivity/mbedtls/source/ssl_srv.c
+            ${ARGV0}/connectivity/mbedtls/source/ssl_ticket.c
+            ${ARGV0}/connectivity/mbedtls/source/ssl_tls.c
+            ${ARGV0}/connectivity/mbedtls/source/ssl_tls13_keys.c
+            ${ARGV0}/connectivity/mbedtls/source/ssl_tls13_keys.h
+            ${ARGV0}/connectivity/mbedtls/source/threading.c
+            ${ARGV0}/connectivity/mbedtls/source/timing.c
+            ${ARGV0}/connectivity/mbedtls/source/version.c
+            ${ARGV0}/connectivity/mbedtls/source/version_features.c
+            ${ARGV0}/connectivity/mbedtls/source/x509.c
+            ${ARGV0}/connectivity/mbedtls/source/x509_create.c
+            ${ARGV0}/connectivity/mbedtls/source/x509_crl.c
+            ${ARGV0}/connectivity/mbedtls/source/x509_crt.c
+            ${ARGV0}/connectivity/mbedtls/source/x509_csr.c
+            ${ARGV0}/connectivity/mbedtls/source/x509write_crt.c
+            ${ARGV0}/connectivity/mbedtls/source/x509write_csr.c
+            ${ARGV0}/connectivity/mbedtls/source/xtea.c
+            ${ARGV0}/connectivity/nanostack/coap-service/coap-service/coap_service_api.h
+            ${ARGV0}/connectivity/nanostack/coap-service/source/coap_connection_handler.c
+            ${ARGV0}/connectivity/nanostack/coap-service/source/coap_message_handler.c
+            ${ARGV0}/connectivity/nanostack/coap-service/source/coap_security_handler.c
+            ${ARGV0}/connectivity/nanostack/coap-service/source/coap_service_api.c
+            ${ARGV0}/connectivity/nanostack/coap-service/source/include/coap_connection_handler.h
+            ${ARGV0}/connectivity/nanostack/coap-service/source/include/coap_message_handler.h
+            ${ARGV0}/connectivity/nanostack/coap-service/source/include/coap_security_handler.h
+            ${ARGV0}/connectivity/nanostack/coap-service/source/include/coap_service_api_internal.h
+            ${ARGV0}/connectivity/nanostack/include/nanostack-interface/Nanostack.h
+            ${ARGV0}/connectivity/nanostack/include/nanostack-interface/NanostackEthernetPhy.h
+            ${ARGV0}/connectivity/nanostack/include/nanostack-interface/NanostackInterface.h
+            ${ARGV0}/connectivity/nanostack/include/nanostack-interface/NanostackLockGuard.h
+            ${ARGV0}/connectivity/nanostack/include/nanostack-interface/NanostackMACPhy.h
+            ${ARGV0}/connectivity/nanostack/include/nanostack-interface/NanostackPPPPhy.h
+            ${ARGV0}/connectivity/nanostack/include/nanostack-interface/NanostackPhy.h
+            ${ARGV0}/connectivity/nanostack/include/nanostack-interface/NanostackRfPhy.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/LoWPANNDInterface.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/MeshInterfaceNanostack.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/NanostackEthernetInterface.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/NanostackPPPInterface.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/ThreadInterface.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/WisunBorderRouter.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/WisunInterface.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api/mesh_interface_types.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/CallbackHandler.cpp
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/LoWPANNDInterface.cpp
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/MeshInterfaceNanostack.cpp
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/NanostackEMACInterface.cpp
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/NanostackEthernetInterface.cpp
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/NanostackMemoryManager.cpp
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/NanostackPPPInterface.cpp
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/ThreadInterface.cpp
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/WisunBorderRouter.cpp
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/WisunInterface.cpp
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/ethernet_tasklet.c
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/include/NanostackMemoryManager.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/include/callback_handler.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/include/enet_tasklet.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/include/mesh_system.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/include/nd_tasklet.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/include/thread_tasklet.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/include/wisun_tasklet.h
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/mesh_system.c
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/nd_tasklet.c
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/thread_tasklet.c
+            ${ARGV0}/connectivity/nanostack/mbed-mesh-api/source/wisun_tasklet.c
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_fhss_timer.cpp
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_interrupt.c
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_interrupt_private.h
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_random.c
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/arm_hal_timer.cpp
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/ns_event_loop.c
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/ns_event_loop.h
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/ns_event_loop_mbed.cpp
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/ns_event_loop_mutex.c
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/ns_event_loop_mutex.h
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/ns_file_system_api.cpp
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/ns_file_system_api.h
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/ns_hal_init.c
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/ns_hal_init.h
+            ${ARGV0}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos/nvm/nvm_ram.c
+            ${ARGV0}/connectivity/nanostack/source/Nanostack.cpp
+            ${ARGV0}/connectivity/netsocket/include/netsocket/CellularInterface.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/CellularNonIPSocket.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/ControlPlane_netif.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/DNS.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/DTLSSocket.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/DTLSSocketWrapper.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/EMAC.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/EMACInterface.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/EMACMemoryManager.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/EthInterface.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/EthernetInterface.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/ICMPSocket.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/InternetDatagramSocket.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/InternetSocket.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/L3IP.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/L3IPInterface.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/MeshInterface.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/MsgHeader.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/NetStackMemoryManager.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/NetworkInterface.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/NetworkStack.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/OnboardNetworkStack.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/PPP.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/PPPInterface.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/Socket.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/SocketAddress.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/SocketStats.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/TCPSocket.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/TLSSocket.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/UDPSocket.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/WiFiAccessPoint.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/WiFiInterface.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/nsapi.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/nsapi_dns.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/nsapi_ppp.h
+            ${ARGV0}/connectivity/netsocket/include/netsocket/nsapi_types.h
+            ${ARGV0}/connectivity/netsocket/source/CellularNonIPSocket.cpp
+            ${ARGV0}/connectivity/netsocket/source/DTLSSocket.cpp
+            ${ARGV0}/connectivity/netsocket/source/DTLSSocketWrapper.cpp
+            ${ARGV0}/connectivity/netsocket/source/EMACInterface.cpp
+            ${ARGV0}/connectivity/netsocket/source/EthernetInterface.cpp
+            ${ARGV0}/connectivity/netsocket/source/ICMPSocket.cpp
+            ${ARGV0}/connectivity/netsocket/source/InternetDatagramSocket.cpp
+            ${ARGV0}/connectivity/netsocket/source/InternetSocket.cpp
+            ${ARGV0}/connectivity/netsocket/source/L3IPInterface.cpp
+            ${ARGV0}/connectivity/netsocket/source/NetStackMemoryManager.cpp
+            ${ARGV0}/connectivity/netsocket/source/NetworkInterface.cpp
+            ${ARGV0}/connectivity/netsocket/source/NetworkInterfaceDefaults.cpp
+            ${ARGV0}/connectivity/netsocket/source/NetworkStack.cpp
+            ${ARGV0}/connectivity/netsocket/source/PPPInterface.cpp
+            ${ARGV0}/connectivity/netsocket/source/SocketAddress.cpp
+            ${ARGV0}/connectivity/netsocket/source/SocketStats.cpp
+            ${ARGV0}/connectivity/netsocket/source/TCPSocket.cpp
+            ${ARGV0}/connectivity/netsocket/source/TLSSocket.cpp
+            ${ARGV0}/connectivity/netsocket/source/TLSSocketWrapper.cpp
+            ${ARGV0}/connectivity/netsocket/source/UDPSocket.cpp
+            ${ARGV0}/connectivity/netsocket/source/WiFiAccessPoint.cpp
+            ${ARGV0}/connectivity/netsocket/source/nsapi_dns.cpp
+            ${ARGV0}/connectivity/netsocket/source/nsapi_ppp.cpp
+            ${ARGV0}/connectivity/nfc/include/nfc/NFC.h
+            ${ARGV0}/connectivity/nfc/include/nfc/NFCController.h
+            ${ARGV0}/connectivity/nfc/include/nfc/NFCControllerDriver.h
+            ${ARGV0}/connectivity/nfc/include/nfc/NFCDefinitions.h
+            ${ARGV0}/connectivity/nfc/include/nfc/NFCEEPROM.h
+            ${ARGV0}/connectivity/nfc/include/nfc/NFCEEPROMDriver.h
+            ${ARGV0}/connectivity/nfc/include/nfc/NFCNDEFCapable.h
+            ${ARGV0}/connectivity/nfc/include/nfc/NFCRemoteEndpoint.h
+            ${ARGV0}/connectivity/nfc/include/nfc/NFCRemoteInitiator.h
+            ${ARGV0}/connectivity/nfc/include/nfc/NFCTarget.h
+            ${ARGV0}/connectivity/nfc/include/nfc/Type4RemoteInitiator.h
+            ${ARGV0}/connectivity/nfc/include/nfc/ndef/MessageBuilder.h
+            ${ARGV0}/connectivity/nfc/include/nfc/ndef/MessageParser.h
+            ${ARGV0}/connectivity/nfc/include/nfc/ndef/Record.h
+            ${ARGV0}/connectivity/nfc/include/nfc/ndef/RecordParser.h
+            ${ARGV0}/connectivity/nfc/include/nfc/ndef/common/Mime.h
+            ${ARGV0}/connectivity/nfc/include/nfc/ndef/common/SimpleMessageParser.h
+            ${ARGV0}/connectivity/nfc/include/nfc/ndef/common/Text.h
+            ${ARGV0}/connectivity/nfc/include/nfc/ndef/common/URI.h
+            ${ARGV0}/connectivity/nfc/include/nfc/ndef/common/util.h
+            ${ARGV0}/connectivity/nfc/libraries/acore/acore/ac_buffer.h
+            ${ARGV0}/connectivity/nfc/libraries/acore/acore/ac_buffer_builder.h
+            ${ARGV0}/connectivity/nfc/libraries/acore/acore/ac_buffer_reader.h
+            ${ARGV0}/connectivity/nfc/libraries/acore/acore/ac_debug.h
+            ${ARGV0}/connectivity/nfc/libraries/acore/acore/ac_macros.h
+            ${ARGV0}/connectivity/nfc/libraries/acore/acore/ac_stream.h
+            ${ARGV0}/connectivity/nfc/libraries/acore/source/ac_buffer.c
+            ${ARGV0}/connectivity/nfc/libraries/acore/source/ac_buffer_builder.c
+            ${ARGV0}/connectivity/nfc/libraries/acore/source/ac_buffer_reader.c
+            ${ARGV0}/connectivity/nfc/libraries/acore/source/ac_stream.c
+            ${ARGV0}/connectivity/nfc/libraries/stack/ndef/ndef.c
+            ${ARGV0}/connectivity/nfc/libraries/stack/ndef/ndef.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/nfc_common.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/nfc_errors.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/platform/nfc_debug.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/platform/nfc_scheduler.c
+            ${ARGV0}/connectivity/nfc/libraries/stack/platform/nfc_scheduler.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/platform/nfc_transport.c
+            ${ARGV0}/connectivity/nfc/libraries/stack/platform/nfc_transport.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/tech/iso7816/iso7816.c
+            ${ARGV0}/connectivity/nfc/libraries/stack/tech/iso7816/iso7816.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_app.c
+            ${ARGV0}/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_app.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/tech/iso7816/iso7816_defs.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/tech/isodep/isodep.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/tech/isodep/isodep_target.c
+            ${ARGV0}/connectivity/nfc/libraries/stack/tech/isodep/isodep_target.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/tech/type4/type4_target.c
+            ${ARGV0}/connectivity/nfc/libraries/stack/tech/type4/type4_target.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/transceiver/protocols.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/transceiver/transceiver.c
+            ${ARGV0}/connectivity/nfc/libraries/stack/transceiver/transceiver.h
+            ${ARGV0}/connectivity/nfc/libraries/stack/transceiver/transceiver_internal.h
+            ${ARGV0}/connectivity/nfc/source/NFCController.cpp
+            ${ARGV0}/connectivity/nfc/source/NFCControllerDriver.cpp
+            ${ARGV0}/connectivity/nfc/source/NFCEEPROM.cpp
+            ${ARGV0}/connectivity/nfc/source/NFCEEPROMDriver.cpp
+            ${ARGV0}/connectivity/nfc/source/NFCNDEFCapable.cpp
+            ${ARGV0}/connectivity/nfc/source/NFCRemoteEndpoint.cpp
+            ${ARGV0}/connectivity/nfc/source/NFCRemoteInitiator.cpp
+            ${ARGV0}/connectivity/nfc/source/NFCTarget.cpp
+            ${ARGV0}/connectivity/nfc/source/Type4RemoteInitiator.cpp
+            ${ARGV0}/connectivity/nfc/source/ndef/MessageBuilder.cpp
+            ${ARGV0}/connectivity/nfc/source/ndef/MessageParser.cpp
+            ${ARGV0}/connectivity/nfc/source/ndef/RecordParser.cpp
+            ${ARGV0}/connectivity/nfc/source/ndef/common/Mime.cpp
+            ${ARGV0}/connectivity/nfc/source/ndef/common/SimpleMessageParser.cpp
+            ${ARGV0}/connectivity/nfc/source/ndef/common/Text.cpp
+            ${ARGV0}/connectivity/nfc/source/ndef/common/URI.cpp
+            ${ARGV0}/connectivity/nfc/source/ndef/common/util.cpp
+            ${ARGV0}/drivers/device_key/include/device_key/DeviceKey.h
+            ${ARGV0}/drivers/device_key/source/DeviceKey.cpp
+            ${ARGV0}/drivers/include/drivers/AnalogIn.h
+            ${ARGV0}/drivers/include/drivers/AnalogOut.h
+            ${ARGV0}/drivers/include/drivers/BufferedSerial.h
+            ${ARGV0}/drivers/include/drivers/BusIn.h
+            ${ARGV0}/drivers/include/drivers/BusInOut.h
+            ${ARGV0}/drivers/include/drivers/BusOut.h
+            ${ARGV0}/drivers/include/drivers/CAN.h
+            ${ARGV0}/drivers/include/drivers/DigitalIn.h
+            ${ARGV0}/drivers/include/drivers/DigitalInOut.h
+            ${ARGV0}/drivers/include/drivers/DigitalOut.h
+            ${ARGV0}/drivers/include/drivers/FlashIAP.h
+            ${ARGV0}/drivers/include/drivers/HighResClock.h
+            ${ARGV0}/drivers/include/drivers/I2C.h
+            ${ARGV0}/drivers/include/drivers/I2CSlave.h
+            ${ARGV0}/drivers/include/drivers/InterruptIn.h
+            ${ARGV0}/drivers/include/drivers/LowPowerClock.h
+            ${ARGV0}/drivers/include/drivers/LowPowerTicker.h
+            ${ARGV0}/drivers/include/drivers/LowPowerTimeout.h
+            ${ARGV0}/drivers/include/drivers/LowPowerTimer.h
+            ${ARGV0}/drivers/include/drivers/MbedCRC.h
+            ${ARGV0}/drivers/include/drivers/OSPI.h
+            ${ARGV0}/drivers/include/drivers/PortIn.h
+            ${ARGV0}/drivers/include/drivers/PortInOut.h
+            ${ARGV0}/drivers/include/drivers/PortOut.h
+            ${ARGV0}/drivers/include/drivers/PwmOut.h
+            ${ARGV0}/drivers/include/drivers/QSPI.h
+            ${ARGV0}/drivers/include/drivers/RawCAN.h
+            ${ARGV0}/drivers/include/drivers/RealTimeClock.h
+            ${ARGV0}/drivers/include/drivers/ResetReason.h
+            ${ARGV0}/drivers/include/drivers/SPI.h
+            ${ARGV0}/drivers/include/drivers/SPISlave.h
+            ${ARGV0}/drivers/include/drivers/SerialBase.h
+            ${ARGV0}/drivers/include/drivers/SerialWireOutput.h
+            ${ARGV0}/drivers/include/drivers/Ticker.h
+            ${ARGV0}/drivers/include/drivers/TickerDataClock.h
+            ${ARGV0}/drivers/include/drivers/Timeout.h
+            ${ARGV0}/drivers/include/drivers/Timer.h
+            ${ARGV0}/drivers/include/drivers/TimerEvent.h
+            ${ARGV0}/drivers/include/drivers/UnbufferedSerial.h
+            ${ARGV0}/drivers/include/drivers/Watchdog.h
+            ${ARGV0}/drivers/include/drivers/interfaces/InterfaceCAN.h
+            ${ARGV0}/drivers/include/drivers/interfaces/InterfaceDigitalIn.h
+            ${ARGV0}/drivers/include/drivers/interfaces/InterfaceDigitalInOut.h
+            ${ARGV0}/drivers/include/drivers/interfaces/InterfaceDigitalOut.h
+            ${ARGV0}/drivers/source/AnalogIn.cpp
+            ${ARGV0}/drivers/source/AnalogOut.cpp
+            ${ARGV0}/drivers/source/BufferedSerial.cpp
+            ${ARGV0}/drivers/source/BusIn.cpp
+            ${ARGV0}/drivers/source/BusInOut.cpp
+            ${ARGV0}/drivers/source/BusOut.cpp
+            ${ARGV0}/drivers/source/CAN.cpp
+            ${ARGV0}/drivers/source/DigitalIn.cpp
+            ${ARGV0}/drivers/source/DigitalInOut.cpp
+            ${ARGV0}/drivers/source/DigitalOut.cpp
+            ${ARGV0}/drivers/source/FlashIAP.cpp
+            ${ARGV0}/drivers/source/I2C.cpp
+            ${ARGV0}/drivers/source/I2CSlave.cpp
+            ${ARGV0}/drivers/source/InterruptIn.cpp
+            ${ARGV0}/drivers/source/MbedCRC.cpp
+            ${ARGV0}/drivers/source/OSPI.cpp
+            ${ARGV0}/drivers/source/PortIn.cpp
+            ${ARGV0}/drivers/source/PortInOut.cpp
+            ${ARGV0}/drivers/source/PortOut.cpp
+            ${ARGV0}/drivers/source/PwmOut.cpp
+            ${ARGV0}/drivers/source/QSPI.cpp
+            ${ARGV0}/drivers/source/ResetReason.cpp
+            ${ARGV0}/drivers/source/SPI.cpp
+            ${ARGV0}/drivers/source/SPISlave.cpp
+            ${ARGV0}/drivers/source/SerialBase.cpp
+            ${ARGV0}/drivers/source/SerialWireOutput.cpp
+            ${ARGV0}/drivers/source/Ticker.cpp
+            ${ARGV0}/drivers/source/Timeout.cpp
+            ${ARGV0}/drivers/source/Timer.cpp
+            ${ARGV0}/drivers/source/TimerEvent.cpp
+            ${ARGV0}/drivers/source/UnbufferedSerial.cpp
+            ${ARGV0}/drivers/source/Watchdog.cpp
+            ${ARGV0}/drivers/usb/include/usb/USBAudio.h
+            ${ARGV0}/drivers/usb/include/usb/USBCDC.h
+            ${ARGV0}/drivers/usb/include/usb/USBCDC_ECM.h
+            ${ARGV0}/drivers/usb/include/usb/USBHID.h
+            ${ARGV0}/drivers/usb/include/usb/USBKeyboard.h
+            ${ARGV0}/drivers/usb/include/usb/USBMIDI.h
+            ${ARGV0}/drivers/usb/include/usb/USBMSD.h
+            ${ARGV0}/drivers/usb/include/usb/USBMouse.h
+            ${ARGV0}/drivers/usb/include/usb/USBMouseKeyboard.h
+            ${ARGV0}/drivers/usb/include/usb/USBSerial.h
+            ${ARGV0}/drivers/usb/include/usb/internal/AsyncOp.h
+            ${ARGV0}/drivers/usb/include/usb/internal/ByteBuffer.h
+            ${ARGV0}/drivers/usb/include/usb/internal/EndpointResolver.h
+            ${ARGV0}/drivers/usb/include/usb/internal/LinkEntry.h
+            ${ARGV0}/drivers/usb/include/usb/internal/LinkedList.h
+            ${ARGV0}/drivers/usb/include/usb/internal/LinkedListBase.h
+            ${ARGV0}/drivers/usb/include/usb/internal/MIDIMessage.h
+            ${ARGV0}/drivers/usb/include/usb/internal/OperationList.h
+            ${ARGV0}/drivers/usb/include/usb/internal/OperationListBase.h
+            ${ARGV0}/drivers/usb/include/usb/internal/PolledQueue.h
+            ${ARGV0}/drivers/usb/include/usb/internal/Task.h
+            ${ARGV0}/drivers/usb/include/usb/internal/TaskBase.h
+            ${ARGV0}/drivers/usb/include/usb/internal/TaskQueue.h
+            ${ARGV0}/drivers/usb/include/usb/internal/USBAudio_Types.h
+            ${ARGV0}/drivers/usb/include/usb/internal/USBDescriptor.h
+            ${ARGV0}/drivers/usb/include/usb/internal/USBDevice.h
+            ${ARGV0}/drivers/usb/include/usb/internal/USBDevice_Types.h
+            ${ARGV0}/drivers/usb/include/usb/internal/USBHID_Types.h
+            ${ARGV0}/drivers/usb/source/AsyncOp.cpp
+            ${ARGV0}/drivers/usb/source/ByteBuffer.cpp
+            ${ARGV0}/drivers/usb/source/EndpointResolver.cpp
+            ${ARGV0}/drivers/usb/source/LinkedListBase.cpp
+            ${ARGV0}/drivers/usb/source/OperationListBase.cpp
+            ${ARGV0}/drivers/usb/source/PolledQueue.cpp
+            ${ARGV0}/drivers/usb/source/TaskBase.cpp
+            ${ARGV0}/drivers/usb/source/USBAudio.cpp
+            ${ARGV0}/drivers/usb/source/USBCDC.cpp
+            ${ARGV0}/drivers/usb/source/USBCDC_ECM.cpp
+            ${ARGV0}/drivers/usb/source/USBDevice.cpp
+            ${ARGV0}/drivers/usb/source/USBHID.cpp
+            ${ARGV0}/drivers/usb/source/USBKeyboard.cpp
+            ${ARGV0}/drivers/usb/source/USBMIDI.cpp
+            ${ARGV0}/drivers/usb/source/USBMSD.cpp
+            ${ARGV0}/drivers/usb/source/USBMouse.cpp
+            ${ARGV0}/drivers/usb/source/USBMouseKeyboard.cpp
+            ${ARGV0}/drivers/usb/source/USBSerial.cpp
+            ${ARGV0}/events/include/events/Event.h
+            ${ARGV0}/events/include/events/EventQueue.h
+            ${ARGV0}/events/include/events/UserAllocatedEvent.h
+            ${ARGV0}/events/include/events/equeue.h
+            ${ARGV0}/events/include/events/internal/equeue_platform.h
+            ${ARGV0}/events/include/events/mbed_events.h
+            ${ARGV0}/events/include/events/mbed_shared_queues.h
+            ${ARGV0}/events/source/EventQueue.cpp
+            ${ARGV0}/events/source/equeue.c
+            ${ARGV0}/events/source/equeue_mbed.cpp
+            ${ARGV0}/events/source/equeue_posix.c
+            ${ARGV0}/events/source/mbed_shared_queues.cpp
+            ${ARGV0}/features/frameworks/greentea-client/greentea-client/greentea_metrics.h
+            ${ARGV0}/features/frameworks/greentea-client/greentea-client/test_env.h
+            ${ARGV0}/features/frameworks/greentea-client/source/greentea_metrics.cpp
+            ${ARGV0}/features/frameworks/greentea-client/source/greentea_test_env.cpp
+            ${ARGV0}/features/frameworks/mbed-client-cli/mbed-client-cli/ns_cmdline.h
+            ${ARGV0}/features/frameworks/mbed-client-cli/source/ns_cmdline.c
+            ${ARGV0}/features/frameworks/mbed-greentea-io/mbed_io.cpp
+            ${ARGV0}/features/frameworks/unity/source/unity.c
+            ${ARGV0}/features/frameworks/unity/unity/unity.h
+            ${ARGV0}/features/frameworks/unity/unity/unity_config.h
+            ${ARGV0}/features/frameworks/unity/unity/unity_internals.h
+            ${ARGV0}/features/frameworks/utest/mbed-utest-shim.cpp
+            ${ARGV0}/features/frameworks/utest/source/unity_handler.cpp
+            ${ARGV0}/features/frameworks/utest/source/utest_case.cpp
+            ${ARGV0}/features/frameworks/utest/source/utest_default_handlers.cpp
+            ${ARGV0}/features/frameworks/utest/source/utest_greentea_handlers.cpp
+            ${ARGV0}/features/frameworks/utest/source/utest_harness.cpp
+            ${ARGV0}/features/frameworks/utest/source/utest_print.cpp
+            ${ARGV0}/features/frameworks/utest/source/utest_shim.cpp
+            ${ARGV0}/features/frameworks/utest/source/utest_stack_trace.cpp
+            ${ARGV0}/features/frameworks/utest/source/utest_types.cpp
+            ${ARGV0}/features/frameworks/utest/utest/unity_handler.h
+            ${ARGV0}/features/frameworks/utest/utest/utest.h
+            ${ARGV0}/features/frameworks/utest/utest/utest_case.h
+            ${ARGV0}/features/frameworks/utest/utest/utest_default_handlers.h
+            ${ARGV0}/features/frameworks/utest/utest/utest_harness.h
+            ${ARGV0}/features/frameworks/utest/utest/utest_print.h
+            ${ARGV0}/features/frameworks/utest/utest/utest_scheduler.h
+            ${ARGV0}/features/frameworks/utest/utest/utest_shim.h
+            ${ARGV0}/features/frameworks/utest/utest/utest_specification.h
+            ${ARGV0}/features/frameworks/utest/utest/utest_stack_trace.h
+            ${ARGV0}/features/frameworks/utest/utest/utest_types.h
+            ${ARGV0}/hal/include/hal/LowPowerTickerWrapper.h
+            ${ARGV0}/hal/include/hal/PinNameAliases.h
+            ${ARGV0}/hal/include/hal/analogin_api.h
+            ${ARGV0}/hal/include/hal/analogout_api.h
+            ${ARGV0}/hal/include/hal/buffer.h
+            ${ARGV0}/hal/include/hal/can_api.h
+            ${ARGV0}/hal/include/hal/can_helper.h
+            ${ARGV0}/hal/include/hal/crc_api.h
+            ${ARGV0}/hal/include/hal/critical_section_api.h
+            ${ARGV0}/hal/include/hal/dma_api.h
+            ${ARGV0}/hal/include/hal/flash_api.h
+            ${ARGV0}/hal/include/hal/gpio_api.h
+            ${ARGV0}/hal/include/hal/gpio_irq_api.h
+            ${ARGV0}/hal/include/hal/i2c_api.h
+            ${ARGV0}/hal/include/hal/itm_api.h
+            ${ARGV0}/hal/include/hal/lp_ticker_api.h
+            ${ARGV0}/hal/include/hal/mbed_lp_ticker_wrapper.h
+            ${ARGV0}/hal/include/hal/mpu_api.h
+            ${ARGV0}/hal/include/hal/ospi_api.h
+            ${ARGV0}/hal/include/hal/pinmap.h
+            ${ARGV0}/hal/include/hal/port_api.h
+            ${ARGV0}/hal/include/hal/pwmout_api.h
+            ${ARGV0}/hal/include/hal/qspi_api.h
+            ${ARGV0}/hal/include/hal/reset_reason_api.h
+            ${ARGV0}/hal/include/hal/rtc_api.h
+            ${ARGV0}/hal/include/hal/serial_api.h
+            ${ARGV0}/hal/include/hal/sleep_api.h
+            ${ARGV0}/hal/include/hal/spi_api.h
+            ${ARGV0}/hal/include/hal/static_pinmap.h
+            ${ARGV0}/hal/include/hal/ticker_api.h
+            ${ARGV0}/hal/include/hal/trng_api.h
+            ${ARGV0}/hal/include/hal/us_ticker_api.h
+            ${ARGV0}/hal/include/hal/watchdog_api.h
+            ${ARGV0}/hal/source/LowPowerTickerWrapper.cpp
+            ${ARGV0}/hal/source/mbed_compat.c
+            ${ARGV0}/hal/source/mbed_critical_section_api.c
+            ${ARGV0}/hal/source/mbed_flash_api.c
+            ${ARGV0}/hal/source/mbed_gpio.c
+            ${ARGV0}/hal/source/mbed_gpio_irq.c
+            ${ARGV0}/hal/source/mbed_itm_api.c
+            ${ARGV0}/hal/source/mbed_lp_ticker_api.c
+            ${ARGV0}/hal/source/mbed_lp_ticker_wrapper.cpp
+            ${ARGV0}/hal/source/mbed_pinmap_common.c
+            ${ARGV0}/hal/source/mbed_pinmap_default.cpp
+            ${ARGV0}/hal/source/mbed_ticker_api.c
+            ${ARGV0}/hal/source/mbed_us_ticker_api.c
+            ${ARGV0}/hal/source/mpu/mbed_mpu_v7m.c
+            ${ARGV0}/hal/source/mpu/mbed_mpu_v8m.c
+            ${ARGV0}/hal/source/static_pinmap.cpp
+            ${ARGV0}/hal/usb/include/usb/USBPhy.h
+            ${ARGV0}/hal/usb/include/usb/USBPhyEvents.h
+            ${ARGV0}/hal/usb/include/usb/USBPhyTypes.h
+            ${ARGV0}/hal/usb/include/usb/usb_phy_api.h
+            ${ARGV0}/hal/usb/source/mbed_usb_phy.cpp
+            ${ARGV0}/mbed.h
+            ${ARGV0}/platform/cxxsupport/mstd_algorithm
+            ${ARGV0}/platform/cxxsupport/mstd_atomic
+            ${ARGV0}/platform/cxxsupport/mstd_cstddef
+            ${ARGV0}/platform/cxxsupport/mstd_functional
+            ${ARGV0}/platform/cxxsupport/mstd_iterator
+            ${ARGV0}/platform/cxxsupport/mstd_memory
+            ${ARGV0}/platform/cxxsupport/mstd_mutex
+            ${ARGV0}/platform/cxxsupport/mstd_mutex.cpp
+            ${ARGV0}/platform/cxxsupport/mstd_new
+            ${ARGV0}/platform/cxxsupport/mstd_span
+            ${ARGV0}/platform/cxxsupport/mstd_tuple
+            ${ARGV0}/platform/cxxsupport/mstd_type_traits
+            ${ARGV0}/platform/cxxsupport/mstd_utility
+            ${ARGV0}/platform/include/platform/ATCmdParser.h
+            ${ARGV0}/platform/include/platform/CThunk.h
+            ${ARGV0}/platform/include/platform/Callback.h
+            ${ARGV0}/platform/include/platform/CircularBuffer.h
+            ${ARGV0}/platform/include/platform/CriticalSectionLock.h
+            ${ARGV0}/platform/include/platform/DeepSleepLock.h
+            ${ARGV0}/platform/include/platform/DirHandle.h
+            ${ARGV0}/platform/include/platform/FileBase.h
+            ${ARGV0}/platform/include/platform/FileHandle.h
+            ${ARGV0}/platform/include/platform/FileLike.h
+            ${ARGV0}/platform/include/platform/FilePath.h
+            ${ARGV0}/platform/include/platform/FileSystemHandle.h
+            ${ARGV0}/platform/include/platform/FileSystemLike.h
+            ${ARGV0}/platform/include/platform/LocalFileSystem.h
+            ${ARGV0}/platform/include/platform/NonCopyable.h
+            ${ARGV0}/platform/include/platform/PlatformMutex.h
+            ${ARGV0}/platform/include/platform/ScopedLock.h
+            ${ARGV0}/platform/include/platform/ScopedRamExecutionLock.h
+            ${ARGV0}/platform/include/platform/ScopedRomWriteLock.h
+            ${ARGV0}/platform/include/platform/SharedPtr.h
+            ${ARGV0}/platform/include/platform/SingletonPtr.h
+            ${ARGV0}/platform/include/platform/Span.h
+            ${ARGV0}/platform/include/platform/Stream.h
+            ${ARGV0}/platform/include/platform/Transaction.h
+            ${ARGV0}/platform/include/platform/internal/CThunkBase.h
+            ${ARGV0}/platform/include/platform/internal/SysTimer.h
+            ${ARGV0}/platform/include/platform/internal/mbed_atomic_impl.h
+            ${ARGV0}/platform/include/platform/internal/mbed_error_hist.h
+            ${ARGV0}/platform/include/platform/internal/mbed_fault_handler.h
+            ${ARGV0}/platform/include/platform/internal/mbed_os_timer.h
+            ${ARGV0}/platform/include/platform/mbed_application.h
+            ${ARGV0}/platform/include/platform/mbed_assert.h
+            ${ARGV0}/platform/include/platform/mbed_atomic.h
+            ${ARGV0}/platform/include/platform/mbed_chrono.h
+            ${ARGV0}/platform/include/platform/mbed_critical.h
+            ${ARGV0}/platform/include/platform/mbed_debug.h
+            ${ARGV0}/platform/include/platform/mbed_enum_flags.h
+            ${ARGV0}/platform/include/platform/mbed_error.h
+            ${ARGV0}/platform/include/platform/mbed_interface.h
+            ${ARGV0}/platform/include/platform/mbed_mem_trace.h
+            ${ARGV0}/platform/include/platform/mbed_mktime.h
+            ${ARGV0}/platform/include/platform/mbed_mpu_mgmt.h
+            ${ARGV0}/platform/include/platform/mbed_poll.h
+            ${ARGV0}/platform/include/platform/mbed_power_mgmt.h
+            ${ARGV0}/platform/include/platform/mbed_preprocessor.h
+            ${ARGV0}/platform/include/platform/mbed_retarget.h
+            ${ARGV0}/platform/include/platform/mbed_rtc_time.h
+            ${ARGV0}/platform/include/platform/mbed_semihost_api.h
+            ${ARGV0}/platform/include/platform/mbed_stats.h
+            ${ARGV0}/platform/include/platform/mbed_thread.h
+            ${ARGV0}/platform/include/platform/mbed_toolchain.h
+            ${ARGV0}/platform/include/platform/mbed_version.h
+            ${ARGV0}/platform/include/platform/mbed_wait_api.h
+            ${ARGV0}/platform/include/platform/platform.h
+            ${ARGV0}/platform/mbed-trace/include/mbed-trace/mbed_trace.h
+            ${ARGV0}/platform/mbed-trace/include/mbed-trace/ns_trace.h
+            ${ARGV0}/platform/mbed-trace/source/mbed_trace.c
+            ${ARGV0}/platform/randlib/include/mbed-client-randlib/platform/arm_hal_random.h
+            ${ARGV0}/platform/randlib/include/mbed-client-randlib/randLIB.h
+            ${ARGV0}/platform/randlib/source/randLIB.c
+            ${ARGV0}/platform/source/ATCmdParser.cpp
+            ${ARGV0}/platform/source/CThunkBase.cpp
+            ${ARGV0}/platform/source/CriticalSectionLock.cpp
+            ${ARGV0}/platform/source/DeepSleepLock.cpp
+            ${ARGV0}/platform/source/FileBase.cpp
+            ${ARGV0}/platform/source/FileHandle.cpp
+            ${ARGV0}/platform/source/FilePath.cpp
+            ${ARGV0}/platform/source/FileSystemHandle.cpp
+            ${ARGV0}/platform/source/LocalFileSystem.cpp
+            ${ARGV0}/platform/source/Stream.cpp
+            ${ARGV0}/platform/source/SysTimer.cpp
+            ${ARGV0}/platform/source/TARGET_CORTEX_M/TOOLCHAIN_GCC/except.S
+            ${ARGV0}/platform/source/TARGET_CORTEX_M/mbed_fault_handler.c
+            ${ARGV0}/platform/source/mbed_alloc_wrappers.cpp
+            ${ARGV0}/platform/source/mbed_application.c
+            ${ARGV0}/platform/source/mbed_assert.c
+            ${ARGV0}/platform/source/mbed_atomic_impl.c
+            ${ARGV0}/platform/source/mbed_board.c
+            ${ARGV0}/platform/source/mbed_crash_data_offsets.h
+            ${ARGV0}/platform/source/mbed_critical.c
+            ${ARGV0}/platform/source/mbed_error.c
+            ${ARGV0}/platform/source/mbed_error_hist.c
+            ${ARGV0}/platform/source/mbed_interface.c
+            ${ARGV0}/platform/source/mbed_mem_trace.cpp
+            ${ARGV0}/platform/source/mbed_mktime.c
+            ${ARGV0}/platform/source/mbed_mpu_mgmt.c
+            ${ARGV0}/platform/source/mbed_os_timer.cpp
+            ${ARGV0}/platform/source/mbed_poll.cpp
+            ${ARGV0}/platform/source/mbed_power_mgmt.c
+            ${ARGV0}/platform/source/mbed_retarget.cpp
+            ${ARGV0}/platform/source/mbed_rtc_time.cpp
+            ${ARGV0}/platform/source/mbed_sdk_boot.c
+            ${ARGV0}/platform/source/mbed_semihost_api.c
+            ${ARGV0}/platform/source/mbed_stats.c
+            ${ARGV0}/platform/source/mbed_thread.cpp
+            ${ARGV0}/platform/source/mbed_wait_api_no_rtos.c
+            ${ARGV0}/platform/source/minimal-printf/mbed_printf_armlink_overrides.c
+            ${ARGV0}/platform/source/minimal-printf/mbed_printf_implementation.c
+            ${ARGV0}/platform/source/minimal-printf/mbed_printf_implementation.h
+            ${ARGV0}/platform/source/minimal-printf/mbed_printf_wrapper.c
+            ${ARGV0}/platform/source/newlib_nano_malloc_workaround.c
+            ${ARGV0}/rtos/include/rtos/ConditionVariable.h
+            ${ARGV0}/rtos/include/rtos/EventFlags.h
+            ${ARGV0}/rtos/include/rtos/Kernel.h
+            ${ARGV0}/rtos/include/rtos/Mail.h
+            ${ARGV0}/rtos/include/rtos/MemoryPool.h
+            ${ARGV0}/rtos/include/rtos/Mutex.h
+            ${ARGV0}/rtos/include/rtos/Queue.h
+            ${ARGV0}/rtos/include/rtos/Semaphore.h
+            ${ARGV0}/rtos/include/rtos/ThisThread.h
+            ${ARGV0}/rtos/include/rtos/Thread.h
+            ${ARGV0}/rtos/include/rtos/internal/mbed_rtos1_types.h
+            ${ARGV0}/rtos/include/rtos/internal/mbed_rtos_storage.h
+            ${ARGV0}/rtos/include/rtos/mbed_rtos_types.h
+            ${ARGV0}/rtos/include/rtos/rtos.h
+            ${ARGV0}/rtos/source/ConditionVariable.cpp
+            ${ARGV0}/rtos/source/EventFlags.cpp
+            ${ARGV0}/rtos/source/Kernel.cpp
+            ${ARGV0}/rtos/source/Mutex.cpp
+            ${ARGV0}/rtos/source/Semaphore.cpp
+            ${ARGV0}/rtos/source/ThisThread.cpp
+            ${ARGV0}/rtos/source/Thread.cpp
+            ${ARGV0}/rtos/source/rtos_handlers.h
+            ${ARGV0}/rtos/source/rtos_idle.h
+            ${ARGV0}/storage/blockdevice/COMPONENT_FLASHIAP/include/FlashIAP/FlashIAPBlockDevice.h
+            ${ARGV0}/storage/blockdevice/COMPONENT_FLASHIAP/source/FlashIAPBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/COMPONENT_QSPIF/include/QSPIF/QSPIFBlockDevice.h
+            ${ARGV0}/storage/blockdevice/COMPONENT_QSPIF/source/QSPIFBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/include/blockdevice/BlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/BufferedBlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/ChainingBlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/ExhaustibleBlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/FlashSimBlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/HeapBlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/MBRBlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/ObservingBlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/ProfilingBlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/ReadOnlyBlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/SlicingBlockDevice.h
+            ${ARGV0}/storage/blockdevice/include/blockdevice/internal/SFDP.h
+            ${ARGV0}/storage/blockdevice/source/BufferedBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/source/ChainingBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/source/ExhaustibleBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/source/FlashSimBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/source/HeapBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/source/MBRBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/source/ObservingBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/source/ProfilingBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/source/ReadOnlyBlockDevice.cpp
+            ${ARGV0}/storage/blockdevice/source/SFDP.cpp
+            ${ARGV0}/storage/blockdevice/source/SlicingBlockDevice.cpp
+            ${ARGV0}/storage/filesystem/fat/ChaN/diskio.h
+            ${ARGV0}/storage/filesystem/fat/ChaN/ff.cpp
+            ${ARGV0}/storage/filesystem/fat/ChaN/ff.h
+            ${ARGV0}/storage/filesystem/fat/ChaN/ffconf.h
+            ${ARGV0}/storage/filesystem/fat/ChaN/ffunicode.cpp
+            ${ARGV0}/storage/filesystem/fat/ChaN/integer.h
+            ${ARGV0}/storage/filesystem/fat/include/fat/FATFileSystem.h
+            ${ARGV0}/storage/filesystem/fat/source/FATFileSystem.cpp
+            ${ARGV0}/storage/filesystem/include/filesystem/Dir.h
+            ${ARGV0}/storage/filesystem/include/filesystem/File.h
+            ${ARGV0}/storage/filesystem/include/filesystem/FileSystem.h
+            ${ARGV0}/storage/filesystem/include/filesystem/mbed_filesystem.h
+            ${ARGV0}/storage/filesystem/littlefs/include/littlefs/LittleFileSystem.h
+            ${ARGV0}/storage/filesystem/littlefs/littlefs/lfs.c
+            ${ARGV0}/storage/filesystem/littlefs/littlefs/lfs.h
+            ${ARGV0}/storage/filesystem/littlefs/littlefs/lfs_util.c
+            ${ARGV0}/storage/filesystem/littlefs/littlefs/lfs_util.h
+            ${ARGV0}/storage/filesystem/littlefs/source/LittleFileSystem.cpp
+            ${ARGV0}/storage/filesystem/littlefsv2/include/littlefsv2/LittleFileSystem2.h
+            ${ARGV0}/storage/filesystem/littlefsv2/littlefs/lfs2.c
+            ${ARGV0}/storage/filesystem/littlefsv2/littlefs/lfs2.h
+            ${ARGV0}/storage/filesystem/littlefsv2/littlefs/lfs2_util.c
+            ${ARGV0}/storage/filesystem/littlefsv2/littlefs/lfs2_util.h
+            ${ARGV0}/storage/filesystem/littlefsv2/source/LittleFileSystem2.cpp
+            ${ARGV0}/storage/filesystem/source/Dir.cpp
+            ${ARGV0}/storage/filesystem/source/File.cpp
+            ${ARGV0}/storage/filesystem/source/FileSystem.cpp
+            ${ARGV0}/storage/kvstore/direct_access_devicekey/include/direct_access_devicekey/DirectAccessDevicekey.h
+            ${ARGV0}/storage/kvstore/direct_access_devicekey/source/DirectAccessDevicekey.cpp
+            ${ARGV0}/storage/kvstore/filesystemstore/include/filesystemstore/FileSystemStore.h
+            ${ARGV0}/storage/kvstore/filesystemstore/source/FileSystemStore.cpp
+            ${ARGV0}/storage/kvstore/include/kvstore/KVStore.h
+            ${ARGV0}/storage/kvstore/kv_config/include/kv_config/kv_config.h
+            ${ARGV0}/storage/kvstore/kv_config/source/kv_config.cpp
+            ${ARGV0}/storage/kvstore/kvstore_global_api/include/kvstore_global_api/KVMap.h
+            ${ARGV0}/storage/kvstore/kvstore_global_api/include/kvstore_global_api/kvstore_global_api.h
+            ${ARGV0}/storage/kvstore/kvstore_global_api/source/KVMap.cpp
+            ${ARGV0}/storage/kvstore/kvstore_global_api/source/kvstore_global_api.cpp
+            ${ARGV0}/storage/kvstore/securestore/include/securestore/SecureStore.h
+            ${ARGV0}/storage/kvstore/securestore/source/SecureStore.cpp
+            ${ARGV0}/storage/kvstore/tdbstore/include/tdbstore/TDBStore.h
+            ${ARGV0}/storage/kvstore/tdbstore/source/TDBStore.cpp
+            ${ARGV0}/storage/platform/source/PlatformStorage.cpp
+            ${ARGV0}/targets/TARGET_STM/PeripheralPins.h
+            ${ARGV0}/targets/TARGET_STM/PinNamesTypes.h
+            ${ARGV0}/targets/TARGET_STM/PortNames.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f722xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f723xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f730xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f732xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f733xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f745xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f746xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f750xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f756xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f765xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f767xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f769xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f777xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f779xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/stm32f7xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS/system_stm32f7xx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/Legacy/stm32_hal_legacy.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/Legacy/stm32f7xx_hal_can_legacy.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/Legacy/stm32f7xx_hal_can_legacy.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_adc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_adc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_adc_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_adc_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_can.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_can.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_cec.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_cec.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_cortex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_cortex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_crc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_crc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_crc_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_crc_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_cryp.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_cryp.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_cryp_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_cryp_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dac.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dac.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dac_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dac_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dcmi.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dcmi.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dcmi_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dcmi_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_def.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dfsdm.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dfsdm.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dma.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dma.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dma2d.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dma2d.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dma_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dma_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dsi.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_dsi.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_eth.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_eth.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_exti.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_exti.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_flash.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_flash.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_flash_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_flash_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_gpio.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_gpio.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_gpio_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_hash.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_hash.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_hash_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_hash_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_hcd.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_hcd.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_i2c.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_i2c.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_i2c_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_i2c_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_i2s.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_i2s.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_irda.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_irda.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_irda_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_iwdg.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_iwdg.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_jpeg.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_jpeg.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_lptim.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_lptim.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_ltdc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_ltdc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_ltdc_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_ltdc_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_mdios.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_mdios.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_mmc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_mmc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_nand.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_nand.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_nor.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_nor.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_pcd.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_pcd.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_pcd_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_pcd_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_pwr.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_pwr.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_pwr_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_pwr_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_qspi.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_qspi.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_rcc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_rcc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_rcc_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_rcc_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_rng.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_rng.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_rtc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_rtc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_rtc_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_rtc_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_sai.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_sai.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_sai_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_sai_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_sd.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_sd.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_sdram.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_sdram.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_smartcard.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_smartcard.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_smartcard_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_smartcard_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_smbus.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_smbus.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_spdifrx.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_spdifrx.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_spi.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_spi.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_spi_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_spi_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_sram.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_sram.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_tim.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_tim.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_tim_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_tim_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_uart.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_uart.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_uart_ex.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_uart_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_usart.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_usart.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_usart_ex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_wwdg.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_hal_wwdg.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_adc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_adc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_bus.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_cortex.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_crc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_crc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_dac.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_dac.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_dma.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_dma.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_dma2d.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_dma2d.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_exti.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_exti.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_fmc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_fmc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_gpio.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_gpio.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_i2c.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_i2c.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_iwdg.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_lptim.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_lptim.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_pwr.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_pwr.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_rcc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_rcc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_rng.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_rng.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_rtc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_rtc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_sdmmc.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_sdmmc.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_spi.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_spi.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_system.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_tim.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_tim.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_usart.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_usart.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_usb.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_usb.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_utils.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_utils.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/stm32f7xx_ll_wwdg.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/stm32f7xx_hal_conf.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/system_stm32f7xx.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralNames.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PeripheralPins.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/PinNames.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG/system_clock.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TOOLCHAIN_GCC_ARM/startup_stm32f746xx.S
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/cmsis_nvic.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/flash_data.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/analogin_device.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/analogout_device.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/can_device.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/cmsis.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/flash_api.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/gpio_irq_device.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/gpio_irq_device.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/i2c_device.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/i2c_device.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/objects.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/pin_device.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/pwmout_device.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/pwmout_device.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/serial_device.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/spi_api.c
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/spi_device.h
+            ${ARGV0}/targets/TARGET_STM/TARGET_STM32F7/us_ticker_data.h
+            ${ARGV0}/targets/TARGET_STM/USBPhyHw.h
+            ${ARGV0}/targets/TARGET_STM/USBPhy_STM32.cpp
+            ${ARGV0}/targets/TARGET_STM/analogin_api.c
+            ${ARGV0}/targets/TARGET_STM/analogout_api.c
+            ${ARGV0}/targets/TARGET_STM/can_api.c
+            ${ARGV0}/targets/TARGET_STM/device.h
+            ${ARGV0}/targets/TARGET_STM/gpio_api.c
+            ${ARGV0}/targets/TARGET_STM/gpio_irq_api.c
+            ${ARGV0}/targets/TARGET_STM/gpio_object.h
+            ${ARGV0}/targets/TARGET_STM/hal_tick_overrides.c
+            ${ARGV0}/targets/TARGET_STM/i2c_api.c
+            ${ARGV0}/targets/TARGET_STM/lp_ticker.c
+            ${ARGV0}/targets/TARGET_STM/lp_ticker_defines.h
+            ${ARGV0}/targets/TARGET_STM/mbed_crc_api.c
+            ${ARGV0}/targets/TARGET_STM/mbed_overrides.c
+            ${ARGV0}/targets/TARGET_STM/mbed_rtx.h
+            ${ARGV0}/targets/TARGET_STM/nvic_addr.h
+            ${ARGV0}/targets/TARGET_STM/ospi_api.c
+            ${ARGV0}/targets/TARGET_STM/pinmap.c
+            ${ARGV0}/targets/TARGET_STM/port_api.c
+            ${ARGV0}/targets/TARGET_STM/pwmout_api.c
+            ${ARGV0}/targets/TARGET_STM/qspi_api.c
+            ${ARGV0}/targets/TARGET_STM/reset_reason.c
+            ${ARGV0}/targets/TARGET_STM/rtc_api.c
+            ${ARGV0}/targets/TARGET_STM/rtc_api_hal.h
+            ${ARGV0}/targets/TARGET_STM/serial_api.c
+            ${ARGV0}/targets/TARGET_STM/serial_api_hal.h
+            ${ARGV0}/targets/TARGET_STM/sleep.c
+            ${ARGV0}/targets/TARGET_STM/stm32_assert.h
+            ${ARGV0}/targets/TARGET_STM/stm_spi_api.c
+            ${ARGV0}/targets/TARGET_STM/trng_api.c
+            ${ARGV0}/targets/TARGET_STM/us_ticker.c
+            ${ARGV0}/targets/TARGET_STM/us_ticker_defines.h
+            ${ARGV0}/targets/TARGET_STM/watchdog_api.c
+            mbed_config.h
+            )
+endmacro()
+
+macro(target_include_directories_mbed)
+    target_include_directories(${ARGV0} PRIVATE
+            ${ARGV1}/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG/TARGET_DISCO_F746NG
+            ${ARGV1}/targets/TARGET_STM/TARGET_STM32F7/TARGET_STM32F746xG
+            ${ARGV1}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver/Legacy
+            ${ARGV1}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/STM32F7xx_HAL_Driver
+            ${ARGV1}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW/CMSIS
+            ${ARGV1}/targets/TARGET_STM/TARGET_STM32F7/STM32Cube_FW
+            ${ARGV1}/targets/TARGET_STM/TARGET_STM32F7
+            ${ARGV1}/targets/TARGET_STM
+            ${ARGV1}/storage/kvstore/tdbstore/include/tdbstore
+            ${ARGV1}/storage/kvstore/tdbstore/include
+            ${ARGV1}/storage/kvstore/tdbstore
+            ${ARGV1}/storage/kvstore/securestore/include/securestore
+            ${ARGV1}/storage/kvstore/securestore/include
+            ${ARGV1}/storage/kvstore/securestore
+            ${ARGV1}/storage/kvstore/kvstore_global_api/include/kvstore_global_api
+            ${ARGV1}/storage/kvstore/kvstore_global_api/include
+            ${ARGV1}/storage/kvstore/kvstore_global_api
+            ${ARGV1}/storage/kvstore/kv_config/include/kv_config
+            ${ARGV1}/storage/kvstore/kv_config/include
+            ${ARGV1}/storage/kvstore/kv_config
+            ${ARGV1}/storage/kvstore/include/kvstore
+            ${ARGV1}/storage/kvstore/include
+            ${ARGV1}/storage/kvstore/filesystemstore/include/filesystemstore
+            ${ARGV1}/storage/kvstore/filesystemstore/include
+            ${ARGV1}/storage/kvstore/filesystemstore
+            ${ARGV1}/storage/kvstore/direct_access_devicekey/include/direct_access_devicekey
+            ${ARGV1}/storage/kvstore/direct_access_devicekey/include
+            ${ARGV1}/storage/kvstore/direct_access_devicekey
+            ${ARGV1}/storage/kvstore
+            ${ARGV1}/storage/filesystem/littlefsv2/littlefs
+            ${ARGV1}/storage/filesystem/littlefsv2/include/littlefsv2
+            ${ARGV1}/storage/filesystem/littlefsv2/include
+            ${ARGV1}/storage/filesystem/littlefsv2
+            ${ARGV1}/storage/filesystem/littlefs/littlefs
+            ${ARGV1}/storage/filesystem/littlefs/include/littlefs
+            ${ARGV1}/storage/filesystem/littlefs/include
+            ${ARGV1}/storage/filesystem/littlefs
+            ${ARGV1}/storage/filesystem/include/filesystem
+            ${ARGV1}/storage/filesystem/include
+            ${ARGV1}/storage/filesystem/fat/include/fat
+            ${ARGV1}/storage/filesystem/fat/include
+            ${ARGV1}/storage/filesystem/fat/ChaN
+            ${ARGV1}/storage/filesystem/fat
+            ${ARGV1}/storage/filesystem
+            ${ARGV1}/storage/blockdevice/include/blockdevice/internal
+            ${ARGV1}/storage/blockdevice/include/blockdevice
+            ${ARGV1}/storage/blockdevice/include
+            ${ARGV1}/storage/blockdevice/COMPONENT_QSPIF/include/QSPIF
+            ${ARGV1}/storage/blockdevice/COMPONENT_QSPIF/include
+            ${ARGV1}/storage/blockdevice/COMPONENT_QSPIF
+            ${ARGV1}/storage/blockdevice/COMPONENT_FLASHIAP/include/FlashIAP
+            ${ARGV1}/storage/blockdevice/COMPONENT_FLASHIAP/include
+            ${ARGV1}/storage/blockdevice/COMPONENT_FLASHIAP
+            ${ARGV1}/storage/blockdevice
+            ${ARGV1}/storage
+            ${ARGV1}/rtos/source
+            ${ARGV1}/rtos/include/rtos/internal
+            ${ARGV1}/rtos/include/rtos
+            ${ARGV1}/rtos/include
+            ${ARGV1}/rtos
+            ${ARGV1}/platform/source/minimal-printf
+            ${ARGV1}/platform/source
+            ${ARGV1}/platform/randlib/include/mbed-client-randlib/platform
+            ${ARGV1}/platform/randlib/include/mbed-client-randlib
+            ${ARGV1}/platform/randlib/include
+            ${ARGV1}/platform/randlib
+            ${ARGV1}/platform/mbed-trace/include/mbed-trace
+            ${ARGV1}/platform/mbed-trace/include
+            ${ARGV1}/platform/mbed-trace
+            ${ARGV1}/platform/include/platform/internal
+            ${ARGV1}/platform/include/platform
+            ${ARGV1}/platform/include
+            ${ARGV1}/platform/cxxsupport
+            ${ARGV1}/platform
+            ${ARGV1}/hal/usb/include/usb
+            ${ARGV1}/hal/usb/include
+            ${ARGV1}/hal/usb
+            ${ARGV1}/hal/include/hal
+            ${ARGV1}/hal/include
+            ${ARGV1}/hal
+            ${ARGV1}/features/frameworks/utest/utest
+            ${ARGV1}/features/frameworks/utest
+            ${ARGV1}/features/frameworks/unity/unity
+            ${ARGV1}/features/frameworks/unity
+            ${ARGV1}/features/frameworks/mbed-client-cli/mbed-client-cli
+            ${ARGV1}/features/frameworks/mbed-client-cli
+            ${ARGV1}/features/frameworks/greentea-client/greentea-client
+            ${ARGV1}/features/frameworks/greentea-client
+            ${ARGV1}/features/frameworks
+            ${ARGV1}/features
+            ${ARGV1}/events/include/events/internal
+            ${ARGV1}/events/include/events
+            ${ARGV1}/events/include
+            ${ARGV1}/events
+            ${ARGV1}/drivers/usb/include/usb/internal
+            ${ARGV1}/drivers/usb/include/usb
+            ${ARGV1}/drivers/usb/include
+            ${ARGV1}/drivers/usb
+            ${ARGV1}/drivers/include/drivers/interfaces
+            ${ARGV1}/drivers/include/drivers
+            ${ARGV1}/drivers/include
+            ${ARGV1}/drivers/device_key/include/device_key
+            ${ARGV1}/drivers/device_key/include
+            ${ARGV1}/drivers/device_key
+            ${ARGV1}/drivers
+            ${ARGV1}/connectivity/nfc/libraries/stack/transceiver
+            ${ARGV1}/connectivity/nfc/libraries/stack/tech/type4
+            ${ARGV1}/connectivity/nfc/libraries/stack/tech/isodep
+            ${ARGV1}/connectivity/nfc/libraries/stack/tech/iso7816
+            ${ARGV1}/connectivity/nfc/libraries/stack/tech
+            ${ARGV1}/connectivity/nfc/libraries/stack/platform
+            ${ARGV1}/connectivity/nfc/libraries/stack/ndef
+            ${ARGV1}/connectivity/nfc/libraries/stack
+            ${ARGV1}/connectivity/nfc/libraries/acore/acore
+            ${ARGV1}/connectivity/nfc/libraries/acore
+            ${ARGV1}/connectivity/nfc/libraries
+            ${ARGV1}/connectivity/nfc/include/nfc/ndef/common
+            ${ARGV1}/connectivity/nfc/include/nfc/ndef
+            ${ARGV1}/connectivity/nfc/include/nfc
+            ${ARGV1}/connectivity/nfc/include
+            ${ARGV1}/connectivity/nfc
+            ${ARGV1}/connectivity/netsocket/include/netsocket
+            ${ARGV1}/connectivity/netsocket/include
+            ${ARGV1}/connectivity/netsocket
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/libNET/src
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/libNET
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/libDHCPv6
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/ipv6_stack
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/configs/base
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/configs
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/whiteboard
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/utils
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/random_early_detection
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/pan_blacklist
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/nist_aes_kw
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/nd_proxy
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mle_service
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet/fnet_stack/stack
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet/fnet_stack/services/serial
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet/fnet_stack/services/poll
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet/fnet_stack/services/mdns
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet/fnet_stack/services/dns
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet/fnet_stack/services
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet/fnet_stack/port/cpu
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet/fnet_stack/port/compiler
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet/fnet_stack/port
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet/fnet_stack
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns/fnet
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mdns
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/mac_neighbor_table
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/load_balance
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/ieee_802_11
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/hmac
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/fnv_hash
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/fhss
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/etx
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/blacklist
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/Trickle
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs/Neighbor_cache
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Service_Libs
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/protocols/tls_sec_prot
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/protocols/radius_sec_prot
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/protocols/msg_sec_prot
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/protocols/key_sec_prot
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/protocols/gkh_sec_prot
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/protocols/fwh_sec_prot
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/protocols/eap_tls_sec_prot
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/protocols
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/kmp
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/eapol
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/TLS
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/PANA
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security/Common
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Security
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/RPL
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/NWK_INTERFACE/Include
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/NWK_INTERFACE
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/MPL
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/MLE
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/MAC/virtual_rf
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/MAC/IEEE802_15_4
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/MAC
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/DHCPv6_client
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/DHCPv6_Server
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Core/include
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Core
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/Common_Protocols
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/BorderRouter
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/6LoWPAN/ws
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/6LoWPAN/Thread
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/6LoWPAN/NVM
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/6LoWPAN/ND
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/6LoWPAN/Mesh
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/6LoWPAN/MAC
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/6LoWPAN/IPHC_Decode
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/6LoWPAN/Fragmentation
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/6LoWPAN/Bootstraps
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source/6LoWPAN
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/source
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/nanostack/platform
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack/nanostack
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack-eventloop/source
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop/platform
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack-eventloop/nanostack-event-loop
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack-eventloop
+            ${ARGV1}/connectivity/nanostack/sal-stack-nanostack
+            ${ARGV1}/connectivity/nanostack/nanostack-hal-mbed-cmsis-rtos
+            ${ARGV1}/connectivity/nanostack/mbed-mesh-api/source/include
+            ${ARGV1}/connectivity/nanostack/mbed-mesh-api/source
+            ${ARGV1}/connectivity/nanostack/mbed-mesh-api/mbed-mesh-api
+            ${ARGV1}/connectivity/nanostack/mbed-mesh-api
+            ${ARGV1}/connectivity/nanostack/include/nanostack-interface
+            ${ARGV1}/connectivity/nanostack/include
+            ${ARGV1}/connectivity/nanostack/coap-service/source/include
+            ${ARGV1}/connectivity/nanostack/coap-service/source
+            ${ARGV1}/connectivity/nanostack/coap-service/coap-service
+            ${ARGV1}/connectivity/nanostack/coap-service
+            ${ARGV1}/connectivity/nanostack
+            ${ARGV1}/connectivity/mbedtls/source
+            ${ARGV1}/connectivity/mbedtls/platform/inc
+            ${ARGV1}/connectivity/mbedtls/platform
+            ${ARGV1}/connectivity/mbedtls/include/mbedtls
+            ${ARGV1}/connectivity/mbedtls/include
+            ${ARGV1}/connectivity/mbedtls
+            ${ARGV1}/connectivity/lwipstack/lwip/src/include/netif
+            ${ARGV1}/connectivity/lwipstack/lwip/src/include/lwip/prot
+            ${ARGV1}/connectivity/lwipstack/lwip/src/include/lwip/priv
+            ${ARGV1}/connectivity/lwipstack/lwip/src/include/lwip
+            ${ARGV1}/connectivity/lwipstack/lwip/src/include/compat/posix/sys
+            ${ARGV1}/connectivity/lwipstack/lwip/src/include/compat/posix/net
+            ${ARGV1}/connectivity/lwipstack/lwip/src/include/compat/posix/arpa
+            ${ARGV1}/connectivity/lwipstack/lwip/src/include/compat/posix
+            ${ARGV1}/connectivity/lwipstack/lwip/src/include/compat
+            ${ARGV1}/connectivity/lwipstack/lwip/src/include
+            ${ARGV1}/connectivity/lwipstack/lwip/src
+            ${ARGV1}/connectivity/lwipstack/lwip-sys/arch
+            ${ARGV1}/connectivity/lwipstack/lwip-sys
+            ${ARGV1}/connectivity/lwipstack/lwip
+            ${ARGV1}/connectivity/lwipstack/include/lwipstack
+            ${ARGV1}/connectivity/lwipstack/include
+            ${ARGV1}/connectivity/lwipstack
+            ${ARGV1}/connectivity/lorawan/system
+            ${ARGV1}/connectivity/lorawan/lorastack/phy
+            ${ARGV1}/connectivity/lorawan/lorastack/mac
+            ${ARGV1}/connectivity/lorawan/lorastack
+            ${ARGV1}/connectivity/lorawan/include/lorawan
+            ${ARGV1}/connectivity/lorawan/include
+            ${ARGV1}/connectivity/lorawan
+            ${ARGV1}/connectivity/libraries/ppp/include/ppp
+            ${ARGV1}/connectivity/libraries/ppp/include/polarssl
+            ${ARGV1}/connectivity/libraries/ppp/include
+            ${ARGV1}/connectivity/libraries/ppp
+            ${ARGV1}/connectivity/libraries/nanostack-libservice/mbed-client-libservice/platform
+            ${ARGV1}/connectivity/libraries/nanostack-libservice/mbed-client-libservice
+            ${ARGV1}/connectivity/libraries/nanostack-libservice
+            ${ARGV1}/connectivity/libraries/mbed-coap/source/include
+            ${ARGV1}/connectivity/libraries/mbed-coap/source
+            ${ARGV1}/connectivity/libraries/mbed-coap/mbed-coap
+            ${ARGV1}/connectivity/libraries/mbed-coap
+            ${ARGV1}/connectivity/libraries
+            ${ARGV1}/connectivity/drivers/wifi/esp8266-driver/ESP8266
+            ${ARGV1}/connectivity/drivers/wifi/esp8266-driver
+            ${ARGV1}/connectivity/drivers/wifi
+            ${ARGV1}/connectivity/drivers/nfc/PN512/source/transceiver
+            ${ARGV1}/connectivity/drivers/nfc/PN512/source
+            ${ARGV1}/connectivity/drivers/nfc/PN512/include/nfc/controllers
+            ${ARGV1}/connectivity/drivers/nfc/PN512/include/nfc
+            ${ARGV1}/connectivity/drivers/nfc/PN512/include
+            ${ARGV1}/connectivity/drivers/nfc/PN512
+            ${ARGV1}/connectivity/drivers/nfc
+            ${ARGV1}/connectivity/drivers/mbedtls/TARGET_STM
+            ${ARGV1}/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7
+            ${ARGV1}/connectivity/drivers/emac/TARGET_STM
+            ${ARGV1}/connectivity/drivers/cellular/UBLOX/PPP
+            ${ARGV1}/connectivity/drivers/cellular/UBLOX/N2XX
+            ${ARGV1}/connectivity/drivers/cellular/UBLOX/AT
+            ${ARGV1}/connectivity/drivers/cellular/UBLOX
+            ${ARGV1}/connectivity/drivers/cellular/TELIT/ME910
+            ${ARGV1}/connectivity/drivers/cellular/TELIT/ME310
+            ${ARGV1}/connectivity/drivers/cellular/TELIT/HE910
+            ${ARGV1}/connectivity/drivers/cellular/TELIT
+            ${ARGV1}/connectivity/drivers/cellular/RiotMicro/AT
+            ${ARGV1}/connectivity/drivers/cellular/RiotMicro
+            ${ARGV1}/connectivity/drivers/cellular/QUECTEL/UG96
+            ${ARGV1}/connectivity/drivers/cellular/QUECTEL/M26
+            ${ARGV1}/connectivity/drivers/cellular/QUECTEL/EC2X
+            ${ARGV1}/connectivity/drivers/cellular/QUECTEL/BG96
+            ${ARGV1}/connectivity/drivers/cellular/QUECTEL/BC95
+            ${ARGV1}/connectivity/drivers/cellular/QUECTEL
+            ${ARGV1}/connectivity/drivers/cellular/MultiTech/DragonflyNano/PPP
+            ${ARGV1}/connectivity/drivers/cellular/MultiTech/DragonflyNano
+            ${ARGV1}/connectivity/drivers/cellular/MultiTech
+            ${ARGV1}/connectivity/drivers/cellular/GENERIC/GENERIC_AT3GPP
+            ${ARGV1}/connectivity/drivers/cellular/GENERIC
+            ${ARGV1}/connectivity/drivers/cellular/GEMALTO/CINTERION
+            ${ARGV1}/connectivity/drivers/cellular/GEMALTO
+            ${ARGV1}/connectivity/drivers/cellular/Altair/ALT1250/PPP
+            ${ARGV1}/connectivity/drivers/cellular/Altair/ALT1250
+            ${ARGV1}/connectivity/drivers/cellular/Altair
+            ${ARGV1}/connectivity/drivers/cellular
+            ${ARGV1}/connectivity/drivers/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver
+            ${ARGV1}/connectivity/drivers/802.15.4_RF/stm-s2lp-rf-driver/source
+            ${ARGV1}/connectivity/drivers/802.15.4_RF/stm-s2lp-rf-driver
+            ${ARGV1}/connectivity/drivers/802.15.4_RF/mcr20a-rf-driver/source
+            ${ARGV1}/connectivity/drivers/802.15.4_RF/mcr20a-rf-driver/mcr20a-rf-driver
+            ${ARGV1}/connectivity/drivers/802.15.4_RF/mcr20a-rf-driver
+            ${ARGV1}/connectivity/drivers/802.15.4_RF/atmel-rf-driver/source
+            ${ARGV1}/connectivity/drivers/802.15.4_RF/atmel-rf-driver/atmel-rf-driver
+            ${ARGV1}/connectivity/drivers/802.15.4_RF/atmel-rf-driver
+            ${ARGV1}/connectivity/drivers/802.15.4_RF
+            ${ARGV1}/connectivity/drivers
+            ${ARGV1}/connectivity/cellular/include/cellular/framework/device
+            ${ARGV1}/connectivity/cellular/include/cellular/framework/common
+            ${ARGV1}/connectivity/cellular/include/cellular/framework/AT
+            ${ARGV1}/connectivity/cellular/include/cellular/framework/API
+            ${ARGV1}/connectivity/cellular/include/cellular/framework
+            ${ARGV1}/connectivity/cellular/include/cellular
+            ${ARGV1}/connectivity/cellular/include
+            ${ARGV1}/connectivity/cellular
+            ${ARGV1}/connectivity
+            ${ARGV1}/cmsis/device/rtos/include
+            ${ARGV1}/cmsis/device/rtos
+            ${ARGV1}/cmsis/device/RTE/include
+            ${ARGV1}/cmsis/device/RTE
+            ${ARGV1}/cmsis/device
+            ${ARGV1}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M/Include
+            ${ARGV1}/cmsis/CMSIS_5/CMSIS/TARGET_CORTEX_M
+            ${ARGV1}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Source
+            ${ARGV1}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include1
+            ${ARGV1}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Include
+            ${ARGV1}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX/Config
+            ${ARGV1}/cmsis/CMSIS_5/CMSIS/RTOS2/RTX
+            ${ARGV1}/cmsis/CMSIS_5/CMSIS/RTOS2/Include
+            ${ARGV1}/cmsis/CMSIS_5/CMSIS/RTOS2
+            ${ARGV1}/cmsis/CMSIS_5/CMSIS
+            ${ARGV1}/cmsis/CMSIS_5
+            ${ARGV1}/cmsis
+            ${ARGV1}
+            )
+
+endmacro()
diff --git a/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/mbed_config.h b/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/mbed_config.h
new file mode 100644 (file)
index 0000000..ca042ca
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ * mbed SDK
+ * Copyright (c) 2017 ARM Limited
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 configuration file.
+// DO NOT EDIT, content will be overwritten.
+
+#ifndef __MBED_CONFIG_DATA__
+#define __MBED_CONFIG_DATA__
+
+// Configuration parameters
+#define CLOCK_SOURCE USE_PLL_HSE_XTAL | USE_PLL_HSI         // set by target:DISCO_F746NG
+#define LPTICKER_DELAY_TICKS 0                              // set by target:MCU_STM32F7
+#define MBED_CONF_ALT1250_PPP_BAUDRATE 115200               // set by library:ALT1250_PPP
+#define MBED_CONF_ALT1250_PPP_PROVIDE_DEFAULT 0             // set by library:ALT1250_PPP
+#define MBED_CONF_ATMEL_RF_ASSUME_SPACED_SPI 1              // set by library:atmel-rf[STM]
+#define MBED_CONF_ATMEL_RF_FULL_SPI_SPEED 7500000           // set by library:atmel-rf
+#define MBED_CONF_ATMEL_RF_FULL_SPI_SPEED_BYTE_SPACING 250  // set by library:atmel-rf
+#define MBED_CONF_ATMEL_RF_IRQ_THREAD_STACK_SIZE 1024       // set by library:atmel-rf
+#define MBED_CONF_ATMEL_RF_LOW_SPI_SPEED 3750000            // set by library:atmel-rf
+#define MBED_CONF_ATMEL_RF_PROVIDE_DEFAULT 0                // set by library:atmel-rf
+#define MBED_CONF_ATMEL_RF_USE_SPI_SPACING_API 0            // set by library:atmel-rf
+#define MBED_CONF_CELLULAR_AT_HANDLER_BUFFER_SIZE 32        // set by library:cellular
+#define MBED_CONF_CELLULAR_CONTROL_PLANE_OPT 0              // set by library:cellular
+#define MBED_CONF_CELLULAR_DEBUG_AT 0                       // set by library:cellular
+#define MBED_CONF_CELLULAR_MAX_CP_DATA_RECV_LEN 1358        // set by library:cellular
+#define MBED_CONF_CELLULAR_PRESENT 1                        // set by library:cellular
+#define MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY 0         // set by library:cellular
+#define MBED_CONF_CELLULAR_USE_APN_LOOKUP 0                 // set by library:cellular
+#define MBED_CONF_CELLULAR_USE_SMS 0                        // set by library:cellular
+#define MBED_CONF_DRIVERS_OSPI_CSN OSPI_FLASH1_CSN          // set by library:drivers
+#define MBED_CONF_DRIVERS_OSPI_DQS OSPI_FLASH1_DQS          // set by library:drivers
+#define MBED_CONF_DRIVERS_OSPI_IO0 OSPI_FLASH1_IO0          // set by library:drivers
+#define MBED_CONF_DRIVERS_OSPI_IO1 OSPI_FLASH1_IO1          // set by library:drivers
+#define MBED_CONF_DRIVERS_OSPI_IO2 OSPI_FLASH1_IO2          // set by library:drivers
+#define MBED_CONF_DRIVERS_OSPI_IO3 OSPI_FLASH1_IO3          // set by library:drivers
+#define MBED_CONF_DRIVERS_OSPI_IO4 OSPI_FLASH1_IO4          // set by library:drivers
+#define MBED_CONF_DRIVERS_OSPI_IO5 OSPI_FLASH1_IO5          // set by library:drivers
+#define MBED_CONF_DRIVERS_OSPI_IO6 OSPI_FLASH1_IO6          // set by library:drivers
+#define MBED_CONF_DRIVERS_OSPI_IO7 OSPI_FLASH1_IO7          // set by library:drivers
+#define MBED_CONF_DRIVERS_OSPI_SCK OSPI_FLASH1_SCK          // set by library:drivers
+#define MBED_CONF_DRIVERS_QSPI_CSN QSPI_FLASH1_CSN          // set by library:drivers
+#define MBED_CONF_DRIVERS_QSPI_IO0 QSPI_FLASH1_IO0          // set by library:drivers
+#define MBED_CONF_DRIVERS_QSPI_IO1 QSPI_FLASH1_IO1          // set by library:drivers
+#define MBED_CONF_DRIVERS_QSPI_IO2 QSPI_FLASH1_IO2          // set by library:drivers
+#define MBED_CONF_DRIVERS_QSPI_IO3 QSPI_FLASH1_IO3          // set by library:drivers
+#define MBED_CONF_DRIVERS_QSPI_SCK QSPI_FLASH1_SCK          // set by library:drivers
+#define MBED_CONF_DRIVERS_UART_SERIAL_RXBUF_SIZE 256        // set by library:drivers
+#define MBED_CONF_DRIVERS_UART_SERIAL_TXBUF_SIZE 256        // set by library:drivers
+#define MBED_CONF_ESP8266_BUILT_IN_DNS 0                    // set by library:esp8266
+#define MBED_CONF_ESP8266_DEBUG 0                           // set by library:esp8266
+#define MBED_CONF_ESP8266_POWER_OFF_TIME_MS 3               // set by library:esp8266
+#define MBED_CONF_ESP8266_POWER_ON_POLARITY 0               // set by library:esp8266
+#define MBED_CONF_ESP8266_POWER_ON_TIME_MS 3                // set by library:esp8266
+#define MBED_CONF_ESP8266_PROVIDE_DEFAULT 0                 // set by library:esp8266
+#define MBED_CONF_ESP8266_SERIAL_BAUDRATE 115200            // set by library:esp8266
+#define MBED_CONF_ESP8266_SNTP_ENABLE 0                     // set by library:esp8266
+#define MBED_CONF_ESP8266_SNTP_SERVER0 ""                   // set by library:esp8266
+#define MBED_CONF_ESP8266_SNTP_SERVER1 ""                   // set by library:esp8266
+#define MBED_CONF_ESP8266_SNTP_SERVER2 ""                   // set by library:esp8266
+#define MBED_CONF_ESP8266_SNTP_TIMEZONE 0                   // set by library:esp8266
+#define MBED_CONF_ESP8266_SOCKET_BUFSIZE 8192               // set by library:esp8266
+#define MBED_CONF_EVENTS_PRESENT 1                          // set by library:events
+#define MBED_CONF_EVENTS_SHARED_DISPATCH_FROM_APPLICATION 0 // set by library:events
+#define MBED_CONF_EVENTS_SHARED_EVENTSIZE 768               // set by library:events
+#define MBED_CONF_EVENTS_SHARED_HIGHPRIO_EVENTSIZE 256      // set by library:events
+#define MBED_CONF_EVENTS_SHARED_HIGHPRIO_STACKSIZE 1024     // set by library:events
+#define MBED_CONF_EVENTS_SHARED_STACKSIZE 2048              // set by library:events
+#define MBED_CONF_EVENTS_USE_LOWPOWER_TIMER_TICKER 0        // set by library:events
+#define MBED_CONF_FAT_CHAN_FFS_DBG 0                        // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_CODE_PAGE 437                 // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_EXFAT 0                    // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_HEAPBUF 1                  // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_LOCK 0                     // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_MINIMIZE 0                 // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_NOFSINFO 0                 // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_NORTC 0                    // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_READONLY 0                 // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_REENTRANT 0                // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_RPATH 1                    // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_TIMEOUT 1000               // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_FS_TINY 1                     // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_LFN_BUF 255                   // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_LFN_UNICODE 0                 // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_MAX_LFN 255                   // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_MAX_SS 4096                   // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_MIN_SS 512                    // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_MULTI_PARTITION 0             // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_NORTC_MDAY 1                  // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_NORTC_MON 1                   // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_NORTC_YEAR 2017               // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_PRINT_FLOAT 0                 // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_PRINT_LLI 0                   // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_SFN_BUF 12                    // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_STRF_ENCODE 3                 // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_STR_VOLUME_ID 0               // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_SYNC_T HANDLE                 // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_USE_CHMOD 0                   // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_USE_EXPAND 0                  // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_USE_FASTSEEK 0                // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_USE_FIND 0                    // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_USE_FORWARD 0                 // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_USE_LABEL 0                   // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_USE_LFN 3                     // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_USE_MKFS 1                    // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_USE_STRFUNC 0                 // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_USE_TRIM 1                    // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_VOLUMES 4                     // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FF_VOLUME_STRS \
+  "RAM", "NAND", "CF", "SD", "SD2", "USB", "USB2", "USB3" // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FLUSH_ON_NEW_CLUSTER 0         // set by library:fat_chan
+#define MBED_CONF_FAT_CHAN_FLUSH_ON_NEW_SECTOR 1          // set by library:fat_chan
+#define MBED_CONF_FILESYSTEM_PRESENT 1                    // set by library:filesystem
+#define MBED_CONF_FLASHIAP_BLOCK_DEVICE_BASE_ADDRESS \
+  0xFFFFFFFF                                          // set by library:flashiap-block-device
+#define MBED_CONF_FLASHIAP_BLOCK_DEVICE_SIZE 0        // set by library:flashiap-block-device
+#define MBED_CONF_GEMALTO_CINTERION_BAUDRATE 115200   // set by library:GEMALTO_CINTERION
+#define MBED_CONF_GEMALTO_CINTERION_PROVIDE_DEFAULT 0 // set by library:GEMALTO_CINTERION
+#define MBED_CONF_GENERIC_AT3GPP_BAUDRATE 115200      // set by library:GENERIC_AT3GPP
+#define MBED_CONF_GENERIC_AT3GPP_PROVIDE_DEFAULT 0    // set by library:GENERIC_AT3GPP
+#define MBED_CONF_LORA_ADR_ON 1                       // set by library:lora
+#define MBED_CONF_LORA_APPLICATION_EUI             \
+  {                                                \
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \
+  } // set by library:lora
+#define MBED_CONF_LORA_APPLICATION_KEY                                                             \
+  {                                                                                                \
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \
+  } // set by library:lora
+#define MBED_CONF_LORA_APPSKEY                                                                     \
+  {                                                                                                \
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \
+  }                                               // set by library:lora
+#define MBED_CONF_LORA_APP_PORT 15                // set by library:lora
+#define MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE 1 // set by library:lora
+#define MBED_CONF_LORA_DEVICE_ADDRESS 0x00000000  // set by library:lora
+#define MBED_CONF_LORA_DEVICE_EUI                  \
+  {                                                \
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \
+  }                                               // set by library:lora
+#define MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH 5 // set by library:lora
+#define MBED_CONF_LORA_DUTY_CYCLE_ON 1            // set by library:lora
+#define MBED_CONF_LORA_DUTY_CYCLE_ON_JOIN 1       // set by library:lora
+#define MBED_CONF_LORA_FSB_MASK            \
+  {                                        \
+    0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF \
+  } // set by library:lora
+#define MBED_CONF_LORA_FSB_MASK_CHINA              \
+  {                                                \
+    0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF \
+  }                                       // set by library:lora
+#define MBED_CONF_LORA_LBT_ON 0           // set by library:lora
+#define MBED_CONF_LORA_MAX_SYS_RX_ERROR 5 // set by library:lora
+#define MBED_CONF_LORA_NB_TRIALS 12       // set by library:lora
+#define MBED_CONF_LORA_NWKSKEY                                                                     \
+  {                                                                                                \
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \
+  }                                                               // set by library:lora
+#define MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION 1                  // set by library:lora
+#define MBED_CONF_LORA_PHY EU868                                  // set by library:lora
+#define MBED_CONF_LORA_PUBLIC_NETWORK 1                           // set by library:lora
+#define MBED_CONF_LORA_TX_MAX_SIZE 64                             // set by library:lora
+#define MBED_CONF_LORA_UPLINK_PREAMBLE_LENGTH 8                   // set by library:lora
+#define MBED_CONF_LORA_WAKEUP_TIME 5                              // set by library:lora
+#define MBED_CONF_LWIP_ADDR_TIMEOUT 5                             // set by library:lwip
+#define MBED_CONF_LWIP_ADDR_TIMEOUT_MODE 1                        // set by library:lwip
+#define MBED_CONF_LWIP_DEBUG_ENABLED 0                            // set by library:lwip
+#define MBED_CONF_LWIP_DEFAULT_THREAD_STACKSIZE 512               // set by library:lwip
+#define MBED_CONF_LWIP_DHCP_TIMEOUT 60                            // set by library:lwip
+#define MBED_CONF_LWIP_ENABLE_PPP_TRACE 0                         // set by library:lwip
+#define MBED_CONF_LWIP_ETHERNET_ENABLED 1                         // set by library:lwip
+#define MBED_CONF_LWIP_IPV4_ENABLED 1                             // set by library:lwip
+#define MBED_CONF_LWIP_IPV6_ENABLED 0                             // set by library:lwip
+#define MBED_CONF_LWIP_IP_VER_PREF 4                              // set by library:lwip
+#define MBED_CONF_LWIP_L3IP_ENABLED 0                             // set by library:lwip
+#define MBED_CONF_LWIP_MBOX_SIZE 8                                // set by library:lwip
+#define MBED_CONF_LWIP_MEMP_NUM_TCPIP_MSG_INPKT 8                 // set by library:lwip
+#define MBED_CONF_LWIP_MEMP_NUM_TCP_SEG 16                        // set by library:lwip
+#define MBED_CONF_LWIP_MEM_SIZE 2310                              // set by library:lwip[STM]
+#define MBED_CONF_LWIP_ND6_QUEUEING 0                             // set by library:lwip
+#define MBED_CONF_LWIP_ND6_RDNSS_MAX_DNS_SERVERS 0                // set by library:lwip
+#define MBED_CONF_LWIP_NUM_NETBUF 8                               // set by library:lwip
+#define MBED_CONF_LWIP_NUM_PBUF 8                                 // set by library:lwip
+#define MBED_CONF_LWIP_PBUF_POOL_SIZE 5                           // set by library:lwip
+#define MBED_CONF_LWIP_PPP_ENABLED 0                              // set by library:lwip
+#define MBED_CONF_LWIP_PPP_IPV4_ENABLED 0                         // set by library:lwip
+#define MBED_CONF_LWIP_PPP_IPV6_ENABLED 0                         // set by library:lwip
+#define MBED_CONF_LWIP_PPP_THREAD_STACKSIZE 768                   // set by library:lwip
+#define MBED_CONF_LWIP_PRESENT 1                                  // set by library:lwip
+#define MBED_CONF_LWIP_RAW_SOCKET_ENABLED 0                       // set by library:lwip
+#define MBED_CONF_LWIP_SOCKET_MAX 4                               // set by library:lwip
+#define MBED_CONF_LWIP_TCPIP_THREAD_PRIORITY osPriorityNormal     // set by library:lwip
+#define MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE 1200                // set by library:lwip
+#define MBED_CONF_LWIP_TCP_CLOSE_TIMEOUT 1000                     // set by library:lwip
+#define MBED_CONF_LWIP_TCP_ENABLED 1                              // set by library:lwip
+#define MBED_CONF_LWIP_TCP_MAXRTX 6                               // set by library:lwip
+#define MBED_CONF_LWIP_TCP_MSS 536                                // set by library:lwip
+#define MBED_CONF_LWIP_TCP_SERVER_MAX 4                           // set by library:lwip
+#define MBED_CONF_LWIP_TCP_SND_BUF (2 * TCP_MSS)                  // set by library:lwip
+#define MBED_CONF_LWIP_TCP_SOCKET_MAX 4                           // set by library:lwip
+#define MBED_CONF_LWIP_TCP_SYNMAXRTX 6                            // set by library:lwip
+#define MBED_CONF_LWIP_TCP_WND (4 * TCP_MSS)                      // set by library:lwip
+#define MBED_CONF_LWIP_UDP_SOCKET_MAX 4                           // set by library:lwip
+#define MBED_CONF_LWIP_USE_MBED_TRACE 0                           // set by library:lwip
+#define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_CHANNEL 0              // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_CHANNEL_MASK 0x7fff800 // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_CHANNEL_PAGE 0         // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_DEVICE_TYPE \
+  NET_6LOWPAN_ROUTER                                           // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_PANID_FILTER 0xffff // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_PSK_KEY                                                 \
+  {                                                                                                \
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf \
+  }                                                                  // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_PSK_KEY_ID 1              // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_SECURITY_MODE NONE        // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_SEC_LEVEL 5               // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_HEAP_SIZE 32500                      // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_HEAP_STAT_INFO NULL                  // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_MAC_NEIGH_TABLE_SIZE 32              // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_RADIUS_RETRY_COUNT 3                 // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_RADIUS_RETRY_IMAX 30                 // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_RADIUS_RETRY_IMIN 20                 // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_SYSTEM_TIME_UPDATE_FROM_NANOSTACK 1  // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL 22             // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL_MASK 0x7fff800 // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL_PAGE 0         // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_COMMISSIONING_DATASET_TIMESTAMP \
+  0x10000 // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_EXTENDED_PANID \
+  {                                                          \
+    0xf1, 0xb5, 0xa1, 0xb2, 0xc4, 0xd5, 0xa1, 0xbd           \
+  } // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_ML_PREFIX \
+  {                                                     \
+    0xfd, 0x0, 0x0d, 0xb8, 0x0, 0x0, 0x0, 0x0           \
+  } // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_NETWORK_NAME \
+  "Thread Network"                                         // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_PANID 0x0700 // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_PSKC                                                 \
+  {                                                                                                \
+    0xc8, 0xa6, 0x2e, 0xae, 0xf3, 0x68, 0xf3, 0x46, 0xa9, 0x9e, 0x57, 0x85, 0x98, 0x9d, 0x1c, 0xd0 \
+  } // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_DEVICE_TYPE \
+  MESH_DEVICE_TYPE_THREAD_ROUTER // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_MASTER_KEY                                                  \
+  {                                                                                                \
+    0x10, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff \
+  }                                                             // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_PSKD "ABCDEFGH"          // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_SECURITY_POLICY 255      // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_THREAD_USE_STATIC_LINK_CONFIG 1 // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_USE_MALLOC_FOR_HEAP 0           // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_BC_CHANNEL_FUNCTION 255   // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_BC_DWELL_INTERVAL 0       // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_BC_FIXED_CHANNEL 65535    // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_BC_INTERVAL 0             // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_CHANNEL_PLAN_ID 255       // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_DEVICE_TYPE \
+  MESH_DEVICE_TYPE_WISUN_ROUTER                                     // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_NETWORK_NAME "Wi-SUN Network" // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_OPERATING_CLASS 255           // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_OPERATING_MODE 255            // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_PHY_MODE_ID 255               // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_REGULATORY_DOMAIN 3           // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_UC_CHANNEL_FUNCTION 255       // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_UC_DWELL_INTERVAL 255         // set by library:mbed-mesh-api
+#define MBED_CONF_MBED_MESH_API_WISUN_UC_FIXED_CHANNEL 65535        // set by library:mbed-mesh-api
+#define MBED_CONF_MCR20A_PROVIDE_DEFAULT 0                          // set by library:mcr20a
+#define MBED_CONF_NANOSTACK_CONFIGURATION nanostack_full            // set by library:nanostack
+#define MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT \
+  0 // set by library:nanostack-hal
+#define MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION \
+  0                                                               // set by library:nanostack-hal
+#define MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_THREAD_STACK_SIZE 6144 // set by library:nanostack-hal
+#define MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_USE_MBED_EVENTS 0      // set by library:nanostack-hal
+#define MBED_CONF_NANOSTACK_HAL_KVSTORE_PATH "/kv/"               // set by library:nanostack-hal
+#define MBED_CONF_NANOSTACK_HAL_USE_KVSTORE 0                     // set by library:nanostack-hal
+#define MBED_CONF_NANOSTACK_LIBSERVICE_NSDYNMEM_TRACKER_ENABLED \
+  0                                                          // set by library:nanostack-libservice
+#define MBED_CONF_NANOSTACK_LIBSERVICE_PRESENT 1             // set by library:nanostack-libservice
+#define MBED_CONF_NSAPI_ADD_EVENT_LISTENER_RETURN_CHANGE 0   // set by library:nsapi
+#define MBED_CONF_NSAPI_DEFAULT_MESH_TYPE THREAD             // set by library:nsapi
+#define MBED_CONF_NSAPI_DEFAULT_STACK LWIP                   // set by library:nsapi
+#define MBED_CONF_NSAPI_DEFAULT_WIFI_SECURITY NONE           // set by library:nsapi
+#define MBED_CONF_NSAPI_DNS_ADDRESSES_LIMIT 10               // set by library:nsapi
+#define MBED_CONF_NSAPI_DNS_CACHE_SIZE 3                     // set by library:nsapi
+#define MBED_CONF_NSAPI_DNS_RESPONSE_WAIT_TIME 10000         // set by library:nsapi
+#define MBED_CONF_NSAPI_DNS_RETRIES 1                        // set by library:nsapi
+#define MBED_CONF_NSAPI_DNS_TOTAL_ATTEMPTS 10                // set by library:nsapi
+#define MBED_CONF_NSAPI_PRESENT 1                            // set by library:nsapi
+#define MBED_CONF_NSAPI_SOCKET_STATS_ENABLED 0               // set by library:nsapi
+#define MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT 10            // set by library:nsapi
+#define MBED_CONF_PLATFORM_CALLBACK_COMPARABLE 1             // set by library:platform
+#define MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL 0             // set by library:platform
+#define MBED_CONF_PLATFORM_CRASH_CAPTURE_ENABLED 0           // set by library:platform
+#define MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX 8                // set by library:platform
+#define MBED_CONF_PLATFORM_DEEPSLEEP_STATS_VERBOSE 0         // set by library:platform[STM]
+#define MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE 9600     // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO 0          // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED 0  // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_HIST_ENABLED 0              // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_HIST_SIZE 4                 // set by library:platform
+#define MBED_CONF_PLATFORM_ERROR_REBOOT_MAX 1                // set by library:platform
+#define MBED_CONF_PLATFORM_FATAL_ERROR_AUTO_REBOOT_ENABLED 0 // set by library:platform
+#define MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN 16         // set by library:platform
+#define MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_64_BIT 1    // set by library:platform
+#define MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT 0 // set by library:platform
+#define MBED_CONF_PLATFORM_MINIMAL_PRINTF_SET_FLOATING_POINT_MAX_DECIMALS \
+  6                                                              // set by library:platform
+#define MBED_CONF_PLATFORM_POLL_USE_LOWPOWER_TIMER 0             // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_BAUD_RATE 9600                  // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_BUFFERED_SERIAL 0               // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES 1              // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES 1          // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT 1                 // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_MINIMAL_CONSOLE_ONLY 0          // set by library:platform
+#define MBED_CONF_PLATFORM_USE_MPU 1                             // set by library:platform
+#define MBED_CONF_PPP_ENABLED 0                                  // set by library:ppp
+#define MBED_CONF_PPP_ENABLE_TRACE 0                             // set by library:ppp
+#define MBED_CONF_PPP_IPV4_ENABLED 1                             // set by library:ppp
+#define MBED_CONF_PPP_IPV6_ENABLED 0                             // set by library:ppp
+#define MBED_CONF_PPP_MBED_EVENT_QUEUE 0                         // set by library:ppp
+#define MBED_CONF_PPP_THREAD_STACKSIZE 816                       // set by library:ppp
+#define MBED_CONF_QSPIF_DIRECT_RESET 0                           // set by library:qspif
+#define MBED_CONF_QSPIF_ENABLE_AND_RESET 1                       // set by library:qspif[N25Q128A]
+#define MBED_CONF_QSPIF_QSPI_CSN MBED_CONF_DRIVERS_QSPI_CSN      // set by library:qspif
+#define MBED_CONF_QSPIF_QSPI_FREQ 80000000                       // set by library:qspif[N25Q128A]
+#define MBED_CONF_QSPIF_QSPI_IO0 MBED_CONF_DRIVERS_QSPI_IO0      // set by library:qspif
+#define MBED_CONF_QSPIF_QSPI_IO1 MBED_CONF_DRIVERS_QSPI_IO1      // set by library:qspif
+#define MBED_CONF_QSPIF_QSPI_IO2 MBED_CONF_DRIVERS_QSPI_IO2      // set by library:qspif
+#define MBED_CONF_QSPIF_QSPI_IO3 MBED_CONF_DRIVERS_QSPI_IO3      // set by library:qspif
+#define MBED_CONF_QSPIF_QSPI_MIN_PROG_SIZE 1                     // set by library:qspif
+#define MBED_CONF_QSPIF_QSPI_MIN_READ_SIZE 1                     // set by library:qspif
+#define MBED_CONF_QSPIF_QSPI_POLARITY_MODE 0                     // set by library:qspif
+#define MBED_CONF_QSPIF_QSPI_SCK MBED_CONF_DRIVERS_QSPI_SCK      // set by library:qspif
+#define MBED_CONF_QUECTEL_BC95_BAUDRATE 9600                     // set by library:QUECTEL_BC95
+#define MBED_CONF_QUECTEL_BC95_PROVIDE_DEFAULT 0                 // set by library:QUECTEL_BC95
+#define MBED_CONF_QUECTEL_BG96_BAUDRATE 115200                   // set by library:QUECTEL_BG96
+#define MBED_CONF_QUECTEL_BG96_PROVIDE_DEFAULT 0                 // set by library:QUECTEL_BG96
+#define MBED_CONF_QUECTEL_EC2X_BAUDRATE 115200                   // set by library:QUECTEL_EC2X
+#define MBED_CONF_QUECTEL_EC2X_PROVIDE_DEFAULT 0                 // set by library:QUECTEL_EC2X
+#define MBED_CONF_QUECTEL_EC2X_START_TIMEOUT 15000               // set by library:QUECTEL_EC2X
+#define MBED_CONF_QUECTEL_M26_BAUDRATE 115200                    // set by library:QUECTEL_M26
+#define MBED_CONF_QUECTEL_M26_PROVIDE_DEFAULT 0                  // set by library:QUECTEL_M26
+#define MBED_CONF_QUECTEL_UG96_BAUDRATE 115200                   // set by library:QUECTEL_UG96
+#define MBED_CONF_QUECTEL_UG96_PROVIDE_DEFAULT 0                 // set by library:QUECTEL_UG96
+#define MBED_CONF_RM1000_AT_BAUDRATE 230400                      // set by library:RM1000_AT
+#define MBED_CONF_RM1000_AT_PROVIDE_DEFAULT 0                    // set by library:RM1000_AT
+#define MBED_CONF_RTOS_API_PRESENT 1                             // set by library:rtos-api
+#define MBED_CONF_RTOS_ENABLE_ALL_RTX_EVENTS 0                   // set by library:rtos
+#define MBED_CONF_RTOS_EVFLAGS_NUM 0                             // set by library:rtos
+#define MBED_CONF_RTOS_IDLE_THREAD_STACK_SIZE 512                // set by library:rtos
+#define MBED_CONF_RTOS_IDLE_THREAD_STACK_SIZE_DEBUG_EXTRA 128    // set by library:rtos[STM]
+#define MBED_CONF_RTOS_IDLE_THREAD_STACK_SIZE_TICKLESS_EXTRA 256 // set by library:rtos
+#define MBED_CONF_RTOS_MAIN_THREAD_STACK_SIZE 4096               // set by library:rtos
+#define MBED_CONF_RTOS_MSGQUEUE_DATA_SIZE 0                      // set by library:rtos
+#define MBED_CONF_RTOS_MSGQUEUE_NUM 0                            // set by library:rtos
+#define MBED_CONF_RTOS_MUTEX_NUM 0                               // set by library:rtos
+#define MBED_CONF_RTOS_PRESENT 1                                 // set by library:rtos
+#define MBED_CONF_RTOS_SEMAPHORE_NUM 0                           // set by library:rtos
+#define MBED_CONF_RTOS_THREAD_NUM 0                              // set by library:rtos
+#define MBED_CONF_RTOS_THREAD_STACK_SIZE 4096                    // set by library:rtos
+#define MBED_CONF_RTOS_THREAD_USER_STACK_SIZE 0                  // set by library:rtos
+#define MBED_CONF_RTOS_TIMER_NUM 0                               // set by library:rtos
+#define MBED_CONF_RTOS_TIMER_THREAD_STACK_SIZE 768               // set by library:rtos
+#define MBED_CONF_S2LP_PROVIDE_DEFAULT 0                         // set by library:s2lp
+#define MBED_CONF_SARA4_PPP_BAUDRATE 115200                      // set by library:SARA4_PPP
+#define MBED_CONF_SARA4_PPP_PROVIDE_DEFAULT 0                    // set by library:SARA4_PPP
+#define MBED_CONF_STM32_EMAC_ETH_PHY_ADDRESS 0                   // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_ETH_PHY_AUTONEGOTIATION \
+  ETH_AUTONEGOTIATION_ENABLE                                        // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_ETH_PHY_DUPLEXMODE ETH_MODE_FULLDUPLEX // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_ETH_PHY_DUPLEX_STATUS 0x0010           // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_ETH_PHY_MEDIA_INTERFACE \
+  ETH_MEDIA_INTERFACE_RMII                                   // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_ETH_PHY_RESET_DELAY 500         // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_ETH_PHY_SPEED ETH_SPEED_100M    // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_ETH_PHY_SPEED_STATUS 0x0004     // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_ETH_PHY_STATUS_REGISTER 31      // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_ETH_RXBUFNB 4                   // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_ETH_TXBUFNB 4                   // set by library:stm32-emac
+#define MBED_CONF_STM32_EMAC_THREAD_STACKSIZE 1024           // set by library:stm32-emac
+#define MBED_CONF_STORAGE_DEFAULT_KV kv                      // set by library:storage
+#define MBED_CONF_STORAGE_FILESYSTEM_BLOCKDEVICE default     // set by library:storage_filesystem
+#define MBED_CONF_STORAGE_FILESYSTEM_EXTERNAL_BASE_ADDRESS 0 // set by library:storage_filesystem
+#define MBED_CONF_STORAGE_FILESYSTEM_EXTERNAL_SIZE 0         // set by library:storage_filesystem
+#define MBED_CONF_STORAGE_FILESYSTEM_FILESYSTEM default      // set by library:storage_filesystem
+#define MBED_CONF_STORAGE_FILESYSTEM_FOLDER_PATH kvstore     // set by library:storage_filesystem
+#define MBED_CONF_STORAGE_FILESYSTEM_INTERNAL_BASE_ADDRESS 0 // set by library:storage_filesystem
+#define MBED_CONF_STORAGE_FILESYSTEM_MOUNT_POINT kv          // set by library:storage_filesystem
+#define MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_BLOCKDEVICE \
+  default // set by library:storage_filesystem_no_rbp
+#define MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_EXTERNAL_BASE_ADDRESS \
+  0 // set by library:storage_filesystem_no_rbp
+#define MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_EXTERNAL_SIZE \
+  0 // set by library:storage_filesystem_no_rbp
+#define MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_FILESYSTEM \
+  default // set by library:storage_filesystem_no_rbp
+#define MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_FOLDER_PATH \
+  kvstore // set by library:storage_filesystem_no_rbp
+#define MBED_CONF_STORAGE_FILESYSTEM_NO_RBP_MOUNT_POINT \
+  kv                                                     // set by library:storage_filesystem_no_rbp
+#define MBED_CONF_STORAGE_FILESYSTEM_RBP_INTERNAL_SIZE 0 // set by library:storage_filesystem
+#define MBED_CONF_STORAGE_STORAGE_TYPE default           // set by library:storage
+#define MBED_CONF_STORAGE_TDB_EXTERNAL_BLOCKDEVICE default // set by library:storage_tdb_external
+#define MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_BASE_ADDRESS \
+  0                                                    // set by library:storage_tdb_external
+#define MBED_CONF_STORAGE_TDB_EXTERNAL_EXTERNAL_SIZE 0 // set by library:storage_tdb_external
+#define MBED_CONF_STORAGE_TDB_EXTERNAL_INTERNAL_BASE_ADDRESS \
+  0 // set by library:storage_tdb_external
+#define MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_BLOCKDEVICE \
+  default // set by library:storage_tdb_external_no_rbp
+#define MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_BASE_ADDRESS \
+  0 // set by library:storage_tdb_external_no_rbp
+#define MBED_CONF_STORAGE_TDB_EXTERNAL_NO_RBP_EXTERNAL_SIZE \
+  0 // set by library:storage_tdb_external_no_rbp
+#define MBED_CONF_STORAGE_TDB_EXTERNAL_RBP_INTERNAL_SIZE 0 // set by library:storage_tdb_external
+#define MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_BASE_ADDRESS \
+  0                                                       // set by library:storage_tdb_internal
+#define MBED_CONF_STORAGE_TDB_INTERNAL_INTERNAL_SIZE 0    // set by library:storage_tdb_internal
+#define MBED_CONF_TARGET_BOOT_STACK_SIZE 0x400            // set by library:rtos[*]
+#define MBED_CONF_TARGET_CONSOLE_UART 1                   // set by target:Target
+#define MBED_CONF_TARGET_CUSTOM_TICKERS 1                 // set by target:Target
+#define MBED_CONF_TARGET_DEEP_SLEEP_LATENCY 4             // set by target:MCU_STM32
+#define MBED_CONF_TARGET_DEFAULT_ADC_VREF NAN             // set by target:Target
+#define MBED_CONF_TARGET_GPIO_RESET_AT_INIT 0             // set by target:MCU_STM32
+#define MBED_CONF_TARGET_I2C_TIMING_VALUE_ALGO 0          // set by target:MCU_STM32F7
+#define MBED_CONF_TARGET_INIT_US_TICKER_AT_BOOT 1         // set by target:MCU_STM32
+#define MBED_CONF_TARGET_INTERNAL_FLASH_UNIFORM_SECTORS 0 // set by target:MCU_STM32F7
+#define MBED_CONF_TARGET_LPTICKER_LPTIM 1                 // set by target:MCU_STM32F7
+#define MBED_CONF_TARGET_LPTICKER_LPTIM_CLOCK 1           // set by target:MCU_STM32
+#define MBED_CONF_TARGET_LPUART_CLOCK_SOURCE \
+  USE_LPUART_CLK_LSE | USE_LPUART_CLK_PCLK1 | USE_LPUART_CLK_PCLK3 // set by target:MCU_STM32
+#define MBED_CONF_TARGET_LSE_AVAILABLE 1                           // set by target:MCU_STM32
+#define MBED_CONF_TARGET_LSE_DRIVE_LOAD_LEVEL RCC_LSEDRIVE_LOW     // set by target:MCU_STM32F7
+#define MBED_CONF_TARGET_MPU_ROM_END 0x0fffffff                    // set by target:Target
+#define MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE ETHERNET   // set by target:DISCO_F746NG
+#define MBED_CONF_TARGET_RTC_CLOCK_SOURCE USE_RTC_CLK_LSE_OR_LSI   // set by target:MCU_STM32
+#define MBED_CONF_TARGET_TICKLESS_FROM_US_TICKER 0                 // set by target:Target
+#define MBED_CONF_TARGET_USB_SPEED USE_USB_OTG_FS                  // set by target:DISCO_F746NG
+#define MBED_CONF_TARGET_XIP_ENABLE 0                              // set by target:Target
+#define MBED_CONF_TELIT_HE910_BAUDRATE 115200                      // set by library:TELIT_HE910
+#define MBED_CONF_TELIT_HE910_PROVIDE_DEFAULT 0                    // set by library:TELIT_HE910
+#define MBED_CONF_TELIT_ME310_BAUDRATE 115200                      // set by library:TELIT_ME310
+#define MBED_CONF_TELIT_ME310_PROVIDE_DEFAULT 0                    // set by library:TELIT_ME310
+#define MBED_CONF_TELIT_ME910_BAUDRATE 115200                      // set by library:TELIT_ME910
+#define MBED_CONF_TELIT_ME910_PROVIDE_DEFAULT 0                    // set by library:TELIT_ME910
+#define MBED_CONF_UBLOX_AT_BAUDRATE 115200                         // set by library:UBLOX_AT
+#define MBED_CONF_UBLOX_AT_PROVIDE_DEFAULT 0                       // set by library:UBLOX_AT
+#define MBED_CONF_UBLOX_N2XX_BAUDRATE 9600                         // set by library:UBLOX_N2XX
+#define MBED_CONF_UBLOX_N2XX_PROVIDE_DEFAULT 0                     // set by library:UBLOX_N2XX
+#define MBED_CONF_UBLOX_PPP_BAUDRATE 115200                        // set by library:UBLOX_PPP
+#define MBED_CONF_UBLOX_PPP_PROVIDE_DEFAULT 0                      // set by library:UBLOX_PPP
+#define MBED_CRC_TABLE_SIZE 16                                     // set by library:drivers
+#define MBED_LFS2_BLOCK_CYCLES 1024                                // set by library:littlefs2
+#define MBED_LFS2_BLOCK_SIZE 512                                   // set by library:littlefs2
+#define MBED_LFS2_CACHE_SIZE 64                                    // set by library:littlefs2
+#define MBED_LFS2_ENABLE_INFO 0                                    // set by library:littlefs2
+#define MBED_LFS2_INTRINSICS 1                                     // set by library:littlefs2
+#define MBED_LFS2_LOOKAHEAD_SIZE 64                                // set by library:littlefs2
+#define MBED_LFS_BLOCK_SIZE 512                                    // set by library:littlefs
+#define MBED_LFS_ENABLE_INFO 0                                     // set by library:littlefs
+#define MBED_LFS_INTRINSICS 1                                      // set by library:littlefs
+#define MBED_LFS_LOOKAHEAD 512                                     // set by library:littlefs
+#define MBED_LFS_PROG_SIZE 64                                      // set by library:littlefs
+#define MBED_LFS_READ_SIZE 64                                      // set by library:littlefs
+#define MBED_STACK_DUMP_ENABLED 0                                  // set by library:platform
+#define MBED_TRACE_COLOR_THEME 0                                   // set by library:mbed-trace
+#define MEM_ALLOC malloc                                           // set by library:mbed-trace
+#define MEM_FREE free                                              // set by library:mbed-trace
+#define PPP_DEBUG 0                                                // set by library:ppp
+// Macros
+#define MBEDTLS_CIPHER_MODE_CTR // defined by library:SecureStore
+#define NSAPI_PPP_AVAILABLE \
+  (MBED_CONF_PPP_ENABLED || MBED_CONF_LWIP_PPP_ENABLED) // defined by library:ppp
+#define NSDYNMEM_TRACKER_ENABLED \
+  MBED_CONF_NANOSTACK_LIBSERVICE_NSDYNMEM_TRACKER_ENABLED // defined by library:nanostack-libservice
+#define NS_USE_EXTERNAL_MBED_TLS                          // defined by library:nanostack
+#define UNITY_INCLUDE_CONFIG_H                            // defined by library:utest
+#define _RTE_                                             // defined by library:rtos
+
+#endif
diff --git a/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/speech_recognition_float.circle.h b/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/speech_recognition_float.circle.h
new file mode 100644 (file)
index 0000000..4fa3cdb
--- /dev/null
@@ -0,0 +1,4285 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SPEECH_RECOGNITION_FLOAT_CIRCLE_H
+#define SPEECH_RECOGNITION_FLOAT_CIRCLE_H
+
+const char circle_model_raw[68200] = {
+  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,
+  0x64, 0x05, 0x01, 0x00, 0xdc, 0x09, 0x01, 0x00, 0x28, 0x0a, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x50, 0x05, 0x01, 0x00, 0x48, 0x05, 0x01, 0x00, 0x18, 0x05, 0x01, 0x00, 0x08, 0xfb, 0x00, 0x00,
+  0xe8, 0xfa, 0x00, 0x00, 0xd0, 0xfa, 0x00, 0x00, 0xb0, 0xfa, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
+  0x98, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x78, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6a, 0xfa, 0xfe, 0xff,
+  0x04, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff,
+  0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00,
+  0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x33, 0x2e, 0x30, 0x00, 0x00, 0xba, 0xfa, 0xfe, 0xff,
+  0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xf6, 0xfe, 0xff, 0x00, 0xf7, 0xfe, 0xff,
+  0x04, 0xf7, 0xfe, 0xff, 0x08, 0xf7, 0xfe, 0xff, 0x0c, 0xf7, 0xfe, 0xff, 0xea, 0xfa, 0xfe, 0xff,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x93, 0x3b, 0x2a, 0xba, 0x66, 0x25, 0x65, 0xbb,
+  0x0c, 0x1b, 0xb2, 0xba, 0xdd, 0xb8, 0xa1, 0x3b, 0xd4, 0x18, 0x69, 0x3b, 0x11, 0xa3, 0x6d, 0x3b,
+  0xaa, 0xbd, 0x58, 0x3b, 0x03, 0x69, 0xba, 0x3a, 0x1f, 0x72, 0x64, 0x3b, 0xec, 0xff, 0xd9, 0xbb,
+  0x93, 0x6c, 0xb7, 0xbc, 0x65, 0x6b, 0x8e, 0x3b, 0xce, 0xba, 0xf7, 0xbb, 0xce, 0x45, 0x35, 0xbc,
+  0x54, 0xb6, 0x9d, 0x3c, 0xe2, 0xfb, 0x8f, 0x3b, 0x90, 0xcd, 0x81, 0xbc, 0xf9, 0xfb, 0x23, 0x3b,
+  0xd2, 0xe3, 0x34, 0xbb, 0x73, 0x4a, 0xf4, 0xbb, 0x2a, 0x62, 0x38, 0xbc, 0xab, 0x8d, 0x60, 0xbc,
+  0x82, 0x95, 0x17, 0x3c, 0x59, 0xac, 0xde, 0x3b, 0xa0, 0x1a, 0x7b, 0x3b, 0xf1, 0xa1, 0x05, 0xbc,
+  0x7b, 0xd3, 0xaf, 0xbc, 0xbf, 0xff, 0x0d, 0xbc, 0x50, 0x8c, 0xe9, 0x3b, 0x91, 0x6b, 0x3d, 0xbc,
+  0xc1, 0x9d, 0x28, 0xbc, 0x9f, 0xfa, 0x1c, 0x3c, 0xe4, 0xf0, 0x88, 0xbb, 0x05, 0xd7, 0x18, 0xbc,
+  0x43, 0xa8, 0xbe, 0xba, 0x74, 0x01, 0x74, 0x3c, 0xe1, 0xfd, 0x39, 0xbc, 0xaa, 0xd5, 0xa9, 0xbc,
+  0xc1, 0xaa, 0x24, 0xbc, 0x1e, 0xcb, 0x06, 0xbb, 0x11, 0x76, 0xd8, 0x3b, 0xbf, 0x57, 0xbe, 0xbb,
+  0x2d, 0x91, 0x91, 0xbb, 0xdd, 0x41, 0x4e, 0x3b, 0xa4, 0x97, 0x12, 0x3b, 0x0d, 0x3f, 0x2d, 0xbc,
+  0xf3, 0x5c, 0x9c, 0xbb, 0x43, 0x8b, 0x70, 0x3c, 0x20, 0x1f, 0x6f, 0xbb, 0x5e, 0x99, 0x92, 0xbc,
+  0x3e, 0x93, 0x8e, 0xbc, 0x9c, 0x26, 0xb4, 0x3b, 0xac, 0x6c, 0xa8, 0x3a, 0xcd, 0x28, 0x8b, 0xbc,
+  0x70, 0x36, 0x9b, 0xbc, 0xb0, 0x4c, 0xd0, 0xbb, 0x0e, 0x4e, 0xea, 0x3b, 0x5b, 0x65, 0x41, 0x3c,
+  0xad, 0x70, 0x6f, 0xbc, 0xab, 0xa8, 0x88, 0x3b, 0xd9, 0x75, 0x0c, 0xbb, 0xfb, 0x92, 0x5c, 0xbc,
+  0x19, 0x7f, 0x98, 0x3a, 0x5e, 0x78, 0xe8, 0x3a, 0xe8, 0xb2, 0xeb, 0xbb, 0x36, 0x9f, 0x07, 0x3b,
+  0x9a, 0xd0, 0x24, 0xbc, 0x69, 0x10, 0xcf, 0xbb, 0x87, 0x4e, 0x6e, 0x3c, 0xca, 0x07, 0x3e, 0x3b,
+  0x8e, 0x92, 0x9d, 0xba, 0xac, 0xaa, 0x01, 0x3c, 0x97, 0x45, 0xea, 0xba, 0x1e, 0x3c, 0x39, 0xbb,
+  0xa2, 0x69, 0x9c, 0xbb, 0x8d, 0x2f, 0x70, 0x3c, 0x08, 0x91, 0xef, 0x3b, 0xa6, 0xa3, 0x46, 0x3a,
+  0x35, 0xc6, 0xa6, 0xbb, 0x94, 0xa7, 0x93, 0xbb, 0x82, 0xc3, 0xc1, 0xb9, 0x86, 0x19, 0x8c, 0x3c,
+  0x18, 0x68, 0x82, 0xbc, 0xf9, 0xb6, 0x8f, 0xbb, 0x69, 0xbf, 0x7b, 0xbb, 0x85, 0x7d, 0xc9, 0xbb,
+  0x1f, 0xf2, 0xa0, 0xbb, 0x12, 0xe2, 0x33, 0xbc, 0x67, 0x20, 0x09, 0xbc, 0x46, 0xea, 0xc0, 0x3a,
+  0x47, 0xa8, 0x88, 0xbc, 0xae, 0xcb, 0xda, 0xbb, 0x91, 0x70, 0x9e, 0x3c, 0x21, 0xbd, 0x75, 0xbc,
+  0xc0, 0xb2, 0xd6, 0xbb, 0x78, 0x47, 0x86, 0x3c, 0x11, 0x9c, 0xbb, 0xbb, 0x41, 0x2a, 0x90, 0x3b,
+  0x2b, 0xca, 0x85, 0xbb, 0xd1, 0xfb, 0x5c, 0xbb, 0xf9, 0x6c, 0xfd, 0xbb, 0xb5, 0x43, 0xad, 0xbc,
+  0xee, 0xea, 0x5c, 0xbb, 0x9c, 0xd0, 0x0d, 0xbc, 0xb4, 0x00, 0x2a, 0xba, 0x0c, 0x92, 0x1e, 0x3c,
+  0xe4, 0xb7, 0x94, 0xbc, 0x90, 0x54, 0xcd, 0xbb, 0xdb, 0x83, 0x06, 0x3c, 0x83, 0x74, 0x67, 0xbc,
+  0xfa, 0x9e, 0x9f, 0xbb, 0xbb, 0x28, 0xc1, 0x3b, 0x61, 0x88, 0xdf, 0xbb, 0x35, 0x62, 0x24, 0xbc,
+  0x5f, 0x70, 0x6f, 0xbb, 0xdb, 0x5e, 0x3d, 0xbc, 0x0a, 0xf4, 0x60, 0xbc, 0x52, 0x67, 0x70, 0x3b,
+  0xf7, 0x37, 0x8c, 0x3a, 0x9c, 0xb8, 0x32, 0x3c, 0x1c, 0xb7, 0xc2, 0xbb, 0x88, 0xf3, 0xa8, 0x3b,
+  0x11, 0x75, 0xb4, 0x3b, 0x2b, 0xe8, 0x98, 0x3c, 0x31, 0xb1, 0x4b, 0xbc, 0x8e, 0xed, 0x47, 0x3a,
+  0x9e, 0x2e, 0xcd, 0x3a, 0x0d, 0xb9, 0x5d, 0xbb, 0x91, 0x62, 0x20, 0x3c, 0x46, 0x3f, 0x3d, 0x3c,
+  0x20, 0x92, 0x9d, 0xbb, 0x4b, 0xd7, 0x20, 0xbc, 0x19, 0xd0, 0x73, 0x3c, 0x3f, 0x1b, 0xb6, 0x3b,
+  0xd0, 0xf6, 0xef, 0xbb, 0x2a, 0xf5, 0x09, 0xbc, 0xf9, 0x27, 0xfc, 0xba, 0x9c, 0x84, 0x83, 0x3b,
+  0x12, 0x19, 0xfd, 0xbb, 0x42, 0x5b, 0x3c, 0xba, 0xdb, 0x14, 0xcf, 0xba, 0x51, 0x96, 0x0d, 0xbc,
+  0xfb, 0xc6, 0x30, 0x3c, 0x42, 0xc7, 0xc2, 0xba, 0xe5, 0xd7, 0x59, 0x3c, 0x98, 0xac, 0x08, 0xbc,
+  0xae, 0x67, 0xac, 0xba, 0x09, 0x8a, 0x85, 0xbc, 0x25, 0xbf, 0xee, 0x3a, 0xb3, 0xeb, 0x28, 0x3b,
+  0xe3, 0x48, 0xf4, 0xbb, 0xca, 0x4c, 0xbe, 0x3c, 0x2a, 0x1c, 0x43, 0xbb, 0x7c, 0x58, 0xb4, 0x3b,
+  0x66, 0xfe, 0x8c, 0xbc, 0x75, 0x5a, 0xcc, 0x3b, 0xae, 0x76, 0x15, 0xbc, 0xd5, 0x48, 0xa8, 0xbb,
+  0x16, 0xa1, 0x43, 0xbb, 0x88, 0x55, 0xbd, 0xbb, 0xab, 0x55, 0x7b, 0x3b, 0x74, 0x27, 0xb6, 0x3b,
+  0x23, 0x59, 0xa0, 0xbc, 0x33, 0x9b, 0x6c, 0x3c, 0x02, 0x6c, 0x24, 0x3c, 0xb3, 0xba, 0xb7, 0x3a,
+  0xb8, 0xd8, 0xac, 0xbb, 0x52, 0x22, 0x85, 0x3a, 0x76, 0x1f, 0xc2, 0xbb, 0x29, 0xa8, 0x0d, 0xbb,
+  0x68, 0x6d, 0x11, 0xbc, 0xa8, 0xe5, 0x24, 0x3a, 0x98, 0x6a, 0x53, 0xba, 0x7a, 0x55, 0xa6, 0xbc,
+  0x78, 0xb6, 0x72, 0x3c, 0x86, 0x39, 0xbc, 0xba, 0x02, 0xff, 0xd1, 0xba, 0x08, 0x96, 0xda, 0x3b,
+  0x88, 0xf4, 0x44, 0xbb, 0x55, 0x75, 0x3b, 0x3b, 0x7a, 0xe9, 0xef, 0xbb, 0x89, 0xa6, 0x63, 0xbb,
+  0x77, 0x60, 0x6b, 0xbc, 0x5d, 0x52, 0x2d, 0x3c, 0xde, 0x87, 0x36, 0xbc, 0x03, 0x6d, 0xe9, 0xbb,
+  0xa9, 0x62, 0xb8, 0x3a, 0xe3, 0x90, 0xca, 0x3b, 0x3b, 0xc4, 0xca, 0x3b, 0x9c, 0x44, 0x83, 0xbc,
+  0xb0, 0x1a, 0x4f, 0xbb, 0x43, 0xfa, 0x4a, 0x3c, 0xb3, 0x87, 0xd5, 0x3b, 0x3d, 0x38, 0x99, 0xbb,
+  0x0c, 0xb5, 0xfe, 0xba, 0x33, 0x4d, 0xa1, 0x3b, 0x1a, 0x09, 0x42, 0x3c, 0xaf, 0x1a, 0x6e, 0xbc,
+  0x57, 0x6d, 0x7d, 0xbc, 0x28, 0xa3, 0x8c, 0x3b, 0x09, 0x8c, 0x27, 0x3c, 0x31, 0x4c, 0x01, 0xbc,
+  0x8f, 0x24, 0xec, 0xbb, 0xc5, 0x08, 0x46, 0x3b, 0x57, 0x9c, 0xe6, 0xbb, 0xf9, 0x08, 0x72, 0xbc,
+  0xc6, 0x56, 0x03, 0xbc, 0x84, 0x37, 0x4d, 0x3c, 0x22, 0x91, 0x82, 0x3b, 0xa8, 0xc3, 0x3b, 0xbc,
+  0x8a, 0xc9, 0xc5, 0xba, 0x90, 0x7e, 0x0b, 0x3c, 0x63, 0x04, 0x1e, 0x3c, 0x42, 0xa6, 0x32, 0x3b,
+  0x85, 0x2e, 0xee, 0xbb, 0xea, 0x58, 0xe0, 0xba, 0x4a, 0x1e, 0x2c, 0xbc, 0x3b, 0xb8, 0x13, 0xbb,
+  0x99, 0xfc, 0x89, 0xbb, 0xb8, 0x29, 0x2b, 0xbc, 0xf2, 0xbb, 0x62, 0x3c, 0xb9, 0xb9, 0x94, 0x3b,
+  0xbf, 0x5e, 0x43, 0xbb, 0x45, 0xdb, 0x9d, 0xbb, 0x6a, 0x19, 0x78, 0x3b, 0x85, 0x1b, 0xd7, 0xbb,
+  0xcf, 0x8a, 0x46, 0xbc, 0x99, 0x50, 0x80, 0xbb, 0x1e, 0xbd, 0xe1, 0xba, 0x94, 0x82, 0x2b, 0x3c,
+  0x45, 0xfc, 0xac, 0xbb, 0xa6, 0x2d, 0xdd, 0x3b, 0xb4, 0xdf, 0x73, 0x3b, 0xa0, 0x21, 0x5d, 0xbb,
+  0x69, 0xe2, 0x9e, 0x3b, 0x36, 0xd3, 0xa2, 0x3a, 0x45, 0xf2, 0x94, 0x3c, 0x37, 0xb2, 0x9b, 0xbc,
+  0xe1, 0x39, 0x79, 0x3a, 0x60, 0xae, 0xb2, 0xbb, 0x33, 0x72, 0x97, 0xbb, 0x08, 0x39, 0xa3, 0xbb,
+  0x70, 0x0f, 0x05, 0xbc, 0xcf, 0xe8, 0x70, 0x3c, 0xb6, 0x7f, 0x5f, 0xbc, 0x97, 0x3e, 0x69, 0xbc,
+  0x66, 0xf5, 0x1c, 0xbb, 0x0d, 0x36, 0x8f, 0x3a, 0xb7, 0x19, 0x53, 0x3c, 0xe9, 0x92, 0x4a, 0xbc,
+  0x5f, 0xad, 0x83, 0xbc, 0xb5, 0x94, 0x05, 0xb9, 0xc3, 0x5e, 0xd4, 0xbb, 0x19, 0x7a, 0x14, 0xbc,
+  0x1b, 0x16, 0x16, 0xbb, 0x01, 0xfc, 0x3e, 0x3c, 0x30, 0x63, 0x59, 0xbc, 0x80, 0x30, 0x2f, 0x3c,
+  0xad, 0x34, 0x4b, 0x3c, 0xce, 0x24, 0x62, 0x3c, 0x98, 0xb4, 0xef, 0xbb, 0x57, 0x01, 0xa0, 0xbb,
+  0x03, 0xba, 0x29, 0xbc, 0x42, 0xd7, 0x2c, 0x3c, 0xcf, 0x61, 0x11, 0x3b, 0xbd, 0x08, 0x86, 0xbc,
+  0x87, 0xce, 0x18, 0xbb, 0xfd, 0x2a, 0x3a, 0x3c, 0x70, 0x72, 0xae, 0xbb, 0x54, 0x6f, 0x5f, 0xbc,
+  0xce, 0xfc, 0x82, 0xba, 0x4f, 0x51, 0x6d, 0xbc, 0x4c, 0x17, 0x52, 0x3c, 0x94, 0x06, 0x59, 0x3c,
+  0xdb, 0x60, 0xb5, 0x3b, 0x5c, 0xc9, 0x3a, 0xbc, 0x19, 0x10, 0x6e, 0x3a, 0x46, 0x89, 0x0f, 0xbc,
+  0x93, 0xc5, 0x2b, 0xbb, 0x51, 0x7b, 0x58, 0x3b, 0xdc, 0x75, 0x8c, 0x3c, 0x62, 0x63, 0xe0, 0xbb,
+  0x06, 0xde, 0x36, 0xbc, 0x5c, 0xcf, 0x43, 0xbb, 0x77, 0xd9, 0xce, 0x3b, 0x7d, 0x88, 0x23, 0x3b,
+  0x5d, 0xac, 0xed, 0xbb, 0x9f, 0x73, 0xc6, 0x3a, 0x7a, 0xc0, 0x90, 0xba, 0x60, 0x1b, 0x99, 0xbb,
+  0xb1, 0x5c, 0x45, 0x3c, 0xbe, 0xb8, 0x33, 0x3b, 0x65, 0xda, 0xe1, 0xb9, 0x37, 0xb9, 0x4c, 0xbb,
+  0x5a, 0xc0, 0x07, 0x3b, 0xf1, 0x06, 0x23, 0xbb, 0xce, 0x01, 0x23, 0x3c, 0x45, 0xd3, 0x01, 0xbc,
+  0xc8, 0xc4, 0xeb, 0xbb, 0x20, 0xb4, 0x77, 0xbb, 0x96, 0x7e, 0x33, 0xbc, 0x86, 0x16, 0x70, 0xbc,
+  0x53, 0x9d, 0x00, 0x3c, 0x46, 0xff, 0xfe, 0x3a, 0xba, 0x46, 0xf2, 0xba, 0xa0, 0x89, 0x4f, 0xbc,
+  0xd7, 0x80, 0x76, 0x3c, 0xdb, 0xad, 0x13, 0xbc, 0x69, 0x9f, 0xa7, 0x3b, 0x9e, 0x07, 0x03, 0xbc,
+  0x9f, 0x9e, 0x69, 0xb4, 0xaf, 0x04, 0x69, 0x3c, 0x6c, 0x82, 0x48, 0xbc, 0x08, 0x38, 0x2b, 0x3c,
+  0x34, 0x16, 0xcc, 0xbb, 0x92, 0x6f, 0x85, 0x3b, 0xa0, 0x43, 0xbb, 0xba, 0x5e, 0xb6, 0x81, 0x3b,
+  0x0f, 0x2a, 0x75, 0x3b, 0xbf, 0x7e, 0x49, 0x3b, 0xa5, 0xcb, 0x48, 0x3b, 0xfb, 0xa0, 0x88, 0x3c,
+  0x9a, 0x26, 0x7f, 0xbc, 0x43, 0x3b, 0x01, 0xbb, 0xdf, 0xc8, 0x7c, 0x3b, 0x89, 0xe7, 0xbb, 0xbb,
+  0x72, 0xeb, 0x28, 0xbc, 0x11, 0xea, 0xb7, 0x3b, 0x87, 0x4a, 0xe0, 0xbb, 0xdd, 0x95, 0x4c, 0xbc,
+  0x35, 0x9b, 0x3a, 0x3c, 0xd1, 0x95, 0xb2, 0xbb, 0x41, 0x9c, 0x77, 0x3a, 0xe9, 0x83, 0x52, 0xbb,
+  0x15, 0x9f, 0x1d, 0x3d, 0xa9, 0x91, 0x8a, 0x3b, 0xa4, 0xeb, 0xeb, 0x39, 0xa2, 0x69, 0x95, 0xbc,
+  0x44, 0x6d, 0xab, 0x3b, 0xf3, 0xc9, 0x19, 0x3b, 0x47, 0xc0, 0x0a, 0x3c, 0xfa, 0x66, 0x39, 0x3c,
+  0x07, 0xaf, 0x06, 0xbc, 0xd9, 0xeb, 0x07, 0x3b, 0xac, 0x73, 0xd8, 0x3b, 0xa4, 0xd4, 0x98, 0xbc,
+  0x88, 0x9e, 0x8a, 0xb9, 0x0f, 0xf4, 0x8d, 0xbc, 0x8b, 0x5a, 0x9f, 0xbb, 0xc0, 0x76, 0x30, 0x3c,
+  0x84, 0xeb, 0x63, 0xbb, 0x37, 0xc5, 0xc0, 0xbb, 0xba, 0x16, 0x1a, 0xbc, 0xff, 0x64, 0xc9, 0xb9,
+  0x19, 0x98, 0x2f, 0xbc, 0x0e, 0x6f, 0x48, 0xbc, 0xc9, 0x16, 0x4a, 0xbb, 0xff, 0x31, 0x97, 0x3b,
+  0x05, 0xb9, 0x17, 0xbc, 0xb2, 0xce, 0x04, 0xbc, 0x46, 0x29, 0x3e, 0x3a, 0x3b, 0xe5, 0xfb, 0xbb,
+  0xbd, 0xca, 0x91, 0x3c, 0xda, 0x11, 0x83, 0x3c, 0x5e, 0x70, 0xed, 0xbb, 0x4b, 0x42, 0x93, 0x3c,
+  0x56, 0x8d, 0xa8, 0xbb, 0xe4, 0xed, 0x16, 0xbc, 0x16, 0x14, 0x91, 0x3b, 0x3f, 0x91, 0x2e, 0xbc,
+  0x25, 0x7f, 0x29, 0xbc, 0x54, 0x23, 0x8e, 0x3c, 0x28, 0xd0, 0x33, 0xbb, 0xad, 0x0a, 0x05, 0x3c,
+  0x17, 0x36, 0x01, 0xbb, 0xe4, 0x7c, 0x80, 0xbc, 0x95, 0x45, 0xce, 0xbb, 0x29, 0x89, 0x96, 0x3b,
+  0x61, 0xeb, 0x9c, 0x3c, 0x45, 0xb5, 0xb7, 0x3b, 0xa3, 0x6e, 0x46, 0x3c, 0x02, 0x9e, 0x1b, 0xba,
+  0xcd, 0x09, 0xa5, 0xbb, 0xc1, 0xd2, 0xa3, 0xbc, 0xef, 0x69, 0xd6, 0x3b, 0x6e, 0x69, 0x6a, 0xbc,
+  0x5e, 0xf8, 0xa3, 0x3c, 0x13, 0x04, 0x43, 0x3b, 0xb4, 0x35, 0x3e, 0xbb, 0x55, 0x32, 0xcb, 0x3a,
+  0x2f, 0x49, 0x5e, 0xbb, 0x7a, 0xa8, 0x4b, 0xbc, 0x83, 0x89, 0x04, 0xbc, 0xf2, 0x1d, 0x8b, 0x3c,
+  0x19, 0x78, 0x5c, 0xbb, 0xd0, 0x2a, 0x4a, 0xbb, 0xdc, 0x85, 0x4d, 0xbc, 0x2e, 0xbd, 0x5a, 0xba,
+  0x6d, 0xed, 0xff, 0xba, 0x71, 0xc7, 0x9d, 0x3a, 0x76, 0xee, 0x3a, 0x3b, 0x2d, 0x0f, 0x4e, 0x3c,
+  0x0c, 0xa1, 0x68, 0xbb, 0x62, 0xc5, 0x74, 0x3b, 0xb9, 0xfe, 0x7b, 0xbc, 0xb7, 0x3f, 0x54, 0xbc,
+  0x33, 0x06, 0x35, 0xba, 0x84, 0x3c, 0x25, 0x3b, 0x0a, 0x0c, 0xed, 0x39, 0x7b, 0x23, 0x42, 0xbc,
+  0x2b, 0x22, 0x0b, 0x3c, 0x88, 0x6b, 0x73, 0x3a, 0x60, 0xd4, 0x64, 0x3c, 0x64, 0x59, 0x1f, 0x3b,
+  0x69, 0xb9, 0xae, 0x3a, 0x95, 0x8a, 0x26, 0x3b, 0x10, 0x81, 0xa5, 0x3b, 0x3c, 0xa7, 0x0e, 0xbc,
+  0x06, 0xd1, 0x11, 0xbc, 0x35, 0x05, 0xef, 0xba, 0xbb, 0x99, 0xeb, 0x3b, 0x87, 0x3b, 0xc9, 0xbb,
+  0x43, 0xb8, 0x89, 0x3a, 0xfb, 0x74, 0x7d, 0xbc, 0x1c, 0xf9, 0x20, 0x3c, 0x94, 0xa2, 0x80, 0xbc,
+  0xfa, 0x74, 0x5e, 0x3a, 0x94, 0x61, 0x17, 0xbc, 0xe4, 0xee, 0xff, 0x3b, 0xa7, 0xe8, 0x94, 0x3c,
+  0x0b, 0x44, 0x08, 0xbc, 0xb8, 0xe8, 0xc6, 0x3b, 0x20, 0x26, 0x47, 0x3b, 0xdd, 0xa8, 0x0f, 0xbc,
+  0x45, 0x45, 0x08, 0xbc, 0xeb, 0x9b, 0x97, 0xbb, 0xdd, 0x2f, 0x24, 0xbc, 0x23, 0x87, 0x07, 0x3c,
+  0xca, 0xea, 0x93, 0x3b, 0x6d, 0x8a, 0xb9, 0xbb, 0x2c, 0x57, 0x90, 0xbb, 0x2d, 0x7b, 0x37, 0x3b,
+  0x37, 0x0c, 0xf0, 0x3b, 0x14, 0x9d, 0x1d, 0x3a, 0x8c, 0x01, 0xa5, 0x3c, 0x46, 0x70, 0xb2, 0x3b,
+  0xbb, 0x19, 0x9f, 0x39, 0x16, 0x18, 0x89, 0xbc, 0x36, 0x8e, 0x09, 0xbb, 0xbf, 0x29, 0xc3, 0xbb,
+  0xf1, 0x88, 0xef, 0xbb, 0x21, 0xf7, 0x31, 0x3c, 0xa2, 0x25, 0xad, 0x3a, 0x72, 0x62, 0xf1, 0x3a,
+  0x81, 0xc2, 0x4e, 0x3b, 0xf5, 0x7c, 0xfb, 0xba, 0x9b, 0xb6, 0x86, 0x3c, 0xdf, 0x65, 0xe1, 0xba,
+  0xdb, 0x17, 0x84, 0xbc, 0x27, 0x8a, 0x6f, 0xba, 0x17, 0x61, 0xad, 0x3b, 0x3a, 0xed, 0xa4, 0x3a,
+  0xa2, 0xcf, 0xcd, 0xbb, 0xcb, 0x74, 0x20, 0xbb, 0xef, 0x08, 0xc2, 0x3b, 0x36, 0x3f, 0x92, 0x3c,
+  0xa9, 0x79, 0xe8, 0x3a, 0x9e, 0x7b, 0x42, 0x3c, 0x3b, 0x46, 0x0a, 0x3b, 0x3f, 0xfd, 0xd5, 0x3a,
+  0x75, 0x5a, 0x0f, 0x3a, 0x29, 0x8e, 0x2e, 0xbb, 0x07, 0x62, 0x0f, 0xbb, 0xcb, 0xde, 0x8e, 0xbb,
+  0x7c, 0xfc, 0xa0, 0xbb, 0x0d, 0x51, 0xde, 0x3b, 0x2c, 0x1b, 0x21, 0x3c, 0xba, 0x7c, 0xd5, 0x3b,
+  0x19, 0x90, 0x89, 0x3b, 0xc9, 0x98, 0x7b, 0xb9, 0x06, 0xcf, 0x45, 0x3b, 0x6a, 0x67, 0x44, 0xbb,
+  0x5a, 0x4f, 0x13, 0xbb, 0x57, 0x9d, 0x6c, 0x3c, 0x9f, 0x37, 0x28, 0xbb, 0xa4, 0x07, 0x28, 0x3b,
+  0x67, 0x1a, 0x86, 0x3c, 0xef, 0xc2, 0x4e, 0xbb, 0xf0, 0x99, 0x51, 0xba, 0xdc, 0xa7, 0x8d, 0xbb,
+  0x53, 0x6b, 0x64, 0x3c, 0xb1, 0x83, 0x11, 0xbc, 0x05, 0x72, 0x81, 0xbc, 0x66, 0xb8, 0x3f, 0x3c,
+  0xe5, 0xfb, 0x8b, 0x3b, 0x78, 0x8f, 0x25, 0xbc, 0x1b, 0xb4, 0x05, 0xbc, 0x25, 0x32, 0xfe, 0x3a,
+  0xbd, 0xef, 0x10, 0x3c, 0x86, 0xa5, 0x2f, 0xbc, 0xa0, 0x34, 0x80, 0xbc, 0x11, 0x05, 0x18, 0xbb,
+  0xb0, 0xcf, 0x94, 0xbc, 0x9b, 0x9c, 0xa2, 0xbb, 0xa5, 0xe3, 0x80, 0xbc, 0xa1, 0xb9, 0x31, 0x3c,
+  0xf2, 0xd1, 0x04, 0xbc, 0x29, 0x0a, 0x08, 0xbc, 0x0c, 0x4e, 0x75, 0xbc, 0x02, 0x21, 0x49, 0x3c,
+  0xf2, 0xfc, 0x96, 0xbc, 0x4c, 0x96, 0x67, 0xbc, 0xf5, 0x98, 0x6e, 0xbc, 0x69, 0x8e, 0xdf, 0xba,
+  0x8d, 0x44, 0x18, 0x3b, 0xf5, 0x8c, 0x02, 0x3c, 0x33, 0x62, 0x9a, 0xbb, 0xa0, 0x4b, 0x0e, 0xbc,
+  0x87, 0xdf, 0x38, 0xbc, 0xac, 0xe7, 0xd8, 0xbb, 0x7c, 0xad, 0x71, 0xbc, 0xc5, 0x86, 0x6e, 0x3b,
+  0xc0, 0x5a, 0x93, 0x3c, 0x9a, 0xcc, 0x07, 0x3b, 0x9e, 0x75, 0x11, 0xbc, 0xfe, 0x04, 0xb2, 0x3a,
+  0x02, 0xb7, 0x7e, 0xbc, 0xd9, 0xf4, 0x1a, 0xbb, 0x92, 0x50, 0x0d, 0xbc, 0x05, 0x0f, 0xb5, 0x3b,
+  0x7e, 0x9e, 0x0a, 0xbc, 0x28, 0x6d, 0xa1, 0xbb, 0x89, 0xea, 0x0c, 0x3b, 0x59, 0xa8, 0xaf, 0x3c,
+  0xf0, 0xc6, 0xd4, 0xbb, 0x5e, 0xad, 0xae, 0xbc, 0x9a, 0xbd, 0xb6, 0xbb, 0xbb, 0x4f, 0x7e, 0xbc,
+  0xd7, 0x52, 0x84, 0xbb, 0x63, 0x6a, 0xc3, 0x3b, 0x6f, 0xcb, 0x98, 0xba, 0x83, 0xb0, 0x07, 0x3c,
+  0x62, 0x46, 0xb4, 0x3b, 0xb7, 0x16, 0xa1, 0xbc, 0xf1, 0xf1, 0xb7, 0xba, 0xa8, 0x53, 0x3a, 0x3c,
+  0x08, 0xaf, 0x4e, 0x3b, 0x4e, 0x84, 0xd0, 0x3b, 0x4c, 0x8d, 0x62, 0x3b, 0x1b, 0xdc, 0x7b, 0x3b,
+  0x0c, 0x96, 0xb4, 0xbb, 0x0b, 0x29, 0xe3, 0xbc, 0x56, 0x83, 0xa4, 0x3b, 0x1f, 0x53, 0xa0, 0x3b,
+  0x0e, 0x5a, 0x75, 0x3c, 0xd3, 0x8e, 0xb5, 0x3b, 0x58, 0xdc, 0xbc, 0xbb, 0x67, 0xa1, 0x62, 0x3c,
+  0x09, 0x51, 0x42, 0x3a, 0x39, 0x39, 0xa7, 0x3b, 0xee, 0x73, 0x89, 0x3b, 0xff, 0xd7, 0xe2, 0x3b,
+  0x6f, 0x40, 0x82, 0x3c, 0xbb, 0xa5, 0x15, 0xba, 0x70, 0x9d, 0x36, 0x3c, 0x07, 0xa7, 0xa8, 0x3b,
+  0x8a, 0x76, 0xca, 0x3b, 0x7a, 0x7c, 0xdb, 0xbb, 0x49, 0x2f, 0x16, 0xbc, 0x92, 0x1d, 0xa2, 0xbc,
+  0xcd, 0xef, 0x96, 0x3b, 0xf5, 0xc1, 0x71, 0xbb, 0x84, 0xf5, 0x9f, 0x3a, 0x12, 0x5d, 0x2f, 0x3b,
+  0xad, 0xc5, 0x49, 0xbb, 0xe3, 0x12, 0x55, 0xbc, 0x63, 0x91, 0xb9, 0xba, 0xce, 0x15, 0xab, 0x3a,
+  0x6e, 0xe7, 0x1f, 0x3c, 0xde, 0x7f, 0xea, 0x3b, 0x73, 0x86, 0x33, 0xbc, 0x86, 0xd9, 0x4d, 0x3c,
+  0xe7, 0x4f, 0xbe, 0xbb, 0xfa, 0x5f, 0x93, 0xbc, 0x00, 0x98, 0x05, 0x3a, 0xc8, 0x17, 0x4b, 0xbc,
+  0x04, 0xb5, 0x8d, 0x3b, 0x65, 0xff, 0x35, 0x3b, 0xf3, 0x59, 0x03, 0x3c, 0xae, 0x55, 0xc6, 0x3b,
+  0x5b, 0x10, 0xca, 0xba, 0xfc, 0x08, 0x23, 0xbc, 0x64, 0x3a, 0x2e, 0x3c, 0x02, 0x1a, 0x89, 0x3c,
+  0x6c, 0x00, 0x3d, 0xbb, 0xed, 0xa9, 0xe0, 0xb8, 0x66, 0x1e, 0xaf, 0x3b, 0x7a, 0x8c, 0x35, 0x3c,
+  0x8c, 0x7a, 0x8c, 0xbb, 0x19, 0x20, 0x94, 0xbc, 0x99, 0x0e, 0x9f, 0xbc, 0xff, 0x17, 0x51, 0x3c,
+  0x3b, 0x35, 0x3d, 0xbb, 0x7a, 0xd6, 0x8e, 0x39, 0xb5, 0x9f, 0xad, 0x3a, 0x31, 0xa8, 0x13, 0x3b,
+  0xd1, 0x52, 0x90, 0xba, 0x18, 0x8b, 0xa6, 0xbc, 0x55, 0x1e, 0x84, 0x3a, 0xb8, 0x06, 0x0e, 0xbc,
+  0x58, 0xf8, 0x0f, 0xbc, 0xd4, 0xe2, 0x96, 0x3a, 0x00, 0xe3, 0xce, 0xbb, 0x3c, 0x92, 0x45, 0x3b,
+  0x7d, 0xa5, 0x11, 0xbc, 0x12, 0xd9, 0xa3, 0x3a, 0xd5, 0x7c, 0x1a, 0xbc, 0x0e, 0xa4, 0x34, 0x3a,
+  0x0c, 0xfc, 0xe0, 0xbb, 0xa6, 0x00, 0xec, 0x3b, 0x6d, 0x8c, 0x28, 0x3b, 0xbc, 0x92, 0x35, 0x3c,
+  0x78, 0xfe, 0xa5, 0x3b, 0x7e, 0x82, 0x2a, 0xbb, 0xaa, 0xff, 0xeb, 0x3b, 0x52, 0x9d, 0x17, 0x3b,
+  0xb4, 0xdb, 0xc2, 0x3a, 0x1c, 0xd9, 0x17, 0x3c, 0x16, 0xb2, 0x87, 0xb9, 0xab, 0x69, 0x32, 0x3b,
+  0x2e, 0x78, 0x97, 0x3a, 0xde, 0x93, 0xa9, 0xbb, 0x78, 0x37, 0xb7, 0xbb, 0xc6, 0x8e, 0x3e, 0x3c,
+  0x7e, 0x3c, 0xa8, 0x3c, 0xa8, 0x62, 0xf5, 0xbb, 0x92, 0xb5, 0x5e, 0xb9, 0x3f, 0x94, 0x31, 0x3c,
+  0x64, 0xb5, 0x01, 0xbb, 0x5e, 0x55, 0xd4, 0xba, 0x06, 0xc6, 0x16, 0x3b, 0xb0, 0xd0, 0xb1, 0x3b,
+  0xd3, 0xa5, 0xd9, 0x3b, 0x94, 0xce, 0x1d, 0x3c, 0x67, 0xfe, 0x76, 0xbc, 0x9d, 0x86, 0x8c, 0x3c,
+  0xf5, 0x60, 0x84, 0x3b, 0xaa, 0xb4, 0x8c, 0x3c, 0xce, 0x77, 0x4c, 0xbc, 0xda, 0xf6, 0x22, 0xbc,
+  0x61, 0x3c, 0x80, 0x3c, 0x00, 0x8d, 0x0c, 0x3c, 0x82, 0x7a, 0x2b, 0xbb, 0x28, 0xab, 0x0e, 0x3c,
+  0x74, 0xda, 0x41, 0xbc, 0x14, 0x91, 0xb9, 0xbb, 0x17, 0xdf, 0x39, 0xbc, 0x72, 0xd8, 0xd4, 0x3b,
+  0xe4, 0xb9, 0x3d, 0x3c, 0x03, 0x3a, 0x10, 0xbc, 0xdc, 0x0b, 0xab, 0xbb, 0x31, 0x33, 0xca, 0xbb,
+  0x44, 0x30, 0x99, 0xbc, 0x3b, 0xae, 0xcf, 0xbb, 0x96, 0xcd, 0x8f, 0xbc, 0xa9, 0x30, 0x1e, 0xbc,
+  0xe8, 0x51, 0xbb, 0x3b, 0xf8, 0x3b, 0x6a, 0x3c, 0xfb, 0xeb, 0xbf, 0xbc, 0x13, 0x53, 0x1b, 0x3c,
+  0x10, 0xe4, 0x90, 0xbc, 0xc3, 0xf7, 0x66, 0xbc, 0xb0, 0xff, 0x8d, 0xbc, 0x53, 0xda, 0x8d, 0x3a,
+  0x48, 0xcf, 0xbb, 0x3b, 0x72, 0xc1, 0x10, 0xbb, 0x9d, 0xc1, 0x91, 0xbc, 0xe3, 0xb7, 0x52, 0x3c,
+  0x1a, 0xcb, 0xbc, 0xbc, 0x4a, 0xeb, 0x94, 0xba, 0x80, 0x73, 0x67, 0xbb, 0x59, 0xeb, 0x8a, 0xba,
+  0x3e, 0x03, 0xa5, 0x3c, 0x06, 0xef, 0xa5, 0xbb, 0x51, 0x77, 0x79, 0xb9, 0x47, 0x21, 0xa9, 0x3b,
+  0x76, 0xf1, 0xc6, 0xbc, 0xb2, 0xbf, 0x7b, 0xbc, 0xc7, 0x06, 0x6c, 0xbc, 0x6d, 0x72, 0xdb, 0x3b,
+  0xfd, 0x06, 0xe2, 0x3a, 0x36, 0x91, 0x7c, 0xbb, 0xbd, 0x94, 0x93, 0xbc, 0xcb, 0x9a, 0x58, 0x3c,
+  0xa8, 0x48, 0x55, 0xbc, 0xc6, 0x7e, 0xf2, 0x3b, 0x72, 0x36, 0x3f, 0xbc, 0xee, 0x2b, 0xb7, 0xbb,
+  0xd0, 0xba, 0x85, 0xbb, 0xa4, 0x46, 0x28, 0x3c, 0x5e, 0xd9, 0x33, 0x3b, 0x1b, 0x81, 0x71, 0xbb,
+  0x85, 0xb9, 0x91, 0x3a, 0xe9, 0x65, 0x8c, 0xbb, 0x4a, 0xbb, 0xe6, 0x3b, 0x66, 0xe6, 0x1d, 0xbb,
+  0xd9, 0x2d, 0x36, 0x3c, 0x52, 0xd3, 0x4e, 0xbb, 0x12, 0x1a, 0x93, 0xbc, 0x70, 0xf8, 0x10, 0x3a,
+  0xb5, 0x8e, 0x95, 0xbc, 0xec, 0x22, 0xba, 0xbc, 0x68, 0x6a, 0x9a, 0xbb, 0xa2, 0x13, 0x4a, 0x3a,
+  0xad, 0x3f, 0xc4, 0xba, 0x5e, 0xf5, 0x2e, 0x3c, 0x52, 0x64, 0xf0, 0xbb, 0x56, 0x3b, 0x5c, 0xbc,
+  0xe9, 0x9f, 0x42, 0xbb, 0xec, 0x0d, 0x68, 0x3b, 0x75, 0xb6, 0x0e, 0xbc, 0x8e, 0x61, 0xa2, 0x3b,
+  0xdc, 0xd5, 0xc7, 0xbb, 0xa5, 0xd7, 0xba, 0xba, 0xc2, 0xb7, 0xe2, 0xbb, 0xe9, 0x31, 0x88, 0x3c,
+  0x01, 0xa1, 0xfd, 0xbb, 0x2b, 0x0b, 0x75, 0xbc, 0x06, 0x4f, 0x97, 0x3b, 0x16, 0xab, 0x49, 0x3c,
+  0x8d, 0xc0, 0x0a, 0x3c, 0x5e, 0xec, 0x71, 0x3c, 0x0d, 0xd1, 0x01, 0xbc, 0x88, 0x8b, 0x97, 0x3c,
+  0xf3, 0xe2, 0x86, 0x3b, 0x28, 0xa6, 0xf1, 0xbb, 0x68, 0x51, 0xb6, 0x3b, 0xf0, 0x7f, 0x11, 0x3c,
+  0x16, 0xba, 0x8a, 0x3c, 0x04, 0x59, 0xbd, 0xba, 0xf6, 0xa7, 0xa9, 0xbb, 0xf9, 0x8a, 0xcc, 0x3a,
+  0xed, 0xbc, 0x40, 0xba, 0x17, 0xaf, 0x88, 0x3b, 0xd5, 0x92, 0xcf, 0xba, 0xac, 0xf2, 0x2a, 0x3c,
+  0xec, 0x96, 0x84, 0xbb, 0x37, 0x4e, 0x6a, 0x3b, 0xde, 0xc4, 0x75, 0x3b, 0x12, 0x12, 0x91, 0x3c,
+  0x97, 0x52, 0x7f, 0x3b, 0x8c, 0x4c, 0x6e, 0xbb, 0x92, 0xeb, 0x96, 0xbb, 0x6a, 0x70, 0xa2, 0x3b,
+  0x0b, 0x1c, 0xf1, 0xbb, 0x0a, 0x8e, 0xac, 0xbb, 0x42, 0xd6, 0x55, 0x3b, 0x03, 0x36, 0x94, 0x3b,
+  0x0c, 0x88, 0x13, 0x3b, 0xca, 0x8b, 0xcd, 0xbc, 0x2c, 0x21, 0x84, 0xbb, 0xf3, 0xc9, 0x82, 0x3b,
+  0xb2, 0x45, 0x16, 0x3c, 0xa7, 0xec, 0x5c, 0xbb, 0x6a, 0x31, 0x65, 0x3c, 0x2f, 0x6f, 0x08, 0x3c,
+  0xd3, 0x6d, 0xea, 0x3b, 0x0d, 0x8c, 0x8d, 0xbc, 0xc7, 0xce, 0x0c, 0xbc, 0xd8, 0x33, 0xcf, 0xbb,
+  0xd5, 0x09, 0x97, 0x3c, 0x20, 0x63, 0x53, 0xbb, 0xf3, 0x74, 0x5e, 0xbb, 0x80, 0x68, 0x86, 0x3c,
+  0x1d, 0xea, 0x44, 0xbb, 0x47, 0xc7, 0xc5, 0x3b, 0xb5, 0x6c, 0x6e, 0xbc, 0x00, 0x62, 0x15, 0x3c,
+  0x6b, 0x03, 0x2b, 0xbb, 0x60, 0x07, 0x07, 0x3c, 0xc4, 0xdb, 0xbd, 0x3a, 0x98, 0xd3, 0x68, 0x3c,
+  0x24, 0x55, 0xe7, 0xb9, 0x90, 0xe0, 0x0d, 0xbb, 0x66, 0xab, 0x14, 0xbc, 0xdc, 0x5b, 0xe6, 0xbb,
+  0xcb, 0x8e, 0xd4, 0x3b, 0x3a, 0x04, 0xaf, 0x3b, 0xae, 0x4d, 0xe8, 0x3b, 0x00, 0x22, 0x37, 0x39,
+  0xfe, 0x24, 0x3e, 0x3b, 0x87, 0x3d, 0x77, 0xbc, 0x56, 0x4a, 0x27, 0x3c, 0x2e, 0x09, 0xc7, 0xbb,
+  0xec, 0xb0, 0x16, 0x3c, 0xcc, 0x54, 0xe2, 0xba, 0x03, 0x99, 0x3b, 0x3c, 0xb0, 0xed, 0x67, 0xbb,
+  0x12, 0xc7, 0x02, 0xba, 0x5b, 0x99, 0x89, 0x3b, 0xaf, 0xb9, 0x40, 0xbb, 0xa1, 0xad, 0x74, 0x3c,
+  0x01, 0xd1, 0x0f, 0x3c, 0x96, 0xb6, 0x56, 0xbc, 0xdf, 0x5c, 0x6d, 0xbc, 0x52, 0x89, 0x3c, 0x3b,
+  0xb3, 0x22, 0x5b, 0xbb, 0x35, 0xb9, 0xc3, 0xbb, 0xb8, 0x1d, 0x5a, 0x3b, 0xaa, 0xca, 0x25, 0x3c,
+  0xa7, 0x50, 0xb2, 0x3b, 0xe5, 0xc9, 0xfe, 0x3a, 0x3d, 0x76, 0x8f, 0xbc, 0x45, 0x3d, 0xd3, 0x3b,
+  0xe4, 0xc8, 0x27, 0xbc, 0x12, 0x44, 0xc5, 0xbb, 0x30, 0x47, 0x4f, 0xbc, 0x55, 0xff, 0x4a, 0x3b,
+  0xe1, 0x9f, 0x51, 0xbc, 0x81, 0xb8, 0x0d, 0xbc, 0x37, 0x76, 0x9c, 0xbc, 0xf5, 0xde, 0x84, 0x3c,
+  0xc0, 0x58, 0x9e, 0xbc, 0xfd, 0xcf, 0xf5, 0x3b, 0x99, 0x3c, 0x29, 0xbc, 0xb3, 0x4d, 0x50, 0xbb,
+  0x53, 0x18, 0x59, 0x3c, 0xe2, 0xc0, 0x8a, 0xbb, 0x04, 0xd1, 0xb0, 0xbc, 0x12, 0x80, 0x02, 0x3c,
+  0xd3, 0x17, 0xef, 0xbc, 0x40, 0xdc, 0x75, 0xbb, 0xeb, 0x75, 0x85, 0xbc, 0x37, 0xd3, 0x14, 0x3b,
+  0x85, 0xec, 0x14, 0x39, 0xa1, 0x27, 0x4f, 0xbc, 0xdd, 0x04, 0x53, 0x3b, 0x00, 0x28, 0xa9, 0xba,
+  0xd5, 0x96, 0xb0, 0xbc, 0x4c, 0x08, 0xc5, 0x3a, 0x5a, 0x3d, 0x2b, 0xbc, 0x87, 0x20, 0x7b, 0xbc,
+  0x48, 0xeb, 0x16, 0x3c, 0xd1, 0x99, 0x1e, 0x3c, 0x4b, 0xd2, 0xbf, 0xbc, 0x7a, 0xcd, 0x22, 0xbc,
+  0xc8, 0x6e, 0xc6, 0xbc, 0x25, 0x79, 0xb1, 0xbc, 0x2e, 0xa2, 0x84, 0xbc, 0x3a, 0x0d, 0xa7, 0xbb,
+  0x7a, 0x2b, 0xf5, 0xbb, 0xa9, 0x53, 0xb5, 0x3b, 0x8d, 0x51, 0xc2, 0x3b, 0xb0, 0xb3, 0x48, 0xbb,
+  0x4a, 0x31, 0x27, 0xbc, 0xac, 0x08, 0xb2, 0xbc, 0xb1, 0x10, 0x10, 0xbb, 0xcb, 0x82, 0xbb, 0xba,
+  0x6b, 0x2b, 0x6d, 0x3b, 0x17, 0x5d, 0x52, 0xbb, 0xb4, 0x24, 0xc2, 0xbb, 0x3c, 0x1c, 0xfd, 0x3b,
+  0xf0, 0xd1, 0x39, 0xbb, 0x4b, 0x19, 0xb2, 0xbc, 0xf4, 0xf2, 0xbd, 0xbb, 0xfb, 0x54, 0x04, 0x3c,
+  0x7e, 0x4d, 0x05, 0x3c, 0xe5, 0x44, 0x84, 0xbb, 0x18, 0xf9, 0x07, 0xbc, 0xf0, 0x7f, 0x83, 0xbb,
+  0x49, 0xb9, 0x7c, 0xbb, 0x74, 0x53, 0xe4, 0xbb, 0x36, 0x9a, 0xf4, 0xba, 0x19, 0x4b, 0x6f, 0xbc,
+  0x43, 0x60, 0x94, 0xbb, 0x55, 0xf2, 0x0e, 0x3c, 0x2d, 0x0e, 0x0b, 0x3b, 0x89, 0x26, 0xbf, 0xbb,
+  0x3f, 0x89, 0x15, 0xbb, 0xda, 0xa1, 0x14, 0xbc, 0x0f, 0xcf, 0x02, 0xbc, 0x66, 0x7b, 0xc0, 0x3b,
+  0xd8, 0x61, 0xa3, 0xba, 0x91, 0xc1, 0x59, 0x3c, 0xc3, 0x3e, 0x96, 0xba, 0x95, 0xbe, 0xd8, 0x3b,
+  0x24, 0x2e, 0xcc, 0xba, 0x4b, 0x20, 0x6d, 0xbc, 0xa1, 0x98, 0x7b, 0xba, 0x6a, 0x86, 0x96, 0x3b,
+  0x21, 0xb7, 0x74, 0x3a, 0x44, 0x77, 0x88, 0xba, 0xfa, 0xa9, 0x4a, 0xbc, 0x97, 0xcf, 0x73, 0x3c,
+  0x9a, 0x98, 0x07, 0xbc, 0x62, 0x78, 0x54, 0xbc, 0xf1, 0x4e, 0x4d, 0xbc, 0xd3, 0xb0, 0x7e, 0xbb,
+  0x60, 0x80, 0x29, 0x3c, 0x33, 0xe3, 0x99, 0x3c, 0xae, 0x4b, 0x39, 0xbc, 0x90, 0x0d, 0x78, 0x3c,
+  0xbb, 0xdc, 0x28, 0x3b, 0x03, 0x98, 0x66, 0xbc, 0x9a, 0xd0, 0xf2, 0xbb, 0x71, 0xe0, 0x05, 0xbc,
+  0x75, 0x39, 0x0d, 0xbc, 0x89, 0x74, 0x17, 0xbc, 0x15, 0xdb, 0xce, 0x3b, 0x1d, 0xde, 0x08, 0x3c,
+  0x3f, 0x57, 0x30, 0x3c, 0x01, 0x40, 0x22, 0xbb, 0x45, 0x0e, 0xcc, 0xbb, 0x1f, 0x7e, 0xab, 0xb9,
+  0x86, 0xfb, 0x1a, 0x3c, 0x28, 0x5b, 0xa8, 0x39, 0x14, 0xa4, 0x29, 0xba, 0x42, 0x0d, 0x26, 0x3c,
+  0x59, 0x1c, 0xf7, 0x3b, 0xeb, 0xb8, 0x9c, 0x3a, 0xca, 0x2c, 0x53, 0xbc, 0x1b, 0x92, 0x9b, 0x3c,
+  0x23, 0xa6, 0xa0, 0x3c, 0xdb, 0x55, 0x18, 0x3c, 0xee, 0x6d, 0x15, 0x3c, 0x97, 0xe4, 0x2e, 0x3c,
+  0x9d, 0xa2, 0x4a, 0xbc, 0x96, 0x26, 0x14, 0x39, 0x6d, 0xf7, 0xb2, 0xbc, 0x40, 0xdc, 0x96, 0x3c,
+  0xf2, 0x51, 0xa1, 0xba, 0x91, 0x14, 0xc2, 0x3a, 0xc8, 0xd2, 0xea, 0x3a, 0x94, 0xbb, 0x1d, 0x3b,
+  0x76, 0x95, 0x4c, 0x3b, 0xf8, 0xa5, 0x42, 0x3b, 0x56, 0xf9, 0xef, 0xbb, 0xe6, 0x04, 0xd8, 0x3b,
+  0xd2, 0x19, 0x28, 0x3b, 0x56, 0xce, 0xcb, 0x3b, 0x45, 0xa5, 0x6c, 0xbc, 0xa0, 0x35, 0xf0, 0x3b,
+  0xad, 0x43, 0x82, 0x3a, 0xb6, 0x70, 0x71, 0xbc, 0x7b, 0x07, 0x63, 0x3b, 0xd0, 0xef, 0x91, 0xbb,
+  0xca, 0x7a, 0x5b, 0x3c, 0x95, 0xf5, 0x36, 0xbb, 0x6d, 0xa8, 0x1b, 0x3c, 0x67, 0x18, 0xbe, 0x3c,
+  0x5d, 0x48, 0x8e, 0xbb, 0x8d, 0x89, 0x0d, 0xbc, 0x40, 0xca, 0x29, 0xb9, 0xa8, 0x8f, 0x47, 0xbb,
+  0x97, 0x6e, 0xf0, 0x3c, 0x53, 0x0b, 0x3f, 0x3b, 0x9a, 0xbc, 0x57, 0x3c, 0xe0, 0x29, 0x02, 0x3b,
+  0x21, 0xbf, 0x2c, 0x3b, 0x18, 0x94, 0x65, 0x3b, 0x59, 0x27, 0x1a, 0x3b, 0x09, 0xb2, 0x4a, 0x3c,
+  0x27, 0x1b, 0xfc, 0x3b, 0x7a, 0x43, 0x9f, 0xbb, 0x8e, 0x41, 0x0c, 0xbc, 0x86, 0xcb, 0x9b, 0x3b,
+  0xd0, 0x67, 0x23, 0xbc, 0x70, 0xd7, 0xfb, 0x3a, 0x74, 0x75, 0x22, 0xbc, 0x91, 0x1b, 0x80, 0xbc,
+  0x74, 0x1f, 0x64, 0x3c, 0x2b, 0x58, 0x91, 0x3b, 0x41, 0x5c, 0xa9, 0xbc, 0x71, 0xcb, 0x3b, 0xbc,
+  0x7d, 0x39, 0xa5, 0xbc, 0x39, 0xbf, 0xba, 0xbb, 0x35, 0x78, 0xf6, 0xbb, 0x5a, 0xc9, 0xf2, 0x3b,
+  0xb3, 0x04, 0x66, 0x3c, 0xbc, 0x9b, 0x29, 0xbc, 0xa7, 0x6c, 0xde, 0xbb, 0x58, 0xb6, 0x80, 0xbb,
+  0x44, 0x94, 0x30, 0xbd, 0xe3, 0x6e, 0xab, 0x3b, 0x87, 0x10, 0x8f, 0xbc, 0x60, 0x68, 0x8e, 0x3b,
+  0x9a, 0xdd, 0x7d, 0x3b, 0x94, 0xb8, 0x8b, 0x3c, 0xbf, 0xd8, 0x0b, 0xbc, 0x06, 0x3c, 0x8d, 0x3c,
+  0x3c, 0xf1, 0x28, 0xbd, 0xcf, 0xcb, 0x5b, 0xbc, 0x69, 0xe7, 0xcd, 0xbc, 0x1d, 0xe7, 0x27, 0x3c,
+  0xb6, 0xde, 0x06, 0xbc, 0xbd, 0xfd, 0x46, 0xbc, 0x5f, 0x47, 0x34, 0xbc, 0x5f, 0xae, 0xc3, 0x3b,
+  0xc2, 0x6e, 0xc0, 0xbc, 0x9e, 0xe7, 0x40, 0x3b, 0xb0, 0x2c, 0x63, 0xbc, 0x31, 0x9e, 0x0f, 0x3c,
+  0x68, 0x19, 0x05, 0x3c, 0x62, 0x73, 0x8e, 0xb8, 0x86, 0xdb, 0x58, 0x3b, 0xac, 0x10, 0x1b, 0x3c,
+  0x86, 0xa4, 0xa1, 0xbc, 0x45, 0xbd, 0x83, 0xbc, 0x03, 0x46, 0x96, 0xbb, 0xe9, 0x72, 0xe9, 0x3b,
+  0x60, 0xda, 0xac, 0x3b, 0x8c, 0xe3, 0x03, 0x3b, 0x4e, 0x99, 0x1f, 0xbb, 0x1a, 0x4f, 0xc9, 0x3b,
+  0x56, 0x8a, 0x71, 0xbb, 0x47, 0x45, 0xcd, 0x3b, 0x29, 0x15, 0x9f, 0xbb, 0xc5, 0x6f, 0x51, 0x3c,
+  0x18, 0x79, 0xea, 0xbb, 0x4e, 0x73, 0x80, 0x3c, 0xee, 0x6a, 0x89, 0xbc, 0xd4, 0xa9, 0x07, 0xbb,
+  0x03, 0x9b, 0xbb, 0xbb, 0x96, 0xac, 0x37, 0xbc, 0x64, 0xc6, 0x6d, 0xbb, 0xfd, 0x60, 0x3a, 0xbc,
+  0x0c, 0x0c, 0x8c, 0xbb, 0x99, 0xc9, 0x40, 0x3b, 0xd1, 0x98, 0xd6, 0x3a, 0x00, 0x3d, 0x69, 0x3c,
+  0x6a, 0x12, 0xc5, 0xbc, 0x65, 0x90, 0x73, 0xbc, 0xe6, 0xac, 0x2e, 0xbc, 0xc1, 0xbc, 0xa0, 0xbb,
+  0xa6, 0xcd, 0x1b, 0x3b, 0x85, 0x1c, 0x4f, 0xbb, 0x30, 0x93, 0x2d, 0x3c, 0xa5, 0x7d, 0x28, 0x3c,
+  0x55, 0xac, 0x08, 0x3b, 0x92, 0x45, 0x7b, 0xbc, 0x3c, 0xb5, 0x1e, 0x3c, 0x64, 0x2b, 0x92, 0xbb,
+  0x5f, 0x52, 0x6e, 0x3c, 0x7c, 0x4c, 0x5c, 0x3c, 0x70, 0xdd, 0x9b, 0x3b, 0x04, 0xc9, 0x99, 0x3c,
+  0x8d, 0x6e, 0x01, 0xbc, 0x4b, 0x08, 0xcf, 0xbb, 0x64, 0x87, 0xee, 0x3b, 0xb9, 0x12, 0xcf, 0xbb,
+  0xd5, 0x0d, 0x11, 0xbc, 0x6a, 0x8f, 0x00, 0x3b, 0x3f, 0x73, 0x70, 0xbb, 0x4e, 0x93, 0xe5, 0xbb,
+  0xe9, 0xda, 0x4d, 0x3b, 0x30, 0xf2, 0x62, 0xbc, 0x06, 0x05, 0x10, 0x3b, 0xef, 0x90, 0xa5, 0x3b,
+  0x73, 0xa1, 0x62, 0x39, 0x0f, 0x6e, 0x5f, 0x3c, 0x29, 0x8c, 0x21, 0x3c, 0x78, 0x3f, 0x98, 0x3c,
+  0xe7, 0x65, 0x59, 0x3b, 0x88, 0x0b, 0x8c, 0xbb, 0xc4, 0x90, 0x43, 0xbb, 0x6b, 0xdb, 0xb0, 0x3b,
+  0x7f, 0xff, 0x38, 0xbb, 0x4b, 0xa9, 0x49, 0xbb, 0xff, 0x84, 0x30, 0x3c, 0x03, 0xb0, 0x16, 0x3c,
+  0x55, 0xeb, 0x72, 0xbc, 0x18, 0x21, 0xb3, 0xbb, 0x8d, 0x47, 0x17, 0xbb, 0x9f, 0x0b, 0xbd, 0x3b,
+  0x22, 0xe2, 0x7f, 0x3c, 0x11, 0x5a, 0xb8, 0x3c, 0x1d, 0xfd, 0xa0, 0xbc, 0xf6, 0xea, 0x20, 0xbb,
+  0xd4, 0x32, 0xad, 0xbb, 0x93, 0x37, 0xcf, 0xba, 0xd3, 0x6b, 0xaf, 0xbc, 0x02, 0xd9, 0xb7, 0xbb,
+  0xad, 0xf2, 0x4f, 0x3b, 0xbe, 0x41, 0xdd, 0x3b, 0x7e, 0x92, 0xa9, 0xba, 0x30, 0x27, 0xad, 0x3b,
+  0xf6, 0xc2, 0xed, 0xba, 0x17, 0x62, 0x3e, 0xbb, 0xb0, 0x29, 0xb2, 0xbb, 0x2f, 0x75, 0xdf, 0x3b,
+  0x96, 0xe6, 0x87, 0x3a, 0xb6, 0x09, 0x3d, 0xbb, 0x35, 0x68, 0x34, 0xbb, 0xa6, 0x77, 0x45, 0x3c,
+  0xfa, 0xf7, 0xbc, 0xba, 0xfd, 0xf4, 0x3e, 0xbb, 0xce, 0x8e, 0xef, 0xba, 0x33, 0x5f, 0x15, 0x3c,
+  0xe0, 0xd6, 0x8d, 0x3c, 0x4a, 0x9f, 0xbe, 0x3b, 0x16, 0x10, 0x5e, 0xbc, 0x3d, 0xf8, 0xc1, 0x3c,
+  0x71, 0x0f, 0x78, 0xbb, 0x2a, 0x11, 0x0f, 0x3c, 0x10, 0x67, 0xba, 0xbb, 0x87, 0x65, 0xef, 0x3a,
+  0xed, 0x38, 0x3a, 0x3c, 0x22, 0x1b, 0xa2, 0x3c, 0x74, 0x3f, 0x97, 0x3c, 0x06, 0xa6, 0x45, 0x3c,
+  0xf3, 0xa0, 0x01, 0xbb, 0xbf, 0x24, 0x81, 0x3b, 0xcf, 0x89, 0x03, 0x3c, 0x32, 0x69, 0x65, 0xbc,
+  0x1b, 0x02, 0x58, 0x3b, 0x11, 0x2a, 0x6f, 0xba, 0xef, 0x2e, 0x93, 0x3c, 0x40, 0xd6, 0xfb, 0x3c,
+  0xb0, 0x1b, 0x25, 0x3b, 0x29, 0xc7, 0x8c, 0x3a, 0x4c, 0x4a, 0x0c, 0x3b, 0x29, 0x77, 0x3d, 0x3a,
+  0x18, 0xe5, 0xf2, 0x3b, 0xc3, 0x03, 0x10, 0xbc, 0x46, 0x54, 0xbb, 0xbb, 0x04, 0x64, 0x99, 0x3c,
+  0x8a, 0x83, 0x2c, 0xbc, 0xf1, 0x66, 0xc3, 0xbb, 0xfc, 0x6b, 0xac, 0xbb, 0xd1, 0x03, 0x07, 0x3c,
+  0xd8, 0x33, 0x96, 0x3c, 0x51, 0x58, 0xac, 0x3b, 0xe6, 0x06, 0x43, 0xbc, 0x6d, 0xd4, 0x27, 0x3b,
+  0x80, 0x28, 0xb6, 0xbc, 0xbe, 0x76, 0x9d, 0xbb, 0x11, 0x0f, 0x30, 0xbc, 0xf4, 0xc9, 0x43, 0xbb,
+  0x76, 0x1d, 0xb0, 0x3b, 0x9e, 0x9d, 0x67, 0xbb, 0x82, 0xb1, 0x35, 0xbb, 0x90, 0xd8, 0x2d, 0x3c,
+  0x8c, 0x47, 0x09, 0xbd, 0xa8, 0x09, 0x61, 0x39, 0x00, 0x31, 0x0f, 0xbb, 0xbe, 0x63, 0xd1, 0x3b,
+  0xa0, 0xce, 0xa9, 0x3b, 0xa5, 0x73, 0x51, 0xbb, 0x9c, 0x3c, 0x4f, 0xbc, 0x87, 0x99, 0x9f, 0xbb,
+  0x9d, 0xae, 0xe5, 0xbc, 0x26, 0x4f, 0x71, 0xbb, 0xfc, 0xfd, 0x97, 0xbb, 0xb0, 0x17, 0x7b, 0x39,
+  0x85, 0xc5, 0xf0, 0x3b, 0x5a, 0x16, 0x18, 0xbc, 0x84, 0xf2, 0x12, 0xbc, 0x47, 0x1e, 0x12, 0x3c,
+  0xe5, 0x5d, 0xc6, 0xbc, 0x0a, 0x04, 0xc5, 0x3b, 0x6e, 0xa8, 0x95, 0xbc, 0x26, 0x65, 0x35, 0x3b,
+  0xff, 0x0d, 0x33, 0x3c, 0xb3, 0x8a, 0x0e, 0xbc, 0xdc, 0x21, 0x4f, 0x3b, 0x20, 0x85, 0x61, 0x3c,
+  0x82, 0x5a, 0x0d, 0xbd, 0x7f, 0x31, 0x49, 0xbb, 0xee, 0xc5, 0x67, 0xbc, 0xdd, 0x29, 0x2c, 0xbc,
+  0x50, 0x2c, 0xdb, 0xbb, 0xa3, 0xfb, 0x0a, 0xbc, 0x7f, 0x3c, 0xe5, 0x3a, 0x0e, 0xa6, 0x71, 0x39,
+  0x4a, 0x1b, 0x8d, 0xbc, 0x0a, 0x63, 0xbc, 0xbc, 0x9f, 0xad, 0x28, 0xbb, 0x9e, 0x24, 0xb2, 0xbb,
+  0xa0, 0xcf, 0x1a, 0xbc, 0x90, 0x71, 0x43, 0xba, 0x51, 0x96, 0xe3, 0xbb, 0x1c, 0xab, 0xd1, 0x3b,
+  0x03, 0x39, 0xfa, 0xbb, 0xf8, 0xbc, 0x91, 0xbc, 0xd7, 0x9b, 0x5e, 0xbb, 0x57, 0xce, 0xca, 0x3b,
+  0xfd, 0x81, 0xb0, 0x3a, 0x73, 0x3f, 0xc0, 0x3a, 0xd7, 0xf4, 0xd3, 0x3b, 0x4f, 0xd3, 0x96, 0x3b,
+  0xf4, 0xe6, 0x95, 0xbc, 0x54, 0xf7, 0xa4, 0xbc, 0xd1, 0x14, 0x8a, 0x39, 0xc5, 0x2d, 0xe0, 0xbb,
+  0x95, 0x67, 0x49, 0x3b, 0x11, 0xf4, 0x19, 0x3c, 0x45, 0x34, 0x5b, 0x3c, 0xb0, 0xb2, 0x71, 0x3c,
+  0x07, 0x84, 0x3c, 0xbc, 0xe6, 0xe0, 0x39, 0xbc, 0x58, 0xde, 0xe1, 0x3b, 0x8d, 0x78, 0xb5, 0xba,
+  0x5e, 0x53, 0xb5, 0x3b, 0x58, 0x3c, 0xb1, 0xbb, 0xb6, 0x58, 0xd0, 0xbb, 0x56, 0x72, 0xed, 0x3c,
+  0xf9, 0xfe, 0xc4, 0xbb, 0x3a, 0x95, 0x17, 0x3b, 0x03, 0xb3, 0xfd, 0x3b, 0x66, 0x7b, 0x30, 0xbb,
+  0x81, 0x5c, 0x53, 0x3c, 0xe1, 0xb4, 0x3b, 0x3c, 0xd3, 0xcc, 0x6d, 0x3b, 0xf7, 0x83, 0xd3, 0x3c,
+  0x1c, 0x60, 0x8f, 0x3b, 0xc5, 0x7e, 0xe4, 0xbb, 0x9c, 0xb1, 0x25, 0xbc, 0x06, 0x75, 0x5c, 0xbb,
+  0xf9, 0x35, 0x86, 0x3c, 0x5a, 0xe2, 0xf3, 0x39, 0x03, 0x48, 0xc4, 0xbb, 0x1b, 0x58, 0x8b, 0xbb,
+  0xc6, 0x4f, 0x81, 0xb9, 0x17, 0x1b, 0xf6, 0xbb, 0x95, 0x05, 0xbe, 0x3b, 0x93, 0x99, 0x30, 0xbc,
+  0xe8, 0x02, 0x1a, 0x3a, 0xc6, 0x76, 0xa0, 0x3c, 0xfa, 0x52, 0x80, 0x3c, 0x3c, 0x9e, 0x25, 0x3c,
+  0x52, 0xc0, 0xb5, 0x3a, 0x86, 0xa8, 0x09, 0xbc, 0xc1, 0x26, 0x32, 0xbc, 0x9b, 0x45, 0x4c, 0x3c,
+  0x38, 0x7a, 0x94, 0xbb, 0xe1, 0x9f, 0x27, 0x3c, 0x3a, 0x21, 0x31, 0x3b, 0xc6, 0xa3, 0x91, 0x3c,
+  0x99, 0x96, 0x43, 0xbb, 0x61, 0x5d, 0xf3, 0xbb, 0x1e, 0x54, 0x5f, 0xbc, 0x7d, 0xb9, 0xe6, 0xbb,
+  0x6b, 0xd6, 0x72, 0x3c, 0x0c, 0xf0, 0x0d, 0x3a, 0x9a, 0x60, 0x8b, 0xbc, 0x81, 0x3a, 0xaf, 0x3c,
+  0xbd, 0xd5, 0xc2, 0xbc, 0x8c, 0xcb, 0x34, 0xbc, 0x27, 0x5c, 0x2a, 0xbc, 0x1e, 0x51, 0xaf, 0x3b,
+  0xec, 0x5a, 0x2f, 0x3b, 0xf0, 0xd5, 0xab, 0x3c, 0xaf, 0x77, 0x95, 0x3b, 0xd9, 0xaf, 0xba, 0x3c,
+  0xe7, 0x4f, 0x44, 0xbc, 0xbf, 0x27, 0x87, 0x3b, 0xb0, 0x15, 0xb8, 0xbb, 0x38, 0xd7, 0xf9, 0xbb,
+  0x9f, 0xe5, 0x00, 0x3c, 0xd0, 0xf9, 0x9f, 0x3c, 0x6a, 0x34, 0x57, 0xbb, 0x92, 0xfa, 0xef, 0x3c,
+  0xc1, 0x83, 0x47, 0xbc, 0x67, 0x59, 0x8b, 0xbc, 0x3f, 0x17, 0x5a, 0xbc, 0x88, 0xea, 0x8e, 0xbb,
+  0x17, 0x8b, 0xe5, 0x3c, 0x95, 0x92, 0x99, 0x3c, 0x6d, 0xbe, 0x89, 0x3c, 0x8a, 0x36, 0xe2, 0x3c,
+  0x24, 0x82, 0x96, 0x3b, 0x58, 0x1c, 0x43, 0x3b, 0xed, 0xa7, 0xe2, 0x3b, 0x1f, 0x27, 0xa1, 0xba,
+  0xe8, 0x1b, 0xac, 0x3c, 0x5b, 0x31, 0x5c, 0x3b, 0x44, 0x53, 0xa8, 0x3c, 0xcd, 0xc3, 0x5b, 0x3c,
+  0xa9, 0xd9, 0x3d, 0xbb, 0xd5, 0xf7, 0xf7, 0xb7, 0xbe, 0x1b, 0x5d, 0xbb, 0x3d, 0x0f, 0x09, 0x3c,
+  0x5d, 0x6d, 0x2e, 0xbc, 0x4d, 0x16, 0x1c, 0x3c, 0x84, 0xcf, 0x27, 0xbc, 0x6a, 0x13, 0xea, 0xba,
+  0x60, 0xb8, 0x3f, 0x3c, 0x84, 0x15, 0xad, 0x3a, 0x32, 0x9e, 0xf2, 0xbb, 0x8c, 0xc8, 0x2e, 0x3c,
+  0x0a, 0xe5, 0x0a, 0x3c, 0x19, 0xc0, 0x06, 0x3b, 0xca, 0x64, 0xc0, 0xbc, 0x61, 0x44, 0x0b, 0x3c,
+  0x46, 0xd0, 0x88, 0xbc, 0x86, 0x0b, 0x5e, 0xbc, 0x11, 0x69, 0xdb, 0x3b, 0xcf, 0x30, 0xf9, 0xbb,
+  0x1a, 0x89, 0x94, 0x3b, 0x2f, 0xb5, 0x3a, 0xbc, 0x69, 0xe1, 0xc7, 0xbb, 0xd6, 0x6b, 0x1a, 0xbb,
+  0x61, 0x21, 0x2d, 0xbd, 0x11, 0x36, 0x62, 0xbb, 0x2e, 0xe3, 0x0f, 0xbc, 0xdb, 0x78, 0x1b, 0xbb,
+  0x6a, 0x65, 0x67, 0x3c, 0x08, 0x45, 0x67, 0x3c, 0x11, 0x91, 0xda, 0xba, 0xdd, 0x93, 0x16, 0x3b,
+  0xae, 0x70, 0x27, 0xbd, 0x11, 0xb5, 0x51, 0xbc, 0x82, 0x5f, 0x01, 0xba, 0xdd, 0x05, 0x0e, 0x3a,
+  0xa7, 0x0b, 0x77, 0xba, 0x63, 0x2a, 0xe2, 0x3a, 0x9b, 0x4c, 0x6a, 0xbb, 0x3e, 0x95, 0x44, 0x3a,
+  0x7a, 0xec, 0x0a, 0xbd, 0x07, 0x4f, 0x8e, 0xbc, 0x84, 0x4e, 0x83, 0xbc, 0x33, 0x85, 0x29, 0x3b,
+  0xee, 0x48, 0xf0, 0xbb, 0x85, 0x82, 0x02, 0xbc, 0x01, 0x36, 0xed, 0xbb, 0x5c, 0x0f, 0x6a, 0x3c,
+  0x20, 0x87, 0xe0, 0xbc, 0x82, 0x70, 0x0d, 0xbc, 0x95, 0xcc, 0x8b, 0xbb, 0xec, 0x0b, 0x6b, 0x3c,
+  0x2e, 0xa8, 0x36, 0x38, 0x4d, 0x9c, 0xf1, 0x38, 0x4c, 0x74, 0x7c, 0xbb, 0xbf, 0xd6, 0xf9, 0x3b,
+  0xf2, 0x23, 0x20, 0xbc, 0x09, 0xbf, 0x38, 0xbc, 0x74, 0x1e, 0xe4, 0x3a, 0x95, 0xda, 0xe9, 0x3b,
+  0x09, 0x1b, 0x9b, 0xbb, 0xc9, 0x82, 0x24, 0xba, 0xc9, 0x7c, 0xe5, 0x3a, 0xd9, 0xe7, 0x8c, 0x3b,
+  0x77, 0xd2, 0x77, 0xbc, 0xd4, 0x75, 0xa3, 0x3b, 0x8f, 0xc2, 0xdd, 0x3b, 0x84, 0x0d, 0x5b, 0xbc,
+  0x7b, 0x2d, 0xf6, 0xbb, 0xfe, 0xe3, 0xe8, 0xbb, 0xf4, 0xb8, 0x2d, 0x3c, 0x88, 0x53, 0xa9, 0x3c,
+  0x9a, 0x83, 0xae, 0xbc, 0xdc, 0x95, 0x76, 0xbc, 0x54, 0x5e, 0xa4, 0x3b, 0x90, 0x16, 0x05, 0xbc,
+  0x7a, 0x6a, 0x5b, 0xbb, 0xf7, 0xca, 0x59, 0xba, 0xe9, 0x89, 0xad, 0x3b, 0x53, 0x8a, 0x83, 0x3c,
+  0xf4, 0x44, 0xb2, 0xbb, 0x5e, 0x37, 0x03, 0x3a, 0xcf, 0x66, 0x9c, 0x3b, 0x5d, 0x53, 0x6b, 0xbb,
+  0x30, 0x6c, 0x8e, 0x3a, 0xbc, 0x59, 0x36, 0xb7, 0x44, 0x33, 0x37, 0x3c, 0x04, 0x56, 0x41, 0x3c,
+  0xc2, 0x08, 0xd1, 0xbb, 0x31, 0xce, 0x0f, 0x3b, 0x6d, 0x48, 0x83, 0x3c, 0x9e, 0x82, 0x30, 0xbb,
+  0xb2, 0x1d, 0x0d, 0xbc, 0x4e, 0x4a, 0x0f, 0xbc, 0x85, 0x1f, 0x0b, 0x3c, 0x86, 0xa7, 0xd7, 0xbb,
+  0x21, 0x05, 0x4a, 0xbb, 0x5a, 0x1f, 0xaf, 0xbb, 0x5e, 0xe5, 0x1e, 0x3b, 0x17, 0x66, 0x0e, 0x3c,
+  0x0c, 0x05, 0x0c, 0xbc, 0x60, 0x12, 0x59, 0xbc, 0xea, 0x7f, 0x9b, 0x3c, 0x87, 0x1a, 0x42, 0xbb,
+  0x3a, 0x66, 0xe6, 0xbb, 0x32, 0xc9, 0xc3, 0x3a, 0xa0, 0xb3, 0x23, 0x3c, 0xf8, 0x7a, 0x2c, 0x3c,
+  0xe1, 0x34, 0x39, 0x3c, 0xde, 0x04, 0xda, 0xba, 0x9a, 0xc0, 0xf2, 0x3b, 0x7c, 0x69, 0x81, 0x3c,
+  0x6f, 0xd8, 0x0a, 0x3b, 0xbc, 0x9e, 0xb9, 0xbb, 0xb2, 0xfb, 0x50, 0xbc, 0xdf, 0x03, 0xbd, 0x3b,
+  0x2d, 0xeb, 0x4a, 0x3b, 0x6e, 0x4b, 0x11, 0x3c, 0xb9, 0xb3, 0x85, 0xbc, 0x5e, 0x0f, 0xd2, 0x3c,
+  0x7a, 0xeb, 0x3d, 0xbc, 0x04, 0x49, 0x2b, 0xbb, 0xbc, 0x66, 0x43, 0xbc, 0x73, 0x44, 0xd2, 0xba,
+  0x37, 0x23, 0xa0, 0xbb, 0xb6, 0x26, 0x0b, 0x3c, 0x8d, 0xe5, 0xd7, 0x3b, 0xff, 0xb8, 0x5f, 0x3c,
+  0x4d, 0xdd, 0x29, 0xbc, 0xdb, 0x1d, 0x7d, 0xbb, 0xb6, 0x29, 0xae, 0xbc, 0x64, 0x14, 0x3e, 0xbc,
+  0x69, 0x3d, 0x42, 0x3c, 0xe8, 0xcf, 0x51, 0x3b, 0x2d, 0xa8, 0x50, 0xbc, 0x5f, 0x0f, 0x5f, 0x3c,
+  0xd6, 0xbf, 0x8f, 0xbb, 0x08, 0xce, 0xb4, 0x3b, 0xe1, 0x30, 0x09, 0xbc, 0x92, 0xef, 0x22, 0x3b,
+  0x92, 0x7c, 0xe7, 0x3b, 0x1b, 0xc0, 0x87, 0x3b, 0xf1, 0x81, 0x89, 0xbc, 0x28, 0x4f, 0x4c, 0x3c,
+  0x91, 0xa2, 0x2e, 0xbc, 0xbe, 0x43, 0x9f, 0xbc, 0x3b, 0xa1, 0x62, 0xbb, 0xee, 0x73, 0x5d, 0xbb,
+  0xeb, 0xe8, 0x0b, 0x3c, 0xae, 0x67, 0x33, 0x3c, 0x6f, 0x24, 0xb3, 0x3c, 0xb5, 0xf2, 0x00, 0x3c,
+  0x33, 0xb3, 0x79, 0x3b, 0x38, 0xd1, 0x64, 0xba, 0x78, 0xf5, 0x18, 0x3c, 0x8b, 0xe6, 0xad, 0xbb,
+  0x38, 0xdb, 0x64, 0x3c, 0x62, 0xf0, 0x43, 0xbb, 0x88, 0xd2, 0x37, 0x3b, 0x4f, 0xc0, 0xc8, 0x3c,
+  0x12, 0xfe, 0x14, 0xbc, 0xa8, 0xc1, 0x97, 0xba, 0xa4, 0xbc, 0x8f, 0xbb, 0x63, 0x90, 0x05, 0x3c,
+  0x37, 0xc8, 0xf3, 0xbb, 0xf8, 0xbe, 0x24, 0x3c, 0xfe, 0x82, 0x6e, 0xbc, 0x27, 0xf0, 0x8e, 0x3c,
+  0xe5, 0xfa, 0x9e, 0xbb, 0xa3, 0x2c, 0x9b, 0x3b, 0x32, 0x1b, 0x69, 0xbc, 0x41, 0x00, 0xec, 0xba,
+  0xd6, 0x66, 0x8a, 0x3c, 0x53, 0xef, 0x0e, 0x3c, 0x76, 0x6c, 0x89, 0xbc, 0x2a, 0x99, 0x07, 0x3c,
+  0xff, 0x92, 0xb1, 0xba, 0xaa, 0x0b, 0x51, 0xbc, 0x13, 0xbc, 0x77, 0x3b, 0x50, 0xff, 0x7e, 0xb9,
+  0x47, 0x71, 0x22, 0x3c, 0x25, 0x58, 0x99, 0xbb, 0xd1, 0x04, 0xe9, 0xbb, 0xc1, 0x45, 0x54, 0x3c,
+  0x98, 0xaa, 0x21, 0xbd, 0xbc, 0x85, 0x8f, 0xba, 0x6b, 0x6c, 0x4e, 0xbc, 0x8c, 0xc3, 0x22, 0x3c,
+  0xf7, 0x66, 0xac, 0x3c, 0x9b, 0xe0, 0xb1, 0x3c, 0xdc, 0x13, 0x28, 0x3c, 0x21, 0x1f, 0x28, 0x3c,
+  0x10, 0xd9, 0xe8, 0xbc, 0x56, 0xe2, 0x74, 0xbb, 0x77, 0x27, 0x2b, 0xbc, 0x31, 0x3b, 0x45, 0xbc,
+  0x3a, 0x26, 0x52, 0x3b, 0x86, 0x6d, 0xf8, 0x3a, 0x73, 0xb5, 0x97, 0xba, 0xcc, 0x81, 0x9b, 0x3c,
+  0x1d, 0x21, 0x3a, 0xbd, 0xba, 0x62, 0xdc, 0xbb, 0xef, 0x79, 0x73, 0xbc, 0x61, 0x43, 0x68, 0xbb,
+  0x51, 0x6c, 0x80, 0xbb, 0x6f, 0xfd, 0x05, 0xba, 0xba, 0x3e, 0xb9, 0xbb, 0x8d, 0x44, 0x84, 0x3c,
+  0x0b, 0x0f, 0x14, 0xbd, 0x08, 0xb9, 0x8f, 0xbc, 0x12, 0x09, 0xc2, 0x3a, 0x41, 0x65, 0x7e, 0x3c,
+  0x53, 0xcc, 0x4a, 0xbc, 0x75, 0x62, 0xd0, 0xbb, 0xb9, 0xbd, 0xdb, 0x3b, 0x39, 0x7b, 0x47, 0x3c,
+  0x60, 0x4d, 0x62, 0xbc, 0x6f, 0x36, 0xa3, 0x3b, 0x04, 0x07, 0x39, 0xbb, 0xf4, 0xbb, 0x0f, 0xbc,
+  0xb4, 0x91, 0xc8, 0xbb, 0xcd, 0xb6, 0x56, 0xbc, 0xa6, 0xe8, 0x9c, 0xbc, 0xb6, 0x2c, 0x5e, 0xbb,
+  0xe2, 0x9e, 0xed, 0xbb, 0x12, 0x6c, 0x83, 0xbc, 0xad, 0x16, 0x49, 0x3b, 0x27, 0x0b, 0x2a, 0x3b,
+  0x6d, 0x1a, 0xe0, 0xbb, 0x05, 0x9f, 0xae, 0xbb, 0x81, 0x33, 0x47, 0xbc, 0x04, 0x3d, 0x29, 0x3c,
+  0x43, 0x5f, 0x9c, 0xbc, 0x8d, 0x3e, 0x52, 0xba, 0x88, 0x76, 0x61, 0x3b, 0x2a, 0xf9, 0x29, 0xbc,
+  0x1f, 0x36, 0x0f, 0xbc, 0x53, 0x1d, 0xd4, 0x3b, 0x4e, 0xdf, 0x4a, 0xbb, 0x78, 0x88, 0x0e, 0xba,
+  0x0a, 0x65, 0x91, 0xbc, 0xe4, 0x4a, 0x43, 0xbc, 0x37, 0xa2, 0xc7, 0x3a, 0x99, 0xa8, 0x13, 0xbc,
+  0x49, 0xef, 0xeb, 0x39, 0xf6, 0x78, 0xca, 0xba, 0xcb, 0x0c, 0x8a, 0x3b, 0xcb, 0x37, 0x4e, 0x3c,
+  0xe7, 0x0b, 0x3b, 0xbb, 0xb6, 0x76, 0x48, 0xbc, 0x9e, 0xee, 0x14, 0x3b, 0x3d, 0x50, 0xf4, 0x3b,
+  0xd5, 0xdd, 0x37, 0xbc, 0x5b, 0x76, 0x32, 0x3a, 0x43, 0xfe, 0x6f, 0x3c, 0xd8, 0xa8, 0x17, 0x3c,
+  0x78, 0x6e, 0x8f, 0xbb, 0x36, 0x31, 0x98, 0xbb, 0xb3, 0xf0, 0x20, 0xbb, 0xbb, 0x5d, 0x12, 0x3c,
+  0xda, 0xe3, 0x07, 0xba, 0x26, 0xd1, 0x90, 0xbc, 0x59, 0x08, 0x17, 0xbc, 0x3e, 0x72, 0x7b, 0xba,
+  0xbb, 0x29, 0x95, 0x3b, 0x01, 0x19, 0xfd, 0x3b, 0x47, 0x45, 0x90, 0x3b, 0x7f, 0x0e, 0x9f, 0x3c,
+  0x25, 0x12, 0xad, 0xbb, 0x21, 0x22, 0xfb, 0x3a, 0x80, 0x00, 0xa5, 0xbb, 0xd5, 0x33, 0x96, 0x3c,
+  0xf0, 0xf4, 0xcd, 0x3b, 0x89, 0x88, 0xbc, 0x3b, 0xfb, 0x6b, 0x68, 0xbb, 0x1b, 0x17, 0x30, 0x3c,
+  0x1b, 0xc9, 0x45, 0xbb, 0xb8, 0xc4, 0x3c, 0x3a, 0x27, 0x85, 0xbb, 0xbb, 0x78, 0x32, 0xb4, 0x3c,
+  0x84, 0x3b, 0x85, 0xbc, 0x0d, 0x52, 0xa7, 0xbb, 0x48, 0xb9, 0x76, 0xbc, 0xc0, 0xdc, 0x63, 0x3c,
+  0x14, 0x5b, 0x15, 0xbb, 0xef, 0x91, 0x80, 0x3a, 0x9c, 0x1c, 0xa9, 0x3b, 0x78, 0xbd, 0x88, 0x3c,
+  0x43, 0xcc, 0x5a, 0x3b, 0x85, 0x8e, 0x2f, 0xbc, 0x5d, 0xe3, 0x97, 0xbc, 0xfc, 0x3c, 0x95, 0x3b,
+  0x3c, 0x3b, 0xd1, 0xbb, 0xa5, 0x63, 0x9f, 0x3b, 0xab, 0x2f, 0xee, 0x3b, 0x36, 0x44, 0x6c, 0x3c,
+  0x84, 0xd8, 0x46, 0xbc, 0x87, 0x25, 0xea, 0xbb, 0xcd, 0x0d, 0x9f, 0xbc, 0x2d, 0x64, 0xb3, 0x3b,
+  0x13, 0x80, 0xa0, 0xbb, 0xbe, 0x8e, 0x99, 0xb9, 0xd2, 0x04, 0xcf, 0x3b, 0xb8, 0x6d, 0x8e, 0x3c,
+  0x06, 0x4b, 0xcc, 0xbc, 0x29, 0x3e, 0x9c, 0x3b, 0xd7, 0xf8, 0x0a, 0xbc, 0x26, 0xd5, 0x96, 0xbc,
+  0x2b, 0x88, 0x1f, 0x3c, 0xba, 0xd9, 0x0c, 0x3c, 0xa6, 0x2e, 0x06, 0x3c, 0x37, 0x42, 0xa1, 0x3c,
+  0x7e, 0x92, 0xc3, 0xbb, 0x61, 0x36, 0x4e, 0x3c, 0x12, 0xff, 0x05, 0xbc, 0x3d, 0x26, 0xaa, 0x3b,
+  0xdf, 0xc2, 0x4b, 0xbb, 0x42, 0x66, 0x1b, 0xbc, 0xc9, 0xa7, 0xb9, 0x3b, 0x9d, 0xb9, 0x54, 0x3c,
+  0x47, 0x49, 0xb8, 0xbb, 0xc2, 0xc2, 0xc9, 0xb9, 0x64, 0xdf, 0xa6, 0xbb, 0x25, 0xe4, 0x06, 0xbc,
+  0x7e, 0x51, 0xe8, 0x3b, 0x92, 0xd0, 0xf7, 0x3b, 0x92, 0x5e, 0xae, 0xbc, 0x8f, 0xd3, 0xf5, 0x3a,
+  0xe2, 0x68, 0x5d, 0xbb, 0x3a, 0x8e, 0x81, 0xbb, 0x78, 0x3b, 0x1f, 0xbc, 0xf0, 0x5c, 0x65, 0xbb,
+  0xb7, 0x77, 0x82, 0x3c, 0xe9, 0xcf, 0x18, 0x3b, 0x82, 0xd4, 0xaf, 0xbc, 0xdd, 0x92, 0x99, 0x3c,
+  0xa3, 0xcd, 0xd0, 0xbb, 0x5e, 0x40, 0x31, 0x3c, 0xf3, 0x9d, 0x1a, 0xba, 0x71, 0xa5, 0x9c, 0xbb,
+  0x5c, 0xd3, 0x24, 0x3c, 0xee, 0x9e, 0x64, 0xbb, 0x14, 0x54, 0x18, 0xbc, 0xfd, 0x7d, 0xa4, 0x3b,
+  0xf4, 0x23, 0x24, 0xbd, 0xc8, 0xb1, 0x88, 0x3a, 0xaa, 0x99, 0xd6, 0xba, 0xe9, 0x6c, 0x17, 0xbb,
+  0x55, 0xd5, 0x0c, 0x3b, 0x1f, 0xfd, 0x9e, 0x3c, 0x82, 0x2a, 0x35, 0x3b, 0x57, 0xe7, 0xc9, 0x3a,
+  0x31, 0xdd, 0x0d, 0xbd, 0xd1, 0xb6, 0x4b, 0xbc, 0x39, 0x3b, 0xa9, 0xbc, 0x1b, 0xf2, 0x33, 0x3c,
+  0xed, 0xd9, 0x90, 0x3b, 0x85, 0xdc, 0x50, 0x3c, 0xa0, 0x96, 0x9c, 0xbb, 0x26, 0x76, 0x57, 0x3c,
+  0xea, 0xe7, 0x25, 0xbd, 0x4c, 0x6d, 0x8e, 0xbc, 0x67, 0x85, 0x82, 0xbc, 0xb7, 0x70, 0xcb, 0xba,
+  0x1f, 0x72, 0x3c, 0x3b, 0x0e, 0x65, 0x8e, 0x3b, 0x6f, 0xa2, 0x91, 0x3b, 0xbc, 0x93, 0xd9, 0x3c,
+  0xce, 0x4e, 0x07, 0xbd, 0x58, 0xcf, 0x16, 0xbc, 0x1b, 0xf7, 0x46, 0x3c, 0x51, 0xdc, 0x9e, 0xbc,
+  0x2e, 0x3b, 0x6e, 0xbc, 0xec, 0x36, 0x8b, 0xbc, 0x6b, 0x23, 0x20, 0x3b, 0x76, 0xd6, 0x22, 0x3a,
+  0xc4, 0x6e, 0x19, 0xbc, 0xa2, 0x65, 0x15, 0xbb, 0x33, 0xeb, 0x5c, 0xbc, 0x94, 0x57, 0xdd, 0x3b,
+  0x65, 0x2a, 0x24, 0xbc, 0x7b, 0x10, 0x00, 0xbc, 0xe4, 0x53, 0xc7, 0x3a, 0x1d, 0x77, 0x35, 0x3c,
+  0x4c, 0x1f, 0xfe, 0x3a, 0x42, 0x27, 0x26, 0xbc, 0x5d, 0xb5, 0x85, 0x3b, 0xcd, 0x1a, 0x0d, 0xbc,
+  0x04, 0x63, 0x28, 0xbc, 0x56, 0xf9, 0x44, 0xbc, 0x6a, 0x28, 0xbe, 0x3b, 0x6f, 0x4e, 0x2b, 0x3c,
+  0x76, 0xcf, 0xce, 0xbc, 0x3b, 0xd7, 0xd4, 0x3b, 0x3b, 0x11, 0x35, 0x3c, 0x33, 0x4e, 0x9b, 0xbc,
+  0x60, 0xba, 0x74, 0xbc, 0x98, 0x90, 0x82, 0xbb, 0xe4, 0xb7, 0xa9, 0x3c, 0xce, 0x3f, 0x42, 0x3c,
+  0x50, 0x2f, 0x87, 0xbc, 0x12, 0x64, 0x28, 0xbc, 0x57, 0x00, 0xfa, 0x3b, 0x92, 0xae, 0xd8, 0xbb,
+  0xe5, 0xbb, 0xe9, 0xb9, 0x37, 0xe9, 0x84, 0xbb, 0x44, 0x05, 0x0f, 0xbc, 0x38, 0xb1, 0xda, 0x3b,
+  0x72, 0x8f, 0x47, 0xbc, 0xef, 0xb9, 0x00, 0xbc, 0xce, 0xeb, 0x24, 0x3c, 0x8a, 0x93, 0x84, 0x3b,
+  0x12, 0x68, 0x7a, 0xbb, 0x47, 0x58, 0x81, 0xbc, 0x01, 0x3f, 0x38, 0x3b, 0x11, 0xe0, 0xc8, 0x3b,
+  0x4f, 0xfc, 0x4f, 0xbb, 0xab, 0x18, 0x1e, 0x3c, 0x9e, 0xd3, 0x2e, 0xbb, 0xb5, 0xb8, 0xa8, 0x3b,
+  0xb5, 0x64, 0xea, 0x3a, 0xab, 0x13, 0xbd, 0xba, 0xf7, 0x1a, 0x27, 0x3c, 0xee, 0x2a, 0x89, 0x3c,
+  0x0a, 0x01, 0x7b, 0x3c, 0x31, 0x2b, 0x0a, 0xba, 0xd0, 0x6c, 0xb6, 0xba, 0x32, 0x9b, 0x64, 0x3c,
+  0x8e, 0xcc, 0xb9, 0x3b, 0x22, 0x37, 0xe5, 0xbb, 0x49, 0xe5, 0x45, 0xba, 0x17, 0x85, 0x25, 0x3c,
+  0x43, 0xd4, 0x9a, 0x3b, 0x4f, 0xb2, 0x9a, 0x3a, 0x92, 0x3d, 0x11, 0xbc, 0x5b, 0xec, 0x76, 0xba,
+  0x37, 0x9d, 0x0f, 0xbb, 0xe8, 0xed, 0xe2, 0x3a, 0x4a, 0xa7, 0x1c, 0xbb, 0x47, 0x8f, 0x6b, 0x3c,
+  0x97, 0x18, 0x89, 0xbc, 0xa7, 0x5a, 0x16, 0x3b, 0xf7, 0xf7, 0x77, 0xbc, 0xcf, 0xfa, 0x2b, 0x3c,
+  0xce, 0x52, 0x4e, 0xbb, 0xb5, 0xd0, 0x95, 0xbb, 0x74, 0xd4, 0xd4, 0xba, 0xb9, 0x78, 0xc4, 0x3c,
+  0xe5, 0x8e, 0x8e, 0xbc, 0x8f, 0xd3, 0xde, 0xbb, 0x83, 0x59, 0xb1, 0xbc, 0x64, 0xed, 0x79, 0x3b,
+  0x0f, 0x57, 0xb9, 0xbb, 0x6e, 0xde, 0x1c, 0xbc, 0x70, 0x89, 0x30, 0x3c, 0xde, 0x6d, 0x92, 0x3c,
+  0x96, 0x52, 0x69, 0xbc, 0x76, 0x7e, 0xf7, 0xbb, 0xf0, 0x15, 0x0c, 0xbc, 0xdc, 0xf3, 0xe4, 0xbb,
+  0x79, 0x65, 0xc5, 0x3b, 0x82, 0x24, 0x6e, 0xba, 0x59, 0x56, 0x17, 0x3c, 0x21, 0x45, 0xb2, 0x3c,
+  0x02, 0x03, 0x36, 0x3a, 0x43, 0x1f, 0x08, 0x3c, 0x9a, 0x91, 0xac, 0xbc, 0xbc, 0x38, 0x5a, 0xbc,
+  0x17, 0xab, 0x62, 0x3b, 0x93, 0xbb, 0x22, 0xbb, 0x17, 0x94, 0xc2, 0x3c, 0x12, 0xeb, 0x06, 0x3c,
+  0x2b, 0x99, 0x1f, 0x3c, 0xef, 0x09, 0x58, 0x3b, 0xbc, 0xfd, 0x9e, 0xbc, 0xf4, 0x31, 0x9a, 0x3a,
+  0x07, 0x3f, 0xf4, 0x3b, 0x33, 0x81, 0x28, 0xbc, 0x65, 0x61, 0xaa, 0x3c, 0x55, 0x68, 0x66, 0x3c,
+  0x64, 0x56, 0x90, 0x39, 0x95, 0xf7, 0xdc, 0xba, 0xe8, 0x6f, 0xc9, 0xbb, 0x52, 0x66, 0x01, 0xbc,
+  0x57, 0x42, 0x13, 0x3c, 0x6e, 0x98, 0x4d, 0x3c, 0xc2, 0x3e, 0x8f, 0xbc, 0x3c, 0x53, 0x7a, 0x3c,
+  0xce, 0xde, 0xdd, 0xb8, 0xe3, 0xc2, 0xfe, 0xbb, 0x30, 0x21, 0xf4, 0xbb, 0x1b, 0xf7, 0x1c, 0x3b,
+  0x54, 0x6e, 0x2c, 0x3c, 0x1b, 0x17, 0xce, 0x3a, 0x85, 0x47, 0xae, 0xbc, 0xaf, 0x6d, 0x61, 0xbc,
+  0xef, 0x44, 0xf3, 0xbc, 0xf5, 0x81, 0x00, 0xbc, 0x5d, 0xa6, 0x45, 0x3b, 0xa8, 0x9c, 0x83, 0x3a,
+  0x62, 0xc7, 0x69, 0x3c, 0xae, 0x70, 0x9a, 0x3b, 0x13, 0x23, 0x1d, 0xbc, 0xf2, 0x71, 0x71, 0x3c,
+  0x1c, 0x17, 0x27, 0xbd, 0x90, 0x37, 0x30, 0xbc, 0x3d, 0x11, 0x43, 0xbb, 0x2b, 0x3a, 0x66, 0xbc,
+  0x2a, 0xad, 0x7c, 0x3c, 0x37, 0x28, 0x87, 0x3c, 0x55, 0x2c, 0xaf, 0x3a, 0x7d, 0x3a, 0x57, 0x3c,
+  0x35, 0xe7, 0x16, 0xbd, 0xec, 0x9c, 0xda, 0x3b, 0x64, 0xc8, 0x61, 0xbc, 0xd4, 0xd9, 0xc8, 0xbb,
+  0x0a, 0x4e, 0x61, 0x3c, 0x53, 0x4a, 0x97, 0x3c, 0xff, 0xb8, 0x66, 0xbc, 0xb5, 0x88, 0x00, 0x3c,
+  0xd5, 0x6b, 0x2e, 0xbd, 0x9e, 0x30, 0x95, 0xbc, 0xe7, 0x65, 0xc8, 0xbb, 0xbe, 0x00, 0x31, 0xb9,
+  0x76, 0xe5, 0x95, 0x3b, 0x87, 0x42, 0xa3, 0x3b, 0xe7, 0x28, 0x02, 0x3b, 0x14, 0x4f, 0x1a, 0xbb,
+  0x1e, 0xef, 0x18, 0xbd, 0xf8, 0xc5, 0xe8, 0x3b, 0x3c, 0xd0, 0xbb, 0x3b, 0x15, 0xea, 0xb1, 0xbb,
+  0xe1, 0x28, 0x66, 0x3b, 0xb8, 0xbd, 0x8e, 0xb9, 0x9a, 0x07, 0x13, 0x3c, 0x21, 0x7d, 0x6e, 0x3c,
+  0xd3, 0x67, 0x90, 0xbc, 0xbb, 0x37, 0x9f, 0xbb, 0xdf, 0x3e, 0x61, 0xbb, 0x4a, 0x1f, 0x05, 0xbc,
+  0x45, 0xed, 0x3b, 0xbc, 0xb7, 0x0a, 0x42, 0xbc, 0xb9, 0x1a, 0x1f, 0xbb, 0x47, 0x15, 0x3e, 0x3c,
+  0x7f, 0x4f, 0x24, 0xbc, 0x9b, 0x4c, 0x1c, 0xbc, 0x6a, 0xe1, 0x90, 0x3b, 0x7d, 0x19, 0x96, 0xbc,
+  0xd8, 0x08, 0xe6, 0xbb, 0x02, 0xda, 0xf3, 0xbb, 0x51, 0xd2, 0xaf, 0x3b, 0xfe, 0x77, 0xe8, 0x3a,
+  0xd4, 0x1f, 0x70, 0xbc, 0xdc, 0xa3, 0x30, 0xbb, 0x1f, 0x50, 0x5e, 0x3c, 0x9d, 0xf2, 0x92, 0x3c,
+  0x28, 0xa0, 0x0b, 0xbc, 0xc5, 0xd7, 0x31, 0x3a, 0xa6, 0x63, 0xa6, 0x3b, 0xfd, 0x46, 0xa2, 0x3c,
+  0x7e, 0xc5, 0xa1, 0xbc, 0x39, 0x61, 0xc3, 0x3b, 0x8a, 0xe7, 0x01, 0x3b, 0x2e, 0x7f, 0xa7, 0x3b,
+  0xb5, 0xc5, 0x03, 0xbc, 0xb9, 0x43, 0xa9, 0xba, 0x20, 0x07, 0x59, 0x3c, 0xf1, 0xaa, 0x01, 0xbb,
+  0x61, 0x58, 0xed, 0xbb, 0xb7, 0xeb, 0x23, 0xbb, 0x22, 0x65, 0xae, 0x3b, 0xe8, 0xe4, 0xec, 0x3b,
+  0x7b, 0x08, 0x82, 0xbc, 0x56, 0x26, 0x17, 0xbc, 0xcd, 0x42, 0x31, 0x3c, 0x8d, 0x33, 0xdc, 0x3c,
+  0xe9, 0xd9, 0xbb, 0x3b, 0x96, 0xfc, 0xa1, 0xbc, 0xd7, 0xf8, 0xea, 0xb9, 0x90, 0x58, 0xa2, 0xba,
+  0x00, 0x51, 0xcb, 0x39, 0xa2, 0x3b, 0xe9, 0xba, 0x1f, 0xc5, 0x15, 0xbb, 0x9f, 0x68, 0x18, 0xbb,
+  0x43, 0xac, 0x3b, 0x3c, 0xd8, 0x2f, 0x4d, 0x3c, 0xac, 0xb0, 0x3a, 0x3c, 0x7c, 0x12, 0x62, 0xbc,
+  0x24, 0x29, 0x4f, 0xbb, 0xdf, 0x23, 0xb9, 0xbb, 0x72, 0x0f, 0x46, 0xbb, 0x01, 0xa9, 0x78, 0x3c,
+  0xd0, 0xa4, 0x4a, 0x3b, 0xcc, 0xfe, 0x88, 0x3b, 0x33, 0xd3, 0x01, 0x3c, 0xf5, 0x8b, 0x71, 0x3b,
+  0x4b, 0x39, 0x64, 0x3c, 0x48, 0x0d, 0x81, 0xbb, 0x2b, 0x78, 0x4a, 0xbb, 0x71, 0x30, 0x63, 0x3c,
+  0x41, 0x1b, 0xb2, 0xbb, 0x1f, 0x8e, 0x59, 0x3c, 0xe4, 0xf7, 0xa8, 0xbb, 0x53, 0x36, 0x42, 0xba,
+  0xb2, 0xeb, 0xbc, 0x3a, 0xc0, 0xa7, 0x5d, 0x3b, 0x09, 0xf5, 0x5c, 0xbc, 0xde, 0xac, 0xc6, 0x3c,
+  0xb6, 0x86, 0xda, 0xbc, 0x3e, 0x2d, 0xbf, 0x3b, 0x45, 0xe8, 0x71, 0xbc, 0x32, 0x1b, 0x12, 0x3c,
+  0x0a, 0x38, 0xd8, 0xb9, 0x51, 0xf4, 0x50, 0xbc, 0x07, 0x81, 0xf7, 0x3b, 0xd6, 0x4d, 0xac, 0x3c,
+  0x1e, 0xcb, 0xb1, 0xbc, 0x90, 0x12, 0xf6, 0xbb, 0x6f, 0x50, 0x14, 0xbc, 0x88, 0x0c, 0x0b, 0x3b,
+  0x6e, 0x20, 0x4f, 0x3b, 0xa3, 0x44, 0x2b, 0x3a, 0xa3, 0x98, 0xef, 0xbb, 0x21, 0x2d, 0x2c, 0x3c,
+  0x28, 0x05, 0x78, 0xbc, 0xfa, 0xaa, 0x12, 0x3c, 0x33, 0xc9, 0x46, 0xbb, 0x2d, 0x5d, 0x03, 0x3c,
+  0x1d, 0xf0, 0x67, 0x3b, 0x36, 0x03, 0x3a, 0xbb, 0x5f, 0xc6, 0x41, 0x3c, 0x5b, 0x5b, 0x30, 0x3c,
+  0xbf, 0xe9, 0xbe, 0x39, 0x72, 0x5d, 0x51, 0x38, 0xf5, 0x03, 0x68, 0x3b, 0x06, 0x35, 0x93, 0x3c,
+  0xa4, 0x09, 0x3f, 0xb9, 0x2d, 0x26, 0x1e, 0xbc, 0x1d, 0x37, 0x61, 0x3c, 0xf2, 0x77, 0x8a, 0x3c,
+  0x1f, 0xa4, 0x18, 0x3b, 0xd0, 0x21, 0xb7, 0xbb, 0x2e, 0xcc, 0x52, 0x3b, 0x2f, 0xa8, 0x37, 0x3c,
+  0x53, 0xca, 0xab, 0x3c, 0xfe, 0xb0, 0x5f, 0x3c, 0xb1, 0x1f, 0x10, 0xbc, 0x4e, 0x3b, 0xf7, 0xbb,
+  0xf5, 0x33, 0xba, 0x3b, 0x97, 0xfc, 0x91, 0x3b, 0xa0, 0xad, 0x60, 0xbc, 0xeb, 0x43, 0x4c, 0x3c,
+  0x8a, 0x93, 0x8e, 0x3c, 0x6e, 0x2e, 0xb2, 0x3b, 0xdd, 0xbe, 0xce, 0xbb, 0x7d, 0x39, 0x6e, 0x3c,
+  0x60, 0xbe, 0xc4, 0xbc, 0x07, 0x38, 0x50, 0xba, 0xe9, 0xbc, 0x9c, 0xba, 0x55, 0x5a, 0x0c, 0x3c,
+  0x4c, 0x34, 0x82, 0x3c, 0xe9, 0x09, 0x4d, 0x3c, 0xef, 0x7f, 0xa3, 0xbb, 0x9f, 0x04, 0x8a, 0x3c,
+  0x52, 0x71, 0xed, 0xbc, 0x70, 0x28, 0x9d, 0x3a, 0x1b, 0x4c, 0xc1, 0xbb, 0x3b, 0x8d, 0xf7, 0x3b,
+  0x99, 0x4b, 0x4f, 0x3c, 0xee, 0xae, 0xa5, 0x3c, 0xa5, 0xbb, 0xb4, 0xbb, 0xda, 0xe1, 0x7c, 0x3b,
+  0x42, 0x5d, 0x00, 0xbd, 0x61, 0xc0, 0x0f, 0xba, 0xe8, 0xb0, 0xe5, 0x3a, 0x42, 0xf0, 0xc1, 0xbb,
+  0x4d, 0x4f, 0xa9, 0x3b, 0xae, 0xc7, 0x66, 0x3c, 0x31, 0x99, 0x48, 0x3c, 0x91, 0xea, 0x76, 0xbb,
+  0x76, 0xfe, 0xc9, 0xbc, 0xdc, 0xdb, 0x4e, 0x39, 0xe3, 0x10, 0x89, 0xbb, 0xa2, 0x20, 0x18, 0x3c,
+  0x0a, 0xaa, 0xb6, 0xbb, 0x50, 0x56, 0xd7, 0xba, 0x07, 0x4d, 0xc1, 0xbb, 0x23, 0xea, 0x41, 0x3c,
+  0x18, 0xd8, 0x03, 0xbd, 0x2a, 0x49, 0x04, 0xbc, 0x00, 0xb4, 0xc2, 0x3b, 0x8c, 0x2b, 0xce, 0x3b,
+  0xab, 0x26, 0x43, 0x3a, 0x10, 0xf7, 0x0a, 0xbb, 0x1d, 0xbe, 0x0d, 0x3c, 0x9e, 0xd2, 0x16, 0x3c,
+  0x89, 0xba, 0x31, 0xbc, 0x3c, 0x50, 0x42, 0xbc, 0x7d, 0x38, 0xab, 0xbb, 0x10, 0xd2, 0x2e, 0xbb,
+  0x38, 0x55, 0x35, 0xbb, 0xdd, 0x54, 0xa1, 0xbb, 0x22, 0x99, 0x4f, 0x3c, 0x6d, 0xd9, 0xb5, 0x3c,
+  0xda, 0x06, 0xc3, 0xbc, 0x3e, 0xd8, 0xad, 0xbc, 0x7b, 0x28, 0xd6, 0x39, 0x23, 0xc7, 0x0c, 0x3c,
+  0x9e, 0xc3, 0xda, 0xba, 0x8d, 0x68, 0xff, 0xba, 0x0c, 0x2d, 0x94, 0x3c, 0x0b, 0x5e, 0xf8, 0x3b,
+  0xa0, 0xff, 0xcc, 0xbc, 0x0b, 0xc0, 0x46, 0xbc, 0xa1, 0x50, 0x0c, 0xbc, 0xd0, 0x35, 0x12, 0x3c,
+  0xaf, 0xee, 0x10, 0xbc, 0x30, 0x73, 0x93, 0xb9, 0x6f, 0x96, 0x02, 0xbc, 0xe4, 0x66, 0x30, 0xbc,
+  0x57, 0x56, 0x82, 0x38, 0x77, 0xcf, 0xd9, 0x3b, 0x4a, 0x59, 0x4a, 0x3c, 0x61, 0x66, 0x32, 0x3c,
+  0x5f, 0x7c, 0x03, 0x3b, 0x0c, 0xc8, 0xbd, 0x3b, 0x22, 0xae, 0x00, 0x3b, 0x16, 0x27, 0xb9, 0x3b,
+  0xb3, 0x2f, 0x4a, 0xbc, 0x71, 0xae, 0xc5, 0xbb, 0xbb, 0x0d, 0x99, 0xbb, 0x2a, 0x2d, 0x8f, 0xbc,
+  0x06, 0x5f, 0x89, 0xbc, 0x95, 0xeb, 0x01, 0x3b, 0x82, 0x12, 0xbb, 0xbb, 0x2c, 0x91, 0x86, 0x3c,
+  0xe6, 0xde, 0x04, 0x3c, 0x19, 0x80, 0x2c, 0x3c, 0x43, 0x5b, 0xc6, 0xbb, 0xdb, 0x35, 0x6b, 0x3b,
+  0x77, 0x54, 0x1f, 0xbc, 0xd0, 0x5a, 0x83, 0xbb, 0x2f, 0xd1, 0xd5, 0xbb, 0x3c, 0xa3, 0x68, 0x3b,
+  0xb0, 0xbf, 0xc7, 0x3a, 0x7d, 0x89, 0x42, 0x3a, 0x8a, 0x86, 0xac, 0xbb, 0x12, 0xee, 0x9f, 0x3b,
+  0xeb, 0x91, 0x9c, 0xbb, 0x87, 0xe4, 0x55, 0x3a, 0x99, 0xce, 0x64, 0x3c, 0x8d, 0x87, 0x51, 0x3c,
+  0xc6, 0xdd, 0x05, 0x3c, 0xc9, 0x51, 0x3c, 0x3b, 0xde, 0xcc, 0x79, 0xbb, 0x73, 0x1a, 0x45, 0x3b,
+  0x3b, 0x4e, 0x8c, 0x3a, 0x7a, 0xef, 0x28, 0xbc, 0xd3, 0x82, 0xcd, 0xbb, 0xdb, 0x4f, 0x65, 0x3c,
+  0xe1, 0x8c, 0xc3, 0xbc, 0xfe, 0x3d, 0x50, 0x38, 0xc3, 0x64, 0x17, 0xbc, 0x8c, 0x55, 0x4e, 0xbb,
+  0xa1, 0x36, 0x02, 0xbc, 0x5f, 0xf6, 0x95, 0xbb, 0x70, 0xbc, 0x19, 0xbc, 0x80, 0xa6, 0x83, 0x3c,
+  0x21, 0x39, 0xdf, 0xbc, 0x95, 0xac, 0xfa, 0xbb, 0x06, 0x40, 0x18, 0xbc, 0x06, 0xe8, 0x90, 0xbc,
+  0x4f, 0x6d, 0x77, 0xbc, 0xb8, 0x9e, 0x54, 0x3a, 0x65, 0x6e, 0x06, 0x3c, 0x2d, 0x2b, 0x64, 0x3b,
+  0x33, 0x96, 0x3e, 0xbc, 0xc7, 0xc6, 0xf7, 0xbb, 0x53, 0xc5, 0xb7, 0xbc, 0x61, 0x04, 0x16, 0xbc,
+  0xef, 0x77, 0x19, 0xba, 0x44, 0xde, 0xa8, 0xba, 0xb3, 0x39, 0xbd, 0x3b, 0x82, 0xc8, 0xb5, 0x3c,
+  0xa3, 0xc4, 0xaa, 0xbc, 0xb5, 0xea, 0x13, 0xbc, 0xcc, 0xc8, 0x1a, 0xbc, 0x2e, 0xc0, 0xdd, 0x3b,
+  0xa5, 0xb5, 0xe4, 0xbb, 0xab, 0xda, 0x66, 0x3b, 0x9c, 0x29, 0x11, 0x3a, 0x8e, 0xac, 0xdf, 0x3b,
+  0x89, 0x5d, 0xd9, 0x3b, 0x84, 0x44, 0x78, 0xba, 0x45, 0x1e, 0x94, 0xbc, 0xe1, 0x58, 0xaa, 0x3b,
+  0x2e, 0x47, 0xa2, 0x3b, 0x57, 0x5c, 0x9a, 0x3b, 0x52, 0x5a, 0x70, 0x3c, 0x54, 0xbe, 0xb5, 0x3c,
+  0x1b, 0x93, 0x17, 0x3c, 0x8b, 0xa1, 0x51, 0x3b, 0x29, 0x4e, 0x9f, 0xb8, 0xc9, 0x51, 0x55, 0x3b,
+  0xd6, 0x75, 0x1a, 0x3c, 0x41, 0xe6, 0x80, 0x3c, 0x1a, 0x9a, 0x32, 0xbc, 0x24, 0x55, 0xfd, 0xba,
+  0x8b, 0x08, 0xfb, 0xbb, 0x55, 0x61, 0x6a, 0x3c, 0x2b, 0xbc, 0xa0, 0xbc, 0x58, 0xb9, 0x2a, 0xbc,
+  0xad, 0xf9, 0xca, 0x3c, 0xf2, 0xf1, 0x57, 0x3b, 0x1d, 0x6f, 0xe2, 0xbc, 0xaa, 0x79, 0xbf, 0x3b,
+  0xa8, 0x75, 0xad, 0xbc, 0x2c, 0x1b, 0x1e, 0xbc, 0x4d, 0xfd, 0xc2, 0xba, 0x95, 0x64, 0x40, 0x3b,
+  0xfd, 0xec, 0x8e, 0x3c, 0xb3, 0x6e, 0x9e, 0x3b, 0xf3, 0xb1, 0xc8, 0xbb, 0xa7, 0x62, 0x23, 0x3c,
+  0x18, 0x5c, 0x1f, 0xbd, 0xda, 0x0d, 0x86, 0xb9, 0x94, 0xd9, 0x36, 0xbc, 0xe2, 0xbf, 0xe4, 0xbb,
+  0xa2, 0x6c, 0xc9, 0x3b, 0x55, 0xb1, 0xf4, 0x3c, 0x51, 0xec, 0x33, 0xbc, 0x14, 0xc3, 0x3a, 0x3c,
+  0x2f, 0x37, 0x0a, 0xbd, 0x54, 0xf9, 0x15, 0x3c, 0xb6, 0xc1, 0x15, 0xbc, 0x9b, 0xa9, 0xa2, 0xbc,
+  0x2c, 0xfb, 0xa5, 0x3b, 0xf4, 0x62, 0xc1, 0x3c, 0x9b, 0xa2, 0x29, 0x3b, 0x4d, 0xdf, 0xe1, 0x3b,
+  0x3a, 0x9b, 0x1e, 0xbd, 0xdb, 0x70, 0x18, 0x3c, 0x58, 0x16, 0xa5, 0xbc, 0x9f, 0xe6, 0xd4, 0x3b,
+  0x88, 0x87, 0x00, 0x3c, 0x7d, 0xf5, 0x81, 0x3a, 0x8c, 0xa1, 0x91, 0x3a, 0xa6, 0x0a, 0x20, 0x3c,
+  0xd6, 0x7e, 0xd0, 0xbc, 0xc4, 0x8d, 0xa8, 0xbc, 0x78, 0x0b, 0x68, 0xbb, 0x70, 0xbb, 0xbb, 0x3b,
+  0x67, 0xe6, 0x63, 0xbb, 0x15, 0x09, 0xdb, 0x3b, 0x82, 0x25, 0x76, 0x3c, 0x71, 0xe9, 0x8d, 0x3c,
+  0x7c, 0x92, 0xa9, 0xbc, 0xc6, 0xc9, 0x23, 0xbc, 0xd9, 0x2a, 0x13, 0xba, 0x94, 0x99, 0xe6, 0xbb,
+  0xbe, 0x11, 0xb4, 0xbb, 0x02, 0xa1, 0xb4, 0x3b, 0x70, 0xe3, 0x80, 0x3b, 0xf6, 0x97, 0x54, 0x3b,
+  0x15, 0x37, 0xb5, 0xbb, 0x39, 0x17, 0x9f, 0xbc, 0xd5, 0x13, 0x3f, 0x3b, 0xa4, 0xc6, 0x00, 0x3c,
+  0xad, 0xbe, 0x3f, 0xbc, 0x5a, 0x6d, 0x07, 0xbc, 0x73, 0xbd, 0x05, 0xbb, 0x29, 0xb0, 0xb7, 0x3c,
+  0x24, 0xb2, 0x09, 0xbc, 0x75, 0xbc, 0xe7, 0xbb, 0xea, 0xc9, 0x3c, 0x3c, 0xee, 0xdd, 0x77, 0xbb,
+  0xe0, 0x3a, 0xc3, 0xbb, 0xdc, 0x43, 0x79, 0x3a, 0x94, 0xc2, 0x03, 0x3c, 0x9a, 0xc3, 0x80, 0x3c,
+  0xb4, 0xb7, 0xae, 0xbc, 0x10, 0x91, 0x0c, 0x3c, 0x82, 0xca, 0x1a, 0x3c, 0xa8, 0xa8, 0x5c, 0xbc,
+  0x7c, 0xb4, 0xb6, 0xbb, 0xf7, 0x6d, 0x6a, 0x3a, 0xd0, 0x40, 0x0d, 0x3b, 0x43, 0x4c, 0x8b, 0x3c,
+  0x27, 0x84, 0xd5, 0xbc, 0x75, 0x5c, 0xd7, 0xbb, 0xd5, 0x18, 0xd3, 0xbb, 0x00, 0x63, 0x24, 0xbc,
+  0xca, 0x29, 0x41, 0xbc, 0xca, 0xa2, 0x70, 0xbb, 0x9d, 0x4b, 0x30, 0x3c, 0x52, 0x97, 0x4d, 0x3c,
+  0xb7, 0xa5, 0x23, 0xbc, 0xa5, 0x4f, 0xd3, 0x3b, 0x52, 0xcb, 0x20, 0x3b, 0x9a, 0x6b, 0x2e, 0x3c,
+  0x92, 0x36, 0xec, 0xbb, 0x9d, 0x70, 0x1d, 0xbc, 0x04, 0x2f, 0x08, 0x3c, 0x9a, 0xc0, 0x5c, 0x3c,
+  0x5d, 0x23, 0x8c, 0x3b, 0x76, 0x7a, 0x6e, 0x3c, 0x4d, 0x14, 0x7a, 0xbc, 0xcb, 0x7d, 0x4e, 0xbc,
+  0xd4, 0xc0, 0x46, 0xbb, 0x4a, 0x10, 0xdf, 0x3b, 0x23, 0x7f, 0xc6, 0x3b, 0xe0, 0xfe, 0xa5, 0x3c,
+  0x0e, 0x46, 0x2c, 0xbc, 0x98, 0xb4, 0xb5, 0x3c, 0xba, 0x90, 0x15, 0xbc, 0x13, 0xde, 0x53, 0xbb,
+  0xa0, 0x8c, 0x87, 0xbb, 0x59, 0x5b, 0x29, 0x3c, 0x85, 0xaa, 0x88, 0x3b, 0x90, 0x2d, 0x1b, 0x3b,
+  0xf2, 0xf2, 0x87, 0xbc, 0x09, 0x00, 0xa3, 0xbc, 0xa9, 0x58, 0x48, 0x3a, 0x29, 0x8a, 0x26, 0xbc,
+  0xc6, 0x21, 0xb1, 0xbb, 0x46, 0x9b, 0xcf, 0xbb, 0x65, 0x40, 0x5a, 0xbc, 0xd9, 0xb4, 0xe8, 0x3c,
+  0xfc, 0x1d, 0x18, 0xbc, 0xe1, 0x69, 0x0b, 0x3b, 0x5a, 0xfc, 0x7b, 0xbc, 0xf4, 0x4f, 0xd6, 0x3b,
+  0x4b, 0x15, 0x9d, 0xba, 0xcd, 0xca, 0x85, 0x3b, 0xe9, 0x7c, 0xc7, 0xba, 0xdd, 0x19, 0xcf, 0x3c,
+  0x6d, 0xe0, 0x8b, 0xbc, 0x34, 0xf6, 0x3e, 0x3c, 0xb0, 0x7b, 0xd2, 0xbb, 0xb1, 0x1d, 0x04, 0x3b,
+  0xdc, 0x5c, 0x4b, 0xbb, 0xc6, 0xbc, 0x17, 0x3b, 0xd1, 0x8b, 0x25, 0x3c, 0xe4, 0x2b, 0xcd, 0x3c,
+  0x8d, 0xff, 0x55, 0xbc, 0xfc, 0x33, 0x76, 0xbc, 0x3f, 0xfc, 0x5b, 0xbc, 0x0e, 0x84, 0xc0, 0xbb,
+  0x28, 0x81, 0x77, 0xbc, 0x0f, 0xc0, 0x5c, 0xbb, 0x1b, 0x3a, 0x7a, 0x3b, 0x1a, 0x4f, 0xc4, 0x3c,
+  0xd2, 0xc4, 0x06, 0x3b, 0x23, 0x3a, 0x6e, 0x3b, 0x8c, 0xe5, 0xbd, 0xbb, 0x43, 0xa5, 0xf1, 0x3b,
+  0x59, 0x2d, 0x3a, 0xba, 0x23, 0x6f, 0x84, 0x3b, 0x86, 0xd5, 0x8b, 0x3b, 0x51, 0x59, 0xb7, 0x3c,
+  0x46, 0x5e, 0x3c, 0x3b, 0x25, 0x0a, 0x6d, 0x3a, 0x27, 0x57, 0xb5, 0xba, 0x49, 0x59, 0x17, 0x3b,
+  0x21, 0xe1, 0xba, 0x3b, 0x02, 0x04, 0x8d, 0x3c, 0xc7, 0x60, 0x63, 0xbc, 0xe7, 0x57, 0x6e, 0x3c,
+  0xd1, 0xbf, 0xaf, 0xbb, 0xfd, 0x44, 0xbf, 0x3b, 0x99, 0x30, 0x88, 0xbc, 0x90, 0x2c, 0x6e, 0xbb,
+  0x99, 0xb8, 0x38, 0x3c, 0xcf, 0xc7, 0x78, 0x3c, 0xc5, 0xbf, 0x9d, 0xbc, 0x7f, 0x65, 0x1f, 0x3c,
+  0xd2, 0x19, 0x02, 0xbc, 0xcb, 0x3b, 0xc1, 0xbb, 0x80, 0x58, 0x34, 0x3c, 0x3d, 0x22, 0x7c, 0x3b,
+  0x85, 0xf4, 0x91, 0x3c, 0xc1, 0xab, 0x1a, 0x3c, 0x2c, 0x7e, 0x06, 0x3b, 0x09, 0x32, 0x37, 0x3b,
+  0xdc, 0x6f, 0x1d, 0xbd, 0xd4, 0xb5, 0xa8, 0xbb, 0x83, 0x94, 0xad, 0xbb, 0x0c, 0x60, 0x87, 0x3b,
+  0x00, 0x8b, 0xf0, 0x3b, 0x5f, 0xf3, 0xf1, 0x3c, 0x04, 0x32, 0x1d, 0xba, 0x13, 0xf8, 0x9d, 0x3c,
+  0x7a, 0x7f, 0x16, 0xbd, 0xfc, 0x0f, 0xa7, 0xbb, 0xc9, 0xfc, 0x46, 0x3c, 0x4b, 0x2d, 0x9c, 0xbc,
+  0x28, 0x75, 0x1f, 0x3c, 0x3f, 0x16, 0x83, 0x3c, 0xba, 0x45, 0x99, 0xbc, 0x52, 0x8d, 0x92, 0xbb,
+  0x89, 0x90, 0x0f, 0xbd, 0x12, 0x77, 0x50, 0xbc, 0x1e, 0xa8, 0x83, 0xba, 0x69, 0x28, 0x44, 0xbc,
+  0xac, 0x95, 0x57, 0x3b, 0x2a, 0xff, 0x6a, 0x3c, 0x87, 0xb1, 0x04, 0x3b, 0x28, 0x77, 0x22, 0x3c,
+  0x6e, 0xd8, 0xe7, 0xbc, 0x37, 0x73, 0x55, 0xbb, 0xb9, 0xea, 0x1f, 0x3c, 0xa7, 0x81, 0x7e, 0x3c,
+  0xaf, 0x4d, 0x26, 0xbc, 0x6c, 0x0e, 0xd4, 0x39, 0xbd, 0x32, 0x9e, 0x39, 0x47, 0xb6, 0x39, 0x3c,
+  0x96, 0x91, 0xc3, 0xbc, 0xcf, 0xab, 0x46, 0xb9, 0x27, 0xca, 0x4c, 0xbc, 0xbd, 0xed, 0x6d, 0xbc,
+  0x35, 0xed, 0x8c, 0xbb, 0x48, 0xd2, 0x16, 0xbb, 0x8b, 0x92, 0xcb, 0xbb, 0xf1, 0x67, 0xc7, 0x3b,
+  0xda, 0xfa, 0xaf, 0xbc, 0xc2, 0x0a, 0xc7, 0xbb, 0x76, 0x68, 0x06, 0x3b, 0x80, 0x47, 0x7c, 0xbb,
+  0x02, 0x33, 0xfe, 0xbb, 0x25, 0xb1, 0xd6, 0x3a, 0xee, 0xa5, 0xeb, 0xbb, 0x9c, 0x99, 0x92, 0x3c,
+  0xfb, 0xe3, 0x12, 0xbd, 0xe7, 0x8a, 0x04, 0xbc, 0xd3, 0x46, 0x1a, 0x3b, 0x94, 0x63, 0x7c, 0xbc,
+  0x4f, 0xd5, 0x2a, 0x3a, 0x16, 0xc5, 0x9c, 0xbb, 0x3c, 0x22, 0x01, 0x3b, 0xbe, 0x36, 0x2b, 0x3c,
+  0x70, 0x42, 0xb9, 0xbc, 0x04, 0xfa, 0x3b, 0x3a, 0x2e, 0x86, 0x97, 0x3b, 0xb4, 0x6a, 0x82, 0x3c,
+  0x7a, 0x8f, 0x88, 0x39, 0x23, 0x92, 0x29, 0x3b, 0x53, 0x4a, 0xe0, 0x3b, 0xa5, 0x45, 0xdb, 0x39,
+  0x0b, 0x55, 0x00, 0xbc, 0xda, 0x96, 0xa1, 0x3b, 0xa0, 0xa0, 0xcf, 0xbb, 0xed, 0xc3, 0x1a, 0xb8,
+  0x15, 0x32, 0xb6, 0x3a, 0x68, 0x9b, 0x84, 0xbb, 0xb6, 0x06, 0x3e, 0xbb, 0x8f, 0xea, 0xd1, 0x3a,
+  0xd7, 0xdd, 0xaf, 0x3b, 0xae, 0xeb, 0x85, 0xbc, 0x1b, 0x5e, 0x75, 0xba, 0xff, 0xab, 0x83, 0xb9,
+  0xb9, 0x97, 0x21, 0xbb, 0xa5, 0x4e, 0x29, 0xbc, 0xa2, 0xce, 0x87, 0x3b, 0x09, 0x81, 0x96, 0x3a,
+  0x43, 0xe2, 0xaf, 0xbb, 0xff, 0x21, 0x39, 0xbc, 0x2e, 0xea, 0x43, 0xbc, 0xb0, 0x17, 0x77, 0x3b,
+  0xff, 0xef, 0x5b, 0x39, 0xe3, 0xea, 0xa5, 0xbb, 0x70, 0x7b, 0x6e, 0xbb, 0x99, 0x7a, 0xea, 0x3b,
+  0xa4, 0x4e, 0x15, 0x3c, 0xb9, 0x9e, 0x3d, 0xbb, 0x99, 0x5d, 0x22, 0xbc, 0x43, 0x02, 0x3d, 0xbc,
+  0x30, 0x97, 0x11, 0xbb, 0x1e, 0x47, 0x6f, 0x3c, 0xee, 0x1d, 0x79, 0x3b, 0x9e, 0xa3, 0x28, 0x3c,
+  0x6a, 0x91, 0x4e, 0xbc, 0x50, 0x3c, 0x33, 0xbb, 0x01, 0x16, 0x72, 0xbc, 0x23, 0x02, 0x4e, 0xb9,
+  0x84, 0xd4, 0xc9, 0x3a, 0x0e, 0x76, 0x89, 0xbc, 0x3c, 0xf0, 0xe3, 0xbb, 0x3a, 0x79, 0x96, 0x3c,
+  0x7a, 0xd7, 0x53, 0xbc, 0x8d, 0x4f, 0x66, 0x3c, 0x4d, 0x24, 0x99, 0xbc, 0x37, 0x8e, 0x18, 0xba,
+  0xa1, 0x0d, 0xdf, 0xbb, 0x39, 0x4d, 0x71, 0xbb, 0xd2, 0xb5, 0xa3, 0xb9, 0x46, 0xdb, 0xc7, 0x3c,
+  0x87, 0xea, 0x2a, 0xbc, 0x7f, 0xd6, 0x52, 0xbc, 0x84, 0xb0, 0xad, 0x3a, 0xe7, 0xc2, 0xba, 0x3b,
+  0xf5, 0x99, 0x58, 0x3b, 0x10, 0xca, 0x5a, 0xbb, 0x72, 0xff, 0x77, 0xbb, 0x6d, 0x1e, 0xf2, 0x3b,
+  0x67, 0x86, 0x73, 0xbc, 0x47, 0x5e, 0x6b, 0x3c, 0x4a, 0xa3, 0x89, 0xbc, 0x1b, 0xba, 0xe7, 0x3b,
+  0x6f, 0xa5, 0x0d, 0x39, 0x9c, 0xb6, 0xe8, 0xbb, 0xb4, 0xb2, 0x46, 0x3b, 0x66, 0xb4, 0x80, 0x3c,
+  0xed, 0x23, 0x90, 0x3b, 0x19, 0x2d, 0x19, 0x3b, 0x14, 0xf7, 0xcc, 0xbb, 0xd1, 0xab, 0x19, 0xbc,
+  0x34, 0xe7, 0x4a, 0xbc, 0xa6, 0xa5, 0x07, 0x3b, 0xb5, 0xf2, 0x6a, 0x3b, 0x82, 0x9f, 0xc5, 0x3c,
+  0x7c, 0xe8, 0xe5, 0xbb, 0xdd, 0x24, 0x58, 0xbb, 0xda, 0xf6, 0xda, 0xbb, 0x4f, 0x3f, 0x01, 0x3a,
+  0xc7, 0x7a, 0x39, 0x3c, 0x56, 0x26, 0x70, 0x3c, 0x76, 0x9b, 0xb3, 0xbc, 0x59, 0x1b, 0x6f, 0xbc,
+  0xf0, 0xfb, 0x9a, 0x3b, 0xfb, 0xf4, 0xb9, 0xbb, 0x8a, 0xed, 0xd1, 0xbc, 0x61, 0x31, 0x06, 0xbb,
+  0x0c, 0xb5, 0x9d, 0x3c, 0xfb, 0xae, 0x29, 0x3c, 0xa8, 0xfc, 0xf2, 0xbc, 0x3e, 0x0a, 0xfc, 0x3b,
+  0x84, 0xee, 0xdc, 0xbb, 0x13, 0xaf, 0x09, 0xbb, 0x90, 0x1f, 0x85, 0x3b, 0x0b, 0x95, 0x31, 0xbc,
+  0x6e, 0x83, 0xa3, 0x3c, 0x1f, 0x12, 0xed, 0x3b, 0x73, 0xd9, 0x2f, 0xbb, 0x1c, 0x6f, 0xaf, 0xbb,
+  0x5a, 0xae, 0x2a, 0xbd, 0xe8, 0x76, 0x5e, 0x3b, 0x78, 0x86, 0x1e, 0xbc, 0xf7, 0x9d, 0x36, 0xbc,
+  0x52, 0x17, 0x46, 0x3c, 0x2c, 0xe1, 0x02, 0x3d, 0x9d, 0x13, 0xad, 0x3b, 0x6d, 0xdf, 0x5c, 0x3c,
+  0x4e, 0xd9, 0x2f, 0xbd, 0x08, 0xae, 0x33, 0xbc, 0xa8, 0x0b, 0xb9, 0xbb, 0xff, 0xc7, 0x28, 0x3c,
+  0x21, 0x38, 0xd0, 0x3b, 0x5f, 0x7b, 0xa7, 0x3c, 0x43, 0x75, 0xe5, 0xba, 0x59, 0xb9, 0x05, 0x3c,
+  0x49, 0x91, 0x47, 0xbd, 0x32, 0xda, 0x6f, 0xbc, 0x5b, 0x71, 0xeb, 0xbb, 0x69, 0x7f, 0x5b, 0x3c,
+  0x21, 0xc7, 0xb3, 0xbb, 0x53, 0x48, 0xf0, 0x3b, 0xaf, 0x19, 0x58, 0xbc, 0xf7, 0x38, 0x3e, 0x3c,
+  0xfb, 0x35, 0xfc, 0xbc, 0xdf, 0xae, 0x97, 0xbc, 0x0d, 0x12, 0x1f, 0x3c, 0x14, 0xef, 0x94, 0x3c,
+  0x8d, 0xac, 0x48, 0xbc, 0xa2, 0x2c, 0x85, 0xbb, 0x7e, 0xc8, 0x9f, 0x3b, 0x15, 0x0c, 0x37, 0x3c,
+  0xfc, 0xa3, 0x20, 0xbc, 0xd2, 0x32, 0x2a, 0xbb, 0xd7, 0x3f, 0x76, 0xbc, 0x3e, 0xb0, 0x86, 0x3c,
+  0x09, 0xd2, 0x82, 0xbc, 0x0c, 0x83, 0xd8, 0xbb, 0xf6, 0x19, 0x58, 0xba, 0xb8, 0x73, 0x6e, 0x3c,
+  0x95, 0x41, 0xad, 0xbc, 0xae, 0x7f, 0x23, 0xbc, 0xcc, 0x1e, 0xa1, 0xbc, 0xb8, 0x66, 0xd6, 0x3b,
+  0xf8, 0x3e, 0x7f, 0x3b, 0x19, 0x96, 0xa3, 0xbb, 0xc7, 0x7f, 0x04, 0xbc, 0xfb, 0xc7, 0xfe, 0xba,
+  0x8d, 0x0b, 0x4c, 0xbc, 0x13, 0x1c, 0xac, 0xbc, 0xa6, 0xf2, 0x87, 0xbb, 0x08, 0x61, 0xb4, 0x3b,
+  0x57, 0x54, 0x2b, 0xbb, 0x32, 0xf4, 0xaa, 0xbb, 0xad, 0x78, 0x9e, 0x39, 0xcd, 0x50, 0x91, 0x3c,
+  0xff, 0xc8, 0xa0, 0xbc, 0x24, 0xb7, 0x1d, 0xbb, 0x60, 0x3e, 0xca, 0x3b, 0x6e, 0x40, 0x99, 0xba,
+  0x37, 0x96, 0xd0, 0xb9, 0xbd, 0x08, 0xd3, 0xbb, 0x4a, 0xde, 0x66, 0x3c, 0x2e, 0x85, 0xc4, 0x3c,
+  0x50, 0xee, 0x50, 0xba, 0x06, 0x19, 0x0b, 0xbc, 0xed, 0x1c, 0x0f, 0x3c, 0xba, 0x7a, 0xe1, 0xbb,
+  0xd0, 0xed, 0xbf, 0x3b, 0x24, 0x2d, 0x1f, 0xbc, 0xb9, 0x3a, 0x88, 0x3a, 0xc7, 0x41, 0x01, 0x3c,
+  0x70, 0x53, 0x05, 0xbc, 0x97, 0x7f, 0xeb, 0x39, 0xcb, 0x55, 0xd7, 0xbb, 0x22, 0x99, 0xb2, 0x3b,
+  0x9b, 0xd8, 0xd2, 0xbb, 0xb8, 0xb2, 0x89, 0xbb, 0xbb, 0xeb, 0x2e, 0xbb, 0x01, 0xdf, 0x92, 0x3c,
+  0x42, 0xe6, 0x1a, 0xbb, 0x05, 0x47, 0xc8, 0x3b, 0xd3, 0xfe, 0x06, 0x3c, 0x51, 0xdb, 0x23, 0x3c,
+  0x5f, 0x05, 0xee, 0x3a, 0x1a, 0x8f, 0x04, 0xbb, 0x7b, 0x58, 0xbb, 0x3b, 0xed, 0xf1, 0x82, 0x3c,
+  0x0b, 0x49, 0x0b, 0x3c, 0x7e, 0x06, 0xa2, 0x3c, 0x71, 0x09, 0xeb, 0x38, 0xb1, 0xf2, 0x49, 0xbb,
+  0x8b, 0xde, 0x99, 0xbb, 0x72, 0x04, 0xa7, 0xbb, 0xa9, 0x76, 0x33, 0x3b, 0x38, 0x8d, 0x85, 0x3c,
+  0x3e, 0xe6, 0x2e, 0xbc, 0xce, 0x85, 0x67, 0xbc, 0x8f, 0x9c, 0x0c, 0xbc, 0x56, 0x01, 0x72, 0xb9,
+  0xc5, 0xdd, 0xb8, 0xba, 0x92, 0x5c, 0xf4, 0xbb, 0x23, 0xcd, 0xa5, 0x3b, 0x85, 0x52, 0x65, 0x3c,
+  0x5a, 0xef, 0xb1, 0xbc, 0x06, 0xa8, 0x58, 0xbc, 0x69, 0x7c, 0x5d, 0xbc, 0x78, 0x17, 0xa3, 0x3b,
+  0xfe, 0x03, 0x0d, 0xbb, 0xce, 0x10, 0x3e, 0xbc, 0x1c, 0x7a, 0x29, 0xbc, 0x7a, 0x9b, 0xaa, 0x3c,
+  0x6a, 0xf7, 0x16, 0xbc, 0xef, 0xe7, 0x16, 0xbc, 0xec, 0x33, 0x06, 0xbc, 0xa4, 0xdf, 0x3a, 0xbc,
+  0x8d, 0x4e, 0xdf, 0xbb, 0x32, 0xb0, 0x1a, 0x3b, 0xd6, 0x1d, 0xb3, 0xba, 0xb3, 0x63, 0x21, 0x3c,
+  0xe4, 0x83, 0x9e, 0xbc, 0x01, 0x88, 0x95, 0xbc, 0xb4, 0x7c, 0xd3, 0xbc, 0x02, 0xb8, 0x09, 0xbc,
+  0xff, 0x2f, 0x49, 0xbb, 0xf9, 0x2d, 0x16, 0xb9, 0x94, 0x56, 0x87, 0xba, 0x08, 0x63, 0xda, 0x3b,
+  0xfa, 0xad, 0xda, 0xbb, 0xbf, 0xa6, 0xf9, 0xbb, 0x9b, 0x88, 0xe1, 0x3b, 0xab, 0xe8, 0xad, 0xbb,
+  0x95, 0x7b, 0x05, 0x3b, 0x04, 0x04, 0xd5, 0x3a, 0xa2, 0xd1, 0x61, 0x3c, 0xc0, 0x52, 0xa7, 0x3c,
+  0xad, 0xea, 0x0a, 0xbc, 0xb0, 0x58, 0x0e, 0x3b, 0xbb, 0x0f, 0xeb, 0x3b, 0x68, 0xce, 0xf6, 0x3b,
+  0xa1, 0xfc, 0x13, 0x3c, 0xff, 0x6a, 0xce, 0x3c, 0xda, 0x49, 0x69, 0xbc, 0xe1, 0x5f, 0x09, 0x3b,
+  0x0a, 0x53, 0xfb, 0x3b, 0x72, 0xb4, 0x82, 0xbc, 0x3b, 0xe3, 0xc0, 0xbc, 0x23, 0xb9, 0x25, 0xbc,
+  0x7d, 0xb2, 0xfc, 0x3c, 0x60, 0xd0, 0x94, 0x3c, 0xdc, 0xec, 0x5e, 0xbc, 0x4e, 0x5b, 0xc3, 0x3a,
+  0x47, 0xa2, 0xce, 0xbb, 0x21, 0xcc, 0x56, 0xbb, 0x91, 0xa9, 0xb2, 0xbb, 0xfa, 0x74, 0x1d, 0x3c,
+  0x73, 0x4c, 0x8d, 0x3c, 0xb6, 0xd8, 0xa4, 0x3c, 0x31, 0xa2, 0x80, 0xbc, 0x1f, 0x42, 0x5b, 0xba,
+  0xd6, 0xd1, 0x25, 0xbd, 0x8f, 0xca, 0x50, 0xbc, 0x80, 0x2e, 0x89, 0xba, 0x00, 0xe0, 0x5d, 0x3c,
+  0xe5, 0xa2, 0x98, 0x3c, 0x4e, 0xd9, 0xcf, 0x3c, 0xf3, 0x6d, 0x8f, 0xbc, 0x97, 0x20, 0x0c, 0xba,
+  0x66, 0xad, 0x25, 0xbd, 0x23, 0x15, 0xb6, 0x39, 0x35, 0x60, 0x95, 0xbb, 0x22, 0x26, 0x00, 0xbb,
+  0x25, 0x95, 0x41, 0x3c, 0x1e, 0x7c, 0x4a, 0x3c, 0xee, 0x3c, 0x05, 0x3c, 0x45, 0x50, 0x6f, 0x3c,
+  0x48, 0xf1, 0x2c, 0xbd, 0x0d, 0xa0, 0xb2, 0xbb, 0x02, 0x62, 0x74, 0x3a, 0x1d, 0xf6, 0xee, 0x3b,
+  0xfe, 0x21, 0x48, 0x3c, 0xef, 0xe7, 0x6f, 0x3c, 0x5e, 0xf1, 0x89, 0xbb, 0x87, 0x03, 0xd4, 0xbb,
+  0x5f, 0xb2, 0x37, 0xbd, 0xba, 0x12, 0x5a, 0xb9, 0x34, 0x2f, 0x21, 0x3c, 0xdf, 0x50, 0x84, 0x3c,
+  0x52, 0x85, 0x5c, 0xbc, 0x0a, 0x49, 0x12, 0x3c, 0x46, 0xd6, 0x71, 0x39, 0x7b, 0x95, 0x94, 0x3b,
+  0x4a, 0x0c, 0x9a, 0xbc, 0x79, 0xda, 0xa6, 0xbc, 0x15, 0xd0, 0x87, 0x3a, 0x51, 0x6a, 0x42, 0x3c,
+  0x73, 0x7b, 0xb9, 0xba, 0x78, 0xd0, 0x76, 0xbb, 0xe8, 0x51, 0x42, 0xbc, 0xc9, 0x5e, 0x8e, 0xb9,
+  0x66, 0xa6, 0x20, 0xbb, 0x83, 0xf2, 0x7c, 0xbc, 0xe8, 0xf5, 0x07, 0xbc, 0x06, 0x5f, 0x88, 0xbb,
+  0xe9, 0x5e, 0x0f, 0xbc, 0x28, 0xa9, 0xcd, 0xbb, 0x4e, 0xd4, 0xc9, 0xbb, 0xdf, 0xfc, 0x46, 0x3c,
+  0xa8, 0x0a, 0x1d, 0xbd, 0x13, 0x1b, 0x82, 0xbc, 0xe8, 0xac, 0x0f, 0x39, 0x31, 0x20, 0xee, 0x3b,
+  0x0f, 0x3f, 0x74, 0x3b, 0x02, 0x7b, 0xd1, 0xbb, 0x01, 0x36, 0x27, 0x3c, 0x8b, 0xd2, 0x36, 0x3c,
+  0x8a, 0xbd, 0x1d, 0xbc, 0x99, 0x2d, 0xe5, 0x3b, 0xa9, 0xed, 0x01, 0x3c, 0x5c, 0x4c, 0x1a, 0x3c,
+  0x89, 0x05, 0x5f, 0x3a, 0x0e, 0x16, 0x84, 0x3b, 0x3e, 0x10, 0xf6, 0x3b, 0x3e, 0xad, 0x37, 0x3c,
+  0xd9, 0x3a, 0x49, 0xbc, 0x81, 0xee, 0x6b, 0x3b, 0x74, 0x17, 0x8e, 0xbb, 0xf1, 0xfa, 0x59, 0x38,
+  0x7b, 0x65, 0x16, 0xbc, 0x20, 0x01, 0x8f, 0xbb, 0x47, 0x7a, 0xa2, 0x3c, 0xcc, 0xfc, 0x61, 0x3b,
+  0xad, 0x1f, 0xff, 0x3b, 0xc6, 0xe5, 0x2a, 0x3b, 0xcb, 0x2c, 0x12, 0x3b, 0x11, 0x25, 0x45, 0xbc,
+  0xcb, 0xb7, 0x13, 0xbc, 0x2a, 0x83, 0xb8, 0xbb, 0x19, 0xbf, 0x60, 0xbb, 0xd9, 0xe7, 0x22, 0x3c,
+  0x58, 0x2c, 0x62, 0xbb, 0x7d, 0x88, 0xf8, 0xbb, 0x6d, 0xb4, 0x7c, 0x3b, 0xf5, 0x96, 0x40, 0x39,
+  0xb1, 0xce, 0xd2, 0x3a, 0xf3, 0x5f, 0x91, 0x3b, 0x39, 0x88, 0x82, 0x3c, 0x57, 0x68, 0x9c, 0x3c,
+  0x03, 0x70, 0x95, 0xbb, 0x1b, 0x85, 0xd8, 0x3b, 0x85, 0x6b, 0x1d, 0xbb, 0x26, 0x98, 0xcd, 0xbb,
+  0x4e, 0x59, 0xce, 0x3a, 0x7b, 0xa4, 0x91, 0xbb, 0x7a, 0x91, 0xeb, 0x3b, 0xc7, 0xd2, 0xbd, 0x3b,
+  0x8b, 0xe0, 0xff, 0xbb, 0xcd, 0x58, 0xac, 0xbb, 0xa2, 0x01, 0x64, 0xbc, 0x8a, 0x15, 0x9c, 0xbc,
+  0xba, 0xeb, 0x6e, 0xbb, 0x83, 0xa8, 0xd6, 0xbb, 0xe2, 0x3b, 0x93, 0x3b, 0xc2, 0xc9, 0x5a, 0x3c,
+  0xb1, 0xbf, 0x44, 0xbc, 0xe5, 0x38, 0x0e, 0xbb, 0xdd, 0xe7, 0x5b, 0xbc, 0x87, 0x74, 0x98, 0xbb,
+  0x3f, 0x66, 0x41, 0xbb, 0xcb, 0x1d, 0x71, 0xbb, 0xc1, 0xac, 0xe5, 0xbb, 0x26, 0xfe, 0x00, 0x3d,
+  0x5b, 0x66, 0x9c, 0xbb, 0x9b, 0x5f, 0x96, 0xbc, 0xed, 0x83, 0x87, 0xbc, 0x86, 0x41, 0xa0, 0xbc,
+  0x48, 0x37, 0x3b, 0xbb, 0x8a, 0xf8, 0x26, 0xba, 0x34, 0x82, 0xb9, 0x3c, 0xd8, 0xe2, 0xaa, 0x3c,
+  0x59, 0x8a, 0x93, 0xbc, 0x42, 0xe0, 0x9b, 0x3b, 0xd3, 0x25, 0x85, 0xbc, 0x9d, 0xc8, 0x1f, 0xbc,
+  0x81, 0x07, 0xe9, 0xbb, 0xad, 0x54, 0x1e, 0x3c, 0x63, 0x37, 0x16, 0xbb, 0x39, 0xca, 0x62, 0x3c,
+  0xc5, 0x94, 0x25, 0xbc, 0x5b, 0xa0, 0x10, 0xbc, 0x85, 0x83, 0xe0, 0xbb, 0x1f, 0x6b, 0x23, 0xbc,
+  0xb3, 0x63, 0xc4, 0xbb, 0xdd, 0xe0, 0x17, 0xbc, 0x32, 0xad, 0xdb, 0x3b, 0x1e, 0xca, 0xd0, 0x3c,
+  0x3e, 0xe5, 0x00, 0xbc, 0x73, 0x8b, 0x3c, 0x3b, 0x0c, 0x5c, 0x43, 0x3c, 0x03, 0x66, 0xdf, 0x3a,
+  0xdf, 0x29, 0xba, 0x3c, 0xfb, 0x04, 0x8a, 0x3c, 0xca, 0x6c, 0x69, 0xbc, 0x76, 0xea, 0x50, 0x3b,
+  0xe8, 0x1e, 0x11, 0x3c, 0xce, 0x38, 0xe8, 0x3b, 0xdf, 0x09, 0x35, 0xbc, 0x8e, 0x2f, 0x01, 0xbc,
+  0x35, 0xa2, 0x86, 0x3c, 0x00, 0x16, 0xb6, 0x3c, 0xf6, 0xb2, 0x97, 0xbc, 0xf0, 0xc3, 0x4a, 0x3c,
+  0x42, 0x11, 0xce, 0xbc, 0x0f, 0x71, 0x15, 0xbc, 0x97, 0x6b, 0x9f, 0xba, 0x51, 0x61, 0x04, 0x3b,
+  0x4d, 0x9b, 0x98, 0x3c, 0xb1, 0x1d, 0x6d, 0x3c, 0x9b, 0xfa, 0x9c, 0xbb, 0xe8, 0xbc, 0x5f, 0x3b,
+  0xcb, 0xcf, 0x4f, 0xbd, 0x55, 0xda, 0xa5, 0xbc, 0x18, 0x61, 0x9b, 0xbc, 0xd0, 0xb2, 0x08, 0x3c,
+  0x36, 0x95, 0x3e, 0x3c, 0xb4, 0xc0, 0x27, 0x3d, 0x04, 0x88, 0xb4, 0xbc, 0xef, 0x46, 0x15, 0xbb,
+  0x12, 0x88, 0x58, 0xbd, 0x0f, 0xc6, 0x0a, 0xbb, 0x9f, 0xc0, 0xaf, 0x3b, 0xd0, 0x33, 0x9b, 0x3b,
+  0x25, 0x9a, 0x30, 0x3c, 0xeb, 0xb8, 0xac, 0x3c, 0xe8, 0x64, 0x51, 0xbc, 0x08, 0x66, 0x08, 0x3b,
+  0x69, 0x7a, 0x37, 0xbd, 0xb8, 0x34, 0x70, 0xbb, 0xd8, 0x26, 0x69, 0xbc, 0x5b, 0x09, 0xf0, 0x3a,
+  0x02, 0x72, 0x4f, 0x3c, 0x87, 0x54, 0xc5, 0x3b, 0x13, 0xdc, 0x20, 0xbc, 0x76, 0x8c, 0x04, 0x3c,
+  0x6e, 0xaa, 0x38, 0xbd, 0x3e, 0xed, 0x51, 0xbc, 0xf4, 0xba, 0x55, 0xbc, 0x21, 0x3b, 0x84, 0xbb,
+  0x08, 0x44, 0x4d, 0x3a, 0xfb, 0x30, 0x8d, 0xbb, 0x1d, 0xd3, 0x33, 0x3c, 0x4b, 0x50, 0xc2, 0x3a,
+  0x95, 0x41, 0xd5, 0xbc, 0xa8, 0x1a, 0x31, 0xbc, 0x4b, 0xdf, 0xb9, 0x3b, 0x1a, 0x20, 0x76, 0x3c,
+  0x65, 0x97, 0x83, 0xba, 0x5d, 0x03, 0xaf, 0xbb, 0x97, 0xfa, 0x3b, 0x3c, 0xdc, 0xb5, 0x10, 0x3c,
+  0x07, 0x50, 0x8a, 0xbc, 0x7c, 0x17, 0x79, 0x3b, 0xfe, 0xaf, 0x21, 0x3c, 0x28, 0x47, 0x2b, 0xba,
+  0xff, 0xdd, 0x02, 0xbb, 0xbd, 0x10, 0x96, 0xbb, 0x8b, 0xa3, 0x74, 0xbc, 0xd5, 0x8c, 0x64, 0x3c,
+  0x0e, 0x90, 0x67, 0xbc, 0x60, 0x95, 0x71, 0xbc, 0x62, 0xd9, 0x43, 0xba, 0x7b, 0xf2, 0x02, 0xbb,
+  0x4b, 0xa2, 0xb4, 0x3a, 0xd9, 0xa0, 0x02, 0xba, 0x1c, 0x3c, 0xd4, 0xbb, 0x30, 0xb2, 0x87, 0x3c,
+  0x90, 0x26, 0xb6, 0xbc, 0x50, 0x72, 0x01, 0x3a, 0xa6, 0x8a, 0x11, 0x3c, 0xe3, 0xeb, 0x87, 0xbc,
+  0x47, 0xe2, 0xc8, 0xbb, 0x6e, 0xa6, 0xb5, 0xbb, 0x41, 0x4a, 0xdb, 0xbb, 0xad, 0x24, 0x4d, 0x3b,
+  0x6b, 0x70, 0x08, 0xbc, 0xfa, 0x8d, 0xbc, 0x3a, 0xf3, 0x3c, 0x21, 0x3c, 0x9e, 0x42, 0x7f, 0x3c,
+  0x64, 0x3b, 0x9d, 0xbc, 0x3e, 0xf8, 0x6c, 0xbb, 0xd1, 0x36, 0x8d, 0x3b, 0x3d, 0x60, 0xca, 0xbb,
+  0x4c, 0x5e, 0x39, 0xbc, 0x8b, 0xf2, 0x2f, 0xbc, 0xf7, 0x76, 0x3b, 0xbc, 0xd7, 0x27, 0xde, 0xbb,
+  0xef, 0xed, 0x79, 0x3b, 0xb0, 0x7d, 0xfe, 0xbb, 0x9a, 0x9d, 0xf0, 0x3a, 0xe4, 0x01, 0x4f, 0x3c,
+  0xce, 0xab, 0xdc, 0xbb, 0xbb, 0x8d, 0x45, 0x3c, 0x05, 0x31, 0x1d, 0xbb, 0x7c, 0x5a, 0x52, 0x3c,
+  0xe8, 0x62, 0x24, 0x3c, 0x6e, 0xdf, 0xe2, 0xba, 0xa0, 0x1d, 0x64, 0x3c, 0x19, 0xfa, 0xba, 0x3c,
+  0xbb, 0x13, 0x57, 0xbc, 0xa2, 0x94, 0x6b, 0x3c, 0xa2, 0xb8, 0x89, 0x3b, 0x6e, 0x32, 0x3e, 0xbc,
+  0x59, 0x0d, 0x31, 0xbc, 0xc1, 0x9d, 0x91, 0x3b, 0xea, 0xc1, 0x90, 0xbb, 0xca, 0x12, 0xa5, 0x3c,
+  0x03, 0x9d, 0x73, 0xbc, 0x13, 0xaa, 0xe1, 0x3b, 0xb5, 0xdc, 0x3f, 0x39, 0xb3, 0x14, 0x7f, 0x3c,
+  0x11, 0x10, 0xd1, 0xbb, 0x4a, 0x76, 0x3b, 0xba, 0x50, 0xec, 0x14, 0xbb, 0x42, 0xe8, 0xf3, 0x39,
+  0x27, 0xde, 0x82, 0xbc, 0x47, 0x06, 0xde, 0xbb, 0xf3, 0xff, 0x7b, 0xba, 0xdb, 0x0d, 0xb6, 0xbb,
+  0x20, 0xaa, 0x00, 0xbb, 0x92, 0xf8, 0xfb, 0xbb, 0xcb, 0x38, 0xb2, 0x3b, 0xe6, 0x1f, 0xa9, 0x3b,
+  0x48, 0x60, 0x88, 0xbc, 0xc6, 0x5b, 0x5e, 0xbc, 0xbe, 0x90, 0xb5, 0xbc, 0x84, 0xce, 0x19, 0x3c,
+  0x3e, 0x05, 0x8b, 0xbb, 0x48, 0xa3, 0x6b, 0xba, 0x81, 0xfe, 0xa7, 0x3b, 0xf0, 0x3f, 0xde, 0x3c,
+  0x5a, 0xe9, 0x96, 0x39, 0x71, 0x65, 0x4d, 0xbc, 0xb3, 0x0d, 0x59, 0xbc, 0xb8, 0x3b, 0x98, 0x3c,
+  0x18, 0x62, 0x42, 0xbb, 0x2e, 0x64, 0x5a, 0xbc, 0xd1, 0x6f, 0xfe, 0x3a, 0x13, 0x42, 0xab, 0x3c,
+  0x97, 0x14, 0x6f, 0xbc, 0xd2, 0x1d, 0xf2, 0x3a, 0x7c, 0x39, 0xa6, 0xbb, 0x1b, 0x02, 0x5a, 0x3b,
+  0x15, 0x76, 0xdb, 0xbb, 0xd5, 0x8d, 0xa0, 0x3a, 0x93, 0x7f, 0xf5, 0xbb, 0x22, 0xaa, 0xff, 0x3b,
+  0x79, 0x86, 0xa7, 0xbb, 0xe2, 0x67, 0x9e, 0xbb, 0x11, 0x25, 0xfb, 0xba, 0x0f, 0x63, 0x2d, 0x3c,
+  0x85, 0x29, 0x84, 0x3c, 0x64, 0x7d, 0x57, 0x3c, 0xb7, 0x94, 0x84, 0xbb, 0xa1, 0x5e, 0x07, 0x3c,
+  0x53, 0x8e, 0x5a, 0xbc, 0xac, 0xa3, 0x8e, 0x3b, 0x8d, 0x5c, 0x95, 0xbb, 0x45, 0x65, 0xf9, 0xbb,
+  0x0d, 0xc8, 0xfe, 0x3c, 0xc7, 0x99, 0x6a, 0x3c, 0x01, 0xdc, 0xc1, 0xbc, 0x59, 0x67, 0x07, 0x3b,
+  0x6e, 0x2e, 0x29, 0xbc, 0xe2, 0x13, 0x0c, 0xbc, 0x7b, 0xd2, 0xde, 0x3b, 0x1b, 0x86, 0xa4, 0xbb,
+  0x4a, 0x21, 0x53, 0x3c, 0xfc, 0x2f, 0xb9, 0x3c, 0x15, 0x3a, 0xe0, 0xbc, 0x88, 0x0b, 0xed, 0xbb,
+  0x60, 0x05, 0x0a, 0xbd, 0x89, 0xd8, 0x03, 0xbc, 0x04, 0xf8, 0xed, 0x3b, 0xb6, 0x89, 0x2c, 0x3c,
+  0xbb, 0xd0, 0x68, 0x3c, 0xfc, 0xbc, 0xe0, 0x3c, 0x4d, 0x82, 0x20, 0x3b, 0xcc, 0x24, 0x69, 0x3c,
+  0xee, 0xd9, 0x5a, 0xbd, 0x8a, 0x21, 0x4a, 0xbc, 0xeb, 0xbd, 0xc6, 0x3b, 0xad, 0x85, 0x36, 0xbb,
+  0x35, 0x90, 0x84, 0x3c, 0x31, 0xc1, 0xf7, 0x3c, 0x27, 0x51, 0x64, 0xbc, 0xba, 0x57, 0x87, 0x3c,
+  0xed, 0x86, 0x31, 0xbd, 0x45, 0x75, 0x60, 0xbc, 0x41, 0xe6, 0x32, 0xbc, 0x6b, 0x36, 0xf0, 0x3b,
+  0x31, 0xd1, 0x13, 0x3b, 0x85, 0x9d, 0x97, 0x3c, 0xfd, 0xec, 0x94, 0x3a, 0xce, 0x2a, 0x08, 0x3c,
+  0xda, 0xfe, 0x48, 0xbd, 0x55, 0x2f, 0x17, 0x3b, 0x9b, 0x2e, 0x46, 0xbb, 0x4d, 0x48, 0x26, 0x3b,
+  0xbb, 0xa6, 0xad, 0x3a, 0x09, 0x0b, 0x0c, 0x3a, 0x8d, 0xf7, 0x21, 0xba, 0x24, 0x94, 0x95, 0x3c,
+  0xc9, 0xd6, 0xb1, 0xbc, 0x48, 0x93, 0x90, 0xbb, 0xcd, 0xf7, 0x87, 0xbb, 0xa1, 0xb4, 0x4e, 0xbb,
+  0x26, 0x10, 0x28, 0x3b, 0x54, 0xfc, 0xc3, 0xbb, 0xc1, 0x4f, 0x06, 0xbc, 0xb9, 0x7e, 0x88, 0x3c,
+  0x9a, 0xb9, 0xb2, 0xbc, 0xa7, 0xd0, 0x89, 0xbc, 0x99, 0x5b, 0x0d, 0x3b, 0x3e, 0xea, 0x82, 0x3b,
+  0x3b, 0x57, 0x3e, 0xbb, 0x0a, 0xc3, 0x24, 0xba, 0x2e, 0x79, 0xcb, 0x3a, 0xa4, 0x03, 0x02, 0x3b,
+  0x4c, 0x02, 0x03, 0xbd, 0x5e, 0x2e, 0xa2, 0xbc, 0x20, 0x60, 0x1d, 0x3c, 0xea, 0xa8, 0x3a, 0x3b,
+  0xc7, 0xd2, 0x04, 0xbc, 0xc3, 0x45, 0x49, 0x3b, 0x2f, 0xb3, 0x54, 0xbc, 0x39, 0x67, 0x15, 0x3b,
+  0x7e, 0xa1, 0x2a, 0xbc, 0x53, 0x77, 0x2f, 0xbc, 0x80, 0x33, 0x49, 0x3a, 0x3e, 0x74, 0xa1, 0xba,
+  0x6d, 0x92, 0xcc, 0x3b, 0x31, 0x0d, 0x4e, 0xb9, 0x7a, 0x95, 0x7e, 0x3b, 0x77, 0x89, 0x13, 0xba,
+  0x26, 0x79, 0x40, 0xbc, 0xc1, 0x83, 0x25, 0xbb, 0x64, 0x86, 0x63, 0xba, 0x99, 0x32, 0x17, 0x3c,
+  0x3f, 0xcb, 0x84, 0xba, 0x0d, 0x39, 0x1b, 0xbc, 0x08, 0x09, 0x63, 0xbb, 0xfc, 0xca, 0x92, 0x3a,
+  0x70, 0x68, 0xcc, 0xbb, 0xb1, 0xd1, 0x15, 0xba, 0x51, 0xc6, 0xb0, 0xb9, 0xd9, 0xad, 0x7c, 0x3b,
+  0xa4, 0x00, 0xfa, 0x3a, 0x4c, 0x25, 0x14, 0xbc, 0xd2, 0xdb, 0x47, 0x3c, 0x13, 0xfe, 0x62, 0x3c,
+  0x51, 0xdd, 0x39, 0xbb, 0x1c, 0xcf, 0x97, 0x3b, 0xdb, 0xed, 0xcd, 0x3b, 0x20, 0xfe, 0xde, 0xbb,
+  0x36, 0xf6, 0xea, 0x3b, 0x4b, 0x07, 0x20, 0xbc, 0x32, 0x38, 0x92, 0x3c, 0x91, 0x16, 0x5a, 0x3c,
+  0xf7, 0xce, 0x1e, 0xbc, 0x1c, 0xb6, 0xaa, 0x3b, 0xdf, 0x3a, 0x2a, 0x3a, 0xce, 0x4a, 0x12, 0xba,
+  0x61, 0xd7, 0x06, 0x3a, 0xaa, 0xda, 0xa1, 0xbb, 0x38, 0xf5, 0x6b, 0x3b, 0x6a, 0xe7, 0x90, 0x3b,
+  0xf4, 0x94, 0x3f, 0xbc, 0xf3, 0xc3, 0x6e, 0xbc, 0xad, 0x90, 0x1b, 0xbc, 0xbb, 0x50, 0x89, 0x3c,
+  0xc4, 0xc3, 0x52, 0xbc, 0x22, 0x78, 0x36, 0xbc, 0xea, 0xdc, 0xfd, 0xbb, 0x23, 0x4a, 0xb3, 0x3c,
+  0x79, 0x45, 0x04, 0xbd, 0xcc, 0x83, 0x72, 0xbc, 0x92, 0xc3, 0x07, 0xbc, 0xfd, 0x37, 0x1e, 0x3c,
+  0xfa, 0xe4, 0x30, 0xbc, 0xa4, 0x1a, 0x97, 0xbb, 0x1b, 0xfe, 0xaa, 0xbb, 0x4c, 0x95, 0x64, 0x3c,
+  0xad, 0xe1, 0x8d, 0xbc, 0x1c, 0x56, 0x67, 0xbc, 0xf7, 0xd5, 0x9f, 0xbc, 0xcc, 0x65, 0xfa, 0xba,
+  0x4f, 0xe1, 0x4d, 0xbb, 0x1b, 0xd3, 0xda, 0xbb, 0x98, 0x6c, 0x64, 0xba, 0xf3, 0xbc, 0x8c, 0x3c,
+  0x5f, 0x5d, 0xd7, 0xbb, 0xc2, 0x31, 0x17, 0x3b, 0x38, 0x84, 0xa9, 0xbc, 0x17, 0x6c, 0x11, 0xbc,
+  0xa9, 0xe8, 0x34, 0xbc, 0x30, 0x8a, 0x6a, 0xbb, 0x85, 0x16, 0x35, 0xbb, 0x98, 0xca, 0xaf, 0x3c,
+  0x58, 0x8c, 0xf3, 0xbb, 0xd1, 0x79, 0x54, 0xba, 0x5a, 0x8a, 0x09, 0xbc, 0xfe, 0x61, 0xe1, 0xbb,
+  0xf8, 0x23, 0x3d, 0xbc, 0x9d, 0xc3, 0x91, 0xbb, 0x56, 0xad, 0x31, 0x3b, 0x32, 0x4c, 0x1f, 0x3c,
+  0xe8, 0xb5, 0x00, 0x3a, 0x99, 0xb3, 0xfd, 0x3b, 0x82, 0xe1, 0x48, 0x3b, 0xc8, 0x51, 0xd1, 0xbb,
+  0xa5, 0x2b, 0xe1, 0x3b, 0x55, 0x38, 0xd9, 0x3b, 0x12, 0x7c, 0xf4, 0xbc, 0xb5, 0xbb, 0x64, 0x3c,
+  0x0d, 0xca, 0xd5, 0xbb, 0x64, 0x7e, 0x5b, 0x3c, 0x39, 0x3d, 0x16, 0xbc, 0x27, 0xa7, 0x65, 0xbc,
+  0x8f, 0x39, 0x23, 0x3d, 0xe4, 0xec, 0x82, 0x3c, 0xa7, 0xdc, 0x0d, 0xbd, 0xc7, 0x08, 0xba, 0x3b,
+  0xc7, 0x12, 0x84, 0xbc, 0x7a, 0x93, 0xc1, 0x3a, 0x74, 0xb7, 0x23, 0x3c, 0x1f, 0xb4, 0x23, 0xbc,
+  0xaf, 0xc8, 0x09, 0x3d, 0xd6, 0x21, 0xdf, 0x3c, 0xfe, 0x3a, 0x80, 0xbc, 0xf7, 0xc0, 0x99, 0xbb,
+  0xda, 0xd3, 0x35, 0xbd, 0x5d, 0x20, 0x0e, 0xbc, 0x54, 0x51, 0x9a, 0xbb, 0x1b, 0xa7, 0x7c, 0xbc,
+  0xb7, 0x9b, 0xc7, 0x3c, 0xe7, 0x9a, 0x1c, 0x3d, 0xa5, 0xbb, 0x8a, 0xbc, 0xb4, 0x78, 0x99, 0x3c,
+  0x20, 0x90, 0x3e, 0xbd, 0x5e, 0x10, 0x50, 0x3b, 0xfa, 0x63, 0x15, 0x3c, 0x03, 0xd7, 0x69, 0xbc,
+  0x21, 0x99, 0x73, 0x3c, 0x4e, 0xee, 0xcd, 0x3c, 0xce, 0xef, 0x16, 0xbc, 0x54, 0x35, 0x71, 0x3c,
+  0xdd, 0x3a, 0x0f, 0xbd, 0xcc, 0xd8, 0x5a, 0x3b, 0x6f, 0x80, 0x08, 0x3c, 0x88, 0xbd, 0x16, 0xbc,
+  0x44, 0xe6, 0x36, 0x3c, 0xa3, 0x4b, 0x9c, 0x3c, 0x7b, 0x94, 0xb4, 0xbb, 0xcc, 0xfd, 0x7b, 0x3c,
+  0x5e, 0xa5, 0xf6, 0xbc, 0x46, 0x8b, 0x1e, 0xbc, 0x72, 0xba, 0x05, 0xbc, 0x83, 0x73, 0x2e, 0x3c,
+  0x0f, 0xc1, 0x5a, 0x3a, 0xd1, 0x79, 0x32, 0xbb, 0xc8, 0x88, 0x7a, 0xbc, 0x27, 0x2c, 0x56, 0x3c,
+  0x8a, 0x1f, 0x88, 0xbb, 0x16, 0x38, 0x8f, 0xbc, 0x8a, 0x2d, 0xa6, 0xba, 0xe8, 0x09, 0x9c, 0x3b,
+  0x8f, 0x40, 0x46, 0xbc, 0xc6, 0x5e, 0x1c, 0xbb, 0x76, 0x59, 0x43, 0xbc, 0xd5, 0x16, 0x90, 0x3c,
+  0x1c, 0x40, 0x6b, 0xbc, 0x5d, 0xa8, 0x47, 0xbc, 0x17, 0x32, 0x72, 0xbb, 0x50, 0x1d, 0xf6, 0xbb,
+  0x98, 0x77, 0x0a, 0xbc, 0x69, 0xc9, 0x37, 0xbc, 0x9f, 0xdc, 0x90, 0x3a, 0xaa, 0xf1, 0x37, 0x3b,
+  0x88, 0x72, 0xd7, 0xbc, 0x68, 0x87, 0x5d, 0xbc, 0xd9, 0xe5, 0x1d, 0x3c, 0x1e, 0xb6, 0x62, 0xbc,
+  0x41, 0x94, 0x6d, 0xbc, 0xf5, 0x08, 0x93, 0xbb, 0x97, 0x69, 0x6d, 0xbb, 0x5c, 0x96, 0xc9, 0xba,
+  0x67, 0xd9, 0x88, 0xbc, 0xfb, 0xb3, 0x68, 0xbc, 0x95, 0xfb, 0x78, 0x3b, 0x9b, 0x9d, 0xa4, 0x3b,
+  0x1c, 0x24, 0x5b, 0xbc, 0xa9, 0x16, 0x12, 0x3b, 0xe2, 0xda, 0xae, 0xbb, 0xd1, 0x18, 0x2f, 0x3c,
+  0xca, 0xd6, 0x45, 0xbc, 0xa0, 0xe0, 0x1d, 0x3a, 0xb2, 0xc8, 0x36, 0xb9, 0x70, 0x95, 0x5c, 0x3c,
+  0x2a, 0xd3, 0x47, 0xbc, 0xf6, 0x1b, 0xf6, 0xbb, 0x42, 0x8d, 0xa3, 0xbb, 0x6d, 0xde, 0x46, 0x3c,
+  0x2b, 0xd9, 0x60, 0xba, 0x78, 0x45, 0xb5, 0x3b, 0xd6, 0xe5, 0xd3, 0xbb, 0x32, 0x64, 0x49, 0x3b,
+  0x30, 0x29, 0xaf, 0x3a, 0xaf, 0x99, 0x3c, 0xbc, 0xf6, 0x37, 0xaf, 0x3b, 0xe6, 0xf6, 0x41, 0xba,
+  0x5a, 0x24, 0x65, 0xbc, 0x74, 0x96, 0x43, 0x3c, 0xaa, 0xe9, 0x7c, 0x3b, 0xb3, 0x69, 0x49, 0x3c,
+  0x2d, 0x26, 0x01, 0x3c, 0x02, 0xc3, 0xbb, 0xba, 0x9c, 0x1b, 0x2e, 0x39, 0x4a, 0x11, 0x83, 0x3c,
+  0xd6, 0xd1, 0x00, 0xbc, 0xde, 0x9d, 0x28, 0xbc, 0xfa, 0xa7, 0x3a, 0x3c, 0x22, 0x79, 0x81, 0x3a,
+  0x39, 0x16, 0xca, 0xbb, 0x70, 0x68, 0xdf, 0x3a, 0xc9, 0x57, 0xf6, 0xbb, 0x4e, 0x08, 0x40, 0x3c,
+  0x63, 0x71, 0x90, 0xbc, 0x2d, 0xa6, 0x1a, 0x3b, 0xd1, 0xe5, 0x28, 0x3a, 0x2f, 0x45, 0x85, 0xbc,
+  0x92, 0x06, 0x14, 0xbc, 0xa0, 0x47, 0x37, 0xbc, 0x7e, 0xf4, 0x8a, 0x3c, 0x5d, 0x4f, 0x22, 0x3c,
+  0xbd, 0xbb, 0x1f, 0xbd, 0x6e, 0xc9, 0x4b, 0xbc, 0x38, 0x94, 0xe3, 0xbb, 0xea, 0x61, 0xa2, 0x3b,
+  0xf9, 0x7b, 0x4b, 0xbc, 0xc8, 0xbe, 0x29, 0xbc, 0x80, 0xc1, 0x01, 0x3a, 0xff, 0x13, 0x3e, 0x3c,
+  0x97, 0x98, 0x9c, 0xbc, 0x7a, 0x64, 0xd7, 0xba, 0xa1, 0x8b, 0xe7, 0xbb, 0x32, 0xeb, 0x4a, 0xbc,
+  0x54, 0x9f, 0x1b, 0xbc, 0x8a, 0xe4, 0xb0, 0xbb, 0x70, 0xc5, 0xdf, 0x3b, 0x12, 0x90, 0x67, 0x3c,
+  0x44, 0xbc, 0xcc, 0xbc, 0xa8, 0x04, 0x00, 0xbb, 0x1a, 0x80, 0x44, 0xbc, 0xf7, 0x42, 0xcd, 0x38,
+  0xd3, 0xf6, 0x32, 0xbc, 0x9a, 0x1d, 0x02, 0x3c, 0xd1, 0x6a, 0xaf, 0xb8, 0x54, 0x48, 0xbd, 0x3c,
+  0x1f, 0x19, 0x59, 0xbb, 0xbd, 0x7a, 0x20, 0x3c, 0xc3, 0xed, 0xbd, 0xbb, 0x8c, 0x7f, 0x42, 0x3c,
+  0x50, 0x1b, 0x8b, 0xbc, 0x01, 0x89, 0x8d, 0xbb, 0xd6, 0x7c, 0x86, 0xbb, 0x16, 0x28, 0xba, 0x3c,
+  0x2b, 0xcd, 0xbd, 0xbb, 0x10, 0x7a, 0xe1, 0xbb, 0x08, 0xe1, 0x16, 0xba, 0xd7, 0xc8, 0x98, 0x3c,
+  0x89, 0x85, 0x24, 0x3c, 0x39, 0x01, 0x59, 0x3c, 0xab, 0xd4, 0x05, 0xbd, 0xd2, 0xd9, 0xb7, 0x3c,
+  0x5c, 0xe8, 0x30, 0xbc, 0x29, 0x58, 0x1e, 0x3c, 0x9c, 0xb9, 0xa4, 0xbb, 0xe7, 0xac, 0x3c, 0xbc,
+  0x23, 0xd0, 0x04, 0x3d, 0xa4, 0x28, 0xbe, 0x3c, 0x2c, 0xa3, 0x3e, 0xbc, 0x3d, 0xbb, 0x61, 0x3c,
+  0xb7, 0x1d, 0x5c, 0xbc, 0xad, 0x3f, 0x3b, 0x3c, 0xcb, 0xf5, 0x03, 0x3c, 0x2c, 0x91, 0x97, 0x37,
+  0x4a, 0x0a, 0xbe, 0x3b, 0xa5, 0x33, 0xa7, 0x3c, 0x65, 0x33, 0xc8, 0xbb, 0x64, 0xa2, 0xa2, 0x3c,
+  0x26, 0x2a, 0x4f, 0xbd, 0x4a, 0x67, 0x78, 0xbc, 0x0a, 0x59, 0x3a, 0x3b, 0x43, 0xa9, 0x0d, 0xbc,
+  0x1f, 0x69, 0xf1, 0x3c, 0xdd, 0xbb, 0x25, 0x3d, 0x24, 0x41, 0x8b, 0xbc, 0x77, 0x1c, 0x11, 0x3c,
+  0x29, 0xf7, 0x4a, 0xbd, 0x3a, 0xf8, 0x82, 0xbc, 0x04, 0x02, 0xfe, 0xbb, 0x2f, 0xa9, 0x78, 0xba,
+  0xac, 0xdd, 0x30, 0x3c, 0xd8, 0xdd, 0xc7, 0x3c, 0x92, 0xb3, 0x39, 0xbc, 0xaa, 0x08, 0x94, 0x3b,
+  0x5c, 0xff, 0x36, 0xbd, 0xf2, 0x85, 0x59, 0x3b, 0xdb, 0xeb, 0x03, 0xbc, 0xe7, 0xa0, 0xde, 0x3b,
+  0xf4, 0x97, 0x61, 0x3c, 0x43, 0x76, 0xd9, 0x3c, 0x52, 0xd7, 0x8a, 0xbc, 0xda, 0xea, 0x77, 0xba,
+  0x8e, 0xfb, 0x13, 0xbd, 0x2b, 0xfd, 0x6c, 0x39, 0x93, 0x76, 0x86, 0xbb, 0x40, 0xa2, 0x77, 0xbc,
+  0x9b, 0xbf, 0x2a, 0xbc, 0x7b, 0x4a, 0xb3, 0xba, 0x75, 0xa3, 0xd5, 0xba, 0x14, 0x43, 0x43, 0x3c,
+  0xae, 0x1c, 0x06, 0xbd, 0xd3, 0x6f, 0xc7, 0xba, 0x11, 0xcd, 0x26, 0x3c, 0x2b, 0x88, 0x96, 0xba,
+  0xea, 0x80, 0xab, 0x39, 0xda, 0x47, 0xc4, 0xbb, 0xdb, 0x4a, 0xa7, 0xbc, 0xd8, 0xc7, 0x78, 0x3c,
+  0x5b, 0x08, 0xff, 0xbc, 0xf2, 0xa1, 0x60, 0xbc, 0x3b, 0xe0, 0x20, 0x3c, 0x5d, 0x6a, 0xdd, 0x3b,
+  0x20, 0x87, 0xf8, 0xbb, 0xb7, 0x92, 0x98, 0xbb, 0x77, 0x98, 0xdf, 0xbb, 0xd7, 0x8f, 0x1e, 0x3c,
+  0x4c, 0x13, 0xcd, 0xbc, 0x0d, 0x97, 0xfe, 0xbb, 0x7e, 0x54, 0x93, 0xbb, 0x08, 0x03, 0xe1, 0x3a,
+  0xbf, 0xa1, 0xdf, 0xbb, 0xdf, 0xb1, 0xef, 0xb9, 0xc5, 0xba, 0xa7, 0x3b, 0xc9, 0x5e, 0x6e, 0x3a,
+  0xa2, 0x57, 0xb6, 0xbc, 0x0e, 0xed, 0x9a, 0xbc, 0xd5, 0x3d, 0x2f, 0xbb, 0x75, 0xd9, 0x04, 0xbb,
+  0x06, 0x0d, 0x57, 0xbc, 0xa0, 0x0b, 0x78, 0x3a, 0xdf, 0x48, 0x94, 0x38, 0x31, 0x71, 0x22, 0xbb,
+  0x41, 0x48, 0xfd, 0xbb, 0xf6, 0xe7, 0x8c, 0xbc, 0x1a, 0x2c, 0x68, 0x3c, 0x3d, 0x39, 0xfd, 0x3b,
+  0xa8, 0xc7, 0x93, 0x3a, 0xaa, 0x8a, 0x7e, 0x39, 0x5e, 0x52, 0x34, 0xb9, 0x8d, 0xe6, 0x39, 0x3c,
+  0x26, 0xde, 0x34, 0xbc, 0x4b, 0x1b, 0x90, 0xbc, 0x1d, 0x21, 0x6b, 0x3c, 0xba, 0xc3, 0x98, 0xbb,
+  0x17, 0xad, 0xe9, 0xba, 0x4b, 0xe6, 0xb6, 0x3a, 0x2f, 0x07, 0x02, 0xbc, 0xcc, 0x7a, 0x9d, 0x3b,
+  0xe3, 0x24, 0x29, 0xb9, 0xe5, 0x0b, 0x2d, 0x3c, 0x27, 0x00, 0x2b, 0xb8, 0xc1, 0x93, 0xf0, 0x3b,
+  0x44, 0x2e, 0xbe, 0xbb, 0x68, 0xeb, 0x2d, 0x3c, 0xb9, 0x99, 0x39, 0xbb, 0x7b, 0x08, 0xa9, 0x3b,
+  0x7d, 0x79, 0x6e, 0xbc, 0xef, 0xed, 0x33, 0xbb, 0x98, 0xf4, 0x78, 0xbc, 0xcf, 0x51, 0x56, 0x3b,
+  0x46, 0x67, 0x12, 0xbb, 0x5d, 0xcf, 0x70, 0x3a, 0x45, 0x8a, 0x81, 0x3c, 0xad, 0xac, 0xdf, 0x3b,
+  0xec, 0x79, 0x88, 0xbc, 0xaa, 0x65, 0xa8, 0x3b, 0xd2, 0x21, 0x30, 0xbc, 0xce, 0x6f, 0xf7, 0xbb,
+  0x87, 0xe9, 0x27, 0xbc, 0x9f, 0x15, 0x17, 0xbb, 0x2d, 0xed, 0x45, 0x3c, 0x68, 0x22, 0x8e, 0x3b,
+  0x61, 0x74, 0xac, 0xbc, 0x58, 0xb7, 0xd7, 0xbb, 0x38, 0x62, 0x05, 0xbc, 0xa8, 0xb2, 0xad, 0x3b,
+  0x20, 0xf0, 0x67, 0x39, 0x83, 0x37, 0x21, 0xbc, 0xc0, 0x62, 0x48, 0x3c, 0xad, 0xef, 0xb8, 0x3c,
+  0x3a, 0xdb, 0x2d, 0xbc, 0xf7, 0xe7, 0x3c, 0x3b, 0xc4, 0x6f, 0xc6, 0x3a, 0xa5, 0xc3, 0x96, 0xbb,
+  0x6e, 0xb7, 0x6f, 0xbb, 0x30, 0x06, 0x2a, 0xbb, 0x2a, 0x4e, 0x9c, 0xba, 0x17, 0xaa, 0x61, 0x3c,
+  0x40, 0xc8, 0x2b, 0xbc, 0xfc, 0xe9, 0x87, 0xbc, 0xb4, 0x01, 0x17, 0xbc, 0x19, 0x22, 0xcb, 0xba,
+  0x93, 0x96, 0x15, 0xbb, 0xc6, 0xda, 0x46, 0xbc, 0x9f, 0x1e, 0x4d, 0xba, 0x8a, 0x2f, 0x39, 0x3c,
+  0x2f, 0x39, 0xbc, 0xbb, 0x99, 0xd6, 0xe0, 0xba, 0x4e, 0x9a, 0xb1, 0x3b, 0xa4, 0x5c, 0x99, 0xbb,
+  0xf4, 0xed, 0x08, 0xbb, 0x43, 0x30, 0xad, 0x3b, 0x4f, 0xdc, 0x25, 0xbb, 0xc4, 0xee, 0x9a, 0x3c,
+  0x96, 0x4a, 0x5d, 0x3b, 0xd5, 0x6d, 0x9c, 0xb9, 0x5e, 0xb6, 0x5c, 0x3b, 0x4a, 0x6e, 0x6d, 0x3c,
+  0x6b, 0x2e, 0xb5, 0x3a, 0xd1, 0xd2, 0x81, 0x3c, 0xdf, 0x24, 0xc1, 0xbc, 0x66, 0x70, 0x84, 0x3c,
+  0x8f, 0x2e, 0x16, 0x3b, 0xe8, 0x0e, 0x4e, 0xbc, 0x52, 0x51, 0x2f, 0xbc, 0x31, 0xfe, 0x40, 0xbc,
+  0x52, 0x94, 0x02, 0x3d, 0xbb, 0xc5, 0xb4, 0x3c, 0x14, 0x65, 0x45, 0xbc, 0x07, 0xa6, 0x20, 0x3c,
+  0x8c, 0xd1, 0x19, 0xbb, 0xbc, 0x2a, 0x97, 0x3b, 0x73, 0xc6, 0x6d, 0x3c, 0x3a, 0x8f, 0x91, 0xba,
+  0x8b, 0xa1, 0xad, 0x3c, 0xaa, 0x8c, 0x8e, 0x3c, 0x38, 0x60, 0xa9, 0xbc, 0x4b, 0x00, 0xd6, 0xba,
+  0xd1, 0xd1, 0x40, 0xbd, 0x5e, 0x31, 0xb8, 0xbc, 0x8e, 0x68, 0xdd, 0xbb, 0x6c, 0x00, 0x5c, 0x3c,
+  0x48, 0x93, 0xc4, 0x3c, 0xe3, 0x0b, 0x1f, 0x3d, 0x20, 0x3e, 0x35, 0x3a, 0x2e, 0x8b, 0xc6, 0xbb,
+  0x8c, 0x87, 0x25, 0xbd, 0x20, 0x7e, 0x73, 0xbc, 0xf3, 0xfa, 0xb7, 0xbb, 0x38, 0x70, 0x54, 0xbc,
+  0xf3, 0xa7, 0x59, 0x3c, 0x55, 0xcc, 0xd7, 0x3c, 0xc4, 0xdc, 0xec, 0xbb, 0xe7, 0x38, 0xeb, 0x3b,
+  0x96, 0x8a, 0x2d, 0xbd, 0x54, 0x09, 0x92, 0xbc, 0xb7, 0x2b, 0x66, 0x38, 0x2a, 0xdf, 0x9d, 0xbb,
+  0x9b, 0xaf, 0xed, 0x3b, 0x51, 0x75, 0x3a, 0x3c, 0x42, 0x72, 0x73, 0xbc, 0x83, 0xd2, 0xf5, 0x3b,
+  0x62, 0x64, 0xd6, 0xbc, 0x83, 0x92, 0xe5, 0xbc, 0x32, 0x10, 0x3c, 0xbc, 0xc3, 0x17, 0x23, 0xbc,
+  0x54, 0x66, 0xe1, 0xbb, 0xe7, 0x10, 0xd0, 0xba, 0xee, 0xb1, 0x9d, 0xbb, 0x1c, 0xd5, 0x91, 0x3a,
+  0x01, 0x5b, 0xf2, 0xbc, 0xc6, 0x19, 0x3b, 0xba, 0x35, 0xcf, 0x12, 0x39, 0xdb, 0x57, 0x46, 0x3c,
+  0x88, 0xf5, 0xda, 0x3a, 0xdd, 0xe0, 0xed, 0x3b, 0x99, 0x0f, 0x9b, 0x3a, 0x43, 0x53, 0x86, 0x3c,
+  0x5d, 0x59, 0xac, 0xbc, 0x24, 0x1b, 0x46, 0xbc, 0x82, 0x00, 0x4f, 0x3b, 0x5b, 0x9c, 0xef, 0x3b,
+  0x70, 0x1d, 0x51, 0xbc, 0x14, 0x86, 0x4e, 0x3c, 0x51, 0x6c, 0x93, 0x3b, 0x44, 0x0a, 0xa5, 0x3b,
+  0x0c, 0xf3, 0x8c, 0xbc, 0xd0, 0x35, 0xb4, 0xbc, 0x22, 0x92, 0x0b, 0x39, 0xa8, 0x25, 0x23, 0x3b,
+  0xa6, 0xd0, 0x0c, 0xbc, 0xf8, 0x0a, 0x78, 0xbb, 0xff, 0x63, 0x8c, 0xbc, 0x15, 0x93, 0x1e, 0x3c,
+  0x45, 0xa9, 0xbb, 0xbc, 0xe2, 0x1c, 0xa0, 0x3b, 0xe3, 0xee, 0x9f, 0x3b, 0x4c, 0x65, 0x31, 0xbb,
+  0x50, 0xf3, 0x22, 0xbc, 0x44, 0xe2, 0x06, 0x3b, 0x89, 0xc2, 0xd0, 0xbb, 0x18, 0xe4, 0x41, 0x3b,
+  0x5a, 0x18, 0x87, 0xbc, 0x5c, 0xf2, 0x1d, 0x3b, 0x31, 0x2f, 0x16, 0xbb, 0xf1, 0x9f, 0xc1, 0xba,
+  0xb1, 0xd9, 0x62, 0xbc, 0x40, 0x86, 0x1b, 0xbc, 0x09, 0x90, 0xd1, 0xba, 0x06, 0x33, 0x20, 0x3c,
+  0x06, 0xd9, 0x9f, 0xbc, 0x61, 0xa1, 0x03, 0x3c, 0x2f, 0xba, 0xdc, 0x3b, 0x88, 0x97, 0x4a, 0xbc,
+  0xd6, 0xe2, 0x3a, 0x3b, 0x18, 0xba, 0x1d, 0xbc, 0x37, 0x3e, 0x85, 0xbc, 0x14, 0x63, 0x83, 0x3c,
+  0xfb, 0xd4, 0x9e, 0xbc, 0xa0, 0xdd, 0x85, 0xb8, 0x23, 0xba, 0xc0, 0x3a, 0xba, 0x72, 0xab, 0xbb,
+  0x13, 0x77, 0xa6, 0xbb, 0xad, 0x1a, 0xc7, 0x3b, 0xd2, 0x3e, 0xe4, 0x39, 0xbb, 0x58, 0x20, 0x3b,
+  0x27, 0x23, 0x2b, 0xbc, 0xd1, 0x57, 0xae, 0x3b, 0xd9, 0x47, 0x30, 0x3c, 0xbb, 0xe9, 0xe3, 0x3a,
+  0x3e, 0x96, 0x10, 0xba, 0xae, 0xb9, 0x18, 0x3c, 0xa1, 0xb1, 0xcd, 0xbb, 0x12, 0x90, 0x10, 0x3c,
+  0x8b, 0xee, 0xb5, 0xbc, 0xfa, 0x74, 0x81, 0xbc, 0x3b, 0x17, 0xac, 0x3b, 0xbf, 0x37, 0x58, 0xbc,
+  0x61, 0xa6, 0x3f, 0x3b, 0x12, 0xcb, 0xa1, 0xbb, 0xee, 0x53, 0x77, 0x3b, 0x8e, 0xf1, 0xb0, 0x3c,
+  0x15, 0xf3, 0xb1, 0xbc, 0xc2, 0xff, 0xa5, 0xbc, 0xc6, 0x9c, 0x41, 0xbc, 0x5c, 0x4a, 0x96, 0x3b,
+  0x17, 0xae, 0x1a, 0xbc, 0xaa, 0x8c, 0x90, 0xb9, 0x19, 0x36, 0x51, 0xba, 0xfb, 0xe0, 0xf9, 0x39,
+  0x93, 0xf4, 0x80, 0xbc, 0x7c, 0xaa, 0xba, 0xbb, 0xb0, 0x5b, 0x7f, 0xbc, 0x09, 0x5f, 0x5c, 0x3c,
+  0x23, 0xdf, 0x95, 0xba, 0x0c, 0x37, 0x54, 0xbb, 0x37, 0xab, 0x87, 0xbb, 0x16, 0x40, 0x14, 0x3c,
+  0xf7, 0x98, 0xd3, 0xbc, 0x3e, 0x7e, 0x1a, 0xba, 0x53, 0x99, 0xbf, 0x3a, 0x7c, 0x9f, 0x3f, 0x3b,
+  0x88, 0x6c, 0x36, 0xbc, 0x10, 0x61, 0x8b, 0xbb, 0x25, 0xfd, 0x49, 0x3b, 0xf1, 0xa0, 0x79, 0x3b,
+  0x75, 0x74, 0xa1, 0xbc, 0x58, 0xce, 0xd2, 0xbb, 0x99, 0xee, 0x14, 0xbc, 0x1c, 0x8c, 0x6f, 0x3b,
+  0xfd, 0x77, 0x60, 0xbc, 0xc8, 0x70, 0x9d, 0xba, 0x87, 0x81, 0xbb, 0x3b, 0x40, 0x05, 0x04, 0x3c,
+  0x38, 0xba, 0x26, 0x3c, 0x2f, 0x56, 0x27, 0xbb, 0x90, 0x56, 0x27, 0x3c, 0xd4, 0x0a, 0x80, 0x3b,
+  0xdb, 0x7c, 0x9d, 0x3c, 0x3e, 0x77, 0xfa, 0x3c, 0xb9, 0x4b, 0x47, 0xbc, 0xaf, 0xfb, 0xc5, 0x3b,
+  0x4d, 0x35, 0x7e, 0x3b, 0x7b, 0xf2, 0x1e, 0xbc, 0xe7, 0x0c, 0x3d, 0xbc, 0x24, 0x6c, 0x2a, 0x3c,
+  0x35, 0x51, 0x49, 0x3d, 0x96, 0x2a, 0x0a, 0x3d, 0x0a, 0xad, 0xdb, 0xbc, 0x52, 0xb5, 0x2e, 0x3c,
+  0xe0, 0xbe, 0xf0, 0xbb, 0x71, 0x84, 0x64, 0x3a, 0x7d, 0x2b, 0x8c, 0x3c, 0x46, 0x43, 0xa1, 0xb8,
+  0x9f, 0xde, 0xe1, 0x3c, 0xa6, 0x7a, 0x03, 0x3d, 0x71, 0x86, 0xa4, 0xbc, 0x1b, 0xb4, 0x10, 0x3c,
+  0x19, 0xa8, 0x21, 0xbd, 0x3b, 0xf2, 0x47, 0xbc, 0x28, 0xa1, 0xb6, 0xbb, 0x2f, 0x81, 0x74, 0xbb,
+  0x26, 0xc6, 0xe4, 0x3c, 0xe6, 0x3f, 0x45, 0x3d, 0x4f, 0xa9, 0x5b, 0xbc, 0xed, 0xdc, 0xbf, 0x3b,
+  0x71, 0xd0, 0x19, 0xbd, 0x31, 0x55, 0x02, 0xbc, 0x73, 0xc1, 0x74, 0x3c, 0x50, 0xd0, 0x3c, 0xbc,
+  0x0e, 0x51, 0x9f, 0x3c, 0xa5, 0xe2, 0x2e, 0x3d, 0x6e, 0x8e, 0x81, 0xbb, 0xb3, 0xf0, 0x07, 0x3c,
+  0xcb, 0x87, 0xec, 0xbc, 0x6b, 0xae, 0x76, 0xbc, 0x49, 0xaf, 0x95, 0xba, 0xf0, 0x42, 0x40, 0xbb,
+  0x99, 0xf9, 0x97, 0x3c, 0x96, 0x78, 0x02, 0x3d, 0x15, 0xc5, 0xd8, 0xbc, 0x6a, 0x1b, 0x69, 0x3c,
+  0x3f, 0xf6, 0x07, 0xbd, 0xed, 0x7f, 0x1c, 0xbb, 0x23, 0x8c, 0xc5, 0xbb, 0x1b, 0xb4, 0x15, 0x3c,
+  0x87, 0xaf, 0x23, 0x3c, 0x90, 0x44, 0xc5, 0x3b, 0xcd, 0x2e, 0xf1, 0xbb, 0xa8, 0x46, 0x14, 0x3c,
+  0x13, 0xb7, 0xc6, 0xbc, 0x97, 0xa9, 0xf6, 0xbb, 0xf6, 0x0d, 0x66, 0x3b, 0x7c, 0x07, 0x43, 0x3c,
+  0x58, 0x14, 0x56, 0x3b, 0xfe, 0xc3, 0x66, 0xb8, 0xb7, 0xa8, 0x9c, 0xbc, 0x6f, 0xa4, 0x25, 0xbc,
+  0x2f, 0x67, 0x00, 0xbd, 0x4d, 0xf9, 0xfa, 0xbb, 0x23, 0x16, 0xfc, 0xba, 0xdf, 0x04, 0xa1, 0xbb,
+  0xd7, 0x16, 0x05, 0xbc, 0x4e, 0xf6, 0x2c, 0x3c, 0xdc, 0xa0, 0xa6, 0x39, 0x27, 0x61, 0x42, 0x3a,
+  0xe7, 0xdd, 0xf7, 0xbc, 0x20, 0x58, 0x83, 0xbc, 0x54, 0xdc, 0xd9, 0xba, 0xb3, 0x0d, 0x37, 0xbc,
+  0x89, 0x02, 0x33, 0x3b, 0x92, 0x9a, 0x42, 0x3b, 0x85, 0x98, 0xf2, 0xbb, 0x38, 0xa9, 0x76, 0x3b,
+  0x20, 0x70, 0xa1, 0xbc, 0xd8, 0xcf, 0xcb, 0xbc, 0x1e, 0x06, 0x29, 0xbb, 0xe4, 0x82, 0xdd, 0x3b,
+  0x52, 0xd9, 0xe8, 0xba, 0x6c, 0x2b, 0x1e, 0x3c, 0xa1, 0x81, 0xdd, 0xbb, 0x77, 0x08, 0x4d, 0x3c,
+  0xf8, 0x4f, 0x69, 0xbc, 0xa6, 0xc1, 0xcf, 0x3b, 0x90, 0xfb, 0x22, 0xbc, 0xa2, 0x9a, 0x94, 0x3b,
+  0x9e, 0xbb, 0x67, 0x3b, 0xf3, 0xec, 0xfb, 0x3b, 0xa4, 0xe0, 0x4a, 0xbc, 0x93, 0x78, 0x16, 0x3c,
+  0x67, 0x82, 0x21, 0xbc, 0x22, 0x7a, 0xa9, 0xbb, 0xc1, 0xfc, 0x21, 0x3c, 0x07, 0xc2, 0x20, 0x3c,
+  0x3c, 0xe5, 0x21, 0xbc, 0x97, 0xd2, 0x3e, 0xba, 0xd7, 0x65, 0x68, 0xbb, 0x19, 0xef, 0x31, 0x3c,
+  0x1e, 0xa1, 0xb5, 0xbc, 0x1c, 0x57, 0x65, 0xbc, 0xd0, 0x03, 0x6d, 0x3c, 0xa1, 0x1f, 0xaf, 0xbb,
+  0x81, 0x29, 0xff, 0x3a, 0x45, 0x5b, 0x9b, 0x3b, 0xbb, 0x0d, 0xe6, 0xbb, 0xa5, 0xc2, 0xe0, 0x3b,
+  0x72, 0x8d, 0x84, 0xbc, 0xd9, 0x9d, 0x42, 0xbc, 0x94, 0xde, 0x2c, 0x3a, 0x4d, 0xe0, 0x7d, 0x3c,
+  0xc6, 0xe0, 0xba, 0x3b, 0xd1, 0x17, 0x04, 0xbb, 0xe0, 0xef, 0x8c, 0xbc, 0x6b, 0xd6, 0x60, 0xbb,
+  0xee, 0x8c, 0x54, 0xbc, 0x8d, 0xe6, 0x34, 0xbc, 0x85, 0x76, 0x9d, 0xb9, 0xaa, 0xd3, 0x66, 0x3c,
+  0xb6, 0xa0, 0x9b, 0x3b, 0x54, 0xa5, 0x5a, 0xba, 0x98, 0x41, 0x1f, 0xbc, 0x0c, 0xe6, 0x92, 0x3c,
+  0xc9, 0x0e, 0x1e, 0xbd, 0xdd, 0x9c, 0xb3, 0xbc, 0x5e, 0x09, 0x04, 0x3a, 0xed, 0x0f, 0x2d, 0x3c,
+  0x81, 0x91, 0xf6, 0xba, 0x55, 0x4f, 0x38, 0x3c, 0xc1, 0xce, 0x3f, 0xbc, 0x5f, 0xd8, 0x6d, 0x3c,
+  0x8d, 0x0c, 0xc9, 0xbc, 0x3e, 0x49, 0x99, 0xbc, 0xf5, 0xdf, 0x6c, 0xbc, 0xb5, 0xbf, 0xe3, 0xbb,
+  0x3f, 0x34, 0x22, 0xbc, 0x31, 0xac, 0x70, 0x3b, 0x78, 0xd6, 0x1a, 0xba, 0x98, 0x2e, 0xc8, 0x3c,
+  0x9f, 0x2d, 0x56, 0xbc, 0x48, 0x09, 0x12, 0xbb, 0x0d, 0x31, 0x21, 0xbc, 0x69, 0x23, 0x00, 0x3b,
+  0xae, 0x68, 0x58, 0xba, 0x57, 0x92, 0x91, 0xbb, 0x0b, 0x76, 0xd4, 0xba, 0x36, 0x36, 0x71, 0x3c,
+  0x9a, 0x23, 0x0f, 0xbc, 0x58, 0x0e, 0x1f, 0xba, 0xec, 0x82, 0x12, 0xbc, 0xd3, 0xbb, 0x7f, 0xbb,
+  0xf9, 0x8c, 0x7b, 0xbc, 0x45, 0x85, 0x80, 0xb9, 0xa2, 0xf9, 0xb5, 0xba, 0x72, 0x24, 0xa9, 0x3c,
+  0x5c, 0xd4, 0x9c, 0x3b, 0xeb, 0x1d, 0xaf, 0xbb, 0x57, 0x9d, 0x21, 0x3c, 0x0a, 0x41, 0x63, 0x3c,
+  0x3b, 0x6d, 0xd2, 0xbb, 0xb7, 0x36, 0xf6, 0x3c, 0x46, 0xa4, 0x2b, 0x3c, 0x03, 0x25, 0x9b, 0xbb,
+  0x24, 0x64, 0xde, 0xbb, 0xec, 0x95, 0x09, 0xbc, 0x43, 0x52, 0xc1, 0xbb, 0xad, 0x13, 0x05, 0xbc,
+  0x47, 0x43, 0xf3, 0xbb, 0xc7, 0xfc, 0x27, 0x3d, 0x20, 0x53, 0xa4, 0x3b, 0xe4, 0xd2, 0x4f, 0x3c,
+  0xa2, 0x98, 0x04, 0xbd, 0x54, 0xdd, 0x02, 0xbb, 0x52, 0xcd, 0xb6, 0x3c, 0xe8, 0xb2, 0x29, 0xbb,
+  0x09, 0x57, 0xff, 0xbb, 0x76, 0x4d, 0x28, 0x3d, 0xa4, 0x8b, 0x69, 0x3c, 0xa3, 0x33, 0xdd, 0x3b,
+  0x0d, 0x3d, 0xe2, 0xbc, 0x9b, 0x92, 0x3d, 0xbc, 0xf4, 0xd7, 0x3d, 0x3b, 0x52, 0xcf, 0xab, 0x3b,
+  0xf2, 0x63, 0x04, 0x3c, 0xbf, 0x3c, 0x3f, 0x3d, 0x61, 0x55, 0xf4, 0x3c, 0x62, 0x72, 0x67, 0xbb,
+  0x1f, 0x1c, 0x0e, 0xbd, 0x02, 0x73, 0xd7, 0xbc, 0x1b, 0xb7, 0x14, 0xbc, 0x60, 0x10, 0x26, 0xbc,
+  0xa4, 0x02, 0x4b, 0x3a, 0x21, 0xf6, 0x41, 0x3d, 0x6e, 0x41, 0xad, 0x3c, 0x45, 0x4d, 0xc2, 0xba,
+  0x33, 0x24, 0xe6, 0xbc, 0xb5, 0xf4, 0x36, 0xbc, 0xff, 0x35, 0x88, 0xb8, 0x6d, 0x26, 0x36, 0x3c,
+  0x37, 0x1d, 0xef, 0x3b, 0xa4, 0x8e, 0xd6, 0x3c, 0xcb, 0x90, 0x82, 0xba, 0x94, 0x82, 0x7b, 0x3c,
+  0x5c, 0x52, 0xcd, 0xbc, 0x2c, 0xe6, 0x77, 0xbc, 0x1e, 0x9e, 0x77, 0xbc, 0xa8, 0xf6, 0xd5, 0x3b,
+  0xb3, 0xaf, 0x48, 0xbc, 0x4b, 0x15, 0x7c, 0x3c, 0xd1, 0xf2, 0x9e, 0x3b, 0xdd, 0x5d, 0xc2, 0xba,
+  0xec, 0x8b, 0x80, 0xbc, 0x16, 0x9d, 0x0a, 0xbc, 0x33, 0x02, 0xb0, 0x3b, 0xfd, 0x01, 0x90, 0x3a,
+  0x22, 0x74, 0x0a, 0xbc, 0x1f, 0x27, 0x72, 0x3c, 0xf0, 0xdd, 0x13, 0xbb, 0xe7, 0x07, 0x35, 0x3b,
+  0xf3, 0x22, 0xb3, 0xbc, 0xb9, 0x12, 0x12, 0xbc, 0x10, 0xfe, 0x7d, 0xba, 0x71, 0x14, 0x27, 0xbc,
+  0xd4, 0xe9, 0x08, 0xbb, 0x10, 0x3a, 0x0f, 0x3c, 0x13, 0xe1, 0xa0, 0xba, 0xc6, 0x88, 0x20, 0x3c,
+  0x4f, 0xb2, 0xa0, 0x38, 0x01, 0x5a, 0x9c, 0xbc, 0x55, 0x8c, 0x83, 0x3b, 0xe2, 0x8f, 0x98, 0xbb,
+  0xc6, 0x2f, 0x1a, 0xbc, 0x7a, 0x2e, 0x37, 0x3c, 0x52, 0x84, 0x69, 0xbb, 0x7f, 0x24, 0x00, 0x3c,
+  0x7d, 0x2d, 0x52, 0x38, 0x4b, 0x1b, 0x9a, 0xbc, 0x7c, 0x41, 0x3d, 0x3c, 0x95, 0x9a, 0xe5, 0xbb,
+  0x41, 0xb5, 0x09, 0xbc, 0x62, 0x15, 0xef, 0x3b, 0x0a, 0x3b, 0xb5, 0xbb, 0x90, 0xb0, 0xc8, 0x3a,
+  0x33, 0x96, 0x0e, 0xbc, 0x8d, 0x9a, 0x28, 0xbc, 0xd2, 0x0d, 0xf5, 0xbb, 0x8d, 0x14, 0x05, 0xbc,
+  0x34, 0x7c, 0xda, 0xbb, 0xc7, 0xe7, 0x4b, 0x3b, 0xeb, 0x8f, 0x07, 0x3b, 0x70, 0x58, 0x04, 0x39,
+  0x22, 0xb3, 0xc3, 0xbb, 0x0b, 0xfd, 0xe9, 0x3b, 0x57, 0xb7, 0x8d, 0x3b, 0x00, 0xd7, 0x3d, 0x3b,
+  0x77, 0xe0, 0x8c, 0xbb, 0x21, 0x5b, 0xb0, 0x3b, 0x6b, 0x6f, 0xc6, 0xba, 0xd1, 0xa9, 0xf8, 0x39,
+  0xf8, 0x21, 0xad, 0x3a, 0x7f, 0x11, 0xcd, 0x3a, 0x78, 0x64, 0xc0, 0xbb, 0xbd, 0x13, 0x95, 0xbb,
+  0xf3, 0xa2, 0x88, 0xbc, 0xfc, 0xc6, 0x1c, 0x3c, 0xe4, 0x15, 0x5d, 0x3c, 0x6e, 0x35, 0x04, 0xbc,
+  0xc5, 0xaf, 0xee, 0xbb, 0xcc, 0xc5, 0x8a, 0xbc, 0xe2, 0xe5, 0x8f, 0xbb, 0x7b, 0x88, 0x18, 0x3c,
+  0x60, 0xa6, 0x9a, 0xbc, 0x97, 0x6a, 0x23, 0x3c, 0x8a, 0xe9, 0x07, 0xbc, 0x40, 0xac, 0x81, 0x3a,
+  0x69, 0xfe, 0xb3, 0xbc, 0x65, 0x53, 0x41, 0xbc, 0xeb, 0x99, 0x29, 0x3b, 0x50, 0x77, 0x16, 0x3b,
+  0x81, 0x05, 0x6f, 0xbc, 0x7e, 0x12, 0x87, 0x3b, 0x78, 0x27, 0xe3, 0xbb, 0x12, 0x4a, 0x04, 0x3c,
+  0x10, 0x3e, 0xb1, 0xbb, 0x21, 0x8f, 0x08, 0xbd, 0x1b, 0xc9, 0xfc, 0xbb, 0xd5, 0xb0, 0x02, 0x3b,
+  0x1b, 0x03, 0x7c, 0xbc, 0xf7, 0x6c, 0x33, 0x3a, 0x96, 0xb1, 0x2e, 0x3b, 0x95, 0x94, 0xfe, 0x3b,
+  0x93, 0x8a, 0x4c, 0xbc, 0x22, 0xf8, 0x01, 0xbc, 0x47, 0x8f, 0xe2, 0xba, 0x90, 0x52, 0x0a, 0x3c,
+  0x6e, 0xbf, 0x61, 0xbb, 0x97, 0x0a, 0xb9, 0xbb, 0xf0, 0x2f, 0x57, 0x3c, 0xa6, 0xfa, 0xb8, 0x3c,
+  0xb2, 0x28, 0x65, 0xbc, 0x54, 0x43, 0xec, 0x3b, 0xf7, 0x3a, 0x9f, 0xbc, 0x32, 0xfb, 0x96, 0xbb,
+  0x18, 0xae, 0xa7, 0x3b, 0x56, 0x08, 0x05, 0x3c, 0xdf, 0x4b, 0x89, 0xbb, 0x1c, 0x37, 0xbe, 0x3b,
+  0x62, 0x59, 0xf1, 0x38, 0x04, 0x36, 0x47, 0x3b, 0x2d, 0x91, 0x38, 0x3c, 0x25, 0xae, 0x08, 0xbc,
+  0x16, 0x5b, 0x4b, 0x3b, 0x40, 0xec, 0xce, 0x3a, 0xb6, 0x15, 0x99, 0x3b, 0x87, 0x01, 0x95, 0x3b,
+  0x7c, 0xf2, 0x9c, 0xbb, 0x6e, 0x38, 0x48, 0x3c, 0xdf, 0xdc, 0xc9, 0x3b, 0x84, 0xeb, 0x16, 0xbc,
+  0x20, 0x45, 0x7b, 0xba, 0xa7, 0x71, 0xae, 0x3c, 0x09, 0xa5, 0x02, 0x3d, 0x07, 0x03, 0xb6, 0xbb,
+  0x05, 0x8c, 0x52, 0xbc, 0xd6, 0x00, 0x86, 0xbc, 0x39, 0x8b, 0xae, 0xbb, 0xfb, 0x93, 0x8c, 0x3a,
+  0x14, 0x83, 0x90, 0x3c, 0x0f, 0xde, 0x30, 0x3d, 0xfd, 0x5f, 0x0e, 0x3d, 0x79, 0xa9, 0xac, 0xbc,
+  0xab, 0xef, 0x4d, 0xbc, 0x07, 0xa7, 0x8b, 0x3c, 0xcf, 0x6b, 0x6e, 0x3c, 0x1e, 0x63, 0x91, 0xbb,
+  0x57, 0x88, 0xdb, 0x3b, 0x33, 0x52, 0x34, 0x3d, 0x1b, 0x68, 0x35, 0x3d, 0x02, 0x53, 0xfe, 0xbb,
+  0xdf, 0xe9, 0x57, 0xbb, 0x6a, 0x71, 0x5c, 0xbc, 0xba, 0x1d, 0x5c, 0x3c, 0xf1, 0x2e, 0x22, 0xbc,
+  0xe7, 0x2f, 0x9e, 0x3c, 0xc0, 0x04, 0x79, 0x3d, 0x09, 0x77, 0x32, 0x3d, 0x35, 0xbe, 0x19, 0xbc,
+  0xb2, 0xad, 0x37, 0xbb, 0xc3, 0xe1, 0x92, 0xbc, 0xbe, 0xa0, 0xb7, 0x3b, 0x3a, 0xe6, 0xaa, 0xbb,
+  0x8a, 0xbf, 0x7a, 0x3c, 0xc3, 0x50, 0x0f, 0x3d, 0x50, 0x37, 0x1e, 0x3d, 0x59, 0x55, 0x74, 0xbc,
+  0x05, 0x3a, 0x15, 0xbc, 0x4f, 0xfa, 0x4e, 0xbc, 0x25, 0xa7, 0xdb, 0x3b, 0x35, 0x96, 0x93, 0x3c,
+  0xdc, 0xfb, 0x9a, 0x3c, 0x1f, 0x83, 0xc7, 0x3c, 0x0f, 0x73, 0xd0, 0x3c, 0xdd, 0x72, 0x1f, 0x3b,
+  0x61, 0xaa, 0x70, 0xbc, 0xa6, 0x88, 0x5d, 0xbc, 0x2a, 0x07, 0x72, 0x3c, 0x7f, 0xfb, 0x0a, 0xbb,
+  0xb9, 0xa6, 0x68, 0xbb, 0x01, 0x53, 0xe1, 0x3c, 0x73, 0xe3, 0x3f, 0x3c, 0xe9, 0x20, 0xff, 0x3a,
+  0xad, 0x8e, 0x12, 0xbc, 0x19, 0x98, 0x16, 0xbc, 0x8e, 0x0b, 0x1e, 0x3a, 0x84, 0xcd, 0x40, 0xbc,
+  0x0c, 0xda, 0x49, 0xbc, 0xd4, 0xa7, 0x7c, 0x3b, 0x5c, 0xed, 0x8f, 0x3b, 0xea, 0x25, 0xc5, 0x3a,
+  0xfb, 0xe0, 0x44, 0xbc, 0x69, 0x25, 0x54, 0xbb, 0x47, 0x58, 0xdf, 0x3b, 0x51, 0x7a, 0x4a, 0x3b,
+  0x5e, 0xb1, 0x19, 0xbc, 0xb3, 0x62, 0x84, 0x3b, 0x10, 0x13, 0x11, 0x3c, 0x7d, 0xb1, 0x4e, 0x3c,
+  0x69, 0x3f, 0x96, 0xbc, 0xbe, 0xbd, 0x02, 0xbc, 0x7b, 0xe9, 0x7f, 0xbc, 0x69, 0x94, 0x67, 0xbb,
+  0xd9, 0x27, 0x6b, 0xbc, 0x39, 0x42, 0x6e, 0x3c, 0xf7, 0x0f, 0x5e, 0x3c, 0xa5, 0x7d, 0x4b, 0x39,
+  0x28, 0x3d, 0x0a, 0x3c, 0xf2, 0xff, 0xa1, 0xbc, 0x1c, 0x99, 0x93, 0x39, 0x03, 0x7f, 0x8f, 0xbb,
+  0x03, 0xe9, 0x7f, 0x3c, 0xdb, 0xe4, 0x35, 0x3c, 0x25, 0xc3, 0x14, 0x3c, 0x48, 0x28, 0x41, 0x3c,
+  0xe8, 0x4b, 0x84, 0xbc, 0x46, 0xfc, 0x7a, 0xbc, 0xac, 0x70, 0x19, 0xbc, 0x7b, 0xe3, 0x2a, 0x3c,
+  0x31, 0x14, 0x9b, 0x39, 0x23, 0x8d, 0x55, 0x3c, 0xab, 0xde, 0x2f, 0x3b, 0xd0, 0xca, 0xbc, 0x3b,
+  0xc5, 0x15, 0x01, 0xbc, 0x0e, 0xb1, 0x3e, 0xbc, 0x1f, 0x30, 0x39, 0x3c, 0xb3, 0xbb, 0x9d, 0x3a,
+  0xfe, 0x70, 0x39, 0x3b, 0x7b, 0x04, 0xdc, 0x3b, 0x82, 0x00, 0x92, 0x3b, 0x83, 0x3b, 0x30, 0xbb,
+  0xfc, 0xbb, 0x9f, 0x3a, 0x2a, 0xc4, 0xc8, 0xbb, 0x67, 0x53, 0x8a, 0xbc, 0x37, 0x94, 0x30, 0x3a,
+  0x18, 0xa1, 0x1a, 0xbb, 0x53, 0xf4, 0x96, 0x3b, 0xd5, 0xea, 0xa3, 0x3c, 0xdf, 0x42, 0xc0, 0xbb,
+  0xe1, 0x09, 0xa0, 0xbb, 0xcb, 0xef, 0x94, 0xbc, 0xff, 0xb1, 0x34, 0xbc, 0x5c, 0xca, 0x79, 0xba,
+  0x9a, 0xf1, 0x33, 0xbc, 0xcf, 0x43, 0x09, 0x3c, 0x15, 0xc0, 0x42, 0x3c, 0x9a, 0x3d, 0x37, 0xbc,
+  0x7a, 0x4e, 0x2b, 0x3b, 0x05, 0x25, 0x83, 0xbc, 0x38, 0x75, 0x27, 0xb9, 0x4a, 0x90, 0x21, 0xbc,
+  0xb0, 0xa9, 0xd9, 0xbb, 0x0e, 0x2b, 0xf4, 0x3b, 0x4e, 0x4a, 0xb8, 0x3b, 0xb6, 0x3c, 0x72, 0xbc,
+  0xda, 0xc4, 0xc7, 0xbc, 0x6e, 0x2a, 0xcf, 0xbc, 0x5f, 0x45, 0xdd, 0xbb, 0x11, 0x6f, 0x76, 0x3c,
+  0xed, 0x8e, 0x97, 0xbc, 0xfd, 0xd5, 0xbe, 0x3b, 0x8c, 0x57, 0x2d, 0xbb, 0xdd, 0x19, 0x11, 0xbb,
+  0xc3, 0xe8, 0x3a, 0xbc, 0xb7, 0x71, 0x83, 0xbc, 0xf9, 0xae, 0xcd, 0x35, 0x64, 0xcd, 0x09, 0xbb,
+  0xcf, 0xa5, 0x55, 0xbc, 0xfb, 0x69, 0x8b, 0x37, 0x4d, 0x53, 0x03, 0x3c, 0x01, 0xcd, 0x72, 0x3a,
+  0x76, 0x4a, 0x4a, 0xbc, 0xd8, 0x77, 0x32, 0x3c, 0xa7, 0x3a, 0x1d, 0x3c, 0x4a, 0xc7, 0x99, 0x38,
+  0x2f, 0xa1, 0xdd, 0xbb, 0xbc, 0x37, 0xd8, 0xba, 0xa9, 0xe9, 0xc0, 0x38, 0x1c, 0x74, 0x70, 0xbc,
+  0x34, 0xff, 0x00, 0x3c, 0x03, 0x08, 0x8c, 0x3c, 0x5c, 0xfc, 0x09, 0x3c, 0x48, 0x3b, 0x20, 0xbc,
+  0x1d, 0x45, 0x13, 0xbc, 0xe0, 0xa5, 0x6b, 0x3c, 0x03, 0xc7, 0x85, 0x3b, 0x3b, 0xa5, 0x3c, 0x3c,
+  0xec, 0xb0, 0xc6, 0x3a, 0x99, 0x62, 0xb5, 0x3b, 0x06, 0x45, 0x06, 0x3b, 0xb4, 0x63, 0xbb, 0xbb,
+  0xf3, 0xe1, 0x24, 0x3c, 0xea, 0xa8, 0xf1, 0x3b, 0xbd, 0x72, 0xfa, 0x3b, 0xda, 0xc4, 0x3e, 0x3c,
+  0x14, 0x87, 0xa3, 0xbc, 0x73, 0xc4, 0xa0, 0x3c, 0xf2, 0x42, 0xf4, 0x3b, 0xf4, 0xdc, 0xe9, 0x3a,
+  0xa6, 0xbc, 0x58, 0x3c, 0x65, 0xb4, 0x02, 0xbc, 0x4f, 0xa3, 0xef, 0x3b, 0x2c, 0x6d, 0xb8, 0x3b,
+  0x89, 0xaf, 0xdd, 0xbc, 0xea, 0x10, 0xe4, 0x3a, 0x81, 0x91, 0x99, 0xba, 0x27, 0x48, 0x23, 0xbc,
+  0x76, 0x5b, 0xc8, 0xb9, 0x31, 0xa8, 0xab, 0xbb, 0xa5, 0x50, 0x67, 0xbc, 0x7e, 0x76, 0x28, 0x3c,
+  0xc7, 0xab, 0x8c, 0xba, 0xeb, 0xda, 0xd0, 0xbc, 0x4d, 0xea, 0xf3, 0x3b, 0x13, 0xd0, 0xdb, 0xb9,
+  0xff, 0x40, 0x0e, 0x3c, 0x29, 0x11, 0x23, 0xbb, 0x39, 0x94, 0x5b, 0xbc, 0x91, 0x46, 0x24, 0xbc,
+  0xb5, 0xc1, 0x62, 0xbb, 0x7b, 0xa3, 0x65, 0xb9, 0x7e, 0x1e, 0x92, 0x3a, 0x9f, 0xde, 0xe5, 0xbb,
+  0x4e, 0x3e, 0x20, 0x3c, 0xca, 0x98, 0x13, 0x3c, 0x64, 0x45, 0x2e, 0x3a, 0x96, 0x22, 0x99, 0x3a,
+  0x0c, 0x38, 0x66, 0xbb, 0x4a, 0xcd, 0x0a, 0x3a, 0xa0, 0xee, 0x49, 0x3b, 0xa0, 0x37, 0xb6, 0x3b,
+  0x4c, 0xcf, 0xa7, 0xbb, 0x5e, 0xf5, 0x9a, 0x3b, 0x76, 0x7f, 0x67, 0x3c, 0x0b, 0x74, 0xdf, 0x39,
+  0xac, 0x86, 0x47, 0x3c, 0x82, 0x5b, 0xd8, 0x3b, 0xb1, 0xe9, 0x25, 0x3b, 0x23, 0xdc, 0xb1, 0xbb,
+  0xb4, 0x4d, 0xa1, 0x3b, 0x69, 0x63, 0x02, 0xba, 0x79, 0x16, 0x02, 0xba, 0x03, 0x75, 0xd8, 0xbb,
+  0x6d, 0xe5, 0x13, 0xbb, 0x2e, 0x46, 0x90, 0xbc, 0x9b, 0x3a, 0x7d, 0xbb, 0x1c, 0xc6, 0x31, 0x3b,
+  0x68, 0x82, 0x30, 0x3c, 0x02, 0xe0, 0xe0, 0xbb, 0x97, 0xbd, 0x8c, 0xbb, 0x13, 0x07, 0xcd, 0x3b,
+  0x2b, 0xa0, 0xdf, 0x3b, 0x4b, 0xaf, 0xb6, 0xbb, 0x08, 0x64, 0x2e, 0xbb, 0xa7, 0xb6, 0x8d, 0xbb,
+  0xe0, 0xc0, 0x1f, 0x3c, 0x37, 0x7c, 0x92, 0xbc, 0xb1, 0x9f, 0x7a, 0xbc, 0x6b, 0x1e, 0xb2, 0xba,
+  0x1f, 0x00, 0x84, 0x3b, 0xc7, 0x1c, 0x2a, 0x3c, 0x25, 0x9b, 0x87, 0xbb, 0xa8, 0x34, 0x29, 0x3c,
+  0x26, 0x7e, 0x06, 0xbb, 0xa6, 0x31, 0x8c, 0x3b, 0x58, 0x5e, 0x99, 0x3c, 0xf7, 0x65, 0x5a, 0x3b,
+  0x30, 0x30, 0x87, 0x3b, 0x58, 0x6f, 0x1f, 0xbb, 0x4c, 0xfd, 0x97, 0x3b, 0xed, 0x26, 0xe2, 0xba,
+  0xb0, 0xc2, 0xbc, 0x3b, 0x2f, 0x6a, 0x5e, 0xbc, 0xc6, 0x40, 0x8f, 0xbc, 0xc1, 0x72, 0x0a, 0xbc,
+  0x07, 0xb3, 0xef, 0xb9, 0x40, 0x43, 0xff, 0x3b, 0x21, 0x5a, 0xd2, 0xbb, 0x3d, 0xb4, 0x93, 0x3b,
+  0x3e, 0x0e, 0x4b, 0xbb, 0xd9, 0xb4, 0xba, 0xbb, 0x36, 0x12, 0x88, 0x3c, 0x89, 0x76, 0xca, 0xbb,
+  0x6b, 0x71, 0xbd, 0xbb, 0x95, 0x7b, 0x40, 0x3c, 0x0a, 0xe9, 0x94, 0xb9, 0xf0, 0xea, 0x2c, 0xbb,
+  0x1e, 0x06, 0x0a, 0xba, 0xaa, 0x6e, 0x41, 0x3c, 0x45, 0x62, 0xe5, 0x3b, 0xca, 0x76, 0x04, 0x3c,
+  0x37, 0xd5, 0x18, 0xbc, 0x56, 0xa3, 0x1d, 0xbc, 0xe2, 0x72, 0x82, 0xbb, 0x46, 0x34, 0xef, 0x3b,
+  0xda, 0x1a, 0xfb, 0x3b, 0x23, 0xb9, 0xc5, 0xbb, 0x5d, 0x3a, 0xac, 0xb9, 0x84, 0xf6, 0xa7, 0x3b,
+  0x6d, 0x9f, 0x92, 0xbb, 0x87, 0xf7, 0x46, 0x3b, 0x70, 0x78, 0xb3, 0x3b, 0x6a, 0xe7, 0xd9, 0x3b,
+  0x86, 0x2f, 0x66, 0x3b, 0x7e, 0xbe, 0x58, 0xbc, 0xbf, 0x73, 0x38, 0x3c, 0x90, 0x41, 0x9d, 0x3b,
+  0x36, 0x29, 0x7a, 0x3b, 0xf4, 0xc0, 0xd7, 0x3b, 0xf8, 0xb7, 0x44, 0x3a, 0x0f, 0xf9, 0x96, 0x3b,
+  0xf0, 0x51, 0x1d, 0x3b, 0x7e, 0x44, 0x43, 0x3c, 0x1f, 0x4f, 0x51, 0x3a, 0x02, 0x0a, 0xc9, 0xbb,
+  0x48, 0xe7, 0x59, 0xba, 0xba, 0xd3, 0x8b, 0xba, 0x87, 0x2d, 0xb1, 0x3b, 0x00, 0x3f, 0xeb, 0x3b,
+  0xc3, 0xae, 0x0c, 0xbb, 0x1a, 0x30, 0x2d, 0xbb, 0x3d, 0x6d, 0x20, 0x3b, 0x70, 0x9b, 0x61, 0xbb,
+  0x37, 0xb9, 0x6b, 0xbc, 0xfa, 0xfa, 0x52, 0xbb, 0xbc, 0x40, 0x53, 0x3c, 0x1d, 0xcc, 0x88, 0xbb,
+  0x9f, 0xf7, 0xe9, 0x3b, 0x11, 0xb5, 0x5d, 0x3b, 0xff, 0x78, 0xe2, 0xba, 0x4b, 0x93, 0x0b, 0x3c,
+  0x17, 0x03, 0x9a, 0xba, 0xfa, 0xd1, 0x06, 0x3a, 0x7e, 0xe9, 0xc3, 0xba, 0x60, 0x57, 0xf5, 0xbb,
+  0xa3, 0x1f, 0x04, 0x3b, 0xa4, 0xb4, 0xb4, 0xbb, 0x2a, 0x3f, 0xdb, 0xba, 0x85, 0x72, 0x57, 0x3b,
+  0x76, 0x62, 0xd6, 0xbb, 0x07, 0xfe, 0x09, 0x3b, 0x5d, 0x1b, 0xf3, 0x3a, 0xa6, 0x4f, 0x69, 0x3b,
+  0x2c, 0x06, 0x03, 0xbc, 0x9e, 0x9a, 0xbd, 0x3b, 0x12, 0x3f, 0x13, 0xbc, 0x53, 0x58, 0xdf, 0x3b,
+  0xc7, 0x81, 0x9c, 0xbb, 0x57, 0xaa, 0x06, 0xbc, 0xf4, 0x45, 0x83, 0x3b, 0x26, 0x03, 0x53, 0x3b,
+  0x07, 0x19, 0xe4, 0x3a, 0x45, 0x8f, 0x33, 0xbc, 0x44, 0x50, 0xcf, 0xbb, 0x1e, 0x57, 0x78, 0x3c,
+  0xfd, 0x62, 0x94, 0xbc, 0x45, 0x6c, 0x24, 0x3c, 0x7e, 0xef, 0x72, 0xbb, 0x99, 0x20, 0x32, 0xba,
+  0x70, 0xfd, 0x19, 0xbc, 0xc4, 0x3b, 0x7c, 0xbc, 0x7a, 0xdb, 0xa3, 0xbb, 0xa6, 0x64, 0x22, 0xba,
+  0x5e, 0xd9, 0x32, 0xbc, 0xbe, 0x7e, 0x81, 0x3b, 0x7f, 0x36, 0x9b, 0x39, 0x94, 0x24, 0xfb, 0x3b,
+  0xfe, 0x21, 0xff, 0xbb, 0xbb, 0xe4, 0xf4, 0xba, 0x33, 0xd9, 0x33, 0xbc, 0x28, 0xa2, 0x73, 0x3b,
+  0xc1, 0xa9, 0x3e, 0xbc, 0x3e, 0xda, 0xb0, 0xbb, 0xab, 0x72, 0x7a, 0xbb, 0xdc, 0x24, 0x55, 0xbc,
+  0x13, 0x99, 0x32, 0x3c, 0x10, 0xd4, 0x4c, 0xbc, 0xbd, 0x0e, 0xd3, 0x3a, 0x5a, 0x49, 0xff, 0xba,
+  0x75, 0x64, 0x92, 0x3b, 0x7d, 0x0f, 0xa7, 0xbb, 0xd4, 0x0d, 0x8a, 0xbc, 0xd5, 0x55, 0xdc, 0xbb,
+  0xbe, 0x22, 0xd4, 0xb9, 0xa2, 0x06, 0x21, 0x3b, 0xd4, 0x7d, 0x95, 0xbb, 0xde, 0x9a, 0x77, 0xbb,
+  0x97, 0xb3, 0xac, 0xbb, 0xb1, 0xd5, 0x56, 0x3b, 0xa4, 0xb5, 0x05, 0xbb, 0x95, 0x59, 0xf0, 0xbb,
+  0x70, 0x84, 0x01, 0x3b, 0x43, 0x6a, 0xc7, 0xbb, 0x96, 0xb1, 0x15, 0x3c, 0xa4, 0x8d, 0x76, 0xbc,
+  0x95, 0x62, 0xef, 0x3b, 0x1f, 0xf0, 0xd9, 0xbb, 0x9a, 0x94, 0x9c, 0x3b, 0x65, 0x34, 0x59, 0xbb,
+  0x16, 0x02, 0x9d, 0xba, 0xe1, 0x30, 0x5f, 0x3c, 0x01, 0x00, 0x7d, 0xbc, 0xb5, 0x8a, 0x05, 0x3c,
+  0xda, 0x08, 0x55, 0x3c, 0x06, 0x41, 0x4f, 0xbc, 0xfc, 0xd6, 0x05, 0xbc, 0xb3, 0x0b, 0x14, 0x3b,
+  0xd5, 0x51, 0x11, 0x3b, 0x44, 0x25, 0xbd, 0x3b, 0x5e, 0x96, 0x8a, 0x3c, 0xb4, 0xf2, 0xfd, 0x3b,
+  0x40, 0x5b, 0x89, 0x3b, 0x0b, 0x08, 0x83, 0xba, 0x19, 0x78, 0x8e, 0xbb, 0xb1, 0x4e, 0x4d, 0x3c,
+  0xf1, 0xf4, 0xf0, 0xbb, 0xad, 0x5c, 0xf9, 0xba, 0x46, 0xd5, 0x01, 0x3c, 0x56, 0x4c, 0x60, 0x3c,
+  0x34, 0x82, 0x00, 0xba, 0x12, 0x08, 0xb6, 0x3a, 0x1e, 0x14, 0xbe, 0x3a, 0x13, 0x6a, 0x4d, 0xbc,
+  0xb8, 0xe0, 0x5c, 0x3b, 0x84, 0x16, 0x09, 0x3c, 0x96, 0xa2, 0xb6, 0x3b, 0x42, 0xde, 0xc8, 0x3b,
+  0x6e, 0x45, 0x30, 0x3c, 0xc8, 0x78, 0x1d, 0x3b, 0x80, 0x5c, 0x2b, 0x3b, 0x0b, 0xbc, 0x91, 0x3c,
+  0x61, 0xe8, 0xc7, 0xbb, 0xfd, 0xee, 0xf8, 0x3b, 0x84, 0x83, 0xf6, 0x3b, 0xc3, 0xa4, 0x45, 0x3b,
+  0xea, 0x64, 0x86, 0x3b, 0xde, 0x43, 0x3b, 0xbc, 0x6b, 0xbd, 0x4a, 0x3c, 0x8d, 0x9e, 0xf3, 0xbb,
+  0x90, 0x48, 0x0d, 0xbc, 0x3a, 0x8b, 0x85, 0x3b, 0x4e, 0x7e, 0x80, 0xb9, 0x8a, 0x09, 0x8d, 0x3c,
+  0x2d, 0xe3, 0x85, 0xbb, 0x77, 0xb0, 0x29, 0xbb, 0xab, 0x97, 0x4e, 0xbc, 0x5a, 0xb2, 0x42, 0x3b,
+  0x6f, 0xca, 0x3f, 0xbb, 0x57, 0x20, 0x83, 0x3b, 0x57, 0x32, 0xc1, 0x3a, 0x6a, 0xaf, 0xd6, 0xb8,
+  0xa2, 0xc1, 0xdd, 0xbb, 0x4d, 0x8c, 0x09, 0x3b, 0xc1, 0x7c, 0xf6, 0xbb, 0xd5, 0x63, 0x22, 0xbc,
+  0x3e, 0x6a, 0x20, 0x3c, 0xe1, 0x48, 0x5d, 0x3c, 0x46, 0x50, 0xb3, 0x3a, 0x19, 0xad, 0x80, 0x3c,
+  0xe7, 0x8e, 0x1e, 0x3c, 0x43, 0x3e, 0x61, 0x3c, 0x4e, 0x0b, 0x66, 0xba, 0xa5, 0xf3, 0xab, 0x3a,
+  0xb2, 0xe3, 0x97, 0xbb, 0x1b, 0xfa, 0x82, 0x3a, 0x7d, 0xc7, 0x8a, 0x3b, 0xb2, 0x61, 0x18, 0xba,
+  0x1a, 0x98, 0x5b, 0xb9, 0x64, 0x4a, 0x14, 0x3c, 0xa4, 0x7c, 0x06, 0xbc, 0xca, 0xa6, 0xf9, 0x3b,
+  0x39, 0x84, 0x6d, 0x3c, 0xd2, 0x5b, 0xaa, 0x3b, 0x07, 0x30, 0x65, 0x3c, 0x71, 0x46, 0x5a, 0x3c,
+  0x29, 0x48, 0xe9, 0xbb, 0x4c, 0x3a, 0x9b, 0xbb, 0xb8, 0xa3, 0x40, 0xbc, 0xfd, 0x34, 0xad, 0xba,
+  0xc7, 0x37, 0x1d, 0x3c, 0x49, 0x03, 0x8f, 0x39, 0x7e, 0x6e, 0x83, 0xb9, 0xf5, 0xef, 0x14, 0x3c,
+  0x76, 0x00, 0x92, 0xbb, 0x6c, 0xd4, 0x06, 0xbb, 0xfd, 0x89, 0x01, 0x39, 0x2a, 0x2d, 0x81, 0x3c,
+  0xbd, 0x4d, 0x65, 0xbc, 0x83, 0x03, 0x27, 0xbc, 0x58, 0xda, 0x54, 0x3b, 0xeb, 0xfd, 0xdc, 0x3b,
+  0x5b, 0x6c, 0x8f, 0x3b, 0x58, 0xd1, 0xef, 0xbb, 0x04, 0xcb, 0x84, 0xbb, 0xa6, 0x4e, 0xaa, 0xba,
+  0x6f, 0x98, 0xc9, 0x3a, 0x3c, 0x6e, 0x09, 0xbc, 0x9b, 0x56, 0x47, 0x3c, 0xeb, 0x52, 0xab, 0xba,
+  0x9a, 0xdf, 0xb7, 0xb9, 0x52, 0x68, 0x29, 0xbb, 0x45, 0xe6, 0x9e, 0xb9, 0x41, 0x82, 0x2b, 0xbc,
+  0xc7, 0x5f, 0x0d, 0xbb, 0x63, 0xf9, 0x62, 0x3b, 0x70, 0xcf, 0x00, 0xbc, 0xda, 0x3f, 0x99, 0x3b,
+  0x2f, 0x01, 0xf0, 0x3a, 0x34, 0xb8, 0x03, 0x3b, 0xe7, 0xd5, 0xab, 0x3b, 0xad, 0xa6, 0x0e, 0x3c,
+  0x1e, 0x6b, 0x4a, 0xba, 0xb4, 0xed, 0xad, 0x3b, 0x8c, 0x63, 0x79, 0xbc, 0x7e, 0x72, 0xde, 0xb9,
+  0x84, 0x3a, 0xa2, 0xbb, 0xa7, 0x99, 0x50, 0xbc, 0xdd, 0x91, 0xf6, 0xba, 0x69, 0x6e, 0x04, 0x3c,
+  0xd5, 0xe1, 0x13, 0xbc, 0xe9, 0x85, 0xd2, 0xba, 0x51, 0x10, 0x28, 0x3c, 0xf0, 0xdb, 0xb9, 0x3a,
+  0x8d, 0x10, 0x8a, 0xbc, 0x10, 0xba, 0x90, 0xbc, 0x9a, 0x14, 0xe6, 0x3a, 0x00, 0xab, 0x3e, 0xba,
+  0x83, 0xb8, 0xe1, 0xb9, 0x78, 0x2c, 0xdc, 0x3b, 0x8c, 0x81, 0xa4, 0xb9, 0xa2, 0x70, 0x4b, 0xbb,
+  0xc4, 0xf1, 0x17, 0xbb, 0x6f, 0x0f, 0x50, 0xbc, 0x96, 0x3b, 0x04, 0xbc, 0x88, 0x90, 0x9c, 0xbb,
+  0xf7, 0x31, 0x6c, 0xba, 0x7e, 0xcf, 0x86, 0x3c, 0x9c, 0xe3, 0xed, 0x3b, 0xd7, 0x45, 0x3d, 0xbc,
+  0x79, 0xbf, 0x59, 0xba, 0x0b, 0x05, 0xba, 0xbb, 0x6e, 0x71, 0x9d, 0xba, 0xe7, 0x8b, 0x97, 0xbc,
+  0x32, 0xb1, 0x9e, 0x3a, 0x49, 0x30, 0xa1, 0x3b, 0x4d, 0x74, 0x80, 0xbc, 0xf6, 0xd1, 0xc1, 0xbc,
+  0x9a, 0x34, 0xf2, 0xbb, 0xa7, 0x16, 0x1a, 0x3c, 0xad, 0xc2, 0x12, 0x3b, 0xca, 0x3b, 0xa5, 0xba,
+  0xe0, 0xdc, 0x1f, 0xbb, 0x41, 0x16, 0xc7, 0xbb, 0x5b, 0x76, 0x2b, 0xbb, 0xab, 0xae, 0x2b, 0xbb,
+  0x08, 0x5b, 0xed, 0x3b, 0xdb, 0x8a, 0x74, 0xbb, 0x61, 0xda, 0x2b, 0x3b, 0xfd, 0x61, 0x87, 0x3b,
+  0x7a, 0x87, 0xb2, 0x3a, 0x8d, 0x38, 0x88, 0xbb, 0x67, 0x90, 0x29, 0x3b, 0x49, 0x2f, 0x21, 0x3b,
+  0x49, 0x92, 0x15, 0x3c, 0x35, 0x70, 0x19, 0xbb, 0xac, 0x17, 0x25, 0xbc, 0x46, 0x88, 0x88, 0x3c,
+  0xd8, 0x7d, 0x41, 0xbc, 0x6c, 0xbf, 0x3a, 0x3c, 0xc8, 0x00, 0x13, 0xbb, 0x81, 0x5d, 0x09, 0x36,
+  0x5a, 0x55, 0x72, 0xba, 0x78, 0xe1, 0x89, 0xbc, 0x82, 0xf7, 0x31, 0xbc, 0x1c, 0x9d, 0x2b, 0xbc,
+  0x5f, 0x76, 0xb1, 0xbc, 0xe9, 0xa5, 0x3f, 0xbc, 0xcb, 0xb6, 0x4c, 0x3c, 0x83, 0xac, 0x03, 0xbc,
+  0xbd, 0x05, 0x38, 0x3a, 0xfc, 0x90, 0xf0, 0xbb, 0x26, 0x07, 0x88, 0x3b, 0x18, 0x95, 0x63, 0x3c,
+  0x04, 0x1e, 0x9e, 0xbc, 0x70, 0xbc, 0x03, 0xbb, 0x8c, 0x31, 0x94, 0xbc, 0x69, 0xb4, 0x47, 0x3c,
+  0xd3, 0x36, 0xd6, 0x3a, 0xff, 0x66, 0x1b, 0xbc, 0x4c, 0xf5, 0x52, 0xbc, 0x25, 0x0e, 0xc8, 0xbb,
+  0x41, 0x93, 0x11, 0xbc, 0x49, 0xa5, 0xa0, 0x3b, 0xc3, 0x6d, 0xc2, 0xbb, 0xd4, 0x2c, 0x17, 0x3c,
+  0xd9, 0xae, 0xa5, 0x3b, 0xa4, 0x3c, 0x8d, 0xbb, 0xfb, 0xf5, 0xbc, 0x3b, 0xfe, 0x23, 0x69, 0xb9,
+  0x47, 0xc3, 0x62, 0xbb, 0x7a, 0xf5, 0x29, 0xbc, 0x32, 0x9c, 0x5f, 0xbc, 0xd2, 0xc2, 0x6a, 0xba,
+  0x03, 0x4f, 0x95, 0xb9, 0x82, 0x05, 0xcf, 0x3b, 0xaa, 0x24, 0xa2, 0x3b, 0xbc, 0x31, 0x56, 0x3c,
+  0x60, 0x84, 0x9f, 0xbc, 0x85, 0xc3, 0x30, 0x3c, 0x5e, 0x45, 0x22, 0xbc, 0xf9, 0xc6, 0x35, 0xbc,
+  0x92, 0x5c, 0xf6, 0xb8, 0x1f, 0x38, 0xdc, 0x3b, 0x0b, 0xaa, 0x0a, 0xbc, 0x9c, 0xa4, 0x8d, 0x3c,
+  0xc3, 0x43, 0x07, 0xbc, 0x9c, 0xde, 0x89, 0x3b, 0xda, 0xf5, 0x50, 0x3b, 0xe9, 0xad, 0x00, 0xbc,
+  0x34, 0x8d, 0xaf, 0xbb, 0x38, 0x06, 0x5b, 0x3b, 0xdf, 0x0b, 0xaa, 0xbb, 0x03, 0xe3, 0xaf, 0xbb,
+  0xf8, 0x45, 0xf7, 0x3b, 0xa5, 0xcd, 0x31, 0x3c, 0x47, 0x62, 0x34, 0x3b, 0xb9, 0x25, 0x88, 0xbb,
+  0xc6, 0x9f, 0xe2, 0xba, 0x59, 0x39, 0x58, 0x3a, 0x2c, 0x29, 0x1f, 0xbb, 0x0b, 0x90, 0x4d, 0xbb,
+  0x60, 0x88, 0x43, 0xbc, 0x75, 0x30, 0xa2, 0x3b, 0xea, 0xc8, 0x95, 0x3c, 0xe8, 0x2c, 0xd2, 0xbb,
+  0x25, 0xb5, 0x8d, 0x39, 0xab, 0xda, 0x04, 0x3a, 0x31, 0x13, 0x92, 0x3b, 0x17, 0xf2, 0xb2, 0x3b,
+  0xf4, 0x25, 0x6b, 0x3a, 0x9b, 0xab, 0x9a, 0x3c, 0x9d, 0x91, 0x78, 0xbb, 0x2f, 0x12, 0x0d, 0xbc,
+  0x0a, 0xcb, 0xda, 0xba, 0x19, 0xf0, 0x5e, 0x3c, 0x44, 0xd5, 0x72, 0xbb, 0x0d, 0xe1, 0xd8, 0xbb,
+  0x41, 0x95, 0xea, 0x3b, 0x1f, 0xd3, 0xdc, 0xba, 0xa9, 0xc6, 0xc4, 0x3b, 0xc0, 0x78, 0x7a, 0xbc,
+  0x10, 0x39, 0x2f, 0xbc, 0xca, 0xe5, 0x8e, 0x3a, 0xf7, 0xe1, 0xb1, 0x3b, 0x80, 0x77, 0x4c, 0xb9,
+  0xc0, 0xa1, 0x78, 0xbc, 0x3c, 0x6c, 0x7d, 0x3b, 0xb8, 0xf2, 0x60, 0xba, 0x3e, 0xd9, 0xf4, 0x3b,
+  0x6c, 0x57, 0xe4, 0x3a, 0x60, 0x40, 0x73, 0xba, 0x5b, 0x40, 0x24, 0xbc, 0x56, 0x28, 0x11, 0x3c,
+  0xd6, 0x37, 0x00, 0x3a, 0x33, 0xff, 0xb9, 0x3b, 0xdb, 0x5d, 0xe0, 0x3b, 0xc7, 0x7a, 0x16, 0xbc,
+  0xb8, 0x6e, 0x92, 0x3b, 0x38, 0xe9, 0xbb, 0x39, 0x78, 0x15, 0xbc, 0x3b, 0x63, 0xe8, 0x5f, 0xbc,
+  0xf4, 0x3e, 0xf8, 0x3b, 0x97, 0x71, 0x7f, 0xbc, 0xe8, 0x02, 0xb8, 0xbc, 0xf7, 0xb0, 0x1d, 0x3c,
+  0x5c, 0x84, 0xcc, 0xbb, 0xa3, 0xc3, 0x04, 0xbc, 0xd3, 0x23, 0x88, 0x3b, 0x20, 0x91, 0xf7, 0xbb,
+  0x1b, 0x74, 0x0f, 0xbc, 0x73, 0xbd, 0x52, 0xbc, 0x9f, 0x75, 0x08, 0x3c, 0x1b, 0x4e, 0xc1, 0xbb,
+  0x86, 0x40, 0xa1, 0xbb, 0x78, 0x19, 0xc9, 0xb7, 0x49, 0x6c, 0x3d, 0xbc, 0x76, 0xe5, 0x7d, 0x3c,
+  0x1e, 0xc5, 0x97, 0x3b, 0x2b, 0x34, 0xe2, 0xba, 0x24, 0x2a, 0x2b, 0xbc, 0x6b, 0x7a, 0x87, 0xbb,
+  0xc9, 0x3f, 0x7c, 0x3a, 0xd2, 0x7e, 0x2b, 0x3c, 0x3f, 0x76, 0x47, 0xbc, 0xf8, 0x2b, 0xca, 0xbb,
+  0x01, 0xdc, 0xc7, 0x3b, 0x65, 0x55, 0x5a, 0xbc, 0x0d, 0x78, 0x01, 0x3b, 0xd6, 0xe2, 0x4c, 0xbc,
+  0x7d, 0xd4, 0x01, 0xbc, 0x9e, 0xf0, 0x80, 0xbb, 0x89, 0xcb, 0xf2, 0x3b, 0x74, 0xea, 0x8a, 0x3c,
+  0x3d, 0x7a, 0x83, 0x3a, 0x5f, 0x45, 0x7a, 0xbc, 0xe3, 0x31, 0x0d, 0x3a, 0x75, 0x0d, 0xed, 0x39,
+  0x7a, 0x40, 0xf6, 0x39, 0x4e, 0x71, 0x15, 0x3b, 0xe8, 0x3b, 0xb0, 0xbb, 0xf1, 0xe5, 0xce, 0x3b,
+  0x65, 0x70, 0xa6, 0xbb, 0x56, 0x87, 0xb3, 0xbb, 0xa2, 0x6f, 0x73, 0xbc, 0xbf, 0x97, 0xdf, 0xb9,
+  0x4d, 0xa4, 0xe4, 0x3a, 0xf0, 0xcd, 0xf3, 0x36, 0xf7, 0x8e, 0xba, 0xbb, 0x12, 0x34, 0xc7, 0x3b,
+  0x15, 0x40, 0x10, 0xbc, 0xda, 0xf7, 0xe9, 0xbb, 0xbb, 0xe8, 0x06, 0xbc, 0x4d, 0x6f, 0x90, 0xbb,
+  0xc7, 0xfb, 0xad, 0x3b, 0x8b, 0xbc, 0x28, 0xba, 0x90, 0x3e, 0x56, 0x3c, 0xb8, 0xa6, 0x1d, 0xbc,
+  0xd6, 0x7d, 0x1b, 0x3b, 0x5c, 0x73, 0x40, 0xbc, 0xbb, 0xab, 0xc5, 0xbb, 0xe3, 0x8f, 0x15, 0x3c,
+  0x41, 0x91, 0x0d, 0x3c, 0x74, 0xc5, 0xdf, 0xbb, 0xea, 0xd6, 0xc5, 0xbb, 0xa4, 0x3e, 0xf4, 0xba,
+  0x72, 0x6e, 0x29, 0xbc, 0xdd, 0xa9, 0x2d, 0x3b, 0xde, 0x1a, 0x4b, 0xba, 0xc2, 0xdd, 0x15, 0x3c,
+  0x21, 0x80, 0x0b, 0x3c, 0x67, 0x6e, 0x92, 0xbc, 0x5f, 0x1e, 0x07, 0x3c, 0x2a, 0xc3, 0x68, 0xbc,
+  0xaf, 0xe1, 0xf6, 0xba, 0xf4, 0x4c, 0xc7, 0x3b, 0x17, 0x77, 0x5d, 0x3c, 0xd0, 0x8d, 0x3b, 0xbc,
+  0x07, 0xf0, 0x66, 0x3c, 0x82, 0x8d, 0xf2, 0xba, 0x25, 0x2d, 0xe0, 0xbb, 0xdf, 0x03, 0x6e, 0xbc,
+  0x27, 0x9a, 0x18, 0x3c, 0x33, 0x1c, 0x65, 0x3c, 0xb1, 0x56, 0x94, 0xbc, 0xa6, 0xf0, 0x9e, 0xbb,
+  0x57, 0x89, 0x5d, 0x3c, 0x6f, 0x23, 0x3b, 0x3c, 0xc3, 0x1c, 0x6a, 0x3c, 0x82, 0x35, 0xc3, 0xbb,
+  0xab, 0xec, 0x38, 0xbb, 0x46, 0x93, 0xac, 0x3a, 0x71, 0x9b, 0x8d, 0xbc, 0x52, 0x8c, 0xea, 0x3b,
+  0x68, 0x08, 0xbe, 0xb9, 0xf7, 0x2f, 0x30, 0xba, 0x1d, 0xc1, 0x3c, 0x3c, 0xa4, 0xb0, 0xa6, 0x3b,
+  0xd5, 0xa2, 0x15, 0xbc, 0x38, 0xa4, 0xe3, 0xbb, 0x4f, 0x2f, 0x84, 0xbb, 0x23, 0x70, 0x9a, 0x3a,
+  0xd6, 0x13, 0xbc, 0xbb, 0x05, 0x6a, 0xf6, 0x3b, 0xa9, 0xcd, 0x64, 0xbb, 0x14, 0x6a, 0x22, 0xbc,
+  0xc5, 0xbb, 0xac, 0x3b, 0x5d, 0x71, 0xd9, 0x3b, 0x75, 0x75, 0xe6, 0x3b, 0x3b, 0x8e, 0x36, 0x3a,
+  0x70, 0x9d, 0x6c, 0x3a, 0x36, 0x48, 0x54, 0x3c, 0xa5, 0xd4, 0x48, 0x3b, 0xb1, 0x86, 0xf7, 0x3b,
+  0xff, 0x0a, 0x56, 0x39, 0x04, 0x09, 0x44, 0xbc, 0xbc, 0xeb, 0x88, 0x3c, 0x1f, 0x6b, 0xd0, 0x3b,
+  0x58, 0xc6, 0xa2, 0xbb, 0x13, 0x9e, 0x03, 0x3c, 0xaa, 0x72, 0x71, 0x3b, 0x72, 0x68, 0xb2, 0xbb,
+  0x04, 0x9c, 0xf0, 0x3b, 0x0e, 0x52, 0x12, 0x3b, 0x0b, 0xe9, 0x12, 0x3c, 0x14, 0x79, 0x8c, 0xbb,
+  0x4d, 0x43, 0x06, 0x3a, 0x76, 0x20, 0x25, 0x3a, 0x06, 0xf1, 0xb6, 0x3b, 0xcb, 0x39, 0xa4, 0xbb,
+  0x45, 0xea, 0x52, 0xbb, 0xb3, 0x49, 0x01, 0xbc, 0xe1, 0xa8, 0xa0, 0x3c, 0x22, 0x3e, 0xa4, 0x39,
+  0x2e, 0xe3, 0x37, 0xbc, 0x4b, 0xe6, 0x01, 0x3c, 0xbb, 0x00, 0x87, 0x3a, 0x0f, 0x1e, 0x35, 0xbb,
+  0xec, 0x7b, 0x28, 0xbc, 0xa7, 0x72, 0x2b, 0x3c, 0x95, 0x78, 0xe2, 0x3b, 0xbb, 0x1c, 0xfd, 0x3b,
+  0x76, 0x12, 0x8e, 0x3b, 0xf8, 0xc3, 0xdf, 0x3b, 0x45, 0x13, 0x5a, 0x3c, 0x2f, 0x69, 0x97, 0x3b,
+  0x9e, 0xa5, 0x5f, 0xbc, 0xe9, 0xeb, 0xaf, 0xbc, 0xe1, 0x32, 0x2d, 0x3a, 0xc8, 0x78, 0x62, 0xbc,
+  0x5c, 0xaa, 0x0d, 0xb9, 0x8b, 0x9a, 0x4a, 0x3b, 0x36, 0xa9, 0x6c, 0xbc, 0x92, 0x59, 0x32, 0xbc,
+  0x78, 0xc6, 0x44, 0x3c, 0x6d, 0x2e, 0x09, 0xbc, 0xfb, 0x8c, 0x0c, 0x3c, 0x06, 0x5a, 0xc5, 0xbb,
+  0xeb, 0x1f, 0xdd, 0xba, 0xbf, 0x5c, 0x8d, 0x3a, 0x90, 0x7d, 0xaf, 0x3b, 0xd8, 0xce, 0xb5, 0x3b,
+  0x52, 0xa0, 0xce, 0x3b, 0x3b, 0x27, 0x17, 0xbc, 0x57, 0x90, 0xa3, 0xba, 0xc7, 0x7f, 0x9d, 0xbb,
+  0x5d, 0x15, 0x65, 0xbb, 0x09, 0xa8, 0x31, 0xbc, 0x5d, 0xbf, 0xe2, 0xbb, 0xb9, 0xb3, 0x9b, 0x3c,
+  0x3d, 0x55, 0x40, 0xba, 0x94, 0xd3, 0xac, 0x3a, 0x17, 0x92, 0x19, 0xbc, 0x73, 0x25, 0xb4, 0x3a,
+  0x8e, 0xae, 0x76, 0x39, 0xaf, 0x21, 0x81, 0xbb, 0xe4, 0x5a, 0x86, 0xbc, 0x2b, 0x4d, 0xca, 0x3b,
+  0x8b, 0xa0, 0x91, 0x3c, 0x76, 0xc6, 0x4d, 0x3b, 0x2b, 0xb8, 0x4d, 0x3c, 0x17, 0x5c, 0x41, 0xbc,
+  0xd1, 0xab, 0xb9, 0xba, 0x53, 0xd2, 0xa0, 0x3c, 0x07, 0x61, 0x9c, 0xbc, 0x9a, 0x0e, 0x92, 0xbb,
+  0x20, 0xd9, 0x1f, 0xbb, 0x50, 0x63, 0x86, 0xbc, 0x40, 0xd3, 0xba, 0x3b, 0xb0, 0x2e, 0x7b, 0x3b,
+  0x6f, 0xbc, 0x42, 0x3b, 0x13, 0x1b, 0x87, 0x3c, 0xb0, 0x13, 0x0d, 0xbc, 0x37, 0x8d, 0x5f, 0x3c,
+  0xea, 0x5b, 0x28, 0x3b, 0x57, 0x66, 0x50, 0x3b, 0xa7, 0xb7, 0xfd, 0xbb, 0x05, 0x23, 0x15, 0xbb,
+  0xd2, 0x39, 0x82, 0xba, 0x9a, 0x0e, 0x50, 0x3b, 0x65, 0x56, 0xe4, 0xbb, 0x55, 0x42, 0x01, 0x3b,
+  0x22, 0xcf, 0x30, 0xbc, 0x49, 0x2e, 0xc9, 0x39, 0xb1, 0x07, 0xfd, 0xba, 0x6a, 0xe4, 0xe8, 0xbb,
+  0x96, 0x3f, 0x48, 0xb9, 0x9c, 0x9d, 0x26, 0xbc, 0xf0, 0xd1, 0x64, 0xbc, 0xac, 0x95, 0x7b, 0x3b,
+  0x38, 0x70, 0x1c, 0xbc, 0x5b, 0x0e, 0x6f, 0xba, 0xa3, 0xbc, 0xe6, 0x3a, 0x9d, 0x73, 0x25, 0xbc,
+  0x67, 0x82, 0xf4, 0xba, 0xd2, 0xa8, 0x90, 0x39, 0xb8, 0x16, 0xa3, 0xbb, 0x92, 0x79, 0xe1, 0x3b,
+  0xc6, 0x7c, 0x82, 0xbc, 0x8a, 0xed, 0x82, 0xbb, 0x5c, 0xe6, 0x09, 0x3c, 0xb8, 0x5e, 0x61, 0xbc,
+  0x55, 0x68, 0x2c, 0x3c, 0x1c, 0xdb, 0x8b, 0xbc, 0x3f, 0x2e, 0x80, 0x3c, 0x02, 0x11, 0xa4, 0x3b,
+  0x1a, 0x10, 0x4a, 0xbc, 0x47, 0x41, 0x41, 0x3b, 0x9b, 0x21, 0x51, 0xbc, 0x19, 0xe3, 0xf9, 0x3b,
+  0x5e, 0xd0, 0x4c, 0x3b, 0x09, 0x88, 0x90, 0xbb, 0x81, 0xba, 0x6b, 0x3c, 0xa5, 0x12, 0x85, 0xbc,
+  0x07, 0xf2, 0x61, 0xbc, 0x06, 0xb2, 0x66, 0x3b, 0x58, 0x1b, 0x2a, 0x3c, 0x1e, 0x0a, 0x13, 0xbc,
+  0x32, 0xe4, 0x89, 0x3c, 0xa1, 0x2c, 0xe1, 0xbb, 0x58, 0x11, 0x0f, 0x3c, 0x44, 0x4e, 0xc8, 0x3b,
+  0xd7, 0xcb, 0x34, 0xbc, 0x6a, 0xb0, 0x5d, 0xbb, 0xf4, 0x26, 0x3e, 0xbc, 0x26, 0x71, 0x95, 0xba,
+  0xfc, 0xe8, 0xd8, 0x3b, 0xc7, 0x52, 0x87, 0x3a, 0x9d, 0xef, 0x3c, 0x3c, 0x94, 0x2c, 0x9f, 0x3b,
+  0xd9, 0xcb, 0x29, 0xbc, 0x41, 0xe6, 0x1d, 0xbc, 0xdc, 0x1e, 0x2a, 0xbb, 0x2e, 0x28, 0x67, 0xba,
+  0x92, 0x12, 0xbd, 0x3b, 0xb7, 0x93, 0x55, 0x3c, 0x3e, 0x03, 0x45, 0x3c, 0x04, 0x15, 0x7a, 0x3c,
+  0x48, 0x67, 0x40, 0xbb, 0xb0, 0xd0, 0x66, 0x3b, 0xc8, 0x4c, 0x50, 0xbc, 0xcc, 0x4a, 0xb7, 0x3b,
+  0x3f, 0x38, 0x09, 0x3b, 0x84, 0x28, 0x9a, 0x3c, 0xd1, 0x9d, 0x91, 0xbc, 0x02, 0x16, 0x4e, 0xbc,
+  0x80, 0x50, 0x86, 0xba, 0x9c, 0xcc, 0xc8, 0x3b, 0x27, 0xd5, 0x96, 0x3b, 0x4f, 0x6a, 0x9d, 0x3b,
+  0x57, 0x7d, 0x4f, 0xba, 0x93, 0x0b, 0xe1, 0x3c, 0x1b, 0x17, 0x89, 0xbc, 0x44, 0xf9, 0x86, 0xbc,
+  0xfc, 0x68, 0x24, 0x3b, 0x37, 0x1d, 0x1c, 0xbc, 0xd7, 0x55, 0x8e, 0x3b, 0x70, 0x3c, 0x1a, 0x3b,
+  0x39, 0x82, 0x99, 0x3b, 0x58, 0x75, 0xad, 0x3c, 0xb2, 0x09, 0xbf, 0xbb, 0x56, 0xf7, 0x4f, 0x3a,
+  0xdb, 0x06, 0x71, 0x3c, 0x28, 0xe2, 0xae, 0xbc, 0x6b, 0x4f, 0x8e, 0x3c, 0x42, 0xad, 0x0a, 0xbc,
+  0xb4, 0x94, 0xf2, 0x3b, 0x3d, 0x00, 0xec, 0x3c, 0x5b, 0x07, 0xa8, 0xbb, 0x47, 0xd2, 0xa5, 0xba,
+  0x48, 0x8f, 0x82, 0xbb, 0x10, 0xf6, 0x77, 0xbb, 0xfe, 0xab, 0x0f, 0x3c, 0x8f, 0xb1, 0xa6, 0xbb,
+  0xf4, 0xf0, 0xcd, 0xbb, 0x4e, 0xf8, 0x41, 0x3c, 0x95, 0x68, 0x63, 0xbb, 0xba, 0xb6, 0x94, 0xbc,
+  0x07, 0xe7, 0xa1, 0xbb, 0x55, 0x94, 0x9e, 0x3b, 0xdc, 0xfa, 0xa3, 0x3b, 0x25, 0x2a, 0xc3, 0xbb,
+  0x10, 0xa9, 0x93, 0x3b, 0xf5, 0x3e, 0xf0, 0x3b, 0x9c, 0x07, 0xe1, 0xba, 0xc5, 0x5c, 0x20, 0xb9,
+  0x2f, 0xdc, 0x31, 0x3a, 0x68, 0xb2, 0x95, 0x39, 0x5a, 0x69, 0xca, 0xbb, 0xdf, 0x2b, 0x7d, 0xbb,
+  0xdc, 0x20, 0x17, 0x3b, 0x8e, 0xf6, 0xc5, 0xbb, 0x17, 0x88, 0xc2, 0x3b, 0x0b, 0xdf, 0x40, 0x3c,
+  0xc6, 0x05, 0xd8, 0x3b, 0xb0, 0x06, 0xd8, 0xba, 0x32, 0x1f, 0x2f, 0xbb, 0xdb, 0x6b, 0x71, 0xbc,
+  0x97, 0x9e, 0xed, 0xba, 0xa4, 0xa9, 0xb8, 0x3b, 0x7e, 0xb9, 0xbd, 0x3a, 0x48, 0xb8, 0x10, 0xbb,
+  0x21, 0x10, 0x57, 0x3c, 0xb6, 0x0e, 0x40, 0x3b, 0xae, 0x19, 0xcb, 0xbc, 0x9d, 0x6a, 0x5e, 0xbc,
+  0xd8, 0x69, 0x76, 0x3b, 0x36, 0x32, 0x6a, 0xbb, 0xa3, 0x31, 0xfb, 0x3b, 0x7a, 0x97, 0x33, 0xbc,
+  0x84, 0x12, 0x2f, 0x3b, 0xf4, 0x3f, 0x6a, 0xb7, 0x2c, 0x9a, 0x34, 0x3c, 0x30, 0x02, 0x3c, 0xbc,
+  0x52, 0x2b, 0xc9, 0x3b, 0x65, 0x74, 0x10, 0x3c, 0x91, 0x77, 0xd5, 0xbc, 0xe6, 0x57, 0xb4, 0xbb,
+  0x2d, 0xf2, 0x89, 0x3c, 0x9d, 0xc5, 0x57, 0xbc, 0xda, 0xf6, 0x7e, 0x3c, 0x86, 0x83, 0x99, 0xbb,
+  0x9e, 0xa9, 0x41, 0x3c, 0xb4, 0xda, 0xc6, 0x3c, 0xa6, 0x15, 0x89, 0xbc, 0xbf, 0xe5, 0x49, 0xbb,
+  0x7f, 0x97, 0xb6, 0x3b, 0xf1, 0xac, 0xbb, 0x39, 0xc6, 0x7f, 0x1c, 0x3c, 0x76, 0x04, 0x50, 0x3b,
+  0x95, 0x06, 0xbc, 0x38, 0xbd, 0x33, 0xcd, 0x3c, 0x72, 0x6d, 0x94, 0xbc, 0x3c, 0x47, 0x22, 0x3b,
+  0xa3, 0xaa, 0x56, 0x3b, 0xd0, 0x8d, 0x00, 0x3a, 0x67, 0xdb, 0x69, 0x3b, 0xda, 0x3f, 0x5b, 0xbc,
+  0x98, 0x7d, 0x48, 0x3b, 0x44, 0x30, 0x8c, 0x3c, 0xd2, 0x3f, 0x8e, 0x3a, 0x82, 0xeb, 0x2f, 0xba,
+  0x31, 0x09, 0xf6, 0xbb, 0x52, 0xff, 0x8f, 0x3b, 0x76, 0xea, 0xf7, 0xba, 0x82, 0x7a, 0xb6, 0xbb,
+  0x85, 0x48, 0xb6, 0x3a, 0x0d, 0xda, 0x33, 0x3b, 0x33, 0x71, 0x0d, 0xbc, 0x6c, 0x2a, 0x74, 0x3b,
+  0x58, 0x72, 0x6d, 0xbc, 0xc5, 0x01, 0x62, 0x3c, 0xba, 0x1b, 0x42, 0xbb, 0x3a, 0x27, 0xbc, 0x3b,
+  0xf2, 0x5f, 0x08, 0xbb, 0xc2, 0x4b, 0x93, 0x3a, 0x46, 0x80, 0xc7, 0x3a, 0xd6, 0x32, 0x50, 0xbc,
+  0xf9, 0x13, 0x01, 0xbc, 0x93, 0x73, 0x6c, 0xbc, 0x80, 0xf9, 0xa2, 0x3b, 0xb0, 0xfd, 0x3f, 0x3c,
+  0x06, 0xa2, 0x0b, 0x3c, 0x5f, 0x59, 0xb6, 0x3b, 0xc8, 0xf7, 0x6b, 0x3c, 0x36, 0x29, 0x7c, 0x3c,
+  0x72, 0x90, 0x17, 0xbc, 0xc7, 0xd2, 0x7d, 0x3c, 0x65, 0x24, 0x58, 0xbc, 0x5a, 0xea, 0x12, 0x3a,
+  0x33, 0x62, 0xa5, 0x3c, 0x62, 0x55, 0x90, 0x3b, 0xcb, 0x15, 0xc4, 0x3b, 0x12, 0x62, 0xe1, 0x3b,
+  0x9a, 0x92, 0xbc, 0xbc, 0x8a, 0x20, 0xba, 0xbb, 0x94, 0xb4, 0x88, 0xbc, 0xf8, 0x5e, 0xb7, 0xba,
+  0x78, 0x7a, 0xa8, 0x3c, 0x53, 0xda, 0xda, 0xbb, 0x4e, 0x40, 0x7e, 0x3b, 0xfa, 0x17, 0xc3, 0x3b,
+  0xe7, 0x8c, 0x77, 0xbb, 0xab, 0xa9, 0x8d, 0xbb, 0x4c, 0xb5, 0x00, 0xbb, 0x5b, 0x0d, 0x62, 0xbb,
+  0x55, 0x94, 0x26, 0x3c, 0xa9, 0xe3, 0x06, 0xbc, 0x72, 0xfa, 0x43, 0x3c, 0xfa, 0xe0, 0x5c, 0x3c,
+  0x41, 0xac, 0x20, 0x3a, 0x10, 0xe0, 0x01, 0xba, 0x57, 0x1e, 0x6d, 0xbc, 0x42, 0x2c, 0x93, 0x39,
+  0x3d, 0xe9, 0xc5, 0xbb, 0x30, 0x58, 0xba, 0x3c, 0x30, 0xf2, 0xde, 0x3b, 0xc6, 0xf3, 0x18, 0xbb,
+  0x76, 0xa4, 0x25, 0x3c, 0x21, 0xc9, 0x3c, 0xbc, 0xdb, 0x9b, 0x59, 0x3c, 0xba, 0x4f, 0x05, 0xb9,
+  0x92, 0xd1, 0x2c, 0xbb, 0xca, 0xd2, 0x2c, 0x3c, 0xd6, 0xca, 0x04, 0xbc, 0xbb, 0x6f, 0x30, 0xbc,
+  0x9f, 0x6b, 0x1e, 0xbb, 0xdb, 0x1d, 0x24, 0x3b, 0x3c, 0xbc, 0xfe, 0xbb, 0x02, 0x75, 0xd5, 0x3b,
+  0x40, 0xac, 0x98, 0x3a, 0x83, 0x5a, 0x12, 0x3c, 0x87, 0x4c, 0xc2, 0xbb, 0xff, 0x61, 0x01, 0x3a,
+  0xc6, 0xf6, 0xa3, 0x3a, 0x88, 0x67, 0x53, 0xbc, 0xec, 0xa5, 0xa1, 0x3c, 0xf1, 0x3e, 0x6b, 0x3b,
+  0x29, 0xc6, 0x90, 0x3b, 0x56, 0x5a, 0x8c, 0x3c, 0x60, 0xd3, 0x60, 0xbb, 0xa4, 0x27, 0x67, 0xbc,
+  0x3e, 0x30, 0x6e, 0xbb, 0x79, 0x2d, 0x85, 0xbc, 0xb3, 0x54, 0xb0, 0x3c, 0x49, 0x33, 0xc3, 0xbb,
+  0x6b, 0x2e, 0xb3, 0xbb, 0x81, 0xb8, 0xfb, 0x3c, 0xb3, 0x7d, 0x13, 0xbc, 0xa4, 0x5f, 0x81, 0xbc,
+  0x78, 0x4d, 0x51, 0x3b, 0xec, 0xec, 0x06, 0xbc, 0x14, 0x82, 0xea, 0x3b, 0x26, 0x42, 0xa1, 0x3b,
+  0x0e, 0x9b, 0xa6, 0x3b, 0x4d, 0xf9, 0xc2, 0x3c, 0x12, 0xb1, 0xd0, 0x3b, 0xee, 0xc7, 0x3e, 0xbc,
+  0xb0, 0x0a, 0x06, 0xb9, 0x39, 0xf4, 0x48, 0xbc, 0x98, 0x6d, 0x98, 0xbb, 0x01, 0xa2, 0x0a, 0xbb,
+  0x39, 0xa9, 0xc5, 0xba, 0xfc, 0x8d, 0x47, 0x3c, 0x65, 0xe8, 0x02, 0x3c, 0x1d, 0x71, 0x8d, 0x3b,
+  0x8c, 0xad, 0xc5, 0xbb, 0x9c, 0xb9, 0xa5, 0x3a, 0x22, 0x17, 0x2f, 0xbc, 0x56, 0xbe, 0xee, 0xbb,
+  0xf6, 0xe2, 0x24, 0xbb, 0x97, 0x33, 0x54, 0x3a, 0x48, 0xe8, 0xd1, 0xba, 0xce, 0xea, 0x2d, 0x3b,
+  0x7e, 0x71, 0x80, 0xb9, 0x66, 0xa4, 0x87, 0xba, 0xf1, 0x3d, 0x94, 0x3b, 0xa5, 0xda, 0x1a, 0xbc,
+  0x13, 0x43, 0x3b, 0x3b, 0x76, 0x5d, 0xb5, 0x3b, 0x58, 0x4e, 0x24, 0x3c, 0xa4, 0xc8, 0x5a, 0xbb,
+  0x2c, 0x09, 0x40, 0x3b, 0x26, 0xce, 0x9f, 0xbc, 0x69, 0x6c, 0x61, 0xbc, 0x82, 0xed, 0x8f, 0xbb,
+  0x53, 0xec, 0x12, 0xbc, 0x28, 0x9e, 0xbc, 0x39, 0x42, 0x28, 0xc8, 0x3a, 0x2c, 0x7c, 0xc5, 0xba,
+  0xf4, 0x63, 0x1e, 0x3c, 0xcd, 0x0d, 0x39, 0x3a, 0x2d, 0x08, 0xd5, 0x3b, 0xa9, 0xb4, 0x7a, 0xbc,
+  0xc6, 0xd2, 0xd6, 0x3c, 0x7c, 0x38, 0xcd, 0x3b, 0xcd, 0x70, 0xb2, 0xbc, 0x1a, 0x3f, 0x3b, 0x3c,
+  0xb1, 0xc7, 0xb9, 0x3c, 0xd4, 0x44, 0x29, 0xbc, 0xde, 0x6c, 0x0a, 0x3c, 0xe0, 0x62, 0xd2, 0x3b,
+  0xc2, 0xb1, 0x22, 0x3b, 0x8d, 0x4f, 0xe5, 0x3c, 0x4c, 0x14, 0xa9, 0xbc, 0xe7, 0x8c, 0x6a, 0x3b,
+  0x14, 0x6c, 0x6c, 0x3c, 0x58, 0x13, 0xda, 0xbb, 0x86, 0x2b, 0x81, 0x3c, 0xd8, 0x74, 0x04, 0x3c,
+  0xa7, 0xf3, 0x51, 0xbb, 0x45, 0x4d, 0xd4, 0x3c, 0xd7, 0x0c, 0xaf, 0xbc, 0x12, 0x47, 0xb0, 0xbb,
+  0xdb, 0x41, 0x0e, 0x3c, 0xfd, 0x33, 0x95, 0xbb, 0x70, 0xf1, 0x21, 0xbb, 0xce, 0x5d, 0x9d, 0xbb,
+  0xef, 0x36, 0x3d, 0x3b, 0x01, 0x39, 0xe5, 0x3b, 0xa3, 0x74, 0x83, 0xbc, 0x29, 0xc8, 0x67, 0xbb,
+  0xee, 0xe5, 0x36, 0x3b, 0xf4, 0xeb, 0x91, 0x3b, 0x01, 0x09, 0x80, 0xbc, 0x47, 0x97, 0xc1, 0xb9,
+  0x41, 0xf5, 0xa6, 0x3b, 0xb7, 0xc6, 0xc6, 0xbb, 0xf3, 0x4f, 0xb1, 0xbb, 0x33, 0x0e, 0x0a, 0x3a,
+  0x34, 0xfc, 0xe7, 0xbb, 0x2e, 0x85, 0x29, 0xbc, 0x98, 0x41, 0xd6, 0xbb, 0x59, 0xf2, 0x4b, 0x3a,
+  0xce, 0xc8, 0x0d, 0x3c, 0xf8, 0x38, 0x03, 0xbb, 0x8e, 0xc9, 0xda, 0x3b, 0x02, 0xf1, 0x0b, 0xbc,
+  0x1a, 0xf7, 0x7e, 0xbb, 0xac, 0x1e, 0x22, 0xbc, 0xcc, 0xa5, 0xc8, 0x38, 0x92, 0xd6, 0x04, 0xbc,
+  0x07, 0xe1, 0x80, 0x3c, 0xfd, 0x15, 0xef, 0x3b, 0x42, 0x21, 0x92, 0x3b, 0x1b, 0x41, 0x03, 0xbc,
+  0x27, 0xb8, 0x23, 0xbc, 0x3a, 0xe7, 0x68, 0x3c, 0x32, 0xb2, 0x01, 0xbc, 0xb6, 0x58, 0xd5, 0xbb,
+  0x90, 0x21, 0x93, 0x3c, 0x85, 0xa2, 0x68, 0xbb, 0x84, 0x5b, 0x37, 0x3c, 0xfd, 0x57, 0xe5, 0xbb,
+  0x7a, 0x1f, 0xe9, 0xbb, 0xe5, 0xce, 0x00, 0xbc, 0xf6, 0xf2, 0xba, 0x3b, 0xd1, 0x76, 0xf8, 0x3b,
+  0x13, 0xdd, 0x65, 0x3c, 0x11, 0x74, 0x05, 0xba, 0x6b, 0xa1, 0x60, 0x3c, 0x05, 0x83, 0x35, 0x3b,
+  0xff, 0x8a, 0xcf, 0x3a, 0xae, 0x47, 0x96, 0xbb, 0xc0, 0x1c, 0x0f, 0xbb, 0x02, 0x02, 0x1a, 0x3c,
+  0x51, 0x78, 0x54, 0x3c, 0x38, 0x03, 0xad, 0x3a, 0xb2, 0x9a, 0x86, 0x3c, 0x76, 0x86, 0xbb, 0xba,
+  0x79, 0x73, 0x1f, 0xbc, 0x0b, 0x07, 0xb9, 0x3a, 0x2f, 0xb1, 0x3d, 0xbb, 0xd5, 0xea, 0x79, 0xbb,
+  0xcc, 0xf3, 0x0c, 0x3a, 0x87, 0x55, 0xa8, 0x3c, 0x80, 0xd2, 0x6e, 0x3c, 0x76, 0xcd, 0x50, 0x3c,
+  0xaf, 0x56, 0x91, 0x3b, 0x01, 0xb8, 0x8d, 0x3b, 0x25, 0x85, 0x59, 0x3b, 0xf5, 0x06, 0x0d, 0xba,
+  0x9e, 0xda, 0xfa, 0xbb, 0x1a, 0xfe, 0x7a, 0x3c, 0xf6, 0x12, 0x11, 0xbc, 0xd8, 0x61, 0x1e, 0x3c,
+  0xeb, 0x87, 0x1e, 0xbb, 0xb0, 0xd0, 0x97, 0xbb, 0x99, 0x36, 0x76, 0xbb, 0x91, 0x45, 0x02, 0x3c,
+  0x17, 0x41, 0x98, 0xbc, 0xfb, 0x10, 0xa0, 0x3c, 0x35, 0x6d, 0xb7, 0xbb, 0xa8, 0xd0, 0x38, 0xbb,
+  0xde, 0x64, 0x56, 0x3b, 0x2e, 0xce, 0x06, 0xbc, 0x38, 0x7a, 0x7a, 0x3c, 0xf3, 0x1c, 0x5a, 0xbb,
+  0x06, 0x72, 0xe0, 0xbb, 0xaa, 0x64, 0xbc, 0x3c, 0x3c, 0xdb, 0x0d, 0xbc, 0x18, 0x85, 0xfe, 0xbb,
+  0x80, 0x18, 0xc7, 0xbb, 0x29, 0xd2, 0xa5, 0xbc, 0xc8, 0xc7, 0xc5, 0x3b, 0x4b, 0xd1, 0x49, 0xba,
+  0x6d, 0xad, 0xb9, 0x3a, 0xaf, 0x7c, 0xd2, 0x3c, 0x46, 0x61, 0xb0, 0xbb, 0x34, 0xa3, 0xa2, 0xbc,
+  0x53, 0xc3, 0x87, 0x39, 0x50, 0x42, 0x4c, 0xbc, 0x2b, 0x7b, 0xe5, 0x3a, 0x55, 0x3d, 0xf9, 0xbb,
+  0x36, 0xdd, 0x12, 0x3b, 0xab, 0xe2, 0x72, 0x3c, 0xdb, 0x20, 0xee, 0x3b, 0x5d, 0xad, 0x8a, 0xbc,
+  0xea, 0xd9, 0x29, 0xba, 0xd4, 0xb3, 0x7d, 0xbb, 0x8f, 0xeb, 0x76, 0x3c, 0xad, 0x9d, 0xda, 0xbb,
+  0x68, 0xae, 0x02, 0x3b, 0x0d, 0x72, 0xd8, 0x3c, 0x71, 0x45, 0x48, 0xbb, 0x73, 0x99, 0x54, 0x39,
+  0x59, 0xfd, 0xb4, 0xba, 0x5b, 0x7e, 0x77, 0xbb, 0xbc, 0x79, 0x00, 0x3c, 0xc5, 0xd8, 0x73, 0xbc,
+  0x0e, 0xf8, 0x24, 0xbb, 0xc4, 0x64, 0xc7, 0x3b, 0x9b, 0xed, 0x11, 0xbc, 0x8e, 0x48, 0x9e, 0xbb,
+  0x1c, 0xc4, 0x6b, 0xbc, 0x4a, 0x12, 0x49, 0xba, 0x3a, 0xec, 0x75, 0x3b, 0x15, 0x55, 0x68, 0xba,
+  0x61, 0x24, 0x4d, 0x3b, 0x03, 0x71, 0x73, 0x3b, 0xe8, 0xda, 0x71, 0x3b, 0xfd, 0xfd, 0x06, 0x3c,
+  0x3a, 0xa2, 0x9e, 0x3b, 0xd3, 0xdd, 0xf9, 0xbb, 0x37, 0xfb, 0x7c, 0xbb, 0xda, 0x87, 0xa5, 0xbb,
+  0x56, 0x65, 0xdc, 0x3a, 0x4a, 0xc4, 0x2d, 0xbc, 0xd2, 0x2c, 0x83, 0x3b, 0x29, 0x0a, 0x0b, 0x3c,
+  0xe5, 0x2b, 0x45, 0x3b, 0xeb, 0xbf, 0xc9, 0x3b, 0x08, 0x5d, 0xe5, 0x3b, 0xe5, 0x5e, 0xff, 0x3b,
+  0xc0, 0xc1, 0xfb, 0x3c, 0x14, 0x88, 0x9d, 0x3c, 0x05, 0x76, 0xf9, 0xbc, 0xaf, 0x54, 0x15, 0xbb,
+  0x47, 0xaf, 0xf7, 0x3c, 0x7b, 0xe0, 0x6d, 0x3b, 0xaa, 0x25, 0x60, 0x3c, 0x43, 0x99, 0x92, 0x3b,
+  0xf9, 0x62, 0x55, 0x3c, 0xfe, 0x5d, 0xed, 0x3c, 0x7a, 0x9d, 0x0f, 0xbc, 0xd7, 0x13, 0xbd, 0xbb,
+  0x42, 0xfe, 0x9f, 0x3c, 0x4e, 0xb5, 0x14, 0x3c, 0xca, 0xae, 0x7a, 0x3c, 0x6a, 0xdc, 0x06, 0xbb,
+  0x53, 0x18, 0x04, 0x3c, 0x11, 0x71, 0x14, 0x3d, 0xaa, 0xbf, 0x8f, 0xbc, 0xe6, 0x92, 0x63, 0x3a,
+  0xa2, 0xe4, 0x21, 0x3c, 0x48, 0x91, 0x23, 0x3b, 0x55, 0xc9, 0x1c, 0xbc, 0x2e, 0x98, 0x26, 0xbc,
+  0x20, 0x12, 0x97, 0x3b, 0xb5, 0x83, 0x85, 0x3c, 0x01, 0xb8, 0x45, 0xbc, 0xeb, 0x82, 0x21, 0x39,
+  0x45, 0xbb, 0x50, 0x3a, 0x7f, 0x9f, 0xad, 0x39, 0x43, 0xc9, 0xab, 0xbc, 0x4d, 0x09, 0x2b, 0xbc,
+  0x1d, 0x5b, 0xa1, 0x3b, 0xc8, 0x86, 0xcb, 0xbb, 0x02, 0x44, 0x67, 0xbc, 0x53, 0x7a, 0x6b, 0xbb,
+  0x30, 0x20, 0xb2, 0xbb, 0xc3, 0x0d, 0x35, 0xbb, 0xd5, 0xaa, 0xa0, 0x39, 0x3c, 0x72, 0xd0, 0x3b,
+  0xce, 0xf2, 0x42, 0x3c, 0xec, 0xa4, 0x31, 0x3b, 0x64, 0xad, 0x8b, 0x3c, 0x93, 0xa2, 0x17, 0x3c,
+  0x5a, 0xed, 0x77, 0x3a, 0xec, 0xac, 0xa6, 0xbb, 0x59, 0x1f, 0xf0, 0xbb, 0x66, 0x6f, 0xe5, 0xbb,
+  0xab, 0xed, 0x55, 0x3c, 0x16, 0xef, 0xe5, 0x3b, 0x46, 0x07, 0x45, 0x3c, 0xc6, 0x9c, 0xf5, 0x3a,
+  0xc1, 0xf8, 0x60, 0xbc, 0x49, 0x17, 0x5d, 0xbb, 0x67, 0xbc, 0x43, 0xbc, 0x58, 0x94, 0x72, 0x3a,
+  0xd9, 0x36, 0xa1, 0x3c, 0x7d, 0x03, 0x0b, 0xbb, 0x12, 0x8d, 0x9f, 0x3c, 0x28, 0xbb, 0x1a, 0xbc,
+  0x71, 0x16, 0x36, 0xbc, 0x0f, 0x9c, 0xe5, 0x3a, 0xf7, 0x12, 0x8c, 0xbc, 0x3c, 0x63, 0x84, 0x3c,
+  0x11, 0xa1, 0x60, 0x3c, 0xda, 0xf9, 0xd6, 0xba, 0x90, 0xd3, 0x75, 0x3c, 0xab, 0xf2, 0xe0, 0x39,
+  0xfa, 0x72, 0x1f, 0xbc, 0x76, 0xf0, 0x3a, 0xbc, 0x5e, 0x12, 0xaa, 0xbb, 0xe8, 0xb8, 0x19, 0x3c,
+  0x1a, 0x55, 0x51, 0x3c, 0x91, 0x0a, 0x47, 0x3c, 0x2a, 0x2c, 0x40, 0x3b, 0xca, 0xcb, 0xda, 0x3b,
+  0xb8, 0xc6, 0x6d, 0x3a, 0x57, 0xd5, 0xcd, 0x3b, 0x47, 0x14, 0x50, 0xbb, 0x7f, 0x7b, 0x36, 0x3b,
+  0x2b, 0xee, 0x07, 0xbb, 0x40, 0x7e, 0x25, 0x3c, 0xba, 0xd6, 0x56, 0x3b, 0x92, 0x90, 0x40, 0xbb,
+  0x13, 0xc9, 0xc3, 0x3b, 0xb2, 0xb3, 0x75, 0xbc, 0x01, 0x67, 0x3a, 0x3c, 0x05, 0xf9, 0x4d, 0x3c,
+  0xa7, 0xbd, 0x3b, 0xbc, 0x8e, 0x09, 0x56, 0x3c, 0xcf, 0x17, 0x37, 0xbc, 0x5d, 0xa9, 0x08, 0xbc,
+  0xff, 0x4f, 0x9d, 0x3b, 0x9e, 0x8a, 0x39, 0x3c, 0xbd, 0xfd, 0xe9, 0xba, 0x33, 0x2b, 0x24, 0x3b,
+  0xbd, 0xeb, 0x60, 0xbb, 0x8c, 0x1e, 0x20, 0x3c, 0x9e, 0x66, 0x8c, 0xbc, 0x14, 0x55, 0xf6, 0x3a,
+  0xad, 0x88, 0x36, 0x3a, 0x5d, 0x1f, 0x86, 0xb9, 0x98, 0x64, 0x5e, 0x3b, 0xe5, 0x6e, 0xb6, 0xba,
+  0xf0, 0x34, 0x00, 0xbc, 0xd6, 0x15, 0xac, 0x3c, 0x1b, 0xa5, 0xd6, 0xbb, 0xbf, 0x53, 0x1c, 0xbc,
+  0x3c, 0x4c, 0xd5, 0x3b, 0xf7, 0x8c, 0x44, 0xbc, 0x7b, 0xe9, 0x4c, 0x3c, 0xa1, 0x8a, 0x21, 0x3b,
+  0x6f, 0x4a, 0x3d, 0xbc, 0x99, 0xcb, 0xce, 0x3c, 0xef, 0xe3, 0x15, 0x3c, 0xe9, 0xb1, 0x92, 0x3b,
+  0xcb, 0xb6, 0x52, 0xbb, 0x8c, 0x3a, 0x56, 0x3b, 0x31, 0x1a, 0x7f, 0xba, 0xf9, 0x5c, 0x44, 0xbb,
+  0xab, 0xdb, 0xc5, 0x3b, 0xea, 0x67, 0xfc, 0x3c, 0xf1, 0xd3, 0xb7, 0x3b, 0x30, 0x4b, 0x29, 0xbc,
+  0x53, 0x95, 0xb7, 0xbb, 0x2f, 0xcd, 0x0a, 0x3b, 0xc0, 0x38, 0x16, 0x3a, 0xb8, 0x22, 0x07, 0x3c,
+  0x8e, 0x40, 0xe3, 0xba, 0x85, 0x18, 0x8b, 0x3c, 0x9e, 0xbd, 0x21, 0xbc, 0x31, 0xb9, 0xc1, 0xbb,
+  0x6b, 0xab, 0x32, 0xbc, 0x0b, 0x9b, 0xfe, 0x3a, 0x60, 0xc2, 0x24, 0xbc, 0x0f, 0xe3, 0x43, 0xbc,
+  0x86, 0xee, 0x56, 0x3b, 0xda, 0xda, 0x86, 0x3b, 0xa5, 0xfa, 0x20, 0xbb, 0x1d, 0x76, 0xeb, 0xbb,
+  0x16, 0x96, 0x99, 0xbb, 0x4a, 0x32, 0xac, 0xba, 0xb8, 0x53, 0x7c, 0x3a, 0xb8, 0x71, 0x30, 0xbb,
+  0xbc, 0x8b, 0x8d, 0x3a, 0xbb, 0x90, 0xe1, 0xb9, 0x73, 0x71, 0x6d, 0x39, 0x12, 0x31, 0x1e, 0xba,
+  0xd7, 0x92, 0xe6, 0xbb, 0xf6, 0x98, 0xe8, 0xbb, 0x2c, 0xfe, 0x48, 0x3c, 0x8a, 0xb6, 0x37, 0xbc,
+  0x80, 0x25, 0x01, 0x3c, 0x28, 0xd7, 0x65, 0xbc, 0x93, 0x8d, 0xa7, 0x3b, 0xb6, 0x43, 0xb5, 0x3b,
+  0x8a, 0xc9, 0x80, 0x3b, 0x7d, 0x2d, 0x05, 0x3b, 0x62, 0x4a, 0x53, 0x3c, 0xbc, 0x78, 0x95, 0x3b,
+  0x75, 0x53, 0xa8, 0x3c, 0x72, 0xed, 0xfa, 0x3b, 0x73, 0x3c, 0x73, 0xbc, 0x71, 0xd1, 0xa1, 0x39,
+  0xc4, 0xca, 0x70, 0x3c, 0xe1, 0x3c, 0x2e, 0x3b, 0x6a, 0x05, 0x0b, 0x3b, 0x9c, 0xf8, 0x18, 0xbc,
+  0xe8, 0x6e, 0x41, 0x3c, 0x50, 0x32, 0x0e, 0x3d, 0xb7, 0xe5, 0x0d, 0xbc, 0xd1, 0xeb, 0x71, 0xbb,
+  0x4f, 0x21, 0x86, 0x3c, 0xdf, 0x8f, 0xb9, 0x3b, 0xd0, 0x86, 0x79, 0x3c, 0x7e, 0xeb, 0x96, 0x3a,
+  0xad, 0xcb, 0x4f, 0x3b, 0x17, 0x67, 0xbe, 0x3c, 0x75, 0x62, 0x44, 0xbc, 0x4b, 0x00, 0xb4, 0xb9,
+  0x32, 0x6f, 0xf2, 0x3b, 0x28, 0xf7, 0xfd, 0xbb, 0xef, 0x05, 0xc0, 0xba, 0x53, 0x0d, 0x2c, 0xbc,
+  0xf3, 0x21, 0x17, 0x3c, 0xdd, 0x45, 0x95, 0x3c, 0x88, 0xe0, 0xc4, 0xbc, 0x33, 0xf6, 0x2c, 0xbb,
+  0xe8, 0x90, 0xa5, 0xb9, 0x49, 0x7e, 0x10, 0xbc, 0xbc, 0x5a, 0x31, 0xbc, 0x5f, 0x81, 0x49, 0xba,
+  0x02, 0xdd, 0x26, 0x3c, 0x93, 0xbc, 0x6e, 0x3b, 0xad, 0xa0, 0x04, 0x3b, 0x1b, 0x3a, 0x1e, 0x3b,
+  0xf9, 0xb5, 0xcf, 0x3b, 0xac, 0xa6, 0x37, 0xbb, 0x43, 0x66, 0x88, 0xbc, 0x35, 0x16, 0x72, 0xbb,
+  0x9a, 0x48, 0x68, 0x3b, 0x5d, 0x3d, 0xac, 0x3b, 0xc3, 0x8c, 0xc6, 0x3c, 0x8b, 0xee, 0x07, 0xbc,
+  0x09, 0xa2, 0x1b, 0xbc, 0x1c, 0x86, 0x64, 0xbb, 0x15, 0xeb, 0x99, 0xbc, 0x40, 0x8b, 0x4b, 0xbc,
+  0x92, 0x1e, 0x65, 0x3c, 0x83, 0xb7, 0xf8, 0x3b, 0x5c, 0xeb, 0xfd, 0x3c, 0xac, 0x8b, 0xa1, 0xbb,
+  0x3c, 0xac, 0x80, 0xbc, 0x38, 0x79, 0x01, 0x3c, 0xda, 0x04, 0x60, 0xbc, 0x55, 0xb3, 0x1c, 0x3c,
+  0x83, 0x47, 0x63, 0x3c, 0xac, 0x00, 0x24, 0xbb, 0xb5, 0x40, 0xa9, 0x3c, 0x31, 0x0d, 0x27, 0x3c,
+  0x78, 0xc6, 0x8e, 0xbc, 0xb9, 0x42, 0x91, 0x3b, 0xb9, 0x3c, 0xa0, 0xbb, 0xdf, 0x52, 0x19, 0x3b,
+  0xc9, 0x42, 0x2c, 0x3c, 0x78, 0x8d, 0x0c, 0xb9, 0xfe, 0xa5, 0x5a, 0x3c, 0x22, 0xaa, 0x98, 0x3c,
+  0xa5, 0x5b, 0x58, 0xbc, 0xf1, 0xa7, 0x02, 0xbb, 0xb8, 0x81, 0x87, 0xbb, 0x93, 0x60, 0x2b, 0x3c,
+  0x14, 0xe8, 0x74, 0x3b, 0x3f, 0xe6, 0x7f, 0x3b, 0xaf, 0xdf, 0xb8, 0x3c, 0x5e, 0x72, 0x87, 0xbc,
+  0xbe, 0xb9, 0x7e, 0xbb, 0x05, 0x7f, 0x4a, 0xbb, 0x5e, 0xbc, 0x33, 0xbc, 0x33, 0x37, 0xe2, 0x3b,
+  0x1a, 0x68, 0xad, 0x3b, 0x2b, 0x75, 0xaf, 0x3b, 0x3d, 0xe1, 0x6d, 0x3a, 0x9b, 0xa3, 0x0e, 0x3c,
+  0xe7, 0x80, 0x70, 0x3a, 0x0d, 0xe6, 0xc6, 0xba, 0xbb, 0x49, 0x47, 0x3c, 0x8b, 0x55, 0xd4, 0x3a,
+  0xf8, 0x7e, 0x26, 0xbc, 0x08, 0x1b, 0x04, 0x3c, 0x8b, 0x45, 0xbc, 0xbb, 0xdc, 0x42, 0x89, 0x3b,
+  0x0d, 0x47, 0x89, 0x3b, 0xbb, 0x43, 0x27, 0x3c, 0x5c, 0xbf, 0x0d, 0x3c, 0xb7, 0xf6, 0xd1, 0x3b,
+  0x5c, 0xb3, 0x05, 0xbc, 0xa9, 0xa9, 0x5b, 0x3c, 0x4f, 0x0f, 0x59, 0xbc, 0xf7, 0xb9, 0x83, 0xba,
+  0x3a, 0xcb, 0x33, 0x3c, 0x34, 0x9a, 0xb5, 0x3b, 0xcc, 0x43, 0x8e, 0x3b, 0xfa, 0xf5, 0xe1, 0x3a,
+  0xeb, 0xb2, 0x2d, 0xbc, 0x15, 0xd9, 0xb6, 0x3c, 0x09, 0xb1, 0xe0, 0xbb, 0x35, 0x76, 0x6a, 0x3c,
+  0x13, 0x5c, 0x95, 0x3a, 0xf4, 0x6d, 0x16, 0xbb, 0x19, 0x51, 0x40, 0xba, 0xa0, 0x04, 0x64, 0xbc,
+  0xfa, 0x35, 0xe9, 0x38, 0xe0, 0x5d, 0xb5, 0x3c, 0xd1, 0xa4, 0x06, 0x3b, 0xdb, 0xfc, 0x65, 0xbb,
+  0x50, 0x26, 0xbf, 0x3b, 0x0e, 0xf0, 0x0d, 0x3b, 0xdd, 0x88, 0x98, 0x3c, 0x8a, 0x72, 0xc0, 0x3b,
+  0xdc, 0x36, 0x63, 0x3b, 0xc4, 0x93, 0xb0, 0x3c, 0x47, 0x19, 0x94, 0xbb, 0x5d, 0x1a, 0xab, 0x3b,
+  0xf9, 0xe6, 0x1d, 0xbb, 0xb6, 0x1f, 0x4e, 0xbb, 0x0a, 0xd7, 0x5e, 0x3c, 0x00, 0x06, 0x7f, 0xbc,
+  0x69, 0xa2, 0x05, 0x3c, 0x5f, 0xe2, 0xd3, 0x3c, 0x55, 0xaf, 0x17, 0x3b, 0x77, 0x90, 0xe1, 0xbb,
+  0xb6, 0x83, 0x97, 0x3a, 0x97, 0xec, 0x75, 0xbb, 0xf9, 0xfc, 0xa4, 0x3b, 0xbc, 0x83, 0x61, 0x3b,
+  0x5e, 0x95, 0x17, 0x3b, 0x73, 0xdc, 0x13, 0xbb, 0x01, 0x6e, 0x09, 0xbb, 0x18, 0x8f, 0xda, 0x3b,
+  0x90, 0x6e, 0x18, 0x3c, 0x4a, 0x8a, 0x3d, 0xbb, 0xda, 0x2e, 0x27, 0xbb, 0x3d, 0xde, 0x93, 0x3b,
+  0x0d, 0xfc, 0xa9, 0xbb, 0x4f, 0x2a, 0xd2, 0xba, 0x6d, 0x6d, 0x4b, 0x3b, 0x8e, 0x00, 0x24, 0x3c,
+  0x85, 0xdf, 0x5d, 0xbb, 0xb8, 0x22, 0xca, 0x3a, 0x4f, 0x96, 0x3c, 0x3c, 0xe4, 0x13, 0xad, 0xba,
+  0xf9, 0x06, 0x4b, 0x3c, 0x80, 0x01, 0x9e, 0x3b, 0x65, 0x88, 0xd7, 0x3a, 0x05, 0xfe, 0x67, 0xbc,
+  0x1e, 0x2a, 0x2a, 0xbb, 0x82, 0x65, 0x6e, 0xb9, 0xef, 0x69, 0x6a, 0x3c, 0xaf, 0x1d, 0x84, 0xba,
+  0x3b, 0x35, 0x1b, 0x3d, 0x77, 0x23, 0x9a, 0x3c, 0xcc, 0x51, 0x73, 0xbc, 0xa3, 0xba, 0x8d, 0xbb,
+  0x05, 0x8a, 0xc0, 0x3c, 0x82, 0x9d, 0xf7, 0xbb, 0x22, 0xdd, 0x56, 0x3c, 0x45, 0xb2, 0x20, 0xbc,
+  0xb3, 0x56, 0x52, 0x3b, 0xac, 0x25, 0x3a, 0x3d, 0x0f, 0x12, 0x6d, 0xbc, 0x21, 0x38, 0x73, 0xbb,
+  0xfc, 0x6a, 0xfb, 0x3c, 0xce, 0x82, 0x19, 0x3b, 0xe0, 0x98, 0x31, 0x3c, 0xcc, 0xe9, 0x8e, 0x3c,
+  0xf0, 0x57, 0xbc, 0x3b, 0x00, 0x5c, 0xea, 0x3c, 0x96, 0x6d, 0xc9, 0xbb, 0xd0, 0x2a, 0xfb, 0x3b,
+  0x40, 0x22, 0x17, 0x3c, 0xd0, 0xee, 0x82, 0xbb, 0x1e, 0xb9, 0xa7, 0x3b, 0x35, 0x46, 0xce, 0xbb,
+  0xdc, 0xd1, 0x4c, 0xbb, 0xa6, 0x9e, 0xd2, 0x3c, 0xf0, 0x97, 0x74, 0xbc, 0x9a, 0xac, 0xc4, 0xbb,
+  0x97, 0xf5, 0xbb, 0xbb, 0x1c, 0xe9, 0x38, 0xbc, 0x5d, 0x33, 0x08, 0xbc, 0xc8, 0xb5, 0x7a, 0xbb,
+  0xb1, 0x62, 0xfd, 0xba, 0x8f, 0x13, 0x24, 0xbc, 0x56, 0x18, 0x64, 0xbc, 0x56, 0xbb, 0x11, 0xbb,
+  0xcd, 0xab, 0xf4, 0xbb, 0x50, 0xc6, 0x0b, 0xbc, 0x10, 0x31, 0x8f, 0xbc, 0x59, 0x69, 0x32, 0x3b,
+  0x37, 0x67, 0xb6, 0x3b, 0x4b, 0x13, 0x07, 0x3c, 0x31, 0x74, 0x6b, 0x3c, 0xa0, 0x66, 0xfe, 0x3b,
+  0xaf, 0x68, 0x6a, 0xbc, 0x0b, 0x9e, 0x37, 0xbc, 0x72, 0xd1, 0x26, 0xbc, 0x7e, 0x50, 0xcc, 0x3b,
+  0xe8, 0xcc, 0xcc, 0x3c, 0xc0, 0xe9, 0xe8, 0x3b, 0x7e, 0xfa, 0x02, 0x3d, 0xa2, 0x09, 0x98, 0xbc,
+  0x4a, 0x00, 0x03, 0xbc, 0xb6, 0xce, 0x6c, 0x3b, 0x55, 0x6f, 0x1c, 0xbc, 0x83, 0x1e, 0x0e, 0x3b,
+  0xf3, 0xb7, 0x65, 0x3c, 0x84, 0xcc, 0x47, 0x3a, 0xd1, 0x91, 0xc7, 0x3c, 0xf4, 0xb2, 0x07, 0xbc,
+  0x92, 0x14, 0xb7, 0xbb, 0x0e, 0x16, 0x89, 0xbb, 0xa3, 0xfc, 0x4c, 0xbc, 0x7b, 0x49, 0x67, 0xbb,
+  0x86, 0x9f, 0x83, 0x3c, 0xc2, 0xc5, 0x53, 0x3b, 0xdd, 0x34, 0xef, 0x3a, 0x9b, 0x83, 0x31, 0x3b,
+  0x25, 0xc6, 0x32, 0xbc, 0x5a, 0x21, 0x5d, 0x3a, 0x7a, 0x75, 0xf9, 0xbb, 0xde, 0xf6, 0x01, 0xbb,
+  0x46, 0x81, 0x8c, 0x3c, 0x4a, 0xe7, 0x7d, 0x3c, 0x09, 0xdd, 0x8b, 0x3c, 0x4b, 0xdf, 0x33, 0x3c,
+  0x31, 0x3f, 0x4e, 0xbc, 0xa4, 0xa9, 0xf1, 0x3b, 0x45, 0xfa, 0x24, 0x3b, 0xf7, 0x71, 0x96, 0xbb,
+  0x45, 0x3f, 0x0a, 0xbb, 0xed, 0xf2, 0x72, 0x3c, 0xe3, 0x47, 0xdf, 0xbb, 0x6e, 0x45, 0x31, 0x3a,
+  0xa2, 0x17, 0xce, 0x3b, 0x3e, 0x97, 0x47, 0xbc, 0xd2, 0x30, 0x12, 0xba, 0x9c, 0x2d, 0x61, 0x3c,
+  0x56, 0x93, 0x00, 0xbc, 0x90, 0xb0, 0x43, 0xbb, 0x9d, 0x5c, 0xbb, 0xbc, 0x39, 0xc6, 0xc0, 0xb8,
+  0x31, 0xd4, 0x01, 0xba, 0x5b, 0x80, 0xde, 0x3b, 0x8f, 0xae, 0x88, 0x3c, 0x07, 0xf8, 0x66, 0xbb,
+  0x69, 0xb1, 0xd2, 0xbb, 0x3b, 0xef, 0x05, 0x3c, 0x52, 0x0e, 0x87, 0xbc, 0x3f, 0xb9, 0xd2, 0x3b,
+  0x4e, 0x65, 0x17, 0x3b, 0x0a, 0x25, 0x03, 0x3b, 0x60, 0x3c, 0xa6, 0x3b, 0xe8, 0x18, 0xa9, 0x3b,
+  0x2e, 0x73, 0x0d, 0xbb, 0x8d, 0x8a, 0x96, 0x3c, 0x6c, 0x48, 0xce, 0x3b, 0x71, 0x0b, 0xd1, 0x3b,
+  0xde, 0x39, 0x7d, 0xb9, 0x46, 0x0d, 0x3f, 0xbc, 0x20, 0xd4, 0x2a, 0x3c, 0x97, 0x8b, 0x3f, 0xbc,
+  0x5b, 0x78, 0xae, 0x3b, 0x28, 0xc5, 0xea, 0x3c, 0xc7, 0xad, 0x3c, 0x3c, 0xb7, 0x17, 0x58, 0xbc,
+  0xad, 0x11, 0x00, 0x3b, 0xc5, 0x9d, 0x91, 0xb9, 0xf9, 0xde, 0x37, 0xbb, 0x65, 0x7a, 0xc6, 0xbb,
+  0x0b, 0xe6, 0x7f, 0xb9, 0x04, 0xd0, 0xfc, 0x3c, 0x2f, 0x24, 0x0e, 0xbc, 0x72, 0x7a, 0x47, 0x3b,
+  0xcf, 0x84, 0x08, 0xbb, 0x93, 0xd5, 0xd1, 0x3b, 0x0e, 0xe3, 0x72, 0xb9, 0x5f, 0xd5, 0x88, 0xbb,
+  0xe2, 0xe8, 0x17, 0x3c, 0x9a, 0x41, 0xf5, 0x3c, 0x4e, 0xfc, 0x85, 0xbb, 0x86, 0x45, 0x16, 0x3c,
+  0x8d, 0x7d, 0x4b, 0x3b, 0x43, 0xec, 0x79, 0x3b, 0x27, 0x27, 0x56, 0xbb, 0x14, 0xb7, 0x11, 0x3c,
+  0xb8, 0x20, 0xe2, 0xbb, 0x8c, 0xb6, 0x47, 0x3c, 0x9c, 0x0a, 0xd1, 0xba, 0xd5, 0xbd, 0x4f, 0xbb,
+  0x76, 0x99, 0xc4, 0xbb, 0xfa, 0x22, 0x4a, 0xbc, 0x94, 0xbd, 0xf3, 0xba, 0x04, 0xae, 0x4d, 0x3b,
+  0x7c, 0xd1, 0x9f, 0xbb, 0x90, 0xec, 0xb9, 0xba, 0x37, 0x49, 0x9b, 0x3b, 0x61, 0xea, 0x84, 0x3c,
+  0xeb, 0x95, 0x27, 0xb9, 0xf0, 0x9c, 0xd5, 0x39, 0xdb, 0x97, 0x44, 0x3c, 0x0e, 0xbd, 0xe1, 0xb9,
+  0x42, 0x86, 0x41, 0xbc, 0x87, 0x46, 0x15, 0xba, 0x47, 0x74, 0x84, 0x3b, 0x0b, 0xec, 0xb4, 0xba,
+  0xae, 0x42, 0xcf, 0x3a, 0xc5, 0x4d, 0xbb, 0xba, 0x4e, 0x98, 0x71, 0x3c, 0xcb, 0x7c, 0x41, 0xbc,
+  0x8f, 0xd7, 0x9d, 0x3c, 0xf5, 0xfa, 0x80, 0x3b, 0x34, 0xed, 0x83, 0xbc, 0x00, 0x45, 0xcc, 0xbb,
+  0x59, 0xaf, 0x02, 0x3d, 0x29, 0x05, 0x9d, 0xbb, 0x30, 0xf9, 0xbc, 0x3b, 0x12, 0xc6, 0x8f, 0xba,
+  0x5b, 0x3f, 0x6b, 0x3c, 0xe9, 0x5b, 0x20, 0x3d, 0x68, 0x70, 0xd7, 0xbb, 0xad, 0x7d, 0xf6, 0x3a,
+  0x08, 0x6c, 0x33, 0x3c, 0xc6, 0x50, 0xdc, 0xbb, 0x86, 0x19, 0x7b, 0x3b, 0x15, 0x40, 0xc5, 0x3b,
+  0x4d, 0xea, 0x08, 0x3b, 0xb3, 0xa9, 0xd9, 0x3c, 0xed, 0x56, 0x84, 0xbc, 0x39, 0x19, 0xc2, 0x3b,
+  0xd5, 0x29, 0xf8, 0x3b, 0x72, 0x5b, 0x05, 0xbc, 0x25, 0xaa, 0x80, 0xbc, 0x53, 0xd7, 0xf1, 0x3b,
+  0x2b, 0x37, 0x24, 0x3a, 0x12, 0xbd, 0x8b, 0x3c, 0x21, 0xd0, 0x83, 0xbc, 0xe6, 0x16, 0x71, 0xbc,
+  0x37, 0xbe, 0xcc, 0x3b, 0x71, 0x23, 0xc7, 0xba, 0x1a, 0x49, 0xac, 0xbc, 0xb2, 0x65, 0x9f, 0xbb,
+  0x7c, 0x06, 0x10, 0x3c, 0x58, 0x74, 0xde, 0x3b, 0x06, 0xb1, 0x14, 0xbc, 0x04, 0xc3, 0xc6, 0x39,
+  0x30, 0x18, 0xff, 0xbb, 0x7d, 0x7b, 0xd3, 0xbb, 0x4b, 0xf8, 0xb0, 0xba, 0x99, 0x5e, 0x2d, 0xba,
+  0x69, 0x5d, 0x39, 0x3c, 0x04, 0x96, 0xd3, 0xbb, 0xcb, 0xf6, 0xd1, 0x3c, 0x7f, 0x41, 0x95, 0xbc,
+  0x98, 0xd7, 0x9d, 0xbb, 0x1d, 0x9f, 0x05, 0xbc, 0xf6, 0x69, 0x3e, 0xbc, 0x93, 0x72, 0x08, 0xbc,
+  0xc3, 0x1f, 0xd6, 0x3c, 0x1f, 0x6a, 0x98, 0x3c, 0x77, 0x6f, 0x19, 0x3d, 0x1e, 0xdd, 0x6c, 0xbb,
+  0xdc, 0x00, 0xbd, 0xbb, 0xac, 0xab, 0x1e, 0xba, 0xd5, 0xe2, 0x52, 0xbc, 0x25, 0xb2, 0xc8, 0xbb,
+  0xce, 0x5f, 0xc4, 0x3c, 0x35, 0x6c, 0xac, 0x3b, 0x35, 0x1e, 0xd2, 0x3c, 0x46, 0x79, 0x84, 0x3b,
+  0x4d, 0x1e, 0x32, 0xbc, 0x40, 0x16, 0xa0, 0xbb, 0x8b, 0xfa, 0x68, 0xbc, 0x8d, 0x12, 0x18, 0x3c,
+  0xe7, 0x7f, 0x80, 0x3c, 0x55, 0x69, 0x61, 0xba, 0x5d, 0x82, 0x0f, 0x3c, 0x63, 0x71, 0x12, 0xbc,
+  0x2e, 0xaf, 0x89, 0xbc, 0x3b, 0xbb, 0x2b, 0xbb, 0x77, 0xcc, 0x6e, 0xbb, 0xbe, 0x90, 0x17, 0x3b,
+  0x21, 0x7e, 0xf1, 0x3b, 0x34, 0xf9, 0xa1, 0x3a, 0x19, 0x77, 0x5c, 0x3c, 0x85, 0x36, 0x01, 0x3b,
+  0x7d, 0x09, 0xe1, 0xba, 0x2e, 0x8a, 0xe1, 0xbb, 0x0e, 0xbd, 0x88, 0x3c, 0x5e, 0x60, 0xda, 0x3b,
+  0x3e, 0x28, 0xbc, 0x3a, 0xee, 0x07, 0xf2, 0xba, 0xc0, 0x40, 0x4c, 0xbb, 0xfc, 0xaf, 0x38, 0x3c,
+  0x6c, 0x7d, 0x86, 0xbb, 0x1d, 0x1f, 0x0d, 0x3a, 0xab, 0x65, 0x56, 0x3c, 0xad, 0xaf, 0xb6, 0x3a,
+  0xee, 0x82, 0xad, 0xbb, 0xe9, 0x85, 0xd5, 0xba, 0x32, 0x2f, 0x84, 0xbc, 0x9a, 0xd5, 0xcb, 0xbb,
+  0x9b, 0x5f, 0x46, 0x3c, 0xe1, 0xcd, 0xf1, 0xba, 0xa7, 0x5b, 0x03, 0x3c, 0x03, 0xb4, 0x97, 0x3a,
+  0x72, 0xb3, 0x43, 0xbc, 0xae, 0x94, 0x11, 0x3c, 0xf1, 0x61, 0x84, 0xbc, 0x49, 0xcb, 0x9b, 0xbc,
+  0x4c, 0xd2, 0xd3, 0xbb, 0xb8, 0xad, 0x2a, 0x3b, 0xad, 0x18, 0x9e, 0x3c, 0x79, 0x4c, 0x71, 0x3a,
+  0x6a, 0xb1, 0x61, 0x3a, 0x6d, 0x8f, 0x99, 0x3c, 0x68, 0xb6, 0x55, 0x3b, 0x38, 0xfc, 0x80, 0x3b,
+  0x35, 0x00, 0x2f, 0xba, 0xa9, 0x03, 0x4c, 0x3b, 0xd9, 0x1d, 0x98, 0x3c, 0x89, 0x95, 0xdb, 0x3b,
+  0xa3, 0x2e, 0x44, 0x3c, 0xde, 0x14, 0xfc, 0x3c, 0xfa, 0x0f, 0x23, 0xbb, 0xee, 0x2e, 0x57, 0x3a,
+  0x2d, 0x2a, 0xba, 0x3b, 0x90, 0xfe, 0xa2, 0xbb, 0x88, 0x9f, 0xc9, 0x3b, 0xca, 0x34, 0x52, 0x3b,
+  0xc3, 0x32, 0xf0, 0x3b, 0x43, 0x5f, 0x0b, 0x3d, 0xee, 0x17, 0x81, 0xbb, 0xc7, 0xfb, 0x2a, 0x3b,
+  0xc9, 0xf3, 0xd4, 0x3b, 0xab, 0x0b, 0xa5, 0xba, 0xea, 0xfc, 0xae, 0x3a, 0xb1, 0x8b, 0x68, 0x3c,
+  0xf9, 0xe3, 0x62, 0x3b, 0x4c, 0x5d, 0xc4, 0x3c, 0xd2, 0xc1, 0x42, 0xbc, 0xa2, 0x28, 0xa1, 0xbb,
+  0x03, 0xeb, 0x8d, 0x3c, 0x21, 0x8a, 0xe7, 0x39, 0xe5, 0x19, 0x16, 0x3a, 0xdf, 0x36, 0x95, 0x3a,
+  0x85, 0x22, 0xa0, 0x3b, 0x1a, 0x6f, 0xdb, 0xb9, 0xff, 0x70, 0x9c, 0xbb, 0x42, 0x31, 0x94, 0x3c,
+  0x24, 0xcc, 0x24, 0x3c, 0xb9, 0x7b, 0xf9, 0xbb, 0x5e, 0xa2, 0x00, 0x3b, 0x01, 0xcd, 0x11, 0x3c,
+  0x45, 0xb3, 0xac, 0x3a, 0x00, 0xb2, 0x2c, 0xbb, 0x46, 0x79, 0x8f, 0xba, 0xf1, 0x05, 0x99, 0xbb,
+  0x1d, 0x8e, 0xf1, 0xbb, 0x33, 0x3a, 0x94, 0x3b, 0xd5, 0x92, 0xa5, 0x3c, 0x31, 0x31, 0x4a, 0xbc,
+  0x33, 0xbe, 0x28, 0xbc, 0x51, 0x66, 0x97, 0xbb, 0x9b, 0xd3, 0x35, 0x3c, 0x50, 0xec, 0x11, 0x3c,
+  0x08, 0xfa, 0x20, 0xbc, 0xfa, 0x4a, 0x26, 0xba, 0x9c, 0x8e, 0x21, 0x3c, 0xfd, 0x67, 0x27, 0xbc,
+  0x88, 0x6a, 0x88, 0x3c, 0x44, 0x49, 0x41, 0x3b, 0x70, 0x75, 0xdd, 0xbc, 0xf8, 0x1c, 0x9f, 0xbb,
+  0x1d, 0x59, 0xc8, 0x3c, 0x6b, 0x1f, 0x27, 0xbc, 0x83, 0x77, 0xbe, 0xbb, 0x4b, 0x29, 0x40, 0xbc,
+  0x90, 0x4f, 0x0b, 0x3c, 0xf2, 0xb5, 0xa5, 0x3c, 0x77, 0x7b, 0x62, 0xbc, 0x54, 0x09, 0x4b, 0xbc,
+  0x9f, 0xbd, 0xc5, 0x3c, 0xad, 0xed, 0x45, 0xbb, 0x3a, 0x6d, 0x30, 0x3c, 0x15, 0x90, 0x22, 0x3c,
+  0x9b, 0xcb, 0x30, 0x3c, 0x23, 0x09, 0xfa, 0x3c, 0xdf, 0x32, 0xec, 0xbb, 0xe2, 0x8b, 0x80, 0x3b,
+  0x04, 0x85, 0x48, 0x3c, 0xbc, 0x62, 0xc5, 0xbb, 0x84, 0xee, 0x9f, 0xbb, 0x9d, 0x57, 0xb7, 0x3b,
+  0x9f, 0x2d, 0xbc, 0x3b, 0x0f, 0xa2, 0x02, 0x3c, 0xf4, 0x93, 0xbc, 0xbc, 0xb0, 0xde, 0x83, 0x3c,
+  0x1b, 0xec, 0x84, 0x3a, 0x2e, 0x15, 0x0e, 0xbc, 0xec, 0x0c, 0x2a, 0xbc, 0xc9, 0x16, 0xb8, 0xbb,
+  0x8d, 0xab, 0x84, 0xbb, 0x6d, 0x6c, 0x4f, 0xbb, 0x5b, 0xee, 0x11, 0x3c, 0x3a, 0xd2, 0xfc, 0x3b,
+  0x55, 0x48, 0x34, 0x3c, 0xa8, 0x02, 0xa8, 0xbb, 0x86, 0x90, 0xeb, 0xbb, 0xdd, 0x5b, 0xa0, 0x3b,
+  0x60, 0x44, 0xdc, 0x3b, 0x02, 0x1c, 0xd0, 0xba, 0x7b, 0x3e, 0xc2, 0x3c, 0x94, 0x58, 0x93, 0xbc,
+  0xe9, 0x33, 0xec, 0xbb, 0xf3, 0x0e, 0x6b, 0xbc, 0xcd, 0xcb, 0x92, 0xbc, 0xf2, 0x32, 0xe3, 0xbb,
+  0x62, 0xfd, 0xc9, 0x3c, 0x9f, 0x02, 0x72, 0x3c, 0x37, 0x88, 0x23, 0x3d, 0xf6, 0x43, 0x08, 0xbb,
+  0x86, 0xd2, 0x57, 0xbc, 0x1c, 0x41, 0xe2, 0xbb, 0x0c, 0x7b, 0x9f, 0xbb, 0x89, 0x7f, 0xd7, 0xbb,
+  0x06, 0x22, 0x63, 0x3c, 0x20, 0x02, 0x04, 0x3b, 0xe8, 0x0c, 0x12, 0x3d, 0xb0, 0xfe, 0x1b, 0xbc,
+  0xf8, 0x49, 0x0f, 0xbc, 0x6f, 0x26, 0x45, 0x3b, 0xf0, 0xb7, 0x82, 0xbc, 0x06, 0x4f, 0x34, 0x3a,
+  0x38, 0x6f, 0x4b, 0x3c, 0xb0, 0x33, 0x04, 0x3b, 0x6d, 0xcc, 0x99, 0x3c, 0x79, 0xe4, 0xfc, 0xba,
+  0x44, 0x11, 0x4f, 0xbc, 0x73, 0x2c, 0x9f, 0xba, 0x84, 0x29, 0x98, 0xbc, 0x43, 0x20, 0x9f, 0xba,
+  0x82, 0x0d, 0xd5, 0x3b, 0xab, 0x8d, 0xeb, 0xb8, 0xd7, 0x41, 0xb5, 0x3b, 0x51, 0x19, 0x2c, 0x3c,
+  0xbd, 0x58, 0xd3, 0xbb, 0xd6, 0xfe, 0xd4, 0x3a, 0xff, 0x35, 0x94, 0xbb, 0x60, 0xe9, 0x0c, 0xbb,
+  0xa1, 0xab, 0xdf, 0x3b, 0xe1, 0xe5, 0xe4, 0x3b, 0x11, 0xcc, 0x88, 0x3b, 0x58, 0xbf, 0x35, 0x3b,
+  0x56, 0x49, 0x41, 0x3b, 0xce, 0xd1, 0x02, 0x3b, 0xe8, 0x23, 0x6f, 0x3b, 0x07, 0x27, 0x8c, 0x3a,
+  0x21, 0x18, 0x13, 0xbc, 0x6d, 0x59, 0xaa, 0xbb, 0x95, 0x85, 0x5d, 0xbc, 0x7a, 0x3f, 0x4f, 0xbc,
+  0x54, 0x4f, 0x52, 0x3b, 0x36, 0x09, 0x4a, 0x3b, 0x03, 0xfe, 0xa9, 0x3a, 0xac, 0x31, 0x3e, 0x3c,
+  0x0c, 0xef, 0x2f, 0xbc, 0xd2, 0x28, 0x12, 0x3c, 0xed, 0x4c, 0x6a, 0xbc, 0x01, 0x93, 0x3b, 0xbb,
+  0x14, 0x76, 0xfc, 0x3b, 0x95, 0x16, 0xd4, 0xbb, 0x48, 0xb6, 0x8f, 0x3a, 0xbd, 0x99, 0x1b, 0xbc,
+  0x3a, 0x3e, 0xb6, 0x3a, 0xd8, 0x77, 0xe9, 0x3c, 0xc5, 0x12, 0x97, 0xbb, 0xaf, 0xbc, 0xa1, 0xbb,
+  0xb0, 0x91, 0x99, 0x3b, 0xa8, 0xb9, 0xfe, 0x3b, 0xfd, 0x3b, 0x86, 0x3b, 0x15, 0xe3, 0x6f, 0xbb,
+  0x33, 0xda, 0x20, 0x3c, 0xc6, 0xc8, 0x8e, 0x3c, 0xd2, 0x41, 0xd2, 0xba, 0x03, 0xb8, 0xd1, 0x3b,
+  0xcd, 0xed, 0x90, 0x3b, 0xc8, 0x92, 0xe5, 0x39, 0xea, 0x49, 0x3f, 0xb9, 0xef, 0x97, 0x83, 0xb9,
+  0x3e, 0x26, 0x33, 0xb9, 0xd1, 0x04, 0x4e, 0x3c, 0x01, 0xc6, 0xf9, 0xbb, 0xa0, 0x9f, 0x0a, 0xbc,
+  0x52, 0x10, 0x70, 0x3b, 0xbb, 0x3f, 0xb2, 0x3a, 0x9e, 0x06, 0x63, 0x3c, 0x3f, 0x3d, 0x0e, 0x3b,
+  0xa7, 0x4b, 0x2d, 0x3c, 0x6c, 0x3d, 0x09, 0x3d, 0x07, 0x1a, 0x4d, 0xbc, 0xbb, 0x12, 0x83, 0xbb,
+  0xb8, 0x68, 0x81, 0x3b, 0x15, 0x63, 0xbe, 0xb8, 0xb0, 0xcd, 0x93, 0x3b, 0xb8, 0xec, 0x93, 0x3b,
+  0x49, 0xa4, 0xc7, 0xb9, 0x89, 0x12, 0xfd, 0x39, 0x17, 0xbe, 0xf7, 0xba, 0x0d, 0xc3, 0x79, 0x3c,
+  0x5a, 0x2f, 0xde, 0xba, 0x71, 0x0d, 0x19, 0xbc, 0x88, 0x0b, 0x21, 0x3b, 0xcd, 0x6a, 0x56, 0x3c,
+  0x45, 0x32, 0xba, 0x3a, 0xa6, 0xf6, 0xe3, 0xbb, 0xb0, 0xb3, 0x09, 0x3c, 0xcf, 0x90, 0x5c, 0xbc,
+  0xaf, 0xfe, 0x3d, 0xbb, 0xb1, 0xcc, 0x8d, 0x3c, 0xb7, 0x88, 0x5a, 0x3c, 0x7b, 0xfc, 0xb0, 0xbb,
+  0xfd, 0x40, 0xd9, 0xbb, 0xcb, 0x79, 0x21, 0x3b, 0x71, 0xe3, 0x04, 0x3c, 0x2c, 0xb0, 0x47, 0xbc,
+  0xbe, 0xda, 0x41, 0xbb, 0x5f, 0x29, 0x87, 0x3a, 0x5e, 0x33, 0x7a, 0x3c, 0xbf, 0xb9, 0x2b, 0xbc,
+  0xa5, 0x44, 0xbf, 0x3c, 0x8d, 0xf0, 0xfb, 0x3b, 0x3e, 0x8c, 0xc1, 0xbc, 0x85, 0x0d, 0x9c, 0xbc,
+  0x8a, 0x7e, 0xc9, 0x3c, 0xe5, 0x86, 0x10, 0xbc, 0x2a, 0x0a, 0x2c, 0xba, 0x6e, 0xc3, 0x89, 0x3b,
+  0xb6, 0x4c, 0x7d, 0x3c, 0x9e, 0xa2, 0xf8, 0x3c, 0xfc, 0xb5, 0x69, 0xbc, 0x78, 0x61, 0x95, 0x3b,
+  0x7a, 0x4d, 0x9f, 0x3c, 0xbd, 0xd3, 0x10, 0xbc, 0x84, 0x46, 0xe4, 0x3c, 0x9b, 0xe3, 0xdf, 0xbb,
+  0xde, 0x05, 0x6b, 0x3c, 0x48, 0xa7, 0xe0, 0x3c, 0xe6, 0x3c, 0x83, 0x3a, 0x76, 0x73, 0x6c, 0x3c,
+  0x30, 0x86, 0x46, 0xba, 0x64, 0x91, 0xda, 0xbb, 0xaf, 0xbf, 0x01, 0xbc, 0x7d, 0x7a, 0x6d, 0xbc,
+  0x62, 0x51, 0xd1, 0x3b, 0x29, 0x0f, 0xf3, 0x3b, 0x32, 0xad, 0xf2, 0xbb, 0xc5, 0xd8, 0x43, 0x3c,
+  0x43, 0xb3, 0x93, 0x3a, 0xa8, 0xec, 0x44, 0xbc, 0xaf, 0x6e, 0x1c, 0xbc, 0xcf, 0x44, 0x20, 0xba,
+  0x4f, 0x83, 0x53, 0xba, 0x22, 0xf2, 0x59, 0xbc, 0x21, 0xb0, 0x98, 0xba, 0xfb, 0x9b, 0x25, 0xbb,
+  0x91, 0xa4, 0x55, 0x3a, 0x6c, 0xf7, 0x98, 0xbb, 0x8c, 0xb8, 0xef, 0xbb, 0x5e, 0xad, 0xb7, 0xbb,
+  0x36, 0xf5, 0x64, 0x3b, 0xca, 0x82, 0x49, 0x3c, 0x31, 0x57, 0xa3, 0x3c, 0x52, 0x5d, 0x67, 0xbb,
+  0x83, 0xc9, 0x34, 0x3b, 0x4b, 0xc3, 0x5b, 0xbb, 0x61, 0xde, 0x94, 0xbc, 0x19, 0xfa, 0xbf, 0xbb,
+  0xf5, 0xb1, 0x83, 0x3c, 0xcb, 0xba, 0x72, 0x3a, 0x91, 0xb4, 0x1a, 0x3d, 0xbc, 0x56, 0x9e, 0x3b,
+  0x3d, 0xec, 0xce, 0xbb, 0x89, 0xf2, 0xde, 0xba, 0xd1, 0xbc, 0xcd, 0xbb, 0x89, 0xaf, 0xa4, 0xbb,
+  0x93, 0x9d, 0x90, 0x3c, 0xfa, 0x55, 0x9f, 0x3b, 0x40, 0xed, 0x9b, 0x3c, 0xbd, 0x89, 0xcf, 0x39,
+  0xee, 0x4d, 0x92, 0xbb, 0x9c, 0x97, 0x8a, 0x3b, 0x2e, 0xf1, 0x4b, 0xbc, 0x31, 0xb3, 0x29, 0x3b,
+  0xe1, 0x5d, 0x9e, 0x3c, 0xda, 0x57, 0x90, 0xbb, 0xa1, 0x92, 0x6e, 0x3c, 0xb9, 0xe5, 0xd7, 0xbb,
+  0x7a, 0x52, 0x0b, 0xbc, 0x7e, 0x3b, 0x13, 0x3c, 0xc1, 0x39, 0x0d, 0xbc, 0xff, 0x4d, 0x0f, 0x3b,
+  0x61, 0x22, 0xee, 0x3b, 0x49, 0x50, 0xa3, 0x3b, 0x10, 0xc9, 0x94, 0x3b, 0x07, 0x33, 0x3e, 0xbc,
+  0xf7, 0xbf, 0x3d, 0xbc, 0xbb, 0xd3, 0xe0, 0x3b, 0x4b, 0xe2, 0x26, 0x3b, 0x12, 0xc5, 0x0d, 0x3c,
+  0xeb, 0x6b, 0xee, 0x3b, 0xcf, 0x18, 0x28, 0x3c, 0x67, 0xb1, 0x86, 0x3a, 0x99, 0x05, 0x1d, 0xbc,
+  0x37, 0x46, 0x7c, 0xbb, 0x5a, 0x0b, 0x3e, 0x3a, 0x7a, 0x4b, 0x8b, 0xbb, 0xbd, 0x3f, 0x2b, 0x3b,
+  0xa4, 0x8b, 0x7f, 0xbb, 0x42, 0x4b, 0x02, 0xba, 0x3e, 0xb5, 0x8e, 0xbc, 0x8c, 0x10, 0x47, 0x39,
+  0x19, 0x84, 0xae, 0x39, 0x6b, 0x93, 0x52, 0xb9, 0xe3, 0x2b, 0x0a, 0x3c, 0xf7, 0x52, 0x31, 0x3c,
+  0x5e, 0x7c, 0x1e, 0xbc, 0xbb, 0xd5, 0x47, 0x3c, 0xd4, 0x3d, 0x45, 0xbb, 0xfd, 0xd4, 0x93, 0x3b,
+  0x61, 0x23, 0x30, 0xbb, 0x7e, 0x51, 0xd0, 0xbb, 0x79, 0xc9, 0x66, 0x3c, 0xe5, 0x72, 0xb0, 0x3b,
+  0x58, 0x7d, 0x5f, 0x3b, 0x6e, 0x35, 0x90, 0x3c, 0x64, 0x73, 0x2c, 0xbc, 0x49, 0xcc, 0xbd, 0x3b,
+  0x1a, 0x19, 0xad, 0xbb, 0xc9, 0x76, 0x3c, 0xbb, 0x1b, 0xd1, 0xed, 0x3a, 0x06, 0x6f, 0x87, 0xbb,
+  0xd2, 0x64, 0x5d, 0xba, 0x2b, 0xcd, 0xc6, 0x3c, 0x57, 0xc2, 0x86, 0xba, 0x73, 0xd0, 0x1c, 0x3c,
+  0x25, 0xe4, 0x04, 0xbc, 0xb8, 0x1f, 0xfd, 0x3a, 0x7e, 0x11, 0xf5, 0xbb, 0x54, 0x13, 0xe3, 0x38,
+  0xc9, 0x07, 0x31, 0x39, 0xb4, 0x71, 0xe2, 0x3c, 0x85, 0x17, 0x2a, 0xbc, 0x63, 0x71, 0x3e, 0xbb,
+  0xa2, 0x29, 0xf9, 0x3b, 0x30, 0xd3, 0x27, 0x3a, 0xc2, 0x05, 0x5b, 0xbc, 0x8f, 0xad, 0xe5, 0xb7,
+  0xbe, 0xe2, 0x34, 0xba, 0xd0, 0xb7, 0x87, 0x3c, 0x6a, 0xbc, 0x36, 0xbc, 0xd7, 0x2f, 0x94, 0x3c,
+  0x1a, 0x9f, 0x23, 0x3c, 0xcf, 0xc0, 0xf7, 0x3b, 0x05, 0xbf, 0x04, 0x3b, 0x28, 0xb5, 0x20, 0x3c,
+  0x61, 0xfc, 0xc7, 0x3b, 0x9b, 0xa0, 0x76, 0x3b, 0x05, 0x78, 0x7a, 0xbb, 0xa6, 0x62, 0xc1, 0xba,
+  0xa8, 0x8b, 0xf5, 0x3b, 0xef, 0xf5, 0x1b, 0xbb, 0x0c, 0xa0, 0xe3, 0x37, 0x00, 0xaa, 0x7f, 0x3c,
+  0x38, 0x29, 0x40, 0x3b, 0x6e, 0x83, 0x2d, 0xbb, 0x00, 0x1c, 0xea, 0x3b, 0x90, 0xa1, 0x82, 0x3b,
+  0x25, 0xeb, 0xe4, 0xbb, 0xd7, 0x5b, 0x8b, 0x3b, 0x63, 0x33, 0x9c, 0x3c, 0xde, 0x34, 0xf4, 0xbb,
+  0x34, 0x06, 0x9c, 0xbc, 0x3c, 0x1b, 0xc6, 0x3b, 0xf5, 0x02, 0x82, 0x3b, 0x17, 0x39, 0x88, 0x3b,
+  0xe8, 0x4a, 0x8d, 0x3a, 0x5a, 0x5d, 0x26, 0xbb, 0x55, 0x90, 0x09, 0x3c, 0xef, 0xe1, 0xd6, 0x3a,
+  0xf7, 0x52, 0xe0, 0x3b, 0x34, 0x9e, 0x16, 0xbb, 0x33, 0xe5, 0xc2, 0xbc, 0x5f, 0x0e, 0xf8, 0xbb,
+  0x16, 0x69, 0xe0, 0x3c, 0x73, 0xa4, 0x55, 0xbc, 0xee, 0x62, 0x86, 0x3b, 0xf3, 0x2b, 0x99, 0xbb,
+  0xfa, 0x6b, 0x73, 0x3c, 0x13, 0xf5, 0xcf, 0x3c, 0x09, 0xc8, 0x89, 0xbc, 0xbe, 0x3e, 0x5c, 0x3c,
+  0x86, 0x74, 0x91, 0x3c, 0xce, 0xc1, 0x07, 0xbc, 0x68, 0x2d, 0x32, 0x3c, 0x1b, 0x8c, 0xbe, 0x3b,
+  0xee, 0x70, 0xa2, 0xbb, 0x60, 0x12, 0xf4, 0x3c, 0xd3, 0xe3, 0x00, 0xbc, 0xbf, 0xc1, 0x81, 0x3c,
+  0x6f, 0x34, 0x84, 0x3b, 0xec, 0x42, 0x7f, 0xb9, 0x08, 0x6e, 0xa2, 0xbc, 0x4c, 0xe2, 0x01, 0xbb,
+  0xf8, 0xee, 0xc3, 0xba, 0xdf, 0x68, 0x72, 0x3c, 0x31, 0x2b, 0x54, 0xbc, 0x43, 0xfa, 0x3d, 0x3c,
+  0xfc, 0xe1, 0x0c, 0x3c, 0xd0, 0x83, 0x37, 0xbc, 0xd2, 0x56, 0xab, 0xbb, 0x79, 0x5f, 0x36, 0xbc,
+  0xe6, 0xc4, 0x09, 0x3c, 0xc7, 0xbd, 0xa3, 0xbb, 0x75, 0xc8, 0x8f, 0x3a, 0xd5, 0x43, 0x18, 0x3c,
+  0xf0, 0x02, 0xbd, 0xbb, 0x21, 0x94, 0xa3, 0x3b, 0x33, 0x70, 0xca, 0xba, 0x5a, 0x72, 0xbe, 0x3a,
+  0x3d, 0x19, 0x90, 0x3b, 0x4f, 0x91, 0x6b, 0x3b, 0x36, 0xd4, 0xb9, 0x3c, 0xfc, 0x70, 0x4e, 0x3b,
+  0xf1, 0xef, 0x0e, 0xbc, 0xfa, 0xd2, 0xab, 0xba, 0x89, 0xdc, 0xa1, 0xbc, 0x83, 0x73, 0x86, 0x38,
+  0x0d, 0xbb, 0xa7, 0x3c, 0x38, 0x95, 0xa0, 0x3c, 0x6e, 0xf3, 0xe8, 0x3c, 0x15, 0x58, 0x92, 0xbc,
+  0x06, 0xa2, 0x84, 0xbc, 0xe5, 0x4b, 0xec, 0xbb, 0x36, 0x2d, 0x75, 0xbc, 0x3a, 0xb7, 0x8c, 0xbb,
+  0x49, 0xc6, 0x0a, 0x3d, 0x64, 0x5e, 0x10, 0x3c, 0x46, 0x7f, 0xcf, 0x3c, 0xea, 0x09, 0xba, 0x3b,
+  0x2d, 0x16, 0x5f, 0xbc, 0x72, 0x6c, 0x8d, 0x3b, 0xe2, 0x52, 0x08, 0xbc, 0x96, 0x81, 0x30, 0x3c,
+  0x8b, 0x40, 0xa8, 0x3c, 0x3c, 0x19, 0x29, 0xbc, 0xd0, 0x23, 0xb0, 0x3c, 0x72, 0x52, 0x73, 0xbb,
+  0x5d, 0x01, 0x40, 0xbc, 0x63, 0x68, 0x3d, 0x3c, 0x8e, 0xfe, 0x06, 0xbc, 0x86, 0x46, 0xc3, 0x3a,
+  0x3f, 0x56, 0x02, 0x3c, 0x8d, 0xa0, 0x9b, 0x3b, 0xdf, 0xb0, 0xf3, 0x3b, 0xf9, 0x55, 0x06, 0xba,
+  0x04, 0x8c, 0x3d, 0xbc, 0xb1, 0x20, 0x5e, 0x3b, 0xbf, 0x31, 0xb8, 0x3b, 0xee, 0x1f, 0x58, 0x3b,
+  0xd3, 0x1a, 0xd1, 0x3a, 0xb9, 0x76, 0x3e, 0x3c, 0x3a, 0xcc, 0x20, 0x3b, 0xe5, 0x87, 0x6b, 0x3b,
+  0x99, 0x03, 0x85, 0xbb, 0xd8, 0x4c, 0x6c, 0xbb, 0x6c, 0x2f, 0x31, 0x3b, 0x99, 0x7e, 0x3f, 0x3c,
+  0x13, 0x99, 0x31, 0xbc, 0xa1, 0xb8, 0x5a, 0xbb, 0x7e, 0x3e, 0x78, 0xbc, 0x7f, 0xff, 0xf2, 0x3b,
+  0x21, 0x7a, 0xc4, 0x3b, 0xd3, 0x06, 0x3f, 0x3c, 0x85, 0x42, 0xf7, 0x3a, 0xe9, 0x58, 0x2f, 0x3a,
+  0x5e, 0x1b, 0x00, 0xbc, 0x2f, 0x0d, 0x5b, 0x3c, 0x0c, 0xae, 0xa1, 0xbb, 0x32, 0x93, 0x1d, 0x3c,
+  0xcd, 0xf3, 0xd6, 0xba, 0x0c, 0xe2, 0x0f, 0x3c, 0x40, 0x18, 0xb8, 0x3b, 0xe6, 0x69, 0xb4, 0x3b,
+  0x98, 0x6f, 0x92, 0x3a, 0xf4, 0x98, 0xcb, 0x3c, 0x49, 0x62, 0xa0, 0xbb, 0x90, 0x37, 0x4d, 0xbc,
+  0xaf, 0x35, 0xa6, 0xba, 0xe1, 0x80, 0x66, 0xbb, 0x39, 0xf3, 0x68, 0xbb, 0x5d, 0x91, 0xd5, 0xba,
+  0xd7, 0x04, 0x47, 0x36, 0x60, 0xf7, 0xa2, 0x3c, 0x0a, 0x61, 0xfc, 0xba, 0xd0, 0xb7, 0x5b, 0xbb,
+  0x01, 0x53, 0xa1, 0xb9, 0x9f, 0x0f, 0x9e, 0x3b, 0xfd, 0xfd, 0x42, 0xba, 0x90, 0xfa, 0x55, 0x3c,
+  0x87, 0x68, 0xab, 0xbb, 0x8d, 0x92, 0xcb, 0x3c, 0x3c, 0xe4, 0x8d, 0xbc, 0xf8, 0x01, 0x56, 0xbb,
+  0x13, 0x37, 0x24, 0x3c, 0x12, 0x25, 0x13, 0x3c, 0xa8, 0x24, 0x42, 0xbc, 0x95, 0xe1, 0x52, 0x3c,
+  0xcf, 0x98, 0x94, 0xbb, 0xed, 0xb6, 0x90, 0x3c, 0xf4, 0x06, 0xa0, 0xba, 0x99, 0x44, 0x8f, 0x3b,
+  0x37, 0x8e, 0x82, 0x3b, 0xc7, 0xd4, 0x9f, 0x3b, 0x2b, 0xb0, 0xf6, 0xbb, 0x9a, 0x54, 0x35, 0x3c,
+  0x8d, 0xcc, 0xe6, 0x3b, 0xeb, 0x60, 0x02, 0x3b, 0x41, 0xf8, 0xb4, 0xbb, 0x1f, 0x47, 0x37, 0xbc,
+  0x8b, 0xec, 0x40, 0x3b, 0x53, 0x86, 0x59, 0x3b, 0x5a, 0x30, 0xab, 0xbb, 0x43, 0x69, 0x46, 0x3a,
+  0x67, 0x61, 0x04, 0xbb, 0xa7, 0xfd, 0xb3, 0xbb, 0xda, 0xcf, 0x87, 0x3b, 0x97, 0x08, 0x0f, 0xbc,
+  0xb8, 0x2f, 0xee, 0xbb, 0x9f, 0x35, 0x4f, 0x3b, 0xf1, 0x9f, 0xdc, 0x3c, 0x60, 0x8e, 0xb6, 0x3a,
+  0x82, 0x9c, 0x2b, 0x3b, 0xc2, 0x44, 0xeb, 0x3b, 0x68, 0x3b, 0x2d, 0x3c, 0xb6, 0xee, 0xe6, 0x3b,
+  0xa3, 0xcb, 0x12, 0xbc, 0xce, 0x96, 0x18, 0xba, 0x9f, 0x64, 0x80, 0x3c, 0xfc, 0x7d, 0x6e, 0xbb,
+  0x67, 0x59, 0xcb, 0x3c, 0xf8, 0xc8, 0x69, 0x3b, 0x10, 0x6d, 0xb9, 0xbc, 0x03, 0x97, 0x61, 0xbb,
+  0x02, 0xc3, 0x99, 0x3c, 0x1b, 0x64, 0x67, 0xb7, 0x19, 0x22, 0xbc, 0x3b, 0x18, 0xb3, 0x81, 0x3c,
+  0x2e, 0xbd, 0x3e, 0x3c, 0x46, 0xf6, 0x01, 0x3d, 0x07, 0x42, 0x48, 0xbc, 0xce, 0x0f, 0x81, 0x3a,
+  0x6b, 0x60, 0x48, 0x3c, 0x82, 0x1b, 0xe7, 0xbb, 0xa2, 0x71, 0xb7, 0x3c, 0xb5, 0x13, 0xf1, 0xbb,
+  0xe1, 0x19, 0xdd, 0x3b, 0xc3, 0xeb, 0xe6, 0x3c, 0x78, 0xff, 0x0f, 0xbc, 0x92, 0x62, 0x77, 0xbb,
+  0x2b, 0x90, 0x81, 0x3b, 0xe1, 0xeb, 0x2b, 0xbc, 0x3f, 0x39, 0x99, 0xba, 0x8c, 0x74, 0x69, 0xbb,
+  0x74, 0x9c, 0xbf, 0x3a, 0x48, 0x8f, 0x3e, 0x3c, 0x32, 0xfe, 0xb0, 0xbb, 0x42, 0x91, 0x7d, 0xbb,
+  0x45, 0x6e, 0xd3, 0x3b, 0xe5, 0x5e, 0x25, 0xbc, 0x1f, 0x5c, 0x2e, 0x3a, 0x40, 0xf9, 0xf4, 0x3b,
+  0x81, 0xfc, 0x93, 0x3b, 0x94, 0xb7, 0x9a, 0x3a, 0xf5, 0x81, 0x25, 0x3c, 0x4b, 0x40, 0x0e, 0xbb,
+  0xc4, 0x90, 0xeb, 0xbb, 0x7a, 0x54, 0xaf, 0x3b, 0xf0, 0x58, 0xde, 0xbb, 0x01, 0xe3, 0x2f, 0x3b,
+  0x98, 0xf2, 0x6f, 0x3b, 0x70, 0x44, 0x94, 0x3b, 0xc9, 0x85, 0xb9, 0x3c, 0x4b, 0x96, 0x40, 0x3c,
+  0x5d, 0x75, 0x4a, 0x3a, 0xec, 0x80, 0x7a, 0xba, 0x08, 0x17, 0x5d, 0xbc, 0x2c, 0x0b, 0x33, 0x3b,
+  0x02, 0x15, 0x70, 0x3c, 0x4d, 0xc8, 0x35, 0x3c, 0xf5, 0xdd, 0x0f, 0x3d, 0x8b, 0xe3, 0xd4, 0xbb,
+  0xde, 0x90, 0x6d, 0xbc, 0xca, 0x20, 0x62, 0x3a, 0xee, 0x7c, 0x04, 0xbc, 0xec, 0x66, 0xee, 0x3a,
+  0x6e, 0xab, 0x96, 0x3c, 0xa9, 0x38, 0x30, 0x3c, 0x0e, 0x4b, 0xf7, 0x3c, 0xcb, 0x00, 0x84, 0x3b,
+  0x4c, 0x9e, 0xf0, 0xbb, 0x04, 0xd4, 0x95, 0x3b, 0xbe, 0xc1, 0xc3, 0xba, 0x44, 0x0a, 0x4e, 0xbb,
+  0x6a, 0x24, 0x9e, 0x3c, 0x90, 0xa1, 0x05, 0x3a, 0xeb, 0x3a, 0x23, 0x3c, 0xfc, 0x06, 0xb2, 0x3b,
+  0x23, 0x11, 0x68, 0xbb, 0xa0, 0x4b, 0xf9, 0x3b, 0x75, 0xbc, 0x8b, 0xbc, 0x8e, 0x4d, 0x7b, 0x3a,
+  0x19, 0xfa, 0x77, 0x3c, 0x24, 0x0e, 0x8c, 0xbb, 0x53, 0x01, 0x2e, 0x3c, 0x44, 0x87, 0x4b, 0xbc,
+  0xbf, 0x93, 0x92, 0x3b, 0x90, 0xcb, 0xc8, 0x3a, 0x5b, 0x92, 0xf0, 0xbb, 0xfc, 0x7c, 0xae, 0xbb,
+  0x00, 0xa1, 0x0a, 0x3c, 0x09, 0xe5, 0x5e, 0x3c, 0xd7, 0x34, 0x2b, 0xbb, 0xf9, 0xee, 0xa4, 0x3c,
+  0xf3, 0x15, 0x6c, 0x3b, 0x63, 0x39, 0x40, 0xbb, 0xcd, 0x50, 0xa1, 0x3b, 0x65, 0xe0, 0x29, 0x3c,
+  0xb4, 0x97, 0x9f, 0xbb, 0x0c, 0x6b, 0x22, 0x3c, 0x21, 0x66, 0x00, 0xbc, 0x7b, 0x21, 0x39, 0x3b,
+  0x30, 0xca, 0x01, 0x3c, 0x38, 0xb2, 0xd6, 0xba, 0x6f, 0xfd, 0xdc, 0x3b, 0xd5, 0x13, 0x63, 0xbb,
+  0x71, 0xc3, 0xa2, 0xbb, 0xaf, 0xac, 0x0d, 0x3c, 0xd9, 0xb1, 0x12, 0xbc, 0xaf, 0x3c, 0xc5, 0xbb,
+  0xaa, 0x4e, 0xd2, 0xba, 0x46, 0xe4, 0x74, 0x3c, 0x92, 0xd9, 0xa5, 0x3b, 0xd3, 0x84, 0x33, 0xbb,
+  0xa9, 0x0c, 0x6c, 0x3b, 0xf4, 0x90, 0xbd, 0x3c, 0xe7, 0x45, 0x73, 0xbb, 0x49, 0x3d, 0xf4, 0xb9,
+  0x74, 0x91, 0xb2, 0x3b, 0x18, 0x64, 0x23, 0xbc, 0x1a, 0x01, 0xfb, 0x3b, 0xb8, 0x71, 0x03, 0xba,
+  0x71, 0x11, 0x57, 0x3b, 0x45, 0xb9, 0x84, 0x3c, 0xa4, 0xe6, 0xc6, 0x3b, 0x99, 0x59, 0x65, 0x3b,
+  0x18, 0xdf, 0x8f, 0x3b, 0x43, 0x2c, 0xc6, 0x3a, 0xec, 0xf7, 0x9b, 0xbb, 0x83, 0x54, 0x85, 0xbb,
+  0x84, 0x34, 0xf2, 0xba, 0x04, 0x61, 0x95, 0x3c, 0x97, 0x26, 0x7c, 0xbb, 0xc8, 0x0b, 0x0c, 0xbc,
+  0xbe, 0xcc, 0x06, 0x3c, 0x16, 0x51, 0x50, 0x3a, 0x2b, 0x42, 0xb0, 0x3a, 0x9a, 0x4b, 0x96, 0x3b,
+  0xd2, 0xaf, 0x01, 0xbc, 0xe1, 0x25, 0xda, 0x3c, 0x65, 0x43, 0x91, 0xba, 0xec, 0x69, 0x16, 0x3c,
+  0x63, 0xbe, 0x51, 0x3c, 0x55, 0x22, 0x88, 0x3b, 0x71, 0xab, 0x69, 0xba, 0xd5, 0x77, 0x41, 0x3b,
+  0x34, 0x93, 0x19, 0x3b, 0x70, 0xd8, 0xc4, 0xbb, 0x08, 0x65, 0x03, 0x3b, 0x51, 0xde, 0x80, 0xbc,
+  0x9f, 0xbf, 0xfe, 0xba, 0xb8, 0x44, 0xd1, 0xb8, 0x30, 0x01, 0x47, 0xbc, 0xba, 0x89, 0x21, 0x3c,
+  0x75, 0xff, 0x1f, 0xbc, 0x24, 0x50, 0xe6, 0xbb, 0x0b, 0xd0, 0x80, 0xbb, 0x51, 0xce, 0x07, 0xbb,
+  0x87, 0x8d, 0x15, 0xbc, 0xb6, 0x2a, 0x16, 0x3b, 0x15, 0x4e, 0xdc, 0x3b, 0xab, 0x32, 0xcd, 0xbb,
+  0x02, 0xa3, 0x24, 0x3c, 0xa7, 0xbc, 0x93, 0x3b, 0x82, 0x04, 0xc3, 0x39, 0x01, 0x12, 0xcf, 0x3b,
+  0x22, 0x21, 0xda, 0xba, 0x2a, 0xac, 0xa9, 0x38, 0xe6, 0xb6, 0x8b, 0x3c, 0x1f, 0x9e, 0x6b, 0xbc,
+  0x1d, 0xf9, 0xbf, 0x3c, 0xd6, 0x19, 0x12, 0x3c, 0xaf, 0x34, 0xa8, 0xbc, 0x05, 0xe8, 0x51, 0x3c,
+  0xf2, 0xdb, 0xa9, 0x3c, 0x39, 0x78, 0x3b, 0xbc, 0x39, 0x80, 0xd2, 0x3a, 0xb1, 0x51, 0x6d, 0x3b,
+  0x01, 0x22, 0x62, 0x3c, 0xcb, 0x26, 0xc9, 0x3c, 0x00, 0x22, 0x8c, 0xbc, 0xf8, 0xcb, 0xbb, 0xba,
+  0x8f, 0x25, 0x8e, 0x3c, 0xad, 0xde, 0x58, 0xbc, 0x2c, 0x0b, 0x79, 0x3c, 0x84, 0x08, 0x49, 0xbb,
+  0x47, 0x05, 0x4c, 0x3b, 0x3d, 0x54, 0xc6, 0x3c, 0xa4, 0x8a, 0xf3, 0x39, 0xd9, 0x3c, 0x0d, 0x3c,
+  0x61, 0x2c, 0x3e, 0x3b, 0xfd, 0xff, 0xb3, 0xbb, 0x26, 0x40, 0x06, 0xbc, 0xad, 0x07, 0x89, 0xbb,
+  0x3f, 0xf6, 0x33, 0xbb, 0x82, 0x98, 0x14, 0x3c, 0x50, 0x9c, 0xe7, 0x39, 0x2e, 0x42, 0x1d, 0xbc,
+  0x69, 0x64, 0x0f, 0xbc, 0x7b, 0xb3, 0x7b, 0xbc, 0xb0, 0x73, 0xb7, 0xba, 0xc2, 0xdc, 0xc4, 0x3b,
+  0xc0, 0x02, 0x8a, 0xb9, 0x47, 0x20, 0x86, 0x3b, 0x84, 0x0c, 0xa3, 0xbb, 0x4b, 0x4e, 0x18, 0x39,
+  0xb8, 0x7a, 0x17, 0xbc, 0xf2, 0xd2, 0x54, 0x3b, 0x01, 0x8b, 0x2f, 0xbc, 0x7b, 0xcf, 0xd4, 0x3b,
+  0xca, 0x47, 0xb8, 0xb9, 0x17, 0x4c, 0xe2, 0x3b, 0x03, 0x7e, 0x96, 0x3c, 0x66, 0x8b, 0xe9, 0xba,
+  0x93, 0xcb, 0xfe, 0xbb, 0xbf, 0x52, 0x40, 0xbc, 0x6c, 0xba, 0x41, 0xbc, 0x81, 0x0e, 0x92, 0xba,
+  0xad, 0x84, 0xbb, 0x3c, 0xd7, 0x66, 0x12, 0xba, 0x63, 0x71, 0x8e, 0x3c, 0xc6, 0x6d, 0xf2, 0x3a,
+  0xce, 0x7f, 0x39, 0x3b, 0xe8, 0x67, 0xbb, 0xbb, 0xbe, 0x90, 0xad, 0xbb, 0xa1, 0x16, 0x84, 0xbb,
+  0xf1, 0x10, 0x8a, 0x3c, 0x4d, 0xf7, 0xe0, 0x3b, 0x39, 0x80, 0xf0, 0x3c, 0xfa, 0x44, 0xd4, 0xbb,
+  0xae, 0x37, 0xa2, 0xba, 0x59, 0x21, 0x0b, 0x3b, 0xdf, 0x6a, 0x3e, 0xbc, 0x70, 0x3a, 0x11, 0xbb,
+  0xe4, 0xc9, 0x8a, 0x3c, 0x33, 0x61, 0x8f, 0xba, 0x4c, 0x27, 0xc6, 0x3c, 0xfe, 0xed, 0x71, 0xbc,
+  0xf1, 0x25, 0x87, 0x39, 0x50, 0x34, 0xd1, 0xba, 0x07, 0xe1, 0x8d, 0xbc, 0x7b, 0x9f, 0x29, 0xbb,
+  0xbe, 0x51, 0xde, 0x3b, 0x17, 0x07, 0x32, 0xbb, 0x5b, 0x8f, 0x86, 0x3c, 0xd6, 0x5f, 0x17, 0xbb,
+  0x3b, 0x91, 0x08, 0x3c, 0xd6, 0x53, 0x36, 0xbb, 0xad, 0x8b, 0xb7, 0xb9, 0xb9, 0xf4, 0x84, 0x3b,
+  0xe4, 0x44, 0x81, 0x3c, 0x90, 0xbe, 0xbc, 0x3c, 0x05, 0x69, 0x11, 0x3c, 0xb7, 0x8c, 0xcd, 0x3a,
+  0xba, 0x95, 0xe1, 0xbb, 0x1b, 0xce, 0xaa, 0x3a, 0xfa, 0xdf, 0x84, 0xbb, 0x0e, 0xe3, 0xe4, 0x3b,
+  0x97, 0xf1, 0x1c, 0xbc, 0xf3, 0x50, 0xd0, 0x3b, 0xc8, 0xe2, 0x01, 0xbc, 0x3b, 0x43, 0xe4, 0x3b,
+  0x74, 0x47, 0xfe, 0x3b, 0x7a, 0xb0, 0xf7, 0x3b, 0x38, 0x3c, 0xe9, 0x3b, 0xce, 0x65, 0xa1, 0xbb,
+  0x15, 0xdf, 0x67, 0xbb, 0xcf, 0xfc, 0x67, 0x3c, 0xf2, 0x97, 0x85, 0xbb, 0x7f, 0xdb, 0x53, 0xbc,
+  0x63, 0x43, 0x82, 0x3b, 0xcd, 0x17, 0x3a, 0xbb, 0x03, 0xd0, 0x8e, 0x3b, 0xa4, 0xa9, 0x83, 0xb9,
+  0x66, 0xc1, 0x25, 0x35, 0x08, 0x1a, 0x28, 0x3c, 0x15, 0x6c, 0x9b, 0x3a, 0x5e, 0x90, 0xcd, 0x37,
+  0xab, 0x9c, 0x6d, 0x3b, 0xb8, 0x27, 0x9a, 0xba, 0x7a, 0x9e, 0x0d, 0xbb, 0xc8, 0xb2, 0xdb, 0x3b,
+  0xb4, 0x33, 0x21, 0x3c, 0xed, 0x52, 0x9c, 0x3c, 0x88, 0x45, 0x33, 0xbb, 0x20, 0xe8, 0x12, 0xbb,
+  0xe3, 0x3e, 0x14, 0x3c, 0x93, 0x5b, 0x2e, 0x3b, 0xe2, 0xf1, 0x1e, 0xbb, 0xe4, 0x24, 0x27, 0x3b,
+  0x08, 0x78, 0x9b, 0xbb, 0xf5, 0xa9, 0x02, 0x3c, 0xb5, 0x07, 0xa1, 0xbb, 0xfb, 0x5c, 0xb3, 0x3b,
+  0x92, 0x93, 0x34, 0x3b, 0x19, 0x92, 0x25, 0x3c, 0xdb, 0xa4, 0x70, 0xbc, 0x90, 0xc4, 0x0b, 0xb9,
+  0x26, 0x57, 0x34, 0xbc, 0xf7, 0xa8, 0xe7, 0x3b, 0x41, 0xfa, 0x71, 0xbc, 0xa9, 0xef, 0x62, 0x3c,
+  0x4f, 0xcd, 0x3b, 0x3c, 0x46, 0x15, 0xbe, 0xba, 0x4b, 0xd4, 0xa9, 0x3b, 0x30, 0xab, 0xe4, 0x3b,
+  0xce, 0x6f, 0x37, 0xba, 0xb1, 0xc0, 0xd8, 0xbb, 0xec, 0xa4, 0xab, 0xbb, 0x4f, 0x26, 0x9f, 0xba,
+  0x76, 0x6a, 0x1d, 0x3c, 0xdb, 0x1d, 0xf6, 0xb9, 0xe1, 0x9c, 0xc2, 0xbb, 0x0b, 0x45, 0x8f, 0xba,
+  0x15, 0x2e, 0x6a, 0xbc, 0xb7, 0xf9, 0x74, 0xbb, 0x91, 0x65, 0x20, 0x3c, 0x12, 0x0c, 0xb0, 0x3b,
+  0xce, 0x00, 0x27, 0xbc, 0xc9, 0x74, 0x66, 0x3b, 0x06, 0x95, 0xce, 0x3c, 0x9a, 0x51, 0x6d, 0xbc,
+  0xc1, 0x05, 0x28, 0xbc, 0x52, 0xc4, 0xaf, 0x3b, 0x3c, 0x46, 0x0c, 0x3b, 0xcd, 0x80, 0x85, 0x3c,
+  0xab, 0x59, 0x44, 0xba, 0x3c, 0x1a, 0xde, 0x3b, 0x28, 0xcf, 0x5f, 0x3c, 0xb1, 0xd7, 0xdf, 0xbb,
+  0x76, 0xe5, 0x8c, 0x3c, 0x19, 0x91, 0x02, 0x3c, 0xd6, 0xa1, 0xcc, 0xbc, 0x79, 0x33, 0x1b, 0xbc,
+  0x15, 0xdf, 0x92, 0x3c, 0xfd, 0xe0, 0x8f, 0xbb, 0x08, 0x35, 0xda, 0xb9, 0x52, 0x32, 0x50, 0xbb,
+  0x4e, 0xd0, 0x37, 0x3b, 0x71, 0xa1, 0x9f, 0x3c, 0xbc, 0x0c, 0x5f, 0xbc, 0xc2, 0x1c, 0x56, 0x3b,
+  0x5f, 0xa5, 0x5b, 0x3c, 0x4a, 0xee, 0x90, 0xbc, 0xf9, 0x62, 0x83, 0xbb, 0xb8, 0xc5, 0x62, 0x3c,
+  0x45, 0x71, 0x31, 0xbb, 0x2b, 0xc1, 0x04, 0x3d, 0xeb, 0xb6, 0xd5, 0xbb, 0x19, 0x1a, 0x22, 0x3a,
+  0xfc, 0x54, 0xf1, 0x3b, 0xf0, 0x03, 0x49, 0xbc, 0x42, 0xd3, 0x06, 0x3c, 0x9f, 0x4a, 0xc1, 0x3a,
+  0x6d, 0x16, 0x0f, 0xbc, 0x86, 0xa6, 0x33, 0x3c, 0xc1, 0x07, 0x4a, 0x3b, 0x30, 0xb7, 0x7e, 0xbc,
+  0x16, 0x62, 0xbf, 0x3b, 0xaa, 0x43, 0x9b, 0xbc, 0x35, 0x7a, 0x35, 0xbc, 0x87, 0x67, 0xd0, 0xba,
+  0x6d, 0xbf, 0x06, 0x3c, 0xcb, 0xb8, 0x83, 0xba, 0xe1, 0xeb, 0x4d, 0x3b, 0xde, 0x0b, 0x8b, 0xbc,
+  0x19, 0x36, 0x2e, 0xbc, 0x08, 0x9b, 0x8d, 0xb9, 0x40, 0xe3, 0x83, 0xbc, 0xd5, 0x8e, 0x88, 0xbc,
+  0x9b, 0x9c, 0x9b, 0x3b, 0x6f, 0x30, 0x94, 0x3b, 0x0a, 0xdd, 0xba, 0x3c, 0xaa, 0xa8, 0xdc, 0xbb,
+  0x42, 0xd4, 0x03, 0x3a, 0x2c, 0x9a, 0x59, 0xbc, 0x12, 0xe1, 0x7e, 0xbc, 0x57, 0x90, 0x26, 0xbc,
+  0x7a, 0xc3, 0xb1, 0x3c, 0x46, 0x8e, 0x09, 0x3c, 0x30, 0x99, 0xaf, 0x3c, 0x3f, 0xd0, 0x25, 0xbc,
+  0x7a, 0x27, 0xf8, 0xba, 0x4e, 0xa5, 0xfe, 0xbb, 0x26, 0x1f, 0x3f, 0xbc, 0x64, 0x24, 0x4c, 0xbb,
+  0x6c, 0x87, 0x71, 0x3c, 0xce, 0x36, 0x83, 0x3b, 0x64, 0xad, 0xf7, 0x3c, 0x39, 0x1b, 0x21, 0xbc,
+  0x4c, 0xd2, 0xe0, 0x3b, 0x1d, 0x02, 0x12, 0x3c, 0x2f, 0xe6, 0x56, 0xbb, 0xa3, 0x8a, 0xb7, 0x3b,
+  0xfd, 0xb9, 0x57, 0x3c, 0x79, 0xf7, 0x7e, 0x3a, 0x9e, 0xf3, 0x8f, 0x3c, 0x6b, 0x4b, 0x1a, 0xbc,
+  0x6c, 0x4a, 0x9b, 0xbb, 0x2f, 0x2a, 0x1d, 0x3b, 0xea, 0x4f, 0xc8, 0xbb, 0x4d, 0xeb, 0xb5, 0xbb,
+  0x53, 0x5e, 0x38, 0x3c, 0xdf, 0x02, 0x6c, 0x3b, 0x62, 0x76, 0x0f, 0x3c, 0x74, 0xef, 0x35, 0xbc,
+  0xa1, 0x0a, 0x0f, 0xbb, 0xe1, 0x72, 0xdb, 0xba, 0x11, 0x40, 0x63, 0xbb, 0xde, 0x0f, 0x73, 0x3b,
+  0x9d, 0xa2, 0x15, 0x3c, 0x59, 0xf6, 0x57, 0x3c, 0x8a, 0x6d, 0x83, 0x3b, 0xe9, 0x6f, 0x1a, 0xbc,
+  0xdc, 0xff, 0x92, 0xba, 0x31, 0x56, 0x6d, 0x3a, 0xf0, 0xec, 0xe3, 0xbb, 0x19, 0x38, 0x44, 0x3c,
+  0xad, 0xd1, 0xc5, 0xbb, 0x5d, 0x68, 0x63, 0x3c, 0xa8, 0x85, 0xe7, 0xbb, 0xb6, 0x65, 0x4e, 0x3b,
+  0x54, 0xeb, 0x08, 0x3c, 0x7c, 0xdb, 0x09, 0x3c, 0x01, 0x97, 0x40, 0xbb, 0x15, 0x1f, 0xd8, 0xbb,
+  0xee, 0x1b, 0x97, 0xbb, 0x61, 0x92, 0xc4, 0x3b, 0xd7, 0x08, 0xe5, 0xb9, 0x10, 0xab, 0x34, 0x3c,
+  0x77, 0x77, 0x9f, 0x3b, 0x20, 0xcf, 0x29, 0xbb, 0x57, 0x5a, 0x6f, 0x3c, 0xf3, 0x8e, 0x7a, 0xbb,
+  0xae, 0x91, 0x06, 0x3c, 0x93, 0xe6, 0x8d, 0x3c, 0xb7, 0xf5, 0x9a, 0xbb, 0xf1, 0x78, 0xeb, 0xba,
+  0x5f, 0x76, 0x40, 0xba, 0xfd, 0x72, 0x5f, 0x3b, 0xb0, 0xaf, 0x13, 0xbc, 0x1d, 0x33, 0x26, 0x3b,
+  0xed, 0x66, 0x5d, 0x3c, 0xb4, 0xf0, 0x81, 0x3c, 0xe1, 0x54, 0x5a, 0xba, 0x6f, 0x81, 0x98, 0xba,
+  0xed, 0xe7, 0x28, 0x3c, 0xe6, 0xa0, 0xca, 0x3b, 0xc2, 0x79, 0x81, 0x3b, 0x35, 0xcb, 0xee, 0x3b,
+  0xbe, 0x77, 0x8d, 0x3b, 0x78, 0xe8, 0xc6, 0x3c, 0xa5, 0x06, 0xc0, 0xbb, 0xb3, 0x57, 0x74, 0x3c,
+  0x47, 0x7b, 0x19, 0x3c, 0x9b, 0x06, 0xb7, 0x3b, 0xa5, 0x5b, 0x4f, 0xba, 0xe7, 0xd8, 0xaa, 0xbb,
+  0x7a, 0xec, 0x23, 0xbc, 0x51, 0xd8, 0xa2, 0x3c, 0x30, 0x94, 0x0d, 0xbc, 0x50, 0x08, 0xd3, 0xbb,
+  0xc0, 0x9f, 0x0f, 0x3c, 0x9d, 0x51, 0x42, 0x3c, 0xa6, 0x29, 0x19, 0xbc, 0x08, 0xab, 0x13, 0x3a,
+  0xbb, 0xf9, 0x38, 0x3b, 0xe1, 0x01, 0x92, 0xbb, 0x35, 0x10, 0x1e, 0x3b, 0x75, 0x07, 0x85, 0x3c,
+  0xcc, 0x82, 0xad, 0x3b, 0x75, 0x49, 0x22, 0xbc, 0x1d, 0x0d, 0x25, 0xbc, 0xd0, 0x31, 0x47, 0x3b,
+  0xdf, 0xe3, 0x6f, 0xbc, 0x58, 0x45, 0xb4, 0xbb, 0xe1, 0x66, 0xc5, 0x3b, 0xdd, 0x65, 0x09, 0xbc,
+  0xa4, 0x01, 0x0e, 0xbb, 0x11, 0x4a, 0x96, 0x3b, 0x10, 0x5b, 0xbf, 0x3c, 0x9b, 0x50, 0xa6, 0xb9,
+  0x37, 0x7b, 0x64, 0xbc, 0xd0, 0x0e, 0x2d, 0xbc, 0x1c, 0x91, 0x3e, 0x3c, 0x21, 0xd6, 0x90, 0x3b,
+  0x99, 0x6a, 0x62, 0xbc, 0x46, 0xd5, 0x66, 0x3b, 0x5a, 0xb0, 0x4c, 0x3c, 0x82, 0xd8, 0x6b, 0xbb,
+  0x74, 0xd0, 0x26, 0x3c, 0x2c, 0x6b, 0xdd, 0xba, 0x84, 0x1e, 0xcd, 0xbc, 0xce, 0xc1, 0xd5, 0xbb,
+  0x7a, 0xb9, 0xa3, 0x3c, 0x22, 0xb5, 0x53, 0xbc, 0x96, 0x09, 0xd0, 0x39, 0x2b, 0x69, 0x2b, 0xbc,
+  0x93, 0xd9, 0xfe, 0x3b, 0xe2, 0x2e, 0x71, 0x3c, 0xd5, 0x5c, 0x99, 0xbc, 0xb2, 0x5b, 0x7a, 0x3a,
+  0x1f, 0x91, 0x11, 0x3c, 0x0e, 0x6a, 0x97, 0xbb, 0x73, 0x60, 0x2c, 0x3c, 0x24, 0xee, 0x1e, 0x3a,
+  0xd5, 0xe6, 0xdc, 0x3b, 0x54, 0x65, 0xeb, 0x3c, 0xf3, 0xd5, 0x8c, 0x3a, 0x26, 0x0b, 0x35, 0x3c,
+  0xbc, 0xc4, 0xec, 0x3a, 0x9e, 0x10, 0xf0, 0xbb, 0xe9, 0x52, 0x90, 0xbb, 0x61, 0x51, 0x5a, 0x3a,
+  0x0d, 0x8c, 0x53, 0x3b, 0x0d, 0xbb, 0xbc, 0x3b, 0xe4, 0x2a, 0x5c, 0x3a, 0x74, 0x32, 0x74, 0x3c,
+  0x35, 0x21, 0xb8, 0xbb, 0x31, 0x71, 0x4a, 0xbc, 0x08, 0xae, 0xff, 0xbb, 0xc5, 0x89, 0x32, 0xbc,
+  0x9e, 0x89, 0x2b, 0x3b, 0x2c, 0x79, 0xc3, 0xbb, 0xf7, 0xe2, 0xd6, 0xba, 0x43, 0x1d, 0x59, 0xbc,
+  0xf3, 0x0c, 0x93, 0xbb, 0x40, 0x6d, 0x35, 0xbc, 0x47, 0x9e, 0x01, 0xbb, 0x9f, 0xb9, 0x04, 0xbc,
+  0xb6, 0x2f, 0x43, 0x3b, 0x08, 0x65, 0x84, 0x3a, 0xab, 0x6b, 0x95, 0x3c, 0x08, 0x5d, 0xf1, 0xbb,
+  0xf9, 0x43, 0xea, 0xbb, 0x4f, 0x68, 0x27, 0xbc, 0xbd, 0x83, 0x30, 0xbc, 0xb1, 0xf5, 0x4a, 0xbc,
+  0xbd, 0xf0, 0xbc, 0x3c, 0xa3, 0x44, 0x5a, 0x3c, 0x5f, 0xc1, 0xda, 0x3c, 0x16, 0xdb, 0xf1, 0x3b,
+  0xff, 0x29, 0xb0, 0x3a, 0x93, 0x3f, 0xe7, 0xbb, 0x8d, 0x5a, 0x01, 0x3c, 0x5e, 0xb3, 0x0b, 0x3b,
+  0x08, 0x5f, 0xba, 0x3c, 0xfb, 0x51, 0x47, 0x3c, 0xa3, 0xa1, 0x72, 0x3c, 0xfa, 0xf8, 0x0f, 0xbb,
+  0xd8, 0x25, 0xf6, 0xba, 0x14, 0x85, 0x20, 0x3b, 0x92, 0xd7, 0x6e, 0xbc, 0x13, 0x52, 0x97, 0xba,
+  0x1a, 0x9a, 0x3d, 0x3c, 0xeb, 0x79, 0xd5, 0xbb, 0xe4, 0xd0, 0x5e, 0x3c, 0xd3, 0x66, 0xd7, 0xbb,
+  0x65, 0xb7, 0xa7, 0xbb, 0x09, 0x85, 0xd8, 0x3b, 0x97, 0xff, 0xda, 0xbb, 0x6d, 0x23, 0x29, 0x3b,
+  0x79, 0x40, 0x64, 0x3c, 0x63, 0x0a, 0x9b, 0x3c, 0x5f, 0xc9, 0x0e, 0x3c, 0x43, 0x57, 0x00, 0xbc,
+  0x70, 0x61, 0xfb, 0xbb, 0x48, 0x5d, 0xea, 0x3b, 0x54, 0x93, 0x99, 0x3b, 0x27, 0xdc, 0xc1, 0x3a,
+  0x0a, 0xe4, 0x4a, 0x3c, 0x81, 0x95, 0x49, 0x3c, 0x38, 0xc2, 0xca, 0xbb, 0xd9, 0x4a, 0x7e, 0x3b,
+  0x69, 0xe8, 0x13, 0x3c, 0xc9, 0xf2, 0x05, 0xbc, 0x1a, 0xd4, 0xa8, 0xbb, 0x4e, 0xd7, 0x5e, 0x3c,
+  0x2b, 0x87, 0x4a, 0x3b, 0x31, 0xc8, 0x0a, 0xb9, 0x16, 0x5b, 0x0f, 0xbc, 0x8f, 0xdb, 0x09, 0x3c,
+  0xd8, 0x71, 0x60, 0x3c, 0x37, 0xf7, 0xa7, 0x3a, 0xc0, 0x39, 0x3d, 0x3c, 0xdd, 0x3e, 0x34, 0x3b,
+  0x60, 0x99, 0xa0, 0x3b, 0xea, 0xa8, 0xe2, 0x3b, 0x05, 0x0b, 0xfa, 0xbb, 0x6f, 0x85, 0x24, 0xbc,
+  0x55, 0x1a, 0x48, 0xbb, 0x24, 0x2f, 0xc7, 0x3b, 0xd3, 0x57, 0x79, 0x3b, 0xc2, 0x83, 0x8a, 0xb9,
+  0x10, 0x91, 0x44, 0x3b, 0x6b, 0xf6, 0x8b, 0x3c, 0x2d, 0x6b, 0xe8, 0x3b, 0xf7, 0x1a, 0xaf, 0x3a,
+  0x53, 0x71, 0xa1, 0x3b, 0xe4, 0xe5, 0xe5, 0x3b, 0x76, 0xbd, 0xdd, 0x3b, 0xdb, 0x0f, 0x16, 0xba,
+  0xfd, 0x22, 0x7d, 0x3b, 0x1d, 0x40, 0xc8, 0x3c, 0x51, 0x13, 0xe4, 0xba, 0x30, 0xa5, 0x6d, 0xb8,
+  0xa5, 0x86, 0xd4, 0x3b, 0xed, 0x07, 0x0f, 0xbb, 0x43, 0x0a, 0x17, 0xbb, 0xe7, 0x77, 0x16, 0x3b,
+  0x12, 0xa0, 0x66, 0x3b, 0x97, 0xc3, 0x40, 0x3c, 0xee, 0xc2, 0x3f, 0xbc, 0x9b, 0xb8, 0x44, 0xbc,
+  0xb4, 0x80, 0x0d, 0x3c, 0x56, 0xfd, 0x01, 0x3c, 0x93, 0x06, 0x26, 0x3c, 0xea, 0xaa, 0x93, 0xbb,
+  0x59, 0xb9, 0xc0, 0x3b, 0x3c, 0xa3, 0x4c, 0x3c, 0x32, 0xc4, 0x9f, 0xbb, 0xc3, 0x27, 0x9c, 0x3c,
+  0x52, 0x1a, 0x75, 0x3b, 0x0d, 0xd5, 0x21, 0xbc, 0x00, 0xbf, 0xdc, 0xbb, 0xce, 0x39, 0x92, 0x3c,
+  0x30, 0xa1, 0x0c, 0xbc, 0x56, 0xf2, 0x37, 0x3a, 0x87, 0x98, 0xc1, 0x3a, 0x50, 0xa6, 0x1b, 0xbc,
+  0xfa, 0x57, 0x12, 0xbc, 0x91, 0xd1, 0x2d, 0xbb, 0x09, 0xef, 0xf3, 0xbb, 0x04, 0xdf, 0xdd, 0xbb,
+  0xa9, 0xea, 0x04, 0xbc, 0x16, 0x6f, 0xf0, 0xbb, 0x3c, 0x14, 0x8d, 0x3a, 0xef, 0x51, 0x8a, 0x3c,
+  0xf5, 0xbc, 0x03, 0xbc, 0xde, 0x09, 0x2f, 0x3a, 0x2d, 0x8c, 0xfe, 0x3c, 0xab, 0xf6, 0x32, 0xbb,
+  0x25, 0x70, 0xb7, 0xbb, 0x73, 0x16, 0xc3, 0xbb, 0x72, 0xf5, 0x25, 0x3c, 0x22, 0x9f, 0xb1, 0xbb,
+  0xa7, 0xf2, 0xae, 0xbb, 0x52, 0xd1, 0x68, 0xbb, 0x3e, 0x6e, 0x9b, 0x3c, 0xf7, 0x27, 0x86, 0xbc,
+  0x72, 0x75, 0x77, 0x3c, 0xed, 0xc8, 0x98, 0xbb, 0x67, 0x51, 0xdf, 0xbc, 0xa9, 0x77, 0x83, 0xbc,
+  0xd2, 0x04, 0x83, 0x3c, 0x31, 0x9d, 0x58, 0xbc, 0xd9, 0xb9, 0x8a, 0xba, 0xbd, 0x3c, 0x1d, 0xbc,
+  0x2a, 0x57, 0xc7, 0x3b, 0xff, 0xd3, 0xad, 0x3c, 0x74, 0x9c, 0x0a, 0xbc, 0xa2, 0xd8, 0x8e, 0x3c,
+  0x8c, 0x98, 0xff, 0x3b, 0x89, 0xfa, 0xf5, 0xbb, 0xaf, 0xa4, 0x65, 0x3c, 0x30, 0x2e, 0x0f, 0x3c,
+  0x8a, 0xce, 0xe2, 0x3b, 0xf1, 0xc6, 0xa7, 0x3c, 0x01, 0x27, 0x31, 0x3b, 0xe7, 0x0d, 0x75, 0xbb,
+  0xda, 0x55, 0xba, 0xba, 0x33, 0x5a, 0x00, 0x3a, 0xe5, 0x65, 0x71, 0x3b, 0x62, 0xc6, 0x06, 0xbc,
+  0xef, 0xcd, 0xb0, 0xba, 0x56, 0xad, 0xe6, 0x3b, 0x1e, 0x54, 0x26, 0xbc, 0x77, 0xf1, 0x17, 0xbc,
+  0x70, 0x41, 0x6f, 0xbc, 0x57, 0xa6, 0x80, 0xbc, 0xae, 0x88, 0xef, 0xbb, 0x9b, 0xce, 0x56, 0xbc,
+  0x80, 0x07, 0x2f, 0x3c, 0xbd, 0x88, 0x60, 0xbc, 0x3d, 0xde, 0x84, 0x3b, 0x8e, 0xaf, 0x05, 0xbb,
+  0x6d, 0xde, 0x9b, 0xbb, 0xe6, 0x91, 0xa4, 0xbb, 0xa0, 0x8f, 0x9d, 0xbc, 0x5d, 0xed, 0xf7, 0xbb,
+  0x68, 0x7a, 0x8a, 0x3c, 0x39, 0x82, 0xdf, 0xba, 0x15, 0x98, 0xa9, 0x3c, 0x3d, 0x67, 0xb2, 0xbb,
+  0x73, 0x2b, 0x8b, 0xb9, 0x2d, 0x72, 0x44, 0xbc, 0x20, 0x56, 0xb5, 0xbb, 0xcb, 0x70, 0x35, 0xbc,
+  0xb3, 0x28, 0xa0, 0x3c, 0x50, 0x80, 0x8c, 0x3b, 0xfd, 0x9f, 0xa7, 0x3c, 0x9f, 0x06, 0xbf, 0x3b,
+  0x7a, 0xee, 0xf3, 0xb9, 0x0a, 0x44, 0x84, 0x3b, 0x35, 0x64, 0xa9, 0x3b, 0x92, 0xa2, 0x17, 0xbc,
+  0x1b, 0xe8, 0xa0, 0x3c, 0x69, 0x7b, 0x1e, 0x3c, 0xf9, 0x01, 0xea, 0x3c, 0x66, 0x0d, 0xae, 0xbb,
+  0x2e, 0xfc, 0x23, 0xbc, 0x46, 0x5e, 0x3e, 0x3c, 0x15, 0xf4, 0x9f, 0xbb, 0x91, 0xfe, 0xf9, 0x3b,
+  0x24, 0x42, 0x85, 0x3c, 0xac, 0xc1, 0x69, 0xbb, 0x10, 0x3a, 0x34, 0x3c, 0x12, 0xf2, 0x87, 0x3c,
+  0xbf, 0x77, 0x61, 0x3a, 0xd2, 0x0b, 0xbd, 0x3b, 0x1e, 0xf9, 0x96, 0xbb, 0x06, 0x27, 0x40, 0xbb,
+  0x5b, 0x80, 0xb7, 0x3c, 0xd9, 0x6c, 0x91, 0xba, 0xb5, 0x83, 0x6c, 0x3c, 0x0a, 0xde, 0x24, 0xbc,
+  0xb7, 0xec, 0xba, 0xba, 0xcf, 0xa3, 0xb2, 0x3a, 0xa3, 0x25, 0xfa, 0xbb, 0x36, 0x3a, 0x54, 0x3b,
+  0x1b, 0xf3, 0x5e, 0x3c, 0x6c, 0xa1, 0x85, 0x3b, 0xf0, 0x95, 0x32, 0xbb, 0xe8, 0x8c, 0x73, 0xbc,
+  0xa2, 0x11, 0xcf, 0x3b, 0x9b, 0x18, 0xe8, 0x3b, 0x1e, 0x00, 0x39, 0x3c, 0xe4, 0x1e, 0xa4, 0x3a,
+  0xa2, 0xb1, 0x97, 0xba, 0x94, 0x12, 0xfd, 0xbb, 0x17, 0xab, 0x1b, 0xbc, 0x36, 0xe8, 0xaa, 0x3b,
+  0x3b, 0x38, 0xff, 0x3b, 0xde, 0xa2, 0x55, 0x3a, 0x18, 0x75, 0x1a, 0x3c, 0x2c, 0x01, 0x3b, 0x3b,
+  0xf8, 0x6f, 0x01, 0xbc, 0xce, 0xeb, 0x94, 0xbb, 0xe5, 0x76, 0x30, 0xbc, 0x5d, 0x4c, 0xb0, 0x3b,
+  0x8e, 0x6b, 0x28, 0x3b, 0x59, 0xe3, 0x95, 0xba, 0x5f, 0x97, 0x70, 0x3c, 0x55, 0x00, 0x47, 0x3b,
+  0x8c, 0x36, 0xe1, 0x3b, 0x53, 0xcc, 0x5f, 0x3b, 0x74, 0x0b, 0x17, 0xb9, 0xd1, 0x79, 0x71, 0xbc,
+  0x6b, 0xb2, 0xd7, 0x39, 0x20, 0x91, 0x0d, 0x3a, 0x28, 0xd3, 0x63, 0x3b, 0x16, 0x75, 0x0d, 0x3b,
+  0x8a, 0x25, 0x8f, 0x3b, 0x8e, 0xb1, 0x90, 0xbb, 0xe8, 0x81, 0x05, 0xbc, 0x34, 0xb1, 0x24, 0x3c,
+  0x7f, 0xf5, 0x91, 0xbb, 0xc7, 0xdc, 0x10, 0x3c, 0x76, 0x77, 0x2c, 0x3b, 0xec, 0x46, 0xbf, 0x3a,
+  0xbc, 0xed, 0x0b, 0x3b, 0x72, 0x98, 0x65, 0x3c, 0x1f, 0x13, 0x01, 0x3b, 0x8e, 0x0c, 0xfb, 0x3b,
+  0x00, 0x59, 0x0a, 0x3c, 0x02, 0xaf, 0x30, 0x3b, 0x85, 0xa7, 0x14, 0x3b, 0x6e, 0x06, 0x3b, 0xb9,
+  0xda, 0xb2, 0x79, 0x3b, 0x73, 0x48, 0x3b, 0x3c, 0x3d, 0x00, 0xa4, 0xbc, 0x4f, 0xae, 0xe1, 0xbb,
+  0xdb, 0x1d, 0x2d, 0xbb, 0x1d, 0xf4, 0x56, 0x3b, 0x8f, 0xec, 0x76, 0xbb, 0x5d, 0xfe, 0x0e, 0x3c,
+  0xcb, 0x18, 0x4f, 0x3b, 0xf5, 0x9c, 0xb9, 0xba, 0xd3, 0x36, 0x89, 0xbc, 0xcf, 0x58, 0xab, 0x38,
+  0x4d, 0x18, 0xe5, 0x3a, 0xee, 0x82, 0x15, 0xbb, 0x3b, 0xb2, 0x83, 0xbb, 0x55, 0x97, 0x8b, 0x3b,
+  0xa5, 0x9e, 0xcd, 0xbb, 0xfc, 0x7f, 0x94, 0x3b, 0xc1, 0x46, 0x10, 0xbb, 0x4b, 0x05, 0xfa, 0xbb,
+  0xd0, 0x94, 0x3b, 0xbc, 0xff, 0x27, 0x89, 0x3b, 0x59, 0xa7, 0x99, 0x3c, 0xf1, 0xc8, 0xa5, 0xbb,
+  0x67, 0xcd, 0x6c, 0xbb, 0xb1, 0x30, 0x3f, 0x3b, 0x6b, 0xd8, 0x90, 0x39, 0x26, 0x30, 0x90, 0x3a,
+  0x59, 0xd5, 0xde, 0x3b, 0xe7, 0x7a, 0x95, 0xbb, 0xe0, 0x71, 0x72, 0x3c, 0x3a, 0x57, 0x3a, 0xbb,
+  0x61, 0x3b, 0x9f, 0x3c, 0xae, 0x15, 0x82, 0xbb, 0x76, 0x3e, 0xa6, 0xbc, 0x5d, 0x69, 0xbb, 0x39,
+  0xbe, 0x3d, 0x85, 0x3c, 0xa4, 0x63, 0x7a, 0xbb, 0xf4, 0x1e, 0x65, 0x3c, 0xe9, 0x2f, 0x62, 0xbc,
+  0x06, 0x42, 0x4d, 0x3c, 0xfd, 0xde, 0xdd, 0x3c, 0x1f, 0xa7, 0xa4, 0x3b, 0xdb, 0x69, 0xcb, 0x3b,
+  0xd9, 0x08, 0x41, 0x3c, 0x89, 0x59, 0xaf, 0xbb, 0x5a, 0xd3, 0x0b, 0x3c, 0xfd, 0xeb, 0x22, 0xbb,
+  0x61, 0xa8, 0x62, 0x3c, 0x5c, 0x06, 0xa3, 0x3c, 0x05, 0x80, 0xd9, 0x3a, 0x8c, 0x66, 0xa3, 0xbb,
+  0x81, 0xc4, 0xc3, 0x3b, 0x87, 0x37, 0xdf, 0xbb, 0x63, 0x86, 0xb6, 0xba, 0xf0, 0x6d, 0x1a, 0xbc,
+  0xb2, 0x57, 0x3c, 0x3c, 0xa5, 0xa4, 0x11, 0x3c, 0x0a, 0x0f, 0x55, 0xba, 0x9d, 0x8d, 0x4c, 0x3c,
+  0xb7, 0xba, 0x38, 0xbc, 0x8a, 0x94, 0x89, 0xbc, 0xfe, 0x3a, 0xf4, 0x39, 0x17, 0x43, 0x7e, 0xbb,
+  0x13, 0x2c, 0xbc, 0x3c, 0x86, 0xbf, 0x3a, 0x3a, 0x42, 0x66, 0x83, 0xbb, 0x02, 0x50, 0x5b, 0xba,
+  0x0d, 0xe6, 0x59, 0xbc, 0x6a, 0x65, 0x43, 0xbc, 0x02, 0x35, 0x19, 0xba, 0x55, 0x4d, 0x21, 0xbc,
+  0x9a, 0x57, 0x88, 0x3c, 0x10, 0xd9, 0x32, 0xbb, 0xb5, 0xa6, 0xab, 0x3c, 0xc0, 0xe3, 0xf3, 0xbb,
+  0x39, 0xc3, 0x00, 0xbb, 0x97, 0xdf, 0x45, 0xbc, 0x9b, 0xd7, 0xa1, 0x3b, 0x6a, 0x1c, 0x79, 0xbb,
+  0x29, 0x4e, 0x39, 0x3c, 0x6f, 0x5a, 0xf6, 0x3b, 0xaf, 0xef, 0x88, 0x3c, 0xe0, 0x4f, 0x06, 0x3a,
+  0x8a, 0x95, 0x38, 0xbb, 0xed, 0x6d, 0x3d, 0xbc, 0x4b, 0x88, 0xe9, 0xbb, 0xd0, 0x45, 0x3a, 0xbb,
+  0xa2, 0xb0, 0x5f, 0x3c, 0xda, 0xf1, 0xdf, 0x3b, 0xa6, 0x93, 0x30, 0x3c, 0xbb, 0x58, 0x46, 0xbc,
+  0x72, 0x45, 0x5b, 0xbc, 0x49, 0xc8, 0xa9, 0xbb, 0x0b, 0x73, 0x55, 0xbb, 0x56, 0x9a, 0xb6, 0x3b,
+  0x0b, 0xf4, 0x37, 0x3c, 0x4f, 0x79, 0xb6, 0x3b, 0xb6, 0x99, 0x15, 0x3c, 0x06, 0xbd, 0x3b, 0xbc,
+  0x0e, 0xef, 0x6f, 0xbc, 0x4b, 0x9f, 0x31, 0x3c, 0x78, 0x93, 0x40, 0x3c, 0xbc, 0xa0, 0x18, 0x3b,
+  0x96, 0x63, 0xaf, 0x3b, 0x3a, 0x03, 0xef, 0x3b, 0xd9, 0x68, 0x8a, 0x3c, 0xde, 0x4b, 0x17, 0xbc,
+  0xc2, 0x8a, 0x32, 0xba, 0x4e, 0x95, 0x4a, 0xba, 0x7f, 0x5d, 0x7d, 0xbc, 0xaa, 0xf9, 0x19, 0x3c,
+  0xdf, 0x90, 0x2e, 0x3c, 0x3a, 0x77, 0x2e, 0xb9, 0x4b, 0x7a, 0xcf, 0x3b, 0xb8, 0xd1, 0x5e, 0x3c,
+  0x7d, 0x3b, 0xa9, 0x3b, 0x50, 0xb1, 0xb1, 0xbb, 0xc8, 0x84, 0x15, 0xbb, 0x22, 0x26, 0x3a, 0x3c,
+  0x92, 0xe6, 0x0f, 0xbc, 0x8e, 0x6a, 0xf4, 0xb9, 0x10, 0xfc, 0x1a, 0xba, 0x6f, 0x70, 0xc4, 0xbb,
+  0x63, 0x53, 0x3e, 0x3c, 0xd4, 0x2b, 0xc3, 0x3b, 0x24, 0xbb, 0x1f, 0x3b, 0x78, 0x83, 0x49, 0xbb,
+  0x1a, 0x8d, 0x96, 0xbb, 0x4a, 0x51, 0x64, 0xba, 0x02, 0x4b, 0x70, 0xba, 0x8b, 0x39, 0x7a, 0xbb,
+  0x39, 0xc7, 0x7b, 0xbb, 0x75, 0xb3, 0x8e, 0x3b, 0xf2, 0xc2, 0x07, 0xbc, 0x15, 0x96, 0x81, 0xbb,
+  0x2b, 0xc3, 0xda, 0x3b, 0x41, 0xfa, 0xf5, 0xbb, 0x9d, 0xc5, 0x3a, 0x39, 0xa0, 0xfb, 0x75, 0xbb,
+  0xf4, 0xb5, 0xba, 0x3b, 0xa4, 0xf9, 0x80, 0xbb, 0x2e, 0xea, 0x97, 0xbb, 0xaa, 0x4a, 0x5f, 0x3b,
+  0xcd, 0xe2, 0x2f, 0x3c, 0x6b, 0xa8, 0x07, 0x3c, 0x69, 0x1a, 0x7b, 0xbb, 0x50, 0x0a, 0x2a, 0xbc,
+  0x95, 0x76, 0x27, 0xba, 0x87, 0x23, 0xaa, 0xb9, 0xc8, 0x8f, 0x12, 0x3a, 0xf2, 0x6a, 0x7c, 0x3c,
+  0xad, 0xbb, 0x62, 0x3b, 0x12, 0x6e, 0x79, 0x3b, 0x64, 0xc4, 0xb0, 0xba, 0x78, 0x6e, 0x5f, 0x3c,
+  0x0b, 0x76, 0x0c, 0xbb, 0x00, 0x5c, 0x37, 0x3b, 0xe8, 0x90, 0x15, 0xbc, 0xc5, 0x29, 0xc5, 0x3b,
+  0x58, 0x74, 0x73, 0x3b, 0xae, 0x0a, 0x21, 0x3c, 0xf3, 0xb3, 0xf8, 0xbb, 0xdd, 0xf0, 0x91, 0x3c,
+  0x9f, 0x6a, 0xc1, 0x39, 0xa2, 0x49, 0x54, 0x3c, 0xa1, 0x6d, 0xc8, 0xb8, 0x7a, 0x91, 0x59, 0x3a,
+  0x9e, 0x90, 0x92, 0xba, 0x1e, 0x02, 0x22, 0x3a, 0x11, 0x54, 0x0f, 0x3b, 0xa7, 0x28, 0xe9, 0x39,
+  0x68, 0x34, 0xb4, 0xba, 0x38, 0x8f, 0xf0, 0xbb, 0xe5, 0x68, 0x57, 0xbc, 0x95, 0x0c, 0xba, 0x3b,
+  0x61, 0x29, 0x58, 0xbc, 0x59, 0x11, 0x72, 0xbc, 0xd8, 0x27, 0xff, 0xbb, 0xdc, 0x5f, 0x48, 0xbb,
+  0x73, 0xca, 0x0a, 0xbc, 0xde, 0xc1, 0xd7, 0x3b, 0x56, 0x40, 0xd0, 0x3c, 0xf0, 0x1a, 0x0e, 0xbc,
+  0x91, 0x8c, 0x25, 0x3c, 0xb5, 0x92, 0x07, 0xbc, 0x61, 0x7f, 0x95, 0x3b, 0xaf, 0x14, 0x5d, 0xbb,
+  0x7c, 0x70, 0xb0, 0x39, 0x42, 0xbe, 0xa7, 0xbb, 0xe7, 0x58, 0x74, 0x3c, 0xbf, 0xc2, 0x22, 0x3b,
+  0x67, 0x33, 0x70, 0x3c, 0xfe, 0x26, 0xd1, 0x3b, 0x9c, 0xd7, 0x74, 0xbc, 0xfa, 0x1f, 0xbc, 0xbb,
+  0x77, 0x97, 0xd2, 0xb9, 0xaa, 0xae, 0xab, 0xbb, 0x46, 0xe7, 0x88, 0x3c, 0x32, 0x79, 0x8f, 0x3a,
+  0x42, 0xe6, 0x3d, 0x3c, 0x89, 0x71, 0xbb, 0x3c, 0x44, 0x82, 0xee, 0xba, 0x38, 0xe3, 0xfd, 0xbb,
+  0xe4, 0xd6, 0xc4, 0x3b, 0x00, 0x0d, 0x08, 0x3b, 0xdc, 0x0e, 0xc8, 0x3b, 0x24, 0xb3, 0x3b, 0x3b,
+  0xf3, 0xd6, 0xa0, 0x3c, 0x8e, 0x2f, 0x60, 0x3c, 0xee, 0x36, 0x53, 0xbb, 0x55, 0xe1, 0x7b, 0x3b,
+  0x5b, 0x43, 0x3b, 0x3b, 0xa6, 0x40, 0x54, 0xbc, 0x7c, 0x51, 0x18, 0x3c, 0x72, 0x2e, 0x9f, 0xba,
+  0x22, 0x56, 0xd0, 0x3b, 0x6c, 0x30, 0x93, 0x3c, 0x50, 0x14, 0x08, 0xbc, 0x77, 0xdc, 0x91, 0x3b,
+  0xb7, 0x35, 0x8e, 0xbc, 0xaf, 0x0a, 0xd8, 0xbb, 0x9d, 0x6a, 0x11, 0x3b, 0x04, 0xbf, 0x80, 0xbc,
+  0xb4, 0xff, 0xc1, 0x3b, 0x3c, 0x10, 0xa1, 0xbb, 0xaf, 0xfc, 0xd2, 0xbb, 0x75, 0x4e, 0x98, 0xbc,
+  0x09, 0xdd, 0x84, 0xbb, 0xcf, 0x8b, 0x7f, 0x3b, 0xa3, 0x5c, 0x08, 0xbc, 0xfa, 0xa3, 0x23, 0xbc,
+  0xe7, 0x13, 0xee, 0x3b, 0x2e, 0xb9, 0x60, 0xbb, 0xe4, 0x0b, 0xe5, 0x3c, 0x81, 0x20, 0xcd, 0x3a,
+  0xda, 0xc6, 0x2e, 0xba, 0x70, 0xd0, 0x78, 0xbc, 0x94, 0xe2, 0x8c, 0xbb, 0x58, 0xb4, 0xf8, 0xbb,
+  0x51, 0x7a, 0x27, 0x3c, 0xc7, 0x5b, 0x0e, 0x3c, 0xef, 0x3b, 0xff, 0x3c, 0x6a, 0x95, 0xb0, 0x3b,
+  0x17, 0xf7, 0xe5, 0xbb, 0xbc, 0xf5, 0xf8, 0x3a, 0x6f, 0x27, 0x06, 0x3b, 0xc6, 0x87, 0x6a, 0xbc,
+  0xc4, 0xd9, 0xd3, 0x3b, 0x58, 0xf0, 0xb1, 0x3b, 0xea, 0xc9, 0xad, 0x3c, 0xdf, 0xe9, 0xa3, 0x3a,
+  0xc6, 0x9c, 0x2b, 0xbc, 0x6f, 0x8f, 0x4a, 0x3a, 0x63, 0x2b, 0x26, 0xbb, 0xa4, 0xf9, 0x40, 0xbc,
+  0x20, 0xb0, 0x7b, 0x3b, 0xb3, 0xeb, 0x33, 0xbc, 0x51, 0x11, 0x87, 0x3c, 0x1d, 0x33, 0xc7, 0xbb,
+  0x75, 0x66, 0xdd, 0xbb, 0x0d, 0x0c, 0x5d, 0x3c, 0xab, 0xe9, 0x47, 0xbb, 0x0b, 0x77, 0xcd, 0xbb,
+  0x59, 0x33, 0x04, 0x3c, 0xad, 0x56, 0xf3, 0x3a, 0x97, 0x43, 0x75, 0x3c, 0xa0, 0x92, 0xa8, 0xbb,
+  0xb6, 0x4d, 0x86, 0x3a, 0xaf, 0xc7, 0xe3, 0x3b, 0x76, 0x69, 0x49, 0x3c, 0x79, 0x1b, 0x71, 0x3c,
+  0xce, 0xd4, 0x8c, 0x3c, 0x97, 0x0f, 0xb1, 0x3b, 0x8a, 0x5d, 0x47, 0x3b, 0xcd, 0x84, 0x73, 0x3c,
+  0x0e, 0x34, 0xc8, 0xbb, 0x60, 0xed, 0x3f, 0x3b, 0x79, 0x9f, 0x77, 0xb9, 0x41, 0x0a, 0x40, 0x3a,
+  0x27, 0x72, 0x3c, 0xbc, 0xbc, 0x35, 0x9f, 0xbb, 0xcd, 0x53, 0xc3, 0xbb, 0x25, 0xb0, 0x3e, 0xbc,
+  0xb5, 0x8b, 0x60, 0x3b, 0x2f, 0x6d, 0xb5, 0x3c, 0x6c, 0xdc, 0x25, 0xbb, 0x1c, 0x1a, 0x7d, 0xbb,
+  0xf0, 0xde, 0xf7, 0x3b, 0x51, 0xcd, 0x8d, 0x3b, 0x1d, 0xd0, 0xfd, 0xbb, 0xa5, 0x3b, 0xdd, 0x3b,
+  0x4a, 0x39, 0x83, 0xb9, 0x55, 0x4e, 0x62, 0xba, 0xa3, 0x32, 0x5d, 0x3c, 0x78, 0xcb, 0x1d, 0x3c,
+  0xaa, 0xe3, 0x31, 0x3c, 0x8e, 0xed, 0x47, 0x3b, 0x84, 0xa5, 0x6e, 0xbc, 0xa4, 0xae, 0xf1, 0xbb,
+  0x6d, 0xaf, 0x31, 0xbb, 0x12, 0x89, 0x1d, 0x3a, 0x26, 0x65, 0x08, 0x3c, 0xc3, 0x46, 0x17, 0x3c,
+  0xc7, 0xef, 0x0c, 0x3c, 0xc2, 0x26, 0x9f, 0x3c, 0x41, 0x74, 0xf0, 0xbb, 0xd1, 0x0e, 0xe9, 0x3b,
+  0x00, 0x89, 0x73, 0x3c, 0x91, 0x46, 0x46, 0xbb, 0x98, 0xbf, 0xa2, 0xba, 0xf7, 0x6c, 0xb6, 0xba,
+  0x9c, 0xb0, 0x3d, 0x3a, 0x9b, 0xeb, 0x60, 0x3b, 0x06, 0xc4, 0xe0, 0x3b, 0xa2, 0xe1, 0x10, 0xbb,
+  0x0c, 0x6c, 0xd6, 0x3b, 0x7b, 0xb9, 0xff, 0x3a, 0xfe, 0xcd, 0x16, 0x3a, 0x06, 0x88, 0x23, 0x3a,
+  0x6a, 0x8d, 0x16, 0xbc, 0xba, 0xdc, 0x85, 0xba, 0xac, 0x15, 0x87, 0xbc, 0xc1, 0x46, 0xa7, 0xba,
+  0x2d, 0x90, 0x79, 0x3b, 0x8a, 0x75, 0x06, 0xbc, 0x67, 0x6d, 0xa3, 0xbb, 0xa4, 0x87, 0x9a, 0x3b,
+  0xbf, 0x34, 0x38, 0xba, 0x21, 0x23, 0xf2, 0x3b, 0x5a, 0xc3, 0x46, 0xbc, 0x1a, 0x80, 0xdf, 0xbb,
+  0x70, 0xe5, 0xe6, 0x3b, 0x71, 0x1b, 0x4c, 0x3a, 0x6e, 0xb0, 0x2b, 0xbc, 0x4f, 0x2b, 0xfc, 0x3b,
+  0x87, 0x28, 0x60, 0xbb, 0xfc, 0xb2, 0x19, 0xbc, 0xd9, 0x83, 0x9d, 0xba, 0x66, 0x71, 0x8d, 0x3b,
+  0xb2, 0xb6, 0x2c, 0xbc, 0xcc, 0xab, 0x71, 0x3c, 0xf1, 0x6c, 0x09, 0x3d, 0x42, 0x4e, 0x89, 0xbc,
+  0xac, 0x90, 0x6e, 0xbc, 0x1a, 0xd8, 0x86, 0xbb, 0xae, 0x85, 0x81, 0x3b, 0x61, 0x1c, 0xad, 0xbb,
+  0x57, 0x42, 0x92, 0xbb, 0x64, 0xd9, 0x34, 0xbc, 0x0d, 0x3b, 0xc8, 0x3c, 0xb4, 0x95, 0x13, 0xbb,
+  0xce, 0x19, 0xb9, 0x3c, 0xb6, 0xc6, 0x95, 0xbb, 0x92, 0xf1, 0x12, 0xbd, 0x0e, 0x76, 0x62, 0x3c,
+  0x77, 0xcc, 0x24, 0x3c, 0x0c, 0xc5, 0x25, 0xbc, 0x04, 0x2f, 0x02, 0x3c, 0xe1, 0xf9, 0x94, 0xbb,
+  0x13, 0x80, 0xa3, 0x3c, 0xab, 0xe7, 0xb4, 0x3c, 0xf8, 0x63, 0x6f, 0x3b, 0xd8, 0x2f, 0x65, 0x3c,
+  0xcc, 0x8d, 0xbc, 0xbb, 0xad, 0x56, 0x1c, 0xbb, 0x2a, 0x0c, 0x26, 0x3c, 0x48, 0xe9, 0x3f, 0xbb,
+  0x30, 0xc1, 0x86, 0x3c, 0x41, 0xbd, 0xcc, 0x3c, 0x4b, 0xf2, 0xb1, 0xb9, 0xdb, 0xe8, 0x3b, 0x3b,
+  0x48, 0xf3, 0xa2, 0xbb, 0xe5, 0x5a, 0xc4, 0xba, 0xda, 0x8b, 0x2e, 0xbb, 0x2a, 0x60, 0x63, 0xbb,
+  0xb4, 0xd3, 0xcd, 0x3a, 0xc4, 0xc5, 0xb0, 0xbb, 0x28, 0x20, 0xbe, 0xbb, 0xfc, 0x2d, 0xbb, 0xbb,
+  0xe0, 0x21, 0xa7, 0xbc, 0x3a, 0x15, 0x2c, 0xbc, 0xcc, 0xe8, 0x9a, 0x39, 0x96, 0x12, 0x6c, 0x3b,
+  0x2a, 0x62, 0x83, 0x3c, 0xb1, 0xc6, 0xed, 0xbb, 0xdf, 0xed, 0xd4, 0xbb, 0xda, 0x31, 0x40, 0x3b,
+  0x70, 0xbf, 0xb8, 0xbc, 0x60, 0x94, 0x51, 0xbc, 0xa1, 0xc1, 0xba, 0x3b, 0x68, 0x17, 0x07, 0xbc,
+  0x4f, 0x8b, 0x0f, 0x3c, 0xd1, 0x97, 0xc9, 0x3a, 0xf6, 0x7f, 0x80, 0x3b, 0x2f, 0x69, 0x9c, 0x3a,
+  0x41, 0x86, 0x86, 0xbb, 0x5c, 0x25, 0x14, 0x3b, 0x1b, 0x4f, 0x52, 0x3c, 0xd4, 0xfd, 0x66, 0x3b,
+  0x5e, 0xee, 0xe0, 0x3c, 0xa2, 0xda, 0xcb, 0x3c, 0x16, 0x00, 0x83, 0x3c, 0xa7, 0x68, 0x6c, 0xbc,
+  0x68, 0xbb, 0x5f, 0xbc, 0x18, 0x72, 0xb2, 0x3b, 0x63, 0x7c, 0xb9, 0x3b, 0xcf, 0x0c, 0x9a, 0xbb,
+  0xcd, 0x95, 0xa2, 0x3c, 0x21, 0x54, 0x8d, 0xbb, 0xda, 0xa4, 0x8d, 0x3c, 0x7d, 0x30, 0xa2, 0x3b,
+  0x1c, 0xbd, 0x06, 0xbb, 0x4b, 0x2e, 0x1e, 0xba, 0xe5, 0x07, 0x4a, 0x3c, 0x70, 0x47, 0xbb, 0xba,
+  0xef, 0xbf, 0x20, 0x3b, 0xf6, 0x32, 0x00, 0xba, 0xe4, 0x9c, 0xdf, 0xb9, 0x13, 0x19, 0xd7, 0x3b,
+  0xa1, 0x10, 0x9e, 0x3b, 0xc0, 0xf5, 0x4d, 0x3c, 0xe4, 0xef, 0x86, 0x3b, 0xd8, 0x3b, 0x15, 0xbb,
+  0xbe, 0x6a, 0x24, 0x3c, 0x4a, 0xf6, 0x03, 0x3b, 0x69, 0x34, 0xcd, 0x3a, 0x22, 0xe9, 0x8b, 0xbb,
+  0x0c, 0x7f, 0x68, 0xba, 0xb5, 0x10, 0x0c, 0xb8, 0xc8, 0x14, 0xef, 0xba, 0x2d, 0x8b, 0x1e, 0xbb,
+  0x66, 0xcf, 0x07, 0x3c, 0xcf, 0x5c, 0x2d, 0xbb, 0x94, 0xc6, 0x62, 0x3c, 0xf3, 0x18, 0xe2, 0x3b,
+  0x7d, 0xef, 0x47, 0x3b, 0x45, 0x05, 0x12, 0xbc, 0x59, 0x49, 0xe3, 0xba, 0x2f, 0x76, 0x87, 0x3c,
+  0xe0, 0xf7, 0x9d, 0xbc, 0x4f, 0xc4, 0xdd, 0xbb, 0xb6, 0x2c, 0xf9, 0x3a, 0x11, 0xb6, 0x56, 0xbc,
+  0xaa, 0x21, 0xe4, 0x3b, 0xd1, 0x3c, 0x2e, 0x3c, 0x96, 0x16, 0x9f, 0x3c, 0x95, 0xe4, 0x8f, 0xba,
+  0x3c, 0x4f, 0xab, 0xbb, 0xb4, 0x15, 0x1c, 0xbc, 0x8f, 0xf6, 0x68, 0xbc, 0x78, 0x93, 0xd9, 0x3b,
+  0x4b, 0x10, 0x27, 0xbc, 0xa0, 0x4a, 0x88, 0x3b, 0xf4, 0x9f, 0x61, 0x3c, 0x94, 0x3d, 0x05, 0x3c,
+  0x0b, 0x38, 0x13, 0x3b, 0x2c, 0x1c, 0x06, 0x3c, 0x06, 0xd4, 0x5d, 0xbc, 0x49, 0x2e, 0xa0, 0x3c,
+  0x2b, 0xfb, 0x0d, 0x3c, 0xcd, 0xe5, 0x43, 0x3a, 0x02, 0xe7, 0x10, 0x3c, 0xd6, 0x1e, 0x44, 0x3c,
+  0x64, 0x69, 0xe2, 0x3b, 0x9f, 0xdd, 0x4b, 0x3c, 0x99, 0x72, 0x0f, 0xbc, 0xf0, 0x4e, 0x56, 0xbb,
+  0x05, 0xa5, 0x2a, 0x3b, 0x4f, 0x50, 0x86, 0x3b, 0x59, 0x8c, 0xa7, 0xbb, 0x68, 0x70, 0xcc, 0xba,
+  0x42, 0xfd, 0x22, 0x3b, 0xa8, 0x41, 0xe3, 0x3a, 0x82, 0x4a, 0x5a, 0xbc, 0x57, 0x92, 0xea, 0xbb,
+  0x75, 0x38, 0x33, 0x3c, 0x66, 0x3d, 0xd1, 0x39, 0x6d, 0x30, 0xdb, 0xbb, 0x08, 0x3d, 0x4c, 0xba,
+  0xc4, 0xb0, 0xac, 0x3b, 0x7f, 0xc6, 0xc1, 0xbb, 0x57, 0xc9, 0xd1, 0x3b, 0x33, 0xe2, 0x0c, 0x3b,
+  0x50, 0xb7, 0x2c, 0x3b, 0x02, 0x0c, 0x8d, 0xba, 0x81, 0xe7, 0x04, 0xba, 0x2f, 0x7b, 0x19, 0xbc,
+  0xf0, 0xb1, 0x33, 0xbc, 0xd0, 0x8c, 0x34, 0x39, 0xdb, 0x11, 0x11, 0xba, 0x65, 0xb0, 0xd5, 0x3a,
+  0x00, 0x20, 0xd4, 0x3a, 0x6e, 0x25, 0xb2, 0xba, 0xa9, 0xcc, 0xee, 0xbb, 0xb0, 0x90, 0x23, 0x3c,
+  0x3d, 0x1c, 0xde, 0xba, 0x5d, 0x78, 0xd1, 0xbb, 0x16, 0x8e, 0xe5, 0xb9, 0x20, 0x2d, 0x8e, 0xba,
+  0x21, 0xdd, 0x94, 0x3b, 0x07, 0xfa, 0x09, 0xbc, 0xae, 0x76, 0xea, 0x3c, 0xd2, 0xee, 0xcb, 0x39,
+  0xa5, 0x2d, 0x1c, 0xbc, 0x13, 0x0b, 0x40, 0x3a, 0xfb, 0xb8, 0xf6, 0xbb, 0xed, 0xb0, 0x9e, 0xbb,
+  0x74, 0x39, 0x78, 0x3c, 0x8b, 0x46, 0x28, 0xbc, 0x69, 0xab, 0x2a, 0x3c, 0x5c, 0x1f, 0x4d, 0x3b,
+  0x51, 0x34, 0xc2, 0x3c, 0x32, 0x88, 0xc4, 0xbb, 0xbe, 0x56, 0xc2, 0xbc, 0x34, 0xf6, 0xfc, 0xbb,
+  0xb3, 0x53, 0x49, 0x3a, 0x6c, 0xb8, 0xad, 0xbc, 0x2f, 0xf1, 0x07, 0x3c, 0x8d, 0x80, 0x4f, 0xbc,
+  0x93, 0x89, 0x9d, 0x3c, 0x3b, 0x38, 0xd8, 0x3b, 0x08, 0x02, 0x60, 0xbc, 0x45, 0x65, 0x80, 0x3c,
+  0xbb, 0x0f, 0x10, 0xbc, 0x53, 0x3b, 0xc4, 0xbc, 0x79, 0xf5, 0x6d, 0x3c, 0xf5, 0x93, 0x9a, 0xbc,
+  0x87, 0x1c, 0x8a, 0x3c, 0x9b, 0x5f, 0x96, 0x3c, 0x15, 0x45, 0x33, 0x3b, 0x4d, 0xeb, 0x3c, 0xbb,
+  0xa7, 0x9e, 0x65, 0xbb, 0x47, 0x44, 0xef, 0xbb, 0xe1, 0x5f, 0x8d, 0x39, 0x10, 0x77, 0x4b, 0xbc,
+  0xc2, 0x4d, 0xaf, 0x3b, 0xbf, 0xe6, 0x5f, 0x3b, 0x75, 0x7b, 0x8c, 0xbc, 0xae, 0xf1, 0x82, 0x3c,
+  0x28, 0xdb, 0x05, 0xbd, 0x09, 0xd8, 0x60, 0xbc, 0x83, 0x63, 0x04, 0xbc, 0x45, 0x56, 0x76, 0xbb,
+  0x62, 0xa1, 0x0b, 0x3c, 0xe5, 0x0c, 0xdf, 0xba, 0x8a, 0x21, 0x4e, 0xbc, 0xcd, 0x34, 0x61, 0xba,
+  0xb0, 0xa5, 0xb0, 0xbb, 0xbe, 0x48, 0xad, 0xbc, 0xa6, 0x8e, 0x21, 0x3c, 0xa3, 0x1f, 0x96, 0x3b,
+  0x7f, 0x16, 0x5b, 0xb8, 0xdd, 0x24, 0x16, 0x3c, 0xd0, 0x89, 0xe4, 0xba, 0x9b, 0x63, 0x1c, 0xbc,
+  0xe1, 0xb2, 0xc7, 0xbb, 0xc1, 0xcc, 0xa2, 0xbc, 0x10, 0x72, 0x4d, 0x3c, 0xe9, 0x6a, 0x64, 0xbc,
+  0x59, 0x12, 0x80, 0x3c, 0x05, 0x44, 0xd2, 0x3c, 0xed, 0x9f, 0xa4, 0x3c, 0xd8, 0xd5, 0xd1, 0x3a,
+  0x50, 0x5b, 0x37, 0xbc, 0x90, 0x8a, 0x65, 0xbc, 0xe4, 0xb9, 0x26, 0xba, 0xa0, 0xed, 0xf6, 0x38,
+  0xc8, 0x23, 0x13, 0x3c, 0x6c, 0x11, 0x58, 0x3c, 0x2f, 0x39, 0xde, 0x3b, 0x1a, 0x44, 0x7e, 0x3c,
+  0x3c, 0xb6, 0x56, 0xbc, 0x45, 0xe5, 0xb2, 0xbb, 0x81, 0x86, 0x8d, 0x3c, 0x50, 0x84, 0xac, 0x3b,
+  0xec, 0xf0, 0x78, 0x3c, 0x48, 0xd7, 0x1e, 0x3c, 0x68, 0xbc, 0x14, 0x3c, 0xef, 0x88, 0x81, 0xbb,
+  0xca, 0xd8, 0xfa, 0x3a, 0x16, 0x11, 0x53, 0x3c, 0x3b, 0xf8, 0xb6, 0x3c, 0x12, 0xa6, 0xa4, 0x3b,
+  0x5b, 0x1d, 0x21, 0x3c, 0x0f, 0x0c, 0x4e, 0xb8, 0x4d, 0x8f, 0xbd, 0xbb, 0x34, 0x12, 0x4d, 0x3c,
+  0xf1, 0xe8, 0x05, 0x3c, 0xf4, 0xcb, 0xce, 0x3b, 0x40, 0x96, 0xb9, 0x3a, 0x87, 0x54, 0x3f, 0x3c,
+  0x0c, 0x34, 0xf1, 0x3b, 0xae, 0x7b, 0x3a, 0x3c, 0x1b, 0x6e, 0x09, 0x3b, 0xc3, 0xa2, 0x76, 0x3c,
+  0x41, 0xaf, 0x21, 0xbb, 0x81, 0x13, 0xe2, 0xbb, 0x83, 0x6f, 0x72, 0x3c, 0x46, 0xaf, 0x25, 0x3c,
+  0xfb, 0xde, 0xcd, 0x3a, 0x1c, 0x6e, 0x0d, 0xbb, 0xb1, 0x54, 0xa5, 0x3b, 0xea, 0x02, 0x35, 0x3c,
+  0xa7, 0x7a, 0x24, 0xbb, 0xb0, 0x66, 0xa5, 0x3b, 0x3c, 0x19, 0x52, 0x3c, 0xb0, 0x78, 0x71, 0x3c,
+  0x26, 0x7b, 0xc2, 0xbb, 0x20, 0xc2, 0x58, 0x3b, 0x0d, 0xa3, 0x5f, 0xbb, 0x2c, 0x2e, 0x50, 0xbb,
+  0x19, 0x3c, 0x78, 0xbb, 0xf9, 0xa0, 0xc0, 0xbb, 0xce, 0xbc, 0x1d, 0x3c, 0x7c, 0xfc, 0xea, 0x3b,
+  0x1d, 0x4b, 0x96, 0xbb, 0x74, 0xa0, 0x41, 0xba, 0xd5, 0x34, 0x88, 0xbc, 0x93, 0x89, 0xab, 0x3b,
+  0x35, 0x58, 0x28, 0xba, 0x02, 0x5a, 0xf2, 0x39, 0x0c, 0xa8, 0x3f, 0x3c, 0x51, 0x69, 0xfe, 0x3a,
+  0x3d, 0xc1, 0x53, 0x3c, 0x08, 0x74, 0x97, 0x3b, 0x6c, 0x1d, 0x18, 0xbc, 0x91, 0x75, 0x44, 0xbc,
+  0x08, 0x8c, 0x62, 0xbb, 0xdb, 0xe6, 0x2d, 0x3c, 0xb4, 0xf3, 0x86, 0x3a, 0xf8, 0x14, 0xd2, 0x39,
+  0xc8, 0x69, 0x3f, 0x38, 0x27, 0xe1, 0x92, 0xbb, 0x40, 0x63, 0xf1, 0xbb, 0x66, 0xc7, 0x58, 0x3b,
+  0xd6, 0x4b, 0xfb, 0xbb, 0x6a, 0xd4, 0x47, 0x3b, 0xc7, 0x4d, 0x82, 0xbb, 0x11, 0x3b, 0xa6, 0x3b,
+  0x7b, 0xeb, 0x56, 0x3a, 0x4f, 0x9c, 0xc5, 0xbb, 0xdf, 0xa7, 0xeb, 0xb9, 0x2c, 0x6c, 0x7d, 0x3c,
+  0x16, 0x8c, 0xbc, 0xba, 0xe8, 0x61, 0x12, 0x3a, 0x59, 0xa5, 0xfc, 0x3a, 0x6c, 0x63, 0xa9, 0xbb,
+  0x54, 0x65, 0x98, 0xbc, 0x3e, 0xc5, 0xbc, 0xbb, 0x1e, 0x80, 0xb7, 0xbb, 0xea, 0x84, 0xde, 0xbb,
+  0x44, 0xb2, 0x38, 0xbc, 0x10, 0x45, 0xfb, 0xb9, 0xcc, 0x88, 0x0b, 0x3b, 0x4f, 0xcd, 0x29, 0x38,
+  0x58, 0x19, 0xf6, 0xbb, 0x50, 0x73, 0x6c, 0xbc, 0x0c, 0x84, 0x87, 0xba, 0x80, 0x11, 0x17, 0xbc,
+  0x7a, 0xe0, 0x51, 0x3c, 0x0d, 0x2e, 0x03, 0xbc, 0x73, 0xd6, 0x7e, 0x3c, 0x11, 0xff, 0x32, 0xbb,
+  0x33, 0xb8, 0x1f, 0xbb, 0x80, 0x89, 0xb9, 0xbb, 0xac, 0x5f, 0x76, 0x3a, 0x9a, 0x55, 0x38, 0x3c,
+  0x9b, 0x1c, 0x5a, 0x3b, 0x0a, 0x93, 0x2a, 0xbb, 0x1b, 0x19, 0x03, 0xbc, 0x15, 0x94, 0x5c, 0xbc,
+  0xc2, 0x09, 0x85, 0x3b, 0xd4, 0xc2, 0xc6, 0x3b, 0xb6, 0xa5, 0x6f, 0xbc, 0xdf, 0x97, 0xda, 0x3b,
+  0x93, 0xd2, 0x90, 0x3c, 0x55, 0x09, 0xe4, 0xbc, 0x8c, 0x8c, 0xab, 0xba, 0x2c, 0x58, 0xbc, 0x3b,
+  0x4d, 0x63, 0x5b, 0x3c, 0x4c, 0x12, 0xad, 0x3b, 0x59, 0xdc, 0xff, 0xbb, 0x32, 0xae, 0xe7, 0x39,
+  0x10, 0x74, 0x59, 0x3c, 0x30, 0x97, 0xab, 0xbc, 0xdd, 0x8c, 0x02, 0x3c, 0xdb, 0x0b, 0xa5, 0xbb,
+  0x51, 0x7a, 0x52, 0x3c, 0xa0, 0x4f, 0x93, 0x3b, 0xbe, 0xd0, 0x29, 0xbb, 0x6a, 0x32, 0x96, 0xbc,
+  0xed, 0x22, 0x12, 0x3c, 0xe0, 0x38, 0x63, 0xbc, 0x4a, 0x66, 0x4e, 0xbb, 0xce, 0x48, 0xf5, 0x3b,
+  0x80, 0xaa, 0x1c, 0x3c, 0x7a, 0xf8, 0x00, 0xbc, 0x79, 0x43, 0xf3, 0xbb, 0xe4, 0x24, 0xd4, 0xba,
+  0x1b, 0x37, 0x70, 0x3c, 0x98, 0x6e, 0xc0, 0xbc, 0x11, 0x23, 0xc3, 0xbb, 0xe1, 0x10, 0x5f, 0xbc,
+  0xf9, 0xe6, 0x27, 0xbb, 0xf7, 0x49, 0xdc, 0x3b, 0x6b, 0xb9, 0x99, 0x3b, 0x20, 0x6c, 0x06, 0x3c,
+  0x94, 0xe0, 0x12, 0xbc, 0xdf, 0x0a, 0x8c, 0xbc, 0xd4, 0x41, 0x03, 0xbb, 0xfa, 0xe9, 0x4b, 0xbc,
+  0x04, 0x0b, 0x8f, 0xbb, 0x70, 0xb8, 0xfd, 0xba, 0xd5, 0x9c, 0x11, 0x3c, 0x30, 0xe7, 0x71, 0xbc,
+  0x03, 0xb6, 0xb3, 0x3b, 0x76, 0xc3, 0x5b, 0xbc, 0x9b, 0x54, 0xf7, 0x3a, 0xa2, 0x5a, 0x02, 0x3c,
+  0x56, 0x0a, 0x10, 0xbc, 0x32, 0x08, 0x80, 0x3c, 0x05, 0xc8, 0x1d, 0x3c, 0x04, 0x0f, 0x70, 0xbc,
+  0xd4, 0x31, 0x52, 0x3b, 0x56, 0xb1, 0x5d, 0xbc, 0xf7, 0xae, 0x19, 0xbb, 0x94, 0x79, 0x7f, 0x3b,
+  0xb3, 0xd1, 0xd2, 0x3a, 0x31, 0x45, 0xa9, 0x3c, 0xcd, 0x38, 0x97, 0x3c, 0xe4, 0xea, 0x9f, 0xbb,
+  0x28, 0x11, 0xcd, 0x3b, 0x0d, 0xd1, 0x58, 0x3a, 0xa1, 0xea, 0x53, 0x3c, 0xc1, 0x0f, 0x8b, 0x3b,
+  0x90, 0xe9, 0x86, 0x3b, 0x81, 0x7b, 0x6d, 0xbb, 0x5e, 0x49, 0x19, 0x3c, 0x3f, 0x1b, 0x45, 0x3c,
+  0x85, 0xad, 0xec, 0x3b, 0x6f, 0xb2, 0xa5, 0x3b, 0x2b, 0x12, 0x93, 0x39, 0xf9, 0x30, 0x01, 0x3c,
+  0x95, 0x80, 0x8a, 0x3b, 0x48, 0xe5, 0x09, 0x3c, 0x36, 0x01, 0xbb, 0x3a, 0x83, 0x84, 0xab, 0xbb,
+  0x3e, 0x58, 0x3b, 0x3c, 0x76, 0x40, 0xce, 0xbb, 0xdc, 0xc9, 0x0e, 0xbb, 0xff, 0x57, 0xb4, 0xbb,
+  0xa1, 0x4a, 0x81, 0x3a, 0xd2, 0x55, 0xe1, 0x3b, 0x4c, 0x97, 0xc8, 0x3b, 0x7d, 0xc5, 0x6d, 0xb9,
+  0xde, 0x27, 0x5e, 0x3b, 0xd2, 0x4b, 0xf8, 0xba, 0x87, 0x33, 0x3a, 0x3c, 0x80, 0x3e, 0x91, 0x3c,
+  0x0f, 0x83, 0xa9, 0x3b, 0xc2, 0xcd, 0xff, 0xbb, 0x37, 0xd6, 0x4f, 0xbb, 0xf9, 0xa5, 0x49, 0xbc,
+  0xed, 0xf2, 0x7a, 0x3b, 0x97, 0xf6, 0xb1, 0x39, 0xae, 0x6c, 0x8d, 0x3c, 0x5c, 0xba, 0x19, 0x3c,
+  0x4d, 0x49, 0x3d, 0xbb, 0xd7, 0x7a, 0x18, 0xbc, 0x53, 0x8f, 0x56, 0xbc, 0x04, 0x0f, 0x70, 0x3c,
+  0xd1, 0x7f, 0x8a, 0x3b, 0x24, 0x5a, 0x41, 0xba, 0xc9, 0x60, 0x84, 0x3b, 0x90, 0x75, 0x10, 0xbc,
+  0xce, 0x71, 0x4c, 0x3c, 0xa6, 0x2b, 0x48, 0x3c, 0xf2, 0xc3, 0x1b, 0x3b, 0x66, 0xc1, 0xc5, 0x38,
+  0x54, 0xd6, 0x29, 0xba, 0xe5, 0x86, 0xc2, 0x3b, 0xb9, 0xb2, 0x75, 0xba, 0xe1, 0x88, 0x63, 0xbb,
+  0x06, 0x1a, 0x05, 0x3c, 0x7b, 0xf3, 0x07, 0x3c, 0xa7, 0xb6, 0x2e, 0xbc, 0x0e, 0x3d, 0x62, 0xba,
+  0xaf, 0x6d, 0x83, 0x3b, 0x8a, 0x34, 0x4e, 0xbb, 0x51, 0xf9, 0xf7, 0xbb, 0x25, 0x89, 0x5e, 0xbc,
+  0xa9, 0x6b, 0xbe, 0x39, 0x30, 0x6d, 0xcb, 0x3b, 0x40, 0xf9, 0xf1, 0xbb, 0xe6, 0x9b, 0x80, 0xb8,
+  0xdc, 0x27, 0xa9, 0x3b, 0xe7, 0x88, 0x2a, 0xbc, 0xa7, 0x33, 0x47, 0x3c, 0xd9, 0x81, 0x2b, 0xbc,
+  0xd3, 0x79, 0xcf, 0xbb, 0xb6, 0x55, 0x7a, 0xbb, 0xf3, 0x33, 0x81, 0x3b, 0xad, 0x9a, 0x09, 0x3c,
+  0x57, 0xfb, 0x57, 0x3c, 0x05, 0xe0, 0x71, 0x3c, 0xfc, 0xa1, 0x28, 0xbb, 0xa9, 0xd0, 0x01, 0xbc,
+  0xc1, 0x99, 0xf3, 0xbb, 0x93, 0xe8, 0xd8, 0xbb, 0x0d, 0xa8, 0x1d, 0x3c, 0x5c, 0xc0, 0x75, 0xbc,
+  0x4f, 0x4e, 0xd7, 0x3a, 0xab, 0x93, 0x41, 0xbb, 0xc3, 0xf9, 0x5c, 0xbb, 0xf4, 0x79, 0x95, 0xbc,
+  0x11, 0x9e, 0x37, 0xbc, 0x6b, 0x2e, 0x01, 0xbb, 0x5e, 0x1c, 0xc7, 0xbb, 0xe9, 0x45, 0x02, 0xba,
+  0xe5, 0x81, 0x10, 0x3c, 0x2c, 0xd1, 0x06, 0x3b, 0xda, 0xb6, 0x92, 0xbb, 0xf6, 0xfb, 0xe2, 0xba,
+  0x2e, 0xa0, 0x30, 0x3c, 0x8b, 0xa3, 0xf0, 0x3b, 0x85, 0x95, 0x05, 0xbb, 0x8d, 0x9d, 0xa0, 0x3c,
+  0x4e, 0x4c, 0xc8, 0x3a, 0xf5, 0x10, 0x52, 0xbc, 0x4f, 0xc6, 0xd8, 0xbb, 0xaa, 0x4f, 0x10, 0xbc,
+  0xe8, 0x44, 0x6e, 0x3c, 0x99, 0x5c, 0x4b, 0xbb, 0x40, 0x85, 0xde, 0x3a, 0xf6, 0x7e, 0x12, 0xbc,
+  0x2c, 0x70, 0x91, 0x3c, 0x82, 0xb9, 0xbd, 0xbb, 0x28, 0x04, 0x73, 0xbc, 0x88, 0x09, 0x27, 0x3c,
+  0xcc, 0x38, 0xf5, 0x3b, 0xde, 0x63, 0x67, 0x3c, 0x78, 0x23, 0x06, 0xbc, 0x2f, 0x6d, 0x58, 0x3c,
+  0xa3, 0xa7, 0xe9, 0x3a, 0xf0, 0x71, 0x84, 0xbc, 0x67, 0xa4, 0x57, 0xbc, 0x69, 0x15, 0x7e, 0x3b,
+  0xe7, 0x8b, 0x80, 0x3c, 0x94, 0xb0, 0xbd, 0xba, 0x0f, 0xae, 0xae, 0xba, 0x8c, 0x71, 0x2e, 0xbc,
+  0xfe, 0xe8, 0xb7, 0x3a, 0x5f, 0xe2, 0xd2, 0xbc, 0xa7, 0xa0, 0x93, 0xbc, 0x6e, 0x48, 0x96, 0x3c,
+  0x5f, 0x9e, 0xfc, 0xb8, 0xbf, 0xcc, 0x95, 0x3b, 0x51, 0x96, 0xcd, 0xba, 0x14, 0x6c, 0x1f, 0x3b,
+  0x8a, 0x27, 0x00, 0xbc, 0xa1, 0xa8, 0xac, 0xbc, 0xcb, 0x20, 0x70, 0xbc, 0xa0, 0x86, 0x4a, 0x3c,
+  0xf6, 0xea, 0x5e, 0xbc, 0x6c, 0x49, 0xae, 0xbb, 0x2b, 0x23, 0x68, 0x3b, 0x56, 0x25, 0x46, 0xbc,
+  0xc3, 0x34, 0x49, 0xbb, 0x7b, 0x3c, 0x83, 0xbc, 0xec, 0xa1, 0xaa, 0xbc, 0x60, 0xb0, 0xcd, 0x3a,
+  0xd1, 0x80, 0xf3, 0xbb, 0x56, 0xe5, 0xfc, 0x3b, 0xd0, 0xc4, 0x26, 0x3c, 0xb4, 0x5e, 0xbd, 0x3b,
+  0x2c, 0xd8, 0xc2, 0xbb, 0x6d, 0xbd, 0x16, 0xbc, 0xdc, 0xf3, 0x60, 0xbc, 0xa7, 0x4e, 0x1b, 0xbb,
+  0xc2, 0x8b, 0xe4, 0x3b, 0xb7, 0xd0, 0x6b, 0x3c, 0xf5, 0x6e, 0x30, 0x3c, 0x49, 0x5c, 0x85, 0x3b,
+  0xdc, 0xc9, 0xed, 0xb7, 0x71, 0x30, 0x1c, 0xbc, 0x28, 0x9a, 0x2c, 0xbc, 0xc5, 0xe6, 0x16, 0x3c,
+  0xda, 0x06, 0x2f, 0x3c, 0xea, 0xb6, 0xa9, 0x3b, 0x9d, 0xbb, 0x82, 0x39, 0x16, 0xd7, 0x19, 0xbb,
+  0xc8, 0xff, 0x1a, 0xba, 0x7d, 0x69, 0xdc, 0xb8, 0xe2, 0x40, 0x0d, 0xbb, 0x64, 0xea, 0x64, 0x3b,
+  0x4c, 0x3e, 0x17, 0x3c, 0x3a, 0x39, 0x7a, 0x3b, 0xd0, 0x3e, 0xb5, 0xbb, 0x83, 0x32, 0x58, 0xbc,
+  0xc1, 0x39, 0x0c, 0x3c, 0xcf, 0x37, 0x0d, 0x39, 0x24, 0x05, 0x29, 0xbb, 0x7e, 0xf3, 0x2c, 0xbb,
+  0x6c, 0xaf, 0xef, 0xba, 0x41, 0xfe, 0x77, 0x3b, 0x87, 0x41, 0x25, 0xbc, 0xfa, 0x87, 0x47, 0x3c,
+  0x6f, 0x4b, 0x6b, 0x3a, 0x96, 0x3a, 0x59, 0x3c, 0x94, 0x71, 0x3a, 0xbc, 0xbb, 0x1a, 0x94, 0x3c,
+  0xad, 0x72, 0xca, 0xbb, 0x7a, 0xda, 0xfd, 0x3b, 0x99, 0xe1, 0x8c, 0x3b, 0x78, 0xa0, 0xf0, 0x3b,
+  0xbc, 0x65, 0x46, 0x3c, 0x23, 0xf5, 0x74, 0x3a, 0xbd, 0xc5, 0x18, 0xbb, 0x8b, 0x49, 0x1d, 0xbc,
+  0x84, 0x18, 0x94, 0xbb, 0x4f, 0x18, 0x69, 0xbc, 0xae, 0xb5, 0x18, 0xbb, 0x99, 0x11, 0x37, 0xbb,
+  0x88, 0xdd, 0x08, 0x3c, 0x07, 0x6d, 0xd3, 0xbb, 0x40, 0xb4, 0xb3, 0x3b, 0x19, 0xa9, 0x77, 0x3b,
+  0x95, 0x69, 0xff, 0xb9, 0x98, 0x69, 0x99, 0xbc, 0x84, 0x77, 0x6c, 0xbb, 0xc0, 0x71, 0x10, 0x3c,
+  0xd8, 0xf3, 0x3f, 0x3c, 0x6c, 0xd0, 0x34, 0x3b, 0xee, 0x71, 0x4c, 0x3b, 0xb5, 0x1f, 0x87, 0x3c,
+  0xc7, 0x5e, 0xb4, 0xb9, 0x6c, 0x99, 0x44, 0x3c, 0xe8, 0xce, 0xad, 0xbb, 0x65, 0x2c, 0xaa, 0x3b,
+  0x99, 0x5c, 0x96, 0x3b, 0x28, 0xa6, 0x17, 0x3c, 0xb8, 0xac, 0xda, 0xbb, 0xf8, 0x70, 0x46, 0xbb,
+  0x51, 0xe2, 0x89, 0x3a, 0x34, 0xc5, 0x81, 0x3c, 0x00, 0x27, 0x21, 0xbc, 0x02, 0x05, 0x05, 0x3c,
+  0x09, 0x29, 0x36, 0x3c, 0x4d, 0xc6, 0x37, 0x3c, 0x06, 0x46, 0x1a, 0xbc, 0xed, 0xe5, 0x71, 0xbc,
+  0x13, 0x96, 0xd5, 0x3b, 0x7c, 0xf5, 0x8a, 0xbb, 0x37, 0xae, 0x39, 0xbc, 0x44, 0xca, 0x9b, 0xbc,
+  0xed, 0xcb, 0xe2, 0x3b, 0x74, 0x78, 0x98, 0x39, 0x02, 0xf1, 0xe5, 0xbb, 0x74, 0x42, 0x11, 0xbc,
+  0xf2, 0x3f, 0x17, 0xbc, 0xa8, 0xc5, 0x00, 0xbc, 0x61, 0x20, 0x88, 0x3b, 0x41, 0xf6, 0x89, 0xbb,
+  0x63, 0x97, 0x41, 0xbc, 0x9d, 0x0d, 0xcd, 0xba, 0x3b, 0x29, 0xfa, 0xbb, 0xbc, 0xff, 0x61, 0xbb,
+  0xea, 0xe3, 0x92, 0xbc, 0x02, 0xbe, 0x09, 0xbc, 0x5b, 0x81, 0x8d, 0xbc, 0x89, 0xa6, 0x29, 0xbb,
+  0x68, 0xaf, 0x82, 0xbb, 0xb8, 0x44, 0x97, 0x3b, 0x1b, 0x9a, 0xa5, 0xbb, 0x93, 0x93, 0xb3, 0x3b,
+  0xd3, 0x50, 0xab, 0xbc, 0x6d, 0xbe, 0xa2, 0xbc, 0x58, 0xc1, 0x77, 0x3b, 0x74, 0x6c, 0x4a, 0x3b,
+  0xd0, 0x0a, 0x3a, 0x3c, 0x59, 0xe7, 0x4b, 0x3b, 0x49, 0x09, 0xc2, 0x3b, 0x5b, 0x5e, 0x13, 0x3c,
+  0x6b, 0xb9, 0xbf, 0xba, 0xe3, 0x28, 0x8c, 0x3b, 0x69, 0xc6, 0x11, 0x3c, 0xd1, 0x7a, 0x96, 0x3c,
+  0xc9, 0xb0, 0x0b, 0x3c, 0xde, 0xc9, 0xba, 0xbb, 0xa8, 0x5a, 0x04, 0xbc, 0x10, 0xd0, 0xfc, 0x36,
+  0x6d, 0x5f, 0xb3, 0xbb, 0x3b, 0x61, 0x9d, 0x3c, 0x2b, 0xd6, 0x3b, 0x3c, 0x7f, 0x31, 0x43, 0xba,
+  0x86, 0xcb, 0xf1, 0x3a, 0x40, 0x3a, 0xdc, 0x3b, 0xb8, 0xa9, 0x81, 0x3c, 0xa6, 0x00, 0x4b, 0x3c,
+  0x21, 0x5a, 0x96, 0x3b, 0xa6, 0xce, 0x6e, 0x3c, 0xdc, 0x4a, 0x8a, 0x3b, 0x71, 0x7a, 0xfe, 0xbb,
+  0x4a, 0xb1, 0xc4, 0x3b, 0xb6, 0x26, 0xf0, 0x3b, 0xd3, 0x70, 0x1f, 0xbc, 0x5d, 0xc5, 0xca, 0xbb,
+  0xe9, 0x4a, 0x34, 0x3c, 0x96, 0xfd, 0x84, 0x3c, 0xe1, 0xd1, 0x32, 0x39, 0x39, 0xdb, 0x19, 0xbc,
+  0x46, 0x71, 0xda, 0x3b, 0x06, 0x51, 0x09, 0x3a, 0xc2, 0x01, 0x32, 0xbc, 0xb9, 0xd4, 0x76, 0x3b,
+  0xa7, 0x43, 0x8b, 0x3b, 0x25, 0xaf, 0xdb, 0xbb, 0xe0, 0x51, 0xe1, 0xbb, 0x7b, 0xfd, 0x75, 0x3b,
+  0xdb, 0x63, 0x01, 0xbc, 0xe4, 0x7a, 0xb3, 0x3b, 0x11, 0x24, 0x9a, 0xbc, 0x13, 0xfb, 0x8a, 0x3b,
+  0x06, 0x98, 0x1d, 0x3c, 0xca, 0xd6, 0xad, 0xbb, 0x00, 0xa5, 0x9c, 0xbb, 0xa6, 0xd5, 0xf7, 0x3a,
+  0xee, 0x29, 0x43, 0x3c, 0xce, 0x69, 0xc0, 0xbb, 0x85, 0x86, 0x08, 0x3c, 0x2b, 0x98, 0x31, 0xbc,
+  0x4e, 0x2c, 0xd9, 0xbb, 0x7c, 0xe0, 0xce, 0x3b, 0xcc, 0x5a, 0x7a, 0x3c, 0x63, 0xca, 0x36, 0x3c,
+  0x5d, 0x42, 0x95, 0x3b, 0x98, 0xcb, 0x16, 0x3b, 0x45, 0xb8, 0xc3, 0x3b, 0x9f, 0xb1, 0xdf, 0x3a,
+  0xd3, 0x97, 0x18, 0x3a, 0x94, 0x58, 0xaa, 0xba, 0x31, 0xb6, 0xb9, 0xbb, 0x6a, 0x6a, 0x2a, 0xbb,
+  0x73, 0x3a, 0x54, 0x3c, 0xb5, 0xcb, 0xc0, 0x3b, 0x30, 0x23, 0xe2, 0xbb, 0xeb, 0x0f, 0xad, 0x3b,
+  0x41, 0xd6, 0x26, 0xba, 0x5e, 0xc1, 0x5c, 0xba, 0x50, 0xac, 0xfb, 0x39, 0x6f, 0x16, 0x9b, 0xbc,
+  0xe6, 0xde, 0x2d, 0xbb, 0x06, 0x51, 0xdd, 0x3b, 0x1e, 0x51, 0xb1, 0xbb, 0xf6, 0xfe, 0x1f, 0x3c,
+  0xbe, 0xfe, 0x54, 0xbb, 0xd1, 0x0c, 0x9b, 0x39, 0x18, 0x02, 0xdc, 0x3a, 0x4d, 0x0c, 0x7a, 0xbb,
+  0xd9, 0x6c, 0x43, 0xbb, 0x90, 0x16, 0x61, 0x3a, 0x2d, 0x38, 0x3a, 0xbc, 0x1d, 0x2b, 0x6a, 0xbb,
+  0x6a, 0xf0, 0x54, 0xbb, 0x94, 0x01, 0x29, 0xbc, 0x19, 0xe6, 0xeb, 0xbb, 0x25, 0x41, 0x61, 0x3b,
+  0x76, 0xa6, 0x2f, 0xba, 0xe0, 0xb1, 0x69, 0x3c, 0xa4, 0xb9, 0x2f, 0x3a, 0x3c, 0x19, 0xac, 0x3b,
+  0xab, 0xf0, 0x92, 0xbb, 0x13, 0xa5, 0x98, 0x3b, 0x39, 0x33, 0x87, 0xbb, 0x91, 0x11, 0xbf, 0x3b,
+  0xee, 0xee, 0xc8, 0xba, 0xd7, 0xc2, 0x1b, 0xbc, 0xc5, 0xcb, 0xcc, 0xbb, 0x60, 0x8e, 0x0e, 0x3b,
+  0xdf, 0x05, 0x84, 0xbb, 0xa7, 0x04, 0x95, 0xbc, 0x7f, 0xf1, 0xa8, 0x3b, 0x39, 0xb6, 0x26, 0x3c,
+  0xc3, 0xd2, 0x97, 0xbb, 0xa5, 0xca, 0x0a, 0xbc, 0x43, 0xbd, 0x61, 0xbb, 0xa7, 0x7b, 0xf3, 0x3b,
+  0x05, 0xf7, 0x2e, 0xbb, 0x83, 0xf4, 0x49, 0xba, 0xda, 0x14, 0x71, 0x3b, 0x06, 0x2d, 0xfb, 0xbb,
+  0x1d, 0x7e, 0x4a, 0xbc, 0x00, 0x50, 0x1a, 0xbc, 0x92, 0x88, 0x25, 0x3b, 0x49, 0x95, 0x30, 0xba,
+  0x0b, 0xa2, 0x27, 0x3c, 0x79, 0x5e, 0x46, 0x3c, 0x83, 0xfd, 0x75, 0x3c, 0xa3, 0x5b, 0x07, 0x3c,
+  0x1e, 0x68, 0x09, 0xbb, 0xad, 0xb3, 0x92, 0x3b, 0xc1, 0x97, 0x7c, 0x3b, 0xb9, 0x6e, 0xae, 0x39,
+  0x76, 0xc4, 0x4a, 0x3b, 0x66, 0x4a, 0x56, 0xba, 0x6f, 0x56, 0xdc, 0x3a, 0x79, 0x46, 0x6e, 0x3b,
+  0x58, 0x2a, 0x18, 0xbb, 0xd9, 0x67, 0x29, 0xbb, 0xff, 0xa1, 0x76, 0x3b, 0xa5, 0x1c, 0xbd, 0xbb,
+  0x56, 0x68, 0x98, 0xbb, 0x75, 0xdf, 0x9c, 0x3c, 0xda, 0x5a, 0xff, 0x3b, 0x04, 0x32, 0x4e, 0xbb,
+  0x1d, 0x60, 0x9b, 0x3c, 0x69, 0x7f, 0xa7, 0x3b, 0xc0, 0xf1, 0x79, 0xbb, 0x6a, 0x3e, 0xc7, 0x3b,
+  0xbc, 0x12, 0x03, 0x3a, 0xe0, 0xa7, 0x17, 0x39, 0x6a, 0x3c, 0x2a, 0xba, 0x1f, 0x9d, 0x90, 0x3a,
+  0x76, 0x54, 0x1c, 0x3b, 0x0e, 0xa2, 0x6c, 0x3b, 0x89, 0x3a, 0x2f, 0xbc, 0x0d, 0x46, 0x34, 0xbc,
+  0xb6, 0xd7, 0xb4, 0xbb, 0xc1, 0xf1, 0x9d, 0xbb, 0x94, 0x30, 0x13, 0x3a, 0xa8, 0x96, 0x2e, 0xbc,
+  0x15, 0x30, 0x82, 0xbc, 0x5e, 0x87, 0x72, 0x3c, 0x0b, 0xf6, 0x8e, 0xba, 0xb4, 0x19, 0x96, 0x3b,
+  0x37, 0xfd, 0x5a, 0xbb, 0x6a, 0x0f, 0x94, 0xbb, 0x25, 0x58, 0xc1, 0x3b, 0x3d, 0x6b, 0x51, 0x3c,
+  0x26, 0xa2, 0x33, 0x3b, 0x31, 0x47, 0x17, 0xbc, 0x0c, 0x55, 0xa3, 0xbb, 0xca, 0x5e, 0xdf, 0xbb,
+  0x07, 0x3b, 0xa8, 0x3a, 0x6f, 0xd0, 0xaf, 0x3a, 0x5c, 0xa1, 0xa5, 0xba, 0x76, 0xcf, 0xf2, 0x3a,
+  0x58, 0x95, 0xaf, 0xbb, 0xb0, 0xd9, 0xf9, 0x3b, 0xf5, 0x47, 0x95, 0x3b, 0x40, 0xef, 0xac, 0x3b,
+  0xf6, 0x48, 0xbc, 0xbb, 0xac, 0x6c, 0x78, 0xbb, 0x0e, 0xfd, 0xe6, 0xbb, 0xbe, 0xae, 0x42, 0xbc,
+  0x4a, 0x0e, 0x22, 0x3b, 0x4b, 0xd1, 0x76, 0xba, 0xbf, 0x42, 0x45, 0xbc, 0xb5, 0xdf, 0xa7, 0x3b,
+  0x88, 0xd8, 0xee, 0xbb, 0x2b, 0x27, 0x1c, 0xbc, 0x4a, 0x66, 0xc1, 0xbb, 0x88, 0x35, 0x1d, 0xbc,
+  0x56, 0xe7, 0x39, 0x3b, 0xdf, 0xd0, 0x10, 0xbc, 0x07, 0xbe, 0x83, 0xbc, 0xc4, 0xe4, 0x27, 0x3b,
+  0xd6, 0x72, 0x50, 0x3c, 0x63, 0xde, 0x87, 0xba, 0xe3, 0xec, 0x17, 0x3c, 0x64, 0x22, 0xce, 0xbb,
+  0xd3, 0xb9, 0x97, 0xbc, 0x95, 0x2a, 0x2b, 0xbc, 0xe9, 0x62, 0xf0, 0x3a, 0xac, 0xb3, 0xf4, 0x3b,
+  0xce, 0xa3, 0x27, 0x3b, 0xf1, 0xb8, 0x16, 0xbc, 0x23, 0xee, 0x27, 0x3c, 0x81, 0xdf, 0x44, 0x3a,
+  0xbd, 0x31, 0xb0, 0x3b, 0xdf, 0x40, 0xf7, 0x3b, 0x45, 0xec, 0x2c, 0xbb, 0x37, 0xae, 0x7d, 0x3a,
+  0x76, 0x34, 0x12, 0x3b, 0x5e, 0xfd, 0xa6, 0x3b, 0x59, 0x76, 0x54, 0x3a, 0x8f, 0xf9, 0x54, 0x3b,
+  0x85, 0x14, 0xe2, 0xba, 0x7e, 0xea, 0xaf, 0xbb, 0x53, 0x6e, 0x26, 0x3c, 0x62, 0xca, 0x19, 0x3c,
+  0xeb, 0x7e, 0x1f, 0x3b, 0xda, 0x2d, 0x8f, 0xbb, 0xc5, 0xaa, 0xb8, 0x3b, 0xef, 0x87, 0x5e, 0xba,
+  0x93, 0x18, 0xa1, 0xbb, 0x4d, 0x92, 0xba, 0xbb, 0xed, 0x6b, 0x31, 0xbb, 0x80, 0x9a, 0x35, 0x3b,
+  0xa1, 0xa2, 0xfb, 0xba, 0xde, 0xc8, 0x15, 0x3c, 0x41, 0x68, 0x8e, 0xbc, 0xec, 0xc3, 0x57, 0xbc,
+  0xb8, 0xe9, 0x94, 0x3b, 0x82, 0xea, 0x43, 0xbb, 0x9a, 0x59, 0x8e, 0x3a, 0xc3, 0x6b, 0x87, 0x3c,
+  0xe9, 0xf0, 0x1b, 0xbc, 0x41, 0x37, 0x32, 0x3b, 0xf6, 0x23, 0x06, 0x3c, 0xa6, 0x30, 0x11, 0x3c,
+  0x12, 0x2b, 0x82, 0xbb, 0xaf, 0xeb, 0x3a, 0xbb, 0x73, 0x46, 0x9a, 0x3c, 0xf7, 0x08, 0x9b, 0x3c,
+  0x2e, 0xb5, 0xaa, 0x3b, 0xd8, 0x69, 0x8a, 0x3c, 0x83, 0x5f, 0x1a, 0xbc, 0x7f, 0xb7, 0xf2, 0xbb,
+  0x5b, 0x7a, 0x90, 0x3b, 0x71, 0x6f, 0x32, 0x3c, 0x25, 0x98, 0xea, 0x3b, 0xa4, 0x28, 0x17, 0x3c,
+  0xe5, 0xf5, 0xb7, 0xb9, 0x7a, 0x66, 0xd5, 0xbb, 0x05, 0x35, 0xed, 0xba, 0x32, 0x26, 0x9e, 0x3b,
+  0xb8, 0x95, 0xb0, 0xbb, 0x4e, 0x0f, 0xc6, 0x3b, 0xb5, 0x92, 0xbf, 0x3a, 0xd8, 0xa2, 0x93, 0x3c,
+  0x11, 0x30, 0xb0, 0x39, 0x91, 0xb0, 0xe5, 0x3b, 0xf2, 0x18, 0x46, 0xba, 0x58, 0x80, 0xe5, 0xbb,
+  0xf4, 0xd4, 0x18, 0xbb, 0x36, 0xa5, 0x4f, 0xbc, 0x3b, 0x70, 0xf7, 0xbb, 0x66, 0x05, 0x96, 0x3a,
+  0x2a, 0x59, 0xd4, 0xbb, 0x6b, 0xbf, 0xad, 0xb9, 0xb9, 0x4a, 0x94, 0x3a, 0xba, 0x16, 0x07, 0x3c,
+  0x29, 0x1b, 0xce, 0xb9, 0xa2, 0x19, 0xad, 0xba, 0x21, 0x4d, 0x5a, 0x3c, 0xce, 0x8d, 0x99, 0x3a,
+  0x3e, 0xca, 0xaf, 0x3b, 0x8d, 0x6c, 0xa4, 0xbb, 0xa8, 0xa1, 0x20, 0x3c, 0x1e, 0xff, 0xb9, 0x3b,
+  0x33, 0xf0, 0xae, 0x3b, 0xd8, 0xc4, 0x82, 0x3c, 0x1a, 0xc7, 0x9c, 0x3c, 0x07, 0x32, 0x00, 0xbc,
+  0xea, 0x41, 0x07, 0x3c, 0xfd, 0xa9, 0x0e, 0x3b, 0x11, 0x12, 0x30, 0x3b, 0x43, 0xd8, 0x11, 0xbc,
+  0x67, 0x60, 0x4e, 0xbb, 0x7f, 0x7d, 0x99, 0x3b, 0x57, 0x86, 0xd8, 0xbb, 0xec, 0x5f, 0x07, 0xbc,
+  0x9c, 0xc9, 0x84, 0xbb, 0x71, 0xc8, 0xed, 0xbb, 0xfb, 0x5f, 0x91, 0xba, 0xaa, 0xdf, 0xca, 0x3b,
+  0x53, 0x4c, 0x5a, 0xbb, 0xf0, 0xd9, 0x93, 0xbb, 0xa2, 0x2e, 0x29, 0xbc, 0xa1, 0xd9, 0x08, 0x38,
+  0x8f, 0x40, 0x76, 0x3b, 0x10, 0x73, 0x90, 0xbc, 0xc0, 0x66, 0x90, 0x3a, 0x8a, 0x71, 0xe4, 0x3b,
+  0x28, 0x09, 0x63, 0xba, 0x33, 0x64, 0xf0, 0x3a, 0x00, 0xed, 0x01, 0xbc, 0x56, 0xbd, 0x7b, 0x3c,
+  0x5f, 0x2c, 0x2b, 0x3c, 0x27, 0x3f, 0xa1, 0x39, 0x51, 0x06, 0x3e, 0xbc, 0xaf, 0x9c, 0x11, 0xbc,
+  0x05, 0xd6, 0x5c, 0xbc, 0xde, 0xac, 0x84, 0x3c, 0xdf, 0xdb, 0x97, 0xbb, 0x5c, 0x16, 0x47, 0x3c,
+  0xd6, 0xe8, 0x26, 0xb8, 0xa1, 0xba, 0xf3, 0x3a, 0x0c, 0x64, 0x39, 0x3a, 0x22, 0xe7, 0x18, 0x3c,
+  0x3c, 0xf4, 0x21, 0xbc, 0xe1, 0x08, 0xd2, 0x3b, 0x1b, 0xe3, 0x1d, 0xbc, 0x04, 0xde, 0x15, 0x3a,
+  0xa9, 0xee, 0x81, 0x3b, 0x1e, 0xa9, 0x26, 0x3b, 0xec, 0x94, 0xb8, 0x3b, 0x78, 0xd7, 0xd4, 0x3b,
+  0x5a, 0x53, 0x74, 0xba, 0x5b, 0x0c, 0x50, 0x3a, 0x13, 0x73, 0x0a, 0x3c, 0xc9, 0x06, 0x89, 0xbb,
+  0x44, 0x1f, 0x99, 0x3c, 0xc9, 0xf1, 0x59, 0xbb, 0x0d, 0x03, 0xad, 0xba, 0x48, 0x04, 0x40, 0x3c,
+  0x52, 0xb4, 0x9c, 0xba, 0x06, 0x0c, 0x8c, 0x3c, 0xe8, 0x90, 0x8c, 0xbb, 0x5b, 0x86, 0x18, 0x3c,
+  0x9b, 0xc8, 0x17, 0xbc, 0x9b, 0xc3, 0x6c, 0x3c, 0x79, 0xbc, 0x8f, 0x3b, 0x1f, 0x26, 0xb2, 0xb9,
+  0x8c, 0x54, 0x9b, 0xbc, 0xf0, 0x6c, 0xbb, 0xbb, 0xde, 0x90, 0x0e, 0x3c, 0x91, 0x21, 0x80, 0xbb,
+  0x5a, 0x60, 0xe1, 0x3a, 0x13, 0x67, 0xbd, 0x3b, 0x64, 0xc2, 0x5b, 0x3c, 0x56, 0x6b, 0x02, 0x3c,
+  0xbc, 0xa4, 0xb5, 0xba, 0xe2, 0xa3, 0x30, 0x3c, 0x1b, 0xc4, 0x65, 0x3c, 0x85, 0xce, 0x26, 0x3a,
+  0x36, 0xb2, 0x17, 0x3c, 0x09, 0xe4, 0x0e, 0xbc, 0xf4, 0xb4, 0x06, 0x3c, 0x47, 0x26, 0xcb, 0xbb,
+  0x28, 0x00, 0x71, 0xbb, 0x15, 0x29, 0x30, 0x3b, 0x91, 0x1f, 0x95, 0xbb, 0x2f, 0xb5, 0x2b, 0x3c,
+  0x72, 0xbd, 0x49, 0xba, 0xb2, 0xf7, 0x27, 0x3c, 0xc3, 0x2c, 0x2d, 0x3c, 0xf1, 0x89, 0x8c, 0xbc,
+  0x95, 0x16, 0x76, 0x3c, 0xa9, 0x97, 0xdf, 0xb8, 0xbc, 0xca, 0x8f, 0x3c, 0x11, 0x5b, 0x0d, 0xbc,
+  0xe3, 0x7e, 0x38, 0xba, 0x0a, 0xa7, 0x85, 0xbb, 0xe8, 0x43, 0x9a, 0xbb, 0x36, 0x89, 0x63, 0x3a,
+  0x4a, 0x17, 0x8a, 0xbc, 0x81, 0x46, 0x26, 0x3c, 0xec, 0xf7, 0xe7, 0xbb, 0x9e, 0xf9, 0x1d, 0x3c,
+  0xcd, 0xa0, 0x80, 0x3b, 0x1c, 0x5a, 0x38, 0xbc, 0xe1, 0xc8, 0x54, 0xbc, 0x18, 0x03, 0x83, 0x3c,
+  0x5c, 0x86, 0x2d, 0xbc, 0xd0, 0x5f, 0xf8, 0xbb, 0xf5, 0x3b, 0x4f, 0x3c, 0x9c, 0x15, 0x4e, 0x3b,
+  0x24, 0x49, 0x30, 0xbc, 0x91, 0x61, 0x81, 0x3b, 0x6c, 0x86, 0x2f, 0xbc, 0x5b, 0x61, 0x5b, 0xbc,
+  0x3a, 0x22, 0x6f, 0x3c, 0xf1, 0xd2, 0x59, 0xb9, 0x5f, 0x90, 0x16, 0x3c, 0x06, 0x4d, 0x35, 0x3c,
+  0xfd, 0xf9, 0x18, 0xbc, 0xc2, 0x09, 0x06, 0x3c, 0xaf, 0x4a, 0xa3, 0xbc, 0x37, 0xe9, 0x01, 0x3c,
+  0x63, 0xdc, 0x39, 0x3c, 0x87, 0xbe, 0x37, 0x3c, 0xc4, 0xdb, 0x06, 0x3b, 0x8d, 0x80, 0x24, 0x3c,
+  0x36, 0x83, 0xa5, 0x3a, 0x57, 0x7a, 0xe3, 0x3c, 0x15, 0xbd, 0xa4, 0xbc, 0xd2, 0x3e, 0x74, 0x3a,
+  0x83, 0x9c, 0x67, 0x3b, 0xba, 0x71, 0xfb, 0x3a, 0x26, 0xad, 0x4e, 0xbc, 0x5d, 0x63, 0x55, 0xbc,
+  0x26, 0xdf, 0x50, 0xba, 0x15, 0xa9, 0xd6, 0x3b, 0xe6, 0xbd, 0xfa, 0xb9, 0x6d, 0xe4, 0x11, 0xbc,
+  0x1e, 0xce, 0xf9, 0xba, 0x44, 0xd3, 0x0f, 0xbb, 0xec, 0xb2, 0xe8, 0xb9, 0x05, 0xfa, 0x5b, 0x3c,
+  0x18, 0x4b, 0x2d, 0x3b, 0x78, 0x8e, 0xa4, 0x3b, 0x50, 0xcb, 0x1a, 0xbb, 0xb2, 0x13, 0x6b, 0xbb,
+  0xd7, 0x42, 0x30, 0xbc, 0xc6, 0xf3, 0x48, 0x3c, 0xf7, 0x05, 0x80, 0x3c, 0x77, 0xd7, 0xac, 0xbb,
+  0x72, 0xbb, 0xe0, 0x3a, 0xe8, 0xd8, 0x2c, 0x3b, 0x47, 0x09, 0x9f, 0x3b, 0xf4, 0x5b, 0x66, 0xbc,
+  0x3e, 0x6c, 0x2c, 0x3c, 0x66, 0x5e, 0x2b, 0xbc, 0xbe, 0xe2, 0xf7, 0x3a, 0x61, 0x8a, 0x6a, 0xbc,
+  0x25, 0xc6, 0x51, 0xbb, 0xb2, 0x62, 0x5d, 0xbb, 0x6b, 0x30, 0x4e, 0xbc, 0xdf, 0x18, 0x28, 0xbb,
+  0x0a, 0x1f, 0xee, 0x3b, 0xd7, 0xc0, 0xf1, 0xba, 0x5f, 0xce, 0x40, 0x3b, 0x2d, 0xd7, 0x27, 0xbb,
+  0x93, 0xda, 0xf3, 0x3b, 0xc9, 0x5d, 0x53, 0x3b, 0x5b, 0xd0, 0x66, 0x3b, 0x7f, 0x75, 0x15, 0x3c,
+  0x66, 0x4b, 0x5b, 0x3b, 0x16, 0x61, 0x03, 0xbb, 0x82, 0xf4, 0x2a, 0x3c, 0xde, 0xf3, 0x07, 0xbc,
+  0xc0, 0x9b, 0x64, 0x3b, 0xde, 0xb0, 0x8b, 0xbc, 0x75, 0x8b, 0x0f, 0x3c, 0x6b, 0x1a, 0x72, 0x3c,
+  0xa8, 0x88, 0x72, 0x3b, 0xef, 0xeb, 0xb9, 0xbb, 0x14, 0x27, 0x36, 0xbc, 0x26, 0x2a, 0x1f, 0x3c,
+  0x0b, 0x0b, 0x30, 0x3b, 0x7f, 0xe1, 0x8b, 0xbb, 0x70, 0x04, 0xf0, 0xbb, 0xb4, 0x99, 0xc1, 0x3b,
+  0x0e, 0xeb, 0x37, 0x3a, 0x5d, 0x4c, 0xb5, 0x3b, 0x18, 0x2b, 0x4f, 0xbc, 0xd8, 0xd8, 0x05, 0x3b,
+  0xd8, 0x2d, 0xd1, 0xbb, 0xda, 0x1b, 0xdd, 0xbb, 0x75, 0xa4, 0x51, 0xbc, 0x55, 0x70, 0xc9, 0xbb,
+  0x94, 0x83, 0x07, 0xbc, 0x38, 0xb5, 0x64, 0x3c, 0x0f, 0x59, 0x97, 0xbb, 0x3a, 0x77, 0x7d, 0x3c,
+  0x32, 0x9e, 0x63, 0x3b, 0x72, 0xc1, 0x4f, 0xba, 0xf5, 0xa9, 0xb7, 0xbb, 0x29, 0x44, 0x27, 0x3b,
+  0x49, 0x2a, 0x0e, 0xbc, 0xb3, 0x75, 0xfc, 0x3b, 0x78, 0xa7, 0xb0, 0xba, 0x22, 0x10, 0xd9, 0x3b,
+  0x48, 0x1f, 0xad, 0x3b, 0xd3, 0x33, 0x5b, 0x3a, 0x5b, 0x2d, 0xc5, 0x3b, 0x0c, 0xbd, 0x9d, 0xbc,
+  0x88, 0x35, 0x53, 0x3b, 0xc3, 0x8c, 0x12, 0xbb, 0xe0, 0x44, 0x95, 0x3c, 0x75, 0x87, 0x98, 0x3b,
+  0x96, 0xf6, 0x5b, 0x3c, 0x75, 0xd7, 0x7f, 0x3c, 0xfe, 0xfc, 0x2c, 0x3b, 0x1c, 0x80, 0x73, 0x3c,
+  0x0e, 0xbb, 0xbe, 0xbb, 0x5d, 0x6c, 0x47, 0x3b, 0x64, 0x8f, 0xd7, 0x3c, 0xb1, 0x14, 0x39, 0x3c,
+  0x90, 0x8b, 0x48, 0xbb, 0x12, 0xc5, 0x28, 0x3c, 0xd0, 0x2c, 0x6c, 0x3c, 0x5c, 0xb6, 0x8d, 0x3c,
+  0x34, 0x2d, 0x12, 0xbb, 0xaf, 0x02, 0x00, 0xbc, 0x64, 0x14, 0x11, 0x3c, 0x51, 0xda, 0x62, 0xbb,
+  0xad, 0xd4, 0x71, 0x3a, 0xfb, 0xc5, 0x93, 0x3b, 0x01, 0x37, 0x33, 0x3c, 0x48, 0x8c, 0x2a, 0x3c,
+  0xda, 0xfa, 0xcc, 0xbb, 0x84, 0xee, 0x69, 0xbb, 0x8c, 0xb9, 0x34, 0x3c, 0x62, 0x33, 0xe3, 0xbb,
+  0xea, 0xe5, 0x99, 0x3a, 0xce, 0xb6, 0x9e, 0x3b, 0xb2, 0xef, 0xb1, 0x3c, 0x03, 0x2c, 0x45, 0xbc,
+  0x2b, 0xb1, 0x65, 0xbc, 0x43, 0x08, 0x91, 0x3c, 0x3d, 0xd8, 0xf5, 0xbb, 0x72, 0x25, 0x67, 0xbb,
+  0x78, 0x23, 0xe7, 0x3b, 0x22, 0xa2, 0x8a, 0xbc, 0xc7, 0xfe, 0x23, 0x3c, 0x03, 0xf4, 0x4e, 0xbc,
+  0x2a, 0x46, 0x05, 0x3b, 0x5d, 0xd8, 0x0a, 0xbb, 0xdc, 0xa7, 0xef, 0xbb, 0xe2, 0x58, 0x37, 0x3c,
+  0xee, 0x60, 0x9e, 0x3b, 0xc4, 0xac, 0x2e, 0xbc, 0x9c, 0xab, 0x8d, 0x3c, 0xab, 0x07, 0x52, 0x3b,
+  0xaf, 0x30, 0xe7, 0xbb, 0x45, 0xc8, 0x03, 0x3c, 0xd0, 0xc0, 0x16, 0x3c, 0x96, 0xd9, 0xa1, 0x3c,
+  0x4e, 0x86, 0xc1, 0xbb, 0x4f, 0xa0, 0xe8, 0xbc, 0x73, 0x94, 0x17, 0xbb, 0xba, 0xc3, 0x60, 0x3b,
+  0x10, 0xb8, 0x04, 0xbc, 0x98, 0x32, 0x16, 0x3c, 0x31, 0x34, 0xaa, 0x3b, 0x63, 0x51, 0x76, 0xbc,
+  0x9e, 0x98, 0xf0, 0xbb, 0x76, 0x9a, 0x22, 0xbc, 0x11, 0x33, 0x74, 0xbb, 0x0e, 0x5e, 0x55, 0x3c,
+  0x28, 0x03, 0x8c, 0x3b, 0x56, 0x87, 0x74, 0x3b, 0x61, 0x37, 0x74, 0x3c, 0xb5, 0xdf, 0x21, 0x3c,
+  0x1b, 0x4d, 0xe2, 0xbb, 0xaf, 0x00, 0x16, 0x3b, 0xbd, 0xb3, 0x6b, 0x3a, 0x86, 0x7d, 0x87, 0xbc,
+  0x9d, 0x7f, 0x8d, 0x3b, 0x84, 0x48, 0xf1, 0x3b, 0xdd, 0xeb, 0x2d, 0x3c, 0x51, 0x4c, 0xf3, 0x3b,
+  0x15, 0x54, 0xb0, 0x39, 0x9e, 0x6d, 0xba, 0x3c, 0x1f, 0x4c, 0xe0, 0xbb, 0xb5, 0x8c, 0x7c, 0xbc,
+  0xb4, 0x5d, 0x99, 0x3c, 0x56, 0x52, 0x87, 0xba, 0x3c, 0x9c, 0xec, 0xbb, 0x8f, 0x4b, 0xd6, 0x3b,
+  0x74, 0x43, 0xe3, 0x3b, 0xdf, 0xb0, 0x65, 0x3b, 0x38, 0xb2, 0x4f, 0xbc, 0xce, 0xea, 0x4c, 0x3b,
+  0x1c, 0xbf, 0xab, 0x3b, 0xbf, 0x67, 0x3f, 0x3c, 0x82, 0xe4, 0x56, 0xba, 0x43, 0x7c, 0xf2, 0x3b,
+  0x7d, 0x3b, 0x39, 0x3a, 0xa0, 0x1b, 0x6b, 0x3b, 0xd0, 0xa9, 0xbe, 0xbb, 0xef, 0xdb, 0x5b, 0x3b,
+  0x34, 0xee, 0x00, 0x3c, 0x43, 0xb4, 0x41, 0xbc, 0x44, 0x79, 0x21, 0xbb, 0xb3, 0x4a, 0xc4, 0xbb,
+  0x35, 0xa1, 0x88, 0xbb, 0x2e, 0x52, 0xa5, 0x3b, 0x74, 0x9b, 0x65, 0xbb, 0xdb, 0x3d, 0x22, 0x3c,
+  0x52, 0x54, 0x3d, 0x3c, 0xda, 0xfa, 0x91, 0x3c, 0x07, 0x39, 0xbe, 0x3b, 0xa8, 0xe4, 0x1e, 0x3c,
+  0x3b, 0x79, 0x89, 0x3a, 0x70, 0x67, 0x7d, 0x3b, 0x20, 0xd2, 0x95, 0x3b, 0x49, 0xc3, 0xe9, 0x3b,
+  0xbf, 0x5f, 0xff, 0x3b, 0xfa, 0xf2, 0x1f, 0xbc, 0x7b, 0x69, 0x0b, 0xbc, 0x03, 0x3b, 0x48, 0x3c,
+  0xb6, 0x21, 0xdb, 0x3a, 0xd7, 0xca, 0x1e, 0x3c, 0x3a, 0xd5, 0xe5, 0x3b, 0x05, 0x6f, 0x31, 0xbb,
+  0xeb, 0x71, 0x90, 0x3c, 0x99, 0xde, 0xd7, 0xb9, 0x57, 0x01, 0x3d, 0x3c, 0x46, 0x30, 0xc5, 0x3b,
+  0xb9, 0x4f, 0xb1, 0x3b, 0x9d, 0x6d, 0x2b, 0xbc, 0x80, 0xe6, 0x72, 0x3c, 0x7a, 0x90, 0x9b, 0x3c,
+  0xc8, 0x07, 0xf5, 0x3b, 0x87, 0x7f, 0xb5, 0x3b, 0xec, 0x55, 0x44, 0xbc, 0xe0, 0x20, 0x0b, 0xbc,
+  0x03, 0xbf, 0x8e, 0xbb, 0x76, 0x07, 0x3b, 0xbb, 0x2a, 0x1a, 0xb4, 0x3a, 0x29, 0xbe, 0x24, 0x3c,
+  0x34, 0x4d, 0xb7, 0x3b, 0x3d, 0x0d, 0x66, 0x3c, 0x81, 0x43, 0x25, 0x3a, 0xf5, 0x73, 0x6d, 0x39,
+  0x00, 0xc8, 0x0e, 0x3c, 0xc8, 0x4d, 0x0c, 0xbc, 0x5a, 0x35, 0x27, 0x3a, 0xa2, 0x8f, 0xe3, 0xbb,
+  0x0d, 0xc4, 0x70, 0xbb, 0x56, 0x66, 0xaa, 0x3b, 0x54, 0x2c, 0xca, 0xbb, 0xa3, 0x8f, 0xd8, 0xba,
+  0xea, 0xd8, 0xdc, 0x3a, 0xb5, 0xf3, 0x80, 0xbb, 0x40, 0xd2, 0x83, 0x3a, 0x82, 0x18, 0x6d, 0x3c,
+  0x2b, 0xb2, 0xe2, 0x3b, 0x4d, 0x58, 0xcb, 0xbb, 0x83, 0x4f, 0x85, 0x3a, 0x6f, 0x52, 0x00, 0x3c,
+  0xbe, 0x1c, 0xa4, 0xba, 0x9b, 0x66, 0x60, 0x3b, 0x58, 0xdf, 0xaf, 0x3b, 0x0d, 0xf1, 0x85, 0x3b,
+  0x2d, 0x8b, 0xa9, 0x3a, 0x70, 0x6b, 0xf7, 0x3b, 0xd2, 0x77, 0xf3, 0x3c, 0x19, 0x80, 0x7a, 0x3b,
+  0x27, 0x4c, 0xe2, 0x3b, 0x41, 0x12, 0xb9, 0x3b, 0x74, 0x6e, 0xba, 0xbb, 0x7d, 0x9d, 0x44, 0xbc,
+  0xbb, 0xf0, 0xd9, 0xba, 0xb7, 0x60, 0x59, 0x3c, 0x44, 0xb3, 0x99, 0x3c, 0x47, 0x1e, 0x4e, 0x3c,
+  0x58, 0x5f, 0x15, 0xbc, 0xed, 0xfe, 0x6f, 0xbc, 0xf9, 0xcf, 0x7c, 0x3b, 0x78, 0x88, 0x8b, 0xbc,
+  0x87, 0xe1, 0x9a, 0xbc, 0xbd, 0xe6, 0xe9, 0xbb, 0x4b, 0x85, 0x67, 0x3c, 0x7b, 0x46, 0x66, 0x3b,
+  0xf0, 0xbb, 0x09, 0x3c, 0x1c, 0x22, 0xf0, 0xbb, 0xe2, 0x2e, 0xfb, 0x3b, 0xf2, 0x24, 0x0f, 0xbb,
+  0xc4, 0x44, 0xdd, 0xbc, 0xa0, 0x61, 0x7d, 0x3b, 0x86, 0xa1, 0xed, 0x3b, 0xa9, 0xed, 0xc4, 0x3a,
+  0x98, 0xab, 0x62, 0x3c, 0x32, 0xcc, 0x8c, 0xbc, 0x0f, 0xb5, 0x8a, 0x3c, 0x83, 0xe3, 0xdc, 0x3a,
+  0xbf, 0xbb, 0x63, 0xbb, 0xbc, 0xad, 0x9c, 0x3b, 0x6f, 0x5d, 0x92, 0xb9, 0x02, 0x88, 0x7a, 0x3b,
+  0xbc, 0x45, 0xe0, 0x3b, 0x6c, 0xb9, 0xd7, 0xbc, 0x7b, 0x24, 0xe0, 0x3c, 0x03, 0x0f, 0x96, 0x3b,
+  0xdb, 0xbb, 0x02, 0x3a, 0xc0, 0x27, 0x55, 0x3b, 0xab, 0xbf, 0x1b, 0xbc, 0x8d, 0x88, 0x77, 0xbc,
+  0xa0, 0x70, 0x24, 0x3b, 0x05, 0x89, 0x3e, 0xbc, 0xe5, 0x30, 0x1b, 0x3c, 0x15, 0x16, 0x9d, 0xbc,
+  0xd3, 0x91, 0x6f, 0xbc, 0x22, 0x2b, 0x32, 0xbb, 0x70, 0x29, 0xa3, 0xbc, 0x0f, 0xdf, 0x82, 0xbb,
+  0x89, 0xab, 0x15, 0xbc, 0x01, 0x27, 0x90, 0xbc, 0x51, 0x29, 0xe0, 0xb9, 0x72, 0xc1, 0x60, 0x3c,
+  0x8d, 0x11, 0xb3, 0xbb, 0x47, 0x9f, 0x30, 0x3c, 0xb7, 0x93, 0xe5, 0x3b, 0xaa, 0x66, 0x5b, 0x3c,
+  0x4f, 0x02, 0x8e, 0xbc, 0xbf, 0xc8, 0x14, 0xbc, 0xb2, 0x57, 0xe8, 0xb9, 0x9c, 0x4d, 0xd7, 0xb9,
+  0x1e, 0x0d, 0x05, 0x3b, 0x2a, 0x92, 0x18, 0x3c, 0x96, 0x17, 0xb2, 0xbb, 0x98, 0xa1, 0x41, 0xbc,
+  0x33, 0x0a, 0xb4, 0xbc, 0xae, 0x18, 0x0e, 0x3c, 0x91, 0xc6, 0x92, 0xbc, 0x5a, 0x0b, 0x77, 0xbc,
+  0x69, 0xe6, 0x15, 0x3c, 0x4d, 0x6a, 0x05, 0x3c, 0xcd, 0xc4, 0x8a, 0x3c, 0xf4, 0x59, 0xd6, 0x3b,
+  0x22, 0x80, 0x4c, 0xbb, 0xd3, 0x79, 0xc1, 0x3c, 0x11, 0xbc, 0x8b, 0xbc, 0xea, 0xc7, 0x05, 0xbc,
+  0x2e, 0x98, 0x50, 0x3b, 0x85, 0x09, 0x9f, 0x3b, 0x19, 0x08, 0x78, 0x3c, 0xaf, 0xb8, 0xd4, 0xbb,
+  0xfd, 0xf5, 0x60, 0xbb, 0x32, 0xce, 0x18, 0x3c, 0x0d, 0xb8, 0xfc, 0xb9, 0x4a, 0x7b, 0x5d, 0x3c,
+  0x28, 0x73, 0xa4, 0x3c, 0x5f, 0x2b, 0x80, 0xbc, 0x4e, 0x0b, 0x90, 0xbc, 0x3c, 0x34, 0x42, 0xbc,
+  0x7d, 0x8e, 0x04, 0x3c, 0x6d, 0x60, 0xd7, 0xbb, 0x2b, 0x3e, 0xb1, 0xba, 0x2d, 0x85, 0x2b, 0xbb,
+  0x34, 0x4d, 0x9e, 0x3c, 0x30, 0x78, 0x3c, 0xb9, 0xe6, 0xde, 0x27, 0x3c, 0x55, 0xcb, 0xc4, 0x3a,
+  0x47, 0x96, 0x99, 0x3a, 0x23, 0x02, 0x7a, 0x3c, 0xdc, 0x25, 0x69, 0x3b, 0xeb, 0x70, 0x8b, 0xbb,
+  0x2e, 0xc2, 0x47, 0x3c, 0x54, 0x2c, 0x11, 0x3c, 0xb2, 0x86, 0x14, 0x3c, 0x21, 0xd4, 0x97, 0xbb,
+  0x6c, 0x7b, 0x8b, 0x3b, 0xae, 0xec, 0x5f, 0xba, 0x87, 0x88, 0xd1, 0xba, 0x8d, 0x8d, 0x78, 0x3c,
+  0x7e, 0xa2, 0x1c, 0x3c, 0x7a, 0x4c, 0xad, 0xbb, 0x0a, 0x59, 0xb2, 0xbb, 0x0b, 0xc9, 0x02, 0xbb,
+  0x88, 0x13, 0x20, 0x3c, 0xee, 0x54, 0xe1, 0x3b, 0xda, 0xcf, 0x33, 0x3c, 0x44, 0x57, 0x7a, 0xba,
+  0x11, 0xba, 0x27, 0x3c, 0x51, 0x21, 0xde, 0x3a, 0x43, 0x8c, 0x67, 0xbb, 0xe3, 0x93, 0x98, 0xbb,
+  0xe3, 0x84, 0x63, 0x3c, 0x67, 0xda, 0x9c, 0xbb, 0x91, 0x04, 0x52, 0x3c, 0x1f, 0x8a, 0x5e, 0xbc,
+  0x21, 0x7b, 0x09, 0xbc, 0x2b, 0x41, 0x9f, 0xba, 0x81, 0x46, 0x54, 0xb8, 0x95, 0xdf, 0x31, 0xbc,
+  0xfb, 0xca, 0x0f, 0xbc, 0x38, 0x76, 0xc5, 0xbc, 0x77, 0x7c, 0xf1, 0x3b, 0xd6, 0x7e, 0x7c, 0x3c,
+  0x5e, 0x94, 0x12, 0x3b, 0x30, 0x04, 0x43, 0x3a, 0xeb, 0x22, 0xc9, 0x3b, 0xb8, 0xc1, 0x36, 0x3b,
+  0x6c, 0x39, 0x18, 0x3b, 0x95, 0xaa, 0x80, 0xbb, 0x4a, 0xdf, 0x08, 0xbc, 0x61, 0x69, 0x80, 0xbc,
+  0x67, 0x10, 0x2a, 0x3c, 0xca, 0x63, 0x33, 0x3c, 0xc0, 0x8d, 0x49, 0xbc, 0x3d, 0x8b, 0xe5, 0xbb,
+  0xf2, 0x1c, 0xf9, 0x3b, 0xe8, 0xb5, 0xce, 0xbb, 0xba, 0xd5, 0x3b, 0x3b, 0x0e, 0x75, 0x0a, 0x3b,
+  0x8d, 0x9e, 0x8f, 0xbc, 0xb4, 0x76, 0x13, 0xbb, 0xc9, 0x68, 0x43, 0xbc, 0x6f, 0x22, 0x7c, 0xbb,
+  0xed, 0x13, 0x49, 0x3a, 0x4c, 0x82, 0x04, 0x3c, 0xc1, 0xca, 0xcc, 0xb9, 0x28, 0x9b, 0xc5, 0x3b,
+  0xe3, 0x59, 0xa1, 0x3b, 0x67, 0x9f, 0x35, 0xbb, 0x17, 0x55, 0x99, 0x3c, 0x86, 0x38, 0x9d, 0x3b,
+  0xc3, 0x22, 0xfd, 0xba, 0xe3, 0x51, 0x39, 0xbc, 0xc5, 0xca, 0x02, 0x3c, 0x1e, 0xa2, 0x32, 0x3c,
+  0xf1, 0x26, 0x01, 0xbc, 0x1b, 0x25, 0xd3, 0x3b, 0xbb, 0x47, 0xcc, 0x3b, 0x86, 0x11, 0x0d, 0xbc,
+  0xd1, 0x73, 0x81, 0xbc, 0x43, 0x13, 0x89, 0xbc, 0xc8, 0x2f, 0xe4, 0xbb, 0xc7, 0x4c, 0x24, 0x3c,
+  0x98, 0x6f, 0xa3, 0xbc, 0x5d, 0x79, 0x93, 0xbb, 0x93, 0x81, 0xc8, 0x37, 0x8e, 0xfb, 0x05, 0xbc,
+  0xed, 0xd9, 0xb2, 0x3c, 0x9a, 0x03, 0x4f, 0xbc, 0x41, 0x03, 0x8f, 0x3c, 0x5e, 0x8f, 0xca, 0xba,
+  0x03, 0x09, 0xaa, 0xbc, 0x11, 0xc5, 0xe2, 0x3a, 0x8d, 0x3d, 0xf9, 0xbb, 0x3c, 0x1a, 0x7b, 0x3b,
+  0x76, 0x87, 0x7b, 0x3b, 0x18, 0x44, 0x12, 0xbc, 0xb9, 0x98, 0x84, 0x3c, 0x7b, 0xf5, 0x52, 0x3b,
+  0x1a, 0x99, 0x72, 0xbc, 0x04, 0x28, 0x91, 0x3b, 0x15, 0x04, 0xbc, 0xbc, 0xc6, 0xe4, 0xab, 0x3b,
+  0x14, 0xa5, 0x38, 0x3c, 0xd8, 0x1d, 0x4e, 0xbc, 0x13, 0xc4, 0xf5, 0x3c, 0x6b, 0xe6, 0x99, 0x3b,
+  0x0a, 0x96, 0x54, 0xbc, 0x4b, 0xdb, 0x6b, 0xbc, 0xf6, 0xda, 0x65, 0xbb, 0x7e, 0x13, 0x7c, 0x3b,
+  0xd6, 0xd6, 0x92, 0x3a, 0xba, 0x6d, 0xa6, 0xbc, 0x84, 0x85, 0x11, 0x3c, 0x24, 0xe9, 0x21, 0x3c,
+  0x58, 0xba, 0x03, 0xbd, 0x92, 0xe0, 0xbe, 0xb8, 0xe9, 0x4d, 0xd6, 0x3b, 0x50, 0x05, 0x74, 0xbb,
+  0xaf, 0xbc, 0x6d, 0xbc, 0xff, 0x92, 0xd3, 0xbc, 0x84, 0xce, 0x19, 0xbc, 0x7c, 0x9b, 0xdb, 0x3b,
+  0xed, 0x82, 0x4e, 0xbc, 0x57, 0xe7, 0x01, 0xbc, 0xc2, 0xfd, 0x21, 0x3c, 0xd4, 0x85, 0x06, 0x3c,
+  0xd4, 0x9a, 0xd1, 0xbc, 0x81, 0xf6, 0x80, 0xbc, 0xa3, 0xe4, 0x52, 0xbb, 0x0a, 0x75, 0xca, 0x3a,
+  0x8c, 0xfa, 0x85, 0x3c, 0xfc, 0x96, 0xfb, 0x3b, 0xd8, 0xf4, 0x26, 0xbb, 0x0a, 0x57, 0x51, 0xbb,
+  0x7c, 0xf5, 0x50, 0xbc, 0xe6, 0x1a, 0x79, 0x3b, 0xf2, 0xa2, 0x76, 0xbc, 0xe0, 0x2d, 0x09, 0x3c,
+  0x93, 0x7e, 0x00, 0x3c, 0xbf, 0x8f, 0xe8, 0xba, 0x1c, 0x93, 0x32, 0xbb, 0x37, 0x35, 0x45, 0x39,
+  0x9e, 0xec, 0x74, 0xbb, 0xb0, 0x7f, 0xbb, 0x3c, 0x72, 0x63, 0x50, 0xbc, 0x59, 0x67, 0x7b, 0x3b,
+  0x40, 0xaa, 0x1e, 0x3c, 0xbd, 0x41, 0x3e, 0xbc, 0x00, 0x39, 0x0c, 0x3c, 0x02, 0xa8, 0x67, 0xbc,
+  0x75, 0x8c, 0xf7, 0x3a, 0xc5, 0xec, 0x45, 0x3c, 0xa2, 0x83, 0xaf, 0x3b, 0xac, 0x62, 0x2f, 0xbb,
+  0x73, 0x5e, 0xc7, 0x3c, 0x4d, 0xa1, 0xd3, 0xbb, 0xb9, 0xc1, 0x1a, 0xbc, 0xe2, 0x33, 0x6e, 0xba,
+  0xae, 0xc9, 0x6d, 0xbb, 0x84, 0x54, 0x8f, 0x3c, 0xbc, 0x09, 0x7c, 0xbb, 0xf0, 0x4e, 0x81, 0x3c,
+  0x67, 0xec, 0x9c, 0x3c, 0x32, 0x4c, 0x03, 0xbc, 0xd2, 0xc1, 0x22, 0xb9, 0x67, 0xb2, 0x84, 0xbc,
+  0xf4, 0x13, 0x3a, 0xba, 0x11, 0x3a, 0xa9, 0x3c, 0x83, 0x50, 0xc7, 0x3a, 0x9b, 0x82, 0x0a, 0xbb,
+  0xc9, 0x53, 0x01, 0x3c, 0xa4, 0xb5, 0xc1, 0x3b, 0xdd, 0x14, 0xc0, 0xbc, 0x4f, 0xf5, 0xcf, 0xba,
+  0x85, 0x95, 0x43, 0x3c, 0xab, 0x5a, 0x96, 0x3b, 0xf4, 0x7c, 0xba, 0x3b, 0x0d, 0xef, 0xd5, 0xbb,
+  0x4c, 0xe5, 0x8e, 0xbb, 0x90, 0xbb, 0xc0, 0x3b, 0xc4, 0x70, 0xd8, 0xba, 0xf7, 0x85, 0x8a, 0x3a,
+  0xc6, 0x18, 0x59, 0x3c, 0xc0, 0x15, 0x80, 0xbc, 0xc1, 0x84, 0x94, 0x3c, 0x96, 0x27, 0xcb, 0x3b,
+  0x53, 0x3c, 0xff, 0xbb, 0xbe, 0x21, 0xb3, 0x3b, 0x33, 0x11, 0xc4, 0xbc, 0x97, 0xc5, 0x24, 0x3c,
+  0x4e, 0x1d, 0x1f, 0xbb, 0x40, 0xdd, 0x19, 0xbc, 0xfc, 0x38, 0x9a, 0x3c, 0xff, 0xc8, 0x9f, 0xbb,
+  0x33, 0xc6, 0x5d, 0xbb, 0x19, 0x85, 0x54, 0xbc, 0xe6, 0x13, 0x6a, 0xbc, 0x41, 0xb8, 0x17, 0xbb,
+  0xf0, 0xd7, 0xa3, 0xba, 0xae, 0xe8, 0x9b, 0xbc, 0x2b, 0x79, 0x9b, 0x3c, 0xaf, 0x91, 0x1d, 0xbc,
+  0xfe, 0xa5, 0x35, 0xbc, 0x8b, 0x8f, 0xe2, 0xbb, 0xd5, 0xe3, 0xd1, 0xbc, 0x5d, 0xd1, 0x91, 0x3b,
+  0xa8, 0xe0, 0x7f, 0x3a, 0x83, 0x25, 0x37, 0x3b, 0xf8, 0x09, 0xbd, 0x3b, 0x7f, 0x57, 0x32, 0xbb,
+  0xe9, 0xc9, 0x15, 0x3b, 0x06, 0x37, 0x1c, 0x3a, 0x71, 0xca, 0xa8, 0xbc, 0xbe, 0x6d, 0x9b, 0x3b,
+  0xb3, 0x94, 0x8a, 0x3a, 0x1e, 0xa8, 0x2a, 0xbb, 0xb5, 0x92, 0xfb, 0x3a, 0xae, 0x48, 0x31, 0x3c,
+  0x2b, 0x9d, 0x87, 0xbc, 0x43, 0x9b, 0x6c, 0xba, 0x0d, 0x69, 0x26, 0xbc, 0x58, 0x60, 0xf1, 0xbb,
+  0xc6, 0x62, 0x88, 0x3b, 0x90, 0x26, 0xf7, 0x3b, 0x87, 0xa3, 0x0b, 0x3c, 0x51, 0x82, 0xe7, 0xb9,
+  0xba, 0xea, 0xe6, 0x38, 0x63, 0x10, 0x7b, 0xbc, 0x3e, 0x91, 0x94, 0x3c, 0x49, 0xa2, 0x94, 0xbb,
+  0x49, 0xa7, 0x17, 0xbc, 0x94, 0xba, 0xbc, 0xbb, 0x42, 0x02, 0x33, 0x38, 0xe4, 0xb2, 0xdd, 0xbb,
+  0xf3, 0x0a, 0x3b, 0xbb, 0xd2, 0x41, 0x4e, 0x3b, 0x2c, 0x7c, 0x3d, 0x3a, 0x78, 0x3f, 0xae, 0xbb,
+  0xca, 0x6d, 0x3a, 0x3b, 0xdb, 0xa8, 0x38, 0xbc, 0xe5, 0x90, 0xaa, 0x3a, 0xda, 0x4d, 0xa4, 0xba,
+  0xf5, 0x67, 0x8d, 0xbc, 0x14, 0x8b, 0xda, 0xbb, 0xbe, 0x38, 0xf3, 0xbc, 0x86, 0xac, 0x01, 0xba,
+  0x45, 0xf7, 0xac, 0x3b, 0x71, 0x04, 0xa6, 0xbc, 0x14, 0x13, 0x92, 0x3c, 0x0e, 0x28, 0xe6, 0x3a,
+  0xb1, 0xe8, 0x35, 0xbc, 0x00, 0x1f, 0xf8, 0xbb, 0x1d, 0x33, 0x97, 0xbc, 0x3d, 0xc0, 0x73, 0x3b,
+  0x43, 0x35, 0x8f, 0x3b, 0x15, 0x1f, 0xe8, 0xbc, 0x8b, 0xf1, 0x88, 0x3c, 0xab, 0xc9, 0x0a, 0x3c,
+  0x83, 0xe4, 0x98, 0xbb, 0x65, 0xb0, 0x16, 0x3c, 0xc0, 0x88, 0x04, 0x3c, 0xaf, 0xad, 0xd3, 0xbb,
+  0x3c, 0x53, 0x3d, 0x3c, 0x5b, 0xb6, 0xf8, 0xbb, 0x39, 0xac, 0xcb, 0x3c, 0x0c, 0x7c, 0x64, 0xba,
+  0x2d, 0x98, 0x80, 0xba, 0x2c, 0xd3, 0x11, 0xbc, 0x29, 0xf5, 0x28, 0xbc, 0xa1, 0x3f, 0x84, 0x3a,
+  0x5c, 0x32, 0x38, 0x3c, 0xa4, 0x97, 0x8d, 0xbc, 0x93, 0xcc, 0x50, 0x3c, 0x20, 0x9b, 0x54, 0x3c,
+  0x46, 0x45, 0x2b, 0xbc, 0xc0, 0xd2, 0x6e, 0xba, 0xce, 0x28, 0x2a, 0xbc, 0xed, 0x81, 0x7b, 0xba,
+  0x48, 0xe8, 0xd6, 0xbb, 0xa7, 0x05, 0xea, 0xbc, 0xc8, 0xf9, 0xbc, 0xba, 0xbf, 0x9f, 0x08, 0x3b,
+  0xd8, 0x1d, 0x38, 0xbc, 0x5a, 0x9a, 0xc9, 0x3b, 0xfc, 0xb7, 0xd0, 0x3b, 0x08, 0x40, 0x8c, 0x3b,
+  0x12, 0x36, 0xd2, 0xbc, 0xb4, 0x7e, 0xac, 0xbc, 0xfc, 0xff, 0x6f, 0xbc, 0x02, 0x69, 0x09, 0x3b,
+  0x12, 0x3e, 0x6b, 0x3c, 0xbf, 0xaa, 0x85, 0xb9, 0x76, 0x5a, 0xf0, 0x3b, 0x63, 0x49, 0x05, 0xbc,
+  0xc0, 0xbb, 0xa5, 0xbc, 0xa5, 0x34, 0xed, 0x3b, 0x09, 0xba, 0xa7, 0xbc, 0xde, 0xb2, 0x7c, 0xbb,
+  0x29, 0xf8, 0x94, 0x3c, 0x93, 0xaf, 0xa3, 0xbc, 0xb0, 0x9b, 0xc8, 0x3c, 0xa0, 0x7e, 0x3e, 0xbc,
+  0x78, 0x01, 0xb3, 0xbb, 0x0b, 0xf8, 0xe7, 0x3c, 0x9b, 0x04, 0xe6, 0xbb, 0x67, 0x50, 0x3e, 0xbc,
+  0xf7, 0x0f, 0xe0, 0x3c, 0x96, 0x72, 0x3c, 0xbc, 0xa4, 0x4e, 0x78, 0x3b, 0x8b, 0xfa, 0x50, 0xbc,
+  0x98, 0x76, 0x23, 0x3a, 0xfc, 0x33, 0x92, 0x3a, 0xc5, 0x1f, 0xe0, 0x3a, 0x8b, 0x6a, 0x9c, 0xbb,
+  0x21, 0x04, 0x41, 0x3c, 0x21, 0x6d, 0x9b, 0x3b, 0x7d, 0x0a, 0xbe, 0xbc, 0x5b, 0x08, 0x23, 0xbc,
+  0xbf, 0x03, 0xaf, 0x3b, 0xbb, 0xf9, 0x22, 0x3c, 0x4c, 0x8a, 0x8a, 0xbb, 0xad, 0x72, 0xe0, 0x3b,
+  0x42, 0xe3, 0x8a, 0x3c, 0x66, 0xb3, 0xa1, 0xbb, 0x31, 0x13, 0xc3, 0xbb, 0xc4, 0x22, 0x9c, 0xbc,
+  0xd5, 0xd6, 0xbf, 0xbb, 0x52, 0x3f, 0x31, 0x3c, 0x4f, 0x4d, 0x8a, 0x3c, 0x7f, 0xb3, 0x91, 0x3c,
+  0x15, 0x96, 0x1c, 0x3c, 0xf4, 0x73, 0x2d, 0x3a, 0x71, 0x66, 0xa0, 0xbc, 0x95, 0x4a, 0xaa, 0xba,
+  0xb9, 0x0a, 0x68, 0xbb, 0xc1, 0x0d, 0x73, 0x3c, 0x04, 0x9c, 0x53, 0x3c, 0xe1, 0x77, 0x06, 0x3c,
+  0xa7, 0x35, 0x95, 0x3b, 0x57, 0x71, 0x3e, 0x3c, 0x33, 0xb3, 0xb0, 0xbb, 0x66, 0xb6, 0xa7, 0xbb,
+  0x9b, 0xab, 0xec, 0x3b, 0x6b, 0x01, 0x7e, 0xbc, 0xc8, 0xe1, 0xb2, 0x3c, 0x89, 0xc0, 0x30, 0x3a,
+  0x7d, 0xd1, 0x52, 0xbc, 0x5a, 0x25, 0x92, 0xbc, 0x13, 0xeb, 0x6c, 0xbc, 0x35, 0x53, 0xd7, 0xbb,
+  0x31, 0x5b, 0x1a, 0x3c, 0x41, 0x97, 0x38, 0xbb, 0xb1, 0x69, 0xa3, 0x3c, 0x82, 0xe6, 0x2b, 0xb8,
+  0xdf, 0xc0, 0x68, 0xbc, 0xcd, 0xf4, 0x2f, 0xbc, 0x0b, 0x8b, 0xd9, 0xba, 0x3b, 0x5f, 0xdf, 0x3b,
+  0x5a, 0xb5, 0x03, 0xbb, 0xd9, 0x48, 0xf5, 0xbc, 0x5e, 0xbd, 0xce, 0x3c, 0x4e, 0x4b, 0x80, 0x3b,
+  0xe9, 0xab, 0xa2, 0xbb, 0xe3, 0x85, 0x53, 0xbb, 0x95, 0xf6, 0x1f, 0xbc, 0x40, 0x13, 0x42, 0x39,
+  0x13, 0xe2, 0x3e, 0x3b, 0x1d, 0x03, 0x6d, 0xb9, 0x7e, 0xe8, 0xb1, 0x3b, 0x74, 0xdb, 0x9a, 0xbb,
+  0x4d, 0xe5, 0x18, 0x3a, 0x4b, 0x5b, 0x64, 0xba, 0x16, 0x81, 0x2b, 0xbc, 0x61, 0x53, 0xb2, 0x3b,
+  0x25, 0xdd, 0x7c, 0x3b, 0x01, 0x59, 0x1e, 0x3b, 0x97, 0xc4, 0x5b, 0xbc, 0x4e, 0x0d, 0x2e, 0xbc,
+  0xca, 0xb0, 0xa2, 0xbc, 0xf5, 0xd0, 0xa9, 0xba, 0x4f, 0x57, 0x0a, 0xbc, 0x4b, 0xfc, 0xcc, 0xbb,
+  0x25, 0xe9, 0xb4, 0x3b, 0xe6, 0x0a, 0xb8, 0x3b, 0x25, 0x23, 0xc4, 0x3b, 0xa5, 0x2e, 0x60, 0x3a,
+  0x55, 0xa9, 0xb2, 0xba, 0x2c, 0x8f, 0x0f, 0xbc, 0xf6, 0x4c, 0x32, 0x3c, 0x8f, 0x8a, 0xfe, 0x3b,
+  0x59, 0x30, 0x14, 0x3c, 0x5a, 0x0f, 0xb1, 0xba, 0xa5, 0xe1, 0x60, 0x3b, 0x04, 0x14, 0xd6, 0x3a,
+  0x6b, 0xa0, 0x72, 0xbb, 0x14, 0x3b, 0xbc, 0x3b, 0xcc, 0x27, 0xae, 0xbc, 0xf8, 0xfe, 0x17, 0xbc,
+  0x9b, 0xdf, 0x8c, 0xba, 0xf8, 0xc3, 0x60, 0x3b, 0x7e, 0x67, 0xc2, 0xbb, 0x2f, 0x6d, 0x09, 0xbc,
+  0xe3, 0x11, 0xc1, 0xbb, 0x85, 0x5f, 0xbf, 0x3a, 0xec, 0xca, 0xf4, 0xbc, 0x4d, 0x0b, 0x3d, 0x3c,
+  0xc7, 0xdf, 0xaa, 0x3c, 0x10, 0xd3, 0xb8, 0xbc, 0xe9, 0xf0, 0xc8, 0x3c, 0x1b, 0xe6, 0x9c, 0xbc,
+  0xc7, 0x39, 0x91, 0xbc, 0x36, 0xed, 0x47, 0xbb, 0xc5, 0xd0, 0x14, 0xbc, 0x3d, 0xd7, 0xf4, 0x3b,
+  0x49, 0x28, 0x5d, 0x3c, 0xb2, 0x10, 0x67, 0xbc, 0xc6, 0x8a, 0xd8, 0x3c, 0xcd, 0xf4, 0xa1, 0x3b,
+  0x94, 0x56, 0x2e, 0xbc, 0xf0, 0x92, 0x99, 0xba, 0x7a, 0xf1, 0x96, 0xbb, 0x4c, 0x2a, 0x05, 0xbc,
+  0x15, 0x3e, 0x7b, 0x3c, 0x3d, 0xe5, 0x12, 0xbc, 0x70, 0x43, 0xc3, 0x3c, 0xf3, 0xf6, 0x89, 0xbb,
+  0x3b, 0xd4, 0xab, 0xbb, 0x16, 0xf1, 0xce, 0xbb, 0xa4, 0x17, 0xd5, 0xbc, 0xb5, 0xf5, 0xd1, 0xba,
+  0x00, 0xab, 0x9a, 0x3b, 0xad, 0xd7, 0xbf, 0xbc, 0x3f, 0x58, 0xd0, 0x3b, 0xe6, 0x4c, 0xf8, 0x3b,
+  0xcf, 0xf4, 0x83, 0xbc, 0x12, 0x82, 0x4d, 0x3b, 0x1f, 0x67, 0x39, 0x3c, 0x61, 0x88, 0x00, 0x3c,
+  0xce, 0x25, 0xf9, 0xbb, 0x88, 0x35, 0xa3, 0xbc, 0xf2, 0x75, 0xc0, 0x3b, 0x7a, 0xb2, 0xf4, 0x3a,
+  0xec, 0x44, 0x28, 0xbc, 0xae, 0xcd, 0x48, 0x3c, 0x13, 0x01, 0x5d, 0xbb, 0x82, 0xe7, 0x75, 0x3b,
+  0x35, 0x70, 0xeb, 0xbc, 0x6e, 0x6f, 0xd1, 0xbc, 0xad, 0x41, 0x58, 0xbc, 0x22, 0x53, 0xab, 0x3b,
+  0xef, 0xc9, 0x46, 0x3c, 0xc1, 0x8b, 0xe6, 0xba, 0x8a, 0x7c, 0x9f, 0x3c, 0x88, 0x74, 0xa0, 0xbb,
+  0x7c, 0xdb, 0x1c, 0xbc, 0x22, 0x66, 0x57, 0x3b, 0x33, 0x66, 0xc9, 0xbb, 0x23, 0xe5, 0x12, 0xbc,
+  0x61, 0xe3, 0xa6, 0x3c, 0xd4, 0xb3, 0x35, 0xbc, 0xae, 0x29, 0x41, 0xbb, 0xed, 0x13, 0x87, 0x3a,
+  0x8e, 0x95, 0x1b, 0xbc, 0x59, 0x0d, 0xa7, 0x3c, 0xb6, 0x62, 0xf5, 0xbb, 0x04, 0xe0, 0xda, 0xbb,
+  0xc3, 0x62, 0xaf, 0x3c, 0x43, 0xc8, 0x3f, 0xbc, 0x47, 0x47, 0x14, 0xbc, 0xb2, 0x69, 0x18, 0x39,
+  0xe8, 0xfc, 0x0b, 0x3c, 0x0d, 0xdd, 0x15, 0x3c, 0x0d, 0xac, 0x18, 0xbc, 0x89, 0x5a, 0x4c, 0x3c,
+  0x0c, 0xcb, 0xee, 0x3c, 0xc8, 0xec, 0x00, 0xbc, 0x2c, 0x50, 0x12, 0x3b, 0x11, 0x61, 0x01, 0x3b,
+  0xa5, 0x51, 0xe4, 0xba, 0x80, 0x52, 0x16, 0x3c, 0x8c, 0xb8, 0xf8, 0x3b, 0x37, 0xbc, 0x20, 0x3a,
+  0x1f, 0xa5, 0xfc, 0x3c, 0xd7, 0x46, 0xdc, 0xbb, 0x76, 0x63, 0x3a, 0x3b, 0x26, 0x8f, 0x8c, 0x3a,
+  0x39, 0x6a, 0x5f, 0xbb, 0x57, 0x45, 0x87, 0x3c, 0xdb, 0x4e, 0x8c, 0x3c, 0xc9, 0x8f, 0xf4, 0xb9,
+  0x10, 0x23, 0x3f, 0x3c, 0x2a, 0x2a, 0x47, 0x39, 0xa6, 0x35, 0x22, 0xbc, 0x32, 0x55, 0x3a, 0xbc,
+  0x58, 0xbf, 0x1b, 0x3c, 0xcf, 0xde, 0x64, 0xbb, 0xa6, 0xa8, 0x90, 0x3c, 0xfa, 0xe2, 0x7b, 0xbc,
+  0xa1, 0x1a, 0x08, 0xba, 0x92, 0xdf, 0xc9, 0x3a, 0xae, 0x63, 0x53, 0xbc, 0x21, 0x35, 0xc9, 0xba,
+  0x16, 0x83, 0x83, 0x3b, 0xb0, 0xe9, 0x2c, 0xbc, 0x0b, 0xf7, 0xb5, 0x3c, 0x6e, 0x6e, 0xb3, 0x3b,
+  0xa9, 0xa0, 0x10, 0x3b, 0xc1, 0x6e, 0x41, 0xbc, 0x2e, 0xbc, 0x86, 0xbc, 0xa9, 0xc5, 0x5a, 0xbc,
+  0x96, 0xc7, 0xb3, 0xbb, 0x98, 0x38, 0x2c, 0xbc, 0x39, 0x7b, 0xe4, 0x3c, 0xe0, 0xb8, 0xb7, 0xbb,
+  0xb1, 0x4c, 0xc3, 0xbb, 0xe0, 0xd3, 0x47, 0xbc, 0xd1, 0x8c, 0x12, 0xbc, 0x3b, 0xd0, 0x1e, 0xbc,
+  0xed, 0x1a, 0x85, 0xbb, 0xc1, 0xb0, 0x0e, 0xbc, 0x1a, 0xa0, 0xbc, 0x3c, 0x27, 0xc7, 0x98, 0x3b,
+  0x6b, 0x27, 0x92, 0xbc, 0xf6, 0x26, 0x1a, 0x3b, 0x08, 0x3f, 0x87, 0xbb, 0xd3, 0xf4, 0x2c, 0x3c,
+  0xdf, 0xeb, 0xdb, 0xb9, 0x7d, 0x67, 0x8e, 0xbb, 0x40, 0x3c, 0x43, 0xbb, 0x5f, 0xf6, 0x72, 0x3c,
+  0x24, 0x64, 0x05, 0xbc, 0x9f, 0xa7, 0x5a, 0xbc, 0x47, 0x4d, 0xc2, 0xbc, 0xda, 0x3c, 0x77, 0xbb,
+  0xa6, 0xc5, 0x17, 0x3c, 0x61, 0x32, 0xe3, 0x3a, 0x52, 0xef, 0x4f, 0xbb, 0x46, 0x1c, 0x0a, 0x3a,
+  0x7c, 0x36, 0x70, 0xbc, 0x0b, 0xb6, 0xd3, 0x3a, 0xce, 0xf2, 0x62, 0xbb, 0xa6, 0xec, 0x53, 0xbb,
+  0xbf, 0x5f, 0x75, 0x3b, 0x98, 0x54, 0x0a, 0x3b, 0x15, 0x34, 0x4b, 0xbb, 0x4d, 0xaf, 0x5d, 0xbc,
+  0xd4, 0x12, 0x43, 0xbc, 0xcb, 0x05, 0x90, 0xbb, 0x6a, 0xa0, 0x9b, 0x3c, 0xf6, 0xd5, 0x9e, 0xba,
+  0x4f, 0x49, 0xba, 0xba, 0x52, 0xbc, 0x3b, 0xb9, 0x0b, 0xeb, 0xdf, 0xba, 0x7c, 0x34, 0x2a, 0xbb,
+  0x68, 0x6e, 0x05, 0xbc, 0xc4, 0x31, 0xa1, 0x3b, 0x5b, 0x86, 0x1a, 0xbc, 0xfa, 0x73, 0xbd, 0x3b,
+  0x05, 0x66, 0xa0, 0x3b, 0x09, 0x8e, 0xb2, 0xbc, 0xe1, 0xcb, 0x25, 0x3b, 0xb0, 0x0d, 0x11, 0xbb,
+  0x84, 0xf3, 0xc8, 0xbc, 0xd3, 0xcf, 0x22, 0xbb, 0xff, 0x0a, 0x43, 0xbd, 0x60, 0x9c, 0x2c, 0xbc,
+  0xdb, 0x24, 0x5f, 0x3c, 0x44, 0x70, 0x57, 0xbc, 0x8c, 0x50, 0x92, 0x3c, 0xf2, 0x0c, 0x3d, 0xbc,
+  0x25, 0xdc, 0x2f, 0xbc, 0xe1, 0xe9, 0xa9, 0x3b, 0xe0, 0x73, 0xf5, 0xbb, 0x7e, 0x25, 0xcf, 0xbb,
+  0x49, 0x92, 0xc5, 0x3b, 0x24, 0xe4, 0x25, 0xbd, 0xe0, 0xb9, 0x0e, 0x3d, 0x69, 0xa2, 0xdc, 0x3b,
+  0x9d, 0xaf, 0x27, 0xbc, 0xf5, 0x25, 0x59, 0x39, 0x80, 0x82, 0x6c, 0xbc, 0x08, 0x97, 0xa1, 0x3a,
+  0x18, 0xa8, 0xa1, 0x3c, 0xb4, 0x36, 0x7b, 0xbc, 0x5f, 0x3b, 0xef, 0x3c, 0xc3, 0x08, 0x2f, 0x3b,
+  0x3f, 0x0c, 0x8f, 0xbb, 0x05, 0xeb, 0x75, 0xbb, 0xf3, 0xff, 0xc0, 0xbc, 0x97, 0xdd, 0xbb, 0x3b,
+  0xac, 0xa6, 0x4a, 0x3c, 0x6b, 0x9e, 0xa3, 0xbc, 0x52, 0x17, 0x72, 0x3c, 0x8b, 0xf4, 0x04, 0xbc,
+  0x3c, 0xce, 0xb3, 0xba, 0x19, 0x0c, 0xbf, 0xb9, 0x53, 0x13, 0x04, 0xbc, 0x6f, 0xe4, 0xbd, 0x3b,
+  0xe1, 0x26, 0x91, 0xbc, 0xec, 0x98, 0x7c, 0xbc, 0x9b, 0x37, 0x7d, 0x3c, 0x42, 0xd0, 0x36, 0x3b,
+  0x10, 0x9d, 0x80, 0xbc, 0x82, 0x81, 0x4f, 0x3c, 0xec, 0xa6, 0x47, 0xbc, 0xe6, 0x48, 0xe5, 0xba,
+  0x13, 0x6c, 0x18, 0xbd, 0xd6, 0xf7, 0xb6, 0xbc, 0x67, 0x16, 0x83, 0xbc, 0x4a, 0x1e, 0x15, 0x3c,
+  0x9b, 0x52, 0x4c, 0x3b, 0x89, 0x45, 0x75, 0x3c, 0x0c, 0xe3, 0xc2, 0x3b, 0x65, 0xba, 0x89, 0xbb,
+  0x8a, 0x21, 0x86, 0xbc, 0x83, 0xb0, 0xa4, 0x3b, 0x9b, 0xaa, 0x90, 0xbc, 0xad, 0xb6, 0x82, 0xbc,
+  0x0c, 0x2c, 0x4d, 0x3c, 0x2c, 0xf3, 0xb3, 0xbb, 0x31, 0x9b, 0xa0, 0x3c, 0x88, 0xd9, 0xc6, 0x3b,
+  0x2c, 0xd8, 0x23, 0xbc, 0xff, 0x69, 0xab, 0x3c, 0x44, 0xd5, 0xbe, 0xbc, 0x15, 0x68, 0xdd, 0x3b,
+  0xe0, 0x6f, 0x94, 0x3c, 0x0c, 0x28, 0x92, 0xba, 0xa5, 0xba, 0x06, 0xbc, 0x98, 0x3e, 0xe5, 0x3a,
+  0x73, 0x19, 0xb0, 0xbb, 0x56, 0x74, 0x1f, 0x3c, 0x06, 0x3b, 0x91, 0x3b, 0x5c, 0x44, 0x11, 0x3c,
+  0xeb, 0x41, 0xcd, 0x3c, 0x8b, 0x54, 0x8e, 0xb9, 0x13, 0x5a, 0x82, 0xba, 0x1b, 0x05, 0xd5, 0x3b,
+  0x6d, 0x7b, 0x42, 0x3b, 0xe2, 0x03, 0xd4, 0x3b, 0x4d, 0x64, 0xfd, 0x3b, 0x25, 0xf1, 0x58, 0xbb,
+  0x4a, 0xc8, 0xa2, 0x3c, 0xe3, 0x03, 0xb2, 0x3b, 0x3c, 0xd0, 0x48, 0xbc, 0x6d, 0xf2, 0x51, 0xba,
+  0x9c, 0xba, 0xe3, 0xbb, 0xab, 0xfe, 0x48, 0x3c, 0x28, 0x89, 0xd4, 0x3c, 0xbd, 0xfb, 0x9e, 0x3c,
+  0x0a, 0x31, 0xa2, 0x3c, 0xe9, 0xdf, 0x1a, 0x3b, 0x78, 0x4c, 0x10, 0x3b, 0x62, 0xcb, 0x9c, 0xbc,
+  0x0f, 0x54, 0x1e, 0x3c, 0xad, 0x9b, 0x10, 0x3c, 0xef, 0xd9, 0x96, 0x3c, 0xc1, 0x60, 0xb1, 0x3b,
+  0x64, 0x7d, 0x3e, 0x3c, 0x57, 0xc6, 0x28, 0xba, 0xd1, 0x38, 0xa2, 0xbc, 0xbb, 0xaf, 0x82, 0xbc,
+  0x94, 0x8c, 0xe3, 0x3b, 0x04, 0x3f, 0x16, 0xbc, 0xbd, 0x2d, 0xc1, 0x3c, 0x3c, 0x9f, 0x8b, 0xbb,
+  0xf3, 0xb7, 0xf0, 0xba, 0x50, 0x79, 0x1e, 0xbc, 0x96, 0xc1, 0xa6, 0x3b, 0x8c, 0x0d, 0x02, 0xbc,
+  0xaf, 0x2e, 0xb7, 0x3b, 0x25, 0x5f, 0xb3, 0xbc, 0xe2, 0x0f, 0xbd, 0x3c, 0x68, 0x11, 0x53, 0xbb,
+  0xb1, 0x4b, 0xf9, 0x3a, 0x97, 0x30, 0x89, 0xba, 0x20, 0xaf, 0x08, 0xbc, 0xc5, 0x95, 0x59, 0xbc,
+  0x4a, 0x50, 0x16, 0xbb, 0xc7, 0xdb, 0xb9, 0xbc, 0x49, 0x87, 0xc5, 0x3c, 0x94, 0x5f, 0x54, 0xbc,
+  0x36, 0xe0, 0x0f, 0xbc, 0x96, 0x14, 0xf6, 0xbb, 0x02, 0xea, 0xbd, 0x3b, 0x59, 0xf7, 0x48, 0xbc,
+  0xc7, 0x72, 0x17, 0x3c, 0x4e, 0x6a, 0x13, 0xbc, 0x99, 0xc0, 0x67, 0x3c, 0x18, 0x31, 0xae, 0x3b,
+  0xf9, 0xb5, 0x5a, 0xbc, 0x03, 0xe7, 0x77, 0xbc, 0xe8, 0xdd, 0x3b, 0xbb, 0xc3, 0x3f, 0xbc, 0xbb,
+  0xba, 0xe2, 0x1f, 0x3c, 0x29, 0x1b, 0xb8, 0xbb, 0x8e, 0x59, 0x3f, 0x3c, 0x51, 0x24, 0x8f, 0xbb,
+  0x94, 0x33, 0x99, 0xbc, 0x20, 0xec, 0x98, 0xbb, 0xe6, 0x79, 0x14, 0xbc, 0x49, 0x4b, 0x30, 0xbc,
+  0x89, 0xd9, 0xeb, 0xba, 0xad, 0x96, 0x42, 0x3b, 0x54, 0x02, 0x0b, 0xbb, 0x11, 0x15, 0xb3, 0xbb,
+  0xf6, 0xa2, 0x11, 0xbc, 0xdf, 0x8c, 0x21, 0xbc, 0x41, 0xda, 0x1a, 0x3b, 0x65, 0xf3, 0xb1, 0x3a,
+  0x6d, 0x81, 0x55, 0x3c, 0xde, 0xe3, 0xa6, 0x3b, 0x0a, 0x68, 0x86, 0xb9, 0x1f, 0x18, 0xb1, 0x3b,
+  0xb1, 0x7a, 0x02, 0xbc, 0xb2, 0xe6, 0xc0, 0x39, 0x09, 0x84, 0xed, 0xbb, 0x07, 0xd8, 0x2c, 0x3c,
+  0x3b, 0xff, 0x29, 0x3b, 0x15, 0x04, 0x58, 0xb9, 0x1d, 0xbb, 0x0f, 0xbc, 0x37, 0x4c, 0x9a, 0x3b,
+  0xfb, 0x01, 0x91, 0xbc, 0x77, 0x38, 0xf9, 0x3b, 0xa0, 0xc2, 0x15, 0xbd, 0x48, 0x1d, 0x1e, 0x3c,
+  0x9a, 0x34, 0xea, 0x3b, 0x34, 0xa6, 0x74, 0xbc, 0x78, 0x54, 0x5a, 0x3c, 0xca, 0xb3, 0xb9, 0xba,
+  0xe3, 0x81, 0xfd, 0xbb, 0x3b, 0x54, 0x82, 0xbb, 0x57, 0x7b, 0xed, 0xbc, 0x98, 0xf5, 0x06, 0x3c,
+  0x98, 0x40, 0x32, 0x3c, 0x22, 0x6f, 0x08, 0xbd, 0xe6, 0x2e, 0x0c, 0x3d, 0x68, 0xba, 0x26, 0x3c,
+  0x50, 0xd3, 0x4c, 0xbc, 0x09, 0x52, 0x0d, 0x3a, 0x28, 0x41, 0x2b, 0xbc, 0x91, 0xc3, 0xe3, 0xbb,
+  0x9f, 0x14, 0xbf, 0x3b, 0x86, 0x15, 0x85, 0x3b, 0xce, 0x42, 0x11, 0x3d, 0x7d, 0x46, 0x26, 0x3c,
+  0x65, 0x82, 0xff, 0xbb, 0xdd, 0x8b, 0x86, 0xbb, 0x73, 0xf9, 0x2b, 0xbc, 0x32, 0x64, 0xff, 0xb7,
+  0x7c, 0x11, 0xab, 0xbb, 0x02, 0x2f, 0xab, 0xbc, 0xcc, 0x89, 0xed, 0xbb, 0x4a, 0xc3, 0x80, 0xb9,
+  0x3c, 0xed, 0x7b, 0xbc, 0x85, 0x5b, 0xb7, 0x3b, 0xe6, 0xdb, 0xb9, 0xbb, 0xf0, 0xb6, 0x34, 0x3c,
+  0xb7, 0xcf, 0x9b, 0xbc, 0x65, 0xfb, 0x2a, 0xbc, 0xc5, 0x07, 0xb2, 0x3a, 0xfa, 0x60, 0xe9, 0xb9,
+  0x71, 0x12, 0xaa, 0xbc, 0xd9, 0x7b, 0x3f, 0x3c, 0x61, 0x42, 0x1b, 0xbb, 0xfc, 0x7f, 0x55, 0x3b,
+  0x84, 0x16, 0xdf, 0xbc, 0x39, 0x92, 0xd6, 0xbc, 0x7c, 0xe7, 0x89, 0xbc, 0x08, 0x5d, 0xcb, 0xbb,
+  0xc7, 0x51, 0x25, 0x3c, 0xe8, 0xda, 0xd0, 0x3b, 0xb0, 0xe9, 0x83, 0x3c, 0x2f, 0x39, 0x30, 0xbc,
+  0xa3, 0x0a, 0x90, 0xbc, 0xdb, 0xc3, 0x9b, 0x3b, 0x24, 0xa8, 0xa3, 0xbc, 0x5b, 0x13, 0x91, 0x3b,
+  0x49, 0xef, 0x64, 0x3c, 0x29, 0xdb, 0x53, 0xbc, 0xe6, 0xe2, 0xae, 0x3c, 0x7a, 0x1a, 0x04, 0x3b,
+  0xbc, 0x03, 0xee, 0xba, 0x63, 0x36, 0xd1, 0x3c, 0x22, 0x0b, 0xe3, 0xbc, 0x99, 0x3f, 0xda, 0x3b,
+  0xec, 0xc6, 0xc9, 0x3c, 0xf6, 0xb6, 0xe7, 0xbb, 0xa3, 0x1c, 0xa0, 0xbc, 0xaf, 0x03, 0x2e, 0xbc,
+  0x5c, 0xb8, 0x93, 0x39, 0x84, 0x7d, 0x57, 0x3c, 0x3a, 0xc4, 0xde, 0x3b, 0x12, 0x18, 0x22, 0x3a,
+  0x22, 0x61, 0xa6, 0x3c, 0x40, 0xbb, 0x06, 0xba, 0x3d, 0xf9, 0x04, 0xbc, 0x76, 0x33, 0xf2, 0xbb,
+  0xc6, 0x79, 0x86, 0xbb, 0x6d, 0x6b, 0xe5, 0x3b, 0xba, 0x20, 0xe4, 0xb9, 0x75, 0x3f, 0xc6, 0xb8,
+  0xe4, 0x45, 0xe6, 0x3c, 0x2f, 0xd3, 0x3d, 0xbc, 0x6e, 0xda, 0x99, 0x3b, 0x03, 0x59, 0x0a, 0xba,
+  0x74, 0x2e, 0xbc, 0xbb, 0x87, 0x12, 0xcc, 0x3b, 0x3c, 0x3d, 0x76, 0x3c, 0x0e, 0x8e, 0xfa, 0x3a,
+  0xb2, 0x59, 0x34, 0x3c, 0xed, 0x0f, 0x86, 0xbb, 0x41, 0x60, 0x82, 0xbc, 0x94, 0x8e, 0x1e, 0xbc,
+  0x87, 0x45, 0x0e, 0x3c, 0xef, 0xe8, 0x95, 0x3c, 0x51, 0xd2, 0xd1, 0x3c, 0x16, 0xaa, 0x58, 0x3b,
+  0x75, 0x69, 0xb7, 0x3b, 0x2d, 0x0e, 0x3c, 0x3b, 0xe4, 0x00, 0x41, 0xbc, 0xbd, 0x93, 0xa6, 0xbc,
+  0x81, 0xc1, 0x12, 0x3c, 0xdc, 0x01, 0x66, 0xbc, 0xc3, 0xc9, 0xbd, 0x3c, 0xfb, 0x93, 0x90, 0x3b,
+  0x2d, 0xbe, 0xfd, 0xb8, 0xac, 0xdb, 0xa4, 0xbb, 0xe7, 0x38, 0x78, 0xbc, 0x13, 0xc3, 0xc6, 0xbb,
+  0xde, 0x8f, 0x06, 0x3c, 0xa2, 0x5a, 0x6b, 0xbc, 0xa2, 0x5c, 0xdd, 0x3c, 0x86, 0xd9, 0xcc, 0x3b,
+  0xcb, 0xb2, 0x9e, 0xbb, 0xa8, 0xb4, 0x1f, 0x3b, 0x6d, 0xc7, 0x1a, 0xbc, 0x16, 0x87, 0x13, 0x3b,
+  0x69, 0xbe, 0x27, 0xb9, 0xc4, 0x4a, 0x51, 0xbc, 0x2a, 0x8d, 0x8c, 0x3c, 0xa9, 0xe4, 0x03, 0xbc,
+  0x3b, 0x0d, 0x48, 0xba, 0xcd, 0x62, 0x78, 0xbb, 0xc9, 0xa9, 0xa8, 0xb8, 0xd2, 0x53, 0x9b, 0xbc,
+  0xfd, 0x8a, 0x3e, 0x3c, 0x3e, 0x70, 0xf0, 0xbb, 0x4c, 0x30, 0x93, 0x3c, 0x86, 0x1b, 0xac, 0x3b,
+  0x31, 0x4c, 0xde, 0xbb, 0xd4, 0x2f, 0x07, 0xbb, 0x3b, 0x4a, 0x7d, 0xbc, 0x40, 0xa3, 0x59, 0xbc,
+  0xdb, 0x44, 0x2e, 0x3b, 0x9e, 0x86, 0xae, 0x3b, 0x3e, 0x2e, 0x4d, 0x3c, 0x05, 0x7b, 0x1a, 0x3b,
+  0xf3, 0x02, 0xe5, 0xbc, 0x97, 0xb3, 0x9e, 0xbb, 0x09, 0x50, 0x39, 0xbc, 0xe0, 0x3d, 0x87, 0xbc,
+  0xa3, 0xf9, 0x55, 0xba, 0xa1, 0x8c, 0xc1, 0x3b, 0xe9, 0xc5, 0xad, 0x3a, 0xee, 0xb6, 0x91, 0x3b,
+  0xb5, 0x4c, 0x45, 0xba, 0x25, 0x22, 0x6c, 0xbc, 0xd4, 0x98, 0x3e, 0x3c, 0xfe, 0x95, 0x51, 0x3c,
+  0xa1, 0xf3, 0x15, 0xbb, 0xc4, 0x36, 0x90, 0xbb, 0xe4, 0xf3, 0x42, 0x3b, 0x2a, 0x37, 0xef, 0xbb,
+  0x0d, 0x22, 0x40, 0xba, 0x39, 0x09, 0xa3, 0xbb, 0x7b, 0xce, 0x03, 0xbc, 0xd7, 0x23, 0x56, 0x3c,
+  0x38, 0x05, 0x4f, 0x3b, 0x0b, 0x91, 0xc8, 0x3b, 0xe8, 0xe6, 0xf8, 0x39, 0x01, 0xe6, 0x9d, 0x3b,
+  0x25, 0x8d, 0x16, 0xbc, 0xae, 0x59, 0xf5, 0xbb, 0x66, 0x8a, 0x22, 0xbd, 0x21, 0x72, 0x4e, 0x3c,
+  0x64, 0x8f, 0x32, 0x3c, 0x9e, 0xb4, 0xa4, 0xbc, 0x60, 0xcb, 0xd5, 0x3c, 0x78, 0x34, 0xd3, 0xba,
+  0xec, 0x39, 0x9d, 0xbc, 0xad, 0xc3, 0x20, 0xbc, 0x81, 0x5c, 0xd3, 0xbc, 0xa8, 0x99, 0xe8, 0xbb,
+  0x51, 0x4d, 0x23, 0x3c, 0xa2, 0xf0, 0xec, 0xbc, 0x43, 0x12, 0xc7, 0x3c, 0x4b, 0x74, 0xec, 0xbb,
+  0x2e, 0xd9, 0x18, 0xbc, 0x5a, 0xab, 0xf5, 0xbb, 0x3c, 0xc1, 0x33, 0xbc, 0xc8, 0x6b, 0x23, 0x3c,
+  0xc3, 0xfb, 0xc9, 0x3b, 0xac, 0x00, 0xde, 0xbb, 0x2f, 0xaf, 0xd2, 0x3c, 0x88, 0xb9, 0x85, 0xbc,
+  0xa7, 0xa0, 0xaf, 0xba, 0x38, 0x09, 0xdf, 0x3b, 0xa4, 0x0b, 0x0f, 0xbb, 0x07, 0xc2, 0xf3, 0x3b,
+  0x4d, 0x9e, 0xed, 0x3b, 0x42, 0x2b, 0x9d, 0xbb, 0x7d, 0x23, 0x58, 0xbb, 0x3f, 0x01, 0xc0, 0x3b,
+  0xf4, 0xef, 0x2c, 0xbc, 0xb9, 0x18, 0xf4, 0xbb, 0x99, 0x4a, 0x51, 0xbc, 0x33, 0x6d, 0xb0, 0x3b,
+  0xcb, 0x71, 0x0f, 0xbc, 0x98, 0x48, 0xf8, 0xbc, 0x44, 0xe7, 0x00, 0x3c, 0x87, 0xff, 0xbe, 0xbb,
+  0x64, 0x43, 0x3d, 0xbc, 0x25, 0xe1, 0x73, 0x3c, 0xa5, 0xde, 0x09, 0xbc, 0x90, 0x72, 0xd0, 0xb8,
+  0xe8, 0x65, 0xbc, 0xbc, 0x5f, 0x16, 0x5b, 0xbc, 0x61, 0x49, 0x46, 0xbc, 0x62, 0x63, 0x17, 0x3c,
+  0xa7, 0x72, 0x6a, 0x3b, 0x11, 0x4a, 0x97, 0x3c, 0xd1, 0xa6, 0x0b, 0x3c, 0x13, 0x1c, 0x30, 0xbc,
+  0x60, 0x47, 0x2a, 0xbc, 0x78, 0xd0, 0xef, 0x3b, 0x88, 0x3a, 0x2c, 0xbc, 0xa0, 0x86, 0xc0, 0xbb,
+  0xff, 0xa2, 0x1d, 0x3c, 0x45, 0x58, 0x10, 0xbc, 0xdf, 0xca, 0x8d, 0xba, 0x96, 0x13, 0x8e, 0x3b,
+  0xac, 0xd4, 0x10, 0xbb, 0x20, 0x1d, 0xc2, 0x3c, 0xae, 0x35, 0x8f, 0xbc, 0xe8, 0x43, 0x55, 0x3c,
+  0x53, 0xc9, 0x57, 0x3c, 0xf7, 0x1e, 0x44, 0xbc, 0xb0, 0xe8, 0x05, 0xbc, 0x76, 0x63, 0xad, 0xbb,
+  0xf2, 0x72, 0x94, 0xbb, 0xbe, 0x8e, 0x4f, 0x3c, 0x73, 0x7a, 0x3a, 0x3b, 0x89, 0x3e, 0xf9, 0x39,
+  0x7e, 0xd9, 0xac, 0x3c, 0x07, 0xcb, 0x13, 0xbc, 0x13, 0x12, 0x1e, 0xbb, 0xa9, 0x99, 0x0b, 0x3b,
+  0x38, 0x79, 0x32, 0xbb, 0x4a, 0x2b, 0x5d, 0x3b, 0xa3, 0x17, 0x47, 0x3c, 0xb9, 0x8c, 0x1b, 0xbc,
+  0x0b, 0x36, 0xa7, 0x3c, 0x13, 0x98, 0xc6, 0x3b, 0x05, 0xc1, 0xfd, 0xba, 0xde, 0x93, 0x9d, 0xbc,
+  0x75, 0x42, 0xe8, 0xba, 0x65, 0x0f, 0xf0, 0x3b, 0x5c, 0x6f, 0x72, 0x3c, 0x35, 0x08, 0xe9, 0xba,
+  0x30, 0x67, 0xb1, 0x3c, 0xbc, 0x38, 0xd1, 0xbb, 0xd1, 0x22, 0xd9, 0xbc, 0x5e, 0x11, 0x95, 0xbc,
+  0x8e, 0xc4, 0x99, 0x3b, 0xbe, 0xf7, 0x97, 0xba, 0x20, 0x5f, 0xa0, 0x3c, 0x02, 0xa5, 0x0e, 0xb8,
+  0x8b, 0xdd, 0x3a, 0xbb, 0x95, 0x48, 0x93, 0x3b, 0x18, 0x84, 0x39, 0xbc, 0x2e, 0x99, 0x96, 0xbb,
+  0x66, 0xff, 0x80, 0x3c, 0x62, 0x7c, 0xd3, 0xbb, 0x52, 0x8b, 0x10, 0x3d, 0x8a, 0x73, 0x4c, 0x3c,
+  0xec, 0xa9, 0x72, 0xbb, 0xa3, 0x38, 0xa6, 0x38, 0xe7, 0x36, 0x40, 0xbc, 0x41, 0xc8, 0xf4, 0xbb,
+  0xda, 0xbd, 0x82, 0x3c, 0xd5, 0x9c, 0xa7, 0x39, 0x47, 0xb4, 0x85, 0x3c, 0x32, 0x26, 0xd2, 0xbb,
+  0xf7, 0x59, 0x71, 0x39, 0x29, 0x12, 0x32, 0xbc, 0xf0, 0xe3, 0x45, 0x3b, 0x41, 0x83, 0x60, 0xbc,
+  0x1a, 0x02, 0x26, 0x3c, 0xd5, 0x0a, 0xa2, 0xbc, 0x62, 0xa9, 0xee, 0x3c, 0xeb, 0xc1, 0xc0, 0x3b,
+  0x3b, 0x40, 0x63, 0x3b, 0x92, 0x16, 0xe6, 0xbb, 0x88, 0x24, 0xc9, 0xbb, 0xbf, 0xac, 0x20, 0xbc,
+  0xde, 0x9c, 0x34, 0x3c, 0x3f, 0xc8, 0x81, 0xbc, 0xf4, 0x54, 0xa2, 0x3c, 0xaf, 0x52, 0x51, 0x3c,
+  0xaa, 0xac, 0xc7, 0xba, 0xce, 0x1f, 0x8b, 0xba, 0xa6, 0x59, 0x27, 0xbc, 0x5c, 0x20, 0x18, 0xbc,
+  0x27, 0x5f, 0x34, 0x3c, 0x9a, 0x72, 0x9e, 0xbb, 0x42, 0x48, 0x89, 0x3c, 0xfa, 0xb7, 0x96, 0x3b,
+  0x50, 0xa9, 0x2e, 0xbc, 0x19, 0x65, 0x09, 0xbc, 0x47, 0x89, 0x54, 0xbb, 0x7a, 0x55, 0xca, 0xbb,
+  0x61, 0x04, 0xe5, 0x3b, 0x69, 0x62, 0xc3, 0x3b, 0x69, 0x51, 0x76, 0xbb, 0xcc, 0xda, 0xac, 0xbb,
+  0xd2, 0xfe, 0x14, 0xbc, 0x20, 0x5c, 0x3a, 0xbc, 0x14, 0x33, 0x5b, 0x3c, 0xef, 0x88, 0x20, 0x3c,
+  0xdd, 0x44, 0x54, 0x3b, 0xf3, 0x04, 0x33, 0x3c, 0xc1, 0x0f, 0xab, 0x3b, 0x06, 0x29, 0xc7, 0x3b,
+  0xac, 0xb8, 0x18, 0xbc, 0xf7, 0xea, 0x85, 0xbb, 0xaa, 0xc9, 0x14, 0xbc, 0xc2, 0x21, 0x00, 0x3c,
+  0x3c, 0x29, 0x5a, 0x3b, 0xe7, 0x41, 0xaa, 0xbc, 0x06, 0xb4, 0xd5, 0xbb, 0xe6, 0x90, 0x91, 0x3b,
+  0xb5, 0xae, 0xa4, 0xbc, 0x6c, 0xdb, 0x88, 0xbb, 0xa1, 0x5e, 0x13, 0xbd, 0x1c, 0x65, 0x9c, 0xbb,
+  0xb3, 0x95, 0x46, 0x3c, 0x93, 0xca, 0xd5, 0xbc, 0xc7, 0x55, 0x92, 0x3c, 0xf6, 0x22, 0x24, 0x3c,
+  0x82, 0xef, 0x38, 0xbc, 0xbc, 0xa1, 0xb2, 0xbb, 0xff, 0xff, 0xeb, 0xbc, 0xf2, 0x53, 0x51, 0xbb,
+  0xd7, 0x6e, 0xa3, 0x3c, 0x76, 0xc1, 0x1c, 0xbd, 0xfe, 0x24, 0xe1, 0x3c, 0x31, 0xec, 0xd7, 0x3b,
+  0xc3, 0x09, 0x93, 0x3a, 0x01, 0x0b, 0x08, 0x3c, 0xc8, 0x44, 0xf4, 0xbb, 0x67, 0xd3, 0x86, 0xbb,
+  0x7e, 0x06, 0x67, 0x3c, 0x9f, 0x37, 0x27, 0xbc, 0x29, 0xcf, 0xdd, 0x3c, 0x58, 0x74, 0xfb, 0x3b,
+  0x5a, 0x44, 0x93, 0x3a, 0xe3, 0x3d, 0x28, 0x3c, 0x0e, 0x77, 0x7b, 0xbc, 0xe1, 0x77, 0x80, 0x3b,
+  0x86, 0x39, 0xd9, 0x39, 0x3f, 0xe7, 0x09, 0xbc, 0xa6, 0x73, 0x5b, 0x3c, 0xf1, 0xf4, 0x68, 0x3c,
+  0x69, 0x89, 0x74, 0x3b, 0xd0, 0xa2, 0xf5, 0x3a, 0xae, 0x79, 0xd5, 0xbb, 0x86, 0x74, 0x74, 0x3a,
+  0x71, 0x0e, 0x3d, 0xbc, 0x07, 0xe5, 0x94, 0xbc, 0x28, 0xd3, 0x33, 0xbb, 0x2d, 0x63, 0x17, 0xbb,
+  0x7c, 0x98, 0x77, 0xbc, 0x60, 0xeb, 0x9a, 0xba, 0x05, 0x85, 0x1b, 0x3b, 0xdb, 0x70, 0x83, 0x3a,
+  0x52, 0xf1, 0xaf, 0xbc, 0x48, 0x23, 0xd5, 0xbc, 0x9b, 0x14, 0xc3, 0xbb, 0x52, 0x10, 0x1d, 0xbc,
+  0xbe, 0x7d, 0xfa, 0x3b, 0x9d, 0xe2, 0x2d, 0x3c, 0x4f, 0x18, 0x27, 0x3b, 0xbf, 0x2e, 0xd1, 0x3b,
+  0x44, 0x14, 0xa2, 0xbc, 0x2c, 0x13, 0x92, 0x3b, 0xcb, 0x89, 0x8d, 0xbc, 0xd8, 0xfe, 0xa3, 0xbb,
+  0x9b, 0x92, 0x69, 0x3c, 0xf4, 0x33, 0x80, 0xbb, 0x10, 0x52, 0xfb, 0x3b, 0x99, 0x41, 0x13, 0xbc,
+  0xb7, 0x17, 0x86, 0xbb, 0x2e, 0x31, 0x97, 0x3c, 0xba, 0x34, 0xaa, 0xbb, 0x1a, 0x03, 0x78, 0x3b,
+  0x3f, 0xf0, 0x9b, 0x3c, 0xd3, 0xe7, 0x0d, 0xbc, 0x57, 0x1e, 0x1b, 0xbc, 0x1b, 0xc1, 0x7a, 0xbc,
+  0xa5, 0xe2, 0x76, 0xbb, 0x0c, 0x45, 0x34, 0x3c, 0x9c, 0x53, 0x24, 0xbb, 0x1b, 0x26, 0x89, 0x3c,
+  0xef, 0x30, 0xb5, 0x3c, 0xb6, 0x39, 0xe9, 0xbb, 0x1b, 0x85, 0x3d, 0xbb, 0xcd, 0xc1, 0xa5, 0xbb,
+  0x62, 0x6d, 0x09, 0xbb, 0xe8, 0x8c, 0x49, 0x3c, 0x18, 0x24, 0x00, 0x3c, 0x98, 0x81, 0x86, 0xbb,
+  0xa5, 0xa9, 0xc3, 0x3c, 0x52, 0xf0, 0x11, 0xbb, 0x39, 0xcd, 0x2a, 0xbb, 0xa2, 0x6f, 0x3d, 0xbc,
+  0x66, 0x08, 0xe6, 0xbb, 0x95, 0xdc, 0xab, 0x3a, 0x42, 0x6d, 0x8c, 0x3c, 0xfe, 0x78, 0x25, 0xbc,
+  0xf6, 0xfa, 0x91, 0x3c, 0xc8, 0x75, 0x5d, 0xbb, 0x69, 0xb5, 0xd2, 0xbc, 0xe3, 0x12, 0xeb, 0xbb,
+  0x1f, 0x16, 0x51, 0xba, 0xc6, 0x5f, 0x08, 0x3a, 0x17, 0x51, 0xb4, 0x3c, 0x88, 0x17, 0x68, 0x3b,
+  0xb6, 0xd3, 0x3d, 0x3c, 0xee, 0x86, 0xb3, 0x3a, 0xcd, 0x71, 0x56, 0xbc, 0x37, 0x07, 0x2b, 0xbc,
+  0x07, 0xeb, 0xfd, 0x3b, 0xdc, 0x8b, 0x47, 0xbb, 0xef, 0x5e, 0xe6, 0x3c, 0x21, 0x9f, 0x4e, 0x3b,
+  0xaa, 0x3a, 0xef, 0x3b, 0x58, 0x10, 0x05, 0x3c, 0x0f, 0x57, 0xeb, 0x3a, 0xbe, 0x99, 0x94, 0xbb,
+  0x54, 0x78, 0x61, 0x3c, 0x39, 0xaf, 0xf0, 0xbb, 0x41, 0x93, 0x8e, 0x3c, 0x7f, 0xa4, 0x97, 0xbc,
+  0x0c, 0x5c, 0x79, 0x3b, 0x0b, 0xc3, 0x08, 0xbc, 0x4d, 0xce, 0x90, 0x3a, 0x83, 0x7a, 0x87, 0xbc,
+  0xf5, 0xc5, 0x69, 0x3b, 0xb3, 0xc1, 0xd9, 0xbc, 0xcf, 0x16, 0xac, 0x3c, 0xff, 0x36, 0xd0, 0x3b,
+  0x5d, 0x65, 0x37, 0x3b, 0x3c, 0xab, 0x1c, 0xbc, 0x12, 0x1f, 0x35, 0x3c, 0x3c, 0xf0, 0x96, 0xbc,
+  0xcb, 0x02, 0x7f, 0x3c, 0xfb, 0xab, 0x82, 0xbc, 0x75, 0x30, 0xcc, 0x3c, 0xef, 0x69, 0x99, 0xbc,
+  0xaa, 0x31, 0x0e, 0xbb, 0x75, 0xcf, 0xdf, 0xbb, 0xd4, 0x77, 0xb5, 0xbb, 0x9c, 0xa5, 0x1e, 0xbc,
+  0xc3, 0xa9, 0xd6, 0x3b, 0x7b, 0x8d, 0x9a, 0x3b, 0x50, 0x71, 0xe7, 0x3b, 0x90, 0xb1, 0xef, 0x3b,
+  0xe3, 0x4f, 0x90, 0xbc, 0x2b, 0x8d, 0x00, 0xbc, 0x5c, 0xea, 0x12, 0xbb, 0xd1, 0xfb, 0x4d, 0xbc,
+  0x84, 0x24, 0xea, 0x3b, 0xea, 0xa8, 0xda, 0xb8, 0x06, 0xbc, 0xe4, 0x3a, 0x92, 0x30, 0x50, 0xbb,
+  0xe4, 0xa9, 0xfc, 0x39, 0x40, 0x24, 0x27, 0x3b, 0x7b, 0x7f, 0x24, 0x3b, 0x72, 0x85, 0x8b, 0xba,
+  0x09, 0x36, 0x83, 0x3b, 0xb6, 0xac, 0xc7, 0xbb, 0x3e, 0xb1, 0xdc, 0x3b, 0x8b, 0x40, 0xdb, 0xbb,
+  0x5a, 0x3e, 0x14, 0xbb, 0x13, 0xde, 0x34, 0x3a, 0x39, 0xdd, 0xbf, 0xba, 0x50, 0x45, 0x3c, 0x3c,
+  0x22, 0x14, 0x63, 0x3c, 0x38, 0x8f, 0x9c, 0xbb, 0x1e, 0xfa, 0x0f, 0xbc, 0x20, 0x3d, 0x30, 0x3b,
+  0xc4, 0x26, 0xc1, 0xbc, 0x1b, 0xed, 0x02, 0xbb, 0x53, 0x15, 0x20, 0xbd, 0xf3, 0x6e, 0x9a, 0x3c,
+  0x98, 0x81, 0x80, 0x3c, 0xd8, 0x70, 0xb3, 0xbc, 0x1e, 0xa5, 0xc8, 0x3c, 0x94, 0x5c, 0xcc, 0x3a,
+  0x92, 0x24, 0x7b, 0xbc, 0xec, 0xc3, 0x7d, 0xbc, 0x94, 0xdb, 0xd8, 0xbc, 0x10, 0x69, 0x23, 0xbb,
+  0x10, 0x1d, 0xe5, 0x3c, 0xee, 0x6d, 0x02, 0xbd, 0xa9, 0x48, 0x16, 0x3d, 0x11, 0x2a, 0xe8, 0x3a,
+  0x81, 0x45, 0x3a, 0xbc, 0xb8, 0xce, 0xb1, 0xbb, 0x9e, 0x20, 0x4f, 0xbc, 0xe8, 0x4b, 0x21, 0xbc,
+  0x3d, 0x3a, 0x42, 0x3c, 0x2d, 0xde, 0xd9, 0xbb, 0x99, 0x01, 0x13, 0x3d, 0x41, 0x35, 0x66, 0x3c,
+  0x95, 0xb4, 0x02, 0xbb, 0xa5, 0x31, 0x8b, 0xbb, 0x3d, 0x14, 0x97, 0xbc, 0x05, 0x86, 0x2b, 0xba,
+  0x8b, 0x6d, 0x81, 0xba, 0x59, 0xe8, 0x29, 0xbc, 0xba, 0x75, 0xf2, 0x3b, 0x54, 0xb8, 0x0c, 0x3b,
+  0xf9, 0x47, 0xe3, 0x3b, 0x55, 0xdc, 0x29, 0x32, 0xd3, 0x12, 0x18, 0xbc, 0x63, 0xf0, 0x42, 0x3c,
+  0x98, 0x8b, 0x34, 0xbc, 0xe8, 0x38, 0x38, 0xbc, 0x61, 0x0e, 0xad, 0xb9, 0x6f, 0x18, 0x09, 0x3c,
+  0xcd, 0xbf, 0x07, 0xbc, 0xee, 0x75, 0x1e, 0x3c, 0x8f, 0xd1, 0x8d, 0x39, 0xd0, 0x0c, 0x31, 0x3c,
+  0x22, 0xed, 0x05, 0xbd, 0x73, 0xd8, 0x13, 0xbd, 0x31, 0x68, 0x05, 0xbc, 0x66, 0x9b, 0xbd, 0x3b,
+  0xd5, 0xec, 0x85, 0x3c, 0xfe, 0x80, 0x9a, 0x3c, 0xd7, 0xa4, 0xe5, 0x3b, 0x62, 0x3e, 0x31, 0x3a,
+  0x9c, 0x22, 0xab, 0xbc, 0x62, 0x37, 0xcd, 0x3a, 0x06, 0x8f, 0xc2, 0xbc, 0x29, 0xe6, 0x0d, 0x3a,
+  0xe8, 0xd0, 0x8f, 0x3c, 0x90, 0x40, 0xd6, 0xb9, 0x39, 0x35, 0x5d, 0xbb, 0xb6, 0x5b, 0xfd, 0xbb,
+  0xff, 0x6d, 0xa4, 0x3b, 0x56, 0x2f, 0x5e, 0x3c, 0xd7, 0x52, 0x55, 0xbc, 0xe9, 0xf6, 0xea, 0x3b,
+  0xf7, 0xdc, 0x5e, 0x3c, 0xf1, 0x22, 0x0e, 0xbc, 0x5a, 0xcf, 0xb5, 0xbb, 0x33, 0x02, 0xe4, 0xbb,
+  0xb7, 0x49, 0xbd, 0xbb, 0x50, 0xf2, 0xc2, 0x3b, 0xcb, 0x68, 0x50, 0x39, 0x4e, 0x6d, 0x7d, 0x3b,
+  0x3d, 0x59, 0x58, 0x3c, 0xad, 0xe3, 0xbf, 0xbb, 0xc3, 0xb5, 0xa8, 0xbc, 0xf4, 0x21, 0xf0, 0xbb,
+  0x02, 0x05, 0xf3, 0xba, 0x8e, 0xea, 0x70, 0x3c, 0xba, 0xca, 0x01, 0x3c, 0xc1, 0x7a, 0x12, 0xb9,
+  0xe0, 0x0f, 0x3e, 0x3c, 0x78, 0x0d, 0xd8, 0x3a, 0xb5, 0x13, 0x91, 0xbb, 0x47, 0x61, 0x5f, 0xbc,
+  0xc3, 0xaa, 0x12, 0xba, 0x2f, 0x4a, 0x58, 0x3b, 0x96, 0x45, 0x94, 0x3b, 0xd2, 0x92, 0x4b, 0x3c,
+  0x06, 0x9b, 0x3a, 0x3c, 0x05, 0xcc, 0x3b, 0xba, 0x5b, 0xc9, 0x29, 0xbc, 0x6c, 0xe0, 0x1a, 0xbc,
+  0xd1, 0xa2, 0xbd, 0xba, 0x27, 0xfa, 0x17, 0x3c, 0xa3, 0x1d, 0xa9, 0x3c, 0xa7, 0x32, 0x84, 0xbb,
+  0x0f, 0x78, 0xbb, 0x3b, 0x1d, 0x2a, 0x36, 0xbb, 0x90, 0x0c, 0x82, 0xbc, 0x31, 0xff, 0x9c, 0xbb,
+  0x5c, 0x2b, 0x04, 0x3c, 0x07, 0x6b, 0x95, 0xbc, 0x44, 0x6a, 0xa6, 0x3c, 0xb7, 0x4a, 0x8b, 0xbc,
+  0x21, 0xae, 0x06, 0xbb, 0x7e, 0x24, 0xbb, 0xb9, 0xf2, 0x92, 0x3b, 0xba, 0xf5, 0x3b, 0x1c, 0xbc,
+  0xb2, 0xf3, 0x10, 0x3c, 0xdf, 0xac, 0x71, 0xbc, 0xb8, 0x48, 0xd8, 0x3c, 0xce, 0x27, 0xc3, 0xba,
+  0xa7, 0x66, 0x27, 0xbc, 0x0d, 0xa6, 0x51, 0xba, 0x02, 0xfe, 0x2e, 0xbc, 0x87, 0xad, 0xb8, 0xbc,
+  0xa8, 0x9a, 0x10, 0x3c, 0xe9, 0x69, 0x42, 0xbb, 0xa5, 0x8e, 0x9e, 0x3c, 0xe2, 0xc8, 0x4f, 0x3c,
+  0x6e, 0xd8, 0xca, 0x3b, 0x9e, 0x06, 0xf4, 0xbb, 0x49, 0x7b, 0x86, 0xbb, 0x96, 0x84, 0x7a, 0xbc,
+  0x18, 0xfd, 0xc1, 0x3b, 0xd4, 0x46, 0x27, 0xbc, 0xec, 0x29, 0xd0, 0x3c, 0x1d, 0x94, 0x1e, 0x3c,
+  0x22, 0x54, 0x28, 0xbc, 0xf4, 0x90, 0xb6, 0xb8, 0x8a, 0xb6, 0x24, 0xbc, 0xb6, 0xed, 0x40, 0xbc,
+  0x69, 0xdd, 0x54, 0x3c, 0x76, 0x1b, 0x01, 0xbb, 0xf3, 0x68, 0x8c, 0x3b, 0xbd, 0x3f, 0xa8, 0x38,
+  0x9b, 0xd3, 0xd5, 0xbb, 0x00, 0x70, 0x06, 0x3b, 0xc2, 0xc5, 0x56, 0xbb, 0x33, 0xa6, 0x50, 0xbc,
+  0x14, 0x33, 0x49, 0x3c, 0xbf, 0x20, 0xd5, 0x3b, 0xd4, 0x04, 0x75, 0x3b, 0xd6, 0x68, 0x10, 0x3c,
+  0xcc, 0xdd, 0x7f, 0xbb, 0xf7, 0xfc, 0x5f, 0xba, 0x1d, 0x48, 0x92, 0x3b, 0xaa, 0xfd, 0xe3, 0x3b,
+  0x31, 0x7b, 0xc6, 0x3b, 0x47, 0x8c, 0x2d, 0xbc, 0xb8, 0x80, 0xc5, 0x3a, 0xfb, 0x1b, 0x75, 0xbc,
+  0xfc, 0xb9, 0x8b, 0xba, 0xc9, 0xe1, 0xde, 0xbb, 0x4b, 0xc3, 0x1e, 0xbc, 0xbe, 0x2c, 0xca, 0x3b,
+  0xf6, 0xa2, 0x9b, 0x3a, 0xbd, 0xac, 0x92, 0xbc, 0x6d, 0x1e, 0xdc, 0x3a, 0xe4, 0xd7, 0x64, 0x3c,
+  0x9a, 0x51, 0xae, 0xbc, 0x22, 0x98, 0xa5, 0x39, 0xed, 0xbb, 0xd2, 0xbc, 0x1a, 0x20, 0x11, 0x3c,
+  0xc5, 0xc0, 0xa1, 0x3c, 0xb4, 0x73, 0xd5, 0xbc, 0x51, 0xfb, 0x9d, 0x3c, 0x6c, 0xb6, 0x03, 0x3b,
+  0xeb, 0xab, 0x68, 0xbc, 0xc0, 0x59, 0xe4, 0xbb, 0x9d, 0x80, 0x90, 0xbc, 0x13, 0xd2, 0xa5, 0x3b,
+  0xcd, 0xa7, 0xac, 0x3c, 0xe4, 0xd1, 0xc9, 0xbc, 0x02, 0xa4, 0x04, 0x3d, 0xa0, 0xfd, 0x82, 0x38,
+  0xe5, 0x9d, 0x41, 0xbc, 0xc9, 0x27, 0xb7, 0xbb, 0x7e, 0x07, 0xbc, 0xbc, 0x44, 0x29, 0x10, 0x3c,
+  0x75, 0x0a, 0x25, 0x3c, 0x0d, 0x3a, 0x05, 0xba, 0x22, 0xe4, 0x01, 0x3d, 0xdc, 0x23, 0x06, 0x3c,
+  0xa7, 0x54, 0x1b, 0x3b, 0xa0, 0xc0, 0xc5, 0xba, 0x38, 0x71, 0x9a, 0xbc, 0xd8, 0xf6, 0x06, 0x3c,
+  0x9a, 0x43, 0x5e, 0x3c, 0xfe, 0xd4, 0xb4, 0xbb, 0xc7, 0xa1, 0x21, 0x3c, 0x3e, 0xf6, 0x18, 0xbc,
+  0x6b, 0xd2, 0xd8, 0xbb, 0x0a, 0x2d, 0x8c, 0x3c, 0x54, 0xa2, 0xa5, 0xbc, 0xd1, 0x11, 0x64, 0x3c,
+  0x8a, 0x86, 0x1b, 0xbc, 0x58, 0xab, 0x94, 0xbc, 0x8e, 0xe3, 0xa8, 0xbb, 0x6e, 0xcf, 0x1e, 0xbc,
+  0x12, 0x6d, 0x56, 0xbc, 0x7a, 0xff, 0x83, 0x3c, 0x1c, 0xe1, 0xd7, 0xbb, 0xf4, 0xe9, 0xb3, 0x3b,
+  0xfa, 0xb4, 0x03, 0xbd, 0x98, 0xb7, 0xbb, 0xbc, 0x80, 0x2b, 0x22, 0xbc, 0xc0, 0xf0, 0x27, 0x3b,
+  0xdb, 0xf0, 0x69, 0x3b, 0x32, 0xa0, 0x54, 0x3c, 0x8b, 0x67, 0xf0, 0x39, 0x2f, 0xed, 0x15, 0xbc,
+  0x28, 0x5a, 0xa6, 0xbb, 0xb0, 0x15, 0x96, 0x3a, 0xd9, 0x98, 0xc1, 0xbc, 0x67, 0x4d, 0x84, 0x3b,
+  0x31, 0xdb, 0x23, 0x3c, 0xbe, 0xfa, 0xa3, 0xba, 0x8c, 0xcf, 0x58, 0x3c, 0xf6, 0xa1, 0x53, 0xbc,
+  0x34, 0x05, 0x01, 0x3b, 0x26, 0x4e, 0x43, 0x3c, 0xa3, 0x0d, 0xe0, 0xbc, 0x87, 0x28, 0x8f, 0x3c,
+  0x7a, 0x8c, 0x86, 0x3c, 0xa0, 0xc8, 0xcc, 0xbb, 0x5a, 0xec, 0x83, 0xbc, 0x7b, 0x7d, 0x25, 0xbb,
+  0xa3, 0xba, 0x1e, 0xbb, 0x66, 0x14, 0x7c, 0x3c, 0xe6, 0x81, 0x95, 0xbb, 0x55, 0x3c, 0x25, 0xbc,
+  0x61, 0x7e, 0x8f, 0x3c, 0x0c, 0x62, 0x94, 0xba, 0x9d, 0xc6, 0xa4, 0xbb, 0x24, 0x51, 0x7d, 0x3b,
+  0x7a, 0xff, 0xab, 0xbb, 0xd7, 0x54, 0x37, 0x3c, 0x75, 0xc8, 0xe1, 0x3b, 0x03, 0x4f, 0x0c, 0x3b,
+  0x1c, 0x48, 0x5d, 0x3c, 0xc4, 0x91, 0x64, 0xbb, 0x0b, 0x6f, 0x0c, 0xbc, 0xbf, 0x23, 0x1f, 0xbc,
+  0x0e, 0x04, 0x71, 0xbc, 0x0e, 0x0f, 0x3d, 0x3b, 0xd8, 0xfb, 0x09, 0x3c, 0x9d, 0xea, 0xb5, 0xb9,
+  0xc7, 0x1f, 0xa5, 0x3c, 0x8b, 0x2c, 0x18, 0x3c, 0xfc, 0xcd, 0x16, 0xbc, 0x78, 0x8d, 0x91, 0xba,
+  0x68, 0x23, 0x1a, 0x3b, 0xaa, 0x48, 0x39, 0x3c, 0xdb, 0xf3, 0x90, 0x3c, 0xe9, 0x52, 0x7c, 0x3c,
+  0x06, 0xd4, 0x8b, 0x3b, 0x70, 0xdc, 0x15, 0x3c, 0x8e, 0xbe, 0x28, 0xbc, 0x6e, 0xa0, 0xa0, 0xbc,
+  0x0e, 0xd9, 0x1b, 0x3b, 0xcd, 0x77, 0x3d, 0x3b, 0x2c, 0xf6, 0xc7, 0x3c, 0x75, 0xe6, 0x90, 0x3c,
+  0x57, 0x81, 0xb0, 0xb9, 0x30, 0x10, 0x9d, 0x3b, 0x70, 0x1f, 0xfc, 0xbb, 0xed, 0xc9, 0x28, 0xbc,
+  0x8c, 0xc6, 0x31, 0x3c, 0x86, 0x45, 0x76, 0xbc, 0xb7, 0x31, 0xbd, 0x3c, 0xb7, 0xc2, 0x41, 0xbb,
+  0x72, 0x0f, 0xcd, 0x3b, 0xc7, 0x15, 0x9f, 0x3b, 0x4b, 0x32, 0xf6, 0x3a, 0x94, 0x03, 0x67, 0xb9,
+  0x6f, 0x7c, 0xd9, 0x3b, 0xa1, 0x4f, 0x33, 0xbc, 0x14, 0x5d, 0x2c, 0x3c, 0xc9, 0xd2, 0x7b, 0x3c,
+  0x4e, 0x77, 0xcb, 0x3b, 0xdc, 0xa5, 0x8d, 0x3a, 0x6a, 0xa9, 0x39, 0xbc, 0x50, 0x47, 0x12, 0xbc,
+  0x4f, 0xc3, 0x51, 0x3b, 0x50, 0xa9, 0x3d, 0xbc, 0x85, 0xb9, 0xe9, 0x3c, 0xab, 0x85, 0xec, 0xbb,
+  0xbb, 0x7c, 0x98, 0xbc, 0xb2, 0x77, 0x3f, 0xbb, 0xea, 0x94, 0x74, 0xbc, 0xb0, 0x01, 0x12, 0xbc,
+  0xc4, 0x9d, 0x3f, 0x3c, 0x1a, 0xfd, 0x01, 0xbb, 0x8e, 0xf3, 0xfd, 0xbb, 0x7b, 0xd9, 0x88, 0x3b,
+  0x69, 0x58, 0x63, 0xbc, 0x90, 0x58, 0x1d, 0x3b, 0xb3, 0x76, 0x60, 0xba, 0xec, 0xfe, 0xb6, 0xbc,
+  0xce, 0x37, 0xa5, 0x3b, 0xb2, 0xe5, 0xdc, 0x3b, 0x36, 0x5d, 0xb1, 0xbb, 0x31, 0x4f, 0x92, 0x3c,
+  0x82, 0xa4, 0xb7, 0xba, 0xf9, 0x0c, 0x1d, 0xbb, 0x01, 0xf1, 0xbb, 0x3c, 0xcb, 0x29, 0x6f, 0x3c,
+  0x96, 0xc6, 0x78, 0x3b, 0xae, 0xd9, 0xfa, 0xba, 0xfb, 0x31, 0xbb, 0x3b, 0x19, 0x07, 0x7f, 0x3c,
+  0x5a, 0x1a, 0x2e, 0xbc, 0x20, 0x0d, 0xdd, 0xba, 0xe0, 0x30, 0x55, 0xbc, 0x3f, 0x28, 0x69, 0x3c,
+  0x76, 0x4b, 0x2d, 0x3c, 0x40, 0x81, 0xa8, 0xbb, 0xe0, 0xc6, 0xb8, 0xbb, 0xe2, 0x0b, 0xec, 0xba,
+  0x63, 0x52, 0x00, 0xbc, 0x66, 0x19, 0x2b, 0xbc, 0x30, 0x35, 0xea, 0xbc, 0xd1, 0x21, 0x81, 0x3c,
+  0xa5, 0xd0, 0x97, 0x3c, 0x1a, 0x69, 0x34, 0xbc, 0xc5, 0xc6, 0xa7, 0x3c, 0x01, 0x5d, 0x92, 0xbc,
+  0xbf, 0x01, 0x92, 0xbc, 0xb1, 0xc0, 0x1c, 0xbc, 0x09, 0xae, 0x52, 0xbc, 0x7b, 0x8b, 0x91, 0xba,
+  0xbe, 0x6d, 0xd9, 0x3c, 0x3a, 0x63, 0x6c, 0xbc, 0x7d, 0x45, 0x09, 0x3d, 0x76, 0xf3, 0x91, 0x3c,
+  0x15, 0x5e, 0x47, 0xbb, 0x0a, 0x3e, 0x1c, 0xbc, 0xf0, 0x2f, 0x5f, 0xbc, 0xb5, 0xe0, 0xcb, 0xbb,
+  0x21, 0x11, 0x44, 0x3c, 0x66, 0x5b, 0xd5, 0xbb, 0x8e, 0x5a, 0x15, 0x3d, 0xbe, 0x98, 0x3f, 0x3b,
+  0x93, 0x61, 0x08, 0x39, 0x3b, 0x41, 0x13, 0xbb, 0xb6, 0x41, 0x24, 0xbc, 0x0d, 0x3b, 0x00, 0x3c,
+  0x89, 0xe7, 0xf3, 0x3b, 0xcd, 0x17, 0x87, 0xbb, 0x50, 0x9c, 0xa4, 0x3c, 0x93, 0x20, 0x72, 0xbb,
+  0xf7, 0x09, 0x34, 0xbc, 0xd9, 0x58, 0x38, 0x3c, 0x9c, 0x31, 0x0d, 0xbc, 0xee, 0x08, 0x80, 0x3c,
+  0x14, 0x45, 0x3f, 0xbc, 0x49, 0xb7, 0xa9, 0xbc, 0xc5, 0x36, 0xbf, 0xbb, 0xa8, 0x56, 0x9a, 0x3b,
+  0xec, 0x43, 0x12, 0xbc, 0xdf, 0x1a, 0x8f, 0x3c, 0xee, 0xde, 0x7d, 0xba, 0x70, 0x8e, 0x65, 0xbb,
+  0x9c, 0x91, 0x19, 0xbd, 0x74, 0x18, 0x06, 0xbd, 0x80, 0x31, 0xc5, 0xbb, 0xf1, 0xac, 0x61, 0x3c,
+  0xf2, 0xd4, 0x61, 0xb7, 0x7a, 0x21, 0xba, 0x3c, 0x9b, 0x95, 0x69, 0x3b, 0xcc, 0x19, 0x84, 0x3b,
+  0x9c, 0xfc, 0x72, 0xbc, 0xc6, 0xe5, 0xec, 0xbb, 0x03, 0x26, 0x13, 0xbc, 0xe9, 0xae, 0x98, 0x3c,
+  0x43, 0x1d, 0x97, 0x3c, 0x25, 0x94, 0x5e, 0xba, 0x43, 0x7c, 0x84, 0x3c, 0x75, 0x55, 0xd5, 0xba,
+  0x77, 0xb8, 0x89, 0x3a, 0x1d, 0x25, 0x79, 0x3c, 0x51, 0x9f, 0x9e, 0xbc, 0xd4, 0x7c, 0x19, 0x3b,
+  0x2f, 0x46, 0x8f, 0x3c, 0x29, 0x73, 0x1c, 0xbc, 0x77, 0xcb, 0xe6, 0xbb, 0x3b, 0x9a, 0x33, 0xba,
+  0x61, 0xf9, 0x9f, 0x3b, 0x57, 0x27, 0xf0, 0x3b, 0x93, 0xbe, 0x48, 0xbc, 0x96, 0x40, 0x94, 0xba,
+  0xbb, 0x2a, 0x09, 0x3d, 0x94, 0xf2, 0xa2, 0xba, 0x72, 0x27, 0x70, 0xbc, 0x83, 0x2f, 0xd2, 0xbc,
+  0xfc, 0x77, 0x8c, 0xbb, 0x88, 0x30, 0x87, 0x3c, 0xcb, 0x93, 0xc3, 0x3a, 0x54, 0x70, 0x82, 0x3b,
+  0xd7, 0xea, 0x81, 0x3c, 0x44, 0xeb, 0xa7, 0xbb, 0x17, 0x01, 0xeb, 0x3b, 0x06, 0x48, 0x8d, 0xbb,
+  0x83, 0x4c, 0x2b, 0xbb, 0xe8, 0x10, 0xb5, 0x3b, 0x1e, 0x77, 0x18, 0xbb, 0x5a, 0x1e, 0x20, 0x3c,
+  0xc9, 0x63, 0xb2, 0x3c, 0x98, 0x11, 0xa8, 0x3a, 0x1d, 0xc7, 0x55, 0xbc, 0x0d, 0x3f, 0x58, 0xbc,
+  0xfe, 0xe6, 0x8f, 0x3b, 0x72, 0xa9, 0xb0, 0x3b, 0x8a, 0x6c, 0x4f, 0x3c, 0x1e, 0x45, 0x4e, 0xbc,
+  0x55, 0xfa, 0xf9, 0x39, 0x62, 0xe9, 0x9c, 0x3c, 0xe5, 0xc3, 0x31, 0xbc, 0x8d, 0x67, 0xa6, 0xbc,
+  0xd1, 0xe6, 0xa8, 0x3b, 0x0b, 0x6c, 0x8e, 0xbb, 0xda, 0x79, 0xac, 0x3c, 0x56, 0xb6, 0x1f, 0xbb,
+  0x9d, 0x41, 0x06, 0x3c, 0xdc, 0x74, 0x0b, 0xbc, 0xed, 0xcc, 0xa8, 0x3b, 0xcd, 0xe5, 0x16, 0xbc,
+  0x47, 0x99, 0x34, 0x3c, 0x44, 0x56, 0xf4, 0xbb, 0x7b, 0x3c, 0xeb, 0x3c, 0xe1, 0x59, 0xae, 0xbb,
+  0xda, 0xd4, 0x6e, 0x3b, 0xb6, 0x7c, 0x41, 0xbb, 0x86, 0xa0, 0x7b, 0xbb, 0xf7, 0x18, 0xc9, 0xbc,
+  0x3a, 0x5b, 0x36, 0x3c, 0x36, 0x2d, 0x2e, 0xbb, 0x52, 0x24, 0xe1, 0x3c, 0xbc, 0xfa, 0x2c, 0xbc,
+  0xdb, 0x69, 0x07, 0x3c, 0xb2, 0xd3, 0xa7, 0xbb, 0x48, 0xf8, 0x17, 0xbc, 0x77, 0x27, 0x0e, 0xbc,
+  0xc1, 0x9a, 0x9b, 0x3b, 0x5f, 0x61, 0x19, 0xbc, 0x2f, 0xe2, 0xfe, 0x3c, 0xfa, 0x26, 0xa3, 0xbc,
+  0xdb, 0x84, 0x40, 0xbc, 0x39, 0x02, 0x6b, 0xbb, 0xe7, 0xcf, 0x45, 0xbb, 0x66, 0x98, 0xda, 0xbc,
+  0x66, 0x4d, 0x24, 0x3c, 0xfd, 0x68, 0x8b, 0xbb, 0x98, 0x04, 0x77, 0x3b, 0x25, 0x57, 0xd5, 0x3b,
+  0x77, 0x87, 0x61, 0xbc, 0x5b, 0x20, 0x6f, 0x3b, 0xed, 0x2b, 0x3a, 0xbc, 0x4c, 0x37, 0x20, 0xbc,
+  0x96, 0xa9, 0x9e, 0xba, 0x1a, 0xcc, 0x5b, 0xba, 0xb6, 0x04, 0xf2, 0xbb, 0x49, 0x3d, 0x52, 0xb9,
+  0x2d, 0xf6, 0x30, 0xbc, 0xa6, 0x9b, 0xc1, 0xbb, 0x4b, 0x8e, 0x8f, 0x3b, 0xb0, 0x8d, 0x95, 0x3c,
+  0xcf, 0x41, 0x5b, 0x3a, 0xa9, 0xae, 0x2d, 0x3c, 0x00, 0x2c, 0xfe, 0xbb, 0x47, 0xce, 0x2a, 0x3a,
+  0xa7, 0xe6, 0x06, 0xbc, 0xaa, 0x0c, 0x31, 0x3a, 0xe5, 0x63, 0xbd, 0xb9, 0xec, 0xf2, 0xaa, 0x3a,
+  0x1a, 0xf5, 0x83, 0x3c, 0x74, 0x25, 0x8f, 0xbc, 0x7a, 0x72, 0xfe, 0xba, 0xe7, 0xa8, 0xa5, 0xbb,
+  0x7f, 0x72, 0x83, 0xbc, 0xd8, 0xce, 0x55, 0xbc, 0x9e, 0x8d, 0xea, 0xbc, 0x90, 0x67, 0x90, 0x39,
+  0x66, 0x08, 0x9c, 0x3c, 0x11, 0xec, 0xab, 0xbc, 0x45, 0x8f, 0xdc, 0x3c, 0x5d, 0x70, 0x71, 0x3b,
+  0x33, 0xf8, 0xbd, 0xbc, 0xf9, 0xcd, 0x1b, 0xbc, 0x85, 0x67, 0xaa, 0xbc, 0x63, 0x03, 0xdc, 0x3a,
+  0x55, 0x1b, 0xb8, 0x3c, 0xd8, 0xea, 0xc2, 0xbc, 0xfe, 0xa1, 0x19, 0x3d, 0x09, 0xb3, 0x26, 0xbc,
+  0x79, 0x0e, 0x4d, 0xbb, 0x18, 0x0c, 0x45, 0xbc, 0x28, 0x11, 0x81, 0xbc, 0x31, 0x32, 0xf5, 0xbb,
+  0x04, 0xf7, 0x53, 0x3c, 0x73, 0x5e, 0xb2, 0xbb, 0x14, 0x0e, 0x01, 0x3d, 0x37, 0x85, 0xe4, 0xbb,
+  0x53, 0x60, 0xa4, 0xbb, 0x8a, 0x38, 0x90, 0x3b, 0x78, 0x81, 0xa7, 0xbc, 0x1b, 0x34, 0xa1, 0x3b,
+  0xa9, 0xa8, 0xd1, 0x3b, 0xb0, 0x72, 0x6d, 0x3b, 0xab, 0xc3, 0xfc, 0x3a, 0x04, 0xcd, 0x14, 0x3b,
+  0x04, 0xae, 0x6d, 0xbc, 0x0c, 0x95, 0xd9, 0x3b, 0x81, 0x27, 0xa1, 0xbc, 0xb5, 0x0e, 0x47, 0x3c,
+  0x23, 0x78, 0x91, 0xbc, 0x86, 0x67, 0x95, 0xbc, 0xfc, 0x2e, 0x73, 0xbc, 0x9c, 0x96, 0x8f, 0x3c,
+  0xb3, 0x3e, 0x84, 0xbc, 0x91, 0x21, 0x27, 0x3c, 0x71, 0xc8, 0xd4, 0x3b, 0x4e, 0xd9, 0x19, 0x3c,
+  0x68, 0x79, 0x02, 0xbd, 0x9c, 0x5f, 0x1c, 0xbd, 0x97, 0xa4, 0x60, 0xbc, 0xd1, 0x25, 0x53, 0xbc,
+  0x72, 0xf6, 0x8e, 0x3c, 0x86, 0xd4, 0x6e, 0x3c, 0xe2, 0x1f, 0x85, 0xbb, 0x0b, 0x24, 0xca, 0x3b,
+  0x49, 0x79, 0x9e, 0xbc, 0x67, 0xb4, 0x89, 0xbb, 0xe8, 0x51, 0xe1, 0xbb, 0xce, 0x75, 0xba, 0xb9,
+  0xba, 0x50, 0x3d, 0x3c, 0x8e, 0x1c, 0xb1, 0xbb, 0xc2, 0x42, 0x4c, 0x3b, 0x8d, 0x89, 0xfc, 0xbb,
+  0xd4, 0xa2, 0x92, 0x3a, 0x63, 0x46, 0x92, 0x3c, 0x76, 0x06, 0xa8, 0xbc, 0xf8, 0x53, 0x69, 0x3c,
+  0x9a, 0xad, 0xb3, 0x3c, 0x1e, 0xdb, 0x80, 0xbc, 0x26, 0xae, 0x40, 0xbc, 0x94, 0xef, 0x16, 0x3b,
+  0xbb, 0x55, 0x02, 0xbc, 0x8c, 0xfe, 0x06, 0x3c, 0xde, 0x2d, 0x39, 0xbc, 0xe1, 0xa7, 0x40, 0xbc,
+  0x57, 0x1e, 0x0b, 0x3d, 0x12, 0x0d, 0xc1, 0xbb, 0xca, 0xfa, 0x72, 0xbc, 0xde, 0x21, 0x84, 0xbc,
+  0x66, 0x09, 0x87, 0x3b, 0x1a, 0x3d, 0xd5, 0x3c, 0xb7, 0x9a, 0x49, 0x3c, 0x42, 0x96, 0x08, 0x3c,
+  0x3d, 0x5f, 0x03, 0x3c, 0xdf, 0x0a, 0xae, 0xbb, 0x5e, 0xa8, 0x0a, 0x3c, 0x68, 0x0e, 0x55, 0xbc,
+  0xf0, 0x52, 0x43, 0xbc, 0xab, 0x59, 0x3d, 0x3c, 0xd8, 0x72, 0xdf, 0x39, 0xd0, 0x50, 0x35, 0x3c,
+  0x1e, 0x17, 0xa5, 0x3c, 0xb0, 0x43, 0xce, 0x3a, 0xa4, 0x0f, 0x21, 0x3b, 0xac, 0x7c, 0x2a, 0xbc,
+  0x15, 0x69, 0x87, 0x3b, 0xc9, 0x45, 0xa7, 0x3b, 0x0b, 0xdb, 0x0a, 0x3c, 0x88, 0xc2, 0x04, 0x3b,
+  0x31, 0x63, 0x32, 0x3c, 0xc4, 0x15, 0x00, 0xbc, 0xaf, 0xae, 0x10, 0xbc, 0x30, 0x82, 0xa1, 0xbc,
+  0xe0, 0x51, 0x06, 0x3c, 0x58, 0x34, 0x11, 0xbc, 0xa4, 0x50, 0xeb, 0x3c, 0xf0, 0xfa, 0x32, 0x3c,
+  0xaa, 0x83, 0x2c, 0x3c, 0xef, 0x35, 0x2e, 0xba, 0x56, 0xe1, 0x7d, 0x3a, 0x90, 0xe7, 0x8b, 0xbc,
+  0x96, 0xe1, 0x80, 0x3c, 0xd5, 0x8a, 0xd0, 0xbb, 0xf4, 0xfe, 0xb3, 0x3c, 0x93, 0x87, 0x54, 0xbc,
+  0x47, 0x5e, 0x17, 0x3c, 0x6b, 0xce, 0x06, 0xbc, 0xdf, 0xb5, 0x1b, 0xbc, 0x35, 0x3b, 0x6d, 0xbc,
+  0xb0, 0x11, 0xf8, 0x3b, 0x8e, 0xf1, 0xba, 0xbc, 0xa2, 0x31, 0xb6, 0x3c, 0x06, 0x1e, 0x0e, 0xbc,
+  0x9e, 0xdb, 0x30, 0xba, 0xf6, 0x1d, 0x9f, 0x39, 0x40, 0x68, 0x7c, 0xbc, 0x88, 0x02, 0x50, 0xbc,
+  0xcf, 0x4d, 0xb0, 0x3b, 0x2c, 0xb5, 0x96, 0xbc, 0xd8, 0xa7, 0x73, 0x3c, 0x82, 0xc4, 0x6c, 0xbb,
+  0x78, 0x25, 0xa4, 0xbb, 0xf2, 0x44, 0x23, 0xbb, 0xaf, 0xd9, 0x5e, 0x3b, 0x66, 0x3b, 0x8f, 0xbc,
+  0xa7, 0xc6, 0x14, 0x3b, 0x11, 0x61, 0x99, 0xbb, 0x70, 0xe4, 0xbf, 0x3b, 0xf4, 0xf8, 0xd0, 0xbb,
+  0x04, 0x41, 0xfb, 0xbb, 0x76, 0x22, 0xf7, 0x3b, 0x23, 0x8e, 0x4c, 0xbb, 0x20, 0xf1, 0xa6, 0xbb,
+  0x73, 0x5d, 0xda, 0xbb, 0x69, 0x0b, 0xd3, 0x3b, 0x69, 0x1c, 0xfc, 0x3b, 0x68, 0x05, 0x87, 0xbb,
+  0xc5, 0x5c, 0x9b, 0xbb, 0x28, 0xc0, 0xc2, 0xb9, 0xda, 0x65, 0xa9, 0x3c, 0xb7, 0xf2, 0xc8, 0x3b,
+  0x92, 0xbf, 0x3b, 0x3b, 0x3b, 0x7a, 0x68, 0x3c, 0xdb, 0xec, 0xca, 0xbb, 0x66, 0xe5, 0xbe, 0x3b,
+  0x30, 0x62, 0x37, 0xbc, 0x02, 0x65, 0x2a, 0x3a, 0xf2, 0x1c, 0xdc, 0xbb, 0x3a, 0x18, 0x8a, 0x3c,
+  0x0d, 0x66, 0x55, 0xba, 0xa1, 0x9b, 0x35, 0xbc, 0xfb, 0xd8, 0x89, 0xbc, 0xc7, 0x45, 0x09, 0x3c,
+  0x84, 0x8e, 0x88, 0xbc, 0x67, 0x7f, 0x8d, 0xbb, 0xa8, 0xd1, 0x07, 0xbd, 0xfe, 0x9e, 0x85, 0x3c,
+  0xb1, 0x3c, 0x57, 0x3c, 0x3b, 0x14, 0xae, 0xbc, 0xc5, 0x9d, 0xdb, 0x3c, 0x56, 0x49, 0xa2, 0x3c,
+  0x35, 0xa0, 0xab, 0xbc, 0xb3, 0x7c, 0xbe, 0xbc, 0x8c, 0x49, 0xae, 0xbb, 0x43, 0x41, 0x52, 0xbb,
+  0x76, 0x5e, 0x98, 0x3c, 0x37, 0x44, 0x89, 0xbc, 0xa6, 0x52, 0x0a, 0x3d, 0xd3, 0x0b, 0x6e, 0x37,
+  0x70, 0x39, 0xdf, 0xbb, 0xde, 0x97, 0x51, 0xbc, 0x29, 0xef, 0x94, 0x3b, 0x9d, 0x04, 0xea, 0xba,
+  0x27, 0x9e, 0xd6, 0x3b, 0xea, 0xed, 0x4c, 0xbb, 0x0d, 0x6f, 0xcb, 0x3c, 0x06, 0x9e, 0x97, 0x3b,
+  0xc4, 0x2d, 0x74, 0x3a, 0xb0, 0xef, 0xa2, 0xba, 0xa8, 0x9d, 0x1e, 0xbc, 0xa5, 0xae, 0x92, 0x3c,
+  0xf8, 0x65, 0x65, 0x3c, 0x11, 0x00, 0xaf, 0x3a, 0xd4, 0x04, 0x27, 0x3c, 0x6d, 0xe8, 0x93, 0x3b,
+  0x03, 0xa8, 0xec, 0xbb, 0xd0, 0x14, 0x50, 0x3c, 0xb3, 0x3f, 0xbb, 0xbc, 0x2d, 0x81, 0x32, 0x3c,
+  0xf0, 0x03, 0x94, 0xbc, 0x67, 0xae, 0x95, 0xbc, 0x1b, 0xa9, 0x43, 0xbc, 0xec, 0x7b, 0x53, 0x3b,
+  0xa7, 0xf6, 0x63, 0xbc, 0xa5, 0xd2, 0x21, 0x3c, 0x5e, 0xc2, 0xf2, 0xbb, 0xe5, 0xf0, 0x85, 0x3a,
+  0xd7, 0xbe, 0x0a, 0xbd, 0x55, 0x83, 0xc4, 0xbc, 0xf3, 0x9a, 0x4e, 0xbc, 0x15, 0xcc, 0xb6, 0x3b,
+  0xb9, 0x33, 0xff, 0x3b, 0xcc, 0x14, 0xbf, 0x3c, 0x7f, 0xdd, 0x89, 0xba, 0xa8, 0x64, 0x86, 0xbb,
+  0x03, 0x68, 0x98, 0xbc, 0x85, 0xdd, 0x4a, 0xbb, 0xd5, 0x7b, 0x15, 0xbc, 0xc5, 0x3a, 0x16, 0xbc,
+  0xde, 0x14, 0xc7, 0x3c, 0xf8, 0x38, 0xbe, 0xbb, 0x5b, 0xfa, 0x44, 0x3c, 0xf8, 0x00, 0x43, 0xbc,
+  0xad, 0xb9, 0x7e, 0xba, 0x6f, 0x4b, 0xf8, 0x3c, 0x0e, 0x7f, 0x55, 0xbc, 0x44, 0xdb, 0x3b, 0x3b,
+  0x2d, 0x2b, 0xb5, 0x3c, 0xf3, 0xb3, 0x4b, 0xbc, 0x66, 0x0e, 0xdb, 0xbb, 0xeb, 0xee, 0x8c, 0xbc,
+  0x2f, 0x9b, 0xae, 0xbb, 0x90, 0x08, 0x3f, 0x3c, 0x53, 0x0b, 0x4c, 0xbc, 0x1c, 0x65, 0x00, 0x3a,
+  0xaf, 0xdb, 0xb9, 0x3c, 0xf7, 0x8f, 0x0b, 0xbc, 0xcf, 0x79, 0x44, 0xbc, 0x1b, 0x9e, 0x5a, 0xbc,
+  0x80, 0xbf, 0x8b, 0xba, 0x1f, 0xda, 0xab, 0x3c, 0x37, 0x4c, 0xa5, 0x3a, 0x15, 0x80, 0x91, 0xbb,
+  0xd1, 0xcb, 0x7c, 0x3c, 0x0e, 0x63, 0x22, 0x3b, 0x85, 0xb7, 0x59, 0x3b, 0x66, 0xba, 0x69, 0xbc,
+  0x06, 0xe7, 0x46, 0x3b, 0xda, 0x8c, 0x6b, 0x3c, 0x2f, 0x91, 0x0e, 0x3b, 0xd8, 0xe8, 0x18, 0xbc,
+  0x34, 0x38, 0xb8, 0x3c, 0x57, 0xa1, 0xd5, 0x3a, 0x35, 0xb1, 0x2b, 0xbc, 0x4b, 0x8e, 0x7a, 0xbb,
+  0xf3, 0x0d, 0xda, 0x3b, 0x2f, 0x84, 0xb6, 0x3b, 0x7a, 0xc9, 0x72, 0x3c, 0xe3, 0x3c, 0x3a, 0xba,
+  0xcc, 0x6e, 0x7c, 0x3c, 0x14, 0x69, 0xc3, 0xbb, 0x73, 0x42, 0x3d, 0xbc, 0xe9, 0x34, 0x70, 0xbc,
+  0x31, 0xe2, 0x58, 0x3c, 0xf0, 0xa2, 0x1f, 0xbc, 0xc3, 0x47, 0x85, 0x3c, 0xc5, 0x33, 0x6b, 0x3c,
+  0x51, 0xd9, 0x0d, 0x3b, 0x5f, 0xdd, 0xc6, 0xba, 0x98, 0xbf, 0xa9, 0xbb, 0x2a, 0x83, 0xd2, 0xbc,
+  0x85, 0xf4, 0xbd, 0x3c, 0x0e, 0xff, 0x33, 0xbc, 0x20, 0xcf, 0xbc, 0x3c, 0x50, 0xed, 0x5e, 0xbc,
+  0x61, 0x55, 0x19, 0x3c, 0xac, 0xc8, 0x00, 0xba, 0xd8, 0x14, 0xd7, 0xbb, 0xfe, 0x82, 0x8c, 0xbc,
+  0xe5, 0x22, 0x33, 0x3c, 0x43, 0x80, 0x7d, 0xbb, 0x06, 0xcc, 0x93, 0x3c, 0xc3, 0xa3, 0x72, 0xbc,
+  0x9f, 0x0c, 0xb3, 0x3b, 0xb2, 0x74, 0x08, 0x3a, 0x71, 0xbf, 0x02, 0x3c, 0x60, 0xc0, 0xf1, 0xbc,
+  0xad, 0x29, 0x65, 0x3a, 0x47, 0x2f, 0xef, 0xbb, 0xf1, 0xe0, 0xd4, 0x3c, 0x4e, 0xad, 0xff, 0x3b,
+  0x8e, 0x7d, 0x80, 0x3a, 0x37, 0x0f, 0x13, 0x3b, 0x00, 0x98, 0x16, 0xbc, 0xc1, 0x84, 0xe5, 0xbb,
+  0xd2, 0xb6, 0x21, 0x3c, 0xce, 0x74, 0x3c, 0xbb, 0x97, 0xcf, 0x30, 0x3c, 0x3d, 0xa5, 0x76, 0xbb,
+  0xdf, 0x02, 0x88, 0xbb, 0x92, 0x58, 0xf2, 0xbb, 0xde, 0x56, 0x3d, 0xbc, 0x6c, 0x79, 0xb1, 0xbc,
+  0x3c, 0xab, 0xbb, 0xba, 0x0a, 0xc0, 0x6b, 0x3b, 0x78, 0x7e, 0x1c, 0xbb, 0xf8, 0x8f, 0x9a, 0x3c,
+  0x9b, 0x5b, 0xae, 0xbb, 0xa9, 0xcb, 0xaa, 0xbb, 0xb7, 0x79, 0x12, 0x3c, 0xc6, 0x3e, 0x48, 0x3b,
+  0x3e, 0x45, 0xb1, 0x3b, 0x5f, 0xe8, 0xfc, 0xbb, 0xd8, 0x69, 0x26, 0x3a, 0xae, 0x2c, 0x53, 0xbb,
+  0x22, 0x11, 0x9f, 0xbc, 0x24, 0x76, 0xda, 0x3b, 0xb9, 0x50, 0x1f, 0xbc, 0x5f, 0xb7, 0x10, 0x3c,
+  0xbc, 0xec, 0x84, 0xba, 0xf6, 0x67, 0xa7, 0xba, 0xcd, 0xd3, 0x0d, 0xbc, 0x51, 0x76, 0x8f, 0x3c,
+  0x0e, 0xb2, 0x9e, 0xbc, 0x05, 0x40, 0xef, 0xbb, 0xce, 0xd0, 0x18, 0xbd, 0xa2, 0xbc, 0x89, 0x3b,
+  0x1e, 0xea, 0x5a, 0x3c, 0xfc, 0xdd, 0xff, 0xbc, 0x97, 0x60, 0xca, 0x3c, 0xb5, 0x7d, 0x2a, 0xbc,
+  0xe8, 0x86, 0xdb, 0xbc, 0x57, 0x5e, 0x30, 0xbc, 0x44, 0x05, 0x92, 0xbc, 0x8a, 0xe0, 0xdb, 0x3b,
+  0x35, 0xad, 0x8c, 0x3c, 0xae, 0x1d, 0x84, 0xbc, 0xf4, 0x51, 0x0b, 0x3d, 0xb9, 0xc1, 0x5e, 0xba,
+  0x50, 0x1a, 0x8e, 0xbc, 0x4b, 0xc4, 0x78, 0xbc, 0x94, 0x62, 0xce, 0xbb, 0xcd, 0x0f, 0x31, 0x3b,
+  0x3c, 0xc2, 0x7d, 0x3c, 0x0b, 0x49, 0x90, 0xba, 0xe6, 0x75, 0xa9, 0x3c, 0xf9, 0xd0, 0x96, 0xbb,
+  0xa7, 0x3f, 0x3a, 0x3c, 0x95, 0xc0, 0x1d, 0x3c, 0x0f, 0x66, 0xc7, 0xbc, 0x45, 0x52, 0x43, 0x3c,
+  0x80, 0x10, 0x29, 0x3c, 0x33, 0x39, 0x9a, 0xba, 0xc4, 0xa7, 0x4f, 0x3c, 0xbb, 0xbd, 0x22, 0x3c,
+  0x5d, 0x07, 0x81, 0xbb, 0x2e, 0xdf, 0x02, 0x3c, 0x14, 0xe0, 0xb8, 0xbb, 0x98, 0xda, 0x84, 0x3c,
+  0xb5, 0x40, 0xa1, 0xbc, 0x2a, 0x0b, 0xcc, 0xbc, 0x11, 0x02, 0x88, 0xbc, 0x6f, 0x4c, 0x28, 0x3c,
+  0xd9, 0x0b, 0x8f, 0xbc, 0x32, 0x3a, 0x1f, 0x3c, 0xb3, 0xc9, 0x65, 0xbb, 0x0d, 0x27, 0x75, 0x3a,
+  0x09, 0xca, 0x07, 0xbd, 0xc5, 0xed, 0xd2, 0xbc, 0xcf, 0x82, 0x61, 0xbc, 0xd1, 0x6b, 0xcf, 0xbb,
+  0x07, 0x89, 0xd3, 0x3b, 0x84, 0xe3, 0x6a, 0x3c, 0xa8, 0x8a, 0xa3, 0x3c, 0xa0, 0xe1, 0xb8, 0x3b,
+  0x5e, 0xef, 0x5a, 0xbc, 0xce, 0x8c, 0x19, 0x3b, 0xe7, 0xfe, 0x77, 0xbc, 0x30, 0x3a, 0x3d, 0x3c,
+  0x3d, 0x6e, 0xa4, 0x3c, 0x76, 0xa1, 0x67, 0x3b, 0x67, 0xe8, 0x7c, 0x3c, 0xfe, 0x9c, 0x11, 0xbc,
+  0x46, 0x64, 0x9e, 0xbb, 0xc4, 0xdc, 0x31, 0x3c, 0x9e, 0x05, 0xc2, 0xbc, 0x02, 0xed, 0xbd, 0xbb,
+  0x91, 0xed, 0xa4, 0x3c, 0x57, 0xcd, 0xa4, 0xbc, 0xb8, 0xc7, 0x1b, 0xbb, 0x53, 0x20, 0xc3, 0xbc,
+  0x00, 0x2a, 0xbd, 0x3a, 0x59, 0x96, 0xd7, 0x3c, 0x41, 0x15, 0x6b, 0xbc, 0xa3, 0x40, 0xc7, 0xba,
+  0xa8, 0x18, 0x65, 0x3c, 0x20, 0x49, 0x1b, 0xbb, 0x05, 0x6b, 0x57, 0xbc, 0x0d, 0xa3, 0x7c, 0xbc,
+  0x8b, 0x6f, 0x21, 0x3b, 0xcc, 0x44, 0xa1, 0x3c, 0xe6, 0x15, 0x08, 0xbc, 0xa9, 0x1f, 0x29, 0x3c,
+  0x05, 0x4e, 0x88, 0x3c, 0x6b, 0xd7, 0x90, 0xbb, 0x35, 0x9c, 0x2a, 0x3a, 0x37, 0x3b, 0xc0, 0xbb,
+  0x80, 0xbb, 0xb8, 0x3b, 0x5b, 0xcf, 0x1f, 0x3c, 0x6f, 0x7c, 0xc7, 0xb9, 0xc5, 0x71, 0x09, 0xbc,
+  0x0f, 0x87, 0xc1, 0x3c, 0x53, 0x7e, 0x5b, 0xbb, 0xd1, 0x4d, 0x0e, 0x3c, 0xa3, 0x7b, 0x50, 0xbb,
+  0x84, 0xd6, 0x1b, 0x3c, 0xe4, 0xc6, 0xa3, 0xbb, 0x1b, 0x41, 0xbb, 0x3b, 0x91, 0xae, 0x9c, 0xbb,
+  0x8f, 0xbb, 0xa6, 0x3b, 0xfc, 0xbe, 0xe3, 0x3b, 0x2f, 0x87, 0x9b, 0xbc, 0x34, 0x48, 0x8c, 0xbc,
+  0xe9, 0x2e, 0x80, 0xba, 0xfe, 0xa2, 0xe7, 0x3b, 0xe9, 0x28, 0xd9, 0x3c, 0xd8, 0xf1, 0x32, 0xbb,
+  0x65, 0xf4, 0x0d, 0x3a, 0x94, 0x14, 0x86, 0x3b, 0xfc, 0xd0, 0xeb, 0x3a, 0x0c, 0x1c, 0xb9, 0xbc,
+  0xbe, 0xcc, 0xa9, 0x3b, 0x0f, 0x45, 0xba, 0x3b, 0xb5, 0x8f, 0xa2, 0x3c, 0x37, 0x0c, 0xc9, 0xbb,
+  0xbe, 0xda, 0xa3, 0x3b, 0x21, 0xe7, 0x4e, 0xbb, 0xea, 0xd7, 0x17, 0xbc, 0x7a, 0xa5, 0xf4, 0xbc,
+  0x6a, 0x38, 0x3a, 0x3c, 0x41, 0x3d, 0xc0, 0xbb, 0xed, 0x64, 0x91, 0x3c, 0xf5, 0xfc, 0x39, 0x3c,
+  0x5f, 0x54, 0xe5, 0x3b, 0xf3, 0xa3, 0x6c, 0x3b, 0x7c, 0xee, 0x87, 0xbb, 0xbf, 0x33, 0x16, 0xbc,
+  0x20, 0xc8, 0x74, 0x3c, 0xb0, 0xd2, 0x8b, 0xbb, 0x94, 0x00, 0x1a, 0x3d, 0xbc, 0x48, 0xd5, 0x3b,
+  0xd9, 0x38, 0xfc, 0xbb, 0x65, 0xb8, 0x5b, 0xbc, 0x1c, 0xd3, 0x4e, 0x38, 0x27, 0x33, 0x22, 0xbc,
+  0x13, 0x06, 0x2d, 0xbb, 0xda, 0xcf, 0x49, 0x3c, 0xdd, 0xad, 0xb9, 0x3b, 0x5a, 0x90, 0xc9, 0x3a,
+  0xcd, 0x7f, 0x32, 0xbc, 0xb9, 0x79, 0xff, 0xba, 0x8d, 0x67, 0x01, 0xbc, 0xa5, 0xbf, 0xcb, 0xbc,
+  0x07, 0x43, 0x3b, 0x3b, 0xed, 0x37, 0x28, 0x3b, 0xd4, 0x58, 0xe1, 0xbb, 0x20, 0xfc, 0x10, 0x3c,
+  0xa7, 0x30, 0xde, 0x3a, 0x90, 0x0b, 0x69, 0xbc, 0x9a, 0x55, 0x2e, 0x3c, 0x0b, 0x69, 0x95, 0x3b,
+  0xee, 0x1f, 0x9c, 0x3b, 0x72, 0xb1, 0xca, 0xbb, 0x1c, 0xed, 0xad, 0x3b, 0xf1, 0x37, 0xcb, 0xbb,
+  0x66, 0x19, 0x8e, 0xbc, 0xf8, 0x05, 0xd7, 0xba, 0x57, 0x51, 0xf6, 0x3b, 0x6f, 0x67, 0xf2, 0xba,
+  0x2c, 0xed, 0xda, 0x3b, 0x67, 0xc4, 0x69, 0xbc, 0x7c, 0x0e, 0x7c, 0xbc, 0xd6, 0xc0, 0x55, 0xba,
+  0xa5, 0x0e, 0xff, 0xbb, 0x16, 0x13, 0xf9, 0xb9, 0xe0, 0x01, 0x1b, 0xbd, 0xc5, 0x30, 0x38, 0x3b,
+  0x20, 0x04, 0x56, 0x3c, 0x20, 0xe0, 0x58, 0xbc, 0xa6, 0x08, 0xbc, 0x3c, 0x15, 0x16, 0x12, 0x3c,
+  0xba, 0x84, 0xe2, 0xbc, 0x8c, 0x66, 0xf0, 0xbc, 0x2e, 0x86, 0x2e, 0xbb, 0x16, 0xb4, 0xbc, 0x3b,
+  0xe9, 0xae, 0x6b, 0x3c, 0x2d, 0x48, 0x97, 0xbc, 0x90, 0x9b, 0x2a, 0x3d, 0x2a, 0xab, 0x01, 0x3c,
+  0x13, 0x3f, 0x73, 0xbc, 0x4f, 0xc9, 0xa4, 0xbc, 0x3d, 0x25, 0x3b, 0xbb, 0xfe, 0x31, 0x0e, 0xbc,
+  0xa3, 0x5f, 0x61, 0x3c, 0xee, 0xf7, 0x88, 0xbb, 0x3a, 0x56, 0xd9, 0x3c, 0x8b, 0xe7, 0x2f, 0xbc,
+  0x3e, 0x0d, 0xfe, 0xbb, 0x57, 0xc1, 0x0d, 0x3b, 0xba, 0x76, 0x06, 0xbc, 0x52, 0x7b, 0x8e, 0x3c,
+  0x47, 0x1a, 0x69, 0x3c, 0x26, 0xdf, 0xeb, 0xbb, 0x34, 0x39, 0xf8, 0x3b, 0x1f, 0x40, 0x39, 0xbc,
+  0xae, 0xac, 0x24, 0xbc, 0xf7, 0x92, 0x45, 0x3c, 0x7c, 0x30, 0xb7, 0xbc, 0x7a, 0x70, 0x38, 0x3c,
+  0x7e, 0x28, 0xa9, 0xbb, 0xaf, 0x5f, 0xdd, 0xbc, 0xe2, 0xd8, 0x6e, 0xbb, 0x2d, 0x1d, 0x1f, 0xbc,
+  0xee, 0x36, 0xac, 0xbb, 0xcb, 0xd9, 0x73, 0x3c, 0xb7, 0x29, 0xd4, 0xbb, 0x34, 0xdb, 0x32, 0xba,
+  0xbf, 0x60, 0x17, 0xbd, 0x05, 0xd6, 0xb4, 0xbc, 0xec, 0x61, 0x48, 0xbc, 0xb5, 0x21, 0xe1, 0x3b,
+  0xb8, 0x41, 0x30, 0x3b, 0x82, 0x0e, 0xb6, 0x3c, 0x10, 0x24, 0x53, 0x3b, 0xb2, 0x94, 0x34, 0x3c,
+  0x8b, 0x63, 0x7a, 0xbc, 0xce, 0xf6, 0xac, 0xbb, 0x4e, 0xde, 0x57, 0x3a, 0xa4, 0xd7, 0x65, 0xbb,
+  0x8b, 0x8c, 0x7c, 0x3c, 0xdd, 0xf9, 0x50, 0x3b, 0x45, 0x26, 0x29, 0x3c, 0xa4, 0xa6, 0x82, 0x3b,
+  0x43, 0x3b, 0x3e, 0xbc, 0x78, 0x42, 0x60, 0x3c, 0x02, 0x7a, 0xb0, 0xbc, 0x07, 0x56, 0x6e, 0x3b,
+  0x63, 0xa6, 0xcb, 0x3c, 0xc3, 0x4f, 0x96, 0xbc, 0x9b, 0x95, 0xdf, 0xbb, 0x87, 0xf8, 0xc4, 0xbc,
+  0x79, 0x95, 0x27, 0xbb, 0x22, 0xa3, 0x6f, 0x3c, 0xe5, 0x2d, 0x74, 0xbc, 0x53, 0xf5, 0x1b, 0x37,
+  0x46, 0x50, 0xb0, 0x3c, 0x84, 0xd8, 0x92, 0xbc, 0x2a, 0x02, 0x82, 0xbc, 0xa8, 0x03, 0xca, 0xbc,
+  0x64, 0x8c, 0x22, 0x3b, 0x69, 0x25, 0x25, 0xbb, 0xb2, 0x68, 0x91, 0xbb, 0xf2, 0xaa, 0x4e, 0xb9,
+  0xf9, 0x9d, 0xc7, 0x3c, 0xb1, 0x09, 0x4c, 0xbb, 0x8e, 0xd3, 0xa6, 0x3b, 0xd7, 0xa8, 0x36, 0x3a,
+  0x64, 0x9c, 0x11, 0x3c, 0x5e, 0xfd, 0x9b, 0x3c, 0x38, 0x71, 0x70, 0xbb, 0x67, 0xb3, 0x66, 0x3b,
+  0x73, 0x95, 0x8e, 0x3c, 0x59, 0x8f, 0x7b, 0xbb, 0x27, 0x6b, 0xf2, 0x3b, 0x8f, 0x06, 0xa6, 0x3a,
+  0x0c, 0x7b, 0xcc, 0x3b, 0xce, 0x93, 0x36, 0xbc, 0xde, 0x44, 0x39, 0x3b, 0x1a, 0x5e, 0x8e, 0xba,
+  0xf8, 0x0a, 0x3e, 0x3c, 0x59, 0x6f, 0x5f, 0xbb, 0xd3, 0xf7, 0x16, 0xbc, 0x4a, 0x5d, 0xb1, 0xbb,
+  0xbd, 0x24, 0xb8, 0x3b, 0xee, 0xa4, 0x7e, 0xbc, 0x32, 0xb8, 0xad, 0x3c, 0x55, 0x92, 0xd4, 0x3b,
+  0x7b, 0x6c, 0x69, 0xbb, 0x1f, 0x1d, 0x32, 0x3b, 0xc5, 0xa9, 0x25, 0xbb, 0x93, 0x76, 0xc4, 0xbc,
+  0xfc, 0xed, 0x97, 0x3c, 0x01, 0xbb, 0x3c, 0xbc, 0xab, 0x69, 0xa1, 0x3c, 0x92, 0xf6, 0x44, 0x3c,
+  0x1f, 0x16, 0x5c, 0xbb, 0x69, 0x4a, 0xf0, 0x39, 0x63, 0xbf, 0xdf, 0x3b, 0x53, 0xc2, 0xdb, 0xbc,
+  0x04, 0xce, 0x92, 0x3c, 0xf7, 0xbe, 0x15, 0xbc, 0xcf, 0x09, 0xbe, 0x3c, 0xd9, 0x7a, 0x24, 0xbc,
+  0x13, 0x0c, 0x9e, 0x39, 0x95, 0xe9, 0x9a, 0xba, 0xff, 0xda, 0xf8, 0x3b, 0x9d, 0x1a, 0x8e, 0xbc,
+  0xa5, 0x92, 0x6c, 0x3c, 0xa5, 0x53, 0x3b, 0xb9, 0xd4, 0x44, 0x6c, 0x3c, 0x07, 0xe1, 0xfb, 0x3b,
+  0x83, 0xb4, 0x51, 0xbb, 0xd0, 0x87, 0x53, 0x39, 0x60, 0x0b, 0xec, 0xba, 0xf6, 0xbd, 0xdb, 0xbc,
+  0x10, 0xa6, 0xe0, 0x3b, 0x2c, 0xfe, 0x03, 0x3b, 0xf8, 0x19, 0x13, 0x3c, 0x46, 0xde, 0x04, 0x3b,
+  0xb1, 0xfe, 0xfc, 0xbb, 0x89, 0xfa, 0x45, 0x3a, 0xa9, 0xa8, 0x87, 0xba, 0x85, 0x99, 0x9e, 0xbc,
+  0x1f, 0x58, 0xef, 0x3b, 0xfb, 0xc1, 0x53, 0x3c, 0x13, 0x39, 0x89, 0xbb, 0x06, 0x73, 0x71, 0xbc,
+  0x1c, 0x96, 0x81, 0xbb, 0x72, 0x9d, 0x86, 0xbc, 0xbe, 0xdc, 0x0a, 0x3c, 0x57, 0x01, 0x6f, 0xbc,
+  0x62, 0xf7, 0x02, 0xbc, 0xd0, 0xfd, 0xa2, 0x3b, 0xf7, 0x95, 0x82, 0x3a, 0xff, 0x5e, 0x77, 0xbc,
+  0xe2, 0x5b, 0x8a, 0xbc, 0x05, 0xad, 0xe8, 0xbb, 0x98, 0x1c, 0xda, 0x3b, 0x2b, 0xf9, 0xa5, 0x3c,
+  0x02, 0x2c, 0x8f, 0x3c, 0xf6, 0x5b, 0x26, 0x3c, 0x0d, 0xb7, 0x24, 0xbc, 0x82, 0x8f, 0x57, 0x3a,
+  0x65, 0x5e, 0xbd, 0xbb, 0x9f, 0x05, 0xff, 0xbb, 0x00, 0x65, 0x00, 0xbd, 0xbf, 0x03, 0xe6, 0xba,
+  0xcc, 0xdf, 0x99, 0x3c, 0x5b, 0xcc, 0x8b, 0xbc, 0xf5, 0x43, 0x01, 0x3d, 0x78, 0xc7, 0xe7, 0x3b,
+  0x4e, 0x6f, 0x33, 0xbc, 0xaa, 0x37, 0x00, 0xbd, 0xfa, 0x5f, 0x3d, 0xbc, 0xe8, 0xcc, 0x7b, 0x3c,
+  0x63, 0x77, 0xc7, 0x3c, 0xc1, 0xc4, 0xd6, 0xbc, 0x1c, 0xf4, 0xf5, 0x3c, 0xf1, 0x96, 0xff, 0x3b,
+  0x8a, 0x7f, 0x1b, 0xbc, 0xd3, 0x34, 0xcb, 0xbb, 0x01, 0x65, 0xb3, 0x3a, 0xe3, 0x54, 0x97, 0x3a,
+  0x5c, 0xcf, 0xad, 0x3c, 0xb7, 0xbf, 0xed, 0x3a, 0x49, 0xfd, 0xdb, 0x3c, 0x71, 0x76, 0x3d, 0x3b,
+  0xbd, 0x87, 0x9e, 0x3b, 0x9a, 0xbe, 0x4d, 0xbb, 0x31, 0xbd, 0x52, 0xbc, 0x34, 0x6e, 0x5f, 0x3c,
+  0x62, 0x89, 0xf7, 0x3c, 0x41, 0xdb, 0xe7, 0x3b, 0x42, 0xc8, 0xb7, 0x3b, 0x64, 0xd7, 0x8f, 0x3c,
+  0xca, 0xd9, 0x67, 0xbc, 0x9d, 0x82, 0x2e, 0x3b, 0xb0, 0x1a, 0x49, 0xbc, 0x3a, 0x9f, 0xb1, 0x3a,
+  0xaa, 0xc2, 0xbd, 0xbb, 0x3b, 0x4a, 0xa2, 0xbc, 0x5a, 0x74, 0x89, 0xba, 0x6d, 0xfd, 0x99, 0xbb,
+  0x7c, 0x7d, 0x41, 0xbc, 0xbc, 0xd1, 0xb8, 0x3c, 0xee, 0x26, 0x31, 0xbb, 0xec, 0x87, 0xda, 0x3a,
+  0x8b, 0x17, 0x11, 0xbd, 0x88, 0x5e, 0xce, 0xbc, 0x76, 0xdb, 0xea, 0xbb, 0x8d, 0x8c, 0x04, 0x3c,
+  0x38, 0x22, 0x96, 0x3b, 0xd6, 0xaf, 0xab, 0x3c, 0x4e, 0x2b, 0xf8, 0xba, 0x6a, 0x1c, 0x68, 0x3c,
+  0x79, 0xd2, 0x7d, 0xbc, 0x60, 0xfc, 0x14, 0xba, 0x1c, 0xea, 0xf3, 0xbc, 0xc0, 0xbe, 0x8a, 0xbc,
+  0x91, 0x38, 0x65, 0x3c, 0xf3, 0xea, 0xcd, 0xbb, 0x0d, 0x4f, 0xfa, 0x3b, 0xf4, 0x06, 0x2d, 0xbb,
+  0xa6, 0x31, 0x51, 0x3b, 0xf8, 0x4f, 0x6c, 0x3c, 0xc7, 0x9b, 0xa1, 0xbb, 0x6d, 0x72, 0x77, 0x3c,
+  0x18, 0xdb, 0x5b, 0x3b, 0x45, 0x8e, 0x4e, 0xbc, 0xa5, 0xcb, 0xf1, 0xbb, 0x96, 0x2f, 0x9b, 0x3b,
+  0x2a, 0x11, 0x39, 0xbc, 0x73, 0x85, 0x97, 0x3c, 0x22, 0x58, 0xec, 0xbb, 0xc7, 0xca, 0xb0, 0xbb,
+  0xc8, 0xbb, 0x8d, 0x3c, 0x06, 0x2b, 0x18, 0xbc, 0x3b, 0x4c, 0xc7, 0xba, 0xbb, 0x5a, 0x0e, 0xbc,
+  0x4e, 0xea, 0x14, 0x3c, 0x4e, 0x89, 0x28, 0x3c, 0x2f, 0xcc, 0x35, 0xbc, 0x6e, 0x5e, 0x6b, 0xbc,
+  0xb9, 0xd9, 0x86, 0x3c, 0x7d, 0xad, 0x52, 0xbc, 0x62, 0x3d, 0x69, 0xbb, 0xd2, 0x7f, 0x87, 0xbc,
+  0xac, 0x3d, 0x66, 0x3c, 0xee, 0xf3, 0xc5, 0x3c, 0x87, 0x16, 0xe1, 0x3a, 0xec, 0x3d, 0x2e, 0xbb,
+  0x14, 0xac, 0x8f, 0x3c, 0xf0, 0x9b, 0x16, 0x39, 0x52, 0xf3, 0x0a, 0xbc, 0x3b, 0xc8, 0x9d, 0xba,
+  0xd8, 0x13, 0xa6, 0x3b, 0x24, 0x91, 0xe2, 0x3b, 0x47, 0x59, 0x8a, 0x3c, 0xd2, 0xb6, 0x42, 0xbb,
+  0x77, 0x7d, 0xee, 0x3b, 0x1d, 0xb6, 0xb6, 0x39, 0xaf, 0x19, 0x7c, 0xbb, 0x14, 0xc7, 0xfd, 0xbb,
+  0x80, 0x6b, 0x25, 0x3c, 0x96, 0x4e, 0x5d, 0xbc, 0xb9, 0x39, 0x83, 0x3c, 0x51, 0x30, 0x8c, 0xbb,
+  0x73, 0x1c, 0xf5, 0x3b, 0x73, 0x7f, 0x5a, 0xbb, 0xe3, 0x9f, 0x45, 0xbc, 0xbe, 0xf1, 0xf0, 0xbc,
+  0xc3, 0x66, 0x41, 0x3c, 0xd0, 0x7e, 0x6f, 0xbc, 0x98, 0x27, 0xcb, 0x3c, 0x74, 0x87, 0x8d, 0xb9,
+  0x91, 0x48, 0x11, 0xbc, 0x95, 0xf1, 0xb5, 0xbb, 0x9f, 0xd6, 0x06, 0xbc, 0x15, 0x07, 0xa1, 0xbc,
+  0xc7, 0x91, 0x82, 0x3c, 0x51, 0x96, 0xd0, 0x39, 0x7f, 0x42, 0xc0, 0x3c, 0x5c, 0x15, 0x0b, 0xbc,
+  0x1a, 0x4b, 0x88, 0xbb, 0xaa, 0x01, 0xd5, 0xbb, 0xb3, 0x11, 0xcb, 0xbb, 0x80, 0x2f, 0x53, 0xbc,
+  0x7e, 0x23, 0x97, 0x3b, 0xc2, 0x0d, 0x10, 0xbc, 0xc6, 0xee, 0xb5, 0x3c, 0xfe, 0xc6, 0x6c, 0x3c,
+  0xe1, 0xcb, 0xe2, 0xbb, 0xff, 0xee, 0xc3, 0x3b, 0x3d, 0x76, 0x64, 0x3b, 0x7e, 0x7c, 0xf3, 0xbc,
+  0xb5, 0xff, 0x82, 0x3b, 0xd4, 0xd4, 0xa2, 0x3b, 0xe3, 0xb3, 0x19, 0x3c, 0xfa, 0x83, 0x1d, 0x3c,
+  0x02, 0x0d, 0x72, 0xb9, 0x35, 0x60, 0x07, 0xbb, 0x8a, 0x4c, 0x64, 0xbb, 0x3c, 0x99, 0xa5, 0xbc,
+  0x49, 0xbe, 0x1d, 0xbb, 0x35, 0xab, 0x7b, 0xbb, 0x06, 0x57, 0x51, 0xbc, 0x1b, 0xa2, 0xe4, 0xbb,
+  0x31, 0x65, 0x43, 0xbb, 0xcb, 0x49, 0x77, 0xbc, 0x4d, 0xbe, 0x24, 0x3c, 0x9d, 0x8c, 0x82, 0x3c,
+  0x97, 0xf7, 0x08, 0xbc, 0x36, 0xa1, 0x3c, 0x3b, 0xf4, 0x3b, 0x51, 0xbb, 0x71, 0xea, 0x5d, 0xb9,
+  0x52, 0xe7, 0xaf, 0xbb, 0x0d, 0xbd, 0xbc, 0xbb, 0xfd, 0x30, 0xaa, 0x3b, 0x80, 0xd9, 0xa8, 0x3b,
+  0x10, 0xbf, 0x3c, 0x3c, 0xb2, 0xb1, 0x45, 0x3a, 0x55, 0xa6, 0xab, 0xbb, 0x38, 0x0f, 0xfc, 0x3a,
+  0xb1, 0xeb, 0x8f, 0xbc, 0xef, 0xb4, 0xbb, 0xba, 0x6d, 0x4f, 0xcb, 0xbc, 0xee, 0x50, 0xc2, 0x3c,
+  0xd9, 0x7c, 0x61, 0x3c, 0xb6, 0xbc, 0xd5, 0xbc, 0x6c, 0x3e, 0xe9, 0x3c, 0x3d, 0x1c, 0x0d, 0x3c,
+  0x49, 0xba, 0x9a, 0xbc, 0x1e, 0x11, 0x1f, 0xbd, 0x72, 0xdb, 0xbf, 0xbc, 0x3e, 0xad, 0xeb, 0x3b,
+  0x92, 0xf8, 0x96, 0x3c, 0x08, 0x2d, 0x86, 0xbc, 0x29, 0x7d, 0xd0, 0x3c, 0xab, 0x0d, 0x5d, 0xbc,
+  0x71, 0xd8, 0x92, 0xbc, 0x91, 0x52, 0xb1, 0xbc, 0x67, 0x28, 0x87, 0x3c, 0xed, 0xea, 0x06, 0x3c,
+  0x44, 0x49, 0xb5, 0x3c, 0x2c, 0xca, 0x1f, 0xbb, 0x1d, 0xa0, 0xd4, 0x3c, 0xd8, 0x18, 0x36, 0xbb,
+  0xe7, 0xac, 0xb6, 0xba, 0xb5, 0x18, 0x8d, 0x3a, 0x99, 0xfc, 0x24, 0xbc, 0xff, 0xde, 0xec, 0x3b,
+  0x52, 0xeb, 0xd8, 0x3c, 0x84, 0xf1, 0xa6, 0x3b, 0xa9, 0xb0, 0x1d, 0x3c, 0xb0, 0x42, 0x63, 0x3c,
+  0x1b, 0xe9, 0x89, 0xbc, 0x7d, 0x82, 0x38, 0x3c, 0x58, 0x24, 0x79, 0xbc, 0x1f, 0xe4, 0xfe, 0x3b,
+  0x23, 0x31, 0x7e, 0xbc, 0xf2, 0x27, 0x80, 0xbc, 0x2b, 0xc6, 0x1e, 0x3c, 0x4f, 0xd1, 0x5d, 0xbb,
+  0xfa, 0xcc, 0xf9, 0xbb, 0xb8, 0x93, 0x40, 0x3c, 0x87, 0x13, 0x92, 0xbb, 0x7e, 0xc0, 0x28, 0xbb,
+  0xc0, 0x30, 0xeb, 0xbc, 0xe7, 0x72, 0x53, 0xbc, 0xd8, 0x61, 0x46, 0xbc, 0xea, 0xb7, 0x06, 0x3c,
+  0xd8, 0x78, 0xe2, 0x39, 0x7a, 0x8e, 0xc1, 0x3c, 0xab, 0xdc, 0x4d, 0x3c, 0xcb, 0x64, 0x85, 0xbb,
+  0x6a, 0x02, 0x9b, 0xbc, 0xf7, 0x6c, 0xe7, 0xbb, 0xa3, 0x71, 0x36, 0xbc, 0xe1, 0x1f, 0xca, 0xbb,
+  0x4c, 0x22, 0x82, 0x3c, 0xf6, 0x79, 0x60, 0xbb, 0x91, 0x9f, 0x52, 0xba, 0xc1, 0x62, 0x5a, 0xbc,
+  0x91, 0xd8, 0x33, 0xbc, 0x96, 0x7c, 0x9b, 0x3a, 0x53, 0xa6, 0xba, 0xbc, 0x15, 0x82, 0x36, 0x3b,
+  0x4c, 0x6a, 0x1e, 0x3c, 0xc0, 0x2c, 0x9f, 0xbc, 0x97, 0x2d, 0xf2, 0xba, 0x3d, 0x96, 0x1c, 0xbc,
+  0x66, 0xf8, 0x41, 0x3b, 0x6d, 0x86, 0xfd, 0x3b, 0xf8, 0x70, 0xde, 0xba, 0x00, 0x4a, 0xf9, 0xbb,
+  0x23, 0x6f, 0x5c, 0x3c, 0xc6, 0xc8, 0x47, 0xbc, 0x55, 0x82, 0x19, 0xbc, 0xd2, 0x15, 0x63, 0xbc,
+  0x22, 0x6d, 0xb5, 0x3a, 0xdc, 0x39, 0x82, 0x3c, 0x3d, 0x22, 0x58, 0xbc, 0xa5, 0x49, 0x0a, 0x3b,
+  0x14, 0xfe, 0x0b, 0x3c, 0x6c, 0x5f, 0xf5, 0xbb, 0x23, 0x6f, 0xc8, 0xbb, 0xcd, 0xae, 0x14, 0xbc,
+  0x60, 0x88, 0x2c, 0x3c, 0xea, 0xfe, 0xd2, 0x3c, 0x2c, 0x1b, 0x94, 0x3a, 0x7a, 0x3d, 0xd4, 0xba,
+  0x7d, 0xc6, 0x16, 0x3c, 0xfd, 0xce, 0x04, 0x3c, 0xa3, 0x60, 0x80, 0xbc, 0xe6, 0x46, 0x28, 0xbc,
+  0x06, 0xf8, 0x41, 0x3c, 0xbe, 0x1b, 0x6a, 0x3b, 0xd7, 0x18, 0x01, 0x3c, 0x19, 0x16, 0xbc, 0x3b,
+  0x9a, 0x32, 0x68, 0xbb, 0x49, 0x45, 0x6f, 0x3b, 0x73, 0xea, 0x78, 0xbb, 0xa9, 0xba, 0xba, 0xbb,
+  0x31, 0x1a, 0x63, 0x3c, 0x04, 0x5c, 0xb6, 0xba, 0x31, 0x0f, 0x62, 0x3c, 0x24, 0x1c, 0x2d, 0x3c,
+  0xbd, 0x9a, 0xc1, 0xbb, 0x86, 0x19, 0xa3, 0x3b, 0xdb, 0x87, 0x75, 0x3b, 0x01, 0x1e, 0x1c, 0xbc,
+  0xde, 0x18, 0xbb, 0x3b, 0xd1, 0x98, 0x94, 0x3b, 0xa0, 0x78, 0xee, 0x3c, 0x27, 0xa6, 0x79, 0xbc,
+  0xff, 0xe6, 0xb1, 0x3b, 0xe9, 0xa1, 0x0f, 0xbc, 0x3d, 0xe8, 0xf8, 0x3b, 0x79, 0x91, 0xb8, 0xbc,
+  0x6a, 0x6c, 0x6e, 0x3c, 0x95, 0x2e, 0x25, 0x3c, 0x73, 0x08, 0x03, 0x3d, 0x13, 0x79, 0x26, 0xbc,
+  0x1b, 0x66, 0x31, 0xbb, 0x15, 0x91, 0xc4, 0xbb, 0x65, 0xd3, 0x23, 0x3b, 0x17, 0xcd, 0xdf, 0xbc,
+  0xec, 0xdc, 0xe2, 0xbb, 0x31, 0xee, 0x97, 0xbc, 0x0e, 0xa3, 0x8f, 0x3c, 0x18, 0x14, 0x7e, 0x3c,
+  0xf0, 0x99, 0x0f, 0xbc, 0x35, 0xbc, 0x33, 0xbc, 0x34, 0x22, 0xa9, 0xba, 0x01, 0xf3, 0xc5, 0xbc,
+  0x56, 0x17, 0x2d, 0x3c, 0xbe, 0x8a, 0xb4, 0x3b, 0xc9, 0x91, 0x97, 0x3c, 0xcc, 0x1e, 0x30, 0x3b,
+  0x22, 0xf5, 0xa1, 0x3b, 0xe5, 0xc3, 0x35, 0x3b, 0x55, 0xc7, 0x4e, 0xbb, 0x13, 0x83, 0xa4, 0xbc,
+  0xb2, 0xd1, 0xa5, 0x3b, 0x00, 0xd8, 0x1e, 0x3b, 0xa2, 0xce, 0x3c, 0xbc, 0xa5, 0xf8, 0x58, 0x3a,
+  0x93, 0x42, 0x3e, 0xbc, 0x4c, 0x7a, 0xb5, 0xbc, 0x97, 0xcc, 0xff, 0x3b, 0xb1, 0x57, 0x27, 0x3a,
+  0x18, 0x95, 0xd4, 0xbb, 0x12, 0x5d, 0x25, 0x3c, 0xdf, 0xe0, 0x91, 0x3b, 0xb6, 0x38, 0xec, 0x3a,
+  0xd2, 0x89, 0xb1, 0xbc, 0x05, 0x7f, 0x6c, 0xbc, 0x4c, 0x35, 0x79, 0xba, 0x3a, 0xbf, 0xf5, 0xbb,
+  0x06, 0x1c, 0xc5, 0x3c, 0x23, 0xea, 0x4f, 0x3c, 0x87, 0x75, 0x97, 0xbc, 0x4f, 0xe8, 0xb3, 0xbb,
+  0x04, 0x38, 0x2d, 0xbc, 0x79, 0x7f, 0xca, 0xbc, 0x8a, 0xc1, 0xce, 0xbc, 0xdf, 0xae, 0xff, 0x3b,
+  0xab, 0x65, 0x5f, 0x3c, 0x6d, 0x44, 0xe5, 0xbb, 0x3d, 0xcd, 0xe7, 0x3c, 0x3f, 0x8f, 0x8c, 0x3a,
+  0x91, 0x75, 0xad, 0xbc, 0x2e, 0xf5, 0xfd, 0xbc, 0xc0, 0x87, 0xd4, 0xbc, 0xa4, 0xa3, 0x94, 0xba,
+  0xaa, 0x29, 0x0f, 0x3c, 0x68, 0x79, 0x92, 0xbc, 0xbe, 0x60, 0xe6, 0x3c, 0xa1, 0xd6, 0x6c, 0xbb,
+  0x4c, 0x4c, 0xa7, 0xbc, 0x9b, 0x87, 0x44, 0xbc, 0x13, 0x80, 0x14, 0x3c, 0xd2, 0xe4, 0xf6, 0x3b,
+  0xa8, 0x4b, 0x48, 0x3c, 0x09, 0xcb, 0xba, 0xbb, 0x7b, 0x26, 0xda, 0x3c, 0x3c, 0x91, 0x89, 0x3b,
+  0x65, 0x8e, 0x77, 0x3b, 0x9e, 0x82, 0x0f, 0xbc, 0x8e, 0x55, 0xc0, 0xbb, 0x51, 0xfb, 0xc1, 0xbb,
+  0x17, 0xa9, 0xeb, 0x3c, 0x18, 0xc7, 0x86, 0xbb, 0x1b, 0x10, 0x26, 0x3c, 0x52, 0x38, 0xe1, 0x3a,
+  0xe2, 0xcd, 0x58, 0xbc, 0x88, 0xe2, 0x3e, 0xbb, 0x0a, 0x8b, 0xb4, 0xbb, 0x6a, 0xa1, 0xea, 0x3a,
+  0x27, 0xa5, 0x0f, 0xbc, 0xaf, 0xf3, 0xb7, 0xbb, 0x71, 0x78, 0x66, 0x3b, 0x51, 0xc7, 0x7a, 0xbb,
+  0x0a, 0x9c, 0x33, 0xbc, 0xe6, 0x78, 0xe5, 0x3c, 0xf4, 0x13, 0x6e, 0xbc, 0xa2, 0x09, 0x71, 0x3c,
+  0xbc, 0x7c, 0xa7, 0xbc, 0x17, 0xbc, 0x12, 0xbc, 0x89, 0xd3, 0x4f, 0xbc, 0xee, 0xcb, 0xcf, 0xba,
+  0xb6, 0x96, 0x39, 0x3c, 0xf6, 0x2a, 0x0e, 0x3d, 0xcc, 0x80, 0x81, 0x3c, 0xaf, 0x2b, 0x48, 0x3b,
+  0x62, 0x69, 0x9d, 0xbc, 0x6e, 0x2a, 0x85, 0xbc, 0x4d, 0xc4, 0x42, 0xbb, 0x4d, 0xdc, 0xfb, 0xbb,
+  0x97, 0x31, 0x55, 0x3c, 0x2e, 0xea, 0x6c, 0xba, 0xef, 0xb9, 0x86, 0xbc, 0xe8, 0x3a, 0x72, 0x3b,
+  0xae, 0xfb, 0x8d, 0xbb, 0x51, 0x83, 0x1d, 0x3c, 0x37, 0x0a, 0xdf, 0xbc, 0x04, 0x80, 0xf0, 0x3b,
+  0x58, 0x7e, 0x65, 0x3c, 0x86, 0x8e, 0xc0, 0xbc, 0x9c, 0xe0, 0x8a, 0xb7, 0x68, 0x44, 0x2f, 0xbc,
+  0x4d, 0x8d, 0x2c, 0xba, 0xd5, 0x44, 0x57, 0x3c, 0x13, 0x35, 0xa9, 0xbc, 0x72, 0x85, 0x6c, 0x3b,
+  0xe6, 0x6f, 0xc5, 0x3b, 0xce, 0x46, 0x9a, 0xbc, 0x59, 0xfa, 0xe7, 0xbb, 0xb3, 0x52, 0xb7, 0xbb,
+  0xf0, 0x82, 0x29, 0x3c, 0xd2, 0x8d, 0x89, 0x3c, 0x14, 0x1b, 0x9c, 0xbc, 0x57, 0x43, 0xc1, 0x3b,
+  0x68, 0x41, 0xa0, 0x3c, 0x63, 0xda, 0x8c, 0xbc, 0x3c, 0x3d, 0xf2, 0xbb, 0x99, 0x02, 0xd9, 0xbb,
+  0xcf, 0xf9, 0x82, 0x3c, 0xa5, 0x87, 0x0e, 0x3d, 0xd5, 0xa8, 0xee, 0xba, 0x7b, 0xc6, 0x69, 0xbc,
+  0x49, 0xb1, 0x72, 0x3b, 0x8f, 0x55, 0xcc, 0x39, 0xd5, 0xb5, 0xfc, 0xbb, 0x4d, 0x21, 0x6d, 0xbb,
+  0x42, 0xc8, 0x37, 0x3c, 0xcc, 0x3a, 0x56, 0xbb, 0xde, 0x71, 0xe5, 0x3b, 0x48, 0x72, 0xa5, 0xbb,
+  0x1e, 0x65, 0x48, 0xbb, 0xf0, 0x01, 0x4e, 0x3c, 0x1c, 0xcd, 0x07, 0xbc, 0x05, 0x50, 0x1e, 0xbc,
+  0x30, 0x76, 0x8e, 0x3b, 0x55, 0x85, 0x26, 0xbc, 0x9c, 0x0c, 0x4e, 0x3c, 0xd0, 0x2e, 0xbc, 0x3b,
+  0xae, 0x27, 0x35, 0x3c, 0x16, 0x7a, 0x8b, 0x3b, 0xbb, 0x0d, 0x05, 0x3c, 0x2c, 0x1e, 0x35, 0xbc,
+  0x04, 0xb6, 0x4b, 0x3c, 0x77, 0x73, 0x8a, 0xbb, 0xf7, 0x2e, 0xa1, 0x3c, 0x65, 0x13, 0x65, 0xbb,
+  0xb2, 0xb7, 0xda, 0xba, 0x1a, 0x3e, 0x62, 0x3b, 0xe7, 0xad, 0x20, 0x3a, 0xa5, 0x48, 0x88, 0xbc,
+  0x83, 0xc3, 0x9b, 0x3b, 0x1c, 0x64, 0x20, 0xbc, 0xe2, 0xe1, 0x86, 0x3c, 0xf9, 0x46, 0x26, 0x3c,
+  0x88, 0x7d, 0xb4, 0x3a, 0x2e, 0xa2, 0xda, 0xba, 0x64, 0x25, 0x6f, 0xbc, 0x3a, 0x16, 0xb6, 0xbc,
+  0x80, 0xd3, 0x21, 0x3c, 0xac, 0x96, 0x1d, 0xbc, 0x5e, 0x57, 0x17, 0x3d, 0xa9, 0xa3, 0x9f, 0xbc,
+  0x59, 0x97, 0xde, 0xba, 0x16, 0x5d, 0x9b, 0xbb, 0x03, 0xf6, 0xa9, 0x3b, 0xdc, 0xfb, 0xc9, 0xbc,
+  0xd6, 0x54, 0xd5, 0x3b, 0x1c, 0x80, 0xf8, 0x3a, 0xc9, 0xff, 0xc0, 0x3a, 0x75, 0x54, 0x86, 0xbb,
+  0x64, 0x79, 0x19, 0xbb, 0xd0, 0x7a, 0x0e, 0xbb, 0x19, 0xa4, 0xd2, 0x3b, 0x60, 0x4d, 0x26, 0xbc,
+  0x57, 0xc4, 0x43, 0x3c, 0x73, 0x74, 0x57, 0x3b, 0x02, 0x8c, 0xba, 0xbb, 0x44, 0xa3, 0xc0, 0xbb,
+  0xee, 0x9a, 0x50, 0xbc, 0x63, 0x8b, 0x86, 0xbc, 0xdd, 0xba, 0x85, 0x3c, 0xdc, 0xf2, 0x5d, 0x3b,
+  0x86, 0xa9, 0x2c, 0xbc, 0x32, 0x9c, 0x87, 0xbb, 0x3b, 0x36, 0x24, 0xbc, 0xd2, 0x0a, 0x89, 0x3c,
+  0x98, 0xd6, 0xdc, 0xbc, 0xfa, 0xc0, 0x0e, 0xbc, 0xd1, 0x44, 0xb0, 0x3a, 0x73, 0x95, 0xe4, 0x3a,
+  0x55, 0xc0, 0xf2, 0x3b, 0xef, 0xec, 0x43, 0x3c, 0x76, 0xbc, 0xf0, 0xbc, 0xfa, 0x92, 0x79, 0xbb,
+  0xef, 0xce, 0x38, 0x3b, 0x99, 0xbf, 0xbb, 0xbc, 0x6e, 0x4e, 0x86, 0xbb, 0x3a, 0x70, 0x59, 0xba,
+  0x18, 0xb2, 0xd5, 0x3b, 0xfc, 0xa0, 0x44, 0xbc, 0xd8, 0x44, 0x9c, 0x3b, 0x22, 0x23, 0x45, 0x3a,
+  0xf4, 0x30, 0x1d, 0xbd, 0x67, 0xe6, 0x0c, 0xbd, 0x64, 0xbb, 0xc2, 0xb8, 0x0d, 0xd5, 0x1c, 0xbb,
+  0xf1, 0x70, 0x3f, 0x3c, 0x70, 0xe6, 0xee, 0x3b, 0x30, 0x05, 0x87, 0x3c, 0x12, 0x41, 0x89, 0xbb,
+  0xb7, 0xf2, 0x31, 0xbc, 0xba, 0xf7, 0x8e, 0xbc, 0xab, 0xa8, 0x8f, 0x3b, 0x1c, 0xe2, 0x25, 0x3c,
+  0x03, 0xdd, 0x8a, 0x3c, 0xad, 0x8b, 0xd2, 0x3b, 0x0d, 0x6c, 0x84, 0x3c, 0xd0, 0xc6, 0x17, 0x3c,
+  0xc5, 0xb9, 0x67, 0xbc, 0x1f, 0xdf, 0x14, 0xbc, 0x77, 0xf5, 0x21, 0xbc, 0x4e, 0x05, 0x39, 0x3c,
+  0x68, 0x52, 0x7a, 0x3c, 0xa7, 0x9d, 0xb1, 0x3b, 0xba, 0x6c, 0x10, 0x3c, 0x3c, 0x28, 0x09, 0xbb,
+  0x46, 0xb0, 0x83, 0x3a, 0x57, 0x2d, 0xf2, 0xbb, 0x41, 0x70, 0x91, 0xbc, 0xd6, 0x87, 0xdd, 0x3b,
+  0xc8, 0x2d, 0x70, 0xbc, 0x40, 0x76, 0x00, 0x3b, 0x5d, 0x45, 0x8f, 0xbc, 0x81, 0xf2, 0xe7, 0x3b,
+  0x40, 0xcb, 0xcc, 0xbb, 0x76, 0x01, 0x4b, 0x3c, 0x3b, 0xff, 0x43, 0x3b, 0x64, 0x45, 0x05, 0xbc,
+  0x5d, 0xa3, 0x90, 0xbc, 0xea, 0xb5, 0x8d, 0xbc, 0x79, 0xb5, 0x87, 0xbc, 0x76, 0x0b, 0x1a, 0xbb,
+  0x4e, 0x44, 0x4b, 0xb9, 0xae, 0xc0, 0xa2, 0x3c, 0x04, 0x7e, 0x7c, 0x3c, 0xc2, 0xde, 0xc8, 0xba,
+  0xc1, 0x13, 0xf7, 0xbc, 0x8a, 0xdd, 0x61, 0xbc, 0xc2, 0x83, 0x06, 0xbc, 0xcd, 0x31, 0x1f, 0x3a,
+  0x5f, 0xae, 0x1c, 0x3c, 0x7b, 0x37, 0xda, 0xbb, 0x3b, 0x80, 0x1c, 0x3c, 0x74, 0x91, 0x1f, 0x38,
+  0x6b, 0x9d, 0xea, 0x3b, 0x02, 0xc7, 0x9c, 0x3c, 0x77, 0xe4, 0x97, 0xbc, 0x69, 0xdb, 0x08, 0xba,
+  0x63, 0x20, 0xb7, 0xbb, 0x08, 0xfb, 0x8c, 0xbc, 0xfa, 0x8a, 0x94, 0x3b, 0x28, 0x7c, 0x3a, 0xbb,
+  0x8c, 0xe8, 0x59, 0x3c, 0x7d, 0x49, 0x83, 0x3b, 0xbf, 0x80, 0xb9, 0xbc, 0xb1, 0x10, 0xcf, 0x3a,
+  0x70, 0xfb, 0x98, 0x3b, 0x5c, 0x05, 0xbc, 0xbb, 0x32, 0xcb, 0x5b, 0xbc, 0x01, 0x49, 0x91, 0xbc,
+  0x64, 0xb9, 0x7b, 0x3c, 0xa2, 0xa9, 0xbc, 0x3c, 0xd1, 0x9c, 0x2d, 0xbc, 0x70, 0xc1, 0x3e, 0x3b,
+  0x47, 0x32, 0x05, 0x3c, 0xe5, 0x28, 0x6e, 0xbc, 0x02, 0x3c, 0x94, 0x3c, 0x51, 0x1a, 0x94, 0xbb,
+  0x34, 0xdc, 0x28, 0x3c, 0x32, 0x65, 0x85, 0x3c, 0x89, 0x67, 0x58, 0xbb, 0x40, 0x1b, 0x59, 0x3b,
+  0xe0, 0x22, 0x8f, 0x3a, 0x5e, 0xec, 0xa8, 0xbb, 0xef, 0x38, 0x98, 0xbb, 0x27, 0xbf, 0x0d, 0xbb,
+  0x6e, 0x99, 0x5f, 0x3c, 0xa7, 0xe8, 0xba, 0x3b, 0xfa, 0xc3, 0x2b, 0x3c, 0xc3, 0x41, 0x98, 0x3b,
+  0xa2, 0xfd, 0x5e, 0x3b, 0x0b, 0x83, 0x63, 0xbb, 0xdd, 0x29, 0x04, 0x3c, 0xed, 0x24, 0x86, 0xbc,
+  0x08, 0x45, 0x77, 0x3c, 0x02, 0xa5, 0x75, 0x3b, 0x84, 0x58, 0x40, 0x3c, 0xc3, 0x21, 0x07, 0x3b,
+  0x8b, 0xc7, 0x9d, 0x3b, 0x0a, 0x4e, 0xac, 0x3b, 0xe5, 0x6b, 0xbf, 0x3b, 0x15, 0x3b, 0x8b, 0xbb,
+  0xdd, 0xfe, 0xbb, 0xbb, 0xd5, 0x63, 0xed, 0xba, 0x7d, 0x87, 0xff, 0x3c, 0x5b, 0x44, 0xe6, 0xbb,
+  0xb1, 0xdd, 0x81, 0xbb, 0x21, 0x0a, 0x30, 0x3c, 0x0f, 0xaa, 0x86, 0x3b, 0x69, 0x0f, 0x8c, 0xbc,
+  0xb0, 0xfb, 0xdf, 0x3b, 0x87, 0x31, 0x49, 0x3c, 0xf9, 0xb2, 0xa7, 0x3c, 0x44, 0xda, 0x71, 0x3c,
+  0xe7, 0x9c, 0x43, 0xbc, 0xfa, 0x88, 0x8d, 0xba, 0xa1, 0x46, 0xf3, 0x39, 0xe8, 0x5e, 0x7b, 0xbc,
+  0x97, 0x9a, 0xb5, 0xba, 0xea, 0x70, 0x69, 0xbc, 0xc3, 0x49, 0xcd, 0x3c, 0xb9, 0x3f, 0x1e, 0xbc,
+  0xb9, 0xa5, 0xd3, 0xbb, 0xc7, 0xc7, 0xad, 0xbb, 0x3c, 0x9d, 0xc9, 0x3a, 0x73, 0xff, 0x19, 0xbc,
+  0x4b, 0xf4, 0xae, 0x3b, 0x37, 0x29, 0x2b, 0xbb, 0x47, 0x78, 0xff, 0x3a, 0x35, 0xe1, 0x95, 0xbb,
+  0xd9, 0x6a, 0x8a, 0xbc, 0xaf, 0x56, 0xa4, 0xba, 0x84, 0x0b, 0x42, 0x3b, 0x00, 0xb0, 0x19, 0x3c,
+  0xd1, 0xd5, 0xd2, 0x3b, 0x45, 0x0f, 0x2e, 0xbb, 0x2b, 0x7e, 0x05, 0xbb, 0x8e, 0x2c, 0xee, 0xbb,
+  0x1f, 0xe3, 0x9c, 0x3b, 0xe3, 0xdc, 0xd2, 0xbc, 0x2f, 0xdd, 0x2c, 0x3a, 0x79, 0xe2, 0x1b, 0xbc,
+  0x2e, 0x61, 0xe2, 0x3b, 0x8b, 0x66, 0xd9, 0x3b, 0x91, 0x23, 0x1d, 0xbc, 0xd9, 0x74, 0xa0, 0xbc,
+  0xd5, 0x22, 0x0f, 0xbc, 0x74, 0xc9, 0xaa, 0xbc, 0x6d, 0xba, 0xde, 0xbb, 0xa1, 0x74, 0x57, 0xba,
+  0xf0, 0x64, 0x2f, 0x3c, 0x55, 0x50, 0x35, 0xbb, 0xa5, 0xc9, 0x03, 0xbd, 0x8c, 0x0d, 0xd2, 0x3b,
+  0x89, 0xf6, 0x04, 0xbc, 0x86, 0x5c, 0xd0, 0xbc, 0xab, 0x19, 0xec, 0xbc, 0xec, 0xf7, 0x0e, 0xbc,
+  0x33, 0x45, 0x16, 0xbc, 0xa6, 0x76, 0x18, 0x3c, 0xbf, 0xe4, 0xff, 0x3b, 0xb8, 0xa3, 0x46, 0x3c,
+  0xa0, 0x2a, 0x82, 0xbb, 0x7a, 0xbc, 0x1a, 0xbd, 0x65, 0x9a, 0xeb, 0xbb, 0xbc, 0x93, 0x62, 0xbc,
+  0x3e, 0x51, 0xff, 0xb7, 0xec, 0x1d, 0xd1, 0xbb, 0xd6, 0x74, 0xb8, 0x3b, 0x91, 0x85, 0x97, 0xbb,
+  0xaa, 0x7f, 0x86, 0xbc, 0x08, 0xdb, 0xe3, 0xbc, 0x15, 0x92, 0x26, 0x3c, 0x7a, 0x30, 0x97, 0x3c,
+  0xbe, 0x10, 0x1d, 0x3c, 0x92, 0xb5, 0xa2, 0x3c, 0x5a, 0xb2, 0x24, 0x3c, 0xcb, 0xc1, 0x9e, 0xbb,
+  0x96, 0xf6, 0xbf, 0xbb, 0x8c, 0x81, 0xb2, 0xbb, 0x60, 0x6f, 0x45, 0xbc, 0x03, 0xb6, 0x51, 0x39,
+  0x77, 0x57, 0xaf, 0x3b, 0xaf, 0x23, 0xb9, 0x3c, 0x53, 0xa3, 0xc1, 0x3b, 0x3e, 0xf3, 0x04, 0xbc,
+  0x54, 0x4a, 0xb8, 0x3a, 0x10, 0xca, 0xf1, 0x3b, 0xba, 0xde, 0xc8, 0xba, 0x82, 0xe1, 0x79, 0x3b,
+  0x4b, 0xf2, 0xcc, 0xbb, 0xfd, 0x4c, 0x51, 0xbb, 0x13, 0x76, 0x66, 0xbb, 0x13, 0xe5, 0x1a, 0x3b,
+  0x10, 0xab, 0xd2, 0x3b, 0xe4, 0x57, 0xcd, 0x3c, 0x92, 0x82, 0x24, 0x3c, 0xb9, 0x7c, 0x55, 0x3c,
+  0xa9, 0xf4, 0xdc, 0xbc, 0x98, 0xcb, 0xb7, 0xbc, 0xe6, 0xca, 0xd8, 0xbb, 0x00, 0x8e, 0x50, 0x3c,
+  0x27, 0x4f, 0x9d, 0x3b, 0xbd, 0xda, 0x85, 0x3c, 0xbf, 0x8b, 0x0f, 0x3c, 0xa1, 0xb0, 0x01, 0x3c,
+  0xfe, 0x25, 0x35, 0xbc, 0x96, 0x6a, 0xbf, 0xbb, 0x4b, 0x2e, 0x76, 0xbc, 0x5d, 0xee, 0xa2, 0x3c,
+  0x8a, 0x66, 0x7d, 0x3c, 0xcc, 0x51, 0xb8, 0x3a, 0x72, 0x52, 0xd9, 0xbb, 0xf9, 0xc1, 0x84, 0xbb,
+  0xbc, 0x6a, 0x1a, 0x3c, 0x5c, 0x74, 0xb1, 0x3b, 0x15, 0xda, 0xbc, 0xbc, 0x59, 0x6b, 0xb4, 0xbb,
+  0x26, 0xca, 0xd8, 0x3b, 0x23, 0x34, 0xff, 0xbc, 0xc5, 0xe9, 0xe1, 0xbc, 0xeb, 0x33, 0x9b, 0xbc,
+  0x6c, 0x54, 0x08, 0x3b, 0xed, 0x02, 0x12, 0x3b, 0x53, 0x38, 0x7d, 0xbb, 0xfd, 0x83, 0xb7, 0xbb,
+  0x03, 0x26, 0x02, 0x3b, 0x28, 0x78, 0xd7, 0xbc, 0x33, 0xba, 0x2d, 0xbc, 0x51, 0xee, 0xa8, 0xba,
+  0x9f, 0x45, 0x91, 0xbb, 0x6a, 0x78, 0x3f, 0xbb, 0x5e, 0x3f, 0x66, 0xbc, 0x90, 0x5c, 0x50, 0x3c,
+  0xd7, 0xa8, 0x07, 0x3c, 0x82, 0xe5, 0x86, 0xbc, 0x42, 0xb2, 0xc2, 0x3b, 0x5c, 0x2a, 0x03, 0x3c,
+  0xb2, 0xb3, 0x90, 0x3c, 0x7f, 0x80, 0xa2, 0x3c, 0xea, 0x90, 0x55, 0xbc, 0xbe, 0x87, 0x87, 0x3a,
+  0x3b, 0xcb, 0x02, 0xbc, 0x1b, 0xfd, 0x02, 0xbc, 0x5d, 0xfb, 0x67, 0x3a, 0x98, 0x07, 0x44, 0xbb,
+  0x8b, 0xa5, 0x4e, 0x3c, 0xd3, 0x0a, 0x83, 0x3c, 0xff, 0xd0, 0x44, 0x3c, 0x7a, 0xb6, 0x8b, 0x3b,
+  0x62, 0x68, 0x80, 0x3b, 0x27, 0x0e, 0x10, 0x3b, 0xe8, 0xc5, 0xee, 0x3a, 0x83, 0x3e, 0x52, 0xbc,
+  0x2d, 0x21, 0x34, 0xbb, 0x54, 0x33, 0x14, 0xbc, 0x78, 0xcf, 0xaf, 0x3c, 0xfc, 0x82, 0x93, 0x3c,
+  0x85, 0xde, 0x3d, 0xbb, 0xc5, 0x47, 0x32, 0x3c, 0x4e, 0x33, 0xa4, 0xbb, 0x2f, 0xb3, 0x39, 0xbc,
+  0x9b, 0x7e, 0x10, 0x3c, 0x10, 0x66, 0x0b, 0x3c, 0xca, 0x72, 0xbe, 0x3c, 0xc7, 0x1e, 0xdd, 0xba,
+  0xd7, 0xef, 0xc8, 0x3b, 0xea, 0xea, 0x13, 0x39, 0x57, 0xa4, 0x93, 0xbb, 0x67, 0x2f, 0x24, 0xbc,
+  0x5d, 0x49, 0x46, 0x3c, 0x1a, 0x95, 0xec, 0xbb, 0x6e, 0xeb, 0xa3, 0x3c, 0xbe, 0x88, 0x33, 0x3b,
+  0xf9, 0x9c, 0x1d, 0x3c, 0x6d, 0xce, 0x1a, 0xbc, 0x6d, 0xa7, 0x82, 0x3b, 0x06, 0xaa, 0xaf, 0xbc,
+  0x1f, 0xa0, 0x80, 0x3c, 0x76, 0x58, 0x5e, 0x3b, 0xe8, 0x20, 0xc3, 0x3c, 0x6a, 0xa1, 0x61, 0xbc,
+  0xe6, 0x7e, 0x80, 0x3a, 0x99, 0x3a, 0xb1, 0x3b, 0x52, 0x1d, 0x16, 0xbb, 0xbd, 0x62, 0x9e, 0xbc,
+  0x14, 0xc3, 0x97, 0x3c, 0xe0, 0x97, 0x5f, 0x3b, 0xf3, 0x1d, 0x1a, 0x3b, 0xfb, 0x30, 0x4a, 0xbc,
+  0x01, 0x68, 0xaa, 0xbb, 0x35, 0x21, 0xac, 0xbb, 0x81, 0xff, 0xa0, 0x3b, 0x8d, 0x6a, 0x87, 0xbb,
+  0xc0, 0xf4, 0xab, 0x3c, 0xbe, 0x7d, 0xa6, 0x3c, 0x36, 0xd6, 0x9b, 0xbc, 0xcd, 0xf6, 0x54, 0x3c,
+  0x1c, 0x9d, 0x96, 0xbc, 0x72, 0x82, 0x88, 0xbb, 0x27, 0x18, 0x2f, 0xbc, 0x10, 0x81, 0x98, 0xbb,
+  0xdc, 0x44, 0x61, 0xbb, 0xf8, 0x43, 0xda, 0x3b, 0x1b, 0x76, 0x83, 0xbb, 0x3e, 0x83, 0xb5, 0x3b,
+  0x01, 0x64, 0x1a, 0x3b, 0xea, 0x04, 0xde, 0xbc, 0x4e, 0xe7, 0xa4, 0xbc, 0x2a, 0xde, 0x2f, 0x3b,
+  0xc5, 0x15, 0x0a, 0x3c, 0x73, 0x1b, 0x63, 0xbc, 0x30, 0xa6, 0x70, 0xbc, 0x85, 0x78, 0x70, 0xbc,
+  0x41, 0x51, 0x9d, 0xbc, 0x89, 0xc5, 0x90, 0xbc, 0xde, 0x5d, 0xe5, 0xbc, 0xc2, 0x11, 0x76, 0xbb,
+  0xb7, 0x95, 0x4e, 0xbc, 0xbe, 0xab, 0x2d, 0xbb, 0x9f, 0x33, 0xbd, 0x3b, 0x19, 0x6c, 0x64, 0x3b,
+  0x62, 0x36, 0x6d, 0xbb, 0xab, 0x18, 0x47, 0xbc, 0xbf, 0x5c, 0x76, 0xbc, 0x8a, 0x65, 0xea, 0x3b,
+  0xca, 0x55, 0xb3, 0x38, 0xcf, 0x68, 0xc9, 0xbb, 0x53, 0x33, 0xd4, 0x3a, 0x9f, 0x47, 0xf9, 0xbb,
+  0x03, 0x65, 0x85, 0xbc, 0xdc, 0x9b, 0xcb, 0xbc, 0xcf, 0x88, 0xa8, 0xbb, 0x6f, 0x4f, 0x0b, 0xbb,
+  0xb6, 0xe9, 0x06, 0xbc, 0xae, 0x72, 0x69, 0x3c, 0x33, 0xb3, 0x2d, 0x3c, 0x90, 0xca, 0x15, 0x3c,
+  0x82, 0x36, 0x1b, 0xbb, 0x54, 0xc6, 0xb7, 0xbb, 0x32, 0x6d, 0xb8, 0x3a, 0xd0, 0x86, 0x32, 0xbc,
+  0x10, 0xbc, 0x02, 0xbb, 0xb4, 0x90, 0x40, 0xbb, 0x12, 0x2e, 0x27, 0x3c, 0xbf, 0xbb, 0x3e, 0xbc,
+  0x4f, 0xe5, 0x20, 0x3c, 0x9b, 0xae, 0x88, 0x3b, 0x91, 0x23, 0xec, 0xbb, 0x90, 0x35, 0xd3, 0x3b,
+  0x73, 0xba, 0x92, 0xbc, 0xc1, 0x4c, 0x9e, 0x3b, 0x95, 0xe8, 0x39, 0xbc, 0x86, 0x3b, 0x87, 0x3b,
+  0xe2, 0x4e, 0xb3, 0xbb, 0x46, 0x56, 0x4c, 0x3c, 0xc3, 0x1f, 0x07, 0x3b, 0x62, 0x0f, 0x75, 0xbb,
+  0x77, 0xc3, 0x9e, 0xbc, 0x84, 0x41, 0xad, 0xbc, 0xc0, 0x7d, 0x0a, 0x3b, 0x73, 0x0a, 0x0d, 0xbc,
+  0x8d, 0x31, 0x92, 0x3c, 0x0d, 0xc6, 0xa1, 0x3c, 0x0a, 0x90, 0x86, 0x3b, 0xf6, 0x0a, 0x80, 0xba,
+  0x54, 0xcd, 0xd1, 0xbb, 0x1d, 0xea, 0xa5, 0xbb, 0xa4, 0x36, 0xac, 0xbc, 0x8d, 0xbc, 0xa3, 0x3b,
+  0xe6, 0x72, 0x23, 0x3c, 0x19, 0xd1, 0x44, 0x3c, 0xb8, 0x87, 0xa7, 0xbb, 0xb0, 0xad, 0x0d, 0x3c,
+  0xf2, 0x0f, 0x71, 0xba, 0x35, 0x9e, 0xdc, 0x3a, 0x09, 0xa4, 0x40, 0xbc, 0xde, 0xa1, 0xe2, 0x39,
+  0xb0, 0xeb, 0x23, 0xbc, 0x62, 0xf4, 0x86, 0xbc, 0x1f, 0x57, 0x01, 0xbd, 0x03, 0x23, 0x70, 0xba,
+  0x90, 0x52, 0x93, 0x3b, 0xcd, 0xa0, 0x0c, 0x3c, 0x8f, 0x68, 0x80, 0xbc, 0x10, 0x3d, 0x18, 0x3c,
+  0x02, 0xa9, 0x7b, 0xbc, 0xfb, 0x63, 0x07, 0xbc, 0x56, 0xd7, 0xdd, 0xbc, 0xf8, 0xc2, 0x98, 0xb9,
+  0x90, 0xf4, 0xa7, 0x3a, 0xef, 0x7f, 0x72, 0x3b, 0x50, 0xfe, 0x67, 0xba, 0xfe, 0xe7, 0xd6, 0xbb,
+  0xa8, 0x0c, 0x44, 0x3c, 0x57, 0x2b, 0x77, 0xbc, 0x5f, 0x8e, 0x5c, 0xbc, 0xfb, 0x8d, 0xc2, 0x3b,
+  0xb1, 0x7d, 0x83, 0x3c, 0x71, 0xbe, 0x6c, 0x3c, 0xd5, 0x5d, 0x2c, 0x3b, 0xfd, 0xfe, 0x91, 0xbb,
+  0x69, 0xf6, 0x28, 0x3c, 0x1c, 0x31, 0xd4, 0xbb, 0x44, 0xd4, 0x4d, 0xbb, 0xae, 0xed, 0x3b, 0x3b,
+  0x80, 0x63, 0x31, 0x3c, 0x21, 0x5d, 0x95, 0xbb, 0x71, 0xbe, 0xc3, 0x3b, 0x80, 0xe5, 0x6e, 0x3c,
+  0xe9, 0xca, 0x89, 0x3c, 0x94, 0xf2, 0x74, 0x3b, 0x4a, 0xb5, 0x8e, 0xba, 0xb3, 0xb6, 0x8b, 0xbc,
+  0x34, 0xa1, 0xb8, 0xba, 0xf6, 0x29, 0x38, 0x3c, 0x00, 0x75, 0x05, 0x3c, 0x20, 0x3d, 0x83, 0xbc,
+  0x5a, 0x50, 0xb3, 0xbb, 0xb8, 0x89, 0xe8, 0x3b, 0x36, 0x39, 0xc3, 0x39, 0x75, 0xde, 0xcb, 0x3a,
+  0x5e, 0xaf, 0x80, 0x3b, 0xd1, 0x4a, 0x0f, 0xbc, 0x05, 0x15, 0x55, 0x3c, 0xb3, 0x00, 0x8d, 0x3a,
+  0xb0, 0x80, 0xa6, 0x3b, 0x0c, 0x20, 0x51, 0x3c, 0x9a, 0x69, 0xb7, 0x3b, 0x24, 0xf8, 0x2a, 0x3c,
+  0x64, 0xdc, 0x4b, 0x3c, 0xe3, 0x0a, 0x38, 0xb9, 0xb6, 0xac, 0xf0, 0x3b, 0x98, 0xc3, 0x94, 0x3c,
+  0x70, 0xc3, 0x1c, 0x3c, 0xa1, 0x98, 0x79, 0xbb, 0x48, 0x34, 0xbd, 0xbb, 0x4a, 0x72, 0xd1, 0xbb,
+  0x0f, 0x77, 0x45, 0x3c, 0xb3, 0x45, 0x29, 0x3c, 0x4f, 0x89, 0x83, 0x3c, 0xaf, 0x41, 0x95, 0x3b,
+  0x8b, 0x42, 0xbd, 0xbc, 0x3a, 0x9f, 0x56, 0xbb, 0xa8, 0x82, 0xee, 0xbb, 0x9b, 0x20, 0x11, 0x3b,
+  0xb2, 0xaf, 0xa6, 0x3c, 0x22, 0x1c, 0x6a, 0x3c, 0xdf, 0xc7, 0x6b, 0x3c, 0xd5, 0x80, 0x06, 0xbc,
+  0x65, 0xcc, 0xb1, 0xbb, 0x35, 0x66, 0x43, 0x3b, 0x2a, 0x36, 0x12, 0x3b, 0x69, 0x8d, 0x41, 0xbc,
+  0x98, 0x55, 0xf6, 0x3c, 0xfd, 0x75, 0xa5, 0x3c, 0x8c, 0xd3, 0x49, 0x3b, 0x0d, 0x39, 0x00, 0xbc,
+  0xba, 0x32, 0x27, 0x3c, 0xc0, 0x7c, 0x1e, 0x3c, 0x38, 0xf2, 0x12, 0x3c, 0xe3, 0xfc, 0x79, 0x3c,
+  0xa5, 0x9c, 0x52, 0x3c, 0xdd, 0x88, 0x85, 0xbc, 0x48, 0xe1, 0xfb, 0x3b, 0xa4, 0xfe, 0x25, 0x3b,
+  0x77, 0x77, 0xc8, 0x3c, 0xb9, 0x66, 0x84, 0xbb, 0x13, 0xd5, 0x7e, 0x3b, 0x5d, 0xf6, 0x05, 0x3b,
+  0x1d, 0xff, 0x32, 0x3c, 0x2a, 0x96, 0xce, 0x3b, 0x59, 0xa0, 0xe9, 0x3b, 0x93, 0x8c, 0x95, 0xbb,
+  0x90, 0x5d, 0x1c, 0x3a, 0x82, 0xda, 0x13, 0xbc, 0x39, 0x2c, 0x9b, 0x3c, 0xb0, 0x30, 0x92, 0x3c,
+  0xcb, 0xc9, 0x58, 0x3c, 0xfc, 0x84, 0x18, 0x3c, 0xef, 0x94, 0x19, 0xbb, 0xcd, 0x9f, 0x2f, 0xbc,
+  0xf5, 0xba, 0x0d, 0xbb, 0x25, 0xb5, 0xc6, 0xbb, 0xa3, 0xe3, 0x59, 0x3c, 0xbc, 0x94, 0x5b, 0xbb,
+  0x35, 0x14, 0x70, 0x3c, 0xbf, 0xaa, 0xfc, 0xbb, 0xe3, 0x54, 0x1a, 0xbb, 0xf5, 0x4a, 0x36, 0x3c,
+  0x47, 0x36, 0x70, 0xbb, 0x22, 0x80, 0x16, 0xba, 0x08, 0x5c, 0xfc, 0x3b, 0x23, 0xdd, 0x90, 0xbb,
+  0xb7, 0x72, 0xab, 0x3b, 0x53, 0xee, 0x8e, 0x3c, 0xe0, 0x35, 0xfa, 0x3a, 0xd7, 0xdb, 0x3a, 0xb9,
+  0x20, 0x87, 0xcf, 0x3b, 0x63, 0xd9, 0xbf, 0x3b, 0xd2, 0x9d, 0x88, 0xbb, 0x6a, 0x36, 0x99, 0x3b,
+  0x4a, 0xed, 0x2c, 0x3c, 0xea, 0x0b, 0x13, 0x3c, 0xb2, 0x94, 0x6c, 0xbb, 0xc0, 0x0c, 0x12, 0x3b,
+  0xdd, 0x6a, 0x95, 0x3b, 0x37, 0xce, 0xe8, 0xbb, 0xf2, 0x0c, 0xb2, 0xbb, 0x25, 0x59, 0x0a, 0xbc,
+  0x3b, 0x59, 0x78, 0xbb, 0x91, 0x39, 0x19, 0x3c, 0x42, 0xbc, 0xdf, 0x3b, 0x2f, 0x62, 0x18, 0xbc,
+  0x2b, 0x59, 0x91, 0xba, 0x4a, 0x1b, 0x50, 0x3c, 0xdb, 0x25, 0x5e, 0xba, 0x91, 0x78, 0x36, 0x3c,
+  0x52, 0x5b, 0x12, 0x3c, 0xd0, 0x7f, 0xfb, 0x3b, 0x12, 0x50, 0x0b, 0x3c, 0xf6, 0x59, 0x82, 0x3c,
+  0x05, 0xfc, 0x5d, 0x3c, 0xe5, 0x3e, 0x49, 0xbb, 0x28, 0x5a, 0x52, 0xbc, 0x87, 0x2f, 0xac, 0x3b,
+  0x09, 0x01, 0x7b, 0x3b, 0xd4, 0x98, 0xc2, 0x3b, 0xd6, 0x8c, 0xfe, 0x3b, 0x27, 0x36, 0x57, 0x3c,
+  0x0f, 0x3b, 0xae, 0x3a, 0x75, 0x52, 0x07, 0xbc, 0x41, 0xe8, 0xd2, 0x3b, 0xe4, 0xa0, 0x2b, 0x3b,
+  0x88, 0xab, 0x9a, 0x3b, 0x2a, 0x24, 0xfc, 0xbb, 0x2b, 0x27, 0xf8, 0x3a, 0xf7, 0x93, 0x05, 0x3c,
+  0x3b, 0xd1, 0x22, 0x3c, 0x3d, 0x63, 0x4d, 0xb9, 0x7b, 0x72, 0xac, 0xba, 0xb1, 0xad, 0x04, 0xbc,
+  0x76, 0x6a, 0x5f, 0x3a, 0x12, 0x77, 0x39, 0x3c, 0xe9, 0xf2, 0xba, 0xbb, 0x94, 0x78, 0x89, 0x3b,
+  0x6a, 0x2e, 0x47, 0xbb, 0x25, 0x2c, 0x97, 0xbb, 0xf6, 0xd6, 0x42, 0x3a, 0x9d, 0xce, 0x86, 0xbb,
+  0xe8, 0x72, 0xd3, 0xba, 0xdb, 0x2d, 0x14, 0x3c, 0x99, 0x2e, 0x08, 0xbc, 0x87, 0xdc, 0x18, 0x3c,
+  0x03, 0xf7, 0x88, 0xbb, 0x4e, 0x06, 0x57, 0xbb, 0x55, 0xc8, 0x30, 0x3c, 0x96, 0x73, 0xe4, 0x3b,
+  0xa3, 0x9a, 0x34, 0xbb, 0x72, 0xcd, 0x79, 0xbb, 0x32, 0x64, 0x23, 0x3c, 0xf4, 0x21, 0xd2, 0xb9,
+  0x8a, 0x5c, 0xfc, 0x3a, 0xed, 0x31, 0x07, 0xbc, 0x20, 0x50, 0x01, 0xbc, 0xb3, 0x6c, 0x27, 0x3c,
+  0xd4, 0xa7, 0x38, 0xbb, 0xae, 0x8e, 0x93, 0xba, 0x02, 0xd5, 0xfe, 0xbb, 0xaa, 0x5e, 0xbf, 0xbb,
+  0xaa, 0x3a, 0x15, 0xbc, 0xe9, 0x08, 0x47, 0x3b, 0x8b, 0x0e, 0x5a, 0x3c, 0xa5, 0x55, 0x66, 0x3a,
+  0x22, 0x2c, 0x20, 0xbb, 0x24, 0x99, 0x88, 0xbb, 0xcb, 0x48, 0x10, 0x3b, 0xb4, 0x08, 0x12, 0xbb,
+  0x87, 0x74, 0xb9, 0x3b, 0xcb, 0x87, 0x05, 0xbc, 0x25, 0x87, 0xba, 0xbb, 0x72, 0xe8, 0xfb, 0xbb,
+  0xce, 0xce, 0x97, 0xbb, 0x4f, 0x7f, 0x1f, 0xbc, 0x9a, 0x5b, 0x36, 0x3c, 0xaa, 0x8f, 0xd2, 0xbb,
+  0xcc, 0x0e, 0xa7, 0xbb, 0x13, 0x7f, 0x03, 0xbc, 0xca, 0xf3, 0x66, 0x3a, 0x0e, 0x7b, 0xca, 0xba,
+  0x43, 0x98, 0x54, 0xbc, 0xec, 0xc1, 0x82, 0x3c, 0xbc, 0x53, 0xb5, 0x3b, 0x64, 0x3b, 0xf2, 0xbb,
+  0xe5, 0x37, 0x6e, 0x3c, 0xef, 0x70, 0x7d, 0x3b, 0x2e, 0xa4, 0xf0, 0xbb, 0xf3, 0xdc, 0xae, 0x3b,
+  0x19, 0xe2, 0x8a, 0xbb, 0x5b, 0x2e, 0x92, 0x3b, 0x22, 0x96, 0x62, 0x3c, 0x86, 0x0a, 0xd8, 0xbb,
+  0x25, 0x59, 0x56, 0xbb, 0x17, 0x2c, 0xd9, 0xbb, 0xb1, 0x0b, 0x2a, 0xbb, 0x88, 0x67, 0xd8, 0x3b,
+  0xb8, 0xc8, 0x12, 0xbc, 0xe2, 0xe8, 0x70, 0xbb, 0x5f, 0xeb, 0x34, 0xbb, 0x67, 0xb0, 0x8a, 0xbc,
+  0xa0, 0x0f, 0xf4, 0xbb, 0x4f, 0x1a, 0xaa, 0xba, 0x11, 0x58, 0x90, 0xbc, 0x82, 0xd5, 0x48, 0x3c,
+  0x24, 0xbc, 0xc1, 0xbb, 0xc2, 0x82, 0x01, 0xbc, 0x20, 0x07, 0xb8, 0x3b, 0xea, 0x57, 0x2d, 0x3b,
+  0xbb, 0x7f, 0xe6, 0x3b, 0x17, 0xff, 0x82, 0xbc, 0xbd, 0x72, 0x6b, 0xbc, 0x91, 0x68, 0x37, 0x3b,
+  0x59, 0xec, 0x35, 0x3b, 0xe6, 0xb3, 0x0f, 0xbc, 0x0e, 0xd5, 0x2c, 0xbb, 0x8a, 0x22, 0xc5, 0x3b,
+  0xcf, 0x89, 0x31, 0x3c, 0x72, 0x7e, 0x03, 0xbb, 0x30, 0x2a, 0x52, 0xbb, 0xd4, 0x87, 0x23, 0x3c,
+  0x62, 0x0c, 0x4a, 0x3c, 0x2f, 0xae, 0x5a, 0xbc, 0xf7, 0xee, 0x24, 0xbb, 0xb5, 0xcd, 0xbb, 0x3b,
+  0x96, 0x4b, 0x4f, 0x3c, 0x50, 0xea, 0x08, 0xbb, 0xca, 0x24, 0x53, 0x3c, 0xeb, 0x9b, 0xf2, 0x3a,
+  0x83, 0xbb, 0x59, 0x3b, 0xdb, 0x6b, 0x7d, 0x3c, 0x1a, 0x8a, 0xe9, 0xb9, 0xa9, 0x53, 0x92, 0x3b,
+  0x21, 0x3c, 0xeb, 0x3b, 0xef, 0x6a, 0xe0, 0xbb, 0x48, 0xca, 0x93, 0x3c, 0xd6, 0xfb, 0x47, 0x3c,
+  0x7f, 0xf0, 0x75, 0x3c, 0xcc, 0xe6, 0xcb, 0x3b, 0x04, 0xa0, 0x85, 0x3a, 0x11, 0x03, 0x30, 0x3c,
+  0x20, 0x53, 0xa5, 0x3a, 0xa0, 0xc7, 0xb7, 0x3a, 0x01, 0x1c, 0xc8, 0xba, 0x0b, 0xab, 0x1e, 0x3b,
+  0xb2, 0xd1, 0x28, 0x3a, 0x37, 0x87, 0x51, 0x3c, 0x0c, 0x12, 0x9a, 0x3b, 0x58, 0x06, 0x03, 0x3c,
+  0x32, 0x60, 0x4a, 0xbb, 0xd1, 0xb5, 0x80, 0x3c, 0xaa, 0xd5, 0x13, 0x3c, 0xec, 0x52, 0x1a, 0xbb,
+  0xf6, 0x1e, 0xbf, 0x3b, 0x2a, 0x91, 0x1c, 0x3b, 0x7e, 0x1b, 0xcf, 0xbb, 0x76, 0xd6, 0x89, 0xbc,
+  0xe3, 0x24, 0x5d, 0xbc, 0x92, 0x73, 0x8e, 0xbc, 0x08, 0x49, 0x87, 0x3c, 0x78, 0x04, 0x53, 0x3c,
+  0xea, 0x6c, 0x21, 0x3c, 0xb6, 0x88, 0x19, 0x3c, 0xb5, 0xc8, 0xdb, 0x3b, 0x33, 0xc9, 0x3a, 0xbc,
+  0xe0, 0xfe, 0xf2, 0xb7, 0xd2, 0xae, 0x8a, 0xbb, 0xae, 0xcc, 0x75, 0xbb, 0x3e, 0xb8, 0xc3, 0xbb,
+  0x86, 0x4b, 0xa8, 0x3b, 0x3a, 0xbb, 0xb0, 0x3b, 0x4a, 0x03, 0xa5, 0xba, 0x85, 0xce, 0x80, 0x3c,
+  0xd8, 0x43, 0x60, 0xbc, 0x45, 0x19, 0xe4, 0x3b, 0x18, 0xd3, 0x74, 0xbc, 0x2b, 0x9c, 0x85, 0x3c,
+  0xd0, 0xf6, 0xca, 0x39, 0xc7, 0xb6, 0x82, 0x3c, 0x46, 0x65, 0xaa, 0x3b, 0xa6, 0xeb, 0x73, 0x3c,
+  0xcb, 0x18, 0x94, 0x3b, 0x3d, 0x30, 0xfb, 0x3b, 0xab, 0xa7, 0x6c, 0xbc, 0x6d, 0x53, 0x3e, 0x3c,
+  0x0f, 0xec, 0x05, 0x3c, 0xef, 0x27, 0xd7, 0x3b, 0x1c, 0xc1, 0x14, 0xbc, 0x2a, 0x96, 0xab, 0x39,
+  0x13, 0x3d, 0x1b, 0x3c, 0x2a, 0x8c, 0x0b, 0x3c, 0x23, 0x8a, 0xc0, 0xba, 0x15, 0x1d, 0x06, 0x3c,
+  0x28, 0x77, 0x9e, 0xbb, 0xcb, 0x26, 0x34, 0xbc, 0xb9, 0x6f, 0x77, 0x3c, 0x70, 0x42, 0x71, 0xbc,
+  0x99, 0xe9, 0xa4, 0xbb, 0xf8, 0x9a, 0x52, 0x3c, 0x69, 0x43, 0x97, 0x3c, 0x01, 0x50, 0x84, 0x3c,
+  0x75, 0x1e, 0x40, 0xbb, 0x1a, 0xa2, 0x90, 0xbb, 0x19, 0x81, 0x91, 0xba, 0xd8, 0x90, 0x16, 0x3c,
+  0xb3, 0x2c, 0x9b, 0xbb, 0xb2, 0x08, 0x8f, 0xbc, 0xc2, 0x43, 0x30, 0x3b, 0xd7, 0x68, 0xce, 0x3b,
+  0x94, 0xd6, 0xc2, 0xbb, 0x1d, 0xe2, 0x19, 0x3b, 0xc4, 0xfb, 0x7d, 0x3c, 0x87, 0xf8, 0xc6, 0x3b,
+  0x91, 0x2b, 0xb2, 0x3b, 0x19, 0xf3, 0x5a, 0xbc, 0x97, 0xab, 0x26, 0x3c, 0xe0, 0xce, 0x9b, 0x3c,
+  0xef, 0x39, 0xc2, 0x3b, 0x19, 0x2e, 0x73, 0x39, 0x7e, 0x0f, 0xb1, 0xbb, 0xae, 0xcf, 0x5b, 0x3b,
+  0xc4, 0x33, 0xbf, 0x3b, 0x2d, 0x69, 0xa1, 0x3b, 0xb3, 0xec, 0x36, 0x3b, 0x95, 0x3f, 0xdb, 0x3b,
+  0xde, 0x06, 0xd3, 0xbb, 0x56, 0xc3, 0x17, 0xbb, 0xd4, 0x19, 0x60, 0xba, 0x07, 0xdd, 0x01, 0x3b,
+  0xa8, 0xa4, 0x77, 0x3b, 0x68, 0xc5, 0xb8, 0xbb, 0x9a, 0x5e, 0x06, 0xbc, 0x97, 0x01, 0xd0, 0x3a,
+  0x5e, 0xc7, 0x5e, 0xbc, 0x8b, 0x04, 0x26, 0xbc, 0x33, 0xb9, 0x43, 0x3b, 0xf5, 0x41, 0x0b, 0xbc,
+  0x91, 0x8c, 0x11, 0xbc, 0x40, 0x2b, 0x91, 0xbc, 0x3d, 0x64, 0x21, 0xbc, 0x60, 0x6b, 0x61, 0x3c,
+  0x60, 0x01, 0xbc, 0xbb, 0x62, 0xc3, 0x37, 0xbb, 0x43, 0x5c, 0xc2, 0x3b, 0xae, 0xd2, 0xdb, 0xba,
+  0x8e, 0x83, 0x64, 0xba, 0x69, 0x9b, 0x01, 0x3c, 0x74, 0x4b, 0x94, 0xbb, 0xdb, 0x39, 0x72, 0xbb,
+  0xd8, 0xdf, 0xb3, 0xbb, 0x2c, 0x2e, 0x05, 0xbc, 0x12, 0x1d, 0x45, 0xbc, 0xc4, 0x65, 0x01, 0xbb,
+  0xe4, 0x69, 0x57, 0x3c, 0xf0, 0x6e, 0x8c, 0xbc, 0x4a, 0x69, 0x36, 0x3c, 0x95, 0xea, 0xd5, 0xba,
+  0x5f, 0xfd, 0x84, 0xba, 0x9f, 0xeb, 0xa6, 0x38, 0xde, 0x98, 0x2f, 0xbc, 0xa4, 0xf8, 0xc2, 0xbb,
+  0xc7, 0x6d, 0xee, 0xbb, 0x44, 0x06, 0x92, 0xbb, 0x2b, 0xe0, 0xf1, 0x3b, 0x6a, 0x34, 0x83, 0x3c,
+  0x8c, 0x45, 0x0a, 0x3b, 0x98, 0x1d, 0xb1, 0xba, 0xf7, 0xa3, 0xc9, 0x3b, 0x85, 0x4b, 0xb6, 0x3b,
+  0xf7, 0xbd, 0x9a, 0x3b, 0x13, 0xfb, 0x1f, 0x3c, 0xcb, 0x29, 0xa2, 0xba, 0x15, 0x2e, 0x44, 0x3c,
+  0xe7, 0x39, 0x86, 0x3b, 0xce, 0x91, 0x35, 0x3a, 0x7b, 0xd4, 0xbb, 0xba, 0x30, 0xfb, 0x6a, 0xbc,
+  0x96, 0x26, 0xba, 0x3b, 0x0a, 0x49, 0xba, 0x3b, 0x8b, 0x20, 0x7b, 0xbc, 0x16, 0x44, 0x90, 0x3c,
+  0x87, 0xd1, 0x0e, 0xbb, 0x1f, 0xe8, 0xc5, 0xb9, 0xf8, 0x53, 0xc4, 0x3b, 0x4f, 0x9e, 0x3d, 0x3c,
+  0x86, 0x2b, 0x9e, 0xbb, 0x6b, 0xb4, 0xb2, 0x3b, 0xc7, 0x7b, 0x40, 0x3c, 0x33, 0xbd, 0x09, 0x3c,
+  0x5c, 0xb1, 0xfd, 0x3b, 0x92, 0xf1, 0x89, 0x3b, 0xa9, 0x1b, 0xb1, 0x3b, 0x65, 0x55, 0x4a, 0x3b,
+  0xba, 0x73, 0x0e, 0x3c, 0xd1, 0x2c, 0x5e, 0x3c, 0x52, 0xf8, 0xfb, 0x3b, 0xc8, 0x31, 0xaf, 0x3a,
+  0xf5, 0xa2, 0x15, 0x3c, 0xf6, 0xb2, 0x9d, 0x3b, 0x48, 0x68, 0x21, 0x3b, 0x85, 0x3c, 0xea, 0x3b,
+  0x8b, 0xc4, 0x90, 0x3b, 0x1c, 0xf3, 0xbd, 0x39, 0xa6, 0x15, 0x81, 0x3c, 0x4e, 0xa2, 0x5c, 0xbc,
+  0x24, 0x28, 0x85, 0x39, 0x4b, 0x72, 0x94, 0x3c, 0x75, 0x07, 0x59, 0xbb, 0x82, 0xf2, 0xbc, 0xbb,
+  0x80, 0x2f, 0x1e, 0x3b, 0xef, 0xa3, 0x40, 0x3c, 0xeb, 0x43, 0xeb, 0xb8, 0x12, 0xd0, 0x19, 0xba,
+  0xd1, 0x27, 0xa7, 0x3b, 0x57, 0x6e, 0x2b, 0xba, 0xda, 0x18, 0x2c, 0x3c, 0x2a, 0x11, 0x90, 0x3b,
+  0xb5, 0x6e, 0x41, 0xbc, 0xed, 0xdb, 0x0c, 0xbc, 0x9d, 0xf6, 0x15, 0xbc, 0xf2, 0x6d, 0xb1, 0xbb,
+  0x1a, 0xa6, 0xf0, 0x3b, 0x5b, 0x9c, 0xb7, 0x3c, 0x57, 0x48, 0x0b, 0xbc, 0x9a, 0x44, 0x46, 0x3c,
+  0xe3, 0x8d, 0xb5, 0x3a, 0x7d, 0x0d, 0x9d, 0x3b, 0x30, 0x10, 0x00, 0x3c, 0x6a, 0xae, 0x09, 0xbc,
+  0x67, 0xf4, 0x91, 0xbb, 0x30, 0xe3, 0xb5, 0x3c, 0x73, 0x15, 0xb6, 0xbb, 0x38, 0x2a, 0x73, 0x3b,
+  0xe0, 0x6e, 0x8a, 0xbb, 0x9f, 0x9c, 0x0c, 0xbc, 0xd7, 0xcc, 0x60, 0x3b, 0xe0, 0xfe, 0xbb, 0x37,
+  0xf6, 0x30, 0xfa, 0xba, 0xc7, 0x2e, 0xd4, 0x3b, 0x3f, 0xc3, 0xff, 0xbb, 0xf6, 0xdf, 0x0e, 0x3c,
+  0x88, 0x46, 0x82, 0x3b, 0x21, 0xaf, 0x18, 0x3b, 0xdf, 0x8b, 0x11, 0xbc, 0x56, 0x74, 0x05, 0x3c,
+  0xa1, 0xe5, 0x0b, 0xbb, 0x5e, 0x72, 0x20, 0xbb, 0xd7, 0x9e, 0x85, 0xbb, 0x72, 0xf8, 0x91, 0x3c,
+  0x0b, 0x98, 0xf2, 0xbb, 0x46, 0x52, 0x1f, 0x3b, 0x89, 0x7f, 0xb9, 0x3b, 0x6a, 0x94, 0x51, 0xbb,
+  0xd7, 0x70, 0x4b, 0xbb, 0x1e, 0x81, 0xdb, 0x3a, 0xc7, 0x56, 0xc1, 0x3b, 0x91, 0x52, 0x30, 0x3c,
+  0x63, 0xf0, 0x0c, 0x3b, 0xc3, 0x8e, 0x90, 0x3c, 0xc6, 0x49, 0x75, 0xbb, 0x0f, 0xa2, 0x47, 0xbc,
+  0x0d, 0xd6, 0xdf, 0xba, 0xf3, 0xb4, 0x03, 0x3c, 0x59, 0x6c, 0xcb, 0x3b, 0x4c, 0x4e, 0x47, 0x3c,
+  0x5d, 0x38, 0x9c, 0xbc, 0x03, 0x68, 0x43, 0xbb, 0x13, 0x1a, 0xa8, 0x3b, 0x47, 0x42, 0x33, 0x3b,
+  0xc6, 0x80, 0xca, 0xba, 0xe8, 0x6b, 0x05, 0xbc, 0xc9, 0x4f, 0x18, 0x3c, 0x9b, 0x1f, 0x98, 0xbb,
+  0x11, 0x21, 0xbd, 0xb9, 0x8a, 0x9e, 0xd6, 0x3b, 0x8a, 0x40, 0x53, 0xbb, 0x46, 0x3d, 0x04, 0x3b,
+  0x24, 0x1e, 0xea, 0xbb, 0xa2, 0x5e, 0x8b, 0xbc, 0x37, 0x4f, 0x26, 0xbb, 0x74, 0xe1, 0x76, 0xbc,
+  0x99, 0x64, 0x9a, 0xbb, 0xc2, 0x39, 0xa8, 0x3b, 0x92, 0x10, 0x24, 0x3c, 0x4e, 0x3f, 0x52, 0x3b,
+  0x39, 0x8b, 0x92, 0xbb, 0x5c, 0xb5, 0x4a, 0x3a, 0x4a, 0xdb, 0xdb, 0x3b, 0xce, 0x07, 0xf2, 0xbb,
+  0xb1, 0x1a, 0xad, 0xba, 0xa2, 0xc1, 0x60, 0xbc, 0x1e, 0xd6, 0x22, 0xbc, 0x5b, 0x54, 0x69, 0x3b,
+  0xfd, 0x90, 0xe3, 0xbb, 0xa6, 0x40, 0x08, 0xbc, 0x04, 0x2c, 0xb9, 0x3a, 0x96, 0x20, 0x3e, 0xba,
+  0x2e, 0xba, 0x74, 0xbb, 0x01, 0x76, 0x56, 0x3b, 0x7e, 0xcc, 0xfa, 0x3b, 0xe9, 0x7c, 0x92, 0xbb,
+  0xb1, 0xef, 0xa2, 0x38, 0xa4, 0xa6, 0x6a, 0xbb, 0x7f, 0xf3, 0xe0, 0xbb, 0xb5, 0x2a, 0xd5, 0x3b,
+  0x48, 0x25, 0x5d, 0xbb, 0x54, 0xdd, 0xd6, 0xbb, 0xae, 0x56, 0x64, 0x3c, 0xb7, 0xa0, 0xa6, 0xbb,
+  0x28, 0xa7, 0x9b, 0xbc, 0xe7, 0xed, 0x98, 0xb9, 0x09, 0xba, 0x48, 0xbc, 0x2f, 0x89, 0x3f, 0x3c,
+  0x2b, 0x3a, 0xa5, 0x3c, 0x19, 0x98, 0x55, 0x3c, 0x04, 0x57, 0xbc, 0x3a, 0x4e, 0x93, 0x29, 0x3c,
+  0x4e, 0x6e, 0x8b, 0xba, 0xc4, 0x8e, 0xb9, 0xbb, 0x6f, 0x80, 0xb1, 0xbb, 0xf8, 0xd9, 0xad, 0xba,
+  0x67, 0x60, 0xfc, 0x3a, 0x4e, 0x3a, 0x20, 0x3a, 0x62, 0xb4, 0x92, 0xba, 0xe3, 0x58, 0x78, 0xba,
+  0xc1, 0x6a, 0x58, 0x3b, 0xb0, 0x10, 0x08, 0xbb, 0x61, 0x13, 0xd8, 0x3b, 0xee, 0xb4, 0x2e, 0xbb,
+  0x88, 0x81, 0x23, 0x3c, 0x31, 0xf3, 0x26, 0xbc, 0x52, 0xec, 0x40, 0x3a, 0xfe, 0xf8, 0x22, 0x3c,
+  0xf7, 0x10, 0x2a, 0xbc, 0xa6, 0xf1, 0xab, 0xba, 0x51, 0xcc, 0x09, 0x3b, 0x53, 0xbb, 0x54, 0xbc,
+  0xf3, 0xc3, 0x90, 0xba, 0xf9, 0xad, 0x12, 0xbc, 0x79, 0xf8, 0x9b, 0xba, 0xe9, 0xc4, 0x48, 0x3c,
+  0xbd, 0x21, 0x90, 0x3b, 0x4f, 0x38, 0xa6, 0x3c, 0xb1, 0x37, 0x52, 0x3c, 0xe8, 0x96, 0x82, 0xbc,
+  0xf2, 0x3b, 0x24, 0xbb, 0xca, 0xa6, 0x6c, 0xbb, 0x7d, 0x16, 0xef, 0xbb, 0x1b, 0x72, 0xfe, 0x3a,
+  0x7e, 0xbc, 0x4f, 0x3c, 0x07, 0x20, 0xcb, 0x3c, 0xf0, 0x2f, 0x5b, 0x3b, 0x00, 0x23, 0x5e, 0xbb,
+  0x3b, 0xca, 0xcd, 0x3b, 0xa8, 0x35, 0xac, 0xbb, 0xf6, 0xf9, 0x08, 0xbc, 0xbf, 0x3b, 0x20, 0xbc,
+  0x1f, 0x4c, 0xf9, 0x3b, 0x47, 0x39, 0x49, 0x3c, 0x86, 0xd6, 0xac, 0x3b, 0xa0, 0xdb, 0xed, 0x3b,
+  0x4e, 0x84, 0x16, 0x3c, 0x14, 0x35, 0x9c, 0xba, 0x5f, 0x41, 0xf4, 0x3b, 0xcf, 0xd9, 0x83, 0x3c,
+  0x62, 0xb5, 0x67, 0x3c, 0x2d, 0x31, 0x4b, 0x3a, 0xa4, 0x69, 0x49, 0xbc, 0xc9, 0x4c, 0x93, 0xbb,
+  0xc2, 0xe0, 0x03, 0x3c, 0xab, 0x4b, 0x37, 0xbb, 0x67, 0x7b, 0x06, 0x3c, 0xf5, 0x5a, 0xe5, 0xba,
+  0x77, 0x2c, 0x56, 0x3c, 0x79, 0xb4, 0x7f, 0x3c, 0xcc, 0xaa, 0x0b, 0x3c, 0x80, 0xc1, 0xbb, 0xbb,
+  0x92, 0x9e, 0x3c, 0x3c, 0x37, 0xc2, 0x2a, 0x3c, 0x4e, 0x01, 0xa2, 0x3c, 0x9d, 0xe4, 0x5d, 0xbc,
+  0xb4, 0x71, 0xc3, 0x3b, 0x16, 0xd6, 0xb5, 0x3c, 0x9d, 0xc7, 0x0f, 0x3c, 0x18, 0x38, 0x61, 0x3b,
+  0x52, 0x2e, 0x78, 0x3c, 0xf4, 0x79, 0xa4, 0xbb, 0x57, 0x8a, 0x60, 0x3c, 0x4b, 0xc4, 0xb8, 0xbb,
+  0x01, 0xbc, 0x0e, 0x3c, 0xd6, 0x50, 0xc6, 0x3c, 0xc4, 0xda, 0xbe, 0xbb, 0x45, 0xef, 0x09, 0xbc,
+  0xa7, 0x76, 0x99, 0xba, 0x33, 0xfb, 0x20, 0x3b, 0x0b, 0x14, 0x3b, 0x3b, 0x9d, 0x28, 0x1d, 0xbb,
+  0xe9, 0x2d, 0x17, 0x3c, 0x8c, 0x41, 0xbd, 0x3b, 0x24, 0xd2, 0xda, 0x3b, 0xd4, 0x1d, 0xf9, 0xbb,
+  0xcd, 0x59, 0xc1, 0xb7, 0x75, 0xea, 0x6f, 0xbb, 0xd7, 0x5f, 0x0a, 0xbc, 0xab, 0x06, 0xce, 0xbb,
+  0x55, 0x3e, 0x33, 0x3c, 0x3e, 0xac, 0x3d, 0x39, 0x75, 0xc1, 0x90, 0xbb, 0x49, 0x11, 0x26, 0xbb,
+  0x6f, 0x63, 0x04, 0xbb, 0x3f, 0xdf, 0xe6, 0x3b, 0x6c, 0xb0, 0xc1, 0xbb, 0xcf, 0x79, 0xa9, 0xbc,
+  0x55, 0x81, 0xa1, 0x3b, 0xa2, 0xfd, 0x12, 0xbc, 0xab, 0x36, 0x21, 0xbc, 0x7e, 0x35, 0xaa, 0xbb,
+  0xe9, 0x15, 0x37, 0xbc, 0x42, 0x34, 0x06, 0xbc, 0x81, 0x2e, 0x9b, 0xbc, 0x01, 0x88, 0xfd, 0xbb,
+  0xff, 0x70, 0x73, 0xbb, 0x8d, 0xab, 0x6b, 0xbc, 0xec, 0x6e, 0x47, 0x3c, 0x64, 0xb4, 0x8b, 0xbb,
+  0x66, 0xd8, 0x6c, 0xbb, 0xd3, 0x33, 0x9a, 0x3b, 0xd6, 0x7f, 0xae, 0x3b, 0x85, 0xa6, 0x88, 0x3b,
+  0x16, 0x7a, 0x49, 0xbb, 0x19, 0xc9, 0x45, 0xbc, 0xc8, 0x7d, 0xe3, 0x3b, 0x6e, 0x64, 0x04, 0xbb,
+  0xd2, 0x57, 0x3a, 0xbc, 0x54, 0x3b, 0x6c, 0x3a, 0xef, 0xde, 0xb3, 0x38, 0x85, 0x96, 0x4d, 0x3c,
+  0x53, 0x92, 0x4d, 0xba, 0x5e, 0x86, 0xac, 0xba, 0x7b, 0xe1, 0x4f, 0x3c, 0x45, 0xe0, 0x4e, 0xbc,
+  0x03, 0xe4, 0x08, 0xbc, 0xa3, 0x52, 0xef, 0x3b, 0xf7, 0x17, 0x61, 0xbc, 0x0e, 0x9a, 0x00, 0x3c,
+  0xf6, 0x4a, 0xe7, 0xbb, 0x37, 0x6b, 0x6c, 0xbc, 0x8a, 0x19, 0xb1, 0x3b, 0xed, 0x76, 0xe1, 0x3b,
+  0x24, 0xf1, 0x47, 0x3b, 0x92, 0x62, 0xa2, 0x3c, 0x9d, 0x4e, 0x7b, 0x38, 0x86, 0x1c, 0x2c, 0x3a,
+  0x7c, 0x7c, 0xc9, 0xbb, 0xb2, 0x82, 0x4a, 0x39, 0x8e, 0xaa, 0x05, 0x3c, 0xe3, 0x4b, 0x05, 0x3b,
+  0xd8, 0xe6, 0xd7, 0xbb, 0xe0, 0x26, 0x89, 0xbb, 0x16, 0xef, 0x29, 0xbc, 0x38, 0xfd, 0x84, 0xbb,
+  0xfd, 0x06, 0x79, 0xbc, 0x93, 0x1e, 0x90, 0x3b, 0x11, 0xe3, 0xdc, 0x3b, 0xdc, 0xff, 0x11, 0x3c,
+  0x1e, 0xf7, 0xb8, 0xbb, 0x12, 0x11, 0xf2, 0x38, 0xb7, 0x20, 0x89, 0x3b, 0x1d, 0x9c, 0x35, 0xbb,
+  0x9b, 0xeb, 0xb2, 0xbb, 0x31, 0x37, 0xba, 0x3b, 0x97, 0xf5, 0x95, 0xb9, 0xcf, 0x5a, 0x3f, 0x3c,
+  0x59, 0x55, 0x75, 0x3b, 0x8a, 0xa9, 0xd0, 0x3b, 0x9a, 0xc6, 0x36, 0xbb, 0xc6, 0x40, 0x84, 0xbc,
+  0x5c, 0x4c, 0x39, 0xbb, 0x0b, 0x88, 0xd4, 0x3a, 0x03, 0x7e, 0xe2, 0xbb, 0x25, 0xb3, 0xcb, 0xbb,
+  0xce, 0x41, 0x50, 0x3c, 0xe5, 0x78, 0x26, 0xbc, 0x40, 0x87, 0x43, 0x3b, 0xab, 0x80, 0x2d, 0xbc,
+  0x78, 0x7d, 0x1c, 0xbb, 0x98, 0xcc, 0x1b, 0xba, 0xa7, 0x7a, 0xcb, 0x3b, 0x03, 0x5b, 0xb0, 0xbb,
+  0xb1, 0xc2, 0xf3, 0x3b, 0x9c, 0x3f, 0x37, 0x3c, 0xb5, 0xdb, 0x81, 0xbb, 0x29, 0xe6, 0x3c, 0xbc,
+  0x16, 0xc8, 0xee, 0xbb, 0xcb, 0xcb, 0xe4, 0xbb, 0x8f, 0x6b, 0xaa, 0xbb, 0xb0, 0x23, 0x21, 0xb9,
+  0xb3, 0xeb, 0x9d, 0x3a, 0x5a, 0xe2, 0xa3, 0x3b, 0x52, 0xba, 0x92, 0x3b, 0x4f, 0x7b, 0x96, 0x3b,
+  0xaf, 0x05, 0xcc, 0xbb, 0xed, 0x9c, 0x0d, 0xbb, 0x1c, 0x0a, 0xc8, 0x3c, 0x3c, 0x59, 0x94, 0x3c,
+  0x5f, 0xe4, 0x40, 0xbc, 0x5a, 0x1d, 0x33, 0x3c, 0x67, 0xf6, 0x65, 0xbc, 0x66, 0x6d, 0x48, 0xbb,
+  0x34, 0x81, 0x70, 0x3c, 0x89, 0x3b, 0x8c, 0x3c, 0x8d, 0x85, 0xf3, 0xba, 0x38, 0x68, 0x54, 0x3b,
+  0x9d, 0x34, 0x84, 0x3a, 0xfd, 0xd3, 0x6e, 0xbc, 0xc7, 0xbe, 0x23, 0xbc, 0x4c, 0x54, 0x75, 0x3b,
+  0x56, 0xc3, 0xab, 0x3c, 0x8f, 0x63, 0x6c, 0xbb, 0x28, 0x7d, 0x61, 0x3a, 0xeb, 0x9a, 0x76, 0x3c,
+  0x6b, 0x80, 0xdc, 0x3a, 0xdb, 0x48, 0x22, 0xbc, 0xc7, 0xbd, 0xb0, 0x3b, 0x33, 0x74, 0xe9, 0x3a,
+  0x15, 0xec, 0x32, 0x3c, 0xe8, 0xb4, 0x8b, 0xbb, 0x7a, 0x56, 0xa0, 0xb9, 0x59, 0x96, 0x5d, 0x3c,
+  0xb2, 0x3c, 0x13, 0xbc, 0x9b, 0x0b, 0x6f, 0x39, 0x4e, 0xe4, 0xf8, 0x3c, 0x03, 0xec, 0xa7, 0xbc,
+  0x30, 0xb8, 0x32, 0x3c, 0xdc, 0x08, 0x61, 0x3c, 0xe7, 0x91, 0x57, 0xba, 0xc6, 0xb1, 0xa9, 0x3a,
+  0xe5, 0x37, 0xe6, 0xbb, 0x8e, 0x6b, 0x59, 0x3c, 0x55, 0x1c, 0x34, 0x3c, 0x92, 0xd5, 0x19, 0xbc,
+  0x1d, 0x94, 0xde, 0x3b, 0x8e, 0x36, 0x25, 0x3d, 0xce, 0xe1, 0x0e, 0xbc, 0x77, 0x0b, 0xaa, 0xbb,
+  0x98, 0xdc, 0x90, 0x3c, 0xc1, 0x79, 0x3f, 0xbb, 0x5f, 0x36, 0x75, 0x3b, 0x99, 0x98, 0x0c, 0xbc,
+  0x09, 0x4b, 0x15, 0x3c, 0xf7, 0xc9, 0xc4, 0x3c, 0xea, 0x57, 0xd8, 0x3b, 0x51, 0x74, 0x9b, 0xbc,
+  0x06, 0xf8, 0x8a, 0x3b, 0xe9, 0x1f, 0xee, 0x3b, 0x83, 0x0e, 0x0e, 0xbc, 0x8b, 0xbe, 0x55, 0xbc,
+  0x48, 0xd0, 0x49, 0x3b, 0x56, 0x56, 0x00, 0x3c, 0x6e, 0x9a, 0xc2, 0xbb, 0x2c, 0x30, 0x21, 0xbb,
+  0x47, 0xa4, 0x5e, 0xbc, 0x0f, 0x09, 0x25, 0xbb, 0xfa, 0xfe, 0x94, 0x3b, 0xe6, 0x34, 0x85, 0xbc,
+  0x63, 0x8a, 0x14, 0x3c, 0x52, 0x4e, 0x26, 0xba, 0xc2, 0xae, 0x40, 0x3a, 0xe9, 0x6a, 0x4c, 0xbb,
+  0xa0, 0x7b, 0x1f, 0xbc, 0x9c, 0x80, 0x9d, 0x3b, 0xbb, 0x95, 0x20, 0x39, 0xa0, 0xac, 0x36, 0xbc,
+  0x6f, 0x7f, 0xa6, 0xba, 0x19, 0x31, 0x8d, 0xbc, 0x36, 0x90, 0x3f, 0x3b, 0x5a, 0x3b, 0x07, 0x3b,
+  0xb7, 0x92, 0x90, 0xbc, 0x0a, 0x0b, 0x3b, 0x3b, 0x48, 0xa3, 0xcc, 0x39, 0x48, 0x97, 0x7a, 0xbb,
+  0xbf, 0x45, 0x93, 0x3b, 0xfe, 0x7f, 0x6c, 0xbc, 0xce, 0xd0, 0xbc, 0x3b, 0xaf, 0x2c, 0x1d, 0x3c,
+  0x9c, 0x16, 0x95, 0xbc, 0x25, 0x2b, 0x9b, 0xba, 0x10, 0x33, 0x78, 0x3c, 0xf8, 0x8f, 0x62, 0xbc,
+  0xd4, 0x78, 0x8b, 0x3b, 0x98, 0x03, 0x96, 0xbc, 0xc5, 0xb4, 0x1a, 0x3c, 0x27, 0xa6, 0x09, 0x3c,
+  0xf1, 0x56, 0x75, 0xbc, 0x33, 0x62, 0x27, 0x3b, 0x3f, 0x6b, 0xc2, 0xb9, 0xd7, 0xea, 0xc7, 0xbb,
+  0xbe, 0x43, 0x30, 0xb9, 0x7b, 0xe2, 0x71, 0x3b, 0x03, 0xf7, 0x1a, 0xbb, 0x21, 0xc0, 0xe5, 0xbb,
+  0x5f, 0x2f, 0xaa, 0xba, 0x26, 0xd5, 0xd1, 0xbb, 0x2d, 0xa7, 0x05, 0x3b, 0x8c, 0x19, 0x32, 0xbb,
+  0xe8, 0x25, 0x80, 0x3b, 0x4e, 0x82, 0x27, 0xba, 0xfd, 0x07, 0x13, 0x3a, 0x4f, 0x15, 0x60, 0x3c,
+  0x8e, 0x55, 0xa7, 0x3b, 0x1a, 0x28, 0xa7, 0xba, 0x2e, 0x33, 0x95, 0x3b, 0x10, 0x9e, 0xb5, 0xbb,
+  0x5f, 0x49, 0x29, 0xbb, 0x59, 0xfa, 0x02, 0xbb, 0xf6, 0xd9, 0x62, 0xbb, 0x10, 0x8a, 0x41, 0x3c,
+  0x9c, 0xc9, 0x18, 0xbc, 0xc1, 0x24, 0xf5, 0xba, 0xe8, 0x2e, 0xdb, 0xbb, 0x62, 0xb0, 0x42, 0x3b,
+  0xd2, 0xc9, 0x46, 0xbc, 0xef, 0x4f, 0x90, 0x3a, 0x39, 0x8f, 0x9f, 0xbb, 0x28, 0xe0, 0xbb, 0x3b,
+  0xf3, 0x98, 0x00, 0xbb, 0x72, 0xe9, 0x11, 0xbb, 0x8e, 0x08, 0xdb, 0x39, 0xbf, 0xd1, 0xbe, 0x3b,
+  0xd9, 0x8c, 0x24, 0xbc, 0x65, 0x8d, 0x52, 0x3c, 0x86, 0x25, 0x10, 0xba, 0xa4, 0x31, 0x09, 0xba,
+  0x3a, 0x32, 0x79, 0x3b, 0x3e, 0xd0, 0x65, 0x3c, 0xa8, 0xb3, 0x87, 0xbb, 0xd9, 0x5c, 0x3f, 0xbc,
+  0x25, 0x1b, 0x01, 0xbb, 0xb1, 0x4d, 0xc2, 0xbb, 0x5a, 0x14, 0xb6, 0x3b, 0x81, 0x7f, 0x36, 0xbb,
+  0xef, 0x4a, 0xee, 0xbb, 0x57, 0x33, 0x0e, 0xbc, 0xad, 0x9e, 0x16, 0xbc, 0x57, 0xdf, 0x87, 0xbc,
+  0x4f, 0xaf, 0xe9, 0xba, 0xaf, 0x88, 0x49, 0x3b, 0x41, 0x9e, 0x1b, 0x3b, 0x1c, 0x6e, 0x8e, 0xbc,
+  0x72, 0x32, 0x4c, 0x3c, 0x1f, 0xba, 0xe3, 0xba, 0xcd, 0xcd, 0x5a, 0xbb, 0x3d, 0x81, 0x64, 0x3b,
+  0x0c, 0x83, 0x81, 0xbc, 0xfa, 0xe4, 0x54, 0x3c, 0x10, 0xca, 0x1b, 0x3c, 0xd4, 0xff, 0xc3, 0x3b,
+  0x36, 0x05, 0xe8, 0xba, 0xf7, 0x5d, 0xd5, 0x39, 0x2a, 0x5a, 0x30, 0x3c, 0xac, 0x27, 0x72, 0xbc,
+  0x6e, 0x32, 0x14, 0xbc, 0x9f, 0x76, 0x94, 0x3b, 0x0a, 0x7c, 0xcd, 0x3c, 0x12, 0x23, 0x0e, 0xbc,
+  0xad, 0x57, 0x5d, 0xbc, 0x16, 0xfc, 0x59, 0x3c, 0x8f, 0x50, 0x51, 0x3c, 0x8a, 0xce, 0xff, 0xba,
+  0xc6, 0x20, 0xe9, 0x3c, 0xe3, 0x73, 0xcc, 0x3a, 0xf3, 0x4c, 0x22, 0x3c, 0x55, 0x23, 0xd7, 0xbb,
+  0xf2, 0x75, 0x27, 0xbc, 0x27, 0xf0, 0x1a, 0x3c, 0x52, 0x24, 0xae, 0x38, 0xcc, 0xa3, 0x89, 0xbc,
+  0xd2, 0xcd, 0x8e, 0x3c, 0x52, 0x01, 0xeb, 0x3a, 0xbf, 0xe7, 0xee, 0xbb, 0xda, 0xa0, 0x17, 0xbc,
+  0x80, 0x8e, 0xa9, 0xba, 0xe7, 0x21, 0x49, 0xbc, 0x8f, 0x6d, 0xc4, 0x3c, 0x1e, 0xac, 0x4f, 0xbb,
+  0xb8, 0xfc, 0x8c, 0x3c, 0x4a, 0x4a, 0xe9, 0x3a, 0x53, 0xdc, 0xe1, 0x3b, 0xa8, 0x51, 0x86, 0x3c,
+  0x0f, 0x4e, 0xcf, 0x3a, 0xaf, 0x42, 0x19, 0x3c, 0x09, 0x1f, 0xb8, 0x3c, 0x39, 0x5c, 0xa7, 0xbb,
+  0x19, 0x80, 0x4a, 0x3c, 0xbb, 0x12, 0xd8, 0x3c, 0x2b, 0xf4, 0xbe, 0xbb, 0xcc, 0xa4, 0x3f, 0x3c,
+  0xac, 0x85, 0xaa, 0x3a, 0xdb, 0xc6, 0xe4, 0x3b, 0xc9, 0xb4, 0x12, 0x3d, 0x28, 0x57, 0x4d, 0xbc,
+  0x0a, 0x67, 0xd3, 0x3b, 0x33, 0xd2, 0x34, 0x3d, 0xdd, 0x71, 0x92, 0xbb, 0x42, 0x8b, 0x71, 0x3c,
+  0x6d, 0xa1, 0x5c, 0x3c, 0x5b, 0x8c, 0x4b, 0xbc, 0x70, 0x01, 0x89, 0x3c, 0xd6, 0xac, 0xba, 0x3b,
+  0x73, 0xf6, 0x20, 0x3c, 0x7c, 0x01, 0x18, 0x3d, 0x58, 0x56, 0x78, 0xbc, 0xe1, 0xc9, 0x1f, 0x3b,
+  0x38, 0x28, 0x58, 0x3c, 0x3f, 0x14, 0x1c, 0xbc, 0x73, 0x76, 0x87, 0xb9, 0x68, 0x2d, 0xe0, 0x3a,
+  0x1b, 0x1a, 0x18, 0x3c, 0xf2, 0xeb, 0x22, 0x3c, 0x72, 0x15, 0x0d, 0xbc, 0x89, 0x30, 0x69, 0x3b,
+  0x4b, 0xed, 0x19, 0xbc, 0xca, 0x24, 0xb8, 0x3b, 0x1b, 0x1f, 0x8b, 0xbc, 0x65, 0x05, 0x6c, 0xbb,
+  0x35, 0x82, 0xdd, 0x3b, 0x65, 0xa7, 0xc4, 0x3a, 0x7e, 0xd3, 0xc1, 0x3b, 0xa8, 0xcf, 0x74, 0x3c,
+  0x66, 0x97, 0x3c, 0xbc, 0x8a, 0x41, 0xd7, 0x3b, 0x8e, 0xec, 0xac, 0xbb, 0xe8, 0x5a, 0x19, 0xbc,
+  0xa2, 0xa3, 0xf8, 0xba, 0x9c, 0x25, 0x68, 0xbc, 0x45, 0x17, 0x3c, 0xbc, 0xe1, 0x12, 0x28, 0xbb,
+  0x6a, 0xdd, 0x9f, 0xbb, 0x44, 0x3d, 0x7a, 0xb9, 0xca, 0x07, 0x55, 0xbc, 0x7c, 0x15, 0x2f, 0xbc,
+  0x87, 0x1c, 0xcf, 0xbb, 0x6f, 0x1b, 0xaf, 0xbc, 0x36, 0xdb, 0xa5, 0xbb, 0x1a, 0x23, 0xa8, 0xba,
+  0x9e, 0xed, 0xb2, 0xbc, 0x84, 0x47, 0xb3, 0xba, 0xa7, 0x4b, 0x50, 0x3c, 0xd6, 0xea, 0x17, 0xbc,
+  0x69, 0xb4, 0x8f, 0x3b, 0xee, 0x34, 0xb7, 0xbc, 0x2d, 0x8e, 0x88, 0x3c, 0x09, 0x59, 0x32, 0xbb,
+  0x90, 0x64, 0xab, 0xbc, 0xeb, 0x0f, 0x87, 0xbb, 0x5e, 0xf8, 0x37, 0xbc, 0x02, 0x5b, 0xf9, 0xbb,
+  0xa9, 0x7a, 0xa3, 0x3b, 0xa2, 0xcf, 0xa5, 0xbc, 0x54, 0xf5, 0x18, 0x3c, 0xa3, 0x77, 0x9d, 0x3a,
+  0x34, 0xdd, 0x48, 0xbc, 0x2f, 0x26, 0xfe, 0x3b, 0xd1, 0x16, 0xbc, 0xbb, 0x67, 0x71, 0x3b, 0x3c,
+  0x06, 0x8f, 0x48, 0xba, 0xd3, 0x73, 0x76, 0xbc, 0x5b, 0x13, 0xb1, 0x3b, 0xcc, 0x59, 0x91, 0x3c,
+  0x32, 0x1e, 0xaa, 0xbb, 0xa9, 0xb4, 0xfa, 0xba, 0x9b, 0x19, 0x38, 0xbc, 0xa4, 0xf9, 0xe1, 0xbb,
+  0xa8, 0xf3, 0x32, 0xbc, 0xa0, 0x71, 0xb6, 0xbb, 0xe4, 0x1d, 0xcb, 0x3b, 0xc5, 0x25, 0xa6, 0xbb,
+  0x1e, 0xbd, 0x1d, 0x39, 0xe3, 0x21, 0x4d, 0xbb, 0xbc, 0x1a, 0x36, 0x3c, 0x12, 0x08, 0x5a, 0x3a,
+  0x2d, 0xe7, 0xc6, 0xba, 0x6f, 0xda, 0xb2, 0x3a, 0xb6, 0x14, 0xeb, 0x3a, 0xb0, 0x6a, 0x82, 0xbb,
+  0xdd, 0xb1, 0xa8, 0xbb, 0x2e, 0x71, 0x1d, 0x3c, 0x59, 0x15, 0x61, 0xbc, 0x4a, 0x5a, 0xaf, 0xbc,
+  0x04, 0xf8, 0x21, 0xbc, 0x26, 0x8f, 0x46, 0xbc, 0x8c, 0x1d, 0x8e, 0x3b, 0x9f, 0x97, 0xc7, 0xbb,
+  0x27, 0x8f, 0x1a, 0x3c, 0x09, 0xfa, 0x35, 0x3c, 0x8d, 0x91, 0x0a, 0xbc, 0xe3, 0x84, 0x4e, 0xbc,
+  0x10, 0xb1, 0x97, 0xbb, 0xce, 0xce, 0x2b, 0xba, 0x5f, 0x7e, 0x03, 0x3c, 0x9a, 0xcf, 0x96, 0x3c,
+  0x93, 0x84, 0xc0, 0xbb, 0x84, 0xdb, 0x86, 0xbb, 0x5d, 0xad, 0x91, 0x3a, 0x45, 0xdf, 0x2f, 0xbb,
+  0xce, 0xf6, 0x27, 0x3b, 0xc1, 0xfa, 0x6c, 0x3b, 0xe9, 0x3f, 0x2f, 0x3c, 0x0e, 0x6c, 0x39, 0xba,
+  0x43, 0xa8, 0xc5, 0x3b, 0xd8, 0xe6, 0x8a, 0xbb, 0x8b, 0x42, 0xef, 0xbb, 0x30, 0x9d, 0x92, 0xbb,
+  0xce, 0x53, 0x4b, 0xbc, 0x22, 0x75, 0x1b, 0xbb, 0x12, 0xe8, 0xe9, 0x3a, 0x2e, 0x81, 0x0c, 0x3b,
+  0xc0, 0xb1, 0x4c, 0x3b, 0xd5, 0x29, 0x81, 0x3a, 0x39, 0xc5, 0xfc, 0x3a, 0x2b, 0x69, 0x92, 0x3b,
+  0x12, 0x7a, 0xa9, 0xbb, 0x5b, 0x10, 0xeb, 0xba, 0xcd, 0x78, 0x39, 0x3d, 0x52, 0xb2, 0xa3, 0xbc,
+  0xbb, 0x27, 0x45, 0xbc, 0x6f, 0xf1, 0xa4, 0x3c, 0xd2, 0xbc, 0x87, 0x3c, 0x50, 0xdb, 0xb6, 0xbb,
+  0x12, 0x78, 0x52, 0x3c, 0xf6, 0xf1, 0x30, 0x3b, 0x29, 0x02, 0x19, 0x3a, 0x8f, 0x68, 0x2b, 0xbc,
+  0xdd, 0x1c, 0x45, 0xbc, 0xa6, 0x29, 0x0e, 0x3b, 0xbe, 0x85, 0x92, 0x3c, 0x51, 0x69, 0x65, 0xbc,
+  0x2f, 0x67, 0x8f, 0x3c, 0x34, 0x61, 0x65, 0x3b, 0xd2, 0x6a, 0x2d, 0xbc, 0x0e, 0x01, 0x10, 0xbb,
+  0x78, 0xcb, 0x2b, 0xbb, 0xff, 0xc6, 0x8d, 0x3b, 0xe3, 0x99, 0x90, 0x3c, 0x00, 0x15, 0x85, 0xbc,
+  0xd8, 0x89, 0xd7, 0x3c, 0x9a, 0x30, 0x08, 0x3b, 0x11, 0xbe, 0x4c, 0x3b, 0x02, 0x15, 0x50, 0xbc,
+  0x2c, 0x62, 0x32, 0xba, 0x57, 0x64, 0x1c, 0x3c, 0x26, 0x14, 0xb9, 0x3c, 0x44, 0x4d, 0x9f, 0x3b,
+  0x57, 0xa5, 0xba, 0x3c, 0xbf, 0xfa, 0x88, 0x3c, 0x9f, 0x40, 0xf4, 0x3a, 0xbe, 0x8c, 0xfc, 0xbb,
+  0xcb, 0x63, 0x89, 0x3c, 0xbc, 0x24, 0x5f, 0xba, 0x2e, 0xf8, 0x5e, 0x3c, 0x2b, 0xc7, 0xb2, 0xbc,
+  0x56, 0x7f, 0xa9, 0x3c, 0x02, 0x0e, 0x27, 0x3d, 0xb4, 0xed, 0x88, 0x39, 0x86, 0xc1, 0x55, 0xbc,
+  0x2a, 0x0f, 0x93, 0x3c, 0xdd, 0x60, 0x49, 0xba, 0xbe, 0x5d, 0x1c, 0x3c, 0xd4, 0x8b, 0x18, 0xbc,
+  0x9b, 0xfa, 0x8d, 0x3c, 0xde, 0x78, 0x09, 0x3d, 0x55, 0xf1, 0x4d, 0xbc, 0x59, 0x31, 0x0a, 0xbc,
+  0xcc, 0xbb, 0xf1, 0x3b, 0x79, 0xaf, 0xa5, 0xba, 0x29, 0xcd, 0x17, 0xbc, 0x15, 0xdb, 0x04, 0xbc,
+  0x41, 0x08, 0xe1, 0x3b, 0x5c, 0x0b, 0x6c, 0x3c, 0x40, 0x2a, 0x2b, 0x3b, 0x4c, 0x45, 0x9b, 0x3b,
+  0x2c, 0x47, 0x09, 0x3c, 0x43, 0x4a, 0xc3, 0xb9, 0xb0, 0xa7, 0x59, 0xbc, 0xf8, 0x23, 0xac, 0xbb,
+  0xde, 0x52, 0xb8, 0x3b, 0xba, 0x9d, 0x14, 0xbc, 0xc7, 0xcd, 0xd2, 0xba, 0xdb, 0x52, 0x30, 0xbc,
+  0x51, 0x66, 0xca, 0x3b, 0xb0, 0x0d, 0x13, 0x3c, 0x4d, 0x8f, 0x4a, 0x3c, 0x75, 0x50, 0x50, 0xbc,
+  0xa7, 0xd1, 0x08, 0xbb, 0x0f, 0x79, 0xf3, 0xbc, 0x5d, 0x2d, 0x02, 0xbc, 0xe4, 0xf0, 0x9a, 0x3b,
+  0xa9, 0x0b, 0x69, 0xbc, 0xfc, 0xd8, 0xf0, 0x3b, 0xeb, 0xda, 0x92, 0xba, 0xcc, 0x5d, 0x1d, 0xba,
+  0x70, 0x42, 0xbd, 0x3b, 0xa1, 0x77, 0xf9, 0xbb, 0xcb, 0xd6, 0xe0, 0xb9, 0x92, 0xe5, 0x80, 0xbc,
+  0xcb, 0x58, 0x2f, 0xbc, 0xe5, 0x9b, 0x18, 0xb9, 0xf4, 0x81, 0x9c, 0xbb, 0x92, 0xe8, 0x73, 0xbc,
+  0xf3, 0x90, 0x04, 0x3b, 0x79, 0x68, 0x9e, 0xbc, 0x9a, 0x5f, 0x94, 0x3c, 0x09, 0x5e, 0x7b, 0x3c,
+  0x3f, 0x70, 0x8e, 0xbc, 0xca, 0x2a, 0xb5, 0xbb, 0xca, 0x4c, 0x45, 0x3c, 0xc0, 0x1f, 0x39, 0x3b,
+  0x70, 0x6e, 0x38, 0xbc, 0x09, 0xb0, 0xb4, 0xbc, 0x8a, 0x4c, 0xf3, 0x3b, 0xe1, 0xbd, 0x05, 0x3b,
+  0x6d, 0x9a, 0xe5, 0xbb, 0x9a, 0x11, 0x45, 0x3a, 0x9c, 0x89, 0xc3, 0x3b, 0xd5, 0xe5, 0x49, 0x3b,
+  0xcc, 0x95, 0xf6, 0xbb, 0xa8, 0xda, 0xf3, 0xbb, 0x44, 0x8f, 0xfc, 0x3a, 0x3d, 0x9b, 0x6f, 0x3c,
+  0xfa, 0x9e, 0xc3, 0xbb, 0x53, 0xc8, 0xb0, 0xbb, 0xc0, 0xdd, 0x14, 0xbc, 0xea, 0xfe, 0xec, 0xbb,
+  0xf3, 0x06, 0x4a, 0xbb, 0x34, 0x14, 0xe4, 0xbb, 0x09, 0xc1, 0xf1, 0x3a, 0x0d, 0xa9, 0x94, 0x3a,
+  0xa9, 0x1d, 0x73, 0xbb, 0x15, 0x2d, 0x17, 0xbb, 0x5b, 0xc9, 0x03, 0x3b, 0x85, 0xd5, 0xe6, 0xbb,
+  0x52, 0xe4, 0x56, 0xbc, 0x17, 0xca, 0x5c, 0xbc, 0x95, 0xe3, 0x9c, 0x3b, 0xd1, 0x49, 0x00, 0xbc,
+  0xb2, 0x9a, 0x7b, 0xba, 0xb7, 0x69, 0x03, 0xbc, 0x5c, 0xeb, 0x5e, 0x3c, 0x03, 0x73, 0x60, 0xbc,
+  0x71, 0x12, 0x24, 0xbc, 0xb9, 0x7c, 0xc8, 0xbb, 0xe6, 0x34, 0xc6, 0x38, 0xeb, 0x92, 0x33, 0x3c,
+  0x93, 0xb5, 0xed, 0x39, 0xfd, 0xf2, 0x16, 0x3c, 0xb5, 0xc8, 0x45, 0x3c, 0x73, 0x3c, 0x95, 0xbc,
+  0x0c, 0x8d, 0x83, 0xbb, 0xda, 0x22, 0x39, 0x3b, 0xdf, 0x13, 0x84, 0xbc, 0x52, 0xf1, 0x04, 0x3c,
+  0x30, 0xe3, 0x2c, 0xbc, 0xa0, 0x21, 0x8e, 0xbb, 0xb6, 0xbf, 0xc2, 0xbb, 0xb9, 0xc6, 0x01, 0xbc,
+  0x9a, 0x0e, 0xd0, 0x3a, 0xa4, 0xf5, 0xf2, 0x3a, 0xc8, 0x94, 0xb2, 0x3b, 0x28, 0x1b, 0x3b, 0xbc,
+  0x40, 0xd5, 0x74, 0x3b, 0xf4, 0xf7, 0xde, 0x3b, 0x27, 0x7f, 0x6a, 0xbc, 0x52, 0xbf, 0x0f, 0xbc,
+  0xff, 0x7f, 0x84, 0xbc, 0x40, 0xcd, 0x47, 0x3b, 0xc8, 0x34, 0xe3, 0x3b, 0x0a, 0x86, 0x9f, 0x3c,
+  0x9d, 0xaf, 0x27, 0xbb, 0x9e, 0xcc, 0x30, 0xbb, 0xc5, 0x6f, 0x9a, 0xb6, 0xbc, 0x02, 0x3d, 0x3a,
+  0x08, 0x90, 0x1c, 0xbc, 0xfe, 0x26, 0x51, 0x3c, 0x5c, 0x71, 0x20, 0x3d, 0x28, 0xae, 0x2c, 0xba,
+  0x43, 0xd9, 0x84, 0xbc, 0x8f, 0xeb, 0xe3, 0x3c, 0x18, 0xf8, 0xb7, 0x3c, 0x0d, 0xfc, 0x16, 0x3c,
+  0xa7, 0x02, 0xbb, 0x3c, 0xe7, 0x9c, 0x31, 0xbc, 0xf6, 0x2f, 0x38, 0xba, 0x65, 0x9e, 0x9c, 0xbb,
+  0xb0, 0x27, 0x44, 0xbc, 0x0d, 0x8d, 0x21, 0x3c, 0x79, 0xa5, 0x64, 0x3c, 0x68, 0xb2, 0x99, 0xbc,
+  0xa4, 0x2c, 0xeb, 0x3c, 0x5f, 0x63, 0xf1, 0x3b, 0xbe, 0x54, 0x4e, 0xbc, 0x36, 0x71, 0x1f, 0x3c,
+  0xa8, 0xa0, 0x10, 0xbc, 0x40, 0x46, 0x15, 0x3c, 0x0c, 0x9e, 0x74, 0x3c, 0x7b, 0xb1, 0x43, 0xbc,
+  0x96, 0x6b, 0xc9, 0x3c, 0xe0, 0xad, 0x7c, 0x3b, 0x81, 0xa2, 0x08, 0xbb, 0xc0, 0x9f, 0x46, 0x3b,
+  0x12, 0x1f, 0xb7, 0x3b, 0x15, 0x4c, 0x83, 0x3b, 0xb2, 0x3b, 0x45, 0x3c, 0xc3, 0xc9, 0x99, 0xbc,
+  0xac, 0xec, 0xa9, 0x3c, 0xb9, 0x6e, 0x72, 0x3c, 0x30, 0x67, 0x56, 0x3b, 0x2b, 0x8b, 0xf5, 0x3b,
+  0xcd, 0xec, 0x8d, 0x3c, 0x19, 0x66, 0x2b, 0x3c, 0x8b, 0x9f, 0xa2, 0x3c, 0xea, 0xbd, 0xfe, 0xba,
+  0x64, 0xfe, 0xc0, 0x3c, 0x53, 0x16, 0x16, 0x3d, 0x03, 0x2e, 0xf5, 0xbb, 0xd4, 0xd3, 0x97, 0xbc,
+  0xae, 0x53, 0xf7, 0x3c, 0xd2, 0xe5, 0xe1, 0xbb, 0x08, 0x55, 0x77, 0x3c, 0xdd, 0x16, 0x6b, 0xbc,
+  0x1c, 0xee, 0x90, 0x3c, 0x31, 0x35, 0x0f, 0x3d, 0x97, 0x55, 0x53, 0xbc, 0x21, 0x14, 0x1e, 0xbc,
+  0x27, 0x6d, 0x9d, 0x3b, 0xc6, 0x5f, 0xb4, 0xbb, 0x9a, 0xb6, 0xd6, 0xbb, 0x5d, 0xae, 0x9a, 0xbc,
+  0xec, 0xe6, 0x83, 0x3c, 0xba, 0x9b, 0x6f, 0x3c, 0xc9, 0x61, 0x12, 0xbc, 0xc6, 0xf0, 0x86, 0x3c,
+  0x1d, 0x00, 0x98, 0x3a, 0x10, 0xdb, 0x99, 0x3b, 0x7e, 0x5f, 0x2d, 0x3c, 0xbe, 0xfd, 0x82, 0x3b,
+  0xb8, 0xc5, 0x87, 0xbb, 0xb1, 0x72, 0x1e, 0xbb, 0x7f, 0xdd, 0xdc, 0x3b, 0x54, 0x6b, 0x0f, 0xbb,
+  0x8e, 0xbf, 0x17, 0xbb, 0x36, 0x8e, 0x66, 0x3c, 0xf8, 0xd1, 0xc9, 0xbb, 0xb4, 0xeb, 0x5d, 0x3c,
+  0x6e, 0x3b, 0xa2, 0xbb, 0xcf, 0x3c, 0x72, 0xbc, 0x30, 0x10, 0xc0, 0xbc, 0xf3, 0xf1, 0x40, 0x3c,
+  0xa3, 0x73, 0xbc, 0xbb, 0x0f, 0x48, 0xe7, 0x3b, 0xb0, 0xd7, 0x0b, 0xbc, 0xda, 0x0c, 0x5f, 0xbb,
+  0x9a, 0x58, 0xde, 0x3a, 0xb1, 0xc5, 0xb9, 0xbc, 0x3a, 0xc2, 0x67, 0xbb, 0xc8, 0xfc, 0x69, 0xbc,
+  0x20, 0xa4, 0x95, 0xbc, 0xbf, 0x9e, 0xec, 0xbb, 0xa2, 0x91, 0x8c, 0x3c, 0xef, 0x1d, 0xb0, 0xbb,
+  0x10, 0x15, 0x61, 0x3b, 0xc7, 0x03, 0x81, 0xbc, 0x4a, 0x5a, 0x60, 0x3c, 0xec, 0xba, 0x5c, 0xbb,
+  0x61, 0x79, 0x90, 0xbc, 0x15, 0xc3, 0x3a, 0x3c, 0x18, 0x15, 0xaf, 0x3b, 0x3b, 0x09, 0x2f, 0xbc,
+  0xb6, 0x77, 0x73, 0x3b, 0x8c, 0x35, 0xd2, 0xbc, 0x77, 0xda, 0xdb, 0xbb, 0xcf, 0x0e, 0x48, 0xbb,
+  0x29, 0xda, 0x1c, 0xbc, 0xcc, 0x26, 0x01, 0x3b, 0xbb, 0x3f, 0xdd, 0x3b, 0x53, 0x8d, 0x37, 0x3c,
+  0xb5, 0xe6, 0x11, 0xbc, 0x5f, 0x42, 0xe9, 0xbb, 0xdc, 0xe8, 0x2f, 0x3b, 0x66, 0x60, 0x27, 0x3c,
+  0x85, 0xe5, 0x02, 0xbb, 0x3c, 0x4b, 0xaf, 0xba, 0x6e, 0x1a, 0x72, 0x3b, 0xde, 0x5e, 0x3e, 0xbb,
+  0x0d, 0x1d, 0x66, 0xbc, 0x40, 0x95, 0x59, 0xbc, 0x7f, 0xba, 0x96, 0x3b, 0x34, 0xde, 0x06, 0xbb,
+  0x02, 0xbf, 0x0c, 0xbc, 0x0f, 0x5c, 0x81, 0x3b, 0x21, 0xb3, 0xa9, 0xbb, 0x47, 0x7d, 0x87, 0x3b,
+  0xc8, 0x15, 0x03, 0xbc, 0x6d, 0x5f, 0x10, 0xbc, 0xb5, 0xda, 0x39, 0x3b, 0xb5, 0xba, 0x08, 0xbc,
+  0x68, 0x96, 0x71, 0xbc, 0xbd, 0x0b, 0x44, 0x3c, 0xce, 0x81, 0x64, 0x3b, 0x43, 0x45, 0x3f, 0xbc,
+  0x32, 0x42, 0x4b, 0xbc, 0x29, 0x79, 0x81, 0xbc, 0xee, 0xb1, 0x2c, 0xbc, 0x0b, 0x5e, 0xc9, 0x3b,
+  0x58, 0xd0, 0xf0, 0xbb, 0x58, 0x54, 0x2e, 0x3c, 0x17, 0xc3, 0x0f, 0xbc, 0xfc, 0x90, 0x15, 0xbc,
+  0x46, 0x33, 0x7e, 0xbb, 0x6e, 0xd1, 0x89, 0x3b, 0xb7, 0xbf, 0x2c, 0xbb, 0xbc, 0xc9, 0x21, 0xbb,
+  0xe0, 0x89, 0xbc, 0x3b, 0x85, 0xe5, 0x82, 0xbb, 0xbb, 0x71, 0x22, 0xbc, 0xad, 0x37, 0x93, 0xbc,
+  0x38, 0x78, 0x26, 0x39, 0x6d, 0xeb, 0xe3, 0xba, 0xd9, 0xdf, 0x06, 0x3b, 0x54, 0x4e, 0x5d, 0xba,
+  0x78, 0xcc, 0xac, 0xbb, 0xd8, 0xa9, 0x0b, 0xba, 0x90, 0x95, 0x95, 0xbb, 0x63, 0xdb, 0x76, 0xbc,
+  0xdc, 0x18, 0xc3, 0x3b, 0x41, 0xf9, 0x9b, 0x3b, 0x8f, 0x10, 0x18, 0x3c, 0x2e, 0xd8, 0xcc, 0x3b,
+  0x74, 0x35, 0x9d, 0xbb, 0x18, 0xcd, 0xa8, 0xbb, 0x10, 0xb3, 0x21, 0x3c, 0xe0, 0xf6, 0x5b, 0x3b,
+  0x8c, 0xb9, 0xd2, 0xbc, 0x2c, 0xb2, 0x1f, 0xbc, 0xe8, 0x7e, 0x1c, 0x3d, 0x0d, 0xf9, 0xe2, 0x3b,
+  0x42, 0xe9, 0xbc, 0xbc, 0x9d, 0x85, 0x94, 0x3c, 0xcb, 0x52, 0x14, 0x3d, 0xa4, 0x14, 0x6f, 0xbb,
+  0x3c, 0xe2, 0x87, 0x3c, 0xc1, 0x8b, 0x21, 0xbc, 0xf4, 0x10, 0xe6, 0xb9, 0xb9, 0xc2, 0x75, 0x3b,
+  0x69, 0x85, 0x62, 0xbc, 0x93, 0x17, 0x05, 0x3c, 0x3c, 0x2c, 0xab, 0x3c, 0xe6, 0x19, 0x5b, 0xbb,
+  0x67, 0x22, 0xa3, 0x3c, 0x6e, 0x19, 0xea, 0xbb, 0xe5, 0x29, 0x36, 0xbc, 0x08, 0xa1, 0xab, 0x3b,
+  0xe7, 0x5f, 0x32, 0xbc, 0x48, 0x1c, 0xef, 0x3b, 0xb0, 0xd6, 0x26, 0x3c, 0xe7, 0x38, 0x1b, 0xbc,
+  0x3e, 0xf2, 0xc9, 0x3c, 0x57, 0xfd, 0x07, 0x3c, 0x2d, 0xd9, 0xbf, 0x3b, 0xe8, 0x33, 0xd2, 0x3b,
+  0x90, 0x8f, 0x86, 0x39, 0xfb, 0x42, 0x91, 0x39, 0x6d, 0x41, 0xc3, 0x3c, 0x6f, 0x00, 0x66, 0xbc,
+  0x18, 0x30, 0x00, 0x3d, 0x66, 0x67, 0x98, 0x3c, 0xb3, 0xa2, 0x03, 0x3c, 0xe3, 0xc6, 0x83, 0x3a,
+  0x35, 0x0c, 0xb4, 0x3c, 0x4f, 0x33, 0x67, 0x3b, 0x3a, 0x92, 0x8e, 0x3b, 0xc2, 0xb2, 0x62, 0xbc,
+  0xd0, 0xd2, 0x86, 0x3c, 0x3f, 0x1c, 0x16, 0x3d, 0x11, 0xd6, 0xee, 0xbb, 0x20, 0x4f, 0x17, 0x3b,
+  0x3b, 0xb5, 0x9a, 0x3c, 0xbe, 0xf4, 0xc3, 0x3a, 0x27, 0x4e, 0x92, 0x3c, 0x07, 0xdf, 0xb1, 0xbb,
+  0x88, 0x70, 0xac, 0x3c, 0x7a, 0x22, 0xe6, 0x3c, 0x0b, 0x4a, 0xb9, 0xbb, 0xad, 0xdb, 0x85, 0xb8,
+  0xe7, 0x8a, 0x2a, 0x3c, 0xb8, 0x99, 0xad, 0x3b, 0x6e, 0x89, 0x1b, 0xbc, 0x1f, 0x57, 0x7f, 0xba,
+  0xba, 0x81, 0x32, 0x3c, 0xd4, 0x36, 0xc4, 0x3b, 0x59, 0xc1, 0xe5, 0xb9, 0xee, 0x77, 0x40, 0xbc,
+  0xeb, 0xf1, 0x90, 0xba, 0xec, 0x4d, 0x8d, 0x3c, 0xdd, 0x87, 0x3b, 0x3b, 0xcf, 0xaa, 0x10, 0xbc,
+  0x6d, 0xdb, 0x00, 0xbc, 0xd2, 0xd2, 0x31, 0xbc, 0xf4, 0xf5, 0x2c, 0xbb, 0x76, 0x94, 0x59, 0x3c,
+  0x20, 0xa0, 0xd8, 0xbb, 0xac, 0xb4, 0x40, 0x3c, 0xde, 0xda, 0x7c, 0x3b, 0x96, 0x1c, 0x2f, 0xbb,
+  0x64, 0x80, 0x2e, 0xba, 0xef, 0xbd, 0xb5, 0xbc, 0x7d, 0x77, 0x1e, 0x3a, 0xf9, 0xe1, 0x75, 0x3a,
+  0xa5, 0x3f, 0x2a, 0xbc, 0x2b, 0x0d, 0x11, 0x3b, 0x31, 0xc5, 0xdf, 0xbb, 0xdf, 0xb4, 0xb4, 0xbb,
+  0x37, 0xe4, 0xa6, 0x3b, 0x9f, 0x54, 0xb4, 0xbc, 0x4e, 0x25, 0x62, 0xbb, 0x41, 0x4e, 0xc8, 0x3b,
+  0xd8, 0x7b, 0xc9, 0xbc, 0xc2, 0xe7, 0xca, 0x3b, 0x02, 0x44, 0x0d, 0x3c, 0xec, 0x1a, 0xe0, 0xbb,
+  0x5e, 0x92, 0xdf, 0x3b, 0xbb, 0x4d, 0x71, 0xbc, 0x0d, 0x58, 0x72, 0x3c, 0xad, 0xc1, 0x91, 0xb8,
+  0xe8, 0x6a, 0x43, 0xbc, 0x47, 0x9f, 0x1a, 0x3c, 0x91, 0x62, 0x03, 0x3b, 0x1a, 0x2d, 0xf3, 0xb9,
+  0x16, 0x4a, 0x8f, 0x3b, 0xbc, 0x66, 0x92, 0xbc, 0x95, 0x18, 0x05, 0xbb, 0x9f, 0xb2, 0x97, 0xbc,
+  0xed, 0x52, 0x38, 0x3b, 0xf1, 0x20, 0x65, 0xbb, 0x7e, 0xdd, 0x20, 0xbc, 0x46, 0xdb, 0x3a, 0x3a,
+  0x86, 0x13, 0x09, 0xbc, 0x9e, 0xf1, 0x42, 0xbb, 0xb0, 0x8e, 0x24, 0xbb, 0xb4, 0xee, 0xa4, 0xbb,
+  0x2a, 0x5a, 0xe4, 0xba, 0xcf, 0x49, 0x0e, 0xbb, 0xe0, 0x11, 0x1e, 0x3c, 0x58, 0x9d, 0x68, 0xbc,
+  0xd3, 0x2b, 0x62, 0xbb, 0x3d, 0xd9, 0xac, 0xbb, 0x60, 0x97, 0x9c, 0x3a, 0xc1, 0x69, 0xc0, 0xba,
+  0xea, 0x3b, 0x02, 0xbb, 0x0f, 0x8e, 0xd4, 0x39, 0xda, 0x86, 0x88, 0xbb, 0x40, 0x6c, 0xc4, 0xbb,
+  0x36, 0x20, 0x33, 0xb9, 0x81, 0x9f, 0x1a, 0xbc, 0x36, 0xa2, 0x43, 0xbc, 0xb7, 0xbb, 0xdc, 0xbb,
+  0x1e, 0xe1, 0xc4, 0xb8, 0x82, 0x80, 0xe8, 0xbb, 0x4a, 0x4a, 0x08, 0x3c, 0x5b, 0xa1, 0x1f, 0xbc,
+  0xfd, 0xc9, 0xf3, 0xbb, 0xde, 0xce, 0x30, 0xbc, 0x79, 0xb7, 0x08, 0x3c, 0xc4, 0xa0, 0x96, 0x3b,
+  0xd9, 0x17, 0x5a, 0x3b, 0xf3, 0xb8, 0x02, 0x3b, 0x65, 0x21, 0x17, 0x3a, 0x01, 0x43, 0x0b, 0xbc,
+  0xa0, 0x9f, 0x15, 0xbb, 0x98, 0x70, 0xe0, 0xbb, 0x6a, 0x38, 0x1d, 0x3c, 0x8a, 0x60, 0xce, 0x39,
+  0x64, 0x1b, 0x0f, 0x3c, 0xf8, 0xf5, 0x00, 0xbc, 0xd3, 0x5e, 0xd7, 0xbb, 0xd5, 0x22, 0xf0, 0xbb,
+  0x4f, 0x71, 0xf8, 0xbb, 0x3b, 0x30, 0x14, 0xbb, 0x1a, 0xca, 0x82, 0x3b, 0x7b, 0x5b, 0xb6, 0x3a,
+  0x37, 0x99, 0x7d, 0xbb, 0x44, 0x9c, 0x09, 0x3a, 0xcc, 0x29, 0x3e, 0xbc, 0x98, 0x35, 0x66, 0xbb,
+  0x22, 0x7d, 0x34, 0x3c, 0x67, 0xa8, 0x93, 0x3c, 0xc7, 0x9c, 0xee, 0x3b, 0x7b, 0x41, 0x2b, 0xbc,
+  0xb1, 0x10, 0x93, 0xbb, 0x3d, 0x9c, 0x81, 0xbb, 0x3b, 0xae, 0x6e, 0x3c, 0x82, 0x31, 0x61, 0xba,
+  0xbb, 0xca, 0xdb, 0xbb, 0x0b, 0xbb, 0x6d, 0xbb, 0xad, 0xe7, 0xf8, 0x3c, 0x47, 0x5d, 0x40, 0xb7,
+  0xbb, 0xe7, 0xad, 0xbc, 0x23, 0x23, 0x5b, 0x3c, 0xe5, 0x35, 0x22, 0x3d, 0xe1, 0x57, 0x9c, 0xba,
+  0x21, 0x4c, 0x6d, 0x3c, 0xb6, 0xf4, 0xe4, 0x3b, 0x57, 0x12, 0x02, 0xbc, 0x6f, 0xdc, 0x88, 0xbc,
+  0x04, 0x44, 0x17, 0xbc, 0xa0, 0x14, 0xfa, 0x3b, 0xde, 0xa7, 0x41, 0x3c, 0x61, 0xea, 0x46, 0xbc,
+  0x95, 0xa4, 0xcd, 0x3c, 0x9a, 0x71, 0xdf, 0x3b, 0x1a, 0xfd, 0x84, 0xbc, 0x86, 0x07, 0x83, 0xbc,
+  0x40, 0xb7, 0x2c, 0xbb, 0x9c, 0x77, 0xd7, 0x3b, 0xed, 0x53, 0xa0, 0x3c, 0xf2, 0xe9, 0x65, 0xbc,
+  0x43, 0xba, 0x2f, 0x3c, 0x8e, 0xb0, 0x8b, 0x3b, 0x90, 0x13, 0x34, 0x3b, 0x2c, 0x81, 0x0a, 0x3c,
+  0xd5, 0x64, 0x28, 0xbc, 0xdd, 0x53, 0x4c, 0xbb, 0xf5, 0x3d, 0xc4, 0x3c, 0xb0, 0xc5, 0x7b, 0xbc,
+  0xb1, 0x4e, 0x49, 0x3c, 0x35, 0x36, 0x60, 0x3c, 0x9c, 0x22, 0xcb, 0xbb, 0xad, 0x4b, 0x11, 0xbc,
+  0xa1, 0x11, 0xf7, 0x3b, 0x60, 0x21, 0x56, 0x3b, 0xca, 0xd1, 0xbe, 0x3c, 0x87, 0x48, 0xdd, 0xbb,
+  0xcf, 0x13, 0x0d, 0x3c, 0x18, 0x59, 0x21, 0x3d, 0xf3, 0x51, 0x25, 0xbc, 0x6a, 0x9b, 0x8b, 0xbb,
+  0x49, 0xa2, 0x68, 0x3c, 0xd9, 0x8e, 0x91, 0xbb, 0x6e, 0x23, 0x48, 0x3c, 0xac, 0x27, 0x8e, 0xbc,
+  0x9d, 0xa2, 0xf4, 0x3c, 0x78, 0x61, 0xc9, 0x3c, 0x1b, 0xa9, 0x64, 0xbc, 0x2b, 0x71, 0x20, 0xbb,
+  0x9f, 0xc1, 0x6f, 0x3c, 0x3d, 0xf0, 0xa4, 0x3b, 0xaf, 0xf1, 0x7b, 0x3b, 0x8b, 0x38, 0x83, 0xba,
+  0x2d, 0x4a, 0x11, 0x3c, 0xbe, 0x45, 0x4a, 0x3c, 0x23, 0x5e, 0xb9, 0xbb, 0x12, 0x90, 0x73, 0xbb,
+  0x3a, 0x38, 0x77, 0xba, 0x62, 0x76, 0x75, 0x3b, 0xef, 0xa4, 0xdf, 0xba, 0x7d, 0x57, 0x36, 0xbc,
+  0xf2, 0xb1, 0x7b, 0xba, 0x9d, 0xcf, 0x26, 0xbc, 0x91, 0x34, 0x4f, 0xbc, 0x0a, 0xcd, 0x96, 0xbb,
+  0x03, 0x0b, 0x57, 0x3a, 0xb9, 0x94, 0x3b, 0x3c, 0xf3, 0xe8, 0x91, 0x3a, 0x87, 0xc0, 0x3c, 0xbc,
+  0xea, 0x39, 0x2a, 0xbb, 0xa1, 0xc0, 0xc5, 0xbb, 0xed, 0x45, 0xd8, 0x39, 0x8c, 0x6f, 0x6e, 0x3b,
+  0x6d, 0x3f, 0xa1, 0xbc, 0xcb, 0x81, 0x12, 0x3c, 0x91, 0x81, 0x0c, 0x3b, 0x9a, 0x84, 0x4e, 0xbc,
+  0xf3, 0x8b, 0x80, 0x3a, 0x08, 0xc8, 0x4a, 0xbc, 0x54, 0x4b, 0xa1, 0xbc, 0x8b, 0x35, 0xf4, 0x39,
+  0x97, 0xc4, 0xaa, 0xbc, 0xda, 0x17, 0x00, 0xbc, 0xc5, 0xbb, 0xd8, 0x3b, 0x69, 0xac, 0x0e, 0x3b,
+  0x67, 0xd1, 0x39, 0x3c, 0xb9, 0x0d, 0x53, 0xbc, 0xfc, 0x35, 0x6d, 0x3b, 0x44, 0xaf, 0x57, 0xbc,
+  0xf3, 0xd1, 0xb3, 0xbc, 0x52, 0xef, 0x2c, 0x3c, 0xcd, 0xfb, 0x0e, 0x3c, 0xd2, 0x10, 0x90, 0xba,
+  0x38, 0x01, 0xd4, 0x3b, 0xa8, 0xca, 0xb0, 0xbc, 0xef, 0x26, 0xf2, 0xba, 0x93, 0x2d, 0x73, 0x3c,
+  0x7a, 0xb7, 0x32, 0xbc, 0x59, 0x55, 0x83, 0xbb, 0xa3, 0x78, 0x01, 0x3c, 0x4a, 0x3c, 0x34, 0x3b,
+  0x77, 0xb2, 0xc7, 0xbb, 0x42, 0xb8, 0xa6, 0xbc, 0x1e, 0x04, 0x83, 0xbb, 0xdd, 0xad, 0x14, 0xba,
+  0x42, 0xdf, 0xf4, 0xbb, 0x9f, 0xb9, 0xf0, 0x3a, 0xe0, 0x2c, 0xa4, 0x3b, 0x71, 0x4d, 0x98, 0xbc,
+  0x63, 0x18, 0x72, 0xbb, 0x15, 0x2c, 0xc3, 0xba, 0xac, 0xf4, 0xaa, 0xbb, 0x99, 0xfa, 0x09, 0x3c,
+  0x86, 0xbf, 0x2d, 0xba, 0x81, 0xba, 0x30, 0x3b, 0xfb, 0x21, 0x51, 0x3c, 0x83, 0x7b, 0x4a, 0xbc,
+  0x57, 0xf7, 0x8c, 0xba, 0x89, 0xc9, 0x80, 0xba, 0xbf, 0xdc, 0x85, 0xbc, 0xf1, 0xd6, 0x0f, 0xbc,
+  0x47, 0x7f, 0x9e, 0xbb, 0x79, 0x03, 0x40, 0x3c, 0x7f, 0x5c, 0xee, 0xbb, 0x2b, 0xa1, 0x6d, 0xbb,
+  0xfb, 0xbb, 0x32, 0x3b, 0xcc, 0xc2, 0xc7, 0xbb, 0xfd, 0x7d, 0x8e, 0x3a, 0x3e, 0xfb, 0x2d, 0xbc,
+  0x76, 0xea, 0xf5, 0x3a, 0x56, 0xb8, 0x20, 0x3c, 0x56, 0x44, 0xe9, 0xba, 0x2c, 0xca, 0x0d, 0xbc,
+  0xd3, 0xb9, 0x4c, 0xbc, 0xab, 0x57, 0x8e, 0x3b, 0x74, 0xef, 0x61, 0xbb, 0x30, 0xdd, 0x0b, 0xbc,
+  0x4b, 0x23, 0x64, 0xbc, 0xe8, 0xb2, 0x43, 0xbc, 0xd9, 0x61, 0x01, 0xbb, 0x81, 0x3a, 0x99, 0xbc,
+  0x6f, 0x60, 0x07, 0xbc, 0x8d, 0x62, 0xe8, 0xba, 0xe9, 0x6a, 0xa3, 0x3b, 0x0b, 0xca, 0xbe, 0x3b,
+  0x66, 0x1d, 0xd5, 0x3a, 0x70, 0x90, 0xa2, 0xbb, 0x5e, 0x1a, 0x6b, 0xbc, 0xc9, 0xa0, 0x05, 0x3c,
+  0xa9, 0xe6, 0xe7, 0x3b, 0x37, 0x0a, 0x45, 0x3c, 0xa1, 0x5e, 0x3a, 0x3c, 0xbb, 0xb6, 0xfd, 0x3b,
+  0x89, 0xc3, 0x03, 0xbc, 0x1a, 0x00, 0x51, 0xbc, 0x71, 0x69, 0x83, 0x3c, 0xc0, 0x5c, 0xb2, 0xbb,
+  0xed, 0x7d, 0x56, 0xbc, 0x19, 0x09, 0x38, 0xbc, 0xa4, 0xc5, 0x12, 0x3d, 0x6d, 0x6b, 0x93, 0xbb,
+  0x78, 0x28, 0x91, 0xbc, 0x26, 0x49, 0xbc, 0x3b, 0xe5, 0x8d, 0x1a, 0x3d, 0x35, 0x43, 0x84, 0xbc,
+  0xfc, 0x4a, 0x87, 0x3c, 0x5c, 0x4d, 0x2f, 0x3c, 0x77, 0x4f, 0x8c, 0x3b, 0x4c, 0x5a, 0x2c, 0x3c,
+  0xda, 0x13, 0xb9, 0xbc, 0x51, 0xe5, 0x7f, 0xbb, 0xba, 0x01, 0x45, 0x3c, 0xfd, 0xfe, 0x7b, 0xbc,
+  0x8a, 0x0b, 0x8f, 0x3c, 0x00, 0x1a, 0x95, 0xba, 0x83, 0xf1, 0x0c, 0xbd, 0x3d, 0xf9, 0x12, 0xbb,
+  0x19, 0x53, 0x55, 0xbc, 0xe6, 0x18, 0x0c, 0x3c, 0xc3, 0x6f, 0x5a, 0x3c, 0x70, 0xa6, 0x65, 0xbc,
+  0xa4, 0xe5, 0x84, 0x3c, 0x0b, 0xd2, 0x92, 0x3b, 0x88, 0x78, 0x1c, 0x3b, 0xc5, 0x66, 0xa0, 0x3c,
+  0x16, 0x07, 0x8d, 0xbb, 0xa8, 0x08, 0x00, 0x3c, 0xda, 0xea, 0xc0, 0x3c, 0xd2, 0x15, 0x74, 0xbc,
+  0x76, 0x8e, 0xc7, 0x3c, 0x7a, 0x27, 0xf7, 0x3c, 0x14, 0x6f, 0x9e, 0xba, 0xef, 0x0c, 0x17, 0xbc,
+  0xaf, 0x8a, 0xf4, 0x3a, 0x8b, 0x0f, 0xa6, 0x3a, 0xe3, 0x24, 0xb3, 0x3c, 0x02, 0xc3, 0x14, 0xbc,
+  0xe3, 0xa5, 0xba, 0x3c, 0x6b, 0xc0, 0xd2, 0x3c, 0xc4, 0x32, 0x0b, 0xbc, 0x51, 0xab, 0x28, 0x3c,
+  0xac, 0xcd, 0xb9, 0x3c, 0x83, 0x92, 0xab, 0xbb, 0xf0, 0x64, 0x52, 0x3c, 0x04, 0x21, 0x8d, 0xbc,
+  0xe5, 0xb3, 0xe4, 0x3c, 0x72, 0x0f, 0x28, 0x3d, 0x08, 0xcf, 0x55, 0xbc, 0x44, 0x04, 0x09, 0xbc,
+  0x61, 0x9b, 0x95, 0x3c, 0x0a, 0x2b, 0x96, 0xb9, 0xb4, 0x9d, 0xce, 0x3a, 0xb4, 0x48, 0x9f, 0xbc,
+  0x31, 0x36, 0xc1, 0x3c, 0x64, 0x5f, 0x29, 0x3c, 0xd6, 0x2f, 0x03, 0xbc, 0x24, 0xa4, 0xed, 0xbb,
+  0xa1, 0x16, 0x84, 0x3b, 0xf4, 0xf1, 0x14, 0x3c, 0xdc, 0x5f, 0x20, 0x3a, 0xdd, 0x1e, 0x54, 0x3a,
+  0xc6, 0x47, 0xb1, 0x3a, 0x38, 0x88, 0xec, 0xbb, 0x97, 0x06, 0xd6, 0xbb, 0xfa, 0x1f, 0x76, 0x3b,
+  0x5d, 0x41, 0xa2, 0xb9, 0x42, 0xa6, 0x11, 0x3b, 0xc8, 0x77, 0x0f, 0x3c, 0xe9, 0x7c, 0xd4, 0xbb,
+  0xb0, 0x53, 0x0d, 0xbc, 0xa5, 0x6b, 0x95, 0xbc, 0xe9, 0x46, 0x11, 0xbc, 0x6d, 0xf0, 0x19, 0xbc,
+  0x2b, 0xb0, 0x2e, 0xbc, 0xfe, 0x5a, 0x85, 0xbb, 0xfd, 0x83, 0xc3, 0x3b, 0xd8, 0x1d, 0xec, 0xbb,
+  0x68, 0xfd, 0x8a, 0x3b, 0x4f, 0x5a, 0x48, 0xbc, 0xa5, 0x29, 0x4b, 0xbc, 0x76, 0x21, 0x60, 0x39,
+  0x25, 0x4a, 0xcd, 0xbc, 0xd7, 0x4d, 0x01, 0x3c, 0x50, 0x00, 0xce, 0x3b, 0x43, 0xb1, 0xc7, 0x3b,
+  0xe1, 0x89, 0x7b, 0x3c, 0xf0, 0x2d, 0xb6, 0xbb, 0x84, 0x37, 0x3f, 0x3c, 0xa9, 0x19, 0x89, 0x3c,
+  0x05, 0xa9, 0x1e, 0xbc, 0x1d, 0x75, 0x5b, 0xbb, 0xc2, 0xad, 0xba, 0xb8, 0x48, 0x4a, 0x59, 0xbc,
+  0x64, 0x6c, 0x52, 0x3b, 0xab, 0xe1, 0xab, 0xbc, 0x4f, 0x76, 0x2c, 0xbb, 0x4a, 0xe4, 0x2d, 0x3c,
+  0x28, 0xc3, 0xb3, 0xbc, 0xd2, 0x76, 0x24, 0x3a, 0x8e, 0x28, 0x4f, 0xbc, 0xd9, 0xa3, 0x15, 0x3a,
+  0xb9, 0xc3, 0x35, 0x3b, 0xc5, 0x22, 0xfa, 0xbb, 0x1c, 0x82, 0x81, 0xba, 0x2b, 0xf4, 0xd3, 0x3a,
+  0xfd, 0xbe, 0xce, 0xbb, 0x26, 0x2f, 0x8d, 0x3b, 0x9a, 0xc0, 0x8b, 0x39, 0x1a, 0xc9, 0xc7, 0x3b,
+  0x46, 0x08, 0x20, 0x3b, 0x29, 0x3c, 0x8d, 0xbb, 0x5b, 0x12, 0xab, 0xbc, 0x49, 0xdd, 0x7c, 0x3a,
+  0xed, 0x49, 0x25, 0xbb, 0x57, 0xac, 0x23, 0xbb, 0x45, 0x1b, 0x6c, 0x3b, 0xb9, 0x20, 0xf8, 0xbb,
+  0x93, 0x48, 0x73, 0x3c, 0x12, 0xbf, 0xc8, 0xbb, 0x3c, 0xd5, 0x69, 0xba, 0x34, 0x1c, 0x23, 0xbc,
+  0x75, 0x27, 0x6f, 0x3a, 0xcb, 0xf4, 0xd4, 0x3b, 0x93, 0x27, 0x55, 0x3c, 0xc2, 0x0c, 0xed, 0x3b,
+  0x2a, 0x6e, 0xeb, 0x3a, 0xe7, 0xcb, 0xac, 0xbb, 0x2e, 0xea, 0xf3, 0xbb, 0xe7, 0x06, 0x70, 0x3c,
+  0x92, 0x80, 0x19, 0x3c, 0xa9, 0xfa, 0x94, 0xbb, 0x12, 0xf7, 0x41, 0x3b, 0xe9, 0xe7, 0x8b, 0xbc,
+  0x54, 0x95, 0x67, 0xbb, 0x63, 0x0a, 0x38, 0xbc, 0xae, 0xbd, 0x10, 0x3a, 0x68, 0xce, 0x02, 0xba,
+  0x63, 0x28, 0x85, 0x3b, 0x91, 0x48, 0xde, 0xbb, 0xe8, 0xca, 0x43, 0x3b, 0x48, 0x86, 0x25, 0xba,
+  0x86, 0xe5, 0x27, 0xba, 0x44, 0x07, 0xd0, 0xbb, 0x99, 0x89, 0x10, 0x3b, 0x27, 0x4b, 0x4b, 0x3c,
+  0xf8, 0xde, 0x09, 0xbb, 0x43, 0x0d, 0x39, 0xbb, 0x94, 0x60, 0x24, 0xbc, 0xbf, 0x93, 0x13, 0xbb,
+  0x3e, 0x76, 0x48, 0xbb, 0x02, 0x7f, 0x10, 0x3c, 0xa7, 0xe6, 0x7a, 0x3c, 0x55, 0x01, 0x9d, 0xbb,
+  0x5e, 0x1a, 0x7e, 0xbc, 0x07, 0x18, 0x3e, 0xbc, 0x88, 0xd0, 0x5c, 0x3c, 0x26, 0x93, 0x49, 0xbb,
+  0xca, 0xdc, 0xa4, 0xbc, 0x3b, 0xcb, 0xc7, 0x3b, 0x67, 0x04, 0xac, 0x3c, 0xad, 0x76, 0x0c, 0x3b,
+  0xda, 0x60, 0x72, 0xbc, 0xb2, 0xf4, 0x8b, 0x3b, 0xf2, 0xe6, 0xe8, 0x3c, 0xd4, 0x4b, 0xb2, 0xbc,
+  0xcb, 0xd6, 0xa2, 0x3c, 0x5f, 0xe9, 0x09, 0xbc, 0xfc, 0x81, 0x8c, 0xbb, 0x43, 0x50, 0x12, 0xbc,
+  0xd3, 0x1a, 0xea, 0xbb, 0xb5, 0x58, 0x90, 0xbb, 0xc9, 0x63, 0xcc, 0x3b, 0x33, 0xab, 0xf4, 0xbb,
+  0x17, 0x70, 0xc4, 0x3c, 0x29, 0x0b, 0xe4, 0x3b, 0x79, 0x3e, 0xd9, 0xbc, 0x51, 0xf1, 0xdd, 0x3b,
+  0x4f, 0xfd, 0x0d, 0xb9, 0xc4, 0x40, 0xfd, 0x3b, 0x9b, 0x81, 0x8e, 0x3c, 0x58, 0xaa, 0x16, 0xbb,
+  0x08, 0xf2, 0xbe, 0x3c, 0x00, 0x14, 0x01, 0xbc, 0x8d, 0xaa, 0xb4, 0xbb, 0x16, 0xf0, 0x89, 0xbc,
+  0x9f, 0x40, 0xb4, 0xbb, 0xa3, 0x50, 0x08, 0x3b, 0x1a, 0x3a, 0x92, 0x3c, 0x7f, 0x78, 0xde, 0xbc,
+  0x08, 0xae, 0x9a, 0x3c, 0x81, 0xcf, 0x8f, 0x3c, 0xb5, 0xda, 0x2d, 0x3c, 0x13, 0xad, 0x02, 0x3c,
+  0x3b, 0x44, 0xb6, 0x3c, 0xf1, 0xf3, 0x90, 0x3b, 0x1f, 0xb1, 0xbd, 0x3c, 0x8c, 0x73, 0xb7, 0xbc,
+  0x77, 0x12, 0xac, 0x3c, 0xd3, 0x6e, 0xcd, 0x3c, 0xec, 0xd4, 0x4a, 0xbc, 0xbe, 0x0d, 0xfe, 0xbb,
+  0xcb, 0xd7, 0x80, 0x3c, 0xed, 0xdd, 0xa5, 0xbb, 0x99, 0x0f, 0x80, 0x3c, 0x6d, 0x45, 0xda, 0xbc,
+  0x1b, 0x98, 0xfb, 0x3c, 0x9f, 0xcd, 0xde, 0x3c, 0x79, 0x9d, 0x84, 0xbc, 0xc0, 0xd4, 0xff, 0xbb,
+  0xac, 0xab, 0x0d, 0x3c, 0x77, 0x30, 0xcd, 0xbb, 0x1d, 0x82, 0xf8, 0x3b, 0x53, 0x82, 0x39, 0xbc,
+  0x00, 0xbc, 0x74, 0x3c, 0xd3, 0xd8, 0x3e, 0x3c, 0x55, 0xa0, 0x3a, 0xbb, 0x10, 0xa4, 0x2d, 0xbc,
+  0x8f, 0x3d, 0x4d, 0x3b, 0xe4, 0xf9, 0x03, 0x3c, 0xcc, 0xa1, 0x82, 0xbc, 0x9e, 0xc9, 0x14, 0xbc,
+  0x52, 0xce, 0x32, 0xbb, 0x6a, 0xd1, 0xfa, 0xbb, 0x14, 0x89, 0x4e, 0x3b, 0x50, 0xae, 0x03, 0xbc,
+  0xa8, 0x25, 0xca, 0xbb, 0xd8, 0x81, 0x29, 0x3b, 0xed, 0x06, 0x01, 0x3c, 0x97, 0x83, 0x53, 0xbc,
+  0x07, 0xae, 0xc8, 0xbb, 0xc0, 0x33, 0x36, 0xbc, 0x75, 0x28, 0x34, 0xbc, 0x33, 0xc6, 0x3d, 0xbc,
+  0xca, 0x4d, 0xa6, 0xbc, 0x14, 0xde, 0xcd, 0x39, 0x40, 0xbd, 0x52, 0xbb, 0xae, 0x14, 0x1f, 0x3b,
+  0x50, 0x01, 0xa7, 0x3b, 0x06, 0xa3, 0x09, 0xbc, 0x9d, 0x65, 0x5e, 0xbb, 0x7b, 0xa9, 0x0c, 0x3c,
+  0x49, 0xb3, 0x5f, 0xbc, 0x58, 0xa1, 0x23, 0x3b, 0x10, 0x01, 0xa5, 0xba, 0x7c, 0x2f, 0x49, 0xbc,
+  0xd9, 0x23, 0x2f, 0x3c, 0x44, 0x93, 0x6a, 0xbc, 0xdb, 0xb3, 0x50, 0x3c, 0x7c, 0x36, 0x10, 0x3c,
+  0x99, 0xab, 0xe7, 0xbc, 0x30, 0x9f, 0x0a, 0x39, 0xf9, 0xfb, 0xb2, 0xba, 0xe2, 0x4d, 0x60, 0x3a,
+  0x91, 0xfb, 0x05, 0x3b, 0x09, 0x8b, 0xb4, 0xbc, 0x92, 0x64, 0x1e, 0xba, 0x61, 0x50, 0x1f, 0xbc,
+  0x52, 0xcd, 0xa1, 0xbb, 0xa9, 0x4e, 0xa8, 0xba, 0xdc, 0x78, 0xc0, 0xb7, 0x19, 0x11, 0x5a, 0xbc,
+  0x9f, 0xee, 0x8d, 0xbb, 0x44, 0xc9, 0xc9, 0xbb, 0xa9, 0x9f, 0x28, 0xbc, 0x96, 0xaf, 0x39, 0xbb,
+  0x5d, 0xde, 0x7a, 0xbb, 0x60, 0x99, 0xd2, 0x3b, 0xe4, 0x0c, 0xd0, 0x3a, 0xff, 0x67, 0x39, 0xbb,
+  0x0c, 0x0b, 0x97, 0xba, 0x32, 0x11, 0x58, 0xbc, 0x0b, 0x0d, 0x90, 0xbc, 0x43, 0xce, 0x66, 0xbc,
+  0xba, 0x7d, 0x2d, 0x3b, 0x5f, 0x02, 0x94, 0xb9, 0xdf, 0xf4, 0xbb, 0xbb, 0xee, 0x5a, 0xdb, 0xbb,
+  0x73, 0x10, 0x52, 0x3c, 0xc3, 0x65, 0xef, 0xbb, 0xa4, 0x14, 0x91, 0xbb, 0xfa, 0x91, 0x7d, 0x3a,
+  0xf6, 0xdf, 0x7f, 0x39, 0x2d, 0x07, 0xdf, 0x3a, 0xf7, 0x97, 0x13, 0x3c, 0x91, 0xff, 0x52, 0xbc,
+  0xbe, 0x37, 0xbb, 0x3b, 0xc3, 0x45, 0x1c, 0x3b, 0xd6, 0x16, 0x8e, 0xbb, 0x08, 0x8a, 0x9e, 0x3b,
+  0x83, 0xbb, 0xba, 0x3a, 0xab, 0x8d, 0xa0, 0x3a, 0x38, 0x46, 0xb1, 0x3b, 0x7e, 0xca, 0x9e, 0x3a,
+  0x45, 0xdc, 0x0c, 0xbc, 0x21, 0x81, 0x8f, 0xbb, 0x00, 0xd5, 0x80, 0x3c, 0x93, 0x7f, 0x7c, 0x3c,
+  0x69, 0x4a, 0xe5, 0xb9, 0xe3, 0xf5, 0xce, 0xbb, 0xf8, 0x6d, 0x94, 0x3b, 0x68, 0xa7, 0x53, 0xbc,
+  0xf2, 0xd4, 0x04, 0xba, 0x72, 0x15, 0x20, 0xbc, 0xe8, 0x35, 0x38, 0x3c, 0xfd, 0x6e, 0x56, 0xb9,
+  0x7d, 0x81, 0x3c, 0x3b, 0xee, 0x69, 0x1e, 0x3c, 0xbb, 0x1b, 0x25, 0xbc, 0x12, 0xf7, 0xd3, 0xbb,
+  0xcc, 0xc3, 0x3e, 0x3c, 0x02, 0x79, 0x2c, 0x3c, 0x57, 0xa5, 0x74, 0x3c, 0xa5, 0x84, 0x1c, 0xbc,
+  0x9b, 0x62, 0x10, 0xbc, 0x0f, 0x5d, 0x70, 0xbc, 0xa5, 0xdf, 0x68, 0x3c, 0xcb, 0xf3, 0xc2, 0x3a,
+  0x53, 0xb3, 0x42, 0xbb, 0x58, 0xed, 0x94, 0xba, 0x6f, 0x8b, 0x9b, 0x3c, 0xe9, 0x0b, 0xab, 0x3a,
+  0x58, 0x0f, 0xd6, 0xbc, 0x1e, 0x3f, 0xc1, 0x3b, 0xac, 0x39, 0xf7, 0x3c, 0xf7, 0xff, 0x9b, 0xbc,
+  0x9f, 0xf1, 0xbd, 0x3c, 0xfa, 0x4a, 0x2c, 0x3c, 0x69, 0x49, 0xbd, 0x3a, 0xce, 0x20, 0x85, 0xbb,
+  0x53, 0xcc, 0x30, 0xbc, 0x18, 0x3c, 0x2a, 0xbb, 0x86, 0x09, 0x9e, 0x3c, 0xae, 0x00, 0x73, 0xbc,
+  0xca, 0x3f, 0xd4, 0x3c, 0x35, 0x6c, 0xa2, 0x3b, 0xe4, 0xe7, 0x81, 0xbc, 0x3e, 0x6b, 0x52, 0xbc,
+  0x2d, 0xd1, 0x25, 0xbc, 0x23, 0x3e, 0x7c, 0x3b, 0x12, 0x9a, 0x5a, 0x3c, 0xb3, 0x1a, 0xc8, 0xbc,
+  0x8c, 0xcf, 0x9f, 0x3c, 0x4f, 0x18, 0xdd, 0xbb, 0xdd, 0x09, 0x01, 0xbb, 0xd0, 0x8f, 0x9f, 0x3b,
+  0x51, 0xe0, 0x15, 0xbc, 0xd7, 0xfd, 0x32, 0x3a, 0x2c, 0x90, 0x9f, 0x3c, 0x89, 0xce, 0xe6, 0xbb,
+  0x4a, 0x05, 0x7e, 0x3c, 0xe8, 0xb5, 0x14, 0x3c, 0x3e, 0xe6, 0x08, 0x3b, 0x7e, 0x61, 0x19, 0xbc,
+  0x22, 0x3f, 0x31, 0x3c, 0x41, 0xab, 0xa1, 0x3b, 0xf3, 0xbf, 0xd1, 0x3c, 0x01, 0x3f, 0xf0, 0xbc,
+  0x2f, 0x4b, 0x4d, 0x3c, 0x02, 0x51, 0x08, 0x3d, 0x26, 0x12, 0x7d, 0xbc, 0xed, 0x1c, 0xa1, 0xbc,
+  0x32, 0x02, 0xed, 0x3c, 0xf3, 0x5e, 0x94, 0x3b, 0xb8, 0x23, 0x9d, 0x3c, 0x77, 0xf4, 0xb9, 0xbc,
+  0xe5, 0x35, 0x85, 0x3c, 0xa7, 0x66, 0x7a, 0x3c, 0x80, 0x66, 0xa7, 0xbc, 0x1d, 0x0c, 0x40, 0xbb,
+  0xd4, 0x16, 0x9d, 0x3c, 0xf4, 0x00, 0x31, 0xbb, 0x9d, 0x84, 0x19, 0xba, 0x69, 0x31, 0x2a, 0xbc,
+  0xa7, 0xbe, 0x60, 0x3c, 0x5a, 0xb2, 0x87, 0x3c, 0xe8, 0xe9, 0x77, 0xbc, 0x0b, 0x77, 0x5b, 0x3b,
+  0xd7, 0x2f, 0x67, 0x3b, 0x93, 0x14, 0xe5, 0x3b, 0x4f, 0x43, 0xe6, 0xbb, 0x25, 0x65, 0xe5, 0xbb,
+  0xe9, 0xf1, 0x78, 0x3b, 0x0b, 0xfc, 0x00, 0xbc, 0x02, 0x38, 0x7c, 0xbb, 0x62, 0x2b, 0x2d, 0xba,
+  0x12, 0x06, 0x0e, 0x3b, 0x75, 0x91, 0x50, 0x3c, 0x8b, 0x07, 0x18, 0x3b, 0xd1, 0xa3, 0x37, 0xbb,
+  0xf1, 0x0c, 0xf4, 0xbb, 0x8a, 0x6f, 0x10, 0xbb, 0x48, 0x03, 0x67, 0xbc, 0x09, 0xf5, 0x58, 0xbc,
+  0x67, 0xad, 0xca, 0xbc, 0xc0, 0x06, 0x4c, 0x3c, 0x9f, 0x60, 0x60, 0xbb, 0xa8, 0x38, 0x87, 0x3b,
+  0x44, 0x64, 0x47, 0x3b, 0x7d, 0xa7, 0x0c, 0xbc, 0xef, 0x3d, 0xc2, 0xbb, 0x67, 0xda, 0xb0, 0x3a,
+  0xab, 0x1c, 0xbc, 0xbc, 0x76, 0xa5, 0x1e, 0x3c, 0xe9, 0x89, 0xc3, 0xbb, 0x55, 0x5f, 0xb6, 0xb9,
+  0xfb, 0x44, 0x66, 0x3c, 0x98, 0xa1, 0x39, 0xbc, 0x52, 0x9c, 0x02, 0x3c, 0x33, 0xa7, 0xbf, 0xbb,
+  0xb3, 0xd8, 0xb7, 0xbc, 0x89, 0x5e, 0xc3, 0xbb, 0x68, 0x4b, 0x0b, 0x3b, 0xdf, 0xb8, 0xae, 0x3b,
+  0x90, 0xab, 0x1d, 0xbb, 0x4f, 0x92, 0x8b, 0xbc, 0x5b, 0x02, 0x97, 0x3b, 0x7a, 0x1d, 0xc1, 0x3b,
+  0xe0, 0xac, 0x21, 0xbc, 0x57, 0xfc, 0x14, 0xbc, 0x5a, 0x66, 0x4b, 0x3b, 0x54, 0x71, 0xc6, 0xbb,
+  0xf8, 0x28, 0x01, 0x3b, 0x5a, 0x77, 0x88, 0xbc, 0x4a, 0x8e, 0x82, 0xbc, 0xd3, 0xd3, 0x4e, 0xbb,
+  0x28, 0x57, 0x2d, 0xbc, 0x1e, 0x65, 0xe8, 0xba, 0x2c, 0xee, 0xa7, 0xbb, 0x1a, 0x98, 0xdb, 0xbb,
+  0xc4, 0x12, 0x1e, 0xbb, 0x16, 0x23, 0x2c, 0xbc, 0xf5, 0x57, 0x60, 0xbc, 0x3b, 0xda, 0xd4, 0x3a,
+  0x7e, 0xf3, 0x0e, 0xbc, 0x21, 0x4a, 0xdf, 0x3b, 0x1f, 0x9e, 0x0e, 0xba, 0x3f, 0x41, 0x90, 0xbc,
+  0xb2, 0x9d, 0x68, 0x3c, 0x52, 0x76, 0xe1, 0x3a, 0x46, 0x2d, 0x8f, 0xbb, 0x65, 0xc5, 0x4b, 0x3c,
+  0x08, 0x48, 0x0b, 0x3b, 0xc5, 0xfa, 0xb9, 0x3b, 0x9f, 0x09, 0xc8, 0x3b, 0x0f, 0xf9, 0x93, 0xbc,
+  0xad, 0xa4, 0x09, 0x3b, 0x9e, 0xdf, 0x34, 0xbc, 0xbf, 0x94, 0x06, 0xba, 0x5a, 0x45, 0x0c, 0x3b,
+  0x0c, 0xd6, 0x55, 0x39, 0xf6, 0x8f, 0xc0, 0x3b, 0xcc, 0x9a, 0x52, 0xbb, 0xea, 0x5e, 0x5f, 0xbc,
+  0xa3, 0x75, 0x16, 0xbb, 0xf2, 0xa9, 0x9f, 0xbb, 0x62, 0xa4, 0x19, 0x3c, 0x29, 0x88, 0x84, 0xbc,
+  0x77, 0x28, 0x51, 0x3c, 0x3a, 0x7e, 0x52, 0xb9, 0x7b, 0xdf, 0xa8, 0x3b, 0xc8, 0xd9, 0x68, 0xba,
+  0xd7, 0xdb, 0x32, 0x3b, 0x7c, 0x92, 0x81, 0xbb, 0x70, 0xd2, 0xec, 0x3b, 0x8c, 0xfc, 0x8e, 0xbc,
+  0x7f, 0x0c, 0xe2, 0x39, 0xdb, 0x6e, 0x03, 0xbc, 0xcf, 0x31, 0x04, 0xbc, 0xe2, 0xd0, 0xcc, 0x3b,
+  0xf0, 0xe5, 0x84, 0xbb, 0x62, 0x79, 0xe5, 0xbb, 0xd0, 0x7a, 0xe6, 0x3b, 0x8c, 0xc4, 0x69, 0xbb,
+  0xea, 0x13, 0x69, 0xbb, 0xaf, 0x20, 0x81, 0xbc, 0xc8, 0xc8, 0xc7, 0x3b, 0xbc, 0x1f, 0x5a, 0xbc,
+  0x4f, 0xb1, 0x97, 0xbc, 0x1d, 0x65, 0x53, 0xbb, 0x70, 0xd6, 0xa6, 0x3c, 0xf3, 0xa6, 0x0a, 0xbc,
+  0x87, 0x54, 0x3b, 0xbc, 0xe6, 0xb8, 0x8c, 0x3b, 0xde, 0xb1, 0xfb, 0x3c, 0x3d, 0x32, 0x5b, 0xbb,
+  0x13, 0xfa, 0xb9, 0x3c, 0xec, 0x55, 0x9a, 0x3b, 0xd0, 0x8c, 0x44, 0xbb, 0x8d, 0x82, 0x3d, 0xbc,
+  0x96, 0xee, 0x32, 0xbc, 0x28, 0x97, 0xb0, 0x39, 0xd7, 0xb9, 0xd8, 0x3b, 0xd7, 0x2e, 0x44, 0xbc,
+  0x63, 0xa6, 0x89, 0x3c, 0xe7, 0x7f, 0x95, 0x3b, 0x67, 0x64, 0xbc, 0xbc, 0xf6, 0x2a, 0x42, 0x3c,
+  0x92, 0xe5, 0xb0, 0xbc, 0xb4, 0x9b, 0xd5, 0x3b, 0x48, 0x78, 0xdf, 0x3a, 0xc7, 0x14, 0x96, 0xbc,
+  0xd1, 0xf7, 0xa8, 0x3c, 0x2b, 0x08, 0xf0, 0x3b, 0xeb, 0x8c, 0x46, 0xbc, 0x99, 0x2e, 0x4a, 0xbc,
+  0x9a, 0x20, 0xce, 0xbb, 0x6a, 0x87, 0x1a, 0xbb, 0x24, 0xcd, 0xaa, 0x3c, 0x05, 0x9b, 0xaf, 0xbc,
+  0x27, 0xe3, 0xd2, 0x3c, 0xea, 0x58, 0x44, 0x3c, 0x53, 0xe5, 0xde, 0x3b, 0x93, 0x6e, 0x82, 0xba,
+  0x80, 0x9b, 0xd3, 0x3a, 0x05, 0xde, 0x49, 0x3c, 0xb0, 0x9b, 0xb2, 0x3c, 0x90, 0xaf, 0xba, 0xbc,
+  0xce, 0x25, 0x89, 0x3c, 0xa4, 0xa5, 0xc3, 0x3c, 0x6d, 0xc3, 0xe5, 0xbb, 0xfa, 0xc3, 0x72, 0xbc,
+  0xa6, 0xdb, 0xa5, 0x3c, 0x43, 0xb7, 0x8b, 0x3b, 0x7e, 0x0f, 0x55, 0x3c, 0x63, 0x5b, 0xa0, 0xbb,
+  0xa5, 0xa3, 0xa2, 0x3c, 0x72, 0x48, 0xf4, 0x3c, 0xf8, 0xe0, 0xc5, 0xbc, 0x9f, 0x47, 0x26, 0x3c,
+  0x5e, 0x95, 0x99, 0x3b, 0xdd, 0xa7, 0x39, 0xbc, 0xc3, 0xaf, 0x1d, 0xbc, 0xd2, 0xb3, 0x81, 0xbc,
+  0xee, 0xb6, 0x04, 0x3d, 0xd4, 0x23, 0x9d, 0x3c, 0x25, 0x54, 0x98, 0xbc, 0x85, 0x44, 0x9d, 0xba,
+  0x1a, 0x6e, 0x40, 0xbb, 0x9a, 0x91, 0x91, 0x3b, 0x66, 0xd6, 0x3a, 0xba, 0x18, 0x44, 0x45, 0xbc,
+  0x53, 0x5f, 0x84, 0x3b, 0x9a, 0xa5, 0x1e, 0xbc, 0x05, 0x86, 0xc3, 0xbb, 0xa3, 0xa1, 0x05, 0xbc,
+  0x02, 0x75, 0x38, 0x3a, 0x5b, 0xbe, 0x46, 0x3c, 0xa0, 0x39, 0x02, 0x3c, 0x74, 0xa3, 0xcc, 0xbb,
+  0xd0, 0x7a, 0x26, 0xbc, 0xa2, 0x48, 0x26, 0xbc, 0x37, 0xdc, 0x11, 0xbc, 0x54, 0xf8, 0x48, 0x3c,
+  0xca, 0x52, 0x88, 0xbc, 0xa4, 0x1d, 0x26, 0x3c, 0x94, 0x56, 0xe9, 0x3b, 0x4a, 0x38, 0x5d, 0x3b,
+  0x58, 0x33, 0x6e, 0xba, 0x7b, 0x44, 0x22, 0xbc, 0xca, 0x35, 0x00, 0xba, 0xe8, 0x57, 0xa3, 0xbc,
+  0xf2, 0xfd, 0xa9, 0xbc, 0x30, 0xcd, 0xe5, 0x3a, 0x33, 0x48, 0xa5, 0xbb, 0xea, 0x21, 0x63, 0x3b,
+  0xdf, 0xbe, 0xff, 0x3b, 0x07, 0x33, 0x4a, 0xbc, 0xd7, 0x36, 0xbd, 0x3b, 0xae, 0x53, 0x5a, 0xbc,
+  0xeb, 0x05, 0x96, 0xbc, 0xef, 0x39, 0xc2, 0x3b, 0x70, 0xe3, 0x81, 0x3b, 0x19, 0x81, 0x09, 0xbc,
+  0x97, 0xa9, 0x3a, 0x3b, 0xf9, 0x43, 0x9c, 0xbc, 0xf4, 0xd5, 0x82, 0xbb, 0xec, 0xd5, 0xe4, 0xbb,
+  0x4f, 0x79, 0x7c, 0xbc, 0xb8, 0x88, 0xfe, 0x39, 0xf0, 0x25, 0x77, 0x3b, 0x2a, 0x9e, 0x8c, 0xba,
+  0x2b, 0xfa, 0x60, 0xbb, 0xb6, 0xc9, 0xc9, 0xbb, 0x49, 0x33, 0x82, 0xbc, 0xf9, 0xe5, 0xa0, 0x3a,
+  0xb0, 0xac, 0x4f, 0xbc, 0x13, 0xa1, 0xbe, 0xbb, 0x69, 0x40, 0x9f, 0x3b, 0x68, 0x09, 0xaf, 0xb9,
+  0x63, 0x9f, 0xde, 0xbb, 0xa9, 0xb6, 0x7c, 0xbc, 0xc5, 0xf7, 0x99, 0xbc, 0xf5, 0x3c, 0x21, 0xbc,
+  0x88, 0xd9, 0x03, 0x3a, 0x75, 0x9c, 0x00, 0x3c, 0x26, 0x91, 0x82, 0x3a, 0xf6, 0x9d, 0xe0, 0xba,
+  0x76, 0x2d, 0xc9, 0x3b, 0xf1, 0xa4, 0x1d, 0x3c, 0x2f, 0x3c, 0x2c, 0xbc, 0xae, 0xb7, 0x6c, 0xbb,
+  0xa2, 0xcf, 0xd9, 0x3a, 0xac, 0x7a, 0x3a, 0x3c, 0x67, 0xa8, 0xca, 0xbb, 0xcd, 0x87, 0x94, 0x3b,
+  0xd2, 0x03, 0x0c, 0xbb, 0xe9, 0x8e, 0xc3, 0x3b, 0x00, 0xcb, 0xab, 0x3b, 0x92, 0x05, 0x73, 0x3c,
+  0x4e, 0xd4, 0xa8, 0xbb, 0x08, 0xc9, 0x28, 0x3b, 0xf7, 0xdc, 0x8d, 0xbb, 0x7e, 0x6b, 0x59, 0xbb,
+  0xd1, 0x42, 0x43, 0x39, 0xbc, 0xc8, 0xce, 0xba, 0xed, 0xa7, 0xf4, 0x3a, 0x8d, 0xb8, 0xdb, 0xba,
+  0xe8, 0xc9, 0x2c, 0x3c, 0xc0, 0x6c, 0x60, 0x3b, 0x7c, 0x19, 0x6d, 0xb8, 0x6d, 0x0e, 0x7f, 0xbc,
+  0x48, 0xfb, 0x5f, 0xbb, 0x38, 0x37, 0x31, 0xbb, 0xc8, 0xf1, 0xbc, 0x3b, 0x48, 0x42, 0x1a, 0xbb,
+  0x9d, 0x4c, 0xb5, 0xbb, 0xfb, 0x68, 0x87, 0xbb, 0x4d, 0x2a, 0x01, 0xbc, 0x50, 0x38, 0x23, 0xbc,
+  0x7b, 0x64, 0x4c, 0x3b, 0x0f, 0x7c, 0x37, 0x3c, 0x86, 0x24, 0x79, 0x3c, 0x13, 0xe1, 0x16, 0xbb,
+  0x59, 0x2d, 0xfe, 0xbb, 0x17, 0xf9, 0x1d, 0xbc, 0x71, 0x0e, 0x07, 0x3b, 0x4d, 0xa2, 0x1f, 0xb9,
+  0xb4, 0xc6, 0x7f, 0xbb, 0x92, 0x87, 0xde, 0xbb, 0x81, 0xaf, 0xb1, 0x3c, 0xeb, 0x1a, 0x52, 0xbb,
+  0x08, 0xe3, 0x99, 0xbc, 0x8d, 0x55, 0xb0, 0x3b, 0xdc, 0xf8, 0x25, 0x3d, 0x1b, 0xf1, 0x1c, 0xbc,
+  0xb6, 0xb4, 0xc8, 0x3c, 0xff, 0x8d, 0x93, 0x3c, 0x58, 0xc2, 0x7a, 0xbb, 0x39, 0x44, 0x9b, 0x3b,
+  0x3d, 0x30, 0xdd, 0xbb, 0x6d, 0x09, 0xab, 0x3b, 0xd7, 0x07, 0x90, 0x3c, 0x1a, 0x34, 0x81, 0xbc,
+  0x13, 0x5e, 0x9f, 0x3c, 0x98, 0x15, 0x2c, 0x3b, 0xb5, 0x89, 0xb9, 0xbc, 0xbf, 0x47, 0x1a, 0x3c,
+  0x39, 0xad, 0x6a, 0xbc, 0x27, 0x20, 0xda, 0xbb, 0xc4, 0xac, 0x0d, 0x3c, 0xee, 0x4c, 0x89, 0xbc,
+  0x97, 0xae, 0x9c, 0x3c, 0xc6, 0x90, 0xf3, 0xba, 0x42, 0xa5, 0x19, 0xbc, 0x69, 0x27, 0x72, 0x3b,
+  0xc9, 0x36, 0xc6, 0xba, 0x70, 0xa2, 0x4f, 0x3a, 0xb8, 0x0b, 0xe4, 0x3c, 0xc8, 0x63, 0x4f, 0xbc,
+  0xc5, 0x2c, 0xa2, 0x3c, 0xa7, 0x04, 0x90, 0x3c, 0xf2, 0x5f, 0xd3, 0x3b, 0xd7, 0x8e, 0xf7, 0x3b,
+  0x8a, 0x3c, 0x88, 0x3b, 0xab, 0xa6, 0x9d, 0x3b, 0xd4, 0x0f, 0xc5, 0x3c, 0xea, 0x56, 0xae, 0xbb,
+  0x8d, 0x54, 0x37, 0x3c, 0x86, 0xa3, 0xae, 0x3c, 0xb9, 0x7e, 0x2a, 0xbc, 0x30, 0xc2, 0x1e, 0xbb,
+  0xf3, 0x8f, 0xce, 0x3c, 0xb7, 0x23, 0xff, 0xba, 0xaf, 0xbf, 0x9c, 0x3c, 0xd7, 0xd0, 0xbd, 0xbc,
+  0x64, 0xf4, 0x9e, 0x3c, 0x5f, 0x6c, 0xb7, 0x3c, 0x5a, 0x39, 0xce, 0xbc, 0xe5, 0x8c, 0x3b, 0x3b,
+  0x48, 0x1f, 0xea, 0x3b, 0x93, 0xce, 0x05, 0x3b, 0x3d, 0x1e, 0xd7, 0xbb, 0x22, 0x53, 0xc5, 0xbb,
+  0x0c, 0x3b, 0xca, 0x3c, 0x8e, 0xde, 0x59, 0x3c, 0x9c, 0x81, 0xbb, 0xbb, 0xf9, 0x56, 0x80, 0x3b,
+  0x3c, 0x67, 0x2b, 0x3b, 0xdc, 0x42, 0x01, 0xbb, 0xe9, 0x29, 0xc9, 0xba, 0x7a, 0xf2, 0x14, 0xbc,
+  0xe3, 0x78, 0xeb, 0x3b, 0x70, 0x09, 0x6e, 0xbb, 0x21, 0x0f, 0x35, 0xbc, 0x56, 0xf9, 0xf5, 0xbb,
+  0x0f, 0x26, 0x93, 0x3b, 0x07, 0xa7, 0x2c, 0x3c, 0x88, 0x1d, 0x4e, 0xba, 0xc6, 0x04, 0x64, 0x3a,
+  0xb2, 0xa3, 0xa3, 0xb9, 0xa1, 0xf8, 0xad, 0xbc, 0x49, 0x35, 0x29, 0xbc, 0x86, 0x61, 0x96, 0x3b,
+  0xbc, 0x72, 0x21, 0xbc, 0x16, 0xfe, 0xbb, 0x3b, 0xdf, 0xa6, 0x81, 0xbb, 0x24, 0x11, 0xbd, 0xbb,
+  0xf9, 0x6b, 0x93, 0x3b, 0x4e, 0x25, 0xc2, 0xbb, 0xd0, 0xb6, 0xdf, 0xbb, 0x21, 0x97, 0x66, 0x3b,
+  0x6b, 0x0b, 0x98, 0xbc, 0x52, 0x96, 0xa7, 0x3b, 0x74, 0x48, 0xa8, 0xba, 0x55, 0x73, 0x5a, 0xbc,
+  0x66, 0xd4, 0x48, 0x3c, 0x6e, 0x44, 0x08, 0xbc, 0xc0, 0xe0, 0x1b, 0x3c, 0x77, 0xb1, 0x7a, 0x3b,
+  0xf4, 0x7e, 0x9c, 0xbc, 0x40, 0x7f, 0x0a, 0xbb, 0x2c, 0x62, 0xb3, 0xbb, 0x4f, 0x94, 0x6f, 0xbc,
+  0x78, 0xf6, 0xa1, 0x3a, 0x81, 0x73, 0xbf, 0xbc, 0x09, 0x58, 0xf2, 0xbb, 0x67, 0x66, 0x07, 0x3c,
+  0xc1, 0x9c, 0x8f, 0xbc, 0x32, 0x4d, 0x28, 0x3c, 0x2f, 0x3c, 0x4d, 0x3b, 0x09, 0x51, 0xf7, 0x3b,
+  0x9d, 0x3c, 0x83, 0xbb, 0x81, 0x47, 0x05, 0xbb, 0x71, 0xb7, 0x69, 0xbc, 0xb3, 0xd0, 0xf2, 0xbb,
+  0x11, 0x15, 0xa9, 0xbb, 0xac, 0x9c, 0x84, 0xbc, 0x41, 0x63, 0xf7, 0xb9, 0xf8, 0xe3, 0x47, 0xbc,
+  0xd0, 0x78, 0x2f, 0x3a, 0xc3, 0xc4, 0x2a, 0xbc, 0x33, 0x7b, 0x0f, 0xbc, 0xae, 0x71, 0x34, 0xbc,
+  0x8b, 0xe7, 0x81, 0x3a, 0x81, 0x6f, 0x99, 0x3b, 0x86, 0x37, 0x3c, 0x3c, 0x30, 0xc0, 0x1d, 0xbc,
+  0x13, 0x4d, 0x7b, 0xba, 0xf8, 0x61, 0x59, 0xbb, 0xc4, 0xa7, 0x8a, 0x3b, 0x39, 0xc2, 0xc9, 0xbb,
+  0x82, 0xa9, 0xe0, 0x3b, 0x0f, 0x0b, 0x74, 0x3a, 0x56, 0xc6, 0xed, 0xbb, 0x70, 0x5f, 0x07, 0xbb,
+  0x6a, 0x36, 0x58, 0xbb, 0x25, 0x01, 0x29, 0x3c, 0x39, 0x3f, 0x2a, 0x3b, 0x81, 0x41, 0x5d, 0x3b,
+  0x76, 0xfd, 0x93, 0x3b, 0x27, 0xff, 0xc4, 0x3b, 0xaa, 0xe8, 0xdb, 0x3b, 0x5f, 0x8f, 0x92, 0xbb,
+  0x16, 0xce, 0x0b, 0x3b, 0xe2, 0x39, 0x14, 0xbc, 0xf5, 0xe3, 0x08, 0x3b, 0x66, 0x09, 0x92, 0xbc,
+  0xe6, 0xfc, 0x00, 0x3b, 0xd8, 0x85, 0x05, 0x3b, 0x21, 0x0f, 0xa3, 0xbb, 0x90, 0xbf, 0x8c, 0xbc,
+  0x0a, 0x7f, 0x10, 0xbc, 0xe3, 0x4e, 0x20, 0xbc, 0x59, 0xfd, 0xb3, 0xbb, 0xf2, 0xc9, 0x94, 0xba,
+  0xba, 0x6e, 0xbe, 0xbb, 0xa8, 0xdd, 0x5e, 0x3a, 0x58, 0x86, 0x5f, 0xbc, 0xd2, 0x19, 0xa8, 0x3b,
+  0xe6, 0xc3, 0x7b, 0xbc, 0xc2, 0x8f, 0x35, 0x3c, 0xbe, 0xbc, 0x96, 0x3b, 0xc1, 0x19, 0x79, 0xbc,
+  0x03, 0x5c, 0x8f, 0xbb, 0x43, 0x0f, 0x8d, 0xbc, 0x38, 0xc9, 0x04, 0x3c, 0x1a, 0x60, 0xa4, 0xbc,
+  0x91, 0xcf, 0x5d, 0xba, 0x8c, 0x6b, 0x3d, 0xbb, 0x24, 0x8d, 0xcf, 0x3c, 0xfb, 0x22, 0x86, 0xbc,
+  0x8e, 0x78, 0x4f, 0xbc, 0x54, 0x3f, 0x32, 0x3b, 0xed, 0x51, 0x05, 0x3d, 0x2c, 0x3a, 0x58, 0xbb,
+  0x5f, 0xaf, 0xce, 0x3c, 0x29, 0xb2, 0xa4, 0x3b, 0x59, 0x35, 0x2b, 0xbb, 0x08, 0xac, 0x1e, 0xba,
+  0x31, 0x7a, 0x1b, 0xbc, 0x30, 0xa1, 0x0e, 0xbb, 0x61, 0x63, 0x2a, 0x3c, 0xd9, 0xb5, 0x97, 0xbc,
+  0x6a, 0xe3, 0x87, 0x3c, 0xff, 0xf5, 0xe8, 0x3b, 0x63, 0x74, 0xae, 0xbc, 0x22, 0xba, 0x02, 0xbc,
+  0xee, 0xf3, 0x7e, 0xbc, 0xad, 0x78, 0x31, 0x3b, 0x71, 0xa8, 0xa5, 0x3b, 0x25, 0x96, 0x98, 0xbc,
+  0xce, 0x37, 0x8f, 0x3c, 0x95, 0xd5, 0x32, 0xba, 0xb8, 0x49, 0x73, 0xbb, 0x5f, 0xb4, 0x24, 0xbc,
+  0xf6, 0xcb, 0xbf, 0xbb, 0xc0, 0x1c, 0x9f, 0x3b, 0x48, 0x28, 0x78, 0x3c, 0x48, 0xc3, 0x55, 0xbc,
+  0xc5, 0x8a, 0x85, 0x3c, 0x85, 0xcf, 0x5b, 0x3c, 0x49, 0xc7, 0x21, 0xbc, 0xd8, 0xbf, 0xb9, 0xbb,
+  0x30, 0x41, 0xc9, 0x3b, 0x10, 0x2a, 0xc1, 0x3b, 0x8d, 0x36, 0x46, 0x3c, 0x81, 0x68, 0x70, 0xbc,
+  0xf1, 0xc6, 0x6b, 0x3c, 0xc3, 0xf8, 0xc0, 0x3c, 0x81, 0xc0, 0x35, 0xbc, 0x8a, 0x12, 0x2b, 0xbb,
+  0x5b, 0x86, 0x7d, 0x3c, 0x11, 0x3f, 0xf8, 0xbb, 0x73, 0x76, 0x89, 0x3c, 0x32, 0x32, 0x63, 0xba,
+  0x02, 0xa9, 0xd1, 0x3c, 0x38, 0xdd, 0x9d, 0x3c, 0x9b, 0x19, 0x15, 0xbd, 0x4b, 0xdc, 0x37, 0x3b,
+  0xe7, 0xd9, 0x9b, 0x3c, 0x77, 0xa1, 0x47, 0xbc, 0x64, 0x48, 0x21, 0xbb, 0x3c, 0xe8, 0x31, 0xbc,
+  0x14, 0x81, 0xa3, 0x3c, 0x7c, 0x1d, 0x48, 0x3c, 0x45, 0xe4, 0x02, 0xbc, 0x22, 0x1c, 0x27, 0x3c,
+  0x30, 0xd0, 0xb8, 0x3b, 0xfb, 0x75, 0x15, 0xbc, 0x4e, 0xff, 0xe3, 0xbb, 0x57, 0xf2, 0xe3, 0x3a,
+  0x81, 0xee, 0xd6, 0x3b, 0x99, 0x01, 0x99, 0x3b, 0x8b, 0xf6, 0x94, 0xb9, 0x8d, 0x35, 0x29, 0x3c,
+  0x75, 0x2f, 0xee, 0x39, 0x94, 0x2b, 0xfa, 0x3a, 0x46, 0x93, 0x35, 0x3c, 0x26, 0x8b, 0x2e, 0xbc,
+  0x27, 0xae, 0x1d, 0xbc, 0x0c, 0x0d, 0x8d, 0xbc, 0x41, 0x9e, 0xb7, 0xbb, 0x7e, 0x20, 0x8f, 0xbb,
+  0xaa, 0xf1, 0xf8, 0x3a, 0xf0, 0x78, 0x2d, 0x3c, 0xe3, 0xe0, 0x70, 0x3c, 0xb9, 0x71, 0x96, 0x3b,
+  0x94, 0x78, 0x08, 0x3c, 0x69, 0xcc, 0x01, 0xbc, 0xb9, 0x69, 0x09, 0x3c, 0xe7, 0x42, 0x81, 0xbc,
+  0x36, 0x8c, 0x97, 0xbc, 0xa4, 0x1f, 0xbd, 0x3b, 0x76, 0xd7, 0xae, 0xbb, 0x82, 0x9e, 0x00, 0x3c,
+  0x06, 0x8e, 0x9c, 0x3a, 0x1f, 0x53, 0xd2, 0xbb, 0x50, 0x2b, 0xf7, 0x3b, 0x50, 0xfd, 0xc2, 0x3a,
+  0x23, 0xcd, 0xae, 0xbc, 0xd6, 0x90, 0xa5, 0xbb, 0x6f, 0x1c, 0xa7, 0x3b, 0x65, 0xb2, 0x93, 0x3a,
+  0xbc, 0x0c, 0x2b, 0xb9, 0xba, 0x1b, 0xd1, 0xbc, 0xe7, 0xaa, 0x9e, 0xbb, 0x14, 0x73, 0x8a, 0x3c,
+  0xed, 0xd8, 0x9c, 0xbb, 0xbf, 0x9e, 0xee, 0xbb, 0xe1, 0xcf, 0x74, 0x3c, 0xdc, 0x73, 0x53, 0xbb,
+  0xde, 0xc3, 0xe7, 0xba, 0x91, 0x72, 0xfb, 0xbb, 0x54, 0xf5, 0xa0, 0xbb, 0x87, 0xa3, 0x91, 0xba,
+  0x50, 0x4b, 0x35, 0xbb, 0xd1, 0x39, 0x7f, 0xbb, 0x58, 0x60, 0x56, 0xbb, 0x91, 0x11, 0xbf, 0xbb,
+  0x3b, 0x05, 0x20, 0xbb, 0x53, 0x7e, 0x9f, 0x3b, 0x47, 0x19, 0xa5, 0xbc, 0x0b, 0x2c, 0x9f, 0x3c,
+  0xe8, 0xf4, 0x90, 0x3b, 0xad, 0x72, 0x6c, 0x3a, 0xeb, 0x71, 0xfd, 0xb7, 0xbc, 0x0a, 0x05, 0xbb,
+  0x7a, 0xd3, 0xff, 0xba, 0xbb, 0xa3, 0x0d, 0xbc, 0x31, 0x58, 0xb3, 0xbb, 0x13, 0x41, 0x0f, 0x3b,
+  0x78, 0x6b, 0x0d, 0xbb, 0xa6, 0x4c, 0x6a, 0x3c, 0xde, 0x76, 0xe8, 0xbb, 0xc7, 0x56, 0xea, 0xbb,
+  0x9f, 0x55, 0xcc, 0xbb, 0xab, 0xa4, 0x79, 0x3a, 0xad, 0x54, 0x1f, 0xbc, 0xc2, 0x3c, 0x58, 0x3c,
+  0x0e, 0xf7, 0xbe, 0x3b, 0x82, 0x08, 0xdb, 0x3b, 0xfb, 0x28, 0xac, 0x3b, 0xce, 0x78, 0xe5, 0x3a,
+  0x90, 0xbf, 0x96, 0xbb, 0xb6, 0x73, 0x41, 0xbc, 0x8b, 0x98, 0x1d, 0x3c, 0x52, 0x96, 0x84, 0x3b,
+  0xf3, 0x7a, 0x97, 0x3c, 0x98, 0xf1, 0x38, 0x3a, 0x63, 0xf0, 0x85, 0xba, 0x30, 0x50, 0x55, 0xbc,
+  0x62, 0x1c, 0x41, 0xbc, 0x65, 0x86, 0xa6, 0x39, 0x63, 0xc2, 0x56, 0x3c, 0xbd, 0xff, 0x00, 0xbc,
+  0x4c, 0xec, 0xa3, 0xbb, 0xfb, 0xb2, 0x2c, 0xba, 0xa4, 0x10, 0xb8, 0xbb, 0xa9, 0x9c, 0x41, 0xbc,
+  0xa7, 0xf7, 0x09, 0xbc, 0x5f, 0xbc, 0x39, 0x3c, 0x8d, 0x6b, 0xcb, 0x3b, 0x07, 0xfd, 0x73, 0x3b,
+  0x45, 0x82, 0x78, 0xbb, 0xb6, 0x4b, 0xa5, 0xbc, 0x8e, 0x97, 0x61, 0x3b, 0x52, 0x11, 0xc4, 0xbb,
+  0x1f, 0x64, 0x7f, 0x3b, 0x19, 0x5b, 0x33, 0xba, 0x5b, 0x9b, 0x62, 0x3c, 0x87, 0x97, 0x12, 0x3c,
+  0x4c, 0xe7, 0x47, 0xbc, 0x83, 0x16, 0xb4, 0x3b, 0x58, 0xd3, 0x01, 0x3d, 0xb7, 0xbd, 0x01, 0xbc,
+  0x83, 0xa2, 0x9d, 0x3c, 0xc1, 0xd2, 0x01, 0x39, 0x18, 0x98, 0x4e, 0xbb, 0x91, 0xa0, 0xff, 0xbb,
+  0x77, 0x20, 0xd2, 0xbb, 0x0a, 0xab, 0x4e, 0x37, 0x29, 0x6c, 0x28, 0x3c, 0xe7, 0x27, 0xc0, 0xba,
+  0x0a, 0xb3, 0x48, 0x3c, 0x5e, 0x68, 0x84, 0x3c, 0x68, 0xd8, 0xf8, 0xbc, 0xe0, 0x0b, 0xb3, 0xbb,
+  0xfd, 0x80, 0x77, 0xbc, 0xc9, 0x46, 0x7a, 0xbb, 0x9e, 0xeb, 0x94, 0x3b, 0x4f, 0xde, 0x4b, 0xbc,
+  0xa7, 0xbe, 0xe2, 0x3b, 0x1b, 0xf6, 0x18, 0x3b, 0x37, 0xeb, 0x52, 0xbb, 0xfc, 0x10, 0x99, 0xbb,
+  0xae, 0x2f, 0x37, 0x3a, 0x94, 0xaa, 0x18, 0x3a, 0x52, 0xf4, 0x11, 0x3c, 0xf5, 0x50, 0x8e, 0xbc,
+  0x5b, 0x9b, 0x71, 0x3c, 0x3f, 0xf3, 0xd0, 0x3b, 0xc4, 0x24, 0x1d, 0xbb, 0x9d, 0xc2, 0xe3, 0x3a,
+  0xe4, 0xcd, 0x83, 0x3b, 0x80, 0x4d, 0xa8, 0x3b, 0xc0, 0x48, 0x26, 0x3c, 0x16, 0x5a, 0x90, 0xbc,
+  0x97, 0x97, 0x9b, 0x3c, 0x12, 0x56, 0xcb, 0x3c, 0x53, 0xcb, 0x15, 0xbc, 0xf0, 0xad, 0xae, 0x3b,
+  0x4f, 0x88, 0xe3, 0x3c, 0xb7, 0x23, 0x18, 0xbc, 0x9f, 0xcd, 0x2b, 0x3c, 0x80, 0x2c, 0x62, 0xbc,
+  0xed, 0xaa, 0xde, 0x3c, 0x57, 0x2d, 0xc3, 0x3c, 0xda, 0x43, 0xeb, 0xbc, 0xdc, 0x88, 0xa7, 0x3b,
+  0x6e, 0xb3, 0x79, 0x3c, 0x86, 0x4f, 0x44, 0xbc, 0x46, 0x2c, 0x8b, 0xbb, 0x8f, 0x18, 0x76, 0x3a,
+  0xf3, 0x32, 0xd1, 0x3c, 0xcf, 0xbc, 0x8e, 0x3c, 0x2d, 0x77, 0xed, 0xba, 0xfc, 0xbf, 0x39, 0xbc,
+  0xf3, 0x62, 0x5e, 0x3c, 0xeb, 0x8d, 0x7d, 0xbb, 0x09, 0xd8, 0xee, 0xbb, 0x11, 0x23, 0x34, 0xbb,
+  0xdc, 0x59, 0xc2, 0x3b, 0xad, 0xbb, 0x61, 0x3c, 0xc7, 0x33, 0xd7, 0xbb, 0x43, 0x8c, 0x1c, 0x3b,
+  0xa6, 0xcd, 0x2b, 0xba, 0xe6, 0xf8, 0x10, 0x3c, 0x1d, 0x26, 0xef, 0x3b, 0x66, 0x78, 0x13, 0x3a,
+  0xdd, 0x13, 0x20, 0xbc, 0x21, 0xa9, 0x2b, 0xbc, 0x09, 0x20, 0xff, 0xbb, 0x09, 0x28, 0xcd, 0x3a,
+  0x58, 0xdc, 0x47, 0xbc, 0xa9, 0x0f, 0x23, 0x3c, 0x43, 0x22, 0xbd, 0xba, 0x02, 0xed, 0x25, 0x3b,
+  0xe4, 0x4e, 0x74, 0x3b, 0xcc, 0xc8, 0x7a, 0xbc, 0x7e, 0x04, 0x54, 0x3c, 0xe5, 0x85, 0x84, 0xbb,
+  0xe7, 0x5b, 0x76, 0xbc, 0x9a, 0x9c, 0x6b, 0x3c, 0x11, 0x92, 0x16, 0xbc, 0x3b, 0x60, 0x8d, 0xbc,
+  0xee, 0x8d, 0x01, 0x3c, 0x8a, 0x79, 0x25, 0xbc, 0x43, 0x55, 0xbc, 0xba, 0x90, 0xee, 0x4e, 0x3c,
+  0xe4, 0x92, 0x22, 0xbc, 0x8a, 0xd8, 0x8c, 0x3b, 0x9f, 0xf5, 0x51, 0xbb, 0x67, 0xa4, 0xc4, 0xbb,
+  0x67, 0x6c, 0x18, 0xb9, 0xd2, 0x39, 0x3c, 0xbc, 0x46, 0x70, 0x4d, 0xbc, 0xb6, 0x5a, 0x83, 0x3b,
+  0x75, 0x3a, 0x8c, 0xbb, 0x1b, 0x9e, 0x85, 0xbc, 0xb0, 0x99, 0x69, 0x3c, 0x1c, 0xa8, 0x70, 0x39,
+  0xeb, 0x9a, 0x19, 0xb9, 0x48, 0x4a, 0x16, 0xb9, 0x7f, 0x32, 0x5b, 0xbc, 0x6a, 0xc9, 0x8f, 0x3b,
+  0xc9, 0xc9, 0xd9, 0xbb, 0x11, 0x10, 0x75, 0xbb, 0x95, 0x57, 0x40, 0xbc, 0xe0, 0x63, 0xd8, 0xbb,
+  0x16, 0x6f, 0xc6, 0x3b, 0xc1, 0xad, 0x46, 0xbb, 0x66, 0x8f, 0x67, 0xbc, 0x2a, 0x0f, 0xf1, 0x3b,
+  0x86, 0x9b, 0xf1, 0x3a, 0xb5, 0x1b, 0x7b, 0x3b, 0x2d, 0xc2, 0xdf, 0xbb, 0x85, 0x36, 0x16, 0x3c,
+  0x39, 0x0f, 0x75, 0xbb, 0x13, 0x48, 0x52, 0xbb, 0x45, 0x84, 0xec, 0xbb, 0xdc, 0xd5, 0x00, 0xba,
+  0xfb, 0xd2, 0xc6, 0x3a, 0x31, 0xdb, 0x03, 0x3c, 0x29, 0x23, 0x0e, 0x3c, 0x99, 0x3f, 0x32, 0xbc,
+  0x49, 0x18, 0xb6, 0xbb, 0x9d, 0x48, 0x12, 0x3c, 0x5d, 0x62, 0x5f, 0x3b, 0x0b, 0x6d, 0xb9, 0x3b,
+  0xea, 0xdd, 0x14, 0x3c, 0xae, 0xf7, 0xa7, 0x3c, 0xcf, 0x37, 0x8d, 0xbb, 0x71, 0x33, 0x8b, 0xbc,
+  0x14, 0x54, 0x56, 0xbb, 0x99, 0xbf, 0x32, 0xbc, 0x86, 0x52, 0x43, 0xbb, 0x18, 0x3f, 0x8f, 0xbc,
+  0x8f, 0x19, 0x66, 0x3c, 0x1e, 0x67, 0x9d, 0xbb, 0xf0, 0xbb, 0x9f, 0xbb, 0x99, 0xda, 0x52, 0xbb,
+  0xcb, 0x08, 0x59, 0xbc, 0x1e, 0x09, 0x9a, 0xbb, 0x84, 0x69, 0xc4, 0x3b, 0x9b, 0x6a, 0x24, 0xbc,
+  0x31, 0x74, 0xcd, 0x3b, 0x64, 0x95, 0x7e, 0x3b, 0x9e, 0xe6, 0x43, 0xbc, 0x25, 0x45, 0x40, 0xbc,
+  0x69, 0xf1, 0xda, 0xbb, 0x82, 0xd2, 0xb3, 0x3a, 0xa6, 0xb2, 0x64, 0x3c, 0xc0, 0x2d, 0x97, 0xbc,
+  0x07, 0xb0, 0x9c, 0xbc, 0x31, 0xaa, 0x5e, 0xbc, 0x43, 0xf7, 0x92, 0xbb, 0xb1, 0xd0, 0x2d, 0xbc,
+  0xb1, 0xf3, 0x8d, 0xbc, 0x75, 0xc9, 0x8c, 0xbc, 0x9c, 0xfd, 0x93, 0x3c, 0xd8, 0xb2, 0x64, 0x3a,
+  0xd3, 0xba, 0x0e, 0xbc, 0x7b, 0x23, 0x46, 0xbb, 0x39, 0x47, 0xda, 0x3c, 0x6c, 0xff, 0xf3, 0xba,
+  0xf0, 0xc9, 0x4c, 0x3c, 0xdc, 0x05, 0x09, 0xbc, 0xfd, 0xf0, 0x93, 0xbc, 0x5c, 0xff, 0xe5, 0xbb,
+  0x2d, 0xa1, 0x80, 0xbc, 0xfd, 0x8c, 0xad, 0x3b, 0xd6, 0x3a, 0x48, 0x3c, 0x6b, 0xc9, 0x7d, 0xbc,
+  0xe7, 0x2a, 0x2c, 0x3c, 0xef, 0x3d, 0x2f, 0x3c, 0x7a, 0x9b, 0x8b, 0xbc, 0xf5, 0xd2, 0xf4, 0x3a,
+  0x18, 0x7a, 0x4b, 0xbb, 0x46, 0x97, 0x92, 0xbb, 0xc8, 0x31, 0x10, 0xbc, 0x97, 0xaf, 0x4f, 0x3a,
+  0x36, 0x8d, 0x90, 0x3c, 0x6f, 0x62, 0x49, 0x3a, 0x66, 0x44, 0xb1, 0xbb, 0xf6, 0x58, 0x1e, 0xbb,
+  0xaf, 0x92, 0x7b, 0x3b, 0x37, 0x80, 0x96, 0xbb, 0x33, 0x25, 0x04, 0x3c, 0x66, 0xdd, 0xaf, 0xbb,
+  0x41, 0xd9, 0x0f, 0x3c, 0x8f, 0x4c, 0x78, 0x3b, 0xf3, 0x19, 0xc3, 0xbb, 0xe8, 0xa6, 0x5f, 0xbc,
+  0xea, 0x3e, 0x57, 0x3c, 0xf5, 0xa5, 0xb3, 0xbb, 0x96, 0xc4, 0xe2, 0x3c, 0x91, 0x25, 0x8d, 0xbc,
+  0xd7, 0x67, 0x77, 0x3c, 0x01, 0xb2, 0xb3, 0x3c, 0xd5, 0x60, 0x77, 0xbc, 0x27, 0xf0, 0xa4, 0xbb,
+  0x27, 0xd3, 0xbd, 0x3c, 0x64, 0x5b, 0x5c, 0xbc, 0x5a, 0xeb, 0x94, 0x3b, 0x9c, 0xbe, 0x80, 0xbb,
+  0x4b, 0x1f, 0xea, 0x3c, 0xd1, 0x94, 0x07, 0x3d, 0x03, 0x1f, 0xb2, 0xbc, 0x5d, 0xa1, 0x73, 0x3b,
+  0x86, 0x1d, 0x88, 0x3c, 0x0f, 0x37, 0x9e, 0xbc, 0x2f, 0x6c, 0x92, 0x3b, 0xed, 0xa6, 0x5a, 0xbc,
+  0x74, 0x92, 0xcf, 0x3c, 0x9e, 0x1d, 0xbb, 0x3c, 0x03, 0xef, 0x5c, 0xbc, 0xd4, 0x69, 0x81, 0xba,
+  0xb3, 0x54, 0x65, 0x3b, 0x68, 0x4d, 0xa1, 0xbb, 0x38, 0xda, 0x27, 0x3b, 0x5e, 0x0c, 0x0a, 0x3a,
+  0xd1, 0x3e, 0x22, 0x3b, 0xfd, 0x04, 0x16, 0xba, 0x50, 0xe7, 0x9b, 0xbb, 0x9e, 0x02, 0xcd, 0x3b,
+  0x7f, 0xd4, 0x41, 0x3a, 0x5b, 0x4a, 0xa1, 0xba, 0xef, 0xde, 0xd3, 0x3a, 0x00, 0x88, 0x28, 0x3b,
+  0xa6, 0xb3, 0xcb, 0x3b, 0x6e, 0x24, 0x58, 0x39, 0x78, 0xf8, 0xaf, 0xbb, 0x1b, 0xcc, 0xa4, 0xbc,
+  0x7d, 0xfa, 0xc0, 0xbc, 0x7f, 0x86, 0x40, 0x3c, 0x1d, 0xeb, 0x35, 0x3b, 0x45, 0x91, 0x10, 0xbc,
+  0x82, 0xbc, 0xd2, 0x3b, 0x5a, 0xe9, 0xdb, 0xbb, 0x3c, 0x79, 0x11, 0x3a, 0x2b, 0x41, 0x3e, 0x3c,
+  0x74, 0x45, 0x07, 0xbc, 0x34, 0x8a, 0x0f, 0x3c, 0x2c, 0x88, 0xed, 0x3a, 0xe3, 0x8c, 0x89, 0x3a,
+  0xce, 0x9b, 0x81, 0x3c, 0xbb, 0x44, 0x98, 0xbc, 0x37, 0x11, 0x7e, 0x3a, 0x7e, 0x8e, 0xc4, 0x3b,
+  0x30, 0x18, 0x22, 0xbc, 0x08, 0xc5, 0x35, 0xbc, 0x3a, 0xc4, 0x12, 0x3c, 0xfe, 0x68, 0x7b, 0x3b,
+  0x3d, 0x85, 0x23, 0x3c, 0xa5, 0x2c, 0xf5, 0xbb, 0xf6, 0x83, 0x09, 0xbc, 0xd7, 0xd2, 0xa3, 0x3a,
+  0x7b, 0x43, 0x20, 0xbc, 0xc0, 0xe1, 0x3d, 0x3b, 0xc7, 0x9c, 0x32, 0x3c, 0xb8, 0xad, 0x11, 0xbc,
+  0xe0, 0xaf, 0x8d, 0x38, 0x9e, 0x4a, 0x4c, 0x3c, 0x08, 0x4d, 0x09, 0xbc, 0xb4, 0xd2, 0xde, 0xbb,
+  0x3b, 0x7f, 0x09, 0xbb, 0xc0, 0x38, 0x8c, 0x3b, 0xb2, 0xb7, 0x1d, 0xbc, 0x38, 0x53, 0x7f, 0xbb,
+  0x26, 0x9c, 0x7c, 0xbb, 0x86, 0x92, 0x3a, 0x3c, 0xfa, 0x77, 0xbe, 0xbb, 0xeb, 0xe9, 0x13, 0x3c,
+  0x3b, 0xe8, 0x0b, 0x3b, 0x4e, 0x4f, 0xa4, 0xbb, 0xc6, 0x63, 0x3e, 0x3a, 0x8f, 0x7d, 0xfc, 0xbb,
+  0x2c, 0x05, 0xe1, 0xba, 0x1c, 0x3f, 0x55, 0xba, 0x9c, 0xc5, 0x64, 0xbc, 0x3c, 0x10, 0xcf, 0x39,
+  0x6f, 0xa7, 0x9a, 0x3b, 0xcb, 0x63, 0x5b, 0x3c, 0x01, 0x48, 0x54, 0x3c, 0x7b, 0x0d, 0x20, 0xbc,
+  0xe5, 0x9a, 0xd6, 0x3b, 0xea, 0xd3, 0xe4, 0x39, 0x2d, 0x4d, 0x2b, 0xbb, 0x90, 0x4d, 0x85, 0x3b,
+  0xc0, 0xc6, 0x01, 0x3c, 0xb2, 0x98, 0xb2, 0xbb, 0x51, 0x34, 0x69, 0x39, 0xf6, 0x52, 0x20, 0x3c,
+  0xad, 0x62, 0x4f, 0xbc, 0xdb, 0xc3, 0x09, 0x3c, 0x9c, 0x3a, 0x5d, 0x3b, 0x40, 0xd6, 0xbc, 0xbb,
+  0xaf, 0x0f, 0x27, 0x3c, 0x81, 0xd8, 0x67, 0x3b, 0x6a, 0xf8, 0xe8, 0xba, 0x78, 0xea, 0x1b, 0xbb,
+  0x04, 0x79, 0xaf, 0xbb, 0x62, 0xf0, 0xe7, 0xbb, 0x42, 0x04, 0x0b, 0x3a, 0x4f, 0xd8, 0x82, 0x3c,
+  0xb7, 0x13, 0xa5, 0x39, 0x95, 0xf3, 0x31, 0xbc, 0xbb, 0xb5, 0x3a, 0xbc, 0xae, 0x8d, 0x01, 0xbc,
+  0xbb, 0x86, 0x90, 0xbc, 0x1f, 0x04, 0x80, 0xbc, 0xc6, 0xb6, 0x74, 0x3c, 0x24, 0x52, 0x99, 0x3b,
+  0x5e, 0x32, 0x8b, 0xbc, 0x87, 0xbc, 0xb7, 0xbc, 0xaa, 0x7d, 0x29, 0x3c, 0x8b, 0x55, 0xdc, 0x3a,
+  0x60, 0xf4, 0x9e, 0xba, 0x37, 0x77, 0x70, 0xbc, 0x47, 0xa9, 0x8e, 0x3c, 0x9f, 0x09, 0xfd, 0xbb,
+  0x16, 0xa9, 0x1d, 0xbc, 0xfc, 0x0d, 0xbb, 0xbb, 0xf1, 0x35, 0xdb, 0x3c, 0x25, 0x98, 0x73, 0xbc,
+  0x7d, 0xe4, 0x2f, 0x3c, 0xe5, 0x43, 0xd2, 0xba, 0x0e, 0xc7, 0x77, 0xbc, 0x35, 0xde, 0x1c, 0xbc,
+  0x8b, 0x44, 0x43, 0xbc, 0x02, 0x3c, 0xb6, 0x3b, 0x31, 0x02, 0xa3, 0x3c, 0x00, 0xbb, 0x01, 0x3b,
+  0x0b, 0xd2, 0xc0, 0x3b, 0x17, 0x41, 0x31, 0x3c, 0xa5, 0x5d, 0x8e, 0xbc, 0x83, 0xb7, 0x3f, 0xbc,
+  0xb3, 0x4a, 0xd5, 0xbb, 0xd3, 0x39, 0xb8, 0x3a, 0x09, 0xb7, 0x1e, 0xbc, 0x47, 0x4a, 0xab, 0xba,
+  0x4e, 0x4e, 0x46, 0x3c, 0x03, 0x4f, 0x8f, 0xba, 0x8e, 0x3c, 0xc8, 0xbb, 0x73, 0x3e, 0xfd, 0xbb,
+  0xf5, 0x08, 0xd2, 0xbb, 0x1c, 0x66, 0x15, 0xbb, 0x80, 0xcf, 0x3b, 0x3c, 0xda, 0xd1, 0x7f, 0xbc,
+  0xb0, 0x1e, 0x5c, 0x3c, 0xe5, 0x76, 0x4f, 0xb9, 0xde, 0x54, 0x90, 0x3b, 0xc5, 0xa6, 0xba, 0xbb,
+  0x5a, 0x0c, 0x3a, 0x3c, 0x14, 0x45, 0xa9, 0x3b, 0x0e, 0xfb, 0x6f, 0x3c, 0xb1, 0x61, 0x98, 0xbb,
+  0x56, 0xd1, 0xca, 0x3c, 0xf0, 0x48, 0x84, 0x3c, 0x9e, 0x0e, 0xbd, 0xbb, 0x4a, 0x47, 0x87, 0x3c,
+  0x3f, 0xad, 0x07, 0x3d, 0x6d, 0x24, 0x28, 0xbc, 0x6c, 0x03, 0x8a, 0x3c, 0x5b, 0x05, 0xbf, 0xbc,
+  0xd0, 0xcc, 0xc5, 0x3c, 0xae, 0x5e, 0xca, 0x3c, 0xf5, 0x2a, 0xd9, 0xbb, 0xb7, 0x9a, 0x52, 0xbb,
+  0x8b, 0x5a, 0xa2, 0x3c, 0x28, 0xa1, 0xab, 0xbc, 0x89, 0xfd, 0x92, 0xbb, 0xf7, 0x1b, 0xb4, 0x3b,
+  0x8e, 0xdd, 0xdb, 0x3c, 0x99, 0x7d, 0xa4, 0x3c, 0x67, 0x62, 0x88, 0x3b, 0xa6, 0x09, 0x4e, 0xbc,
+  0x93, 0x1b, 0x2b, 0x3b, 0x12, 0x5b, 0x17, 0x3a, 0xcd, 0xb5, 0xae, 0x3b, 0xb2, 0x1b, 0x91, 0xba,
+  0x61, 0x84, 0x31, 0x3c, 0xa7, 0xec, 0x1c, 0xbb, 0x3f, 0x8e, 0x6c, 0xb9, 0x5a, 0x03, 0x28, 0xbc,
+  0x5d, 0x28, 0x7d, 0x3b, 0x53, 0xf0, 0xb4, 0xba, 0x71, 0x24, 0xba, 0x3b, 0xde, 0xaa, 0x42, 0x3a,
+  0x82, 0x54, 0x67, 0x3c, 0xa5, 0xe8, 0x2b, 0xbc, 0x51, 0x76, 0x31, 0xbb, 0x5c, 0xd2, 0xae, 0x3b,
+  0x1f, 0xcb, 0x21, 0xbc, 0x24, 0xac, 0x91, 0x3b, 0x8a, 0xfa, 0x94, 0xba, 0x4b, 0xf1, 0x40, 0xba,
+  0xfa, 0xeb, 0xf9, 0x3b, 0x27, 0xc5, 0x7c, 0xbc, 0x02, 0xe6, 0x9a, 0xbb, 0x92, 0xfa, 0x44, 0x3b,
+  0x07, 0xe5, 0xf8, 0xbb, 0xd0, 0x5e, 0x26, 0x3c, 0xac, 0x94, 0xc8, 0xbb, 0xc5, 0xb3, 0x8e, 0x3b,
+  0x42, 0xf8, 0x04, 0x3c, 0xce, 0xcd, 0x5e, 0xbc, 0xe2, 0x08, 0x5d, 0xbb, 0x1a, 0xda, 0x57, 0x3b,
+  0xdc, 0xa0, 0x72, 0xbc, 0xa2, 0xd3, 0x18, 0xbc, 0x4f, 0x97, 0x32, 0x3c, 0x40, 0x8c, 0x21, 0x3b,
+  0xe7, 0xf4, 0xb9, 0x3b, 0xef, 0x95, 0x76, 0xbc, 0xcc, 0xd2, 0x92, 0xbc, 0x31, 0xa5, 0xdc, 0xbb,
+  0x08, 0xcb, 0x83, 0xbb, 0x74, 0x0d, 0x30, 0xbc, 0x55, 0xec, 0x85, 0x3c, 0x79, 0xa4, 0x33, 0xbc,
+  0xff, 0x25, 0x8b, 0x3a, 0xe3, 0xd6, 0x4f, 0xb9, 0x2f, 0x5a, 0x9d, 0xba, 0x3d, 0xf2, 0x42, 0xbc,
+  0xc6, 0x63, 0xd6, 0xbb, 0x8d, 0x5d, 0x6f, 0xbb, 0x6a, 0x80, 0x63, 0xbb, 0x04, 0x83, 0x09, 0xbb,
+  0x28, 0xce, 0x4a, 0xbb, 0xe1, 0xf4, 0x3e, 0xbc, 0xb1, 0x2f, 0x3b, 0xbc, 0xd0, 0xa8, 0x22, 0xbc,
+  0xa6, 0x50, 0x34, 0xbc, 0xa4, 0x5a, 0xd0, 0x3b, 0xd3, 0x7e, 0x09, 0x3b, 0x35, 0x10, 0x85, 0xbb,
+  0x55, 0x41, 0x7f, 0xbb, 0x5e, 0xea, 0x8d, 0xbb, 0x50, 0xba, 0x6b, 0xbb, 0xfa, 0x62, 0xc7, 0x3b,
+  0x61, 0xac, 0xd6, 0x3a, 0x00, 0x75, 0xbf, 0x3b, 0xf5, 0x82, 0x11, 0x3c, 0xae, 0xef, 0xde, 0xbb,
+  0x96, 0xd0, 0xed, 0x3b, 0x7f, 0xf8, 0x50, 0xbb, 0x74, 0xf1, 0x4e, 0xbc, 0x29, 0xb3, 0xd5, 0xba,
+  0x2b, 0x63, 0xe5, 0x3b, 0xbe, 0x11, 0x44, 0x3c, 0xbc, 0x58, 0x75, 0x3b, 0xa6, 0xf6, 0x86, 0xbb,
+  0xdc, 0x34, 0x34, 0xbb, 0x46, 0xe9, 0x19, 0x3a, 0x88, 0x91, 0xcc, 0xbb, 0x50, 0x84, 0x10, 0x3c,
+  0x82, 0x58, 0x68, 0x3c, 0x97, 0x9e, 0x29, 0x3b, 0x6c, 0x2e, 0x96, 0x3b, 0xda, 0xbf, 0x85, 0x3b,
+  0x94, 0x37, 0xce, 0xba, 0x96, 0xb6, 0xa4, 0x3b, 0xed, 0x51, 0x51, 0x3b, 0x5c, 0x77, 0x81, 0x3b,
+  0x31, 0x0d, 0x9b, 0x3a, 0x33, 0x81, 0x05, 0xbb, 0x7d, 0xed, 0xa5, 0xbc, 0x98, 0xc3, 0x3d, 0xbc,
+  0xbe, 0xb9, 0x1a, 0x3c, 0x7f, 0x18, 0xe3, 0x39, 0xc3, 0x8f, 0x12, 0x3c, 0x5f, 0xf4, 0x43, 0x3c,
+  0x36, 0x17, 0x06, 0xbc, 0x09, 0x73, 0x95, 0xbc, 0xa1, 0xbc, 0xdc, 0x3b, 0x0a, 0xf9, 0xa2, 0x3b,
+  0x44, 0x83, 0x4c, 0x3b, 0x6f, 0x76, 0x06, 0xbc, 0x17, 0x87, 0xcb, 0x3c, 0x57, 0x62, 0x7d, 0xbc,
+  0x83, 0x9a, 0x14, 0x3b, 0xf6, 0x08, 0x6a, 0x3c, 0x22, 0x37, 0x19, 0x3d, 0x4f, 0x0a, 0x37, 0xbc,
+  0x1b, 0x7b, 0x42, 0x3c, 0x05, 0xdf, 0x16, 0xba, 0xc8, 0x0a, 0x70, 0xbc, 0x0f, 0x0e, 0xf2, 0x3a,
+  0xfb, 0xa1, 0x0f, 0xbb, 0xfe, 0x08, 0xde, 0x3b, 0x93, 0x2d, 0x09, 0x3c, 0x87, 0x37, 0x0d, 0x3b,
+  0xcb, 0x58, 0x76, 0x3c, 0x31, 0x6a, 0x26, 0x3c, 0x42, 0x46, 0xab, 0xbc, 0xa5, 0x1b, 0x1a, 0xbc,
+  0xc6, 0x53, 0x4d, 0xbb, 0x5f, 0x68, 0x43, 0xbc, 0xfa, 0x55, 0x5c, 0xbb, 0x83, 0x75, 0x04, 0xbb,
+  0xc3, 0x2c, 0x90, 0x3c, 0x62, 0x26, 0x26, 0xba, 0xde, 0xca, 0x40, 0x3b, 0x9c, 0xdd, 0xdd, 0xbb,
+  0xde, 0x9c, 0x8e, 0x39, 0xd9, 0x10, 0xa4, 0xbb, 0x22, 0x65, 0xa6, 0x3c, 0xfa, 0x1e, 0x35, 0x3c,
+  0xf8, 0x55, 0x8c, 0x3c, 0x6d, 0xb7, 0x03, 0x3c, 0xc6, 0xfe, 0xc8, 0xbb, 0x2c, 0x62, 0x4c, 0x3c,
+  0x48, 0xd0, 0x76, 0x3c, 0x87, 0x4b, 0x1c, 0xbb, 0xc3, 0x7b, 0xc4, 0x3c, 0x98, 0x59, 0x28, 0xbc,
+  0x1b, 0x43, 0xc9, 0x3c, 0xf4, 0xb4, 0xb9, 0x3c, 0xdb, 0xc2, 0x7c, 0x38, 0x70, 0x58, 0x75, 0x3b,
+  0xe2, 0xc6, 0xab, 0x3c, 0xe4, 0x2e, 0xf9, 0xbb, 0xa9, 0x59, 0x94, 0x3c, 0xde, 0x35, 0xbe, 0xbb,
+  0xda, 0xe7, 0x92, 0x3c, 0x24, 0xa9, 0xd4, 0x3c, 0x8f, 0x16, 0x98, 0xbc, 0xee, 0x51, 0xe9, 0xbb,
+  0x5b, 0xb6, 0x49, 0x3c, 0x03, 0xff, 0xa6, 0xbc, 0xd3, 0xf2, 0x1a, 0xbc, 0x0c, 0xa3, 0x58, 0xbb,
+  0x7f, 0xc4, 0xc4, 0x3c, 0x10, 0x8d, 0x98, 0x3c, 0x59, 0xd1, 0xfd, 0xba, 0xea, 0xb2, 0xbc, 0xbb,
+  0xbb, 0xf9, 0xfa, 0xbb, 0x7d, 0xea, 0x5f, 0xbc, 0xa1, 0x3a, 0x3c, 0xbb, 0x08, 0x4e, 0xc2, 0x3b,
+  0xa7, 0x21, 0x30, 0x3c, 0x1a, 0x97, 0x36, 0x3c, 0x2f, 0x91, 0x32, 0xbb, 0x12, 0x44, 0x5a, 0xbb,
+  0x7e, 0xb4, 0x55, 0xbc, 0x51, 0xab, 0x75, 0x3c, 0x48, 0x2f, 0x75, 0x3c, 0x3c, 0x41, 0x49, 0xbb,
+  0x1a, 0xf0, 0x04, 0xba, 0x76, 0x27, 0xbe, 0xba, 0x0a, 0xf0, 0xc9, 0x3b, 0x6d, 0x75, 0x62, 0x3a,
+  0x9e, 0x0e, 0x38, 0xbc, 0x7e, 0xd0, 0xde, 0x3b, 0x93, 0x28, 0xf7, 0xbb, 0xf8, 0xbc, 0x0d, 0x3c,
+  0xf8, 0xf0, 0x8d, 0x3b, 0xc6, 0x97, 0x95, 0xbc, 0x9b, 0xd1, 0x94, 0x3a, 0xe5, 0x4c, 0x2d, 0xbc,
+  0xde, 0x44, 0x51, 0xbc, 0x22, 0x9f, 0x9a, 0x3b, 0xe0, 0x19, 0xfd, 0xb9, 0x56, 0x97, 0xcc, 0x3a,
+  0x18, 0x1a, 0x18, 0x3c, 0xab, 0x9f, 0xf4, 0xbb, 0x69, 0x00, 0x9b, 0x3b, 0x97, 0x2b, 0x5c, 0xbb,
+  0x2a, 0x7e, 0x33, 0xbc, 0xcf, 0x52, 0x0e, 0xba, 0x19, 0x95, 0xf4, 0x3b, 0x23, 0x1d, 0xfb, 0xba,
+  0x0e, 0x02, 0x48, 0x3c, 0xd5, 0x18, 0xce, 0xbb, 0xc3, 0x04, 0x86, 0xbb, 0x2b, 0x2c, 0xed, 0x3b,
+  0x66, 0x64, 0xb5, 0xbb, 0x88, 0x7a, 0x34, 0xbb, 0xbe, 0x08, 0xb7, 0xbb, 0x75, 0x65, 0x2a, 0x3b,
+  0x30, 0x12, 0xfa, 0x3b, 0xfe, 0x52, 0xa2, 0x3b, 0x1f, 0x5f, 0x88, 0xbc, 0x20, 0x72, 0x8f, 0x3b,
+  0xb5, 0x02, 0x92, 0xbb, 0x42, 0x63, 0x00, 0xbc, 0x6f, 0x36, 0x56, 0xbc, 0xc9, 0x12, 0x5a, 0x3b,
+  0x7d, 0xda, 0x69, 0x3b, 0x4c, 0x20, 0x48, 0xbb, 0x3b, 0x8b, 0x3e, 0x3a, 0x9d, 0xc8, 0xa0, 0xbc,
+  0x4c, 0xd8, 0x79, 0xbb, 0x37, 0x7a, 0x8e, 0xbb, 0xb9, 0x18, 0x2b, 0x3a, 0xa0, 0x28, 0x2c, 0xbb,
+  0x1c, 0x4d, 0xd9, 0x3b, 0xcd, 0x29, 0x6f, 0xbb, 0x6d, 0x38, 0x5b, 0x3b, 0x7c, 0xbf, 0xe9, 0x3b,
+  0xfd, 0xb7, 0x55, 0xba, 0xbe, 0x28, 0xc8, 0x3a, 0xfb, 0xdd, 0x09, 0x3c, 0x8e, 0x6b, 0x16, 0x3b,
+  0x1d, 0xba, 0x93, 0x3b, 0x42, 0xe7, 0x16, 0x3c, 0x45, 0x7f, 0x83, 0xbb, 0xeb, 0x46, 0x8d, 0xbc,
+  0x79, 0x3a, 0xc2, 0xba, 0xfd, 0xdc, 0x98, 0x3c, 0x21, 0x40, 0xea, 0x3b, 0xbe, 0xf3, 0x1d, 0xbc,
+  0x7b, 0x8a, 0x8d, 0xbb, 0x85, 0x07, 0x69, 0x3b, 0x57, 0xc2, 0xe1, 0x38, 0x26, 0xc8, 0xe3, 0xba,
+  0x4c, 0xf5, 0x0c, 0x3c, 0xca, 0x0c, 0x84, 0xbb, 0x66, 0x57, 0x10, 0xbb, 0x32, 0xe9, 0x2e, 0xbc,
+  0xc7, 0xe3, 0x5e, 0xbc, 0xb4, 0x57, 0x32, 0xbc, 0x0b, 0x30, 0x34, 0xbc, 0x10, 0x1b, 0x7b, 0xbc,
+  0xfd, 0x41, 0xe1, 0xb9, 0x3a, 0x1b, 0x8f, 0xbc, 0x3c, 0x85, 0xa5, 0xbc, 0x5d, 0x91, 0x23, 0xbc,
+  0x84, 0x89, 0xdb, 0xbb, 0x0d, 0x42, 0x8a, 0xbb, 0xfb, 0xa7, 0xd0, 0x3b, 0xa6, 0xb3, 0x53, 0x3c,
+  0x31, 0xef, 0x30, 0xbc, 0x79, 0x89, 0xea, 0xbc, 0xca, 0xfd, 0x31, 0x3b, 0x31, 0x7a, 0x4e, 0x39,
+  0x88, 0x56, 0xb6, 0xba, 0x3a, 0x84, 0xe5, 0x3a, 0x60, 0x9e, 0x08, 0x3d, 0x9e, 0x8b, 0x63, 0xbb,
+  0x53, 0xbf, 0x36, 0xbc, 0x90, 0x91, 0x11, 0x3c, 0xc9, 0xf1, 0xae, 0x3c, 0x0c, 0xdc, 0xc2, 0x3b,
+  0x7b, 0xf1, 0x75, 0x3c, 0x84, 0x70, 0x79, 0xbb, 0xa2, 0xaa, 0xb0, 0xbc, 0x64, 0xa2, 0xbc, 0x3b,
+  0xf1, 0xa6, 0x1e, 0x3c, 0xa6, 0x66, 0x03, 0x3c, 0xcb, 0x3e, 0x24, 0x3b, 0xe5, 0x00, 0x51, 0xbc,
+  0xea, 0xe7, 0x97, 0x3c, 0x53, 0x84, 0x80, 0x3b, 0x0f, 0x3c, 0xe7, 0xbc, 0x53, 0x59, 0x07, 0xbc,
+  0xac, 0x95, 0x80, 0xbc, 0x67, 0x8f, 0x8a, 0xbc, 0xc6, 0x52, 0x0b, 0x3b, 0xec, 0xf1, 0x74, 0xbb,
+  0x8c, 0x03, 0x09, 0x3c, 0x2e, 0x72, 0xf8, 0x3b, 0xe2, 0xf4, 0xf7, 0xbb, 0xdb, 0x88, 0x45, 0xbc,
+  0x4b, 0xbf, 0x19, 0xbb, 0x4c, 0x47, 0xa7, 0x3a, 0x35, 0x7d, 0xe9, 0x3c, 0x40, 0xa9, 0x46, 0xbc,
+  0x8f, 0xb0, 0x1b, 0x3c, 0xac, 0x13, 0xba, 0x3b, 0xb8, 0x13, 0xb9, 0xbb, 0x6c, 0x5e, 0x9a, 0xbb,
+  0x64, 0xf6, 0x56, 0x3c, 0x9a, 0xd1, 0x96, 0x3b, 0xd4, 0xc4, 0x87, 0x3c, 0xda, 0xe9, 0xde, 0xbb,
+  0x6f, 0x6f, 0xaf, 0x3c, 0x8e, 0x1f, 0x4c, 0x3c, 0xf7, 0xf5, 0x80, 0x3b, 0x9a, 0xd4, 0x13, 0xba,
+  0x58, 0xa8, 0xc5, 0x3c, 0xec, 0xc0, 0x43, 0xbc, 0x36, 0xa8, 0x49, 0x3c, 0xe6, 0x7a, 0x27, 0x3b,
+  0x99, 0xf2, 0xa8, 0x3c, 0x93, 0x2f, 0xcc, 0x3c, 0xd7, 0x4d, 0xe4, 0xbb, 0x19, 0x9b, 0x9b, 0x3b,
+  0x6e, 0x0d, 0xd3, 0x38, 0x49, 0x0d, 0x3c, 0xbc, 0xe8, 0xd6, 0x7b, 0x3a, 0x84, 0xd2, 0x80, 0xbc,
+  0xd2, 0x1b, 0xad, 0x3c, 0xbb, 0x16, 0xa3, 0x3c, 0x16, 0x4d, 0xc5, 0x3a, 0xa4, 0x6f, 0x48, 0xbc,
+  0xe8, 0x6e, 0xf3, 0xba, 0x55, 0x2e, 0x05, 0xbc, 0x14, 0x25, 0x07, 0xbb, 0x8a, 0xec, 0x5b, 0xbc,
+  0xb8, 0xf8, 0xbf, 0x3a, 0x49, 0x1c, 0xc1, 0x39, 0x48, 0xa2, 0xd0, 0x3a, 0x1a, 0xa7, 0x0e, 0xbc,
+  0x63, 0x35, 0x34, 0xbc, 0xff, 0xb3, 0x25, 0x3c, 0x02, 0x44, 0x23, 0x3b, 0xba, 0x10, 0xa0, 0x3a,
+  0x2e, 0x3f, 0x14, 0x3c, 0x1f, 0xd3, 0x05, 0x3c, 0x82, 0x4d, 0xe3, 0x3b, 0xf5, 0x08, 0x0a, 0xbc,
+  0xc9, 0x7f, 0xb0, 0xbb, 0x67, 0xcf, 0x83, 0x3c, 0xaf, 0x1f, 0x55, 0x3c, 0x5d, 0x87, 0xdc, 0x3b,
+  0xd7, 0xf8, 0x9e, 0xba, 0xb1, 0x22, 0xc6, 0xbb, 0x5b, 0xb9, 0x9e, 0x3b, 0xf6, 0xa5, 0x82, 0x3a,
+  0x49, 0xd1, 0x88, 0xbc, 0x92, 0x50, 0x7b, 0x3c, 0x72, 0x2c, 0x23, 0xbc, 0x0a, 0x01, 0x46, 0x3b,
+  0xad, 0x03, 0x85, 0xbb, 0x7a, 0x99, 0x6b, 0xbc, 0xec, 0x35, 0x3c, 0x3b, 0x9f, 0x28, 0xd6, 0x3b,
+  0x34, 0xc3, 0x84, 0xbc, 0xd3, 0x95, 0xd3, 0x3b, 0xe0, 0x30, 0x67, 0xbb, 0xc3, 0xb5, 0x2d, 0x3c,
+  0x9d, 0x3e, 0x5d, 0x3c, 0x0d, 0x65, 0xb9, 0x3b, 0xe3, 0xbc, 0x7d, 0xbc, 0x19, 0xb8, 0xf8, 0xbb,
+  0x05, 0x55, 0x20, 0xbc, 0x06, 0x0f, 0xb6, 0x3b, 0xe9, 0x9b, 0xf1, 0x3b, 0x9e, 0xdf, 0xd4, 0xbb,
+  0x1c, 0x04, 0x98, 0x3c, 0xfb, 0x76, 0x66, 0x3c, 0x3c, 0xc1, 0x83, 0xbc, 0x6d, 0x90, 0x4b, 0xbc,
+  0x58, 0x3a, 0x00, 0xbc, 0xe6, 0xb8, 0x4f, 0xbb, 0xec, 0x27, 0xfa, 0xbb, 0xbe, 0x8b, 0x93, 0x3a,
+  0x4f, 0x1d, 0xa2, 0x3b, 0x94, 0x9d, 0x58, 0x3b, 0xf0, 0x0f, 0x47, 0x3b, 0xf7, 0xec, 0x4d, 0xbb,
+  0x7e, 0xd9, 0xef, 0x3b, 0x33, 0x10, 0x4b, 0xbb, 0x76, 0x16, 0xf6, 0xbb, 0x2a, 0xfe, 0x09, 0xbc,
+  0x34, 0x95, 0xee, 0xbb, 0x09, 0x7f, 0x89, 0xbb, 0x05, 0xd8, 0x8f, 0xb9, 0x50, 0x48, 0x67, 0x3a,
+  0x1b, 0x82, 0xac, 0x3b, 0x44, 0xa3, 0xcc, 0x3b, 0xb6, 0x54, 0x50, 0x3c, 0x43, 0xea, 0x0f, 0xbc,
+  0xda, 0xe5, 0xa2, 0xbb, 0x44, 0x7c, 0x1a, 0x3b, 0x28, 0xca, 0x2a, 0xba, 0x9f, 0xbf, 0x5a, 0x3c,
+  0x02, 0x01, 0x34, 0x3c, 0x2f, 0xbb, 0xea, 0x3a, 0x9d, 0x37, 0x18, 0x3b, 0xfe, 0xa5, 0x32, 0x3c,
+  0xff, 0x02, 0x29, 0x38, 0x36, 0x69, 0x83, 0xb9, 0x59, 0x53, 0xc9, 0x3b, 0x45, 0xee, 0xc4, 0xbb,
+  0x17, 0x7f, 0x8a, 0x3c, 0xc2, 0xe9, 0x00, 0x3c, 0xf9, 0xe0, 0xac, 0xba, 0x63, 0x4c, 0x10, 0x3b,
+  0x6a, 0x91, 0x0d, 0xbb, 0x44, 0x50, 0x2d, 0xbc, 0x10, 0x87, 0xae, 0x3a, 0x05, 0xb0, 0x00, 0x3c,
+  0xf0, 0xb6, 0x4f, 0x3b, 0x5d, 0x24, 0xa1, 0xbc, 0x6b, 0xa5, 0x8a, 0xbb, 0x9a, 0x8d, 0x21, 0xba,
+  0x68, 0xc1, 0xd1, 0xbb, 0x7b, 0x78, 0xea, 0xbb, 0x4a, 0x18, 0x37, 0x3c, 0x4d, 0xfb, 0x14, 0xbc,
+  0xd5, 0xfd, 0xae, 0xbc, 0xca, 0x49, 0xce, 0xbc, 0x91, 0xdf, 0x1a, 0x3c, 0x98, 0x1c, 0x5a, 0x3c,
+  0xb5, 0xbc, 0xb3, 0xbb, 0x9c, 0xd9, 0xb5, 0x3a, 0x31, 0x18, 0x0b, 0x3d, 0x6e, 0xb9, 0xa3, 0xbb,
+  0xf7, 0x12, 0x87, 0xbb, 0x18, 0x00, 0xe3, 0xbb, 0x51, 0xd1, 0xf1, 0x3c, 0x0b, 0x45, 0xdd, 0xbb,
+  0x9a, 0x0d, 0x87, 0x3c, 0xcb, 0x85, 0xbb, 0xbb, 0x2f, 0xc3, 0x13, 0xbc, 0x14, 0x77, 0xfb, 0xba,
+  0xde, 0x26, 0x10, 0xbc, 0x20, 0xca, 0xae, 0x3b, 0x0e, 0xde, 0xbf, 0xbb, 0x7b, 0x65, 0xeb, 0xbb,
+  0x1b, 0xe6, 0x91, 0x3c, 0xe7, 0xa6, 0xf3, 0x3b, 0xcd, 0x29, 0xbc, 0xbc, 0xc6, 0x6a, 0xa2, 0xbb,
+  0xeb, 0x4f, 0xed, 0x38, 0xea, 0x28, 0x09, 0xbc, 0x64, 0xf0, 0xf9, 0x3b, 0x29, 0x54, 0xe8, 0xba,
+  0xd0, 0x72, 0x24, 0x3c, 0xf0, 0x80, 0x54, 0xbc, 0xa8, 0x0f, 0x92, 0xbc, 0xfb, 0x24, 0xd3, 0xbb,
+  0x59, 0xdb, 0x2c, 0xbc, 0x87, 0x0d, 0xfb, 0x3b, 0xd4, 0x2c, 0x85, 0x3c, 0x5e, 0x8f, 0xdc, 0xbb,
+  0x88, 0x07, 0xa8, 0x3c, 0x29, 0x29, 0x07, 0x3c, 0x94, 0xb7, 0x59, 0xbb, 0xf8, 0x20, 0x9a, 0x3b,
+  0x50, 0xfa, 0xf4, 0xba, 0xba, 0xfc, 0xaa, 0xbb, 0xbe, 0xdf, 0x22, 0x3d, 0x2e, 0x0b, 0x2e, 0x3c,
+  0x4f, 0x96, 0x92, 0x3c, 0xcd, 0x87, 0x03, 0x3d, 0xc2, 0x9f, 0x79, 0xbc, 0xdf, 0xd7, 0xd5, 0x3b,
+  0x44, 0x6f, 0x16, 0x3c, 0xc7, 0x32, 0x02, 0xbb, 0xac, 0xed, 0xaf, 0x3c, 0x11, 0x13, 0x6f, 0xbc,
+  0x90, 0x99, 0x27, 0x3d, 0x83, 0xee, 0x45, 0x3d, 0xf6, 0x9f, 0xb7, 0xbb, 0x4e, 0x3e, 0x7a, 0x3b,
+  0x80, 0xa5, 0xa9, 0x39, 0xe4, 0x21, 0x82, 0xbc, 0xa9, 0x88, 0x96, 0x3b, 0xa0, 0xc2, 0x25, 0x39,
+  0xfa, 0x97, 0x0f, 0x3d, 0x2e, 0x8b, 0x58, 0x3c, 0x44, 0xea, 0x94, 0xba, 0xeb, 0x90, 0x81, 0xbc,
+  0xf4, 0x85, 0x02, 0xbc, 0x42, 0x8b, 0xdd, 0xbb, 0x1d, 0xe1, 0x67, 0xbb, 0x7f, 0x1e, 0x98, 0xbb,
+  0x9d, 0x44, 0xc7, 0xba, 0x7e, 0xa3, 0xce, 0xb9, 0xfe, 0xb4, 0xd0, 0xbb, 0x7f, 0x0a, 0x8f, 0x3a,
+  0x95, 0x34, 0x96, 0xbb, 0x60, 0x46, 0x1b, 0x3c, 0x41, 0xae, 0xac, 0x3b, 0x50, 0x7a, 0x39, 0xbc,
+  0xcf, 0xf2, 0x8a, 0x3b, 0x84, 0x5c, 0x0a, 0xbb, 0x62, 0xfb, 0x01, 0xbb, 0xf7, 0x73, 0x67, 0xbc,
+  0x5e, 0x8d, 0x53, 0xbc, 0x2d, 0xbd, 0x04, 0x3c, 0xd2, 0xfc, 0xb4, 0x3a, 0x69, 0xc6, 0x8a, 0x3b,
+  0x92, 0x62, 0x25, 0xbb, 0x84, 0x61, 0x2d, 0x3b, 0xfa, 0xb6, 0xfa, 0x3b, 0x73, 0xf5, 0x48, 0x3c,
+  0x69, 0x38, 0xc7, 0xbb, 0x5e, 0xfe, 0xc4, 0x3b, 0xd3, 0x55, 0x40, 0xbb, 0xdf, 0x42, 0x9a, 0x3b,
+  0x4c, 0x73, 0xaa, 0xbc, 0x06, 0x0b, 0xae, 0xbb, 0xa5, 0xd0, 0x4c, 0x3c, 0xce, 0x04, 0x08, 0x3c,
+  0xd9, 0xf5, 0xe0, 0xbb, 0x60, 0xfe, 0x00, 0xbb, 0x72, 0x62, 0x76, 0x3c, 0xf3, 0xe4, 0x77, 0xba,
+  0xdd, 0xaa, 0xda, 0x3b, 0x44, 0x10, 0x5e, 0xbc, 0x04, 0x73, 0x07, 0xbc, 0x7e, 0x3e, 0x9f, 0xbc,
+  0x16, 0x26, 0x0c, 0xbc, 0x33, 0x77, 0x37, 0x3b, 0x2a, 0xa8, 0x6e, 0x3c, 0x25, 0x65, 0x0c, 0x3b,
+  0x33, 0xe7, 0x10, 0x3c, 0x28, 0xde, 0x9d, 0x3c, 0xb2, 0x20, 0x8b, 0xbb, 0x98, 0x47, 0xdd, 0x3b,
+  0x81, 0xf0, 0x2f, 0x3b, 0x51, 0xbe, 0x7e, 0xbb, 0xdf, 0xb4, 0x0d, 0xbc, 0x39, 0x38, 0xf5, 0xbb,
+  0x92, 0x04, 0x4a, 0x3c, 0x13, 0xfd, 0x35, 0x3a, 0x54, 0x8a, 0x86, 0xbb, 0x6c, 0xb6, 0xa6, 0xba,
+  0xef, 0xf9, 0x9f, 0x3a, 0xff, 0xef, 0x05, 0x3c, 0x90, 0x56, 0x43, 0x3c, 0xa7, 0x68, 0xfd, 0x3b,
+  0xef, 0x5f, 0xe8, 0x3a, 0x85, 0x50, 0x27, 0xbb, 0xec, 0xfe, 0x9e, 0xbc, 0xb0, 0x79, 0x48, 0xbb,
+  0x9d, 0xbb, 0x2c, 0x3c, 0xc2, 0xcd, 0x48, 0x3b, 0x1f, 0x02, 0x4f, 0x3b, 0xa0, 0xf9, 0x8a, 0x3c,
+  0x97, 0xe7, 0x32, 0xbb, 0x8c, 0x54, 0x1f, 0x3c, 0x6c, 0x1e, 0x06, 0x3c, 0xb0, 0x9b, 0xef, 0xbb,
+  0x63, 0xe7, 0x0f, 0x3c, 0xe8, 0x84, 0x00, 0x3c, 0xe9, 0x55, 0x08, 0x3b, 0x8c, 0x01, 0x76, 0xbc,
+  0x55, 0x0b, 0x0c, 0xbc, 0xf9, 0x8c, 0x8d, 0xbb, 0x21, 0x9d, 0x81, 0x3c, 0xa0, 0xa8, 0xdd, 0x3b,
+  0x19, 0x92, 0x96, 0x3b, 0xff, 0xe4, 0x97, 0x3b, 0x8b, 0xc5, 0x7b, 0xbb, 0x69, 0x1f, 0x68, 0x3b,
+  0x02, 0x1f, 0x9f, 0x3b, 0xf5, 0xfb, 0x09, 0xbc, 0xd1, 0xc6, 0xb8, 0x3a, 0xb2, 0x42, 0x75, 0x3c,
+  0x17, 0x18, 0x40, 0xbb, 0x78, 0x6e, 0xe9, 0xbc, 0x46, 0x56, 0x1d, 0xbc, 0xad, 0x8e, 0x0b, 0x3c,
+  0x70, 0x58, 0x00, 0x3a, 0x0c, 0x02, 0x6c, 0x3c, 0x2c, 0x3a, 0xd4, 0xba, 0x42, 0x83, 0xef, 0xbb,
+  0x42, 0xf8, 0x3e, 0xbc, 0x6e, 0xe8, 0xcb, 0xbc, 0xe1, 0x2e, 0xc0, 0xbb, 0xe6, 0x0d, 0x38, 0x3c,
+  0xbb, 0x04, 0xff, 0xb9, 0xa4, 0xb8, 0x87, 0xbc, 0xc1, 0xaa, 0x06, 0x3d, 0x95, 0x5d, 0xfb, 0x3b,
+  0xc2, 0xe3, 0x0a, 0xbc, 0x42, 0xe2, 0x39, 0xbb, 0x2f, 0xbd, 0xed, 0x3c, 0xe0, 0x87, 0x43, 0xbc,
+  0x9b, 0x00, 0x99, 0x3c, 0xe7, 0xea, 0x88, 0xbc, 0x70, 0x9a, 0xa1, 0xbc, 0xb8, 0xd5, 0x56, 0xbb,
+  0xcb, 0xb9, 0xb7, 0xbb, 0xdc, 0x87, 0x98, 0xbb, 0x89, 0x74, 0x2e, 0x3b, 0xfe, 0x15, 0x83, 0xbb,
+  0x45, 0x80, 0x6d, 0x3c, 0xfe, 0xa0, 0x14, 0x3c, 0x11, 0xb3, 0x46, 0xbc, 0x07, 0x22, 0x6c, 0xbc,
+  0x5b, 0x7d, 0xf1, 0xbb, 0xb4, 0xee, 0x62, 0xbc, 0xb0, 0x23, 0xc7, 0xbb, 0xb6, 0x6f, 0x93, 0xbb,
+  0xf1, 0x9b, 0x3b, 0x3c, 0x91, 0x44, 0x0d, 0x3c, 0x22, 0x19, 0x5d, 0xbc, 0x15, 0xeb, 0x96, 0x3b,
+  0x3a, 0x52, 0x8f, 0xbc, 0x25, 0x40, 0xda, 0xb9, 0x59, 0x60, 0xc3, 0xb9, 0x84, 0x15, 0x72, 0xba,
+  0xae, 0x2c, 0x77, 0x3c, 0x52, 0x43, 0x8b, 0x3b, 0xaf, 0xa8, 0xbc, 0x38, 0x67, 0x50, 0x91, 0xbb,
+  0xf4, 0x8e, 0x87, 0x3c, 0x12, 0x1f, 0x99, 0xbb, 0x66, 0x8a, 0xb0, 0x3c, 0xdc, 0xe0, 0x1a, 0x3c,
+  0xce, 0x92, 0x96, 0x3c, 0xaf, 0xfd, 0x9a, 0x3c, 0xe5, 0x03, 0x51, 0xbc, 0x12, 0x41, 0xdb, 0xb9,
+  0x57, 0xb8, 0xec, 0x3b, 0x8c, 0x74, 0x60, 0xbc, 0x1e, 0x0a, 0x61, 0x3c, 0xe4, 0x7d, 0x39, 0xbc,
+  0xfc, 0x53, 0x29, 0x3d, 0xf5, 0xcc, 0x03, 0x3d, 0x35, 0xf5, 0x45, 0xbc, 0xbd, 0xe7, 0x20, 0xbb,
+  0x0c, 0x2f, 0x5e, 0xbb, 0x71, 0xa7, 0x4d, 0xbc, 0xa0, 0xcc, 0x35, 0xbc, 0x75, 0x02, 0x6a, 0xbc,
+  0xa6, 0x08, 0x47, 0x3c, 0xbc, 0xb2, 0x43, 0x3c, 0x42, 0x40, 0x80, 0x3b, 0xc5, 0x18, 0x2e, 0xbb,
+  0x61, 0x4c, 0xc8, 0xbb, 0xe1, 0x65, 0x56, 0xbc, 0xae, 0xb7, 0x8a, 0x3c, 0x9d, 0x0f, 0x5e, 0x3b,
+  0xa2, 0x37, 0xe5, 0x3b, 0x47, 0x87, 0x81, 0xbb, 0x48, 0x57, 0x7d, 0xbb, 0xd1, 0x8c, 0xc7, 0xbb,
+  0xba, 0x20, 0x0b, 0xbb, 0xa6, 0x9f, 0x06, 0x3c, 0xd6, 0xcc, 0xa2, 0x3c, 0x72, 0x3d, 0x23, 0x3b,
+  0x56, 0x08, 0xc0, 0xbb, 0x2e, 0xa7, 0xf0, 0xbb, 0x2a, 0xce, 0x3e, 0xbb, 0x28, 0xe9, 0x15, 0xbb,
+  0x20, 0x8b, 0xeb, 0xbb, 0x60, 0x22, 0x6d, 0x3c, 0x7a, 0xdb, 0x16, 0x3c, 0x7d, 0x9e, 0xe7, 0x3b,
+  0x6b, 0x89, 0x5e, 0xbb, 0x61, 0xa8, 0xb1, 0xbb, 0xca, 0xd7, 0x3b, 0xbb, 0xe1, 0x60, 0x90, 0x3b,
+  0xfc, 0xc3, 0x5a, 0xbb, 0xb7, 0x52, 0xc0, 0x3a, 0x02, 0x28, 0xf6, 0xbb, 0xf9, 0xc1, 0xfb, 0xbb,
+  0xfb, 0xc0, 0x40, 0xbc, 0x19, 0x34, 0x20, 0xbc, 0xc3, 0x27, 0xef, 0xbb, 0x5f, 0x7a, 0xc0, 0x3b,
+  0x80, 0x46, 0x4e, 0xbc, 0x7b, 0xee, 0x0e, 0xbc, 0xf1, 0xc4, 0xa3, 0xbb, 0xf4, 0xc2, 0x7c, 0x3c,
+  0xec, 0x9d, 0xe4, 0x3b, 0xbc, 0x19, 0x35, 0xbc, 0x35, 0x04, 0x40, 0x39, 0x00, 0xea, 0xba, 0xbb,
+  0xfd, 0x4c, 0x8e, 0xba, 0xe2, 0xc4, 0xf5, 0xbb, 0x90, 0x09, 0x14, 0x3c, 0x94, 0x29, 0xa0, 0x3b,
+  0x29, 0x45, 0x31, 0x3c, 0x9f, 0x51, 0x18, 0x3c, 0x7c, 0xb7, 0x09, 0xbc, 0xe2, 0xf2, 0x17, 0x3c,
+  0xb0, 0x2b, 0x1b, 0xbb, 0xf4, 0xec, 0xf8, 0xb9, 0xf6, 0x45, 0x7f, 0xbb, 0xe2, 0x48, 0xc7, 0xba,
+  0x0f, 0x83, 0xc3, 0xbb, 0x75, 0xcd, 0x67, 0xbc, 0x58, 0x86, 0x3e, 0xbc, 0x3a, 0xbc, 0x45, 0x3b,
+  0x3f, 0xbc, 0xf4, 0xba, 0x33, 0xad, 0x1b, 0x3c, 0x5d, 0xf3, 0xab, 0x3a, 0xe2, 0xd6, 0x34, 0x3c,
+  0xfc, 0xf6, 0xde, 0xb8, 0x80, 0x97, 0xa1, 0x3a, 0x8c, 0xe9, 0x4c, 0xbc, 0x27, 0x92, 0xc2, 0xba,
+  0xe6, 0x30, 0xd7, 0xbb, 0x3d, 0x1a, 0x0d, 0x3c, 0xa3, 0xb0, 0x0d, 0x3c, 0x48, 0x40, 0x77, 0x3c,
+  0x55, 0x31, 0x22, 0xbc, 0x77, 0x48, 0xf9, 0x3b, 0xc1, 0x62, 0x95, 0x3a, 0x5e, 0x88, 0x87, 0xbb,
+  0xa3, 0x1f, 0x14, 0x3c, 0xcf, 0x62, 0xd1, 0x3b, 0xae, 0xe0, 0x05, 0x3c, 0x03, 0x8a, 0xd6, 0xba,
+  0x17, 0x46, 0x85, 0xbc, 0x9e, 0xfa, 0xa6, 0xbb, 0x65, 0x57, 0x63, 0x3b, 0xc6, 0xc0, 0xd1, 0xbb,
+  0xec, 0x2e, 0x01, 0x3b, 0xe2, 0x0b, 0x35, 0xba, 0xc4, 0x4f, 0x3c, 0x3b, 0xe6, 0x58, 0x1f, 0x3b,
+  0xb2, 0x2a, 0x24, 0xbb, 0x73, 0xad, 0x29, 0xbc, 0xf2, 0xda, 0xfe, 0xbb, 0x5b, 0x6a, 0xa4, 0x3b,
+  0x6b, 0x1a, 0xba, 0xb8, 0xca, 0x46, 0x12, 0xbd, 0x10, 0x79, 0x38, 0xbc, 0x67, 0xa7, 0x4a, 0x3c,
+  0x93, 0xe1, 0xb4, 0x3a, 0x47, 0xf0, 0x8a, 0xba, 0x51, 0x4d, 0xcd, 0x3b, 0xd9, 0x71, 0x4d, 0x3c,
+  0x7e, 0x65, 0x46, 0xbc, 0x27, 0x27, 0xfb, 0xbc, 0x2b, 0x4e, 0xa5, 0xbc, 0x09, 0x91, 0x8e, 0xbc,
+  0x99, 0xb2, 0x9b, 0xbb, 0xd8, 0xaf, 0x7f, 0xbb, 0x51, 0x78, 0xdf, 0x3c, 0xe5, 0x43, 0xac, 0xbb,
+  0x46, 0x28, 0xaa, 0xbc, 0xe6, 0x1d, 0x7a, 0xbb, 0x2e, 0xfa, 0x84, 0x3c, 0xa7, 0x79, 0x45, 0xbb,
+  0x1d, 0xee, 0x84, 0x3c, 0xed, 0xc1, 0x21, 0x3b, 0x5c, 0x3c, 0xbc, 0xbc, 0x9f, 0xa2, 0xbb, 0xbb,
+  0x78, 0x1c, 0xaf, 0x3c, 0x10, 0x74, 0x09, 0xbb, 0x57, 0x94, 0x50, 0x38, 0x4d, 0xfd, 0xa0, 0x3b,
+  0x4c, 0x1f, 0x50, 0x3c, 0xd0, 0xa7, 0xe8, 0xba, 0x7d, 0x16, 0x49, 0xbc, 0xeb, 0x14, 0x8b, 0x3b,
+  0xe7, 0x0d, 0x1f, 0x3c, 0x25, 0xa1, 0x34, 0xbb, 0x34, 0x4b, 0x50, 0x39, 0x68, 0xf0, 0x61, 0x3c,
+  0x97, 0x40, 0x4b, 0x3c, 0x8c, 0x8f, 0xb1, 0xba, 0xa3, 0x4e, 0xc8, 0xbb, 0x29, 0x8f, 0x39, 0x3c,
+  0xff, 0x7d, 0xea, 0xba, 0x4a, 0x30, 0x25, 0xbc, 0x27, 0xf2, 0x21, 0x3c, 0x19, 0x88, 0xab, 0xbb,
+  0xe9, 0xcb, 0xda, 0x3b, 0xec, 0xf0, 0x9b, 0x3b, 0xbf, 0x28, 0xc7, 0xbb, 0x0d, 0x6e, 0xe5, 0xbb,
+  0x64, 0x13, 0x51, 0x3c, 0xc5, 0x9f, 0x0f, 0x3b, 0x6b, 0xfd, 0x18, 0x3c, 0xac, 0x1f, 0xa2, 0x3a,
+  0x58, 0x3f, 0xb1, 0x3c, 0xee, 0x7c, 0x98, 0x3c, 0xc1, 0x65, 0x1b, 0xbb, 0xb9, 0x83, 0x3a, 0x3c,
+  0x67, 0xf9, 0x86, 0x3c, 0xff, 0x70, 0x03, 0xbc, 0x2b, 0x1f, 0xa2, 0xbb, 0x48, 0xc7, 0x42, 0x3b,
+  0xc3, 0xff, 0x9d, 0x3c, 0xaf, 0x79, 0xa7, 0x3c, 0x23, 0xe5, 0x84, 0xbc, 0x10, 0x43, 0x1e, 0xbc,
+  0x16, 0x2e, 0x08, 0xbc, 0x96, 0x77, 0x39, 0xbc, 0x58, 0xd9, 0xb0, 0xbc, 0xfa, 0x8a, 0x3f, 0xba,
+  0xec, 0x44, 0x33, 0x3c, 0x69, 0x35, 0x10, 0x3c, 0x0c, 0x74, 0x2d, 0x3a, 0x48, 0xc3, 0x12, 0x3c,
+  0xd6, 0xc7, 0x0d, 0x3b, 0x42, 0x0e, 0x86, 0xbb, 0x17, 0xbc, 0xe7, 0xb3, 0xa8, 0xb7, 0x84, 0xbc,
+  0x71, 0x20, 0xc4, 0xbb, 0x13, 0x62, 0x51, 0xbc, 0x89, 0x27, 0xcb, 0x3a, 0xaf, 0xcf, 0x19, 0xbb,
+  0xd0, 0x0e, 0x55, 0x3b, 0xad, 0xd7, 0xad, 0x3b, 0x9c, 0x08, 0xb4, 0xba, 0xcc, 0x19, 0x8d, 0xbc,
+  0x7c, 0x7c, 0x82, 0xbc, 0x03, 0x23, 0xad, 0x3a, 0x22, 0x06, 0xc1, 0x3b, 0xe2, 0x2b, 0x68, 0xb9,
+  0x18, 0xad, 0x49, 0xbb, 0xbc, 0x8b, 0x42, 0x3b, 0x39, 0xc2, 0xd4, 0x3b, 0x39, 0x97, 0x99, 0x3a,
+  0xb8, 0xb1, 0x28, 0x3b, 0x63, 0xe4, 0x48, 0xbb, 0x37, 0x3b, 0xa0, 0xba, 0x2a, 0xaa, 0x14, 0xbc,
+  0x86, 0x65, 0x93, 0x3b, 0x6b, 0x1d, 0xb7, 0x3b, 0x6d, 0x35, 0xc4, 0xba, 0x03, 0x8c, 0x10, 0xbb,
+  0x51, 0x9c, 0xbc, 0x3b, 0xf9, 0xb9, 0xf5, 0xbb, 0x06, 0xb1, 0x5a, 0xbc, 0xfe, 0x0f, 0xe8, 0x3a,
+  0x53, 0xed, 0xa4, 0xbc, 0xe5, 0x28, 0xcd, 0xbb, 0x35, 0x92, 0x91, 0x3b, 0xea, 0x36, 0x9d, 0x3b,
+  0x2f, 0x11, 0x64, 0xbb, 0xae, 0xef, 0x6c, 0xbb, 0xbb, 0x77, 0x6d, 0xbc, 0x6c, 0xbc, 0x02, 0xbc,
+  0xba, 0xaf, 0x7f, 0xbc, 0x6f, 0xad, 0xf3, 0xbb, 0x5a, 0x39, 0x80, 0xbb, 0xd8, 0xd4, 0xb9, 0x3a,
+  0x2a, 0x90, 0xe9, 0x3b, 0xca, 0xfa, 0x7b, 0x3c, 0xe5, 0x87, 0xc0, 0xbb, 0x4b, 0x68, 0x66, 0xbc,
+  0xaa, 0xef, 0x6e, 0xbb, 0x50, 0xbb, 0x58, 0x3a, 0x25, 0xb0, 0x6a, 0xbc, 0xd7, 0x81, 0x57, 0xbc,
+  0xbe, 0x42, 0x8f, 0x3c, 0x38, 0xb8, 0xf2, 0x3b, 0xb2, 0xf0, 0x21, 0xbc, 0x41, 0x88, 0x6c, 0xbb,
+  0x55, 0x5d, 0x32, 0xbc, 0x29, 0xdf, 0xd2, 0xba, 0x53, 0x8d, 0x01, 0x3b, 0x83, 0x4d, 0xc2, 0x3b,
+  0x15, 0x8c, 0xbe, 0x3b, 0x24, 0xd7, 0x4b, 0xba, 0x64, 0x31, 0x18, 0x3a, 0x2f, 0x0a, 0x7f, 0x3b,
+  0x8e, 0xc2, 0xe0, 0xba, 0xce, 0xde, 0x02, 0xbb, 0xed, 0x63, 0x57, 0x3c, 0x1b, 0x07, 0x9f, 0x39,
+  0x9e, 0x92, 0x57, 0xbc, 0x41, 0x70, 0x11, 0x3c, 0x9e, 0x6a, 0x52, 0xbb, 0xf7, 0x13, 0x3b, 0xbc,
+  0xb6, 0xa2, 0x4e, 0x3b, 0x53, 0x93, 0x7d, 0x3c, 0x54, 0xea, 0x60, 0xba, 0xfa, 0x79, 0x35, 0x3b,
+  0x82, 0xc5, 0x1a, 0xbc, 0x7f, 0xdf, 0x4f, 0xba, 0x8b, 0xdd, 0x8e, 0x3b, 0xdb, 0x99, 0x06, 0xbc,
+  0x03, 0x63, 0x1d, 0x3c, 0x58, 0xe7, 0xfc, 0x3a, 0x53, 0x86, 0xaa, 0x3b, 0xa1, 0x05, 0xa7, 0xbb,
+  0x37, 0x43, 0x47, 0xbc, 0x93, 0xc3, 0xbc, 0xb9, 0x11, 0xd0, 0x97, 0x3b, 0x0f, 0x44, 0x44, 0x3a,
+  0x68, 0x0e, 0x91, 0x3b, 0xc7, 0xb0, 0x32, 0xbc, 0x02, 0x36, 0xea, 0xbc, 0x61, 0xf2, 0x2f, 0x3c,
+  0x30, 0x5a, 0xd2, 0x3b, 0x97, 0x5b, 0x44, 0xbc, 0x3e, 0xd0, 0x25, 0x3c, 0xf0, 0x88, 0x1a, 0x3c,
+  0x8d, 0xce, 0xed, 0xbb, 0x35, 0x1a, 0xbb, 0xbc, 0xea, 0xbc, 0x1d, 0xbc, 0xeb, 0xb1, 0x43, 0xbc,
+  0x40, 0x6a, 0xfb, 0xbb, 0x70, 0x6c, 0xf7, 0xbb, 0x0e, 0xcd, 0xc8, 0x3c, 0xbd, 0x61, 0x28, 0x3b,
+  0xbf, 0x5c, 0x94, 0xbc, 0x20, 0x93, 0xd4, 0xbb, 0x32, 0x3b, 0xaa, 0x3b, 0xf7, 0x2c, 0x83, 0x3b,
+  0x4e, 0x90, 0xdc, 0x3c, 0xc5, 0x9a, 0x2f, 0x3a, 0x39, 0x36, 0x69, 0x3b, 0x1f, 0x28, 0xc8, 0xba,
+  0x63, 0xdd, 0x9c, 0xbc, 0x67, 0xbc, 0x32, 0x3b, 0xd9, 0x51, 0x99, 0xbc, 0x1c, 0x8d, 0xfa, 0xbb,
+  0x9e, 0x38, 0x2d, 0x3c, 0xd1, 0xc3, 0x70, 0x3c, 0x92, 0xb7, 0x0d, 0xba, 0xc9, 0x43, 0x93, 0xbb,
+  0x25, 0xa1, 0x78, 0xbc, 0xc6, 0x2b, 0x9d, 0xbc, 0x01, 0xa4, 0xcd, 0xbb, 0x83, 0x72, 0x90, 0xbb,
+  0xec, 0x3a, 0x0f, 0x3c, 0xc3, 0x7a, 0x6c, 0x3b, 0xa8, 0x0a, 0xdf, 0x3b, 0x68, 0x2d, 0x11, 0x3b,
+  0xa5, 0x5b, 0x99, 0xbb, 0x58, 0x7c, 0xba, 0x3a, 0x7e, 0xbe, 0x03, 0xbc, 0xa8, 0x6c, 0x51, 0x3c,
+  0x7a, 0xbd, 0x0c, 0x3c, 0xad, 0x81, 0xb8, 0xbb, 0x63, 0x22, 0x3f, 0xbc, 0x7e, 0x38, 0xef, 0x3b,
+  0xe7, 0xcd, 0x4d, 0x3a, 0x80, 0xb7, 0xd3, 0xba, 0xbd, 0x88, 0xd7, 0xbb, 0x06, 0xf1, 0x2b, 0x3c,
+  0x24, 0xfe, 0x95, 0x3c, 0x59, 0xaf, 0x86, 0x3c, 0xb1, 0xdb, 0x78, 0xbc, 0x4c, 0x58, 0x5d, 0x3b,
+  0x2e, 0x39, 0x8d, 0xbb, 0xd9, 0x6a, 0x4e, 0xbc, 0xec, 0xb2, 0x25, 0xbc, 0xb2, 0xe7, 0x2b, 0x3c,
+  0x56, 0xa5, 0x84, 0x3c, 0x66, 0xa2, 0x49, 0x3c, 0x1a, 0x44, 0xa8, 0x3b, 0x00, 0xd7, 0xcc, 0x39,
+  0xf3, 0x3f, 0xa6, 0xbb, 0x4e, 0x97, 0x29, 0xbc, 0x94, 0x1a, 0xb5, 0xbc, 0xfc, 0x9f, 0x84, 0x3c,
+  0xa3, 0x11, 0xf1, 0x3b, 0xf6, 0xea, 0x13, 0x3c, 0xc4, 0xf0, 0x27, 0x3c, 0x4d, 0x2a, 0x7a, 0x3b,
+  0x4f, 0x56, 0xfa, 0xbb, 0x51, 0xe1, 0x27, 0xbb, 0x90, 0xa2, 0x13, 0xbc, 0x81, 0xdd, 0x08, 0x3c,
+  0xaa, 0x80, 0xcf, 0xbb, 0xb4, 0xe9, 0x35, 0xbc, 0x7b, 0x32, 0x2a, 0xba, 0xb5, 0xad, 0x85, 0xbc,
+  0x44, 0x91, 0xa1, 0x3b, 0x09, 0xec, 0x3a, 0x3c, 0x13, 0x48, 0xe6, 0x3b, 0x0d, 0xac, 0x53, 0x3a,
+  0xb8, 0x38, 0x27, 0xbb, 0x6f, 0x94, 0x6a, 0xbb, 0xe9, 0x55, 0x20, 0xbb, 0xd6, 0x1e, 0x39, 0xbc,
+  0xa3, 0xe2, 0x0f, 0x3c, 0x6f, 0x6e, 0x3d, 0x3c, 0x54, 0xe4, 0xd0, 0x39, 0xad, 0xb0, 0xbc, 0xbb,
+  0xd0, 0x60, 0x9e, 0xbb, 0x02, 0xfb, 0x7b, 0xbb, 0x4d, 0x8b, 0xf4, 0xbb, 0x88, 0xd6, 0x74, 0x3c,
+  0x24, 0x6e, 0x8c, 0x3c, 0x2e, 0xc0, 0x25, 0x3c, 0xf5, 0x4f, 0xb1, 0xbb, 0xd4, 0x6c, 0x94, 0x38,
+  0x5a, 0x49, 0x5a, 0x3c, 0xec, 0x05, 0x63, 0xbb, 0x28, 0x3b, 0x3a, 0x3a, 0xe6, 0xe4, 0x9a, 0x3b,
+  0xb4, 0x7a, 0x07, 0x3c, 0x8a, 0x0b, 0xa9, 0xbc, 0x03, 0x31, 0x04, 0x3a, 0x4e, 0xde, 0x0c, 0x3c,
+  0xb4, 0x1b, 0x3f, 0x3a, 0x0e, 0xd8, 0x1a, 0xbc, 0x4b, 0xfa, 0xc5, 0xba, 0xe9, 0x12, 0x5e, 0x3b,
+  0x8d, 0x1a, 0xe3, 0xbb, 0x9e, 0xe1, 0x28, 0xbc, 0x66, 0x1b, 0x55, 0xbb, 0xe0, 0x48, 0x19, 0xba,
+  0x5f, 0x93, 0x87, 0xbb, 0xde, 0x05, 0x29, 0xbb, 0xa0, 0xa0, 0x26, 0x3c, 0x5f, 0xe8, 0x1a, 0xbc,
+  0xaa, 0xf5, 0x53, 0xbc, 0x2d, 0x8a, 0xdb, 0x39, 0x16, 0x55, 0x25, 0xbc, 0x87, 0xa6, 0x25, 0x3b,
+  0x29, 0xd7, 0x6a, 0xbb, 0x83, 0xd3, 0xf6, 0x3b, 0x50, 0x4c, 0x96, 0xba, 0x3a, 0x1f, 0x9c, 0x3c,
+  0xee, 0x72, 0x54, 0xbc, 0xa9, 0x58, 0xa3, 0x3b, 0x0c, 0x1f, 0x23, 0xbc, 0x15, 0xa6, 0x57, 0x3c,
+  0x55, 0x55, 0xd9, 0x3b, 0x4f, 0x13, 0x5c, 0xbb, 0xd4, 0x9a, 0x85, 0xbc, 0x9f, 0x29, 0x99, 0x3a,
+  0xc7, 0xe6, 0x27, 0x3c, 0x7c, 0x50, 0x9d, 0x3b, 0xc1, 0x4d, 0xe5, 0xb9, 0xc4, 0xb4, 0x42, 0xba,
+  0xef, 0x40, 0x06, 0x3c, 0xd4, 0x4f, 0x8c, 0x3c, 0x62, 0xce, 0xbb, 0x3a, 0x56, 0x8e, 0x7d, 0xbb,
+  0x60, 0xff, 0x48, 0xb9, 0xbd, 0x50, 0x6e, 0x3b, 0x66, 0x34, 0xae, 0xba, 0x1d, 0xb4, 0xd7, 0x3b,
+  0x50, 0x86, 0x28, 0xbc, 0xef, 0x7c, 0xcd, 0xbb, 0x5d, 0x09, 0xa2, 0xbb, 0xf1, 0xc0, 0x8c, 0xbb,
+  0x82, 0x2a, 0x19, 0x3c, 0x5f, 0x42, 0xdd, 0x3b, 0xa3, 0x59, 0x05, 0xbb, 0x2f, 0x5c, 0xad, 0xbb,
+  0x66, 0x5c, 0x85, 0xbc, 0x82, 0x31, 0xb3, 0xbb, 0xf6, 0xf4, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x31, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x12, 0xf5, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0xa0, 0x0f, 0x00, 0x00, 0x26, 0xf5, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x9f, 0xd4, 0x8c, 0x3c, 0x32, 0xfe, 0xaa, 0xbc, 0xee, 0x4e, 0x79, 0xbb,
+  0xb5, 0x4d, 0xf5, 0x3b, 0x42, 0xf5, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
+  0xa6, 0x6f, 0x7f, 0xbb, 0x11, 0x4c, 0x98, 0x3c, 0x09, 0xb8, 0x6b, 0x3d, 0xcc, 0x8b, 0xb8, 0x3b,
+  0x52, 0x0f, 0x0a, 0x3d, 0x17, 0xf8, 0x1e, 0xbd, 0x2e, 0xf1, 0x8f, 0x3b, 0xc7, 0xa4, 0x61, 0xbd,
+  0x1a, 0x18, 0x05, 0xbd, 0x55, 0x94, 0x2c, 0xb9, 0x39, 0x30, 0x48, 0x3d, 0xb1, 0x03, 0x56, 0x3b,
+  0xe5, 0x93, 0x38, 0x3d, 0xc9, 0x28, 0xaa, 0xbc, 0x39, 0x57, 0xed, 0x3c, 0x1d, 0x3d, 0xfa, 0xbc,
+  0x2e, 0xbc, 0x3f, 0xbd, 0xf8, 0x87, 0x8f, 0xbc, 0x2d, 0xc7, 0x23, 0x3d, 0xa0, 0x20, 0x8d, 0xbc,
+  0x53, 0x2a, 0x38, 0x3d, 0x06, 0xa7, 0x46, 0xbc, 0x53, 0x31, 0x45, 0x3d, 0x79, 0x65, 0xa7, 0xbb,
+  0x3c, 0xc6, 0x93, 0xbd, 0x15, 0x46, 0xe7, 0xbc, 0x8b, 0xc0, 0xf8, 0x3c, 0x32, 0xd9, 0x95, 0x3a,
+  0x6d, 0x9a, 0x48, 0x3d, 0xea, 0x03, 0x3f, 0xbc, 0x46, 0x1a, 0x8c, 0x3d, 0x07, 0x76, 0x38, 0x3c,
+  0xd5, 0xd7, 0xa1, 0xbd, 0xf4, 0xf3, 0x31, 0xbd, 0x08, 0x58, 0xbb, 0x3c, 0x79, 0xbb, 0x67, 0xbc,
+  0x73, 0x24, 0x6f, 0x3d, 0xa8, 0xb3, 0x93, 0xbc, 0x41, 0xa5, 0x8d, 0x3d, 0x73, 0x3d, 0x9e, 0x3c,
+  0xe6, 0x9a, 0x8e, 0xbd, 0xcb, 0x59, 0x1d, 0xbd, 0x0a, 0x60, 0x55, 0x3c, 0xc8, 0xe5, 0x1d, 0xbc,
+  0x09, 0xd5, 0x13, 0x3d, 0x30, 0xfd, 0xd8, 0xbb, 0x25, 0xa7, 0x8a, 0x3d, 0x28, 0x84, 0x62, 0x3c,
+  0x37, 0x8a, 0x91, 0xbd, 0x8a, 0x82, 0x20, 0xbd, 0x83, 0x01, 0xd0, 0x3a, 0xa8, 0x5c, 0x88, 0xbb,
+  0x1f, 0x23, 0x03, 0x3d, 0xa0, 0xdb, 0xdf, 0xbb, 0xed, 0x89, 0x8c, 0x3d, 0x7d, 0xeb, 0xca, 0x3c,
+  0xe1, 0x25, 0x88, 0xbd, 0xf6, 0xfa, 0x01, 0xbd, 0xeb, 0x2e, 0xd3, 0x3b, 0x8d, 0x71, 0x16, 0xbc,
+  0xb7, 0xc9, 0xc0, 0x3c, 0x2a, 0x6b, 0x2b, 0xbc, 0xdb, 0x33, 0x91, 0x3d, 0x3a, 0xde, 0x6e, 0x3c,
+  0x6d, 0x0b, 0x8c, 0xbd, 0xcc, 0xcd, 0xf7, 0xbc, 0x09, 0x82, 0x60, 0xbc, 0x14, 0x71, 0xc9, 0xbb,
+  0xef, 0x16, 0x9a, 0x3c, 0xde, 0xc0, 0xd4, 0x3b, 0x3d, 0xd2, 0x70, 0x3d, 0xa5, 0xd3, 0x26, 0x3c,
+  0x3f, 0xf1, 0x7b, 0xbd, 0x54, 0xb2, 0x4d, 0xbd, 0x7c, 0x86, 0x07, 0xbc, 0x35, 0xd8, 0xd7, 0xbc,
+  0xba, 0x6a, 0x1d, 0x3b, 0x80, 0x07, 0xb4, 0xbb, 0x88, 0xe6, 0x1a, 0x3d, 0xcc, 0xf7, 0x67, 0xbc,
+  0xd7, 0x3c, 0x29, 0xbb, 0xbb, 0x6d, 0xa8, 0xba, 0x3e, 0x20, 0xff, 0xbb, 0x1b, 0x3e, 0xfe, 0xba,
+  0xd7, 0x43, 0x2b, 0xbc, 0x1d, 0xaf, 0x67, 0xbc, 0x94, 0x38, 0xa4, 0xbb, 0x3f, 0xe2, 0x4a, 0x3b,
+  0x3c, 0x62, 0x23, 0xbc, 0x23, 0x2f, 0xfa, 0xb9, 0x84, 0x5f, 0xe4, 0xbb, 0x35, 0x07, 0x0b, 0xbc,
+  0x0f, 0x25, 0x5b, 0x3b, 0xf5, 0xd5, 0x27, 0xbb, 0x8f, 0x3e, 0xc5, 0x3b, 0xd5, 0xf9, 0x47, 0xbc,
+  0x7f, 0x95, 0x72, 0x3c, 0xcd, 0x94, 0x2a, 0x3c, 0x25, 0x3f, 0x4f, 0xbc, 0x6a, 0xa6, 0x45, 0x3c,
+  0x5b, 0x76, 0x94, 0xbc, 0x8b, 0x12, 0x2f, 0x3c, 0xd6, 0x8b, 0x50, 0xbc, 0x7a, 0xba, 0x90, 0x3b,
+  0xeb, 0x0a, 0x55, 0x3b, 0x49, 0xfb, 0x3c, 0x3c, 0x17, 0x37, 0x58, 0x3b, 0x57, 0x07, 0x10, 0x3b,
+  0x71, 0xe8, 0xf4, 0xbb, 0xd6, 0x45, 0x1f, 0xbc, 0xe3, 0x8c, 0x4d, 0x3c, 0x81, 0xbc, 0x8d, 0xbc,
+  0xee, 0xa4, 0xaa, 0x3b, 0x69, 0x64, 0x88, 0xb8, 0x4a, 0x4f, 0x78, 0xbc, 0xb9, 0x50, 0xe5, 0xba,
+  0xe7, 0x98, 0x29, 0xbc, 0x29, 0x59, 0x92, 0xbb, 0xc5, 0x13, 0x8c, 0xbb, 0x10, 0xb7, 0x23, 0x3c,
+  0xd2, 0xca, 0x89, 0x3b, 0x27, 0xe0, 0x0b, 0x3c, 0x8f, 0xdc, 0x75, 0x39, 0x9f, 0x76, 0x11, 0xbc,
+  0xad, 0xe9, 0x1c, 0x3c, 0x07, 0x03, 0x39, 0xbb, 0x08, 0x23, 0x19, 0xbc, 0x30, 0x01, 0x41, 0xbc,
+  0x72, 0xad, 0x0f, 0xbc, 0x84, 0x5f, 0x34, 0xbc, 0x24, 0x11, 0x13, 0x3c, 0xc8, 0x10, 0x51, 0xbc,
+  0x1d, 0x7a, 0x25, 0xbc, 0xd4, 0xbc, 0x36, 0xbc, 0xd0, 0x4c, 0xae, 0x3a, 0x44, 0x2d, 0x3a, 0x3b,
+  0x02, 0xb5, 0xff, 0x3b, 0x5c, 0x58, 0xe4, 0x3b, 0x6b, 0x32, 0xe4, 0x3a, 0x6f, 0x52, 0x2e, 0xbc,
+  0x8b, 0xea, 0x00, 0xbc, 0x9a, 0x70, 0xe8, 0x39, 0xb5, 0x21, 0xd9, 0xba, 0x4a, 0xda, 0x5b, 0x3c,
+  0x7a, 0x61, 0xe8, 0x3b, 0x14, 0x5f, 0x1f, 0xbc, 0xed, 0xdd, 0x29, 0x3b, 0xcd, 0x8f, 0x94, 0xbb,
+  0x98, 0x9b, 0x16, 0x3b, 0x90, 0xa6, 0xad, 0xbb, 0x39, 0x97, 0x62, 0x3a, 0x76, 0xc8, 0x61, 0xbc,
+  0x1d, 0x63, 0xa0, 0x38, 0x94, 0xd8, 0x5c, 0xbb, 0xf5, 0xbf, 0xfe, 0x3b, 0x20, 0xe6, 0x64, 0xbc,
+  0x5c, 0x1b, 0x47, 0xbb, 0x0e, 0xf7, 0x41, 0xbc, 0x89, 0x89, 0x90, 0xbc, 0x6b, 0x33, 0x0b, 0x3c,
+  0x29, 0x75, 0xf9, 0x3c, 0x6d, 0xfe, 0xc0, 0x3c, 0xf5, 0x78, 0x96, 0x3c, 0x9c, 0xec, 0x92, 0x3c,
+  0xe8, 0xfc, 0xb9, 0x3c, 0x4b, 0x47, 0x3e, 0xbc, 0x53, 0xdb, 0xfc, 0xba, 0x77, 0xc6, 0x03, 0xbd,
+  0x2b, 0x54, 0xb7, 0x3c, 0xa9, 0x6c, 0xf5, 0x3c, 0x1e, 0x1b, 0xd9, 0x3b, 0xe0, 0xe9, 0x8d, 0x3c,
+  0xd0, 0xff, 0x13, 0xbc, 0x66, 0x6c, 0xae, 0xbc, 0x17, 0xda, 0x68, 0xbc, 0x71, 0xcf, 0x0e, 0xbd,
+  0xba, 0xc7, 0x5b, 0x3c, 0x0d, 0x20, 0x76, 0x3c, 0x8b, 0xbc, 0xf5, 0xbb, 0x6d, 0x34, 0xb1, 0x3c,
+  0x03, 0x72, 0x8e, 0xbc, 0xbc, 0x34, 0x6b, 0xbc, 0x68, 0x59, 0x68, 0xbc, 0x80, 0x44, 0xee, 0xbc,
+  0x8c, 0x30, 0x3b, 0x3c, 0x7b, 0x74, 0x0d, 0x3d, 0xee, 0x92, 0x45, 0xbc, 0xa5, 0x7c, 0xbc, 0x3c,
+  0xb6, 0xa2, 0x0a, 0xbd, 0x6e, 0x0c, 0x13, 0xbc, 0xba, 0xf2, 0x76, 0xbc, 0xec, 0xbf, 0xf7, 0xbc,
+  0x22, 0xe8, 0x8b, 0xbc, 0x9d, 0x8b, 0x98, 0x3c, 0xba, 0x48, 0x0f, 0xbd, 0x85, 0x18, 0x09, 0xbc,
+  0x12, 0x99, 0x74, 0xbd, 0xea, 0x32, 0xc7, 0xbc, 0x51, 0x97, 0x7f, 0xbb, 0xd4, 0xa8, 0x1e, 0xbc,
+  0x66, 0x93, 0x45, 0xbd, 0xbe, 0xd5, 0x96, 0xbb, 0xb3, 0x52, 0x75, 0xbd, 0x98, 0xbf, 0x12, 0xbc,
+  0x20, 0xc2, 0x5c, 0xbd, 0x40, 0x5c, 0xa2, 0xbb, 0xd2, 0x09, 0x1e, 0x3c, 0x14, 0x61, 0xf2, 0x3b,
+  0x4c, 0x0a, 0x8a, 0xbd, 0xb8, 0x2b, 0xee, 0xbc, 0x03, 0xaa, 0x4a, 0xbd, 0xf4, 0x98, 0xe1, 0xbb,
+  0x18, 0x2b, 0xfc, 0xbc, 0x41, 0x59, 0xd3, 0xba, 0x9f, 0xbd, 0x25, 0x3d, 0xcc, 0xd3, 0x0e, 0x3d,
+  0xab, 0x01, 0x82, 0xbd, 0x24, 0x5b, 0xd2, 0xbc, 0xf6, 0x24, 0xd5, 0xbc, 0x1b, 0x6a, 0x40, 0x3b,
+  0xf8, 0x09, 0x10, 0xbc, 0x20, 0x96, 0xfe, 0x3b, 0xa3, 0x58, 0x8a, 0x3d, 0x78, 0xcc, 0x86, 0x3d,
+  0x7e, 0xfd, 0x23, 0xbd, 0x98, 0x6a, 0x96, 0xbc, 0x3a, 0xe5, 0x36, 0xbc, 0xb6, 0x95, 0xd1, 0x3b,
+  0x3f, 0xef, 0x49, 0x3b, 0x99, 0x8c, 0x02, 0x3d, 0x75, 0x04, 0xb0, 0x3d, 0xef, 0x4f, 0x8b, 0x3d,
+  0xfc, 0x61, 0xc5, 0xbc, 0xf2, 0x01, 0x1a, 0xbd, 0x82, 0x29, 0xb7, 0x3b, 0x9f, 0x65, 0xec, 0x3b,
+  0xd3, 0x45, 0xdf, 0x3c, 0xa7, 0xba, 0xad, 0x3c, 0x51, 0xde, 0xc3, 0x3d, 0xf2, 0xbb, 0x27, 0x3d,
+  0x49, 0x0a, 0xd8, 0xbc, 0x5d, 0x84, 0x22, 0x3b, 0x5f, 0x1e, 0x4f, 0xbc, 0x1e, 0x72, 0xb8, 0x3c,
+  0x3f, 0x17, 0x81, 0xbb, 0xf1, 0xb1, 0x4a, 0x3b, 0xe6, 0xf2, 0xd8, 0xbc, 0xdb, 0x36, 0xd4, 0xbb,
+  0x4b, 0xd3, 0xbb, 0xbc, 0xc3, 0x21, 0xf2, 0x3c, 0xbd, 0xc7, 0xe2, 0xbb, 0xc0, 0x7c, 0x26, 0x3d,
+  0xc1, 0xe0, 0x22, 0xbc, 0xac, 0x5d, 0x63, 0x3b, 0xcc, 0xf4, 0xdb, 0xbc, 0xdd, 0x06, 0x37, 0xbb,
+  0x61, 0x75, 0x04, 0xbd, 0xe6, 0xce, 0x14, 0x3c, 0x77, 0x91, 0xc0, 0xbc, 0xa9, 0xa3, 0xab, 0x3c,
+  0xc5, 0x87, 0xdd, 0xbb, 0xde, 0x48, 0x21, 0xbb, 0x1d, 0x59, 0xcd, 0xbc, 0x7b, 0x4d, 0x1f, 0xbb,
+  0xc5, 0x72, 0xfd, 0xbc, 0xbe, 0xd1, 0x01, 0x3d, 0xd6, 0x7a, 0xf7, 0xbb, 0x77, 0x2c, 0x57, 0x3d,
+  0x57, 0x2e, 0x12, 0xba, 0x9c, 0x08, 0x9e, 0x3b, 0x0d, 0x25, 0xd5, 0xbc, 0x33, 0x1d, 0x36, 0x3b,
+  0x45, 0x8d, 0x16, 0xbd, 0xb9, 0x57, 0x1d, 0x3d, 0x8a, 0xcc, 0x0f, 0xbc, 0xa5, 0xac, 0x3b, 0x3d,
+  0x86, 0x9f, 0x3d, 0xbc, 0x70, 0xcf, 0xbe, 0x3b, 0x06, 0xe1, 0x37, 0xbd, 0xa8, 0x2f, 0xcc, 0x3a,
+  0x6c, 0xd8, 0x3f, 0xbd, 0xf1, 0xfd, 0x80, 0x3c, 0x10, 0x6f, 0x31, 0xbc, 0x8f, 0x7f, 0x32, 0x3d,
+  0xfc, 0x1a, 0x5b, 0xbc, 0xab, 0x6e, 0x41, 0xbc, 0x5c, 0x2f, 0x4b, 0xbd, 0xc7, 0x59, 0x7b, 0x3a,
+  0xa9, 0x7a, 0xbf, 0xbc, 0xc7, 0x96, 0xbd, 0x3c, 0x43, 0x63, 0xff, 0xbb, 0x41, 0x1a, 0x63, 0x3d,
+  0x34, 0x72, 0x30, 0xbc, 0x08, 0x78, 0x29, 0xbc, 0x05, 0x95, 0x02, 0xbd, 0x05, 0xc2, 0x28, 0x3c,
+  0x54, 0xec, 0xb6, 0xbc, 0x5e, 0x3b, 0xdf, 0x3a, 0x5c, 0xd9, 0x1c, 0x3c, 0x41, 0xe5, 0x12, 0x3d,
+  0x26, 0x31, 0x67, 0xbb, 0x31, 0x7f, 0xe6, 0xbc, 0x77, 0xd3, 0xc5, 0xbc, 0x7d, 0x64, 0x32, 0x39,
+  0x6f, 0xd1, 0x90, 0xbc, 0x6a, 0xae, 0x1a, 0x3d, 0x7a, 0x67, 0x76, 0xbb, 0x46, 0x09, 0x49, 0x3d,
+  0x8d, 0xee, 0x86, 0xbb, 0x92, 0x70, 0x20, 0xbd, 0x36, 0x3b, 0x7a, 0xbc, 0x78, 0x5c, 0x23, 0x3c,
+  0x00, 0x17, 0x62, 0xbc, 0x54, 0xcc, 0x37, 0x3a, 0xae, 0x70, 0xc0, 0xbc, 0x9f, 0x35, 0x95, 0x3c,
+  0xd0, 0xef, 0xb9, 0xbc, 0xdb, 0x95, 0x32, 0xbd, 0xeb, 0x17, 0xba, 0xbc, 0xb3, 0x55, 0x03, 0xbc,
+  0x3e, 0xd7, 0x21, 0xbc, 0x27, 0x66, 0xee, 0x3b, 0x0c, 0xdd, 0x72, 0xbb, 0xdb, 0x4e, 0x63, 0x3d,
+  0x6a, 0x34, 0x07, 0x3d, 0x81, 0xdd, 0x59, 0x3d, 0xcf, 0xf8, 0xb8, 0xbc, 0xa4, 0xdc, 0x0c, 0xbd,
+  0x1c, 0x77, 0xbe, 0xbc, 0x9d, 0x0e, 0x38, 0xbb, 0x9f, 0x78, 0x68, 0xbb, 0xd0, 0x5e, 0x67, 0x3d,
+  0xbc, 0x2e, 0xd5, 0x3c, 0x13, 0x8b, 0x01, 0x3d, 0xe8, 0x49, 0x15, 0xbd, 0xfe, 0x5b, 0x41, 0xbd,
+  0xf2, 0x66, 0xe6, 0xbc, 0x85, 0x73, 0xec, 0x3a, 0xbf, 0x62, 0x3c, 0xbb, 0x66, 0x56, 0x20, 0x3d,
+  0xd4, 0xfa, 0x8a, 0x3c, 0x35, 0x97, 0xd8, 0x3c, 0x38, 0x72, 0x7d, 0xbd, 0x2b, 0x8f, 0x80, 0xbd,
+  0xf3, 0x77, 0xd5, 0xbc, 0x5b, 0xad, 0x90, 0x3c, 0x57, 0xb3, 0x40, 0xba, 0xff, 0xa8, 0x75, 0x3d,
+  0x85, 0x32, 0xb8, 0x3b, 0x1e, 0x40, 0x18, 0x3d, 0x5d, 0x89, 0x6e, 0xbd, 0x24, 0x9d, 0x58, 0xbd,
+  0x88, 0xfa, 0xe6, 0xbc, 0x2e, 0x60, 0xbe, 0x3c, 0xc0, 0x1b, 0xfa, 0x3b, 0x4b, 0x95, 0x76, 0x3d,
+  0x40, 0x56, 0x1b, 0x3c, 0x96, 0x12, 0x37, 0x3d, 0xa3, 0x9b, 0x91, 0xbd, 0x6a, 0xf0, 0x05, 0xbd,
+  0xc5, 0x08, 0x11, 0xbc, 0x7e, 0xd7, 0xb0, 0x3a, 0xbb, 0x0a, 0xb6, 0x3c, 0x29, 0xad, 0x00, 0x3d,
+  0x76, 0x0b, 0xef, 0x3b, 0xea, 0xaf, 0x9b, 0x3c, 0x0e, 0xa8, 0x29, 0xbd, 0xcd, 0x33, 0x83, 0xbd,
+  0x44, 0x7f, 0xc8, 0xbb, 0x1d, 0x5d, 0x90, 0xbb, 0x06, 0xda, 0x68, 0x3c, 0xe6, 0x8e, 0x85, 0x3c,
+  0xa5, 0xcf, 0x5a, 0xbc, 0x37, 0x92, 0xf0, 0xbb, 0xaf, 0xc1, 0xf0, 0xbc, 0xa9, 0xb5, 0x4c, 0xbd,
+  0x04, 0xcb, 0xbe, 0xbc, 0x42, 0x8b, 0x54, 0xbc, 0x8e, 0xf8, 0x91, 0xbc, 0x05, 0x35, 0x45, 0x3a,
+  0x27, 0xec, 0xbf, 0xbc, 0x89, 0x82, 0xcb, 0xbc, 0x3c, 0xad, 0xbe, 0xbc, 0x2c, 0xa5, 0x2f, 0xbd,
+  0x92, 0x5d, 0x0d, 0xbd, 0x35, 0x52, 0x6a, 0xbd, 0x85, 0x84, 0xaa, 0xbc, 0x27, 0x7e, 0x59, 0xbd,
+  0xd5, 0x22, 0x48, 0xbd, 0xf7, 0x5b, 0x2b, 0xbd, 0xe4, 0x98, 0xdd, 0xbc, 0x6d, 0xba, 0x35, 0xbd,
+  0x9e, 0x65, 0x3a, 0xbd, 0x40, 0x4f, 0x88, 0xbd, 0x5a, 0xb7, 0xf4, 0xbc, 0xb6, 0xaf, 0x92, 0xbd,
+  0x1d, 0xea, 0xfe, 0xbc, 0xd2, 0x1c, 0x54, 0xbd, 0xb0, 0x82, 0xcd, 0xbc, 0x5f, 0x80, 0xc6, 0xbc,
+  0x86, 0x14, 0x5a, 0xba, 0x43, 0x12, 0x15, 0xbc, 0x27, 0xa7, 0x20, 0x3c, 0xb4, 0x9a, 0x2e, 0xbc,
+  0xf9, 0xe9, 0x85, 0x3c, 0x79, 0xc6, 0xb5, 0x3b, 0xc5, 0x17, 0x12, 0x3d, 0x91, 0x8e, 0x10, 0x3b,
+  0xf2, 0xdc, 0xf1, 0x3c, 0xe0, 0xd2, 0xd7, 0xbb, 0xbe, 0x39, 0x08, 0x3d, 0xfc, 0x51, 0xe3, 0xb8,
+  0x3c, 0x94, 0x14, 0x3d, 0xd8, 0xce, 0xec, 0xbb, 0xb4, 0xd4, 0xd4, 0x3c, 0x7c, 0xb2, 0x18, 0x3c,
+  0x5e, 0x2c, 0xe2, 0x3b, 0x04, 0xa2, 0x16, 0xbc, 0x6b, 0x13, 0xc1, 0xb8, 0xe4, 0x0f, 0x6e, 0xbc,
+  0x90, 0x61, 0xfb, 0xba, 0xaa, 0x11, 0xb5, 0xbc, 0xd9, 0x11, 0x84, 0xbc, 0xb8, 0x94, 0xa8, 0xbb,
+  0x4d, 0xed, 0xe0, 0xbc, 0x3a, 0x33, 0x04, 0xbd, 0x71, 0xc8, 0x0e, 0xbd, 0x97, 0x7a, 0x1f, 0xbd,
+  0xf0, 0x70, 0x52, 0xbd, 0x12, 0xa9, 0xde, 0xbc, 0xfc, 0x19, 0x22, 0xbd, 0x91, 0x7c, 0xf6, 0xbc,
+  0x91, 0xfc, 0x12, 0xbd, 0xb3, 0x8d, 0x12, 0xbd, 0x5f, 0x12, 0x46, 0xbd, 0x0d, 0xa1, 0x15, 0xbd,
+  0x31, 0xd1, 0x47, 0xbd, 0xe1, 0x5f, 0x33, 0xbd, 0xfc, 0xcd, 0x34, 0xbd, 0x61, 0x67, 0xd7, 0xbc,
+  0x53, 0xc0, 0x44, 0x3c, 0xab, 0x7f, 0x19, 0x3d, 0xdc, 0x6b, 0x88, 0x3c, 0xbb, 0x4b, 0xff, 0x3c,
+  0x76, 0x71, 0x27, 0x3c, 0x56, 0xdc, 0xd5, 0x3c, 0x95, 0x9e, 0x26, 0x3c, 0xd8, 0xe6, 0x1e, 0x3c,
+  0x7a, 0xb7, 0x7b, 0x3d, 0x4b, 0x67, 0x7b, 0x3d, 0xd1, 0xfd, 0x4e, 0x3d, 0x95, 0xeb, 0x68, 0x3d,
+  0xfc, 0x3e, 0x4f, 0x3d, 0xfd, 0x79, 0x33, 0x3d, 0xf4, 0x64, 0xdc, 0x3c, 0x8d, 0x3e, 0x97, 0x3c,
+  0xf2, 0x4f, 0x21, 0x3d, 0xee, 0x62, 0x52, 0x3d, 0xc6, 0x5b, 0x8e, 0x3c, 0xe7, 0x57, 0x1f, 0x3d,
+  0x7c, 0xe8, 0xc0, 0x3c, 0xe9, 0x85, 0x1c, 0x3d, 0x47, 0x96, 0xc1, 0x3c, 0x84, 0x46, 0xe4, 0x3c,
+  0x41, 0x19, 0x32, 0xbd, 0x8f, 0x0b, 0x36, 0xbc, 0x3c, 0x09, 0x0d, 0xbd, 0x7f, 0x5a, 0x19, 0xbc,
+  0xf5, 0x91, 0x10, 0xbd, 0x97, 0x73, 0xf7, 0x3b, 0x51, 0x5b, 0x0c, 0xbd, 0xa3, 0xb2, 0x42, 0xbc,
+  0x89, 0x18, 0x47, 0xbd, 0x51, 0xe1, 0x07, 0xbd, 0x11, 0xa2, 0x6f, 0xbd, 0xc7, 0x6b, 0xa4, 0xbc,
+  0x05, 0x6f, 0x54, 0xbd, 0x0b, 0xe1, 0xa6, 0xbc, 0xfc, 0x3e, 0x1f, 0xbd, 0x2d, 0x2f, 0xc3, 0xbc,
+  0x79, 0xba, 0x20, 0xbd, 0x50, 0x15, 0x96, 0xbc, 0xe2, 0x67, 0x05, 0x3d, 0x2b, 0x4b, 0x62, 0xbc,
+  0x19, 0xf9, 0x04, 0x3d, 0x69, 0x86, 0xc6, 0x3c, 0x31, 0x3e, 0x32, 0xbc, 0x25, 0xd5, 0x0c, 0xbb,
+  0xe1, 0xe5, 0x11, 0xbd, 0xe1, 0x92, 0x2c, 0xbc, 0x89, 0x88, 0x58, 0x3d, 0xdd, 0xca, 0xc6, 0xbb,
+  0x19, 0x37, 0x19, 0x3d, 0xf5, 0xb8, 0x90, 0x3c, 0x9f, 0x88, 0x1e, 0xbc, 0xd6, 0x09, 0x0a, 0xbc,
+  0xe0, 0x63, 0xdd, 0xbc, 0x4f, 0x0d, 0xab, 0xbb, 0x18, 0x36, 0x7e, 0x3d, 0x4b, 0x83, 0x4b, 0xbb,
+  0x4f, 0xd4, 0xd9, 0x3c, 0xa0, 0xea, 0x96, 0xbb, 0xe0, 0x92, 0xae, 0xbc, 0x5c, 0x6a, 0xb4, 0xbc,
+  0x7d, 0x39, 0xf6, 0xba, 0x74, 0x84, 0x95, 0x3a, 0xf6, 0xb6, 0x99, 0x3d, 0xa8, 0x61, 0xb8, 0xbb,
+  0xf8, 0x2f, 0xc6, 0x3c, 0x74, 0x1e, 0x45, 0xbc, 0x30, 0xf0, 0xee, 0xbc, 0x93, 0xc6, 0xaa, 0xbc,
+  0xa9, 0xc5, 0x87, 0x3c, 0x3e, 0xf0, 0xa0, 0xba, 0xdb, 0x13, 0x9f, 0x3d, 0x93, 0x4f, 0xce, 0xbc,
+  0xd9, 0x66, 0x9d, 0x3c, 0xf7, 0xb6, 0xdd, 0xbc, 0x75, 0x6a, 0x36, 0xbd, 0xe1, 0x73, 0x09, 0xbd,
+  0x0c, 0x65, 0x1f, 0x3d, 0x0f, 0x2f, 0x98, 0x3b, 0x75, 0x14, 0xaa, 0x3d, 0x02, 0x5a, 0xdc, 0xbc,
+  0x4e, 0xc7, 0x5b, 0x3c, 0x15, 0xe6, 0xb9, 0xbc, 0x5c, 0x86, 0x56, 0xbd, 0x77, 0x70, 0xf9, 0xbc,
+  0x10, 0x68, 0x86, 0x3d, 0x1f, 0xdf, 0x4c, 0x3b, 0x62, 0x79, 0xc6, 0x3d, 0x54, 0x6c, 0xf5, 0xbc,
+  0x08, 0xf2, 0x89, 0x3c, 0x82, 0x56, 0xc7, 0xbc, 0xef, 0x4a, 0x56, 0xbd, 0x26, 0x5d, 0x2e, 0xbd,
+  0xb2, 0xfd, 0xa9, 0x3d, 0xa4, 0xa1, 0xd8, 0xb8, 0xd3, 0x3b, 0xd0, 0x3d, 0x36, 0x49, 0xe8, 0xbc,
+  0xec, 0x06, 0xb4, 0x3c, 0xb5, 0x93, 0xc9, 0xbc, 0xe2, 0x1e, 0x53, 0xbd, 0x2a, 0xd9, 0x38, 0xbd,
+  0xd1, 0x5a, 0xa4, 0x3d, 0x73, 0x4a, 0xf2, 0xbb, 0x99, 0x19, 0xd2, 0x3d, 0xd0, 0x5d, 0x2b, 0xbd,
+  0xb4, 0x20, 0x2b, 0x3d, 0xc0, 0xa9, 0x93, 0xbc, 0x43, 0x4b, 0x0a, 0xbd, 0x46, 0xda, 0x54, 0xbd,
+  0x5b, 0xbc, 0x66, 0x3d, 0x56, 0xa0, 0xbb, 0xbc, 0xae, 0xca, 0xb5, 0x3d, 0x5f, 0x64, 0x23, 0xbd,
+  0xeb, 0xed, 0x29, 0x3d, 0xa9, 0xfa, 0xc0, 0xbb, 0x58, 0xfe, 0x20, 0xbc, 0x01, 0x06, 0x29, 0xbd,
+  0x50, 0xde, 0x20, 0x3c, 0xc6, 0xe5, 0xa9, 0xbd, 0x43, 0x81, 0xe5, 0x3c, 0x62, 0x66, 0xe3, 0xbc,
+  0x27, 0x56, 0x19, 0x3d, 0x4e, 0x79, 0xed, 0x3c, 0x79, 0xdb, 0xda, 0x3c, 0xc1, 0xf3, 0xd0, 0x3c,
+  0x3c, 0x1d, 0xde, 0x3c, 0x44, 0x56, 0x49, 0xbd, 0x73, 0x11, 0x46, 0x3d, 0x42, 0x25, 0x47, 0xbc,
+  0x7a, 0xbb, 0x2b, 0x3d, 0xc7, 0x88, 0x50, 0x3c, 0x3e, 0x8f, 0xc7, 0x3a, 0xb8, 0x5b, 0x84, 0xbc,
+  0xc1, 0x77, 0x6e, 0x3d, 0x71, 0xa4, 0xeb, 0xbc, 0x07, 0xfb, 0x7e, 0x3d, 0x76, 0xe4, 0x2a, 0x3a,
+  0xbf, 0x52, 0x08, 0x3d, 0x22, 0x0c, 0x4e, 0xbb, 0xd5, 0x43, 0xc6, 0xbc, 0x48, 0x10, 0x21, 0xbd,
+  0x6c, 0xaf, 0x8c, 0x3d, 0x90, 0xc9, 0x60, 0xbc, 0x0f, 0x43, 0x84, 0x3d, 0x45, 0xab, 0xb5, 0xba,
+  0x7f, 0x77, 0xee, 0x3c, 0x05, 0x4a, 0x72, 0xbc, 0x4c, 0x87, 0xe0, 0xbc, 0x47, 0xd8, 0x7d, 0xbd,
+  0xc6, 0x7c, 0x90, 0x3d, 0x46, 0x24, 0x43, 0x3a, 0x91, 0x79, 0x80, 0x3d, 0x83, 0x0b, 0xdc, 0xbb,
+  0x59, 0xbd, 0x2a, 0x3c, 0xa2, 0x53, 0x91, 0xbc, 0xcd, 0xd5, 0x48, 0xbd, 0xd8, 0x4b, 0x8e, 0xbd,
+  0x0d, 0x76, 0xa0, 0x3d, 0x06, 0x77, 0x9b, 0x3b, 0x3b, 0x4b, 0x50, 0x3d, 0x0c, 0x94, 0xd2, 0xbb,
+  0x2d, 0xca, 0xd2, 0xba, 0x70, 0xae, 0xf9, 0xba, 0xc6, 0x2c, 0x83, 0xbd, 0xd4, 0x57, 0x88, 0xbd,
+  0x21, 0xe0, 0x68, 0x3d, 0x92, 0xbb, 0xd7, 0x3b, 0xe2, 0xb4, 0x59, 0x3d, 0xcb, 0x1a, 0x82, 0xbc,
+  0x15, 0x5a, 0xb8, 0xbb, 0x29, 0xc1, 0x77, 0x3b, 0xe6, 0x25, 0x9f, 0xbd, 0xa7, 0xa5, 0x52, 0xbd,
+  0xd4, 0x63, 0x39, 0x3d, 0x52, 0xe6, 0x4c, 0x3c, 0x7e, 0xdf, 0x44, 0x3d, 0x8d, 0xe1, 0xf4, 0xbb,
+  0x50, 0xdb, 0x00, 0xbd, 0x57, 0x82, 0x0f, 0xbb, 0xae, 0xc0, 0x9a, 0xbd, 0x1c, 0x29, 0xfb, 0xbc,
+  0x09, 0xcc, 0xcb, 0x3c, 0x97, 0x1d, 0x99, 0x3c, 0xc6, 0xe2, 0x6e, 0x3c, 0xdf, 0x33, 0x24, 0xbc,
+  0x64, 0xa6, 0x67, 0xbd, 0x9d, 0x32, 0xac, 0xbb, 0xad, 0x91, 0x81, 0xbd, 0x5d, 0xd5, 0xf3, 0x39,
+  0xbf, 0x90, 0xda, 0xbc, 0x06, 0xa8, 0xd3, 0xbb, 0xa6, 0x53, 0x0c, 0xbd, 0xbb, 0x28, 0x2d, 0xbd,
+  0x20, 0xf6, 0xab, 0xbd, 0x13, 0x60, 0x8d, 0xbc, 0x49, 0xf2, 0x7e, 0xbd, 0x26, 0x62, 0xf3, 0x3c,
+  0x4e, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xbb, 0xba, 0xc1, 0xbc,
+  0x5d, 0xce, 0x20, 0x3b, 0x7c, 0xb5, 0x6e, 0xbb, 0x50, 0x21, 0x17, 0x3c, 0x08, 0xe9, 0x9a, 0x3b,
+  0x46, 0x7c, 0x95, 0x39, 0x1b, 0x17, 0xca, 0xbd, 0x65, 0x15, 0x3f, 0xbd, 0xa0, 0xfb, 0xff, 0xff,
+  0xa4, 0xfb, 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, 0x54, 0x01, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00,
+  0x5c, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x1a, 0x00, 0x14, 0x00,
+  0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+  0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0xaa, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x5c, 0xfc, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x82, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x04, 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, 0x01, 0x1c, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00,
+  0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x07, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 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, 0x07, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0xb8, 0x02, 0x00, 0x00, 0x74, 0x02, 0x00, 0x00, 0x38, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+  0xc4, 0x01, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00,
+  0xb4, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x86, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x78, 0xfd, 0xff, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x6c, 0x61, 0x62, 0x65,
+  0x6c, 0x73, 0x5f, 0x73, 0x6f, 0x66, 0x74, 0x6d, 0x61, 0x78, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xbe, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0xb0, 0xfd, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x3b, 0x61, 0x64, 0x64, 0x5f, 0x31,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0xf6, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0xe8, 0xfd, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68,
+  0x61, 0x70, 0x65, 0x5f, 0x33, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xa0, 0x0f, 0x00, 0x00, 0x2a, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, 0xfe, 0xff, 0xff, 0x1a, 0x00, 0x00, 0x00,
+  0x52, 0x65, 0x6c, 0x75, 0x3b, 0x61, 0x64, 0x64, 0x3b, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x3b,
+  0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x76, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x68, 0xfe, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68,
+  0x61, 0x70, 0x65, 0x5f, 0x32, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x31, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xb2, 0xfe, 0xff, 0xff,
+  0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0xa4, 0xfe, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00, 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x00, 0xc6, 0xff, 0xff, 0xff,
+  0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x1c, 0x00, 0x00, 0x00, 0xd8, 0xfe, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68,
+  0x61, 0x70, 0x65, 0x5f, 0x32, 0x2f, 0x73, 0x68, 0x61, 0x70, 0x65, 0x00, 0x01, 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, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f, 0x33, 0x2f, 0x73, 0x68,
+  0x61, 0x70, 0x65, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x62, 0xff, 0xff, 0xff,
+  0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x54, 0xff, 0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x66, 0x63,
+  0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x96, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x88, 0xff, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x6e, 0x76,
+  0x32, 0x44, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xce, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
+  0x0a, 0x00, 0x00, 0x00, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x08, 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, 0x09, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x68, 0x61, 0x70, 0x65, 0x5f,
+  0x31, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x07, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xdc, 0xff, 0xff, 0xff, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
+  0xe8, 0xff, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xf4, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 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};
+
+#endif // SPEECH_RECOGNITION_FLOAT_CIRCLE_H
diff --git a/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/test_data.h b/onert-micro/examples/speech_recognition/DISCO_F746/mbed-os/test_data.h
new file mode 100644 (file)
index 0000000..f337e3a
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_DATA_H
+#define TEST_DATA_H
+float test_data[1960] = {
+  25.234375, 23.281250, 25.156250, 23.125000, 25.039062, 23.125000, 25.273438, 23.359375, 25.429688,
+  23.164062, 25.039062, 23.007812, 25.039062, 23.164062, 25.312500, 23.242188, 25.390625, 23.320312,
+  25.468750, 23.125000, 25.234375, 23.320312, 25.351562, 23.125000, 25.000000, 22.929688, 24.492188,
+  23.085938, 25.117188, 22.929688, 24.765625, 22.968750, 24.960938, 22.929688, 24.765625, 22.734375,
+  24.765625, 22.929688, 24.609375, 22.890625, 23.945312, 21.445312, 22.539062, 19.609375, 22.890625,
+  20.703125, 23.437500, 19.726562, 23.437500, 20.585938, 23.828125, 21.601562, 23.671875, 21.210938,
+  23.632812, 20.781250, 23.476562, 21.484375, 23.945312, 21.718750, 23.750000, 20.820312, 23.515625,
+  21.328125, 23.398438, 21.640625, 24.140625, 20.781250, 23.671875, 21.523438, 23.906250, 20.898438,
+  23.320312, 20.625000, 23.398438, 20.625000, 22.695312, 21.250000, 23.164062, 20.859375, 20.195312,
+  13.945312, 22.968750, 19.570312, 22.148438, 21.093750, 22.890625, 20.000000, 22.304688, 20.468750,
+  22.812500, 19.726562, 23.125000, 20.976562, 23.203125, 20.859375, 23.281250, 17.851562, 21.250000,
+  19.648438, 21.328125, 19.296875, 22.695312, 21.132812, 22.539062, 20.585938, 23.007812, 20.664062,
+  22.343750, 20.703125, 22.382812, 20.859375, 21.757812, 19.335938, 22.382812, 20.703125, 21.757812,
+  19.609375, 22.968750, 19.960938, 19.921875, 12.929688, 20.117188, 6.914062,  21.914062, 20.585938,
+  22.890625, 19.765625, 21.796875, 18.554688, 21.796875, 19.179688, 20.000000, 18.164062, 22.343750,
+  20.625000, 20.859375, 17.812500, 21.953125, 20.742188, 22.929688, 18.984375, 22.890625, 19.765625,
+  21.484375, 18.476562, 22.421875, 20.039062, 22.656250, 20.078125, 21.757812, 17.851562, 20.664062,
+  18.515625, 21.093750, 18.867188, 22.148438, 19.023438, 21.835938, 19.609375, 18.750000, 11.601562,
+  16.484375, 10.390625, 19.062500, 18.789062, 21.328125, 18.125000, 21.562500, 18.945312, 21.406250,
+  18.906250, 21.015625, 12.578125, 18.789062, 18.476562, 21.914062, 19.062500, 22.421875, 19.804688,
+  21.250000, 16.601562, 19.648438, 18.593750, 21.835938, 16.992188, 20.351562, 17.265625, 19.960938,
+  16.679688, 21.289062, 18.281250, 20.664062, 17.578125, 19.648438, 17.421875, 20.820312, 17.382812,
+  20.312500, 18.906250, 15.898438, 0.000000,  15.312500, 0.000000,  20.859375, 16.679688, 21.250000,
+  18.945312, 20.429688, 12.421875, 18.828125, 16.679688, 21.796875, 17.734375, 20.625000, 14.609375,
+  21.640625, 16.093750, 20.195312, 17.773438, 19.921875, 15.859375, 20.742188, 18.789062, 22.148438,
+  18.515625, 18.007812, 15.625000, 20.820312, 18.710938, 20.859375, 17.460938, 20.312500, 17.148438,
+  20.156250, 17.851562, 20.351562, 17.773438, 20.859375, 17.421875, 18.906250, 13.789062, 18.906250,
+  11.953125, 21.132812, 19.140625, 20.117188, 10.703125, 14.531250, 9.218750,  17.343750, 17.773438,
+  20.468750, 18.164062, 19.687500, 6.914062,  19.375000, 18.320312, 18.906250, 13.632812, 17.617188,
+  17.070312, 20.234375, 15.351562, 19.882812, 17.851562, 21.171875, 17.109375, 20.234375, 17.109375,
+  18.945312, 13.359375, 20.234375, 17.460938, 20.429688, 16.328125, 19.570312, 13.437500, 19.218750,
+  15.742188, 17.929688, 11.210938, 18.984375, 17.148438, 20.976562, 17.070312, 19.960938, 15.117188,
+  19.531250, 13.242188, 16.406250, 11.210938, 21.171875, 17.968750, 19.921875, 18.437500, 20.117188,
+  15.546875, 19.375000, 18.476562, 19.921875, 15.429688, 19.570312, 15.156250, 19.062500, 13.710938,
+  20.078125, 16.835938, 20.429688, 17.421875, 20.781250, 15.781250, 19.257812, 15.781250, 19.687500,
+  15.820312, 19.375000, 15.156250, 19.531250, 17.265625, 16.171875, 13.710938, 18.984375, 10.390625,
+  17.890625, 13.867188, 20.234375, 15.429688, 16.953125, 16.171875, 15.468750, 12.265625, 20.078125,
+  15.312500, 19.687500, 16.718750, 18.906250, 16.796875, 19.531250, 14.296875, 18.398438, 16.601562,
+  19.531250, 14.375000, 17.382812, 14.804688, 18.984375, 5.195312,  20.312500, 17.421875, 19.609375,
+  14.921875, 19.375000, 16.132812, 19.921875, 16.445312, 18.789062, 14.609375, 19.531250, 17.070312,
+  0.000000,  0.000000,  18.554688, 15.703125, 20.195312, 19.570312, 21.367188, 17.109375, 20.234375,
+  16.484375, 18.242188, 13.515625, 17.851562, 10.078125, 16.328125, 13.242188, 20.703125, 17.148438,
+  17.968750, 15.742188, 19.140625, 13.359375, 16.406250, 17.070312, 20.507812, 16.445312, 19.375000,
+  14.296875, 17.460938, 14.726562, 18.476562, 14.804688, 20.351562, 16.015625, 17.265625, 10.078125,
+  16.757812, 13.437500, 20.703125, 14.492188, 14.492188, 0.000000,  16.484375, 12.929688, 18.984375,
+  15.859375, 18.710938, 15.312500, 20.546875, 15.312500, 17.851562, 10.703125, 18.320312, 11.601562,
+  18.007812, 17.656250, 19.648438, 16.484375, 19.882812, 16.718750, 18.632812, 14.648438, 18.359375,
+  16.953125, 19.453125, 15.742188, 19.531250, 9.687500,  17.773438, 13.945312, 18.164062, 13.359375,
+  18.242188, 16.406250, 19.023438, 10.390625, 18.671875, 14.101562, 18.359375, 14.531250, 0.000000,
+  0.000000,  7.929688,  14.960938, 18.007812, 16.210938, 19.414062, 16.210938, 20.078125, 9.218750,
+  18.593750, 14.726562, 17.656250, 16.289062, 16.601562, 13.046875, 16.679688, 11.601562, 16.640625,
+  12.695312, 17.968750, 10.937500, 20.000000, 14.726562, 17.226562, 15.078125, 18.750000, 13.867188,
+  18.710938, 10.703125, 18.085938, 14.765625, 18.945312, 14.218750, 18.476562, 16.015625, 19.062500,
+  12.148438, 18.750000, 14.804688, 7.929688,  0.000000,  16.171875, 0.000000,  17.812500, 12.695312,
+  18.359375, 0.000000,  16.406250, 14.765625, 19.296875, 15.312500, 18.242188, 10.078125, 14.492188,
+  11.601562, 18.984375, 15.273438, 18.789062, 15.742188, 18.164062, 10.703125, 17.773438, 16.679688,
+  17.968750, 6.914062,  15.820312, 15.234375, 19.804688, 6.914062,  17.187500, 11.796875, 19.218750,
+  14.648438, 18.398438, 14.140625, 18.984375, 12.695312, 17.734375, 12.421875, 14.296875, 6.914062,
+  19.257812, 14.609375, 12.265625, 7.929688,  14.804688, 12.929688, 18.164062, 14.101562, 14.609375,
+  9.687500,  17.695312, 0.000000,  16.289062, 15.585938, 17.148438, 0.000000,  16.914062, 14.492188,
+  18.828125, 11.953125, 17.421875, 10.703125, 18.398438, 15.312500, 19.023438, 15.781250, 19.257812,
+  15.234375, 18.242188, 14.609375, 18.515625, 14.414062, 18.906250, 13.046875, 16.171875, 8.671875,
+  18.593750, 15.312500, 15.117188, 0.000000,  14.882812, 13.359375, 18.476562, 8.671875,  17.304688,
+  0.000000,  15.312500, 14.609375, 18.750000, 11.210938, 10.390625, 5.195312,  17.460938, 14.726562,
+  16.171875, 14.648438, 18.984375, 13.515625, 17.578125, 10.703125, 15.234375, 12.812500, 18.593750,
+  10.390625, 19.335938, 15.664062, 18.515625, 9.687500,  17.265625, 13.515625, 20.000000, 13.945312,
+  18.671875, 14.531250, 17.460938, 9.218750,  17.734375, 10.703125, 16.523438, 11.210938, 18.476562,
+  12.695312, 18.671875, 10.078125, 15.546875, 10.703125, 15.781250, 6.914062,  16.679688, 8.671875,
+  18.515625, 11.953125, 17.226562, 17.304688, 16.679688, 0.000000,  16.406250, 9.218750,  16.914062,
+  5.195312,  16.171875, 0.000000,  15.742188, 10.937500, 16.289062, 14.023438, 17.656250, 11.601562,
+  17.929688, 10.390625, 17.304688, 11.406250, 18.125000, 12.812500, 16.875000, 10.078125, 18.281250,
+  14.492188, 0.000000,  0.000000,  16.171875, 14.492188, 18.554688, 7.929688,  17.421875, 17.578125,
+  18.789062, 16.250000, 18.867188, 14.882812, 16.679688, 14.101562, 13.867188, 9.218750,  17.304688,
+  13.242188, 14.648438, 0.000000,  13.046875, 10.078125, 19.453125, 12.812500, 17.851562, 5.195312,
+  16.484375, 14.414062, 16.250000, 14.140625, 17.656250, 13.867188, 17.343750, 14.140625, 18.203125,
+  12.929688, 16.796875, 11.601562, 17.851562, 11.953125, 6.914062,  0.000000,  14.921875, 5.195312,
+  16.289062, 14.296875, 18.046875, 9.687500,  16.289062, 0.000000,  8.671875,  9.218750,  17.031250,
+  6.914062,  18.125000, 13.359375, 11.953125, 5.195312,  17.734375, 13.046875, 13.242188, 8.671875,
+  18.671875, 11.601562, 16.679688, 12.929688, 19.765625, 12.695312, 17.265625, 0.000000,  14.921875,
+  6.914062,  14.765625, 9.687500,  17.031250, 0.000000,  16.914062, 14.609375, 15.585938, 6.914062,
+  0.000000,  0.000000,  13.125000, 11.953125, 7.929688,  0.000000,  16.523438, 12.695312, 17.421875,
+  10.703125, 19.687500, 13.242188, 14.882812, 7.929688,  13.867188, 0.000000,  15.976562, 9.218750,
+  17.851562, 13.125000, 17.031250, 9.687500,  15.117188, 13.710938, 12.421875, 7.929688,  17.929688,
+  10.390625, 14.921875, 5.195312,  16.250000, 11.406250, 13.710938, 10.078125, 17.265625, 11.796875,
+  17.187500, 11.953125, 14.960938, 6.914062,  10.703125, 14.531250, 17.929688, 12.148438, 18.437500,
+  14.296875, 18.593750, 7.929688,  16.054688, 0.000000,  16.953125, 11.953125, 17.578125, 11.210938,
+  11.601562, 0.000000,  17.265625, 0.000000,  16.679688, 10.937500, 16.210938, 13.046875, 17.734375,
+  0.000000,  15.546875, 12.929688, 16.562500, 9.218750,  16.562500, 10.078125, 17.109375, 13.359375,
+  16.367188, 10.078125, 17.304688, 0.000000,  15.468750, 6.914062,  16.484375, 9.687500,  13.437500,
+  0.000000,  7.929688,  0.000000,  0.000000,  11.601562, 16.953125, 0.000000,  17.070312, 9.218750,
+  18.281250, 10.937500, 0.000000,  0.000000,  12.265625, 0.000000,  12.695312, 0.000000,  12.812500,
+  12.929688, 17.968750, 7.929688,  16.601562, 0.000000,  15.117188, 7.929688,  16.875000, 10.703125,
+  16.484375, 11.953125, 15.468750, 10.078125, 17.734375, 10.703125, 14.609375, 7.929688,  16.171875,
+  12.929688, 13.867188, 6.914062,  0.000000,  0.000000,  15.351562, 13.710938, 14.765625, 0.000000,
+  15.507812, 11.601562, 13.359375, 0.000000,  0.000000,  0.000000,  16.601562, 9.218750,  18.281250,
+  6.914062,  11.796875, 0.000000,  10.937500, 0.000000,  15.078125, 9.687500,  14.218750, 0.000000,
+  16.054688, 6.914062,  15.664062, 0.000000,  13.359375, 0.000000,  17.226562, 12.578125, 16.757812,
+  11.210938, 17.968750, 11.796875, 17.109375, 7.929688,  14.921875, 8.671875,  14.609375, 0.000000,
+  0.000000,  0.000000,  15.625000, 13.515625, 17.304688, 0.000000,  14.609375, 13.789062, 16.171875,
+  0.000000,  17.500000, 13.867188, 11.210938, 0.000000,  14.023438, 13.242188, 17.617188, 0.000000,
+  14.218750, 6.914062,  14.218750, 0.000000,  11.953125, 5.195312,  15.664062, 5.195312,  9.687500,
+  0.000000,  16.796875, 5.195312,  13.242188, 5.195312,  16.132812, 11.406250, 13.359375, 0.000000,
+  14.648438, 13.242188, 15.859375, 8.671875,  11.796875, 0.000000,  7.929688,  0.000000,  12.929688,
+  8.671875,  9.687500,  8.671875,  12.929688, 0.000000,  9.218750,  9.687500,  17.070312, 0.000000,
+  17.109375, 13.125000, 10.390625, 5.195312,  17.382812, 6.914062,  17.226562, 6.914062,  14.023438,
+  7.929688,  15.976562, 0.000000,  13.046875, 9.687500,  14.765625, 10.937500, 14.296875, 0.000000,
+  14.882812, 6.914062,  11.406250, 0.000000,  15.078125, 9.687500,  5.195312,  0.000000,  0.000000,
+  0.000000,  6.914062,  0.000000,  0.000000,  0.000000,  6.914062,  0.000000,  17.343750, 15.976562,
+  14.414062, 0.000000,  10.937500, 0.000000,  14.609375, 8.671875,  17.656250, 10.937500, 17.031250,
+  0.000000,  12.578125, 6.914062,  14.804688, 0.000000,  15.117188, 11.210938, 16.093750, 10.078125,
+  16.523438, 8.671875,  15.976562, 0.000000,  17.148438, 5.195312,  12.812500, 5.195312,  13.515625,
+  0.000000,  14.296875, 12.578125, 15.976562, 0.000000,  15.742188, 13.242188, 17.070312, 11.406250,
+  16.679688, 0.000000,  17.968750, 12.148438, 14.140625, 0.000000,  12.265625, 0.000000,  9.218750,
+  0.000000,  8.671875,  6.914062,  14.375000, 12.265625, 15.703125, 0.000000,  14.218750, 6.914062,
+  14.804688, 11.210938, 16.796875, 9.218750,  11.601562, 5.195312,  12.421875, 5.195312,  15.937500,
+  5.195312,  12.421875, 5.195312,  16.601562, 6.914062,  0.000000,  0.000000,  16.718750, 13.046875,
+  14.218750, 0.000000,  0.000000,  0.000000,  14.726562, 12.421875, 15.703125, 12.148438, 14.101562,
+  0.000000,  13.437500, 0.000000,  0.000000,  5.195312,  11.796875, 0.000000,  11.406250, 0.000000,
+  15.585938, 10.703125, 14.648438, 0.000000,  14.492188, 12.421875, 17.265625, 0.000000,  14.492188,
+  0.000000,  16.484375, 6.914062,  11.953125, 11.601562, 16.054688, 7.929688,  13.046875, 0.000000,
+  0.000000,  11.210938, 16.210938, 0.000000,  17.500000, 0.000000,  14.960938, 9.687500,  0.000000,
+  0.000000,  6.914062,  0.000000,  0.000000,  0.000000,  0.000000,  0.000000,  12.695312, 7.929688,
+  15.351562, 10.937500, 14.023438, 9.687500,  15.468750, 6.914062,  17.109375, 8.671875,  15.546875,
+  0.000000,  13.789062, 5.195312,  13.515625, 0.000000,  9.687500,  7.929688,  12.148438, 0.000000,
+  14.531250, 0.000000,  14.140625, 5.195312,  0.000000,  6.914062,  17.578125, 8.671875,  14.609375,
+  10.703125, 15.859375, 0.000000,  11.796875, 0.000000,  0.000000,  0.000000,  5.195312,  11.601562,
+  12.578125, 10.703125, 17.773438, 10.078125, 16.171875, 0.000000,  11.406250, 6.914062,  14.101562,
+  12.148438, 16.015625, 0.000000,  9.687500,  0.000000,  11.406250, 0.000000,  16.171875, 11.210938,
+  14.414062, 0.000000,  11.601562, 5.195312,  13.789062, 5.195312,  14.218750, 5.195312,  13.437500,
+  8.671875,  14.218750, 6.914062,  13.359375, 13.632812, 14.609375, 0.000000,  13.515625, 13.632812,
+  9.218750,  0.000000,  10.078125, 7.929688,  15.742188, 10.703125, 13.437500, 5.195312,  10.390625,
+  0.000000,  17.031250, 11.210938, 9.687500,  0.000000,  14.726562, 10.390625, 11.953125, 0.000000,
+  14.609375, 13.867188, 6.914062,  0.000000,  11.210938, 0.000000,  9.687500,  0.000000,  12.265625,
+  0.000000,  14.375000, 9.218750,  13.437500, 10.390625, 13.242188, 6.914062,  12.578125, 11.601562,
+  17.929688, 0.000000,  9.218750,  10.703125, 14.296875, 0.000000,  15.429688, 5.195312,  16.796875,
+  14.609375, 0.000000,  0.000000,  10.703125, 10.078125, 17.226562, 7.929688,  15.273438, 0.000000,
+  11.210938, 6.914062,  12.578125, 9.218750,  16.210938, 9.218750,  12.578125, 7.929688,  11.953125,
+  6.914062,  13.710938, 0.000000,  10.937500, 6.914062,  13.515625, 7.929688,  0.000000,  0.000000,
+  0.000000,  0.000000,  0.000000,  6.914062,  16.406250, 0.000000,  0.000000,  10.390625, 13.359375,
+  5.195312,  0.000000,  6.914062,  17.343750, 0.000000,  5.195312,  5.195312,  12.812500, 6.914062,
+  0.000000,  7.929688,  15.078125, 0.000000,  0.000000,  0.000000,  0.000000,  9.218750,  13.632812,
+  5.195312,  13.710938, 8.671875,  12.578125, 0.000000,  15.156250, 6.914062,  11.406250, 0.000000,
+  7.929688,  0.000000,  12.148438, 10.078125, 16.679688, 7.929688,  15.625000, 0.000000,  9.687500,
+  0.000000,  9.218750,  0.000000,  16.601562, 6.914062,  0.000000,  0.000000,  9.687500,  0.000000,
+  14.960938, 5.195312,  0.000000,  6.914062,  13.867188, 0.000000,  0.000000,  0.000000,  10.703125,
+  6.914062,  11.796875, 0.000000,  0.000000,  0.000000,  13.359375, 0.000000,  12.578125, 0.000000,
+  14.140625, 9.687500,  11.601562, 0.000000,  11.210938, 0.000000,  13.359375, 0.000000,  0.000000,
+  0.000000,  16.328125, 0.000000,  13.945312, 7.929688,  14.804688, 0.000000,  13.515625, 6.914062,
+  0.000000,  0.000000,  0.000000,  0.000000,  0.000000,  0.000000,  11.601562, 10.078125, 11.406250,
+  11.601562, 15.976562, 7.929688,  10.390625, 0.000000,  11.796875, 0.000000,  8.671875,  0.000000,
+  10.703125, 0.000000,  0.000000,  0.000000,  12.695312, 0.000000,  10.078125, 0.000000,  13.125000,
+  5.195312,  7.929688,  10.937500, 12.929688, 7.929688,  6.914062,  0.000000,  0.000000,  10.078125,
+  16.835938, 6.914062,  5.195312,  6.914062,  0.000000,  0.000000,  15.039062, 9.687500,  0.000000,
+  12.812500, 11.601562, 0.000000,  15.273438, 0.000000,  11.796875, 11.210938, 17.500000, 0.000000,
+  13.046875, 0.000000,  10.078125, 0.000000,  10.937500, 8.671875,  13.242188, 0.000000,  11.953125,
+  6.914062,  14.726562, 9.687500,  14.296875, 0.000000,  0.000000,  0.000000,  15.585938, 0.000000,
+  13.710938, 0.000000,  0.000000,  0.000000,  0.000000,  0.000000,  0.000000,  0.000000,  8.671875,
+  0.000000,  13.242188, 0.000000,  0.000000,  0.000000,  13.710938, 0.000000,  16.875000, 13.125000,
+  12.929688, 0.000000,  7.929688,  0.000000,  8.671875,  10.390625, 16.171875, 10.390625, 12.695312,
+  0.000000,  0.000000,  0.000000,  11.953125, 6.914062,  14.023438, 0.000000,  14.218750, 7.929688,
+  6.914062,  7.929688,  11.953125, 0.000000,  0.000000,  0.000000,  12.265625, 17.304688, 18.906250,
+  7.929688,  16.679688, 12.265625, 11.796875, 0.000000,  6.914062,  0.000000,  17.226562, 7.929688,
+  10.390625, 0.000000,  9.218750,  10.937500, 14.960938, 0.000000,  11.953125, 0.000000,  11.406250,
+  0.000000,  5.195312,  0.000000,  11.406250, 9.687500,  11.601562, 5.195312,  10.703125, 5.195312,
+  10.078125, 6.914062,  12.695312, 0.000000,  0.000000,  0.000000,  0.000000,  0.000000,  0.000000,
+  0.000000,  10.078125, 0.000000,  15.078125, 12.148438, 13.632812, 0.000000,  12.578125, 0.000000,
+  12.695312, 0.000000,  0.000000,  0.000000,  10.078125, 0.000000,  0.000000,  0.000000,  5.195312,
+  11.406250, 16.914062, 5.195312,  6.914062,  9.218750,  13.515625, 6.914062,  10.390625, 0.000000,
+  9.687500,  0.000000,  13.125000, 0.000000,  13.125000, 6.914062,  10.078125, 0.000000,  7.929688,
+  0.000000,  0.000000,  0.000000,  15.625000, 11.406250, 6.914062,  0.000000,  8.671875,  0.000000,
+  0.000000,  0.000000,  11.406250, 0.000000,  11.796875, 6.914062,  15.078125, 0.000000,  0.000000,
+  0.000000,  15.859375, 10.390625, 15.468750, 5.195312,  9.218750,  0.000000,  0.000000,  0.000000,
+  0.000000,  5.195312,  13.945312, 0.000000,  5.195312,  0.000000,  9.218750,  6.914062,  13.515625,
+  0.000000,  9.218750,  0.000000,  15.234375, 0.000000,  9.687500,  5.195312,  13.710938, 0.000000,
+  14.414062, 10.078125, 12.265625, 0.000000,  16.289062, 0.000000,  16.484375, 10.078125, 14.804688,
+  6.914062,  14.414062, 0.000000,  13.632812, 0.000000,  10.937500, 10.390625, 10.078125, 7.929688,
+  15.859375, 8.671875,  12.421875, 0.000000,  10.390625, 0.000000,  13.867188, 5.195312,  5.195312,
+  0.000000,  11.210938, 0.000000,  10.390625, 13.125000, 13.046875, 0.000000,  0.000000,  0.000000,
+  14.804688, 5.195312,  0.000000,  0.000000,  11.210938, 13.359375, 16.250000, 13.945312, 11.953125,
+  11.406250, 6.914062,  0.000000,  16.445312, 5.195312,  8.671875,  0.000000,  0.000000,  5.195312,
+  15.546875, 7.929688,  10.703125, 0.000000,  11.406250, 5.195312,  5.195312,  0.000000,  15.117188,
+  13.359375, 12.695312, 8.671875,  11.796875, 0.000000,  10.703125, 0.000000,  5.195312,  0.000000,
+  13.437500, 0.000000,  16.015625, 0.000000,  0.000000,  0.000000,  13.125000, 8.671875,  11.210938,
+  0.000000,  0.000000,  0.000000,  13.359375, 0.000000,  0.000000,  0.000000,  12.265625, 10.937500,
+  13.242188, 10.937500, 13.046875, 0.000000,  6.914062,  0.000000,  10.390625, 0.000000,  11.406250,
+  0.000000,  10.703125, 7.929688,  8.671875,  0.000000,  0.000000,  6.914062,  11.601562, 0.000000,
+  6.914062,  0.000000,  10.390625, 10.390625, 9.218750,  0.000000,  9.218750,  0.000000,  0.000000,
+  0.000000,  6.914062,  11.796875, 15.859375, 0.000000,  0.000000,  0.000000,  0.000000,  0.000000,
+  0.000000,  8.671875,  15.976562, 0.000000,  9.687500,  8.671875,  13.125000, 0.000000,  0.000000,
+  0.000000,  14.296875, 12.265625, 15.312500, 8.671875,  10.937500, 0.000000,  5.195312,  0.000000,
+  12.265625, 10.937500, 12.929688, 0.000000,  7.929688,  0.000000,  11.953125, 0.000000,  11.953125,
+  5.195312,  0.000000,  0.000000,  10.390625, 0.000000,  12.812500, 5.195312,  14.218750, 12.812500,
+  14.375000, 0.000000,  15.429688, 7.929688,  10.078125, 0.000000,  16.093750, 0.000000,  12.695312,
+  0.000000,  6.914062,  10.703125, 15.156250, 10.078125, 17.031250, 0.000000,  0.000000,  0.000000,
+  8.671875,  0.000000,  11.796875, 0.000000,  12.421875, 0.000000,  12.265625, 0.000000,  9.218750,
+  0.000000,  13.359375, 0.000000,  13.242188, 0.000000,  0.000000,  0.000000,  11.406250, 0.000000,
+  13.945312, 10.390625, 12.695312, 0.000000,  11.796875, 10.390625, 12.148438, 0.000000,  10.390625,
+  13.125000, 0.000000,  0.000000,  13.125000, 5.195312,  10.390625, 0.000000,  8.671875,  0.000000,
+  10.937500, 0.000000,  0.000000,  0.000000,  9.218750,  11.406250, 11.406250, 0.000000,  0.000000,
+  0.000000,  5.195312,  0.000000,  12.148438, 7.929688,  14.726562, 0.000000,  11.796875, 6.914062,
+  15.039062, 11.953125, 11.796875, 5.195312,  13.437500, 9.687500,  16.718750, 10.390625, 10.078125,
+  0.000000,  5.195312,  0.000000,  15.664062, 12.929688, 12.695312, 0.000000,  6.914062,  0.000000,
+  0.000000,  0.000000,  6.914062,  0.000000,  14.531250, 0.000000,  12.812500, 0.000000,  13.359375,
+  0.000000,  0.000000,  0.000000,  9.687500,  9.687500,  11.953125, 8.671875,  12.421875, 5.195312,
+  12.148438, 0.000000,  9.218750,  0.000000,  0.000000,  0.000000,  0.000000,  0.000000,  0.000000,
+  0.000000,  13.359375, 9.218750,  16.054688, 5.195312,  0.000000,  0.000000,  0.000000,  0.000000,
+  0.000000,  0.000000,  13.867188, 5.195312,  14.101562, 6.914062,  11.210938, 0.000000,  12.265625,
+  0.000000,  0.000000,  0.000000,  0.000000,  6.914062,  13.125000, 0.000000,  0.000000,  0.000000,
+  11.796875, 8.671875,  11.406250, 5.195312,  10.937500, 10.703125, 14.375000, 10.703125, 13.125000,
+  5.195312,  11.210938, 0.000000,  13.242188, 0.000000,  5.195312,  0.000000,  0.000000,  0.000000,
+  9.687500,  5.195312,  12.812500, 7.929688,  0.000000,  0.000000,  14.218750, 0.000000,  0.000000,
+  0.000000,  0.000000,  6.914062,  12.148438, 0.000000,  10.390625, 0.000000,  0.000000,  0.000000,
+  5.195312,  0.000000,  5.195312,  0.000000,  7.929688,  6.914062,  9.218750,  0.000000,  13.242188,
+  0.000000,  10.703125, 5.195312,  7.929688,  0.000000,  0.000000,  6.914062,  0.000000,  0.000000,
+  7.929688,  0.000000,  0.000000,  0.000000,  14.101562, 8.671875,  10.390625, 0.000000,  0.000000,
+  0.000000,  11.210938, 0.000000,  15.898438, 5.195312,  5.195312,  0.000000,  5.195312,  8.671875,
+  14.101562, 0.000000,  6.914062,  0.000000,  0.000000,  0.000000,  6.914062,  0.000000,  10.703125,
+  0.000000,  10.078125, 0.000000,  5.195312,  0.000000,  10.078125, 0.000000};
+#endif // TEST_DATA_H
diff --git a/onert-micro/externals/.FORMATDENY b/onert-micro/externals/.FORMATDENY
new file mode 100644 (file)
index 0000000..e69de29
index 221001c..5bf1dc4 100644 (file)
@@ -1,9 +1,8 @@
-unset(OUTPUT_FILES)
-set(OUTPUT_FILES "${ONERT_MICRO_EXTERNAL_DIR}/gen/circle-generated/circle/schema_generated.h")
-set(TGT luci_micro_circle_schema)
+unset(SOURCES)
+set(SOURCES "${ONERT_MICRO_EXTERNAL_DIR}/gen/circle-generated/circle/schema_generated.h")
 
 # 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}")
+add_library(${OM_CIRCLE_SCHEMA} STATIC ${SOURCES})
+set_target_properties(${OM_CIRCLE_SCHEMA} PROPERTIES LINKER_LANGUAGE CXX)
+target_include_directories(${OM_CIRCLE_SCHEMA} PUBLIC "${ONERT_MICRO_EXTERNAL_DIR}/gen")
+target_include_directories(${OM_CIRCLE_SCHEMA} PUBLIC "${ONERT_MICRO_EXTERNAL_DIR}")
index 2531319..d71257d 100644 (file)
@@ -1,19 +1,3 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_
@@ -52,6 +36,10 @@ struct SparsityParameters;
 struct SparsityParametersBuilder;
 struct SparsityParametersT;
 
+struct VariantSubType;
+struct VariantSubTypeBuilder;
+struct VariantSubTypeT;
+
 struct Tensor;
 struct TensorBuilder;
 struct TensorT;
@@ -512,6 +500,54 @@ struct RandomOptions;
 struct RandomOptionsBuilder;
 struct RandomOptionsT;
 
+struct BucketizeOptions;
+struct BucketizeOptionsBuilder;
+struct BucketizeOptionsT;
+
+struct GeluOptions;
+struct GeluOptionsBuilder;
+struct GeluOptionsT;
+
+struct DynamicUpdateSliceOptions;
+struct DynamicUpdateSliceOptionsBuilder;
+struct DynamicUpdateSliceOptionsT;
+
+struct UnsortedSegmentProdOptions;
+struct UnsortedSegmentProdOptionsBuilder;
+struct UnsortedSegmentProdOptionsT;
+
+struct UnsortedSegmentMaxOptions;
+struct UnsortedSegmentMaxOptionsBuilder;
+struct UnsortedSegmentMaxOptionsT;
+
+struct UnsortedSegmentSumOptions;
+struct UnsortedSegmentSumOptionsBuilder;
+struct UnsortedSegmentSumOptionsT;
+
+struct ATan2Options;
+struct ATan2OptionsBuilder;
+struct ATan2OptionsT;
+
+struct UnsortedSegmentMinOptions;
+struct UnsortedSegmentMinOptionsBuilder;
+struct UnsortedSegmentMinOptionsT;
+
+struct SignOptions;
+struct SignOptionsBuilder;
+struct SignOptionsT;
+
+struct BitcastOptions;
+struct BitcastOptionsBuilder;
+struct BitcastOptionsT;
+
+struct BitwiseXorOptions;
+struct BitwiseXorOptionsBuilder;
+struct BitwiseXorOptionsT;
+
+struct RightShiftOptions;
+struct RightShiftOptionsBuilder;
+struct RightShiftOptionsT;
+
 struct BCQGatherOptions;
 struct BCQGatherOptionsBuilder;
 struct BCQGatherOptionsT;
@@ -574,32 +610,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];
@@ -1036,11 +1075,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,
@@ -1191,13 +1245,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",
                                          "",
@@ -1348,14 +1417,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];
@@ -1478,6 +1561,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,
@@ -1485,7 +1580,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,
@@ -1602,6 +1697,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};
@@ -1725,18 +1832,18 @@ inline const char *const *EnumNamesBuiltinOptions()
                                          "ReadVariableOptions",
                                          "AssignVariableOptions",
                                          "RandomOptions",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
+                                         "BucketizeOptions",
+                                         "GeluOptions",
+                                         "DynamicUpdateSliceOptions",
+                                         "UnsortedSegmentProdOptions",
+                                         "UnsortedSegmentMaxOptions",
+                                         "UnsortedSegmentMinOptions",
+                                         "UnsortedSegmentSumOptions",
+                                         "ATan2Options",
+                                         "SignOptions",
+                                         "BitcastOptions",
+                                         "BitwiseXorOptions",
+                                         "RightShiftOptions",
                                          "",
                                          "",
                                          "",
@@ -2452,6 +2559,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;
@@ -3824,6 +3991,147 @@ struct BuiltinOptionsUnion
              ? reinterpret_cast<const circle::RandomOptionsT *>(value)
              : nullptr;
   }
+  circle::BucketizeOptionsT *AsBucketizeOptions()
+  {
+    return type == BuiltinOptions_BucketizeOptions
+             ? reinterpret_cast<circle::BucketizeOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::BucketizeOptionsT *AsBucketizeOptions() const
+  {
+    return type == BuiltinOptions_BucketizeOptions
+             ? reinterpret_cast<const circle::BucketizeOptionsT *>(value)
+             : nullptr;
+  }
+  circle::GeluOptionsT *AsGeluOptions()
+  {
+    return type == BuiltinOptions_GeluOptions ? reinterpret_cast<circle::GeluOptionsT *>(value)
+                                              : nullptr;
+  }
+  const circle::GeluOptionsT *AsGeluOptions() const
+  {
+    return type == BuiltinOptions_GeluOptions
+             ? reinterpret_cast<const circle::GeluOptionsT *>(value)
+             : nullptr;
+  }
+  circle::DynamicUpdateSliceOptionsT *AsDynamicUpdateSliceOptions()
+  {
+    return type == BuiltinOptions_DynamicUpdateSliceOptions
+             ? reinterpret_cast<circle::DynamicUpdateSliceOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::DynamicUpdateSliceOptionsT *AsDynamicUpdateSliceOptions() const
+  {
+    return type == BuiltinOptions_DynamicUpdateSliceOptions
+             ? reinterpret_cast<const circle::DynamicUpdateSliceOptionsT *>(value)
+             : nullptr;
+  }
+  circle::UnsortedSegmentProdOptionsT *AsUnsortedSegmentProdOptions()
+  {
+    return type == BuiltinOptions_UnsortedSegmentProdOptions
+             ? reinterpret_cast<circle::UnsortedSegmentProdOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::UnsortedSegmentProdOptionsT *AsUnsortedSegmentProdOptions() const
+  {
+    return type == BuiltinOptions_UnsortedSegmentProdOptions
+             ? reinterpret_cast<const circle::UnsortedSegmentProdOptionsT *>(value)
+             : nullptr;
+  }
+  circle::UnsortedSegmentMaxOptionsT *AsUnsortedSegmentMaxOptions()
+  {
+    return type == BuiltinOptions_UnsortedSegmentMaxOptions
+             ? reinterpret_cast<circle::UnsortedSegmentMaxOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::UnsortedSegmentMaxOptionsT *AsUnsortedSegmentMaxOptions() const
+  {
+    return type == BuiltinOptions_UnsortedSegmentMaxOptions
+             ? reinterpret_cast<const circle::UnsortedSegmentMaxOptionsT *>(value)
+             : nullptr;
+  }
+  circle::UnsortedSegmentMinOptionsT *AsUnsortedSegmentMinOptions()
+  {
+    return type == BuiltinOptions_UnsortedSegmentMinOptions
+             ? reinterpret_cast<circle::UnsortedSegmentMinOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::UnsortedSegmentMinOptionsT *AsUnsortedSegmentMinOptions() const
+  {
+    return type == BuiltinOptions_UnsortedSegmentMinOptions
+             ? reinterpret_cast<const circle::UnsortedSegmentMinOptionsT *>(value)
+             : nullptr;
+  }
+  circle::UnsortedSegmentSumOptionsT *AsUnsortedSegmentSumOptions()
+  {
+    return type == BuiltinOptions_UnsortedSegmentSumOptions
+             ? reinterpret_cast<circle::UnsortedSegmentSumOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::UnsortedSegmentSumOptionsT *AsUnsortedSegmentSumOptions() const
+  {
+    return type == BuiltinOptions_UnsortedSegmentSumOptions
+             ? reinterpret_cast<const circle::UnsortedSegmentSumOptionsT *>(value)
+             : nullptr;
+  }
+  circle::ATan2OptionsT *AsATan2Options()
+  {
+    return type == BuiltinOptions_ATan2Options ? reinterpret_cast<circle::ATan2OptionsT *>(value)
+                                               : nullptr;
+  }
+  const circle::ATan2OptionsT *AsATan2Options() const
+  {
+    return type == BuiltinOptions_ATan2Options
+             ? reinterpret_cast<const circle::ATan2OptionsT *>(value)
+             : nullptr;
+  }
+  circle::SignOptionsT *AsSignOptions()
+  {
+    return type == BuiltinOptions_SignOptions ? reinterpret_cast<circle::SignOptionsT *>(value)
+                                              : nullptr;
+  }
+  const circle::SignOptionsT *AsSignOptions() const
+  {
+    return type == BuiltinOptions_SignOptions
+             ? reinterpret_cast<const circle::SignOptionsT *>(value)
+             : nullptr;
+  }
+  circle::BitcastOptionsT *AsBitcastOptions()
+  {
+    return type == BuiltinOptions_BitcastOptions
+             ? reinterpret_cast<circle::BitcastOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::BitcastOptionsT *AsBitcastOptions() const
+  {
+    return type == BuiltinOptions_BitcastOptions
+             ? reinterpret_cast<const circle::BitcastOptionsT *>(value)
+             : nullptr;
+  }
+  circle::BitwiseXorOptionsT *AsBitwiseXorOptions()
+  {
+    return type == BuiltinOptions_BitwiseXorOptions
+             ? reinterpret_cast<circle::BitwiseXorOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::BitwiseXorOptionsT *AsBitwiseXorOptions() const
+  {
+    return type == BuiltinOptions_BitwiseXorOptions
+             ? reinterpret_cast<const circle::BitwiseXorOptionsT *>(value)
+             : nullptr;
+  }
+  circle::RightShiftOptionsT *AsRightShiftOptions()
+  {
+    return type == BuiltinOptions_RightShiftOptions
+             ? reinterpret_cast<circle::RightShiftOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::RightShiftOptionsT *AsRightShiftOptions() const
+  {
+    return type == BuiltinOptions_RightShiftOptions
+             ? reinterpret_cast<const circle::RightShiftOptionsT *>(value)
+             : nullptr;
+  }
   circle::BCQGatherOptionsT *AsBCQGatherOptions()
   {
     return type == BuiltinOptions_BCQGatherOptions
@@ -4909,6 +5217,100 @@ flatbuffers::Offset<SparsityParameters>
 CreateSparsityParameters(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT *_o,
                          const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
+struct VariantSubTypeT : public flatbuffers::NativeTable
+{
+  typedef VariantSubType TableType;
+  std::vector<int32_t> shape{};
+  circle::TensorType type = circle::TensorType_FLOAT32;
+  bool has_rank = false;
+};
+
+struct VariantSubType FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+  typedef VariantSubTypeT NativeTableType;
+  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();
+  }
+  VariantSubTypeT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(VariantSubTypeT *_o,
+                const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<VariantSubType>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT *_o,
+       const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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);
+}
+
+flatbuffers::Offset<VariantSubType>
+CreateVariantSubType(flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
 struct TensorT : public flatbuffers::NativeTable
 {
   typedef Tensor TableType;
@@ -4920,6 +5322,8 @@ struct TensorT : public flatbuffers::NativeTable
   bool is_variable = false;
   std::unique_ptr<circle::SparsityParametersT> sparsity{};
   std::vector<int32_t> shape_signature{};
+  bool has_rank = false;
+  std::vector<std::unique_ptr<circle::VariantSubTypeT>> variant_tensors{};
 };
 
 struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
@@ -4935,7 +5339,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
   {
@@ -4963,6 +5369,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) &&
@@ -4972,7 +5384,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();
   }
   TensorT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
   void UnPackTo(TensorT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
@@ -5015,6 +5429,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();
@@ -5027,22 +5451,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();
@@ -5053,13 +5480,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__);
 }
 
 flatbuffers::Offset<Tensor>
@@ -6745,6 +7177,7 @@ struct UnidirectionalSequenceLSTMOptionsT : public flatbuffers::NativeTable
   float proj_clip = 0.0f;
   bool time_major = false;
   bool asymmetric_quantize_inputs = false;
+  bool diagonal_recurrent_tensors = false;
 };
 
 struct UnidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
@@ -6757,7 +7190,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
   {
@@ -6771,6 +7205,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) &&
@@ -6778,7 +7216,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();
   }
   UnidirectionalSequenceLSTMOptionsT *
   UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
@@ -6817,6 +7256,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)
   {
@@ -6835,11 +7279,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);
@@ -9216,6 +9661,7 @@ struct TransposeConvOptionsT : public flatbuffers::NativeTable
   circle::Padding padding = circle::Padding_SAME;
   int32_t stride_w = 0;
   int32_t stride_h = 0;
+  circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
 };
 
 struct TransposeConvOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
@@ -9226,7 +9672,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
   {
@@ -9234,11 +9681,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();
   }
   TransposeConvOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
   void UnPackTo(TransposeConvOptionsT *_o,
@@ -9265,6 +9718,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();
@@ -9277,14 +9735,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();
 }
@@ -12289,8 +12748,8 @@ CreateAssignVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const AssignVa
 struct RandomOptionsT : public flatbuffers::NativeTable
 {
   typedef RandomOptions TableType;
-  int32_t seed = 0;
-  int32_t seed2 = 0;
+  int64_t seed = 0;
+  int64_t seed2 = 0;
 };
 
 struct RandomOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
@@ -12302,12 +12761,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();
   }
   RandomOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
   void UnPackTo(RandomOptionsT *_o,
@@ -12322,8 +12781,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();
@@ -12337,7 +12796,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);
@@ -12349,1273 +12808,1977 @@ flatbuffers::Offset<RandomOptions>
 CreateRandomOptions(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT *_o,
                     const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
-struct BCQGatherOptionsT : public flatbuffers::NativeTable
+struct BucketizeOptionsT : public flatbuffers::NativeTable
 {
-  typedef BCQGatherOptions TableType;
-  int32_t input_hidden_size = 0;
-  int32_t axis = 0;
+  typedef BucketizeOptions TableType;
+  std::vector<float> boundaries{};
 };
 
-struct BCQGatherOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+struct BucketizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
 {
-  typedef BCQGatherOptionsT NativeTableType;
-  typedef BCQGatherOptionsBuilder Builder;
+  typedef BucketizeOptionsT NativeTableType;
+  typedef BucketizeOptionsBuilder Builder;
   enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
   {
-    VT_INPUT_HIDDEN_SIZE = 4,
-    VT_AXIS = 6
+    VT_BOUNDARIES = 4
   };
-  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); }
+  const flatbuffers::Vector<float> *boundaries() const
+  {
+    return GetPointer<const flatbuffers::Vector<float> *>(VT_BOUNDARIES);
+  }
   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();
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_BOUNDARIES) &&
+           verifier.VerifyVector(boundaries()) && verifier.EndTable();
   }
-  BCQGatherOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
-  void UnPackTo(BCQGatherOptionsT *_o,
+  BucketizeOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(BucketizeOptionsT *_o,
                 const flatbuffers::resolver_function_t *_resolver = nullptr) const;
-  static flatbuffers::Offset<BCQGatherOptions>
-  Pack(flatbuffers::FlatBufferBuilder &_fbb, const BCQGatherOptionsT *_o,
+  static flatbuffers::Offset<BucketizeOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT *_o,
        const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 };
 
-struct BCQGatherOptionsBuilder
+struct BucketizeOptionsBuilder
 {
-  typedef BCQGatherOptions Table;
+  typedef BucketizeOptions Table;
   flatbuffers::FlatBufferBuilder &fbb_;
   flatbuffers::uoffset_t start_;
-  void add_input_hidden_size(int32_t input_hidden_size)
+  void add_boundaries(flatbuffers::Offset<flatbuffers::Vector<float>> boundaries)
   {
-    fbb_.AddElement<int32_t>(BCQGatherOptions::VT_INPUT_HIDDEN_SIZE, input_hidden_size, 0);
+    fbb_.AddOffset(BucketizeOptions::VT_BOUNDARIES, boundaries);
   }
-  void add_axis(int32_t axis) { fbb_.AddElement<int32_t>(BCQGatherOptions::VT_AXIS, axis, 0); }
-  explicit BCQGatherOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  explicit BucketizeOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
     start_ = fbb_.StartTable();
   }
-  flatbuffers::Offset<BCQGatherOptions> Finish()
+  flatbuffers::Offset<BucketizeOptions> Finish()
   {
     const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<BCQGatherOptions>(end);
+    auto o = flatbuffers::Offset<BucketizeOptions>(end);
     return o;
   }
 };
 
-inline flatbuffers::Offset<BCQGatherOptions>
-CreateBCQGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, int32_t input_hidden_size = 0,
-                       int32_t axis = 0)
+inline flatbuffers::Offset<BucketizeOptions>
+CreateBucketizeOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                       flatbuffers::Offset<flatbuffers::Vector<float>> boundaries = 0)
 {
-  BCQGatherOptionsBuilder builder_(_fbb);
-  builder_.add_axis(axis);
-  builder_.add_input_hidden_size(input_hidden_size);
+  BucketizeOptionsBuilder builder_(_fbb);
+  builder_.add_boundaries(boundaries);
   return builder_.Finish();
 }
 
-flatbuffers::Offset<BCQGatherOptions>
-CreateBCQGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, const BCQGatherOptionsT *_o,
+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__);
+}
+
+flatbuffers::Offset<BucketizeOptions>
+CreateBucketizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT *_o,
                        const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
-struct BCQFullyConnectedOptionsT : public flatbuffers::NativeTable
+struct GeluOptionsT : public flatbuffers::NativeTable
 {
-  typedef BCQFullyConnectedOptions TableType;
-  int32_t weights_hidden_size = 0;
-  circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+  typedef GeluOptions TableType;
+  bool approximate = false;
 };
 
-struct BCQFullyConnectedOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+struct GeluOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
 {
-  typedef BCQFullyConnectedOptionsT NativeTableType;
-  typedef BCQFullyConnectedOptionsBuilder Builder;
+  typedef GeluOptionsT NativeTableType;
+  typedef GeluOptionsBuilder Builder;
   enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
   {
-    VT_WEIGHTS_HIDDEN_SIZE = 4,
-    VT_FUSED_ACTIVATION_FUNCTION = 6
+    VT_APPROXIMATE = 4
   };
-  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 approximate() const { return GetField<uint8_t>(VT_APPROXIMATE, 0) != 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();
+    return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_APPROXIMATE) &&
+           verifier.EndTable();
   }
-  BCQFullyConnectedOptionsT *
-  UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
-  void UnPackTo(BCQFullyConnectedOptionsT *_o,
+  GeluOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(GeluOptionsT *_o,
                 const flatbuffers::resolver_function_t *_resolver = nullptr) const;
-  static flatbuffers::Offset<BCQFullyConnectedOptions>
-  Pack(flatbuffers::FlatBufferBuilder &_fbb, const BCQFullyConnectedOptionsT *_o,
+  static flatbuffers::Offset<GeluOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT *_o,
        const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 };
 
-struct BCQFullyConnectedOptionsBuilder
+struct GeluOptionsBuilder
 {
-  typedef BCQFullyConnectedOptions Table;
+  typedef GeluOptions 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)
+  void add_approximate(bool approximate)
   {
-    fbb_.AddElement<int8_t>(BCQFullyConnectedOptions::VT_FUSED_ACTIVATION_FUNCTION,
-                            static_cast<int8_t>(fused_activation_function), 0);
+    fbb_.AddElement<uint8_t>(GeluOptions::VT_APPROXIMATE, static_cast<uint8_t>(approximate), 0);
   }
-  explicit BCQFullyConnectedOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  explicit GeluOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
     start_ = fbb_.StartTable();
   }
-  flatbuffers::Offset<BCQFullyConnectedOptions> Finish()
+  flatbuffers::Offset<GeluOptions> Finish()
   {
     const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<BCQFullyConnectedOptions>(end);
+    auto o = flatbuffers::Offset<GeluOptions>(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)
+inline flatbuffers::Offset<GeluOptions> CreateGeluOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                                          bool approximate = false)
 {
-  BCQFullyConnectedOptionsBuilder builder_(_fbb);
-  builder_.add_weights_hidden_size(weights_hidden_size);
-  builder_.add_fused_activation_function(fused_activation_function);
+  GeluOptionsBuilder builder_(_fbb);
+  builder_.add_approximate(approximate);
   return builder_.Finish();
 }
 
-flatbuffers::Offset<BCQFullyConnectedOptions>
-CreateBCQFullyConnectedOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                               const BCQFullyConnectedOptionsT *_o,
-                               const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+flatbuffers::Offset<GeluOptions>
+CreateGeluOptions(flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
-struct InstanceNormOptionsT : public flatbuffers::NativeTable
+struct DynamicUpdateSliceOptionsT : public flatbuffers::NativeTable
 {
-  typedef InstanceNormOptions TableType;
-  float epsilon = 0.0f;
-  circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+  typedef DynamicUpdateSliceOptions TableType;
 };
 
-struct InstanceNormOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+struct DynamicUpdateSliceOptions 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));
-  }
+  typedef DynamicUpdateSliceOptionsT NativeTableType;
+  typedef DynamicUpdateSliceOptionsBuilder Builder;
   bool Verify(flatbuffers::Verifier &verifier) const
   {
-    return VerifyTableStart(verifier) && VerifyField<float>(verifier, VT_EPSILON) &&
-           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
+    return VerifyTableStart(verifier) && verifier.EndTable();
   }
-  InstanceNormOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
-  void UnPackTo(InstanceNormOptionsT *_o,
+  DynamicUpdateSliceOptionsT *
+  UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(DynamicUpdateSliceOptionsT *_o,
                 const flatbuffers::resolver_function_t *_resolver = nullptr) const;
-  static flatbuffers::Offset<InstanceNormOptions>
-  Pack(flatbuffers::FlatBufferBuilder &_fbb, const InstanceNormOptionsT *_o,
+  static flatbuffers::Offset<DynamicUpdateSliceOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const DynamicUpdateSliceOptionsT *_o,
        const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 };
 
-struct InstanceNormOptionsBuilder
+struct DynamicUpdateSliceOptionsBuilder
 {
-  typedef InstanceNormOptions Table;
+  typedef DynamicUpdateSliceOptions 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)
+  explicit DynamicUpdateSliceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
     start_ = fbb_.StartTable();
   }
-  flatbuffers::Offset<InstanceNormOptions> Finish()
+  flatbuffers::Offset<DynamicUpdateSliceOptions> Finish()
   {
     const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<InstanceNormOptions>(end);
+    auto o = flatbuffers::Offset<DynamicUpdateSliceOptions>(end);
     return o;
   }
 };
 
-inline flatbuffers::Offset<InstanceNormOptions> CreateInstanceNormOptions(
-  flatbuffers::FlatBufferBuilder &_fbb, float epsilon = 0.0f,
-  circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE)
+inline flatbuffers::Offset<DynamicUpdateSliceOptions>
+CreateDynamicUpdateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb)
 {
-  InstanceNormOptionsBuilder builder_(_fbb);
-  builder_.add_epsilon(epsilon);
-  builder_.add_fused_activation_function(fused_activation_function);
+  DynamicUpdateSliceOptionsBuilder builder_(_fbb);
   return builder_.Finish();
 }
 
-flatbuffers::Offset<InstanceNormOptions>
-CreateInstanceNormOptions(flatbuffers::FlatBufferBuilder &_fbb, const InstanceNormOptionsT *_o,
-                          const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+flatbuffers::Offset<DynamicUpdateSliceOptions>
+CreateDynamicUpdateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                const DynamicUpdateSliceOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
-struct OperatorCodeT : public flatbuffers::NativeTable
+struct UnsortedSegmentProdOptionsT : 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;
+  typedef UnsortedSegmentProdOptions TableType;
 };
 
-struct OperatorCode FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+struct UnsortedSegmentProdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
 {
-  typedef OperatorCodeT NativeTableType;
-  typedef OperatorCodeBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  typedef UnsortedSegmentProdOptionsT NativeTableType;
+  typedef UnsortedSegmentProdOptionsBuilder Builder;
+  bool Verify(flatbuffers::Verifier &verifier) const
   {
-    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 VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  UnsortedSegmentProdOptionsT *
+  UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(UnsortedSegmentProdOptionsT *_o,
+                const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<UnsortedSegmentProdOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentProdOptionsT *_o,
+       const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct UnsortedSegmentProdOptionsBuilder
+{
+  typedef UnsortedSegmentProdOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  explicit UnsortedSegmentProdOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    return GetPointer<const flatbuffers::String *>(VT_CUSTOM_CODE);
+    start_ = fbb_.StartTable();
   }
-  int32_t version() const { return GetField<int32_t>(VT_VERSION, 1); }
-  circle::BuiltinOperator builtin_code() const
+  flatbuffers::Offset<UnsortedSegmentProdOptions> Finish()
   {
-    return static_cast<circle::BuiltinOperator>(GetField<int32_t>(VT_BUILTIN_CODE, 0));
+    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();
+}
+
+flatbuffers::Offset<UnsortedSegmentProdOptions>
+CreateUnsortedSegmentProdOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                 const UnsortedSegmentProdOptionsT *_o,
+                                 const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct UnsortedSegmentMaxOptionsT : public flatbuffers::NativeTable
+{
+  typedef UnsortedSegmentMaxOptions TableType;
+};
+
+struct UnsortedSegmentMaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+  typedef UnsortedSegmentMaxOptionsT NativeTableType;
+  typedef UnsortedSegmentMaxOptionsBuilder Builder;
   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();
+    return VerifyTableStart(verifier) && verifier.EndTable();
   }
-  OperatorCodeT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
-  void UnPackTo(OperatorCodeT *_o,
+  UnsortedSegmentMaxOptionsT *
+  UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(UnsortedSegmentMaxOptionsT *_o,
                 const flatbuffers::resolver_function_t *_resolver = nullptr) const;
-  static flatbuffers::Offset<OperatorCode>
-  Pack(flatbuffers::FlatBufferBuilder &_fbb, const OperatorCodeT *_o,
+  static flatbuffers::Offset<UnsortedSegmentMaxOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMaxOptionsT *_o,
        const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 };
 
-struct OperatorCodeBuilder
+struct UnsortedSegmentMaxOptionsBuilder
 {
-  typedef OperatorCode Table;
+  typedef UnsortedSegmentMaxOptions 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)
+  explicit UnsortedSegmentMaxOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    fbb_.AddOffset(OperatorCode::VT_CUSTOM_CODE, custom_code);
+    start_ = fbb_.StartTable();
   }
-  void add_version(int32_t version)
+  flatbuffers::Offset<UnsortedSegmentMaxOptions> Finish()
   {
-    fbb_.AddElement<int32_t>(OperatorCode::VT_VERSION, version, 1);
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<UnsortedSegmentMaxOptions>(end);
+    return o;
   }
-  void add_builtin_code(circle::BuiltinOperator builtin_code)
+};
+
+inline flatbuffers::Offset<UnsortedSegmentMaxOptions>
+CreateUnsortedSegmentMaxOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+  UnsortedSegmentMaxOptionsBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<UnsortedSegmentMaxOptions>
+CreateUnsortedSegmentMaxOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMaxOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct UnsortedSegmentSumOptionsT : public flatbuffers::NativeTable
+{
+  typedef UnsortedSegmentSumOptions TableType;
+};
+
+struct UnsortedSegmentSumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+  typedef UnsortedSegmentSumOptionsT NativeTableType;
+  typedef UnsortedSegmentSumOptionsBuilder Builder;
+  bool Verify(flatbuffers::Verifier &verifier) const
   {
-    fbb_.AddElement<int32_t>(OperatorCode::VT_BUILTIN_CODE, static_cast<int32_t>(builtin_code), 0);
+    return VerifyTableStart(verifier) && verifier.EndTable();
   }
-  explicit OperatorCodeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  UnsortedSegmentSumOptionsT *
+  UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(UnsortedSegmentSumOptionsT *_o,
+                const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<UnsortedSegmentSumOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentSumOptionsT *_o,
+       const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct UnsortedSegmentSumOptionsBuilder
+{
+  typedef UnsortedSegmentSumOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  explicit UnsortedSegmentSumOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
     start_ = fbb_.StartTable();
   }
-  flatbuffers::Offset<OperatorCode> Finish()
+  flatbuffers::Offset<UnsortedSegmentSumOptions> Finish()
   {
     const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<OperatorCode>(end);
+    auto o = flatbuffers::Offset<UnsortedSegmentSumOptions>(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)
+inline flatbuffers::Offset<UnsortedSegmentSumOptions>
+CreateUnsortedSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb)
 {
-  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);
+  UnsortedSegmentSumOptionsBuilder builder_(_fbb);
   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<UnsortedSegmentSumOptions>
+CreateUnsortedSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentSumOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
-flatbuffers::Offset<OperatorCode>
-CreateOperatorCode(flatbuffers::FlatBufferBuilder &_fbb, const OperatorCodeT *_o,
-                   const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+struct ATan2OptionsT : public flatbuffers::NativeTable
+{
+  typedef ATan2Options TableType;
+};
 
-struct OperatorT : public flatbuffers::NativeTable
+struct ATan2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
 {
-  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{};
+  typedef ATan2OptionsT NativeTableType;
+  typedef ATan2OptionsBuilder Builder;
+  bool Verify(flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  ATan2OptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(ATan2OptionsT *_o,
+                const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<ATan2Options>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT *_o,
+       const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 };
 
-struct Operator FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+struct ATan2OptionsBuilder
 {
-  typedef OperatorT NativeTableType;
-  typedef OperatorBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  typedef ATan2Options Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  explicit ATan2OptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    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);
+    start_ = fbb_.StartTable();
   }
-  const flatbuffers::Vector<int32_t> *outputs() const
+  flatbuffers::Offset<ATan2Options> Finish()
   {
-    return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_OUTPUTS);
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<ATan2Options>(end);
+    return o;
   }
-  circle::BuiltinOptions builtin_options_type() const
+};
+
+inline flatbuffers::Offset<ATan2Options> CreateATan2Options(flatbuffers::FlatBufferBuilder &_fbb)
+{
+  ATan2OptionsBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<ATan2Options>
+CreateATan2Options(flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct UnsortedSegmentMinOptionsT : public flatbuffers::NativeTable
+{
+  typedef UnsortedSegmentMinOptions TableType;
+};
+
+struct UnsortedSegmentMinOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+  typedef UnsortedSegmentMinOptionsT NativeTableType;
+  typedef UnsortedSegmentMinOptionsBuilder Builder;
+  bool Verify(flatbuffers::Verifier &verifier) const
   {
-    return static_cast<circle::BuiltinOptions>(GetField<uint8_t>(VT_BUILTIN_OPTIONS_TYPE, 0));
+    return VerifyTableStart(verifier) && verifier.EndTable();
   }
-  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
+  UnsortedSegmentMinOptionsT *
+  UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(UnsortedSegmentMinOptionsT *_o,
+                const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<UnsortedSegmentMinOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMinOptionsT *_o,
+       const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct UnsortedSegmentMinOptionsBuilder
+{
+  typedef UnsortedSegmentMinOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  explicit UnsortedSegmentMinOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    return builtin_options_type() == circle::BuiltinOptions_Conv2DOptions
-             ? static_cast<const circle::Conv2DOptions *>(builtin_options())
-             : nullptr;
+    start_ = fbb_.StartTable();
   }
-  const circle::DepthwiseConv2DOptions *builtin_options_as_DepthwiseConv2DOptions() const
+  flatbuffers::Offset<UnsortedSegmentMinOptions> Finish()
   {
-    return builtin_options_type() == circle::BuiltinOptions_DepthwiseConv2DOptions
-             ? static_cast<const circle::DepthwiseConv2DOptions *>(builtin_options())
-             : nullptr;
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<UnsortedSegmentMinOptions>(end);
+    return o;
   }
-  const circle::ConcatEmbeddingsOptions *builtin_options_as_ConcatEmbeddingsOptions() const
+};
+
+inline flatbuffers::Offset<UnsortedSegmentMinOptions>
+CreateUnsortedSegmentMinOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+  UnsortedSegmentMinOptionsBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<UnsortedSegmentMinOptions>
+CreateUnsortedSegmentMinOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMinOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SignOptionsT : public flatbuffers::NativeTable
+{
+  typedef SignOptions TableType;
+};
+
+struct SignOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+  typedef SignOptionsT NativeTableType;
+  typedef SignOptionsBuilder Builder;
+  bool Verify(flatbuffers::Verifier &verifier) const
   {
-    return builtin_options_type() == circle::BuiltinOptions_ConcatEmbeddingsOptions
-             ? static_cast<const circle::ConcatEmbeddingsOptions *>(builtin_options())
-             : nullptr;
+    return VerifyTableStart(verifier) && verifier.EndTable();
   }
-  const circle::LSHProjectionOptions *builtin_options_as_LSHProjectionOptions() const
+  SignOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(SignOptionsT *_o,
+                const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<SignOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT *_o,
+       const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SignOptionsBuilder
+{
+  typedef SignOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  explicit SignOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    return builtin_options_type() == circle::BuiltinOptions_LSHProjectionOptions
-             ? static_cast<const circle::LSHProjectionOptions *>(builtin_options())
-             : nullptr;
+    start_ = fbb_.StartTable();
   }
-  const circle::Pool2DOptions *builtin_options_as_Pool2DOptions() const
+  flatbuffers::Offset<SignOptions> Finish()
   {
-    return builtin_options_type() == circle::BuiltinOptions_Pool2DOptions
-             ? static_cast<const circle::Pool2DOptions *>(builtin_options())
-             : nullptr;
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<SignOptions>(end);
+    return o;
   }
-  const circle::SVDFOptions *builtin_options_as_SVDFOptions() const
+};
+
+inline flatbuffers::Offset<SignOptions> CreateSignOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+  SignOptionsBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<SignOptions>
+CreateSignOptions(flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BitcastOptionsT : public flatbuffers::NativeTable
+{
+  typedef BitcastOptions TableType;
+};
+
+struct BitcastOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+  typedef BitcastOptionsT NativeTableType;
+  typedef BitcastOptionsBuilder Builder;
+  bool Verify(flatbuffers::Verifier &verifier) const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SVDFOptions
-             ? static_cast<const circle::SVDFOptions *>(builtin_options())
-             : nullptr;
+    return VerifyTableStart(verifier) && verifier.EndTable();
   }
-  const circle::RNNOptions *builtin_options_as_RNNOptions() const
+  BitcastOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(BitcastOptionsT *_o,
+                const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<BitcastOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const BitcastOptionsT *_o,
+       const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct BitcastOptionsBuilder
+{
+  typedef BitcastOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  explicit BitcastOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    return builtin_options_type() == circle::BuiltinOptions_RNNOptions
-             ? static_cast<const circle::RNNOptions *>(builtin_options())
-             : nullptr;
+    start_ = fbb_.StartTable();
   }
-  const circle::FullyConnectedOptions *builtin_options_as_FullyConnectedOptions() const
+  flatbuffers::Offset<BitcastOptions> Finish()
   {
-    return builtin_options_type() == circle::BuiltinOptions_FullyConnectedOptions
-             ? static_cast<const circle::FullyConnectedOptions *>(builtin_options())
-             : nullptr;
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<BitcastOptions>(end);
+    return o;
   }
-  const circle::SoftmaxOptions *builtin_options_as_SoftmaxOptions() const
+};
+
+inline flatbuffers::Offset<BitcastOptions>
+CreateBitcastOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+  BitcastOptionsBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<BitcastOptions>
+CreateBitcastOptions(flatbuffers::FlatBufferBuilder &_fbb, const BitcastOptionsT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BitwiseXorOptionsT : public flatbuffers::NativeTable
+{
+  typedef BitwiseXorOptions TableType;
+};
+
+struct BitwiseXorOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+  typedef BitwiseXorOptionsT NativeTableType;
+  typedef BitwiseXorOptionsBuilder Builder;
+  bool Verify(flatbuffers::Verifier &verifier) const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SoftmaxOptions
-             ? static_cast<const circle::SoftmaxOptions *>(builtin_options())
-             : nullptr;
+    return VerifyTableStart(verifier) && verifier.EndTable();
   }
-  const circle::ConcatenationOptions *builtin_options_as_ConcatenationOptions() const
+  BitwiseXorOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(BitwiseXorOptionsT *_o,
+                const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<BitwiseXorOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const BitwiseXorOptionsT *_o,
+       const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct BitwiseXorOptionsBuilder
+{
+  typedef BitwiseXorOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  explicit BitwiseXorOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    return builtin_options_type() == circle::BuiltinOptions_ConcatenationOptions
-             ? static_cast<const circle::ConcatenationOptions *>(builtin_options())
-             : nullptr;
+    start_ = fbb_.StartTable();
   }
-  const circle::AddOptions *builtin_options_as_AddOptions() const
+  flatbuffers::Offset<BitwiseXorOptions> Finish()
   {
-    return builtin_options_type() == circle::BuiltinOptions_AddOptions
-             ? static_cast<const circle::AddOptions *>(builtin_options())
-             : nullptr;
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<BitwiseXorOptions>(end);
+    return o;
   }
-  const circle::L2NormOptions *builtin_options_as_L2NormOptions() const
+};
+
+inline flatbuffers::Offset<BitwiseXorOptions>
+CreateBitwiseXorOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+  BitwiseXorOptionsBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<BitwiseXorOptions>
+CreateBitwiseXorOptions(flatbuffers::FlatBufferBuilder &_fbb, const BitwiseXorOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct RightShiftOptionsT : public flatbuffers::NativeTable
+{
+  typedef RightShiftOptions TableType;
+};
+
+struct RightShiftOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+{
+  typedef RightShiftOptionsT NativeTableType;
+  typedef RightShiftOptionsBuilder Builder;
+  bool Verify(flatbuffers::Verifier &verifier) const
   {
-    return builtin_options_type() == circle::BuiltinOptions_L2NormOptions
-             ? static_cast<const circle::L2NormOptions *>(builtin_options())
-             : nullptr;
+    return VerifyTableStart(verifier) && verifier.EndTable();
   }
-  const circle::LocalResponseNormalizationOptions *
-  builtin_options_as_LocalResponseNormalizationOptions() const
+  RightShiftOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(RightShiftOptionsT *_o,
+                const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<RightShiftOptions>
+  Pack(flatbuffers::FlatBufferBuilder &_fbb, const RightShiftOptionsT *_o,
+       const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct RightShiftOptionsBuilder
+{
+  typedef RightShiftOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  explicit RightShiftOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    return builtin_options_type() == circle::BuiltinOptions_LocalResponseNormalizationOptions
-             ? static_cast<const circle::LocalResponseNormalizationOptions *>(builtin_options())
-             : nullptr;
+    start_ = fbb_.StartTable();
   }
-  const circle::LSTMOptions *builtin_options_as_LSTMOptions() const
+  flatbuffers::Offset<RightShiftOptions> Finish()
   {
-    return builtin_options_type() == circle::BuiltinOptions_LSTMOptions
-             ? static_cast<const circle::LSTMOptions *>(builtin_options())
-             : nullptr;
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<RightShiftOptions>(end);
+    return o;
   }
-  const circle::ResizeBilinearOptions *builtin_options_as_ResizeBilinearOptions() const
+};
+
+inline flatbuffers::Offset<RightShiftOptions>
+CreateRightShiftOptions(flatbuffers::FlatBufferBuilder &_fbb)
+{
+  RightShiftOptionsBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<RightShiftOptions>
+CreateRightShiftOptions(flatbuffers::FlatBufferBuilder &_fbb, const RightShiftOptionsT *_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
   {
-    return builtin_options_type() == circle::BuiltinOptions_ResizeBilinearOptions
-             ? static_cast<const circle::ResizeBilinearOptions *>(builtin_options())
-             : nullptr;
+    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();
   }
-  const circle::CallOptions *builtin_options_as_CallOptions() const
+  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)
   {
-    return builtin_options_type() == circle::BuiltinOptions_CallOptions
-             ? static_cast<const circle::CallOptions *>(builtin_options())
-             : nullptr;
+    fbb_.AddElement<int32_t>(BCQGatherOptions::VT_INPUT_HIDDEN_SIZE, input_hidden_size, 0);
   }
-  const circle::ReshapeOptions *builtin_options_as_ReshapeOptions() const
+  void add_axis(int32_t axis) { fbb_.AddElement<int32_t>(BCQGatherOptions::VT_AXIS, axis, 0); }
+  explicit BCQGatherOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    return builtin_options_type() == circle::BuiltinOptions_ReshapeOptions
-             ? static_cast<const circle::ReshapeOptions *>(builtin_options())
-             : nullptr;
+    start_ = fbb_.StartTable();
   }
-  const circle::SkipGramOptions *builtin_options_as_SkipGramOptions() const
+  flatbuffers::Offset<BCQGatherOptions> Finish()
   {
-    return builtin_options_type() == circle::BuiltinOptions_SkipGramOptions
-             ? static_cast<const circle::SkipGramOptions *>(builtin_options())
-             : nullptr;
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<BCQGatherOptions>(end);
+    return o;
   }
-  const circle::SpaceToDepthOptions *builtin_options_as_SpaceToDepthOptions() const
+};
+
+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
   {
-    return builtin_options_type() == circle::BuiltinOptions_SpaceToDepthOptions
-             ? static_cast<const circle::SpaceToDepthOptions *>(builtin_options())
-             : nullptr;
-  }
-  const circle::EmbeddingLookupSparseOptions *
-  builtin_options_as_EmbeddingLookupSparseOptions() const
+    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 builtin_options_type() == circle::BuiltinOptions_EmbeddingLookupSparseOptions
-             ? static_cast<const circle::EmbeddingLookupSparseOptions *>(builtin_options())
-             : nullptr;
+    return static_cast<circle::ActivationFunctionType>(
+      GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
   }
-  const circle::MulOptions *builtin_options_as_MulOptions() const
+  bool Verify(flatbuffers::Verifier &verifier) const
   {
-    return builtin_options_type() == circle::BuiltinOptions_MulOptions
-             ? static_cast<const circle::MulOptions *>(builtin_options())
-             : nullptr;
+    return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_WEIGHTS_HIDDEN_SIZE) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
   }
-  const circle::PadOptions *builtin_options_as_PadOptions() const
+  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)
   {
-    return builtin_options_type() == circle::BuiltinOptions_PadOptions
-             ? static_cast<const circle::PadOptions *>(builtin_options())
-             : nullptr;
+    fbb_.AddElement<int32_t>(BCQFullyConnectedOptions::VT_WEIGHTS_HIDDEN_SIZE, weights_hidden_size,
+                             0);
   }
-  const circle::GatherOptions *builtin_options_as_GatherOptions() const
+  void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
   {
-    return builtin_options_type() == circle::BuiltinOptions_GatherOptions
-             ? static_cast<const circle::GatherOptions *>(builtin_options())
-             : nullptr;
+    fbb_.AddElement<int8_t>(BCQFullyConnectedOptions::VT_FUSED_ACTIVATION_FUNCTION,
+                            static_cast<int8_t>(fused_activation_function), 0);
   }
-  const circle::BatchToSpaceNDOptions *builtin_options_as_BatchToSpaceNDOptions() const
+  explicit BCQFullyConnectedOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    return builtin_options_type() == circle::BuiltinOptions_BatchToSpaceNDOptions
-             ? static_cast<const circle::BatchToSpaceNDOptions *>(builtin_options())
-             : nullptr;
+    start_ = fbb_.StartTable();
   }
-  const circle::SpaceToBatchNDOptions *builtin_options_as_SpaceToBatchNDOptions() const
+  flatbuffers::Offset<BCQFullyConnectedOptions> Finish()
   {
-    return builtin_options_type() == circle::BuiltinOptions_SpaceToBatchNDOptions
-             ? static_cast<const circle::SpaceToBatchNDOptions *>(builtin_options())
-             : nullptr;
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<BCQFullyConnectedOptions>(end);
+    return o;
   }
-  const circle::TransposeOptions *builtin_options_as_TransposeOptions() const
+};
+
+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
   {
-    return builtin_options_type() == circle::BuiltinOptions_TransposeOptions
-             ? static_cast<const circle::TransposeOptions *>(builtin_options())
-             : nullptr;
-  }
-  const circle::ReducerOptions *builtin_options_as_ReducerOptions() const
+    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 builtin_options_type() == circle::BuiltinOptions_ReducerOptions
-             ? static_cast<const circle::ReducerOptions *>(builtin_options())
-             : nullptr;
+    return static_cast<circle::ActivationFunctionType>(
+      GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
   }
-  const circle::SubOptions *builtin_options_as_SubOptions() const
+  bool Verify(flatbuffers::Verifier &verifier) const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SubOptions
-             ? static_cast<const circle::SubOptions *>(builtin_options())
-             : nullptr;
+    return VerifyTableStart(verifier) && VerifyField<float>(verifier, VT_EPSILON) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION) && verifier.EndTable();
   }
-  const circle::DivOptions *builtin_options_as_DivOptions() const
+  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)
   {
-    return builtin_options_type() == circle::BuiltinOptions_DivOptions
-             ? static_cast<const circle::DivOptions *>(builtin_options())
-             : nullptr;
+    fbb_.AddElement<float>(InstanceNormOptions::VT_EPSILON, epsilon, 0.0f);
   }
-  const circle::SqueezeOptions *builtin_options_as_SqueezeOptions() const
+  void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
   {
-    return builtin_options_type() == circle::BuiltinOptions_SqueezeOptions
-             ? static_cast<const circle::SqueezeOptions *>(builtin_options())
-             : nullptr;
+    fbb_.AddElement<int8_t>(InstanceNormOptions::VT_FUSED_ACTIVATION_FUNCTION,
+                            static_cast<int8_t>(fused_activation_function), 0);
   }
-  const circle::SequenceRNNOptions *builtin_options_as_SequenceRNNOptions() const
+  explicit InstanceNormOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    return builtin_options_type() == circle::BuiltinOptions_SequenceRNNOptions
-             ? static_cast<const circle::SequenceRNNOptions *>(builtin_options())
-             : nullptr;
+    start_ = fbb_.StartTable();
   }
-  const circle::StridedSliceOptions *builtin_options_as_StridedSliceOptions() const
+  flatbuffers::Offset<InstanceNormOptions> Finish()
   {
-    return builtin_options_type() == circle::BuiltinOptions_StridedSliceOptions
-             ? static_cast<const circle::StridedSliceOptions *>(builtin_options())
-             : nullptr;
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<InstanceNormOptions>(end);
+    return o;
   }
-  const circle::ExpOptions *builtin_options_as_ExpOptions() const
+};
+
+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
   {
-    return builtin_options_type() == circle::BuiltinOptions_ExpOptions
-             ? static_cast<const circle::ExpOptions *>(builtin_options())
-             : nullptr;
-  }
-  const circle::TopKV2Options *builtin_options_as_TopKV2Options() const
+    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 builtin_options_type() == circle::BuiltinOptions_TopKV2Options
-             ? static_cast<const circle::TopKV2Options *>(builtin_options())
-             : nullptr;
+    return GetPointer<const flatbuffers::String *>(VT_CUSTOM_CODE);
   }
-  const circle::SplitOptions *builtin_options_as_SplitOptions() const
+  int32_t version() const { return GetField<int32_t>(VT_VERSION, 1); }
+  circle::BuiltinOperator builtin_code() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SplitOptions
-             ? static_cast<const circle::SplitOptions *>(builtin_options())
-             : nullptr;
+    return static_cast<circle::BuiltinOperator>(GetField<int32_t>(VT_BUILTIN_CODE, 0));
   }
-  const circle::LogSoftmaxOptions *builtin_options_as_LogSoftmaxOptions() const
+  bool Verify(flatbuffers::Verifier &verifier) const
   {
-    return builtin_options_type() == circle::BuiltinOptions_LogSoftmaxOptions
-             ? static_cast<const circle::LogSoftmaxOptions *>(builtin_options())
-             : nullptr;
+    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();
   }
-  const circle::CastOptions *builtin_options_as_CastOptions() const
+  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)
   {
-    return builtin_options_type() == circle::BuiltinOptions_CastOptions
-             ? static_cast<const circle::CastOptions *>(builtin_options())
-             : nullptr;
+    fbb_.AddElement<int8_t>(OperatorCode::VT_DEPRECATED_BUILTIN_CODE, deprecated_builtin_code, 0);
   }
-  const circle::DequantizeOptions *builtin_options_as_DequantizeOptions() const
+  void add_custom_code(flatbuffers::Offset<flatbuffers::String> custom_code)
   {
-    return builtin_options_type() == circle::BuiltinOptions_DequantizeOptions
-             ? static_cast<const circle::DequantizeOptions *>(builtin_options())
-             : nullptr;
+    fbb_.AddOffset(OperatorCode::VT_CUSTOM_CODE, custom_code);
   }
-  const circle::MaximumMinimumOptions *builtin_options_as_MaximumMinimumOptions() const
+  void add_version(int32_t version)
   {
-    return builtin_options_type() == circle::BuiltinOptions_MaximumMinimumOptions
-             ? static_cast<const circle::MaximumMinimumOptions *>(builtin_options())
-             : nullptr;
+    fbb_.AddElement<int32_t>(OperatorCode::VT_VERSION, version, 1);
   }
-  const circle::ArgMaxOptions *builtin_options_as_ArgMaxOptions() const
+  void add_builtin_code(circle::BuiltinOperator builtin_code)
   {
-    return builtin_options_type() == circle::BuiltinOptions_ArgMaxOptions
-             ? static_cast<const circle::ArgMaxOptions *>(builtin_options())
-             : nullptr;
+    fbb_.AddElement<int32_t>(OperatorCode::VT_BUILTIN_CODE, static_cast<int32_t>(builtin_code), 0);
   }
-  const circle::LessOptions *builtin_options_as_LessOptions() const
+  explicit OperatorCodeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    return builtin_options_type() == circle::BuiltinOptions_LessOptions
-             ? static_cast<const circle::LessOptions *>(builtin_options())
-             : nullptr;
+    start_ = fbb_.StartTable();
   }
-  const circle::NegOptions *builtin_options_as_NegOptions() const
+  flatbuffers::Offset<OperatorCode> Finish()
   {
-    return builtin_options_type() == circle::BuiltinOptions_NegOptions
-             ? static_cast<const circle::NegOptions *>(builtin_options())
-             : nullptr;
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<OperatorCode>(end);
+    return o;
   }
-  const circle::PadV2Options *builtin_options_as_PadV2Options() const
+};
+
+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
   {
-    return builtin_options_type() == circle::BuiltinOptions_PadV2Options
-             ? static_cast<const circle::PadV2Options *>(builtin_options())
-             : nullptr;
-  }
-  const circle::GreaterOptions *builtin_options_as_GreaterOptions() const
+    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 builtin_options_type() == circle::BuiltinOptions_GreaterOptions
-             ? static_cast<const circle::GreaterOptions *>(builtin_options())
-             : nullptr;
+    return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_INPUTS);
   }
-  const circle::GreaterEqualOptions *builtin_options_as_GreaterEqualOptions() const
+  const flatbuffers::Vector<int32_t> *outputs() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_GreaterEqualOptions
-             ? static_cast<const circle::GreaterEqualOptions *>(builtin_options())
-             : nullptr;
+    return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_OUTPUTS);
   }
-  const circle::LessEqualOptions *builtin_options_as_LessEqualOptions() const
+  circle::BuiltinOptions builtin_options_type() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_LessEqualOptions
-             ? static_cast<const circle::LessEqualOptions *>(builtin_options())
-             : nullptr;
+    return static_cast<circle::BuiltinOptions>(GetField<uint8_t>(VT_BUILTIN_OPTIONS_TYPE, 0));
   }
-  const circle::SelectOptions *builtin_options_as_SelectOptions() const
+  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_SelectOptions
-             ? static_cast<const circle::SelectOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_Conv2DOptions
+             ? static_cast<const circle::Conv2DOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::SliceOptions *builtin_options_as_SliceOptions() const
+  const circle::DepthwiseConv2DOptions *builtin_options_as_DepthwiseConv2DOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SliceOptions
-             ? static_cast<const circle::SliceOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_DepthwiseConv2DOptions
+             ? static_cast<const circle::DepthwiseConv2DOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::TransposeConvOptions *builtin_options_as_TransposeConvOptions() const
+  const circle::ConcatEmbeddingsOptions *builtin_options_as_ConcatEmbeddingsOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_TransposeConvOptions
-             ? static_cast<const circle::TransposeConvOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ConcatEmbeddingsOptions
+             ? static_cast<const circle::ConcatEmbeddingsOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::SparseToDenseOptions *builtin_options_as_SparseToDenseOptions() const
+  const circle::LSHProjectionOptions *builtin_options_as_LSHProjectionOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SparseToDenseOptions
-             ? static_cast<const circle::SparseToDenseOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_LSHProjectionOptions
+             ? static_cast<const circle::LSHProjectionOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::TileOptions *builtin_options_as_TileOptions() const
+  const circle::Pool2DOptions *builtin_options_as_Pool2DOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_TileOptions
-             ? static_cast<const circle::TileOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_Pool2DOptions
+             ? static_cast<const circle::Pool2DOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::ExpandDimsOptions *builtin_options_as_ExpandDimsOptions() const
+  const circle::SVDFOptions *builtin_options_as_SVDFOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_ExpandDimsOptions
-             ? static_cast<const circle::ExpandDimsOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SVDFOptions
+             ? static_cast<const circle::SVDFOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::EqualOptions *builtin_options_as_EqualOptions() const
+  const circle::RNNOptions *builtin_options_as_RNNOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_EqualOptions
-             ? static_cast<const circle::EqualOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_RNNOptions
+             ? static_cast<const circle::RNNOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::NotEqualOptions *builtin_options_as_NotEqualOptions() const
+  const circle::FullyConnectedOptions *builtin_options_as_FullyConnectedOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_NotEqualOptions
-             ? static_cast<const circle::NotEqualOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_FullyConnectedOptions
+             ? static_cast<const circle::FullyConnectedOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::ShapeOptions *builtin_options_as_ShapeOptions() const
+  const circle::SoftmaxOptions *builtin_options_as_SoftmaxOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_ShapeOptions
-             ? static_cast<const circle::ShapeOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SoftmaxOptions
+             ? static_cast<const circle::SoftmaxOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::PowOptions *builtin_options_as_PowOptions() const
+  const circle::ConcatenationOptions *builtin_options_as_ConcatenationOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_PowOptions
-             ? static_cast<const circle::PowOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ConcatenationOptions
+             ? static_cast<const circle::ConcatenationOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::ArgMinOptions *builtin_options_as_ArgMinOptions() const
+  const circle::AddOptions *builtin_options_as_AddOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_ArgMinOptions
-             ? static_cast<const circle::ArgMinOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_AddOptions
+             ? static_cast<const circle::AddOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::FakeQuantOptions *builtin_options_as_FakeQuantOptions() const
+  const circle::L2NormOptions *builtin_options_as_L2NormOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_FakeQuantOptions
-             ? static_cast<const circle::FakeQuantOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_L2NormOptions
+             ? static_cast<const circle::L2NormOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::PackOptions *builtin_options_as_PackOptions() const
+  const circle::LocalResponseNormalizationOptions *
+  builtin_options_as_LocalResponseNormalizationOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_PackOptions
-             ? static_cast<const circle::PackOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_LocalResponseNormalizationOptions
+             ? static_cast<const circle::LocalResponseNormalizationOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::LogicalOrOptions *builtin_options_as_LogicalOrOptions() const
+  const circle::LSTMOptions *builtin_options_as_LSTMOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_LogicalOrOptions
-             ? static_cast<const circle::LogicalOrOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_LSTMOptions
+             ? static_cast<const circle::LSTMOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::OneHotOptions *builtin_options_as_OneHotOptions() const
+  const circle::ResizeBilinearOptions *builtin_options_as_ResizeBilinearOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_OneHotOptions
-             ? static_cast<const circle::OneHotOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ResizeBilinearOptions
+             ? static_cast<const circle::ResizeBilinearOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::LogicalAndOptions *builtin_options_as_LogicalAndOptions() const
+  const circle::CallOptions *builtin_options_as_CallOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_LogicalAndOptions
-             ? static_cast<const circle::LogicalAndOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_CallOptions
+             ? static_cast<const circle::CallOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::LogicalNotOptions *builtin_options_as_LogicalNotOptions() const
+  const circle::ReshapeOptions *builtin_options_as_ReshapeOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_LogicalNotOptions
-             ? static_cast<const circle::LogicalNotOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ReshapeOptions
+             ? static_cast<const circle::ReshapeOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::UnpackOptions *builtin_options_as_UnpackOptions() const
+  const circle::SkipGramOptions *builtin_options_as_SkipGramOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_UnpackOptions
-             ? static_cast<const circle::UnpackOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SkipGramOptions
+             ? static_cast<const circle::SkipGramOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::FloorDivOptions *builtin_options_as_FloorDivOptions() const
+  const circle::SpaceToDepthOptions *builtin_options_as_SpaceToDepthOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_FloorDivOptions
-             ? static_cast<const circle::FloorDivOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SpaceToDepthOptions
+             ? static_cast<const circle::SpaceToDepthOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::SquareOptions *builtin_options_as_SquareOptions() const
+  const circle::EmbeddingLookupSparseOptions *
+  builtin_options_as_EmbeddingLookupSparseOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SquareOptions
-             ? static_cast<const circle::SquareOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_EmbeddingLookupSparseOptions
+             ? static_cast<const circle::EmbeddingLookupSparseOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::ZerosLikeOptions *builtin_options_as_ZerosLikeOptions() const
+  const circle::MulOptions *builtin_options_as_MulOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_ZerosLikeOptions
-             ? static_cast<const circle::ZerosLikeOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_MulOptions
+             ? static_cast<const circle::MulOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::FillOptions *builtin_options_as_FillOptions() const
+  const circle::PadOptions *builtin_options_as_PadOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_FillOptions
-             ? static_cast<const circle::FillOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_PadOptions
+             ? static_cast<const circle::PadOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::BidirectionalSequenceLSTMOptions *
-  builtin_options_as_BidirectionalSequenceLSTMOptions() const
+  const circle::GatherOptions *builtin_options_as_GatherOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_BidirectionalSequenceLSTMOptions
-             ? static_cast<const circle::BidirectionalSequenceLSTMOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_GatherOptions
+             ? static_cast<const circle::GatherOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::BidirectionalSequenceRNNOptions *
-  builtin_options_as_BidirectionalSequenceRNNOptions() const
+  const circle::BatchToSpaceNDOptions *builtin_options_as_BatchToSpaceNDOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_BidirectionalSequenceRNNOptions
-             ? static_cast<const circle::BidirectionalSequenceRNNOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_BatchToSpaceNDOptions
+             ? static_cast<const circle::BatchToSpaceNDOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::UnidirectionalSequenceLSTMOptions *
-  builtin_options_as_UnidirectionalSequenceLSTMOptions() const
+  const circle::SpaceToBatchNDOptions *builtin_options_as_SpaceToBatchNDOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_UnidirectionalSequenceLSTMOptions
-             ? static_cast<const circle::UnidirectionalSequenceLSTMOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SpaceToBatchNDOptions
+             ? static_cast<const circle::SpaceToBatchNDOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::FloorModOptions *builtin_options_as_FloorModOptions() const
+  const circle::TransposeOptions *builtin_options_as_TransposeOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_FloorModOptions
-             ? static_cast<const circle::FloorModOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_TransposeOptions
+             ? static_cast<const circle::TransposeOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::RangeOptions *builtin_options_as_RangeOptions() const
+  const circle::ReducerOptions *builtin_options_as_ReducerOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_RangeOptions
-             ? static_cast<const circle::RangeOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ReducerOptions
+             ? static_cast<const circle::ReducerOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::ResizeNearestNeighborOptions *
-  builtin_options_as_ResizeNearestNeighborOptions() const
+  const circle::SubOptions *builtin_options_as_SubOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_ResizeNearestNeighborOptions
-             ? static_cast<const circle::ResizeNearestNeighborOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SubOptions
+             ? static_cast<const circle::SubOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::LeakyReluOptions *builtin_options_as_LeakyReluOptions() const
+  const circle::DivOptions *builtin_options_as_DivOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_LeakyReluOptions
-             ? static_cast<const circle::LeakyReluOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_DivOptions
+             ? static_cast<const circle::DivOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::SquaredDifferenceOptions *builtin_options_as_SquaredDifferenceOptions() const
+  const circle::SqueezeOptions *builtin_options_as_SqueezeOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SquaredDifferenceOptions
-             ? static_cast<const circle::SquaredDifferenceOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SqueezeOptions
+             ? static_cast<const circle::SqueezeOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::MirrorPadOptions *builtin_options_as_MirrorPadOptions() const
+  const circle::SequenceRNNOptions *builtin_options_as_SequenceRNNOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_MirrorPadOptions
-             ? static_cast<const circle::MirrorPadOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SequenceRNNOptions
+             ? static_cast<const circle::SequenceRNNOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::AbsOptions *builtin_options_as_AbsOptions() const
+  const circle::StridedSliceOptions *builtin_options_as_StridedSliceOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_AbsOptions
-             ? static_cast<const circle::AbsOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_StridedSliceOptions
+             ? static_cast<const circle::StridedSliceOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::SplitVOptions *builtin_options_as_SplitVOptions() const
+  const circle::ExpOptions *builtin_options_as_ExpOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SplitVOptions
-             ? static_cast<const circle::SplitVOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ExpOptions
+             ? static_cast<const circle::ExpOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::UniqueOptions *builtin_options_as_UniqueOptions() const
+  const circle::TopKV2Options *builtin_options_as_TopKV2Options() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_UniqueOptions
-             ? static_cast<const circle::UniqueOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_TopKV2Options
+             ? static_cast<const circle::TopKV2Options *>(builtin_options())
              : nullptr;
   }
-  const circle::ReverseV2Options *builtin_options_as_ReverseV2Options() const
+  const circle::SplitOptions *builtin_options_as_SplitOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_ReverseV2Options
-             ? static_cast<const circle::ReverseV2Options *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SplitOptions
+             ? static_cast<const circle::SplitOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::AddNOptions *builtin_options_as_AddNOptions() const
+  const circle::LogSoftmaxOptions *builtin_options_as_LogSoftmaxOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_AddNOptions
-             ? static_cast<const circle::AddNOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_LogSoftmaxOptions
+             ? static_cast<const circle::LogSoftmaxOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::GatherNdOptions *builtin_options_as_GatherNdOptions() const
+  const circle::CastOptions *builtin_options_as_CastOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_GatherNdOptions
-             ? static_cast<const circle::GatherNdOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_CastOptions
+             ? static_cast<const circle::CastOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::CosOptions *builtin_options_as_CosOptions() const
+  const circle::DequantizeOptions *builtin_options_as_DequantizeOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_CosOptions
-             ? static_cast<const circle::CosOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_DequantizeOptions
+             ? static_cast<const circle::DequantizeOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::WhereOptions *builtin_options_as_WhereOptions() const
+  const circle::MaximumMinimumOptions *builtin_options_as_MaximumMinimumOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_WhereOptions
-             ? static_cast<const circle::WhereOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_MaximumMinimumOptions
+             ? static_cast<const circle::MaximumMinimumOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::RankOptions *builtin_options_as_RankOptions() const
+  const circle::ArgMaxOptions *builtin_options_as_ArgMaxOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_RankOptions
-             ? static_cast<const circle::RankOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ArgMaxOptions
+             ? static_cast<const circle::ArgMaxOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::ReverseSequenceOptions *builtin_options_as_ReverseSequenceOptions() const
+  const circle::LessOptions *builtin_options_as_LessOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_ReverseSequenceOptions
-             ? static_cast<const circle::ReverseSequenceOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_LessOptions
+             ? static_cast<const circle::LessOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::MatrixDiagOptions *builtin_options_as_MatrixDiagOptions() const
+  const circle::NegOptions *builtin_options_as_NegOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_MatrixDiagOptions
-             ? static_cast<const circle::MatrixDiagOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_NegOptions
+             ? static_cast<const circle::NegOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::QuantizeOptions *builtin_options_as_QuantizeOptions() const
+  const circle::PadV2Options *builtin_options_as_PadV2Options() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_QuantizeOptions
-             ? static_cast<const circle::QuantizeOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_PadV2Options
+             ? static_cast<const circle::PadV2Options *>(builtin_options())
              : nullptr;
   }
-  const circle::MatrixSetDiagOptions *builtin_options_as_MatrixSetDiagOptions() const
+  const circle::GreaterOptions *builtin_options_as_GreaterOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_MatrixSetDiagOptions
-             ? static_cast<const circle::MatrixSetDiagOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_GreaterOptions
+             ? static_cast<const circle::GreaterOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::HardSwishOptions *builtin_options_as_HardSwishOptions() const
+  const circle::GreaterEqualOptions *builtin_options_as_GreaterEqualOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_HardSwishOptions
-             ? static_cast<const circle::HardSwishOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_GreaterEqualOptions
+             ? static_cast<const circle::GreaterEqualOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::IfOptions *builtin_options_as_IfOptions() const
+  const circle::LessEqualOptions *builtin_options_as_LessEqualOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_IfOptions
-             ? static_cast<const circle::IfOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_LessEqualOptions
+             ? static_cast<const circle::LessEqualOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::WhileOptions *builtin_options_as_WhileOptions() const
+  const circle::SelectOptions *builtin_options_as_SelectOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_WhileOptions
-             ? static_cast<const circle::WhileOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SelectOptions
+             ? static_cast<const circle::SelectOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::DepthToSpaceOptions *builtin_options_as_DepthToSpaceOptions() const
+  const circle::SliceOptions *builtin_options_as_SliceOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_DepthToSpaceOptions
-             ? static_cast<const circle::DepthToSpaceOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SliceOptions
+             ? static_cast<const circle::SliceOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::NonMaxSuppressionV4Options *builtin_options_as_NonMaxSuppressionV4Options() const
+  const circle::TransposeConvOptions *builtin_options_as_TransposeConvOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_NonMaxSuppressionV4Options
-             ? static_cast<const circle::NonMaxSuppressionV4Options *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_TransposeConvOptions
+             ? static_cast<const circle::TransposeConvOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::NonMaxSuppressionV5Options *builtin_options_as_NonMaxSuppressionV5Options() const
+  const circle::SparseToDenseOptions *builtin_options_as_SparseToDenseOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_NonMaxSuppressionV5Options
-             ? static_cast<const circle::NonMaxSuppressionV5Options *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SparseToDenseOptions
+             ? static_cast<const circle::SparseToDenseOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::ScatterNdOptions *builtin_options_as_ScatterNdOptions() const
+  const circle::TileOptions *builtin_options_as_TileOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_ScatterNdOptions
-             ? static_cast<const circle::ScatterNdOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_TileOptions
+             ? static_cast<const circle::TileOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::SelectV2Options *builtin_options_as_SelectV2Options() const
+  const circle::ExpandDimsOptions *builtin_options_as_ExpandDimsOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SelectV2Options
-             ? static_cast<const circle::SelectV2Options *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ExpandDimsOptions
+             ? static_cast<const circle::ExpandDimsOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::DensifyOptions *builtin_options_as_DensifyOptions() const
+  const circle::EqualOptions *builtin_options_as_EqualOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_DensifyOptions
-             ? static_cast<const circle::DensifyOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_EqualOptions
+             ? static_cast<const circle::EqualOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::SegmentSumOptions *builtin_options_as_SegmentSumOptions() const
+  const circle::NotEqualOptions *builtin_options_as_NotEqualOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_SegmentSumOptions
-             ? static_cast<const circle::SegmentSumOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_NotEqualOptions
+             ? static_cast<const circle::NotEqualOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::BatchMatMulOptions *builtin_options_as_BatchMatMulOptions() const
+  const circle::ShapeOptions *builtin_options_as_ShapeOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_BatchMatMulOptions
-             ? static_cast<const circle::BatchMatMulOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ShapeOptions
+             ? static_cast<const circle::ShapeOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::CumsumOptions *builtin_options_as_CumsumOptions() const
+  const circle::PowOptions *builtin_options_as_PowOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_CumsumOptions
-             ? static_cast<const circle::CumsumOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_PowOptions
+             ? static_cast<const circle::PowOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::CallOnceOptions *builtin_options_as_CallOnceOptions() const
+  const circle::ArgMinOptions *builtin_options_as_ArgMinOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_CallOnceOptions
-             ? static_cast<const circle::CallOnceOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ArgMinOptions
+             ? static_cast<const circle::ArgMinOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::BroadcastToOptions *builtin_options_as_BroadcastToOptions() const
+  const circle::FakeQuantOptions *builtin_options_as_FakeQuantOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_BroadcastToOptions
-             ? static_cast<const circle::BroadcastToOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_FakeQuantOptions
+             ? static_cast<const circle::FakeQuantOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::Rfft2dOptions *builtin_options_as_Rfft2dOptions() const
+  const circle::PackOptions *builtin_options_as_PackOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_Rfft2dOptions
-             ? static_cast<const circle::Rfft2dOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_PackOptions
+             ? static_cast<const circle::PackOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::Conv3DOptions *builtin_options_as_Conv3DOptions() const
+  const circle::LogicalOrOptions *builtin_options_as_LogicalOrOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_Conv3DOptions
-             ? static_cast<const circle::Conv3DOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_LogicalOrOptions
+             ? static_cast<const circle::LogicalOrOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::HashtableOptions *builtin_options_as_HashtableOptions() const
+  const circle::OneHotOptions *builtin_options_as_OneHotOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_HashtableOptions
-             ? static_cast<const circle::HashtableOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_OneHotOptions
+             ? static_cast<const circle::OneHotOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::HashtableFindOptions *builtin_options_as_HashtableFindOptions() const
+  const circle::LogicalAndOptions *builtin_options_as_LogicalAndOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_HashtableFindOptions
-             ? static_cast<const circle::HashtableFindOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_LogicalAndOptions
+             ? static_cast<const circle::LogicalAndOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::HashtableImportOptions *builtin_options_as_HashtableImportOptions() const
+  const circle::LogicalNotOptions *builtin_options_as_LogicalNotOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_HashtableImportOptions
-             ? static_cast<const circle::HashtableImportOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_LogicalNotOptions
+             ? static_cast<const circle::LogicalNotOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::HashtableSizeOptions *builtin_options_as_HashtableSizeOptions() const
+  const circle::UnpackOptions *builtin_options_as_UnpackOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_HashtableSizeOptions
-             ? static_cast<const circle::HashtableSizeOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_UnpackOptions
+             ? static_cast<const circle::UnpackOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::VarHandleOptions *builtin_options_as_VarHandleOptions() const
+  const circle::FloorDivOptions *builtin_options_as_FloorDivOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_VarHandleOptions
-             ? static_cast<const circle::VarHandleOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_FloorDivOptions
+             ? static_cast<const circle::FloorDivOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::ReadVariableOptions *builtin_options_as_ReadVariableOptions() const
+  const circle::SquareOptions *builtin_options_as_SquareOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_ReadVariableOptions
-             ? static_cast<const circle::ReadVariableOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_SquareOptions
+             ? static_cast<const circle::SquareOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::AssignVariableOptions *builtin_options_as_AssignVariableOptions() const
+  const circle::ZerosLikeOptions *builtin_options_as_ZerosLikeOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_AssignVariableOptions
-             ? static_cast<const circle::AssignVariableOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_ZerosLikeOptions
+             ? static_cast<const circle::ZerosLikeOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::RandomOptions *builtin_options_as_RandomOptions() const
+  const circle::FillOptions *builtin_options_as_FillOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_RandomOptions
-             ? static_cast<const circle::RandomOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_FillOptions
+             ? static_cast<const circle::FillOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::BCQGatherOptions *builtin_options_as_BCQGatherOptions() const
+  const circle::BidirectionalSequenceLSTMOptions *
+  builtin_options_as_BidirectionalSequenceLSTMOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_BCQGatherOptions
-             ? static_cast<const circle::BCQGatherOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_BidirectionalSequenceLSTMOptions
+             ? static_cast<const circle::BidirectionalSequenceLSTMOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::BCQFullyConnectedOptions *builtin_options_as_BCQFullyConnectedOptions() const
+  const circle::BidirectionalSequenceRNNOptions *
+  builtin_options_as_BidirectionalSequenceRNNOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_BCQFullyConnectedOptions
-             ? static_cast<const circle::BCQFullyConnectedOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_BidirectionalSequenceRNNOptions
+             ? static_cast<const circle::BidirectionalSequenceRNNOptions *>(builtin_options())
              : nullptr;
   }
-  const circle::InstanceNormOptions *builtin_options_as_InstanceNormOptions() const
+  const circle::UnidirectionalSequenceLSTMOptions *
+  builtin_options_as_UnidirectionalSequenceLSTMOptions() const
   {
-    return builtin_options_type() == circle::BuiltinOptions_InstanceNormOptions
-             ? static_cast<const circle::InstanceNormOptions *>(builtin_options())
+    return builtin_options_type() == circle::BuiltinOptions_UnidirectionalSequenceLSTMOptions
+             ? static_cast<const circle::UnidirectionalSequenceLSTMOptions *>(builtin_options())
              : nullptr;
   }
-  const flatbuffers::Vector<uint8_t> *custom_options() const
+  const circle::FloorModOptions *builtin_options_as_FloorModOptions() const
   {
-    return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_CUSTOM_OPTIONS);
+    return builtin_options_type() == circle::BuiltinOptions_FloorModOptions
+             ? static_cast<const circle::FloorModOptions *>(builtin_options())
+             : nullptr;
   }
-  circle::CustomOptionsFormat custom_options_format() const
+  const circle::RangeOptions *builtin_options_as_RangeOptions() const
   {
-    return static_cast<circle::CustomOptionsFormat>(GetField<int8_t>(VT_CUSTOM_OPTIONS_FORMAT, 0));
+    return builtin_options_type() == circle::BuiltinOptions_RangeOptions
+             ? static_cast<const circle::RangeOptions *>(builtin_options())
+             : nullptr;
   }
-  const flatbuffers::Vector<uint8_t> *mutating_variable_inputs() const
+  const circle::ResizeNearestNeighborOptions *
+  builtin_options_as_ResizeNearestNeighborOptions() const
   {
-    return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_MUTATING_VARIABLE_INPUTS);
+    return builtin_options_type() == circle::BuiltinOptions_ResizeNearestNeighborOptions
+             ? static_cast<const circle::ResizeNearestNeighborOptions *>(builtin_options())
+             : nullptr;
   }
-  const flatbuffers::Vector<int32_t> *intermediates() const
+  const circle::LeakyReluOptions *builtin_options_as_LeakyReluOptions() const
   {
-    return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_INTERMEDIATES);
+    return builtin_options_type() == circle::BuiltinOptions_LeakyReluOptions
+             ? static_cast<const circle::LeakyReluOptions *>(builtin_options())
+             : nullptr;
   }
-  bool Verify(flatbuffers::Verifier &verifier) const
+  const circle::SquaredDifferenceOptions *builtin_options_as_SquaredDifferenceOptions() 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();
+    return builtin_options_type() == circle::BuiltinOptions_SquaredDifferenceOptions
+             ? static_cast<const circle::SquaredDifferenceOptions *>(builtin_options())
+             : nullptr;
   }
-  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
-{
+  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::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
+             ? 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();
 }
 
@@ -14030,1183 +15193,2161 @@ Operator::builtin_options_as<circle::MatrixDiagOptions>() const
   return builtin_options_as_MatrixDiagOptions();
 }
 
-template <>
-inline const circle::QuantizeOptions *Operator::builtin_options_as<circle::QuantizeOptions>() const
+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::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
+{
+  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)
 {
-  return builtin_options_as_QuantizeOptions();
+  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();
 }
 
-template <>
-inline const circle::MatrixSetDiagOptions *
-Operator::builtin_options_as<circle::MatrixSetDiagOptions>() const
+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)
 {
-  return builtin_options_as_MatrixSetDiagOptions();
+  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__);
 }
 
-template <>
-inline const circle::HardSwishOptions *
-Operator::builtin_options_as<circle::HardSwishOptions>() const
-{
-  return builtin_options_as_HardSwishOptions();
-}
+flatbuffers::Offset<Operator>
+CreateOperator(flatbuffers::FlatBufferBuilder &_fbb, const OperatorT *_o,
+               const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
-template <> inline const circle::IfOptions *Operator::builtin_options_as<circle::IfOptions>() const
+struct SubGraphT : public flatbuffers::NativeTable
 {
-  return builtin_options_as_IfOptions();
-}
+  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;
+};
 
-template <>
-inline const circle::WhileOptions *Operator::builtin_options_as<circle::WhileOptions>() const
+struct SubGraph FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
 {
-  return builtin_options_as_WhileOptions();
-}
+  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);
+};
 
-template <>
-inline const circle::DepthToSpaceOptions *
-Operator::builtin_options_as<circle::DepthToSpaceOptions>() const
+struct SubGraphBuilder
 {
-  return builtin_options_as_DepthToSpaceOptions();
-}
+  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;
+  }
+};
 
-template <>
-inline const circle::NonMaxSuppressionV4Options *
-Operator::builtin_options_as<circle::NonMaxSuppressionV4Options>() const
+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)
 {
-  return builtin_options_as_NonMaxSuppressionV4Options();
+  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();
 }
 
-template <>
-inline const circle::NonMaxSuppressionV5Options *
-Operator::builtin_options_as<circle::NonMaxSuppressionV5Options>() const
+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)
 {
-  return builtin_options_as_NonMaxSuppressionV5Options();
+  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);
 }
 
-template <>
-inline const circle::ScatterNdOptions *
-Operator::builtin_options_as<circle::ScatterNdOptions>() const
-{
-  return builtin_options_as_ScatterNdOptions();
-}
+flatbuffers::Offset<SubGraph>
+CreateSubGraph(flatbuffers::FlatBufferBuilder &_fbb, const SubGraphT *_o,
+               const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
-template <>
-inline const circle::SelectV2Options *Operator::builtin_options_as<circle::SelectV2Options>() const
+struct BufferT : public flatbuffers::NativeTable
 {
-  return builtin_options_as_SelectV2Options();
-}
+  typedef Buffer TableType;
+  std::vector<uint8_t> data{};
+};
 
-template <>
-inline const circle::DensifyOptions *Operator::builtin_options_as<circle::DensifyOptions>() const
+struct Buffer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
 {
-  return builtin_options_as_DensifyOptions();
-}
+  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);
+};
 
-template <>
-inline const circle::SegmentSumOptions *
-Operator::builtin_options_as<circle::SegmentSumOptions>() const
+struct BufferBuilder
 {
-  return builtin_options_as_SegmentSumOptions();
-}
+  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;
+  }
+};
 
-template <>
-inline const circle::BatchMatMulOptions *
-Operator::builtin_options_as<circle::BatchMatMulOptions>() const
+inline flatbuffers::Offset<Buffer>
+CreateBuffer(flatbuffers::FlatBufferBuilder &_fbb,
+             flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data = 0)
 {
-  return builtin_options_as_BatchMatMulOptions();
+  BufferBuilder builder_(_fbb);
+  builder_.add_data(data);
+  return builder_.Finish();
 }
 
-template <>
-inline const circle::CumsumOptions *Operator::builtin_options_as<circle::CumsumOptions>() const
+inline flatbuffers::Offset<Buffer> CreateBufferDirect(flatbuffers::FlatBufferBuilder &_fbb,
+                                                      const std::vector<uint8_t> *data = nullptr)
 {
-  return builtin_options_as_CumsumOptions();
+  if (data)
+  {
+    _fbb.ForceVectorAlignment(data->size(), sizeof(uint8_t), 16);
+  }
+  auto data__ = data ? _fbb.CreateVector<uint8_t>(*data) : 0;
+  return circle::CreateBuffer(_fbb, data__);
 }
 
-template <>
-inline const circle::CallOnceOptions *Operator::builtin_options_as<circle::CallOnceOptions>() const
+flatbuffers::Offset<Buffer>
+CreateBuffer(flatbuffers::FlatBufferBuilder &_fbb, const BufferT *_o,
+             const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct MetadataT : public flatbuffers::NativeTable
 {
-  return builtin_options_as_CallOnceOptions();
-}
+  typedef Metadata TableType;
+  std::string name{};
+  uint32_t buffer = 0;
+};
 
-template <>
-inline const circle::BroadcastToOptions *
-Operator::builtin_options_as<circle::BroadcastToOptions>() const
+struct Metadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
 {
-  return builtin_options_as_BroadcastToOptions();
-}
+  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);
+};
 
-template <>
-inline const circle::Rfft2dOptions *Operator::builtin_options_as<circle::Rfft2dOptions>() const
+struct MetadataBuilder
 {
-  return builtin_options_as_Rfft2dOptions();
-}
+  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;
+  }
+};
 
-template <>
-inline const circle::Conv3DOptions *Operator::builtin_options_as<circle::Conv3DOptions>() const
+inline flatbuffers::Offset<Metadata>
+CreateMetadata(flatbuffers::FlatBufferBuilder &_fbb,
+               flatbuffers::Offset<flatbuffers::String> name = 0, uint32_t buffer = 0)
 {
-  return builtin_options_as_Conv3DOptions();
+  MetadataBuilder builder_(_fbb);
+  builder_.add_buffer(buffer);
+  builder_.add_name(name);
+  return builder_.Finish();
 }
 
-template <>
-inline const circle::HashtableOptions *
-Operator::builtin_options_as<circle::HashtableOptions>() const
+inline flatbuffers::Offset<Metadata> CreateMetadataDirect(flatbuffers::FlatBufferBuilder &_fbb,
+                                                          const char *name = nullptr,
+                                                          uint32_t buffer = 0)
 {
-  return builtin_options_as_HashtableOptions();
+  auto name__ = name ? _fbb.CreateString(name) : 0;
+  return circle::CreateMetadata(_fbb, name__, buffer);
 }
 
-template <>
-inline const circle::HashtableFindOptions *
-Operator::builtin_options_as<circle::HashtableFindOptions>() const
+flatbuffers::Offset<Metadata>
+CreateMetadata(flatbuffers::FlatBufferBuilder &_fbb, const MetadataT *_o,
+               const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct TensorMapT : public flatbuffers::NativeTable
 {
-  return builtin_options_as_HashtableFindOptions();
-}
+  typedef TensorMap TableType;
+  std::string name{};
+  uint32_t tensor_index = 0;
+};
 
-template <>
-inline const circle::HashtableImportOptions *
-Operator::builtin_options_as<circle::HashtableImportOptions>() const
+struct TensorMap FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
 {
-  return builtin_options_as_HashtableImportOptions();
-}
+  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);
+};
 
-template <>
-inline const circle::HashtableSizeOptions *
-Operator::builtin_options_as<circle::HashtableSizeOptions>() const
+struct TensorMapBuilder
 {
-  return builtin_options_as_HashtableSizeOptions();
-}
+  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;
+  }
+};
 
-template <>
-inline const circle::VarHandleOptions *
-Operator::builtin_options_as<circle::VarHandleOptions>() const
+inline flatbuffers::Offset<TensorMap>
+CreateTensorMap(flatbuffers::FlatBufferBuilder &_fbb,
+                flatbuffers::Offset<flatbuffers::String> name = 0, uint32_t tensor_index = 0)
 {
-  return builtin_options_as_VarHandleOptions();
+  TensorMapBuilder builder_(_fbb);
+  builder_.add_tensor_index(tensor_index);
+  builder_.add_name(name);
+  return builder_.Finish();
 }
 
-template <>
-inline const circle::ReadVariableOptions *
-Operator::builtin_options_as<circle::ReadVariableOptions>() const
+inline flatbuffers::Offset<TensorMap> CreateTensorMapDirect(flatbuffers::FlatBufferBuilder &_fbb,
+                                                            const char *name = nullptr,
+                                                            uint32_t tensor_index = 0)
 {
-  return builtin_options_as_ReadVariableOptions();
+  auto name__ = name ? _fbb.CreateString(name) : 0;
+  return circle::CreateTensorMap(_fbb, name__, tensor_index);
 }
 
-template <>
-inline const circle::AssignVariableOptions *
-Operator::builtin_options_as<circle::AssignVariableOptions>() const
+flatbuffers::Offset<TensorMap>
+CreateTensorMap(flatbuffers::FlatBufferBuilder &_fbb, const TensorMapT *_o,
+                const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SignatureDefT : public flatbuffers::NativeTable
 {
-  return builtin_options_as_AssignVariableOptions();
-}
+  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;
+};
 
-template <>
-inline const circle::RandomOptions *Operator::builtin_options_as<circle::RandomOptions>() const
+struct SignatureDef FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
 {
-  return builtin_options_as_RandomOptions();
-}
+  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);
+};
 
-template <>
-inline const circle::BCQGatherOptions *
-Operator::builtin_options_as<circle::BCQGatherOptions>() const
+struct SignatureDefBuilder
 {
-  return builtin_options_as_BCQGatherOptions();
-}
+  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;
+  }
+};
 
-template <>
-inline const circle::BCQFullyConnectedOptions *
-Operator::builtin_options_as<circle::BCQFullyConnectedOptions>() const
+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)
 {
-  return builtin_options_as_BCQFullyConnectedOptions();
+  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();
 }
 
-template <>
-inline const circle::InstanceNormOptions *
-Operator::builtin_options_as<circle::InstanceNormOptions>() const
+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)
 {
-  return builtin_options_as_InstanceNormOptions();
+  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);
 }
 
-struct OperatorBuilder
+flatbuffers::Offset<SignatureDef>
+CreateSignatureDef(flatbuffers::FlatBufferBuilder &_fbb, const SignatureDefT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ModelT : public flatbuffers::NativeTable
 {
-  typedef Operator Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_opcode_index(uint32_t opcode_index)
+  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
   {
-    fbb_.AddElement<uint32_t>(Operator::VT_OPCODE_INDEX, opcode_index, 0);
+    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);
   }
-  void add_inputs(flatbuffers::Offset<flatbuffers::Vector<int32_t>> inputs)
+  const flatbuffers::Vector<flatbuffers::Offset<circle::SubGraph>> *subgraphs() const
   {
-    fbb_.AddOffset(Operator::VT_INPUTS, inputs);
+    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::SubGraph>> *>(
+      VT_SUBGRAPHS);
   }
-  void add_outputs(flatbuffers::Offset<flatbuffers::Vector<int32_t>> outputs)
+  const flatbuffers::String *description() const
   {
-    fbb_.AddOffset(Operator::VT_OUTPUTS, outputs);
+    return GetPointer<const flatbuffers::String *>(VT_DESCRIPTION);
   }
-  void add_builtin_options_type(circle::BuiltinOptions builtin_options_type)
+  const flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>> *buffers() const
   {
-    fbb_.AddElement<uint8_t>(Operator::VT_BUILTIN_OPTIONS_TYPE,
-                             static_cast<uint8_t>(builtin_options_type), 0);
+    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>> *>(VT_BUFFERS);
   }
-  void add_builtin_options(flatbuffers::Offset<void> builtin_options)
+  const flatbuffers::Vector<int32_t> *metadata_buffer() const
   {
-    fbb_.AddOffset(Operator::VT_BUILTIN_OPTIONS, builtin_options);
+    return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_METADATA_BUFFER);
   }
-  void add_custom_options(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> custom_options)
+  const flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>> *metadata() const
   {
-    fbb_.AddOffset(Operator::VT_CUSTOM_OPTIONS, custom_options);
+    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>> *>(
+      VT_METADATA);
   }
-  void add_custom_options_format(circle::CustomOptionsFormat custom_options_format)
+  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_.AddElement<int8_t>(Operator::VT_CUSTOM_OPTIONS_FORMAT,
-                            static_cast<int8_t>(custom_options_format), 0);
+    fbb_.AddOffset(Model::VT_METADATA_BUFFER, metadata_buffer);
   }
-  void add_mutating_variable_inputs(
-    flatbuffers::Offset<flatbuffers::Vector<uint8_t>> mutating_variable_inputs)
+  void add_metadata(
+    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>>> metadata)
   {
-    fbb_.AddOffset(Operator::VT_MUTATING_VARIABLE_INPUTS, mutating_variable_inputs);
+    fbb_.AddOffset(Model::VT_METADATA, metadata);
   }
-  void add_intermediates(flatbuffers::Offset<flatbuffers::Vector<int32_t>> intermediates)
+  void add_signature_defs(
+    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::SignatureDef>>>
+      signature_defs)
   {
-    fbb_.AddOffset(Operator::VT_INTERMEDIATES, intermediates);
+    fbb_.AddOffset(Model::VT_SIGNATURE_DEFS, signature_defs);
   }
-  explicit OperatorBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  explicit ModelBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
     start_ = fbb_.StartTable();
   }
-  flatbuffers::Offset<Operator> Finish()
+  flatbuffers::Offset<Model> Finish()
   {
     const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<Operator>(end);
+    auto o = flatbuffers::Offset<Model>(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)
+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)
 {
-  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);
+  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<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)
+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 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__);
+  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<Operator>
-CreateOperator(flatbuffers::FlatBufferBuilder &_fbb, const OperatorT *_o,
-               const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+flatbuffers::Offset<Model> CreateModel(flatbuffers::FlatBufferBuilder &_fbb, const ModelT *_o,
+                                       const flatbuffers::rehasher_function_t *_rehasher = nullptr);
 
-struct SubGraphT : public flatbuffers::NativeTable
+inline CustomQuantizationT *
+CustomQuantization::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  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;
-};
+  auto _o = std::unique_ptr<CustomQuantizationT>(new CustomQuantizationT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
 
-struct SubGraph FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+inline void CustomQuantization::UnPackTo(CustomQuantizationT *_o,
+                                         const flatbuffers::resolver_function_t *_resolver) const
 {
-  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
+  (void)_o;
+  (void)_resolver;
   {
-    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();
+    auto _e = custom();
+    if (_e)
+    {
+      _o->custom.resize(_e->size());
+      std::copy(_e->begin(), _e->end(), _o->custom.begin());
+    }
   }
-  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
+inline flatbuffers::Offset<CustomQuantization>
+CustomQuantization::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT *_o,
+                         const flatbuffers::rehasher_function_t *_rehasher)
 {
-  typedef SubGraph Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void
-  add_tensors(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Tensor>>> tensors)
+  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
   {
-    fbb_.AddOffset(SubGraph::VT_TENSORS, tensors);
-  }
-  void add_inputs(flatbuffers::Offset<flatbuffers::Vector<int32_t>> inputs)
+    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;
   {
-    fbb_.AddOffset(SubGraph::VT_INPUTS, inputs);
+    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);
+      }
+    }
   }
-  void add_outputs(flatbuffers::Offset<flatbuffers::Vector<int32_t>> outputs)
   {
-    fbb_.AddOffset(SubGraph::VT_OUTPUTS, outputs);
+    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);
+      }
+    }
   }
-  void add_operators(
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Operator>>> operators)
   {
-    fbb_.AddOffset(SubGraph::VT_OPERATORS, operators);
+    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);
+      }
+    }
   }
-  void add_name(flatbuffers::Offset<flatbuffers::String> name)
   {
-    fbb_.AddOffset(SubGraph::VT_NAME, name);
+    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);
+      }
+    }
   }
-  void add_data_format(circle::DataFormat data_format)
   {
-    fbb_.AddElement<int8_t>(SubGraph::VT_DATA_FORMAT, static_cast<int8_t>(data_format), 0);
+    auto _e = details_type();
+    _o->details.type = _e;
   }
-  explicit SubGraphBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    start_ = fbb_.StartTable();
+    auto _e = details();
+    if (_e)
+      _o->details.value = circle::QuantizationDetailsUnion::UnPack(_e, details_type(), _resolver);
   }
-  flatbuffers::Offset<SubGraph> Finish()
   {
-    const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<SubGraph>(end);
-    return o;
+    auto _e = quantized_dimension();
+    _o->quantized_dimension = _e;
   }
-};
+}
 
-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)
+inline flatbuffers::Offset<QuantizationParameters>
+QuantizationParameters::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                             const QuantizationParametersT *_o,
+                             const flatbuffers::rehasher_function_t *_rehasher)
 {
-  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();
+  return CreateQuantizationParameters(_fbb, _o, _rehasher);
 }
 
-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)
+inline flatbuffers::Offset<QuantizationParameters>
+CreateQuantizationParameters(flatbuffers::FlatBufferBuilder &_fbb,
+                             const QuantizationParametersT *_o,
+                             const flatbuffers::rehasher_function_t *_rehasher)
 {
-  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);
+  (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);
 }
 
-flatbuffers::Offset<SubGraph>
-CreateSubGraph(flatbuffers::FlatBufferBuilder &_fbb, const SubGraphT *_o,
-               const flatbuffers::rehasher_function_t *_rehasher = nullptr);
-
-struct BufferT : public flatbuffers::NativeTable
+inline Int32VectorT *Int32Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  typedef Buffer TableType;
-  std::vector<uint8_t> data{};
-};
+  auto _o = std::unique_ptr<Int32VectorT>(new Int32VectorT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
 
-struct Buffer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+inline void Int32Vector::UnPackTo(Int32VectorT *_o,
+                                  const flatbuffers::resolver_function_t *_resolver) const
 {
-  typedef BufferT NativeTableType;
-  typedef BufferBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_DATA = 4
-  };
-  const flatbuffers::Vector<uint8_t> *data() const
+  (void)_o;
+  (void)_resolver;
   {
-    return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_DATA);
+    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);
+      }
+    }
   }
-  bool Verify(flatbuffers::Verifier &verifier) const
+}
+
+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
   {
-    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);
-};
+    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);
+}
 
-struct BufferBuilder
+inline Uint16VectorT *Uint16Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  typedef Buffer Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_data(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data)
+  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;
   {
-    fbb_.AddOffset(Buffer::VT_DATA, data);
+    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);
+      }
+    }
   }
-  explicit BufferBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+}
+
+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
   {
-    start_ = fbb_.StartTable();
-  }
-  flatbuffers::Offset<Buffer> Finish()
+    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;
   {
-    const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<Buffer>(end);
-    return o;
+    auto _e = values();
+    if (_e)
+    {
+      _o->values.resize(_e->size());
+      std::copy(_e->begin(), _e->end(), _o->values.begin());
+    }
   }
-};
+}
 
-inline flatbuffers::Offset<Buffer>
-CreateBuffer(flatbuffers::FlatBufferBuilder &_fbb,
-             flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data = 0)
+inline flatbuffers::Offset<Uint8Vector>
+Uint8Vector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  BufferBuilder builder_(_fbb);
-  builder_.add_data(data);
-  return builder_.Finish();
+  return CreateUint8Vector(_fbb, _o, _rehasher);
 }
-
-inline flatbuffers::Offset<Buffer> CreateBufferDirect(flatbuffers::FlatBufferBuilder &_fbb,
-                                                      const std::vector<uint8_t> *data = nullptr)
+
+inline flatbuffers::Offset<Uint8Vector>
+CreateUint8Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  if (data)
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
   {
-    _fbb.ForceVectorAlignment(data->size(), sizeof(uint8_t), 16);
-  }
-  auto data__ = data ? _fbb.CreateVector<uint8_t>(*data) : 0;
-  return circle::CreateBuffer(_fbb, data__);
+    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);
 }
 
-flatbuffers::Offset<Buffer>
-CreateBuffer(flatbuffers::FlatBufferBuilder &_fbb, const BufferT *_o,
-             const flatbuffers::rehasher_function_t *_rehasher = nullptr);
-
-struct MetadataT : public flatbuffers::NativeTable
+inline DimensionMetadataT *
+DimensionMetadata::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  typedef Metadata TableType;
-  std::string name{};
-  uint32_t buffer = 0;
-};
+  auto _o = std::unique_ptr<DimensionMetadataT>(new DimensionMetadataT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
 
-struct Metadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+inline void DimensionMetadata::UnPackTo(DimensionMetadataT *_o,
+                                        const flatbuffers::resolver_function_t *_resolver) const
 {
-  typedef MetadataT NativeTableType;
-  typedef MetadataBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  (void)_o;
+  (void)_resolver;
   {
-    VT_NAME = 4,
-    VT_BUFFER = 6
-  };
-  const flatbuffers::String *name() const
+    auto _e = format();
+    _o->format = _e;
+  }
   {
-    return GetPointer<const flatbuffers::String *>(VT_NAME);
+    auto _e = dense_size();
+    _o->dense_size = _e;
   }
-  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();
+    auto _e = array_segments_type();
+    _o->array_segments.type = _e;
   }
-  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);
+    auto _e = array_segments();
+    if (_e)
+      _o->array_segments.value =
+        circle::SparseIndexVectorUnion::UnPack(_e, array_segments_type(), _resolver);
   }
-  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();
+    auto _e = array_indices_type();
+    _o->array_indices.type = _e;
   }
-  flatbuffers::Offset<Metadata> Finish()
   {
-    const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<Metadata>(end);
-    return o;
+    auto _e = array_indices();
+    if (_e)
+      _o->array_indices.value =
+        circle::SparseIndexVectorUnion::UnPack(_e, array_indices_type(), _resolver);
   }
-};
+}
 
-inline flatbuffers::Offset<Metadata>
-CreateMetadata(flatbuffers::FlatBufferBuilder &_fbb,
-               flatbuffers::Offset<flatbuffers::String> name = 0, uint32_t buffer = 0)
+inline flatbuffers::Offset<DimensionMetadata>
+DimensionMetadata::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  MetadataBuilder builder_(_fbb);
-  builder_.add_buffer(buffer);
-  builder_.add_name(name);
-  return builder_.Finish();
+  return CreateDimensionMetadata(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<Metadata> CreateMetadataDirect(flatbuffers::FlatBufferBuilder &_fbb,
-                                                          const char *name = nullptr,
-                                                          uint32_t buffer = 0)
+inline flatbuffers::Offset<DimensionMetadata>
+CreateDimensionMetadata(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  auto name__ = name ? _fbb.CreateString(name) : 0;
-  return circle::CreateMetadata(_fbb, name__, buffer);
+  (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);
 }
 
-flatbuffers::Offset<Metadata>
-CreateMetadata(flatbuffers::FlatBufferBuilder &_fbb, const MetadataT *_o,
-               const flatbuffers::rehasher_function_t *_rehasher = nullptr);
-
-struct TensorMapT : public flatbuffers::NativeTable
+inline SparsityParametersT *
+SparsityParameters::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  typedef TensorMap TableType;
-  std::string name{};
-  uint32_t tensor_index = 0;
-};
+  auto _o = std::unique_ptr<SparsityParametersT>(new SparsityParametersT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
 
-struct TensorMap FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+inline void SparsityParameters::UnPackTo(SparsityParametersT *_o,
+                                         const flatbuffers::resolver_function_t *_resolver) const
 {
-  typedef TensorMapT NativeTableType;
-  typedef TensorMapBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  (void)_o;
+  (void)_resolver;
   {
-    VT_NAME = 4,
-    VT_TENSOR_INDEX = 6
-  };
-  const flatbuffers::String *name() const
+    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);
+      }
+    }
+  }
   {
-    return GetPointer<const flatbuffers::String *>(VT_NAME);
+    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);
+      }
+    }
   }
-  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();
+    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));
+      }
+    }
   }
-  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
+inline flatbuffers::Offset<SparsityParameters>
+SparsityParameters::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT *_o,
+                         const flatbuffers::rehasher_function_t *_rehasher)
 {
-  typedef TensorMap Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_name(flatbuffers::Offset<flatbuffers::String> name)
+  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
   {
-    fbb_.AddOffset(TensorMap::VT_NAME, name);
-  }
-  void add_tensor_index(uint32_t tensor_index)
+    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 VariantSubTypeT *
+VariantSubType::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<VariantSubTypeT>(new VariantSubTypeT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void VariantSubType::UnPackTo(VariantSubTypeT *_o,
+                                     const flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
   {
-    fbb_.AddElement<uint32_t>(TensorMap::VT_TENSOR_INDEX, tensor_index, 0);
+    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);
+      }
+    }
   }
-  explicit TensorMapBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    start_ = fbb_.StartTable();
+    auto _e = type();
+    _o->type = _e;
   }
-  flatbuffers::Offset<TensorMap> Finish()
   {
-    const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<TensorMap>(end);
-    return o;
+    auto _e = has_rank();
+    _o->has_rank = _e;
   }
-};
+}
 
-inline flatbuffers::Offset<TensorMap>
-CreateTensorMap(flatbuffers::FlatBufferBuilder &_fbb,
-                flatbuffers::Offset<flatbuffers::String> name = 0, uint32_t tensor_index = 0)
+inline flatbuffers::Offset<VariantSubType>
+VariantSubType::Pack(flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher)
 {
-  TensorMapBuilder builder_(_fbb);
-  builder_.add_tensor_index(tensor_index);
-  builder_.add_name(name);
-  return builder_.Finish();
+  return CreateVariantSubType(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<TensorMap> CreateTensorMapDirect(flatbuffers::FlatBufferBuilder &_fbb,
-                                                            const char *name = nullptr,
-                                                            uint32_t tensor_index = 0)
+inline flatbuffers::Offset<VariantSubType>
+CreateVariantSubType(flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher)
 {
-  auto name__ = name ? _fbb.CreateString(name) : 0;
-  return circle::CreateTensorMap(_fbb, name__, tensor_index);
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    flatbuffers::FlatBufferBuilder *__fbb;
+    const VariantSubTypeT *__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 _has_rank = _o->has_rank;
+  return circle::CreateVariantSubType(_fbb, _shape, _type, _has_rank);
 }
 
-flatbuffers::Offset<TensorMap>
-CreateTensorMap(flatbuffers::FlatBufferBuilder &_fbb, const TensorMapT *_o,
-                const flatbuffers::rehasher_function_t *_rehasher = nullptr);
-
-struct SignatureDefT : public flatbuffers::NativeTable
+inline TensorT *Tensor::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  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;
-};
+  auto _o = std::unique_ptr<TensorT>(new TensorT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
 
-struct SignatureDef FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
+inline void Tensor::UnPackTo(TensorT *_o, const flatbuffers::resolver_function_t *_resolver) const
 {
-  typedef SignatureDefT NativeTableType;
-  typedef SignatureDefBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  (void)_o;
+  (void)_resolver;
   {
-    VT_INPUTS = 4,
-    VT_OUTPUTS = 6,
-    VT_SIGNATURE_KEY = 8,
-    VT_SUBGRAPH_INDEX = 12
-  };
-  const flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>> *inputs() const
+    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);
+      }
+    }
+  }
   {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>> *>(
-      VT_INPUTS);
+    auto _e = type();
+    _o->type = _e;
   }
-  const flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>> *outputs() const
   {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>> *>(
-      VT_OUTPUTS);
+    auto _e = buffer();
+    _o->buffer = _e;
   }
-  const flatbuffers::String *signature_key() const
   {
-    return GetPointer<const flatbuffers::String *>(VT_SIGNATURE_KEY);
+    auto _e = name();
+    if (_e)
+      _o->name = _e->str();
   }
-  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();
+    auto _e = quantization();
+    if (_e)
+      _o->quantization = std::unique_ptr<circle::QuantizationParametersT>(_e->UnPack(_resolver));
   }
-  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);
-};
+  {
+    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);
+      }
+    }
+  }
+  {
+    auto _e = has_rank();
+    _o->has_rank = _e;
+  }
+  {
+    auto _e = variant_tensors();
+    if (_e)
+    {
+      _o->variant_tensors.resize(_e->size());
+      for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->variant_tensors[_i] =
+          std::unique_ptr<circle::VariantSubTypeT>(_e->Get(_i)->UnPack(_resolver));
+      }
+    }
+  }
+}
 
-struct SignatureDefBuilder
+inline flatbuffers::Offset<Tensor> Tensor::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                                const TensorT *_o,
+                                                const flatbuffers::rehasher_function_t *_rehasher)
 {
-  typedef SignatureDef Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_inputs(
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>>> inputs)
+  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
   {
-    fbb_.AddOffset(SignatureDef::VT_INPUTS, inputs);
+    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;
+  auto _has_rank = _o->has_rank;
+  auto _variant_tensors =
+    _o->variant_tensors.size()
+      ? _fbb.CreateVector<flatbuffers::Offset<circle::VariantSubType>>(
+          _o->variant_tensors.size(),
+          [](size_t i, _VectorArgs *__va) {
+            return CreateVariantSubType(*__va->__fbb, __va->__o->variant_tensors[i].get(),
+                                        __va->__rehasher);
+          },
+          &_va)
+      : 0;
+  return circle::CreateTensor(_fbb, _shape, _type, _buffer, _name, _quantization, _is_variable,
+                              _sparsity, _shape_signature, _has_rank, _variant_tensors);
+}
+
+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;
   }
-  void add_outputs(
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::TensorMap>>> outputs)
   {
-    fbb_.AddOffset(SignatureDef::VT_OUTPUTS, outputs);
+    auto _e = stride_w();
+    _o->stride_w = _e;
   }
-  void add_signature_key(flatbuffers::Offset<flatbuffers::String> signature_key)
   {
-    fbb_.AddOffset(SignatureDef::VT_SIGNATURE_KEY, signature_key);
+    auto _e = stride_h();
+    _o->stride_h = _e;
   }
-  void add_subgraph_index(uint32_t subgraph_index)
   {
-    fbb_.AddElement<uint32_t>(SignatureDef::VT_SUBGRAPH_INDEX, subgraph_index, 0);
+    auto _e = fused_activation_function();
+    _o->fused_activation_function = _e;
   }
-  explicit SignatureDefBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    start_ = fbb_.StartTable();
+    auto _e = dilation_w_factor();
+    _o->dilation_w_factor = _e;
   }
-  flatbuffers::Offset<SignatureDef> Finish()
   {
-    const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<SignatureDef>(end);
-    return o;
+    auto _e = dilation_h_factor();
+    _o->dilation_h_factor = _e;
   }
-};
+}
 
-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)
+inline flatbuffers::Offset<Conv2DOptions>
+Conv2DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv2DOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  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();
+  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 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)
+inline Conv3DOptionsT *
+Conv3DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  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);
+  auto _o = std::unique_ptr<Conv3DOptionsT>(new Conv3DOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
 }
 
-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
+inline void Conv3DOptions::UnPackTo(Conv3DOptionsT *_o,
+                                    const flatbuffers::resolver_function_t *_resolver) const
 {
-  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
+  (void)_o;
+  (void)_resolver;
   {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::OperatorCode>> *>(
-      VT_OPERATOR_CODES);
+    auto _e = padding();
+    _o->padding = _e;
   }
-  const flatbuffers::Vector<flatbuffers::Offset<circle::SubGraph>> *subgraphs() const
   {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::SubGraph>> *>(
-      VT_SUBGRAPHS);
+    auto _e = stride_d();
+    _o->stride_d = _e;
   }
-  const flatbuffers::String *description() const
   {
-    return GetPointer<const flatbuffers::String *>(VT_DESCRIPTION);
+    auto _e = stride_w();
+    _o->stride_w = _e;
   }
-  const flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>> *buffers() const
   {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>> *>(VT_BUFFERS);
+    auto _e = stride_h();
+    _o->stride_h = _e;
   }
-  const flatbuffers::Vector<int32_t> *metadata_buffer() const
   {
-    return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_METADATA_BUFFER);
+    auto _e = fused_activation_function();
+    _o->fused_activation_function = _e;
   }
-  const flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>> *metadata() const
   {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>> *>(
-      VT_METADATA);
+    auto _e = dilation_d_factor();
+    _o->dilation_d_factor = _e;
   }
-  const flatbuffers::Vector<flatbuffers::Offset<circle::SignatureDef>> *signature_defs() const
   {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<circle::SignatureDef>> *>(
-      VT_SIGNATURE_DEFS);
+    auto _e = dilation_w_factor();
+    _o->dilation_w_factor = _e;
   }
-  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();
+    auto _e = dilation_h_factor();
+    _o->dilation_h_factor = _e;
   }
-  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
+inline flatbuffers::Offset<Conv3DOptions>
+Conv3DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  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)
+  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
   {
-    fbb_.AddOffset(Model::VT_DESCRIPTION, description);
-  }
-  void
-  add_buffers(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>>> buffers)
+    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;
   {
-    fbb_.AddOffset(Model::VT_BUFFERS, buffers);
+    auto _e = padding();
+    _o->padding = _e;
   }
-  void add_metadata_buffer(flatbuffers::Offset<flatbuffers::Vector<int32_t>> metadata_buffer)
   {
-    fbb_.AddOffset(Model::VT_METADATA_BUFFER, metadata_buffer);
+    auto _e = stride_w();
+    _o->stride_w = _e;
   }
-  void add_metadata(
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>>> metadata)
   {
-    fbb_.AddOffset(Model::VT_METADATA, metadata);
+    auto _e = stride_h();
+    _o->stride_h = _e;
   }
-  void add_signature_defs(
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::SignatureDef>>>
-      signature_defs)
   {
-    fbb_.AddOffset(Model::VT_SIGNATURE_DEFS, signature_defs);
+    auto _e = filter_width();
+    _o->filter_width = _e;
   }
-  explicit ModelBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
   {
-    start_ = fbb_.StartTable();
+    auto _e = filter_height();
+    _o->filter_height = _e;
   }
-  flatbuffers::Offset<Model> Finish()
   {
-    const auto end = fbb_.EndTable(start_);
-    auto o = flatbuffers::Offset<Model>(end);
-    return o;
+    auto _e = fused_activation_function();
+    _o->fused_activation_function = _e;
   }
-};
+}
 
-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)
+inline flatbuffers::Offset<Pool2DOptions>
+Pool2DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  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();
+  return CreatePool2DOptions(_fbb, _o, _rehasher);
 }
 
-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)
+inline flatbuffers::Offset<Pool2DOptions>
+CreatePool2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  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__);
+  (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);
 }
 
-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
+inline DepthwiseConv2DOptionsT *
+DepthwiseConv2DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<CustomQuantizationT>(new CustomQuantizationT());
+  auto _o = std::unique_ptr<DepthwiseConv2DOptionsT>(new DepthwiseConv2DOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void CustomQuantization::UnPackTo(CustomQuantizationT *_o,
-                                         const flatbuffers::resolver_function_t *_resolver) const
+inline void
+DepthwiseConv2DOptions::UnPackTo(DepthwiseConv2DOptionsT *_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());
-    }
+    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<CustomQuantization>
-CustomQuantization::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT *_o,
-                         const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<DepthwiseConv2DOptions>
+DepthwiseConv2DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                             const DepthwiseConv2DOptionsT *_o,
+                             const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateCustomQuantization(_fbb, _o, _rehasher);
+  return CreateDepthwiseConv2DOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<CustomQuantization>
-CreateCustomQuantization(flatbuffers::FlatBufferBuilder &_fbb, const CustomQuantizationT *_o,
-                         const flatbuffers::rehasher_function_t *_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 CustomQuantizationT *__o;
+    const DepthwiseConv2DOptionsT *__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);
+  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 QuantizationParametersT *
-QuantizationParameters::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ConcatEmbeddingsOptionsT *
+ConcatEmbeddingsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<QuantizationParametersT>(new QuantizationParametersT());
+  auto _o = std::unique_ptr<ConcatEmbeddingsOptionsT>(new ConcatEmbeddingsOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
 inline void
-QuantizationParameters::UnPackTo(QuantizationParametersT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+ConcatEmbeddingsOptions::UnPackTo(ConcatEmbeddingsOptionsT *_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 = num_channels();
+    _o->num_channels = _e;
   }
   {
-    auto _e = scale();
+    auto _e = num_columns_per_channel();
     if (_e)
     {
-      _o->scale.resize(_e->size());
+      _o->num_columns_per_channel.resize(_e->size());
       for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
       {
-        _o->scale[_i] = _e->Get(_i);
+        _o->num_columns_per_channel[_i] = _e->Get(_i);
       }
     }
   }
   {
-    auto _e = zero_point();
+    auto _e = embedding_dim_per_channel();
     if (_e)
     {
-      _o->zero_point.resize(_e->size());
+      _o->embedding_dim_per_channel.resize(_e->size());
       for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
       {
-        _o->zero_point[_i] = _e->Get(_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
   {
-    auto _e = details_type();
-    _o->details.type = _e;
-  }
-  {
-    auto _e = details();
-    if (_e)
-      _o->details.value = circle::QuantizationDetailsUnion::UnPack(_e, details_type(), _resolver);
-  }
+    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 = quantized_dimension();
-    _o->quantized_dimension = _e;
+    auto _e = type();
+    _o->type = _e;
   }
 }
 
-inline flatbuffers::Offset<QuantizationParameters>
-QuantizationParameters::Pack(flatbuffers::FlatBufferBuilder &_fbb,
-                             const QuantizationParametersT *_o,
-                             const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<LSHProjectionOptions>
+LSHProjectionOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT *_o,
+                           const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateQuantizationParameters(_fbb, _o, _rehasher);
+  return CreateLSHProjectionOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<QuantizationParameters>
-CreateQuantizationParameters(flatbuffers::FlatBufferBuilder &_fbb,
-                             const QuantizationParametersT *_o,
-                             const flatbuffers::rehasher_function_t *_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 QuantizationParametersT *__o;
+    const LSHProjectionOptionsT *__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);
+  auto _type = _o->type;
+  return circle::CreateLSHProjectionOptions(_fbb, _type);
 }
 
-inline Int32VectorT *Int32Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SVDFOptionsT *SVDFOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<Int32VectorT>(new Int32VectorT());
+  auto _o = std::unique_ptr<SVDFOptionsT>(new SVDFOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void Int32Vector::UnPackTo(Int32VectorT *_o,
+inline void SVDFOptions::UnPackTo(SVDFOptionsT *_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);
-      }
-    }
+    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<Int32Vector>
-Int32Vector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT *_o,
+inline flatbuffers::Offset<SVDFOptions>
+SVDFOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT *_o,
                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateInt32Vector(_fbb, _o, _rehasher);
+  return CreateSVDFOptions(_fbb, _o, _rehasher);
 }
-
-inline flatbuffers::Offset<Int32Vector>
-CreateInt32Vector(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT *_o,
+
+inline flatbuffers::Offset<SVDFOptions>
+CreateSVDFOptions(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT *_o,
                   const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
@@ -15214,837 +17355,674 @@ CreateInt32Vector(flatbuffers::FlatBufferBuilder &_fbb, const Int32VectorT *_o,
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const Int32VectorT *__o;
+    const SVDFOptionsT *__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);
+  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 Uint16VectorT *Uint16Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline RNNOptionsT *RNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<Uint16VectorT>(new Uint16VectorT());
+  auto _o = std::unique_ptr<RNNOptionsT>(new RNNOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void Uint16Vector::UnPackTo(Uint16VectorT *_o,
-                                   const flatbuffers::resolver_function_t *_resolver) const
+inline void RNNOptions::UnPackTo(RNNOptionsT *_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);
-      }
-    }
+    auto _e = fused_activation_function();
+    _o->fused_activation_function = _e;
+  }
+  {
+    auto _e = asymmetric_quantize_inputs();
+    _o->asymmetric_quantize_inputs = _e;
   }
 }
 
-inline flatbuffers::Offset<Uint16Vector>
-Uint16Vector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint16VectorT *_o,
-                   const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<RNNOptions>
+RNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateUint16Vector(_fbb, _o, _rehasher);
+  return CreateRNNOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<Uint16Vector>
-CreateUint16Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint16VectorT *_o,
-                   const flatbuffers::rehasher_function_t *_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 Uint16VectorT *__o;
+    const RNNOptionsT *__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);
+  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 Uint8VectorT *Uint8Vector::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SequenceRNNOptionsT *
+SequenceRNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<Uint8VectorT>(new Uint8VectorT());
+  auto _o = std::unique_ptr<SequenceRNNOptionsT>(new SequenceRNNOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void Uint8Vector::UnPackTo(Uint8VectorT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+inline void SequenceRNNOptions::UnPackTo(SequenceRNNOptionsT *_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());
-    }
+    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<Uint8Vector>
-Uint8Vector::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT *_o,
-                  const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<SequenceRNNOptions>
+SequenceRNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT *_o,
+                         const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateUint8Vector(_fbb, _o, _rehasher);
+  return CreateSequenceRNNOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<Uint8Vector>
-CreateUint8Vector(flatbuffers::FlatBufferBuilder &_fbb, const Uint8VectorT *_o,
-                  const flatbuffers::rehasher_function_t *_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 Uint8VectorT *__o;
+    const SequenceRNNOptionsT *__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);
+  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 DimensionMetadataT *
-DimensionMetadata::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline BidirectionalSequenceRNNOptionsT *
+BidirectionalSequenceRNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<DimensionMetadataT>(new DimensionMetadataT());
+  auto _o =
+    std::unique_ptr<BidirectionalSequenceRNNOptionsT>(new BidirectionalSequenceRNNOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void DimensionMetadata::UnPackTo(DimensionMetadataT *_o,
-                                        const flatbuffers::resolver_function_t *_resolver) const
+inline void
+BidirectionalSequenceRNNOptions::UnPackTo(BidirectionalSequenceRNNOptionsT *_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 = time_major();
+    _o->time_major = _e;
   }
   {
-    auto _e = array_segments();
-    if (_e)
-      _o->array_segments.value =
-        circle::SparseIndexVectorUnion::UnPack(_e, array_segments_type(), _resolver);
+    auto _e = fused_activation_function();
+    _o->fused_activation_function = _e;
   }
   {
-    auto _e = array_indices_type();
-    _o->array_indices.type = _e;
+    auto _e = merge_outputs();
+    _o->merge_outputs = _e;
   }
   {
-    auto _e = array_indices();
-    if (_e)
-      _o->array_indices.value =
-        circle::SparseIndexVectorUnion::UnPack(_e, array_indices_type(), _resolver);
+    auto _e = asymmetric_quantize_inputs();
+    _o->asymmetric_quantize_inputs = _e;
   }
 }
 
-inline flatbuffers::Offset<DimensionMetadata>
-DimensionMetadata::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT *_o,
-                        const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<BidirectionalSequenceRNNOptions>
+BidirectionalSequenceRNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                      const BidirectionalSequenceRNNOptionsT *_o,
+                                      const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateDimensionMetadata(_fbb, _o, _rehasher);
+  return CreateBidirectionalSequenceRNNOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<DimensionMetadata>
-CreateDimensionMetadata(flatbuffers::FlatBufferBuilder &_fbb, const DimensionMetadataT *_o,
-                        const flatbuffers::rehasher_function_t *_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 DimensionMetadataT *__o;
+    const BidirectionalSequenceRNNOptionsT *__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);
+  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 SparsityParametersT *
-SparsityParameters::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline FullyConnectedOptionsT *
+FullyConnectedOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SparsityParametersT>(new SparsityParametersT());
+  auto _o = std::unique_ptr<FullyConnectedOptionsT>(new FullyConnectedOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SparsityParameters::UnPackTo(SparsityParametersT *_o,
-                                         const flatbuffers::resolver_function_t *_resolver) const
+inline void FullyConnectedOptions::UnPackTo(FullyConnectedOptionsT *_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 = fused_activation_function();
+    _o->fused_activation_function = _e;
   }
   {
-    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 = weights_format();
+    _o->weights_format = _e;
   }
   {
-    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));
-      }
-    }
+    auto _e = keep_num_dims();
+    _o->keep_num_dims = _e;
+  }
+  {
+    auto _e = asymmetric_quantize_inputs();
+    _o->asymmetric_quantize_inputs = _e;
   }
 }
 
-inline flatbuffers::Offset<SparsityParameters>
-SparsityParameters::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT *_o,
-                         const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<FullyConnectedOptions>
+FullyConnectedOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT *_o,
+                            const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSparsityParameters(_fbb, _o, _rehasher);
+  return CreateFullyConnectedOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SparsityParameters>
-CreateSparsityParameters(flatbuffers::FlatBufferBuilder &_fbb, const SparsityParametersT *_o,
-                         const flatbuffers::rehasher_function_t *_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 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);
+    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 TensorT *Tensor::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SoftmaxOptionsT *
+SoftmaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<TensorT>(new TensorT());
+  auto _o = std::unique_ptr<SoftmaxOptionsT>(new SoftmaxOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void Tensor::UnPackTo(TensorT *_o, const flatbuffers::resolver_function_t *_resolver) const
+inline void SoftmaxOptions::UnPackTo(SoftmaxOptionsT *_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);
-      }
-    }
+    auto _e = beta();
+    _o->beta = _e;
   }
 }
 
-inline flatbuffers::Offset<Tensor> Tensor::Pack(flatbuffers::FlatBufferBuilder &_fbb,
-                                                const TensorT *_o,
-                                                const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<SoftmaxOptions>
+SoftmaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SoftmaxOptionsT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateTensor(_fbb, _o, _rehasher);
+  return CreateSoftmaxOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<Tensor> CreateTensor(flatbuffers::FlatBufferBuilder &_fbb,
-                                                const TensorT *_o,
-                                                const flatbuffers::rehasher_function_t *_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 TensorT *__o;
+    const SoftmaxOptionsT *__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);
+  auto _beta = _o->beta;
+  return circle::CreateSoftmaxOptions(_fbb, _beta);
 }
 
-inline Conv2DOptionsT *
-Conv2DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ConcatenationOptionsT *
+ConcatenationOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<Conv2DOptionsT>(new Conv2DOptionsT());
+  auto _o = std::unique_ptr<ConcatenationOptionsT>(new ConcatenationOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void Conv2DOptions::UnPackTo(Conv2DOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void ConcatenationOptions::UnPackTo(ConcatenationOptionsT *_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 = axis();
+    _o->axis = _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)
+inline flatbuffers::Offset<ConcatenationOptions>
+ConcatenationOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ConcatenationOptionsT *_o,
+                           const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateConv2DOptions(_fbb, _o, _rehasher);
+  return CreateConcatenationOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<Conv2DOptions>
-CreateConv2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Conv2DOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 Conv2DOptionsT *__o;
+    const ConcatenationOptionsT *__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 _axis = _o->axis;
   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);
+  return circle::CreateConcatenationOptions(_fbb, _axis, _fused_activation_function);
 }
 
-inline Conv3DOptionsT *
-Conv3DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline AddOptionsT *AddOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<Conv3DOptionsT>(new Conv3DOptionsT());
+  auto _o = std::unique_ptr<AddOptionsT>(new AddOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void Conv3DOptions::UnPackTo(Conv3DOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void AddOptions::UnPackTo(AddOptionsT *_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;
+    auto _e = pot_scale_int16();
+    _o->pot_scale_int16 = _e;
   }
 }
 
-inline flatbuffers::Offset<Conv3DOptions>
-Conv3DOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<AddOptions>
+AddOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateConv3DOptions(_fbb, _o, _rehasher);
+  return CreateAddOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<Conv3DOptions>
-CreateConv3DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Conv3DOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 Conv3DOptionsT *__o;
+    const AddOptionsT *__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);
+  auto _pot_scale_int16 = _o->pot_scale_int16;
+  return circle::CreateAddOptions(_fbb, _fused_activation_function, _pot_scale_int16);
 }
 
-inline Pool2DOptionsT *
-Pool2DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline MulOptionsT *MulOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<Pool2DOptionsT>(new Pool2DOptionsT());
+  auto _o = std::unique_ptr<MulOptionsT>(new MulOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void Pool2DOptions::UnPackTo(Pool2DOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void MulOptions::UnPackTo(MulOptionsT *_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)
+inline flatbuffers::Offset<MulOptions>
+MulOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MulOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreatePool2DOptions(_fbb, _o, _rehasher);
+  return CreateMulOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<Pool2DOptions>
-CreatePool2DOptions(flatbuffers::FlatBufferBuilder &_fbb, const Pool2DOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 Pool2DOptionsT *__o;
+    const MulOptionsT *__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);
+  return circle::CreateMulOptions(_fbb, _fused_activation_function);
 }
 
-inline DepthwiseConv2DOptionsT *
-DepthwiseConv2DOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline L2NormOptionsT *
+L2NormOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<DepthwiseConv2DOptionsT>(new DepthwiseConv2DOptionsT());
+  auto _o = std::unique_ptr<L2NormOptionsT>(new L2NormOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void
-DepthwiseConv2DOptions::UnPackTo(DepthwiseConv2DOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+inline void L2NormOptions::UnPackTo(L2NormOptionsT *_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)
+inline flatbuffers::Offset<L2NormOptions>
+L2NormOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const L2NormOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateDepthwiseConv2DOptions(_fbb, _o, _rehasher);
+  return CreateL2NormOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<DepthwiseConv2DOptions>
-CreateDepthwiseConv2DOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                             const DepthwiseConv2DOptionsT *_o,
-                             const flatbuffers::rehasher_function_t *_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 DepthwiseConv2DOptionsT *__o;
+    const L2NormOptionsT *__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);
+  return circle::CreateL2NormOptions(_fbb, _fused_activation_function);
 }
 
-inline ConcatEmbeddingsOptionsT *
-ConcatEmbeddingsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline LocalResponseNormalizationOptionsT *
+LocalResponseNormalizationOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ConcatEmbeddingsOptionsT>(new ConcatEmbeddingsOptionsT());
+  auto _o =
+    std::unique_ptr<LocalResponseNormalizationOptionsT>(new LocalResponseNormalizationOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
 inline void
-ConcatEmbeddingsOptions::UnPackTo(ConcatEmbeddingsOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+LocalResponseNormalizationOptions::UnPackTo(LocalResponseNormalizationOptionsT *_o,
+                                            const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = num_channels();
-    _o->num_channels = _e;
+    auto _e = radius();
+    _o->radius = _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 = bias();
+    _o->bias = _e;
   }
   {
-    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);
-      }
-    }
+    auto _e = alpha();
+    _o->alpha = _e;
+  }
+  {
+    auto _e = beta();
+    _o->beta = _e;
   }
 }
 
-inline flatbuffers::Offset<ConcatEmbeddingsOptions>
-ConcatEmbeddingsOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
-                              const ConcatEmbeddingsOptionsT *_o,
-                              const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<LocalResponseNormalizationOptions>
+LocalResponseNormalizationOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                        const LocalResponseNormalizationOptionsT *_o,
+                                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateConcatEmbeddingsOptions(_fbb, _o, _rehasher);
+  return CreateLocalResponseNormalizationOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ConcatEmbeddingsOptions>
-CreateConcatEmbeddingsOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                              const ConcatEmbeddingsOptionsT *_o,
-                              const flatbuffers::rehasher_function_t *_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 ConcatEmbeddingsOptionsT *__o;
+    const LocalResponseNormalizationOptionsT *__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);
+  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 LSHProjectionOptionsT *
-LSHProjectionOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline LSTMOptionsT *LSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<LSHProjectionOptionsT>(new LSHProjectionOptionsT());
+  auto _o = std::unique_ptr<LSTMOptionsT>(new LSTMOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void LSHProjectionOptions::UnPackTo(LSHProjectionOptionsT *_o,
-                                           const flatbuffers::resolver_function_t *_resolver) const
+inline void LSTMOptions::UnPackTo(LSTMOptionsT *_o,
+                                  const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = type();
-    _o->type = _e;
+    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<LSHProjectionOptions>
-LSHProjectionOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT *_o,
-                           const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<LSTMOptions>
+LSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateLSHProjectionOptions(_fbb, _o, _rehasher);
+  return CreateLSTMOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<LSHProjectionOptions>
-CreateLSHProjectionOptions(flatbuffers::FlatBufferBuilder &_fbb, const LSHProjectionOptionsT *_o,
-                           const flatbuffers::rehasher_function_t *_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 LSHProjectionOptionsT *__o;
+    const LSTMOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  auto _type = _o->type;
-  return circle::CreateLSHProjectionOptions(_fbb, _type);
+  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 SVDFOptionsT *SVDFOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline UnidirectionalSequenceLSTMOptionsT *
+UnidirectionalSequenceLSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SVDFOptionsT>(new SVDFOptionsT());
+  auto _o =
+    std::unique_ptr<UnidirectionalSequenceLSTMOptionsT>(new UnidirectionalSequenceLSTMOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SVDFOptions::UnPackTo(SVDFOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+inline void
+UnidirectionalSequenceLSTMOptions::UnPackTo(UnidirectionalSequenceLSTMOptionsT *_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 = 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;
   }
+  {
+    auto _e = diagonal_recurrent_tensors();
+    _o->diagonal_recurrent_tensors = _e;
+  }
 }
 
-inline flatbuffers::Offset<SVDFOptions>
-SVDFOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<UnidirectionalSequenceLSTMOptions>
+UnidirectionalSequenceLSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                        const UnidirectionalSequenceLSTMOptionsT *_o,
+                                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSVDFOptions(_fbb, _o, _rehasher);
+  return CreateUnidirectionalSequenceLSTMOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SVDFOptions>
-CreateSVDFOptions(flatbuffers::FlatBufferBuilder &_fbb, const SVDFOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_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 SVDFOptionsT *__o;
+    const UnidirectionalSequenceLSTMOptionsT *__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 _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::CreateSVDFOptions(_fbb, _rank, _fused_activation_function,
-                                   _asymmetric_quantize_inputs);
+  auto _diagonal_recurrent_tensors = _o->diagonal_recurrent_tensors;
+  return circle::CreateUnidirectionalSequenceLSTMOptions(
+    _fbb, _fused_activation_function, _cell_clip, _proj_clip, _time_major,
+    _asymmetric_quantize_inputs, _diagonal_recurrent_tensors);
 }
 
-inline RNNOptionsT *RNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline BidirectionalSequenceLSTMOptionsT *
+BidirectionalSequenceLSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<RNNOptionsT>(new RNNOptionsT());
+  auto _o =
+    std::unique_ptr<BidirectionalSequenceLSTMOptionsT>(new BidirectionalSequenceLSTMOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void RNNOptions::UnPackTo(RNNOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+inline void
+BidirectionalSequenceLSTMOptions::UnPackTo(BidirectionalSequenceLSTMOptionsT *_o,
+                                           const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
@@ -16053,641 +18031,549 @@ inline void RNNOptions::UnPackTo(RNNOptionsT *_o,
     _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<RNNOptions>
-RNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<BidirectionalSequenceLSTMOptions>
+BidirectionalSequenceLSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                       const BidirectionalSequenceLSTMOptionsT *_o,
+                                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateRNNOptions(_fbb, _o, _rehasher);
+  return CreateBidirectionalSequenceLSTMOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<RNNOptions>
-CreateRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const RNNOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 RNNOptionsT *__o;
+    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::CreateRNNOptions(_fbb, _fused_activation_function, _asymmetric_quantize_inputs);
+  return circle::CreateBidirectionalSequenceLSTMOptions(_fbb, _fused_activation_function,
+                                                        _cell_clip, _proj_clip, _merge_outputs,
+                                                        _time_major, _asymmetric_quantize_inputs);
 }
 
-inline SequenceRNNOptionsT *
-SequenceRNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ResizeBilinearOptionsT *
+ResizeBilinearOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SequenceRNNOptionsT>(new SequenceRNNOptionsT());
+  auto _o = std::unique_ptr<ResizeBilinearOptionsT>(new ResizeBilinearOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SequenceRNNOptions::UnPackTo(SequenceRNNOptionsT *_o,
-                                         const flatbuffers::resolver_function_t *_resolver) const
+inline void ResizeBilinearOptions::UnPackTo(ResizeBilinearOptionsT *_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 = align_corners();
+    _o->align_corners = _e;
   }
   {
-    auto _e = asymmetric_quantize_inputs();
-    _o->asymmetric_quantize_inputs = _e;
+    auto _e = half_pixel_centers();
+    _o->half_pixel_centers = _e;
   }
 }
 
-inline flatbuffers::Offset<SequenceRNNOptions>
-SequenceRNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT *_o,
-                         const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<ResizeBilinearOptions>
+ResizeBilinearOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT *_o,
+                            const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSequenceRNNOptions(_fbb, _o, _rehasher);
+  return CreateResizeBilinearOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SequenceRNNOptions>
-CreateSequenceRNNOptions(flatbuffers::FlatBufferBuilder &_fbb, const SequenceRNNOptionsT *_o,
-                         const flatbuffers::rehasher_function_t *_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 SequenceRNNOptionsT *__o;
+    const ResizeBilinearOptionsT *__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);
+  auto _align_corners = _o->align_corners;
+  auto _half_pixel_centers = _o->half_pixel_centers;
+  return circle::CreateResizeBilinearOptions(_fbb, _align_corners, _half_pixel_centers);
 }
 
-inline BidirectionalSequenceRNNOptionsT *
-BidirectionalSequenceRNNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ResizeNearestNeighborOptionsT *
+ResizeNearestNeighborOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o =
-    std::unique_ptr<BidirectionalSequenceRNNOptionsT>(new BidirectionalSequenceRNNOptionsT());
+  auto _o = std::unique_ptr<ResizeNearestNeighborOptionsT>(new ResizeNearestNeighborOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
 inline void
-BidirectionalSequenceRNNOptions::UnPackTo(BidirectionalSequenceRNNOptionsT *_o,
-                                          const flatbuffers::resolver_function_t *_resolver) const
+ResizeNearestNeighborOptions::UnPackTo(ResizeNearestNeighborOptionsT *_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 = align_corners();
+    _o->align_corners = _e;
   }
   {
-    auto _e = asymmetric_quantize_inputs();
-    _o->asymmetric_quantize_inputs = _e;
+    auto _e = half_pixel_centers();
+    _o->half_pixel_centers = _e;
   }
 }
 
-inline flatbuffers::Offset<BidirectionalSequenceRNNOptions>
-BidirectionalSequenceRNNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
-                                      const BidirectionalSequenceRNNOptionsT *_o,
-                                      const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<ResizeNearestNeighborOptions>
+ResizeNearestNeighborOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                   const ResizeNearestNeighborOptionsT *_o,
+                                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateBidirectionalSequenceRNNOptions(_fbb, _o, _rehasher);
+  return CreateResizeNearestNeighborOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<BidirectionalSequenceRNNOptions>
-CreateBidirectionalSequenceRNNOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                                      const BidirectionalSequenceRNNOptionsT *_o,
-                                      const flatbuffers::rehasher_function_t *_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 BidirectionalSequenceRNNOptionsT *__o;
+    const ResizeNearestNeighborOptionsT *__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);
+  auto _align_corners = _o->align_corners;
+  auto _half_pixel_centers = _o->half_pixel_centers;
+  return circle::CreateResizeNearestNeighborOptions(_fbb, _align_corners, _half_pixel_centers);
 }
 
-inline FullyConnectedOptionsT *
-FullyConnectedOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline CallOptionsT *CallOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<FullyConnectedOptionsT>(new FullyConnectedOptionsT());
+  auto _o = std::unique_ptr<CallOptionsT>(new CallOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void FullyConnectedOptions::UnPackTo(FullyConnectedOptionsT *_o,
-                                            const flatbuffers::resolver_function_t *_resolver) const
+inline void CallOptions::UnPackTo(CallOptionsT *_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;
+    auto _e = subgraph();
+    _o->subgraph = _e;
   }
 }
 
-inline flatbuffers::Offset<FullyConnectedOptions>
-FullyConnectedOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT *_o,
-                            const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<CallOptions>
+CallOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateFullyConnectedOptions(_fbb, _o, _rehasher);
+  return CreateCallOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<FullyConnectedOptions>
-CreateFullyConnectedOptions(flatbuffers::FlatBufferBuilder &_fbb, const FullyConnectedOptionsT *_o,
-                            const flatbuffers::rehasher_function_t *_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 FullyConnectedOptionsT *__o;
+    const CallOptionsT *__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);
+  auto _subgraph = _o->subgraph;
+  return circle::CreateCallOptions(_fbb, _subgraph);
 }
 
-inline SoftmaxOptionsT *
-SoftmaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline PadOptionsT *PadOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SoftmaxOptionsT>(new SoftmaxOptionsT());
+  auto _o = std::unique_ptr<PadOptionsT>(new PadOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SoftmaxOptions::UnPackTo(SoftmaxOptionsT *_o,
-                                     const flatbuffers::resolver_function_t *_resolver) const
+inline void PadOptions::UnPackTo(PadOptionsT *_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)
+inline flatbuffers::Offset<PadOptions>
+PadOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSoftmaxOptions(_fbb, _o, _rehasher);
+  return CreatePadOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SoftmaxOptions>
-CreateSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const SoftmaxOptionsT *_o,
-                     const flatbuffers::rehasher_function_t *_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 SoftmaxOptionsT *__o;
+    const PadOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  auto _beta = _o->beta;
-  return circle::CreateSoftmaxOptions(_fbb, _beta);
+  return circle::CreatePadOptions(_fbb);
 }
 
-inline ConcatenationOptionsT *
-ConcatenationOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline PadV2OptionsT *PadV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ConcatenationOptionsT>(new ConcatenationOptionsT());
+  auto _o = std::unique_ptr<PadV2OptionsT>(new PadV2OptionsT());
   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)
+inline void PadV2Options::UnPackTo(PadV2OptionsT *_o,
+                                   const flatbuffers::resolver_function_t *_resolver) const
 {
-  return CreateConcatenationOptions(_fbb, _o, _rehasher);
+  (void)_o;
+  (void)_resolver;
 }
 
-inline flatbuffers::Offset<ConcatenationOptions>
-CreateConcatenationOptions(flatbuffers::FlatBufferBuilder &_fbb, const ConcatenationOptionsT *_o,
-                           const flatbuffers::rehasher_function_t *_rehasher)
+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 ConcatenationOptionsT *__o;
+    const PadV2OptionsT *__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);
+  return circle::CreatePadV2Options(_fbb);
 }
 
-inline AddOptionsT *AddOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ReshapeOptionsT *
+ReshapeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<AddOptionsT>(new AddOptionsT());
+  auto _o = std::unique_ptr<ReshapeOptionsT>(new ReshapeOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void AddOptions::UnPackTo(AddOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+inline void ReshapeOptions::UnPackTo(ReshapeOptionsT *_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;
+    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<AddOptions>
-AddOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<ReshapeOptions>
+ReshapeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReshapeOptionsT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateAddOptions(_fbb, _o, _rehasher);
+  return CreateReshapeOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<AddOptions>
-CreateAddOptions(flatbuffers::FlatBufferBuilder &_fbb, const AddOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 AddOptionsT *__o;
+    const ReshapeOptionsT *__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);
+  auto _new_shape = _o->new_shape.size() ? _fbb.CreateVector(_o->new_shape) : 0;
+  return circle::CreateReshapeOptions(_fbb, _new_shape);
 }
 
-inline MulOptionsT *MulOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SpaceToBatchNDOptionsT *
+SpaceToBatchNDOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<MulOptionsT>(new MulOptionsT());
+  auto _o = std::unique_ptr<SpaceToBatchNDOptionsT>(new SpaceToBatchNDOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void MulOptions::UnPackTo(MulOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+inline void SpaceToBatchNDOptions::UnPackTo(SpaceToBatchNDOptionsT *_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)
+inline flatbuffers::Offset<SpaceToBatchNDOptions>
+SpaceToBatchNDOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToBatchNDOptionsT *_o,
+                            const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateMulOptions(_fbb, _o, _rehasher);
+  return CreateSpaceToBatchNDOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<MulOptions>
-CreateMulOptions(flatbuffers::FlatBufferBuilder &_fbb, const MulOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 MulOptionsT *__o;
+    const SpaceToBatchNDOptionsT *__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);
+  return circle::CreateSpaceToBatchNDOptions(_fbb);
 }
 
-inline L2NormOptionsT *
-L2NormOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline BatchToSpaceNDOptionsT *
+BatchToSpaceNDOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<L2NormOptionsT>(new L2NormOptionsT());
+  auto _o = std::unique_ptr<BatchToSpaceNDOptionsT>(new BatchToSpaceNDOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void L2NormOptions::UnPackTo(L2NormOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void BatchToSpaceNDOptions::UnPackTo(BatchToSpaceNDOptionsT *_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)
+inline flatbuffers::Offset<BatchToSpaceNDOptions>
+BatchToSpaceNDOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT *_o,
+                            const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateL2NormOptions(_fbb, _o, _rehasher);
+  return CreateBatchToSpaceNDOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<L2NormOptions>
-CreateL2NormOptions(flatbuffers::FlatBufferBuilder &_fbb, const L2NormOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 L2NormOptionsT *__o;
+    const BatchToSpaceNDOptionsT *__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);
+  return circle::CreateBatchToSpaceNDOptions(_fbb);
 }
 
-inline LocalResponseNormalizationOptionsT *
-LocalResponseNormalizationOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SkipGramOptionsT *
+SkipGramOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o =
-    std::unique_ptr<LocalResponseNormalizationOptionsT>(new LocalResponseNormalizationOptionsT());
+  auto _o = std::unique_ptr<SkipGramOptionsT>(new SkipGramOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void
-LocalResponseNormalizationOptions::UnPackTo(LocalResponseNormalizationOptionsT *_o,
-                                            const flatbuffers::resolver_function_t *_resolver) const
+inline void SkipGramOptions::UnPackTo(SkipGramOptionsT *_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 = ngram_size();
+    _o->ngram_size = _e;
   }
   {
-    auto _e = alpha();
-    _o->alpha = _e;
+    auto _e = max_skip_size();
+    _o->max_skip_size = _e;
   }
   {
-    auto _e = beta();
-    _o->beta = _e;
+    auto _e = include_all_ngrams();
+    _o->include_all_ngrams = _e;
   }
 }
 
-inline flatbuffers::Offset<LocalResponseNormalizationOptions>
-LocalResponseNormalizationOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
-                                        const LocalResponseNormalizationOptionsT *_o,
-                                        const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<SkipGramOptions>
+SkipGramOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT *_o,
+                      const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateLocalResponseNormalizationOptions(_fbb, _o, _rehasher);
+  return CreateSkipGramOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<LocalResponseNormalizationOptions>
-CreateLocalResponseNormalizationOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                                        const LocalResponseNormalizationOptionsT *_o,
-                                        const flatbuffers::rehasher_function_t *_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 LocalResponseNormalizationOptionsT *__o;
+    const SkipGramOptionsT *__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);
+  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 LSTMOptionsT *LSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SpaceToDepthOptionsT *
+SpaceToDepthOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<LSTMOptionsT>(new LSTMOptionsT());
+  auto _o = std::unique_ptr<SpaceToDepthOptionsT>(new SpaceToDepthOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void LSTMOptions::UnPackTo(LSTMOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+inline void SpaceToDepthOptions::UnPackTo(SpaceToDepthOptionsT *_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;
+    auto _e = block_size();
+    _o->block_size = _e;
   }
 }
 
-inline flatbuffers::Offset<LSTMOptions>
-LSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<SpaceToDepthOptions>
+SpaceToDepthOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT *_o,
+                          const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateLSTMOptions(_fbb, _o, _rehasher);
+  return CreateSpaceToDepthOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<LSTMOptions>
-CreateLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb, const LSTMOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_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 LSTMOptionsT *__o;
+    const SpaceToDepthOptionsT *__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);
+  auto _block_size = _o->block_size;
+  return circle::CreateSpaceToDepthOptions(_fbb, _block_size);
 }
 
-inline UnidirectionalSequenceLSTMOptionsT *
-UnidirectionalSequenceLSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline DepthToSpaceOptionsT *
+DepthToSpaceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o =
-    std::unique_ptr<UnidirectionalSequenceLSTMOptionsT>(new UnidirectionalSequenceLSTMOptionsT());
+  auto _o = std::unique_ptr<DepthToSpaceOptionsT>(new DepthToSpaceOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void
-UnidirectionalSequenceLSTMOptions::UnPackTo(UnidirectionalSequenceLSTMOptionsT *_o,
-                                            const flatbuffers::resolver_function_t *_resolver) const
+inline void DepthToSpaceOptions::UnPackTo(DepthToSpaceOptionsT *_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;
+    auto _e = block_size();
+    _o->block_size = _e;
   }
 }
 
-inline flatbuffers::Offset<UnidirectionalSequenceLSTMOptions>
-UnidirectionalSequenceLSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
-                                        const UnidirectionalSequenceLSTMOptionsT *_o,
-                                        const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<DepthToSpaceOptions>
+DepthToSpaceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT *_o,
+                          const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateUnidirectionalSequenceLSTMOptions(_fbb, _o, _rehasher);
+  return CreateDepthToSpaceOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<UnidirectionalSequenceLSTMOptions>
-CreateUnidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                                        const UnidirectionalSequenceLSTMOptionsT *_o,
-                                        const flatbuffers::rehasher_function_t *_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 UnidirectionalSequenceLSTMOptionsT *__o;
+    const DepthToSpaceOptionsT *__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);
+  auto _block_size = _o->block_size;
+  return circle::CreateDepthToSpaceOptions(_fbb, _block_size);
 }
 
-inline BidirectionalSequenceLSTMOptionsT *
-BidirectionalSequenceLSTMOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SubOptionsT *SubOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o =
-    std::unique_ptr<BidirectionalSequenceLSTMOptionsT>(new BidirectionalSequenceLSTMOptionsT());
+  auto _o = std::unique_ptr<SubOptionsT>(new SubOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void
-BidirectionalSequenceLSTMOptions::UnPackTo(BidirectionalSequenceLSTMOptionsT *_o,
-                                           const flatbuffers::resolver_function_t *_resolver) const
+inline void SubOptions::UnPackTo(SubOptionsT *_o,
+                                 const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
@@ -16696,901 +18582,872 @@ BidirectionalSequenceLSTMOptions::UnPackTo(BidirectionalSequenceLSTMOptionsT *_o
     _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;
+    auto _e = pot_scale_int16();
+    _o->pot_scale_int16 = _e;
   }
 }
 
-inline flatbuffers::Offset<BidirectionalSequenceLSTMOptions>
-BidirectionalSequenceLSTMOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
-                                       const BidirectionalSequenceLSTMOptionsT *_o,
-                                       const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<SubOptions>
+SubOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateBidirectionalSequenceLSTMOptions(_fbb, _o, _rehasher);
+  return CreateSubOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<BidirectionalSequenceLSTMOptions>
-CreateBidirectionalSequenceLSTMOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                                       const BidirectionalSequenceLSTMOptionsT *_o,
-                                       const flatbuffers::rehasher_function_t *_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 BidirectionalSequenceLSTMOptionsT *__o;
+    const SubOptionsT *__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);
+  auto _pot_scale_int16 = _o->pot_scale_int16;
+  return circle::CreateSubOptions(_fbb, _fused_activation_function, _pot_scale_int16);
 }
 
-inline ResizeBilinearOptionsT *
-ResizeBilinearOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline DivOptionsT *DivOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ResizeBilinearOptionsT>(new ResizeBilinearOptionsT());
+  auto _o = std::unique_ptr<DivOptionsT>(new DivOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ResizeBilinearOptions::UnPackTo(ResizeBilinearOptionsT *_o,
-                                            const flatbuffers::resolver_function_t *_resolver) const
+inline void DivOptions::UnPackTo(DivOptionsT *_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;
+    auto _e = fused_activation_function();
+    _o->fused_activation_function = _e;
   }
 }
 
-inline flatbuffers::Offset<ResizeBilinearOptions>
-ResizeBilinearOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT *_o,
-                            const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<DivOptions>
+DivOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DivOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateResizeBilinearOptions(_fbb, _o, _rehasher);
+  return CreateDivOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ResizeBilinearOptions>
-CreateResizeBilinearOptions(flatbuffers::FlatBufferBuilder &_fbb, const ResizeBilinearOptionsT *_o,
-                            const flatbuffers::rehasher_function_t *_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 ResizeBilinearOptionsT *__o;
+    const DivOptionsT *__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);
+  auto _fused_activation_function = _o->fused_activation_function;
+  return circle::CreateDivOptions(_fbb, _fused_activation_function);
 }
 
-inline ResizeNearestNeighborOptionsT *
-ResizeNearestNeighborOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline TopKV2OptionsT *
+TopKV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ResizeNearestNeighborOptionsT>(new ResizeNearestNeighborOptionsT());
+  auto _o = std::unique_ptr<TopKV2OptionsT>(new TopKV2OptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void
-ResizeNearestNeighborOptions::UnPackTo(ResizeNearestNeighborOptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+inline void TopKV2Options::UnPackTo(TopKV2OptionsT *_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)
+inline flatbuffers::Offset<TopKV2Options>
+TopKV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateResizeNearestNeighborOptions(_fbb, _o, _rehasher);
+  return CreateTopKV2Options(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ResizeNearestNeighborOptions>
-CreateResizeNearestNeighborOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                                   const ResizeNearestNeighborOptionsT *_o,
-                                   const flatbuffers::rehasher_function_t *_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 ResizeNearestNeighborOptionsT *__o;
+    const TopKV2OptionsT *__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);
+  return circle::CreateTopKV2Options(_fbb);
 }
 
-inline CallOptionsT *CallOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline EmbeddingLookupSparseOptionsT *
+EmbeddingLookupSparseOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<CallOptionsT>(new CallOptionsT());
+  auto _o = std::unique_ptr<EmbeddingLookupSparseOptionsT>(new EmbeddingLookupSparseOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void CallOptions::UnPackTo(CallOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+inline void
+EmbeddingLookupSparseOptions::UnPackTo(EmbeddingLookupSparseOptionsT *_o,
+                                       const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = subgraph();
-    _o->subgraph = _e;
+    auto _e = combiner();
+    _o->combiner = _e;
   }
 }
 
-inline flatbuffers::Offset<CallOptions>
-CallOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<EmbeddingLookupSparseOptions>
+EmbeddingLookupSparseOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                   const EmbeddingLookupSparseOptionsT *_o,
+                                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateCallOptions(_fbb, _o, _rehasher);
+  return CreateEmbeddingLookupSparseOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<CallOptions>
-CreateCallOptions(flatbuffers::FlatBufferBuilder &_fbb, const CallOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_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 CallOptionsT *__o;
+    const EmbeddingLookupSparseOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  auto _subgraph = _o->subgraph;
-  return circle::CreateCallOptions(_fbb, _subgraph);
+  auto _combiner = _o->combiner;
+  return circle::CreateEmbeddingLookupSparseOptions(_fbb, _combiner);
 }
 
-inline PadOptionsT *PadOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline GatherOptionsT *
+GatherOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<PadOptionsT>(new PadOptionsT());
+  auto _o = std::unique_ptr<GatherOptionsT>(new GatherOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void PadOptions::UnPackTo(PadOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+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<PadOptions>
-PadOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<GatherOptions>
+GatherOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreatePadOptions(_fbb, _o, _rehasher);
+  return CreateGatherOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<PadOptions>
-CreatePadOptions(flatbuffers::FlatBufferBuilder &_fbb, const PadOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 PadOptionsT *__o;
+    const GatherOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreatePadOptions(_fbb);
+  auto _axis = _o->axis;
+  auto _batch_dims = _o->batch_dims;
+  return circle::CreateGatherOptions(_fbb, _axis, _batch_dims);
 }
 
-inline PadV2OptionsT *PadV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline TransposeOptionsT *
+TransposeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<PadV2OptionsT>(new PadV2OptionsT());
+  auto _o = std::unique_ptr<TransposeOptionsT>(new TransposeOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void PadV2Options::UnPackTo(PadV2OptionsT *_o,
-                                   const flatbuffers::resolver_function_t *_resolver) const
+inline void TransposeOptions::UnPackTo(TransposeOptionsT *_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)
+inline flatbuffers::Offset<TransposeOptions>
+TransposeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TransposeOptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreatePadV2Options(_fbb, _o, _rehasher);
+  return CreateTransposeOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<PadV2Options>
-CreatePadV2Options(flatbuffers::FlatBufferBuilder &_fbb, const PadV2OptionsT *_o,
-                   const flatbuffers::rehasher_function_t *_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 PadV2OptionsT *__o;
+    const TransposeOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreatePadV2Options(_fbb);
+  return circle::CreateTransposeOptions(_fbb);
 }
 
-inline ReshapeOptionsT *
-ReshapeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ExpOptionsT *ExpOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ReshapeOptionsT>(new ReshapeOptionsT());
+  auto _o = std::unique_ptr<ExpOptionsT>(new ExpOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ReshapeOptions::UnPackTo(ReshapeOptionsT *_o,
-                                     const flatbuffers::resolver_function_t *_resolver) const
+inline void ExpOptions::UnPackTo(ExpOptionsT *_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)
+inline flatbuffers::Offset<ExpOptions>
+ExpOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateReshapeOptions(_fbb, _o, _rehasher);
+  return CreateExpOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ReshapeOptions>
-CreateReshapeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReshapeOptionsT *_o,
-                     const flatbuffers::rehasher_function_t *_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 ReshapeOptionsT *__o;
+    const ExpOptionsT *__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);
+  return circle::CreateExpOptions(_fbb);
 }
 
-inline SpaceToBatchNDOptionsT *
-SpaceToBatchNDOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline CosOptionsT *CosOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SpaceToBatchNDOptionsT>(new SpaceToBatchNDOptionsT());
+  auto _o = std::unique_ptr<CosOptionsT>(new CosOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SpaceToBatchNDOptions::UnPackTo(SpaceToBatchNDOptionsT *_o,
-                                            const flatbuffers::resolver_function_t *_resolver) const
+inline void CosOptions::UnPackTo(CosOptionsT *_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)
+inline flatbuffers::Offset<CosOptions>
+CosOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSpaceToBatchNDOptions(_fbb, _o, _rehasher);
+  return CreateCosOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SpaceToBatchNDOptions>
-CreateSpaceToBatchNDOptions(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToBatchNDOptionsT *_o,
-                            const flatbuffers::rehasher_function_t *_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 SpaceToBatchNDOptionsT *__o;
+    const CosOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateSpaceToBatchNDOptions(_fbb);
+  return circle::CreateCosOptions(_fbb);
 }
 
-inline BatchToSpaceNDOptionsT *
-BatchToSpaceNDOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ReducerOptionsT *
+ReducerOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<BatchToSpaceNDOptionsT>(new BatchToSpaceNDOptionsT());
+  auto _o = std::unique_ptr<ReducerOptionsT>(new ReducerOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void BatchToSpaceNDOptions::UnPackTo(BatchToSpaceNDOptionsT *_o,
-                                            const flatbuffers::resolver_function_t *_resolver) const
+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<BatchToSpaceNDOptions>
-BatchToSpaceNDOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT *_o,
-                            const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<ReducerOptions>
+ReducerOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateBatchToSpaceNDOptions(_fbb, _o, _rehasher);
+  return CreateReducerOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<BatchToSpaceNDOptions>
-CreateBatchToSpaceNDOptions(flatbuffers::FlatBufferBuilder &_fbb, const BatchToSpaceNDOptionsT *_o,
-                            const flatbuffers::rehasher_function_t *_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 BatchToSpaceNDOptionsT *__o;
+    const ReducerOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateBatchToSpaceNDOptions(_fbb);
+  auto _keep_dims = _o->keep_dims;
+  return circle::CreateReducerOptions(_fbb, _keep_dims);
 }
 
-inline SkipGramOptionsT *
-SkipGramOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SqueezeOptionsT *
+SqueezeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SkipGramOptionsT>(new SkipGramOptionsT());
+  auto _o = std::unique_ptr<SqueezeOptionsT>(new SqueezeOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SkipGramOptions::UnPackTo(SkipGramOptionsT *_o,
-                                      const flatbuffers::resolver_function_t *_resolver) const
+inline void SqueezeOptions::UnPackTo(SqueezeOptionsT *_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;
+    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<SkipGramOptions>
-SkipGramOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT *_o,
-                      const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<SqueezeOptions>
+SqueezeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SqueezeOptionsT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSkipGramOptions(_fbb, _o, _rehasher);
+  return CreateSqueezeOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SkipGramOptions>
-CreateSkipGramOptions(flatbuffers::FlatBufferBuilder &_fbb, const SkipGramOptionsT *_o,
-                      const flatbuffers::rehasher_function_t *_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 SkipGramOptionsT *__o;
+    const SqueezeOptionsT *__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);
+  auto _squeeze_dims = _o->squeeze_dims.size() ? _fbb.CreateVector(_o->squeeze_dims) : 0;
+  return circle::CreateSqueezeOptions(_fbb, _squeeze_dims);
 }
 
-inline SpaceToDepthOptionsT *
-SpaceToDepthOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SplitOptionsT *SplitOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SpaceToDepthOptionsT>(new SpaceToDepthOptionsT());
+  auto _o = std::unique_ptr<SplitOptionsT>(new SplitOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SpaceToDepthOptions::UnPackTo(SpaceToDepthOptionsT *_o,
-                                          const flatbuffers::resolver_function_t *_resolver) const
+inline void SplitOptions::UnPackTo(SplitOptionsT *_o,
+                                   const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = block_size();
-    _o->block_size = _e;
+    auto _e = num_splits();
+    _o->num_splits = _e;
   }
 }
 
-inline flatbuffers::Offset<SpaceToDepthOptions>
-SpaceToDepthOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT *_o,
-                          const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<SplitOptions>
+SplitOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSpaceToDepthOptions(_fbb, _o, _rehasher);
+  return CreateSplitOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SpaceToDepthOptions>
-CreateSpaceToDepthOptions(flatbuffers::FlatBufferBuilder &_fbb, const SpaceToDepthOptionsT *_o,
-                          const flatbuffers::rehasher_function_t *_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 SpaceToDepthOptionsT *__o;
+    const SplitOptionsT *__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);
+  auto _num_splits = _o->num_splits;
+  return circle::CreateSplitOptions(_fbb, _num_splits);
 }
 
-inline DepthToSpaceOptionsT *
-DepthToSpaceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SplitVOptionsT *
+SplitVOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<DepthToSpaceOptionsT>(new DepthToSpaceOptionsT());
+  auto _o = std::unique_ptr<SplitVOptionsT>(new SplitVOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void DepthToSpaceOptions::UnPackTo(DepthToSpaceOptionsT *_o,
-                                          const flatbuffers::resolver_function_t *_resolver) const
+inline void SplitVOptions::UnPackTo(SplitVOptionsT *_o,
+                                    const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = block_size();
-    _o->block_size = _e;
+    auto _e = num_splits();
+    _o->num_splits = _e;
   }
 }
 
-inline flatbuffers::Offset<DepthToSpaceOptions>
-DepthToSpaceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT *_o,
-                          const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<SplitVOptions>
+SplitVOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateDepthToSpaceOptions(_fbb, _o, _rehasher);
+  return CreateSplitVOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<DepthToSpaceOptions>
-CreateDepthToSpaceOptions(flatbuffers::FlatBufferBuilder &_fbb, const DepthToSpaceOptionsT *_o,
-                          const flatbuffers::rehasher_function_t *_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 DepthToSpaceOptionsT *__o;
+    const SplitVOptionsT *__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);
+  auto _num_splits = _o->num_splits;
+  return circle::CreateSplitVOptions(_fbb, _num_splits);
 }
 
-inline SubOptionsT *SubOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline StridedSliceOptionsT *
+StridedSliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SubOptionsT>(new SubOptionsT());
+  auto _o = std::unique_ptr<StridedSliceOptionsT>(new StridedSliceOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SubOptions::UnPackTo(SubOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+inline void StridedSliceOptions::UnPackTo(StridedSliceOptionsT *_o,
+                                          const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = fused_activation_function();
-    _o->fused_activation_function = _e;
+    auto _e = begin_mask();
+    _o->begin_mask = _e;
+  }
+  {
+    auto _e = end_mask();
+    _o->end_mask = _e;
   }
   {
-    auto _e = pot_scale_int16();
-    _o->pot_scale_int16 = _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<SubOptions>
-SubOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<StridedSliceOptions>
+StridedSliceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const StridedSliceOptionsT *_o,
+                          const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSubOptions(_fbb, _o, _rehasher);
+  return CreateStridedSliceOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SubOptions>
-CreateSubOptions(flatbuffers::FlatBufferBuilder &_fbb, const SubOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 SubOptionsT *__o;
+    const StridedSliceOptionsT *__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);
+  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 DivOptionsT *DivOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline LogSoftmaxOptionsT *
+LogSoftmaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<DivOptionsT>(new DivOptionsT());
+  auto _o = std::unique_ptr<LogSoftmaxOptionsT>(new LogSoftmaxOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void DivOptions::UnPackTo(DivOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+inline void LogSoftmaxOptions::UnPackTo(LogSoftmaxOptionsT *_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)
+inline flatbuffers::Offset<LogSoftmaxOptions>
+LogSoftmaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogSoftmaxOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateDivOptions(_fbb, _o, _rehasher);
+  return CreateLogSoftmaxOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<DivOptions>
-CreateDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const DivOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 DivOptionsT *__o;
+    const LogSoftmaxOptionsT *__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);
+  return circle::CreateLogSoftmaxOptions(_fbb);
 }
 
-inline TopKV2OptionsT *
-TopKV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline CastOptionsT *CastOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<TopKV2OptionsT>(new TopKV2OptionsT());
+  auto _o = std::unique_ptr<CastOptionsT>(new CastOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void TopKV2Options::UnPackTo(TopKV2OptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+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<TopKV2Options>
-TopKV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<CastOptions>
+CastOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CastOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateTopKV2Options(_fbb, _o, _rehasher);
+  return CreateCastOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<TopKV2Options>
-CreateTopKV2Options(flatbuffers::FlatBufferBuilder &_fbb, const TopKV2OptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 TopKV2OptionsT *__o;
+    const CastOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateTopKV2Options(_fbb);
+  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 EmbeddingLookupSparseOptionsT *
-EmbeddingLookupSparseOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline DequantizeOptionsT *
+DequantizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<EmbeddingLookupSparseOptionsT>(new EmbeddingLookupSparseOptionsT());
+  auto _o = std::unique_ptr<DequantizeOptionsT>(new DequantizeOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void
-EmbeddingLookupSparseOptions::UnPackTo(EmbeddingLookupSparseOptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+inline void DequantizeOptions::UnPackTo(DequantizeOptionsT *_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)
+inline flatbuffers::Offset<DequantizeOptions>
+DequantizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateEmbeddingLookupSparseOptions(_fbb, _o, _rehasher);
+  return CreateDequantizeOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<EmbeddingLookupSparseOptions>
-CreateEmbeddingLookupSparseOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                                   const EmbeddingLookupSparseOptionsT *_o,
-                                   const flatbuffers::rehasher_function_t *_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 EmbeddingLookupSparseOptionsT *__o;
+    const DequantizeOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  auto _combiner = _o->combiner;
-  return circle::CreateEmbeddingLookupSparseOptions(_fbb, _combiner);
+  return circle::CreateDequantizeOptions(_fbb);
 }
 
-inline GatherOptionsT *
-GatherOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline MaximumMinimumOptionsT *
+MaximumMinimumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<GatherOptionsT>(new GatherOptionsT());
+  auto _o = std::unique_ptr<MaximumMinimumOptionsT>(new MaximumMinimumOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void GatherOptions::UnPackTo(GatherOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void MaximumMinimumOptions::UnPackTo(MaximumMinimumOptionsT *_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)
+inline flatbuffers::Offset<MaximumMinimumOptions>
+MaximumMinimumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MaximumMinimumOptionsT *_o,
+                            const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateGatherOptions(_fbb, _o, _rehasher);
+  return CreateMaximumMinimumOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<GatherOptions>
-CreateGatherOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 GatherOptionsT *__o;
+    const MaximumMinimumOptionsT *__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);
+  return circle::CreateMaximumMinimumOptions(_fbb);
 }
 
-inline TransposeOptionsT *
-TransposeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline TileOptionsT *TileOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<TransposeOptionsT>(new TransposeOptionsT());
+  auto _o = std::unique_ptr<TileOptionsT>(new TileOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void TransposeOptions::UnPackTo(TransposeOptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+inline void TileOptions::UnPackTo(TileOptionsT *_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)
+inline flatbuffers::Offset<TileOptions>
+TileOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateTransposeOptions(_fbb, _o, _rehasher);
+  return CreateTileOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<TransposeOptions>
-CreateTransposeOptions(flatbuffers::FlatBufferBuilder &_fbb, const TransposeOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_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 TransposeOptionsT *__o;
+    const TileOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateTransposeOptions(_fbb);
+  return circle::CreateTileOptions(_fbb);
 }
 
-inline ExpOptionsT *ExpOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ArgMaxOptionsT *
+ArgMaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ExpOptionsT>(new ExpOptionsT());
+  auto _o = std::unique_ptr<ArgMaxOptionsT>(new ArgMaxOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ExpOptions::UnPackTo(ExpOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+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<ExpOptions>
-ExpOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<ArgMaxOptions>
+ArgMaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArgMaxOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateExpOptions(_fbb, _o, _rehasher);
+  return CreateArgMaxOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ExpOptions>
-CreateExpOptions(flatbuffers::FlatBufferBuilder &_fbb, const ExpOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 ExpOptionsT *__o;
+    const ArgMaxOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateExpOptions(_fbb);
+  auto _output_type = _o->output_type;
+  return circle::CreateArgMaxOptions(_fbb, _output_type);
 }
 
-inline CosOptionsT *CosOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ArgMinOptionsT *
+ArgMinOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<CosOptionsT>(new CosOptionsT());
+  auto _o = std::unique_ptr<ArgMinOptionsT>(new ArgMinOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void CosOptions::UnPackTo(CosOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+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<CosOptions>
-CosOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<ArgMinOptions>
+ArgMinOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArgMinOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateCosOptions(_fbb, _o, _rehasher);
+  return CreateArgMinOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<CosOptions>
-CreateCosOptions(flatbuffers::FlatBufferBuilder &_fbb, const CosOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 CosOptionsT *__o;
+    const ArgMinOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateCosOptions(_fbb);
+  auto _output_type = _o->output_type;
+  return circle::CreateArgMinOptions(_fbb, _output_type);
 }
 
-inline ReducerOptionsT *
-ReducerOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline GreaterOptionsT *
+GreaterOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ReducerOptionsT>(new ReducerOptionsT());
+  auto _o = std::unique_ptr<GreaterOptionsT>(new GreaterOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ReducerOptions::UnPackTo(ReducerOptionsT *_o,
+inline void GreaterOptions::UnPackTo(GreaterOptionsT *_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,
+inline flatbuffers::Offset<GreaterOptions>
+GreaterOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT *_o,
                      const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateReducerOptions(_fbb, _o, _rehasher);
+  return CreateGreaterOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ReducerOptions>
-CreateReducerOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT *_o,
+inline flatbuffers::Offset<GreaterOptions>
+CreateGreaterOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT *_o,
                      const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
@@ -17598,634 +19455,609 @@ CreateReducerOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReducerOptionsT
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const ReducerOptionsT *__o;
+    const GreaterOptionsT *__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);
+  return circle::CreateGreaterOptions(_fbb);
 }
 
-inline SqueezeOptionsT *
-SqueezeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline GreaterEqualOptionsT *
+GreaterEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SqueezeOptionsT>(new SqueezeOptionsT());
+  auto _o = std::unique_ptr<GreaterEqualOptionsT>(new GreaterEqualOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SqueezeOptions::UnPackTo(SqueezeOptionsT *_o,
-                                     const flatbuffers::resolver_function_t *_resolver) const
+inline void GreaterEqualOptions::UnPackTo(GreaterEqualOptionsT *_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)
+inline flatbuffers::Offset<GreaterEqualOptions>
+GreaterEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterEqualOptionsT *_o,
+                          const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSqueezeOptions(_fbb, _o, _rehasher);
+  return CreateGreaterEqualOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SqueezeOptions>
-CreateSqueezeOptions(flatbuffers::FlatBufferBuilder &_fbb, const SqueezeOptionsT *_o,
-                     const flatbuffers::rehasher_function_t *_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 SqueezeOptionsT *__o;
+    const GreaterEqualOptionsT *__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);
+  return circle::CreateGreaterEqualOptions(_fbb);
 }
 
-inline SplitOptionsT *SplitOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline LessOptionsT *LessOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SplitOptionsT>(new SplitOptionsT());
+  auto _o = std::unique_ptr<LessOptionsT>(new LessOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SplitOptions::UnPackTo(SplitOptionsT *_o,
-                                   const flatbuffers::resolver_function_t *_resolver) const
+inline void LessOptions::UnPackTo(LessOptionsT *_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)
+inline flatbuffers::Offset<LessOptions>
+LessOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSplitOptions(_fbb, _o, _rehasher);
+  return CreateLessOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SplitOptions>
-CreateSplitOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT *_o,
-                   const flatbuffers::rehasher_function_t *_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 SplitOptionsT *__o;
+    const LessOptionsT *__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);
+  return circle::CreateLessOptions(_fbb);
 }
 
-inline SplitVOptionsT *
-SplitVOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline LessEqualOptionsT *
+LessEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SplitVOptionsT>(new SplitVOptionsT());
+  auto _o = std::unique_ptr<LessEqualOptionsT>(new LessEqualOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SplitVOptions::UnPackTo(SplitVOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void LessEqualOptions::UnPackTo(LessEqualOptionsT *_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)
+inline flatbuffers::Offset<LessEqualOptions>
+LessEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSplitVOptions(_fbb, _o, _rehasher);
+  return CreateLessEqualOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SplitVOptions>
-CreateSplitVOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 SplitVOptionsT *__o;
+    const LessEqualOptionsT *__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);
+  return circle::CreateLessEqualOptions(_fbb);
 }
 
-inline StridedSliceOptionsT *
-StridedSliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline NegOptionsT *NegOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<StridedSliceOptionsT>(new StridedSliceOptionsT());
+  auto _o = std::unique_ptr<NegOptionsT>(new NegOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void StridedSliceOptions::UnPackTo(StridedSliceOptionsT *_o,
-                                          const flatbuffers::resolver_function_t *_resolver) const
+inline void NegOptions::UnPackTo(NegOptionsT *_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)
+inline flatbuffers::Offset<NegOptions>
+NegOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateStridedSliceOptions(_fbb, _o, _rehasher);
+  return CreateNegOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<StridedSliceOptions>
-CreateStridedSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const StridedSliceOptionsT *_o,
-                          const flatbuffers::rehasher_function_t *_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 StridedSliceOptionsT *__o;
+    const NegOptionsT *__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);
+  return circle::CreateNegOptions(_fbb);
 }
 
-inline LogSoftmaxOptionsT *
-LogSoftmaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SelectOptionsT *
+SelectOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<LogSoftmaxOptionsT>(new LogSoftmaxOptionsT());
+  auto _o = std::unique_ptr<SelectOptionsT>(new SelectOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void LogSoftmaxOptions::UnPackTo(LogSoftmaxOptionsT *_o,
-                                        const flatbuffers::resolver_function_t *_resolver) const
+inline void SelectOptions::UnPackTo(SelectOptionsT *_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)
+inline flatbuffers::Offset<SelectOptions>
+SelectOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SelectOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateLogSoftmaxOptions(_fbb, _o, _rehasher);
+  return CreateSelectOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<LogSoftmaxOptions>
-CreateLogSoftmaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogSoftmaxOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_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 LogSoftmaxOptionsT *__o;
+    const SelectOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateLogSoftmaxOptions(_fbb);
+  return circle::CreateSelectOptions(_fbb);
 }
 
-inline CastOptionsT *CastOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SliceOptionsT *SliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<CastOptionsT>(new CastOptionsT());
+  auto _o = std::unique_ptr<SliceOptionsT>(new SliceOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void CastOptions::UnPackTo(CastOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+inline void SliceOptions::UnPackTo(SliceOptionsT *_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)
+}
+
+inline flatbuffers::Offset<SliceOptions>
+SliceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateCastOptions(_fbb, _o, _rehasher);
+  return CreateSliceOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<CastOptions>
-CreateCastOptions(flatbuffers::FlatBufferBuilder &_fbb, const CastOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_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 CastOptionsT *__o;
+    const SliceOptionsT *__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);
+  return circle::CreateSliceOptions(_fbb);
 }
 
-inline DequantizeOptionsT *
-DequantizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline TransposeConvOptionsT *
+TransposeConvOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<DequantizeOptionsT>(new DequantizeOptionsT());
+  auto _o = std::unique_ptr<TransposeConvOptionsT>(new TransposeConvOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void DequantizeOptions::UnPackTo(DequantizeOptionsT *_o,
-                                        const flatbuffers::resolver_function_t *_resolver) const
+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;
+  }
+  {
+    auto _e = fused_activation_function();
+    _o->fused_activation_function = _e;
+  }
 }
 
-inline flatbuffers::Offset<DequantizeOptions>
-DequantizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<TransposeConvOptions>
+TransposeConvOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TransposeConvOptionsT *_o,
+                           const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateDequantizeOptions(_fbb, _o, _rehasher);
+  return CreateTransposeConvOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<DequantizeOptions>
-CreateDequantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const DequantizeOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_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 DequantizeOptionsT *__o;
+    const TransposeConvOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateDequantizeOptions(_fbb);
+  auto _padding = _o->padding;
+  auto _stride_w = _o->stride_w;
+  auto _stride_h = _o->stride_h;
+  auto _fused_activation_function = _o->fused_activation_function;
+  return circle::CreateTransposeConvOptions(_fbb, _padding, _stride_w, _stride_h,
+                                            _fused_activation_function);
 }
 
-inline MaximumMinimumOptionsT *
-MaximumMinimumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ExpandDimsOptionsT *
+ExpandDimsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<MaximumMinimumOptionsT>(new MaximumMinimumOptionsT());
+  auto _o = std::unique_ptr<ExpandDimsOptionsT>(new ExpandDimsOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void MaximumMinimumOptions::UnPackTo(MaximumMinimumOptionsT *_o,
-                                            const flatbuffers::resolver_function_t *_resolver) const
+inline void ExpandDimsOptions::UnPackTo(ExpandDimsOptionsT *_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)
+inline flatbuffers::Offset<ExpandDimsOptions>
+ExpandDimsOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ExpandDimsOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateMaximumMinimumOptions(_fbb, _o, _rehasher);
+  return CreateExpandDimsOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<MaximumMinimumOptions>
-CreateMaximumMinimumOptions(flatbuffers::FlatBufferBuilder &_fbb, const MaximumMinimumOptionsT *_o,
-                            const flatbuffers::rehasher_function_t *_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 MaximumMinimumOptionsT *__o;
+    const ExpandDimsOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateMaximumMinimumOptions(_fbb);
+  return circle::CreateExpandDimsOptions(_fbb);
 }
 
-inline TileOptionsT *TileOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SparseToDenseOptionsT *
+SparseToDenseOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<TileOptionsT>(new TileOptionsT());
+  auto _o = std::unique_ptr<SparseToDenseOptionsT>(new SparseToDenseOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void TileOptions::UnPackTo(TileOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+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<TileOptions>
-TileOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<SparseToDenseOptions>
+SparseToDenseOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparseToDenseOptionsT *_o,
+                           const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateTileOptions(_fbb, _o, _rehasher);
+  return CreateSparseToDenseOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<TileOptions>
-CreateTileOptions(flatbuffers::FlatBufferBuilder &_fbb, const TileOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_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 TileOptionsT *__o;
+    const SparseToDenseOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateTileOptions(_fbb);
+  auto _validate_indices = _o->validate_indices;
+  return circle::CreateSparseToDenseOptions(_fbb, _validate_indices);
 }
 
-inline ArgMaxOptionsT *
-ArgMaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline EqualOptionsT *EqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ArgMaxOptionsT>(new ArgMaxOptionsT());
+  auto _o = std::unique_ptr<EqualOptionsT>(new EqualOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ArgMaxOptions::UnPackTo(ArgMaxOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void EqualOptions::UnPackTo(EqualOptionsT *_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)
+inline flatbuffers::Offset<EqualOptions>
+EqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const EqualOptionsT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateArgMaxOptions(_fbb, _o, _rehasher);
+  return CreateEqualOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ArgMaxOptions>
-CreateArgMaxOptions(flatbuffers::FlatBufferBuilder &_fbb, const ArgMaxOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 ArgMaxOptionsT *__o;
+    const EqualOptionsT *__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);
+  return circle::CreateEqualOptions(_fbb);
 }
 
-inline ArgMinOptionsT *
-ArgMinOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline NotEqualOptionsT *
+NotEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ArgMinOptionsT>(new ArgMinOptionsT());
+  auto _o = std::unique_ptr<NotEqualOptionsT>(new NotEqualOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ArgMinOptions::UnPackTo(ArgMinOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void NotEqualOptions::UnPackTo(NotEqualOptionsT *_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)
+inline flatbuffers::Offset<NotEqualOptions>
+NotEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT *_o,
+                      const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateArgMinOptions(_fbb, _o, _rehasher);
+  return CreateNotEqualOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ArgMinOptions>
-CreateArgMinOptions(flatbuffers::FlatBufferBuilder &_fbb, const ArgMinOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 ArgMinOptionsT *__o;
+    const NotEqualOptionsT *__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);
+  return circle::CreateNotEqualOptions(_fbb);
 }
 
-inline GreaterOptionsT *
-GreaterOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ShapeOptionsT *ShapeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<GreaterOptionsT>(new GreaterOptionsT());
+  auto _o = std::unique_ptr<ShapeOptionsT>(new ShapeOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void GreaterOptions::UnPackTo(GreaterOptionsT *_o,
-                                     const flatbuffers::resolver_function_t *_resolver) const
+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<GreaterOptions>
-GreaterOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT *_o,
-                     const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<ShapeOptions>
+ShapeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ShapeOptionsT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateGreaterOptions(_fbb, _o, _rehasher);
+  return CreateShapeOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<GreaterOptions>
-CreateGreaterOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterOptionsT *_o,
-                     const flatbuffers::rehasher_function_t *_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 GreaterOptionsT *__o;
+    const ShapeOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateGreaterOptions(_fbb);
+  auto _out_type = _o->out_type;
+  return circle::CreateShapeOptions(_fbb, _out_type);
 }
 
-inline GreaterEqualOptionsT *
-GreaterEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline RankOptionsT *RankOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<GreaterEqualOptionsT>(new GreaterEqualOptionsT());
+  auto _o = std::unique_ptr<RankOptionsT>(new RankOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void GreaterEqualOptions::UnPackTo(GreaterEqualOptionsT *_o,
-                                          const flatbuffers::resolver_function_t *_resolver) const
+inline void RankOptions::UnPackTo(RankOptionsT *_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)
+inline flatbuffers::Offset<RankOptions>
+RankOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RankOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateGreaterEqualOptions(_fbb, _o, _rehasher);
+  return CreateRankOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<GreaterEqualOptions>
-CreateGreaterEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const GreaterEqualOptionsT *_o,
-                          const flatbuffers::rehasher_function_t *_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 GreaterEqualOptionsT *__o;
+    const RankOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateGreaterEqualOptions(_fbb);
+  return circle::CreateRankOptions(_fbb);
 }
 
-inline LessOptionsT *LessOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline PowOptionsT *PowOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<LessOptionsT>(new LessOptionsT());
+  auto _o = std::unique_ptr<PowOptionsT>(new PowOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void LessOptions::UnPackTo(LessOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+inline void PowOptions::UnPackTo(PowOptionsT *_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)
+inline flatbuffers::Offset<PowOptions>
+PowOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PowOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateLessOptions(_fbb, _o, _rehasher);
+  return CreatePowOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<LessOptions>
-CreateLessOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_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 LessOptionsT *__o;
+    const PowOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateLessOptions(_fbb);
+  return circle::CreatePowOptions(_fbb);
 }
 
-inline LessEqualOptionsT *
-LessEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline FakeQuantOptionsT *
+FakeQuantOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<LessEqualOptionsT>(new LessEqualOptionsT());
+  auto _o = std::unique_ptr<FakeQuantOptionsT>(new FakeQuantOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void LessEqualOptions::UnPackTo(LessEqualOptionsT *_o,
+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<LessEqualOptions>
-LessEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT *_o,
+inline flatbuffers::Offset<FakeQuantOptions>
+FakeQuantOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT *_o,
                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateLessEqualOptions(_fbb, _o, _rehasher);
+  return CreateFakeQuantOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<LessEqualOptions>
-CreateLessEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOptionsT *_o,
+inline flatbuffers::Offset<FakeQuantOptions>
+CreateFakeQuantOptions(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT *_o,
                        const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
@@ -18233,697 +20065,682 @@ CreateLessEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const LessEqualOpti
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const LessEqualOptionsT *__o;
+    const FakeQuantOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateLessEqualOptions(_fbb);
+  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 NegOptionsT *NegOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline PackOptionsT *PackOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<NegOptionsT>(new NegOptionsT());
+  auto _o = std::unique_ptr<PackOptionsT>(new PackOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void NegOptions::UnPackTo(NegOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+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<NegOptions>
-NegOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<PackOptions>
+PackOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const PackOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateNegOptions(_fbb, _o, _rehasher);
+  return CreatePackOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<NegOptions>
-CreateNegOptions(flatbuffers::FlatBufferBuilder &_fbb, const NegOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 NegOptionsT *__o;
+    const PackOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateNegOptions(_fbb);
+  auto _values_count = _o->values_count;
+  auto _axis = _o->axis;
+  return circle::CreatePackOptions(_fbb, _values_count, _axis);
 }
 
-inline SelectOptionsT *
-SelectOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline LogicalOrOptionsT *
+LogicalOrOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SelectOptionsT>(new SelectOptionsT());
+  auto _o = std::unique_ptr<LogicalOrOptionsT>(new LogicalOrOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SelectOptions::UnPackTo(SelectOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void LogicalOrOptions::UnPackTo(LogicalOrOptionsT *_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)
+inline flatbuffers::Offset<LogicalOrOptions>
+LogicalOrOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalOrOptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSelectOptions(_fbb, _o, _rehasher);
+  return CreateLogicalOrOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SelectOptions>
-CreateSelectOptions(flatbuffers::FlatBufferBuilder &_fbb, const SelectOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 SelectOptionsT *__o;
+    const LogicalOrOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateSelectOptions(_fbb);
+  return circle::CreateLogicalOrOptions(_fbb);
 }
 
-inline SliceOptionsT *SliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline OneHotOptionsT *
+OneHotOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SliceOptionsT>(new SliceOptionsT());
+  auto _o = std::unique_ptr<OneHotOptionsT>(new OneHotOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SliceOptions::UnPackTo(SliceOptionsT *_o,
-                                   const flatbuffers::resolver_function_t *_resolver) const
+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<SliceOptions>
-SliceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT *_o,
-                   const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<OneHotOptions>
+OneHotOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSliceOptions(_fbb, _o, _rehasher);
+  return CreateOneHotOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SliceOptions>
-CreateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb, const SliceOptionsT *_o,
-                   const flatbuffers::rehasher_function_t *_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 SliceOptionsT *__o;
+    const OneHotOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateSliceOptions(_fbb);
+  auto _axis = _o->axis;
+  return circle::CreateOneHotOptions(_fbb, _axis);
 }
 
-inline TransposeConvOptionsT *
-TransposeConvOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline AbsOptionsT *AbsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<TransposeConvOptionsT>(new TransposeConvOptionsT());
+  auto _o = std::unique_ptr<AbsOptionsT>(new AbsOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void TransposeConvOptions::UnPackTo(TransposeConvOptionsT *_o,
-                                           const flatbuffers::resolver_function_t *_resolver) const
+inline void AbsOptions::UnPackTo(AbsOptionsT *_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)
+inline flatbuffers::Offset<AbsOptions>
+AbsOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT *_o,
+                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateTransposeConvOptions(_fbb, _o, _rehasher);
+  return CreateAbsOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<TransposeConvOptions>
-CreateTransposeConvOptions(flatbuffers::FlatBufferBuilder &_fbb, const TransposeConvOptionsT *_o,
-                           const flatbuffers::rehasher_function_t *_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 TransposeConvOptionsT *__o;
+    const AbsOptionsT *__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);
+  return circle::CreateAbsOptions(_fbb);
 }
 
-inline ExpandDimsOptionsT *
-ExpandDimsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline HardSwishOptionsT *
+HardSwishOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ExpandDimsOptionsT>(new ExpandDimsOptionsT());
+  auto _o = std::unique_ptr<HardSwishOptionsT>(new HardSwishOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ExpandDimsOptions::UnPackTo(ExpandDimsOptionsT *_o,
-                                        const flatbuffers::resolver_function_t *_resolver) const
+inline void HardSwishOptions::UnPackTo(HardSwishOptionsT *_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)
+inline flatbuffers::Offset<HardSwishOptions>
+HardSwishOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateExpandDimsOptions(_fbb, _o, _rehasher);
+  return CreateHardSwishOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ExpandDimsOptions>
-CreateExpandDimsOptions(flatbuffers::FlatBufferBuilder &_fbb, const ExpandDimsOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_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 ExpandDimsOptionsT *__o;
+    const HardSwishOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateExpandDimsOptions(_fbb);
+  return circle::CreateHardSwishOptions(_fbb);
 }
 
-inline SparseToDenseOptionsT *
-SparseToDenseOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline LogicalAndOptionsT *
+LogicalAndOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SparseToDenseOptionsT>(new SparseToDenseOptionsT());
+  auto _o = std::unique_ptr<LogicalAndOptionsT>(new LogicalAndOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SparseToDenseOptions::UnPackTo(SparseToDenseOptionsT *_o,
-                                           const flatbuffers::resolver_function_t *_resolver) const
+inline void LogicalAndOptions::UnPackTo(LogicalAndOptionsT *_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)
+inline flatbuffers::Offset<LogicalAndOptions>
+LogicalAndOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSparseToDenseOptions(_fbb, _o, _rehasher);
+  return CreateLogicalAndOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SparseToDenseOptions>
-CreateSparseToDenseOptions(flatbuffers::FlatBufferBuilder &_fbb, const SparseToDenseOptionsT *_o,
-                           const flatbuffers::rehasher_function_t *_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 SparseToDenseOptionsT *__o;
+    const LogicalAndOptionsT *__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);
+  return circle::CreateLogicalAndOptions(_fbb);
 }
 
-inline EqualOptionsT *EqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline LogicalNotOptionsT *
+LogicalNotOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<EqualOptionsT>(new EqualOptionsT());
+  auto _o = std::unique_ptr<LogicalNotOptionsT>(new LogicalNotOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void EqualOptions::UnPackTo(EqualOptionsT *_o,
-                                   const flatbuffers::resolver_function_t *_resolver) const
+inline void LogicalNotOptions::UnPackTo(LogicalNotOptionsT *_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)
+inline flatbuffers::Offset<LogicalNotOptions>
+LogicalNotOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalNotOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateEqualOptions(_fbb, _o, _rehasher);
+  return CreateLogicalNotOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<EqualOptions>
-CreateEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const EqualOptionsT *_o,
-                   const flatbuffers::rehasher_function_t *_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 EqualOptionsT *__o;
+    const LogicalNotOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateEqualOptions(_fbb);
+  return circle::CreateLogicalNotOptions(_fbb);
 }
 
-inline NotEqualOptionsT *
-NotEqualOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline UnpackOptionsT *
+UnpackOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<NotEqualOptionsT>(new NotEqualOptionsT());
+  auto _o = std::unique_ptr<UnpackOptionsT>(new UnpackOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void NotEqualOptions::UnPackTo(NotEqualOptionsT *_o,
-                                      const flatbuffers::resolver_function_t *_resolver) const
+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<NotEqualOptions>
-NotEqualOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT *_o,
-                      const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<UnpackOptions>
+UnpackOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UnpackOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateNotEqualOptions(_fbb, _o, _rehasher);
+  return CreateUnpackOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<NotEqualOptions>
-CreateNotEqualOptions(flatbuffers::FlatBufferBuilder &_fbb, const NotEqualOptionsT *_o,
-                      const flatbuffers::rehasher_function_t *_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 NotEqualOptionsT *__o;
+    const UnpackOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateNotEqualOptions(_fbb);
+  auto _num = _o->num;
+  auto _axis = _o->axis;
+  return circle::CreateUnpackOptions(_fbb, _num, _axis);
 }
 
-inline ShapeOptionsT *ShapeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline FloorDivOptionsT *
+FloorDivOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ShapeOptionsT>(new ShapeOptionsT());
+  auto _o = std::unique_ptr<FloorDivOptionsT>(new FloorDivOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ShapeOptions::UnPackTo(ShapeOptionsT *_o,
-                                   const flatbuffers::resolver_function_t *_resolver) const
+inline void FloorDivOptions::UnPackTo(FloorDivOptionsT *_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)
+inline flatbuffers::Offset<FloorDivOptions>
+FloorDivOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT *_o,
+                      const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateShapeOptions(_fbb, _o, _rehasher);
+  return CreateFloorDivOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ShapeOptions>
-CreateShapeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ShapeOptionsT *_o,
-                   const flatbuffers::rehasher_function_t *_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 ShapeOptionsT *__o;
+    const FloorDivOptionsT *__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);
+  return circle::CreateFloorDivOptions(_fbb);
 }
 
-inline RankOptionsT *RankOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SquareOptionsT *
+SquareOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<RankOptionsT>(new RankOptionsT());
+  auto _o = std::unique_ptr<SquareOptionsT>(new SquareOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void RankOptions::UnPackTo(RankOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+inline void SquareOptions::UnPackTo(SquareOptionsT *_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)
+inline flatbuffers::Offset<SquareOptions>
+SquareOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SquareOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateRankOptions(_fbb, _o, _rehasher);
+  return CreateSquareOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<RankOptions>
-CreateRankOptions(flatbuffers::FlatBufferBuilder &_fbb, const RankOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_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 RankOptionsT *__o;
+    const SquareOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateRankOptions(_fbb);
+  return circle::CreateSquareOptions(_fbb);
 }
 
-inline PowOptionsT *PowOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ZerosLikeOptionsT *
+ZerosLikeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<PowOptionsT>(new PowOptionsT());
+  auto _o = std::unique_ptr<ZerosLikeOptionsT>(new ZerosLikeOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void PowOptions::UnPackTo(PowOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+inline void ZerosLikeOptions::UnPackTo(ZerosLikeOptionsT *_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)
+inline flatbuffers::Offset<ZerosLikeOptions>
+ZerosLikeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreatePowOptions(_fbb, _o, _rehasher);
+  return CreateZerosLikeOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<PowOptions>
-CreatePowOptions(flatbuffers::FlatBufferBuilder &_fbb, const PowOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 PowOptionsT *__o;
+    const ZerosLikeOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreatePowOptions(_fbb);
+  return circle::CreateZerosLikeOptions(_fbb);
 }
 
-inline FakeQuantOptionsT *
-FakeQuantOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline FillOptionsT *FillOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<FakeQuantOptionsT>(new FakeQuantOptionsT());
+  auto _o = std::unique_ptr<FillOptionsT>(new FillOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void FakeQuantOptions::UnPackTo(FakeQuantOptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+inline void FillOptions::UnPackTo(FillOptionsT *_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)
+inline flatbuffers::Offset<FillOptions>
+FillOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FillOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateFakeQuantOptions(_fbb, _o, _rehasher);
+  return CreateFillOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<FakeQuantOptions>
-CreateFakeQuantOptions(flatbuffers::FlatBufferBuilder &_fbb, const FakeQuantOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_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 FakeQuantOptionsT *__o;
+    const FillOptionsT *__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);
+  return circle::CreateFillOptions(_fbb);
 }
 
-inline PackOptionsT *PackOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline FloorModOptionsT *
+FloorModOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<PackOptionsT>(new PackOptionsT());
+  auto _o = std::unique_ptr<FloorModOptionsT>(new FloorModOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void PackOptions::UnPackTo(PackOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+inline void FloorModOptions::UnPackTo(FloorModOptionsT *_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)
+inline flatbuffers::Offset<FloorModOptions>
+FloorModOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT *_o,
+                      const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreatePackOptions(_fbb, _o, _rehasher);
+  return CreateFloorModOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<PackOptions>
-CreatePackOptions(flatbuffers::FlatBufferBuilder &_fbb, const PackOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_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 PackOptionsT *__o;
+    const FloorModOptionsT *__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);
+  return circle::CreateFloorModOptions(_fbb);
 }
 
-inline LogicalOrOptionsT *
-LogicalOrOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline RangeOptionsT *RangeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<LogicalOrOptionsT>(new LogicalOrOptionsT());
+  auto _o = std::unique_ptr<RangeOptionsT>(new RangeOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void LogicalOrOptions::UnPackTo(LogicalOrOptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+inline void RangeOptions::UnPackTo(RangeOptionsT *_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)
+inline flatbuffers::Offset<RangeOptions>
+RangeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateLogicalOrOptions(_fbb, _o, _rehasher);
+  return CreateRangeOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<LogicalOrOptions>
-CreateLogicalOrOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalOrOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_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 LogicalOrOptionsT *__o;
+    const RangeOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateLogicalOrOptions(_fbb);
+  return circle::CreateRangeOptions(_fbb);
 }
 
-inline OneHotOptionsT *
-OneHotOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline LeakyReluOptionsT *
+LeakyReluOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<OneHotOptionsT>(new OneHotOptionsT());
+  auto _o = std::unique_ptr<LeakyReluOptionsT>(new LeakyReluOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void OneHotOptions::UnPackTo(OneHotOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void LeakyReluOptions::UnPackTo(LeakyReluOptionsT *_o,
+                                       const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = axis();
-    _o->axis = _e;
+    auto _e = alpha();
+    _o->alpha = _e;
   }
 }
 
-inline flatbuffers::Offset<OneHotOptions>
-OneHotOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<LeakyReluOptions>
+LeakyReluOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateOneHotOptions(_fbb, _o, _rehasher);
+  return CreateLeakyReluOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<OneHotOptions>
-CreateOneHotOptions(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 OneHotOptionsT *__o;
+    const LeakyReluOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  auto _axis = _o->axis;
-  return circle::CreateOneHotOptions(_fbb, _axis);
+  auto _alpha = _o->alpha;
+  return circle::CreateLeakyReluOptions(_fbb, _alpha);
 }
 
-inline AbsOptionsT *AbsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SquaredDifferenceOptionsT *
+SquaredDifferenceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<AbsOptionsT>(new AbsOptionsT());
+  auto _o = std::unique_ptr<SquaredDifferenceOptionsT>(new SquaredDifferenceOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void AbsOptions::UnPackTo(AbsOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+inline void
+SquaredDifferenceOptions::UnPackTo(SquaredDifferenceOptionsT *_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)
+inline flatbuffers::Offset<SquaredDifferenceOptions>
+SquaredDifferenceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                               const SquaredDifferenceOptionsT *_o,
+                               const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateAbsOptions(_fbb, _o, _rehasher);
+  return CreateSquaredDifferenceOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<AbsOptions>
-CreateAbsOptions(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT *_o,
-                 const flatbuffers::rehasher_function_t *_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 AbsOptionsT *__o;
+    const SquaredDifferenceOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateAbsOptions(_fbb);
+  return circle::CreateSquaredDifferenceOptions(_fbb);
 }
 
-inline HardSwishOptionsT *
-HardSwishOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline MirrorPadOptionsT *
+MirrorPadOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<HardSwishOptionsT>(new HardSwishOptionsT());
+  auto _o = std::unique_ptr<MirrorPadOptionsT>(new MirrorPadOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void HardSwishOptions::UnPackTo(HardSwishOptionsT *_o,
+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<HardSwishOptions>
-HardSwishOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT *_o,
+inline flatbuffers::Offset<MirrorPadOptions>
+MirrorPadOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o,
                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateHardSwishOptions(_fbb, _o, _rehasher);
+  return CreateMirrorPadOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<HardSwishOptions>
-CreateHardSwishOptions(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOptionsT *_o,
+inline flatbuffers::Offset<MirrorPadOptions>
+CreateMirrorPadOptions(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o,
                        const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
@@ -18931,161 +20748,156 @@ CreateHardSwishOptions(flatbuffers::FlatBufferBuilder &_fbb, const HardSwishOpti
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const HardSwishOptionsT *__o;
+    const MirrorPadOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateHardSwishOptions(_fbb);
+  auto _mode = _o->mode;
+  return circle::CreateMirrorPadOptions(_fbb, _mode);
 }
 
-inline LogicalAndOptionsT *
-LogicalAndOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline UniqueOptionsT *
+UniqueOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<LogicalAndOptionsT>(new LogicalAndOptionsT());
+  auto _o = std::unique_ptr<UniqueOptionsT>(new UniqueOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void LogicalAndOptions::UnPackTo(LogicalAndOptionsT *_o,
-                                        const flatbuffers::resolver_function_t *_resolver) const
+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<LogicalAndOptions>
-LogicalAndOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<UniqueOptions>
+UniqueOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const UniqueOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateLogicalAndOptions(_fbb, _o, _rehasher);
+  return CreateUniqueOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<LogicalAndOptions>
-CreateLogicalAndOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalAndOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_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 LogicalAndOptionsT *__o;
+    const UniqueOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateLogicalAndOptions(_fbb);
+  auto _idx_out_type = _o->idx_out_type;
+  return circle::CreateUniqueOptions(_fbb, _idx_out_type);
 }
 
-inline LogicalNotOptionsT *
-LogicalNotOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ReverseV2OptionsT *
+ReverseV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<LogicalNotOptionsT>(new LogicalNotOptionsT());
+  auto _o = std::unique_ptr<ReverseV2OptionsT>(new ReverseV2OptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void LogicalNotOptions::UnPackTo(LogicalNotOptionsT *_o,
-                                        const flatbuffers::resolver_function_t *_resolver) const
+inline void ReverseV2Options::UnPackTo(ReverseV2OptionsT *_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)
+inline flatbuffers::Offset<ReverseV2Options>
+ReverseV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReverseV2OptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateLogicalNotOptions(_fbb, _o, _rehasher);
+  return CreateReverseV2Options(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<LogicalNotOptions>
-CreateLogicalNotOptions(flatbuffers::FlatBufferBuilder &_fbb, const LogicalNotOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_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 LogicalNotOptionsT *__o;
+    const ReverseV2OptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateLogicalNotOptions(_fbb);
+  return circle::CreateReverseV2Options(_fbb);
 }
 
-inline UnpackOptionsT *
-UnpackOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline AddNOptionsT *AddNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<UnpackOptionsT>(new UnpackOptionsT());
+  auto _o = std::unique_ptr<AddNOptionsT>(new AddNOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void UnpackOptions::UnPackTo(UnpackOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void AddNOptions::UnPackTo(AddNOptionsT *_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)
+inline flatbuffers::Offset<AddNOptions>
+AddNOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AddNOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateUnpackOptions(_fbb, _o, _rehasher);
+  return CreateAddNOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<UnpackOptions>
-CreateUnpackOptions(flatbuffers::FlatBufferBuilder &_fbb, const UnpackOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 UnpackOptionsT *__o;
+    const AddNOptionsT *__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);
+  return circle::CreateAddNOptions(_fbb);
 }
 
-inline FloorDivOptionsT *
-FloorDivOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline GatherNdOptionsT *
+GatherNdOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<FloorDivOptionsT>(new FloorDivOptionsT());
+  auto _o = std::unique_ptr<GatherNdOptionsT>(new GatherNdOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void FloorDivOptions::UnPackTo(FloorDivOptionsT *_o,
+inline void GatherNdOptions::UnPackTo(GatherNdOptionsT *_o,
                                       const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
 }
 
-inline flatbuffers::Offset<FloorDivOptions>
-FloorDivOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT *_o,
+inline flatbuffers::Offset<GatherNdOptions>
+GatherNdOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT *_o,
                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateFloorDivOptions(_fbb, _o, _rehasher);
+  return CreateGatherNdOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<FloorDivOptions>
-CreateFloorDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOptionsT *_o,
+inline flatbuffers::Offset<GatherNdOptions>
+CreateGatherNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT *_o,
                       const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
@@ -19093,150 +20905,163 @@ CreateFloorDivOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorDivOption
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const FloorDivOptionsT *__o;
+    const GatherNdOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateFloorDivOptions(_fbb);
+  return circle::CreateGatherNdOptions(_fbb);
 }
 
-inline SquareOptionsT *
-SquareOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline WhereOptionsT *WhereOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SquareOptionsT>(new SquareOptionsT());
+  auto _o = std::unique_ptr<WhereOptionsT>(new WhereOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SquareOptions::UnPackTo(SquareOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void WhereOptions::UnPackTo(WhereOptionsT *_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)
+inline flatbuffers::Offset<WhereOptions>
+WhereOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const WhereOptionsT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSquareOptions(_fbb, _o, _rehasher);
+  return CreateWhereOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SquareOptions>
-CreateSquareOptions(flatbuffers::FlatBufferBuilder &_fbb, const SquareOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 SquareOptionsT *__o;
+    const WhereOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateSquareOptions(_fbb);
+  return circle::CreateWhereOptions(_fbb);
 }
 
-inline ZerosLikeOptionsT *
-ZerosLikeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ReverseSequenceOptionsT *
+ReverseSequenceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ZerosLikeOptionsT>(new ZerosLikeOptionsT());
+  auto _o = std::unique_ptr<ReverseSequenceOptionsT>(new ReverseSequenceOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ZerosLikeOptions::UnPackTo(ZerosLikeOptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+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<ZerosLikeOptions>
-ZerosLikeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<ReverseSequenceOptions>
+ReverseSequenceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                             const ReverseSequenceOptionsT *_o,
+                             const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateZerosLikeOptions(_fbb, _o, _rehasher);
+  return CreateReverseSequenceOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ZerosLikeOptions>
-CreateZerosLikeOptions(flatbuffers::FlatBufferBuilder &_fbb, const ZerosLikeOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_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 ZerosLikeOptionsT *__o;
+    const ReverseSequenceOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateZerosLikeOptions(_fbb);
+  auto _seq_dim = _o->seq_dim;
+  auto _batch_dim = _o->batch_dim;
+  return circle::CreateReverseSequenceOptions(_fbb, _seq_dim, _batch_dim);
 }
 
-inline FillOptionsT *FillOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline MatrixDiagOptionsT *
+MatrixDiagOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<FillOptionsT>(new FillOptionsT());
+  auto _o = std::unique_ptr<MatrixDiagOptionsT>(new MatrixDiagOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void FillOptions::UnPackTo(FillOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+inline void MatrixDiagOptions::UnPackTo(MatrixDiagOptionsT *_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)
+inline flatbuffers::Offset<MatrixDiagOptions>
+MatrixDiagOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateFillOptions(_fbb, _o, _rehasher);
+  return CreateMatrixDiagOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<FillOptions>
-CreateFillOptions(flatbuffers::FlatBufferBuilder &_fbb, const FillOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_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 FillOptionsT *__o;
+    const MatrixDiagOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateFillOptions(_fbb);
+  return circle::CreateMatrixDiagOptions(_fbb);
 }
 
-inline FloorModOptionsT *
-FloorModOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline QuantizeOptionsT *
+QuantizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<FloorModOptionsT>(new FloorModOptionsT());
+  auto _o = std::unique_ptr<QuantizeOptionsT>(new QuantizeOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void FloorModOptions::UnPackTo(FloorModOptionsT *_o,
+inline void QuantizeOptions::UnPackTo(QuantizeOptionsT *_o,
                                       const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
 }
 
-inline flatbuffers::Offset<FloorModOptions>
-FloorModOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT *_o,
+inline flatbuffers::Offset<QuantizeOptions>
+QuantizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT *_o,
                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateFloorModOptions(_fbb, _o, _rehasher);
+  return CreateQuantizeOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<FloorModOptions>
-CreateFloorModOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOptionsT *_o,
+inline flatbuffers::Offset<QuantizeOptions>
+CreateQuantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT *_o,
                       const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
@@ -19244,319 +21069,332 @@ CreateFloorModOptions(flatbuffers::FlatBufferBuilder &_fbb, const FloorModOption
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const FloorModOptionsT *__o;
+    const QuantizeOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateFloorModOptions(_fbb);
+  return circle::CreateQuantizeOptions(_fbb);
 }
 
-inline RangeOptionsT *RangeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline MatrixSetDiagOptionsT *
+MatrixSetDiagOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<RangeOptionsT>(new RangeOptionsT());
+  auto _o = std::unique_ptr<MatrixSetDiagOptionsT>(new MatrixSetDiagOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void RangeOptions::UnPackTo(RangeOptionsT *_o,
-                                   const flatbuffers::resolver_function_t *_resolver) const
+inline void MatrixSetDiagOptions::UnPackTo(MatrixSetDiagOptionsT *_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)
+inline flatbuffers::Offset<MatrixSetDiagOptions>
+MatrixSetDiagOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixSetDiagOptionsT *_o,
+                           const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateRangeOptions(_fbb, _o, _rehasher);
+  return CreateMatrixSetDiagOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<RangeOptions>
-CreateRangeOptions(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT *_o,
-                   const flatbuffers::rehasher_function_t *_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 RangeOptionsT *__o;
+    const MatrixSetDiagOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateRangeOptions(_fbb);
+  return circle::CreateMatrixSetDiagOptions(_fbb);
 }
 
-inline LeakyReluOptionsT *
-LeakyReluOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline IfOptionsT *IfOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<LeakyReluOptionsT>(new LeakyReluOptionsT());
+  auto _o = std::unique_ptr<IfOptionsT>(new IfOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void LeakyReluOptions::UnPackTo(LeakyReluOptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+inline void IfOptions::UnPackTo(IfOptionsT *_o,
+                                const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = alpha();
-    _o->alpha = _e;
+    auto _e = then_subgraph_index();
+    _o->then_subgraph_index = _e;
+  }
+  {
+    auto _e = else_subgraph_index();
+    _o->else_subgraph_index = _e;
   }
 }
 
-inline flatbuffers::Offset<LeakyReluOptions>
-LeakyReluOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<IfOptions>
+IfOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const IfOptionsT *_o,
+                const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateLeakyReluOptions(_fbb, _o, _rehasher);
+  return CreateIfOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<LeakyReluOptions>
-CreateLeakyReluOptions(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_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 LeakyReluOptionsT *__o;
+    const IfOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  auto _alpha = _o->alpha;
-  return circle::CreateLeakyReluOptions(_fbb, _alpha);
+  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 SquaredDifferenceOptionsT *
-SquaredDifferenceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline CallOnceOptionsT *
+CallOnceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SquaredDifferenceOptionsT>(new SquaredDifferenceOptionsT());
+  auto _o = std::unique_ptr<CallOnceOptionsT>(new CallOnceOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void
-SquaredDifferenceOptions::UnPackTo(SquaredDifferenceOptionsT *_o,
-                                   const flatbuffers::resolver_function_t *_resolver) const
+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<SquaredDifferenceOptions>
-SquaredDifferenceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
-                               const SquaredDifferenceOptionsT *_o,
-                               const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<CallOnceOptions>
+CallOnceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT *_o,
+                      const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSquaredDifferenceOptions(_fbb, _o, _rehasher);
+  return CreateCallOnceOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SquaredDifferenceOptions>
-CreateSquaredDifferenceOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                               const SquaredDifferenceOptionsT *_o,
-                               const flatbuffers::rehasher_function_t *_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 SquaredDifferenceOptionsT *__o;
+    const CallOnceOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateSquaredDifferenceOptions(_fbb);
+  auto _init_subgraph_index = _o->init_subgraph_index;
+  return circle::CreateCallOnceOptions(_fbb, _init_subgraph_index);
 }
 
-inline MirrorPadOptionsT *
-MirrorPadOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline WhileOptionsT *WhileOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<MirrorPadOptionsT>(new MirrorPadOptionsT());
+  auto _o = std::unique_ptr<WhileOptionsT>(new WhileOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void MirrorPadOptions::UnPackTo(MirrorPadOptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+inline void WhileOptions::UnPackTo(WhileOptionsT *_o,
+                                   const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = mode();
-    _o->mode = _e;
+    auto _e = cond_subgraph_index();
+    _o->cond_subgraph_index = _e;
+  }
+  {
+    auto _e = body_subgraph_index();
+    _o->body_subgraph_index = _e;
   }
 }
 
-inline flatbuffers::Offset<MirrorPadOptions>
-MirrorPadOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<WhileOptions>
+WhileOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const WhileOptionsT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateMirrorPadOptions(_fbb, _o, _rehasher);
+  return CreateWhileOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<MirrorPadOptions>
-CreateMirrorPadOptions(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_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 MirrorPadOptionsT *__o;
+    const WhileOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  auto _mode = _o->mode;
-  return circle::CreateMirrorPadOptions(_fbb, _mode);
+  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 UniqueOptionsT *
-UniqueOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline NonMaxSuppressionV4OptionsT *
+NonMaxSuppressionV4Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<UniqueOptionsT>(new UniqueOptionsT());
+  auto _o = std::unique_ptr<NonMaxSuppressionV4OptionsT>(new NonMaxSuppressionV4OptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void UniqueOptions::UnPackTo(UniqueOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void
+NonMaxSuppressionV4Options::UnPackTo(NonMaxSuppressionV4OptionsT *_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)
+inline flatbuffers::Offset<NonMaxSuppressionV4Options>
+NonMaxSuppressionV4Options::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                 const NonMaxSuppressionV4OptionsT *_o,
+                                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateUniqueOptions(_fbb, _o, _rehasher);
+  return CreateNonMaxSuppressionV4Options(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<UniqueOptions>
-CreateUniqueOptions(flatbuffers::FlatBufferBuilder &_fbb, const UniqueOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_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 UniqueOptionsT *__o;
+    const NonMaxSuppressionV4OptionsT *__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);
+  return circle::CreateNonMaxSuppressionV4Options(_fbb);
 }
 
-inline ReverseV2OptionsT *
-ReverseV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline NonMaxSuppressionV5OptionsT *
+NonMaxSuppressionV5Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ReverseV2OptionsT>(new ReverseV2OptionsT());
+  auto _o = std::unique_ptr<NonMaxSuppressionV5OptionsT>(new NonMaxSuppressionV5OptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ReverseV2Options::UnPackTo(ReverseV2OptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+inline void
+NonMaxSuppressionV5Options::UnPackTo(NonMaxSuppressionV5OptionsT *_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)
+inline flatbuffers::Offset<NonMaxSuppressionV5Options>
+NonMaxSuppressionV5Options::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                 const NonMaxSuppressionV5OptionsT *_o,
+                                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateReverseV2Options(_fbb, _o, _rehasher);
+  return CreateNonMaxSuppressionV5Options(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ReverseV2Options>
-CreateReverseV2Options(flatbuffers::FlatBufferBuilder &_fbb, const ReverseV2OptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_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 ReverseV2OptionsT *__o;
+    const NonMaxSuppressionV5OptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateReverseV2Options(_fbb);
+  return circle::CreateNonMaxSuppressionV5Options(_fbb);
 }
 
-inline AddNOptionsT *AddNOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ScatterNdOptionsT *
+ScatterNdOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<AddNOptionsT>(new AddNOptionsT());
+  auto _o = std::unique_ptr<ScatterNdOptionsT>(new ScatterNdOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void AddNOptions::UnPackTo(AddNOptionsT *_o,
-                                  const flatbuffers::resolver_function_t *_resolver) const
+inline void ScatterNdOptions::UnPackTo(ScatterNdOptionsT *_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)
+inline flatbuffers::Offset<ScatterNdOptions>
+ScatterNdOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateAddNOptions(_fbb, _o, _rehasher);
+  return CreateScatterNdOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<AddNOptions>
-CreateAddNOptions(flatbuffers::FlatBufferBuilder &_fbb, const AddNOptionsT *_o,
-                  const flatbuffers::rehasher_function_t *_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 AddNOptionsT *__o;
+    const ScatterNdOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateAddNOptions(_fbb);
+  return circle::CreateScatterNdOptions(_fbb);
 }
 
-inline GatherNdOptionsT *
-GatherNdOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SelectV2OptionsT *
+SelectV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<GatherNdOptionsT>(new GatherNdOptionsT());
+  auto _o = std::unique_ptr<SelectV2OptionsT>(new SelectV2OptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void GatherNdOptions::UnPackTo(GatherNdOptionsT *_o,
+inline void SelectV2Options::UnPackTo(SelectV2OptionsT *_o,
                                       const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
 }
 
-inline flatbuffers::Offset<GatherNdOptions>
-GatherNdOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT *_o,
+inline flatbuffers::Offset<SelectV2Options>
+SelectV2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT *_o,
                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateGatherNdOptions(_fbb, _o, _rehasher);
+  return CreateSelectV2Options(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<GatherNdOptions>
-CreateGatherNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOptionsT *_o,
+inline flatbuffers::Offset<SelectV2Options>
+CreateSelectV2Options(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT *_o,
                       const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
@@ -19564,458 +21402,471 @@ CreateGatherNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const GatherNdOption
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const GatherNdOptionsT *__o;
+    const SelectV2OptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateGatherNdOptions(_fbb);
+  return circle::CreateSelectV2Options(_fbb);
 }
 
-inline WhereOptionsT *WhereOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline DensifyOptionsT *
+DensifyOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<WhereOptionsT>(new WhereOptionsT());
+  auto _o = std::unique_ptr<DensifyOptionsT>(new DensifyOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void WhereOptions::UnPackTo(WhereOptionsT *_o,
-                                   const flatbuffers::resolver_function_t *_resolver) const
+inline void DensifyOptions::UnPackTo(DensifyOptionsT *_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)
+inline flatbuffers::Offset<DensifyOptions>
+DensifyOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const DensifyOptionsT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateWhereOptions(_fbb, _o, _rehasher);
+  return CreateDensifyOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<WhereOptions>
-CreateWhereOptions(flatbuffers::FlatBufferBuilder &_fbb, const WhereOptionsT *_o,
-                   const flatbuffers::rehasher_function_t *_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 WhereOptionsT *__o;
+    const DensifyOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateWhereOptions(_fbb);
+  return circle::CreateDensifyOptions(_fbb);
 }
 
-inline ReverseSequenceOptionsT *
-ReverseSequenceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SegmentSumOptionsT *
+SegmentSumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ReverseSequenceOptionsT>(new ReverseSequenceOptionsT());
+  auto _o = std::unique_ptr<SegmentSumOptionsT>(new SegmentSumOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void
-ReverseSequenceOptions::UnPackTo(ReverseSequenceOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+inline void SegmentSumOptions::UnPackTo(SegmentSumOptionsT *_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)
+inline flatbuffers::Offset<SegmentSumOptions>
+SegmentSumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateReverseSequenceOptions(_fbb, _o, _rehasher);
+  return CreateSegmentSumOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ReverseSequenceOptions>
-CreateReverseSequenceOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                             const ReverseSequenceOptionsT *_o,
-                             const flatbuffers::rehasher_function_t *_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 ReverseSequenceOptionsT *__o;
+    const SegmentSumOptionsT *__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);
+  return circle::CreateSegmentSumOptions(_fbb);
 }
 
-inline MatrixDiagOptionsT *
-MatrixDiagOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline BatchMatMulOptionsT *
+BatchMatMulOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<MatrixDiagOptionsT>(new MatrixDiagOptionsT());
+  auto _o = std::unique_ptr<BatchMatMulOptionsT>(new BatchMatMulOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void MatrixDiagOptions::UnPackTo(MatrixDiagOptionsT *_o,
-                                        const flatbuffers::resolver_function_t *_resolver) const
+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<MatrixDiagOptions>
-MatrixDiagOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<BatchMatMulOptions>
+BatchMatMulOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT *_o,
+                         const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateMatrixDiagOptions(_fbb, _o, _rehasher);
+  return CreateBatchMatMulOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<MatrixDiagOptions>
-CreateMatrixDiagOptions(flatbuffers::FlatBufferBuilder &_fbb, const MatrixDiagOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_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 MatrixDiagOptionsT *__o;
+    const BatchMatMulOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateMatrixDiagOptions(_fbb);
+  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 QuantizeOptionsT *
-QuantizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline CumsumOptionsT *
+CumsumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<QuantizeOptionsT>(new QuantizeOptionsT());
+  auto _o = std::unique_ptr<CumsumOptionsT>(new CumsumOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void QuantizeOptions::UnPackTo(QuantizeOptionsT *_o,
-                                      const flatbuffers::resolver_function_t *_resolver) const
+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<QuantizeOptions>
-QuantizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT *_o,
-                      const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<CumsumOptions>
+CumsumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateQuantizeOptions(_fbb, _o, _rehasher);
+  return CreateCumsumOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<QuantizeOptions>
-CreateQuantizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const QuantizeOptionsT *_o,
-                      const flatbuffers::rehasher_function_t *_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 QuantizeOptionsT *__o;
+    const CumsumOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateQuantizeOptions(_fbb);
+  auto _exclusive = _o->exclusive;
+  auto _reverse = _o->reverse;
+  return circle::CreateCumsumOptions(_fbb, _exclusive, _reverse);
 }
 
-inline MatrixSetDiagOptionsT *
-MatrixSetDiagOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline BroadcastToOptionsT *
+BroadcastToOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<MatrixSetDiagOptionsT>(new MatrixSetDiagOptionsT());
+  auto _o = std::unique_ptr<BroadcastToOptionsT>(new BroadcastToOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void MatrixSetDiagOptions::UnPackTo(MatrixSetDiagOptionsT *_o,
-                                           const flatbuffers::resolver_function_t *_resolver) const
+inline void BroadcastToOptions::UnPackTo(BroadcastToOptionsT *_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)
+inline flatbuffers::Offset<BroadcastToOptions>
+BroadcastToOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BroadcastToOptionsT *_o,
+                         const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateMatrixSetDiagOptions(_fbb, _o, _rehasher);
+  return CreateBroadcastToOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<MatrixSetDiagOptions>
-CreateMatrixSetDiagOptions(flatbuffers::FlatBufferBuilder &_fbb, const MatrixSetDiagOptionsT *_o,
-                           const flatbuffers::rehasher_function_t *_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 MatrixSetDiagOptionsT *__o;
+    const BroadcastToOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateMatrixSetDiagOptions(_fbb);
+  return circle::CreateBroadcastToOptions(_fbb);
 }
 
-inline IfOptionsT *IfOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline Rfft2dOptionsT *
+Rfft2dOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<IfOptionsT>(new IfOptionsT());
+  auto _o = std::unique_ptr<Rfft2dOptionsT>(new Rfft2dOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void IfOptions::UnPackTo(IfOptionsT *_o,
-                                const flatbuffers::resolver_function_t *_resolver) const
+inline void Rfft2dOptions::UnPackTo(Rfft2dOptionsT *_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)
+inline flatbuffers::Offset<Rfft2dOptions>
+Rfft2dOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const Rfft2dOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateIfOptions(_fbb, _o, _rehasher);
+  return CreateRfft2dOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<IfOptions>
-CreateIfOptions(flatbuffers::FlatBufferBuilder &_fbb, const IfOptionsT *_o,
-                const flatbuffers::rehasher_function_t *_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 IfOptionsT *__o;
+    const Rfft2dOptionsT *__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);
+  return circle::CreateRfft2dOptions(_fbb);
 }
 
-inline CallOnceOptionsT *
-CallOnceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline HashtableOptionsT *
+HashtableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<CallOnceOptionsT>(new CallOnceOptionsT());
+  auto _o = std::unique_ptr<HashtableOptionsT>(new HashtableOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void CallOnceOptions::UnPackTo(CallOnceOptionsT *_o,
-                                      const flatbuffers::resolver_function_t *_resolver) const
+inline void HashtableOptions::UnPackTo(HashtableOptionsT *_o,
+                                       const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = init_subgraph_index();
-    _o->init_subgraph_index = _e;
+    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<CallOnceOptions>
-CallOnceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT *_o,
-                      const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<HashtableOptions>
+HashtableOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableOptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateCallOnceOptions(_fbb, _o, _rehasher);
+  return CreateHashtableOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<CallOnceOptions>
-CreateCallOnceOptions(flatbuffers::FlatBufferBuilder &_fbb, const CallOnceOptionsT *_o,
-                      const flatbuffers::rehasher_function_t *_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 CallOnceOptionsT *__o;
+    const HashtableOptionsT *__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);
+  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 WhileOptionsT *WhileOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline HashtableFindOptionsT *
+HashtableFindOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<WhileOptionsT>(new WhileOptionsT());
+  auto _o = std::unique_ptr<HashtableFindOptionsT>(new HashtableFindOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void WhileOptions::UnPackTo(WhileOptionsT *_o,
-                                   const flatbuffers::resolver_function_t *_resolver) const
+inline void HashtableFindOptions::UnPackTo(HashtableFindOptionsT *_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)
+inline flatbuffers::Offset<HashtableFindOptions>
+HashtableFindOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableFindOptionsT *_o,
+                           const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateWhileOptions(_fbb, _o, _rehasher);
+  return CreateHashtableFindOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<WhileOptions>
-CreateWhileOptions(flatbuffers::FlatBufferBuilder &_fbb, const WhileOptionsT *_o,
-                   const flatbuffers::rehasher_function_t *_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 WhileOptionsT *__o;
+    const HashtableFindOptionsT *__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);
+  return circle::CreateHashtableFindOptions(_fbb);
 }
 
-inline NonMaxSuppressionV4OptionsT *
-NonMaxSuppressionV4Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline HashtableImportOptionsT *
+HashtableImportOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<NonMaxSuppressionV4OptionsT>(new NonMaxSuppressionV4OptionsT());
+  auto _o = std::unique_ptr<HashtableImportOptionsT>(new HashtableImportOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
 inline void
-NonMaxSuppressionV4Options::UnPackTo(NonMaxSuppressionV4OptionsT *_o,
-                                     const flatbuffers::resolver_function_t *_resolver) const
+HashtableImportOptions::UnPackTo(HashtableImportOptionsT *_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)
+inline flatbuffers::Offset<HashtableImportOptions>
+HashtableImportOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                             const HashtableImportOptionsT *_o,
+                             const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateNonMaxSuppressionV4Options(_fbb, _o, _rehasher);
+  return CreateHashtableImportOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<NonMaxSuppressionV4Options>
-CreateNonMaxSuppressionV4Options(flatbuffers::FlatBufferBuilder &_fbb,
-                                 const NonMaxSuppressionV4OptionsT *_o,
-                                 const flatbuffers::rehasher_function_t *_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 NonMaxSuppressionV4OptionsT *__o;
+    const HashtableImportOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateNonMaxSuppressionV4Options(_fbb);
+  return circle::CreateHashtableImportOptions(_fbb);
 }
 
-inline NonMaxSuppressionV5OptionsT *
-NonMaxSuppressionV5Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline HashtableSizeOptionsT *
+HashtableSizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<NonMaxSuppressionV5OptionsT>(new NonMaxSuppressionV5OptionsT());
+  auto _o = std::unique_ptr<HashtableSizeOptionsT>(new HashtableSizeOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void
-NonMaxSuppressionV5Options::UnPackTo(NonMaxSuppressionV5OptionsT *_o,
-                                     const flatbuffers::resolver_function_t *_resolver) const
+inline void HashtableSizeOptions::UnPackTo(HashtableSizeOptionsT *_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)
+inline flatbuffers::Offset<HashtableSizeOptions>
+HashtableSizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const HashtableSizeOptionsT *_o,
+                           const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateNonMaxSuppressionV5Options(_fbb, _o, _rehasher);
+  return CreateHashtableSizeOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<NonMaxSuppressionV5Options>
-CreateNonMaxSuppressionV5Options(flatbuffers::FlatBufferBuilder &_fbb,
-                                 const NonMaxSuppressionV5OptionsT *_o,
-                                 const flatbuffers::rehasher_function_t *_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 NonMaxSuppressionV5OptionsT *__o;
+    const HashtableSizeOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateNonMaxSuppressionV5Options(_fbb);
+  return circle::CreateHashtableSizeOptions(_fbb);
 }
 
-inline ScatterNdOptionsT *
-ScatterNdOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline VarHandleOptionsT *
+VarHandleOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ScatterNdOptionsT>(new ScatterNdOptionsT());
+  auto _o = std::unique_ptr<VarHandleOptionsT>(new VarHandleOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ScatterNdOptions::UnPackTo(ScatterNdOptionsT *_o,
+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<ScatterNdOptions>
-ScatterNdOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT *_o,
+inline flatbuffers::Offset<VarHandleOptions>
+VarHandleOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT *_o,
                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateScatterNdOptions(_fbb, _o, _rehasher);
+  return CreateVarHandleOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ScatterNdOptions>
-CreateScatterNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOptionsT *_o,
+inline flatbuffers::Offset<VarHandleOptions>
+CreateVarHandleOptions(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT *_o,
                        const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
@@ -20023,647 +21874,622 @@ CreateScatterNdOptions(flatbuffers::FlatBufferBuilder &_fbb, const ScatterNdOpti
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const ScatterNdOptionsT *__o;
+    const VarHandleOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateScatterNdOptions(_fbb);
+  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 SelectV2OptionsT *
-SelectV2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ReadVariableOptionsT *
+ReadVariableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SelectV2OptionsT>(new SelectV2OptionsT());
+  auto _o = std::unique_ptr<ReadVariableOptionsT>(new ReadVariableOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SelectV2Options::UnPackTo(SelectV2OptionsT *_o,
-                                      const flatbuffers::resolver_function_t *_resolver) const
+inline void ReadVariableOptions::UnPackTo(ReadVariableOptionsT *_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)
+inline flatbuffers::Offset<ReadVariableOptions>
+ReadVariableOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ReadVariableOptionsT *_o,
+                          const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSelectV2Options(_fbb, _o, _rehasher);
+  return CreateReadVariableOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SelectV2Options>
-CreateSelectV2Options(flatbuffers::FlatBufferBuilder &_fbb, const SelectV2OptionsT *_o,
-                      const flatbuffers::rehasher_function_t *_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 SelectV2OptionsT *__o;
+    const ReadVariableOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateSelectV2Options(_fbb);
+  return circle::CreateReadVariableOptions(_fbb);
 }
 
-inline DensifyOptionsT *
-DensifyOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline AssignVariableOptionsT *
+AssignVariableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<DensifyOptionsT>(new DensifyOptionsT());
+  auto _o = std::unique_ptr<AssignVariableOptionsT>(new AssignVariableOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void DensifyOptions::UnPackTo(DensifyOptionsT *_o,
-                                     const flatbuffers::resolver_function_t *_resolver) const
+inline void AssignVariableOptions::UnPackTo(AssignVariableOptionsT *_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)
+inline flatbuffers::Offset<AssignVariableOptions>
+AssignVariableOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AssignVariableOptionsT *_o,
+                            const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateDensifyOptions(_fbb, _o, _rehasher);
+  return CreateAssignVariableOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<DensifyOptions>
-CreateDensifyOptions(flatbuffers::FlatBufferBuilder &_fbb, const DensifyOptionsT *_o,
-                     const flatbuffers::rehasher_function_t *_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 DensifyOptionsT *__o;
+    const AssignVariableOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateDensifyOptions(_fbb);
+  return circle::CreateAssignVariableOptions(_fbb);
 }
 
-inline SegmentSumOptionsT *
-SegmentSumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline RandomOptionsT *
+RandomOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<SegmentSumOptionsT>(new SegmentSumOptionsT());
+  auto _o = std::unique_ptr<RandomOptionsT>(new RandomOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void SegmentSumOptions::UnPackTo(SegmentSumOptionsT *_o,
-                                        const flatbuffers::resolver_function_t *_resolver) const
+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<SegmentSumOptions>
-SegmentSumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<RandomOptions>
+RandomOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT *_o,
+                    const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateSegmentSumOptions(_fbb, _o, _rehasher);
+  return CreateRandomOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<SegmentSumOptions>
-CreateSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb, const SegmentSumOptionsT *_o,
-                        const flatbuffers::rehasher_function_t *_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 SegmentSumOptionsT *__o;
+    const RandomOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateSegmentSumOptions(_fbb);
+  auto _seed = _o->seed;
+  auto _seed2 = _o->seed2;
+  return circle::CreateRandomOptions(_fbb, _seed, _seed2);
 }
 
-inline BatchMatMulOptionsT *
-BatchMatMulOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline BucketizeOptionsT *
+BucketizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<BatchMatMulOptionsT>(new BatchMatMulOptionsT());
+  auto _o = std::unique_ptr<BucketizeOptionsT>(new BucketizeOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void BatchMatMulOptions::UnPackTo(BatchMatMulOptionsT *_o,
-                                         const flatbuffers::resolver_function_t *_resolver) const
+inline void BucketizeOptions::UnPackTo(BucketizeOptionsT *_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;
+    auto _e = boundaries();
+    if (_e)
+    {
+      _o->boundaries.resize(_e->size());
+      for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->boundaries[_i] = _e->Get(_i);
+      }
+    }
   }
 }
 
-inline flatbuffers::Offset<BatchMatMulOptions>
-BatchMatMulOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT *_o,
-                         const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<BucketizeOptions>
+BucketizeOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateBatchMatMulOptions(_fbb, _o, _rehasher);
+  return CreateBucketizeOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<BatchMatMulOptions>
-CreateBatchMatMulOptions(flatbuffers::FlatBufferBuilder &_fbb, const BatchMatMulOptionsT *_o,
-                         const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<BucketizeOptions>
+CreateBucketizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT *_o,
+                       const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const BatchMatMulOptionsT *__o;
+    const BucketizeOptionsT *__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);
+  auto _boundaries = _o->boundaries.size() ? _fbb.CreateVector(_o->boundaries) : 0;
+  return circle::CreateBucketizeOptions(_fbb, _boundaries);
 }
 
-inline CumsumOptionsT *
-CumsumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline GeluOptionsT *GeluOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<CumsumOptionsT>(new CumsumOptionsT());
+  auto _o = std::unique_ptr<GeluOptionsT>(new GeluOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void CumsumOptions::UnPackTo(CumsumOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void GeluOptions::UnPackTo(GeluOptionsT *_o,
+                                  const flatbuffers::resolver_function_t *_resolver) const
 {
   (void)_o;
   (void)_resolver;
   {
-    auto _e = exclusive();
-    _o->exclusive = _e;
-  }
-  {
-    auto _e = reverse();
-    _o->reverse = _e;
+    auto _e = approximate();
+    _o->approximate = _e;
   }
 }
 
-inline flatbuffers::Offset<CumsumOptions>
-CumsumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<GeluOptions>
+GeluOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateCumsumOptions(_fbb, _o, _rehasher);
+  return CreateGeluOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<CumsumOptions>
-CreateCumsumOptions(flatbuffers::FlatBufferBuilder &_fbb, const CumsumOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<GeluOptions>
+CreateGeluOptions(flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const CumsumOptionsT *__o;
+    const GeluOptionsT *__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);
+  auto _approximate = _o->approximate;
+  return circle::CreateGeluOptions(_fbb, _approximate);
 }
 
-inline BroadcastToOptionsT *
-BroadcastToOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline DynamicUpdateSliceOptionsT *
+DynamicUpdateSliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<BroadcastToOptionsT>(new BroadcastToOptionsT());
+  auto _o = std::unique_ptr<DynamicUpdateSliceOptionsT>(new DynamicUpdateSliceOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void BroadcastToOptions::UnPackTo(BroadcastToOptionsT *_o,
-                                         const flatbuffers::resolver_function_t *_resolver) const
+inline void
+DynamicUpdateSliceOptions::UnPackTo(DynamicUpdateSliceOptionsT *_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)
+inline flatbuffers::Offset<DynamicUpdateSliceOptions>
+DynamicUpdateSliceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                const DynamicUpdateSliceOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateBroadcastToOptions(_fbb, _o, _rehasher);
+  return CreateDynamicUpdateSliceOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<BroadcastToOptions>
-CreateBroadcastToOptions(flatbuffers::FlatBufferBuilder &_fbb, const BroadcastToOptionsT *_o,
-                         const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<DynamicUpdateSliceOptions>
+CreateDynamicUpdateSliceOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                const DynamicUpdateSliceOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const BroadcastToOptionsT *__o;
+    const DynamicUpdateSliceOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateBroadcastToOptions(_fbb);
+  return circle::CreateDynamicUpdateSliceOptions(_fbb);
 }
 
-inline Rfft2dOptionsT *
-Rfft2dOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline UnsortedSegmentProdOptionsT *
+UnsortedSegmentProdOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<Rfft2dOptionsT>(new Rfft2dOptionsT());
+  auto _o = std::unique_ptr<UnsortedSegmentProdOptionsT>(new UnsortedSegmentProdOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void Rfft2dOptions::UnPackTo(Rfft2dOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void
+UnsortedSegmentProdOptions::UnPackTo(UnsortedSegmentProdOptionsT *_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)
+inline flatbuffers::Offset<UnsortedSegmentProdOptions>
+UnsortedSegmentProdOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                 const UnsortedSegmentProdOptionsT *_o,
+                                 const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateRfft2dOptions(_fbb, _o, _rehasher);
+  return CreateUnsortedSegmentProdOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<Rfft2dOptions>
-CreateRfft2dOptions(flatbuffers::FlatBufferBuilder &_fbb, const Rfft2dOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<UnsortedSegmentProdOptions>
+CreateUnsortedSegmentProdOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                 const UnsortedSegmentProdOptionsT *_o,
+                                 const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const Rfft2dOptionsT *__o;
+    const UnsortedSegmentProdOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateRfft2dOptions(_fbb);
+  return circle::CreateUnsortedSegmentProdOptions(_fbb);
 }
 
-inline HashtableOptionsT *
-HashtableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline UnsortedSegmentMaxOptionsT *
+UnsortedSegmentMaxOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<HashtableOptionsT>(new HashtableOptionsT());
+  auto _o = std::unique_ptr<UnsortedSegmentMaxOptionsT>(new UnsortedSegmentMaxOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void HashtableOptions::UnPackTo(HashtableOptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+inline void
+UnsortedSegmentMaxOptions::UnPackTo(UnsortedSegmentMaxOptionsT *_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)
+inline flatbuffers::Offset<UnsortedSegmentMaxOptions>
+UnsortedSegmentMaxOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMaxOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateHashtableOptions(_fbb, _o, _rehasher);
+  return CreateUnsortedSegmentMaxOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<HashtableOptions>
-CreateHashtableOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<UnsortedSegmentMaxOptions>
+CreateUnsortedSegmentMaxOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMaxOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const HashtableOptionsT *__o;
+    const UnsortedSegmentMaxOptionsT *__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);
+  return circle::CreateUnsortedSegmentMaxOptions(_fbb);
 }
 
-inline HashtableFindOptionsT *
-HashtableFindOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline UnsortedSegmentSumOptionsT *
+UnsortedSegmentSumOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<HashtableFindOptionsT>(new HashtableFindOptionsT());
+  auto _o = std::unique_ptr<UnsortedSegmentSumOptionsT>(new UnsortedSegmentSumOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void HashtableFindOptions::UnPackTo(HashtableFindOptionsT *_o,
-                                           const flatbuffers::resolver_function_t *_resolver) const
+inline void
+UnsortedSegmentSumOptions::UnPackTo(UnsortedSegmentSumOptionsT *_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)
+inline flatbuffers::Offset<UnsortedSegmentSumOptions>
+UnsortedSegmentSumOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentSumOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateHashtableFindOptions(_fbb, _o, _rehasher);
+  return CreateUnsortedSegmentSumOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<HashtableFindOptions>
-CreateHashtableFindOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableFindOptionsT *_o,
-                           const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<UnsortedSegmentSumOptions>
+CreateUnsortedSegmentSumOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentSumOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const HashtableFindOptionsT *__o;
+    const UnsortedSegmentSumOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateHashtableFindOptions(_fbb);
+  return circle::CreateUnsortedSegmentSumOptions(_fbb);
 }
 
-inline HashtableImportOptionsT *
-HashtableImportOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline ATan2OptionsT *ATan2Options::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<HashtableImportOptionsT>(new HashtableImportOptionsT());
+  auto _o = std::unique_ptr<ATan2OptionsT>(new ATan2OptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void
-HashtableImportOptions::UnPackTo(HashtableImportOptionsT *_o,
-                                 const flatbuffers::resolver_function_t *_resolver) const
+inline void ATan2Options::UnPackTo(ATan2OptionsT *_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)
+inline flatbuffers::Offset<ATan2Options>
+ATan2Options::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateHashtableImportOptions(_fbb, _o, _rehasher);
+  return CreateATan2Options(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<HashtableImportOptions>
-CreateHashtableImportOptions(flatbuffers::FlatBufferBuilder &_fbb,
-                             const HashtableImportOptionsT *_o,
-                             const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<ATan2Options>
+CreateATan2Options(flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT *_o,
+                   const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const HashtableImportOptionsT *__o;
+    const ATan2OptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateHashtableImportOptions(_fbb);
+  return circle::CreateATan2Options(_fbb);
 }
 
-inline HashtableSizeOptionsT *
-HashtableSizeOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline UnsortedSegmentMinOptionsT *
+UnsortedSegmentMinOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<HashtableSizeOptionsT>(new HashtableSizeOptionsT());
+  auto _o = std::unique_ptr<UnsortedSegmentMinOptionsT>(new UnsortedSegmentMinOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void HashtableSizeOptions::UnPackTo(HashtableSizeOptionsT *_o,
-                                           const flatbuffers::resolver_function_t *_resolver) const
+inline void
+UnsortedSegmentMinOptions::UnPackTo(UnsortedSegmentMinOptionsT *_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)
+inline flatbuffers::Offset<UnsortedSegmentMinOptions>
+UnsortedSegmentMinOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMinOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateHashtableSizeOptions(_fbb, _o, _rehasher);
+  return CreateUnsortedSegmentMinOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<HashtableSizeOptions>
-CreateHashtableSizeOptions(flatbuffers::FlatBufferBuilder &_fbb, const HashtableSizeOptionsT *_o,
-                           const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<UnsortedSegmentMinOptions>
+CreateUnsortedSegmentMinOptions(flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMinOptionsT *_o,
+                                const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const HashtableSizeOptionsT *__o;
+    const UnsortedSegmentMinOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateHashtableSizeOptions(_fbb);
+  return circle::CreateUnsortedSegmentMinOptions(_fbb);
 }
 
-inline VarHandleOptionsT *
-VarHandleOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline SignOptionsT *SignOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<VarHandleOptionsT>(new VarHandleOptionsT());
+  auto _o = std::unique_ptr<SignOptionsT>(new SignOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void VarHandleOptions::UnPackTo(VarHandleOptionsT *_o,
-                                       const flatbuffers::resolver_function_t *_resolver) const
+inline void SignOptions::UnPackTo(SignOptionsT *_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)
+}
+
+inline flatbuffers::Offset<SignOptions>
+SignOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateVarHandleOptions(_fbb, _o, _rehasher);
+  return CreateSignOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<VarHandleOptions>
-CreateVarHandleOptions(flatbuffers::FlatBufferBuilder &_fbb, const VarHandleOptionsT *_o,
-                       const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<SignOptions>
+CreateSignOptions(flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT *_o,
+                  const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const VarHandleOptionsT *__o;
+    const SignOptionsT *__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);
+  return circle::CreateSignOptions(_fbb);
 }
 
-inline ReadVariableOptionsT *
-ReadVariableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline BitcastOptionsT *
+BitcastOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<ReadVariableOptionsT>(new ReadVariableOptionsT());
+  auto _o = std::unique_ptr<BitcastOptionsT>(new BitcastOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void ReadVariableOptions::UnPackTo(ReadVariableOptionsT *_o,
-                                          const flatbuffers::resolver_function_t *_resolver) const
+inline void BitcastOptions::UnPackTo(BitcastOptionsT *_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)
+inline flatbuffers::Offset<BitcastOptions>
+BitcastOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BitcastOptionsT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateReadVariableOptions(_fbb, _o, _rehasher);
+  return CreateBitcastOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<ReadVariableOptions>
-CreateReadVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const ReadVariableOptionsT *_o,
-                          const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<BitcastOptions>
+CreateBitcastOptions(flatbuffers::FlatBufferBuilder &_fbb, const BitcastOptionsT *_o,
+                     const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const ReadVariableOptionsT *__o;
+    const BitcastOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateReadVariableOptions(_fbb);
+  return circle::CreateBitcastOptions(_fbb);
 }
 
-inline AssignVariableOptionsT *
-AssignVariableOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline BitwiseXorOptionsT *
+BitwiseXorOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<AssignVariableOptionsT>(new AssignVariableOptionsT());
+  auto _o = std::unique_ptr<BitwiseXorOptionsT>(new BitwiseXorOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void AssignVariableOptions::UnPackTo(AssignVariableOptionsT *_o,
-                                            const flatbuffers::resolver_function_t *_resolver) const
+inline void BitwiseXorOptions::UnPackTo(BitwiseXorOptionsT *_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)
+inline flatbuffers::Offset<BitwiseXorOptions>
+BitwiseXorOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BitwiseXorOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateAssignVariableOptions(_fbb, _o, _rehasher);
+  return CreateBitwiseXorOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<AssignVariableOptions>
-CreateAssignVariableOptions(flatbuffers::FlatBufferBuilder &_fbb, const AssignVariableOptionsT *_o,
-                            const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<BitwiseXorOptions>
+CreateBitwiseXorOptions(flatbuffers::FlatBufferBuilder &_fbb, const BitwiseXorOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const AssignVariableOptionsT *__o;
+    const BitwiseXorOptionsT *__o;
     const flatbuffers::rehasher_function_t *__rehasher;
   } _va = {&_fbb, _o, _rehasher};
   (void)_va;
-  return circle::CreateAssignVariableOptions(_fbb);
+  return circle::CreateBitwiseXorOptions(_fbb);
 }
 
-inline RandomOptionsT *
-RandomOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
+inline RightShiftOptionsT *
+RightShiftOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const
 {
-  auto _o = std::unique_ptr<RandomOptionsT>(new RandomOptionsT());
+  auto _o = std::unique_ptr<RightShiftOptionsT>(new RightShiftOptionsT());
   UnPackTo(_o.get(), _resolver);
   return _o.release();
 }
 
-inline void RandomOptions::UnPackTo(RandomOptionsT *_o,
-                                    const flatbuffers::resolver_function_t *_resolver) const
+inline void RightShiftOptions::UnPackTo(RightShiftOptionsT *_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)
+inline flatbuffers::Offset<RightShiftOptions>
+RightShiftOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const RightShiftOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
-  return CreateRandomOptions(_fbb, _o, _rehasher);
+  return CreateRightShiftOptions(_fbb, _o, _rehasher);
 }
 
-inline flatbuffers::Offset<RandomOptions>
-CreateRandomOptions(flatbuffers::FlatBufferBuilder &_fbb, const RandomOptionsT *_o,
-                    const flatbuffers::rehasher_function_t *_rehasher)
+inline flatbuffers::Offset<RightShiftOptions>
+CreateRightShiftOptions(flatbuffers::FlatBufferBuilder &_fbb, const RightShiftOptionsT *_o,
+                        const flatbuffers::rehasher_function_t *_rehasher)
 {
   (void)_rehasher;
   (void)_o;
   struct _VectorArgs
   {
     flatbuffers::FlatBufferBuilder *__fbb;
-    const RandomOptionsT *__o;
+    const RightShiftOptionsT *__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);
+  return circle::CreateRightShiftOptions(_fbb);
 }
 
 inline BCQGatherOptionsT *
@@ -22333,6 +24159,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);
@@ -22946,6 +24832,66 @@ inline void *BuiltinOptionsUnion::UnPack(const void *obj, BuiltinOptions type,
       auto ptr = reinterpret_cast<const circle::RandomOptions *>(obj);
       return ptr->UnPack(resolver);
     }
+    case BuiltinOptions_BucketizeOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BucketizeOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_GeluOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::GeluOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_DynamicUpdateSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::DynamicUpdateSliceOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_UnsortedSegmentProdOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentProdOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_UnsortedSegmentMaxOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentMaxOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_UnsortedSegmentMinOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentMinOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_UnsortedSegmentSumOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentSumOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_ATan2Options:
+    {
+      auto ptr = reinterpret_cast<const circle::ATan2Options *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_SignOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::SignOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_BitcastOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BitcastOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_BitwiseXorOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BitwiseXorOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_RightShiftOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::RightShiftOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
     case BuiltinOptions_BCQGatherOptions:
     {
       auto ptr = reinterpret_cast<const circle::BCQGatherOptions *>(obj);
@@ -23542,6 +25488,66 @@ BuiltinOptionsUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb,
       auto ptr = reinterpret_cast<const circle::RandomOptionsT *>(value);
       return CreateRandomOptions(_fbb, ptr, _rehasher).Union();
     }
+    case BuiltinOptions_BucketizeOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BucketizeOptionsT *>(value);
+      return CreateBucketizeOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_GeluOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::GeluOptionsT *>(value);
+      return CreateGeluOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_DynamicUpdateSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::DynamicUpdateSliceOptionsT *>(value);
+      return CreateDynamicUpdateSliceOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_UnsortedSegmentProdOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentProdOptionsT *>(value);
+      return CreateUnsortedSegmentProdOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_UnsortedSegmentMaxOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentMaxOptionsT *>(value);
+      return CreateUnsortedSegmentMaxOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_UnsortedSegmentMinOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentMinOptionsT *>(value);
+      return CreateUnsortedSegmentMinOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_UnsortedSegmentSumOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentSumOptionsT *>(value);
+      return CreateUnsortedSegmentSumOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_ATan2Options:
+    {
+      auto ptr = reinterpret_cast<const circle::ATan2OptionsT *>(value);
+      return CreateATan2Options(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_SignOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::SignOptionsT *>(value);
+      return CreateSignOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_BitcastOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BitcastOptionsT *>(value);
+      return CreateBitcastOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_BitwiseXorOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BitwiseXorOptionsT *>(value);
+      return CreateBitwiseXorOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_RightShiftOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::RightShiftOptionsT *>(value);
+      return CreateRightShiftOptions(_fbb, ptr, _rehasher).Union();
+    }
     case BuiltinOptions_BCQGatherOptions:
     {
       auto ptr = reinterpret_cast<const circle::BCQGatherOptionsT *>(value);
@@ -24190,6 +26196,74 @@ inline BuiltinOptionsUnion::BuiltinOptionsUnion(const BuiltinOptionsUnion &u)
       value = new circle::RandomOptionsT(*reinterpret_cast<circle::RandomOptionsT *>(u.value));
       break;
     }
+    case BuiltinOptions_BucketizeOptions:
+    {
+      value =
+        new circle::BucketizeOptionsT(*reinterpret_cast<circle::BucketizeOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_GeluOptions:
+    {
+      value = new circle::GeluOptionsT(*reinterpret_cast<circle::GeluOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_DynamicUpdateSliceOptions:
+    {
+      value = new circle::DynamicUpdateSliceOptionsT(
+        *reinterpret_cast<circle::DynamicUpdateSliceOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentProdOptions:
+    {
+      value = new circle::UnsortedSegmentProdOptionsT(
+        *reinterpret_cast<circle::UnsortedSegmentProdOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentMaxOptions:
+    {
+      value = new circle::UnsortedSegmentMaxOptionsT(
+        *reinterpret_cast<circle::UnsortedSegmentMaxOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentMinOptions:
+    {
+      value = new circle::UnsortedSegmentMinOptionsT(
+        *reinterpret_cast<circle::UnsortedSegmentMinOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentSumOptions:
+    {
+      value = new circle::UnsortedSegmentSumOptionsT(
+        *reinterpret_cast<circle::UnsortedSegmentSumOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_ATan2Options:
+    {
+      value = new circle::ATan2OptionsT(*reinterpret_cast<circle::ATan2OptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_SignOptions:
+    {
+      value = new circle::SignOptionsT(*reinterpret_cast<circle::SignOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_BitcastOptions:
+    {
+      value = new circle::BitcastOptionsT(*reinterpret_cast<circle::BitcastOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_BitwiseXorOptions:
+    {
+      value =
+        new circle::BitwiseXorOptionsT(*reinterpret_cast<circle::BitwiseXorOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_RightShiftOptions:
+    {
+      value =
+        new circle::RightShiftOptionsT(*reinterpret_cast<circle::RightShiftOptionsT *>(u.value));
+      break;
+    }
     case BuiltinOptions_BCQGatherOptions:
     {
       value =
@@ -24901,6 +26975,78 @@ inline void BuiltinOptionsUnion::Reset()
       delete ptr;
       break;
     }
+    case BuiltinOptions_BucketizeOptions:
+    {
+      auto ptr = reinterpret_cast<circle::BucketizeOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_GeluOptions:
+    {
+      auto ptr = reinterpret_cast<circle::GeluOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_DynamicUpdateSliceOptions:
+    {
+      auto ptr = reinterpret_cast<circle::DynamicUpdateSliceOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentProdOptions:
+    {
+      auto ptr = reinterpret_cast<circle::UnsortedSegmentProdOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentMaxOptions:
+    {
+      auto ptr = reinterpret_cast<circle::UnsortedSegmentMaxOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentMinOptions:
+    {
+      auto ptr = reinterpret_cast<circle::UnsortedSegmentMinOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentSumOptions:
+    {
+      auto ptr = reinterpret_cast<circle::UnsortedSegmentSumOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_ATan2Options:
+    {
+      auto ptr = reinterpret_cast<circle::ATan2OptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_SignOptions:
+    {
+      auto ptr = reinterpret_cast<circle::SignOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_BitcastOptions:
+    {
+      auto ptr = reinterpret_cast<circle::BitcastOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_BitwiseXorOptions:
+    {
+      auto ptr = reinterpret_cast<circle::BitwiseXorOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_RightShiftOptions:
+    {
+      auto ptr = reinterpret_cast<circle::RightShiftOptionsT *>(value);
+      delete ptr;
+      break;
+    }
     case BuiltinOptions_BCQGatherOptions:
     {
       auto ptr = reinterpret_cast<circle::BCQGatherOptionsT *>(value);
diff --git a/onert-micro/externals/gen/circle-generated/circle/traininfo_generated.h b/onert-micro/externals/gen/circle-generated/circle/traininfo_generated.h
new file mode 100644 (file)
index 0000000..0ac4d7d
--- /dev/null
@@ -0,0 +1,1298 @@
+// automatically generated by the FlatBuffers compiler, do not modify
+
+
+#ifndef FLATBUFFERS_GENERATED_TRAININFO_CIRCLE_H_
+#define FLATBUFFERS_GENERATED_TRAININFO_CIRCLE_H_
+
+#include "flatbuffers/flatbuffers.h"
+
+namespace circle {
+
+struct SGDOptions;
+struct SGDOptionsBuilder;
+struct SGDOptionsT;
+
+struct AdamOptions;
+struct AdamOptionsBuilder;
+struct AdamOptionsT;
+
+struct SparseCategoricalCrossentropyOptions;
+struct SparseCategoricalCrossentropyOptionsBuilder;
+struct SparseCategoricalCrossentropyOptionsT;
+
+struct CategoricalCrossentropyOptions;
+struct CategoricalCrossentropyOptionsBuilder;
+struct CategoricalCrossentropyOptionsT;
+
+struct MeanSquaredErrorOptions;
+struct MeanSquaredErrorOptionsBuilder;
+struct MeanSquaredErrorOptionsT;
+
+struct ModelTraining;
+struct ModelTrainingBuilder;
+struct ModelTrainingT;
+
+enum Optimizer : int8_t {
+  Optimizer_SGD = 0,
+  Optimizer_ADAM = 1,
+  Optimizer_MIN = Optimizer_SGD,
+  Optimizer_MAX = Optimizer_ADAM
+};
+
+inline const Optimizer (&EnumValuesOptimizer())[2] {
+  static const Optimizer values[] = {
+    Optimizer_SGD,
+    Optimizer_ADAM
+  };
+  return values;
+}
+
+inline const char * const *EnumNamesOptimizer() {
+  static const char * const names[3] = {
+    "SGD",
+    "ADAM",
+    nullptr
+  };
+  return names;
+}
+
+inline const char *EnumNameOptimizer(Optimizer e) {
+  if (flatbuffers::IsOutRange(e, Optimizer_SGD, Optimizer_ADAM)) return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesOptimizer()[index];
+}
+
+enum OptimizerOptions : uint8_t {
+  OptimizerOptions_NONE = 0,
+  OptimizerOptions_SGDOptions = 1,
+  OptimizerOptions_AdamOptions = 2,
+  OptimizerOptions_MIN = OptimizerOptions_NONE,
+  OptimizerOptions_MAX = OptimizerOptions_AdamOptions
+};
+
+inline const OptimizerOptions (&EnumValuesOptimizerOptions())[3] {
+  static const OptimizerOptions values[] = {
+    OptimizerOptions_NONE,
+    OptimizerOptions_SGDOptions,
+    OptimizerOptions_AdamOptions
+  };
+  return values;
+}
+
+inline const char * const *EnumNamesOptimizerOptions() {
+  static const char * const names[4] = {
+    "NONE",
+    "SGDOptions",
+    "AdamOptions",
+    nullptr
+  };
+  return names;
+}
+
+inline const char *EnumNameOptimizerOptions(OptimizerOptions e) {
+  if (flatbuffers::IsOutRange(e, OptimizerOptions_NONE, OptimizerOptions_AdamOptions)) return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesOptimizerOptions()[index];
+}
+
+template<typename T> struct OptimizerOptionsTraits {
+  static const OptimizerOptions enum_value = OptimizerOptions_NONE;
+};
+
+template<> struct OptimizerOptionsTraits<circle::SGDOptions> {
+  static const OptimizerOptions enum_value = OptimizerOptions_SGDOptions;
+};
+
+template<> struct OptimizerOptionsTraits<circle::AdamOptions> {
+  static const OptimizerOptions enum_value = OptimizerOptions_AdamOptions;
+};
+
+struct OptimizerOptionsUnion {
+  OptimizerOptions type;
+  void *value;
+
+  OptimizerOptionsUnion() : type(OptimizerOptions_NONE), value(nullptr) {}
+  OptimizerOptionsUnion(OptimizerOptionsUnion&& u) FLATBUFFERS_NOEXCEPT :
+    type(OptimizerOptions_NONE), value(nullptr)
+    { std::swap(type, u.type); std::swap(value, u.value); }
+  OptimizerOptionsUnion(const OptimizerOptionsUnion &);
+  OptimizerOptionsUnion &operator=(const OptimizerOptionsUnion &u)
+    { OptimizerOptionsUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; }
+  OptimizerOptionsUnion &operator=(OptimizerOptionsUnion &&u) FLATBUFFERS_NOEXCEPT
+    { std::swap(type, u.type); std::swap(value, u.value); return *this; }
+  ~OptimizerOptionsUnion() { Reset(); }
+
+  void Reset();
+
+#ifndef FLATBUFFERS_CPP98_STL
+  template <typename T>
+  void Set(T&& val) {
+    using RT = typename std::remove_reference<T>::type;
+    Reset();
+    type = OptimizerOptionsTraits<typename RT::TableType>::enum_value;
+    if (type != OptimizerOptions_NONE) {
+      value = new RT(std::forward<T>(val));
+    }
+  }
+#endif  // FLATBUFFERS_CPP98_STL
+
+  static void *UnPack(const void *obj, OptimizerOptions type, const flatbuffers::resolver_function_t *resolver);
+  flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
+
+  circle::SGDOptionsT *AsSGDOptions() {
+    return type == OptimizerOptions_SGDOptions ?
+      reinterpret_cast<circle::SGDOptionsT *>(value) : nullptr;
+  }
+  const circle::SGDOptionsT *AsSGDOptions() const {
+    return type == OptimizerOptions_SGDOptions ?
+      reinterpret_cast<const circle::SGDOptionsT *>(value) : nullptr;
+  }
+  circle::AdamOptionsT *AsAdamOptions() {
+    return type == OptimizerOptions_AdamOptions ?
+      reinterpret_cast<circle::AdamOptionsT *>(value) : nullptr;
+  }
+  const circle::AdamOptionsT *AsAdamOptions() const {
+    return type == OptimizerOptions_AdamOptions ?
+      reinterpret_cast<const circle::AdamOptionsT *>(value) : nullptr;
+  }
+};
+
+bool VerifyOptimizerOptions(flatbuffers::Verifier &verifier, const void *obj, OptimizerOptions type);
+bool VerifyOptimizerOptionsVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
+
+enum LossFn : int8_t {
+  LossFn_SPARSE_CATEGORICAL_CROSSENTROPY = 0,
+  LossFn_CATEGORICAL_CROSSENTROPY = 1,
+  LossFn_MEAN_SQUARED_ERROR = 2,
+  LossFn_MIN = LossFn_SPARSE_CATEGORICAL_CROSSENTROPY,
+  LossFn_MAX = LossFn_MEAN_SQUARED_ERROR
+};
+
+inline const LossFn (&EnumValuesLossFn())[3] {
+  static const LossFn values[] = {
+    LossFn_SPARSE_CATEGORICAL_CROSSENTROPY,
+    LossFn_CATEGORICAL_CROSSENTROPY,
+    LossFn_MEAN_SQUARED_ERROR
+  };
+  return values;
+}
+
+inline const char * const *EnumNamesLossFn() {
+  static const char * const names[4] = {
+    "SPARSE_CATEGORICAL_CROSSENTROPY",
+    "CATEGORICAL_CROSSENTROPY",
+    "MEAN_SQUARED_ERROR",
+    nullptr
+  };
+  return names;
+}
+
+inline const char *EnumNameLossFn(LossFn e) {
+  if (flatbuffers::IsOutRange(e, LossFn_SPARSE_CATEGORICAL_CROSSENTROPY, LossFn_MEAN_SQUARED_ERROR)) return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesLossFn()[index];
+}
+
+enum LossFnOptions : uint8_t {
+  LossFnOptions_NONE = 0,
+  LossFnOptions_SparseCategoricalCrossentropyOptions = 1,
+  LossFnOptions_CategoricalCrossentropyOptions = 2,
+  LossFnOptions_MeanSquaredErrorOptions = 3,
+  LossFnOptions_MIN = LossFnOptions_NONE,
+  LossFnOptions_MAX = LossFnOptions_MeanSquaredErrorOptions
+};
+
+inline const LossFnOptions (&EnumValuesLossFnOptions())[4] {
+  static const LossFnOptions values[] = {
+    LossFnOptions_NONE,
+    LossFnOptions_SparseCategoricalCrossentropyOptions,
+    LossFnOptions_CategoricalCrossentropyOptions,
+    LossFnOptions_MeanSquaredErrorOptions
+  };
+  return values;
+}
+
+inline const char * const *EnumNamesLossFnOptions() {
+  static const char * const names[5] = {
+    "NONE",
+    "SparseCategoricalCrossentropyOptions",
+    "CategoricalCrossentropyOptions",
+    "MeanSquaredErrorOptions",
+    nullptr
+  };
+  return names;
+}
+
+inline const char *EnumNameLossFnOptions(LossFnOptions e) {
+  if (flatbuffers::IsOutRange(e, LossFnOptions_NONE, LossFnOptions_MeanSquaredErrorOptions)) return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesLossFnOptions()[index];
+}
+
+template<typename T> struct LossFnOptionsTraits {
+  static const LossFnOptions enum_value = LossFnOptions_NONE;
+};
+
+template<> struct LossFnOptionsTraits<circle::SparseCategoricalCrossentropyOptions> {
+  static const LossFnOptions enum_value = LossFnOptions_SparseCategoricalCrossentropyOptions;
+};
+
+template<> struct LossFnOptionsTraits<circle::CategoricalCrossentropyOptions> {
+  static const LossFnOptions enum_value = LossFnOptions_CategoricalCrossentropyOptions;
+};
+
+template<> struct LossFnOptionsTraits<circle::MeanSquaredErrorOptions> {
+  static const LossFnOptions enum_value = LossFnOptions_MeanSquaredErrorOptions;
+};
+
+struct LossFnOptionsUnion {
+  LossFnOptions type;
+  void *value;
+
+  LossFnOptionsUnion() : type(LossFnOptions_NONE), value(nullptr) {}
+  LossFnOptionsUnion(LossFnOptionsUnion&& u) FLATBUFFERS_NOEXCEPT :
+    type(LossFnOptions_NONE), value(nullptr)
+    { std::swap(type, u.type); std::swap(value, u.value); }
+  LossFnOptionsUnion(const LossFnOptionsUnion &);
+  LossFnOptionsUnion &operator=(const LossFnOptionsUnion &u)
+    { LossFnOptionsUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; }
+  LossFnOptionsUnion &operator=(LossFnOptionsUnion &&u) FLATBUFFERS_NOEXCEPT
+    { std::swap(type, u.type); std::swap(value, u.value); return *this; }
+  ~LossFnOptionsUnion() { Reset(); }
+
+  void Reset();
+
+#ifndef FLATBUFFERS_CPP98_STL
+  template <typename T>
+  void Set(T&& val) {
+    using RT = typename std::remove_reference<T>::type;
+    Reset();
+    type = LossFnOptionsTraits<typename RT::TableType>::enum_value;
+    if (type != LossFnOptions_NONE) {
+      value = new RT(std::forward<T>(val));
+    }
+  }
+#endif  // FLATBUFFERS_CPP98_STL
+
+  static void *UnPack(const void *obj, LossFnOptions type, const flatbuffers::resolver_function_t *resolver);
+  flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
+
+  circle::SparseCategoricalCrossentropyOptionsT *AsSparseCategoricalCrossentropyOptions() {
+    return type == LossFnOptions_SparseCategoricalCrossentropyOptions ?
+      reinterpret_cast<circle::SparseCategoricalCrossentropyOptionsT *>(value) : nullptr;
+  }
+  const circle::SparseCategoricalCrossentropyOptionsT *AsSparseCategoricalCrossentropyOptions() const {
+    return type == LossFnOptions_SparseCategoricalCrossentropyOptions ?
+      reinterpret_cast<const circle::SparseCategoricalCrossentropyOptionsT *>(value) : nullptr;
+  }
+  circle::CategoricalCrossentropyOptionsT *AsCategoricalCrossentropyOptions() {
+    return type == LossFnOptions_CategoricalCrossentropyOptions ?
+      reinterpret_cast<circle::CategoricalCrossentropyOptionsT *>(value) : nullptr;
+  }
+  const circle::CategoricalCrossentropyOptionsT *AsCategoricalCrossentropyOptions() const {
+    return type == LossFnOptions_CategoricalCrossentropyOptions ?
+      reinterpret_cast<const circle::CategoricalCrossentropyOptionsT *>(value) : nullptr;
+  }
+  circle::MeanSquaredErrorOptionsT *AsMeanSquaredErrorOptions() {
+    return type == LossFnOptions_MeanSquaredErrorOptions ?
+      reinterpret_cast<circle::MeanSquaredErrorOptionsT *>(value) : nullptr;
+  }
+  const circle::MeanSquaredErrorOptionsT *AsMeanSquaredErrorOptions() const {
+    return type == LossFnOptions_MeanSquaredErrorOptions ?
+      reinterpret_cast<const circle::MeanSquaredErrorOptionsT *>(value) : nullptr;
+  }
+};
+
+bool VerifyLossFnOptions(flatbuffers::Verifier &verifier, const void *obj, LossFnOptions type);
+bool VerifyLossFnOptionsVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
+
+enum LossReductionType : int8_t {
+  LossReductionType_SumOverBatchSize = 0,
+  LossReductionType_Sum = 1,
+  LossReductionType_MIN = LossReductionType_SumOverBatchSize,
+  LossReductionType_MAX = LossReductionType_Sum
+};
+
+inline const LossReductionType (&EnumValuesLossReductionType())[2] {
+  static const LossReductionType values[] = {
+    LossReductionType_SumOverBatchSize,
+    LossReductionType_Sum
+  };
+  return values;
+}
+
+inline const char * const *EnumNamesLossReductionType() {
+  static const char * const names[3] = {
+    "SumOverBatchSize",
+    "Sum",
+    nullptr
+  };
+  return names;
+}
+
+inline const char *EnumNameLossReductionType(LossReductionType e) {
+  if (flatbuffers::IsOutRange(e, LossReductionType_SumOverBatchSize, LossReductionType_Sum)) return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesLossReductionType()[index];
+}
+
+struct SGDOptionsT : public flatbuffers::NativeTable {
+  typedef SGDOptions TableType;
+  float learning_rate = 0.0f;
+};
+
+struct SGDOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  typedef SGDOptionsT NativeTableType;
+  typedef SGDOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+    VT_LEARNING_RATE = 4
+  };
+  float learning_rate() const {
+    return GetField<float>(VT_LEARNING_RATE, 0.0f);
+  }
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           VerifyField<float>(verifier, VT_LEARNING_RATE) &&
+           verifier.EndTable();
+  }
+  SGDOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(SGDOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<SGDOptions> Pack(flatbuffers::FlatBufferBuilder &_fbb, const SGDOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SGDOptionsBuilder {
+  typedef SGDOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  void add_learning_rate(float learning_rate) {
+    fbb_.AddElement<float>(SGDOptions::VT_LEARNING_RATE, learning_rate, 0.0f);
+  }
+  explicit SGDOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+        : fbb_(_fbb) {
+    start_ = fbb_.StartTable();
+  }
+  flatbuffers::Offset<SGDOptions> Finish() {
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<SGDOptions>(end);
+    return o;
+  }
+};
+
+inline flatbuffers::Offset<SGDOptions> CreateSGDOptions(
+    flatbuffers::FlatBufferBuilder &_fbb,
+    float learning_rate = 0.0f) {
+  SGDOptionsBuilder builder_(_fbb);
+  builder_.add_learning_rate(learning_rate);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<SGDOptions> CreateSGDOptions(flatbuffers::FlatBufferBuilder &_fbb, const SGDOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct AdamOptionsT : public flatbuffers::NativeTable {
+  typedef AdamOptions TableType;
+  float learning_rate = 0.0f;
+  float beta_1 = 0.0f;
+  float beta_2 = 0.0f;
+  float epsilon = 0.0f;
+};
+
+struct AdamOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  typedef AdamOptionsT NativeTableType;
+  typedef AdamOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+    VT_LEARNING_RATE = 4,
+    VT_BETA_1 = 6,
+    VT_BETA_2 = 8,
+    VT_EPSILON = 10
+  };
+  float learning_rate() const {
+    return GetField<float>(VT_LEARNING_RATE, 0.0f);
+  }
+  float beta_1() const {
+    return GetField<float>(VT_BETA_1, 0.0f);
+  }
+  float beta_2() const {
+    return GetField<float>(VT_BETA_2, 0.0f);
+  }
+  float epsilon() const {
+    return GetField<float>(VT_EPSILON, 0.0f);
+  }
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           VerifyField<float>(verifier, VT_LEARNING_RATE) &&
+           VerifyField<float>(verifier, VT_BETA_1) &&
+           VerifyField<float>(verifier, VT_BETA_2) &&
+           VerifyField<float>(verifier, VT_EPSILON) &&
+           verifier.EndTable();
+  }
+  AdamOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(AdamOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<AdamOptions> Pack(flatbuffers::FlatBufferBuilder &_fbb, const AdamOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct AdamOptionsBuilder {
+  typedef AdamOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  void add_learning_rate(float learning_rate) {
+    fbb_.AddElement<float>(AdamOptions::VT_LEARNING_RATE, learning_rate, 0.0f);
+  }
+  void add_beta_1(float beta_1) {
+    fbb_.AddElement<float>(AdamOptions::VT_BETA_1, beta_1, 0.0f);
+  }
+  void add_beta_2(float beta_2) {
+    fbb_.AddElement<float>(AdamOptions::VT_BETA_2, beta_2, 0.0f);
+  }
+  void add_epsilon(float epsilon) {
+    fbb_.AddElement<float>(AdamOptions::VT_EPSILON, epsilon, 0.0f);
+  }
+  explicit AdamOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+        : fbb_(_fbb) {
+    start_ = fbb_.StartTable();
+  }
+  flatbuffers::Offset<AdamOptions> Finish() {
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<AdamOptions>(end);
+    return o;
+  }
+};
+
+inline flatbuffers::Offset<AdamOptions> CreateAdamOptions(
+    flatbuffers::FlatBufferBuilder &_fbb,
+    float learning_rate = 0.0f,
+    float beta_1 = 0.0f,
+    float beta_2 = 0.0f,
+    float epsilon = 0.0f) {
+  AdamOptionsBuilder builder_(_fbb);
+  builder_.add_epsilon(epsilon);
+  builder_.add_beta_2(beta_2);
+  builder_.add_beta_1(beta_1);
+  builder_.add_learning_rate(learning_rate);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<AdamOptions> CreateAdamOptions(flatbuffers::FlatBufferBuilder &_fbb, const AdamOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SparseCategoricalCrossentropyOptionsT : public flatbuffers::NativeTable {
+  typedef SparseCategoricalCrossentropyOptions TableType;
+  bool from_logits = false;
+};
+
+struct SparseCategoricalCrossentropyOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  typedef SparseCategoricalCrossentropyOptionsT NativeTableType;
+  typedef SparseCategoricalCrossentropyOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+    VT_FROM_LOGITS = 4
+  };
+  bool from_logits() const {
+    return GetField<uint8_t>(VT_FROM_LOGITS, 0) != 0;
+  }
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           VerifyField<uint8_t>(verifier, VT_FROM_LOGITS) &&
+           verifier.EndTable();
+  }
+  SparseCategoricalCrossentropyOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(SparseCategoricalCrossentropyOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<SparseCategoricalCrossentropyOptions> Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparseCategoricalCrossentropyOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct SparseCategoricalCrossentropyOptionsBuilder {
+  typedef SparseCategoricalCrossentropyOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  void add_from_logits(bool from_logits) {
+    fbb_.AddElement<uint8_t>(SparseCategoricalCrossentropyOptions::VT_FROM_LOGITS, static_cast<uint8_t>(from_logits), 0);
+  }
+  explicit SparseCategoricalCrossentropyOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+        : fbb_(_fbb) {
+    start_ = fbb_.StartTable();
+  }
+  flatbuffers::Offset<SparseCategoricalCrossentropyOptions> Finish() {
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<SparseCategoricalCrossentropyOptions>(end);
+    return o;
+  }
+};
+
+inline flatbuffers::Offset<SparseCategoricalCrossentropyOptions> CreateSparseCategoricalCrossentropyOptions(
+    flatbuffers::FlatBufferBuilder &_fbb,
+    bool from_logits = false) {
+  SparseCategoricalCrossentropyOptionsBuilder builder_(_fbb);
+  builder_.add_from_logits(from_logits);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<SparseCategoricalCrossentropyOptions> CreateSparseCategoricalCrossentropyOptions(flatbuffers::FlatBufferBuilder &_fbb, const SparseCategoricalCrossentropyOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct CategoricalCrossentropyOptionsT : public flatbuffers::NativeTable {
+  typedef CategoricalCrossentropyOptions TableType;
+  bool from_logits = false;
+};
+
+struct CategoricalCrossentropyOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  typedef CategoricalCrossentropyOptionsT NativeTableType;
+  typedef CategoricalCrossentropyOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+    VT_FROM_LOGITS = 4
+  };
+  bool from_logits() const {
+    return GetField<uint8_t>(VT_FROM_LOGITS, 0) != 0;
+  }
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           VerifyField<uint8_t>(verifier, VT_FROM_LOGITS) &&
+           verifier.EndTable();
+  }
+  CategoricalCrossentropyOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(CategoricalCrossentropyOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<CategoricalCrossentropyOptions> Pack(flatbuffers::FlatBufferBuilder &_fbb, const CategoricalCrossentropyOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct CategoricalCrossentropyOptionsBuilder {
+  typedef CategoricalCrossentropyOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  void add_from_logits(bool from_logits) {
+    fbb_.AddElement<uint8_t>(CategoricalCrossentropyOptions::VT_FROM_LOGITS, static_cast<uint8_t>(from_logits), 0);
+  }
+  explicit CategoricalCrossentropyOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+        : fbb_(_fbb) {
+    start_ = fbb_.StartTable();
+  }
+  flatbuffers::Offset<CategoricalCrossentropyOptions> Finish() {
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<CategoricalCrossentropyOptions>(end);
+    return o;
+  }
+};
+
+inline flatbuffers::Offset<CategoricalCrossentropyOptions> CreateCategoricalCrossentropyOptions(
+    flatbuffers::FlatBufferBuilder &_fbb,
+    bool from_logits = false) {
+  CategoricalCrossentropyOptionsBuilder builder_(_fbb);
+  builder_.add_from_logits(from_logits);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<CategoricalCrossentropyOptions> CreateCategoricalCrossentropyOptions(flatbuffers::FlatBufferBuilder &_fbb, const CategoricalCrossentropyOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct MeanSquaredErrorOptionsT : public flatbuffers::NativeTable {
+  typedef MeanSquaredErrorOptions TableType;
+};
+
+struct MeanSquaredErrorOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  typedef MeanSquaredErrorOptionsT NativeTableType;
+  typedef MeanSquaredErrorOptionsBuilder Builder;
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           verifier.EndTable();
+  }
+  MeanSquaredErrorOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(MeanSquaredErrorOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<MeanSquaredErrorOptions> Pack(flatbuffers::FlatBufferBuilder &_fbb, const MeanSquaredErrorOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct MeanSquaredErrorOptionsBuilder {
+  typedef MeanSquaredErrorOptions Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  explicit MeanSquaredErrorOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+        : fbb_(_fbb) {
+    start_ = fbb_.StartTable();
+  }
+  flatbuffers::Offset<MeanSquaredErrorOptions> Finish() {
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<MeanSquaredErrorOptions>(end);
+    return o;
+  }
+};
+
+inline flatbuffers::Offset<MeanSquaredErrorOptions> CreateMeanSquaredErrorOptions(
+    flatbuffers::FlatBufferBuilder &_fbb) {
+  MeanSquaredErrorOptionsBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+flatbuffers::Offset<MeanSquaredErrorOptions> CreateMeanSquaredErrorOptions(flatbuffers::FlatBufferBuilder &_fbb, const MeanSquaredErrorOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ModelTrainingT : public flatbuffers::NativeTable {
+  typedef ModelTraining TableType;
+  uint32_t version = 0;
+  circle::Optimizer optimizer = circle::Optimizer_SGD;
+  circle::OptimizerOptionsUnion optimizer_opt{};
+  circle::LossFn lossfn = circle::LossFn_SPARSE_CATEGORICAL_CROSSENTROPY;
+  circle::LossFnOptionsUnion lossfn_opt{};
+  int32_t epochs = 0;
+  int32_t batch_size = 0;
+  circle::LossReductionType loss_reduction_type = circle::LossReductionType_SumOverBatchSize;
+  std::vector<int32_t> trainable_ops{};
+};
+
+struct ModelTraining FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  typedef ModelTrainingT NativeTableType;
+  typedef ModelTrainingBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+    VT_VERSION = 4,
+    VT_OPTIMIZER = 6,
+    VT_OPTIMIZER_OPT_TYPE = 8,
+    VT_OPTIMIZER_OPT = 10,
+    VT_LOSSFN = 12,
+    VT_LOSSFN_OPT_TYPE = 14,
+    VT_LOSSFN_OPT = 16,
+    VT_EPOCHS = 18,
+    VT_BATCH_SIZE = 20,
+    VT_LOSS_REDUCTION_TYPE = 22,
+    VT_TRAINABLE_OPS = 24
+  };
+  uint32_t version() const {
+    return GetField<uint32_t>(VT_VERSION, 0);
+  }
+  circle::Optimizer optimizer() const {
+    return static_cast<circle::Optimizer>(GetField<int8_t>(VT_OPTIMIZER, 0));
+  }
+  circle::OptimizerOptions optimizer_opt_type() const {
+    return static_cast<circle::OptimizerOptions>(GetField<uint8_t>(VT_OPTIMIZER_OPT_TYPE, 0));
+  }
+  const void *optimizer_opt() const {
+    return GetPointer<const void *>(VT_OPTIMIZER_OPT);
+  }
+  template<typename T> const T *optimizer_opt_as() const;
+  const circle::SGDOptions *optimizer_opt_as_SGDOptions() const {
+    return optimizer_opt_type() == circle::OptimizerOptions_SGDOptions ? static_cast<const circle::SGDOptions *>(optimizer_opt()) : nullptr;
+  }
+  const circle::AdamOptions *optimizer_opt_as_AdamOptions() const {
+    return optimizer_opt_type() == circle::OptimizerOptions_AdamOptions ? static_cast<const circle::AdamOptions *>(optimizer_opt()) : nullptr;
+  }
+  circle::LossFn lossfn() const {
+    return static_cast<circle::LossFn>(GetField<int8_t>(VT_LOSSFN, 0));
+  }
+  circle::LossFnOptions lossfn_opt_type() const {
+    return static_cast<circle::LossFnOptions>(GetField<uint8_t>(VT_LOSSFN_OPT_TYPE, 0));
+  }
+  const void *lossfn_opt() const {
+    return GetPointer<const void *>(VT_LOSSFN_OPT);
+  }
+  template<typename T> const T *lossfn_opt_as() const;
+  const circle::SparseCategoricalCrossentropyOptions *lossfn_opt_as_SparseCategoricalCrossentropyOptions() const {
+    return lossfn_opt_type() == circle::LossFnOptions_SparseCategoricalCrossentropyOptions ? static_cast<const circle::SparseCategoricalCrossentropyOptions *>(lossfn_opt()) : nullptr;
+  }
+  const circle::CategoricalCrossentropyOptions *lossfn_opt_as_CategoricalCrossentropyOptions() const {
+    return lossfn_opt_type() == circle::LossFnOptions_CategoricalCrossentropyOptions ? static_cast<const circle::CategoricalCrossentropyOptions *>(lossfn_opt()) : nullptr;
+  }
+  const circle::MeanSquaredErrorOptions *lossfn_opt_as_MeanSquaredErrorOptions() const {
+    return lossfn_opt_type() == circle::LossFnOptions_MeanSquaredErrorOptions ? static_cast<const circle::MeanSquaredErrorOptions *>(lossfn_opt()) : nullptr;
+  }
+  int32_t epochs() const {
+    return GetField<int32_t>(VT_EPOCHS, 0);
+  }
+  int32_t batch_size() const {
+    return GetField<int32_t>(VT_BATCH_SIZE, 0);
+  }
+  circle::LossReductionType loss_reduction_type() const {
+    return static_cast<circle::LossReductionType>(GetField<int8_t>(VT_LOSS_REDUCTION_TYPE, 0));
+  }
+  const flatbuffers::Vector<int32_t> *trainable_ops() const {
+    return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_TRAINABLE_OPS);
+  }
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           VerifyField<uint32_t>(verifier, VT_VERSION) &&
+           VerifyField<int8_t>(verifier, VT_OPTIMIZER) &&
+           VerifyField<uint8_t>(verifier, VT_OPTIMIZER_OPT_TYPE) &&
+           VerifyOffset(verifier, VT_OPTIMIZER_OPT) &&
+           VerifyOptimizerOptions(verifier, optimizer_opt(), optimizer_opt_type()) &&
+           VerifyField<int8_t>(verifier, VT_LOSSFN) &&
+           VerifyField<uint8_t>(verifier, VT_LOSSFN_OPT_TYPE) &&
+           VerifyOffset(verifier, VT_LOSSFN_OPT) &&
+           VerifyLossFnOptions(verifier, lossfn_opt(), lossfn_opt_type()) &&
+           VerifyField<int32_t>(verifier, VT_EPOCHS) &&
+           VerifyField<int32_t>(verifier, VT_BATCH_SIZE) &&
+           VerifyField<int8_t>(verifier, VT_LOSS_REDUCTION_TYPE) &&
+           VerifyOffset(verifier, VT_TRAINABLE_OPS) &&
+           verifier.VerifyVector(trainable_ops()) &&
+           verifier.EndTable();
+  }
+  ModelTrainingT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(ModelTrainingT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static flatbuffers::Offset<ModelTraining> Pack(flatbuffers::FlatBufferBuilder &_fbb, const ModelTrainingT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+template<> inline const circle::SGDOptions *ModelTraining::optimizer_opt_as<circle::SGDOptions>() const {
+  return optimizer_opt_as_SGDOptions();
+}
+
+template<> inline const circle::AdamOptions *ModelTraining::optimizer_opt_as<circle::AdamOptions>() const {
+  return optimizer_opt_as_AdamOptions();
+}
+
+template<> inline const circle::SparseCategoricalCrossentropyOptions *ModelTraining::lossfn_opt_as<circle::SparseCategoricalCrossentropyOptions>() const {
+  return lossfn_opt_as_SparseCategoricalCrossentropyOptions();
+}
+
+template<> inline const circle::CategoricalCrossentropyOptions *ModelTraining::lossfn_opt_as<circle::CategoricalCrossentropyOptions>() const {
+  return lossfn_opt_as_CategoricalCrossentropyOptions();
+}
+
+template<> inline const circle::MeanSquaredErrorOptions *ModelTraining::lossfn_opt_as<circle::MeanSquaredErrorOptions>() const {
+  return lossfn_opt_as_MeanSquaredErrorOptions();
+}
+
+struct ModelTrainingBuilder {
+  typedef ModelTraining Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  void add_version(uint32_t version) {
+    fbb_.AddElement<uint32_t>(ModelTraining::VT_VERSION, version, 0);
+  }
+  void add_optimizer(circle::Optimizer optimizer) {
+    fbb_.AddElement<int8_t>(ModelTraining::VT_OPTIMIZER, static_cast<int8_t>(optimizer), 0);
+  }
+  void add_optimizer_opt_type(circle::OptimizerOptions optimizer_opt_type) {
+    fbb_.AddElement<uint8_t>(ModelTraining::VT_OPTIMIZER_OPT_TYPE, static_cast<uint8_t>(optimizer_opt_type), 0);
+  }
+  void add_optimizer_opt(flatbuffers::Offset<void> optimizer_opt) {
+    fbb_.AddOffset(ModelTraining::VT_OPTIMIZER_OPT, optimizer_opt);
+  }
+  void add_lossfn(circle::LossFn lossfn) {
+    fbb_.AddElement<int8_t>(ModelTraining::VT_LOSSFN, static_cast<int8_t>(lossfn), 0);
+  }
+  void add_lossfn_opt_type(circle::LossFnOptions lossfn_opt_type) {
+    fbb_.AddElement<uint8_t>(ModelTraining::VT_LOSSFN_OPT_TYPE, static_cast<uint8_t>(lossfn_opt_type), 0);
+  }
+  void add_lossfn_opt(flatbuffers::Offset<void> lossfn_opt) {
+    fbb_.AddOffset(ModelTraining::VT_LOSSFN_OPT, lossfn_opt);
+  }
+  void add_epochs(int32_t epochs) {
+    fbb_.AddElement<int32_t>(ModelTraining::VT_EPOCHS, epochs, 0);
+  }
+  void add_batch_size(int32_t batch_size) {
+    fbb_.AddElement<int32_t>(ModelTraining::VT_BATCH_SIZE, batch_size, 0);
+  }
+  void add_loss_reduction_type(circle::LossReductionType loss_reduction_type) {
+    fbb_.AddElement<int8_t>(ModelTraining::VT_LOSS_REDUCTION_TYPE, static_cast<int8_t>(loss_reduction_type), 0);
+  }
+  void add_trainable_ops(flatbuffers::Offset<flatbuffers::Vector<int32_t>> trainable_ops) {
+    fbb_.AddOffset(ModelTraining::VT_TRAINABLE_OPS, trainable_ops);
+  }
+  explicit ModelTrainingBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+        : fbb_(_fbb) {
+    start_ = fbb_.StartTable();
+  }
+  flatbuffers::Offset<ModelTraining> Finish() {
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<ModelTraining>(end);
+    return o;
+  }
+};
+
+inline flatbuffers::Offset<ModelTraining> CreateModelTraining(
+    flatbuffers::FlatBufferBuilder &_fbb,
+    uint32_t version = 0,
+    circle::Optimizer optimizer = circle::Optimizer_SGD,
+    circle::OptimizerOptions optimizer_opt_type = circle::OptimizerOptions_NONE,
+    flatbuffers::Offset<void> optimizer_opt = 0,
+    circle::LossFn lossfn = circle::LossFn_SPARSE_CATEGORICAL_CROSSENTROPY,
+    circle::LossFnOptions lossfn_opt_type = circle::LossFnOptions_NONE,
+    flatbuffers::Offset<void> lossfn_opt = 0,
+    int32_t epochs = 0,
+    int32_t batch_size = 0,
+    circle::LossReductionType loss_reduction_type = circle::LossReductionType_SumOverBatchSize,
+    flatbuffers::Offset<flatbuffers::Vector<int32_t>> trainable_ops = 0) {
+  ModelTrainingBuilder builder_(_fbb);
+  builder_.add_trainable_ops(trainable_ops);
+  builder_.add_batch_size(batch_size);
+  builder_.add_epochs(epochs);
+  builder_.add_lossfn_opt(lossfn_opt);
+  builder_.add_optimizer_opt(optimizer_opt);
+  builder_.add_version(version);
+  builder_.add_loss_reduction_type(loss_reduction_type);
+  builder_.add_lossfn_opt_type(lossfn_opt_type);
+  builder_.add_lossfn(lossfn);
+  builder_.add_optimizer_opt_type(optimizer_opt_type);
+  builder_.add_optimizer(optimizer);
+  return builder_.Finish();
+}
+
+inline flatbuffers::Offset<ModelTraining> CreateModelTrainingDirect(
+    flatbuffers::FlatBufferBuilder &_fbb,
+    uint32_t version = 0,
+    circle::Optimizer optimizer = circle::Optimizer_SGD,
+    circle::OptimizerOptions optimizer_opt_type = circle::OptimizerOptions_NONE,
+    flatbuffers::Offset<void> optimizer_opt = 0,
+    circle::LossFn lossfn = circle::LossFn_SPARSE_CATEGORICAL_CROSSENTROPY,
+    circle::LossFnOptions lossfn_opt_type = circle::LossFnOptions_NONE,
+    flatbuffers::Offset<void> lossfn_opt = 0,
+    int32_t epochs = 0,
+    int32_t batch_size = 0,
+    circle::LossReductionType loss_reduction_type = circle::LossReductionType_SumOverBatchSize,
+    const std::vector<int32_t> *trainable_ops = nullptr) {
+  auto trainable_ops__ = trainable_ops ? _fbb.CreateVector<int32_t>(*trainable_ops) : 0;
+  return circle::CreateModelTraining(
+      _fbb,
+      version,
+      optimizer,
+      optimizer_opt_type,
+      optimizer_opt,
+      lossfn,
+      lossfn_opt_type,
+      lossfn_opt,
+      epochs,
+      batch_size,
+      loss_reduction_type,
+      trainable_ops__);
+}
+
+flatbuffers::Offset<ModelTraining> CreateModelTraining(flatbuffers::FlatBufferBuilder &_fbb, const ModelTrainingT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+inline SGDOptionsT *SGDOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
+  auto _o = std::unique_ptr<SGDOptionsT>(new SGDOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void SGDOptions::UnPackTo(SGDOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const {
+  (void)_o;
+  (void)_resolver;
+  { auto _e = learning_rate(); _o->learning_rate = _e; }
+}
+
+inline flatbuffers::Offset<SGDOptions> SGDOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SGDOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
+  return CreateSGDOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SGDOptions> CreateSGDOptions(flatbuffers::FlatBufferBuilder &_fbb, const SGDOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SGDOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
+  auto _learning_rate = _o->learning_rate;
+  return circle::CreateSGDOptions(
+      _fbb,
+      _learning_rate);
+}
+
+inline AdamOptionsT *AdamOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
+  auto _o = std::unique_ptr<AdamOptionsT>(new AdamOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void AdamOptions::UnPackTo(AdamOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const {
+  (void)_o;
+  (void)_resolver;
+  { auto _e = learning_rate(); _o->learning_rate = _e; }
+  { auto _e = beta_1(); _o->beta_1 = _e; }
+  { auto _e = beta_2(); _o->beta_2 = _e; }
+  { auto _e = epsilon(); _o->epsilon = _e; }
+}
+
+inline flatbuffers::Offset<AdamOptions> AdamOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AdamOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
+  return CreateAdamOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<AdamOptions> CreateAdamOptions(flatbuffers::FlatBufferBuilder &_fbb, const AdamOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const AdamOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
+  auto _learning_rate = _o->learning_rate;
+  auto _beta_1 = _o->beta_1;
+  auto _beta_2 = _o->beta_2;
+  auto _epsilon = _o->epsilon;
+  return circle::CreateAdamOptions(
+      _fbb,
+      _learning_rate,
+      _beta_1,
+      _beta_2,
+      _epsilon);
+}
+
+inline SparseCategoricalCrossentropyOptionsT *SparseCategoricalCrossentropyOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
+  auto _o = std::unique_ptr<SparseCategoricalCrossentropyOptionsT>(new SparseCategoricalCrossentropyOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void SparseCategoricalCrossentropyOptions::UnPackTo(SparseCategoricalCrossentropyOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const {
+  (void)_o;
+  (void)_resolver;
+  { auto _e = from_logits(); _o->from_logits = _e; }
+}
+
+inline flatbuffers::Offset<SparseCategoricalCrossentropyOptions> SparseCategoricalCrossentropyOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SparseCategoricalCrossentropyOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
+  return CreateSparseCategoricalCrossentropyOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<SparseCategoricalCrossentropyOptions> CreateSparseCategoricalCrossentropyOptions(flatbuffers::FlatBufferBuilder &_fbb, const SparseCategoricalCrossentropyOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SparseCategoricalCrossentropyOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
+  auto _from_logits = _o->from_logits;
+  return circle::CreateSparseCategoricalCrossentropyOptions(
+      _fbb,
+      _from_logits);
+}
+
+inline CategoricalCrossentropyOptionsT *CategoricalCrossentropyOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
+  auto _o = std::unique_ptr<CategoricalCrossentropyOptionsT>(new CategoricalCrossentropyOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void CategoricalCrossentropyOptions::UnPackTo(CategoricalCrossentropyOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const {
+  (void)_o;
+  (void)_resolver;
+  { auto _e = from_logits(); _o->from_logits = _e; }
+}
+
+inline flatbuffers::Offset<CategoricalCrossentropyOptions> CategoricalCrossentropyOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const CategoricalCrossentropyOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
+  return CreateCategoricalCrossentropyOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<CategoricalCrossentropyOptions> CreateCategoricalCrossentropyOptions(flatbuffers::FlatBufferBuilder &_fbb, const CategoricalCrossentropyOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const CategoricalCrossentropyOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
+  auto _from_logits = _o->from_logits;
+  return circle::CreateCategoricalCrossentropyOptions(
+      _fbb,
+      _from_logits);
+}
+
+inline MeanSquaredErrorOptionsT *MeanSquaredErrorOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
+  auto _o = std::unique_ptr<MeanSquaredErrorOptionsT>(new MeanSquaredErrorOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void MeanSquaredErrorOptions::UnPackTo(MeanSquaredErrorOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const {
+  (void)_o;
+  (void)_resolver;
+}
+
+inline flatbuffers::Offset<MeanSquaredErrorOptions> MeanSquaredErrorOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MeanSquaredErrorOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
+  return CreateMeanSquaredErrorOptions(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<MeanSquaredErrorOptions> CreateMeanSquaredErrorOptions(flatbuffers::FlatBufferBuilder &_fbb, const MeanSquaredErrorOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MeanSquaredErrorOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
+  return circle::CreateMeanSquaredErrorOptions(
+      _fbb);
+}
+
+inline ModelTrainingT *ModelTraining::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
+  auto _o = std::unique_ptr<ModelTrainingT>(new ModelTrainingT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void ModelTraining::UnPackTo(ModelTrainingT *_o, const flatbuffers::resolver_function_t *_resolver) const {
+  (void)_o;
+  (void)_resolver;
+  { auto _e = version(); _o->version = _e; }
+  { auto _e = optimizer(); _o->optimizer = _e; }
+  { auto _e = optimizer_opt_type(); _o->optimizer_opt.type = _e; }
+  { auto _e = optimizer_opt(); if (_e) _o->optimizer_opt.value = circle::OptimizerOptionsUnion::UnPack(_e, optimizer_opt_type(), _resolver); }
+  { auto _e = lossfn(); _o->lossfn = _e; }
+  { auto _e = lossfn_opt_type(); _o->lossfn_opt.type = _e; }
+  { auto _e = lossfn_opt(); if (_e) _o->lossfn_opt.value = circle::LossFnOptionsUnion::UnPack(_e, lossfn_opt_type(), _resolver); }
+  { auto _e = epochs(); _o->epochs = _e; }
+  { auto _e = batch_size(); _o->batch_size = _e; }
+  { auto _e = loss_reduction_type(); _o->loss_reduction_type = _e; }
+  { auto _e = trainable_ops(); if (_e) { _o->trainable_ops.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->trainable_ops[_i] = _e->Get(_i); } } }
+}
+
+inline flatbuffers::Offset<ModelTraining> ModelTraining::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ModelTrainingT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
+  return CreateModelTraining(_fbb, _o, _rehasher);
+}
+
+inline flatbuffers::Offset<ModelTraining> CreateModelTraining(flatbuffers::FlatBufferBuilder &_fbb, const ModelTrainingT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ModelTrainingT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
+  auto _version = _o->version;
+  auto _optimizer = _o->optimizer;
+  auto _optimizer_opt_type = _o->optimizer_opt.type;
+  auto _optimizer_opt = _o->optimizer_opt.Pack(_fbb);
+  auto _lossfn = _o->lossfn;
+  auto _lossfn_opt_type = _o->lossfn_opt.type;
+  auto _lossfn_opt = _o->lossfn_opt.Pack(_fbb);
+  auto _epochs = _o->epochs;
+  auto _batch_size = _o->batch_size;
+  auto _loss_reduction_type = _o->loss_reduction_type;
+  auto _trainable_ops = _o->trainable_ops.size() ? _fbb.CreateVector(_o->trainable_ops) : 0;
+  return circle::CreateModelTraining(
+      _fbb,
+      _version,
+      _optimizer,
+      _optimizer_opt_type,
+      _optimizer_opt,
+      _lossfn,
+      _lossfn_opt_type,
+      _lossfn_opt,
+      _epochs,
+      _batch_size,
+      _loss_reduction_type,
+      _trainable_ops);
+}
+
+inline bool VerifyOptimizerOptions(flatbuffers::Verifier &verifier, const void *obj, OptimizerOptions type) {
+  switch (type) {
+    case OptimizerOptions_NONE: {
+      return true;
+    }
+    case OptimizerOptions_SGDOptions: {
+      auto ptr = reinterpret_cast<const circle::SGDOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case OptimizerOptions_AdamOptions: {
+      auto ptr = reinterpret_cast<const circle::AdamOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    default: return true;
+  }
+}
+
+inline bool VerifyOptimizerOptionsVector(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 (!VerifyOptimizerOptions(
+        verifier,  values->Get(i), types->GetEnum<OptimizerOptions>(i))) {
+      return false;
+    }
+  }
+  return true;
+}
+
+inline void *OptimizerOptionsUnion::UnPack(const void *obj, OptimizerOptions type, const flatbuffers::resolver_function_t *resolver) {
+  switch (type) {
+    case OptimizerOptions_SGDOptions: {
+      auto ptr = reinterpret_cast<const circle::SGDOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case OptimizerOptions_AdamOptions: {
+      auto ptr = reinterpret_cast<const circle::AdamOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    default: return nullptr;
+  }
+}
+
+inline flatbuffers::Offset<void> OptimizerOptionsUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const {
+  switch (type) {
+    case OptimizerOptions_SGDOptions: {
+      auto ptr = reinterpret_cast<const circle::SGDOptionsT *>(value);
+      return CreateSGDOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case OptimizerOptions_AdamOptions: {
+      auto ptr = reinterpret_cast<const circle::AdamOptionsT *>(value);
+      return CreateAdamOptions(_fbb, ptr, _rehasher).Union();
+    }
+    default: return 0;
+  }
+}
+
+inline OptimizerOptionsUnion::OptimizerOptionsUnion(const OptimizerOptionsUnion &u) : type(u.type), value(nullptr) {
+  switch (type) {
+    case OptimizerOptions_SGDOptions: {
+      value = new circle::SGDOptionsT(*reinterpret_cast<circle::SGDOptionsT *>(u.value));
+      break;
+    }
+    case OptimizerOptions_AdamOptions: {
+      value = new circle::AdamOptionsT(*reinterpret_cast<circle::AdamOptionsT *>(u.value));
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+inline void OptimizerOptionsUnion::Reset() {
+  switch (type) {
+    case OptimizerOptions_SGDOptions: {
+      auto ptr = reinterpret_cast<circle::SGDOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case OptimizerOptions_AdamOptions: {
+      auto ptr = reinterpret_cast<circle::AdamOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    default: break;
+  }
+  value = nullptr;
+  type = OptimizerOptions_NONE;
+}
+
+inline bool VerifyLossFnOptions(flatbuffers::Verifier &verifier, const void *obj, LossFnOptions type) {
+  switch (type) {
+    case LossFnOptions_NONE: {
+      return true;
+    }
+    case LossFnOptions_SparseCategoricalCrossentropyOptions: {
+      auto ptr = reinterpret_cast<const circle::SparseCategoricalCrossentropyOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case LossFnOptions_CategoricalCrossentropyOptions: {
+      auto ptr = reinterpret_cast<const circle::CategoricalCrossentropyOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case LossFnOptions_MeanSquaredErrorOptions: {
+      auto ptr = reinterpret_cast<const circle::MeanSquaredErrorOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    default: return true;
+  }
+}
+
+inline bool VerifyLossFnOptionsVector(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 (!VerifyLossFnOptions(
+        verifier,  values->Get(i), types->GetEnum<LossFnOptions>(i))) {
+      return false;
+    }
+  }
+  return true;
+}
+
+inline void *LossFnOptionsUnion::UnPack(const void *obj, LossFnOptions type, const flatbuffers::resolver_function_t *resolver) {
+  switch (type) {
+    case LossFnOptions_SparseCategoricalCrossentropyOptions: {
+      auto ptr = reinterpret_cast<const circle::SparseCategoricalCrossentropyOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case LossFnOptions_CategoricalCrossentropyOptions: {
+      auto ptr = reinterpret_cast<const circle::CategoricalCrossentropyOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case LossFnOptions_MeanSquaredErrorOptions: {
+      auto ptr = reinterpret_cast<const circle::MeanSquaredErrorOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    default: return nullptr;
+  }
+}
+
+inline flatbuffers::Offset<void> LossFnOptionsUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const {
+  switch (type) {
+    case LossFnOptions_SparseCategoricalCrossentropyOptions: {
+      auto ptr = reinterpret_cast<const circle::SparseCategoricalCrossentropyOptionsT *>(value);
+      return CreateSparseCategoricalCrossentropyOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case LossFnOptions_CategoricalCrossentropyOptions: {
+      auto ptr = reinterpret_cast<const circle::CategoricalCrossentropyOptionsT *>(value);
+      return CreateCategoricalCrossentropyOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case LossFnOptions_MeanSquaredErrorOptions: {
+      auto ptr = reinterpret_cast<const circle::MeanSquaredErrorOptionsT *>(value);
+      return CreateMeanSquaredErrorOptions(_fbb, ptr, _rehasher).Union();
+    }
+    default: return 0;
+  }
+}
+
+inline LossFnOptionsUnion::LossFnOptionsUnion(const LossFnOptionsUnion &u) : type(u.type), value(nullptr) {
+  switch (type) {
+    case LossFnOptions_SparseCategoricalCrossentropyOptions: {
+      value = new circle::SparseCategoricalCrossentropyOptionsT(*reinterpret_cast<circle::SparseCategoricalCrossentropyOptionsT *>(u.value));
+      break;
+    }
+    case LossFnOptions_CategoricalCrossentropyOptions: {
+      value = new circle::CategoricalCrossentropyOptionsT(*reinterpret_cast<circle::CategoricalCrossentropyOptionsT *>(u.value));
+      break;
+    }
+    case LossFnOptions_MeanSquaredErrorOptions: {
+      value = new circle::MeanSquaredErrorOptionsT(*reinterpret_cast<circle::MeanSquaredErrorOptionsT *>(u.value));
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+inline void LossFnOptionsUnion::Reset() {
+  switch (type) {
+    case LossFnOptions_SparseCategoricalCrossentropyOptions: {
+      auto ptr = reinterpret_cast<circle::SparseCategoricalCrossentropyOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case LossFnOptions_CategoricalCrossentropyOptions: {
+      auto ptr = reinterpret_cast<circle::CategoricalCrossentropyOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case LossFnOptions_MeanSquaredErrorOptions: {
+      auto ptr = reinterpret_cast<circle::MeanSquaredErrorOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    default: break;
+  }
+  value = nullptr;
+  type = LossFnOptions_NONE;
+}
+
+inline const circle::ModelTraining *GetModelTraining(const void *buf) {
+  return flatbuffers::GetRoot<circle::ModelTraining>(buf);
+}
+
+inline const circle::ModelTraining *GetSizePrefixedModelTraining(const void *buf) {
+  return flatbuffers::GetSizePrefixedRoot<circle::ModelTraining>(buf);
+}
+
+inline const char *ModelTrainingIdentifier() {
+  return "CTR0";
+}
+
+inline bool ModelTrainingBufferHasIdentifier(const void *buf) {
+  return flatbuffers::BufferHasIdentifier(
+      buf, ModelTrainingIdentifier());
+}
+
+inline bool VerifyModelTrainingBuffer(
+    flatbuffers::Verifier &verifier) {
+  return verifier.VerifyBuffer<circle::ModelTraining>(ModelTrainingIdentifier());
+}
+
+inline bool VerifySizePrefixedModelTrainingBuffer(
+    flatbuffers::Verifier &verifier) {
+  return verifier.VerifySizePrefixedBuffer<circle::ModelTraining>(ModelTrainingIdentifier());
+}
+
+inline const char *ModelTrainingExtension() {
+  return "circletr";
+}
+
+inline void FinishModelTrainingBuffer(
+    flatbuffers::FlatBufferBuilder &fbb,
+    flatbuffers::Offset<circle::ModelTraining> root) {
+  fbb.Finish(root, ModelTrainingIdentifier());
+}
+
+inline void FinishSizePrefixedModelTrainingBuffer(
+    flatbuffers::FlatBufferBuilder &fbb,
+    flatbuffers::Offset<circle::ModelTraining> root) {
+  fbb.FinishSizePrefixed(root, ModelTrainingIdentifier());
+}
+
+inline std::unique_ptr<circle::ModelTrainingT> UnPackModelTraining(
+    const void *buf,
+    const flatbuffers::resolver_function_t *res = nullptr) {
+  return std::unique_ptr<circle::ModelTrainingT>(GetModelTraining(buf)->UnPack(res));
+}
+
+inline std::unique_ptr<circle::ModelTrainingT> UnPackSizePrefixedModelTraining(
+    const void *buf,
+    const flatbuffers::resolver_function_t *res = nullptr) {
+  return std::unique_ptr<circle::ModelTrainingT>(GetSizePrefixedModelTraining(buf)->UnPack(res));
+}
+
+}  // namespace circle
+
+#endif  // FLATBUFFERS_GENERATED_TRAININFO_CIRCLE_H_
index 1bdfa49..cfb865c 100644 (file)
@@ -25,6 +25,10 @@ if (DIS_FLOAT)
     add_definitions(-DDIS_FLOAT)
 endif()
 
+if (ENABLE_TRAINING)
+    add_definitions(-DENABLE_TRAINING)
+endif()
+
 add_compile_options(-fno-exceptions)
 add_compile_options(-Os)
 
index 0d29475..d2afd6e 100644 (file)
 namespace luci_interpreter
 {
 
+#ifdef ENABLE_TRAINING
+namespace training
+{
+class TrainingOnertMicro;
+} // namespace training
+
+#endif // ENABLE_TRAINING
+
 class Interpreter
 {
 public:
@@ -45,7 +53,8 @@ public:
 
   ~Interpreter();
 
-  void allocateAndWriteInputTensor(int32_t input_tensor_index, const void *data, size_t data_size);
+  void allocateAndWriteInputTensor(int32_t input_tensor_index, const uint8_t *data,
+                                   size_t data_size);
   uint8_t *allocateInputTensor(int32_t input_tensor_index);
 
   uint8_t *readOutputTensor(int32_t output_tensor_index);
@@ -55,6 +64,10 @@ public:
 
   void interpret();
 
+#ifdef ENABLE_TRAINING
+  friend class training::TrainingOnertMicro;
+#endif // ENABLE_TRAINING
+
 private:
   // _default_memory_manager should be before _runtime_module due to
   // the order of deletion in the destructor
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/TrainableWeightStorage.h b/onert-micro/luci-interpreter/include/luci_interpreter/TrainableWeightStorage.h
new file mode 100644 (file)
index 0000000..9b4bd79
--- /dev/null
@@ -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.
+ */
+
+#ifdef ENABLE_TRAINING
+
+#ifndef LUCI_INTERPRETER_CORE_TRAINABLE_WEIGHT_STORAGE_H
+#define LUCI_INTERPRETER_CORE_TRAINABLE_WEIGHT_STORAGE_H
+
+#include "luci_interpreter/TrainingSettings.h"
+#include "luci_interpreter/core/reader/CircleMicroReader.h"
+#include "memory_managers/SimpleMemoryManager.h"
+
+#include <unordered_map>
+
+namespace luci_interpreter
+{
+namespace training
+{
+
+class TrainableWeightStorage
+{
+public:
+  TrainableWeightStorage() = default;
+
+public:
+  Status getTrainWeightDataByTensor(const circle::Tensor *tensor, uint8_t **result_data);
+
+  Status clearAllTrainableWeights();
+
+  training::Status fillTrainableWeightsStorage(const CircleReader *reader,
+                                               SimpleMemoryManager *memory_manager,
+                                               uint32_t number_of_last_trainable_layers);
+
+private:
+  Status createTrainableWeightForTensor(const circle::Tensor *tensor,
+                                        SimpleMemoryManager *memoryManager,
+                                        const uint8_t *const_data);
+
+private:
+  std::unordered_map<const circle::Tensor *, uint8_t *> _tensor_to_data;
+};
+
+} // namespace training
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_CORE_TRAINABLE_WEIGHT_STORAGE_H
+
+#endif // ENABLE_TRAINING
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/TrainingOnertMicro.h b/onert-micro/luci-interpreter/include/luci_interpreter/TrainingOnertMicro.h
new file mode 100644 (file)
index 0000000..f1ca776
--- /dev/null
@@ -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.
+ */
+
+#ifdef ENABLE_TRAINING
+
+#ifndef LUCI_INTERPRETER_TRAINING_ONERT_MICRO_H
+#define LUCI_INTERPRETER_TRAINING_ONERT_MICRO_H
+
+#include "luci_interpreter/TrainingSettings.h"
+#include "luci_interpreter/Interpreter.h"
+#include "core/TrainingModule.h"
+
+namespace luci_interpreter
+{
+namespace training
+{
+
+class TrainingOnertMicro
+{
+public:
+  explicit TrainingOnertMicro(Interpreter *interpreter, TrainingSettings &settings);
+
+  ~TrainingOnertMicro();
+
+  Status enableTrainingMode();
+
+  Status disableTrainingMode(bool resetWeights = false);
+
+  Status train(uint32_t number_of_train_samples, const uint8_t *train_data,
+               const uint8_t *label_train_data);
+
+  Status test(uint32_t number_of_train_samples, const uint8_t *test_data,
+              const uint8_t *label_test_data, void *metric_value_result);
+
+private:
+  Interpreter *_interpreter;
+
+  TrainingSettings &_settings;
+
+  TrainingModule _module;
+
+  bool _is_training_mode;
+};
+
+} // namespace training
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TRAINING_ONERT_MICRO_H
+
+#endif // ENABLE_TRAINING
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h
new file mode 100644 (file)
index 0000000..464fa29
--- /dev/null
@@ -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_FLOAT_BATCH_TO_SPACE_ND_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_BATCH_TO_SPACE_ND_KERNEL_H
+
+#include "TestDataBatchToSpaceNDBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace batch_to_space_nd_float
+{
+/*
+ * BatchToSpaceND Kernel:
+ *
+ *      Input(4, 1, 1, 1)
+ *            |
+ *       BatchToSpaceND
+ *            |
+ *      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,
+  0x68, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 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, 0x18, 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, 0x02, 0x00, 0x00, 0x00, 0x01, 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, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x68,
+  0x61, 0x70, 0x65, 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,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x63, 0x72, 0x6f, 0x70, 0x73, 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, 0x04, 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, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 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 = {13.344007, 88.19333, -0.350749, 45.71498};
+const std::vector<float> reference_output_data = {13.344007, 88.19333, -0.350749, 45.71498};
+
+} // namespace batch_to_space_nd_float
+
+class TestDataFloatBatchToSpaceND : public TestDataBatchToSpaceNDBase<float>
+{
+public:
+  TestDataFloatBatchToSpaceND()
+  {
+    _input_data = batch_to_space_nd_float::input_data;
+    _reference_output_data = batch_to_space_nd_float::reference_output_data;
+    _test_kernel_model_circle = batch_to_space_nd_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatBatchToSpaceND() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_BATCH_TO_SPACE_ND_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h
new file mode 100644 (file)
index 0000000..fcbc36d
--- /dev/null
@@ -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_BATCH_TO_SPACE_ND_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_BATCH_TO_SPACE_ND_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_batch_to_space_nd_kernel
+{
+/*
+ * BatchToSpaceND kernel with input output type mismatch:
+ *
+ *      Input(4, 1, 1, 1) - Float32
+ *            |
+ *        BatchToSpaceND
+ *            |
+ *      Output(1, 2, 2 , 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,
+  0x68, 0x00, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 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, 0x18, 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, 0x02, 0x00, 0x00, 0x00, 0x01, 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, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x6f, 0x63,
+  0x6b, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 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, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x63, 0x72, 0x6f, 0x70, 0x73, 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,
+  0x04, 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, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25,
+  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_batch_to_space_nd_kernel
+
+class NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_batch_to_space_nd_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel() 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_BATCH_TO_SPACE_ND_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/TestDataBatchToSpaceNDBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/batch_to_space_nd/TestDataBatchToSpaceNDBase.h
new file mode 100644 (file)
index 0000000..c7689b6
--- /dev/null
@@ -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_BATCH_TO_SPACE_ND_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_BATCH_TO_SPACE_ND_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataBatchToSpaceNDBase : public TestDataBase<T>
+{
+public:
+  TestDataBatchToSpaceNDBase() = 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_BATCH_TO_SPACE_ND_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/broadcast_to/FloatBroadcastToKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/broadcast_to/FloatBroadcastToKernel.h
new file mode 100644 (file)
index 0000000..dbe05a6
--- /dev/null
@@ -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_FLOAT_BROADCAST_TO_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_BROADCAST_TO_KERNEL_H
+
+#include "TestDataBroadcastToBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace broadcast_to_float
+{
+/*
+ * BroadcastTo Kernel:
+ *
+ *      Input(2, 3)
+ *            |
+ *         BroadcastTo
+ *            |
+ *      Output(1, 2, 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,
+  0x50, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x3c, 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, 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, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x54, 0x00, 0x54, 0x69, 0x64, 0x78, 0x00, 0x02,
+  0x08, 0x07, 0x02, 0x01, 0x02, 0x00, 0x02, 0x04, 0x04, 0x04, 0x24, 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, 0x7c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x9c, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x62, 0x63, 0x5f, 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 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,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x62, 0x63, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 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, 0x14, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x62, 0x63, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+  0x0b, 0x00, 0x00, 0x00, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x54, 0x6f, 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> input_data = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
+
+const std::vector<float> reference_output_data = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
+
+} // namespace broadcast_to_float
+
+class TestDataFloatBroadcastTo : public TestDataBroadcastToBase<float>
+{
+public:
+  TestDataFloatBroadcastTo()
+  {
+    _input_data = broadcast_to_float::input_data;
+    _reference_output_data = broadcast_to_float::reference_output_data;
+    _test_kernel_model_circle = broadcast_to_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatBroadcastTo() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_BROADCAST_TO_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/broadcast_to/NegBroadcastToKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/broadcast_to/NegBroadcastToKernel.h
new file mode 100644 (file)
index 0000000..9ee513f
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_BROADCAST_TO_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_BROADCAST_TO_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_broadcast_to_kernel
+{
+/*
+ * BroadcastTo Kernel with input output type mismatch:
+ *
+ *      Input(2, 3) - Float32
+ *            |
+ *           BroadcastTo
+ *            |
+ *      Output(1, 2, 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,
+  0x50, 0x00, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0xcc, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x3c, 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, 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, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x54, 0x00, 0x54, 0x69, 0x64, 0x78, 0x00, 0x02,
+  0x08, 0x07, 0x02, 0x01, 0x02, 0x00, 0x02, 0x04, 0x04, 0x04, 0x24, 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, 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,
+  0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x62, 0x63, 0x5f, 0x6f, 0x66, 0x6d, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x01, 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, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x62, 0x63, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 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,
+  0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x62, 0x63, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x20, 0x0b, 0x00, 0x00, 0x00, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73,
+  0x74, 0x54, 0x6f, 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_input_output_type_mismatch_broadcast_to_kernel
+
+class NegTestDataInputOutputTypeMismatchBroadcastToKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchBroadcastToKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_broadcast_to_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchBroadcastToKernel() 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_BROADCAST_TO_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/broadcast_to/TestDataBroadcastToBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/broadcast_to/TestDataBroadcastToBase.h
new file mode 100644 (file)
index 0000000..dcdc5be
--- /dev/null
@@ -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_BROADCAST_TO_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_BROADCAST_TO_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataBroadcastToBase : public TestDataBase<T>
+{
+public:
+  TestDataBroadcastToBase() = 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_BROADCAST_TO_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cast/FloatCastKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cast/FloatCastKernel.h
new file mode 100644 (file)
index 0000000..e1d4085
--- /dev/null
@@ -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_CAST_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_CAST_KERNEL_H
+
+#include "TestDataCastBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace cast_float
+{
+/*
+ * Cast Kernel:
+ *
+ *      Input(1, 3, 3, 2) - Float
+ *            |
+ *          Cast
+ *            |
+ *      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, 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, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x08, 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, 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, 0x35, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x35, 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.791723, -85.53769, 37.783722, -90.81935, 17.43155,
+                                       44.95357,   51.40224,  90.3479,   23.142117, -31.959887,
+                                       -1.5401196, -64.85761, 53.559418, -52.90431, 25.37937,
+                                       -71.28326,  -63.8249,  -5.807645};
+
+const std::vector<int32_t> reference_output_data = {-17, -85, 37,  -90, 17,  44, 51,  90,  23,
+                                                    -31, -1,  -64, 53,  -52, 25, -71, -63, -5};
+
+} // namespace cast_float
+
+class TestDataFloatCast : public TestDataCastBase<float, int32_t>
+{
+public:
+  TestDataFloatCast()
+  {
+    _input_data = cast_float::input_data;
+    _reference_output_data = cast_float::reference_output_data;
+    _test_kernel_model_circle = cast_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatCast() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_CAST_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cast/NegCastKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cast/NegCastKernel.h
new file mode 100644 (file)
index 0000000..b45f086
--- /dev/null
@@ -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_TEST_MODELS_NEG_CAST_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_CAST_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_shape_mismatch_cast_kernel
+{
+/*
+ * Cast Kernel with input output shape mismatch:
+ *
+ *      Input(1, 1, 3, 3, 2) - Float32
+ *            |
+ *           Cast
+ *            |
+ *      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, 0x44, 0x01, 0x00, 0x00, 0x60, 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, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x08, 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, 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,
+  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,
+  0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 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_shape_mismatch_cast_kernel
+
+class NegTestDataInputOutputShapeMismatchCeilKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputShapeMismatchCeilKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_shape_mismatch_cast_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputShapeMismatchCeilKernel() 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_CAST_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cast/TestDataCastBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cast/TestDataCastBase.h
new file mode 100644 (file)
index 0000000..42e2a9e
--- /dev/null
@@ -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_CAST_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_CAST_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename U> class TestDataCastBase : public TestDataBase<T, U>
+{
+public:
+  TestDataCastBase() = 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_CAST_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/ceil/FloatCeilKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/ceil/FloatCeilKernel.h
new file mode 100644 (file)
index 0000000..4bde012
--- /dev/null
@@ -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_FLOAT_CEIL_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_CEIL_KERNEL_H
+
+#include "TestDataCeilBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace ceil_float
+{
+/*
+ * Ceil Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Ceil
+ *            |
+ *      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, 0x04, 0x01, 0x00, 0x00, 0x20, 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, 0x38, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xdc, 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,
+  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,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x02, 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,
+  0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 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 = {-42.36898,  89.1144,  -21.332403,
+                                       -7.6364737, 31.91192, 77.05993};
+
+const std::vector<float> reference_output_data = {-42.0, 90.0, -21.0, -7.0, 32.0, 78.0};
+
+} // namespace ceil_float
+
+class TestDataFloatCeil : public TestDataCeilBase<float>
+{
+public:
+  TestDataFloatCeil()
+  {
+    _input_data = ceil_float::input_data;
+    _reference_output_data = ceil_float::reference_output_data;
+    _test_kernel_model_circle = ceil_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatCeil() 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/ceil/NegCeilKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/ceil/NegCeilKernel.h
new file mode 100644 (file)
index 0000000..72e0591
--- /dev/null
@@ -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_CEIL_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_CEIL_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_ceil_kernel
+{
+/*
+ * Ceil Kernel with input output type mismatch:
+ *
+ *      Input(2, 3) - Float32
+ *            |
+ *           Ceil
+ *            |
+ *      Output(2, 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,
+  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, 0x48, 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, 0x02, 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,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x02, 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,
+  0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 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_ceil_kernel
+
+class NegTestDataInputOutputTypeMismatchCeilKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchCeilKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_ceil_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchCeilKernel() 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_CEIL_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/ceil/TestDataCeilBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/ceil/TestDataCeilBase.h
new file mode 100644 (file)
index 0000000..a63c0ed
--- /dev/null
@@ -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_CEIL_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_CEIL_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataCeilBase : public TestDataBase<T>
+{
+public:
+  TestDataCeilBase() = 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_CEIL_KERNEL_BASE_H
index 52baf89..25a1990 100644 (file)
@@ -209,15 +209,15 @@ protected:
   const unsigned char *_test_kernel_model_circle;
 };
 
-class NegTestDataInvalidInputTypeConv2DKernel : public NegTestDataBase
+class NegTestDataInvalidInputShapeConv2DKernel : public NegTestDataBase
 {
 public:
-  NegTestDataInvalidInputTypeConv2DKernel()
+  NegTestDataInvalidInputShapeConv2DKernel()
   {
-    _test_kernel_model_circle = neg_conv2d_bias_wrong_type::test_kernel_model_circle;
+    _test_kernel_model_circle = neg_conv2d_invalid_input_shape::test_kernel_model_circle;
   }
 
-  ~NegTestDataInvalidInputTypeConv2DKernel() override = default;
+  ~NegTestDataInvalidInputShapeConv2DKernel() override = default;
 
   const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
 
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cos/FloatCosKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cos/FloatCosKernel.h
new file mode 100644 (file)
index 0000000..d92290a
--- /dev/null
@@ -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_FLOAT_COS_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_COS_KERNEL_H
+
+#include "TestDataCosBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace cos_float
+{
+/*
+ * Cos Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Cos
+ *            |
+ *      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, 0x54, 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,
+  0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 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.387439727783203,  9.756175994873047,   -3.3056538105010986,
+                                       -6.788370609283447, 3.284966468811035,   8.500691413879395,
+                                       7.117439270019531,  -1.2989126443862915, -6.051342964172363,
+                                       3.2069919109344482, -5.918918609619141,  2.415487051010132,
+                                       5.600773811340332,  8.547533988952637,   3.106605052947998,
+                                       7.0716776847839355, -2.9120774269104004, -9.454291343688965};
+
+const std::vector<float> reference_output_data = {
+  -0.31926071643829346, -0.9455884099006653, -0.9865721464157104, 0.8750848174095154,
+  -0.9897395968437195,  -0.6025638580322266, 0.6717305183410645,  0.2685464024543762,
+  0.9732447266578674,   -0.9978622198104858, 0.9343852400779724,  -0.7477657794952393,
+  0.7760541439056396,   -0.639272928237915,  -0.9993879795074463, 0.7049154043197632,
+  -0.9737768173217773,  -0.999564528465271};
+
+} // namespace cos_float
+
+class TestDataFloatCos : public TestDataCosBase<float>
+{
+public:
+  TestDataFloatCos()
+  {
+    _input_data = cos_float::input_data;
+    _reference_output_data = cos_float::reference_output_data;
+    _test_kernel_model_circle = cos_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatCos() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_COS_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cos/NegCosKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cos/NegCosKernel.h
new file mode 100644 (file)
index 0000000..67c318b
--- /dev/null
@@ -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_COS_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_COS_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Cos Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Cos
+ *            |
+ *      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, 0x54, 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,
+  0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 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 NegTestDataInputOutputTypeMismatchCosKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchCosKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchCosKernel() 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_COS_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cos/TestDataCosBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/cos/TestDataCosBase.h
new file mode 100644 (file)
index 0000000..ef97520
--- /dev/null
@@ -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_COS_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_COS_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataCosBase : public TestDataBase<T>
+{
+public:
+  TestDataCosBase() = 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_COS_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depth_to_space/FloatDepthToSpaceKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depth_to_space/FloatDepthToSpaceKernel.h
new file mode 100644 (file)
index 0000000..44e43c0
--- /dev/null
@@ -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_DEPTH_TO_SPACE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_DEPTH_TO_SPACE_KERNEL_H
+
+#include "TestDataDepthToSpaceBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace depth_to_space_float
+{
+/*
+ * DepthToSpace Kernel:
+ *
+ *      Input(1, 2, 2, 4)
+ *            |
+ *       DepthToSpace
+ *            |
+ *      Output(1, 4, 4, 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, 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, 0x5e, 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, 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,
+  0x04, 0x00, 0x00, 0x00, 0x04, 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, 0x02, 0x00, 0x00, 0x00, 0x02, 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, 0x05, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x05, 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 = {
+  -88.77164,  8.495978,  -2.749088, 73.70849, -68.09995, 67.459724, -14.851314, 25.076237,
+  -31.075678, 50.127613, 72.91088,  18.95467, 39.1749,   -40.51118, 20.050987,  -9.049585};
+const std::vector<float> reference_output_data = {
+  -88.77164,  8.495978,  -68.09995, 67.459724, -2.749088, 73.70849, -14.851314, 25.076237,
+  -31.075678, 50.127613, 39.1749,   -40.51118, 72.91088,  18.95467, 20.050987,  -9.049585};
+
+} // namespace depth_to_space_float
+
+class TestDataFloatDepthToSpace : public TestDataDepthToSpaceBase<float>
+{
+public:
+  TestDataFloatDepthToSpace()
+  {
+    _input_data = depth_to_space_float::input_data;
+    _reference_output_data = depth_to_space_float::reference_output_data;
+    _test_kernel_model_circle = depth_to_space_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatDepthToSpace() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_DEPTH_TO_SPACE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depth_to_space/NegDepthToSpaceKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depth_to_space/NegDepthToSpaceKernel.h
new file mode 100644 (file)
index 0000000..c418cea
--- /dev/null
@@ -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_TEST_MODELS_NEG_DEPTH_TO_SPACE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_DEPTH_TO_SPACE_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_depth_to_space_kernel
+{
+/*
+ * DepthToSpace kernel with input output type mismatch:
+ *
+ *      Input(1, 2, 2, 4) - Float32
+ *            |
+ *        DepthToSpace
+ *            |
+ *      Output(1, 4, 4, 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, 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, 0x5e, 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, 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,
+  0x04, 0x00, 0x00, 0x00, 0x04, 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, 0x02, 0x00, 0x00, 0x00, 0x02, 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, 0x05, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x05, 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_depth_to_space_kernel
+
+class NegTestDataInputOutputTypeMismatchDepthToSpaceKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchDepthToSpaceKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_depth_to_space_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchDepthToSpaceKernel() 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_DEPTH_TO_SPACE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depth_to_space/TestDataDepthToSpaceBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depth_to_space/TestDataDepthToSpaceBase.h
new file mode 100644 (file)
index 0000000..e8c48a1
--- /dev/null
@@ -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_DEPTH_TO_SPACE_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_DEPTH_TO_SPACE_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataDepthToSpaceBase : public TestDataBase<T>
+{
+public:
+  TestDataDepthToSpaceBase() = 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_DEPTH_TO_SPACE_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depthwise_conv_2d/FloatDepthwiseConv2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depthwise_conv_2d/FloatDepthwiseConv2DKernel.h
new file mode 100644 (file)
index 0000000..bdfaa79
--- /dev/null
@@ -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_DEPTHWISE_CONV_2D_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_FLOAT_H
+
+#include "TestDataDepthwiseConv2DBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace depthwiseconv2d_float
+{
+
+/*
+ * DepthwiseConv2D Kernel:
+ *
+ * Input(1, 4, 2, 2)   Weight(1, 2, 2, 4)   Bias(4)
+ *              \            |             /
+ *               \           |            /
+ *                    DepthwiseConv2D
+ *                           |
+ *                    Output(1, 2, 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,
+  0xa4, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x7c, 0x00, 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, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 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, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x10, 0xc1, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x30, 0xc1,
+  0x00, 0x00, 0x40, 0x41, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0x60, 0xc1, 0x00, 0x00, 0x70, 0x41,
+  0x00, 0x00, 0x80, 0xc1, 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, 0x84, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x8c, 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, 0x02,
+  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, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 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, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 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.5529652, 4.395708,  7.810858,  0.8234205, 8.967432, 0.8667908, 9.755089,  -1.0849819,
+  3.721611,   6.6046314, -5.122017, -7.123464, 8.446955, 1.757657,  16.904526, 4.1345367};
+
+const std::vector<float> reference_output_data = {99.80263,  0.0, 0.0,       55.757915,
+                                                  312.81335, 0.0, 175.49365, 0.0};
+
+} // namespace depthwiseconv2d_float
+
+class TestDataFloatDepthwiseConv2D : public TestDataDepthwiseConv2DBase<float>
+{
+public:
+  TestDataFloatDepthwiseConv2D()
+  {
+    _input_data = depthwiseconv2d_float::input_data;
+    _reference_output_data = depthwiseconv2d_float::reference_output_data;
+    _test_kernel_model_circle = depthwiseconv2d_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatDepthwiseConv2D() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depthwise_conv_2d/NegDepthwiseConv2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depthwise_conv_2d/NegDepthwiseConv2DKernel.h
new file mode 100644 (file)
index 0000000..81d2be3
--- /dev/null
@@ -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 LUCI_INTERPRETER_TEST_MODELS_NEG_DEPTHWISE_CONV_2D_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_DEPTHWISE_CONV_2D_KERNEL_H
+
+#include "TestDataDepthwiseConv2DBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_depthwise_conv2d_input_type_mismatch
+{
+
+/*
+ * DepthwiseConv2D Kernel with input type mismatch (input_type should be equal to weight_type):
+ *
+ * Input(1, 4, 2, 2) - Float32   Weight(1, 2, 2, 4) - Int32   Bias(4)- FLOAT32
+ *              \                       |                   /
+ *               \                      |                  /
+ *                               DepthwiseConv2D
+ *                                     |
+ *                             Output(1, 2, 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,
+  0xa4, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x7c, 0x00, 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, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00, 0xf5, 0xff, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xf2, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0xf0, 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, 0x84, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x8c, 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, 0x02,
+  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, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 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,
+  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,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 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, 0x0c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 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_depthwise_conv2d_input_type_mismatch
+
+namespace neg_depthwise_conv2d_bias_wrong_type
+{
+/*
+ * DepthwiseConv2D 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
+ *              \                       |                   /
+ *               \                      |                  /
+ *                                DepthwiseConv2D
+ *                                     |
+ *                             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,
+  0xa4, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x7c, 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,
+  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x10, 0xc1, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x30, 0xc1,
+  0x00, 0x00, 0x40, 0x41, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0x60, 0xc1, 0x00, 0x00, 0x70, 0x41,
+  0x00, 0x00, 0x80, 0xc1, 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, 0x84, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x8c, 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, 0x02,
+  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, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 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,
+  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,
+  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,
+  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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 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_depthwise_conv2d_bias_wrong_type
+
+namespace neg_depthwise_conv2d_invalid_input_shape
+{
+/*
+ * DepthwiseConv2D Kernel with invalid input shape (rank should be == 4):
+ *
+ * Input(1, 1, 3, 3, 2) - Float32   Weight(1, 1, 1, 2) - Float32   Bias(1) - Float32
+ *              \                       |                   /
+ *               \                      |                  /
+ *                                DepthwiseConv2D
+ *                                     |
+ *                             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,
+  0xa4, 0x00, 0x00, 0x00, 0x24, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x7c, 0x00, 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, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 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, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x10, 0xc1, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x30, 0xc1,
+  0x00, 0x00, 0x40, 0x41, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0x60, 0xc1, 0x00, 0x00, 0x70, 0x41,
+  0x00, 0x00, 0x80, 0xc1, 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, 0x84, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x8c, 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, 0x02,
+  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, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 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, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 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_depthwise_conv2d_invalid_input_shape
+
+class NegTestDataInputMismatchDepthwiseConv2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputMismatchDepthwiseConv2DKernel()
+  {
+    _test_kernel_model_circle = neg_depthwise_conv2d_input_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputMismatchDepthwiseConv2DKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataWrongBiasTypeDepthwiseConv2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataWrongBiasTypeDepthwiseConv2DKernel()
+  {
+    _test_kernel_model_circle = neg_depthwise_conv2d_bias_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataWrongBiasTypeDepthwiseConv2DKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputTypeDepthwiseConv2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInvalidInputTypeDepthwiseConv2DKernel()
+  {
+    _test_kernel_model_circle = neg_depthwise_conv2d_bias_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInvalidInputTypeDepthwiseConv2DKernel() 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_DEPTHWISE_CONV_2D_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depthwise_conv_2d/TestDataDepthwiseConv2DBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/depthwise_conv_2d/TestDataDepthwiseConv2DBase.h
new file mode 100644 (file)
index 0000000..f89aec5
--- /dev/null
@@ -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_DEPTHWISE_CONV_2D_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataDepthwiseConv2DBase : 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_DEPTHWISE_CONV_2D_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/dequantize/FloatDequantizeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/dequantize/FloatDequantizeKernel.h
new file mode 100644 (file)
index 0000000..1333460
--- /dev/null
@@ -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_DEQUANTIZE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_DEQUANTIZE_KERNEL_H
+
+#include "TestDataDequantizeBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace dequantize_float
+{
+/*
+ * Dequantize Kernel:
+ *
+ *         Input(4)
+ *            |
+ *         Dequantize
+ *            |
+ *         Output(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, 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, 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, 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, 0x01, 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, 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,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0xae, 0xa7, 0x3f,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 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, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+  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 = {2, 9, 10, 7};
+
+const std::vector<float> reference_output_data = {2.62, 11.789999, 13.099999, 9.17};
+
+} // namespace dequantize_float
+
+class TestDataFloatDequantize : public TestDataDequantizeBase<uint8_t, float>
+{
+public:
+  TestDataFloatDequantize()
+  {
+    _input_data = dequantize_float::input_data;
+    _reference_output_data = dequantize_float::reference_output_data;
+    _test_kernel_model_circle = dequantize_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatDequantize() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_QUANTIZE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/dequantize/NegDequantizeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/dequantize/NegDequantizeKernel.h
new file mode 100644 (file)
index 0000000..4856e6e
--- /dev/null
@@ -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_DEQUANTIZE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_DEQUANTIZE_KERNEL_H
+
+#include "TestDataDequantizeBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace neg_invalid_input_output_shape_mismatch_dequantize_kernel
+{
+/*
+ * Dequantize Kernel with input-output shape mismatch:
+ *
+ *      Input(1, 4) = Float32
+ *            |
+ *           Dequantize
+ *            |
+ *      Output(4) = Float32
+ */
+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, 0x2c, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x7c, 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, 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, 0x01, 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,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x14, 0xae, 0xa7, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 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,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 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_output_shape_mismatch_dequantize_kernel
+
+class NegTestDataInputOutputShapeMismatchDequantizeKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputShapeMismatchDequantizeKernel()
+  {
+    _test_kernel_model_circle =
+      neg_invalid_input_output_shape_mismatch_dequantize_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputShapeMismatchDequantizeKernel() 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_QUANTIZE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/dequantize/TestDataDequantizeBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/dequantize/TestDataDequantizeBase.h
new file mode 100644 (file)
index 0000000..266c133
--- /dev/null
@@ -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_DEQUANTIZE_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_DEQUANTIZE_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename U> class TestDataDequantizeBase : public TestDataBase<T, U>
+{
+public:
+  TestDataDequantizeBase() = 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_DEQUANTIZE_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floor/FloatFloorKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floor/FloatFloorKernel.h
new file mode 100644 (file)
index 0000000..4d88b77
--- /dev/null
@@ -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_FLOAT_FLOOR_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_FLOOR_KERNEL_H
+
+#include "TestDataFloorBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace floor_float
+{
+/*
+ * Floor Kernel:
+ *
+ *        Input(2, 3)
+ *            |
+ *          Floor
+ *            |
+ *        Output(2, 3)
+ */
+unsigned char test_kernel_model_circle[] = {
+  0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x12, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00,
+  0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6e, 0x6e, 0x70, 0x61,
+  0x63, 0x6b, 0x61, 0x67, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x64, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xd8, 0xff, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0xbc, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0xf0, 0xff, 0xff, 0xff,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+  0x04, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {7.297842,   30.999863, 15.692827,
+                                       -18.824865, 22.614136, 5.7466774};
+
+const std::vector<float> reference_output_data = {7, 30, 15, -19, 22, 5};
+
+} // namespace floor_float
+
+class TestDataFloatFloor : public TestDataFloorBase<float>
+{
+public:
+  TestDataFloatFloor()
+  {
+    _input_data = floor_float::input_data;
+    _reference_output_data = floor_float::reference_output_data;
+    _test_kernel_model_circle = floor_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatFloor() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_FLOOR_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floor/NegFloorKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floor/NegFloorKernel.h
new file mode 100644 (file)
index 0000000..37b023f
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_FLOOR_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_FLOOR_KERNEL_H
+
+#include "TestDataFloorBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_floor_kernel
+{
+/*
+ * Floor Kernel with input output type mismatch (should be equal):
+ *
+ *      Input(2, 3) - Uint8
+ *            |
+ *           Floor
+ *            |
+ *      Output(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,
+  0x2c, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x80, 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, 0x48, 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, 0x02, 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, 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, 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, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x02, 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,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 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_floor_kernel
+
+namespace neg_invalid_input_output_shape_floor_kernel
+{
+/*
+ * Floor Kernel with different input output shapes:
+ *
+ *      Input(1, 2, 3)
+ *            |
+ *           Floor
+ *            |
+ *      Output(2, 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, 0x08, 0x01, 0x00, 0x00, 0x24, 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, 0x38, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xdc, 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,
+  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,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 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, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 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_output_shape_floor_kernel
+
+class NegTestDataInputOutputTypeMismatchFloorKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchFloorKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_floor_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchFloorKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputOutputShapeFloorKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInvalidInputOutputShapeFloorKernel()
+  {
+    _test_kernel_model_circle =
+      neg_invalid_input_output_shape_floor_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInvalidInputOutputShapeFloorKernel() 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_FLOOR_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floor/TestDataFloorBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floor/TestDataFloorBase.h
new file mode 100644 (file)
index 0000000..c0a32f9
--- /dev/null
@@ -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_FLOOR_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOOR_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataFloorBase : public TestDataBase<T>
+{
+public:
+  TestDataFloorBase() = 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_FLOOR_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floordiv/FloatFloorDivKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floordiv/FloatFloorDivKernel.h
new file mode 100644 (file)
index 0000000..9bc0c86
--- /dev/null
@@ -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_FLOORDIV_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOORDIV_KERNEL_FLOAT_H
+
+#include "TestDataFloorDivBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace floordiv_float_with_broadcasting
+{
+
+/*
+ * FloorDiv Kernel:
+ *
+ * Input_1(2, 5)   Input_2(2, 1)
+ *       \             /
+ *     FloorDiv(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, 0x41, 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,
+  0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 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 = {-5, -3, -9, 4, 6, -2, 0, 0, -2, 1};
+
+} // namespace floordiv_float_with_broadcasting
+
+namespace floordiv_float_no_broadcasting
+{
+/*
+ * FloorDiv Kernel:
+ *
+ * Input_1(2, 3)   Input_2(2, 3)
+ *              \             /
+ *          FloorDiv(no broadcast)
+ *                     |
+ *            Output(2, 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, 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, 0x41, 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, 0x03, 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,
+  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, 0x02, 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,
+  0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 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};
+std::vector<float> input2_data = {-0.62832826, 7.937863,   -14.899745,
+                                  0.2819096,   -5.8306913, 8.6010685};
+std::vector<float> reference_output_data = {-6, 1, -1, 39, -1, 1};
+
+} // namespace floordiv_float_no_broadcasting
+
+class TestDataFloatFloorDiv : public TestDataFloorDivBase<float>
+{
+public:
+  explicit TestDataFloatFloorDiv(bool is_with_broadcast)
+    : TestDataFloorDivBase<float>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = floordiv_float_with_broadcasting::input1_data;
+      _input2_data = floordiv_float_with_broadcasting::input2_data;
+      _reference_output_data = floordiv_float_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = floordiv_float_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = floordiv_float_no_broadcasting::input1_data;
+      _input2_data = floordiv_float_no_broadcasting::input2_data;
+      _reference_output_data = floordiv_float_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = floordiv_float_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataFloatFloorDiv() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOORDIV_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floordiv/NegFloorDivKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floordiv/NegFloorDivKernel.h
new file mode 100644 (file)
index 0000000..dd460d6
--- /dev/null
@@ -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_NEG_FLOORDIV_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_FLOORDIV_KERNEL_H
+
+#include "TestDataFloorDivBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace input_1_wrong_type
+{
+
+/*
+ * FloorDiv Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Int32   Input_2(2, 1) - Float
+ *               \             /
+ *           FloorDiv(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, 0x41, 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,
+  0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 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
+{
+
+/*
+ * FloorDiv Kernel with input2 type mismatch:
+ *
+ * Input_1(2, 5)- Float   Input_2(2, 1) - Int32
+ *       \             /
+ *     FloorDiv(with broadcast)
+ *              |
+ *          Output(2, 5) - 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, 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, 0x41, 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,
+  0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 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 NegTestDataInput1WrongTypeFloorDiv : public NegTestDataBase
+{
+public:
+  NegTestDataInput1WrongTypeFloorDiv()
+  {
+    _test_kernel_model_circle = input_1_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput1WrongTypeFloorDiv() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInput2WrongTypeFloorDiv : public NegTestDataBase
+{
+public:
+  NegTestDataInput2WrongTypeFloorDiv()
+  {
+    _test_kernel_model_circle = input_2_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput2WrongTypeFloorDiv() 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_FLOORDIV_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floordiv/TestDataFloorDivBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floordiv/TestDataFloorDivBase.h
new file mode 100644 (file)
index 0000000..995cb88
--- /dev/null
@@ -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_FLOORDIV_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOORDIV_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataFloorDivBase : public TestDataBase<T>
+{
+public:
+  explicit TestDataFloorDivBase(bool)
+  {
+    // Do nothing
+  }
+
+  TestDataFloorDivBase() = 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/floormod/FloatFloorModKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floormod/FloatFloorModKernel.h
new file mode 100644 (file)
index 0000000..65cac39
--- /dev/null
@@ -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_FLOORMOD_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOORMOD_KERNEL_FLOAT_H
+
+#include "TestDataFloorModBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace floormod_float_with_broadcasting
+{
+
+/*
+ * FloorMod Kernel:
+ *
+ * Input_1(2, 5)   Input_2(2, 1)
+ *       \             /
+ *     FloorMod(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, 0x48, 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,
+  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 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 = {-1.7485305, -0.6419221, -1.4687741, -1.8597124,
+                                                  -1.9120156, -6.361024,  -7.5779333, -1.1460792,
+                                                  -3.481703,  -3.142033};
+
+} // namespace floormod_float_with_broadcasting
+
+namespace floormod_float_no_broadcasting
+{
+/*
+ * FloorMod Kernel:
+ *
+ * Input_1(2, 3)   Input_2(2, 3)
+ *              \             /
+ *          FloorMod(no broadcast)
+ *                     |
+ *            Output(2, 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, 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, 0x48, 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, 0x03, 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,
+  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, 0x02, 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,
+  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 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};
+std::vector<float> input2_data = {-0.62832826, 7.937863,   -14.899745,
+                                  0.2819096,   -5.8306913, 8.6010685};
+std::vector<float> reference_output_data = {-0.20693356, 5.707271,   -14.472599,
+                                            0.0384486,   -5.4117867, 7.1362065};
+
+} // namespace floormod_float_no_broadcasting
+
+class TestDataFloatFloorMod : public TestDataFloorModBase<float>
+{
+public:
+  explicit TestDataFloatFloorMod(bool is_with_broadcast)
+    : TestDataFloorModBase<float>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = floormod_float_with_broadcasting::input1_data;
+      _input2_data = floormod_float_with_broadcasting::input2_data;
+      _reference_output_data = floormod_float_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = floormod_float_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = floormod_float_no_broadcasting::input1_data;
+      _input2_data = floormod_float_no_broadcasting::input2_data;
+      _reference_output_data = floormod_float_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = floormod_float_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataFloatFloorMod() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOORMOD_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floormod/NegFloorModKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floormod/NegFloorModKernel.h
new file mode 100644 (file)
index 0000000..b7ef708
--- /dev/null
@@ -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_NEG_FLOORMOD_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_FLOORMOD_KERNEL_H
+
+#include "TestDataFloorModBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace input_1_wrong_type
+{
+
+/*
+ * FloorMod Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Int32   Input_2(2, 1) - Float
+ *               \             /
+ *           FloorMod(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, 0x48, 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,
+  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 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
+{
+
+/*
+ * FloorMod Kernel with input2  type mismatch:
+ *
+ * Input_1(2, 5)- Float   Input_2(2, 1) - Int32
+ *       \             /
+ *     FloorMod(with broadcast)
+ *              |
+ *          Output(2, 5) - 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, 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, 0x48, 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, 0x02, 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,
+  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 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 NegTestDataInput1WrongTypeFloorMod : public NegTestDataBase
+{
+public:
+  NegTestDataInput1WrongTypeFloorMod()
+  {
+    _test_kernel_model_circle = input_1_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput1WrongTypeFloorMod() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInput2WrongTypeFloorMod : public NegTestDataBase
+{
+public:
+  NegTestDataInput2WrongTypeFloorMod()
+  {
+    _test_kernel_model_circle = input_2_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput2WrongTypeFloorMod() 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_FLOORMOD_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floormod/TestDataFloorModBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/floormod/TestDataFloorModBase.h
new file mode 100644 (file)
index 0000000..dc0c2c4
--- /dev/null
@@ -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_FLOORMOD_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOORMOD_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataFloorModBase : public TestDataBase<T>
+{
+public:
+  explicit TestDataFloorModBase(bool)
+  {
+    // Do nothing
+  }
+
+  TestDataFloorModBase() = 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_FLOORMOD_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather_nd/FloatGatherNDKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather_nd/FloatGatherNDKernel.h
new file mode 100644 (file)
index 0000000..4a789c7
--- /dev/null
@@ -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_GATHER_ND_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_GATHER_ND_KERNEL_H
+
+#include "TestDataGatherNDBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace gather_nd_float
+{
+/*
+ * GatherND Kernel:
+ *
+ *      Input(1, 4, 4, 3)
+ *            |
+ *           GatherND
+ *            |
+ *      Output(1, 2, 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,
+  0x50, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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, 0x53, 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, 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,
+  0x02, 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, 0x69, 0x6e, 0x64, 0x69,
+  0x63, 0x65, 0x73, 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, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x70, 0x61, 0x72, 0x61, 0x6d, 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,
+  0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 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 = {-63.555645, 32.902435,  -61.76536, 28.280264,
+                                       66.80893,   -13.163652, -66.06793, -15.827837};
+const std::vector<float> reference_output_data = {-61.76536, 28.280264, 66.80893, -13.163652};
+
+} // namespace gather_nd_float
+
+class TestDataFloatGatherND : public TestDataGatherNDBase<float>
+{
+public:
+  TestDataFloatGatherND()
+  {
+    _input_data = gather_nd_float::input_data;
+    _reference_output_data = gather_nd_float::reference_output_data;
+    _test_kernel_model_circle = gather_nd_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatGatherND() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_GATHER_ND_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather_nd/NegGatherNDKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather_nd/NegGatherNDKernel.h
new file mode 100644 (file)
index 0000000..71cba6b
--- /dev/null
@@ -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_NEG_GATHER_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_GATHER_KERNEL_H
+
+#include "TestDataGatherNDBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_gather_nd_mismatch_input_output_type
+{
+/*
+ * GatherND Kernel with input output type mismatch (should be equal):
+ *
+ * Input(1, 4, 4, 3) - FLOAT32   Indices(1, 2, 1)
+ *       \                 /
+ *           GatherND
+ *                 |
+ *          Output(1, 2, 2, 4) - 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,
+  0x50, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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, 0x53, 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, 0x3c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xd8, 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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 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, 0x10, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 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, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 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_nd_mismatch_input_output_type
+
+class NegTestDataInputOutputTypeMismatchGatherNDKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchGatherNDKernel()
+  {
+    _test_kernel_model_circle = neg_gather_nd_mismatch_input_output_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchGatherNDKernel() 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_ND_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather_nd/TestDataGatherNDBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/gather_nd/TestDataGatherNDBase.h
new file mode 100644 (file)
index 0000000..a9485ad
--- /dev/null
@@ -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_ND_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_GATHER_ND_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataGatherNDBase : public TestDataBase<T>
+{
+public:
+  TestDataGatherNDBase() = 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_ND_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/if/IfKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/if/IfKernel.h
new file mode 100644 (file)
index 0000000..ab5986f
--- /dev/null
@@ -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_IF_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_IF_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace if_kernel
+{
+/*
+ * If Kernel:
+ *    Main graph:
+ *  Input Bool(1) Input_1(2,3) Input_2(2,3)
+ *                    |
+ *                   If
+ *                    |
+ *                Output(2,3)
+ *
+ *    If else graph:
+ *         Input_1(2,3) Input_2(2,3)
+ *                     |
+ *                    Add
+ *                     |
+ *                 Output(2,3)
+ *
+ *    If then graph:
+ *         Input_1(2,3) Input_2(2,3)
+ *                     |
+ *                    Mul
+ *                     |
+ *                 Output(2,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, 0xd4, 0x03, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x30, 0xfc, 0xff, 0xff,
+  0x34, 0xfc, 0xff, 0xff, 0x38, 0xfc, 0xff, 0xff, 0x3c, 0xfc, 0xff, 0xff, 0x40, 0xfc, 0xff, 0xff,
+  0x44, 0xfc, 0xff, 0xff, 0x48, 0xfc, 0xff, 0xff, 0x4c, 0xfc, 0xff, 0xff, 0x50, 0xfc, 0xff, 0xff,
+  0x54, 0xfc, 0xff, 0xff, 0x58, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00,
+  0xfc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x49, 0x46, 0x5f, 0x54, 0x48, 0x45, 0x4e, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xfa, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x15, 0x10, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xb0, 0xfc, 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, 0x58, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x84, 0xfd, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa8, 0xfd, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x09, 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,
+  0x03, 0x00, 0x00, 0x00, 0xd0, 0xfd, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x08, 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, 0x03, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xff, 0xff,
+  0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+  0x68, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x49, 0x46, 0x5f, 0x45, 0x4c, 0x53, 0x45, 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, 0xb0, 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, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x84, 0xfe, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa8, 0xfe, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x06, 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,
+  0x03, 0x00, 0x00, 0x00, 0xd0, 0xfe, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x05, 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, 0x03, 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,
+  0x84, 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, 0x5c,
+  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, 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, 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, 0x64, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 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,
+  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, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 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, 0x06, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x62,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff, 0x76, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x76, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 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> input_data = {1.}; // cast to bool
+
+const std::vector<float> input1_data = {1., 1., 1., 1., 1., 1.};
+const std::vector<float> input2_data = {1., 1., 1., 1., 1., 1.};
+
+const std::vector<float> reference_output_data = {1., 1., 1., 1., 1., 1.};
+} // namespace if_kernel
+
+template <typename T> class TestDataIfKernel : public TestDataBase<T>
+{
+public:
+  TestDataIfKernel()
+  {
+    _input_data = if_kernel::input_data;
+    _input1_data = if_kernel::input1_data;
+    _input2_data = if_kernel::input2_data;
+    _reference_output_data = if_kernel::reference_output_data;
+    _test_kernel_model_circle = if_kernel::test_kernel_model_circle;
+  }
+
+  ~TestDataIfKernel() 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;
+      case 1:
+        return _input1_data;
+      case 2:
+        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> _input_data;
+  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_IF_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/if/NegIfKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/if/NegIfKernel.h
new file mode 100644 (file)
index 0000000..eb8af53
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_IF_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_IF_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace neg_if_kernel
+{
+/*
+ * If Kernel with wrong cond tensor size(should be 1):
+ *    Main graph:
+ *  Input Bool(2) Input_1(2,3) Input_2(2,3)
+ *                    |
+ *                   If
+ *                    |
+ *                Output(2,3)
+ *
+ *    If else graph:
+ *         Input_1(2,3) Input_2(2,3)
+ *                     |
+ *                    Add
+ *                     |
+ *                 Output(2,3)
+ *
+ *    If then graph:
+ *         Input_1(2,3) Input_2(2,3)
+ *                     |
+ *                    Mul
+ *                     |
+ *                 Output(2,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, 0xd8, 0x03, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2c, 0xfc, 0xff, 0xff,
+  0x30, 0xfc, 0xff, 0xff, 0x34, 0xfc, 0xff, 0xff, 0x38, 0xfc, 0xff, 0xff, 0x3c, 0xfc, 0xff, 0xff,
+  0x40, 0xfc, 0xff, 0xff, 0x44, 0xfc, 0xff, 0xff, 0x48, 0xfc, 0xff, 0xff, 0x4c, 0xfc, 0xff, 0xff,
+  0x50, 0xfc, 0xff, 0xff, 0x54, 0xfc, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00,
+  0xfc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x49, 0x46, 0x5f, 0x54, 0x48, 0x45, 0x4e, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xfa, 0xfd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x15, 0x10, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xac, 0xfc, 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, 0x58, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x84, 0xfd, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa8, 0xfd, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x09, 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,
+  0x03, 0x00, 0x00, 0x00, 0xd0, 0xfd, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x08, 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, 0x03, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xff, 0xff,
+  0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+  0x68, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x49, 0x46, 0x5f, 0x45, 0x4c, 0x53, 0x45, 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, 0xac, 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, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x84, 0xfe, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa8, 0xfe, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x06, 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,
+  0x03, 0x00, 0x00, 0x00, 0xd0, 0xfe, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x05, 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, 0x03, 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,
+  0x84, 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, 0x5c,
+  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, 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, 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, 0x64, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xd8, 0xff, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 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,
+  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, 0x31, 0x00, 0x00, 0x00, 0x00, 0x02, 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, 0x06, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x62,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x34, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff,
+  0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x0c, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+  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_if_kernel
+
+class NegTestDataIfKernel : public NegTestDataBase
+{
+public:
+  NegTestDataIfKernel() { _test_kernel_model_circle = neg_if_kernel::test_kernel_model_circle; }
+
+  ~NegTestDataIfKernel() 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_IF_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_normalization/FloatL2NormalizeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_normalization/FloatL2NormalizeKernel.h
new file mode 100644 (file)
index 0000000..9d66561
--- /dev/null
@@ -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 LUCI_INTERPRETER_TEST_MODELS_FLOAT_L2_NORMALIZATION_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_L2_NORMALIZATION_KERNEL_H
+
+#include "TestDataL2NormalizeBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace l2_normalization_float
+{
+/*
+ * L2Normalization Kernel:
+ *
+ *      Input(1, 4, 4, 3)
+ *            |
+ *      L2Normalization
+ *            |
+ *      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,
+  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, 0x0c, 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, 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, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 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.992603,  8.346985,  22.960445, 45.584763, 26.916512, 33.256886, 12.787039, 40.30215,
+  32.26641,  13.645262, 36.445396, 33.06842,  37.449368, 14.05669,  17.87454,  7.8050013,
+  5.6068754, 17.868938, 40.134842, 24.222584, 42.0985,   26.406887, 11.48271,  33.00633,
+  39.676426, 46.740967, 38.20928,  45.924362, 39.70501,  32.05231,  41.742085, 29.257357,
+  42.27183,  35.843292, 28.056007, 31.480331, 34.84266,  34.666496, 26.273453, 33.72813,
+  23.426928, 14.348057, 52.57121,  17.464836, 33.1741,   29.476301, 22.09747,  32.685722};
+
+const std::vector<float> reference_output_data = {
+  0.3785766,  0.31623122, 0.86987215, 0.72914726, 0.4305408,  0.53195775, 0.24041508, 0.75773954,
+  0.60665584, 0.26719585, 0.71365863, 0.64753205, 0.8547623,  0.32083663, 0.40797707, 0.38468635,
+  0.27634698, 0.8807093,  0.63699496, 0.3844456,  0.66816086, 0.6028728,  0.2621518,  0.7535389,
+  0.54921657, 0.6470067,  0.5289077,  0.66895926, 0.5783648,  0.46689144, 0.6303393,  0.4418098,
+  0.6383389,  0.6476525,  0.506944,   0.56881815, 0.6251807,  0.6220198,  0.47142372, 0.77535427,
+  0.53854656, 0.32983825, 0.81417507, 0.2704795,  0.5137703,  0.59851044, 0.44868472, 0.6636771};
+
+} // namespace l2_normalization_float
+
+class TestDataFloatL2Normalization : public TestDataL2NormalizationBase<float>
+{
+public:
+  TestDataFloatL2Normalization()
+  {
+    _input_data = l2_normalization_float::input_data;
+    _reference_output_data = l2_normalization_float::reference_output_data;
+    _test_kernel_model_circle = l2_normalization_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatL2Normalization() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_L2_NORMALIZATION_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_normalization/NegL2NormalizeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_normalization/NegL2NormalizeKernel.h
new file mode 100644 (file)
index 0000000..e660668
--- /dev/null
@@ -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_TEST_MODELS_NEG_L2_NORMALIZE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_L2_NORMALIZE_KERNEL_H
+
+#include "TestDataL2NormalizeBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_l2_normalization_kernel
+{
+/*
+ * L2Normalization Kernel with input output type mismatch (should be equal):
+ *
+ *      Input(1, 4, 4, 3) - Float
+ *            |
+ *           L2Normalization
+ *            |
+ *      Output(1, 4, 4, 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,
+  0x28, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x54, 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, 0x0c, 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, 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, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 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_l2_normalization_kernel
+
+class NegTestDataInputOutputTypeMismatchNegKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchNegKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_l2_normalization_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;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_L2_NORMALIZE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_normalization/TestDataL2NormalizeBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_normalization/TestDataL2NormalizeBase.h
new file mode 100644 (file)
index 0000000..3f8ad81
--- /dev/null
@@ -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_L2_NORMALIZATION_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_L2_NORMALIZATION_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataL2NormalizationBase : public TestDataBase<T>
+{
+public:
+  TestDataL2NormalizationBase() = 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_L2_NORMALIZATION_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_poop_2d/FloatL2Pool2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_poop_2d/FloatL2Pool2DKernel.h
new file mode 100644 (file)
index 0000000..696948e
--- /dev/null
@@ -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 LUCI_INTERPRETER_TEST_MODELS_FLOAT_L2_POOL_2D_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_L2_POOL_2D_KERNEL_H
+
+#include "TestDataL2Pool2DBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace l2_pool_2d_float
+{
+/*
+ * L2Pool2D Kernel:
+ *
+ *      Input(1, 8, 8, 1)
+ *            |
+ *           L2Pool2D
+ *            |
+ *      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, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 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 = {
+  67.38262,   67.41811,   1.2834148,  -98.304276, -79.165695, 15.270965,  3.746103,   -54.763,
+  -42.926304, -23.553911, -19.94737,  47.355026,  31.100943,  8.447245,   -75.31512,  -16.644464,
+  22.489397,  -39.29673,  -98.54282,  -85.136086, 41.03638,   -37.152763, -79.57822,  -68.96887,
+  11.1106205, -10.539243, -8.441398,  -52.19395,  6.378709,   9.458231,   -77.18643,  99.294,
+  76.699104,  45.281494,  -19.284706, 65.62093,   -66.792015, -1.4548094, -82.337814, -73.516815,
+  5.0163054,  80.22257,   15.349068,  19.546398,  24.824991,  16.236868,  92.39976,   76.70845,
+  -36.775307, -12.240916, 59.4311,    60.621857,  11.79261,   -64.71309,  -63.46639,  -33.302174,
+  -36.784237, -40.939827, 15.621524,  -90.70094,  29.704996,  -71.49415,  14.5302105, -17.651545};
+const std::vector<float> reference_output_data = {
+  53.57955,  37.07942,  55.465694, 69.174965, 43.413803, 38.700638, 47.33504,  33.34464,  55.244015,
+  69.998634, 55.095154, 32.02708,  58.0016,   65.26638,  23.898365, 53.472546, 70.27501,  54.07641,
+  28.25977,  58.65199,  82.015915, 45.18763,  25.517868, 43.224625, 53.693985, 33.887444, 56.632225,
+  83.667915, 59.987476, 47.6801,   36.385647, 49.41058,  36.54862,  62.415905, 81.55694,  44.618065,
+  50.875214, 44.228725, 34.68579,  36.07896,  65.22483,  69.9266,   33.657883, 37.423244, 62.605423,
+  56.839954, 50.79529,  58.17711,  37.61556};
+
+} // namespace l2_pool_2d_float
+
+class TestDataFloatL2Pool2D : public TestDataL2Pool2DBase<float>
+{
+public:
+  TestDataFloatL2Pool2D()
+  {
+    _input_data = l2_pool_2d_float::input_data;
+    _reference_output_data = l2_pool_2d_float::reference_output_data;
+    _test_kernel_model_circle = l2_pool_2d_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatL2Pool2D() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_L2_POOL_2D_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_poop_2d/NegL2Pool2DKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_poop_2d/NegL2Pool2DKernel.h
new file mode 100644 (file)
index 0000000..b8850b4
--- /dev/null
@@ -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_L2_POOL_2D_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_L2_POOL_2D_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_l2_pool_2d_kernel
+{
+/*
+ * L2Pool2D Kernel with input output type mismatch:
+ *
+ *      Input(1, 8, 8, 1) - Float32
+ *            |
+ *           L2Pool2D
+ *            |
+ *      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, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 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_l2_pool_2d_kernel
+
+class NegTestDataInputOutputTypeMismatchL2Pool2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchL2Pool2DKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_l2_pool_2d_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchL2Pool2DKernel() 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_L2_POOL_2D_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_poop_2d/TestDataL2Pool2DBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/l2_poop_2d/TestDataL2Pool2DBase.h
new file mode 100644 (file)
index 0000000..ca19172
--- /dev/null
@@ -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_L2_POOL_2D_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_L2_POOL_2D_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataL2Pool2DBase : public TestDataBase<T>
+{
+public:
+  TestDataL2Pool2DBase() = 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_L2_POOL_2D_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log/FloatLogKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log/FloatLogKernel.h
new file mode 100644 (file)
index 0000000..c6ede70
--- /dev/null
@@ -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_LOG_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_LOG_KERNEL_H
+
+#include "TestDataLogBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace log_float
+{
+/*
+ * Log Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Log
+ *            |
+ *      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,
+  0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 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.9393284, 12.591625, 14.310633, 4.178408, 9.743034, 7.6983232, 10.804855,  2.9712732, 13.964229,
+  8.660442,  12.715771, 12.287443, 11.55983, 6.143016, 1.032474,  10.3692465, 13.885086, 12.157783};
+const std::vector<float> reference_output_data = {
+  1.0781811, 2.533032,  2.6610029,   1.4299303, 2.2765527, 2.0410025,
+  2.3799956, 1.0889906, 2.636499,    2.1587658, 2.542843,  2.5085778,
+  2.4475362, 1.8153158, 0.031957902, 2.3388443, 2.6308153, 2.4979694};
+
+} // namespace log_float
+
+class TestDataFloatLog : public TestDataLogBase<float>
+{
+public:
+  TestDataFloatLog()
+  {
+    _input_data = log_float::input_data;
+    _reference_output_data = log_float::reference_output_data;
+    _test_kernel_model_circle = log_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatLog() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_LOG_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log/NegLogKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log/NegLogKernel.h
new file mode 100644 (file)
index 0000000..27cfd38
--- /dev/null
@@ -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_LOG_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_LOG_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Log Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Log
+ *            |
+ *      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,
+  0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 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 NegTestDataInputOutputTypeMismatchLogKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchLogKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchLogKernel() 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_LOG_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log/TestDataLogBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log/TestDataLogBase.h
new file mode 100644 (file)
index 0000000..83f22ee
--- /dev/null
@@ -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_LOG_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_LOG_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataLogBase : public TestDataBase<T>
+{
+public:
+  TestDataLogBase() = 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_LOG_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log_softmax/FloatLogSoftmaxKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log_softmax/FloatLogSoftmaxKernel.h
new file mode 100644 (file)
index 0000000..cecf620
--- /dev/null
@@ -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_LOG_SOFTMAX_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_LOG_SOFTMAX_KERNEL_H
+
+#include "TestDataLogSoftmaxBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace log_softmax_float
+{
+/*
+ * LogSoftmax Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *        LogSoftmax
+ *            |
+ *      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, 0x24, 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,
+  0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 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 = {
+  -98.99295, 67.388435, 48.43881, -61.26518, 35.86871, 22.69142,  -61.265385, -87.11669, -20.316734,
+  50.533947, -93.46988, 75.58928, -36.26448, 96.57878, 63.916878, -87.25623,  30.606735, 65.762665};
+const std::vector<float> reference_output_data = {
+  -166.38138, 0.0,        0.0,       -109.70399, -1.9073468e-06, -13.177292,
+  0.0,        -25.851307, -70.85068, 0.0,        -169.05916,     0.0,
+  -132.84326, 0.0,        0.0,       -151.17311, -35.15593,      0.0};
+
+} // namespace log_softmax_float
+
+class TestDataFloatLogSoftmax : public TestDataLogSoftmaxBase<float>
+{
+public:
+  TestDataFloatLogSoftmax()
+  {
+    _input_data = log_softmax_float::input_data;
+    _reference_output_data = log_softmax_float::reference_output_data;
+    _test_kernel_model_circle = log_softmax_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatLogSoftmax() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_LOG_SOFTMAX_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log_softmax/NegLogSoftmaxKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log_softmax/NegLogSoftmaxKernel.h
new file mode 100644 (file)
index 0000000..b15be46
--- /dev/null
@@ -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.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_NEG_LOG_SOFTMAX_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_LOG_SOFTMAX_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_log_softmax_kernel
+{
+/*
+ * LogSoftmax Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           LogSoftmax
+ *            |
+ *      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, 0x24, 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,
+  0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 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_log_softmax_kernel
+
+class NegTestDataInputOutputTypeMismatchLogSoftmaxKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchLogSoftmaxKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_log_softmax_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchLogSoftmaxKernel() 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_LOG_SOFTMAX_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log_softmax/TestDataLogSoftmaxBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/log_softmax/TestDataLogSoftmaxBase.h
new file mode 100644 (file)
index 0000000..07236cc
--- /dev/null
@@ -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_LOG_SOFTMAX_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_LOG_SOFTMAX_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataLogSoftmaxBase : public TestDataBase<T>
+{
+public:
+  TestDataLogSoftmaxBase() = 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_LOG_SOFTMAX_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_not/BoolLogicalNotKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_not/BoolLogicalNotKernel.h
new file mode 100644 (file)
index 0000000..d39ee5c
--- /dev/null
@@ -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_BOOL_LOGICAL_NOT_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_BOOL_LOGICAL_NOT_KERNEL_H
+
+#include "TestDataLogicalNotBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace logical_not_bool
+{
+/*
+ * LogicalNot Kernel:
+ *
+ *    Input(1, 3, 3, 2)
+ *            |
+ *        LogicalNot
+ *            |
+ *    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, 0x2c, 0x01, 0x00, 0x00, 0x48, 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, 0x3f, 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, 0x44, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 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, 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, 0x06,
+  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, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
+  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> input_data = {false, true,  false, false, true, true, false, false, false,
+                                      false, false, true,  false, true, true, true,  true,  true};
+
+const std::vector<bool> reference_output_data = {true, false, true,  true,  false, false,
+                                                 true, true,  true,  true,  true,  false,
+                                                 true, false, false, false, false, false};
+
+} // namespace logical_not_bool
+
+class TestDataBoolLogicalNot : public TestDataLogicalNotBase<bool>
+{
+public:
+  TestDataBoolLogicalNot()
+  {
+    _input_data = logical_not_bool::input_data;
+    _reference_output_data = logical_not_bool::reference_output_data;
+    _test_kernel_model_circle = logical_not_bool::test_kernel_model_circle;
+  }
+
+  ~TestDataBoolLogicalNot() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_BOOL_LOGICAL_NOT_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_not/NegLogicalNotKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_not/NegLogicalNotKernel.h
new file mode 100644 (file)
index 0000000..14fb434
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_NOT_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_LOGICAL_NOT_KERNEL_H
+
+#include "TestDataLogicalNotBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_wrong_output_type_logical_not_kernel
+{
+/*
+ * LogicalNot Kernel with wrong output type (should be bool):
+ *
+ *      Input(1, 3, 3, 2) - Bool
+ *            |
+ *           LogicalNot
+ *            |
+ *      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, 0x2c, 0x01, 0x00, 0x00, 0x48, 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, 0x3f, 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, 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, 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, 0x06,
+  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, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
+  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_output_type_logical_not_kernel
+
+namespace neg_input_output_shape_mismatch_logical_not_kernel
+{
+/*
+ * LogicalNot Kernel with input output shapes mismatch (should be equal):
+ *
+ *      Input(1, 3, 3, 2) - Bool
+ *            |
+ *           LogicalNot
+ *            |
+ *      Output(1, 3, 3) - Bool
+ */
+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, 0x2c, 0x01, 0x00, 0x00, 0x48, 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, 0x3f, 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, 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, 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, 0x06,
+  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, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
+  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_shape_mismatch_logical_not_kernel
+
+class NegTestDataInputOutputTypeMismatchLogicalNotKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchLogicalNotKernel()
+  {
+    _test_kernel_model_circle = neg_wrong_output_type_logical_not_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchLogicalNotKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInputOutputShapeMismatchLogicalNotKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputShapeMismatchLogicalNotKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_shape_mismatch_logical_not_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputShapeMismatchLogicalNotKernel() 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_NOT_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_not/TestDataLogicalNotBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/logical_not/TestDataLogicalNotBase.h
new file mode 100644 (file)
index 0000000..d57fadb
--- /dev/null
@@ -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_LOGICAL_NOT_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_LOGICAL_NOT_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataLogicalNotBase : public TestDataBase<T>
+{
+public:
+  TestDataLogicalNotBase() = 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_LOGICAL_NOT_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maximum/FloatMaximumKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maximum/FloatMaximumKernel.h
new file mode 100644 (file)
index 0000000..d62a2f0
--- /dev/null
@@ -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_MAXIMUM_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_MAXIMUM_KERNEL_FLOAT_H
+
+#include "TestDataMaximumBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace maximum_float_with_broadcasting
+{
+
+/*
+ * Maximum Kernel:
+ *
+ * Input_1(2, 5)   Input_2(2, 1)
+ *       \             /
+ *     Maximum(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, 0x27, 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,
+  0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 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 = {3.6702812, 3.9503734, 6.2998962, -1.8228233, 1.0596895,
+                                        6.8552585, 6.7857623, 5.0216885, 5.6108203,  -7.2084064};
+const std::vector<float> input2_data = {-7.1075683, 0.7976927};
+const std::vector<float> reference_output_data = {3.6702812, 3.9503734, 6.2998962, -1.8228233,
+                                                  1.0596895, 6.8552585, 6.7857623, 5.0216885,
+                                                  5.6108203, 0.7976927};
+
+} // namespace maximum_float_with_broadcasting
+
+namespace maximum_float_no_broadcasting
+{
+/*
+ * Maximum Kernel:
+ *
+ * Input_1(2, 3)   Input_2(2, 3)
+ *              \             /
+ *          Maximum(no broadcast)
+ *                     |
+ *            Output(2, 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, 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, 0x27, 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, 0x03, 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,
+  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, 0x02, 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,
+  0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 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 = {0.68642193, 1.5050905,   -2.4937015,
+                                  -3.9648914, -0.54440844, 0.884532};
+std::vector<float> input2_data = {-3.052149,  6.7323585,  -7.5222282,
+                                  -7.1619887, -4.9076447, -1.6525323};
+std::vector<float> reference_output_data = {0.68642193, 6.7323585,   -2.4937015,
+                                            -3.9648914, -0.54440844, 0.884532};
+
+} // namespace maximum_float_no_broadcasting
+
+class TestDataFloatMaximum : public TestDataMaximumBase<float>
+{
+public:
+  explicit TestDataFloatMaximum(bool is_with_broadcast)
+    : TestDataMaximumBase<float>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = maximum_float_with_broadcasting::input1_data;
+      _input2_data = maximum_float_with_broadcasting::input2_data;
+      _reference_output_data = maximum_float_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = maximum_float_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = maximum_float_no_broadcasting::input1_data;
+      _input2_data = maximum_float_no_broadcasting::input2_data;
+      _reference_output_data = maximum_float_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = maximum_float_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataFloatMaximum() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_MAXIMUM_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maximum/NegMaximumKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maximum/NegMaximumKernel.h
new file mode 100644 (file)
index 0000000..d464c22
--- /dev/null
@@ -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_NEG_MINIMUM_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_MINIMUM_KERNEL_H
+
+#include "TestDataMaximumBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace input_1_wrong_type
+{
+
+/*
+ * Maximum Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Int32   Input_2(2, 1) - Float
+ *               \             /
+ *           Maximum(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, 0x27, 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,
+  0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 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
+{
+
+/*
+ * Maximum Kernel with input2  type mismatch:
+ *
+ * Input_1(2, 5)- Float   Input_2(2, 1) - Int32
+ *       \             /
+ *     Maximum(with broadcast)
+ *              |
+ *          Output(2, 5) - 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, 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, 0x27, 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,
+  0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 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 NegTestDataInput1WrongTypeMaximum : public NegTestDataBase
+{
+public:
+  NegTestDataInput1WrongTypeMaximum()
+  {
+    _test_kernel_model_circle = input_1_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput1WrongTypeMaximum() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInput2WrongTypeMaximum : public NegTestDataBase
+{
+public:
+  NegTestDataInput2WrongTypeMaximum()
+  {
+    _test_kernel_model_circle = input_2_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput2WrongTypeMaximum() 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_MINIMUM_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maximum/TestDataMaximumBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/maximum/TestDataMaximumBase.h
new file mode 100644 (file)
index 0000000..68053af
--- /dev/null
@@ -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_MAXIMUM_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_MAXIMUM_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataMaximumBase : public TestDataBase<T>
+{
+public:
+  explicit TestDataMaximumBase(bool)
+  {
+    // Do nothing
+  }
+
+  TestDataMaximumBase() = 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_MAXIMUM_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mean/FloatMeanKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mean/FloatMeanKernel.h
new file mode 100644 (file)
index 0000000..909b741
--- /dev/null
@@ -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 LUCI_INTERPRETER_TEST_MODELS_FLOAT_MEAN_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_MEAN_KERNEL_H
+
+#include "TestDataMeanBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace mean_float
+{
+/*
+ * Mean Kernel:
+ *
+ *      Input(1, 8, 8, 4)
+ *            |
+ *           Mean
+ *            |
+ *      Output(1, 8, 8, 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,
+  0x48, 0x00, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0xb0, 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, 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, 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, 0x1b, 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, 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, 0x84, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x94, 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, 0x08, 0x00, 0x00, 0x00, 0x08, 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, 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, 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, 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,
+  0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 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 = {
+  -73.19745,  -62.66789,  -15.868883, -69.99245,  -86.77558,  -47.07158,  -59.42521,  5.4639907,
+  -15.482954, 58.430527,  30.962307,  -8.479264,  64.87171,   67.23879,   54.92413,   -75.001656,
+  4.095402,   -11.012883, 1.7135352,  -13.673498, 87.62411,   88.27154,   86.84994,   61.68961,
+  -67.81691,  -36.073383, 54.346165,  -83.79197,  35.099308,  -23.05919,  26.401726,  20.99549,
+  -68.63421,  -93.027596, 20.0895,    -16.020033, 57.642673,  8.66057,    39.191364,  29.198711,
+  -5.9334397, 11.010835,  82.77485,   -34.213863, -38.869553, 16.539444,  51.105484,  25.632273,
+  -55.436813, -26.42026,  77.96095,   -59.019154, -82.52756,  -94.416176, -83.77591,  46.43875,
+  0.7686069,  57.346397,  -89.24597,  -8.594538,  -98.168755, -33.18969,  -41.993664, 13.660449,
+  50.10378,   9.801906,   -4.2520585, 27.210102,  48.8715,    -19.44194,  38.652195,  23.77053,
+  -82.0674,   -93.96652,  99.148094,  22.794533,  0.5715625,  0.84766275, 87.92019,   37.35077,
+  -32.265865, 67.46462,   -24.098558, 87.36311,   90.409134,  33.023712,  -15.923093, 40.05901,
+  -12.006578, 31.039108,  -63.882004, -73.78517,  -24.940235, 30.9098,    31.745,     -89.77378,
+  -46.777866, 58.79768,   -24.669464, 96.29413,   61.62126,   45.743416,  38.30191,   71.805405,
+  -31.20969,  33.56755,   -1.926614,  72.13441,   -22.292011, -16.355177, 21.689945,  87.95895,
+  -98.04168,  93.35264,   -12.684541, -18.105795, 30.574284,  42.890903,  -94.390366, -47.013157,
+  -98.465126, 28.63009,   -83.54015,  86.82799,   0.6768988,  6.070787,   43.308678,  1.8557712,
+  -73.0521,   -90.86948,  43.77232,   68.301056,  66.867775,  97.34002,   -59.342876, -51.359367,
+  17.27793,   52.223003,  -3.9915564, 29.598532,  34.474148,  -80.920456, -30.45005,  -17.469683,
+  -67.02992,  -34.23075,  -35.53944,  61.557327,  -66.91338,  -94.03176,  -45.88021,  97.36409,
+  96.45681,   -32.885677, 72.40823,   -62.28857,  20.948895,  1.259363,   -84.97583,  60.83626,
+  -94.692535, -15.315798, -99.92936,  40.56625,   -8.6356325, -7.3984733, 56.255993,  -31.700819,
+  62.08311,   52.800938,  32.27374,   -99.46793,  -40.924038, 24.67266,   -58.954403, 42.263252,
+  -72.13501,  -58.40316,  14.619292,  -43.400642, -82.13468,  -47.54976,  -42.642033, -8.409653,
+  74.90983,   97.76474,   -71.152916, 83.61312,   -37.22972,  21.405357,  -56.848846, 90.63024,
+  -70.21143,  -29.522697, 94.9647,    74.74478,   37.564766,  -40.22343,  -63.337795, -65.86191,
+  -48.546135, -58.20052,  36.73888,   67.78194,   -43.096832, 94.7046,    9.798892,   -79.97487,
+  -15.868657, -84.753975, 4.8745494,  -18.346195, 54.9818,    75.854,     41.797707,  -5.673281,
+  -36.31264,  -73.4931,   -41.090492, 6.3805137,  -73.66098,  85.20992,   91.28027,   -73.26658,
+  -92.18044,  41.29011,   5.5041995,  -73.70062,  -16.678818, 30.614132,  92.100555,  11.274231,
+  -37.915485, 34.91591,   36.32971,   -37.70164,  -23.708878, 19.026278,  -41.71216,  67.325356,
+  78.23511,   -43.154037, 22.667723,  30.742237,  -6.086414,  17.191307,  65.828896,  -40.83338,
+  -18.61725,  23.976517,  80.2347,    -92.53064,  71.6477,    -38.28841,  -60.853157, 24.402542};
+
+const std::vector<float> reference_output_data = {
+  -55.431667, -46.952095, 16.357655,   28.008245,  -4.7193613, 81.108795,  -33.334023, 14.859333,
+  -39.398083, 33.673332,  13.409595,   13.601912,  -15.728818, -53.57022,  -9.9313755, -39.922916,
+  20.71593,   22.963072,  -13.522823,  31.672546,  24.615828,  36.89219,   -29.65866,  -13.014804,
+  20.91112,   54.368,     18.141413,   17.750427,  -8.869844,  -16.984585, -16.636799, 12.978033,
+  -12.962048, 13.376387,  23.776978,   -23.59151,  -18.810696, -27.365314, 18.422699,  -0.4828272,
+  -42.342857, 2.1302667,  11.922464,   -8.235632,  -39.82988,  -45.184032, 46.28369,   4.489258,
+  17.493837,  -32.964592, -0.55646133, -4.6420527, -28.523571, 41.74006,   -36.128933, 7.3906593,
+  -29.771688, 29.327526,  -1.0928774,  5.232649,   22.122757,  9.025103,   -1.7341671, -0.7728319};
+
+} // namespace mean_float
+
+class TestDataFloatMean : public TestDataMeanBase<float>
+{
+public:
+  TestDataFloatMean()
+  {
+    _input_data = mean_float::input_data;
+    _reference_output_data = mean_float::reference_output_data;
+    _test_kernel_model_circle = mean_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatMean() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_MEAN_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mean/NegMeanKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mean/NegMeanKernel.h
new file mode 100644 (file)
index 0000000..708f05e
--- /dev/null
@@ -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_MEAN_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_MEAN_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_mean_kernel
+{
+/*
+ * Mean Kernel with input output type mismatch:
+ *
+ *      Input(1, 8, 8, 4) - Float32
+ *            |
+ *           Mean
+ *            |
+ *      Output(1, 8, 8, 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,
+  0x48, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0xb4, 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, 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, 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, 0x1b, 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, 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, 0x88, 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, 0x08, 0x00, 0x00, 0x00, 0x08, 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,
+  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,
+  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, 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, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 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_mean_kernel
+
+class NegTestDataInputOutputTypeMismatchMeanKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchMeanKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_mean_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchMeanKernel() 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_LOG_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mean/TestDataMeanBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mean/TestDataMeanBase.h
new file mode 100644 (file)
index 0000000..8892899
--- /dev/null
@@ -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_MEAN_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_MEAN_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataMeanBase : public TestDataBase<T>
+{
+public:
+  TestDataMeanBase() = 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_MEAN_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/minimum/FloatMinimumKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/minimum/FloatMinimumKernel.h
new file mode 100644 (file)
index 0000000..bf8544a
--- /dev/null
@@ -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_MINIMUM_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_MINIMUM_KERNEL_FLOAT_H
+
+#include "TestDataMinimumBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace minimum_float_with_broadcasting
+{
+
+/*
+ * Minimum Kernel:
+ *
+ * Input_1(2, 5)   Input_2(2, 1)
+ *       \             /
+ *     Minimum(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, 0x27, 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,
+  0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 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 = {3.9078786, 4.825119,   -6.9444265, 0.5244622,  -5.321703,
+                                        -9.686515, -1.3499693, -5.8468533, -0.5371767, 8.364615};
+const std::vector<float> input2_data = {-7.73631, 1.0758704};
+const std::vector<float> reference_output_data = {-7.73631,   -7.73631,  -7.73631,   -7.73631,
+                                                  -7.73631,   -9.686515, -1.3499693, -5.8468533,
+                                                  -0.5371767, 1.0758704};
+
+} // namespace minimum_float_with_broadcasting
+
+namespace minimum_float_no_broadcasting
+{
+/*
+ * Minimum Kernel:
+ *
+ * Input_1(2, 3)   Input_2(2, 3)
+ *              \             /
+ *          Minimum(no broadcast)
+ *                     |
+ *            Output(2, 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, 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, 0x27, 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, 0x03, 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,
+  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, 0x02, 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,
+  0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 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 = {7.1328354,  -3.694989,  -7.1043596,
+                                  -7.4285483, -7.1077704, 3.0919213};
+std::vector<float> input2_data = {-0.31031138, 4.8659816, -9.223121,
+                                  -9.779761,   -4.288633, -3.4242167};
+std::vector<float> reference_output_data = {-0.31031138, -3.694989,  -9.223121,
+                                            -9.779761,   -7.1077704, -3.4242167};
+
+} // namespace minimum_float_no_broadcasting
+
+class TestDataFloatMinimum : public TestDataMinimumBase<float>
+{
+public:
+  explicit TestDataFloatMinimum(bool is_with_broadcast)
+    : TestDataMinimumBase<float>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = minimum_float_with_broadcasting::input1_data;
+      _input2_data = minimum_float_with_broadcasting::input2_data;
+      _reference_output_data = minimum_float_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = minimum_float_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = minimum_float_no_broadcasting::input1_data;
+      _input2_data = minimum_float_no_broadcasting::input2_data;
+      _reference_output_data = minimum_float_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = minimum_float_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataFloatMinimum() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_MINIMUM_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/minimum/NegMinimumKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/minimum/NegMinimumKernel.h
new file mode 100644 (file)
index 0000000..03d7ea5
--- /dev/null
@@ -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_NEG_MINIMUM_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_MINIMUM_KERNEL_H
+
+#include "TestDataMinimumBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace input_1_wrong_type
+{
+
+/*
+ * Minimum Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Int32   Input_2(2, 1) - Float
+ *               \             /
+ *           Minimum(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, 0x27, 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,
+  0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 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
+{
+
+/*
+ * Minimum Kernel with input2  type mismatch:
+ *
+ * Input_1(2, 5)- Float   Input_2(2, 1) - Int32
+ *       \             /
+ *     Minimum(with broadcast)
+ *              |
+ *          Output(2, 5) - 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, 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, 0x27, 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,
+  0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 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 NegTestDataInput1WrongTypeMinimum : public NegTestDataBase
+{
+public:
+  NegTestDataInput1WrongTypeMinimum()
+  {
+    _test_kernel_model_circle = input_1_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput1WrongTypeMinimum() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInput2WrongTypeMinimum : public NegTestDataBase
+{
+public:
+  NegTestDataInput2WrongTypeMinimum()
+  {
+    _test_kernel_model_circle = input_2_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput2WrongTypeMinimum() 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_MINIMUM_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/minimum/TestDataMinimumBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/minimum/TestDataMinimumBase.h
new file mode 100644 (file)
index 0000000..eb9bee6
--- /dev/null
@@ -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_MINIMUM_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_MINIMUM_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataMinimumBase : public TestDataBase<T>
+{
+public:
+  explicit TestDataMinimumBase(bool)
+  {
+    // Do nothing
+  }
+
+  TestDataMinimumBase() = 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_MINIMUM_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mirror_pad/FloatMirrorPadKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mirror_pad/FloatMirrorPadKernel.h
new file mode 100644 (file)
index 0000000..a62c421
--- /dev/null
@@ -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_FLOAT_MIRROR_PAD_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_MIRROR_PAD_KERNEL_H
+
+#include "TestDataMirrorPadBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace mirror_pad_float
+{
+/*
+ * MirrorPad Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           MirrorPad
+ *            |
+ *      Output(1, 5, 7, 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, 0x4d, 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, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64,
+  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 = {-91.67193, 92.42922,  -34.20932, 31.049513, 82.94563,
+                                       -71.50903, 73.466835, 6.7792625, -94.79867, -62.1785,
+                                       95.14197,  -7.264842, -76.86396, 58.690563, -12.9692545,
+                                       77.169426, 52.5776,   62.414425};
+const std::vector<float> reference_output_data = {
+  95.14197,    -7.264842, -94.79867, -62.1785,  73.466835,   6.7792625, -94.79867, -62.1785,
+  95.14197,    -7.264842, -94.79867, -62.1785,  73.466835,   6.7792625, 82.94563,  -71.50903,
+  -34.20932,   31.049513, -91.67193, 92.42922,  -34.20932,   31.049513, 82.94563,  -71.50903,
+  -34.20932,   31.049513, -91.67193, 92.42922,  95.14197,    -7.264842, -94.79867, -62.1785,
+  73.466835,   6.7792625, -94.79867, -62.1785,  95.14197,    -7.264842, -94.79867, -62.1785,
+  73.466835,   6.7792625, 52.5776,   62.414425, -12.9692545, 77.169426, -76.86396, 58.690563,
+  -12.9692545, 77.169426, 52.5776,   62.414425, -12.9692545, 77.169426, -76.86396, 58.690563,
+  95.14197,    -7.264842, -94.79867, -62.1785,  73.466835,   6.7792625, -94.79867, -62.1785,
+  95.14197,    -7.264842, -94.79867, -62.1785,  73.466835,   6.7792625};
+
+} // namespace mirror_pad_float
+
+class TestDataFloatMirrorPad : public TestDataMirrorPadBase<float>
+{
+public:
+  TestDataFloatMirrorPad()
+  {
+    _input_data = mirror_pad_float::input_data;
+    _reference_output_data = mirror_pad_float::reference_output_data;
+    _test_kernel_model_circle = mirror_pad_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatMirrorPad() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_MIRROR_PAD_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mirror_pad/NegMirrorPadKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mirror_pad/NegMirrorPadKernel.h
new file mode 100644 (file)
index 0000000..5571349
--- /dev/null
@@ -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_MIRROR_PAD_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_MIRROR_PAD_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_mirror_pad_kernel
+{
+/*
+ * MirrorPad Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           MirrorPad
+ *            |
+ *      Output(1, 5, 7, 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,
+  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, 0x4d, 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, 0x64, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x64, 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_mirror_pad_kernel
+
+class NegTestDataInputOutputTypeMismatchMirrorPadKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchMirrorPadKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_mirror_pad_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchMirrorPadKernel() 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_MIRROR_PAD_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mirror_pad/TestDataMirrorPadBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/mirror_pad/TestDataMirrorPadBase.h
new file mode 100644 (file)
index 0000000..e726097
--- /dev/null
@@ -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_MIRROR_PAD_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_MIRROR_PAD_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataMirrorPadBase : public TestDataBase<T>
+{
+public:
+  TestDataMirrorPadBase() = 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_MIRROR_PAD_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/prelu/FloatPReluKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/prelu/FloatPReluKernel.h
new file mode 100644 (file)
index 0000000..01a256f
--- /dev/null
@@ -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_PRELU_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_PRELU_KERNEL_FLOAT_H
+
+#include "TestDataPReluBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace prelu_float
+{
+
+/*
+ * PRelu Kernel:
+ *
+ * Input_1(2, 5)   Input_2(2, 1)
+ *       \             /
+ *     PRelu(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,
+  0x34, 0x00, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x74, 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, 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, 0x70, 0x00, 0x00, 0x00,
+  0x34, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x32, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x01, 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, 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, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 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.028845,   -2.256134,  5.871517,  3.6350298,  -1.1245594, -8.281773,  2.9255466,  -5.459926,
+  13.205927,  2.6914148,  7.8167467, -3.0257807, -3.5172105, 12.896618,  -4.804066,  -1.2078629,
+  -3.355052,  2.079568,   11.507849, -4.21969,   5.263505,   5.169158,   8.4644985,  6.6823874,
+  -12.781622, -2.936924,  12.260782, 0.6924944,  13.423675,  8.054682,   -7.9333363, 7.8090687,
+  -17.695854, -3.7374554, 6.134268,  4.91667,    -18.230255, -3.6263142, -10.009817, -4.900553,
+  -2.6339025, 10.807385,  8.37227,   -2.2637882, -3.136509,  1.1572075,  -5.7503166, 6.0806875};
+const std::vector<float> input2_data = {-1.646285, 2.2777863, 8.24495};
+const std::vector<float> reference_output_data = {
+  8.028845,   -5.138991, 5.871517,  3.6350298,  -2.561506,  -68.28281, 2.9255466,  -12.436544,
+  13.205927,  2.6914148, 7.8167467, -24.94741,  5.790331,   12.896618, -39.609287, 1.9884865,
+  -7.6420913, 2.079568,  11.507849, -9.611551,  5.263505,   5.169158,  8.4644985,  6.6823874,
+  21.042192,  -6.689685, 12.260782, 0.6924944,  13.423675,  8.054682,  13.060533,  7.8090687,
+  -145.90144, 6.152917,  6.134268,  4.91667,    30.012197,  -8.259969, -82.53044,  8.067708,
+  -5.999467,  10.807385, 8.37227,   -5.1564255, -25.860361, 1.1572075, -13.097992, 6.0806875};
+
+} // namespace prelu_float
+
+class TestDataFloatPRelu : public TestDataPReluBase<float>
+{
+public:
+  explicit TestDataFloatPRelu() : TestDataPReluBase<float>()
+  {
+    _input1_data = prelu_float::input1_data;
+    _input2_data = prelu_float::input2_data;
+    _reference_output_data = prelu_float::reference_output_data;
+    _test_kernel_model_circle = prelu_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatPRelu() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_PRELU_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/prelu/NegPReluKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/prelu/NegPReluKernel.h
new file mode 100644 (file)
index 0000000..99e36a0
--- /dev/null
@@ -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_PRELU_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_PRELU_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_inputs_type_mismatch_prelu_kernel
+{
+/*
+ * PRelu Kernel with inputs type mismatch:
+ *
+ * Input_1(1, 4, 4, 3)-Int   Input_2(1, 1, 3)-Float
+ *       \             /
+ *            PRelu
+ *              |
+ *       Output(1, 4, 4, 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,
+  0x34, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x84, 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, 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, 0x80, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x98, 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, 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,
+  0x03, 0x00, 0x00, 0x00, 0x01, 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, 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, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 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_prelu_kernel
+
+namespace neg_input_output_type_mismatch_prelu_kernel
+{
+/*
+ * PRelu Kernel with input output types mismatch:
+ *
+ * Input_1(1, 4, 4, 3)-Float   Input_2(1, 1, 3)-Float
+ *       \             /
+ *       PRelu(no broadcast)
+ *              |
+ *          Output(1, 4, 4, 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,
+  0x34, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00, 0x84, 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, 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, 0x80, 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, 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, 0xd4, 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,
+  0x03, 0x00, 0x00, 0x00, 0x01, 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, 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, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 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_prelu_kernel
+
+class NegTestDataInputsTypeMismatchPReluKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputsTypeMismatchPReluKernel()
+  {
+    _test_kernel_model_circle = neg_inputs_type_mismatch_prelu_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputsTypeMismatchPReluKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInputOutputTypeMismatchPReluKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchPReluKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_prelu_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchPReluKernel() 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_PRelu_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/prelu/TestDataPReluBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/prelu/TestDataPReluBase.h
new file mode 100644 (file)
index 0000000..8ce4bb8
--- /dev/null
@@ -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_PRELU_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_PRELU_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataPReluBase : public TestDataBase<T>
+{
+public:
+  TestDataPReluBase() = 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_PRelu_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/quantize/FloatQuantizeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/quantize/FloatQuantizeKernel.h
new file mode 100644 (file)
index 0000000..7e5e3cb
--- /dev/null
@@ -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_QUANTIZE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_QUANTIZE_KERNEL_H
+
+#include "TestDataQuantizeBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace quantize_float
+{
+/*
+ * Quantize Kernel:
+ *
+ *         Input(4)
+ *            |
+ *         Quantize
+ *            |
+ *         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,
+  0x2c, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x78, 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, 0x94, 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,
+  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, 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, 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, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72,
+  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.0429811, 8.062888, 10.98376, 3.8719032};
+
+const std::vector<uint8_t> reference_output_data = {1, 8, 11, 4};
+
+} // namespace quantize_float
+
+class TestDataFloatQuantize : public TestDataQuantizeBase<float, uint8_t>
+{
+public:
+  TestDataFloatQuantize()
+  {
+    _input_data = quantize_float::input_data;
+    _reference_output_data = quantize_float::reference_output_data;
+    _test_kernel_model_circle = quantize_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatQuantize() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_QUANTIZE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/quantize/NegQuantizeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/quantize/NegQuantizeKernel.h
new file mode 100644 (file)
index 0000000..d42a00c
--- /dev/null
@@ -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_QUANTIZE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_QUANTIZE_KERNEL_H
+
+#include "TestDataQuantizeBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace neg_invalid_input_output_shape_mismatch_quantize_kernel
+{
+/*
+ * Quantize Kernel with input-output shape mismatch:
+ *
+ *      Input(4) = Float32
+ *            |
+ *           Quantize
+ *            |
+ *      Output(5) = 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, 0x5c, 0x01, 0x00, 0x00, 0x78, 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, 0x94, 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,
+  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, 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, 0x0c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 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, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72,
+  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_output_shape_mismatch_quantize_kernel
+
+class NegTestDataInputOutputShapeMismatchQuantizeKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputShapeMismatchQuantizeKernel()
+  {
+    _test_kernel_model_circle =
+      neg_invalid_input_output_shape_mismatch_quantize_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputShapeMismatchQuantizeKernel() 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_QUANTIZE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/quantize/TestDataQuantizeBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/quantize/TestDataQuantizeBase.h
new file mode 100644 (file)
index 0000000..412d012
--- /dev/null
@@ -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_QUANTIZE_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_QUANTIZE_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T, typename U> class TestDataQuantizeBase : public TestDataBase<T, U>
+{
+public:
+  TestDataQuantizeBase() = 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_QUANTIZE_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_max/FloatReduceMaxKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_max/FloatReduceMaxKernel.h
new file mode 100644 (file)
index 0000000..7281cfc
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_REDUCE_MAX_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_REDUCE_MAX_KERNEL_H
+
+#include "TestDataReduceMaxBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace reduce_max_float
+{
+/*
+ * ReduceMax Kernel:
+ *
+ *      Input(1, 8, 8, 4)
+ *            |
+ *         ReduceMax
+ *            |
+ *      Output(1, 8, 8, 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,
+  0x48, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0xa4, 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, 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, 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, 0x1b, 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, 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,
+  0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 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, 0x61, 0x78, 0x69, 0x73, 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, 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, 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, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 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 = {
+  -58.396225, -57.8394,   -22.581873, -7.3766093,  50.05206,    44.310944,   -22.120514,
+  89.867386,  -91.13295,  -75.18169,  -33.539833,  54.117905,   -57.211536,  -75.14148,
+  35.73325,   -53.776833, 78.74013,   96.87235,    18.837658,   -21.393923,  79.88659,
+  93.544235,  -21.981659, 20.892723,  -67.582954,  92.50712,    -34.099873,  -98.411545,
+  -3.2956834, -84.42002,  12.189543,  58.688896,   64.54378,    25.744835,   -62.094837,
+  -40.566822, -14.790133, 88.69836,   -0.85036707, -75.469086,  -76.663185,  -73.1051,
+  81.93762,   -36.66421,  22.026539,  78.44858,    -46.12408,   95.41604,    -2.5305836,
+  -44.67528,  -31.300688, -77.539474, -57.611828,  88.97927,    91.47717,    -65.54501,
+  13.034883,  20.921251,  -8.355765,  97.18682,    -46.770386,  -40.81952,   -11.165613,
+  -61.271793, 48.646477,  -58.25151,  -99.41481,   -56.780544,  -91.58536,   29.882515,
+  75.78485,   16.52929,   60.873188,  -88.43013,   71.16324,    -56.13273,   -77.14864,
+  -96.57215,  -62.9608,   -82.15136,  -70.5029,    -57.31731,   -31.835693,  16.929976,
+  -28.129372, 1.0691411,  -78.68238,  73.23079,    9.220803,    71.94672,    -41.762787,
+  52.63332,   -3.018665,  -61.8149,   37.66296,    58.77569,    45.250633,   -60.578415,
+  -17.983448, -72.786026, 92.85505,   21.268763,   51.62619,    -16.931017,  -82.45312,
+  -14.521056, 37.67377,   0.43315408, -52.960613,  24.414982,   7.908148,    44.165127,
+  -12.226681, 82.412865,  -76.48077,  25.110634,   75.99246,    -82.51244,   56.823624,
+  -63.978146, 76.70215,   6.5520577,  43.948025,   77.97921,    66.8605,     -58.332287,
+  -18.538721, 21.059021,  77.90356,   -60.71419,   -41.935356,  -96.56075,   32.188824,
+  73.61105,   -65.56257,  11.194895,  -60.269417,  -34.02883,   13.059088,   -19.561983,
+  -52.756477, 77.42064,   51.02234,   72.507164,   -14.971463,  -22.252535,  80.21801,
+  17.34239,   -99.05458,  70.16757,   -53.11618,   -49.292202,  -10.7446995, -97.751434,
+  15.030712,  24.94627,   15.125146,  65.612595,   -60.434036,  67.13268,    34.535175,
+  47.78571,   -82.69534,  6.3039026,  83.856606,   -40.564785,  -24.283085,  2.700711,
+  -34.432743, 94.35208,   87.09138,   48.820133,   -98.51997,   12.918642,   -99.678535,
+  19.517574,  95.35628,   9.565377,   81.70518,    72.262695,   -64.77105,   63.354713,
+  -24.879864, -35.13848,  29.116499,  -67.15977,   0.082829006, 23.524176,   83.07935,
+  -17.429674, -53.3588,   -7.9096246, 51.51446,    -6.559965,   16.146408,   -70.894936,
+  -6.540736,  47.5225,    -88.1789,   81.44994,    -54.391083,  27.788023,   5.2649994,
+  -16.410364, -20.530712, 27.685137,  4.1711197,   -74.07635,   -75.02475,   35.800602,
+  5.787267,   -31.852463, -31.70899,  -64.29493,   -10.572503,  87.88721,    13.402711,
+  97.945244,  -48.55172,  -69.19836,  -26.148186,  -0.15473571, -22.69506,   7.7602525,
+  82.74399,   -73.62917,  44.55469,   -40.60742,   84.94042,    75.093544,   54.614388,
+  -86.34934,  87.09241,   -71.10903,  18.455446,   94.97241,    -21.166073,  83.72585,
+  70.848335,  -74.588745, 72.356,     -43.17074,   -60.627457,  4.996212,    67.50039,
+  83.59536,   -55.00903,  39.611755,  43.5844,     61.593533,   45.228355,   -30.009733,
+  -49.846306, 27.54924,   85.339745,  -96.16337};
+const std::vector<float> reference_output_data = {
+  -7.3766093, 89.867386, 54.117905, 35.73325,  96.87235,   93.544235, 92.50712,  58.688896,
+  64.54378,   88.69836,  81.93762,  95.41604,  -2.5305836, 91.47717,  97.18682,  -11.165613,
+  48.646477,  75.78485,  71.16324,  -62.9608,  16.929976,  73.23079,  71.94672,  58.77569,
+  45.250633,  92.85505,  37.67377,  44.165127, 82.412865,  75.99246,  77.97921,  66.8605,
+  77.90356,   73.61105,  13.059088, 77.42064,  80.21801,   70.16757,  24.94627,  67.13268,
+  47.78571,   83.856606, 94.35208,  19.517574, 95.35628,   63.354713, 29.116499, 83.07935,
+  51.51446,   81.44994,  27.788023, 27.685137, 35.800602,  87.88721,  97.945244, 7.7602525,
+  82.74399,   84.94042,  94.97241,  83.72585,  72.356,     83.59536,  61.593533, 85.339745};
+
+} // namespace reduce_max_float
+
+class TestDataFloatReduceMax : public TestDataReduceMaxBase<float>
+{
+public:
+  TestDataFloatReduceMax()
+  {
+    _input_data = reduce_max_float::input_data;
+    _reference_output_data = reduce_max_float::reference_output_data;
+    _test_kernel_model_circle = reduce_max_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatReduceMax() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_REDUCE_MAX_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_max/NegReduceMaxKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_max/NegReduceMaxKernel.h
new file mode 100644 (file)
index 0000000..8ca3cbf
--- /dev/null
@@ -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_NEG_REDUCE_MAX_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_REDUCE_MAX_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_reduce_max_kernel
+{
+/*
+ * ReduceMax Kernel with input output type mismatch:
+ *
+ *      Input(1, 8, 8, 4) - Float32
+ *            |
+ *          ReduceMax
+ *            |
+ *      Output(1, 8, 8, 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,
+  0x48, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0xa8, 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, 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, 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, 0x1b, 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, 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, 0x7c, 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, 0x08, 0x00, 0x00, 0x00, 0x08, 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, 0x61, 0x78, 0x69, 0x73, 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,
+  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, 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, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52,
+  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_reduce_max_kernel
+
+class NegTestDataInputOutputTypeMismatchReduceMaxKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchReduceMaxKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_reduce_max_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchReduceMaxKernel() 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_MAX_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_max/TestDataReduceMaxBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/reduce_max/TestDataReduceMaxBase.h
new file mode 100644 (file)
index 0000000..fe01565
--- /dev/null
@@ -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_MAX_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_REDUCE_MAX_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataReduceMaxBase : public TestDataBase<T>
+{
+public:
+  TestDataReduceMaxBase() = 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_MAX_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_nearest_neighbor/FloatResizeNearestNeighborKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_nearest_neighbor/FloatResizeNearestNeighborKernel.h
new file mode 100644 (file)
index 0000000..9b4e7d2
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_NEAREST_NEIGHBOR_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_RESIZE_NEAREST_NEIGHBOR_KERNEL_H
+
+#include "TestDataResizeNearestNeighborBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace resize_nearest_neighbor_float
+{
+/*
+ * ResizeNearestNeighbor Kernel:
+ *
+ *      Input(1, 4, 4, 8)
+ *            |
+ *      ResizeNearestNeighbor
+ *            |
+ *      Output(1, 16, 16, 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,
+  0x4c, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0xa8, 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, 0x10, 0x00, 0x00, 0x00, 0x10, 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, 0x4a, 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, 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, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 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, 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,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 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, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61,
+  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.298298,   -65.56192,  -65.48421,  -51.370033, -37.358875, 68.09911,   -28.049213, -74.103264,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -97.28447,   72.05543,   76.05356,   95.023445,  -27.921726, -11.455247, 31.07193,   -65.78694,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  50.312668,   -46.917915, 31.022425,  -30.1396,   12.878587,  65.19479,   13.271307,  -80.23689,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -0.69525874, 41.214996,  18.559265,  16.980064,  4.0301347,  -28.414703, -59.516068, 62.129013};
+
+const std::vector<float> reference_output_data = {
+  10.298298,   -65.56192,  -65.48421,  -51.370033, -37.358875, 68.09911,   -28.049213, -74.103264,
+  10.298298,   -65.56192,  -65.48421,  -51.370033, -37.358875, 68.09911,   -28.049213, -74.103264,
+  10.298298,   -65.56192,  -65.48421,  -51.370033, -37.358875, 68.09911,   -28.049213, -74.103264,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -97.28447,   72.05543,   76.05356,   95.023445,  -27.921726, -11.455247, 31.07193,   -65.78694,
+  -97.28447,   72.05543,   76.05356,   95.023445,  -27.921726, -11.455247, 31.07193,   -65.78694,
+  -97.28447,   72.05543,   76.05356,   95.023445,  -27.921726, -11.455247, 31.07193,   -65.78694,
+  10.298298,   -65.56192,  -65.48421,  -51.370033, -37.358875, 68.09911,   -28.049213, -74.103264,
+  10.298298,   -65.56192,  -65.48421,  -51.370033, -37.358875, 68.09911,   -28.049213, -74.103264,
+  10.298298,   -65.56192,  -65.48421,  -51.370033, -37.358875, 68.09911,   -28.049213, -74.103264,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -97.28447,   72.05543,   76.05356,   95.023445,  -27.921726, -11.455247, 31.07193,   -65.78694,
+  -97.28447,   72.05543,   76.05356,   95.023445,  -27.921726, -11.455247, 31.07193,   -65.78694,
+  -97.28447,   72.05543,   76.05356,   95.023445,  -27.921726, -11.455247, 31.07193,   -65.78694,
+  10.298298,   -65.56192,  -65.48421,  -51.370033, -37.358875, 68.09911,   -28.049213, -74.103264,
+  10.298298,   -65.56192,  -65.48421,  -51.370033, -37.358875, 68.09911,   -28.049213, -74.103264,
+  10.298298,   -65.56192,  -65.48421,  -51.370033, -37.358875, 68.09911,   -28.049213, -74.103264,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  54.290348,   -39.651768, 96.38616,   98.89169,   -55.091187, -83.808556, -83.01185,  -28.333675,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -50.724545,  3.110519,   21.322432,  9.211258,   25.231798,  46.919487,  99.83142,   55.398502,
+  -97.28447,   72.05543,   76.05356,   95.023445,  -27.921726, -11.455247, 31.07193,   -65.78694,
+  -97.28447,   72.05543,   76.05356,   95.023445,  -27.921726, -11.455247, 31.07193,   -65.78694,
+  -97.28447,   72.05543,   76.05356,   95.023445,  -27.921726, -11.455247, 31.07193,   -65.78694,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  -25.030579,  48.61087,   -4.1321445, 75.28256,   -68.740875, 1.433968,   88.15704,   -6.77664,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  29.764292,   22.71885,   -92.61434,  84.98954,   51.975292,  -39.413055, 7.8604083,  63.997437,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  17.589115,   -59.45725,  83.951096,  -39.29275,  20.051659,  8.571633,   -41.56029,  -23.022821,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  29.8412,     2.6516876,  -47.806282, 69.98114,   -79.093735, -28.039436, -53.41087,  2.8676255,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  21.599058,   55.24438,   28.319221,  -96.02833,  48.20593,   -37.2331,   -51.708584, -51.362064,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  -60.841843,  -6.8476315, -93.64622,  90.07673,   9.962581,   79.38798,   -75.8042,   -57.65992,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  90.61799,    -93.56624,  2.743451,   -22.862207, -66.0843,   7.904722,   29.070421,  -13.117169,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  46.179005,   -46.155643, -65.15945,  -3.1775346, 0.5456849,  -96.185036, -63.52502,  -75.50465,
+  50.312668,   -46.917915, 31.022425,  -30.1396,   12.878587,  65.19479,   13.271307,  -80.23689,
+  50.312668,   -46.917915, 31.022425,  -30.1396,   12.878587,  65.19479,   13.271307,  -80.23689,
+  50.312668,   -46.917915, 31.022425,  -30.1396,   12.878587,  65.19479,   13.271307,  -80.23689,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -0.69525874, 41.214996,  18.559265,  16.980064,  4.0301347,  -28.414703, -59.516068, 62.129013,
+  -0.69525874, 41.214996,  18.559265,  16.980064,  4.0301347,  -28.414703, -59.516068, 62.129013,
+  -0.69525874, 41.214996,  18.559265,  16.980064,  4.0301347,  -28.414703, -59.516068, 62.129013,
+  50.312668,   -46.917915, 31.022425,  -30.1396,   12.878587,  65.19479,   13.271307,  -80.23689,
+  50.312668,   -46.917915, 31.022425,  -30.1396,   12.878587,  65.19479,   13.271307,  -80.23689,
+  50.312668,   -46.917915, 31.022425,  -30.1396,   12.878587,  65.19479,   13.271307,  -80.23689,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -0.69525874, 41.214996,  18.559265,  16.980064,  4.0301347,  -28.414703, -59.516068, 62.129013,
+  -0.69525874, 41.214996,  18.559265,  16.980064,  4.0301347,  -28.414703, -59.516068, 62.129013,
+  -0.69525874, 41.214996,  18.559265,  16.980064,  4.0301347,  -28.414703, -59.516068, 62.129013,
+  50.312668,   -46.917915, 31.022425,  -30.1396,   12.878587,  65.19479,   13.271307,  -80.23689,
+  50.312668,   -46.917915, 31.022425,  -30.1396,   12.878587,  65.19479,   13.271307,  -80.23689,
+  50.312668,   -46.917915, 31.022425,  -30.1396,   12.878587,  65.19479,   13.271307,  -80.23689,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -55.38661,   -46.709187, -1.5717866, -1.8434023, 61.15225,   -19.636839, 28.600264,  69.90152,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -91.06497,   -13.100779, -30.178743, -93.116486, 37.64633,   -60.00845,  64.729324,  -55.224663,
+  -0.69525874, 41.214996,  18.559265,  16.980064,  4.0301347,  -28.414703, -59.516068, 62.129013,
+  -0.69525874, 41.214996,  18.559265,  16.980064,  4.0301347,  -28.414703, -59.516068, 62.129013,
+  -0.69525874, 41.214996,  18.559265,  16.980064,  4.0301347,  -28.414703, -59.516068, 62.129013};
+
+} // namespace resize_nearest_neighbor_float
+
+class TestDataFloatResizeNearestNeighbor : public TestDataResizeNearestNeighborBase<float>
+{
+public:
+  TestDataFloatResizeNearestNeighbor()
+  {
+    _input_data = resize_nearest_neighbor_float::input_data;
+    _reference_output_data = resize_nearest_neighbor_float::reference_output_data;
+    _test_kernel_model_circle = resize_nearest_neighbor_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatResizeNearestNeighbor() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_RESIZE_NEAREST_NEIGHBOR_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_nearest_neighbor/NegResizeNearestNeighborKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_nearest_neighbor/NegResizeNearestNeighborKernel.h
new file mode 100644 (file)
index 0000000..8f6f7b3
--- /dev/null
@@ -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_RESIZE_NEAREST_NEIGHBOR_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_RESIZE_NEAREST_NEIGHBOR_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_resize_nearest_neighbor_kernel
+{
+/*
+ * ResizeNearestNeighbor Kernel with input output type mismatch:
+ *
+ *      Input(1, 4, 4, 8) - Float32
+ *            |
+ *       ResizeNearestNeighbor
+ *            |
+ *      Output(1, 16, 16, 8) - 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, 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, 0x10, 0x00, 0x00, 0x00, 0x10, 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, 0x4a, 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, 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, 0x7c, 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, 0x10, 0x00, 0x00, 0x00,
+  0x10, 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, 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, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 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, 0x61, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x61, 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_resize_nearest_neighbor_kernel
+
+class NegTestDataInputOutputTypeMismatchResizeNearestNeighborKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchResizeNearestNeighborKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_resize_nearest_neighbor_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchResizeNearestNeighborKernel() 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_NEAREST_NEIGHBOR_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_nearest_neighbor/TestDataResizeNearestNeighborBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/resize_nearest_neighbor/TestDataResizeNearestNeighborBase.h
new file mode 100644 (file)
index 0000000..4eea7a1
--- /dev/null
@@ -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_RESIZE_NEAREST_NEIGHBOR_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_RESIZE_NEAREST_NEIGHBOR_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataResizeNearestNeighborBase : public TestDataBase<T>
+{
+public:
+  TestDataResizeNearestNeighborBase() = 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_NEAREST_NEIGHBOR_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/round/FloatRoundKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/round/FloatRoundKernel.h
new file mode 100644 (file)
index 0000000..553b140
--- /dev/null
@@ -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_ROUND_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_ROUND_KERNEL_H
+
+#include "TestDataRoundBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace round_float
+{
+/*
+ * Round Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Round
+ *            |
+ *      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,
+  0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 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 = {-80.601204, 72.38307,  -22.146687, 2.6873038, -7.440473,
+                                       27.860895,  -79.27248, -61.29374,  90.22741,  89.19607,
+                                       31.390116,  50.23514,  60.073032,  61.747887, -72.03697,
+                                       96.049965,  88.859566, -68.925575};
+
+const std::vector<float> reference_output_data = {-81.0, 72.0,  -22.0, 3.0,  -7.0, 28.0,
+                                                  -79.0, -61.0, 90.0,  89.0, 31.0, 50.0,
+                                                  60.0,  62.0,  -72.0, 96.0, 89.0, -69.0};
+
+} // namespace round_float
+
+class TestDataFloatRound : public TestDataRoundBase<float>
+{
+public:
+  TestDataFloatRound()
+  {
+    _input_data = round_float::input_data;
+    _reference_output_data = round_float::reference_output_data;
+    _test_kernel_model_circle = round_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatRound() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_ROUND_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/round/NegRoundKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/round/NegRoundKernel.h
new file mode 100644 (file)
index 0000000..5152d10
--- /dev/null
@@ -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_ROUND_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_ROUND_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_round_kernel
+{
+/*
+ * Round Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Round
+ *            |
+ *      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,
+  0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 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_round_kernel
+
+class NegTestDataInputOutputTypeMismatchRoundKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchRoundKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_round_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchRoundKernel() 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_ROUND_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/round/TestDataRoundBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/round/TestDataRoundBase.h
new file mode 100644 (file)
index 0000000..0178f77
--- /dev/null
@@ -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 TestDataRoundBase : public TestDataBase<T>
+{
+public:
+  TestDataRoundBase() = 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_ROUND_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/rsqrt/FloatRsqrtKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/rsqrt/FloatRsqrtKernel.h
new file mode 100644 (file)
index 0000000..51fa2df
--- /dev/null
@@ -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_RSQRT_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_RSQRT_KERNEL_H
+
+#include "TestDataRsqrtBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace rsqrt_float
+{
+/*
+ * Rsqrt Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Rsqrt
+ *            |
+ *      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,
+  0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 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 = {
+  23.484858, 44.7245,   37.12629,  48.7498,  22.87489, 38.79412, 16.368074, 17.066277, 21.366201,
+  22.673359, 42.429207, 45.798313, 29.01582, 32.38278, 24.38851, 32.807495, 24.529152, 41.338783};
+
+const std::vector<float> reference_output_data = {
+  0.20635073, 0.14952964, 0.16411914, 0.14322327, 0.20908386, 0.16055249,
+  0.2471731,  0.24206422, 0.21633977, 0.21001102, 0.15352091, 0.14776625,
+  0.18564472, 0.17572881, 0.20249178, 0.17458762, 0.2019104,  0.1555325};
+
+} // namespace rsqrt_float
+
+class TestDataFloatRsqrt : public TestDataRsqrtBase<float>
+{
+public:
+  TestDataFloatRsqrt()
+  {
+    _input_data = rsqrt_float::input_data;
+    _reference_output_data = rsqrt_float::reference_output_data;
+    _test_kernel_model_circle = rsqrt_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatRsqrt() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_RSQRT_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/rsqrt/NegRsqrtKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/rsqrt/NegRsqrtKernel.h
new file mode 100644 (file)
index 0000000..0ee2eb5
--- /dev/null
@@ -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_RSQRT_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_RSQRT_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Rsqrt Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Rsqrt
+ *            |
+ *      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,
+  0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 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 NegTestDataInputOutputTypeMismatchRsqrtKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchRsqrtKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchRsqrtKernel() 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_RSQRT_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/rsqrt/TestDataRsqrtBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/rsqrt/TestDataRsqrtBase.h
new file mode 100644 (file)
index 0000000..d0a0cc5
--- /dev/null
@@ -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_RSQRT_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_RSQRT_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataRsqrtBase : public TestDataBase<T>
+{
+public:
+  TestDataRsqrtBase() = 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_RSQRT_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/select_v2/FloatSelectV2Kernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/select_v2/FloatSelectV2Kernel.h
new file mode 100644 (file)
index 0000000..fc73dbd
--- /dev/null
@@ -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_SELECT_V2_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_SELECT_V2_KERNEL_H
+
+#include "TestDataSelectV2Base.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace select_v2_float
+{
+/*
+ * SelectV2 Kernel:
+ *
+ * InputCond(1, 3)     X(1, 3)     Y(1, 3)
+ *            |           |        |
+ *                    SelectV2
+ *                        |
+ *                   Output(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,
+  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, 0x62, 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, 0x94, 0x00, 0x00, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb8, 0xff, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xdc, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x02, 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, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x02, 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, 0x06,
+  0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6e, 0x64, 0x00, 0x00, 0x00, 0x00,
+  0x02, 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, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 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> input_data_1 = {true, false, false};
+
+const std::vector<float> input_data_2 = {1.1, 1.2, 1.3};
+
+const std::vector<float> input_data_3 = {2.1, 2.2, 2.3};
+
+const std::vector<float> reference_output_data = {1.1, 2.2, 2.3};
+
+} // namespace select_v2_float
+
+class TestDataFloatSelectV2 : public TestDataSelectV2Base<float>
+{
+public:
+  TestDataFloatSelectV2()
+  {
+    _input_data_1 = select_v2_float::input_data_1;
+    _input_data_2 = select_v2_float::input_data_2;
+    _input_data_3 = select_v2_float::input_data_3;
+    _reference_output_data = select_v2_float::reference_output_data;
+    _test_kernel_model_circle = select_v2_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSelectV2() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_SELECT_V2_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/select_v2/NegSelectV2Kernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/select_v2/NegSelectV2Kernel.h
new file mode 100644 (file)
index 0000000..0a96f9a
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_SELECT_V2_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SELECT_V2_KERNEL_H
+
+#include "TestDataSelectV2Base.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_select_v2_input_type_mismatch
+{
+
+/*
+ * SelectV2 Kernel with input type mismatch (input_x_type should be equal to input_y_type):
+ *
+ * Input_conv(1, 3) - Bool   input_x(1, 3) - Int32  input_y(1, 3)- Float32
+ *                           \        |         /
+ *                            \       |        /
+ *                                 SelectV2
+ *                                    |
+ *                             Output(1, 4, 4, 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,
+  0x38, 0x00, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0xb8, 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, 0x62, 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, 0x98, 0x00, 0x00, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xdc, 0xff, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x6f, 0x66, 0x6d, 0x00, 0x02, 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, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x65, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xd8, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x02, 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, 0x06, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6e, 0x64,
+  0x00, 0x00, 0x00, 0x00, 0x02, 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, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b,
+  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_select_v2_input_type_mismatch
+
+class NegTestDataInputMismatchSelectV2Kernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputMismatchSelectV2Kernel()
+  {
+    _test_kernel_model_circle = neg_select_v2_input_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputMismatchSelectV2Kernel() 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_TRANSPOSE_CONV_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/select_v2/TestDataSelectV2Base.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/select_v2/TestDataSelectV2Base.h
new file mode 100644 (file)
index 0000000..b0d951a
--- /dev/null
@@ -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_SELECT_V2_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SELECT_V2_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSelectV2Base : public TestDataBase<T>
+{
+public:
+  TestDataSelectV2Base() = 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 1:
+        return _input_data_2;
+      case 2:
+        return _input_data_3;
+      default:
+        assert(false && "Wrong input index");
+    }
+  }
+
+  const std::vector<bool> &get_cond_input() { return _input_data_1; }
+
+  const std::vector<T> &get_output_data_by_index(int i) override final
+  {
+    assert(i == 0);
+    return _reference_output_data;
+  }
+
+protected:
+  std::vector<bool> _input_data_1;
+  std::vector<T> _input_data_2;
+  std::vector<T> _input_data_3;
+  std::vector<T> _reference_output_data;
+  const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SELECT_V2_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sin/FloatSinKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sin/FloatSinKernel.h
new file mode 100644 (file)
index 0000000..3099373
--- /dev/null
@@ -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_FLOAT_SIN_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_SIN_KERNEL_H
+
+#include "TestDataSinBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace sin_float
+{
+/*
+ * Sin Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Sin
+ *            |
+ *      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,
+  0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 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.893156051635742,   1.95573091506958,    -5.393098831176758,   -1.6336439847946167,
+  -9.043712615966797,  -0.7334932088851929, 7.328176975250244,    1.0357639789581299,
+  9.292394638061523,   -1.3363385200500488, 7.083470821380615,    -6.271344184875488,
+  -2.0852465629577637, 9.942416191101074,   -0.12190937995910645, 7.505262851715088,
+  5.940338611602783,   5.232614040374756};
+
+const std::vector<float> reference_output_data = {
+  -0.45143964886665344, 0.9268230199813843,  0.7771261930465698,   -0.9980257153511047,
+  -0.37190958857536316, -0.6694685816764832, 0.8649203777313232,   0.8602521419525146,
+  0.1319969743490219,   -0.9726404547691345, 0.7175549864768982,   0.011840845458209515,
+  -0.8705633878707886,  -0.4948291480541229, -0.12160763889551163, 0.9398112893104553,
+  -0.3361694812774658,  -0.8677073121070862};
+
+} // namespace sin_float
+
+class TestDataFloatSin : public TestDataSinBase<float>
+{
+public:
+  TestDataFloatSin()
+  {
+    _input_data = sin_float::input_data;
+    _reference_output_data = sin_float::reference_output_data;
+    _test_kernel_model_circle = sin_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSin() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_SIN_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sin/NegSinKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sin/NegSinKernel.h
new file mode 100644 (file)
index 0000000..d1c5ac4
--- /dev/null
@@ -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_SIN_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SIN_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Sin Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Sin
+ *            |
+ *      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,
+  0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 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 NegTestDataInputOutputTypeMismatchSinKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSinKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSinKernel() 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_SIN_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sin/TestDataSinBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sin/TestDataSinBase.h
new file mode 100644 (file)
index 0000000..94a3a93
--- /dev/null
@@ -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_SIN_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SIN_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSinBase : public TestDataBase<T>
+{
+public:
+  TestDataSinBase() = 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_SIN_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_batch_nd/FloatSpaceToBatchNDKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_batch_nd/FloatSpaceToBatchNDKernel.h
new file mode 100644 (file)
index 0000000..553572a
--- /dev/null
@@ -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_FLOAT_SPACE_TO_BATCH_ND_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_SPACE_TO_BATCH_ND_KERNEL_H
+
+#include "TestDataSpaceToBatchNDBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace space_to_batch_nd_float
+{
+/*
+ * SpaceToBatchND Kernel:
+ *
+ *      Input(1, 2, 2, 1)
+ *            |
+ *       SpaceToBatchND
+ *            |
+ *      Output(4, 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, 0xdc, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xe2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x02, 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, 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, 0x19, 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, 0x34, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6c, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x73,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 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, 0x14, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 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, 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, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26,
+  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 = {32.4077, -66.77965, 47.65211, 75.57922};
+const std::vector<float> reference_output_data = {32.4077, -66.77965, 47.65211, 75.57922};
+
+} // namespace space_to_batch_nd_float
+
+class TestDataFloatSpaceToBatchND : public TestDataSpaceToBatchNDBase<float>
+{
+public:
+  TestDataFloatSpaceToBatchND()
+  {
+    _input_data = space_to_batch_nd_float::input_data;
+    _reference_output_data = space_to_batch_nd_float::reference_output_data;
+    _test_kernel_model_circle = space_to_batch_nd_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSpaceToBatchND() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_SPACE_TO_BATCH_ND_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_batch_nd/NegSpaceToBatchNDKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_batch_nd/NegSpaceToBatchNDKernel.h
new file mode 100644 (file)
index 0000000..606a333
--- /dev/null
@@ -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_SPACE_TO_BATCH_ND_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SPACE_TO_BATCH_ND_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_space_to_batch_nd_kernel
+{
+/*
+ * SpaceToBatchND kernel with input output type mismatch:
+ *
+ *      Input(1, 2, 2, 1) - Float32
+ *            |
+ *        SpaceToBatchND
+ *            |
+ *      Output(4, 1, 1 , 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,
+  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, 0x2c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xe2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x02, 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, 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, 0x19, 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, 0xb4, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xa0, 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, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
+  0x69, 0x6e, 0x67, 0x73, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x68,
+  0x61, 0x70, 0x65, 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, 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, 0x26, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x26, 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_space_to_batch_nd_kernel
+
+class NegTestDataInputOutputTypeMismatchSpaceToBatchNDKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSpaceToBatchNDKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_space_to_batch_nd_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSpaceToBatchNDKernel() 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_SPACE_TO_BATCH_ND_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_batch_nd/TestDataSpaceToBatchNDBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_batch_nd/TestDataSpaceToBatchNDBase.h
new file mode 100644 (file)
index 0000000..a3827be
--- /dev/null
@@ -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_SPACE_TO_BATCH_ND_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SPACE_TO_BATCH_ND_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSpaceToBatchNDBase : public TestDataBase<T>
+{
+public:
+  TestDataSpaceToBatchNDBase() = 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_SPACE_TO_BATCH_ND_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_depth/FloatSpaceToDepthKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_depth/FloatSpaceToDepthKernel.h
new file mode 100644 (file)
index 0000000..4982d3e
--- /dev/null
@@ -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 LUCI_INTERPRETER_TEST_MODELS_FLOAT_SPACE_TO_DEPTH_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_SPACE_TO_DEPTH_KERNEL_H
+
+#include "TestDataSpaceToDepthBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace space_to_depth_float
+{
+/*
+ * SpaceToDepth Kernel:
+ *
+ *      Input(1, 4, 4, 3)
+ *            |
+ *       SpaceToDepth
+ *            |
+ *      Output(1, 2, 2, 12)
+ */
+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, 0x13, 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, 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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 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, 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, 0x1a, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1a, 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 = {
+  30.991892,  47.0218,    -96.94782,  41.75081,   13.22614,   60.732224, 55.300236,  4.7265563,
+  -96.22574,  -60.987602, -12.473722, -92.82498,  37.063133,  53.67425,  74.06907,   14.154034,
+  -69.062805, 78.23639,   46.7026,    19.651571,  -59.871742, -38.91334, 95.758804,  85.42076,
+  6.2756233,  26.522488,  60.209923,  78.387436,  87.826294,  -61.8489,  -22.721363, 41.05879,
+  76.31915,   17.438269,  54.071205,  -27.286413, 5.965944,   20.973064, -3.8931062, 26.459524,
+  -22.902449, -75.43978,  11.68149,   -78.51755,  10.050673,  86.07591,  5.0900855,  -72.07779};
+
+const std::vector<float> reference_output_data = {
+  30.991892,  47.0218,    -96.94782,  41.75081,  13.22614,   60.732224, 37.063133, 53.67425,
+  74.06907,   14.154034,  -69.062805, 78.23639,  55.300236,  4.7265563, -96.22574, -60.987602,
+  -12.473722, -92.82498,  46.7026,    19.651571, -59.871742, -38.91334, 95.758804, 85.42076,
+  6.2756233,  26.522488,  60.209923,  78.387436, 87.826294,  -61.8489,  5.965944,  20.973064,
+  -3.8931062, 26.459524,  -22.902449, -75.43978, -22.721363, 41.05879,  76.31915,  17.438269,
+  54.071205,  -27.286413, 11.68149,   -78.51755, 10.050673,  86.07591,  5.0900855, -72.07779};
+
+} // namespace space_to_depth_float
+
+class TestDataFloatSpaceToDepth : public TestDataSpaceToDepthBase<float>
+{
+public:
+  TestDataFloatSpaceToDepth()
+  {
+    _input_data = space_to_depth_float::input_data;
+    _reference_output_data = space_to_depth_float::reference_output_data;
+    _test_kernel_model_circle = space_to_depth_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSpaceToDepth() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_SPACE_TO_DEPTH_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_depth/NegSpaceToDepthKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_depth/NegSpaceToDepthKernel.h
new file mode 100644 (file)
index 0000000..09cfcb3
--- /dev/null
@@ -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_TEST_MODELS_NEG_SPACE_TO_DEPTH_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SPACE_TO_DEPTH_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_space_to_depth_kernel
+{
+/*
+ * SpaceToDepth kernel with input output type mismatch:
+ *
+ *      Input(1, 4, 4, 3) - Float32
+ *            |
+ *        SpaceToDepth
+ *            |
+ *      Output(1, 2, 2, 12) - 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, 0x13, 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, 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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 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, 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, 0x1a, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1a, 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_space_to_depth_kernel
+
+class NegTestDataInputOutputTypeMismatchSpaceToDepthKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSpaceToDepthKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_space_to_depth_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSpaceToDepthKernel() 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_SPACE_TO_DEPTH_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_depth/TestDataSpaceToDepthBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/space_to_depth/TestDataSpaceToDepthBase.h
new file mode 100644 (file)
index 0000000..ef4c83d
--- /dev/null
@@ -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_SPACE_TO_DEPTH_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SPACE_TO_DEPTH_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSpaceToDepthBase : public TestDataBase<T>
+{
+public:
+  TestDataSpaceToDepthBase() = 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_SPACE_TO_DEPTH_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sqrt/FloatSqrtKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sqrt/FloatSqrtKernel.h
new file mode 100644 (file)
index 0000000..4f155f6
--- /dev/null
@@ -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_SQRT_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_SQRT_KERNEL_H
+
+#include "TestDataSqrtBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace sqrt_float
+{
+/*
+ * Sqrt Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Sqrt
+ *            |
+ *      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,
+  0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 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 = {
+  14.583464, 44.010857, 30.89816,  52.36842, 31.285244, 46.0197,  30.435776, 27.172525, 41.825855,
+  27.010614, 21.654316, 12.085457, 34.82241, 34.682625, 26.42978, 36.799065, 16.062561, 40.312984};
+
+const std::vector<float> reference_output_data = {
+  3.8188303, 6.634068, 5.5586114, 7.236603,  5.5933213, 6.783782,  5.516863, 5.212727,  6.4672914,
+  5.1971736, 4.65342,  3.4764144, 5.9010515, 5.8891954, 5.1409903, 6.066223, 4.0078125, 6.349251};
+
+} // namespace sqrt_float
+
+class TestDataFloatSqrt : public TestDataSqrtBase<float>
+{
+public:
+  TestDataFloatSqrt()
+  {
+    _input_data = sqrt_float::input_data;
+    _reference_output_data = sqrt_float::reference_output_data;
+    _test_kernel_model_circle = sqrt_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSqrt() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_SQRT_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sqrt/NegSqrtKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sqrt/NegSqrtKernel.h
new file mode 100644 (file)
index 0000000..b846448
--- /dev/null
@@ -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_SQRT_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SQRT_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Sqrt Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Sqrt
+ *            |
+ *      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,
+  0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 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 NegTestDataInputOutputTypeMismatchSqrtKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSqrtKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSqrtKernel() 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_SQRT_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sqrt/TestDataSqrtBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sqrt/TestDataSqrtBase.h
new file mode 100644 (file)
index 0000000..d86fdbf
--- /dev/null
@@ -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_SQRT_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SQRT_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSqrtBase : public TestDataBase<T>
+{
+public:
+  TestDataSqrtBase() = 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_SQRT_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/square/FloatSquareKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/square/FloatSquareKernel.h
new file mode 100644 (file)
index 0000000..62c7857
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_SQUARE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_SQUARE_KERNEL_H
+
+#include "TestDataSquareBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace square_float
+{
+/*
+ * Square Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Square
+ *            |
+ *      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, 0x42, 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,
+  0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 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.40094518661499,    -2.4671132564544678, -1.7699997425079346,  -9.150614738464355,
+  2.7930896282196045,  -2.115478992462158,  -2.631648302078247,   -2.829446792602539,
+  -4.645663261413574,  9.3477144241333,     -0.36478859186172485, 7.513015270233154,
+  6.249550819396973,   -4.590481281280518,  9.549201965332031,    7.113796234130859,
+  -3.2525429725646973, 4.204875946044922};
+
+const std::vector<float> reference_output_data = {
+  19.368318557739258,  6.086647987365723,  3.132899045944214, 83.73374938964844,  7.801349639892578,
+  4.475251197814941,   6.925572872161865,  8.005768775939941, 21.58218765258789,  87.37976837158203,
+  0.13307072222232819, 56.44540023803711,  39.056884765625,   21.072519302368164, 91.187255859375,
+  50.60609817504883,   10.579035758972168, 17.68098258972168};
+
+} // namespace square_float
+
+class TestDataFloatSquare : public TestDataSquareBase<float>
+{
+public:
+  TestDataFloatSquare()
+  {
+    _input_data = square_float::input_data;
+    _reference_output_data = square_float::reference_output_data;
+    _test_kernel_model_circle = square_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSquare() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_SQUARE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/square/NegSquareKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/square/NegSquareKernel.h
new file mode 100644 (file)
index 0000000..3932e33
--- /dev/null
@@ -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_SQUARE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SQUARE_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Square Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Square
+ *            |
+ *      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, 0x42, 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,
+  0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 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 NegTestDataInputOutputTypeMismatchSquareKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSquareKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSquareKernel() 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_SQUARE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/square/TestDataSquareBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/square/TestDataSquareBase.h
new file mode 100644 (file)
index 0000000..2478573
--- /dev/null
@@ -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_SQUARE_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SQUARE_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSquareBase : public TestDataBase<T>
+{
+public:
+  TestDataSquareBase() = 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_SQUARE_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squared_difference/FloatSquaredDifferenceKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squared_difference/FloatSquaredDifferenceKernel.h
new file mode 100644 (file)
index 0000000..5b6fd9b
--- /dev/null
@@ -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_SQUARED_DIFFERENCE_KERNEL_FLOAT_H
+#define LUCI_INTERPRETER_TEST_MODELS_SQUARED_DIFFERENCE_KERNEL_FLOAT_H
+
+#include "TestDataSquaredDifferenceBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace squared_difference_float_with_broadcasting
+{
+
+/*
+ * SquaredDifference Kernel:
+ *
+ * Input_1(1, 4, 4, 3)   Input_2(1, 4, 4, 3)
+ *       \             /
+ *     SquaredDifference(with 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, 0x4c, 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, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63,
+  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 = {
+  33.44,     44.74834,  42.31354,  17.271736,  46.138657, 42.50795,  9.75354,   11.343542,
+  25.705894, 36.687202, 17.357473, 29.17235,   34.9576,   34.23016,  22.528538, 25.484097,
+  38.542297, 32.78322,  31.368523, 52.47518,   29.052322, 35.70844,  19.942907, 30.840899,
+  45.22654,  22.581013, 24.37784,  -7.1113133, 44.58411,  42.722954, 20.67068,  47.006798,
+  40.08999,  25.972889, 51.532227, 15.329674,  22.725258, 37.83095,  24.72808,  32.937607,
+  39.836365, 11.756248, 8.707649,  42.69889,   22.493517, 26.656416, 19.543903, 38.58926};
+const std::vector<float> input2_data = {
+  45.496315, 47.277058, 43.62587,  25.520176, 26.66666,  21.242783, 38.55497,  29.928194,
+  32.247902, 5.110588,  35.261402, 35.692963, 30.808405, 30.916706, 38.445484, 32.367344,
+  20.506172, 21.414955, 39.93972,  34.694054, 36.724403, 17.250431, 34.863686, 32.42676,
+  31.634842, 44.39825,  31.116629, 18.85633,  19.150063, 33.974716, 26.233631, 29.054287,
+  29.618658, 38.05911,  54.44181,  28.360674, 15.703876, 39.576363, 29.899979, 26.719788,
+  56.03285,  50.236435, 41.24733,  31.759392, 47.402603, 34.884254, 38.37292,  18.049467};
+const std::vector<float> reference_output_data = {
+  145.35477,  6.3944097, 1.7222056, 68.03676,  379.15863, 452.20734, 829.52234, 345.38928,
+  42.797863,  997.0826,  320.55066, 42.51839,  17.215816, 10.978975, 253.34918, 47.379093,
+  325.30182,  129.23741, 73.46542,  316.16852, 58.86083,  340.69806, 222.62962, 2.5149617,
+  184.73425,  475.99188, 45.41127,  674.31854, 646.8908,  76.53166,  30.946436, 322.29263,
+  109.648766, 146.0767,  8.465679,  169.80696, 49.29981,  3.0464592, 26.748528, 38.661274,
+  262.32608,  1480.7247, 1058.8308, 119.67264, 620.4626,  67.69733,  354.5319,  421.8831};
+
+} // namespace squared_difference_float_with_broadcasting
+
+class TestDataFloatSquaredDifference : public TestDataSquaredDifferenceBase<float>
+{
+public:
+  TestDataFloatSquaredDifference()
+  {
+
+    _input1_data = squared_difference_float_with_broadcasting::input1_data;
+    _input2_data = squared_difference_float_with_broadcasting::input2_data;
+    _reference_output_data = squared_difference_float_with_broadcasting::reference_output_data;
+    _test_kernel_model_circle =
+      squared_difference_float_with_broadcasting::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSquaredDifference() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_SQUARED_DIFFERENCE_KERNEL_FLOAT_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squared_difference/NegSquaredDifferenceKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squared_difference/NegSquaredDifferenceKernel.h
new file mode 100644 (file)
index 0000000..d22d9db
--- /dev/null
@@ -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_NEG_SQUARED_DIFFERENCE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SQUARED_DIFFERENCE_KERNEL_H
+
+#include "TestDataSquaredDifferenceBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace inputs_type_mismatch
+{
+
+/*
+ * SquaredDifference Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Float   Input_2(2, 1) - Int
+ *       \             /
+ *       SquaredDifference
+ *              |
+ *          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, 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, 0x4c, 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, 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, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63,
+  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 inputs_type_mismatch
+
+class NegTestDataInputsTypeMismatchSquaredDifference : public NegTestDataBase
+{
+public:
+  NegTestDataInputsTypeMismatchSquaredDifference()
+  {
+    _test_kernel_model_circle = inputs_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputsTypeMismatchSquaredDifference() 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_SQUARED_DIFFERENCE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squared_difference/TestDataSquaredDifferenceBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squared_difference/TestDataSquaredDifferenceBase.h
new file mode 100644 (file)
index 0000000..c07dd76
--- /dev/null
@@ -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_SQUARED_DIFFERENCE_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SQUARED_DIFFERENCE_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSquaredDifferenceBase : public TestDataBase<T>
+{
+public:
+  TestDataSquaredDifferenceBase() = 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_SQUARED_DIFFERENCE_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squeeze/FloatSqueezeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squeeze/FloatSqueezeKernel.h
new file mode 100644 (file)
index 0000000..021b685
--- /dev/null
@@ -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.
+ */
+
+#ifndef LUCI_INTERPRETER_TEST_MODELS_FLOAT_SQUEEZE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_SQUEEZE_KERNEL_H
+
+#include "TestDataSqueezeBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace squeeze_float
+{
+/*
+ * Squeeze Kernel: parameters - squeeze_dims [0,3]
+ *
+ *      Input(1, 4, 5, 1)
+ *            |
+ *           Squeeze
+ *            |
+ *      Output(4, 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,
+  0x2c, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x50, 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,
+  0x70, 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, 0x1e, 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, 0x00, 0x00, 0x00, 0x00, 0x03, 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,
+  0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 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, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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,
+  0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 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, -5, -6, -7, -8, -9, -10,
+                                       11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
+
+const std::vector<float> reference_output_data = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10,
+                                                  11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
+
+} // namespace squeeze_float
+
+namespace squeeze_float_no_param
+{
+/*
+ * Squeeze Kernel: no parameters
+ *
+ *      Input(1, 4, 5, 1)
+ *            |
+ *           Squeeze
+ *            |
+ *      Output(4, 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,
+  0x2c, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x48, 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,
+  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, 0x1e, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 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, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x04, 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,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b,
+  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,  5,  6,  7,  8,  9,  10,
+                                       11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
+
+const std::vector<float> reference_output_data = {1,  2,  3,  4,  5,  6,  7,  8,  9,  10,
+                                                  11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
+
+} // namespace squeeze_float_no_param
+
+class TestDataFloatSqueeze : public TestDataSqueezeBase<float>
+{
+public:
+  TestDataFloatSqueeze(bool no_param = false)
+  {
+    if (no_param)
+    {
+      _input_data = squeeze_float_no_param::input_data;
+      _reference_output_data = squeeze_float_no_param::reference_output_data;
+      _test_kernel_model_circle = squeeze_float_no_param::test_kernel_model_circle;
+    }
+    else
+    {
+      _input_data = squeeze_float_no_param::input_data;
+      _reference_output_data = squeeze_float_no_param::reference_output_data;
+      _test_kernel_model_circle = squeeze_float_no_param::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataFloatSqueeze() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_SQUEEZE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squeeze/NegSqueezeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squeeze/NegSqueezeKernel.h
new file mode 100644 (file)
index 0000000..8d05fe7
--- /dev/null
@@ -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_FLOAT_SQUEEZE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_FLOAT_SQUEEZE_KERNEL_H
+
+#include "TestDataSqueezeBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+namespace neg_wrong_parameters_squeeze_float
+{
+/*
+ * Squeeze Kernel: parameters - squeeze_dims [0,1,3]
+ *
+ *      Input(1, 4, 5, 1)
+ *            |
+ *           Squeeze
+ *            |
+ *      Output(4, 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,
+  0x2c, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x54, 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,
+  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, 0x1e, 0x14, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x03, 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, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 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, 0x0c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x04, 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, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 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_parameters_squeeze_float
+
+namespace neg_input_otput_mismatch_squeeze_float
+{
+/*
+ * Squeeze Kernel: parameters - squeeze_dims [0,3]
+ *
+ *      Input(1, 4, 5, 1)
+ *            |
+ *           Squeeze
+ *            |
+ *      Output(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, 0x2c, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x50, 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, 0x70, 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, 0x1e, 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, 0x00, 0x00, 0x00, 0x00, 0x03, 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, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00,
+  0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
+  0x00, 0x00, 0x04, 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, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2b, 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_otput_mismatch_squeeze_float
+
+class NegTestDataWrongParamFloatSqueeze : public NegTestDataBase
+{
+public:
+  NegTestDataWrongParamFloatSqueeze()
+  {
+
+    _test_kernel_model_circle = neg_wrong_parameters_squeeze_float::test_kernel_model_circle;
+  }
+
+  ~NegTestDataWrongParamFloatSqueeze() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestIOMismatchParamFloatSqueeze : public NegTestDataBase
+{
+public:
+  NegTestIOMismatchParamFloatSqueeze()
+  {
+    _test_kernel_model_circle = neg_input_otput_mismatch_squeeze_float::test_kernel_model_circle;
+  }
+
+  ~NegTestIOMismatchParamFloatSqueeze() 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_FLOAT_SQUEEZE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squeeze/TestDataSqueezeBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/squeeze/TestDataSqueezeBase.h
new file mode 100644 (file)
index 0000000..70e9bde
--- /dev/null
@@ -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_SQUEEZE_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SQUEEZE_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSqueezeBase : public TestDataBase<T>
+{
+public:
+  TestDataSqueezeBase() = 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_SQUEEZE_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sum/FloatSumKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sum/FloatSumKernel.h
new file mode 100644 (file)
index 0000000..ade3057
--- /dev/null
@@ -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 LUCI_INTERPRETER_TEST_MODELS_FLOAT_SUM_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_SUM_KERNEL_H
+
+#include "TestDataSumBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace sum_float
+{
+/*
+ * Sum Kernel:
+ *
+ *      Input(1, 8, 8, 4)
+ *            |
+ *           Sum
+ *            |
+ *      Output(1, 8, 8, 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,
+  0x48, 0x00, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00, 0xb0, 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, 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, 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, 0x1b, 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, 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, 0x84, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x94, 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, 0x08, 0x00, 0x00, 0x00, 0x08, 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, 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, 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, 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,
+  0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 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 = {
+  -73.19745,  -62.66789,  -15.868883, -69.99245,  -86.77558,  -47.07158,  -59.42521,  5.4639907,
+  -15.482954, 58.430527,  30.962307,  -8.479264,  64.87171,   67.23879,   54.92413,   -75.001656,
+  4.095402,   -11.012883, 1.7135352,  -13.673498, 87.62411,   88.27154,   86.84994,   61.68961,
+  -67.81691,  -36.073383, 54.346165,  -83.79197,  35.099308,  -23.05919,  26.401726,  20.99549,
+  -68.63421,  -93.027596, 20.0895,    -16.020033, 57.642673,  8.66057,    39.191364,  29.198711,
+  -5.9334397, 11.010835,  82.77485,   -34.213863, -38.869553, 16.539444,  51.105484,  25.632273,
+  -55.436813, -26.42026,  77.96095,   -59.019154, -82.52756,  -94.416176, -83.77591,  46.43875,
+  0.7686069,  57.346397,  -89.24597,  -8.594538,  -98.168755, -33.18969,  -41.993664, 13.660449,
+  50.10378,   9.801906,   -4.2520585, 27.210102,  48.8715,    -19.44194,  38.652195,  23.77053,
+  -82.0674,   -93.96652,  99.148094,  22.794533,  0.5715625,  0.84766275, 87.92019,   37.35077,
+  -32.265865, 67.46462,   -24.098558, 87.36311,   90.409134,  33.023712,  -15.923093, 40.05901,
+  -12.006578, 31.039108,  -63.882004, -73.78517,  -24.940235, 30.9098,    31.745,     -89.77378,
+  -46.777866, 58.79768,   -24.669464, 96.29413,   61.62126,   45.743416,  38.30191,   71.805405,
+  -31.20969,  33.56755,   -1.926614,  72.13441,   -22.292011, -16.355177, 21.689945,  87.95895,
+  -98.04168,  93.35264,   -12.684541, -18.105795, 30.574284,  42.890903,  -94.390366, -47.013157,
+  -98.465126, 28.63009,   -83.54015,  86.82799,   0.6768988,  6.070787,   43.308678,  1.8557712,
+  -73.0521,   -90.86948,  43.77232,   68.301056,  66.867775,  97.34002,   -59.342876, -51.359367,
+  17.27793,   52.223003,  -3.9915564, 29.598532,  34.474148,  -80.920456, -30.45005,  -17.469683,
+  -67.02992,  -34.23075,  -35.53944,  61.557327,  -66.91338,  -94.03176,  -45.88021,  97.36409,
+  96.45681,   -32.885677, 72.40823,   -62.28857,  20.948895,  1.259363,   -84.97583,  60.83626,
+  -94.692535, -15.315798, -99.92936,  40.56625,   -8.6356325, -7.3984733, 56.255993,  -31.700819,
+  62.08311,   52.800938,  32.27374,   -99.46793,  -40.924038, 24.67266,   -58.954403, 42.263252,
+  -72.13501,  -58.40316,  14.619292,  -43.400642, -82.13468,  -47.54976,  -42.642033, -8.409653,
+  74.90983,   97.76474,   -71.152916, 83.61312,   -37.22972,  21.405357,  -56.848846, 90.63024,
+  -70.21143,  -29.522697, 94.9647,    74.74478,   37.564766,  -40.22343,  -63.337795, -65.86191,
+  -48.546135, -58.20052,  36.73888,   67.78194,   -43.096832, 94.7046,    9.798892,   -79.97487,
+  -15.868657, -84.753975, 4.8745494,  -18.346195, 54.9818,    75.854,     41.797707,  -5.673281,
+  -36.31264,  -73.4931,   -41.090492, 6.3805137,  -73.66098,  85.20992,   91.28027,   -73.26658,
+  -92.18044,  41.29011,   5.5041995,  -73.70062,  -16.678818, 30.614132,  92.100555,  11.274231,
+  -37.915485, 34.91591,   36.32971,   -37.70164,  -23.708878, 19.026278,  -41.71216,  67.325356,
+  78.23511,   -43.154037, 22.667723,  30.742237,  -6.086414,  17.191307,  65.828896,  -40.83338,
+  -18.61725,  23.976517,  80.2347,    -92.53064,  71.6477,    -38.28841,  -60.853157, 24.402542};
+
+const std::vector<float> reference_output_data = {
+  -221.72667,  -187.80838, 65.43062,   112.03298,  -18.877445,  324.43518,  -133.33609, 59.437332,
+  -157.59233,  134.69333,  53.63838,   54.407646,  -62.91527,   -214.28088, -39.725502, -159.69167,
+  82.86372,    91.85229,   -54.091293, 126.690186, 98.46331,    147.56876,  -118.63464, -52.059216,
+  83.64448,    217.472,    72.56565,   71.00171,   -35.479378,  -67.93834,  -66.547195, 51.912132,
+  -51.84819,   53.505547,  95.10791,   -94.36604,  -75.24278,   -109.46126, 73.690796,  -1.9313087,
+  -169.37143,  8.521067,   47.689857,  -32.942528, -159.31952,  -180.73613, 185.13477,  17.957031,
+  69.97535,    -131.85837, -2.2258453, -18.56821,  -114.094284, 166.96024,  -144.51573, 29.562637,
+  -119.086754, 117.310104, -4.3715096, 20.930595,  88.49103,    36.10041,   -6.9366684, -3.0913277};
+
+} // namespace sum_float
+
+class TestDataFloatSum : public TestDataSumBase<float>
+{
+public:
+  TestDataFloatSum()
+  {
+    _input_data = sum_float::input_data;
+    _reference_output_data = sum_float::reference_output_data;
+    _test_kernel_model_circle = sum_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSum() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_SUM_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sum/NegSumKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sum/NegSumKernel.h
new file mode 100644 (file)
index 0000000..8e42284
--- /dev/null
@@ -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_NEG_SUM_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SUM_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_sum_kernel
+{
+/*
+ * Sum Kernel with input output type mismatch:
+ *
+ *      Input(1, 8, 8, 4) - Float32
+ *            |
+ *           Sum
+ *            |
+ *      Output(1, 8, 8, 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,
+  0x48, 0x00, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0xb4, 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, 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, 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, 0x1b, 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, 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, 0x88, 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, 0x08, 0x00, 0x00, 0x00, 0x08, 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,
+  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,
+  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, 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, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 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_sum_kernel
+
+class NegTestDataInputOutputTypeMismatchSumKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSumKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_sum_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSumKernel() 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/sum/TestDataSumBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/sum/TestDataSumBase.h
new file mode 100644 (file)
index 0000000..1d96909
--- /dev/null
@@ -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_SUM_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SUM_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSumBase : public TestDataBase<T>
+{
+public:
+  TestDataSumBase() = 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_SUM_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/svdf/FloatSVDFKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/svdf/FloatSVDFKernel.h
new file mode 100644 (file)
index 0000000..708e0ce
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_SVDF_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_SVDF_KERNEL_H
+
+#include "TestDataSVDFBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace svdf_float
+{
+/*
+ * SVDF Kernel:
+ *
+ *      Input(1, 16)
+ *            |
+ *           SVDF
+ *            |
+ *      Output(1, 64)
+ */
+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, 0x19, 0x00, 0x00, 0x50, 0x1b, 0x00, 0x00, 0x6c, 0x1b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x58, 0x19, 0x00, 0x00, 0x4c, 0x19, 0x00, 0x00, 0x44, 0x19, 0x00, 0x00, 0x34, 0x09, 0x00, 0x00,
+  0x1c, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc8, 0xe6, 0xff, 0xff,
+  0xe6, 0xf6, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x35, 0x99, 0x20, 0x3f,
+  0xda, 0x4f, 0xd8, 0xbd, 0x67, 0xa6, 0x33, 0x3f, 0xbb, 0x81, 0x2a, 0x3f, 0x6d, 0x7d, 0x87, 0x3f,
+  0x2d, 0xbd, 0x64, 0x3e, 0xa6, 0x1f, 0x50, 0x3f, 0x98, 0x2e, 0x03, 0xc0, 0xa4, 0x8d, 0xe5, 0x3f,
+  0xe6, 0x11, 0xbc, 0x3f, 0x17, 0xc3, 0x70, 0xbf, 0x54, 0xca, 0x3d, 0x3f, 0x14, 0xdc, 0x1e, 0xbf,
+  0xe1, 0x81, 0x90, 0xbe, 0x8b, 0xa6, 0xf8, 0x3f, 0x5f, 0xbe, 0x79, 0x3e, 0x88, 0x81, 0xb2, 0xbf,
+  0xf8, 0x40, 0x70, 0x3f, 0x7e, 0xc0, 0x0d, 0x40, 0x13, 0x79, 0x08, 0x3f, 0x16, 0xbf, 0xf4, 0x3e,
+  0xfb, 0xd9, 0xa3, 0x3f, 0xd4, 0x08, 0x86, 0x3f, 0x14, 0xd3, 0xb8, 0x3e, 0xe5, 0x82, 0x36, 0x3f,
+  0xb6, 0xd8, 0xdf, 0xbf, 0xfa, 0x99, 0x00, 0x3e, 0xcc, 0xb9, 0x42, 0x3f, 0x3e, 0x3a, 0x29, 0xbf,
+  0x1c, 0x2a, 0xa4, 0xbe, 0x4d, 0x34, 0x4c, 0x3f, 0x2f, 0x5b, 0x0f, 0x3f, 0xe9, 0x7c, 0x1e, 0xbf,
+  0x6d, 0x5a, 0x8f, 0x3f, 0x42, 0x07, 0xa8, 0x3f, 0x37, 0x59, 0x26, 0x3f, 0x4b, 0xf0, 0xe2, 0xbf,
+  0x9b, 0x10, 0xaa, 0x3c, 0xd1, 0x74, 0x0b, 0xbf, 0xed, 0xfd, 0xe1, 0x3d, 0xd8, 0x76, 0x97, 0x3f,
+  0x8e, 0x81, 0xd3, 0x3e, 0xc7, 0x97, 0x2e, 0x3f, 0x61, 0xf6, 0x0b, 0x3e, 0xd6, 0xff, 0x90, 0xbf,
+  0x1f, 0xe6, 0x83, 0xbe, 0x8c, 0x42, 0x54, 0x3f, 0x3c, 0x95, 0x24, 0x3f, 0xd2, 0x7f, 0x94, 0xbf,
+  0x2a, 0x18, 0xa5, 0xbf, 0xdc, 0x72, 0xa7, 0xbf, 0x2d, 0x54, 0x84, 0xbf, 0x88, 0xc1, 0xf7, 0xbe,
+  0x7b, 0xe8, 0x99, 0xbe, 0x09, 0x21, 0xd2, 0x3f, 0x47, 0xa1, 0x92, 0xbf, 0x13, 0xa3, 0x52, 0x3f,
+  0x5b, 0x23, 0x3f, 0x3f, 0xb2, 0xf2, 0xdd, 0xbf, 0x0c, 0xd7, 0x07, 0xbf, 0x68, 0xc5, 0x32, 0xbf,
+  0x94, 0xbf, 0x30, 0x3e, 0x90, 0x1e, 0x55, 0x3f, 0x96, 0x51, 0x28, 0xbf, 0xf2, 0xf7, 0xff, 0xff,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0c, 0x6e, 0x8f, 0x3c, 0x43, 0x1d, 0xc2, 0x3e,
+  0x4a, 0xec, 0xc2, 0x3f, 0xce, 0x89, 0x27, 0x3e, 0xd9, 0xe0, 0x2c, 0xbf, 0xe4, 0x54, 0x22, 0xbf,
+  0xae, 0x26, 0xb4, 0xbe, 0x81, 0xf4, 0x49, 0x3e, 0x87, 0x1c, 0xf6, 0xbe, 0xd9, 0x78, 0x1b, 0xbf,
+  0x2b, 0xa6, 0xd3, 0x3f, 0x25, 0x20, 0x3e, 0x3f, 0xd6, 0x2c, 0xa7, 0x3f, 0x62, 0xed, 0x0c, 0x3f,
+  0x20, 0x6e, 0xc6, 0x3e, 0x87, 0x31, 0x10, 0xc0, 0xf1, 0x84, 0x50, 0xbf, 0x22, 0xf6, 0x03, 0xbf,
+  0xff, 0x80, 0xf1, 0xbf, 0x65, 0xfc, 0x82, 0xbf, 0x37, 0x0b, 0x01, 0xc0, 0x90, 0x38, 0x98, 0x3f,
+  0x03, 0x5a, 0xa9, 0xbf, 0x0b, 0x95, 0x9d, 0x3e, 0x5c, 0xb7, 0x70, 0x3f, 0x9d, 0xff, 0x65, 0x3f,
+  0x99, 0x25, 0xa6, 0x3e, 0xbd, 0x5c, 0x84, 0x3e, 0xa9, 0xb4, 0x50, 0xbf, 0xae, 0x70, 0x4e, 0x3f,
+  0x60, 0x8c, 0x83, 0x3f, 0xd0, 0xc5, 0xc6, 0x3f, 0x7b, 0x70, 0xd0, 0x3d, 0xa9, 0xc1, 0x76, 0xbf,
+  0x39, 0x37, 0xb2, 0xbe, 0xea, 0x40, 0xbd, 0xbd, 0x31, 0x2b, 0x86, 0x3f, 0xb6, 0x28, 0xc5, 0xbf,
+  0x92, 0x9a, 0x8e, 0x3e, 0x86, 0x10, 0x1c, 0x3e, 0xd8, 0x24, 0x9e, 0xbf, 0xac, 0x22, 0xa1, 0x3d,
+  0x78, 0xee, 0xed, 0xbf, 0x68, 0xce, 0x1d, 0x40, 0xf6, 0x1b, 0xdf, 0x3e, 0x97, 0x10, 0x44, 0x3e,
+  0x52, 0xde, 0x19, 0x3f, 0x1c, 0xbd, 0xfd, 0xbf, 0xa1, 0x64, 0x4c, 0x3f, 0x1b, 0xaa, 0x00, 0xbf,
+  0x36, 0xa7, 0x11, 0xbe, 0x6e, 0xdf, 0x9b, 0xbf, 0x3d, 0xc8, 0x11, 0x40, 0xda, 0x8f, 0xc9, 0x3f,
+  0x36, 0x26, 0x99, 0xbf, 0x54, 0x0f, 0x7a, 0x3f, 0x3e, 0x41, 0x64, 0x3d, 0xc5, 0xd4, 0x54, 0xc0,
+  0xb2, 0x18, 0xa6, 0x3e, 0xd3, 0xed, 0x3c, 0xbe, 0xea, 0x0c, 0x7f, 0xbf, 0xf6, 0xd5, 0xd7, 0xbe,
+  0xf8, 0x29, 0x65, 0xbd, 0x79, 0x6e, 0x6a, 0xbf, 0x78, 0x61, 0xde, 0x3f, 0x18, 0xef, 0x7d, 0xbf,
+  0xde, 0x29, 0x42, 0x3f, 0x21, 0xfc, 0x0c, 0xbf, 0x90, 0x77, 0x82, 0x3f, 0x85, 0x5e, 0x14, 0xc0,
+  0xfd, 0x7d, 0xf2, 0x3e, 0x3f, 0x7a, 0xc9, 0xbf, 0x70, 0x99, 0x5b, 0x3f, 0x63, 0xe9, 0x1c, 0x3e,
+  0x29, 0x07, 0x95, 0xbe, 0xa9, 0x3e, 0x0e, 0x3f, 0x2f, 0x57, 0x67, 0x3e, 0x18, 0xe0, 0xb4, 0xbe,
+  0xcb, 0x10, 0xe4, 0x3e, 0xc5, 0xd6, 0xa2, 0xbd, 0x7f, 0x1a, 0x59, 0x3e, 0xf3, 0x3b, 0x62, 0x3f,
+  0xad, 0x5f, 0x18, 0x3f, 0x87, 0x9a, 0x52, 0x3e, 0x6c, 0x91, 0xc2, 0xbf, 0x32, 0xcc, 0xb9, 0xbf,
+  0x17, 0x14, 0xc2, 0x3f, 0xed, 0xbb, 0x73, 0x3f, 0xe2, 0xba, 0x10, 0xbf, 0x62, 0x23, 0xc3, 0xbf,
+  0x05, 0x41, 0xed, 0xbe, 0xc9, 0x13, 0xca, 0xbe, 0xa1, 0x7f, 0x8d, 0xbe, 0x1b, 0x08, 0x09, 0x3f,
+  0xfe, 0xc7, 0x39, 0x3f, 0x41, 0x06, 0x0f, 0xc0, 0xdd, 0x06, 0xdb, 0x3f, 0x96, 0x5f, 0x07, 0x3e,
+  0x37, 0x22, 0x66, 0xbf, 0x59, 0xf4, 0xfd, 0xbf, 0x00, 0x6f, 0x68, 0xbd, 0x2e, 0x62, 0x0f, 0xc0,
+  0xf3, 0xb0, 0xc5, 0xbf, 0xb8, 0xaa, 0x62, 0xbf, 0x9b, 0x00, 0x4f, 0x3f, 0xec, 0xbd, 0xfe, 0x3e,
+  0x4e, 0x7e, 0xc4, 0xbc, 0x8e, 0x8d, 0xa7, 0x3f, 0xef, 0xa5, 0xfb, 0xbf, 0xaf, 0x17, 0x92, 0xbf,
+  0xe5, 0x98, 0xc5, 0xbf, 0x6d, 0x3a, 0x19, 0x3f, 0x25, 0x29, 0x57, 0xbf, 0x80, 0x58, 0x00, 0x3f,
+  0x10, 0x21, 0x80, 0xbe, 0x19, 0x5c, 0x50, 0xbe, 0x4f, 0xb2, 0x71, 0x3f, 0x4b, 0xa0, 0x2f, 0x3f,
+  0x0f, 0xcf, 0x82, 0xbd, 0x51, 0x86, 0x8b, 0x3f, 0x33, 0xa9, 0x83, 0xbf, 0xa4, 0x21, 0x53, 0x3e,
+  0xae, 0x6a, 0x08, 0x3c, 0x23, 0xf4, 0xb6, 0x3f, 0xb2, 0x5b, 0xcc, 0x3e, 0xf3, 0xd1, 0x5c, 0x3f,
+  0xea, 0x1c, 0xeb, 0x3e, 0xe9, 0x4e, 0x03, 0xbf, 0x30, 0x56, 0xe6, 0xbe, 0x17, 0xf5, 0xc4, 0xbd,
+  0x94, 0x41, 0xcf, 0x3f, 0x0c, 0xb2, 0xec, 0x3f, 0xcb, 0xc5, 0x99, 0xbe, 0x05, 0x18, 0xa6, 0x3f,
+  0x1d, 0x06, 0x1a, 0xbf, 0xbe, 0x1d, 0x0a, 0x40, 0xad, 0x0e, 0xb4, 0x3f, 0x51, 0xd6, 0x25, 0xbf,
+  0x61, 0x87, 0xa7, 0xbf, 0x13, 0x07, 0x7a, 0x3e, 0xc6, 0x13, 0xe0, 0xbe, 0x1f, 0xfe, 0x42, 0xbf,
+  0x26, 0x9c, 0x96, 0xbe, 0x15, 0x1f, 0xdf, 0x3e, 0x80, 0x11, 0x06, 0xbd, 0xf5, 0x7f, 0x03, 0x3d,
+  0x9c, 0x46, 0x5f, 0xbe, 0xe9, 0x86, 0x2b, 0x3f, 0x3e, 0x82, 0x02, 0xc0, 0x70, 0xa4, 0xd9, 0x3f,
+  0x05, 0xcf, 0xf8, 0xbe, 0xb3, 0x0a, 0x9d, 0xbf, 0x20, 0xfc, 0x87, 0xbf, 0xec, 0xe9, 0x1a, 0x3f,
+  0x37, 0x5f, 0x4f, 0xbe, 0xc6, 0x3d, 0x0f, 0xbf, 0x9d, 0x72, 0xa4, 0xbf, 0x87, 0x45, 0x87, 0xbd,
+  0xb8, 0xc2, 0x60, 0xbe, 0x65, 0x2e, 0xe0, 0x3f, 0x69, 0xaa, 0xbc, 0x3e, 0xb5, 0xc4, 0x2c, 0xbf,
+  0x62, 0x2d, 0x4c, 0x3e, 0x5d, 0x10, 0x09, 0xbe, 0x75, 0xe9, 0x0e, 0xbf, 0x88, 0x3a, 0x46, 0x3e,
+  0xd1, 0x5b, 0x86, 0x3f, 0x10, 0x73, 0x36, 0xbf, 0x8c, 0x9d, 0xfb, 0x3e, 0xd6, 0x35, 0xac, 0x3f,
+  0x3b, 0x14, 0xe1, 0xbe, 0xab, 0xe9, 0xc0, 0x3f, 0x1c, 0x97, 0xe9, 0x3d, 0xdf, 0x26, 0xac, 0x3e,
+  0x67, 0x88, 0x59, 0xbf, 0x4e, 0xf7, 0xb8, 0xbf, 0x52, 0x85, 0x46, 0x3f, 0xa7, 0x8b, 0x0c, 0x3f,
+  0x2a, 0x14, 0x48, 0xbe, 0x13, 0x62, 0xe6, 0xbf, 0x5d, 0x88, 0x18, 0x3f, 0xea, 0x9c, 0x17, 0x40,
+  0x20, 0x77, 0xb0, 0xbf, 0x71, 0xb1, 0x56, 0x3f, 0x4e, 0x88, 0xcc, 0xbf, 0x2f, 0x42, 0x00, 0x40,
+  0x2d, 0x52, 0x4a, 0xbf, 0x08, 0x8d, 0xff, 0x3f, 0x6e, 0x6f, 0x05, 0x3f, 0xcc, 0x05, 0x5e, 0x3f,
+  0xe0, 0x25, 0x24, 0x3f, 0xd0, 0xaf, 0x15, 0x40, 0xb7, 0x6a, 0xba, 0xbe, 0x51, 0xeb, 0x83, 0xbe,
+  0x0b, 0x12, 0x58, 0x3e, 0x4e, 0x78, 0xe3, 0x3f, 0xcb, 0x34, 0xa1, 0x3f, 0xb6, 0xb4, 0x85, 0xbf,
+  0x27, 0xf2, 0xf7, 0x3d, 0xee, 0x30, 0x27, 0xbf, 0x5f, 0xd1, 0x53, 0xbf, 0xf0, 0x42, 0x0c, 0xbf,
+  0xa0, 0x57, 0xad, 0xbf, 0x47, 0x27, 0xcb, 0x3f, 0xfb, 0x02, 0xb5, 0x3e, 0x06, 0xb4, 0xfa, 0xbf,
+  0xab, 0x85, 0x0c, 0x3f, 0x41, 0x8f, 0xb6, 0xbf, 0x01, 0xca, 0x1b, 0x3f, 0xd3, 0xf1, 0x48, 0x40,
+  0x40, 0x4c, 0x01, 0x40, 0x60, 0xb3, 0x2c, 0x3f, 0x48, 0x48, 0xce, 0x3b, 0x6e, 0x7d, 0x50, 0x3e,
+  0xe9, 0xbf, 0x6e, 0xbf, 0x5e, 0x24, 0x13, 0x3f, 0x65, 0x3a, 0x80, 0xbf, 0x07, 0x43, 0x86, 0x3e,
+  0x66, 0x9d, 0x76, 0xbf, 0x46, 0xb3, 0x42, 0xbf, 0x3a, 0x69, 0xc9, 0xbf, 0xb8, 0x61, 0x6f, 0x3f,
+  0xc8, 0xbd, 0xd4, 0x3f, 0x74, 0x73, 0x98, 0x3f, 0x92, 0x49, 0x05, 0xc0, 0xbe, 0x9d, 0xb5, 0x3e,
+  0x9d, 0x72, 0x58, 0x3f, 0x12, 0x29, 0x78, 0x3d, 0x74, 0x96, 0xf1, 0xbe, 0x02, 0xab, 0x02, 0xbf,
+  0xca, 0xf9, 0x18, 0xbe, 0xb0, 0x33, 0x6b, 0xbf, 0xd7, 0x1e, 0x89, 0xbf, 0xb0, 0xc5, 0x26, 0xbf,
+  0x99, 0xcf, 0xd0, 0x3e, 0xb1, 0xae, 0x68, 0xbf, 0xb7, 0xc3, 0xd0, 0xbe, 0x1a, 0x33, 0x37, 0xbf,
+  0x4d, 0xf8, 0x95, 0xbf, 0xb4, 0x3e, 0x8e, 0xbf, 0x25, 0x81, 0x6f, 0x3f, 0x78, 0x33, 0xd2, 0xbf,
+  0x16, 0x3b, 0xf2, 0x3d, 0x8f, 0x27, 0x53, 0x3f, 0x08, 0x75, 0x27, 0x40, 0x2f, 0x89, 0xd1, 0xbe,
+  0xd8, 0x59, 0xb8, 0x3e, 0x41, 0x36, 0x1a, 0xbf, 0xa5, 0x92, 0x01, 0x3e, 0x90, 0xef, 0xb9, 0x3f,
+  0xcf, 0x82, 0x8d, 0xbf, 0x04, 0x60, 0x54, 0xbe, 0x93, 0xc2, 0xf1, 0x3f, 0xbb, 0x09, 0x36, 0xbf,
+  0xf8, 0x6b, 0x59, 0x3f, 0x01, 0xa7, 0x8f, 0x3f, 0xd3, 0x11, 0x33, 0xbf, 0xed, 0x9d, 0xc7, 0x3f,
+  0x55, 0x60, 0x1d, 0x3e, 0x46, 0xff, 0x08, 0xbf, 0xcf, 0xc5, 0xd3, 0xbf, 0x4c, 0xa6, 0x35, 0xbf,
+  0x86, 0x41, 0x49, 0xbf, 0x56, 0xef, 0xb1, 0xbf, 0x2c, 0x62, 0x54, 0xbf, 0xe7, 0x81, 0x7a, 0x3f,
+  0x38, 0x4b, 0x80, 0x3f, 0xd5, 0x37, 0xf3, 0xbf, 0x0c, 0x67, 0xa7, 0x3f, 0xb7, 0xbf, 0x32, 0x3e,
+  0xa1, 0x05, 0x36, 0xbf, 0x0c, 0x7b, 0x95, 0x3f, 0x8d, 0xd0, 0x86, 0xbf, 0x3b, 0x74, 0xe9, 0xbe,
+  0x02, 0x76, 0xb1, 0xbe, 0x6b, 0xbe, 0xb3, 0xbf, 0x12, 0xda, 0x8f, 0xbf, 0xc3, 0x7d, 0x2c, 0xbf,
+  0x0a, 0x9a, 0x14, 0x3f, 0xf3, 0xbb, 0x77, 0x3f, 0x5d, 0x8f, 0x87, 0xbf, 0x2c, 0x03, 0xdc, 0x3f,
+  0xc0, 0xb0, 0xd0, 0x3f, 0x7f, 0xde, 0x47, 0x3f, 0x02, 0xc0, 0x98, 0xbf, 0xec, 0x93, 0x08, 0xc0,
+  0x8e, 0x78, 0x9f, 0x3f, 0x27, 0xc5, 0x85, 0x3f, 0xa1, 0x13, 0x40, 0x3f, 0x77, 0xec, 0xc5, 0xbf,
+  0x88, 0x7a, 0x6d, 0xbe, 0x96, 0xa1, 0xa9, 0xbf, 0x0e, 0x67, 0xb9, 0x3f, 0xa0, 0x0e, 0xa9, 0xbf,
+  0x61, 0xce, 0x4c, 0x3f, 0xcb, 0xd4, 0x73, 0xbf, 0xf6, 0x2d, 0xb6, 0x3e, 0xa0, 0xd3, 0xb4, 0xbf,
+  0x42, 0x20, 0x21, 0xbf, 0xf3, 0xf2, 0x00, 0xbf, 0xe3, 0x01, 0x92, 0x3f, 0x19, 0x4f, 0x3f, 0xbf,
+  0xb4, 0x47, 0x28, 0xbf, 0x22, 0xa3, 0x94, 0x3f, 0x90, 0x21, 0x9a, 0xbf, 0x35, 0xdd, 0x62, 0xbf,
+  0x50, 0x78, 0x8b, 0xbe, 0x9e, 0xac, 0x7d, 0x3f, 0xb3, 0x12, 0xaf, 0x3f, 0x5b, 0x3e, 0xbb, 0x3d,
+  0x85, 0xcf, 0x87, 0xbf, 0x51, 0xa3, 0xb5, 0x3f, 0x91, 0x6f, 0xbd, 0xbf, 0xb6, 0x66, 0x3a, 0xbf,
+  0x0c, 0x74, 0xc1, 0x3f, 0xa6, 0x79, 0x0b, 0x3f, 0x77, 0x2f, 0x51, 0x3f, 0x3d, 0x3c, 0x51, 0xbf,
+  0x3e, 0x83, 0x64, 0xbf, 0xab, 0x82, 0xd7, 0xbe, 0x2c, 0xdf, 0x9f, 0xbe, 0x73, 0x76, 0x1f, 0xbf,
+  0x53, 0xfd, 0xf0, 0xbd, 0xec, 0xb5, 0x8a, 0xbf, 0x4b, 0xc8, 0x6e, 0xbf, 0xc6, 0xd2, 0xc4, 0x3e,
+  0x27, 0xc9, 0x77, 0x3d, 0xce, 0x0e, 0x5a, 0x3e, 0x7d, 0xbe, 0x22, 0x3f, 0x5b, 0xc8, 0x9a, 0x3e,
+  0xe4, 0x5f, 0x9b, 0x3f, 0x18, 0x35, 0x41, 0xbf, 0x5d, 0x5c, 0xd5, 0x3e, 0x46, 0x06, 0x43, 0xbe,
+  0xb9, 0x0b, 0x80, 0x3f, 0x70, 0x5a, 0x47, 0x3f, 0xb6, 0x48, 0xa8, 0x3e, 0x5c, 0x5e, 0x24, 0xbf,
+  0x8d, 0x46, 0x6c, 0xbe, 0x53, 0x39, 0xf7, 0xbe, 0xac, 0xae, 0x8a, 0xbe, 0x56, 0x69, 0xe2, 0xbf,
+  0x1e, 0xb3, 0x85, 0x3f, 0x5a, 0x79, 0x75, 0xbf, 0x9e, 0x78, 0x16, 0x3f, 0xbf, 0xf0, 0x50, 0xbf,
+  0x64, 0x26, 0x1e, 0xbd, 0xd4, 0x6a, 0x97, 0xbe, 0xf5, 0x47, 0xab, 0xbf, 0xca, 0x3a, 0x85, 0x3f,
+  0x25, 0xbf, 0x58, 0xbf, 0x3c, 0x13, 0xf2, 0x3c, 0x0b, 0x0c, 0xa9, 0xbf, 0xea, 0xf8, 0xf8, 0x3f,
+  0x8a, 0x5a, 0xe4, 0x3e, 0xa2, 0x6e, 0x44, 0xbf, 0x37, 0x66, 0x88, 0xbf, 0xa5, 0x52, 0xb2, 0xbf,
+  0xef, 0x3f, 0xd5, 0xbf, 0x0b, 0x74, 0x31, 0xbe, 0x74, 0x86, 0x5b, 0xbf, 0x6f, 0x58, 0x5d, 0xbf,
+  0x94, 0x04, 0xdc, 0x3f, 0xc4, 0x9e, 0x55, 0x3e, 0x3b, 0x18, 0x07, 0xbf, 0x8d, 0x07, 0x7a, 0x3f,
+  0xb9, 0x29, 0x15, 0xc0, 0xc7, 0xa1, 0xd1, 0x3e, 0x3c, 0x44, 0x98, 0xbd, 0x60, 0xce, 0x09, 0xbf,
+  0xf7, 0x72, 0x85, 0xbe, 0x38, 0x6e, 0x05, 0xc0, 0x98, 0xee, 0xc2, 0xbf, 0x45, 0x73, 0xaa, 0xbd,
+  0x3c, 0xef, 0xc9, 0xbf, 0x13, 0x64, 0xb4, 0x3f, 0x26, 0x6b, 0x38, 0x3f, 0x52, 0x90, 0xca, 0xbf,
+  0x9c, 0x66, 0xd1, 0x3f, 0x77, 0x8d, 0x2d, 0xbf, 0x84, 0xe2, 0x91, 0xbe, 0x9b, 0x02, 0x19, 0x3f,
+  0x27, 0x9c, 0x82, 0xbf, 0x38, 0xb1, 0x77, 0x3f, 0x75, 0xbd, 0x5f, 0x3f, 0x30, 0xa6, 0x0c, 0xbd,
+  0xc8, 0xc5, 0xa9, 0x3e, 0xba, 0x84, 0x40, 0xbe, 0xb6, 0x11, 0xd8, 0xbd, 0xdd, 0x1c, 0x27, 0xbf,
+  0x63, 0x10, 0x0c, 0x40, 0xbc, 0xfc, 0x24, 0xbf, 0x70, 0xc8, 0x82, 0xbf, 0x5b, 0x57, 0x51, 0x3e,
+  0x35, 0xb6, 0x86, 0x3f, 0xa2, 0x44, 0x0e, 0x40, 0xbf, 0x7e, 0x8c, 0x3e, 0x4c, 0x6b, 0x96, 0x3f,
+  0xc0, 0x85, 0xcb, 0x3e, 0x64, 0x83, 0x86, 0xbf, 0xe3, 0x41, 0xed, 0x3e, 0x5f, 0x77, 0x27, 0xbd,
+  0x9e, 0x94, 0xd2, 0x3f, 0xe0, 0x62, 0xa2, 0xbe, 0x78, 0xe5, 0xb5, 0xbe, 0xba, 0xfc, 0xed, 0xbe,
+  0xfe, 0xd0, 0xe6, 0xbf, 0x33, 0xd5, 0xbd, 0xbe, 0xed, 0x7e, 0x7a, 0xbf, 0x75, 0x0e, 0xe6, 0x3e,
+  0xf6, 0x05, 0x0d, 0x3f, 0x40, 0x53, 0x6c, 0x3e, 0xbe, 0xf3, 0x4a, 0xbe, 0x78, 0x92, 0x02, 0xbf,
+  0x1e, 0x9a, 0xb3, 0x3e, 0x2f, 0x32, 0x94, 0xbf, 0x33, 0xb2, 0x46, 0xbf, 0x5b, 0x5f, 0x18, 0x3d,
+  0x81, 0xe8, 0xa5, 0x3f, 0xf9, 0xeb, 0xa9, 0xbe, 0x2c, 0x46, 0x76, 0x3f, 0xf4, 0x34, 0x43, 0x3f,
+  0xfe, 0x03, 0x75, 0x3f, 0x57, 0x4c, 0x97, 0x3f, 0xdc, 0x54, 0xb1, 0xbe, 0x68, 0x1b, 0xaa, 0x3f,
+  0x82, 0xd0, 0xe5, 0x3f, 0x08, 0xa7, 0x1c, 0x3f, 0xbc, 0x1c, 0x5e, 0xbf, 0xba, 0x18, 0x74, 0xbf,
+  0x48, 0xed, 0xc0, 0xbf, 0xd9, 0xf8, 0xbe, 0xbe, 0x0b, 0x86, 0x4a, 0xbf, 0x9b, 0x83, 0x51, 0x3c,
+  0x0f, 0x9e, 0xba, 0x3e, 0xc9, 0x59, 0xca, 0xbf, 0x6a, 0x26, 0x6c, 0x3f, 0x35, 0xfa, 0x6d, 0x3f,
+  0x15, 0xea, 0x3c, 0xbf, 0x26, 0xe8, 0x1b, 0x3e, 0x97, 0xec, 0x1a, 0xbf, 0x5e, 0x58, 0x86, 0x3e,
+  0xdc, 0xed, 0x16, 0xbf, 0x6e, 0xc6, 0x1c, 0x3f, 0xee, 0xd4, 0x91, 0x3c, 0x4d, 0x2f, 0x6d, 0x3e,
+  0x86, 0x76, 0x33, 0xbf, 0xdd, 0x07, 0xb2, 0x3f, 0x49, 0x01, 0x17, 0x3f, 0x5c, 0xc6, 0xd9, 0xbf,
+  0x89, 0xf2, 0x5f, 0xbf, 0xbc, 0xe6, 0xea, 0xbe, 0x19, 0xec, 0x11, 0xbd, 0x50, 0x0b, 0xe5, 0x3d,
+  0x73, 0x8b, 0xa5, 0x3e, 0xff, 0x41, 0x34, 0xbf, 0x0d, 0xa5, 0xb2, 0xbf, 0xef, 0x88, 0xdd, 0x3d,
+  0x40, 0x66, 0x92, 0xbe, 0x1d, 0x5b, 0x22, 0xbf, 0x9c, 0x7f, 0xfb, 0x3d, 0x59, 0xfb, 0xc8, 0xbd,
+  0x34, 0xe3, 0x47, 0x3e, 0x85, 0x8d, 0xf1, 0xbe, 0xb2, 0x56, 0xdf, 0xbe, 0x82, 0x67, 0x08, 0x3f,
+  0x69, 0x40, 0xec, 0x3e, 0x48, 0x59, 0xd4, 0x3f, 0xc7, 0xac, 0xf1, 0x3e, 0x01, 0xe6, 0x48, 0xbe,
+  0x51, 0xa7, 0x0b, 0xbf, 0xda, 0x0a, 0x54, 0xbf, 0x0a, 0x87, 0x91, 0x3f, 0x00, 0x86, 0x4d, 0xbf,
+  0x4e, 0xba, 0xb5, 0x3f, 0xee, 0x28, 0xeb, 0x3f, 0x3d, 0xde, 0xb0, 0xbf, 0xc4, 0x0c, 0x69, 0xbe,
+  0xc2, 0x91, 0xf9, 0xbd, 0x37, 0x7c, 0x6a, 0xbf, 0xd9, 0x9b, 0xbc, 0xbc, 0x46, 0x17, 0x09, 0xc0,
+  0x5c, 0xa8, 0xd2, 0x3e, 0xb8, 0xfd, 0x3f, 0xbf, 0x25, 0x11, 0x90, 0x3f, 0xdc, 0x01, 0xa5, 0x3e,
+  0xae, 0x16, 0x3e, 0xbf, 0xbb, 0xb4, 0x1b, 0x3f, 0x4c, 0x43, 0x5e, 0x3f, 0x96, 0xeb, 0x83, 0xbe,
+  0x0b, 0xd6, 0x0f, 0x3f, 0xd9, 0xa2, 0xa8, 0xbc, 0x04, 0x25, 0x9d, 0x3f, 0x35, 0xc1, 0x32, 0xbf,
+  0x22, 0x3f, 0x6b, 0xbf, 0x5b, 0x10, 0xff, 0xbd, 0x6c, 0xd2, 0x94, 0xbf, 0x6f, 0x8e, 0x97, 0xbf,
+  0x36, 0x88, 0xd8, 0xbf, 0xf6, 0x1d, 0x49, 0xbf, 0xc0, 0x35, 0x50, 0x3f, 0x37, 0x39, 0x72, 0x3f,
+  0x92, 0x97, 0x5f, 0x3e, 0xd3, 0xa8, 0x45, 0xbe, 0xef, 0x0a, 0x00, 0x3f, 0xd0, 0x2c, 0x03, 0xc0,
+  0x6e, 0x1c, 0x4c, 0xbf, 0xb6, 0xd4, 0x22, 0x3f, 0x54, 0xfe, 0x05, 0x3f, 0xf9, 0x6e, 0x44, 0x3f,
+  0xed, 0x1b, 0x27, 0xc0, 0x7b, 0x39, 0x84, 0x3e, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x8c, 0x6e, 0x1a, 0xbe,
+  0x55, 0x01, 0xb5, 0x3f, 0xd3, 0x3f, 0x3d, 0xbf, 0x05, 0x55, 0x2e, 0x3f, 0xb9, 0xf7, 0x3f, 0xbf,
+  0xcf, 0x42, 0x9e, 0xbf, 0x6b, 0xff, 0x7a, 0xbe, 0x9d, 0x11, 0x7f, 0xbf, 0xe1, 0xe9, 0x32, 0xbf,
+  0x91, 0xaa, 0x7b, 0xbf, 0x54, 0xa4, 0xb7, 0x3b, 0x77, 0x80, 0xa9, 0xbd, 0x1d, 0xfc, 0x6d, 0xbf,
+  0xf4, 0x7d, 0x86, 0xbf, 0x43, 0x92, 0x49, 0x3e, 0x3d, 0x0d, 0x60, 0x3f, 0x77, 0xbf, 0x08, 0x40,
+  0x12, 0x2d, 0x71, 0x3d, 0xf9, 0xca, 0xc6, 0x3f, 0xb8, 0x57, 0x05, 0xc0, 0xec, 0xe0, 0x02, 0x3f,
+  0x40, 0x33, 0x25, 0x3f, 0x13, 0x97, 0x67, 0x3e, 0x33, 0x1e, 0x80, 0xbe, 0xb4, 0xe6, 0x15, 0xbf,
+  0x62, 0x11, 0x82, 0xbf, 0x34, 0x91, 0x83, 0x3f, 0x8c, 0x38, 0xe8, 0xbd, 0xf5, 0x3e, 0x90, 0xbf,
+  0xcf, 0x66, 0x49, 0x3f, 0x8d, 0xa2, 0xc0, 0x3f, 0x76, 0x3a, 0xc7, 0x3e, 0x6e, 0xcf, 0x9f, 0x3f,
+  0xf4, 0x0c, 0xc0, 0xbe, 0xbe, 0x83, 0xc5, 0xbf, 0xfd, 0xb3, 0xa8, 0x3e, 0xca, 0x78, 0x83, 0x3f,
+  0x95, 0x08, 0x46, 0xbe, 0x97, 0xa6, 0x40, 0x3f, 0xf2, 0x5e, 0xaf, 0xbe, 0x4e, 0x27, 0x0c, 0xc0,
+  0xe7, 0xd0, 0x03, 0x3f, 0x5e, 0x09, 0x74, 0xbf, 0x03, 0x93, 0xd2, 0x3e, 0xc0, 0xfa, 0x01, 0x3f,
+  0xb7, 0xea, 0xd4, 0xbf, 0xd4, 0xad, 0xcf, 0x3d, 0xdf, 0x2f, 0xff, 0xbf, 0x16, 0xc5, 0x27, 0xbf,
+  0xf3, 0x69, 0xff, 0xbe, 0xb0, 0x4b, 0xb9, 0xbf, 0x25, 0xa2, 0x92, 0x3c, 0xb0, 0xf7, 0xf0, 0x3f,
+  0x0e, 0x74, 0x95, 0x3f, 0xb0, 0x75, 0x84, 0x3f, 0x88, 0x54, 0x18, 0x3f, 0x29, 0xa2, 0x6c, 0xbd,
+  0x0c, 0x49, 0x29, 0xbf, 0xf7, 0x5b, 0xb1, 0x3f, 0x3e, 0x6a, 0x17, 0x3f, 0x2d, 0xe8, 0x0c, 0xbf,
+  0x87, 0xc6, 0x48, 0xbf, 0x71, 0x80, 0xc5, 0x3e, 0x51, 0x27, 0x0e, 0x3e, 0x80, 0xb2, 0x1b, 0x40,
+  0x19, 0xe3, 0xc8, 0x3e, 0x29, 0x9e, 0xb1, 0xbe, 0xe6, 0x2a, 0x40, 0xbf, 0x2f, 0xc3, 0x1c, 0xc0,
+  0xc5, 0x83, 0xbf, 0xbe, 0xfb, 0x70, 0xb4, 0xbf, 0x6a, 0xa7, 0x49, 0xbf, 0x4c, 0x7a, 0x9d, 0xbf,
+  0xc9, 0x3c, 0xd0, 0x3e, 0x0b, 0x76, 0xa8, 0xbe, 0x78, 0xe0, 0xd4, 0x3e, 0xa8, 0x00, 0xad, 0xbf,
+  0x44, 0xb5, 0x94, 0x3f, 0x36, 0xd5, 0x9c, 0xbd, 0xb6, 0xe7, 0xaf, 0x3e, 0x14, 0xcc, 0x1f, 0xbe,
+  0x26, 0x1b, 0xae, 0xbf, 0x63, 0xdf, 0xe3, 0x3d, 0x90, 0xff, 0x27, 0xbe, 0xc5, 0x77, 0x92, 0xbd,
+  0x6d, 0x7a, 0x61, 0xbf, 0x55, 0x50, 0x9c, 0x3d, 0x5f, 0x74, 0x4a, 0x3c, 0x1f, 0x2f, 0x80, 0x3d,
+  0x92, 0xa6, 0xb4, 0xbf, 0xe4, 0x5f, 0x49, 0xbf, 0x61, 0xfb, 0x3d, 0x3f, 0xf0, 0x12, 0x96, 0x3f,
+  0xe6, 0x94, 0xd9, 0xbf, 0xe2, 0x8e, 0xa2, 0x3f, 0x18, 0x65, 0xee, 0x3e, 0x2c, 0x7d, 0x0d, 0xbe,
+  0x9d, 0xb3, 0xda, 0x3f, 0x71, 0x09, 0x8f, 0x3e, 0xd0, 0xd0, 0xe0, 0xbf, 0x36, 0x43, 0x3f, 0x3e,
+  0x44, 0xc5, 0x0b, 0x3f, 0xe5, 0x1a, 0x19, 0xbf, 0x0a, 0x90, 0x00, 0x3f, 0xe0, 0x15, 0xe2, 0x3e,
+  0x5c, 0xf6, 0xd4, 0x3e, 0x2b, 0x27, 0x89, 0x3c, 0xc9, 0x33, 0xf5, 0x3e, 0x7e, 0x7f, 0x2c, 0x3f,
+  0xcb, 0xda, 0xdd, 0x3f, 0x61, 0x32, 0xed, 0xbf, 0xde, 0x93, 0xdc, 0xbe, 0xfe, 0x17, 0x0a, 0x3e,
+  0xe9, 0xd5, 0x65, 0xbd, 0xf4, 0xd9, 0x94, 0xbf, 0xa5, 0x6b, 0xaa, 0xbd, 0x80, 0xa2, 0x1b, 0x3f,
+  0xa6, 0xdb, 0xa3, 0xbf, 0xd9, 0xb7, 0x8d, 0xbf, 0xec, 0xf1, 0x49, 0xbf, 0xef, 0x4f, 0x28, 0xbf,
+  0x74, 0x4e, 0x19, 0x3f, 0xed, 0x71, 0xd1, 0xbf, 0x5c, 0x6e, 0xa0, 0xbf, 0xc0, 0x5b, 0xe2, 0xbe,
+  0x8f, 0xf2, 0xc9, 0x3e, 0x30, 0x1f, 0x2b, 0xbe, 0x0f, 0x96, 0xfb, 0xbf, 0xa3, 0x49, 0xfb, 0x3f,
+  0x23, 0x34, 0x8b, 0x3f, 0xbd, 0x38, 0x77, 0xbe, 0x9f, 0x90, 0x07, 0x3f, 0x9f, 0xdf, 0xab, 0x3e,
+  0x91, 0xaa, 0xc2, 0xbf, 0xfb, 0x33, 0x0d, 0xbf, 0x42, 0x52, 0x95, 0xbe, 0xf7, 0x52, 0x51, 0x3f,
+  0x83, 0x3e, 0xa3, 0x3e, 0x5c, 0x26, 0xe5, 0x3e, 0x4f, 0x14, 0xc0, 0x3e, 0x88, 0xdf, 0xcf, 0xbf,
+  0xc9, 0xdc, 0x5b, 0x3f, 0x1f, 0xa9, 0x53, 0x3f, 0x91, 0x66, 0xa4, 0x3f, 0xab, 0xfe, 0x79, 0x3e,
+  0xe3, 0xce, 0x66, 0x3f, 0x6a, 0xa9, 0x0f, 0xc0, 0x32, 0x12, 0x9a, 0x3f, 0x97, 0xee, 0x35, 0x3f,
+  0xc8, 0x0b, 0x56, 0x3e, 0x82, 0xd5, 0xa1, 0xbe, 0xc8, 0x5d, 0x5d, 0xbd, 0x06, 0x1f, 0x02, 0x3f,
+  0x65, 0x32, 0x33, 0x40, 0xd2, 0xa2, 0x2f, 0xbf, 0xb9, 0xca, 0x92, 0x3d, 0x4b, 0xea, 0xc9, 0x3f,
+  0xf7, 0x3e, 0xce, 0x3e, 0xf2, 0x8f, 0x0a, 0xbe, 0x66, 0xcb, 0xe5, 0x3e, 0x7a, 0x98, 0x89, 0x3f,
+  0x04, 0x8a, 0xc8, 0xbe, 0xbe, 0x83, 0xbe, 0x3f, 0x13, 0x5f, 0xad, 0x3d, 0x15, 0x6c, 0x43, 0xbe,
+  0xab, 0x85, 0xf5, 0xbe, 0xa0, 0x12, 0xf4, 0x3d, 0x58, 0x6d, 0x90, 0x3f, 0x8e, 0x8a, 0x10, 0xc0,
+  0x2a, 0x80, 0xad, 0xbf, 0x2e, 0xac, 0x8c, 0xbe, 0xe5, 0xe5, 0x67, 0xbf, 0xe6, 0xd8, 0x0f, 0x3f,
+  0x4c, 0x61, 0x8a, 0xbf, 0x12, 0x06, 0x37, 0xbf, 0xf1, 0xcd, 0xdc, 0xbf, 0xa9, 0xd9, 0x00, 0xbe,
+  0x33, 0x0b, 0x91, 0x3d, 0x1b, 0xb4, 0x44, 0xbd, 0x82, 0xe3, 0xce, 0x3e, 0x1d, 0x55, 0x73, 0xbf,
+  0x47, 0x84, 0xfa, 0x3f, 0x7d, 0x18, 0xa6, 0x3f, 0xf1, 0x23, 0x25, 0xbf, 0xce, 0x0b, 0x25, 0xc0,
+  0xaf, 0xce, 0x1d, 0xbc, 0x6c, 0x91, 0xdc, 0xbe, 0x96, 0xd2, 0x82, 0x3b, 0x05, 0x89, 0x6d, 0xbf,
+  0x4a, 0x1a, 0x14, 0xbf, 0x36, 0xac, 0x22, 0xc0, 0xd1, 0x78, 0x9d, 0xbe, 0xa8, 0x6c, 0xa2, 0xbc,
+  0x39, 0x81, 0x2b, 0x3d, 0x52, 0xe5, 0x5d, 0x3f, 0xfa, 0x88, 0x2b, 0xbf, 0x2a, 0xca, 0x61, 0xbf,
+  0x1b, 0x6c, 0xd1, 0x3c, 0xd7, 0x99, 0xc3, 0x3e, 0x7a, 0x8c, 0xc2, 0xbe, 0xc3, 0x4c, 0x31, 0xbf,
+  0x6c, 0xbc, 0x2f, 0x3f, 0x5c, 0x15, 0x4a, 0xbf, 0xa0, 0xa1, 0x12, 0x3e, 0x43, 0x5b, 0xf1, 0x3e,
+  0xbf, 0xc1, 0x4f, 0x3f, 0xf9, 0xdb, 0x04, 0xbf, 0x2a, 0x9b, 0x39, 0xbf, 0xed, 0x24, 0x68, 0xbf,
+  0xd0, 0xe2, 0xe2, 0xbe, 0x7a, 0x5f, 0xb4, 0xbf, 0x1a, 0x83, 0xb9, 0xbf, 0xef, 0x0e, 0x3d, 0x3d,
+  0x2c, 0x4d, 0x06, 0x3f, 0x75, 0x03, 0xbd, 0xbe, 0x1c, 0x32, 0x28, 0xbf, 0x99, 0x41, 0x94, 0x3f,
+  0x5f, 0x3f, 0x0a, 0x40, 0x64, 0x0c, 0x8d, 0xc0, 0x99, 0xdb, 0x5d, 0x3f, 0x49, 0x3c, 0x53, 0x3d,
+  0xb9, 0xb2, 0xbf, 0x3f, 0x64, 0x93, 0x58, 0xbf, 0x9d, 0x08, 0x0a, 0xbf, 0x90, 0xc6, 0x18, 0x3f,
+  0xeb, 0xa3, 0x98, 0x3e, 0xe9, 0x92, 0x01, 0xbc, 0x68, 0xef, 0xb6, 0xba, 0x43, 0xed, 0x94, 0x3f,
+  0x8b, 0xf6, 0x43, 0x3f, 0x3e, 0x13, 0xa5, 0xbe, 0x70, 0x0d, 0x97, 0x3e, 0x83, 0x81, 0x26, 0xbd,
+  0x9b, 0x8f, 0xae, 0x3f, 0x03, 0x14, 0x60, 0xbf, 0x16, 0x9d, 0xac, 0xbf, 0x4f, 0xac, 0xc0, 0x3f,
+  0xc6, 0x6d, 0x98, 0xbf, 0xe4, 0xe7, 0x26, 0x3f, 0x2d, 0x12, 0x28, 0xbe, 0x53, 0x28, 0x01, 0xbe,
+  0x0e, 0x24, 0xae, 0x3f, 0x7c, 0x6e, 0x96, 0x3f, 0x4e, 0xc1, 0xd3, 0xbf, 0x76, 0xb7, 0xc8, 0xbe,
+  0xdb, 0x89, 0x02, 0xbf, 0xe6, 0x79, 0xeb, 0x3e, 0x8d, 0xaa, 0x06, 0xbe, 0x15, 0xd4, 0x14, 0xbf,
+  0xb7, 0xee, 0xd7, 0x3e, 0x07, 0x02, 0xd8, 0x3f, 0x59, 0x81, 0x03, 0xc0, 0xeb, 0x2c, 0x09, 0xbf,
+  0x56, 0x63, 0xcb, 0xbf, 0x56, 0x93, 0x3b, 0x3e, 0x95, 0x5c, 0xed, 0xbe, 0xea, 0x26, 0x75, 0x3f,
+  0xb3, 0xdb, 0x96, 0x3e, 0xb4, 0xa9, 0x20, 0x3e, 0x87, 0x35, 0xd5, 0x3f, 0xa0, 0x3b, 0xdc, 0x3e,
+  0x10, 0x74, 0xeb, 0x3f, 0xee, 0xbf, 0xac, 0xbf, 0x0f, 0xb3, 0x1c, 0xbf, 0x6b, 0x1a, 0xb9, 0x3f,
+  0xe5, 0xbb, 0x0c, 0x40, 0x3d, 0xea, 0xb9, 0x3f, 0xa3, 0xf5, 0x7f, 0x3f, 0x95, 0x6f, 0xc1, 0x3e,
+  0x48, 0xdb, 0xa7, 0xbf, 0x7c, 0x10, 0x74, 0xbe, 0x03, 0xbd, 0x77, 0x3f, 0x44, 0x38, 0x0a, 0xbf,
+  0x88, 0x40, 0x08, 0x3f, 0x34, 0xac, 0x2a, 0x3f, 0xe7, 0x71, 0x77, 0x3f, 0xf5, 0xa0, 0x22, 0x3e,
+  0x73, 0x3c, 0xe0, 0x3f, 0xfd, 0xb0, 0xaa, 0xbe, 0xb1, 0xb0, 0x1f, 0x3f, 0x35, 0xae, 0xae, 0xbf,
+  0x46, 0xdc, 0x03, 0x40, 0xeb, 0x54, 0xcd, 0x3e, 0xc1, 0x3b, 0x21, 0xbe, 0xce, 0x67, 0x43, 0xbe,
+  0xc5, 0x2b, 0xb2, 0x3f, 0x46, 0x30, 0x53, 0x3f, 0x76, 0x5a, 0x5a, 0xbf, 0x1b, 0x33, 0xa6, 0x3e,
+  0x97, 0x19, 0x0c, 0x3f, 0x4d, 0x67, 0x25, 0xbf, 0xae, 0xa5, 0x6c, 0x3f, 0xb1, 0xfe, 0x17, 0x3d,
+  0xfc, 0x32, 0x03, 0xbe, 0xbc, 0x9e, 0xa7, 0xbe, 0x7c, 0x69, 0x98, 0x3f, 0xed, 0x41, 0xdb, 0x3e,
+  0x81, 0x72, 0x7c, 0xbe, 0xc2, 0x3d, 0x9a, 0xbf, 0xcc, 0x47, 0x26, 0xc0, 0x53, 0xeb, 0x8b, 0x3e,
+  0x04, 0x58, 0x8d, 0x3f, 0x7e, 0x73, 0x1e, 0xbe, 0x54, 0x43, 0xc9, 0xbe, 0x29, 0x4d, 0xe5, 0xbf,
+  0x9a, 0x4d, 0x52, 0x3d, 0x25, 0xe5, 0x7c, 0x3e, 0x69, 0x23, 0x55, 0xbf, 0x96, 0xc5, 0xfe, 0x3e,
+  0xb6, 0x40, 0x6a, 0x3f, 0x3a, 0x36, 0x62, 0x3f, 0x3e, 0x27, 0x8c, 0x3e, 0x07, 0xd0, 0x36, 0x3f,
+  0x4f, 0x34, 0x1c, 0x3f, 0x87, 0x2d, 0x01, 0x3f, 0x98, 0xf4, 0xe1, 0xbe, 0x40, 0x21, 0xae, 0x3f,
+  0x5c, 0x6e, 0xa9, 0xbe, 0x88, 0x09, 0x05, 0xbf, 0x8c, 0x9a, 0x1c, 0x3f, 0x4f, 0xba, 0x86, 0xbe,
+  0x95, 0x1a, 0xf0, 0xbf, 0x80, 0x85, 0x96, 0xbf, 0xcf, 0xd5, 0x3d, 0x3f, 0x61, 0x23, 0xb8, 0x3e,
+  0x0d, 0x12, 0x0b, 0xbf, 0x80, 0x08, 0x83, 0xbf, 0xc8, 0x8a, 0x0e, 0xbe, 0x9e, 0x2c, 0xc8, 0xbe,
+  0xf1, 0xce, 0xef, 0xbf, 0x74, 0x62, 0x9f, 0xbe, 0x74, 0x23, 0x80, 0xbe, 0x00, 0xd1, 0x84, 0x3f,
+  0x45, 0xff, 0x60, 0x3f, 0x4b, 0x78, 0x17, 0xbf, 0x47, 0xdd, 0xa6, 0xbf, 0xf5, 0xec, 0x17, 0x3f,
+  0xf6, 0x66, 0xa5, 0x3f, 0x40, 0x8e, 0x4e, 0xbf, 0xab, 0x71, 0x28, 0x3e, 0x0c, 0xad, 0xb5, 0xbe,
+  0xd6, 0x5c, 0x59, 0xbf, 0x71, 0x1c, 0x21, 0x3f, 0x80, 0x7e, 0x0d, 0x40, 0x5e, 0x1d, 0x23, 0x3e,
+  0x8f, 0x0d, 0x45, 0xbf, 0x16, 0xb6, 0x3c, 0xc0, 0x74, 0xb7, 0x96, 0xbf, 0xdc, 0xa4, 0xc2, 0xbf,
+  0xd2, 0x3e, 0xca, 0xbf, 0xf3, 0x38, 0x0b, 0xbf, 0x00, 0x07, 0x7a, 0x3f, 0x43, 0x9c, 0x2c, 0x3f,
+  0x5f, 0xaa, 0xcf, 0xbf, 0x90, 0x8a, 0x45, 0xbf, 0x1d, 0xd2, 0x83, 0xbf, 0x23, 0xf3, 0x30, 0xbd,
+  0x33, 0xa1, 0xf3, 0xbf, 0xc8, 0x41, 0x93, 0xbe, 0x3c, 0x1a, 0x65, 0xbe, 0xfd, 0xda, 0xed, 0xbe,
+  0x26, 0x3d, 0xd3, 0xbe, 0xcd, 0xb0, 0x0f, 0xc0, 0x74, 0x92, 0x19, 0x3f, 0x00, 0x4d, 0x6f, 0x3f,
+  0xa0, 0x47, 0xa9, 0x3e, 0x38, 0x05, 0xdf, 0xbf, 0x41, 0x4e, 0xc3, 0xbe, 0x52, 0xc2, 0x1e, 0xbe,
+  0xc9, 0xb3, 0xe6, 0x3e, 0x03, 0xbe, 0x1e, 0x3f, 0x9f, 0xaf, 0x85, 0xbf, 0xbb, 0xbc, 0x9c, 0x3f,
+  0xe1, 0xfc, 0x16, 0xbf, 0xea, 0x09, 0x3e, 0xbe, 0xbb, 0xe0, 0x42, 0x40, 0xd2, 0x28, 0xd4, 0x3e,
+  0x7b, 0xd1, 0x73, 0xbf, 0xd3, 0x77, 0x98, 0x3f, 0x73, 0x4c, 0x5e, 0xbf, 0x2c, 0x3e, 0x11, 0x3f,
+  0x95, 0x64, 0x15, 0xbe, 0x0d, 0x4f, 0x1a, 0x3f, 0x7f, 0x1b, 0xc8, 0x3e, 0x1d, 0x68, 0x35, 0x3f,
+  0x99, 0xf7, 0xd6, 0xbe, 0x3d, 0xb9, 0x99, 0x3f, 0x17, 0x50, 0xce, 0x3e, 0x8e, 0x04, 0x8d, 0xbe,
+  0x08, 0x0c, 0xf9, 0x3f, 0x6b, 0xb2, 0xd0, 0xbe, 0xc7, 0xcb, 0xba, 0xbe, 0xd0, 0x70, 0x3a, 0x3e,
+  0xa9, 0x54, 0xe8, 0x3e, 0xe7, 0x3b, 0xc4, 0xbe, 0x94, 0x5b, 0x5c, 0x3f, 0x57, 0xc4, 0xfc, 0xbd,
+  0x38, 0x6f, 0x9b, 0xbd, 0xdb, 0x1d, 0x47, 0x3f, 0x36, 0x78, 0x78, 0x3f, 0x9f, 0x61, 0x52, 0xbf,
+  0x67, 0x23, 0x86, 0x3e, 0x74, 0x04, 0xde, 0xbe, 0x19, 0x1b, 0x51, 0xbf, 0x73, 0x5f, 0x05, 0x3e,
+  0x06, 0xe6, 0x9c, 0x3e, 0x95, 0xfe, 0x9b, 0x3f, 0x94, 0xce, 0x76, 0xbf, 0xc1, 0xf8, 0x8e, 0x3f,
+  0x8c, 0x5b, 0x63, 0x3f, 0x70, 0x00, 0xaa, 0xbf, 0x1a, 0xb8, 0x6c, 0xbf, 0x42, 0x20, 0x91, 0x3d,
+  0x97, 0x4b, 0x1a, 0xbf, 0xbc, 0x32, 0xb4, 0x3e, 0x77, 0xf0, 0xc6, 0x3e, 0xeb, 0x56, 0xa2, 0x3f,
+  0x0e, 0xb0, 0x25, 0x40, 0x4b, 0xce, 0x40, 0xbf, 0x5b, 0xfd, 0x35, 0xbf, 0x9e, 0x78, 0x7f, 0xbe,
+  0xe3, 0x03, 0xac, 0xbf, 0x89, 0xc2, 0x77, 0x3f, 0xd8, 0x2e, 0x63, 0xbf, 0xce, 0x9f, 0x40, 0x3f,
+  0xe2, 0x52, 0xce, 0x3e, 0x5c, 0xeb, 0x63, 0x3f, 0x4e, 0xd3, 0x9d, 0x3f, 0x7c, 0xe3, 0x47, 0xbf,
+  0xea, 0xca, 0x31, 0xbf, 0xae, 0x7b, 0x0d, 0x3f, 0x04, 0xa0, 0x58, 0x3f, 0x8a, 0xc5, 0x87, 0x3f,
+  0x22, 0xfa, 0xa8, 0xbf, 0x5e, 0x7e, 0xbf, 0xbd, 0xdc, 0x05, 0x70, 0x3f, 0x8e, 0x2c, 0xee, 0x3e,
+  0xfb, 0x13, 0x14, 0xbf, 0x2e, 0xf2, 0x17, 0x3d, 0x7f, 0x3e, 0xe8, 0x3c, 0x86, 0xfa, 0x35, 0xbf,
+  0x21, 0x83, 0x8d, 0x3e, 0x77, 0xab, 0x3b, 0xbf, 0xda, 0x43, 0x00, 0xbf, 0x32, 0xd5, 0x7e, 0xbd,
+  0x5a, 0xd6, 0xa1, 0xbf, 0xc3, 0xad, 0xdd, 0xbe, 0x33, 0xa0, 0x20, 0x3f, 0x07, 0x4a, 0x0e, 0x3f,
+  0x4c, 0x98, 0x5d, 0x3e, 0x0e, 0xba, 0x86, 0x3f, 0xe4, 0xc3, 0x42, 0xbc, 0x42, 0x8f, 0x04, 0x3f,
+  0x49, 0xc0, 0x68, 0xbe, 0xe9, 0x21, 0x18, 0x40, 0xd0, 0x13, 0x85, 0x3e, 0x65, 0xc6, 0x8c, 0xbd,
+  0xa4, 0x15, 0xff, 0x3e, 0xf5, 0x61, 0x79, 0xbd, 0x44, 0xbb, 0x3e, 0x3f, 0xc5, 0xdd, 0xa5, 0xbe,
+  0xc7, 0x8d, 0xea, 0xbf, 0x31, 0xf2, 0xce, 0x3f, 0x7e, 0xb7, 0x5d, 0x3f, 0xfa, 0x62, 0x8a, 0xbe,
+  0x98, 0x4a, 0x82, 0xbe, 0x3a, 0x08, 0x29, 0x40, 0xb1, 0xc8, 0xec, 0x3f, 0x60, 0x74, 0x82, 0x3f,
+  0x35, 0x65, 0x1c, 0x3f, 0x9b, 0x63, 0x75, 0x3d, 0xe5, 0x3c, 0x21, 0x3f, 0xf8, 0xac, 0x84, 0x3f,
+  0xc5, 0xe6, 0x9d, 0xbf, 0x2a, 0xf6, 0xc5, 0x3e, 0x34, 0x33, 0x6b, 0xbf, 0x66, 0x93, 0x71, 0xbd,
+  0x4b, 0xff, 0xbe, 0xbf, 0x8f, 0x72, 0x05, 0xbf, 0x4e, 0xee, 0xc7, 0xbc, 0x20, 0x1a, 0xa1, 0x3e,
+  0xec, 0x65, 0x9c, 0xbf, 0x94, 0x44, 0x4a, 0xbe, 0x6f, 0x68, 0x20, 0x3e, 0xd7, 0x49, 0x04, 0x40,
+  0x53, 0x37, 0x30, 0xbf, 0x92, 0x86, 0x1c, 0xbe, 0x20, 0x0c, 0xd9, 0x3f, 0xfe, 0xa7, 0x98, 0x3f,
+  0x92, 0xa3, 0x72, 0x3f, 0xed, 0x1c, 0xce, 0x3d, 0x41, 0xb5, 0x94, 0xbe, 0xae, 0x1c, 0xa7, 0x3e,
+  0x9d, 0xdc, 0x9b, 0xbf, 0xe7, 0x82, 0x23, 0x40, 0xe6, 0x19, 0x28, 0xbf, 0xb9, 0xfb, 0x94, 0xbf,
+  0xb1, 0x45, 0xa2, 0xbe, 0x79, 0x6e, 0x9c, 0xbe, 0xc6, 0x56, 0x6d, 0x3f, 0xa4, 0x5a, 0x02, 0x40,
+  0x10, 0x10, 0x41, 0xbd, 0xbd, 0x92, 0xbf, 0xbe, 0xa7, 0x20, 0x63, 0x3f, 0x15, 0x39, 0x83, 0xbf,
+  0x53, 0x34, 0x2b, 0xbe, 0x96, 0x72, 0xa4, 0x3f, 0x47, 0x91, 0xfe, 0xbf, 0x36, 0xea, 0xcd, 0xbe,
+  0x8e, 0x28, 0x91, 0xbe, 0x89, 0x45, 0x9e, 0x3e, 0xa6, 0x56, 0x18, 0x3c, 0x4c, 0x2c, 0x5d, 0x3e,
+  0x13, 0xbd, 0x3b, 0xbf, 0x10, 0xcb, 0xcc, 0xbf, 0x33, 0x58, 0x9f, 0xbf, 0x2d, 0x85, 0x29, 0x3f,
+  0xfe, 0x70, 0x85, 0xbf, 0x67, 0x91, 0x09, 0x3f, 0xf4, 0xda, 0x28, 0xbe, 0xa3, 0x72, 0x85, 0xbf,
+  0x2c, 0x0d, 0xce, 0x3e, 0x49, 0xc4, 0x34, 0xbf, 0xb8, 0x18, 0x80, 0xbe, 0x63, 0x92, 0xc8, 0x3e,
+  0x59, 0x84, 0xb9, 0x3f, 0x30, 0xb0, 0x94, 0x3f, 0x5b, 0xaa, 0xf2, 0xbe, 0x00, 0x52, 0x32, 0xbf,
+  0x2c, 0x14, 0x8b, 0x3f, 0xf2, 0x65, 0xa4, 0xbf, 0x72, 0x30, 0xec, 0xbd, 0xaf, 0xb0, 0x9d, 0xbe,
+  0x9b, 0xdc, 0x93, 0xbf, 0x3b, 0x8c, 0x1d, 0xbe, 0x22, 0x50, 0x39, 0x3e, 0x2c, 0xdf, 0x80, 0xbf,
+  0x0a, 0x89, 0x18, 0xbf, 0xe8, 0x84, 0xb1, 0xbf, 0x36, 0x36, 0x7a, 0x3f, 0xe2, 0xdb, 0x28, 0x40,
+  0x99, 0x1b, 0x01, 0xc0, 0x23, 0x56, 0x1d, 0xbf, 0x9f, 0xf0, 0x41, 0x3f, 0x50, 0x0c, 0x44, 0x3f,
+  0x6a, 0x7b, 0x02, 0xbf, 0xd9, 0xdf, 0xe6, 0x3f, 0xca, 0xac, 0xe9, 0xbe, 0x32, 0x20, 0x19, 0xbf,
+  0x74, 0x1a, 0xa5, 0xbf, 0xf8, 0xf1, 0x24, 0x3f, 0xfd, 0x45, 0x00, 0x3f, 0xca, 0x6f, 0x80, 0xbe,
+  0x1f, 0x86, 0x5c, 0x3e, 0xc6, 0x34, 0x41, 0x3f, 0xeb, 0x0b, 0xd7, 0xbd, 0x9c, 0x6c, 0x90, 0x3e,
+  0x2b, 0x87, 0xcb, 0x3e, 0x7a, 0xbc, 0x57, 0x3f, 0x36, 0x6f, 0x1e, 0xbe, 0x12, 0xbd, 0x6d, 0x3e,
+  0x7e, 0x8f, 0xbc, 0x3e, 0x82, 0x91, 0xaf, 0xbe, 0x61, 0x72, 0x3b, 0x3f, 0xfa, 0x54, 0x7d, 0x3f,
+  0x5a, 0x38, 0x81, 0x3f, 0x09, 0x04, 0xf7, 0x3e, 0xc1, 0x7b, 0xa0, 0xbf, 0xd1, 0x5c, 0x81, 0x3e,
+  0x48, 0x6e, 0x3f, 0x3e, 0x42, 0x28, 0x03, 0x3f, 0x3f, 0x22, 0xc8, 0xbf, 0x11, 0x34, 0xf2, 0xbe,
+  0xff, 0xa4, 0x0a, 0xbf, 0x34, 0xe0, 0x1f, 0xbe, 0xcb, 0x44, 0x04, 0x40, 0x07, 0x7b, 0x05, 0x3f,
+  0xa1, 0x37, 0x85, 0xbe, 0x72, 0x32, 0x2f, 0x3f, 0xf0, 0x9b, 0x77, 0x3e, 0x09, 0xef, 0xac, 0x3d,
+  0x6d, 0xc4, 0x60, 0xbe, 0xc3, 0xa4, 0x63, 0xbf, 0x15, 0xa8, 0x94, 0xbe, 0x12, 0xe4, 0x2a, 0x40,
+  0x48, 0xc3, 0x51, 0x3f, 0x5e, 0x42, 0x86, 0x3f, 0x4b, 0x5e, 0x2d, 0x3f, 0x95, 0x04, 0x83, 0xbe,
+  0xbe, 0x31, 0x07, 0x40, 0xed, 0xcb, 0xbd, 0xbe, 0x63, 0xa7, 0x36, 0x3e, 0xf9, 0xa5, 0x2b, 0x3f,
+  0x12, 0xbd, 0x6d, 0x3f, 0x66, 0xa4, 0xcb, 0x3f, 0x3e, 0xd0, 0xc5, 0x3f, 0x32, 0xeb, 0xdc, 0x3f,
+  0x8c, 0x0d, 0x99, 0xbe, 0xd3, 0x07, 0x96, 0x3f, 0x64, 0xc0, 0xee, 0x3f, 0xbe, 0x0b, 0xcb, 0x3f,
+  0x64, 0x45, 0xc5, 0x3c, 0xcc, 0x2d, 0x84, 0xbf, 0xa3, 0xcf, 0x34, 0xbf, 0xa3, 0xce, 0x32, 0xbe,
+  0xc6, 0x11, 0xa5, 0xbe, 0xf0, 0xb5, 0x42, 0x3f, 0x18, 0xd5, 0xe9, 0x3e, 0x30, 0x23, 0xd4, 0x3e,
+  0xe8, 0x81, 0x0b, 0xc0, 0x20, 0x1a, 0x91, 0xbe, 0xcf, 0x6c, 0xbd, 0x3f, 0x33, 0x54, 0xf3, 0x3d,
+  0xce, 0xf8, 0xa4, 0x3f, 0xc4, 0x15, 0x9e, 0xbd, 0x10, 0x5a, 0x43, 0x3e, 0x73, 0x5f, 0x5c, 0x3d,
+  0x1c, 0xb9, 0x20, 0xbf, 0x00, 0xdb, 0x30, 0x3f, 0xeb, 0x76, 0x13, 0x3d, 0x6e, 0x88, 0x5c, 0xbf,
+  0xc9, 0xf0, 0x8b, 0xbd, 0xb0, 0x89, 0xc4, 0x3e, 0x94, 0xcc, 0x55, 0xbe, 0x9c, 0xfb, 0x4c, 0x3f,
+  0x9f, 0xb2, 0xf4, 0xbf, 0x98, 0xef, 0xf9, 0x3e, 0x4e, 0x62, 0x28, 0x3f, 0x0d, 0x53, 0x31, 0xbf,
+  0x53, 0x48, 0x76, 0xbf, 0x27, 0x4f, 0xce, 0xbd, 0x38, 0x36, 0xac, 0x3f, 0xe0, 0xcf, 0x49, 0x3f,
+  0x9c, 0xa2, 0x80, 0xbf, 0x0d, 0x87, 0xf0, 0x3d, 0x98, 0xee, 0xce, 0x3f, 0x74, 0x70, 0x26, 0xbf,
+  0x9b, 0x52, 0x84, 0xbf, 0x72, 0x8f, 0xe4, 0xbe, 0x0a, 0x5f, 0x54, 0xbe, 0x20, 0xe8, 0xb4, 0x3f,
+  0x5f, 0x57, 0xd2, 0xbf, 0xff, 0xf7, 0x12, 0x3f, 0xd2, 0x28, 0x99, 0xbf, 0xf0, 0x4a, 0x4f, 0x3e,
+  0x9d, 0x98, 0xec, 0xbf, 0x98, 0x1d, 0xb4, 0xbf, 0x65, 0xd7, 0x2a, 0x3d, 0x09, 0x9b, 0x93, 0x3f,
+  0x36, 0xd8, 0x1b, 0xbf, 0xcb, 0x5a, 0xbe, 0xbe, 0x63, 0x99, 0x3e, 0xbf, 0x59, 0x44, 0xec, 0xbd,
+  0xc2, 0x30, 0x1d, 0xbf, 0x83, 0xcf, 0xeb, 0x3e, 0x93, 0x49, 0xe2, 0xbe, 0xbe, 0x26, 0x3a, 0xbf,
+  0xc1, 0x9e, 0xf9, 0xbf, 0xbb, 0x1b, 0x58, 0xbf, 0xaa, 0xba, 0x2c, 0xbe, 0x71, 0x66, 0xaf, 0xbf,
+  0x5f, 0x4f, 0x52, 0x3e, 0xe2, 0x1f, 0x5c, 0x3f, 0x4c, 0xd4, 0x6a, 0x3e, 0x12, 0xc7, 0xee, 0x3d,
+  0x37, 0x50, 0x18, 0x3d, 0xa3, 0x31, 0xd1, 0xbd, 0xd6, 0xda, 0x74, 0xbe, 0x79, 0xbc, 0xa1, 0x3f,
+  0x97, 0xbc, 0x0a, 0xbf, 0xc6, 0x5b, 0x41, 0x3f, 0xbb, 0x04, 0xcf, 0xbf, 0xc5, 0x18, 0x43, 0xbf,
+  0xfb, 0x76, 0xe5, 0x3f, 0x67, 0x2e, 0x86, 0x3d, 0xc7, 0xec, 0x6d, 0xbf, 0xf1, 0xb7, 0xac, 0x3f,
+  0x57, 0x11, 0x3e, 0x3f, 0xdf, 0xa7, 0x7f, 0x3e, 0x77, 0x61, 0x3e, 0xbf, 0x79, 0xec, 0xfe, 0x3f,
+  0xf7, 0x27, 0xe7, 0x3e, 0x1a, 0xc5, 0xa5, 0xbe, 0xec, 0xf9, 0xf7, 0x3e, 0x8f, 0x6b, 0xd0, 0xbe,
+  0xfe, 0x31, 0xe4, 0xbd, 0x4c, 0x97, 0x85, 0xbe, 0xcf, 0x85, 0x46, 0xbe, 0x2f, 0x0b, 0x99, 0x3f,
+  0x66, 0x7b, 0x29, 0xbd, 0xb9, 0xff, 0xff, 0xbe, 0xef, 0x41, 0x25, 0x3f, 0xe5, 0x50, 0xf7, 0x3e,
+  0xe0, 0xe9, 0xa2, 0xbe, 0xaa, 0x40, 0x37, 0xbf, 0x85, 0x73, 0xe4, 0x3e, 0x28, 0xdc, 0x9d, 0xbe,
+  0x53, 0xec, 0xd4, 0x3e, 0x63, 0xa7, 0x36, 0x3f, 0xcb, 0xe3, 0x09, 0x3f, 0x6a, 0x54, 0xc7, 0xbd,
+  0x96, 0x45, 0xf4, 0x3f, 0x02, 0xa9, 0x07, 0xbd, 0x7c, 0x2e, 0x3f, 0xbf, 0x04, 0x19, 0x7c, 0xbf,
+  0xf8, 0x36, 0x61, 0x3e, 0x25, 0xef, 0xc3, 0xbf, 0x0e, 0xd7, 0x98, 0x3f, 0x16, 0xae, 0x51, 0x3f,
+  0xff, 0xd4, 0xea, 0xbe, 0x02, 0x5d, 0x0c, 0xbf, 0x8d, 0x5e, 0xf8, 0xbe, 0x2d, 0x66, 0xb1, 0xbd,
+  0x2e, 0xd4, 0x51, 0x3f, 0xe0, 0x1a, 0x93, 0xbe, 0x95, 0x96, 0xcb, 0x3f, 0x99, 0xa0, 0xab, 0xbf,
+  0x87, 0x75, 0x0d, 0x3f, 0x90, 0xf4, 0xbd, 0xbf, 0xd7, 0x1e, 0x26, 0x40, 0x5d, 0xc9, 0x83, 0x3f,
+  0x5b, 0x1b, 0x17, 0x3f, 0xd4, 0xe6, 0x07, 0xc0, 0xae, 0x09, 0xcb, 0x3e, 0x83, 0xa9, 0x97, 0x3d,
+  0x9d, 0xf4, 0xbf, 0x3f, 0x01, 0xe5, 0xb3, 0x3d, 0xf2, 0x3a, 0x9a, 0x3e, 0x65, 0x1c, 0x0c, 0xbf,
+  0xad, 0x91, 0x6a, 0xbe, 0x7a, 0x8b, 0x0f, 0x3f, 0xfe, 0x20, 0x2a, 0x3d, 0xae, 0xbe, 0x09, 0x40,
+  0xed, 0xfe, 0xa4, 0x3f, 0xa3, 0xfe, 0x21, 0xbf, 0xba, 0x12, 0x22, 0xbe, 0xc0, 0xf7, 0xcb, 0xbe,
+  0xdf, 0x81, 0xa1, 0x3d, 0x2a, 0x80, 0x27, 0x3f, 0xb0, 0xa6, 0x03, 0x3f, 0x9f, 0xb1, 0xe4, 0x3f,
+  0x00, 0xee, 0x8a, 0xbe, 0xbc, 0x85, 0x18, 0xbf, 0xf5, 0x8c, 0x65, 0x3e, 0x69, 0xaf, 0xb3, 0xbd,
+  0x01, 0xba, 0x20, 0xc0, 0x67, 0x8c, 0x53, 0x3f, 0xc7, 0x91, 0xe9, 0x3e, 0x82, 0x1e, 0x66, 0xbe,
+  0xfa, 0xed, 0x1b, 0x3f, 0xde, 0x84, 0x04, 0xbf, 0xce, 0x2b, 0xa8, 0x3f, 0x8f, 0xfd, 0x34, 0xbf,
+  0x61, 0x17, 0x53, 0xbe, 0x7f, 0xc1, 0xf1, 0x3e, 0x84, 0x66, 0x63, 0xbd, 0x40, 0xf4, 0x95, 0x3e,
+  0x2b, 0x75, 0x2f, 0x3f, 0x7a, 0x89, 0x17, 0xbf, 0x21, 0x51, 0x94, 0xbf, 0xbb, 0x9b, 0xc0, 0x3f,
+  0x2d, 0xce, 0xa4, 0x3f, 0x8c, 0x30, 0xdc, 0x3e, 0x92, 0xca, 0x0e, 0x3e, 0x26, 0x66, 0x2a, 0xbf,
+  0xb3, 0x26, 0xdc, 0x3d, 0xd0, 0xcd, 0xa2, 0x3f, 0x47, 0x8d, 0x2b, 0xbe, 0xbf, 0xa4, 0x10, 0xbf,
+  0x23, 0x07, 0x71, 0x3e, 0xc2, 0xa6, 0xc5, 0xbf, 0x80, 0x4f, 0xb1, 0xbf, 0x74, 0xe1, 0xc5, 0x3e,
+  0xae, 0xb7, 0x0b, 0x3f, 0xdf, 0xbd, 0xab, 0x3f, 0x5f, 0xd1, 0x63, 0x3e, 0xa6, 0x82, 0x00, 0x3f,
+  0xe4, 0xa4, 0x27, 0xbe, 0xc2, 0x41, 0x01, 0xbf, 0xdb, 0xf7, 0x53, 0x3e, 0x08, 0x77, 0x4f, 0xbe,
+  0x7c, 0x5a, 0x57, 0xbf, 0x78, 0x96, 0x02, 0x3d, 0xd8, 0x7f, 0x90, 0xbf, 0x9c, 0xec, 0x29, 0xbd,
+  0xb2, 0x61, 0xa7, 0x3f, 0x9c, 0xca, 0xb0, 0x3f, 0x5a, 0x17, 0xc2, 0x3f, 0x4b, 0x84, 0xcd, 0xbe,
+  0x61, 0x0e, 0xc7, 0x3e, 0xfe, 0xdc, 0x27, 0xbf, 0x6f, 0xba, 0x80, 0x3e, 0x0b, 0x12, 0xb5, 0xbd,
+  0x72, 0xb3, 0xc9, 0x3d, 0xa5, 0xd9, 0x66, 0x3f, 0x03, 0x27, 0x14, 0x3f, 0x1c, 0x5c, 0xac, 0x3e,
+  0xf1, 0xaf, 0xa8, 0x3f, 0xf5, 0x8a, 0x5e, 0x3e, 0x21, 0x7a, 0xcb, 0x3e, 0x6a, 0x1b, 0x3a, 0xbf,
+  0x61, 0x1a, 0x36, 0x3e, 0x47, 0x18, 0xf4, 0xbe, 0xfb, 0x44, 0xeb, 0x3f, 0xed, 0xec, 0x84, 0xbf,
+  0xa9, 0xba, 0x2f, 0xbf, 0x57, 0x9b, 0xd4, 0x3e, 0xb8, 0xed, 0xde, 0x3f, 0xc2, 0x0f, 0x15, 0x3e,
+  0xb8, 0x75, 0x43, 0xbf, 0x98, 0x16, 0x0e, 0xbd, 0x92, 0x44, 0x84, 0x3e, 0x6e, 0x4c, 0xe5, 0x3f,
+  0x36, 0x90, 0x6f, 0xbd, 0x49, 0x20, 0x0a, 0xbf, 0x56, 0x7d, 0x0a, 0x40, 0x4d, 0xc7, 0xad, 0x3f,
+  0x7f, 0x1a, 0x89, 0xbe, 0xc0, 0x51, 0xe7, 0x3f, 0xdf, 0x12, 0x74, 0x3e, 0x33, 0x0e, 0x8d, 0xbf,
+  0x3b, 0xf9, 0x50, 0xbf, 0x5a, 0x90, 0x95, 0xbf, 0x8e, 0x4d, 0x14, 0xbf, 0x7b, 0x43, 0x4f, 0xbf,
+  0x81, 0xee, 0x56, 0x3f, 0xa8, 0x23, 0x13, 0xbe, 0x40, 0xe0, 0x80, 0x3f, 0x40, 0x42, 0xe2, 0xbf,
+  0x58, 0x4f, 0x39, 0x3f, 0xc3, 0x30, 0x46, 0x3e, 0x2d, 0x04, 0xc6, 0xbf, 0xd3, 0x04, 0x0b, 0xbf,
+  0x0f, 0xa8, 0xfd, 0x3f, 0x8b, 0xc7, 0xa8, 0x3f, 0xb4, 0x24, 0xe2, 0x3e, 0x51, 0x9e, 0x54, 0xbe,
+  0xd1, 0x8d, 0x6e, 0xbe, 0xf8, 0x1b, 0x15, 0x3e, 0xb7, 0xaf, 0x17, 0x3f, 0xf1, 0x2f, 0xda, 0x3f,
+  0x92, 0xc8, 0x17, 0x3f, 0xee, 0x0b, 0x6c, 0xbf, 0xd3, 0x35, 0x69, 0xbf, 0x48, 0x69, 0x1e, 0x3f,
+  0x2a, 0x98, 0xb1, 0x3e, 0x9e, 0xab, 0x83, 0xbe, 0x47, 0x71, 0x8d, 0xbf, 0x2f, 0x13, 0x59, 0x3f,
+  0x31, 0xed, 0xc8, 0x3e, 0x25, 0x9b, 0xc3, 0xbe, 0x82, 0xe8, 0x3c, 0xbf, 0x5e, 0xf0, 0x04, 0x3e,
+  0x81, 0x07, 0xaa, 0xbf, 0x23, 0xe6, 0x87, 0xbf, 0x85, 0x1e, 0x92, 0xbe, 0xf1, 0xfb, 0xaf, 0xbd,
+  0xb0, 0xb0, 0x2d, 0x3f, 0xc9, 0xd5, 0x25, 0x3f, 0x7b, 0xe9, 0x06, 0x3e, 0xb3, 0xf0, 0xc5, 0xbe,
+  0x2a, 0xcf, 0x57, 0x3e, 0xeb, 0x4d, 0x87, 0x3e, 0xaa, 0x3a, 0x89, 0x3f, 0x5f, 0x35, 0xd8, 0x3e,
+  0x5a, 0xd9, 0xc6, 0xbe, 0xb7, 0xe4, 0x12, 0xbf, 0x95, 0x20, 0x65, 0x3f, 0x8a, 0x2f, 0xa8, 0xbd,
+  0x09, 0x11, 0xc8, 0xbf, 0x93, 0xf5, 0x80, 0x3f, 0x78, 0x3a, 0x1f, 0x3f, 0x3a, 0x9d, 0x0e, 0xbf,
+  0x25, 0x38, 0x67, 0x3f, 0x0d, 0xbe, 0x74, 0x3f, 0x84, 0x08, 0x11, 0xbd, 0xae, 0xae, 0xa4, 0xbf,
+  0xd6, 0xe0, 0x9b, 0x3f, 0x64, 0x85, 0x26, 0x3f, 0xd0, 0x7b, 0x82, 0x3f, 0xa3, 0xc7, 0x62, 0x3f,
+  0x54, 0xdd, 0xf6, 0x3e, 0x9b, 0xe5, 0x6f, 0xbf, 0x35, 0xa9, 0x9d, 0xbf, 0x3e, 0x21, 0xa1, 0xbf,
+  0x56, 0x58, 0x8a, 0xbf, 0x52, 0x54, 0x14, 0x3f, 0x36, 0xcb, 0x64, 0xbf, 0x78, 0xac, 0x58, 0x3f,
+  0x63, 0x7e, 0x5e, 0x3f, 0x23, 0xc9, 0x91, 0x3f, 0x41, 0x95, 0xb0, 0x3f, 0x99, 0xa2, 0x30, 0x3f,
+  0x9d, 0xf4, 0x27, 0xbf, 0x3e, 0xe1, 0xaf, 0x3e, 0x39, 0x54, 0xad, 0xbf, 0xe0, 0x5c, 0xf8, 0xbe,
+  0x36, 0x19, 0x8a, 0x3f, 0x0f, 0x5b, 0x68, 0xbe, 0x51, 0xdf, 0x98, 0x3f, 0x1a, 0xf8, 0x06, 0xbf,
+  0xf6, 0xc1, 0x16, 0x3f, 0x30, 0x2e, 0x3e, 0xbf, 0x38, 0xe0, 0xaf, 0x3e, 0x0d, 0xf9, 0x61, 0x3f,
+  0xdd, 0xbb, 0x68, 0x3e, 0x3e, 0x61, 0xc4, 0x3d, 0x25, 0x7a, 0x15, 0x3e, 0xce, 0xb5, 0x1c, 0x3e,
+  0x49, 0x88, 0x09, 0x3f, 0x86, 0x5b, 0xf9, 0x3f, 0xcb, 0xed, 0x96, 0xbd, 0xcb, 0xd9, 0x3f, 0x3f,
+  0x84, 0x9f, 0x0f, 0x3f, 0x5d, 0x0a, 0xa1, 0xbd, 0x30, 0xb1, 0xa6, 0xbf, 0xb1, 0x23, 0x20, 0x3e,
+  0x4b, 0xbb, 0xcc, 0x3e, 0xdf, 0x65, 0xfa, 0x3f, 0x5a, 0xb8, 0x32, 0xbf, 0x55, 0x4a, 0xc6, 0xbd,
+  0x3d, 0x14, 0x7e, 0xbf, 0xc9, 0x6a, 0x41, 0x3e, 0x1a, 0x7b, 0xc8, 0x3e, 0xd4, 0x52, 0x1b, 0x3e,
+  0x81, 0xcb, 0x8c, 0xbd, 0xc4, 0xae, 0xba, 0x3f, 0xca, 0xba, 0x95, 0x3f, 0x71, 0xbd, 0x4b, 0xbf,
+  0x08, 0x26, 0xe5, 0x3e, 0xed, 0xad, 0x1a, 0xbf, 0xcd, 0x2c, 0x09, 0x3f, 0xfd, 0x48, 0x3e, 0x3f,
+  0x14, 0x76, 0x5a, 0x3f, 0x31, 0x8d, 0x7a, 0x3f, 0xae, 0xba, 0x0f, 0x3e, 0x11, 0x27, 0xa4, 0x3f,
+  0xd9, 0xae, 0x9b, 0xbe, 0x45, 0x9b, 0xcc, 0x3f, 0x63, 0x00, 0xbd, 0xbf, 0x3f, 0x81, 0x59, 0xbf,
+  0x66, 0xcc, 0x1a, 0xbf, 0x25, 0x25, 0xab, 0xbf, 0x6a, 0x64, 0x91, 0x3f, 0xb2, 0xed, 0x92, 0x3f,
+  0x7b, 0xf2, 0x30, 0xbd, 0x0f, 0x53, 0x30, 0xbd, 0x1c, 0x73, 0x04, 0xbf, 0x69, 0xae, 0x91, 0x3f,
+  0x24, 0x91, 0x2e, 0x3f, 0x2a, 0x51, 0xdd, 0x3f, 0xc8, 0xf0, 0xa1, 0xbf, 0xe6, 0x5e, 0x23, 0xbe,
+  0x1f, 0x74, 0x3e, 0xbf, 0x36, 0x5c, 0x66, 0x3f, 0xe9, 0xb1, 0xdf, 0xbe, 0x03, 0x80, 0x90, 0x3f,
+  0x62, 0x31, 0x8a, 0xbf, 0x04, 0x89, 0x0b, 0x3f, 0xff, 0xc5, 0x76, 0x3f, 0x6e, 0xf7, 0x96, 0xbf,
+  0x6c, 0xda, 0x9b, 0xbe, 0x7b, 0xde, 0x89, 0x3e, 0x74, 0x7d, 0x61, 0xbe, 0x66, 0xf3, 0xe1, 0x3f,
+  0xcf, 0xd5, 0x82, 0xbf, 0x6d, 0xa7, 0x9c, 0x3f, 0x6d, 0x3b, 0xf2, 0xbe, 0xc7, 0x15, 0xa8, 0xbf,
+  0xa1, 0x9a, 0xa8, 0x3f, 0xb9, 0xa3, 0x1a, 0x3f, 0x6d, 0x80, 0x2e, 0x3f, 0x4b, 0xe3, 0xc0, 0xbe,
+  0x14, 0xba, 0x91, 0x3f, 0x88, 0x11, 0xed, 0xbc, 0xb2, 0xe1, 0xc1, 0xbe, 0x40, 0x18, 0x17, 0xbf,
+  0x3c, 0x5e, 0xbb, 0x3c, 0x06, 0x97, 0x23, 0x40, 0xe4, 0x06, 0xb9, 0xbf, 0x57, 0xf1, 0x1a, 0xbe,
+  0x49, 0x85, 0xa8, 0x3c, 0xd7, 0xfa, 0x62, 0x3d, 0x63, 0x9d, 0x96, 0xbe, 0x64, 0x02, 0x23, 0x3e,
+  0x9a, 0x9d, 0x15, 0x3c, 0xeb, 0xbb, 0x6a, 0xbf, 0xfb, 0xd8, 0xa7, 0x3f, 0x2f, 0x3e, 0xc7, 0xbe,
+  0xe8, 0x3b, 0xeb, 0xbe, 0x90, 0x12, 0x75, 0x3d, 0xd0, 0x35, 0x94, 0x3d, 0x04, 0x0e, 0x4b, 0xbf,
+  0x20, 0xff, 0xc2, 0x3e, 0x98, 0xb2, 0x4a, 0xbf, 0x9f, 0x8d, 0x2b, 0x3f, 0x7c, 0x8e, 0xcb, 0x3e,
+  0x9d, 0xbc, 0x80, 0x3e, 0x59, 0xa0, 0x4b, 0x3f, 0x52, 0x95, 0x13, 0xbf, 0xe4, 0x5e, 0x50, 0xbe,
+  0x9b, 0x5e, 0xb7, 0x3f, 0x6d, 0xa0, 0xa8, 0x3f, 0x82, 0xc6, 0x1b, 0xbe, 0xbd, 0x47, 0x24, 0x3d,
+  0xd6, 0x2d, 0x9a, 0xbf, 0x28, 0xd2, 0x42, 0x3e, 0x3f, 0xf4, 0x86, 0xbf, 0x90, 0xa8, 0x1b, 0x3f,
+  0x5b, 0x22, 0x1b, 0xbe, 0x46, 0x77, 0x04, 0x3f, 0x63, 0x8c, 0xba, 0xbe, 0x45, 0x27, 0xc5, 0x3f,
+  0xb9, 0x8a, 0xa4, 0xbe, 0xda, 0xd1, 0x8a, 0xbd, 0x09, 0xe6, 0x53, 0xbf, 0xad, 0xad, 0x0b, 0xbf,
+  0xc2, 0x14, 0x71, 0x3f, 0x15, 0x78, 0x25, 0x3f, 0x53, 0x26, 0x6a, 0xbf, 0x07, 0x3a, 0xbe, 0x3e,
+  0xb9, 0x37, 0x1e, 0xbf, 0x0d, 0x07, 0x80, 0x3f, 0xd9, 0x9f, 0x01, 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, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 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, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00,
+  0xd4, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x10, 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, 0x40, 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, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+  0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67,
+  0x68, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x66,
+  0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x02, 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, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 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, 0x1b, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1b, 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 = {
+  -88.04056, 80.27833,  21.511183, 85.93182, 90.22253,  -50.795647, 78.00544, -17.377474,
+  -62.31908, 14.504589, 3.2413504, 32.54737, 25.954002, 9.092799,   70.73234, -45.636135};
+
+const std::vector<float> reference_output_data = {
+  26.202744, 463.3182,  84.626854, 289.90292,  0.0,       0.0,       0.0,       0.0,
+  69.141045, 0.0,       31.10253,  130.52267,  5.652733,  0.0,       72.082275, 0.0,
+  0.0,       128.29478, 63.66363,  136.1562,   47.363857, 197.50403, 0.0,       48.581432,
+  102.55079, 0.0,       75.65965,  0.0,        0.0,       0.0,       0.0,       338.36807,
+  0.0,       211.63658, 39.766064, 0.0,        215.11708, 363.6181,  0.0,       109.92663,
+  0.0,       0.0,       0.0,       0.84396774, 0.0,       0.0,       161.46375, 28.506226,
+  0.0,       0.0,       0.0,       92.488815,  222.40182, 48.270275, 26.44544,  0.0,
+  0.0,       0.0,       51.692745, 0.0,        316.81906, 0.6861581, 0.0,       42.598343};
+
+} // namespace svdf_float
+
+class TestDataFloatSVDF : public TestDataSVDFBase<float>
+{
+public:
+  TestDataFloatSVDF()
+  {
+    _input_data = svdf_float::input_data;
+    _reference_output_data = svdf_float::reference_output_data;
+    _test_kernel_model_circle = svdf_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSVDF() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_SVDF_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/svdf/NegSVDFKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/svdf/NegSVDFKernel.h
new file mode 100644 (file)
index 0000000..50dc14d
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_SVDF_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_SVDF_KERNEL_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_input_output_type_mismatch_svdf_kernel
+{
+/*
+ * SVDF Kernel with input output type mismatch:
+ *
+ *      Input(1, 16) - Float32
+ *            |
+ *           SVDF
+ *            |
+ *      Output(1, 64) - 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,
+  0x6c, 0x19, 0x00, 0x00, 0x60, 0x1b, 0x00, 0x00, 0x7c, 0x1b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x58, 0x19, 0x00, 0x00, 0x4c, 0x19, 0x00, 0x00, 0x44, 0x19, 0x00, 0x00, 0x34, 0x09, 0x00, 0x00,
+  0x1c, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc8, 0xe6, 0xff, 0xff,
+  0xe6, 0xf6, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc3, 0x55, 0x87, 0x3f,
+  0xc4, 0xb8, 0xd9, 0xbf, 0x10, 0xa4, 0x80, 0xbe, 0x8e, 0x9f, 0x95, 0x3f, 0xc6, 0xfb, 0x45, 0xbf,
+  0x52, 0x7d, 0xd3, 0x3e, 0xe0, 0xc9, 0x02, 0x3f, 0xe9, 0xd1, 0xee, 0x3d, 0xeb, 0x3a, 0xbc, 0xbf,
+  0x2b, 0xc6, 0x94, 0x3f, 0x00, 0x04, 0x98, 0xbe, 0x03, 0xb9, 0x23, 0x3f, 0x52, 0x74, 0x80, 0xbf,
+  0xcc, 0x61, 0x9d, 0xbf, 0x07, 0x81, 0x32, 0xbf, 0x27, 0x68, 0x0b, 0xbf, 0x0d, 0xef, 0xe7, 0xbe,
+  0xbd, 0xda, 0xb1, 0xbf, 0x2e, 0xc0, 0x96, 0x3f, 0x4c, 0x5a, 0x82, 0x3e, 0xdd, 0x0d, 0x31, 0xbf,
+  0x9e, 0xaa, 0x09, 0xbf, 0x04, 0xca, 0xc7, 0xbf, 0x75, 0xc6, 0x4b, 0x3e, 0x23, 0x2e, 0x94, 0x3e,
+  0x54, 0x1b, 0x85, 0x3f, 0xe2, 0x42, 0xf3, 0xbf, 0x86, 0xe9, 0x10, 0xc0, 0x73, 0xb9, 0x0a, 0x3f,
+  0x9a, 0xb2, 0x34, 0x3e, 0xd5, 0x03, 0x80, 0x3e, 0x51, 0x91, 0x2b, 0xbf, 0x5f, 0x5a, 0x37, 0xbf,
+  0xed, 0x27, 0xec, 0x3f, 0x1e, 0x65, 0xaa, 0x3e, 0xa7, 0x3f, 0x9c, 0x3e, 0x4a, 0xf7, 0x7e, 0xbf,
+  0x24, 0x57, 0xb0, 0xbf, 0xa4, 0x06, 0x61, 0x3f, 0x82, 0x86, 0xce, 0x3e, 0x99, 0x32, 0x9b, 0xbf,
+  0xc9, 0xc1, 0xc3, 0x3f, 0x51, 0xed, 0x85, 0x3f, 0x8d, 0x3a, 0x30, 0x3f, 0xd4, 0xe0, 0x2a, 0xc0,
+  0xf1, 0x5d, 0x92, 0xbf, 0x09, 0x85, 0x0e, 0xbf, 0x1b, 0x93, 0x0f, 0xbf, 0x80, 0xae, 0x98, 0x3e,
+  0x7e, 0x7e, 0x77, 0x3f, 0xfe, 0x4b, 0x26, 0xbe, 0x77, 0x12, 0x1b, 0xbf, 0x81, 0xf5, 0xcc, 0xbe,
+  0x55, 0xdd, 0x28, 0x3f, 0xad, 0x11, 0x25, 0xc0, 0xff, 0x87, 0xfd, 0x3f, 0x6f, 0x5a, 0x2e, 0x3f,
+  0x59, 0x8f, 0x8e, 0x3f, 0xf0, 0x03, 0xe8, 0x3f, 0xbb, 0x41, 0x0e, 0x3f, 0x62, 0x9d, 0x0d, 0xbf,
+  0xaf, 0xcc, 0xec, 0xbc, 0x71, 0x8d, 0x87, 0xbf, 0xbe, 0x72, 0x5a, 0x3f, 0xf2, 0xf7, 0xff, 0xff,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xd3, 0xc7, 0xee, 0x3e, 0xe8, 0x29, 0x4e, 0x40,
+  0xbb, 0xc5, 0x9c, 0xbe, 0xeb, 0x24, 0x9c, 0xbf, 0xf3, 0x50, 0x92, 0xbe, 0x22, 0x9a, 0x70, 0x3f,
+  0x60, 0xea, 0xcf, 0x3c, 0x25, 0x80, 0xa0, 0x3f, 0xef, 0xde, 0xb5, 0xbe, 0x04, 0x9e, 0x53, 0xbf,
+  0xc4, 0xac, 0xd7, 0x3f, 0xd6, 0xef, 0xba, 0xbf, 0x19, 0x73, 0x13, 0x40, 0xec, 0x4d, 0x81, 0x3f,
+  0xe1, 0xd3, 0xf3, 0x3d, 0x46, 0xb7, 0x51, 0x3f, 0x2c, 0xc7, 0x96, 0x3f, 0x6a, 0x42, 0x29, 0xbe,
+  0xc7, 0x72, 0x29, 0xbd, 0x88, 0x8c, 0xa3, 0x3f, 0xf9, 0xb8, 0xf0, 0x3f, 0x39, 0xde, 0x5b, 0xbf,
+  0xa5, 0x7c, 0xfc, 0x3f, 0xfe, 0xa7, 0x1d, 0xbe, 0x42, 0x6c, 0xb1, 0x3f, 0xa7, 0x06, 0x12, 0xbf,
+  0x6a, 0x1d, 0x7f, 0x3f, 0x38, 0xe0, 0x4a, 0xbf, 0xdd, 0x30, 0xc4, 0xbf, 0x8a, 0x51, 0x0d, 0xbe,
+  0x67, 0xef, 0x47, 0x3e, 0xad, 0x06, 0x1d, 0xbe, 0x9f, 0x53, 0xe1, 0x3f, 0x85, 0xbe, 0x38, 0xbe,
+  0xe2, 0x3b, 0x82, 0xbf, 0xda, 0xce, 0x9c, 0xbf, 0x00, 0xa8, 0x20, 0xbf, 0x45, 0x30, 0x45, 0xc0,
+  0x4f, 0x52, 0xe8, 0x3d, 0x08, 0x86, 0xd9, 0x3f, 0x08, 0xb4, 0x61, 0xbe, 0x92, 0x6f, 0x9e, 0x3e,
+  0xba, 0xa1, 0x78, 0x3f, 0x2f, 0x86, 0xfa, 0xbe, 0x02, 0xfc, 0x98, 0x3c, 0x5c, 0x64, 0xc8, 0x3f,
+  0x98, 0x48, 0x18, 0xc0, 0x53, 0xa8, 0xee, 0xbe, 0xfa, 0xe3, 0x39, 0x3f, 0x28, 0x7e, 0x23, 0xbf,
+  0x26, 0xac, 0xb8, 0xbf, 0xc9, 0x35, 0x8b, 0x3f, 0xa3, 0x96, 0xb7, 0x3e, 0x3d, 0x5c, 0x9a, 0x3f,
+  0xb4, 0xaa, 0xd5, 0xbf, 0x04, 0xd3, 0x93, 0xbf, 0xd6, 0xf5, 0x80, 0xbe, 0x4b, 0xf1, 0x6a, 0x3f,
+  0xbd, 0xae, 0x89, 0xbb, 0x45, 0x8f, 0xaa, 0x3d, 0x52, 0xde, 0x17, 0xc0, 0xa8, 0xfe, 0x82, 0xbf,
+  0x60, 0xcd, 0xf8, 0xbe, 0xfa, 0xdc, 0x25, 0x3e, 0x13, 0xd8, 0x7d, 0xbe, 0x2b, 0x7b, 0xac, 0xbf,
+  0x71, 0xde, 0x8f, 0xbf, 0x48, 0xf3, 0x18, 0xbf, 0xd0, 0x50, 0x70, 0x3e, 0x12, 0x48, 0xb6, 0xbe,
+  0x5e, 0xda, 0x49, 0x3f, 0x28, 0x57, 0xf8, 0x3f, 0x2e, 0x2b, 0xf4, 0x3d, 0x6f, 0xa7, 0xa3, 0x3e,
+  0xd3, 0x19, 0xa9, 0xbf, 0xa1, 0x2d, 0xe4, 0xbe, 0x44, 0x66, 0x7b, 0x3e, 0x28, 0x66, 0x02, 0x3e,
+  0x0b, 0xae, 0xa1, 0xbf, 0xec, 0xb1, 0x8e, 0x3e, 0x1b, 0xb5, 0x1f, 0xbf, 0xe1, 0x2c, 0xa1, 0xbe,
+  0xbb, 0x0f, 0x2e, 0xbf, 0x3b, 0xb1, 0xf5, 0x3d, 0x08, 0x75, 0xeb, 0xbf, 0x3a, 0x2f, 0xa2, 0xbf,
+  0x35, 0x46, 0xe6, 0xbf, 0xa6, 0xac, 0xcb, 0xbe, 0xb3, 0xb0, 0x70, 0xbf, 0x0d, 0xd4, 0x89, 0x3e,
+  0x13, 0x5b, 0x3b, 0x3d, 0x89, 0x15, 0x21, 0xbf, 0x43, 0xf2, 0x93, 0xbf, 0x36, 0x8f, 0xed, 0x3f,
+  0x90, 0x41, 0x17, 0xbf, 0x35, 0x6d, 0xd6, 0x3f, 0xe9, 0xa7, 0x5d, 0x3e, 0xe4, 0xcf, 0xbd, 0x3e,
+  0xb7, 0xb1, 0xed, 0xbe, 0x97, 0x8a, 0xbe, 0xbf, 0xd0, 0x5e, 0xb2, 0x3e, 0x08, 0x4f, 0xb0, 0x3f,
+  0x08, 0xfe, 0x2f, 0xc0, 0xc8, 0x4f, 0x97, 0x3f, 0x5e, 0x4d, 0xc3, 0x3f, 0x4f, 0x56, 0x6f, 0x3b,
+  0x7a, 0xdb, 0x3f, 0x3f, 0x88, 0xb5, 0x80, 0x3e, 0xf4, 0x8b, 0x68, 0x3f, 0x32, 0xd3, 0xb8, 0x3e,
+  0x37, 0x92, 0xc9, 0xbf, 0x87, 0x6d, 0x99, 0xbe, 0xd2, 0x96, 0x81, 0xbf, 0x6f, 0x47, 0xab, 0x3f,
+  0x20, 0x81, 0x98, 0xbd, 0x55, 0xef, 0xe8, 0xbe, 0xb4, 0x0a, 0x93, 0xbe, 0x05, 0x3a, 0xe5, 0x3d,
+  0x99, 0x94, 0x99, 0xbe, 0x1b, 0xaf, 0xe2, 0xbd, 0x9c, 0x30, 0x22, 0xbf, 0x22, 0x7f, 0xc9, 0x3f,
+  0x91, 0xbc, 0x10, 0x3f, 0x29, 0xcc, 0xeb, 0x3f, 0xc0, 0x1b, 0xec, 0x3e, 0x5c, 0x5a, 0xae, 0xbf,
+  0x0f, 0x5b, 0xf5, 0xbf, 0x61, 0xc9, 0x8b, 0x3f, 0x38, 0xd9, 0x1e, 0x3f, 0xf5, 0x1f, 0x82, 0x3e,
+  0x99, 0x04, 0xae, 0x3f, 0x20, 0xd3, 0x00, 0x3f, 0xe7, 0x58, 0xd9, 0x3d, 0xcb, 0x1b, 0x67, 0xbf,
+  0xc5, 0x95, 0x8c, 0x3f, 0x64, 0x39, 0x5b, 0x3b, 0x2a, 0x80, 0x20, 0x3f, 0x44, 0x4f, 0x1e, 0xbf,
+  0x3f, 0xf4, 0xb7, 0x3e, 0x22, 0x5e, 0x45, 0xbd, 0x87, 0x00, 0x26, 0xbf, 0xa3, 0x7a, 0xc2, 0x3f,
+  0xac, 0x45, 0x9b, 0xbf, 0xa4, 0x59, 0x87, 0x3e, 0x0c, 0xc1, 0x19, 0xbf, 0x78, 0x40, 0xc3, 0x3f,
+  0x5a, 0x69, 0xef, 0x3f, 0x47, 0x5b, 0x8c, 0xbf, 0x10, 0x73, 0x22, 0x3f, 0xd0, 0xe0, 0x7d, 0xbf,
+  0xdd, 0x87, 0xd7, 0x3d, 0x60, 0xd7, 0xd8, 0x3e, 0x2e, 0xbf, 0x47, 0x3f, 0xdb, 0x13, 0xbe, 0xbf,
+  0x80, 0x90, 0xc5, 0x3e, 0xe5, 0x46, 0x62, 0x3f, 0x9d, 0x13, 0xb8, 0xbf, 0x2d, 0x31, 0x68, 0xbf,
+  0xa1, 0xe4, 0x13, 0xbf, 0x91, 0xba, 0x5b, 0xbd, 0xb6, 0x07, 0xc0, 0xbf, 0x83, 0xde, 0x1f, 0xc0,
+  0xb2, 0xee, 0x06, 0xbf, 0x33, 0xbf, 0x3d, 0x3f, 0x10, 0xbb, 0x64, 0x3f, 0x4d, 0x9a, 0xd2, 0xbe,
+  0x85, 0xf4, 0xf8, 0xbe, 0xf9, 0x2f, 0x8a, 0xbf, 0x4f, 0xc6, 0x61, 0x3f, 0x3f, 0x19, 0xde, 0xbf,
+  0x39, 0xd7, 0x83, 0xbc, 0x8a, 0xe7, 0xa9, 0xbe, 0x8f, 0x41, 0xb8, 0x3e, 0x5a, 0x75, 0xb6, 0xbe,
+  0xd1, 0x33, 0x4a, 0xbe, 0xc0, 0xf4, 0x1b, 0xbf, 0xc8, 0xc4, 0xdb, 0xbe, 0xca, 0x58, 0x90, 0x3e,
+  0x24, 0x3c, 0xf4, 0xbf, 0x01, 0xe5, 0x77, 0xbf, 0xc4, 0x16, 0x94, 0xbe, 0xee, 0x88, 0x65, 0x3f,
+  0x34, 0xe3, 0x87, 0xbf, 0x9d, 0x7d, 0x5d, 0xbf, 0xdc, 0x18, 0x22, 0x3e, 0x39, 0x31, 0x12, 0xc0,
+  0x3f, 0x6f, 0xce, 0x3f, 0x5a, 0xa4, 0x90, 0xbf, 0x9e, 0x51, 0xd0, 0xbf, 0x19, 0xb0, 0xdf, 0xbf,
+  0xbf, 0x27, 0xb9, 0x3d, 0xdf, 0x28, 0x5d, 0xbf, 0x1f, 0x15, 0x07, 0xbf, 0x98, 0xfb, 0xf6, 0xbf,
+  0x17, 0x2b, 0x49, 0x3e, 0x68, 0x8e, 0x0b, 0xc0, 0xbd, 0xab, 0x06, 0xbe, 0x31, 0xb5, 0x95, 0x3f,
+  0x31, 0xcd, 0xb5, 0x3f, 0x1a, 0x46, 0x16, 0xbf, 0x95, 0xf0, 0xbc, 0xbe, 0xae, 0xae, 0xb3, 0xbf,
+  0xb7, 0x30, 0x1b, 0x3f, 0x37, 0x42, 0xf3, 0x3f, 0x7a, 0x64, 0x01, 0xbf, 0xbc, 0x47, 0x10, 0x3f,
+  0xd9, 0x9b, 0xae, 0x3f, 0x18, 0x34, 0x40, 0xbf, 0x23, 0x6f, 0x66, 0x3e, 0x4c, 0x46, 0x68, 0x3e,
+  0x71, 0x4d, 0xe5, 0xbf, 0x23, 0x2b, 0xe0, 0xbc, 0x0a, 0x92, 0x27, 0xbe, 0xe6, 0x3c, 0x12, 0x3f,
+  0x2b, 0x68, 0xac, 0x3f, 0x60, 0xcd, 0xb8, 0xbf, 0x37, 0x90, 0xbd, 0xbe, 0x77, 0x1a, 0xd4, 0x3f,
+  0xd2, 0x67, 0x95, 0x3f, 0xf4, 0xdf, 0xd7, 0x3f, 0x3c, 0x61, 0x70, 0x3e, 0xb7, 0xfc, 0x8e, 0x3f,
+  0x70, 0x89, 0x97, 0xbf, 0xc1, 0x97, 0xa3, 0xbe, 0x12, 0x8c, 0x36, 0x3e, 0x64, 0xdf, 0x83, 0xbf,
+  0xd2, 0xce, 0xbc, 0x3f, 0x64, 0xbd, 0x2e, 0x3e, 0x39, 0xe6, 0x1c, 0xbf, 0x04, 0xc6, 0x43, 0xbf,
+  0x5d, 0x21, 0x8a, 0x3f, 0xd8, 0x09, 0x31, 0x3f, 0x6e, 0xd6, 0xc8, 0x3d, 0x67, 0x5a, 0x22, 0xc0,
+  0x72, 0xbd, 0x18, 0xbf, 0xab, 0xb6, 0x3e, 0x3e, 0x62, 0x34, 0x9f, 0xbd, 0xcc, 0x5a, 0x94, 0xbf,
+  0xd5, 0x9c, 0x9b, 0xbe, 0xbc, 0x0f, 0x89, 0x3e, 0xa5, 0x30, 0x04, 0xc0, 0xa4, 0x16, 0x75, 0xbf,
+  0x37, 0xea, 0x2f, 0x3e, 0xb0, 0xcd, 0xf0, 0x3e, 0x5a, 0x86, 0xe4, 0x3e, 0xe0, 0x31, 0x92, 0xbf,
+  0xb5, 0x56, 0xa4, 0xbe, 0xf8, 0xf6, 0xdd, 0x3f, 0x45, 0x27, 0x25, 0xbe, 0xff, 0x8d, 0x2c, 0x3e,
+  0x10, 0x84, 0x6b, 0xbf, 0x80, 0xb7, 0x95, 0x3e, 0xdf, 0xe0, 0xe0, 0x3f, 0x5e, 0xfe, 0xc7, 0xbe,
+  0xd0, 0xd3, 0x8e, 0xbf, 0xcf, 0x68, 0x8d, 0x3f, 0x23, 0x49, 0x3e, 0xbf, 0x4e, 0x4c, 0x92, 0x3f,
+  0x5d, 0xba, 0x8c, 0x3e, 0xf6, 0x8b, 0x4f, 0x3f, 0x0a, 0x1e, 0xf6, 0xbf, 0x28, 0xc7, 0x8d, 0x3f,
+  0xcd, 0xf2, 0x12, 0xbf, 0x0b, 0x84, 0xe3, 0x3f, 0xdc, 0x9d, 0xcc, 0x3f, 0xa5, 0x46, 0x4a, 0xbf,
+  0x95, 0x2d, 0x77, 0xbe, 0x64, 0x9d, 0x96, 0x3e, 0x96, 0x02, 0x7a, 0xbf, 0x4d, 0x58, 0x41, 0x3f,
+  0x74, 0x5b, 0xca, 0xbf, 0x50, 0x70, 0xe1, 0x3e, 0x68, 0xa4, 0xa1, 0x3f, 0xb5, 0x10, 0x05, 0x3f,
+  0x99, 0x3e, 0x37, 0x40, 0xec, 0x59, 0xc7, 0x3f, 0x56, 0x68, 0x63, 0xbf, 0x03, 0xfd, 0xd6, 0x3e,
+  0x7a, 0x63, 0x84, 0x3f, 0x09, 0x18, 0x99, 0x3f, 0x3c, 0x41, 0xbb, 0x3e, 0x2c, 0x06, 0x8f, 0xbf,
+  0xf1, 0x31, 0x96, 0xbe, 0x56, 0x5e, 0xdf, 0x3f, 0xa3, 0x51, 0x94, 0x3f, 0x2b, 0xc4, 0x34, 0x3e,
+  0xe4, 0x0b, 0xf2, 0x3e, 0x2b, 0x4f, 0xdc, 0x3e, 0xb7, 0xbb, 0x8d, 0x3e, 0xb8, 0xfe, 0xcf, 0xbe,
+  0xa1, 0xe6, 0x28, 0x3f, 0xa0, 0xa6, 0x21, 0x3f, 0xbf, 0xa8, 0xba, 0x3e, 0xe3, 0xb2, 0xb3, 0xbd,
+  0x16, 0x8a, 0x09, 0x3f, 0x06, 0x3c, 0xe5, 0xbd, 0xe9, 0xcf, 0x7d, 0x3e, 0xdd, 0x8a, 0x13, 0x3f,
+  0xd2, 0xd6, 0x43, 0xbf, 0xd6, 0x99, 0xad, 0xbe, 0xeb, 0xfa, 0x03, 0x40, 0xc0, 0x1e, 0xac, 0xbd,
+  0x0c, 0x8a, 0x70, 0xbd, 0x8a, 0x78, 0x1a, 0xbc, 0x90, 0xc5, 0xf1, 0xbe, 0x48, 0xfc, 0xb2, 0xbe,
+  0x70, 0x87, 0x50, 0xbf, 0x00, 0x5a, 0x56, 0xbf, 0xce, 0xe9, 0x28, 0x3f, 0xf6, 0x8a, 0x82, 0xbe,
+  0xb1, 0x12, 0xf0, 0xbf, 0x9a, 0xbc, 0x1d, 0xbf, 0x31, 0x71, 0xec, 0x3d, 0x14, 0x67, 0x9a, 0xbc,
+  0x92, 0xc1, 0x19, 0x3f, 0xcc, 0x6c, 0xe4, 0xbf, 0xde, 0x5a, 0x9f, 0x3f, 0x6d, 0xf3, 0x12, 0x3e,
+  0x49, 0x3f, 0xd9, 0xbf, 0x9d, 0xc5, 0x62, 0xbe, 0x2d, 0xcd, 0xe9, 0xbe, 0xfc, 0xda, 0xc2, 0xbf,
+  0x0e, 0xa1, 0x4a, 0x3d, 0xa4, 0x58, 0x04, 0x40, 0x71, 0xe1, 0x4c, 0x3f, 0x40, 0xfc, 0xd9, 0x3d,
+  0xa3, 0x49, 0x03, 0x3f, 0xbe, 0xaa, 0x5e, 0x3e, 0xde, 0x4e, 0x07, 0x40, 0xe2, 0x20, 0x17, 0x3f,
+  0xe0, 0x35, 0xe2, 0x3f, 0xad, 0x18, 0x1d, 0xbd, 0x67, 0xbb, 0x13, 0xbf, 0x9d, 0x36, 0xb6, 0x3e,
+  0x09, 0x38, 0x38, 0xbf, 0x6d, 0x88, 0x01, 0x3e, 0x3c, 0x4e, 0x84, 0x3f, 0x71, 0xc2, 0x0a, 0xbf,
+  0x2b, 0x80, 0x91, 0xbe, 0x99, 0x77, 0x7f, 0xbf, 0x07, 0xa4, 0x0a, 0x3c, 0xaf, 0xd3, 0x8a, 0xbe,
+  0x4b, 0xfb, 0x83, 0x3f, 0x48, 0x45, 0xcb, 0x3e, 0x67, 0x7e, 0xf2, 0x3e, 0x53, 0xde, 0x2b, 0x3f,
+  0xc7, 0xec, 0x1a, 0x3d, 0x15, 0x3a, 0xad, 0x3e, 0x09, 0x7e, 0xaa, 0x3e, 0xf2, 0xa6, 0x89, 0xbd,
+  0xa4, 0x0c, 0xb9, 0xbe, 0xb1, 0x65, 0x31, 0x3e, 0x51, 0x9e, 0x29, 0xbf, 0xd5, 0x74, 0x6b, 0x3f,
+  0x69, 0x68, 0x52, 0x3e, 0xeb, 0xc3, 0x21, 0xbf, 0x72, 0xa0, 0xf3, 0x3d, 0x74, 0x2f, 0x31, 0xbe,
+  0x1c, 0xf3, 0x21, 0x3e, 0x70, 0xce, 0xe7, 0x3e, 0xb3, 0x88, 0x7a, 0x3e, 0x94, 0x86, 0x8d, 0xbf,
+  0x0a, 0x11, 0x15, 0x3f, 0x57, 0xfc, 0x24, 0x3f, 0x5f, 0x2c, 0x3c, 0x3f, 0xbc, 0xb4, 0xcb, 0xbf,
+  0x71, 0x91, 0xd6, 0xbf, 0x46, 0x77, 0xa2, 0xbd, 0xa7, 0x30, 0x8b, 0xbf, 0x5b, 0xfb, 0x51, 0xbf,
+  0xc6, 0x06, 0xaf, 0xbd, 0x65, 0xb8, 0x5a, 0x3e, 0xb5, 0x0d, 0xb4, 0xbf, 0xe6, 0xa1, 0xa5, 0xbe,
+  0x15, 0xaa, 0xb5, 0xbe, 0x0a, 0x1d, 0xd2, 0xbf, 0x4e, 0x6e, 0x1c, 0xbf, 0x35, 0xec, 0x50, 0x3d,
+  0xe1, 0x1b, 0x32, 0x3f, 0xee, 0xe0, 0x0c, 0xbd, 0x78, 0x81, 0xdc, 0x3e, 0x32, 0xa0, 0x4d, 0x3e,
+  0x49, 0xa3, 0x0c, 0xc0, 0x0b, 0xa0, 0x38, 0xbf, 0x1f, 0x78, 0x4a, 0xbf, 0xa2, 0xef, 0x18, 0xbf,
+  0x1b, 0x81, 0xb2, 0x3f, 0x4d, 0x72, 0x98, 0x3f, 0x61, 0xbe, 0x12, 0xbf, 0xc7, 0x6f, 0xdf, 0xbd,
+  0x4e, 0x87, 0x98, 0x3f, 0x3d, 0x23, 0x1d, 0x3d, 0x8f, 0x10, 0x41, 0xbf, 0x6b, 0x4c, 0x63, 0x3f,
+  0x0d, 0x64, 0xf9, 0xbe, 0xc7, 0xdd, 0x20, 0xbf, 0xe8, 0x2b, 0xa7, 0xbf, 0x2d, 0xb4, 0x7c, 0xbe,
+  0xa0, 0x5a, 0xe8, 0x3e, 0xd2, 0xd3, 0x55, 0x3f, 0x2d, 0x60, 0x91, 0xbe, 0xc2, 0x9f, 0xb5, 0x3f,
+  0xf5, 0x63, 0x3c, 0x3f, 0xca, 0x48, 0x92, 0xbf, 0xc5, 0xf8, 0x0a, 0x3f, 0x0a, 0x6a, 0x31, 0x3d,
+  0xea, 0x1a, 0x43, 0x3f, 0x2a, 0x48, 0xa6, 0xbf, 0x62, 0x30, 0x31, 0x3f, 0xcc, 0x53, 0x93, 0xbf,
+  0x12, 0x96, 0x3b, 0x3f, 0x6e, 0xa1, 0xc4, 0x3f, 0xd2, 0xae, 0x06, 0xbc, 0xd1, 0xdd, 0xbb, 0xbf,
+  0xea, 0x3a, 0x7e, 0xbf, 0xcb, 0x67, 0x9c, 0x3e, 0x1a, 0x9f, 0x44, 0xbf, 0x6c, 0xd5, 0x2f, 0xbf,
+  0xc9, 0xe9, 0x8f, 0xbe, 0xe6, 0xf1, 0x90, 0x3c, 0x35, 0x83, 0xac, 0xbf, 0x6c, 0xc0, 0xca, 0x3f,
+  0x81, 0x21, 0x90, 0x3f, 0x51, 0x96, 0xdc, 0xbf, 0xd6, 0x4a, 0xa4, 0xbf, 0x5d, 0x9e, 0x77, 0xbf,
+  0x49, 0x63, 0x2d, 0x3f, 0xf0, 0x1e, 0xc8, 0xbf, 0x17, 0xf7, 0xd9, 0x3f, 0xdc, 0xbb, 0xe4, 0x3f,
+  0x31, 0x5e, 0x38, 0x3f, 0xf8, 0xc1, 0xa5, 0xbf, 0x33, 0x50, 0xe2, 0xbe, 0xb0, 0x33, 0x80, 0x3f,
+  0x1b, 0xd2, 0x45, 0x3e, 0x31, 0x16, 0xc4, 0x3f, 0x2e, 0x45, 0x2d, 0xbf, 0xc9, 0x3f, 0x8a, 0xbe,
+  0x4b, 0x6e, 0x7c, 0xbe, 0x78, 0xbf, 0x39, 0xbe, 0x72, 0x8d, 0x3f, 0xbf, 0x66, 0x0a, 0xd9, 0x3e,
+  0x17, 0xe3, 0x47, 0x3f, 0x50, 0x01, 0x58, 0x3f, 0x00, 0x56, 0x1c, 0xbf, 0xd9, 0xcd, 0x5f, 0x3f,
+  0x7e, 0x31, 0xd3, 0xbf, 0xf3, 0x4e, 0x5f, 0xbf, 0x49, 0xdd, 0x9c, 0xbf, 0x17, 0xb7, 0x32, 0x3d,
+  0x28, 0xfe, 0xa9, 0x3e, 0x0a, 0xc5, 0x33, 0x3c, 0x46, 0x83, 0xec, 0x3f, 0xcf, 0x56, 0x9b, 0xbf,
+  0xe1, 0xf2, 0x0e, 0x3d, 0x52, 0xfe, 0x6c, 0x3f, 0xe0, 0x3c, 0x92, 0xbe, 0x88, 0xed, 0x8c, 0xbf,
+  0x53, 0x61, 0xf6, 0x3e, 0xe9, 0xe7, 0x02, 0x3e, 0xf1, 0x9d, 0x93, 0xbd, 0xa5, 0x17, 0x74, 0xbf,
+  0x78, 0x1e, 0xda, 0x3f, 0xc7, 0x7d, 0x00, 0x3f, 0x8a, 0xbd, 0x47, 0x3e, 0x3d, 0xcb, 0xac, 0xbf,
+  0x30, 0xcc, 0x96, 0x3f, 0x22, 0x5c, 0x9c, 0xbf, 0xf3, 0xec, 0x26, 0x40, 0xe3, 0x7d, 0xaa, 0x3f,
+  0x22, 0xdb, 0x04, 0x3f, 0x33, 0x03, 0x97, 0x3f, 0xce, 0x27, 0xdf, 0xbe, 0x03, 0x0d, 0xec, 0x3e,
+  0xad, 0xb0, 0x33, 0x3f, 0x65, 0x39, 0x4e, 0xbf, 0xc2, 0xac, 0x8f, 0xbe, 0x6a, 0xe8, 0xd7, 0xbf,
+  0xd1, 0xae, 0x99, 0x3f, 0x6d, 0x13, 0x3e, 0x3f, 0x15, 0x4f, 0xb6, 0xbf, 0xd0, 0x38, 0x5c, 0xbf,
+  0xc3, 0xb8, 0xae, 0x3f, 0x30, 0xd3, 0xf2, 0xbe, 0xce, 0x78, 0x7d, 0x3d, 0x40, 0x01, 0xce, 0x3d,
+  0x61, 0x55, 0xc5, 0xbe, 0x8a, 0xb0, 0x9d, 0x3f, 0x5d, 0x8e, 0x59, 0x3f, 0xca, 0xf9, 0x95, 0xbf,
+  0x68, 0xd8, 0xd9, 0xbf, 0x8a, 0x9e, 0xa2, 0x3f, 0x42, 0x18, 0xe6, 0xbf, 0xda, 0xf7, 0xed, 0x3f,
+  0x5b, 0x02, 0xf2, 0x3f, 0x1d, 0x80, 0x99, 0xbf, 0x05, 0x6f, 0x0e, 0x40, 0x86, 0xa9, 0xa2, 0x3e,
+  0x7e, 0x3d, 0xe7, 0x3f, 0x24, 0x13, 0x9b, 0xbf, 0x79, 0x66, 0xaa, 0x3f, 0xed, 0x09, 0x31, 0xbf,
+  0x90, 0x3f, 0xc0, 0x3f, 0x05, 0xfc, 0x9d, 0x3f, 0xd4, 0x9f, 0x9c, 0xbf, 0x45, 0x84, 0x22, 0x3f,
+  0xbc, 0x6b, 0x4d, 0xbf, 0xdb, 0x8c, 0x8c, 0xbf, 0xcb, 0xdf, 0x7d, 0xbf, 0xd5, 0xb7, 0xb7, 0xbf,
+  0x1e, 0xf5, 0xb8, 0xbf, 0xe9, 0x64, 0x94, 0xbf, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xc4, 0x03, 0x56, 0xbe,
+  0x11, 0x52, 0x42, 0xbf, 0xe6, 0xd6, 0x1a, 0xbe, 0xf6, 0xe7, 0x9e, 0xbd, 0x64, 0x6a, 0xc9, 0x3e,
+  0xc3, 0x73, 0xd6, 0x3c, 0x31, 0x19, 0x1b, 0x3e, 0x9c, 0x6f, 0x97, 0x3f, 0x9c, 0x48, 0x73, 0xbe,
+  0x6c, 0x01, 0xcc, 0xbe, 0x94, 0x04, 0x79, 0xbf, 0xd2, 0x1b, 0x92, 0xbf, 0x8b, 0xee, 0xdb, 0xbf,
+  0x87, 0x3a, 0x36, 0xbe, 0xec, 0x19, 0x39, 0x3f, 0x73, 0xe8, 0xb8, 0x3f, 0xda, 0x91, 0xed, 0x3f,
+  0xa9, 0xf3, 0x3a, 0xbf, 0xad, 0x10, 0x39, 0x3f, 0x62, 0x46, 0xab, 0xbf, 0xe5, 0xd6, 0xa7, 0x3f,
+  0x97, 0xb8, 0x99, 0xbe, 0x22, 0x1c, 0xd7, 0xbe, 0x30, 0xfb, 0x14, 0x40, 0xce, 0x87, 0x8a, 0xbe,
+  0xfa, 0xc6, 0x8a, 0xbf, 0xbf, 0x9d, 0xab, 0xbf, 0x25, 0xb7, 0x00, 0x40, 0xca, 0xdf, 0x5d, 0xbf,
+  0xd0, 0xd5, 0xb7, 0xbf, 0x64, 0xb4, 0x5b, 0xbe, 0x8e, 0xd3, 0x3e, 0xc0, 0xa2, 0x75, 0xb9, 0x3e,
+  0x8b, 0x23, 0x84, 0x3e, 0xb5, 0xb7, 0xcf, 0x3f, 0xbc, 0xcb, 0xdc, 0x3e, 0xbe, 0x8d, 0x35, 0x3f,
+  0x93, 0x12, 0xb2, 0x3e, 0xd4, 0x32, 0x5c, 0xbb, 0x81, 0x4d, 0xce, 0x3f, 0x77, 0x79, 0x0e, 0xbf,
+  0xed, 0x9e, 0xa4, 0xbf, 0x25, 0x26, 0x86, 0xbe, 0x76, 0xb3, 0x8b, 0x3f, 0x6f, 0xf4, 0x58, 0xbf,
+  0xb8, 0x1b, 0xfa, 0x3e, 0xbe, 0x72, 0x58, 0xbf, 0x4f, 0xaf, 0x61, 0x3f, 0x01, 0x84, 0x8f, 0xbf,
+  0xe7, 0xc1, 0x64, 0x3f, 0xe2, 0x63, 0xb1, 0xbf, 0xc9, 0xad, 0x5c, 0x3f, 0xca, 0x88, 0xd9, 0x3f,
+  0xd8, 0x70, 0x04, 0x3f, 0xdd, 0x06, 0xd0, 0xbe, 0x4a, 0xac, 0x91, 0xbe, 0x6a, 0x8e, 0x00, 0x3f,
+  0x5b, 0x9a, 0xd1, 0x3f, 0xba, 0x37, 0xda, 0xbb, 0x58, 0x93, 0x12, 0x3e, 0xee, 0xbe, 0x57, 0xbf,
+  0x0c, 0x6b, 0x26, 0x40, 0x64, 0x64, 0x85, 0x3d, 0x0a, 0x86, 0xd0, 0xbf, 0xa0, 0xa5, 0xe2, 0xbf,
+  0x6f, 0xe5, 0xb5, 0x3f, 0x58, 0xa1, 0x10, 0x3c, 0x87, 0x14, 0xb2, 0xbf, 0x81, 0x11, 0xa8, 0x3e,
+  0x28, 0x3d, 0x32, 0x3f, 0x57, 0x26, 0x86, 0xbf, 0xd6, 0x6f, 0x16, 0x3f, 0x16, 0x2f, 0xa4, 0x3f,
+  0xc9, 0x13, 0x9b, 0x3f, 0xb1, 0x4e, 0xa2, 0xbf, 0x47, 0x0e, 0x7c, 0x3e, 0x98, 0xdd, 0xe5, 0xbe,
+  0xab, 0x11, 0xd1, 0x3f, 0xd9, 0x67, 0x00, 0xc0, 0xae, 0xbc, 0x9d, 0x3f, 0x93, 0x4e, 0x42, 0xc0,
+  0xb7, 0x1b, 0xfa, 0x3f, 0xef, 0xd6, 0xe3, 0xbf, 0x3a, 0x3c, 0x57, 0x3e, 0x57, 0x1b, 0x97, 0xbf,
+  0x88, 0x83, 0xb5, 0xbf, 0x03, 0x60, 0xe6, 0x3e, 0x4a, 0x5d, 0x99, 0xbe, 0xb9, 0x4d, 0xa4, 0xbc,
+  0x82, 0x99, 0x1c, 0xbf, 0xb7, 0x08, 0x80, 0xbf, 0x88, 0xb5, 0x9d, 0xbf, 0x22, 0x75, 0xff, 0xbd,
+  0xaa, 0x4d, 0x35, 0x3e, 0x3a, 0xba, 0xfe, 0xbe, 0xe7, 0x38, 0x8f, 0xbf, 0x3e, 0xc3, 0xb3, 0x3d,
+  0x35, 0xff, 0xb6, 0xbf, 0xdd, 0xdd, 0x98, 0xbf, 0x4f, 0xb9, 0xd4, 0x3f, 0xd2, 0xeb, 0xe2, 0x3e,
+  0xa0, 0xfc, 0xaf, 0xbf, 0x60, 0x49, 0x06, 0xc0, 0x2b, 0x97, 0xf9, 0xbe, 0x23, 0x94, 0xef, 0xbc,
+  0xe8, 0xf9, 0x9f, 0xbe, 0x66, 0x00, 0x85, 0xbf, 0x7b, 0x74, 0x21, 0x3f, 0xba, 0xe4, 0x1c, 0xbe,
+  0x9a, 0x89, 0x17, 0xbe, 0xaa, 0xeb, 0x42, 0xbe, 0x17, 0xd7, 0xb1, 0xbf, 0x24, 0x9a, 0xe4, 0xbe,
+  0x44, 0x5f, 0xba, 0x3e, 0xeb, 0x0c, 0x27, 0xbf, 0x86, 0xa9, 0xae, 0xbe, 0x9d, 0x0f, 0xe2, 0x3e,
+  0xe3, 0xce, 0xb1, 0x3e, 0xc2, 0x09, 0xbc, 0xbc, 0xe0, 0xa4, 0x0a, 0x3f, 0xac, 0x7c, 0xd9, 0x3e,
+  0x57, 0x9d, 0x45, 0x3f, 0xb1, 0xc0, 0x43, 0xbf, 0x7a, 0x23, 0x22, 0x3f, 0xd1, 0x82, 0x2d, 0x3f,
+  0x70, 0x7c, 0x3a, 0xbf, 0xc5, 0x47, 0xad, 0x3f, 0x13, 0x7c, 0x2d, 0xbf, 0x7a, 0x6a, 0x85, 0x3f,
+  0xf0, 0x8d, 0xe6, 0x3f, 0xd4, 0x6b, 0x9c, 0x3f, 0x25, 0x8d, 0x71, 0x3f, 0x77, 0x3b, 0x91, 0x3f,
+  0x31, 0x8e, 0xfb, 0x3e, 0xd8, 0xcd, 0xda, 0x3f, 0xdc, 0x12, 0x9c, 0x3f, 0x58, 0xb6, 0x9e, 0xbf,
+  0xc8, 0xe0, 0x9b, 0x3f, 0xf0, 0xcb, 0xc5, 0x3d, 0x15, 0xbc, 0x9b, 0xbf, 0xd5, 0x43, 0xdf, 0x3f,
+  0x61, 0xfb, 0xb9, 0x3e, 0xbf, 0x41, 0xbf, 0x3d, 0x3d, 0x36, 0x33, 0x3d, 0xbc, 0x8a, 0xa5, 0x3c,
+  0xa6, 0x74, 0x42, 0xbf, 0x8b, 0xf6, 0x4b, 0xbe, 0xb7, 0x70, 0xea, 0xbf, 0x99, 0xd3, 0x40, 0x3f,
+  0xa2, 0x8e, 0x7f, 0x3e, 0x69, 0xc6, 0x46, 0x3f, 0x68, 0x08, 0xae, 0xbe, 0x30, 0x2e, 0xb6, 0xbf,
+  0xd5, 0x34, 0x9d, 0xbf, 0x4a, 0x66, 0x22, 0xbd, 0x70, 0x85, 0x40, 0x3f, 0x93, 0xb6, 0x71, 0xbe,
+  0x96, 0xdc, 0xbc, 0x3f, 0x7b, 0x83, 0x8a, 0xbf, 0x6a, 0x89, 0x8f, 0x3f, 0x57, 0xe0, 0xe2, 0x3e,
+  0x12, 0xf1, 0xfc, 0x3f, 0x20, 0x6c, 0x91, 0x3f, 0x7a, 0x19, 0x0d, 0x3f, 0xcc, 0x2c, 0x66, 0x3f,
+  0x91, 0x6b, 0x86, 0xbe, 0x9b, 0xe0, 0x9b, 0x3f, 0x29, 0xd5, 0xfa, 0x3e, 0xe2, 0x25, 0xe9, 0x3c,
+  0x8d, 0x3d, 0x12, 0xc0, 0x55, 0xe5, 0xb4, 0x3d, 0x17, 0x13, 0xa2, 0x3e, 0x75, 0xc0, 0x9c, 0xbf,
+  0x5f, 0xa0, 0xf1, 0xbd, 0x4a, 0x61, 0x09, 0x3d, 0x28, 0xef, 0x1b, 0x3f, 0xd4, 0x3b, 0x28, 0xbf,
+  0x61, 0xf3, 0x24, 0x40, 0x44, 0x7f, 0xd5, 0xbf, 0x36, 0xc8, 0x53, 0xbf, 0x9c, 0x28, 0x27, 0x3e,
+  0x85, 0xf9, 0x70, 0xbf, 0xcc, 0xed, 0x89, 0x3e, 0x63, 0x81, 0x87, 0xbf, 0x1f, 0xe6, 0xea, 0x3d,
+  0x97, 0xbd, 0xf8, 0x3e, 0x14, 0xbc, 0x37, 0xbf, 0xba, 0xaf, 0x31, 0xbf, 0x6d, 0x46, 0x15, 0x3e,
+  0xd8, 0x04, 0x4e, 0xbf, 0x45, 0x76, 0x2d, 0xbf, 0x28, 0xe9, 0xfb, 0x3f, 0x9e, 0x67, 0xbd, 0xbf,
+  0xb8, 0x4c, 0x59, 0x40, 0x91, 0xda, 0x4c, 0x3f, 0x58, 0x88, 0x6e, 0x3d, 0xfd, 0xaf, 0x29, 0xbd,
+  0xff, 0xe6, 0x39, 0xbf, 0x71, 0x82, 0x84, 0x3e, 0x5c, 0xf3, 0x8c, 0xbf, 0x16, 0x1b, 0x3a, 0x3f,
+  0x31, 0x06, 0x8e, 0x3f, 0x2a, 0x22, 0x99, 0xbd, 0xf9, 0x44, 0x32, 0xbf, 0xa4, 0x47, 0xae, 0x3e,
+  0x9c, 0x76, 0xd8, 0xbe, 0xf9, 0xae, 0x40, 0xbf, 0xd6, 0xb4, 0x97, 0x3f, 0xb4, 0xa9, 0x52, 0xbe,
+  0x25, 0x7f, 0x44, 0xbf, 0xff, 0xc4, 0xa4, 0xbf, 0x59, 0x65, 0x8f, 0x3f, 0x2a, 0xaa, 0x46, 0xbf,
+  0xc0, 0x3f, 0xdb, 0xbe, 0x7e, 0xbc, 0xb3, 0xbe, 0x1b, 0x1a, 0x24, 0x3f, 0xf5, 0xa7, 0xf1, 0x3e,
+  0x72, 0x28, 0x9e, 0x3e, 0x85, 0xb8, 0xc8, 0x3e, 0xf0, 0x0f, 0x08, 0xbf, 0xbd, 0xcf, 0x26, 0xbe,
+  0x78, 0x4b, 0xe6, 0xbe, 0x29, 0x7d, 0xc5, 0x3e, 0x68, 0xf6, 0x98, 0x3e, 0xbd, 0xf9, 0xac, 0x3f,
+  0x00, 0xbf, 0x3e, 0xbe, 0xf6, 0x7a, 0x0e, 0xc0, 0x9d, 0xb7, 0x3e, 0xbf, 0x05, 0x35, 0x6c, 0x3f,
+  0xcd, 0x8f, 0x46, 0x3f, 0x23, 0xd6, 0xb0, 0x3f, 0x3c, 0xec, 0x14, 0xbf, 0x18, 0x98, 0x32, 0x3b,
+  0x6c, 0x5a, 0x56, 0xbf, 0xae, 0xe0, 0xa8, 0xbf, 0xfe, 0xad, 0xaf, 0xbe, 0x7d, 0x3f, 0x99, 0x3e,
+  0xf5, 0x21, 0x5b, 0xbc, 0xec, 0xf1, 0xbf, 0x3e, 0x0d, 0xae, 0x67, 0x3f, 0xb7, 0xb3, 0xa8, 0x3d,
+  0xc9, 0x64, 0xdf, 0xbf, 0xeb, 0xaa, 0xcb, 0xbd, 0x8c, 0x1c, 0xc1, 0x3e, 0xbd, 0xb0, 0x72, 0xbf,
+  0x88, 0x99, 0x03, 0xbf, 0x64, 0x43, 0x60, 0xbf, 0xef, 0xc2, 0x8c, 0xbd, 0xff, 0x6a, 0xa4, 0xbf,
+  0x39, 0xff, 0x96, 0x3f, 0xb6, 0x67, 0x66, 0xbf, 0xba, 0x5f, 0xe6, 0xbf, 0x29, 0x19, 0x2a, 0xbe,
+  0x5e, 0x60, 0xa1, 0x3e, 0xb8, 0xfd, 0x7c, 0x3f, 0x68, 0xd0, 0x56, 0x3f, 0xe6, 0x1e, 0xf9, 0xbf,
+  0xe0, 0x4b, 0x86, 0x3f, 0xd9, 0xf7, 0x88, 0x3e, 0x88, 0x17, 0x87, 0x3f, 0x2a, 0x5d, 0x95, 0xbf,
+  0xd0, 0xaf, 0x50, 0x3f, 0x78, 0xe4, 0xfb, 0xbe, 0x75, 0xa1, 0x88, 0xbf, 0x86, 0xdc, 0x93, 0xbe,
+  0xbf, 0x66, 0xa3, 0xbf, 0x83, 0xf3, 0xbd, 0xbe, 0x39, 0x86, 0x99, 0xbe, 0xd9, 0xb5, 0x29, 0x40,
+  0xf8, 0x67, 0xa3, 0xbf, 0xd6, 0x9d, 0xb7, 0xbf, 0x71, 0x74, 0x81, 0xbf, 0x12, 0x7a, 0x5b, 0xbf,
+  0xa2, 0xc0, 0xe6, 0x3e, 0x37, 0xc6, 0x36, 0x3f, 0x24, 0xf5, 0xd1, 0xbf, 0xdf, 0xa6, 0x82, 0xbe,
+  0x5c, 0x71, 0xea, 0xbd, 0x09, 0x5b, 0xab, 0xbd, 0xf5, 0x26, 0xce, 0x3f, 0xe7, 0xe2, 0x7a, 0x3f,
+  0x3a, 0x39, 0xe0, 0x3e, 0x34, 0x5c, 0x26, 0xbf, 0xb1, 0x30, 0x1b, 0x3f, 0x31, 0xf9, 0xd4, 0x3e,
+  0x48, 0xc1, 0x44, 0xbf, 0x1c, 0xf3, 0x92, 0xbf, 0x7e, 0x0d, 0x53, 0x3f, 0xc2, 0x80, 0x25, 0xbf,
+  0x02, 0x3c, 0x17, 0x3e, 0x95, 0x61, 0x84, 0xbe, 0x89, 0x55, 0xe0, 0x3e, 0x8e, 0xa1, 0xd3, 0x3f,
+  0x90, 0xa7, 0xee, 0xbe, 0x8f, 0xd2, 0x9b, 0xbe, 0x56, 0x39, 0x07, 0xbf, 0x19, 0x67, 0xda, 0x3f,
+  0x16, 0x68, 0x9a, 0xbf, 0x71, 0xb6, 0x11, 0x3f, 0x64, 0x3f, 0xb5, 0x3f, 0x6c, 0x01, 0x1d, 0xbf,
+  0x23, 0x94, 0x85, 0xbf, 0x31, 0x56, 0xb8, 0xbf, 0xd7, 0x92, 0x29, 0xbf, 0xb0, 0x14, 0x70, 0x3f,
+  0x4f, 0x6b, 0xbd, 0xbe, 0x4e, 0xe9, 0x88, 0xbf, 0xd5, 0xa3, 0xf8, 0xbd, 0xa3, 0xa2, 0x84, 0x3f,
+  0x48, 0x39, 0x04, 0x3e, 0xe2, 0x65, 0x8f, 0xbe, 0xa9, 0x43, 0x64, 0xbf, 0xdc, 0x72, 0x8d, 0xbf,
+  0xb1, 0x21, 0x68, 0x3f, 0x25, 0x73, 0xd8, 0xbe, 0xdb, 0x94, 0x24, 0x3f, 0xe9, 0x18, 0x33, 0xbe,
+  0x03, 0xb1, 0x31, 0xbf, 0x93, 0xf8, 0xa2, 0xbd, 0x31, 0x65, 0xd3, 0xbf, 0x8e, 0xcc, 0x44, 0xbd,
+  0xc6, 0x5e, 0x38, 0xbf, 0x03, 0x74, 0x33, 0xc0, 0x08, 0x37, 0x57, 0x3e, 0x40, 0xc3, 0x19, 0xbe,
+  0xe1, 0x18, 0x7a, 0xbe, 0x23, 0xe2, 0x18, 0xbf, 0xef, 0x0e, 0x2c, 0x3f, 0x1b, 0x2d, 0x77, 0xbf,
+  0x3d, 0xa2, 0xe3, 0x3d, 0xb9, 0x23, 0x26, 0x3f, 0x66, 0x32, 0xee, 0x3f, 0xfb, 0xe5, 0xed, 0xbe,
+  0x97, 0x06, 0xec, 0xbe, 0x79, 0x50, 0xf2, 0x3e, 0x1d, 0xbd, 0x93, 0xbf, 0xf3, 0x29, 0xdd, 0xbd,
+  0xa0, 0x78, 0x90, 0x3f, 0x01, 0x2b, 0xa4, 0xbf, 0x01, 0x44, 0xd5, 0x3e, 0xbc, 0x26, 0x5e, 0x3f,
+  0x37, 0xf2, 0x6b, 0x3e, 0x14, 0x5a, 0x98, 0x3e, 0x94, 0xe3, 0x0f, 0x40, 0x6c, 0x3a, 0xec, 0x3f,
+  0x28, 0x0e, 0xcb, 0x3f, 0x1f, 0xf0, 0x85, 0x3f, 0xc8, 0x86, 0x87, 0xbf, 0xed, 0x86, 0xa0, 0xbe,
+  0xb4, 0x41, 0xf3, 0x3d, 0x73, 0xb1, 0x9a, 0xbe, 0x30, 0xce, 0xb1, 0x3f, 0x44, 0x3e, 0xcd, 0xbf,
+  0x81, 0x19, 0xc9, 0xbe, 0x4e, 0x14, 0x7e, 0xbf, 0x8e, 0x00, 0x7c, 0x3f, 0x54, 0xaf, 0x2b, 0x3f,
+  0xc4, 0xa4, 0x11, 0x3f, 0xa8, 0x1b, 0xe4, 0x3e, 0xc8, 0x01, 0xf3, 0x3f, 0xfd, 0xdb, 0x48, 0x3f,
+  0xb2, 0x38, 0x07, 0x3e, 0xbe, 0xfa, 0xf3, 0xbf, 0x5d, 0xdb, 0x19, 0xc0, 0xf2, 0xd9, 0x98, 0xbe,
+  0x35, 0x97, 0xd9, 0x3e, 0x59, 0x28, 0x41, 0xbf, 0xc5, 0x56, 0x90, 0x3e, 0xdb, 0xc6, 0x54, 0xbf,
+  0x6c, 0xa9, 0xbc, 0x3e, 0xd7, 0x20, 0x14, 0xbf, 0xea, 0xe3, 0x7f, 0xbd, 0xb6, 0xdf, 0x04, 0x3f,
+  0x50, 0x66, 0x5c, 0x3e, 0x87, 0xa7, 0x83, 0xbe, 0x44, 0x0a, 0x28, 0x3e, 0x3c, 0x05, 0x30, 0x3e,
+  0x44, 0x3d, 0x09, 0x3f, 0x4d, 0x64, 0x9a, 0xbf, 0x4f, 0xd4, 0x82, 0xbd, 0x68, 0x62, 0x69, 0x3e,
+  0x54, 0x0f, 0x9a, 0x3f, 0x3b, 0x24, 0x3c, 0xbf, 0x80, 0x89, 0x8a, 0xbe, 0xab, 0x1a, 0x82, 0x3f,
+  0x9a, 0x80, 0xe3, 0x3e, 0x93, 0xe0, 0x3b, 0x3f, 0xe4, 0x87, 0xc0, 0x3e, 0x1f, 0xa9, 0x3e, 0x3f,
+  0x18, 0x8b, 0x56, 0xbe, 0xc5, 0xff, 0xcb, 0xbe, 0xb5, 0xc7, 0x7e, 0x3d, 0x67, 0xfe, 0x51, 0x3e,
+  0x74, 0x59, 0x80, 0x3f, 0xbb, 0x71, 0x75, 0x3f, 0x4e, 0x8b, 0x8a, 0x3f, 0xb9, 0x19, 0x82, 0x3f,
+  0x51, 0x16, 0xdd, 0xbf, 0x8d, 0x7b, 0x90, 0x3d, 0xc4, 0xcd, 0x56, 0xbf, 0x4d, 0xd9, 0xff, 0xbe,
+  0xa9, 0x8f, 0x1b, 0xbf, 0x76, 0x50, 0xbe, 0x3e, 0x7a, 0x25, 0xf1, 0xbf, 0x6a, 0x42, 0x9f, 0xbe,
+  0xe4, 0x58, 0x66, 0x3f, 0xd5, 0xad, 0x49, 0x3f, 0x29, 0xeb, 0x2f, 0x3f, 0x1b, 0x8e, 0xeb, 0xbf,
+  0x4f, 0x75, 0x6e, 0x3f, 0x03, 0x16, 0x11, 0xbe, 0xa2, 0x35, 0xa2, 0xbc, 0xba, 0x67, 0x64, 0xbf,
+  0x66, 0x3a, 0x1c, 0xbf, 0xfc, 0xb5, 0xc1, 0x3e, 0xca, 0x46, 0xf9, 0x3f, 0xd0, 0xa7, 0x03, 0x3f,
+  0x45, 0xde, 0x87, 0xbf, 0xde, 0x93, 0x04, 0x3f, 0x98, 0x2d, 0x19, 0x40, 0x70, 0x8e, 0x99, 0x3f,
+  0x98, 0xb8, 0xf9, 0xbf, 0xf1, 0x7e, 0xb1, 0x3d, 0x7d, 0x7e, 0x3b, 0xbf, 0x50, 0xc2, 0xc6, 0xbe,
+  0xe8, 0xb4, 0x8d, 0xbf, 0xdb, 0x6a, 0x1c, 0xc0, 0x85, 0x23, 0xd4, 0xbe, 0xea, 0x03, 0xf2, 0xbe,
+  0xc4, 0x51, 0xf9, 0x3e, 0x5d, 0xd5, 0x9c, 0xbc, 0x30, 0x93, 0x9f, 0x3e, 0x0b, 0x8c, 0x24, 0xbf,
+  0xf9, 0x6f, 0x0c, 0xc0, 0x19, 0x92, 0x27, 0x40, 0x7e, 0xe5, 0x8d, 0xbf, 0x1b, 0xed, 0x60, 0xbd,
+  0x36, 0x80, 0xba, 0xbf, 0xda, 0xb1, 0x60, 0xbf, 0x0b, 0xe7, 0x47, 0xbf, 0xd7, 0x50, 0x14, 0x3f,
+  0xab, 0x11, 0x85, 0xbf, 0xd8, 0x58, 0x15, 0x3e, 0x46, 0x8e, 0x01, 0xbf, 0x25, 0x96, 0x5c, 0xbf,
+  0x23, 0xe2, 0xcc, 0xbe, 0xa5, 0x97, 0x3f, 0xbf, 0xa0, 0xec, 0x9a, 0xbf, 0x60, 0x54, 0x9b, 0x3f,
+  0x6d, 0x92, 0x41, 0x3f, 0x74, 0xeb, 0x03, 0xbd, 0x49, 0xe2, 0x9b, 0x3f, 0x22, 0x80, 0x1b, 0x3f,
+  0x9d, 0xa2, 0xfe, 0xbe, 0xb6, 0x93, 0xec, 0x3f, 0x6a, 0x38, 0x09, 0xc0, 0x27, 0x72, 0x89, 0xbe,
+  0xe6, 0x0e, 0x33, 0xbe, 0xbd, 0x5c, 0x92, 0x3f, 0x13, 0x3b, 0xa1, 0xbf, 0xab, 0x05, 0x13, 0x3f,
+  0x30, 0x84, 0x8c, 0x3c, 0xd7, 0xca, 0x02, 0x3f, 0xb0, 0x17, 0x6b, 0xbf, 0x5d, 0x34, 0x9a, 0xbf,
+  0xa3, 0x50, 0x1b, 0x40, 0x9f, 0x12, 0xbd, 0x3e, 0xfa, 0x5d, 0x82, 0x3f, 0x86, 0xf6, 0x7e, 0x3f,
+  0x1e, 0x8e, 0xf2, 0xbf, 0xfc, 0xbc, 0x15, 0xbf, 0xe4, 0xf7, 0xe8, 0xbe, 0xde, 0x5b, 0xb6, 0xbe,
+  0x1f, 0x4d, 0x8d, 0xbe, 0x2b, 0x51, 0x30, 0xbf, 0xc1, 0xd0, 0xd8, 0x3f, 0x51, 0x5e, 0x4f, 0xbf,
+  0x99, 0xca, 0xf4, 0x3e, 0xe0, 0xe8, 0xb4, 0x3f, 0x5b, 0xf0, 0x31, 0xbf, 0x77, 0xed, 0x66, 0xbf,
+  0x55, 0x9b, 0xc7, 0xbf, 0x05, 0xbc, 0x35, 0xbf, 0xed, 0x67, 0x6c, 0x3f, 0x9f, 0x4d, 0x7a, 0x3f,
+  0x2e, 0x4e, 0x18, 0x3f, 0x19, 0x3f, 0x26, 0x3c, 0x74, 0x0a, 0x4d, 0xbf, 0x57, 0x10, 0x71, 0xbf,
+  0xf0, 0x01, 0x7b, 0x3e, 0x38, 0x3a, 0xa6, 0xbf, 0x4e, 0x95, 0x9c, 0xbe, 0x6b, 0xcd, 0xad, 0x3e,
+  0x54, 0xe2, 0x91, 0x3e, 0x3b, 0xef, 0x18, 0x3e, 0x63, 0x20, 0x5d, 0xbf, 0x68, 0xc6, 0xe4, 0xbe,
+  0x4c, 0xee, 0x1c, 0x3f, 0x1e, 0xce, 0x5c, 0x3d, 0x0b, 0xd5, 0xc9, 0x3f, 0x49, 0x9e, 0x01, 0x3f,
+  0x22, 0x5c, 0x91, 0xbe, 0x34, 0x9a, 0x86, 0x3f, 0x0a, 0xf1, 0x85, 0x3e, 0x75, 0xd2, 0x6b, 0x3f,
+  0x13, 0x96, 0xcf, 0x3f, 0x43, 0xe1, 0x28, 0x3f, 0xa9, 0xb1, 0x78, 0xbf, 0xaa, 0x0d, 0x3a, 0xbf,
+  0xfe, 0x86, 0x8b, 0x3f, 0x9e, 0x0a, 0x38, 0x3e, 0x69, 0x55, 0x9a, 0xbf, 0x6e, 0x3d, 0x57, 0xbf,
+  0xb0, 0x75, 0x01, 0x40, 0x55, 0x6b, 0xfc, 0x3f, 0xde, 0xe8, 0xa1, 0xbf, 0x68, 0x05, 0x79, 0xbf,
+  0xac, 0xe1, 0xc1, 0xbf, 0x99, 0x8c, 0x6f, 0x3f, 0x29, 0x8a, 0x18, 0xbe, 0xba, 0xa2, 0x88, 0x3e,
+  0x9d, 0xc3, 0x3e, 0x3f, 0xea, 0x41, 0x13, 0xbf, 0x2f, 0xa6, 0xb9, 0xbf, 0xdf, 0x95, 0xda, 0x3e,
+  0x2e, 0x29, 0x5f, 0xbf, 0x3d, 0x86, 0x9c, 0x3f, 0x4b, 0x6f, 0x4b, 0xbf, 0x15, 0xd1, 0x16, 0xbc,
+  0x76, 0x39, 0xb7, 0x3f, 0xf1, 0x0e, 0x96, 0xbd, 0xa7, 0x55, 0xf1, 0x3a, 0x2c, 0x0e, 0xa3, 0x3e,
+  0x1e, 0x94, 0x2b, 0x3f, 0x98, 0xf8, 0x4a, 0xbe, 0x95, 0x99, 0xc3, 0x3f, 0x99, 0x9b, 0xa8, 0xbf,
+  0x08, 0xd0, 0x1b, 0xbf, 0x64, 0xeb, 0xfb, 0x3e, 0xb9, 0x2e, 0xc4, 0x3e, 0x9d, 0x41, 0xb1, 0xbf,
+  0x51, 0xbd, 0xc0, 0x3f, 0x44, 0x15, 0x0f, 0xbf, 0x1a, 0xf1, 0x0f, 0xbf, 0xef, 0xa0, 0x1c, 0x40,
+  0xdb, 0xdc, 0x50, 0xbf, 0xfe, 0x0a, 0x37, 0xbf, 0x96, 0xef, 0xe4, 0x3e, 0xdb, 0x5b, 0x97, 0x3e,
+  0x8d, 0xcf, 0x96, 0xbf, 0x4f, 0xe8, 0xe3, 0x3f, 0x32, 0xd8, 0xe6, 0xbf, 0xe3, 0x1f, 0x9e, 0x3f,
+  0x08, 0xeb, 0x6d, 0x3e, 0x2e, 0xf7, 0x9d, 0xbf, 0x03, 0x8e, 0x81, 0x3f, 0xa2, 0xdc, 0x80, 0xbf,
+  0x7e, 0x21, 0x08, 0xbf, 0x4c, 0xa2, 0x5c, 0xbf, 0xec, 0xdd, 0x25, 0xbd, 0x22, 0xcd, 0x9a, 0xbf,
+  0x4f, 0x87, 0x36, 0x3f, 0x43, 0xb9, 0x24, 0x3f, 0x76, 0x26, 0x47, 0xbf, 0xf0, 0xf3, 0xae, 0xbf,
+  0x46, 0x25, 0xd3, 0xbe, 0x9a, 0x22, 0x0a, 0x3f, 0x01, 0x51, 0x94, 0xbf, 0x82, 0x37, 0xd7, 0xbe,
+  0x18, 0xd0, 0xb4, 0x3f, 0x76, 0xf8, 0x0a, 0x3f, 0x6e, 0xd7, 0x98, 0xbf, 0xd5, 0x11, 0x86, 0xbf,
+  0x0f, 0x31, 0xf3, 0xbd, 0xa7, 0x95, 0xe1, 0xbf, 0x9e, 0xab, 0x78, 0xbf, 0x89, 0xa5, 0xe2, 0xbe,
+  0x9f, 0x09, 0xf5, 0xbe, 0xa1, 0x39, 0x52, 0x3f, 0x2f, 0x8c, 0x6b, 0x3f, 0xfd, 0x89, 0xaa, 0x3e,
+  0xbd, 0x17, 0xb5, 0xbf, 0x5d, 0xff, 0x8a, 0xbd, 0xe9, 0x3f, 0x91, 0xbf, 0x0e, 0xe0, 0x11, 0x3d,
+  0xca, 0x65, 0x0f, 0xc0, 0x30, 0xe9, 0x0f, 0xbf, 0xd7, 0x35, 0x85, 0x3f, 0xbe, 0x41, 0xba, 0xbf,
+  0xdf, 0x3e, 0xf8, 0xbe, 0x6d, 0x2c, 0x35, 0x3f, 0x43, 0xa6, 0x11, 0x3f, 0x7d, 0x9d, 0x89, 0xbe,
+  0x0f, 0xe2, 0xd8, 0x3f, 0x75, 0x3c, 0x01, 0x3f, 0xd4, 0x81, 0x90, 0x3f, 0x2e, 0x61, 0x87, 0x3f,
+  0xba, 0x5c, 0x94, 0xbf, 0x1c, 0x46, 0x5f, 0x3f, 0xe2, 0x65, 0x07, 0xbf, 0xad, 0xbb, 0xa6, 0x3f,
+  0x6e, 0xb7, 0x8d, 0xbf, 0x28, 0xef, 0x02, 0xbf, 0x02, 0x3f, 0x28, 0xbf, 0x15, 0xd6, 0x23, 0xbe,
+  0x51, 0x9b, 0xd7, 0x3e, 0x56, 0x03, 0x95, 0x3f, 0xd7, 0x7f, 0x78, 0xbf, 0x42, 0x8c, 0x33, 0xbf,
+  0x30, 0xc3, 0x31, 0x3f, 0x4c, 0xea, 0x7f, 0x3e, 0xd8, 0x64, 0xfa, 0xbe, 0x96, 0x70, 0xe4, 0xbe,
+  0x95, 0xb8, 0x07, 0x3e, 0x48, 0xbd, 0xaa, 0xbc, 0x8f, 0x01, 0x4a, 0x3d, 0xa6, 0x79, 0x92, 0xbe,
+  0xef, 0x6d, 0x55, 0x3f, 0x76, 0xdc, 0x5e, 0xbf, 0x93, 0x99, 0x9c, 0x3f, 0x2e, 0x6e, 0xa9, 0xbe,
+  0x02, 0xae, 0x93, 0x3e, 0x33, 0xc9, 0xba, 0x3f, 0x63, 0x55, 0x76, 0xbf, 0x14, 0x02, 0xaa, 0x3e,
+  0xd8, 0x72, 0x2e, 0x3c, 0xa1, 0xd3, 0x4f, 0x3e, 0x5c, 0xf8, 0x4c, 0xbf, 0xb2, 0xdf, 0x05, 0xbf,
+  0xbf, 0x0e, 0x43, 0x3f, 0xdc, 0xc6, 0x65, 0x3f, 0x9b, 0x80, 0x5f, 0x3e, 0x3e, 0xca, 0x03, 0xc0,
+  0xb1, 0x1d, 0xc9, 0xbf, 0x02, 0x59, 0x4e, 0x3e, 0x87, 0x94, 0x6c, 0x3d, 0xd1, 0x8e, 0x42, 0xbf,
+  0x4e, 0xaa, 0xb0, 0xbf, 0x58, 0x1b, 0x40, 0x3d, 0xf9, 0x61, 0x95, 0x3f, 0x52, 0xd3, 0xc1, 0xbf,
+  0xd4, 0x8e, 0x22, 0x3f, 0x10, 0x58, 0x2a, 0xbe, 0x36, 0xf0, 0xab, 0xbe, 0x0f, 0x12, 0x6a, 0xbf,
+  0x12, 0xaa, 0x1d, 0x3f, 0xdf, 0x4c, 0x83, 0xbf, 0x43, 0xe7, 0x3b, 0x3e, 0x32, 0xb9, 0xc0, 0xbf,
+  0x66, 0xac, 0x3d, 0x3f, 0x81, 0x4d, 0x56, 0x3f, 0x18, 0x26, 0x2a, 0xc0, 0x90, 0xe9, 0x53, 0x3e,
+  0xcb, 0x52, 0x96, 0x3e, 0xb1, 0x32, 0x14, 0x3e, 0xa8, 0xcd, 0x88, 0xbf, 0x96, 0x64, 0x96, 0x3e,
+  0x94, 0x44, 0xca, 0xbe, 0x85, 0xaf, 0x6e, 0xbe, 0x69, 0x20, 0x4c, 0x3f, 0xd6, 0x09, 0x0e, 0x3f,
+  0xd8, 0x46, 0x44, 0x3e, 0x40, 0x42, 0x91, 0x3c, 0xa3, 0x78, 0x73, 0xbf, 0xc5, 0x38, 0x97, 0x3f,
+  0x4d, 0xf4, 0x5e, 0xbf, 0x7a, 0x7f, 0x32, 0x3f, 0x5d, 0x33, 0x44, 0xbe, 0x92, 0x56, 0xa6, 0xbf,
+  0xfa, 0xd7, 0x14, 0x3e, 0x18, 0xee, 0xb2, 0xbe, 0xc6, 0xb3, 0x2c, 0x3f, 0x15, 0x0d, 0xb0, 0xbf,
+  0x48, 0x0a, 0x26, 0x3f, 0x72, 0x53, 0xcb, 0x3d, 0x24, 0x8e, 0x06, 0x40, 0xc8, 0xa7, 0xb2, 0xbf,
+  0x6e, 0xf7, 0x30, 0x3f, 0x1f, 0x94, 0x1d, 0x40, 0x0b, 0xb4, 0x0d, 0x3e, 0xff, 0x64, 0x8a, 0xbf,
+  0x4b, 0x55, 0x7b, 0xbe, 0x23, 0x00, 0xef, 0x3e, 0x33, 0xc1, 0x34, 0xbf, 0x97, 0x40, 0x81, 0xbf,
+  0xc7, 0x1c, 0x9b, 0xbf, 0x66, 0xa5, 0x7c, 0xbe, 0x5b, 0xff, 0x99, 0x3e, 0xc3, 0x28, 0x6e, 0x3f,
+  0x6e, 0x40, 0x5e, 0x3f, 0x73, 0x59, 0xa7, 0xbf, 0x22, 0xdc, 0x95, 0x3f, 0x63, 0xff, 0xa3, 0xbf,
+  0x02, 0x7a, 0x4d, 0x3f, 0x50, 0x1e, 0xd8, 0x3d, 0x50, 0xae, 0x37, 0xbd, 0xc2, 0xd7, 0x9b, 0xbf,
+  0x10, 0x98, 0x01, 0x3f, 0xda, 0xa9, 0x1f, 0x3f, 0x16, 0x29, 0x7d, 0x3e, 0x31, 0x31, 0xa4, 0xbf,
+  0x0e, 0xef, 0x25, 0x3f, 0x62, 0xa2, 0x9d, 0xbf, 0xdb, 0xfe, 0x07, 0xbf, 0xfb, 0x1e, 0x79, 0xbf,
+  0x82, 0xf9, 0x63, 0x3e, 0x1f, 0x20, 0x9d, 0x3c, 0xd9, 0xaf, 0x02, 0xc0, 0xb6, 0x0a, 0xb7, 0xbf,
+  0xc9, 0xb4, 0xc6, 0xbe, 0x5c, 0xf3, 0x5f, 0xbf, 0xcb, 0x62, 0x9a, 0x3f, 0xf4, 0xd0, 0x7f, 0x3f,
+  0x74, 0x32, 0x76, 0x3f, 0x44, 0xf4, 0x03, 0xbf, 0xc4, 0x92, 0x1c, 0x3f, 0x38, 0xec, 0x28, 0x3f,
+  0x38, 0x63, 0xd6, 0xbe, 0xe5, 0x29, 0x91, 0x3f, 0x03, 0x06, 0x8e, 0x3e, 0xb6, 0x98, 0xd4, 0x3f,
+  0xc4, 0x99, 0x07, 0x3f, 0x6a, 0x20, 0xd5, 0x3f, 0x46, 0xed, 0x70, 0xbf, 0x83, 0xfc, 0xd2, 0xbf,
+  0x8e, 0x91, 0x87, 0xbf, 0xce, 0xe2, 0x04, 0x3f, 0x1c, 0xc2, 0x14, 0xc0, 0x2c, 0x72, 0x92, 0x3f,
+  0x98, 0x41, 0x55, 0x3e, 0x91, 0x83, 0x59, 0x3d, 0xb5, 0xd4, 0x0b, 0xbf, 0x77, 0x1c, 0xd8, 0x3f,
+  0xca, 0x18, 0x96, 0x3f, 0x0f, 0x95, 0x7f, 0x3e, 0x1b, 0x8e, 0x22, 0xbf, 0xe4, 0x4e, 0xc2, 0x3f,
+  0x1a, 0xe6, 0x77, 0x3f, 0x10, 0x28, 0x39, 0x3f, 0xb3, 0xf7, 0x01, 0x40, 0x77, 0x39, 0xb8, 0x3f,
+  0x25, 0xfb, 0xfb, 0x3e, 0x66, 0x68, 0x29, 0x3e, 0x2d, 0x4d, 0xf6, 0xbf, 0x03, 0x46, 0xbb, 0x3e,
+  0xab, 0xbd, 0x96, 0xbf, 0xd5, 0xcb, 0x69, 0xbf, 0x93, 0x9d, 0xd0, 0xbe, 0x43, 0x35, 0x26, 0xbe,
+  0x05, 0x87, 0x47, 0xbf, 0xe5, 0xa5, 0xad, 0x3e, 0x15, 0xe1, 0x6b, 0x3f, 0x77, 0x79, 0xfa, 0x3d,
+  0x6f, 0x68, 0x87, 0xbf, 0xec, 0x4d, 0x40, 0x3f, 0xb9, 0x26, 0x88, 0xbf, 0x22, 0x3b, 0x89, 0xbf,
+  0x16, 0x31, 0x21, 0x3f, 0x89, 0x16, 0xba, 0x3d, 0xeb, 0x18, 0xec, 0xbe, 0x46, 0x5e, 0x14, 0x3e,
+  0x53, 0xf8, 0x04, 0xbf, 0xec, 0xd2, 0x9e, 0x3e, 0x3c, 0xe6, 0xa1, 0x3f, 0xad, 0x41, 0x8f, 0x3f,
+  0xb9, 0x4d, 0xba, 0x3f, 0x11, 0xba, 0x8b, 0x3f, 0xb1, 0x1d, 0xe0, 0xbe, 0xe7, 0xcd, 0x58, 0xbd,
+  0xc4, 0x30, 0x09, 0x3f, 0x3b, 0x69, 0x9e, 0x3f, 0xcc, 0xcb, 0x1d, 0x3f, 0x16, 0x6e, 0x48, 0xbd,
+  0x62, 0x5e, 0x36, 0xbf, 0xf9, 0x96, 0x0f, 0x40, 0xd0, 0x45, 0xad, 0xbe, 0xd3, 0x8a, 0x9e, 0x3f,
+  0xc4, 0xf6, 0x33, 0xbf, 0xc1, 0x8b, 0x23, 0x3e, 0x4f, 0x3a, 0xfd, 0xbe, 0x64, 0x7a, 0x1b, 0x3f,
+  0xdb, 0xfc, 0x9b, 0x3f, 0x02, 0x53, 0x99, 0xbf, 0x2c, 0x5a, 0x42, 0x3f, 0x33, 0x3c, 0xe1, 0x3f,
+  0x14, 0xfd, 0xc4, 0xbf, 0xd3, 0x51, 0xb6, 0xbf, 0xb9, 0x42, 0x8d, 0x3e, 0xfb, 0xb2, 0x8e, 0xbe,
+  0xde, 0x7b, 0x16, 0x3f, 0x1c, 0x4f, 0x81, 0xbf, 0xd7, 0xd1, 0x02, 0x3e, 0x97, 0xb5, 0xea, 0xbf,
+  0xec, 0x38, 0x9b, 0xbf, 0xa7, 0xa5, 0x4b, 0xbf, 0xc1, 0x99, 0x37, 0x3f, 0xe1, 0x65, 0x07, 0x3e,
+  0x79, 0x06, 0x25, 0x3e, 0xbc, 0xdd, 0xcc, 0x3e, 0x80, 0x5c, 0x57, 0xbf, 0xca, 0xe7, 0x99, 0x3f,
+  0x4f, 0xe8, 0xab, 0xbe, 0x91, 0xd1, 0x01, 0xc0, 0xd6, 0xa2, 0xb7, 0x3e, 0x47, 0x15, 0x4e, 0x3f,
+  0x65, 0x95, 0x38, 0x3f, 0xb6, 0xad, 0x8a, 0xbe, 0xb2, 0xad, 0x1c, 0xbd, 0x40, 0x00, 0x03, 0xbe,
+  0x29, 0xce, 0x54, 0xbf, 0xe4, 0x75, 0xc6, 0xbf, 0xc0, 0x83, 0x9b, 0xbf, 0x12, 0xae, 0xa0, 0x3c,
+  0xe7, 0x4e, 0xd3, 0x3e, 0xec, 0x81, 0xc7, 0xbf, 0x4e, 0x80, 0x8e, 0xbf, 0x59, 0x23, 0xa2, 0xbf,
+  0x28, 0x02, 0xc6, 0x3f, 0x3a, 0x0f, 0xce, 0x3e, 0x02, 0x69, 0x63, 0x3f, 0x75, 0x8a, 0x36, 0x3d,
+  0x24, 0xf4, 0x1c, 0x3f, 0xd8, 0xf1, 0xc6, 0x3f, 0x55, 0x23, 0x5f, 0x3e, 0x2b, 0xdf, 0x97, 0x3e,
+  0xd3, 0x22, 0x18, 0xbd, 0x70, 0xf0, 0x8e, 0x3e, 0xe3, 0xdf, 0x7c, 0x3f, 0xac, 0x4a, 0x87, 0x3f,
+  0x0e, 0x3f, 0x9e, 0x3e, 0xdd, 0x55, 0xfa, 0xbf, 0x63, 0x6f, 0x8f, 0xbf, 0xd0, 0x47, 0xe1, 0x3f,
+  0x75, 0x93, 0x68, 0xbf, 0xd3, 0x42, 0x36, 0x3e, 0x48, 0xc7, 0x9d, 0x3d, 0x85, 0xfd, 0x63, 0xbf,
+  0x50, 0x8e, 0xb2, 0xbf, 0x6a, 0xbf, 0xc6, 0x3e, 0x98, 0x4c, 0x7e, 0x3f, 0x27, 0x46, 0x5d, 0xbe,
+  0xb3, 0x2b, 0xd3, 0x3f, 0xcc, 0x3d, 0xbf, 0x3f, 0x30, 0x9f, 0x5c, 0x3f, 0xf0, 0xc3, 0x67, 0xbe,
+  0x70, 0xeb, 0xa7, 0xbf, 0x92, 0xd2, 0x74, 0xbe, 0xe9, 0x72, 0x9d, 0x3f, 0xf2, 0x42, 0x9e, 0xbf,
+  0x90, 0x02, 0x2d, 0x3f, 0x91, 0xd4, 0x1e, 0xbf, 0x12, 0x95, 0x7f, 0xbd, 0xdf, 0x11, 0x7c, 0xbf,
+  0x81, 0x01, 0xc7, 0x3e, 0xaf, 0x26, 0xe5, 0x3e, 0xfc, 0x9d, 0xcc, 0xbf, 0xa5, 0x0d, 0xe7, 0x3e,
+  0xea, 0x46, 0xc3, 0x3e, 0x04, 0xca, 0x79, 0x3e, 0xb5, 0x30, 0x13, 0x3d, 0x3f, 0x6f, 0x5d, 0x3e,
+  0x48, 0x73, 0x75, 0xbe, 0x1f, 0xb3, 0x35, 0x3e, 0xfd, 0xda, 0xc6, 0xbf, 0x4a, 0x6d, 0xc6, 0x3e,
+  0xd5, 0x66, 0x99, 0x3e, 0x33, 0x05, 0xb3, 0x3f, 0x1b, 0x87, 0xd8, 0xbf, 0xc2, 0x9e, 0xfc, 0x3e,
+  0xac, 0x0b, 0xff, 0xbe, 0x5d, 0x2a, 0x0b, 0xc0, 0xb3, 0xdb, 0x7b, 0xbf, 0x72, 0x63, 0x34, 0xbf,
+  0x71, 0xca, 0x4e, 0x3f, 0x05, 0x80, 0x4c, 0x3e, 0x41, 0x39, 0x06, 0xbf, 0x41, 0x5e, 0x18, 0x3f,
+  0x4e, 0x4a, 0xf2, 0xbf, 0xa7, 0xbf, 0xce, 0x3e, 0x33, 0x12, 0x49, 0x3f, 0x1e, 0xa3, 0x4f, 0xbe,
+  0x5e, 0xd5, 0x3a, 0xbe, 0x6f, 0x82, 0x10, 0xbf, 0x87, 0xf2, 0x01, 0x40, 0x42, 0x1f, 0x93, 0xbf,
+  0x6a, 0xc2, 0x02, 0x3f, 0xd8, 0x50, 0xd6, 0x3f, 0xf2, 0x80, 0x76, 0xbf, 0x8d, 0xc7, 0xb2, 0xbf,
+  0xb3, 0xfc, 0x5b, 0x3f, 0x6d, 0x29, 0xb6, 0x3e, 0x48, 0x03, 0x2a, 0x3f, 0xc1, 0xa5, 0xb3, 0x3e,
+  0x16, 0x3d, 0xa5, 0xbe, 0x47, 0xcc, 0x3e, 0xbf, 0x87, 0xca, 0x37, 0xbf, 0x3b, 0x6a, 0x61, 0x3e,
+  0x69, 0x87, 0xad, 0x3f, 0x6a, 0x4e, 0xc1, 0xbf, 0xee, 0xa9, 0x5a, 0xbf, 0x65, 0x75, 0xa6, 0x3f,
+  0x8d, 0x12, 0x24, 0xbd, 0x80, 0x25, 0x37, 0xc0, 0xbd, 0x92, 0xc4, 0x3f, 0x61, 0x0c, 0xf3, 0xbe,
+  0xda, 0x3e, 0x0d, 0xbf, 0xc1, 0xc4, 0xb2, 0x3e, 0x41, 0xab, 0x02, 0x3f, 0x34, 0x7e, 0x54, 0xbf,
+  0x96, 0xa0, 0x96, 0x3f, 0xb7, 0x1c, 0xb3, 0xbe, 0xdf, 0x95, 0xf7, 0x3e, 0x4a, 0x41, 0x7c, 0x3e,
+  0xfb, 0xc3, 0x91, 0xbf, 0x55, 0x29, 0x9b, 0x3e, 0x91, 0x67, 0xb7, 0x3e, 0xdf, 0xb1, 0x62, 0xbf,
+  0xe4, 0x83, 0x4c, 0xbf, 0x5e, 0x74, 0x37, 0x3f, 0x03, 0x60, 0x11, 0x3e, 0x70, 0x4e, 0xe0, 0x3d,
+  0x9c, 0x75, 0x04, 0x40, 0x3a, 0x14, 0xc4, 0x3e, 0xe1, 0x10, 0x46, 0xbe, 0xfc, 0x11, 0xb4, 0x3e,
+  0x8b, 0x9d, 0xbf, 0xbe, 0xaf, 0x19, 0xca, 0xbe, 0xc4, 0x91, 0x2a, 0x3f, 0x3d, 0xc5, 0x54, 0xbf,
+  0xd3, 0x11, 0x02, 0x3e, 0x0c, 0xee, 0xbf, 0x3f, 0x69, 0xa4, 0x27, 0x40, 0x17, 0x7e, 0xfc, 0x3d,
+  0xa8, 0xf7, 0x8b, 0xbf, 0x39, 0xa2, 0xbb, 0xbe, 0xb8, 0x70, 0x70, 0xbe, 0x9d, 0x3f, 0xdb, 0xbf,
+  0x4f, 0x7b, 0x59, 0xbe, 0xa2, 0xcb, 0x75, 0xbd, 0x4b, 0xc8, 0x14, 0x3f, 0x93, 0x57, 0xd4, 0xbf,
+  0xbd, 0x08, 0xa3, 0xbf, 0x2b, 0xe2, 0x5b, 0x3e, 0x0e, 0x60, 0x73, 0xbf, 0xee, 0xd4, 0xb8, 0x3d,
+  0xa5, 0x6b, 0x05, 0x3f, 0x0e, 0x5c, 0xed, 0xbf, 0x6d, 0xc7, 0x1e, 0xbe, 0x86, 0x53, 0xb4, 0x3f,
+  0x5b, 0xcd, 0xc3, 0xbd, 0xdc, 0x1e, 0x44, 0xbf, 0x74, 0xea, 0xfb, 0xbe, 0xb1, 0xef, 0xc8, 0xbf,
+  0xeb, 0xa2, 0x93, 0xbf, 0x4f, 0x02, 0x91, 0xbf, 0xdd, 0x61, 0xb3, 0xbe, 0xc0, 0x4b, 0x4d, 0xbf,
+  0x07, 0x74, 0x0c, 0xbe, 0x1b, 0x36, 0x4a, 0xbf, 0xc5, 0x5e, 0x62, 0x3f, 0x27, 0x31, 0x15, 0xc0,
+  0x30, 0xb9, 0x99, 0xbf, 0x45, 0x24, 0x86, 0xbf, 0x26, 0x35, 0xaa, 0xbf, 0xbe, 0x58, 0x8c, 0xbe,
+  0xfa, 0x29, 0x0f, 0xbf, 0x36, 0xb7, 0xef, 0xbf, 0xc1, 0x41, 0x35, 0xbf, 0x70, 0x1b, 0x75, 0x3d,
+  0x5a, 0x2f, 0x93, 0xbf, 0xae, 0x3a, 0x20, 0x3e, 0x9d, 0x62, 0xeb, 0x3e, 0x93, 0xd3, 0x7c, 0xbe,
+  0x7f, 0x83, 0xad, 0x3f, 0xfd, 0xe1, 0x10, 0xc0, 0xcb, 0x4b, 0xc7, 0x3f, 0xa2, 0x92, 0x27, 0x3f,
+  0x98, 0x6c, 0xd0, 0xbf, 0x10, 0xd2, 0xf3, 0xbe, 0xc5, 0x2f, 0xa2, 0x3f, 0x76, 0x07, 0xd8, 0x3f,
+  0xed, 0xf2, 0xff, 0x3e, 0xfd, 0x93, 0xa9, 0xbf, 0x73, 0xd1, 0x92, 0xbe, 0x22, 0x57, 0x5b, 0xbf,
+  0x3e, 0xc9, 0xc8, 0xbf, 0x16, 0x7d, 0x21, 0x3e, 0x78, 0x6e, 0x7d, 0xbf, 0x3c, 0x7a, 0xf2, 0x3e,
+  0x92, 0x17, 0xae, 0xbf, 0x8d, 0xbf, 0x01, 0x3e, 0x9d, 0xbf, 0x40, 0x3f, 0x18, 0x72, 0x59, 0x3f,
+  0xb1, 0x87, 0xdb, 0x3f, 0xba, 0xfe, 0x83, 0x3f, 0x43, 0x33, 0x34, 0xc0, 0x8e, 0x34, 0x25, 0xbf,
+  0x8d, 0x61, 0xba, 0xbe, 0x85, 0xc4, 0x3a, 0xbf, 0x03, 0x42, 0xde, 0x3e, 0xb6, 0x7d, 0xed, 0x3e,
+  0x8d, 0xf1, 0xc3, 0x3f, 0x0f, 0xb7, 0x77, 0x3f, 0x30, 0xa5, 0x8e, 0xbe, 0xbd, 0x8b, 0xba, 0x3f,
+  0xae, 0x85, 0x1b, 0x3f, 0x19, 0x8c, 0x87, 0xbf, 0xe0, 0x76, 0x4f, 0x3d, 0x7f, 0x60, 0x03, 0x3f,
+  0xdc, 0xc4, 0x83, 0xbf, 0xe4, 0xf2, 0x64, 0x3e, 0x28, 0x56, 0x9b, 0x3f, 0x26, 0xe5, 0xa2, 0x3e,
+  0x71, 0x6a, 0xd9, 0xbe, 0xb4, 0xc8, 0x09, 0x3f, 0x7e, 0x99, 0xcb, 0x3f, 0xf2, 0x3f, 0x9e, 0xbe,
+  0x15, 0x37, 0x2d, 0xbf, 0x4b, 0xc3, 0x22, 0xbf, 0x1d, 0x45, 0xe8, 0x3e, 0xd6, 0x07, 0xe9, 0x3f,
+  0xf6, 0x20, 0xe1, 0x3f, 0x42, 0xfe, 0xc4, 0x3d, 0xf6, 0x3f, 0xcf, 0xbf, 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, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 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, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x00,
+  0xe4, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x4c, 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, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x40, 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, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+  0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67,
+  0x68, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x66,
+  0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x00, 0x00, 0x02, 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, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 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, 0x1b, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1b, 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_svdf_kernel
+
+class NegTestDataInputOutputTypeMismatchSVDFKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSVDFKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_svdf_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSVDFKernel() 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_SVDF_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/svdf/TestDataSVDFBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/svdf/TestDataSVDFBase.h
new file mode 100644 (file)
index 0000000..971e507
--- /dev/null
@@ -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_SVDF_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_SVDF_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataSVDFBase : public TestDataBase<T>
+{
+public:
+  TestDataSVDFBase() = 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_SVDF_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose_conv/FloatTransposeConvKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose_conv/FloatTransposeConvKernel.h
new file mode 100644 (file)
index 0000000..a74a1a4
--- /dev/null
@@ -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_TRANSPOSE_CONV_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_TRANSPOSE_CONV_KERNEL_H
+
+#include "TestDataTransposeConvBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace transpose_conv_float
+{
+/*
+ * TransposeConv Kernel:
+ *
+ * Input(1, 4, 4, 2)      Weights(1, 3, 3, 2)
+ *            |           |
+ *            TransposeConv
+ *                  |
+ *           Output(1, 4, 4, 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,
+  0xac, 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x48, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x98, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x80, 0xc0,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x00, 0x10, 0xc1, 0x00, 0x00, 0x20, 0xc1, 0x00, 0x00, 0x30, 0x41, 0x00, 0x00, 0x40, 0xc1,
+  0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0x60, 0x41, 0x00, 0x00, 0x70, 0xc1, 0x00, 0x00, 0x80, 0xc1,
+  0x00, 0x00, 0x88, 0x41, 0x00, 0x00, 0x90, 0xc1, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 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,
+  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, 0x31, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+  0x34, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 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, 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, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x6b, 0x65, 0x72, 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, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x5f,
+  0x73, 0x68, 0x61, 0x70, 0x65, 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, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+  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.050506,   24.50502,  -2.1620092, -10.667578, -6.026517,    0.45524502, -9.493163, 11.918655,
+  0.89637375, 4.3721895, 15.263344,  4.124815,   -0.085579395, 12.434898,  8.761413,  -0.016460419,
+  14.467015,  7.194871,  8.063942,   -1.125905,  -3.0618992,   7.227646,   9.65494,   -7.4324093,
+  1.7922368,  2.179245,  2.5192776,  -8.438859,  5.4460173,    3.9627461,  5.714366,  -0.14670324};
+const std::vector<float> reference_output_data = {
+  -423.64435, -166.1708,  193.6256,  -206.75839, -683.60583, -257.56488, 359.98495, -445.70508,
+  -10.393387, -102.10723, 203.30502, -502.5265,  -330.8531,  199.97214,  188.26364, -245.66447};
+
+} // namespace transpose_conv_float
+
+class TestDataFloatTransposeConv : public TestDataTransposeConvBase<float>
+{
+public:
+  TestDataFloatTransposeConv()
+  {
+    _input_data = transpose_conv_float::input_data;
+    _reference_output_data = transpose_conv_float::reference_output_data;
+    _test_kernel_model_circle = transpose_conv_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatTransposeConv() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_TRANSPOSE_CONV_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose_conv/NegTransposeConvKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose_conv/NegTransposeConvKernel.h
new file mode 100644 (file)
index 0000000..b2d85e8
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_TRANSPOSE_CONV_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_TRANSPOSE_CONV_KERNEL_H
+
+#include "TestDataTransposeConvBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_transpose_conv_input_type_mismatch
+{
+
+/*
+ * TransposeConv Kernel with input type mismatch (input_type should be equal to weight_type):
+ *
+ * Input(1, 4, 4, 2) - Float32   Weight(1, 3, 3, 2) - Int32
+ *                 \                       /
+ *                  \                     /
+ *                       TransposeConv
+ *                             |
+ *                      Output(1, 4, 4, 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,
+  0xac, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x98, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
+  0x05, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0xf7, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xff, 0xff, 0x0b, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff,
+  0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf1, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff,
+  0x11, 0x00, 0x00, 0x00, 0xee, 0xff, 0xff, 0xff, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 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,
+  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, 0x31, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x70, 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, 0x04, 0x00, 0x00, 0x00, 0x04, 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,
+  0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff,
+  0x10, 0x00, 0x00, 0x00, 0x04, 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,
+  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,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x6f, 0x75, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 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, 0x43, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 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_transpose_conv_input_type_mismatch
+
+namespace neg_transpose_conv_invalid_input_shape
+{
+/*
+ * TransposeConv Kernel with input type mismatch (input_type should be equal to weight_type):
+ *
+ * Input(1, 1, 4, 4, 2) - Float32   Weight(1, 3, 3, 2) - Float32
+ *                 \                       /
+ *                  \                     /
+ *                       TransposeConv
+ *                             |
+ *                      Output(1, 4, 4, 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,
+  0xac, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x98, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x80, 0xc0,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x00, 0x10, 0xc1, 0x00, 0x00, 0x20, 0xc1, 0x00, 0x00, 0x30, 0x41, 0x00, 0x00, 0x40, 0xc1,
+  0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0x60, 0x41, 0x00, 0x00, 0x70, 0xc1, 0x00, 0x00, 0x80, 0xc1,
+  0x00, 0x00, 0x88, 0x41, 0x00, 0x00, 0x90, 0xc1, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 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,
+  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, 0x31, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+  0x34, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 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, 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, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 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,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x6f, 0x75, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 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, 0x43, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 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_transpose_conv_invalid_input_shape
+
+class NegTestDataInputMismatchTransposeConvKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputMismatchTransposeConvKernel()
+  {
+    _test_kernel_model_circle = neg_transpose_conv_input_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputMismatchTransposeConvKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputShapeTransposeConvKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInvalidInputShapeTransposeConvKernel()
+  {
+    _test_kernel_model_circle = neg_transpose_conv_invalid_input_shape::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInvalidInputShapeTransposeConvKernel() 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_TRANSPOSE_CONV_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose_conv/TestDataTransposeConvBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/transpose_conv/TestDataTransposeConvBase.h
new file mode 100644 (file)
index 0000000..504fa80
--- /dev/null
@@ -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_TRANSPOSE_CONV_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_TRANSPOSE_CONV_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataTransposeConvBase : public TestDataBase<T>
+{
+public:
+  TestDataTransposeConvBase() = 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_CONV_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unpack/FloatUnpackKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unpack/FloatUnpackKernel.h
new file mode 100644 (file)
index 0000000..9098a95
--- /dev/null
@@ -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_UNPACK_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_UNPACK_KERNEL_H
+
+#include "TestDataUnpackBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace unpack_float
+{
+/*
+ * Unpack Kernel:
+ *
+ *        Input(2, 2, 3, 4)
+ *          |
+ *     Unpack(num=2, axis=0)
+ *     /                  \
+ * Output1(2, 3, 4)        Output1(2, 3, 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,
+  0x34, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x88, 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, 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, 0x16, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+  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,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xac, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x3a, 0x31, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 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, 0x02, 0x00, 0x00, 0x00,
+  0x03, 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, 0x04, 0x00, 0x00, 0x00,
+  0x02, 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, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58,
+  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 = {
+  80.8925,     -4.4767537, 38.051624,  69.14668,  -23.124884,  -8.138234,  79.53351,   40.877926,
+  -12.0593405, 41.621094,  69.482895,  7.9741273, 3.7500796,   -80.87057,  10.576268,  -16.321995,
+  -12.388415,  -20.782156, 47.479202,  -56.73159, 81.99104,    70.61185,   32.652695,  -93.72114,
+  -75.67862,   -70.78546,  -42.199966, -12.66376, 21.785488,   -7.168219,  -19.772392, -17.600962,
+  64.1301,     -4.7490916, 76.81972,   -41.70657, -83.13318,   45.003937,  85.05216,   -29.184652,
+  40.685417,   -35.482887, -60.648735, -0.268777, -0.59301615, -19.212725, 87.67197,   -37.269848};
+const std::vector<float> reference_output_data_1 = {
+  80.8925,     -4.4767537, 38.051624, 69.14668,  -23.124884, -8.138234, 79.53351,  40.877926,
+  -12.0593405, 41.621094,  69.482895, 7.9741273, 3.7500796,  -80.87057, 10.576268, -16.321995,
+  -12.388415,  -20.782156, 47.479202, -56.73159, 81.99104,   70.61185,  32.652695, -93.72114};
+const std::vector<float> reference_output_data_2 = {
+  -75.67862, -70.78546,  -42.199966, -12.66376, 21.785488,   -7.168219,  -19.772392, -17.600962,
+  64.1301,   -4.7490916, 76.81972,   -41.70657, -83.13318,   45.003937,  85.05216,   -29.184652,
+  40.685417, -35.482887, -60.648735, -0.268777, -0.59301615, -19.212725, 87.67197,   -37.269848};
+
+} // namespace unpack_float
+
+class TestDataFloatUnpack : public TestDataUnpackBase<float>
+{
+public:
+  TestDataFloatUnpack()
+  {
+    _input_data = unpack_float::input_data;
+    _reference_output_data_1 = unpack_float::reference_output_data_1;
+    _reference_output_data_2 = unpack_float::reference_output_data_2;
+    _test_kernel_model_circle = unpack_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatUnpack() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_UNPACK_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unpack/NegUnpackKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unpack/NegUnpackKernel.h
new file mode 100644 (file)
index 0000000..4da828e
--- /dev/null
@@ -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_UNPACK_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_UNPACK_KERNEL_H
+
+#include "TestDataUnpackBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_unpack_input_type_mismatch
+{
+
+/*
+ * Unpack Kernel with input type mismatch (input_type should be equal to output_type):
+ *
+ *        Input(2, 2, 3, 4) - Int32
+ *                  |
+ *         Unpack(num=2, axis=0)
+ *     /                        \
+ * Output1(2, 3, 4)-Float32        Output1(2, 3, 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,
+  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, 0x68, 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, 0x16, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+  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,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 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, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x3a, 0x31, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 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, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x6f, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 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, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58,
+  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_unpack_input_type_mismatch
+
+class NegTestDataInputMismatchUnpackKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputMismatchUnpackKernel()
+  {
+    _test_kernel_model_circle = neg_unpack_input_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputMismatchUnpackKernel() 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_UNPACK_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unpack/TestDataUnpackBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/unpack/TestDataUnpackBase.h
new file mode 100644 (file)
index 0000000..65ad088
--- /dev/null
@@ -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_UNPACK_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_UNPACK_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataUnpackBase : public TestDataBase<T>
+{
+public:
+  TestDataUnpackBase() = 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_UNPACK_KERNEL_BASE_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/zeros_like/FloatZerosLikeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/zeros_like/FloatZerosLikeKernel.h
new file mode 100644 (file)
index 0000000..125a93f
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_ZEROS_LIKE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_FLOAT_ZEROS_LIKE_KERNEL_H
+
+#include "TestDataZerosLikeBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace zeros_like_float
+{
+/*
+ * ZerosLike Kernel:
+ *
+ *           Input(1, 8, 8, 4)
+ *                 |
+ *              ZerosLike
+ *                  |
+ *           Output(1, 8, 8, 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,
+  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, 0x43, 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, 0x08, 0x00, 0x00, 0x00, 0x08, 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, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x08, 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,
+  0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 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.7787564, 13.526123,  14.194824,  10.215213,  6.5696063,  0.32476053, 5.172812,   11.58254,
+  1.2253664, 6.448969,   4.818403,   5.173219,   5.2025485,  8.907726,   4.8675847,  9.658814,
+  5.3619566, 3.8089416,  2.4607596,  9.53005,    4.313822,   4.409469,   2.5364797,  13.099183,
+  5.745605,  11.5468855, 3.1745827,  11.864263,  3.6772785,  9.995764,   7.7593145,  7.6526804,
+  6.112807,  5.48038,    3.7828858,  7.090309,   5.489285,   2.3067036,  14.311049,  13.833762,
+  12.089778, 12.386912,  11.303204,  14.277523,  11.803083,  6.6585464,  2.7015727,  14.788383,
+  12.607371, 9.1037035,  14.309183,  11.836715,  2.358639,   3.6424284,  7.4297013,  2.298006,
+  12.073541, 4.2871723,  6.96936,    2.777173,   10.598123,  9.057254,   8.749597,   12.798924,
+  5.3618493, 6.4888196,  0.8675639,  1.0193392,  8.820988,   8.71598,    2.3144798,  6.4430947,
+  9.2404785, 14.713503,  7.9737625,  14.192959,  7.2330065,  1.4928365,  13.074282,  8.062984,
+  2.477071,  1.0175642,  8.497505,   4.331551,   4.4471636,  4.101821,   3.2111287,  7.7156234,
+  9.624156,  7.312001,   14.068299,  3.1033943,  5.766773,   0.14364493, 6.7649574,  14.875702,
+  8.498291,  4.2673383,  12.381352,  5.6543016,  10.172108,  13.540233,  5.5367966,  8.703237,
+  2.8888083, 12.95428,   4.149702,   14.5791,    8.460501,   10.52306,   4.754477,   12.637787,
+  4.265919,  12.244986,  7.511471,   6.9737573,  10.677587,  12.313292,  1.9264419,  14.983515,
+  12.197964, 9.873872,   2.853508,   8.904088,   11.980053,  12.680642,  14.272312,  6.467417,
+  6.7574244, 11.432324,  8.442689,   11.535555,  7.413639,   12.879065,  1.3870583,  11.108672,
+  7.102633,  12.837867,  13.467441,  14.339677,  13.595035,  9.505788,   3.3638806,  7.9711785,
+  5.9886556, 9.487856,   13.933081,  12.057823,  12.9993105, 4.722163,   0.95726097, 10.479345,
+  1.531544,  10.66464,   6.4508915,  6.547761,   10.806489,  12.947966,  14.944827,  6.6092124,
+  13.971567, 4.359874,   13.894613,  10.704036,  6.450422,   5.7402406,  1.3440402,  10.858341,
+  11.920715, 8.983641,   3.759923,   7.9603405,  13.422217,  14.646154,  11.382288,  11.591205,
+  13.14068,  14.599585,  14.313996,  11.4980135, 11.228389,  2.3352063,  0.26753145, 12.255293,
+  2.3492632, 13.274841,  3.6202207,  0.5872089,  10.600124,  13.302039,  13.432229,  2.3966095,
+  14.03712,  5.0836163,  13.029095,  8.314608,   13.133893,  2.7634015,  4.304786,   7.431993,
+  2.6958325, 8.048784,   12.457581,  11.330703,  12.303246,  7.140373,   11.876143,  0.8814453,
+  6.90046,   10.70249,   12.065882,  12.265273,  9.0821085,  10.044222,  0.72431827, 14.340595,
+  14.978852, 6.455387,   0.76369095, 2.1449616,  6.9374723,  11.827915,  1.2242815,  9.756281,
+  8.263249,  4.867419,   2.4891205,  2.9900494,  6.7416954,  6.3161993,  5.616863,   13.482001,
+  12.058539, 8.699999,   12.006457,  10.08873,   12.14564,   4.7759733,  10.889552,  6.1692514,
+  5.365749,  9.306172,   9.769926,   9.491741,   1.2538989,  2.4900718,  0.6668129,  9.1738,
+  13.009842, 11.950754,  6.241434,   5.1960526,  7.8892946,  7.969435,   0.75331974, 8.6089735};
+
+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.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, 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.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, 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.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, 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.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, 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.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, 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.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, 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.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 zeros_like_float
+
+class TestDataFloatZerosLike : public TestDataZerosLikeBase<float>
+{
+public:
+  TestDataFloatZerosLike()
+  {
+    _input_data = zeros_like_float::input_data;
+    _reference_output_data = zeros_like_float::reference_output_data;
+    _test_kernel_model_circle = zeros_like_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatZerosLike() override = default;
+};
+
+} // namespace test_kernel
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_FLOAT_ZEROS_LIKE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/zeros_like/NegZerosLikeKernel.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/zeros_like/NegZerosLikeKernel.h
new file mode 100644 (file)
index 0000000..afb9730
--- /dev/null
@@ -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_ZEROS_LIKE_KERNEL_H
+#define LUCI_INTERPRETER_TEST_MODELS_NEG_ZEROS_LIKE_KERNEL_H
+
+#include "TestDataZerosLikeBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+namespace neg_zeros_like_input_type_mismatch
+{
+
+/*
+ * ZerosLike Kernel with input type mismatch (input_type should be equal to output_type):
+ *
+ *           Input(1, 8, 8, 4) - Float32
+ *                 |
+ *              ZerosLike
+ *                  |
+ *           Output(1, 8, 8, 4) - 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, 0x43, 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, 0x08, 0x00, 0x00, 0x00, 0x08, 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, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x08, 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,
+  0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 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_zeros_like_input_type_mismatch
+
+class NegTestDataInputMismatchZerosLikeKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputMismatchZerosLikeKernel()
+  {
+    _test_kernel_model_circle = neg_zeros_like_input_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputMismatchZerosLikeKernel() 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_ZEROS_LIKE_KERNEL_H
diff --git a/onert-micro/luci-interpreter/include/luci_interpreter/test_models/zeros_like/TestDataZerosLikeBase.h b/onert-micro/luci-interpreter/include/luci_interpreter/test_models/zeros_like/TestDataZerosLikeBase.h
new file mode 100644 (file)
index 0000000..7e3a14e
--- /dev/null
@@ -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_ZEROS_LIKE_KERNEL_BASE_H
+#define LUCI_INTERPRETER_TEST_MODELS_ZEROS_LIKE_KERNEL_BASE_H
+
+#include "luci_interpreter/test_models/TestDataBase.h"
+
+namespace luci_interpreter
+{
+namespace test_kernel
+{
+
+template <typename T> class TestDataZerosLikeBase : public TestDataBase<T>
+{
+public:
+  TestDataZerosLikeBase() = 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_ZEROS_LIKE_KERNEL_BASE_H
index 353e117..934fb97 100644 (file)
@@ -1,61 +1,71 @@
+REGISTER_KERNEL(ABS, Abs)
 REGISTER_KERNEL(ADD, Add)
-REGISTER_KERNEL(ARG_MAX, ArgMax)
 REGISTER_KERNEL(AVERAGE_POOL_2D, AveragePool2D)
+REGISTER_KERNEL(ARG_MAX, ArgMax)
+REGISTER_KERNEL(ARG_MIN, ArgMin)
+REGISTER_KERNEL(BROADCAST_TO, BroadcastTo)
 REGISTER_KERNEL(BATCH_TO_SPACE_ND, BatchToSpaceND)
+REGISTER_KERNEL(CEIL, Ceil)
 REGISTER_KERNEL(CAST, Cast)
-REGISTER_KERNEL(CONCATENATION, Concatenation)
-REGISTER_KERNEL(CONV_2D, Conv2D)
+REGISTER_KERNEL(DIV, Div)
 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(ADD_N, AddN)
+REGISTER_KERNEL(CONV_2D, Conv2D)
+REGISTER_KERNEL(LOGISTIC, Logistic)
+REGISTER_KERNEL(LOG, Log)
+REGISTER_KERNEL(GATHER, Gather)
+REGISTER_KERNEL(GATHER_ND, GatherND)
 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(GREATER, Greater)
 REGISTER_KERNEL(GREATER_EQUAL, GreaterEqual)
-REGISTER_KERNEL(INSTANCE_NORM, InstanceNorm)
+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(REDUCE_MAX, ReduceMax)
+REGISTER_KERNEL(ROUND, Round)
+REGISTER_KERNEL(LESS, Less)
 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(LOGICAL_AND, LogicalAnd)
-REGISTER_KERNEL(LOGICAL_NOT, LogicalNot)
 REGISTER_KERNEL(LOGICAL_OR, LogicalOr)
-REGISTER_KERNEL(LOGISTIC, Logistic)
-REGISTER_KERNEL(MAXIMUM, Maximum)
-REGISTER_KERNEL(MAX_POOL_2D, MaxPool2D)
-REGISTER_KERNEL(MINIMUM, Minimum)
-REGISTER_KERNEL(MIRROR_PAD, MirrorPad)
+REGISTER_KERNEL(LEAKY_RELU, LeakyRelu)
+REGISTER_KERNEL(LOG_SOFTMAX, LogSoftmax)
 REGISTER_KERNEL(MUL, Mul)
-REGISTER_KERNEL(NEG, Neg)
-REGISTER_KERNEL(NOT_EQUAL, NotEqual)
-REGISTER_KERNEL(PAD, Pad)
-REGISTER_KERNEL(PADV2, PadV2)
-REGISTER_KERNEL(PRELU, PRelu)
-REGISTER_KERNEL(QUANTIZE, Quantize)
-REGISTER_KERNEL(RESHAPE, Reshape)
-REGISTER_KERNEL(RESIZE_BILINEAR, ResizeBilinear)
-REGISTER_KERNEL(RESIZE_NEAREST_NEIGHBOR, ResizeNearestNeighbor)
-REGISTER_KERNEL(RSQRT, Rsqrt)
+REGISTER_KERNEL(MIRROR_PAD, MirrorPad)
+REGISTER_KERNEL(MAX_POOL_2D, MaxPool2D)
+REGISTER_KERNEL(MEAN, Mean)
+REGISTER_KERNEL(CONCATENATION, Concatenation)
 REGISTER_KERNEL(SHAPE, Shape)
-REGISTER_KERNEL(SOFTMAX, Softmax)
+REGISTER_KERNEL(NOT_EQUAL, NotEqual)
+REGISTER_KERNEL(SQUARED_DIFFERENCE, SquaredDifference)
+REGISTER_KERNEL(SLICE, Slice)
+REGISTER_KERNEL(SPLIT, Split)
 REGISTER_KERNEL(SPACE_TO_BATCH_ND, SpaceToBatchND)
-REGISTER_KERNEL(SPACE_TO_DEPTH, SpaceToDepth)
 REGISTER_KERNEL(STRIDED_SLICE, StridedSlice)
+REGISTER_KERNEL(SPLIT_V, SplitV)
 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(SPACE_TO_DEPTH, SpaceToDepth)
+REGISTER_KERNEL(QUANTIZE, Quantize)
 REGISTER_KERNEL(TANH, Tanh)
 REGISTER_KERNEL(TRANSPOSE, Transpose)
-REGISTER_KERNEL(TRANSPOSE_CONV, TransposeConv)
-REGISTER_KERNEL(UNIDIRECTIONAL_SEQUENCE_LSTM, UnidirectionalSequenceLSTM)
+REGISTER_KERNEL(SOFTMAX, Softmax)
+REGISTER_KERNEL(SUM, Sum)
+REGISTER_KERNEL(SELECT_V2, SelectV2)
+REGISTER_KERNEL(SVDF, SVDF)
+REGISTER_KERNEL(WHILE, While)
+REGISTER_KERNEL(RESIZE_BILINEAR, ResizeBilinear)
+REGISTER_KERNEL(RESIZE_NEAREST_NEIGHBOR, ResizeNearestNeighbor)
+REGISTER_KERNEL(RSQRT, Rsqrt)
+REGISTER_KERNEL(NEG, Neg)
+REGISTER_KERNEL(ZEROS_LIKE, ZerosLike)
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/KernelsToTrain.lst b/onert-micro/luci-interpreter/pal/cmsisnn/KernelsToTrain.lst
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALAdd.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALAdd.h
new file mode 100644 (file)
index 0000000..3576cf0
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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"
+#include "arm_nnfunctions.h"
+
+namespace luci_interpreter_pal
+{
+template <>
+inline void Add<int8_t>(const ArithmeticParams &params, const int flat_size,
+                        const int8_t *input1_data, const int8_t *input2_data, int8_t *output_data)
+{
+  auto status = arm_elementwise_add_s8(
+    input1_data, input2_data, params.input1_offset, params.input1_multiplier, params.input1_shift,
+    params.input2_offset, params.input2_multiplier, params.input2_shift, params.left_shift,
+    output_data, params.output_offset, params.output_multiplier, params.output_shift,
+    params.quantized_activation_min, params.quantized_activation_max, flat_size);
+  assert(status == ARM_CMSIS_NN_SUCCESS);
+}
+
+template <>
+inline void Add<int16_t>(const ArithmeticParams &params, const int flat_size,
+                         const int16_t *input1_data, const int16_t *input2_data,
+                         int16_t *output_data)
+{
+  auto status = arm_elementwise_add_s16(
+    input1_data, input2_data, params.input1_offset, params.input1_multiplier, params.input1_shift,
+    params.input2_offset, params.input2_multiplier, params.input2_shift, params.left_shift,
+    output_data, params.output_offset, params.output_multiplier, params.output_shift,
+    params.quantized_activation_min, params.quantized_activation_max, flat_size);
+  assert(status == ARM_CMSIS_NN_SUCCESS);
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_ADD_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALAveragePool2D.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALAveragePool2D.h
new file mode 100644 (file)
index 0000000..32858ac
--- /dev/null
@@ -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_CMSIS_NN_AVERAGE_POOL_2D_H
+#define LUCI_INTERPRETER_PAL_CMSIS_NN_AVERAGE_POOL_2D_H
+
+#include "PALAveragePool2DCommon.h"
+
+#include <arm_nnfunctions.h>
+
+namespace luci_interpreter_pal
+{
+inline void AveragePool(const PoolParams &params, const luci_interpreter::RuntimeShape &input_shape,
+                        const uint8_t *input_data,
+                        const luci_interpreter::RuntimeShape &output_shape, uint8_t *output_data,
+                        luci_interpreter::DataType data_type)
+{
+  cmsis_nn_dims input_dims;
+  cmsis_nn_dims output_dims;
+  cmsis_nn_pool_params pool_params;
+  cmsis_nn_dims filter_dims;
+  cmsis_nn_context ctx;
+
+  const int depth = input_shape.dims(3);
+  const int output_width = output_shape.dims(2);
+
+  input_dims.n = 1;
+  input_dims.h = input_shape.dims(1);
+  input_dims.w = input_shape.dims(2);
+  input_dims.c = depth;
+
+  output_dims.n = 1;
+  output_dims.h = output_shape.dims(1);
+  output_dims.w = output_width;
+  output_dims.c = depth;
+
+  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;
+
+  filter_dims.n = 1;
+  filter_dims.h = params.filter_height;
+  filter_dims.w = params.filter_width;
+  filter_dims.c = 1;
+
+  const int32_t buffer_size = data_type == luci_interpreter::DataType::S16
+                                ? arm_avgpool_s16_get_buffer_size(output_width, depth)
+                                : arm_avgpool_s8_get_buffer_size(output_width, depth);
+  int8_t *buffer = nullptr;
+  if (buffer_size > 0)
+  {
+    buffer = new int8_t[buffer_size];
+  }
+
+  ctx.buf = buffer;
+  ctx.size = buffer_size;
+
+  if (data_type == luci_interpreter::DataType::S8)
+  {
+    arm_avgpool_s8(&ctx, &pool_params, &input_dims,
+                   luci_interpreter::kernels::getTensorData<int8_t>(input_data), &filter_dims,
+                   &output_dims, luci_interpreter::kernels::getTensorData<int8_t>(output_data));
+  }
+  else
+  {
+    arm_avgpool_s16(&ctx, &pool_params, &input_dims,
+                    luci_interpreter::kernels::getTensorData<int16_t>(input_data), &filter_dims,
+                    &output_dims, luci_interpreter::kernels::getTensorData<int16_t>(output_data));
+  }
+
+  if (buffer_size > 0)
+    delete[] buffer;
+}
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_CMSIS_NN_AVERAGE_POOL_2D_H
index bd47a88..202203c 100644 (file)
 #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 <arm_nn_types.h>
+#include "PALConv2DCommon.h"
+
 #include <arm_nnfunctions.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 *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)
-{
-  (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);
-}
-
-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)
-{
-  if (scratchpad_data)
-  {
-    cmsis_nn_conv_params conv_params;
-    conv_params.dilation.h = params.dilation_height_factor;
-    conv_params.dilation.w = params.dilation_width_factor;
-
-    assert(conv_params.dilation.h == 1);
-    assert(conv_params.dilation.w == 1);
-
-    conv_params.input_offset = params.input_offset;
-    conv_params.output_offset = params.output_offset;
-    conv_params.stride.h = params.stride_height;
-    conv_params.stride.w = params.stride_width;
-    conv_params.padding.h = params.padding_values.height;
-    conv_params.padding.w = params.padding_values.width;
-    conv_params.activation.min = params.quantized_activation_min;
-    conv_params.activation.max = params.quantized_activation_max;
-
-    cmsis_nn_per_channel_quant_params quant_params;
-    quant_params.multiplier = const_cast<int32_t *>(mult);
-    quant_params.shift = const_cast<int32_t *>(shifts);
-
-    assert(conv_params.activation.min <= conv_params.activation.max);
-    assert(input_shape.DimensionsCount() == 4);
-    assert(filter_shape.DimensionsCount() == 4);
-    assert(output_shape.DimensionsCount() == 4);
-    const int batch_size = tflite::MatchingDim(input_shape, 0, output_shape, 0);
-    const int input_depth = tflite::MatchingDim(input_shape, 3, filter_shape, 3);
-    const int output_depth = tflite::MatchingDim(filter_shape, 0, 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_depth;
-
-    cmsis_nn_dims filter_dims;
-    filter_dims.n = output_depth;
-    filter_dims.h = filter_shape.Dims(1);
-    filter_dims.w = filter_shape.Dims(2);
-    filter_dims.c = input_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_convolve_wrapper_s8(&ctx, &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::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)
+static inline void QuantizedConvPerChannel(const ConvParams &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)
 {
   cmsis_nn_conv_params conv_params;
   conv_params.dilation.h = params.dilation_height_factor;
   conv_params.dilation.w = params.dilation_width_factor;
 
-  if (input_data_type == luci_interpreter::DataType::S8 && conv_params.dilation.h == 1 &&
-      conv_params.dilation.w == 1)
-  {
-    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_depth = tflite::MatchingDim(filter_shape, 0, output_shape, 3);
-    const int32_t filter_height = filter_shape.Dims(1);
-    const int32_t filter_width = filter_shape.Dims(2);
-    const int32_t output_height = output_shape.Dims(1);
-    const int32_t output_width = output_shape.Dims(2);
-
-    conv_params.input_offset = params.input_offset;
-    conv_params.output_offset = params.output_offset;
-    conv_params.stride.h = params.stride_height;
-    conv_params.stride.w = params.stride_width;
-    conv_params.padding.h = params.padding_values.height;
-    conv_params.padding.w = params.padding_values.width;
-
-    cmsis_nn_dims input_dims;
-    input_dims.n = batches;
-    input_dims.h = input_shape.Dims(1);
-    input_dims.w = input_shape.Dims(2);
-    input_dims.c = input_depth;
-
-    cmsis_nn_dims filter_dims;
-    filter_dims.n = output_depth;
-    filter_dims.h = filter_height;
-    filter_dims.w = filter_width;
-    filter_dims.c = input_depth;
-
-    cmsis_nn_dims output_dims;
-    output_dims.n = batches;
-    output_dims.h = output_height;
-    output_dims.w = output_width;
-    output_dims.c = output_depth;
-
-    const int32_t buf_size = arm_convolve_wrapper_s8_get_buffer_size(&conv_params, &input_dims,
-                                                                     &filter_dims, &output_dims);
-
-    luci_interpreter::Shape scratchpad_shape{buf_size};
-    scratchpad->resize(scratchpad_shape);
-  }
-  else
-  {
-    scratchpad->set_allocatable(false);
-  }
+  assert(conv_params.dilation.h == 1);
+  assert(conv_params.dilation.w == 1);
+
+  conv_params.input_offset = params.input_offset;
+  conv_params.output_offset = params.output_offset;
+  conv_params.stride.h = params.stride_height;
+  conv_params.stride.w = params.stride_width;
+  conv_params.padding.h = params.padding_values.height;
+  conv_params.padding.w = params.padding_values.width;
+  conv_params.activation.min = params.quantized_activation_min;
+  conv_params.activation.max = params.quantized_activation_max;
+
+  cmsis_nn_per_channel_quant_params quant_params;
+  quant_params.multiplier = const_cast<int32_t *>(params.per_channel_output_multiplier.data());
+  quant_params.shift = const_cast<int32_t *>(
+    reinterpret_cast<const int32_t *>(params.per_channel_output_shift.data()));
+
+  assert(conv_params.activation.min <= conv_params.activation.max);
+  const int batch_size = input_shape[0];
+  const int input_depth = input_shape[3];
+  const int output_depth = filter_shape[0];
+
+  cmsis_nn_dims input_dims;
+  input_dims.n = batch_size;
+  input_dims.h = input_shape[1];
+  input_dims.w = input_shape[2];
+  input_dims.c = input_depth;
+
+  cmsis_nn_dims filter_dims;
+  filter_dims.n = output_depth;
+  filter_dims.h = filter_shape[1];
+  filter_dims.w = filter_shape[2];
+  filter_dims.c = input_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[1];
+  output_dims.w = output_shape[2];
+  output_dims.c = output_depth;
+
+  auto buf_size =
+    arm_convolve_wrapper_s8_get_buffer_size(&conv_params, &input_dims, &filter_dims, &output_dims);
+
+  auto buffer = std::make_unique<int8_t[]>(buf_size);
+  assert(buffer != nullptr);
+
+  cmsis_nn_context ctx;
+  ctx.buf = buffer.get();
+  ctx.size = buf_size;
+
+  auto res = arm_convolve_wrapper_s8(&ctx, &conv_params, &quant_params, &input_dims, input_data,
+                                     &filter_dims, filter_data, &bias_dims, bias_data, &output_dims,
+                                     output_data);
+
+  assert(res == ARM_CMSIS_NN_SUCCESS);
 }
 
 } // namespace luci_interpreter_pal
index 32e9057..a2fe2b2 100644 (file)
  * 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 "PALFullyConnectedCommon.h"
 
-#include <tensorflow/lite/kernels/internal/reference/fully_connected.h>
-#include <tensorflow/lite/kernels/internal/reference/integer_ops/fully_connected.h>
 #include <arm_nnfunctions.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)
+inline void FullyConnected<int8_t>(const luci_interpreter_pal::FullyConnectedParams &params,
+                                   const int32_t *, 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, uint32_t output_dims_count,
+                                   uint32_t weights_dims_count)
 {
-  assert(output_shape.DimensionsCount() == 2);
-
-  const int batches = output_shape.Dims(0);
-  const int output_depth = output_shape.Dims(1);
-
-  const int filter_dim_count = filter_shape.DimensionsCount();
-  const int accum_depth = filter_shape.Dims(filter_dim_count - 1);
+  const int batches = flatSizeSkipDim(output_shape, output_dims_count - 1, output_dims_count);
+  const int output_depth = output_shape[output_dims_count - 1];
+  const int accum_depth = filter_shape[weights_dims_count - 1];
 
   cmsis_nn_fc_params fc_params;
   fc_params.input_offset = params.input_offset;
@@ -107,8 +82,69 @@ FullyConnected<int8_t>(const tflite::FullyConnectedParams &params,
   auto res =
     arm_fully_connected_s8(&ctx, &fc_params, &quant_params, &input_dims, input_data, &filter_dims,
                            filter_data, &bias_dims, bias_data, &output_dims, output_data);
-  assert(res == ARM_MATH_SUCCESS);
+  assert(res == ARM_CMSIS_NN_SUCCESS);
+}
+
+template <>
+inline void FullyConnected(const luci_interpreter_pal::FullyConnectedParams &params,
+                           const int32_t *, const int16_t *input_data, const int32_t *filter_shape,
+                           const int8_t *filter_data, const int64_t *bias_data,
+                           const int32_t *output_shape, int16_t *output_data,
+                           uint32_t output_dims_count, uint32_t weights_dims_count)
+{
+  const int batches = flatSizeSkipDim(output_shape, output_dims_count - 1, output_dims_count);
+  const int output_depth = output_shape[output_dims_count - 1];
+  const int accum_depth = filter_shape[weights_dims_count - 1];
+
+  cmsis_nn_fc_params fc_params;
+  fc_params.input_offset = params.input_offset;
+  fc_params.output_offset = params.output_offset;
+  fc_params.filter_offset = params.weights_offset;
+  fc_params.activation.min = params.quantized_activation_min;
+  fc_params.activation.max = params.quantized_activation_max;
+
+  cmsis_nn_per_tensor_quant_params quant_params;
+  quant_params.multiplier = params.output_multiplier;
+  quant_params.shift = params.output_shift;
+
+  cmsis_nn_dims input_dims;
+  input_dims.n = batches;
+  input_dims.h = 1;
+  input_dims.w = 1;
+  input_dims.c = accum_depth;
+
+  cmsis_nn_dims filter_dims;
+  filter_dims.n = accum_depth;
+  filter_dims.h = 1;
+  filter_dims.w = 1;
+  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 = batches;
+  output_dims.h = 1;
+  output_dims.w = 1;
+  output_dims.c = output_depth;
+
+  int32_t buf_size = arm_fully_connected_s16_get_buffer_size(&filter_dims);
+  auto buffer = std::make_unique<int8_t[]>(buf_size);
+  assert(buffer != nullptr);
+
+  cmsis_nn_context ctx;
+  ctx.buf = buffer.get();
+  ctx.size = buf_size;
+
+  auto res =
+    arm_fully_connected_s16(&ctx, &fc_params, &quant_params, &input_dims, input_data, &filter_dims,
+                            filter_data, &bias_dims, bias_data, &output_dims, output_data);
+  assert(res == ARM_CMSIS_NN_SUCCESS);
 }
+
 } // 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/cmsisnn/PALL2Pool2D.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALL2Pool2D.h
deleted file mode 100644 (file)
index 38a302f..0000000
+++ /dev/null
@@ -1,33 +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.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_L2POOL2D_H
-#define LUCI_INTERPRETER_PAL_L2POOL2D_H
-
-#include <tensorflow/lite/kernels/internal/reference/pooling.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::reference_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/cmsisnn/PALMaxPool2D.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALMaxPool2D.h
new file mode 100644 (file)
index 0000000..d422f20
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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_CMSIS_NN_MAX_POOL_2D_H
+#define LUCI_INTERPRETER_PAL_CMSIS_NN_MAX_POOL_2D_H
+
+#include "PALMaxPool2DCommon.h"
+
+#include <arm_nnfunctions.h>
+
+namespace luci_interpreter_pal
+{
+
+inline void MaxPool(const PoolParams &params, const luci_interpreter::RuntimeShape &input_shape,
+                    const uint8_t *input_data, const luci_interpreter::RuntimeShape &output_shape,
+                    uint8_t *output_data, luci_interpreter::DataType data_type)
+{
+  cmsis_nn_dims input_dims;
+  cmsis_nn_dims output_dims;
+  cmsis_nn_pool_params pool_params;
+  cmsis_nn_dims filter_dims;
+  cmsis_nn_context ctx;
+
+  const int depth = input_shape.dims(3);
+  const int output_width = output_shape.dims(2);
+
+  input_dims.n = 1;
+  input_dims.h = input_shape.dims(1);
+  input_dims.w = input_shape.dims(2);
+  input_dims.c = depth;
+
+  output_dims.n = 1;
+  output_dims.h = output_shape.dims(1);
+  output_dims.w = output_width;
+  output_dims.c = depth;
+
+  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;
+
+  filter_dims.n = 1;
+  filter_dims.h = params.filter_height;
+  filter_dims.w = params.filter_width;
+  filter_dims.c = 1;
+
+  if (data_type == luci_interpreter::DataType::S8)
+  {
+    arm_max_pool_s8(&ctx, &pool_params, &input_dims,
+                    luci_interpreter::kernels::getTensorData<int8_t>(input_data), &filter_dims,
+                    &output_dims, luci_interpreter::kernels::getTensorData<int8_t>(output_data));
+  }
+  else
+  {
+    arm_max_pool_s16(&ctx, &pool_params, &input_dims,
+                     luci_interpreter::kernels::getTensorData<int16_t>(input_data), &filter_dims,
+                     &output_dims, luci_interpreter::kernels::getTensorData<int16_t>(output_data));
+  }
+}
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_CMSIS_NN_MAX_POOL_2D_H
index 347a97a..e640c35 100644 (file)
 #ifndef LUCI_INTERPRETER_PAL_MUL_H
 #define LUCI_INTERPRETER_PAL_MUL_H
 
-#include <tensorflow/lite/kernels/internal/reference/mul.h>
+#include "PALMulCommon.h"
+#include "arm_nnfunctions.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 &params, const int flat_size,
+                        const int8_t *input1_data, const int8_t *input2_data, int8_t *output_data)
 {
-  tflite::reference_ops::BroadcastMul4DSlow(params, input1_shape, input1_data, input2_shape,
-                                            input2_data, output_shape, output_data);
+  auto status = arm_elementwise_mul_s8(
+    input1_data, input2_data, params.input1_offset, params.input2_offset, output_data,
+    params.output_offset, params.output_multiplier, params.output_shift,
+    params.quantized_activation_min, params.quantized_activation_max, flat_size);
+  assert(status == ARM_CMSIS_NN_SUCCESS);
 }
 
-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 &params, const int flat_size,
+                         const int16_t *input1_data, const int16_t *input2_data,
+                         int16_t *output_data)
 {
-  tflite::reference_ops::BroadcastMul4DSlow(params, input1_shape, input1_data, input2_shape,
-                                            input2_data, output_shape, output_data);
+  auto status = arm_elementwise_mul_s16(
+    input1_data, input2_data, params.input1_offset, params.input2_offset, output_data,
+    params.output_offset, params.output_multiplier, params.output_shift,
+    params.quantized_activation_min, params.quantized_activation_max, flat_size);
+  assert(status == ARM_CMSIS_NN_SUCCESS);
 }
+
 } // namespace luci_interpreter_pal
 
 #endif // LUCI_INTERPRETER_PAL_MUL_H
diff --git a/onert-micro/luci-interpreter/pal/cmsisnn/PALSVDF.h b/onert-micro/luci-interpreter/pal/cmsisnn/PALSVDF.h
new file mode 100644 (file)
index 0000000..ea05dd7
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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_SVDF_H
+#define LUCI_INTERPRETER_PAL_SVDF_H
+
+#include "PALSVDFCommon.h"
+
+// TODO: add INT8 version
+
+#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
new file mode 100644 (file)
index 0000000..2bc7985
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * 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_SOFTMAX_H
+#define LUCI_INTERPRETER_PAL_SOFTMAX_H
+
+#include "PALSoftmaxCommon.h"
+
+#include <arm_nnfunctions.h>
+
+namespace
+{
+const int kInt16LUTArraySize = 513;
+
+// LUTPopulate takes an optional type-erased transform_params to allow passing
+// extra parameters to the transform function pointer. const void* is used
+// instead of std::function to be compatible with TFLite Micro
+template <typename FloatT, typename Func>
+inline typename std::enable_if<std::is_same<Func, FloatT (*)(FloatT)>::value, FloatT>::type
+LUTTransform(Func transform, const void * /*transform_params*/, FloatT value)
+{
+  static_assert(std::is_floating_point<FloatT>::value, "FloatT must be a floating-point type.");
+  return transform(value);
+}
+
+// Keep floating-point type configurable for backward compatibility. float
+// should be used for FloatT by default.
+template <typename FloatT, typename Func>
+inline void LUTPopulateInt16(FloatT input_scale, int32_t input_zero_point, FloatT output_scale,
+                             int32_t output_zero_point, Func transform,
+                             const void *transform_params, int16_t *lut)
+{
+  static_assert(std::is_floating_point<FloatT>::value, "FloatT must be a floating-point type.");
+  const FloatT input_min = input_scale * (std::numeric_limits<int16_t>::min() - input_zero_point);
+  const FloatT input_max = input_scale * (std::numeric_limits<int16_t>::max() - input_zero_point);
+  const FloatT output_min =
+    output_scale * (std::numeric_limits<int16_t>::min() - output_zero_point);
+  const FloatT output_max =
+    output_scale * (std::numeric_limits<int16_t>::max() - output_zero_point);
+
+  const int nb_steps = 512;
+  const FloatT step = (input_max - input_min) / nb_steps;
+  const FloatT half_step = step / 2;
+  const FloatT output_scaling_inv = static_cast<FloatT>(std::numeric_limits<int16_t>::max() -
+                                                        std::numeric_limits<int16_t>::min() + 1) /
+                                    (output_max - output_min);
+  const FloatT table_min = static_cast<FloatT>(std::numeric_limits<int16_t>::min());
+  const FloatT table_max = static_cast<FloatT>(std::numeric_limits<int16_t>::max());
+
+  for (int i = 0; i < nb_steps; i++)
+  {
+    const FloatT val = LUTTransform<FloatT>(transform, transform_params, input_min + i * step);
+    const FloatT val_midpoint =
+      LUTTransform<FloatT>(transform, transform_params, input_min + i * step + half_step);
+    const FloatT val_next =
+      LUTTransform<FloatT>(transform, transform_params, input_min + (i + 1) * step);
+
+    const FloatT sample_val = std::round(val * output_scaling_inv);
+    const FloatT midpoint_interp_val =
+      std::round((val_next * output_scaling_inv + std::round(val * output_scaling_inv)) / 2);
+    const FloatT midpoint_val = std::round(val_midpoint * output_scaling_inv);
+    const FloatT midpoint_err = midpoint_interp_val - midpoint_val;
+    const FloatT bias = std::round(midpoint_err / 2);
+
+    lut[i] = static_cast<int16_t>(
+      std::min<FloatT>(std::max<FloatT>(sample_val - bias, table_min), table_max));
+  }
+
+  lut[nb_steps] = static_cast<int16_t>(std::min<FloatT>(
+    std::max<FloatT>(
+      std::round(LUTTransform<FloatT>(transform, transform_params, input_max) * output_scaling_inv),
+      table_min),
+    table_max));
+}
+
+template <typename T>
+inline typename std::enable_if<std::is_same<T, int16_t>::value, void>::type
+LUTPopulate(float input_scale, int32_t input_zero_point, float output_scale,
+            int32_t output_zero_point, float (*transform)(float), T *lut)
+{
+  LUTPopulateInt16<float>(input_scale, input_zero_point, output_scale, output_zero_point, transform,
+                          nullptr, lut);
+}
+
+} // namespace
+
+namespace luci_interpreter_pal
+{
+
+inline void Softmax(const SoftmaxParams &params, const int8_t *input_data, int8_t *output_data)
+{
+  arm_softmax_s8(input_data, params.num_rows, params.row_size, params.input_multiplier,
+                 params.input_left_shift, params.diff_min, output_data);
+}
+
+inline void Softmax(const SoftmaxParams &params, const int8_t *input_data, int16_t *output_data)
+{
+  arm_softmax_s8_s16(input_data, params.num_rows, params.row_size, params.input_multiplier,
+                     params.input_left_shift, params.diff_min, output_data);
+}
+
+inline void Softmax(const SoftmaxParams &params, const int16_t *input_data, int16_t *output_data)
+{
+  cmsis_nn_softmax_lut_s16 softmax_params{};
+
+  auto raw_exp_lut = std::make_unique<int16_t[]>(kInt16LUTArraySize);
+  auto one_over_one_plus_x_lut = std::make_unique<int16_t[]>(kInt16LUTArraySize);
+
+  // exp LUT only used on negative values
+  // we consider exp(-10.0) is insignificant to accumulation
+  const int32_t range = std::numeric_limits<int16_t>::max() - std::numeric_limits<int16_t>::min();
+
+  LUTPopulate<int16_t>(
+    10.0f / range, std::numeric_limits<int16_t>::max(), 2.0f / range, 0,
+    [](float value) { return std::exp(value); }, raw_exp_lut.get());
+
+  LUTPopulate<int16_t>(
+    1.0f / range, std::numeric_limits<int16_t>::min(), 2.0f / range, 0,
+    [](float value) { return 1.0f / (1.0f + value); }, one_over_one_plus_x_lut.get());
+
+  softmax_params.exp_lut = raw_exp_lut.get();
+  softmax_params.one_by_one_lut = one_over_one_plus_x_lut.get();
+
+  arm_softmax_s16(input_data, params.num_rows, params.row_size, params.input_multiplier,
+                  params.input_left_shift, &softmax_params, output_data);
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SOFTMAX_H
index 5110474..fc8b635 100644 (file)
@@ -1,34 +1,5 @@
 macro(initialize_pal)
-    nnas_find_package(TensorFlowSource EXACT 2.6.0 REQUIRED)
-    nnas_find_package(TensorFlowGEMMLowpSource EXACT 2.6.0 REQUIRED)
-    nnas_find_package(TensorFlowEigenSource EXACT 2.6.0 REQUIRED)
-    nnas_find_package(TensorFlowRuySource EXACT 2.6.0 REQUIRED)
-    nnas_find_package(CMSIS-NN EXACT 4.0.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 ()
-
-    if (NOT CMSISSource_FOUND)
-        message(STATUS "Skipping luci-interpreter: CMSISSource not found")
-        return()
-    endif ()
+    nnas_find_package(CMSIS-NN EXACT 4.1.0 REQUIRED)
 
     if (NOT CMSIS_NNSource_FOUND)
         message(STATUS "Skipping luci-interpreter: CMSIS-NN not found")
@@ -39,13 +10,7 @@ macro(initialize_pal)
 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})
+    target_include_directories(${TGT} PUBLIC ${LUCI_INTERPRETER_PAL_DIR})
 
     file(GLOB_RECURSE PAL_SOURCES "${CMSIS_NNSource_DIR}/Source/ActivationFunctions/*.c"
             "${CMSIS_NNSource_DIR}/Source/BasicMathFunctions/*.c"
@@ -57,27 +22,12 @@ macro(add_pal_to_target TGT)
             "${CMSIS_NNSource_DIR}/Source/PoolingFunctions/*.c"
             "${CMSIS_NNSource_DIR}/Source/ReshapeFunctions/*.c"
             "${CMSIS_NNSource_DIR}/Source/SoftmaxFunctions/*.c")
-
-    list(APPEND 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_cmsisnn_pal STATIC ${PAL_SOURCES})
     set_property(TARGET luci_interpreter_cmsisnn_pal PROPERTY POSITION_INDEPENDENT_CODE ON)
     target_include_directories(luci_interpreter_cmsisnn_pal PRIVATE
-            "${TensorFlowRuySource_DIR}"
-            "${TensorFlowGEMMLowpSource_DIR}"
-            "${TensorFlowEigenSource_DIR}"
-            "${TensorFlowSource_DIR}"
-            "${CMSIS_NNSource_DIR}"
-    )
-
-    set(CMSIS_PATH ${CMSISSource_DIR} CACHE INTERNAL "CMSIS_PATH")
+            "${CMSIS_NNSource_DIR}")
     add_subdirectory(${CMSIS_NNSource_DIR} ${CMAKE_CURRENT_BINARY_DIR}/CMSISNN)
-
     target_include_directories(luci_interpreter_cmsisnn_pal PUBLIC
-            "${CMSISSource_DIR}/CMSIS/DSP/Include"
-            "${CMSISSource_DIR}/CMSIS/Core/Include"
             "${CMSIS_NNSource_DIR}/Include")
-
     target_link_libraries(${TGT} PRIVATE luci_interpreter_cmsisnn_pal)
 endmacro()
diff --git a/onert-micro/luci-interpreter/pal/common/Broadcast.h b/onert-micro/luci-interpreter/pal/common/Broadcast.h
new file mode 100644 (file)
index 0000000..42cd01a
--- /dev/null
@@ -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 LUCI_INTERPRETER_BROADCAST_H
+#define LUCI_INTERPRETER_BROADCAST_H
+
+#include <functional>
+#include <luci_interpreter/core/Tensor.h>
+#include "ProcessBroadcastShapes.h"
+namespace luci_interpreter_pal
+{
+template <typename T>
+inline void
+BroadcastTISO4DSlow(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,
+                    std::function<const T &(const T &, const T &)> func)
+{
+  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);
+
+  // 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] = func(input1_data[subscriptToIndex(desc1, b, y, x, c)],
+                                                 input2_data[subscriptToIndex(desc2, b, y, x, c)]);
+        }
+      }
+    }
+  }
+}
+} // namespace luci_interpreter_pal
+#endif // LUCI_INTERPRETER_BROADCAST_H
index 57f9b10..fa2d273 100644 (file)
@@ -18,9 +18,7 @@
 #ifndef LUCI_INTERPRETER_PAL_ADD_COMMON_H
 #define LUCI_INTERPRETER_PAL_ADD_COMMON_H
 
-#include "Params.h"
-#include "PALUtils.h"
-#include "ProcessBroadcastShapes.h"
+#include "PALArithmeticOpCommon.h"
 
 namespace luci_interpreter_pal
 {
@@ -30,12 +28,7 @@ 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);
+  ArithmeticOp<T, AddFn<T>>(params, flat_size, input1_data, input2_data, output_data);
 }
 
 template <typename T>
@@ -45,48 +38,8 @@ BroadcastAdd4DSlow(const ArithmeticParams &params,
                    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);
-        }
-      }
-    }
-  }
+  BroadcastArithmeticOp4DSlow<T, AddFn<T>>(params, input1_shape, input1_data, input2_shape,
+                                           input2_data, output_shape, output_data);
 }
 
 } // namespace luci_interpreter_pal
diff --git a/onert-micro/luci-interpreter/pal/common/PALArithmeticOpCommon.h b/onert-micro/luci-interpreter/pal/common/PALArithmeticOpCommon.h
new file mode 100644 (file)
index 0000000..69587e5
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2024 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_ARITHMETICOPCOMMON_H
+#define LUCI_INTERPRETER_PAL_ARITHMETICOPCOMMON_H
+
+#include "Params.h"
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+
+namespace luci_interpreter_pal
+{
+
+template <typename T> struct AddFn
+{
+  T operator()(T lhs, T rhs) { return lhs + rhs; }
+};
+template <typename T> struct SubFn
+{
+  T operator()(T lhs, T rhs) { return lhs - rhs; }
+};
+template <typename T> struct MulFn
+{
+  T operator()(T lhs, T rhs) { return lhs * rhs; }
+};
+template <typename T> struct DivFn
+{
+  T operator()(T lhs, T rhs) { return lhs / rhs; }
+};
+
+// TODO: check if there real activation value
+template <typename T, typename Fn>
+inline void ArithmeticOp(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);
+
+  Fn func;
+  for (int i = 0; i < flat_size; ++i)
+    output_data[i] =
+      std::min(std::max(func(input1_data[i], input2_data[i]), activation_min), activation_max);
+}
+
+template <typename T, typename Fn>
+inline void ArithmeticOpScalar(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(func(input_data[i], scalar_value), activation_min), activation_max);
+}
+
+template <typename T, typename Fn>
+inline void BroadcastArithmeticOp4DSlow(
+  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.
+  Fn func;
+  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(func(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_ARITHMETICOPCOMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALBatchToSpaceND.h b/onert-micro/luci-interpreter/pal/common/PALBatchToSpaceND.h
new file mode 100644 (file)
index 0000000..67d95f9
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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_BATCH_TO_SPACE_ND_COMMON_H
+#define LUCI_INTERPRETER_PAL_BATCH_TO_SPACE_ND_COMMON_H
+
+#include "Params.h"
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+namespace
+{
+inline luci_interpreter::RuntimeShape
+extendShapeBatchToSpace(const luci_interpreter::RuntimeShape &shape)
+{
+  if (shape.dimensionsCount() == 4)
+  {
+    return shape;
+  }
+  luci_interpreter::RuntimeShape new_shape(4, 1);
+  new_shape.setDim(0, shape.dims(0));
+  new_shape.setDim(1, shape.dims(1));
+  new_shape.setDim(3, shape.dims(2));
+  return new_shape;
+}
+} // namespace
+
+template <typename T>
+inline void BatchToSpaceND(
+  const luci_interpreter::RuntimeShape &unextended_input1_shape, const T *input1_data,
+  const luci_interpreter::RuntimeShape &unextended_input2_shape, const int32_t *block_shape_data,
+  const luci_interpreter::RuntimeShape &unextended_input3_shape, const int32_t *crops_data,
+  const luci_interpreter::RuntimeShape &unextended_output_shape, T *output_data)
+{
+  const luci_interpreter::RuntimeShape input1_shape =
+    extendShapeBatchToSpace(unextended_input1_shape);
+  const luci_interpreter::RuntimeShape output_shape =
+    extendShapeBatchToSpace(unextended_output_shape);
+
+  const int output_width = output_shape.dims(2);
+  const int output_height = output_shape.dims(1);
+  const int output_batch_size = output_shape.dims(0);
+
+  const int depth = input1_shape.dims(3);
+  const int input_width = input1_shape.dims(2);
+  const int input_height = input1_shape.dims(1);
+  const int input_batch_size = input1_shape.dims(0);
+
+  const int block_shape_height = block_shape_data[0];
+  const int block_shape_width =
+    unextended_input1_shape.dimensionsCount() == 4 ? block_shape_data[1] : 1;
+  const int crops_top = crops_data[0];
+  const int crops_left = unextended_input1_shape.dimensionsCount() == 4 ? crops_data[2] : 0;
+  for (int in_batch = 0; in_batch < input_batch_size; ++in_batch)
+  {
+    const int out_batch = in_batch % output_batch_size;
+    const int spatial_offset = in_batch / output_batch_size;
+    for (int in_h = 0; in_h < input_height; ++in_h)
+    {
+      const int out_h = in_h * block_shape_height + spatial_offset / block_shape_width - crops_top;
+      if (out_h < 0 || out_h >= output_height)
+      {
+        continue;
+      }
+      for (int in_w = 0; in_w < input_width; ++in_w)
+      {
+        const int out_w =
+          in_w * block_shape_width + spatial_offset % block_shape_width - crops_left;
+
+        if (out_w < 0 || out_w >= output_width)
+        {
+          continue;
+        }
+        T *out = output_data + offset(output_shape.dimsData(), out_batch, out_h, out_w, 0);
+        const T *in = input1_data + offset(input1_shape.dimsData(), in_batch, in_h, in_w, 0);
+        memcpy(out, in, depth * sizeof(T));
+      }
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_BATCH_TO_SPACE_ND_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALBinaryOpCommon.h b/onert-micro/luci-interpreter/pal/common/PALBinaryOpCommon.h
new file mode 100644 (file)
index 0000000..615c098
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2024 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_BINARYOPCOMMON_H
+#define LUCI_INTERPRETER_PAL_BINARYOPCOMMON_H
+
+#include "Params.h"
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+
+namespace luci_interpreter_pal
+{
+
+template <typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
+struct FloorDivFn
+{
+  T operator()(T lhs, T rhs)
+  {
+    return std::floor(static_cast<double>(lhs) / static_cast<double>(rhs));
+  }
+};
+template <typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
+struct FloorModFn
+{
+  T operator()(T lhs, T rhs)
+  {
+    T trunc_mod = std::fmod(lhs, rhs);
+    return (trunc_mod != 0) && ((rhs < 0) != (trunc_mod < 0)) ? (trunc_mod + rhs) : trunc_mod;
+  }
+};
+template <typename T> struct MaximumFn
+{
+  T operator()(T lhs, T rhs) { return std::max(lhs, rhs); }
+};
+template <typename T> struct MinimumFn
+{
+  T operator()(T lhs, T rhs) { return std::min(lhs, rhs); }
+};
+
+// TODO: check if there real activation value
+template <typename T, typename Fn>
+inline void BinaryOp(const int flat_size, const T *input1_data, const T *input2_data,
+                     T *output_data)
+{
+  Fn func;
+  for (int i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = func(input1_data[i], input2_data[i]);
+  }
+}
+
+template <typename T, typename Fn>
+inline void BroadcastBinaryOp4DSlow(const luci_interpreter::RuntimeShape &input1_shape,
+                                    const float *input1_data,
+                                    const luci_interpreter::RuntimeShape &input2_shape,
+                                    const float *input2_data,
+                                    const luci_interpreter::RuntimeShape &output_shape,
+                                    float *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);
+
+  // 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.
+
+  Fn func;
+  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] = func(input1_data[subscriptToIndex(desc1, b, y, x, c)],
+                                                 input2_data[subscriptToIndex(desc2, b, y, x, c)]);
+        }
+      }
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_BINARYOPCOMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALBroadcastTo.h b/onert-micro/luci-interpreter/pal/common/PALBroadcastTo.h
new file mode 100644 (file)
index 0000000..5f57c53
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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_BROADCAST_TO_COMMON_H
+#define LUCI_INTERPRETER_PAL_BROADCAST_TO_COMMON_H
+
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+template <int N>
+void BroadcastImpl(const NdArrayDesc<N> &input_desc, const uint8_t *input_data,
+                   const NdArrayDesc<N> &output_desc, uint8_t *output_data, int indexes[N], int dim,
+                   const int last_broadcasting_dim, const uint32_t type_size)
+{
+  // Copy data from input to output.
+  if (dim == last_broadcasting_dim)
+  {
+    int copy_size = output_desc.strides[dim] * type_size;
+    const uint8_t *data_src = input_data + subscriptToIndex(input_desc, indexes) * type_size;
+    uint8_t *data_dst = output_data + subscriptToIndex(output_desc, indexes) * type_size;
+    for (int i = 0; i < output_desc.extents[dim]; ++i, data_dst += copy_size)
+    {
+      memcpy(data_dst, data_src, copy_size);
+    }
+    return;
+  }
+
+  // Recursive call to find the next broadcasting.
+  for (indexes[dim] = 0; indexes[dim] < input_desc.extents[dim]; ++indexes[dim])
+  {
+    BroadcastImpl<N>(input_desc, input_data, output_desc, output_data, indexes, dim + 1,
+                     last_broadcasting_dim, type_size);
+  }
+
+  // Duplicate data in output tensor.
+  indexes[dim] = 0;
+  if (input_desc.extents[dim] != output_desc.extents[dim])
+  {
+    int copy_size = output_desc.strides[dim] * type_size;
+    uint8_t *data_src = output_data + subscriptToIndex(output_desc, indexes) * type_size;
+    uint8_t *data_dst = data_src + copy_size;
+    for (int i = 1; i < output_desc.extents[dim]; ++i, data_dst += copy_size)
+    {
+      memcpy(data_dst, data_src, copy_size);
+    }
+  }
+}
+
+template <int N>
+inline void BroadcastTo(const luci_interpreter::RuntimeShape &unextended_input_shape,
+                        const uint8_t *input_data,
+                        const luci_interpreter::RuntimeShape &unextended_output_shape,
+                        uint8_t *output_data, luci_interpreter::DataType data_type)
+{
+  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);
+
+  // Get the last dimension has broadcasting. At this dimension, the data is
+  // copied from input tensor to output tensor.
+  int last_broadcast_dim = -1;
+  for (int i = N - 1; i >= 0; --i)
+  {
+    if (input_desc.extents[i] != output_desc.extents[i])
+    {
+      last_broadcast_dim = i;
+      break;
+    }
+  }
+
+  // If non-broadcasting, just copy data from input to output tensor.
+  if (last_broadcast_dim == -1)
+  {
+    memcpy(output_data, input_data, unextended_input_shape.flatSize() * sizeof(data_type));
+    return;
+  }
+
+  // Broadcasting using memcpy.
+  int indexes[N] = {0};
+  BroadcastImpl<N>(input_desc, input_data, output_desc, output_data, indexes, 0, last_broadcast_dim,
+                   luci_interpreter::size(data_type));
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_BROADCAST_TO_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALCeil.h b/onert-micro/luci-interpreter/pal/common/PALCeil.h
new file mode 100644 (file)
index 0000000..7e54ce3
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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_CEIL_COMMON_H
+#define LUCI_INTERPRETER_PAL_CEIL_COMMON_H
+
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+inline void Ceil(const int32_t flat_size, const float *input_data, float *output_data)
+{
+  for (int i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = std::ceil(input_data[i]);
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_BATCH_TO_SPACE_ND_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALCosCommon.h b/onert-micro/luci-interpreter/pal/common/PALCosCommon.h
new file mode 100644 (file)
index 0000000..3ff3ee3
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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_COS_COMMON_H
+#define LUCI_INTERPRETER_PAL_COS_COMMON_H
+
+#include "PALUtils.h"
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+inline void Cos(const int flat_size, const float *input_data, float *output_data)
+{
+  for (int i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = std::cos(input_data[i]);
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_COS_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALDepthToSpace.h b/onert-micro/luci-interpreter/pal/common/PALDepthToSpace.h
new file mode 100644 (file)
index 0000000..5f98c88
--- /dev/null
@@ -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_INTERPRETER_PAL_DEPTH_TO_SPACE_COMMON_H
+#define LUCI_INTERPRETER_PAL_DEPTH_TO_SPACE_COMMON_H
+
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+template <typename T>
+inline void
+DepthToSpace(const int32_t block_size, const luci_interpreter::RuntimeShape &unextended_input_shape,
+             const T *input_data, const luci_interpreter::RuntimeShape &unextended_output_shape,
+             T *output_data)
+{
+  const luci_interpreter::RuntimeShape input_shape =
+    luci_interpreter::RuntimeShape::extendedShape(4, unextended_input_shape);
+  const luci_interpreter::RuntimeShape output_shape =
+    luci_interpreter::RuntimeShape::extendedShape(4, unextended_output_shape);
+
+  const int output_depth = output_shape.dims(3);
+  const int output_width = output_shape.dims(2);
+  const int output_height = output_shape.dims(1);
+  const int output_batch = output_shape.dims(0);
+
+  for (int out_b = 0; out_b < output_batch; ++out_b)
+  {
+    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)
+        {
+          const int in_d =
+            out_d + ((out_h % block_size) * block_size + out_w % block_size) * output_depth;
+
+          const int in_w = out_w / block_size;
+          const int in_h = out_h / block_size;
+          const int in_b = out_b;
+
+          const int input_index = offset(input_shape.dimsData(), in_b, in_h, in_w, in_d);
+          const int output_index = offset(output_shape.dimsData(), out_b, out_h, out_w, out_d);
+
+          output_data[output_index] = input_data[input_index];
+        }
+      }
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_DEPTH_TO_SPACE_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALDepthwiseConv2DCommon.h b/onert-micro/luci-interpreter/pal/common/PALDepthwiseConv2DCommon.h
new file mode 100644 (file)
index 0000000..e9a1c08
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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_DEPTHWISE_CONV2D_COMMON_H
+#define LUCI_INTERPRETER_PAL_DEPTHWISE_CONV2D_COMMON_H
+#include "Params.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+static inline void DepthwiseConv2D(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 int depth_multiplier = params.depth_multiplier;
+  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 input_height = input_shape[1];
+  const int input_width = input_shape[2];
+  const int input_depth = input_shape[3];
+  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 b = 0; b < batches; ++b)
+  {
+    for (int out_y = 0; out_y < output_height; ++out_y)
+    {
+      for (int out_x = 0; out_x < output_width; ++out_x)
+      {
+        for (int ic = 0; ic < input_depth; ++ic)
+        {
+          for (int m = 0; m < depth_multiplier; m++)
+          {
+            const int oc = m + ic * depth_multiplier;
+            const int in_x_origin = (out_x * stride_width) - pad_width;
+            const int in_y_origin = (out_y * stride_height) - pad_height;
+            float total = 0.f;
+            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;
+                // 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))
+                {
+                  float input_value = input_data[offset(input_shape, b, in_y, in_x, ic)];
+                  float filter_value = filter_data[offset(filter_shape, 0, filter_y, filter_x, oc)];
+                  total += (input_value * filter_value);
+                }
+              }
+            }
+            float bias_value = 0.0f;
+            if (bias_data)
+            {
+              bias_value = bias_data[oc];
+            }
+            output_data[offset(output_shape, b, out_y, out_x, oc)] = activationFunctionWithMinMax(
+              total + bias_value, output_activation_min, output_activation_max);
+          }
+        }
+      }
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_DEPTHWISE_CONV2D_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALDequantize.h b/onert-micro/luci-interpreter/pal/common/PALDequantize.h
new file mode 100644 (file)
index 0000000..d967ae7
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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_DEQUANTIZE_H
+#define LUCI_INTERPRETER_PAL_DEQUANTIZE_H
+
+#include "Params.h"
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+template <typename InputT, typename OutputT>
+inline void Dequantize(const QuantizationParams &op_params, const int flat_size,
+                       const InputT *input_data, OutputT *output_data)
+{
+  const int32_t zero_point = op_params.zero_point;
+  const double scale = op_params.scale;
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    const int32_t val = input_data[i];
+    const OutputT result = static_cast<OutputT>(scale * (val - zero_point));
+    output_data[i] = result;
+  }
+}
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_QUANTIZE_H
index cca85cd..7d2907a 100644 (file)
@@ -18,9 +18,7 @@
 #ifndef LUCI_INTERPRETER_PAL_DIV_COMMON_H
 #define LUCI_INTERPRETER_PAL_DIV_COMMON_H
 
-#include "Params.h"
-#include "PALUtils.h"
-#include "ProcessBroadcastShapes.h"
+#include "PALArithmeticOpCommon.h"
 
 namespace luci_interpreter_pal
 {
@@ -28,24 +26,14 @@ 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);
+  ArithmeticOp<T, DivFn<T>>(params, flat_size, input1_data, input2_data, output_data);
 }
 
 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);
+  ArithmeticOpScalar<T, DivFn<T>>(params, flat_size, input_data, scalar_value, output_data);
 }
 
 template <typename T>
@@ -55,59 +43,8 @@ BroadcastDiv4DSlow(const ArithmeticParams &params,
                    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);
-        }
-      }
-    }
-  }
+  BroadcastArithmeticOp4DSlow<T, DivFn<T>>(params, input1_shape, input1_data, input2_shape,
+                                           input2_data, output_shape, output_data);
 }
 
 } // namespace luci_interpreter_pal
diff --git a/onert-micro/luci-interpreter/pal/common/PALFloorCommon.h b/onert-micro/luci-interpreter/pal/common/PALFloorCommon.h
new file mode 100644 (file)
index 0000000..e833478
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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_FLOOR_COMMON_H
+#define LUCI_INTERPRETER_PAL_FLOOR_COMMON_H
+
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+inline void Floor(const luci_interpreter::RuntimeShape &input_shape, const float *input_data,
+                  const luci_interpreter::RuntimeShape &output_shape, float *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++)
+  {
+    int offset = i;
+    output_data[offset] = std::floor(input_data[offset]);
+  }
+}
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_FLOOR_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALFloorDivCommon.h b/onert-micro/luci-interpreter/pal/common/PALFloorDivCommon.h
new file mode 100644 (file)
index 0000000..a7ba1a3
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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_FLOORDIV_COMMON_H
+#define LUCI_INTERPRETER_PAL_FLOORDIV_COMMON_H
+
+#include "PALBinaryOpCommon.h"
+
+namespace luci_interpreter_pal
+{
+inline void FloorDiv(const int flat_size, const float *input1_data, const float *input2_data,
+                     float *output_data)
+{
+  BinaryOp<float, FloorDivFn<float>>(flat_size, input1_data, input2_data, output_data);
+}
+
+inline void
+
+BroadcastFloorDiv4DSlow(const luci_interpreter::RuntimeShape &input1_shape,
+                        const float *input1_data,
+                        const luci_interpreter::RuntimeShape &input2_shape,
+                        const float *input2_data,
+                        const luci_interpreter::RuntimeShape &output_shape, float *output_data)
+{
+  BroadcastBinaryOp4DSlow<float, FloorDivFn<float>>(input1_shape, input1_data, input2_shape,
+                                                    input2_data, output_shape, output_data);
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_FLOORDIV_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALFloorModCommon.h b/onert-micro/luci-interpreter/pal/common/PALFloorModCommon.h
new file mode 100644 (file)
index 0000000..dfb6725
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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_FLOORMOD_COMMON_H
+#define LUCI_INTERPRETER_PAL_FLOORMOD_COMMON_H
+
+#include "PALBinaryOpCommon.h"
+
+namespace luci_interpreter_pal
+{
+inline void FloorMod(const int flat_size, const float *input1_data, const float *input2_data,
+                     float *output_data)
+{
+  BinaryOp<float, FloorModFn<float>>(flat_size, input1_data, input2_data, output_data);
+}
+
+inline void
+
+BroadcastFloorMod4DSlow(const luci_interpreter::RuntimeShape &input1_shape,
+                        const float *input1_data,
+                        const luci_interpreter::RuntimeShape &input2_shape,
+                        const float *input2_data,
+                        const luci_interpreter::RuntimeShape &output_shape, float *output_data)
+{
+  BroadcastBinaryOp4DSlow<float, FloorModFn<float>>(input1_shape, input1_data, input2_shape,
+                                                    input2_data, output_shape, output_data);
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_FLOORMOD_COMMON_H
index 14934cc..1468d81 100644 (file)
@@ -21,6 +21,8 @@
 #include "PALUtils.h"
 #include "Params.h"
 
+#include <type_traits>
+
 namespace luci_interpreter_pal
 {
 
@@ -28,7 +30,8 @@ template <typename InputType, typename WeightType, typename OutputType, typename
 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 *output_shape, OutputType *output_data,
+                           uint32_t output_dims_count, uint32_t weights_dims_count)
 {
   const int32_t input_offset = params.input_offset;
   const int32_t filter_offset = params.weights_offset;
@@ -38,9 +41,9 @@ inline void FullyConnected(const FullyConnectedParams &params, const int32_t *in
   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];
+  const int batches = flatSizeSkipDim(output_shape, output_dims_count - 1, output_dims_count);
+  const int output_depth = output_shape[output_dims_count - 1];
+  const int accum_depth = filter_shape[weights_dims_count - 1];
 
   for (int b = 0; b < batches; ++b)
   {
@@ -65,27 +68,40 @@ inline void FullyConnected(const FullyConnectedParams &params, const int32_t *in
     }
   }
 }
-template <>
+template <typename WeightType>
 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 WeightType *filter_data, const float *bias_data,
+                           const int32_t *output_shape, float *output_data,
+                           uint32_t output_dims_count, uint32_t weights_dims_count)
 {
   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];
+  const int batches = flatSizeSkipDim(output_shape, output_dims_count - 1, output_dims_count);
+  const int output_depth = output_shape[output_dims_count - 1];
+  const int accum_depth = filter_shape[weights_dims_count - 1];
 
   for (int b = 0; b < batches; ++b)
   {
+    const float *weight_scale_ptr = params.weights_scales;
     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];
+        auto input_value = input_data[b * accum_depth + d];
+        if (std::is_same<WeightType, float>::value)
+        {
+          total += input_value * filter_data[out_c * accum_depth + d];
+        }
+        else
+        {
+          const float filter_scale = *weight_scale_ptr;
+          const float filter_value =
+            static_cast<float>(filter_data[out_c * accum_depth + d]) * filter_scale;
+          total += input_value * filter_value;
+        }
       }
       float bias_value = 0.0f;
       if (bias_data)
@@ -94,6 +110,11 @@ inline void FullyConnected(const FullyConnectedParams &params, const int32_t *in
       }
       output_data[out_c + output_depth * b] =
         std::min(std::max(total + bias_value, output_activation_min), output_activation_max);
+      if (std::is_same<WeightType, int8_t>::value)
+      {
+        if (params.is_channel_wise_quant)
+          weight_scale_ptr++;
+      }
     }
   }
 }
diff --git a/onert-micro/luci-interpreter/pal/common/PALGatherND.h b/onert-micro/luci-interpreter/pal/common/PALGatherND.h
new file mode 100644 (file)
index 0000000..63aced3
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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_GATHER_ND_COMMON_H
+#define LUCI_INTERPRETER_PAL_GATHER_ND_COMMON_H
+
+#include "PALUtils.h"
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+constexpr int MAX_INDICES_ND = 5;
+
+template <typename ParamsT, typename IndicesT>
+inline void GatherND(luci_interpreter::RuntimeShape params_shape, const ParamsT *param_data,
+                     luci_interpreter::RuntimeShape indices_shape, const IndicesT *index_data,
+                     ParamsT *output_data)
+{
+  const int indices_dims = indices_shape.dimensionsCount();
+  const int indices_nd = indices_shape.dims(indices_dims - 1);
+  const int params_dims = params_shape.dimensionsCount();
+
+  int n_slices = 1;
+  for (int i = 0; i < indices_dims - 1; ++i)
+  {
+    n_slices *= indices_shape.dims(i);
+  }
+
+  // If indices[-1] == params.rank, fetch single elements.
+  // If indices[-1] < params.rank, fetch slices.
+  int slice_size = 1;
+  for (int i = indices_nd; i < params_dims; ++i)
+  {
+    slice_size *= params_shape.dims(i);
+  }
+
+  int params_flat_size = params_shape.flatSize();
+  int remain_flat_size = params_flat_size;
+
+  // Number of elements per dimension
+  int dims_to_count[MAX_INDICES_ND];
+  for (int i = 0; i < indices_nd; ++i)
+  {
+    dims_to_count[i] = remain_flat_size / params_shape.dims(i);
+    remain_flat_size = dims_to_count[i];
+  }
+
+  for (int i = 0; i < n_slices; ++i)
+  {
+    int from_pos = 0;
+    for (int j = 0; j < indices_nd; ++j)
+    {
+      int offset = i * indices_nd + j;
+      IndicesT index = index_data[offset];
+      from_pos += index * dims_to_count[j];
+    }
+    if (from_pos < 0 || from_pos + slice_size > params_flat_size)
+    {
+      assert(false && "GatherND error");
+      return;
+    }
+    std::memcpy(output_data + i * slice_size, param_data + from_pos, sizeof(ParamsT) * slice_size);
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_GATHER_ND_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALL2Normalize.h b/onert-micro/luci-interpreter/pal/common/PALL2Normalize.h
new file mode 100644 (file)
index 0000000..f890bf0
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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_L2_NORMALIZE_COMMON_H
+#define LUCI_INTERPRETER_PAL_L2_NORMALIZE_COMMON_H
+
+#include "PALUtils.h"
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+inline void L2Normalization(const luci_interpreter::RuntimeShape &input_shape,
+                            const float *input_data,
+                            const luci_interpreter::RuntimeShape &output_shape, float *output_data,
+                            float epsilon = 1e-6)
+{
+  const int trailing_dim = input_shape.dimensionsCount() - 1;
+  const int outer_size =
+    flatSizeSkipDim(input_shape.dimsData(), trailing_dim, input_shape.dimensionsCount());
+  const int depth = MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim);
+  for (int i = 0; i < outer_size; ++i)
+  {
+    float squared_l2_norm = 0;
+    for (int c = 0; c < depth; ++c)
+    {
+      const float val = input_data[depth * i + c];
+      squared_l2_norm += val * val;
+    }
+    float l2_norm = std::sqrt(squared_l2_norm);
+    l2_norm = std::fmax(l2_norm, epsilon);
+    for (int c = 0; c < depth; ++c)
+    {
+      output_data[depth * i + c] = input_data[depth * i + c] / l2_norm;
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_L2_NORMALIZE_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALL2Pool2D.h b/onert-micro/luci-interpreter/pal/common/PALL2Pool2D.h
new file mode 100644 (file)
index 0000000..c58aae6
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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_L2_POOL_2D_COMMON_H
+#define LUCI_INTERPRETER_PAL_L2_POOL_2D_COMMON_H
+
+#include "Params.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+inline void L2Pool(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 = MatchingDim(input_shape, 0, output_shape, 0);
+  const int depth = MatchingDim(input_shape, 3, output_shape, 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 sum_squares = 0.f;
+          int 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 float val =
+                input_data[offset(input_shape.dimsData(), batch, in_y, in_x, channel)];
+              sum_squares += val * val;
+              filter_count++;
+            }
+          }
+          assert(filter_count != 0);
+          const float l2pool_result = std::sqrt(sum_squares / filter_count);
+          output_data[offset(output_shape.dimsData(), batch, out_y, out_x, channel)] =
+            activationFunctionWithMinMax(l2pool_result, params.float_activation_min,
+                                         params.float_activation_max);
+        }
+      }
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_L2_POOL_2D_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALLog.h b/onert-micro/luci-interpreter/pal/common/PALLog.h
new file mode 100644 (file)
index 0000000..3087038
--- /dev/null
@@ -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 LUCI_INTERPRETER_PAL_EXP_H
+#define LUCI_INTERPRETER_PAL_EXP_H
+
+#include "PALUtils.h"
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+inline void Log(const int flat_size, const float *input_data, float *output_data)
+{
+  for (int i = 0; i < flat_size; i++)
+  {
+    const float val = input_data[i];
+    const float result = std::log(val);
+    output_data[i] = result;
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_EXP_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALLogSoftmax.h b/onert-micro/luci-interpreter/pal/common/PALLogSoftmax.h
new file mode 100644 (file)
index 0000000..13bb0e5
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_LOG_SOFTMAX_COMMON_H
+#define LUCI_INTERPRETER_PAL_LOG_SOFTMAX_COMMON_H
+
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+inline void LogSoftmax(const luci_interpreter::RuntimeShape &input_shape, const float *input_data,
+                       const luci_interpreter::RuntimeShape &output_shape, float *output_data)
+{
+  const int trailing_dim = input_shape.dimensionsCount() - 1;
+  const int outer_size =
+    flatSizeSkipDim(input_shape.dimsData(), trailing_dim, input_shape.dimensionsCount());
+  const int depth = MatchingDim(input_shape, trailing_dim, output_shape, 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:
+    // log(exp(x[i])/sum(exp(x[i]))) == log(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)
+    {
+      sum += std::exp(input_data[i * depth + c] - max);
+    }
+
+    // Compute result.
+    const float log_sum = std::log(sum);
+    for (int c = 0; c < depth; ++c)
+    {
+      output_data[i * depth + c] = input_data[i * depth + c] - max - log_sum;
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_LOG_SOFTMAX_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALLogicalNotCommon.h b/onert-micro/luci-interpreter/pal/common/PALLogicalNotCommon.h
new file mode 100644 (file)
index 0000000..446c59f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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_NOT_COMMON_H
+#define LUCI_INTERPRETER_PAL_LOGICAL_NOT_COMMON_H
+
+namespace luci_interpreter_pal
+{
+
+inline void LogicalNot(const int flat_size, const bool *input_data, bool *output_data)
+{
+  for (int i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = !input_data[i];
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_LOGICAL_NOT_COMMON_H
index 034319b..ab40dcc 100644 (file)
@@ -81,66 +81,6 @@ inline void MaxPool(const PoolParams &params, const luci_interpreter::RuntimeSha
   }
 }
 
-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/PALMaximumCommon.h b/onert-micro/luci-interpreter/pal/common/PALMaximumCommon.h
new file mode 100644 (file)
index 0000000..9bf6a68
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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_MAXIMUM_COMMON_H
+#define LUCI_INTERPRETER_PAL_MAXIMUM_COMMON_H
+
+#include "PALBinaryOpCommon.h"
+
+namespace luci_interpreter_pal
+{
+inline void Maximum(const int flat_size, const float *input1_data, const float *input2_data,
+                    float *output_data)
+{
+  BinaryOp<float, MaximumFn<float>>(flat_size, input1_data, input2_data, output_data);
+}
+
+inline void
+BroadcastMaximum4DSlow(const luci_interpreter::RuntimeShape &input1_shape, const float *input1_data,
+                       const luci_interpreter::RuntimeShape &input2_shape, const float *input2_data,
+                       const luci_interpreter::RuntimeShape &output_shape, float *output_data)
+{
+  BroadcastBinaryOp4DSlow<float, MaximumFn<float>>(input1_shape, input1_data, input2_shape,
+                                                   input2_data, output_shape, output_data);
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_MAXIMUM_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALMean.h b/onert-micro/luci-interpreter/pal/common/PALMean.h
new file mode 100644 (file)
index 0000000..f2926af
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * 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_MEAN_COMMON_H
+#define LUCI_INTERPRETER_PAL_MEAN_COMMON_H
+
+#include "Params.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_axis,
+                        int *out_num_axis)
+{
+  *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;
+}
+
+// A generic reduce method that can be used for reduce_sum, reduce_mean, etc.
+// This method iterates through input data and reduce elements along the
+// dimensions given in axis.
+template <typename In, typename Out>
+inline bool reduce(const In *input_data, const int *input_dims, const int *,
+                   const int input_num_dims, const int, const int *axis, const int num_axis,
+                   int *input_iter, Out reducer(Out, const In), Out *output_data)
+{
+  // Reset input iterator.
+  for (int idx = 0; idx < input_num_dims; ++idx)
+  {
+    input_iter[idx] = 0;
+  }
+  // Iterate through input_data.
+  do
+  {
+    size_t input_offset = reducedOutputOffset(input_num_dims, input_dims, input_iter, 0, nullptr);
+    size_t output_offset =
+      reducedOutputOffset(input_num_dims, input_dims, input_iter, num_axis, axis);
+    output_data[output_offset] = reducer(output_data[output_offset], input_data[input_offset]);
+  } while (nextIndex(input_num_dims, input_dims, input_iter));
+  return true;
+}
+
+// This method expects that output_data has been initialized.
+template <typename In, typename Out>
+inline bool reduceSumImpl(const In *input_data, const int *input_dims, const int *output_dims,
+                          const int input_num_dims, const int output_num_dims, const int *axis,
+                          const int num_axis, int *input_iter, Out *output_data)
+{
+  auto reducer = [](const Out current, const In in) -> Out {
+    const Out actual_in = static_cast<Out>(in);
+    return current + actual_in;
+  };
+  return reduce<In, Out>(input_data, input_dims, output_dims, input_num_dims, output_num_dims, axis,
+                         num_axis, input_iter, reducer, output_data);
+}
+} // namespace
+
+template <typename T, typename U>
+inline bool Mean(const T *input_data, const int *input_dims, const int input_num_dims,
+                 T *output_data, const int *output_dims, const int output_num_dims, const int *axis,
+                 const int num_axis_dimensions, bool, int *temp_index, int *resolved_axis,
+                 U *temp_sum)
+{
+  // Reset output data.
+  size_t num_outputs = 1;
+  for (int idx = 0; idx < output_num_dims; ++idx)
+  {
+    size_t current = static_cast<size_t>(output_dims[idx]);
+    // Overflow prevention.
+    if (num_outputs > std::numeric_limits<size_t>::max() / current)
+    {
+      return false;
+    }
+    num_outputs *= current;
+  }
+  for (size_t idx = 0; idx < num_outputs; ++idx)
+  {
+    output_data[idx] = T();
+    temp_sum[idx] = U();
+  }
+
+  // Resolve axis.
+  int num_resolved_axis = 0;
+  if (!resolveAxis(input_num_dims, axis, num_axis_dimensions, resolved_axis, &num_resolved_axis))
+  {
+    return false;
+  }
+
+  if (!reduceSumImpl<T, U>(input_data, input_dims, output_dims, input_num_dims, output_num_dims,
+                           resolved_axis, num_resolved_axis, temp_index, temp_sum))
+  {
+    return false;
+  }
+
+  // Calculate mean by dividing output_data by num of aggregated element.
+  size_t num_elements_in_axis = 1;
+  for (int idx = 0; idx < num_resolved_axis; ++idx)
+  {
+    size_t current = static_cast<size_t>(input_dims[resolved_axis[idx]]);
+    // Overflow prevention.
+    if (current > (std::numeric_limits<size_t>::max() / num_elements_in_axis))
+    {
+      return false;
+    }
+    num_elements_in_axis *= current;
+  }
+
+  if (num_elements_in_axis > 0)
+  {
+    for (size_t idx = 0; idx < num_outputs; ++idx)
+    {
+      output_data[idx] = static_cast<T>(temp_sum[idx] / static_cast<U>(num_elements_in_axis));
+    }
+  }
+  return true;
+}
+
+inline void Mean(const MeanParams &op_params,
+                 const luci_interpreter::RuntimeShape &unextended_input_shape,
+                 const float *input_data,
+                 const luci_interpreter::RuntimeShape &unextended_output_shape, float *output_data)
+{
+  // Current implementation only supports dimension equals 4 and simultaneous
+  // reduction over width and height.
+  const luci_interpreter::RuntimeShape input_shape =
+    luci_interpreter::RuntimeShape::extendedShape(4, unextended_input_shape);
+  const luci_interpreter::RuntimeShape output_shape =
+    luci_interpreter::RuntimeShape::extendedShape(4, unextended_output_shape);
+
+  const int output_batch = output_shape.dims(0);
+  const int output_depth = output_shape.dims(3);
+
+  const int input_height = input_shape.dims(1);
+  const int input_width = input_shape.dims(2);
+
+  for (int out_b = 0; out_b < output_batch; ++out_b)
+  {
+    for (int out_d = 0; out_d < output_depth; ++out_d)
+    {
+      float value = 0;
+      for (int in_h = 0; in_h < input_height; ++in_h)
+      {
+        for (int in_w = 0; in_w < input_width; ++in_w)
+        {
+          value += input_data[offset(input_shape.dimsData(), out_b, in_h, in_w, out_d)];
+        }
+      }
+      output_data[offset(output_shape.dimsData(), out_b, 0, 0, out_d)] =
+        value / (input_width * input_height);
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_MEAN_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALMinimumCommon.h b/onert-micro/luci-interpreter/pal/common/PALMinimumCommon.h
new file mode 100644 (file)
index 0000000..f2fadcb
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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_MINIMUM_COMMON_H
+#define LUCI_INTERPRETER_PAL_MINIMUM_COMMON_H
+
+#include "PALBinaryOpCommon.h"
+
+namespace luci_interpreter_pal
+{
+inline void Minimum(const int flat_size, const float *input1_data, const float *input2_data,
+                    float *output_data)
+{
+  BinaryOp<float, MinimumFn<float>>(flat_size, input1_data, input2_data, output_data);
+}
+
+template <typename T>
+inline void
+BroadcastMinimum4DSlow(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)
+{
+  BroadcastBinaryOp4DSlow<float, MinimumFn<float>>(input1_shape, input1_data, input2_shape,
+                                                   input2_data, output_shape, output_data);
+}
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_MINIMUM_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALMirrorPad.h b/onert-micro/luci-interpreter/pal/common/PALMirrorPad.h
new file mode 100644 (file)
index 0000000..80fd484
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * 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_MIRROR_PAD_COMMON_H
+#define LUCI_INTERPRETER_PAL_MIRROR_PAD_COMMON_H
+
+#include "PALUtils.h"
+#include "Params.h"
+
+namespace luci_interpreter_pal
+{
+namespace
+{
+
+// Helper method that fills the left and right pads.
+template <typename T>
+inline void getPadding(const T *data, int offset, int64_t *left_pad, int64_t *right_pad)
+{
+  *left_pad = static_cast<int64_t>(*(data + offset * 2));
+  *right_pad = static_cast<int64_t>(*(data + offset * 2 + 1));
+}
+
+// Given dimension index and the left/right padding.
+// Returns the corresponding dimension in the input array.
+inline int getInputDimension(int padded_dimension, int left_pad, int right_pad, int input_dim_size,
+                             int offset)
+{
+  if (padded_dimension < left_pad)
+  {
+    const int original_ind = left_pad + offset - 1;
+    return original_ind - (std::min(padded_dimension, original_ind - offset));
+  }
+  padded_dimension -= left_pad;
+  if (padded_dimension >= input_dim_size)
+  {
+    padded_dimension -= input_dim_size;
+    const int original_ind = input_dim_size - (1 + offset);
+    return original_ind - std::min(padded_dimension, original_ind);
+  }
+  return padded_dimension;
+}
+
+// Given and index in output array, returns the index of the value
+// in input array.
+int getFlatIndex(int index, int num_dims, const luci_interpreter::DataType padding_matrix_type,
+                 const uint8_t *padding_matrix_data, const int32_t *input_dims,
+                 int *output_dims_num_elements, int *input_dims_num_elements, const int offset)
+{
+  int flat_index = 0;
+  int64_t left_pad = 0, right_pad = 0, dimension_index, index_in_input;
+
+  for (int i = 0; i < num_dims; ++i)
+  {
+    switch (padding_matrix_type)
+    {
+      case luci_interpreter::DataType::S32:
+        getPadding(luci_interpreter::kernels::getTensorData<int32_t>(padding_matrix_data), i,
+                   &left_pad, &right_pad);
+        break;
+      case luci_interpreter::DataType::S64:
+        getPadding(luci_interpreter::kernels::getTensorData<int64_t>(padding_matrix_data), i,
+                   &left_pad, &right_pad);
+        break;
+      default:
+        break;
+    }
+    dimension_index = index / output_dims_num_elements[i];
+
+    index_in_input = getInputDimension(dimension_index, left_pad, right_pad, input_dims[i], offset);
+
+    flat_index += index_in_input * (input_dims_num_elements)[i];
+    index %= output_dims_num_elements[i];
+  }
+
+  return flat_index;
+}
+
+} // namespace
+
+template <typename T>
+void MirrorPad(const luci_interpreter::DataType padding_matrix_type,
+               const uint8_t *padding_matrix_data, const int32_t *input_dims,
+               int *output_dims_num_elements, int *input_dims_num_elements, const T *input_data,
+               T *output_data, const int offset, const int num_dims, const int output_size)
+{
+  for (int i = 0; i < output_size; ++i)
+  {
+    output_data[i] =
+      input_data[getFlatIndex(i, num_dims, padding_matrix_type, padding_matrix_data, input_dims,
+                              output_dims_num_elements, input_dims_num_elements, offset)];
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_MIRROR_PAD_COMMON_H
index f171040..c20b2fd 100644 (file)
@@ -18,9 +18,7 @@
 #ifndef LUCI_INTERPRETER_PAL_MUL_COMMON_H
 #define LUCI_INTERPRETER_PAL_MUL_COMMON_H
 
-#include "Params.h"
-#include "PALUtils.h"
-#include "ProcessBroadcastShapes.h"
+#include "PALArithmeticOpCommon.h"
 
 namespace luci_interpreter_pal
 {
@@ -28,24 +26,14 @@ 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);
+  ArithmeticOp<T, MulFn<T>>(params, flat_size, input1_data, input2_data, output_data);
 }
 
 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);
+  ArithmeticOpScalar<T, MulFn<T>>(params, flat_size, input_data, scalar_value, output_data);
 }
 
 template <typename T>
@@ -55,59 +43,8 @@ BroadcastMul4DSlow(const ArithmeticParams &params,
                    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);
-        }
-      }
-    }
-  }
+  BroadcastArithmeticOp4DSlow<T, MulFn<T>>(params, input1_shape, input1_data, input2_shape,
+                                           input2_data, output_shape, output_data);
 }
 
 } // namespace luci_interpreter_pal
diff --git a/onert-micro/luci-interpreter/pal/common/PALPreluCommon.h b/onert-micro/luci-interpreter/pal/common/PALPreluCommon.h
new file mode 100644 (file)
index 0000000..b4ee7f1
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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"
+#include "Params.h"
+#include "ProcessBroadcastShapes.h"
+
+namespace luci_interpreter_pal
+{
+
+void BroadcastPrelu4DSlowFloat(const luci_interpreter::RuntimeShape &unextended_input1_shape,
+                               const float *input1_data,
+                               const luci_interpreter::RuntimeShape &unextended_input2_shape,
+                               const float *input2_data,
+                               const luci_interpreter::RuntimeShape &unextended_output_shape,
+                               float *output_data)
+{
+  const luci_interpreter::RuntimeShape output_shape =
+    luci_interpreter::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.dimsData(), 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] = in1_val >= 0.0f ? in1_val : in1_val * in2_val;
+        }
+      }
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_RELU_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALQuantize.h b/onert-micro/luci-interpreter/pal/common/PALQuantize.h
new file mode 100644 (file)
index 0000000..ad2f6ab
--- /dev/null
@@ -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.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_QUANTIZE_H
+#define LUCI_INTERPRETER_PAL_QUANTIZE_H
+
+#include "Params.h"
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+template <typename InputT, typename OutputT>
+inline void Quantize(const QuantizationParams &op_params, const int flat_size,
+                     const InputT *input_data, OutputT *output_data)
+{
+  const int32_t zero_point = op_params.zero_point;
+  const double scale = op_params.scale;
+  static constexpr int32_t min_val = std::numeric_limits<OutputT>::min();
+  static constexpr int32_t max_val = std::numeric_limits<OutputT>::max();
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    const InputT val = input_data[i];
+    int32_t unclamped =
+      static_cast<int32_t>(std::round(val / static_cast<float>(scale))) + zero_point;
+    int32_t clamped = std::min(std::max(unclamped, min_val), max_val);
+    output_data[i] = clamped;
+  }
+}
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_QUANTIZE_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALResizeNearestNeighbor.h b/onert-micro/luci-interpreter/pal/common/PALResizeNearestNeighbor.h
new file mode 100644 (file)
index 0000000..28959a2
--- /dev/null
@@ -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_PAL_RESIZE_NEAREST_NEIGHBOR_COMMON_H
+#define LUCI_INTERPRETER_PAL_RESIZE_NEAREST_NEIGHBOR_COMMON_H
+
+#include "Params.h"
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+inline int32_t getNearestNeighbor(const int input_value, const int32_t input_size,
+                                  const int32_t output_size, const bool align_corners,
+                                  const bool half_pixel_centers)
+{
+  const float scale = (align_corners && output_size > 1)
+                        ? (input_size - 1) / static_cast<float>(output_size - 1)
+                        : input_size / static_cast<float>(output_size);
+  const float offset = half_pixel_centers ? 0.5f : 0.0f;
+  int32_t output_value =
+    std::min(align_corners ? static_cast<int32_t>(std::round((input_value + offset) * scale))
+                           : static_cast<int32_t>(std::floor((input_value + offset) * scale)),
+             input_size - 1);
+  if (half_pixel_centers)
+  {
+    output_value = std::max(static_cast<int32_t>(0), output_value);
+  }
+  return output_value;
+}
+
+template <typename T>
+inline void
+ResizeNearestNeighbor(const ResizeNearestNeighborParams &op_params,
+                      const luci_interpreter::RuntimeShape &unextended_input_shape,
+                      const T *input_data, const luci_interpreter::RuntimeShape &output_size_shape,
+                      const int32_t *output_size_data,
+                      const luci_interpreter::RuntimeShape &unextended_output_shape, T *output_data)
+{
+  const luci_interpreter::RuntimeShape input_shape =
+    luci_interpreter::RuntimeShape::extendedShape(4, unextended_input_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);
+
+  int32_t output_height = output_size_data[0];
+  int32_t output_width = output_size_data[1];
+
+  const int col_offset = input_shape.dims(3);
+  const int row_offset = input_shape.dims(2) * col_offset;
+  const int batch_offset = input_shape.dims(1) * row_offset;
+
+  const T *input_ptr = input_data;
+  T *output_ptr = output_data;
+  for (int b = 0; b < batches; ++b)
+  {
+    for (int y = 0; y < output_height; ++y)
+    {
+      int32_t in_y = getNearestNeighbor(y, input_height, output_height, op_params.align_corners,
+                                        op_params.half_pixel_centers);
+      const T *y_input_ptr = input_ptr + in_y * row_offset;
+      for (int x = 0; x < output_width; ++x)
+      {
+        int32_t in_x = getNearestNeighbor(x, input_width, output_width, op_params.align_corners,
+                                          op_params.half_pixel_centers);
+        const T *x_input_ptr = y_input_ptr + in_x * col_offset;
+        memcpy(output_ptr, x_input_ptr, depth * sizeof(T));
+        output_ptr += depth;
+      }
+    }
+    input_ptr += batch_offset;
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_RESIZE_NEAREST_NEIGHBOR_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALRound.h b/onert-micro/luci-interpreter/pal/common/PALRound.h
new file mode 100644 (file)
index 0000000..33abab3
--- /dev/null
@@ -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_INTERPRETER_PAL_ROUND_COMMON_H
+#define LUCI_INTERPRETER_PAL_ROUND_COMMON_H
+
+namespace luci_interpreter_pal
+{
+
+inline float RoundToNearest(float value)
+{
+  auto floor_val = std::floor(value);
+  auto diff = value - floor_val;
+  if ((diff < 0.5f) || ((diff == 0.5f) && (static_cast<int>(floor_val) % 2 == 0)))
+  {
+    return floor_val;
+  }
+  else
+  {
+    return floor_val + 1.0f;
+  }
+}
+
+inline void Round(const int32_t flat_size, const float *input_data, float *output_data)
+{
+  for (int i = 0; i < flat_size; ++i)
+  {
+    // Note that this implementation matches that of tensorFlow tf.round
+    // and corresponds to the bankers rounding method.
+    // cfenv (for fesetround) is not yet supported universally on Android, so
+    // using a work around.
+    output_data[i] = RoundToNearest(input_data[i]);
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_ROUND_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALRsqrt.h b/onert-micro/luci-interpreter/pal/common/PALRsqrt.h
new file mode 100644 (file)
index 0000000..a8f4871
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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_RSQRT_COMMON_H
+#define LUCI_INTERPRETER_PAL_RSQRT_COMMON_H
+
+#include "PALUtils.h"
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+inline void Rsqrt(const int flat_size, const float *input_data, float *output_data)
+{
+  for (int i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = 1.f / std::sqrt(input_data[i]);
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_RSQRT_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALSVDFCommon.h b/onert-micro/luci-interpreter/pal/common/PALSVDFCommon.h
new file mode 100644 (file)
index 0000000..52cf8d9
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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_SVDF_COMMON_H
+#define LUCI_INTERPRETER_PAL_SVDF_COMMON_H
+
+#include "Params.h"
+
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+namespace
+{
+
+// Returns the floating point value for a fused activation:
+inline float activationValFloat(const circle::ActivationFunctionType act, float a)
+{
+  switch (act)
+  {
+    case circle::ActivationFunctionType_NONE:
+      return a;
+    case circle::ActivationFunctionType_RELU:
+      return std::max(0.0f, a);
+    case circle::ActivationFunctionType_RELU_N1_TO_1:
+      return std::max(-1.0f, std::min(a, 1.0f));
+    case circle::ActivationFunctionType_RELU6:
+      return std::max(0.0f, std::min(a, 6.0f));
+    case circle::ActivationFunctionType_TANH:
+      return std::tanh(a);
+    case circle::ActivationFunctionType_SIGN_BIT:
+      return std::signbit(a);
+    default:
+      assert(false && "Not supported");
+  }
+  return 0.0f; // To indicate an unsupported activation (i.e. when a new fused
+  // activation is added to the enum and not handled here).
+}
+
+static inline void
+applyTimeWeightsBiasAndActivation(int batch_size, int memory_size, int num_filters, int num_units,
+                                  int rank, const float *const weights_time_ptr,
+                                  const float *const bias_ptr,
+                                  circle::ActivationFunctionType activation, float *const state_ptr,
+                                  float *const scratch_ptr, float *const output_ptr)
+{
+  // Compute matmul(activation_state, weights_time).
+  for (int b = 0; b < batch_size; ++b)
+  {
+    // Perform batched vector dot product:
+    float *scratch_ptr_batch = scratch_ptr + b * num_filters;
+    const float *vector1_ptr = weights_time_ptr;
+    const float *vector2_ptr = state_ptr + b * memory_size * num_filters;
+    for (int i = 0; i < num_filters; ++i)
+    {
+      *scratch_ptr_batch = 0.f;
+      for (int j = 0; j < memory_size; ++j)
+      {
+        *scratch_ptr_batch += *vector1_ptr++ * *vector2_ptr++;
+      }
+      scratch_ptr_batch++;
+    }
+  }
+
+  // Initialize output with bias if provided.
+  if (bias_ptr)
+  {
+    // VectorBatchVectorAssign
+    for (int i = 0; i < batch_size; ++i)
+    {
+      float *output_data = output_ptr + i * num_units;
+      const float *bias_data = bias_ptr;
+      for (int j = 0; j < num_units; ++j)
+      {
+        *output_data++ = *bias_data++;
+      }
+    }
+  }
+  else
+  {
+    float *output_data = output_ptr;
+    for (int i = 0; i < batch_size * num_units; ++i)
+    {
+      *output_data++ = 0.0f;
+    }
+  }
+
+  // Reduction sum.
+  for (int b = 0; b < batch_size; ++b)
+  {
+    float *output_ptr_batch = output_ptr + b * num_units;
+    float *scratch_ptr_batch = scratch_ptr + b * num_filters;
+
+    // Reduction sum vector
+    for (int i = 0; i < num_units; ++i)
+    {
+      for (int j = 0; j < rank; j++)
+      {
+        output_ptr_batch[i] += *scratch_ptr_batch++;
+      }
+    }
+  }
+
+  // Apply activation.
+  for (int b = 0; b < batch_size; ++b)
+  {
+    float *output_ptr_batch = output_ptr + b * num_units;
+    for (int i = 0; i < num_units; ++i)
+    {
+      *output_ptr_batch = activationValFloat(activation, *output_ptr_batch);
+      ++output_ptr_batch;
+    }
+  }
+}
+
+} // namespace
+
+inline void SVDF(const float *input_data, const float *weights_feature_data,
+                 const float *weights_time_data, const float *bias_data, float *state_data,
+                 float *scratch_data, float *output_data, const int rank, const int input_size,
+                 const int batch_size, const int num_filters, const int num_units,
+                 const int memory_size, const circle::ActivationFunctionType activation)
+{
+  // Left shift the activation_state.
+  {
+    float *new_state_start = state_data;
+    const float *old_state_start = state_data + 1;
+    const float *old_state_end = 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 = weights_feature_data;
+    const float *vector = input_data;
+    float *result = &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;
+      }
+    }
+  }
+
+  applyTimeWeightsBiasAndActivation(batch_size, memory_size, num_filters, num_units, rank,
+                                    weights_time_data, bias_data, activation, state_data,
+                                    scratch_data, output_data);
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SVDF_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALSelectV2.h b/onert-micro/luci-interpreter/pal/common/PALSelectV2.h
new file mode 100644 (file)
index 0000000..52302b7
--- /dev/null
@@ -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 LUCI_INTERPRETER_PAL_SELECT_V2_COMMON_H
+#define LUCI_INTERPRETER_PAL_SELECT_V2_COMMON_H
+
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+
+namespace luci_interpreter_pal
+{
+
+template <typename D, typename T>
+void Select(const luci_interpreter::RuntimeShape &input_condition_shape,
+            const D *input_condition_data, const luci_interpreter::RuntimeShape &input_x_shape,
+            const T *input_x_data, const luci_interpreter::RuntimeShape &input_y_shape,
+            const T *input_y_data, const luci_interpreter::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 = input_condition_shape.flatSize();
+  }
+  for (int64_t i = 0; i < flatsize; ++i)
+  {
+    output_data[i] = input_condition_data[i] ? input_x_data[i] : input_y_data[i];
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SELECT_V2_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALSinCommon.h b/onert-micro/luci-interpreter/pal/common/PALSinCommon.h
new file mode 100644 (file)
index 0000000..617833e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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_SIN_COMMON_H
+#define LUCI_INTERPRETER_PAL_SIN_COMMON_H
+
+#include "PALUtils.h"
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+inline void Sin(const int flat_size, const float *input_data, float *output_data)
+{
+  for (int i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = std::sin(input_data[i]);
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SIN_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALSoftmax.h b/onert-micro/luci-interpreter/pal/common/PALSoftmax.h
deleted file mode 100644 (file)
index a677856..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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/PALSoftmaxCommon.h b/onert-micro/luci-interpreter/pal/common/PALSoftmaxCommon.h
new file mode 100644 (file)
index 0000000..a7ddadb
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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
+
+#include "Params.h"
+
+namespace luci_interpreter_pal
+{
+inline void Softmax(const SoftmaxParams &params, const float *input_data, float *output_data)
+{
+  const int outer_size = params.num_rows;
+  const int depth = params.row_size;
+  const double beta = params.beta;
+
+  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/PALSpaceToBatchND.h b/onert-micro/luci-interpreter/pal/common/PALSpaceToBatchND.h
new file mode 100644 (file)
index 0000000..80ed99c
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * 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_SPACE_TO_BATCH_ND_COMMON_H
+#define LUCI_INTERPRETER_PAL_SPACE_TO_BATCH_ND_COMMON_H
+
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+namespace
+{
+inline luci_interpreter::RuntimeShape
+extendShapeSpaceToBatch(const luci_interpreter::RuntimeShape &shape)
+{
+  if (shape.dimensionsCount() == 4)
+  {
+    return shape;
+  }
+  luci_interpreter::RuntimeShape new_shape(4, 1);
+  new_shape.setDim(0, shape.dims(0));
+  new_shape.setDim(1, shape.dims(1));
+  new_shape.setDim(3, shape.dims(2));
+  return new_shape;
+}
+} // namespace
+
+template <typename T>
+inline void SpaceToBatchND(
+  const int32_t pad_value, const luci_interpreter::RuntimeShape &unextended_input1_shape,
+  const T *input1_data, const luci_interpreter::RuntimeShape &unextended_input2_shape,
+  const int32_t *block_shape_data, const luci_interpreter::RuntimeShape &unextended_input3_shape,
+  const int32_t *paddings_data, const luci_interpreter::RuntimeShape &unextended_output_shape,
+  T *output_data)
+{
+  // Extends the input/output shape from 3D to 4D if needed, NHC -> NH1C.
+  const luci_interpreter::RuntimeShape input1_shape =
+    extendShapeSpaceToBatch(unextended_input1_shape);
+  const luci_interpreter::RuntimeShape output_shape =
+    extendShapeSpaceToBatch(unextended_output_shape);
+
+  const int depth = input1_shape.dims(3);
+  const int input_width = input1_shape.dims(2);
+  const int input_height = input1_shape.dims(1);
+  const int input_batch_size = input1_shape.dims(0);
+
+  const int output_width = output_shape.dims(2);
+  const int output_height = output_shape.dims(1);
+  const int output_batch_size = output_shape.dims(0);
+
+  const int block_shape_height = block_shape_data[0];
+  const int block_shape_width =
+    unextended_input1_shape.dimensionsCount() == 4 ? block_shape_data[1] : 1;
+  const int padding_top = paddings_data[0];
+  const int padding_left = unextended_input1_shape.dimensionsCount() == 4 ? paddings_data[2] : 0;
+
+  for (int out_b = 0; out_b < output_batch_size; ++out_b)
+  {
+    int input_batch = out_b % input_batch_size;
+    int shift_w = (out_b / input_batch_size) % block_shape_width;
+    int shift_h = (out_b / input_batch_size) / block_shape_width;
+    for (int out_h = 0; out_h < output_height; ++out_h)
+    {
+      for (int out_w = 0; out_w < output_width; ++out_w)
+      {
+        T *out = output_data + offset(output_shape.dimsData(), out_b, out_h, out_w, 0);
+        if (out_h * block_shape_height + shift_h < padding_top ||
+            out_h * block_shape_height + shift_h >= padding_top + input_height ||
+            out_w * block_shape_width + shift_w < padding_left ||
+            out_w * block_shape_width + shift_w >= padding_left + input_width)
+        {
+          // This may not execute correctly when pad_value != 0 and T != uint8.
+          memset(out, pad_value, depth * sizeof(T));
+        }
+        else
+        {
+          const T *in =
+            input1_data + offset(input1_shape.dimsData(), input_batch,
+                                 (out_h * block_shape_height + shift_h) - padding_top,
+                                 (out_w * block_shape_width + shift_w) - padding_left, 0);
+          memcpy(out, in, depth * sizeof(T));
+        }
+      }
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SPACE_TO_BATCH_ND_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALSpaceToDepth.h b/onert-micro/luci-interpreter/pal/common/PALSpaceToDepth.h
new file mode 100644 (file)
index 0000000..2b13a5a
--- /dev/null
@@ -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 LUCI_INTERPRETER_PAL_SPACE_TO_DEPTH_COMMON_H
+#define LUCI_INTERPRETER_PAL_SPACE_TO_DEPTH_COMMON_H
+
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+template <typename T>
+inline void
+SpaceToDepth(const int32_t block_size, const luci_interpreter::RuntimeShape &unextended_input_shape,
+             const T *input_data, const luci_interpreter::RuntimeShape &unextended_output_shape,
+             T *output_data)
+{
+  const luci_interpreter::RuntimeShape input_shape =
+    luci_interpreter::RuntimeShape::extendedShape(4, unextended_input_shape);
+  const luci_interpreter::RuntimeShape output_shape =
+    luci_interpreter::RuntimeShape::extendedShape(4, unextended_output_shape);
+
+  const int input_depth = input_shape.dims(3);
+  const int input_width = input_shape.dims(2);
+  const int input_height = input_shape.dims(1);
+  const int input_batch = input_shape.dims(0);
+
+  for (int in_b = 0; in_b < input_batch; ++in_b)
+  {
+    for (int in_h = 0; in_h < input_height; ++in_h)
+    {
+      for (int in_w = 0; in_w < input_width; ++in_w)
+      {
+        for (int in_d = 0; in_d < input_depth; ++in_d)
+        {
+          const int out_d =
+            in_d + ((in_h % block_size) * block_size + in_w % block_size) * input_depth;
+          const int out_w = in_w / block_size;
+          const int out_h = in_h / block_size;
+          const int out_b = in_b;
+
+          const int input_index = offset(input_shape.dimsData(), in_b, in_h, in_w, in_d);
+          const int output_index = offset(output_shape.dimsData(), out_b, out_h, out_w, out_d);
+
+          output_data[output_index] = input_data[input_index];
+        }
+      }
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SPACE_TO_DEPTH_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALSqrt.h b/onert-micro/luci-interpreter/pal/common/PALSqrt.h
new file mode 100644 (file)
index 0000000..5dd393a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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_SQRT_COMMON_H
+#define LUCI_INTERPRETER_PAL_SQRT_COMMON_H
+
+#include "PALUtils.h"
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+inline void Sqrt(const int flat_size, const float *input_data, float *output_data)
+{
+  for (int i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = std::sqrt(input_data[i]);
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SQRT_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALSquareCommon.h b/onert-micro/luci-interpreter/pal/common/PALSquareCommon.h
new file mode 100644 (file)
index 0000000..f5bc487
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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_SQUARE_COMMON_H
+#define LUCI_INTERPRETER_PAL_SQUARE_COMMON_H
+
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+inline void Square(const int flat_size, const float *input_data, float *output_data)
+{
+  for (int i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = input_data[i] * input_data[i];
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SQUARE_COMMON_H
diff --git a/onert-micro/luci-interpreter/pal/common/PALSquaredDifference.h b/onert-micro/luci-interpreter/pal/common/PALSquaredDifference.h
new file mode 100644 (file)
index 0000000..396267e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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_SQUARED_DIFFERENCE_COMMON_H
+#define LUCI_INTERPRETER_PAL_SQUARED_DIFFERENCE_COMMON_H
+
+#include "PALUtils.h"
+#include <cmath>
+
+namespace luci_interpreter_pal
+{
+
+inline void SquaredDifference(const int flat_size, const float *input_data_1,
+                              const float *input_data_2, float *output_data)
+{
+  for (int i = 0; i < flat_size; ++i)
+  {
+    float diff = input_data_1[i] - input_data_2[i];
+    output_data[i] = diff * diff;
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SQUARED_DIFFERENCE_COMMON_H
index faa94fd..825a9fd 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef LUCI_INTERPRETER_PAL_SUB_COMMON_H
 #define LUCI_INTERPRETER_PAL_SUB_COMMON_H
 
-#include "PALUtils.h"
+#include "PALArithmeticOpCommon.h"
 
 namespace luci_interpreter_pal
 {
@@ -25,12 +25,7 @@ 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);
+  ArithmeticOp<T, SubFn<T>>(params, flat_size, input1_data, input2_data, output_data);
 }
 
 template <typename T>
@@ -40,48 +35,8 @@ BroadcastSub4DSlow(const ArithmeticParams &params,
                    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);
-        }
-      }
-    }
-  }
+  BroadcastArithmeticOp4DSlow<T, SubFn<T>>(params, input1_shape, input1_data, input2_shape,
+                                           input2_data, output_shape, output_data);
 }
 
 } // namespace luci_interpreter_pal
diff --git a/onert-micro/luci-interpreter/pal/common/PALTransposeConv.h b/onert-micro/luci-interpreter/pal/common/PALTransposeConv.h
new file mode 100644 (file)
index 0000000..7aad34e
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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_CONV_H
+#define LUCI_INTERPRETER_PAL_TRANSPOSE_CONV_H
+
+#include "PALUtils.h"
+
+namespace luci_interpreter_pal
+{
+
+inline void TransposeConv(const ConvParams &params,
+                          const luci_interpreter::RuntimeShape &input_shape,
+                          const float *input_data,
+                          const luci_interpreter::RuntimeShape &filter_shape,
+                          const float *filter_data,
+                          const luci_interpreter::RuntimeShape &bias_shape, const float *bias_data,
+                          const luci_interpreter::RuntimeShape &output_shape, float *output_data)
+{
+  const int stride_width = params.stride_width;
+  const int stride_height = params.stride_height;
+  const int pad_width = params.padding_values.width;
+  const int pad_height = params.padding_values.height;
+
+  const int batches = input_shape.dims(0);
+  const int input_depth = input_shape.dims(3);
+  const int output_depth = filter_shape.dims(0);
+  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 output_height = output_shape.dims(1);
+  const int output_width = output_shape.dims(2);
+  const float output_activation_min = params.float_activation_min;
+  const float output_activation_max = params.float_activation_max;
+
+  // Although transpose convolution simplifies to convolution with transposed
+  // weights for strides of 1, non-unitary striding complicates matters. To
+  // keep this reference implementation as clear as possible, we use a
+  // "scatter" access pattern, where we loop through all the input elements,
+  // computing their influence on the output, rather than looping through the
+  // output elements in the typical "gather" access pattern of a conv. We
+  // therefore must initialize the output array to zero.
+  const int num_elements = output_shape.flatSize();
+  for (int i = 0; i < num_elements; i++)
+  {
+    output_data[i] = 0.0f;
+  }
+
+  // Loop through input elements one at a time.
+  for (int batch = 0; batch < batches; ++batch)
+  {
+    for (int in_y = 0; in_y < input_height; ++in_y)
+    {
+      for (int in_x = 0; in_x < input_width; ++in_x)
+      {
+        for (int in_channel = 0; in_channel < input_depth; ++in_channel)
+        {
+          // Loop through the output elements it will influence
+          const int out_x_origin = (in_x * stride_width) - pad_width;
+          const int out_y_origin = (in_y * stride_height) - pad_height;
+          for (int filter_y = 0; filter_y < filter_height; ++filter_y)
+          {
+            for (int filter_x = 0; filter_x < filter_width; ++filter_x)
+            {
+              for (int out_channel = 0; out_channel < output_depth; ++out_channel)
+              {
+                // Compute output element location
+                const int out_x = out_x_origin + filter_x;
+                const int out_y = out_y_origin + filter_y;
+                // We cannot accumulate out of bounds
+                if ((out_x >= 0) && (out_x < output_width) && (out_y >= 0) &&
+                    (out_y < output_height))
+                {
+                  float input_value =
+                    input_data[offset(input_shape.dimsData(), batch, in_y, in_x, in_channel)];
+                  float filter_value = filter_data[offset(filter_shape.dimsData(), out_channel,
+                                                          filter_y, filter_x, in_channel)];
+                  output_data[offset(output_shape.dimsData(), batch, out_y, out_x, out_channel)] +=
+                    input_value * filter_value;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  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)
+        {
+          float acc =
+            output_data[offset(output_shape.dimsData(), batch, out_y, out_x, out_channel)];
+          if (bias_data)
+            acc += bias_data[out_channel];
+
+          output_data[offset(output_shape.dimsData(), batch, out_y, out_x, out_channel)] =
+            activationFunctionWithMinMax(acc, output_activation_min, output_activation_max);
+        }
+      }
+    }
+  }
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_TRANSPOSE_CONV_H
index ad9631c..b090287 100644 (file)
@@ -312,7 +312,8 @@ void calculateLstmGate(const LstmStepManager *step_info,
                      runtime_graph->getConstDataByTensor(input_weight)),
                    luci_interpreter::kernels::getTensorData<BiasType>(
                      runtime_graph->getConstDataByTensor(input_bias)),
-                   gate_output_shape.dimsData(), gate_output);
+                   gate_output_shape.dimsData(), gate_output, gate_output_shape.dimensionsCount(),
+                   luci_interpreter::Tensor::num_dims(input_weight));
   }
 
   // Recurrent FC
@@ -338,7 +339,9 @@ void calculateLstmGate(const LstmStepManager *step_info,
                      runtime_graph->getConstDataByTensor(recurrent_weight)),
                    luci_interpreter::kernels::getTensorData<BiasType>(
                      runtime_graph->getConstDataByTensor(recurrent_bias)),
-                   gate_output_shape.dimsData(), fc_output_buffer);
+                   gate_output_shape.dimsData(), fc_output_buffer,
+                   gate_output_shape.dimensionsCount(),
+                   luci_interpreter::Tensor::num_dims(recurrent_weight));
 
     addElementWise(gate_output, fc_output_buffer, /*n_batch=*/gate_output_shape.dimsData()[0],
                    /*n_state=*/gate_output_shape.dimsData()[1], gate_output);
index 1e05bfc..1b3796e 100644 (file)
@@ -177,6 +177,37 @@ inline int MatchingDim(const luci_interpreter::RuntimeShape &shape1, int index1,
   return shape1.dims(index1);
 }
 
+// Data is required to be contiguous, and so many operators can use either the
+// full array flat size or the flat size with one dimension skipped (commonly
+// the depth).
+inline int flatSizeSkipDim(const int32_t *dims_data, int skip_dim, int num_dims)
+{
+  int flat_size = 1;
+  for (int i = 0; i < num_dims; ++i)
+  {
+    flat_size *= (i == skip_dim) ? 1 : dims_data[i];
+  }
+  return flat_size;
+}
+
+inline int offset(const int32_t *dims_data, int i0, int i1, int i2, int i3)
+{
+  return ((i0 * dims_data[1] + i1) * dims_data[2] + i2) * dims_data[3] + i3;
+}
+
+inline int offset(const int32_t *dims_data, int i0, int i1, int i2, int i3, int i4)
+{
+  return (((i0 * dims_data[1] + i1) * dims_data[2] + i2) * dims_data[3] + i3) * dims_data[4] + i4;
+}
+
+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);
+}
+
 } // namespace luci_interpreter_pal
 
 #endif // LUCI_INTERPRETER_PAL_UTILS_H
index 0dea294..06d5493 100644 (file)
 namespace luci_interpreter_pal
 {
 
+struct MeanParams
+{
+  int8_t axis_count;
+  int16_t axis[4];
+};
+
+struct ResizeNearestNeighborParams
+{
+  bool align_corners;
+  bool half_pixel_centers;
+};
+
 struct PadParams
 {
   int8_t left_padding_count;
@@ -33,6 +45,8 @@ struct FullyConnectedParams
 {
   int32_t input_offset;
   int32_t weights_offset;
+  const float *weights_scales;
+  bool is_channel_wise_quant;
   int32_t output_offset;
   int32_t output_multiplier;
   int output_shift;
@@ -86,6 +100,9 @@ struct ConvParams
   // float activation params.
   float float_activation_min;
   float float_activation_max;
+  int32_t depth_multiplier;
+  std::vector<int32_t> per_channel_output_multiplier;
+  std::vector<int> per_channel_output_shift;
 };
 
 enum class BroadcastableOpCategory : uint8_t
@@ -115,6 +132,17 @@ struct TransposeParams
   int32_t perm[5];
 };
 
+struct PreluParams
+{
+  int32_t input_offset;
+  int32_t alpha_offset;
+  int32_t output_offset;
+  int32_t output_multiplier_1;
+  int output_shift_1;
+  int32_t output_multiplier_2;
+  int output_shift_2;
+};
+
 struct ComparisonParams
 {
   // uint8_t inference params.
@@ -209,6 +237,22 @@ struct PoolParams
   float float_activation_max;
 };
 
+struct SoftmaxParams
+{
+  float beta;
+  int32_t input_multiplier;
+  int32_t input_left_shift;
+  int diff_min;
+  int num_rows;
+  int row_size;
+};
+
+struct QuantizationParams
+{
+  float scale;
+  int zero_point;
+};
+
 } // namespace luci_interpreter_pal
 
 #endif // LUCI_INTERPRETER_PAL_PARAMS_H
index 4288319..4a4d200 100644 (file)
@@ -3,12 +3,22 @@ REGISTER_KERNEL(ADD, Add)
 REGISTER_KERNEL(AVERAGE_POOL_2D, AveragePool2D)
 REGISTER_KERNEL(ARG_MAX, ArgMax)
 REGISTER_KERNEL(ARG_MIN, ArgMin)
+REGISTER_KERNEL(CUSTOM, BroadcastTo)
+REGISTER_KERNEL(BATCH_TO_SPACE_ND, BatchToSpaceND)
+REGISTER_KERNEL(CEIL, Ceil)
+REGISTER_KERNEL(COS, Cos)
+REGISTER_KERNEL(CAST, Cast)
 REGISTER_KERNEL(DIV, Div)
+REGISTER_KERNEL(DEPTHWISE_CONV_2D, DepthwiseConv2D)
+REGISTER_KERNEL(DEPTH_TO_SPACE, DepthToSpace)
+REGISTER_KERNEL(DEQUANTIZE, Dequantize)
 REGISTER_KERNEL(ADD_N, AddN)
 REGISTER_KERNEL(FULLY_CONNECTED, FullyConnected)
 REGISTER_KERNEL(CONV_2D, Conv2D)
 REGISTER_KERNEL(LOGISTIC, Logistic)
+REGISTER_KERNEL(LOG, Log)
 REGISTER_KERNEL(GATHER, Gather)
+REGISTER_KERNEL(GATHER_ND, GatherND)
 REGISTER_KERNEL(EXP, Exp)
 REGISTER_KERNEL(GREATER, Greater)
 REGISTER_KERNEL(GREATER_EQUAL, GreaterEqual)
@@ -16,32 +26,62 @@ REGISTER_KERNEL(EXPAND_DIMS, ExpandDims)
 REGISTER_KERNEL(ELU, Elu)
 REGISTER_KERNEL(EQUAL, Equal)
 REGISTER_KERNEL(FILL, Fill)
+REGISTER_KERNEL(FLOOR, Floor)
+REGISTER_KERNEL(FLOOR_DIV, FloorDiv)
+REGISTER_KERNEL(FLOOR_MOD, FloorMod)
 REGISTER_KERNEL(PACK, Pack)
 REGISTER_KERNEL(PAD, Pad)
 REGISTER_KERNEL(PADV2, PadV2)
+REGISTER_KERNEL(PRELU, PRelu)
 REGISTER_KERNEL(RESHAPE, Reshape)
 REGISTER_KERNEL(RELU, Relu)
 REGISTER_KERNEL(RELU6, Relu6)
 REGISTER_KERNEL(REDUCE_PROD, ReduceCommon)
+REGISTER_KERNEL(REDUCE_MAX, ReduceMax)
+REGISTER_KERNEL(ROUND, Round)
 REGISTER_KERNEL(LESS, Less)
+REGISTER_KERNEL(L2_NORMALIZATION, L2Normalize)
+REGISTER_KERNEL(L2_POOL_2D, L2Pool2D)
 REGISTER_KERNEL(LESS_EQUAL, LessEqual)
 REGISTER_KERNEL(LOGICAL_AND, LogicalAnd)
+REGISTER_KERNEL(LOGICAL_NOT, LogicalNot)
 REGISTER_KERNEL(LOGICAL_OR, LogicalOr)
 REGISTER_KERNEL(LEAKY_RELU, LeakyRelu)
+REGISTER_KERNEL(LOG_SOFTMAX, LogSoftmax)
 REGISTER_KERNEL(MUL, Mul)
+REGISTER_KERNEL(MIRROR_PAD, MirrorPad)
+REGISTER_KERNEL(MAXIMUM, Maximum)
+REGISTER_KERNEL(MEAN, Mean)
 REGISTER_KERNEL(MAX_POOL_2D, MaxPool2D)
+REGISTER_KERNEL(MINIMUM, Minimum)
 REGISTER_KERNEL(CONCATENATION, Concatenation)
 REGISTER_KERNEL(SHAPE, Shape)
 REGISTER_KERNEL(NOT_EQUAL, NotEqual)
+REGISTER_KERNEL(SIN, Sin)
+REGISTER_KERNEL(SQUARED_DIFFERENCE, SquaredDifference)
 REGISTER_KERNEL(SLICE, Slice)
 REGISTER_KERNEL(SUB, Sub)
 REGISTER_KERNEL(SPLIT, Split)
+REGISTER_KERNEL(SPACE_TO_BATCH_ND, SpaceToBatchND)
 REGISTER_KERNEL(STRIDED_SLICE, StridedSlice)
 REGISTER_KERNEL(SPLIT_V, SplitV)
+REGISTER_KERNEL(SQUARE, Square)
+REGISTER_KERNEL(SQRT, Sqrt)
+REGISTER_KERNEL(SPACE_TO_DEPTH, SpaceToDepth)
+REGISTER_KERNEL(QUANTIZE, Quantize)
 REGISTER_KERNEL(TANH, Tanh)
 REGISTER_KERNEL(TRANSPOSE, Transpose)
+REGISTER_KERNEL(TRANSPOSE_CONV, TransposeConv)
 REGISTER_KERNEL(SOFTMAX, Softmax)
+REGISTER_KERNEL(SUM, Sum)
+REGISTER_KERNEL(SELECT_V2, SelectV2)
+REGISTER_KERNEL(SVDF, SVDF)
 REGISTER_KERNEL(WHILE, While)
 REGISTER_KERNEL(UNIDIRECTIONAL_SEQUENCE_LSTM, UnidirectionalSequenceLSTM)
 REGISTER_KERNEL(RESIZE_BILINEAR, ResizeBilinear)
+REGISTER_KERNEL(RESIZE_NEAREST_NEIGHBOR, ResizeNearestNeighbor)
+REGISTER_KERNEL(RSQRT, Rsqrt)
 REGISTER_KERNEL(NEG, Neg)
+REGISTER_KERNEL(ZEROS_LIKE, ZerosLike)
+REGISTER_KERNEL(SQUEEZE, Squeeze)
+REGISTER_KERNEL(UNPACK, Unpack)
diff --git a/onert-micro/luci-interpreter/pal/mcu/KernelsToTrain.lst b/onert-micro/luci-interpreter/pal/mcu/KernelsToTrain.lst
new file mode 100644 (file)
index 0000000..1025141
--- /dev/null
@@ -0,0 +1 @@
+REGISTER_TRAIN_KERNEL(FULLY_CONNECTED, FullyConnected)
index ef5fe72..ffc3e81 100644 (file)
 
 namespace luci_interpreter_pal
 {
-// TODO: add S8 and S16 kernel
+
+inline void AveragePool(const PoolParams &, const luci_interpreter::RuntimeShape &, const uint8_t *,
+                        const luci_interpreter::RuntimeShape &, uint8_t *,
+                        luci_interpreter::DataType)
+{
+  assert(false && "Not impl yet");
+}
+
 } // namespace luci_interpreter_pal
 
 #endif // LUCI_INTERPRETER_PAL_AVERAGE_POOL_2D_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALCos.h b/onert-micro/luci-interpreter/pal/mcu/PALCos.h
new file mode 100644 (file)
index 0000000..7745fc2
--- /dev/null
@@ -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_COS_H
+#define LUCI_INTERPRETER_PAL_COS_H
+
+#include "PALCosCommon.h"
+
+namespace luci_interpreter_pal
+{
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_COS_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALDepthwiseConv2D.h b/onert-micro/luci-interpreter/pal/mcu/PALDepthwiseConv2D.h
new file mode 100644 (file)
index 0000000..d08de8b
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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_DEPTHWISE_CONV2D_H
+#define LUCI_INTERPRETER_PAL_DEPTHWISE_CONV2D_H
+#include "PALDepthwiseConv2DCommon.h"
+
+namespace luci_interpreter_pal
+{
+// TODO: add quantize version
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_DEPTHWISE_CONV2D_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALFloor.h b/onert-micro/luci-interpreter/pal/mcu/PALFloor.h
new file mode 100644 (file)
index 0000000..1f8aca2
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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_FLOOR_H
+#define LUCI_INTERPRETER_PAL_FLOOR_H
+
+#include "PALFloorCommon.h"
+
+namespace luci_interpreter_pal
+{
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_FLOOR_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALFloorDiv.h b/onert-micro/luci-interpreter/pal/mcu/PALFloorDiv.h
new file mode 100644 (file)
index 0000000..c954c52
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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_FLOOR_H
+#define LUCI_INTERPRETER_PAL_FLOOR_H
+
+#include "PALFloorDivCommon.h"
+
+namespace luci_interpreter_pal
+{
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_FLOOR_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALFloorMod.h b/onert-micro/luci-interpreter/pal/mcu/PALFloorMod.h
new file mode 100644 (file)
index 0000000..9c873bb
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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_FLOORMOD_H
+#define LUCI_INTERPRETER_PAL_FLOORMOD_H
+
+#include "PALFloorModCommon.h"
+
+namespace luci_interpreter_pal
+{
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_FLOORMOD_H
index 4a024b1..b0935e4 100644 (file)
@@ -24,10 +24,11 @@ namespace luci_interpreter_pal
 {
 
 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)
+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, uint32_t, uint32_t)
 {
   // MARK: At this moment this operation doesn't support
   assert(false && "FullyConnected INT8 NYI");
@@ -44,10 +45,10 @@ FullyConnected(const luci_interpreter_pal::FullyConnectedParams &params, const i
 template <>
 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 *)
+                           const int32_t *, int16_t *, uint32_t, uint32_t)
 {
   // MARK: At this moment this operation doesn't support
-  assert(false && "FullyConnected INT8 NYI");
+  assert(false && "FullyConnected INT16 NYI");
 }
 
 } // namespace luci_interpreter_pal
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALL2Pool2D.h b/onert-micro/luci-interpreter/pal/mcu/PALL2Pool2D.h
deleted file mode 100644 (file)
index 38a302f..0000000
+++ /dev/null
@@ -1,33 +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.
- */
-
-#ifndef LUCI_INTERPRETER_PAL_L2POOL2D_H
-#define LUCI_INTERPRETER_PAL_L2POOL2D_H
-
-#include <tensorflow/lite/kernels/internal/reference/pooling.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::reference_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/mcu/PALLogicalNot.h b/onert-micro/luci-interpreter/pal/mcu/PALLogicalNot.h
new file mode 100644 (file)
index 0000000..3ec6960
--- /dev/null
@@ -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.
+ */
+
+#ifndef LUCI_INTERPRETER_PAL_LOGICAL_NOT_H
+#define LUCI_INTERPRETER_PAL_LOGICAL_NOT_H
+
+#include "PALLogicalNotCommon.h"
+
+namespace luci_interpreter_pal
+{
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_LOGICAL_NOT_H
index a0fff0c..05a7d49 100644 (file)
 
 namespace luci_interpreter_pal
 {
-// TODO: Add INT8, INT16 kernels
+inline void MaxPool(const PoolParams &, const luci_interpreter::RuntimeShape &, const uint8_t *,
+                    const luci_interpreter::RuntimeShape &, uint8_t *, luci_interpreter::DataType)
+{
+  assert(false && "Not impl yet");
+}
 } // namespace luci_interpreter_pal
 
 #endif // LUCI_INTERPRETER_PAL_MAX_POOL_2D_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALMaximum.h b/onert-micro/luci-interpreter/pal/mcu/PALMaximum.h
new file mode 100644 (file)
index 0000000..003b619
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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_MAXIMUM_H
+#define LUCI_INTERPRETER_PAL_MAXIMUM_H
+
+#include "PALMaximumCommon.h"
+
+namespace luci_interpreter_pal
+{
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_MAXIMUM_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALMinimum.h b/onert-micro/luci-interpreter/pal/mcu/PALMinimum.h
new file mode 100644 (file)
index 0000000..5d048e3
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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_MINIMUM_H
+#define LUCI_INTERPRETER_PAL_MINIMUM_H
+
+#include "PALMinimumCommon.h"
+
+namespace luci_interpreter_pal
+{
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_MINIMUM_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALSVDF.h b/onert-micro/luci-interpreter/pal/mcu/PALSVDF.h
new file mode 100644 (file)
index 0000000..ea05dd7
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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_SVDF_H
+#define LUCI_INTERPRETER_PAL_SVDF_H
+
+#include "PALSVDFCommon.h"
+
+// TODO: add INT8 version
+
+#endif // LUCI_INTERPRETER_PAL_SVDF_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALSin.h b/onert-micro/luci-interpreter/pal/mcu/PALSin.h
new file mode 100644 (file)
index 0000000..a4af66c
--- /dev/null
@@ -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_SIN_H
+#define LUCI_INTERPRETER_PAL_SIN_H
+
+#include "PALSinCommon.h"
+
+namespace luci_interpreter_pal
+{
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SIN_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALSoftmax.h b/onert-micro/luci-interpreter/pal/mcu/PALSoftmax.h
new file mode 100644 (file)
index 0000000..e47111f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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_SOFTMAX_H
+#define LUCI_INTERPRETER_PAL_SOFTMAX_H
+
+#include "PALSoftmaxCommon.h"
+
+namespace luci_interpreter_pal
+{
+
+inline void Softmax(const SoftmaxParams &params, const int8_t *input_data, int8_t *output_data)
+{
+  assert(false && "Not supported now");
+}
+
+inline void Softmax(const SoftmaxParams &params, const int8_t *input_data, int16_t *output_data)
+{
+  assert(false && "Not supported now");
+}
+
+inline void Softmax(const SoftmaxParams &params, const int16_t *input_data, int16_t *output_data)
+{
+  assert(false && "Not supported now");
+}
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SOFTMAX_H
diff --git a/onert-micro/luci-interpreter/pal/mcu/PALSquare.h b/onert-micro/luci-interpreter/pal/mcu/PALSquare.h
new file mode 100644 (file)
index 0000000..f624305
--- /dev/null
@@ -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_SQUARE_H
+#define LUCI_INTERPRETER_PAL_SQUARE_H
+
+#include "PALSquareCommon.h"
+
+namespace luci_interpreter_pal
+{
+
+} // namespace luci_interpreter_pal
+
+#endif // LUCI_INTERPRETER_PAL_SQUARE_H
index 35592ac..d0d4060 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "PALUnidirectionalSequenceLSTMCommon.h"
 
+#ifndef DIS_QUANT
+
 namespace luci_interpreter_pal
 {
 // Evaluate the LSTM kernel with (potential) multi-steps and multi-batch input
@@ -79,4 +81,6 @@ void evalLSTM<int8_t, int8_t, int16_t, int32_t>(
 
 } // namespace luci_interpreter_pal
 
+#endif // DIS_QUANT
+
 #endif // LUCI_INTERPRETER_PAL_UNIDIRECTIONAL_SEQUENCE_LSTM_H
index 75d6836..d890d3b 100644 (file)
@@ -31,7 +31,7 @@ target_include_directories(${LUCI_INTERPRETER_CORE} PUBLIC ${LUCI_INTERPRETER_KE
 message(STATUS "LUCI INTERPTER INITALIZED")
 
 set(SOURCES
-        "${LUCI_INTERPRETER_INCLUDE_DIR}/luci_interpreter/Interpreter.h" Interpreter.cpp)
+        "${LUCI_INTERPRETER_INCLUDE_DIR}/luci_interpreter/Interpreter.h" Interpreter.cpp TrainingOnertMicro.cpp)
 
 add_library(${LUCI_INTERPRETER_BINARY} STATIC ${SOURCES})
 
index 658b28f..a0dd655 100644 (file)
@@ -38,7 +38,10 @@ Interpreter::Interpreter(const char *model_data_raw, const InterpreterConfigure
     _memory_manager = std::make_unique<StaticMemoryManager>(
       configuration._input_buf_size, configuration._temp_buf_size, configuration._output_buf_size);
   }
-  else { _memory_manager = std::make_unique<SimpleMemoryManager>(); }
+  else
+  {
+    _memory_manager = std::make_unique<SimpleMemoryManager>();
+  }
 
   _memory_manager->is_allocate_input(configuration.getAllocateInputValue());
 
@@ -77,7 +80,7 @@ int32_t Interpreter::getOutputDataSizeByIndex(int32_t output_tensor_index)
   return runtime_graph->getOutputDataSizeByIndex(output_tensor_index);
 }
 
-void Interpreter::allocateAndWriteInputTensor(int32_t input_tensor_index, const void *data,
+void Interpreter::allocateAndWriteInputTensor(int32_t input_tensor_index, const uint8_t *data,
                                               size_t data_size)
 {
   assert(data_size > 0);
diff --git a/onert-micro/luci-interpreter/src/TrainingOnertMicro.cpp b/onert-micro/luci-interpreter/src/TrainingOnertMicro.cpp
new file mode 100644 (file)
index 0000000..a485697
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
+
+#include "luci_interpreter/TrainingOnertMicro.h"
+#include "core/TrainingModule.h"
+
+#include <cmath>
+
+namespace luci_interpreter
+{
+
+namespace training
+{
+
+namespace
+{
+
+float calculateMSEError(const float *predicted_values, const float *target_values,
+                        const uint32_t output_size)
+{
+  const uint32_t output_number_values = output_size / sizeof(float);
+  float result = 0.0f;
+  for (int i = 0; i < output_number_values; ++i)
+  {
+    result += std::pow(predicted_values[i] - target_values[i], 2);
+  }
+
+  return result / output_number_values;
+}
+
+float calculateMAEError(const float *predicted_values, const float *target_values,
+                        const uint32_t output_size)
+{
+  const uint32_t output_number_values = output_size / sizeof(float);
+  float result = 0.0f;
+  for (int i = 0; i < output_number_values; ++i)
+  {
+    result += std::abs(predicted_values[i] - target_values[i]);
+  }
+
+  return result / output_number_values;
+}
+
+Status calculateError(const uint8_t *predicted_value, const uint8_t *target_value, void *result,
+                      const uint32_t output_size, MetricsTypeEnum error_type)
+{
+  switch (error_type)
+  {
+    case MSE:
+    {
+      float *result_float = reinterpret_cast<float *>(result);
+      *result_float +=
+        calculateMSEError(reinterpret_cast<const float *>(predicted_value),
+                          reinterpret_cast<const float *>(target_value), output_size);
+      break;
+    }
+    case MAE:
+    {
+      float *result_float = reinterpret_cast<float *>(result);
+      *result_float +=
+        calculateMAEError(reinterpret_cast<const float *>(predicted_value),
+                          reinterpret_cast<const float *>(target_value), output_size);
+      break;
+    }
+    default:
+    {
+      return Error;
+    }
+  }
+
+  return Ok;
+}
+
+} // namespace
+
+TrainingOnertMicro::TrainingOnertMicro(Interpreter *interpreter, TrainingSettings &settings)
+  : _interpreter(interpreter), _settings(settings), _is_training_mode(false),
+    _module(&interpreter->_runtime_module)
+{
+  // Do nothing
+}
+
+Status TrainingOnertMicro::enableTrainingMode()
+{
+  if (_is_training_mode)
+  {
+    return DoubleTrainModeError;
+  }
+
+  const Status status = _module.enableTrainingMode(_settings, &_interpreter->_memory_manager);
+
+  if (status != Ok)
+    assert("Some error during enabling training mode");
+
+  _is_training_mode = true;
+
+  return status;
+}
+
+Status TrainingOnertMicro::disableTrainingMode(bool resetWeights)
+{
+  if (_is_training_mode == false)
+  {
+    return Ok;
+  }
+
+  const Status status = _module.disableTrainingMode(resetWeights);
+
+  if (status != Ok)
+    assert("Some error during disabling training mode");
+
+  _is_training_mode = false;
+
+  return status;
+}
+
+Status TrainingOnertMicro::train(uint32_t number_of_train_samples, const uint8_t *train_data,
+                                 const uint8_t *label_train_data)
+{
+  if (_is_training_mode == false)
+    return EnableTrainModeError;
+
+  const uint32_t batch_size = _settings.batch_size;
+
+  const uint32_t num_inferences = number_of_train_samples / batch_size;
+
+  const uint32_t remains = number_of_train_samples % batch_size;
+
+  const uint32_t epochs = _settings.number_of_epochs;
+
+  const int32_t input_tensor_size = _interpreter->getInputDataSizeByIndex(0);
+  const int32_t output_tensor_size = _interpreter->getOutputDataSizeByIndex(0);
+
+  const uint8_t *cur_train_data = train_data;
+  const uint8_t *cur_label_train_data = label_train_data;
+
+  for (uint32_t epoch = 0; epoch < epochs; ++epoch)
+  {
+    for (uint32_t infer = 0; infer < num_inferences; ++infer)
+    {
+      for (uint32_t batch = 0; batch < batch_size; ++batch)
+      {
+        _interpreter->allocateAndWriteInputTensor(0, cur_train_data, input_tensor_size);
+
+        _interpreter->interpret();
+
+        _module.computeGradients(_settings, cur_label_train_data);
+        cur_train_data += input_tensor_size;
+        cur_label_train_data += output_tensor_size;
+      }
+
+      _module.updateWeights(_settings);
+    }
+    cur_train_data = train_data;
+    cur_label_train_data = label_train_data;
+  }
+
+  return Ok;
+}
+
+Status TrainingOnertMicro::test(uint32_t number_of_train_samples, const uint8_t *test_data,
+                                const uint8_t *label_test_data, void *metric_value_result)
+{
+  const int32_t input_tensor_size = _interpreter->getInputDataSizeByIndex(0);
+  const int32_t output_tensor_size = _interpreter->getOutputDataSizeByIndex(0);
+
+  const uint8_t *cur_test_data = test_data;
+  const uint8_t *cur_label_test_data = label_test_data;
+
+  switch (_settings.metric)
+  {
+    case MSE:
+    case MAE:
+    {
+      float *result_float = reinterpret_cast<float *>(metric_value_result);
+      *result_float = 0.0f;
+      break;
+    }
+    default:
+    {
+      return Error;
+    }
+  }
+
+  for (uint32_t sample = 0; sample < number_of_train_samples; ++sample)
+  {
+    _interpreter->allocateAndWriteInputTensor(0, cur_test_data, input_tensor_size);
+
+    _interpreter->interpret();
+
+    const uint8_t *output_data = _interpreter->readOutputTensor(0);
+
+    Status status = calculateError(output_data, cur_label_test_data, metric_value_result,
+                                   output_tensor_size, _settings.metric);
+
+    if (status != Ok)
+      return status;
+
+    cur_test_data += input_tensor_size;
+    cur_label_test_data += output_tensor_size;
+  }
+
+  switch (_settings.metric)
+  {
+    case MSE:
+    case MAE:
+    {
+      float *result_float = reinterpret_cast<float *>(metric_value_result);
+      *result_float /= number_of_train_samples;
+      break;
+    }
+    default:
+    {
+      return Error;
+    }
+  }
+
+  return Ok;
+}
+
+TrainingOnertMicro::~TrainingOnertMicro() { disableTrainingMode(); }
+
+} // namespace training
+
+} // namespace luci_interpreter
+
+#endif // ENABLE_TRAINING
index 48d92aa..8ccd10e 100644 (file)
@@ -3,7 +3,11 @@ set(SOURCES
     "${LUCI_INTERPRETER_INCLUDE_DIR}/luci_interpreter/core/Tensor.h"
     RuntimeGraph.h
     RuntimeGraph.cpp
-    RuntimeModule.h)
+    RuntimeModule.h
+    TrainingGraph.cpp
+    GradientCalculationStorage.cpp
+    TrainableWeightStorage.cpp
+    TrainingModule.cpp)
 
 add_library(${LUCI_INTERPRETER_CORE} STATIC ${SOURCES})
 if (NOT NNCC_LIBRARY_NO_PIC)
diff --git a/onert-micro/luci-interpreter/src/core/GradientCalculationStorage.cpp b/onert-micro/luci-interpreter/src/core/GradientCalculationStorage.cpp
new file mode 100644 (file)
index 0000000..22f1f42
--- /dev/null
@@ -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.
+ */
+
+#ifdef ENABLE_TRAINING
+
+#include "GradientCalculationStorage.h"
+#include "luci_interpreter/core/Tensor.h"
+
+#include <unordered_map>
+
+namespace luci_interpreter
+{
+namespace training
+{
+
+Status GradientCalculationStorage::clearComputedData()
+{
+  for (const auto &pair : _tensor_to_data)
+  {
+    delete[] pair.second;
+  }
+
+  _tensor_to_data.clear();
+
+  return Ok;
+}
+
+Status GradientCalculationStorage::clearComputedGradients()
+{
+  for (const auto &pair : _gradients)
+  {
+    delete[] pair.second;
+  }
+
+  _gradients.clear();
+
+  return Ok;
+}
+
+Status GradientCalculationStorage::saveDataToTensor(const circle::Tensor *tensor, uint8_t *data)
+{
+  const auto it = _tensor_to_data.find(tensor);
+  if (it != _tensor_to_data.end())
+  {
+    delete[] it->second;
+  }
+
+  _tensor_to_data[tensor] = data;
+  return Ok;
+}
+
+Status GradientCalculationStorage::saveGradients(const circle::Tensor *tensor, uint8_t *data)
+{
+  const auto it = _gradients.find(tensor);
+  if (it != _gradients.end())
+    return Error;
+
+  _gradients[tensor] = data;
+  return Ok;
+}
+
+Status GradientCalculationStorage::getDataByTensor(const circle::Tensor *tensor, uint8_t **data)
+{
+  assert(tensor != nullptr); // CALLER SIDE
+
+  auto it = _tensor_to_data.find(tensor);
+
+  assert(it != _tensor_to_data.end() && "No data");
+  if (it == _tensor_to_data.end())
+  {
+    return Error;
+  }
+
+  *data = it->second;
+
+  return Ok;
+}
+
+Status GradientCalculationStorage::createGradientMatrix(const circle::Tensor *tensor)
+{
+  const auto rows = Tensor::dim(tensor, 0);
+  const auto cols = Tensor::dim(tensor, 1);
+
+  uint8_t *gradient_values = new uint8_t[rows * cols * size(Tensor::element_type(tensor))];
+
+  switch (Tensor::element_type(tensor))
+  {
+    case DataType::FLOAT32:
+    {
+      float *gradient_values_float = reinterpret_cast<float *>(gradient_values);
+      for (int row = 0; row < rows; ++row)
+      {
+        for (int col = 0; col < cols; ++col)
+        {
+          gradient_values_float[col + row * cols] = 0;
+        }
+      }
+      break;
+    }
+    default:
+    {
+      assert(false && "Unsupported type");
+      return Error;
+    }
+  }
+  saveGradients(tensor, gradient_values);
+
+  return Ok;
+}
+
+Status GradientCalculationStorage::getGradients(const circle::Tensor *tensor, uint8_t **data)
+{
+  assert(tensor != nullptr); // CALLER SIDE
+
+  auto it = _gradients.find(tensor);
+
+  if (it == _gradients.end())
+  {
+    Status status = createGradientMatrix(tensor);
+    if (status != Ok)
+      return status;
+  }
+
+  it = _gradients.find(tensor);
+
+  *data = it->second;
+
+  if (*data == nullptr)
+    return Error;
+
+  return Ok;
+}
+
+GradientCalculationStorage::~GradientCalculationStorage()
+{
+  clearComputedGradients();
+  clearComputedData();
+}
+
+} // namespace training
+} // namespace luci_interpreter
+
+#endif // ENABLE_TRAINING
diff --git a/onert-micro/luci-interpreter/src/core/GradientCalculationStorage.h b/onert-micro/luci-interpreter/src/core/GradientCalculationStorage.h
new file mode 100644 (file)
index 0000000..f6a3711
--- /dev/null
@@ -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.
+ */
+
+#ifdef ENABLE_TRAINING
+
+#ifndef LUCI_INTERPRETER_SRC_CORE_GRADIENT_CALCULATION_STORAGE_H
+#define LUCI_INTERPRETER_SRC_CORE_GRADIENT_CALCULATION_STORAGE_H
+
+#include "luci_interpreter/TrainingSettings.h"
+#include "luci_interpreter/core/reader/CircleMicroReader.h"
+
+#include <unordered_map>
+
+namespace luci_interpreter
+{
+namespace training
+{
+
+class GradientCalculationStorage
+{
+public:
+  GradientCalculationStorage() = default;
+
+  ~GradientCalculationStorage();
+
+public:
+  Status getDataByTensor(const circle::Tensor *tensor, uint8_t **data);
+  Status saveDataToTensor(const circle::Tensor *tensor, uint8_t *data);
+
+  Status getGradients(const circle::Tensor *tensor, uint8_t **data);
+  Status saveGradients(const circle::Tensor *tensor, uint8_t *data);
+
+  Status clearComputedData();
+
+  Status clearComputedGradients();
+
+private:
+  Status createGradientMatrix(const circle::Tensor *tensor);
+
+private:
+  std::unordered_map<const circle::Tensor *, uint8_t *> _tensor_to_data;
+  std::unordered_map<const circle::Tensor *, uint8_t *> _gradients;
+};
+
+} // namespace training
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_SRC_CORE_GRADIENT_CALCULATION_STORAGE_H
+
+#endif // ENABLE_TRAINING
index 917ebbb..5824e16 100644 (file)
@@ -172,13 +172,33 @@ void RuntimeGraph::deallocate(size_t kernel_index)
 {
   assert(_reader->get_current_subgraph_index() == _subgraph_index);
   assert(_is_valid && kernel_index < _dealloc_plan.size());
+
+#ifdef ENABLE_TRAINING
+  // const uint32_t number_of_trainable_last_layers = _number_of_last_trainable_layers;
+  const uint32_t last_layer = _number_of_last_trainable_layers > 0
+                                ? _reader->operators().size() - _number_of_last_trainable_layers
+                                : 0;
+#endif // ENABLE_TRAINING
+
   for (const circle::Tensor *tensor : _dealloc_plan[kernel_index])
   {
     const auto it = _tensor_to_data.find(tensor);
     assert(it != _tensor_to_data.end());
 
     auto *data = _tensor_to_data.at(tensor);
+
+#ifdef ENABLE_TRAINING
+    if (_number_of_last_trainable_layers > 0 and kernel_index >= last_layer)
+    {
+      _gradient_calc_storage->saveDataToTensor(tensor, data);
+    }
+    else
+    {
+      _memory_manager->release_memory(data);
+    }
+#else
     _memory_manager->release_memory(data);
+#endif // ENABLE_TRAINING
 
     _tensor_to_data.erase(it);
   }
@@ -308,7 +328,14 @@ int32_t RuntimeGraph::getOutputDataSizeByIndex(int32_t output_index)
   const auto tensor = _reader->tensors()[tensor_index];
   assert(tensor != nullptr);
 
-  return Tensor::num_elements(tensor) * size(Tensor::element_type(tensor));
+  uint32_t num_elements = Tensor::num_elements(tensor);
+  auto it = _dynamic_tensor_shapes.find(tensor);
+  if (it != _dynamic_tensor_shapes.end())
+  {
+    num_elements = it->second.flatSize();
+  }
+
+  return num_elements * size(Tensor::element_type(tensor));
 }
 
 uint8_t *RuntimeGraph::getOutputDataByIndex(int32_t output_index)
@@ -374,6 +401,21 @@ uint8_t *RuntimeGraph::getConstDataByTensor(const circle::Tensor *raw_tensor)
   if (raw_tensor == nullptr)
     return nullptr;
 
+#ifdef ENABLE_TRAINING
+  assert(_number_of_last_trainable_layers == 0 or
+         _storage != nullptr && "Storage should not be null here");
+
+  if (_storage != nullptr)
+  {
+    uint8_t *result = nullptr;
+    _storage->getTrainWeightDataByTensor(raw_tensor, &result);
+
+    if (result != nullptr)
+      return result;
+  }
+
+#endif // ENABLE_TRAINING
+
   auto const &buffer = wrap(_reader->buffers()[raw_tensor->buffer()]->data());
 
   return const_cast<uint8_t *>(buffer.data());
@@ -438,6 +480,20 @@ void RuntimeGraph::execute()
 
     deallocate(i);
   }
+
+#ifdef ENABLE_TRAINING
+  if (_number_of_last_trainable_layers > 0)
+  {
+    const auto graph_output = _reader->outputs();
+
+    assert(graph_output.size() == 1);
+
+    const auto output_tensor = _reader->tensors()[graph_output[0]];
+    uint8_t *output_data = _tensor_to_data.at(output_tensor);
+    _gradient_calc_storage->saveDataToTensor(output_tensor, output_data);
+    _tensor_to_data.erase(output_tensor);
+  }
+#endif // ENABLE_TRAINING
 }
 
 } // namespace luci_interpreter
index baac0b1..d75bfc6 100644 (file)
 #define LUCI_INTERPRETER_CORE_RUNTIMEGRAPH_H
 
 #include "luci_interpreter/core/Tensor.h"
+
+#ifdef ENABLE_TRAINING
+#include "TrainingGraph.h"
+#endif // ENABLE_TRAINING
+
 #ifdef USE_STATIC_ALLOC
 #include "memory_managers/StaticMemoryManager.h"
 #else
@@ -110,6 +115,18 @@ public:
     return _inplace_op_indexes.find(op) != _inplace_op_indexes.end();
   }
 
+#ifdef ENABLE_TRAINING
+  void setLastTrainingLayersNumber(uint32_t training_number)
+  {
+    _number_of_last_trainable_layers = training_number;
+  }
+  void setGradientCalculationStorage(training::GradientCalculationStorage *gradient_calc_storage)
+  {
+    _gradient_calc_storage = gradient_calc_storage;
+  }
+  void setTrainingWeightStorage(training::TrainableWeightStorage *storage) { _storage = storage; }
+#endif // ENABLE_TRAINING
+
 #ifndef DIS_DYN_SHAPES
   void addDynamicShapeTensor(const circle::Tensor *tensor, luci_interpreter::RuntimeShape &&shapes);
 
@@ -133,6 +150,12 @@ private:
 
   bool _is_valid = false;
 
+#ifdef ENABLE_TRAINING
+  uint32_t _number_of_last_trainable_layers = 0; // 0 means there is no training
+  training::GradientCalculationStorage *_gradient_calc_storage = nullptr;
+  training::TrainableWeightStorage *_storage = nullptr;
+#endif // ENABLE_TRAINING
+
   // 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;
index d426982..ceb9ef1 100644 (file)
 #include "core/RuntimeGraph.h"
 #include "luci_interpreter/core/reader/CircleMicroReader.h"
 
+#ifdef ENABLE_TRAINING
+#include "luci_interpreter/TrainableWeightStorage.h"
+#include "TrainingGraph.h"
+#include "core/RuntimeGraph.h"
+#endif // ENABLE_TRAINING
+
 #include <memory>
 #include <vector>
 
@@ -34,11 +40,24 @@ using BaseRuntimeGraph = RuntimeGraph;
 using MemoryManager = SimpleMemoryManager;
 #endif // USE_STATIC_ALLOC
 
+#ifdef ENABLE_TRAINING
+namespace training
+{
+
+class TrainingModule;
+
+} // namespace training
+#endif // ENABLE_TRAINING
+
 class RuntimeModule
 {
 public:
   RuntimeModule() = default;
 
+#ifdef ENABLE_TRAINING
+  friend class training::TrainingModule;
+#endif // ENABLE_TRAINING
+
   void addGraph(MemoryManager *memory_manager)
   {
     _graphs.emplace_back(memory_manager, &_circle_reader, this,
@@ -59,6 +78,10 @@ private:
   std::vector<BaseRuntimeGraph> _graphs;
 
   CircleReader _circle_reader;
+
+#ifdef ENABLE_TRAINING
+  std::unique_ptr<training::TrainableWeightStorage> _storage;
+#endif // ENABLE_TRAINING
 };
 
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/core/TrainableWeightStorage.cpp b/onert-micro/luci-interpreter/src/core/TrainableWeightStorage.cpp
new file mode 100644 (file)
index 0000000..95a1c7d
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+#ifdef ENABLE_TRAINING
+
+#include "luci_interpreter/TrainableWeightStorage.h"
+
+namespace luci_interpreter
+{
+namespace training
+{
+
+Status TrainableWeightStorage::createTrainableWeightForTensor(const circle::Tensor *tensor,
+                                                              SimpleMemoryManager *memoryManager,
+                                                              const uint8_t *const_data)
+{
+  assert(_tensor_to_data.count(tensor) == 0 && "Double training weight");
+
+  if (_tensor_to_data.count(tensor) != 0)
+  {
+    return Error;
+  }
+
+  uint8_t *allocated_data = memoryManager->allocate_memory(tensor);
+
+  std::memcpy(allocated_data, const_data,
+              size(Tensor::element_type(tensor)) * Tensor::num_elements(tensor));
+
+  _tensor_to_data[tensor] = allocated_data;
+
+  return Ok;
+}
+
+training::Status
+TrainableWeightStorage::fillTrainableWeightsStorage(const CircleReader *reader,
+                                                    SimpleMemoryManager *memory_manager,
+                                                    uint32_t number_of_last_trainable_layers)
+{
+  const auto operators_size = reader->operators().size();
+  const auto operators = reader->operators();
+
+  const uint32_t first_trainable_layer_pos = operators_size - number_of_last_trainable_layers;
+
+  for (uint32_t i = first_trainable_layer_pos; i < operators_size; ++i)
+  {
+    const auto op = operators.at(i);
+    assert(op != nullptr);
+
+    const auto *op_inputs = op->inputs();
+
+    for (const int32_t input_idx : *op_inputs)
+    {
+      if (input_idx == -1)
+        continue;
+      const circle::Tensor *tensor = reader->tensors()[input_idx];
+
+      if (_tensor_to_data.count(tensor) > 0)
+        continue;
+
+      const auto tensor_data = reader->buffers()[tensor->buffer()]->data();
+      if (tensor_data != nullptr)
+      {
+        if (createTrainableWeightForTensor(tensor, memory_manager, tensor_data->data()) ==
+            training::Error)
+          return training::Error;
+      }
+    }
+  }
+  return training::Ok;
+}
+
+Status TrainableWeightStorage::clearAllTrainableWeights()
+{
+  for (const auto &pair : _tensor_to_data)
+  {
+    delete[] pair.second;
+  }
+
+  _tensor_to_data.clear();
+  return Ok;
+}
+
+Status TrainableWeightStorage::getTrainWeightDataByTensor(const circle::Tensor *tensor,
+                                                          uint8_t **result_data)
+{
+  assert(tensor != nullptr); // CALLER SIDE
+
+  auto it = _tensor_to_data.find(tensor);
+
+  if (it == _tensor_to_data.end())
+  {
+    result_data = nullptr;
+    return Ok;
+  }
+
+  *result_data = it->second;
+
+  return Ok;
+}
+
+} // namespace training
+} // namespace luci_interpreter
+
+#endif // ENABLE_TRAINING
diff --git a/onert-micro/luci-interpreter/src/core/TrainingGraph.cpp b/onert-micro/luci-interpreter/src/core/TrainingGraph.cpp
new file mode 100644 (file)
index 0000000..7cac7aa
--- /dev/null
@@ -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.
+ */
+
+#ifdef ENABLE_TRAINING
+
+#include "TrainingGraph.h"
+
+#include "kernels/KernelBuilder.h"
+
+#include <unordered_map>
+
+namespace luci_interpreter
+{
+namespace training
+{
+
+Status TrainingGraph::saveLabelDataAsBackDerivative(CircleReader *reader,
+                                                    TrainableWeightStorage *storage,
+                                                    const uint8_t *label_train_data)
+{
+  Status status;
+
+  const auto graph_outputs = reader->outputs();
+  assert(graph_outputs.size() == 1);
+  if (graph_outputs.size() != 1)
+    return Error;
+
+  const circle::Tensor *output_graph_tensor = reader->tensors()[graph_outputs[0]];
+
+  uint8_t *output_data = nullptr;
+  status = _gradient_calculation_storage.getDataByTensor(output_graph_tensor, &output_data);
+  if (status != Ok)
+    return status;
+
+  assert(output_data != nullptr);
+  if (output_data == nullptr)
+    return Error;
+
+  const auto tensor_size = Tensor::num_elements(output_graph_tensor);
+  const auto tensor_type = Tensor::element_type(output_graph_tensor);
+
+  switch (tensor_type)
+  {
+    case DataType::FLOAT32:
+    {
+      float *casted_output_data = reinterpret_cast<float *>(output_data);
+      const float *casted_label_data = reinterpret_cast<const float *>(label_train_data);
+
+      // For MSE
+      for (int i = 0; i < tensor_size; ++i)
+        casted_output_data[i] = casted_output_data[i] - casted_label_data[i];
+
+      break;
+    }
+    default:
+    {
+      assert(false && "Unsupported type");
+      return Error;
+    }
+  }
+
+  return Ok;
+}
+
+Status TrainingGraph::computeGradients(const TrainingSettings &settings,
+                                       TrainableWeightStorage *storage, CircleReader *reader,
+                                       const uint8_t *label_train_data)
+{
+  assert(settings.number_of_last_trainable_layers != 0);
+
+  const int last_op_pos = reader->operators().size() - 1;
+  const int last_train_op_pos = settings.number_of_last_trainable_layers > 0
+                                  ? last_op_pos - settings.number_of_last_trainable_layers
+                                  : -1;
+  Status status;
+
+  // Save label_data as gradient to output tensor
+  status = saveLabelDataAsBackDerivative(reader, storage, label_train_data);
+  if (status != Ok)
+    return status;
+
+  for (auto op_pos = last_op_pos; op_pos > last_train_op_pos; --op_pos)
+  {
+    const auto op = reader->operators().at(op_pos);
+    const auto opcode = reader->builtin_code(op);
+
+    status = kernel_train.train_kernel(op, opcode, reader, &_gradient_calculation_storage, settings,
+                                       storage, true /* compute gradient mode */);
+
+    if (status != Ok)
+      return status;
+  }
+
+  _gradient_calculation_storage.clearComputedData();
+
+  return Ok;
+}
+
+Status TrainingGraph::updateWeights(const TrainingSettings &settings,
+                                    TrainableWeightStorage *storage, CircleReader *reader)
+{
+  const int last_op_pos = reader->operators().size() - 1;
+  const int last_train_op_pos = settings.number_of_last_trainable_layers > 0
+                                  ? last_op_pos - settings.number_of_last_trainable_layers
+                                  : -1;
+  Status status;
+  for (auto op_pos = last_op_pos; op_pos > last_train_op_pos; --op_pos)
+  {
+    const auto op = reader->operators().at(op_pos);
+    const auto opcode = reader->builtin_code(op);
+
+    status = kernel_train.train_kernel(op, opcode, reader, &_gradient_calculation_storage, settings,
+                                       storage, false /* update weights mode */);
+
+    assert(status == Ok);
+
+    if (status != Ok)
+    {
+      return status;
+    }
+  }
+  _gradient_calculation_storage.clearComputedData();
+  _gradient_calculation_storage.clearComputedGradients();
+
+  return Ok;
+}
+
+} // namespace training
+} // namespace luci_interpreter
+
+#endif // ENABLE_TRAINING
diff --git a/onert-micro/luci-interpreter/src/core/TrainingGraph.h b/onert-micro/luci-interpreter/src/core/TrainingGraph.h
new file mode 100644 (file)
index 0000000..15ade84
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_SRC_CORE_TRAINING_GRAPH_H
+#define LUCI_INTERPRETER_SRC_CORE_TRAINING_GRAPH_H
+
+#include "luci_interpreter/TrainingSettings.h"
+#include "luci_interpreter/TrainableWeightStorage.h"
+#include "luci_interpreter/core/reader/CircleMicroReader.h"
+#include "memory_managers/SimpleMemoryManager.h"
+
+#include "GradientCalculationStorage.h"
+
+#include <unordered_map>
+
+namespace luci_interpreter
+{
+namespace training
+{
+
+class TrainingGraph
+{
+public:
+  TrainingGraph() = default;
+
+public:
+  Status computeGradients(const TrainingSettings &settings, TrainableWeightStorage *storage,
+                          CircleReader *reader, const uint8_t *label_train_data);
+
+  Status updateWeights(const TrainingSettings &settings, TrainableWeightStorage *storage,
+                       CircleReader *reader);
+
+  GradientCalculationStorage *getGradientCalculationStorage()
+  {
+    return &_gradient_calculation_storage;
+  }
+
+private:
+  Status saveLabelDataAsBackDerivative(CircleReader *reader, TrainableWeightStorage *storage,
+                                       const uint8_t *label_train_data);
+
+  GradientCalculationStorage _gradient_calculation_storage;
+};
+
+} // namespace training
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_SRC_CORE_TRAINING_GRAPH_H
+
+#endif // ENABLE_TRAINING
diff --git a/onert-micro/luci-interpreter/src/core/TrainingModule.cpp b/onert-micro/luci-interpreter/src/core/TrainingModule.cpp
new file mode 100644 (file)
index 0000000..41e7d6e
--- /dev/null
@@ -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.
+ */
+
+#ifdef ENABLE_TRAINING
+
+#include "TrainingModule.h"
+
+#include <memory>
+
+namespace luci_interpreter
+{
+namespace training
+{
+
+training::Status TrainingModule::enableTrainingMode(training::TrainingSettings &settings,
+                                                    SimpleMemoryManager *memoryManager)
+{
+  if (_runtime_module->_storage.get() == nullptr)
+  {
+    _runtime_module->_storage = std::make_unique<TrainableWeightStorage>();
+  }
+
+  if (_runtime_module->_storage->fillTrainableWeightsStorage(
+        &_runtime_module->_circle_reader, memoryManager,
+        settings.number_of_last_trainable_layers) == training::Error)
+    return training::Error;
+
+  _training_graph = std::make_unique<training::TrainingGraph>();
+
+  for (auto &graph : _runtime_module->_graphs)
+  {
+    graph.setLastTrainingLayersNumber(settings.number_of_last_trainable_layers);
+    graph.setGradientCalculationStorage(_training_graph->getGradientCalculationStorage());
+    graph.setTrainingWeightStorage(_runtime_module->_storage.get());
+  }
+
+  return training::Ok;
+}
+
+training::Status TrainingModule::disableTrainingMode(bool resetWeights)
+{
+  _training_graph.release();
+
+  if (resetWeights)
+  {
+    if (_runtime_module->_storage->clearAllTrainableWeights() == training::Error)
+      return training::Error;
+    _runtime_module->_storage.release();
+  }
+
+  for (auto &graph : _runtime_module->_graphs)
+  {
+    graph.setLastTrainingLayersNumber(0);
+    graph.setGradientCalculationStorage(nullptr);
+    if (resetWeights)
+      graph.setTrainingWeightStorage(nullptr);
+  }
+
+  return training::Ok;
+}
+
+} // namespace training
+} // namespace luci_interpreter
+
+#endif // ENABLE_TRAINING
diff --git a/onert-micro/luci-interpreter/src/core/TrainingModule.h b/onert-micro/luci-interpreter/src/core/TrainingModule.h
new file mode 100644 (file)
index 0000000..9041282
--- /dev/null
@@ -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.
+ */
+
+#ifdef ENABLE_TRAINING
+
+#ifndef LUCI_INTERPRETER_CORE_TRAINING_MODULE_H
+#define LUCI_INTERPRETER_CORE_TRAINING_MODULE_H
+
+#include "core/RuntimeModule.h"
+
+#include "luci_interpreter/TrainableWeightStorage.h"
+#include "TrainingGraph.h"
+
+namespace luci_interpreter
+{
+namespace training
+{
+
+class TrainingModule
+{
+public:
+  TrainingModule(RuntimeModule *runtime_module) : _runtime_module(runtime_module)
+  {
+    // Do nothing
+  }
+
+  training::Status enableTrainingMode(training::TrainingSettings &settings,
+                                      SimpleMemoryManager *memoryManager);
+
+  training::Status disableTrainingMode(bool resetWeights);
+
+  training::Status computeGradients(const TrainingSettings &settings,
+                                    const uint8_t *label_train_data)
+  {
+    return _training_graph->computeGradients(settings, _runtime_module->_storage.get(),
+                                             &_runtime_module->_circle_reader, label_train_data);
+  }
+
+  training::Status updateWeights(const TrainingSettings &settings)
+  {
+    return _training_graph->updateWeights(settings, _runtime_module->_storage.get(),
+                                          &_runtime_module->_circle_reader);
+  }
+
+private:
+  RuntimeModule *_runtime_module;
+
+  std::unique_ptr<training::TrainingGraph> _training_graph;
+};
+
+} // namespace training
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_CORE_TRAINING_MODULE_H
+
+#endif // ENABLE_TRAINING
index 98acd13..6370a46 100644 (file)
 #include "Builders.h"
 #include "kernels/Utils.h"
 #include "PALAbs.h"
+#include "SISOKernel.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);
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-  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));
+  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 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);
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-  assert(input != nullptr);
-  assert(output != nullptr);
+  const auto input = kernel.input();
+  const auto output = kernel.output();
 
   bool is_inplace = runtime_graph->is_inplace_op(cur_op);
 
index 6e0398c..5c67e31 100644 (file)
 namespace luci_interpreter
 {
 
+namespace
+{
+
+#ifndef DIS_QUANT
+void evalQuantized(const circle::Tensor *input1, const circle::Tensor *input2,
+                   const circle::Tensor *output, const circle::AddOptions *options,
+                   BaseRuntimeGraph *runtime_graph, DataType type)
+{
+  assert(type == DataType::S16 or type == DataType::S8 && "Wrong Type");
+
+  luci_interpreter_pal::ArithmeticParams params{};
+  luci_interpreter::RuntimeShape input_shape1 =
+    kernels::getTensorRuntimeShape(input1, runtime_graph);
+  luci_interpreter::RuntimeShape input_shape2 =
+    kernels::getTensorRuntimeShape(input2, runtime_graph);
+
+  const bool need_broadcast =
+    luci_interpreter_pal::ProcessBroadcastShapes(input_shape1, input_shape2, &params);
+
+  assert(need_broadcast == false && "Broadcast for INT8 and INT16 not supported now");
+
+  params.input1_offset = -Tensor::zero_point(input1);
+  params.input2_offset = -Tensor::zero_point(input2);
+  params.output_offset = Tensor::zero_point(output);
+  params.left_shift = (type == DataType::S16) ? 15 : 20;
+
+  const auto input1_scale = Tensor::scale(input1);
+  const auto input2_scale = Tensor::scale(input2);
+  const auto output_scale = Tensor::scale(output);
+
+  const double twice_max_input_scale =
+    2 * static_cast<double>(std::max(input1_scale, input2_scale));
+  const double real_input1_multiplier = static_cast<double>(input1_scale / twice_max_input_scale);
+  const double real_input2_multiplier = static_cast<double>(input2_scale / twice_max_input_scale);
+  const double real_output_multiplier =
+    twice_max_input_scale / ((1 << params.left_shift) * static_cast<double>(output_scale));
+
+  kernels::quantizeMultiplierSmallerThanOneExp(real_input1_multiplier, &params.input1_multiplier,
+                                               &params.input1_shift);
+  kernels::quantizeMultiplierSmallerThanOneExp(real_input2_multiplier, &params.input2_multiplier,
+                                               &params.input2_shift);
+  kernels::quantizeMultiplierSmallerThanOneExp(real_output_multiplier, &params.output_multiplier,
+                                               &params.output_shift);
+
+  kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
+                                             output, &params.quantized_activation_min,
+                                             &params.quantized_activation_max);
+  if (type == DataType::S8)
+  {
+    luci_interpreter_pal::Add(
+      params, input_shape1.flatSize(),
+      kernels::getTensorData<int8_t>(runtime_graph->getDataByTensor(input1)),
+      kernels::getTensorData<int8_t>(runtime_graph->getDataByTensor(input2)),
+      kernels::getTensorData<int8_t>(runtime_graph->getDataByTensor(output)));
+  }
+  else
+  {
+    luci_interpreter_pal::Add(
+      params, input_shape1.flatSize(),
+      kernels::getTensorData<int16_t>(runtime_graph->getDataByTensor(input1)),
+      kernels::getTensorData<int16_t>(runtime_graph->getDataByTensor(input2)),
+      kernels::getTensorData<int16_t>(runtime_graph->getDataByTensor(output)));
+  }
+}
+#endif // DIS_QUANT
+
+} // namespace
+
 void configure_kernel_CircleAdd(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
   kernels::TISOKernel kernel(cur_op, runtime_graph);
@@ -59,7 +127,49 @@ void execute_kernel_CircleAdd(const circle::Operator *cur_op, BaseRuntimeGraph *
 
   bool is_inplace = runtime_graph->is_inplace_op(cur_op);
 
-  switch (Tensor::element_type(kernel.input1()))
+  // TODO remove code duplication, introduce func
+#ifndef DIS_DYN_SHAPES
+  luci_interpreter::RuntimeShape output_shape =
+    kernels::getTensorRuntimeShape(kernel.output(), runtime_graph);
+  // Dynamic shape case
+  if (not is_inplace and not(input_shape1 == output_shape) and not(input_shape2 == output_shape))
+  {
+    int32_t num_dims;
+
+    if (input_shape1.flatSize() > input_shape2.flatSize())
+    {
+      output_shape = input_shape1;
+      num_dims = input_shape1.dimensionsCount();
+    }
+    else
+    {
+      output_shape = input_shape2;
+      num_dims = input_shape2.dimensionsCount();
+    }
+
+    luci_interpreter::RuntimeShape dynamic_shape(num_dims);
+    int32_t data_size = 1;
+    for (int i = 0; i < num_dims; ++i)
+    {
+      dynamic_shape.setDim(i, output_shape.dims(i));
+      data_size *= output_shape.dims(i);
+    }
+    data_size *= size(Tensor::element_type(kernel.output()));
+
+    runtime_graph->addDynamicShapeTensor(kernel.output(), std::move(dynamic_shape));
+
+    if (data_size == 0)
+    {
+      runtime_graph->resetTensorData(nullptr, kernel.output());
+      return;
+    }
+    auto new_output_data = new uint8_t[data_size];
+    runtime_graph->resetTensorData(new_output_data, kernel.output());
+  }
+#endif // DIS_DYN_SHAPES
+
+  const auto type = Tensor::element_type(kernel.input1());
+  switch (type)
   {
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
@@ -69,13 +179,15 @@ void execute_kernel_CircleAdd(const circle::Operator *cur_op, BaseRuntimeGraph *
       if (is_inplace)
       {
         kernels::evalTISOInplaceKernel<float>(tiso_func, broadcast_tiso_func, &kernel, options,
-                                              std::move(input_shape1), std::move(input_shape2));
+                                              std::move(input_shape1), std::move(input_shape2),
+                                              std::move(output_shape));
       }
       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));
+                                       options, std::move(input_shape1), std::move(input_shape2),
+                                       std::move(output_shape));
       }
     }
     break;
@@ -87,13 +199,15 @@ void execute_kernel_CircleAdd(const circle::Operator *cur_op, BaseRuntimeGraph *
       if (is_inplace)
       {
         kernels::evalTISOInplaceKernel<int64_t>(tiso_func, broadcast_tiso_func, &kernel, options,
-                                                std::move(input_shape1), std::move(input_shape2));
+                                                std::move(input_shape1), std::move(input_shape2),
+                                                std::move(output_shape));
       }
       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));
+                                         options, std::move(input_shape1), std::move(input_shape2),
+                                         std::move(output_shape));
       }
     }
     break;
@@ -104,16 +218,27 @@ void execute_kernel_CircleAdd(const circle::Operator *cur_op, BaseRuntimeGraph *
       if (is_inplace)
       {
         kernels::evalTISOInplaceKernel<int32_t>(tiso_func, broadcast_tiso_func, &kernel, options,
-                                                std::move(input_shape1), std::move(input_shape2));
+                                                std::move(input_shape1), std::move(input_shape2),
+                                                std::move(output_shape));
       }
       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));
+                                         options, std::move(input_shape1), std::move(input_shape2),
+                                         std::move(output_shape));
       }
     }
     break;
+#ifndef DIS_QUANT
+    case DataType::S8:
+    case DataType::S16:
+    {
+      evalQuantized(kernel.input1(), kernel.input2(), kernel.output(), options, runtime_graph,
+                    type);
+    }
+    break;
+#endif
     default:
       assert(false && "Unsupported type.");
   }
index 6df81d3..591b4d5 100644 (file)
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#include "BinaryOpCommon.h"
 #include "kernels/TestUtils.h"
 #include "luci_interpreter/test_models/add/FloatAddKernel.h"
 #include "luci_interpreter/test_models/add/IntAddKernel.h"
 
 #include "loader/ModuleLoader.h"
 
+#include "PALAdd.h"
+
+#include <array>
+#include <numeric>
+
 namespace luci_interpreter
 {
 namespace
@@ -164,3 +170,72 @@ TEST_F(AddTest, No_quant_params_NEG)
 
 } // namespace
 } // namespace luci_interpreter
+
+namespace luci_interpreter
+{
+namespace
+{
+
+class PALAddTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(PALAddTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatAdd test_data_float_add_no_broadcasting(is_with_broadcast);
+
+    luci_interpreter_pal::ArithmeticParams params{};
+    kernels::fillArithmeticActivationRange<float>(params, kernels::Activation::NONE);
+
+    const auto &input1 = test_data_float_add_no_broadcasting.get_input_data_by_index(0);
+    const auto &input2 = test_data_float_add_no_broadcasting.get_input_data_by_index(1);
+
+    const auto num_elements = input1.size();
+    EXPECT_EQ(num_elements, input2.size());
+
+    std::vector<float> output = std::vector<float>(num_elements);
+    luci_interpreter_pal::Add<float>(params, num_elements, input1.data(), input2.data(),
+                                     output.data());
+
+    EXPECT_THAT(output,
+                kernels::testing::FloatArrayNear(
+                  test_data_float_add_no_broadcasting.get_output_data_by_index(0), 0.0001f));
+  }
+
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_kernel::TestDataFloatAdd test_data_float_add_with_broadcasting(is_with_broadcast);
+
+    luci_interpreter_pal::ArithmeticParams params{};
+    kernels::fillArithmeticActivationRange<float>(params, kernels::Activation::NONE);
+
+    const auto &input1 = test_data_float_add_with_broadcasting.get_input_data_by_index(0);
+    const auto &input2 = test_data_float_add_with_broadcasting.get_input_data_by_index(1);
+
+    const int32_t shape[2] = {2, 5};
+    const int32_t shape_broadcast[2] = {2, 1};
+
+    assert(input1.size() ==
+           std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    assert(input2.size() == std::accumulate(std::begin(shape_broadcast), std::end(shape_broadcast),
+                                            1, std::multiplies<float>()));
+
+    std::vector<float> output = std::vector<float>(
+      std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    luci_interpreter_pal::BroadcastAdd4DSlow<float>(
+      params, RuntimeShape{2, shape}, input1.data(), RuntimeShape{2, shape_broadcast},
+      input2.data(), RuntimeShape{2, shape}, const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output,
+                kernels::testing::FloatArrayNear(
+                  test_data_float_add_with_broadcasting.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+} // namespace
+} // namespace luci_interpreter
index ccdda84..ee09fda 100644 (file)
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-#include "Builders.h"
+#include "Pool2DCommon.h"
 
-#include "kernels/Utils.h"
 #include "PALAveragePool2D.h"
 
 namespace luci_interpreter
@@ -26,64 +25,25 @@ namespace luci_interpreter
 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);
-
-  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);
+  configure_kernel_CirclePool2DCommon(cur_op, runtime_graph);
 }
 
 void execute_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);
-
-  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 kernels::SISOKernel siso_kernel(cur_op, 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 = siso_kernel.input();
+  const auto output = siso_kernel.output();
 
   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;
+  const DataType input_type = Tensor::element_type(input);
+
+  const auto params = createPoolParams(cur_op, siso_kernel);
 
-  switch (Tensor::element_type(input))
+  switch (input_type)
   {
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
@@ -92,6 +52,14 @@ void execute_kernel_CircleAveragePool2D(const circle::Operator *cur_op,
         kernels::getTensorShape(output), kernels::getTensorData<float>(output_data));
       break;
 #endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case DataType::S8:
+    case DataType::S16:
+      luci_interpreter_pal::AveragePool(
+        params, kernels::getTensorShape(input), kernels::getTensorData<uint8_t>(input_data),
+        kernels::getTensorShape(output), kernels::getTensorData<uint8_t>(output_data), input_type);
+      break;
+#endif // DIS_QUANT
     default:
       assert(false && "Unsupported type.");
   }
index 9ebe289..747c39c 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/BatchToSpaceND.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "MISOKernel.h"
 
 #include "PALBatchToSpaceND.h"
 
 namespace luci_interpreter
 {
 
-namespace kernels
-{
-
-namespace
-{
-const int kInputMinDimensionNum = 3;
-const int kInputMaxDimensionNum = 4;
-} // namespace
-
-BatchToSpaceND::BatchToSpaceND(const Tensor *input, const Tensor *block_shape, const Tensor *crops,
-                               Tensor *output)
-  : Kernel({input, block_shape, crops}, {output})
+void configure_kernel_CircleBatchToSpaceND(const circle::Operator *cur_op,
+                                           BaseRuntimeGraph *runtime_graph)
 {
+  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);
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input3()) == DataType::S32);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.output()) >= 3);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) >= 3);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.output()) <= 4);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) <= 4);
 }
 
-void BatchToSpaceND::configure()
+void execute_kernel_CircleBatchToSpaceND(const circle::Operator *cur_op,
+                                         BaseRuntimeGraph *runtime_graph)
 {
+  kernels::MISOKernel kernel(cur_op, runtime_graph);
 
-  const auto *block_shape_data = block_shape()->data<int32_t>();
-  const auto *crops_data = crops()->data<int32_t>();
-  LUCI_INTERPRETER_CHECK(input()->shape().num_dims() >= kInputMinDimensionNum);
-  LUCI_INTERPRETER_CHECK(input()->shape().num_dims() <= kInputMaxDimensionNum);
-  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
-
-  int spatial_dims_num = input()->shape().num_dims() - 2;
-
-  LUCI_INTERPRETER_CHECK(block_shape()->shape().num_dims() == 1);
-  LUCI_INTERPRETER_CHECK(block_shape()->shape().dim(0) == spatial_dims_num);
-
-  LUCI_INTERPRETER_CHECK(crops()->shape().num_dims() == 2);
-  LUCI_INTERPRETER_CHECK(crops()->shape().dim(0) == spatial_dims_num);
-  LUCI_INTERPRETER_CHECK(crops()->shape().dim(1) == 2);
-  for (int i = 0; i < spatial_dims_num * 2; ++i)
-  {
-    LUCI_INTERPRETER_CHECK(crops_data[i] >= 0);
-  }
-
-  Shape output_shape = Shape(input()->shape().num_dims());
-  int output_batch_size = input()->shape().dim(0);
-  for (int i = 0; i < spatial_dims_num; ++i)
-  {
-    LUCI_INTERPRETER_CHECK(output_batch_size % block_shape_data[i] == 0);
-    output_batch_size = output_batch_size / block_shape_data[i];
-    output_shape.dim(i + 1) =
-      input()->shape().dim(i + 1) * block_shape_data[i] - crops_data[i * 2] - crops_data[i * 2 + 1];
-  }
-
-  output_shape.dim(0) = output_batch_size;
-  output_shape.dim(input()->shape().num_dims() - 1) =
-    input()->shape().dim(input()->shape().num_dims() - 1);
-
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(output_shape);
-}
-
-void BatchToSpaceND::execute() const
-{
-  switch (input()->element_type())
+  switch (Tensor::element_type(kernel.input1()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
+    {
       luci_interpreter_pal::BatchToSpaceND(
-        getTensorShape(input()), getTensorData<float>(input()), getTensorShape(block_shape()),
-        getTensorData<int32_t>(block_shape()), getTensorShape(crops()),
-        getTensorData<int32_t>(crops()), getTensorShape(output()), getTensorData<float>(output()));
-      break;
-    case DataType::U8:
-      luci_interpreter_pal::BatchToSpaceND(
-        getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(block_shape()),
-        getTensorData<int32_t>(block_shape()), getTensorShape(crops()),
-        getTensorData<int32_t>(crops()), getTensorShape(output()),
-        getTensorData<uint8_t>(output()));
+        kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph),
+        kernels::getTensorData<float>(runtime_graph->getDataByTensor(kernel.input1())),
+        kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph),
+        kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(kernel.input2())),
+        kernels::getTensorRuntimeShape(kernel.input3(), runtime_graph),
+        kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(kernel.input3())),
+        kernels::getTensorRuntimeShape(kernel.output(), runtime_graph),
+        kernels::getTensorData<float>(runtime_graph->getDataByTensor(kernel.output())));
       break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
 }
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h b/onert-micro/luci-interpreter/src/kernels/BatchToSpaceND.h
deleted file mode 100644 (file)
index 57703ea..0000000
+++ /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.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_BATCHTOSPACEND_H
-#define LUCI_INTERPRETER_KERNELS_BATCHTOSPACEND_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class BatchToSpaceND : public Kernel
-{
-public:
-  BatchToSpaceND(const Tensor *input, const Tensor *block_shape, const Tensor *crops,
-                 Tensor *output);
-
-  const Tensor *input() const { return _inputs[0]; }
-  const Tensor *block_shape() const { return _inputs[1]; }
-  const Tensor *crops() 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_BATCHTOSPACEND_H
index 52647a7..783d93e 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/BatchToSpaceND.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h"
+#include "luci_interpreter/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
 using namespace testing;
 
+class BatchToSpaceNDTest : public ::testing::Test
+{
+  // Do nothing
+};
+
 template <typename T>
-void Check(std::initializer_list<int32_t> input_shape,
-           std::initializer_list<int32_t> block_shape_shape,
-           std::initializer_list<int32_t> crops_shape, std::initializer_list<int32_t> output_shape,
-           std::initializer_list<T> input_data, std::initializer_list<int32_t> block_shape_data,
-           std::initializer_list<int32_t> crops_data, std::initializer_list<T> output_data)
+std::vector<T> checkBatchToSpaceNDKernel(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 block_shape_tensor =
-    makeInputTensor<DataType::S32>(block_shape_shape, block_shape_data, memory_manager.get());
-  Tensor crops_tensor =
-    makeInputTensor<DataType::S32>(crops_shape, crops_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(element_type);
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  BatchToSpaceND kernel(&input_tensor, &block_shape_tensor, &crops_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));
-  EXPECT_THAT(extractTensorShape(output_tensor), output_shape);
-}
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-template <typename T> class BatchToSpaceNDTest : 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(BatchToSpaceNDTest, DataTypes);
+  runtime_module.execute();
 
-TYPED_TEST(BatchToSpaceNDTest, Simple)
-{
-  Check<TypeParam>(/*input_shape=*/{4, 2, 2, 1}, /*block_shape_shape=*/{2}, /*crops_shape=*/{2, 2},
-                   /*output_shape=*/{1, 4, 4, 1},
-                   /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
-                   /*block_shape_data=*/{2, 2}, /*crops_data=*/{0, 0, 0, 0},
-                   /*output_data=*/{1, 5, 2, 6, 9, 13, 10, 14, 3, 7, 4, 8, 11, 15, 12, 16});
+  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(BatchToSpaceNDTest, Invalid_Shape_NEG)
+TEST_F(BatchToSpaceNDTest, Float_P)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(
-    {3, 2, 2, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, memory_manager.get());
-  Tensor block_shape_tensor = makeInputTensor<DataType::S32>({2}, {2, 2}, memory_manager.get());
-  Tensor crops_tensor = makeInputTensor<DataType::S32>({2, 2}, {0, 0, 0, 0}, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  BatchToSpaceND kernel(&input_tensor, &block_shape_tensor, &crops_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::TestDataFloatBatchToSpaceND test_data_kernel;
+  std::vector<float> output_data_vector = checkBatchToSpaceNDKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST(BatchToSpaceNDTest, Invalid_Crops_NEG)
+TEST_F(BatchToSpaceNDTest, Input_output_type_mismatch_NEG)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(
-    {4, 2, 2, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, memory_manager.get());
-  Tensor block_shape_tensor = makeInputTensor<DataType::S32>({2}, {2, 2}, memory_manager.get());
-  Tensor crops_tensor = makeInputTensor<DataType::S32>({2, 2}, {0, 0, -1, 0}, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  BatchToSpaceND kernel(&input_tensor, &block_shape_tensor, &crops_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel 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
index 1fd27ea..8ba1b18 100644 (file)
@@ -19,8 +19,9 @@
 #define LUCI_INTERPRETER_KERNELS_BINARYOPUTILS_H
 
 #include "TISOKernel.h"
+#include "PALComparisons.h"
+#include "Params.h"
 #include "ProcessBroadcastShapes.h"
-
 #include "Utils.h"
 
 namespace luci_interpreter
@@ -60,10 +61,8 @@ template <typename T, typename TISOFunc = nullptr_t, typename TISOBroadcastFunc
 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)
+                    RuntimeShape &&input_shape_2, RuntimeShape &&output_shape)
 {
-  const auto *output = kernel->output();
-
   luci_interpreter_pal::ArithmeticParams params{};
   fillArithmeticActivationRange<T>(params, luci_actfunc(options->fused_activation_function()));
 
@@ -74,8 +73,7 @@ void evalTISOKernel(TISOFunc tiso_func, TISOBroadcastFunc tiso_broadcast_func,
   {
     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));
+                        output_shape, kernels::getTensorData<T>(kernel_data->output_data));
   }
   else
   {
@@ -90,7 +88,8 @@ template <typename T, typename TISOFunc = nullptr_t, typename TISOBroadcastFunc
           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)
+                           RuntimeShape &&input_shape_1, RuntimeShape &&input_shape_2,
+                           RuntimeShape &&output_shape)
 {
   uint8_t *inplace_data_ptr = nullptr;
   circle::Tensor *input_inplace_tensor = nullptr;
@@ -99,7 +98,7 @@ void evalTISOInplaceKernel(TISOFunc tiso_func, TISOBroadcastFunc tiso_broadcast_
 
   evalTISOKernel<T, TISOFunc, TISOBroadcastFunc, Options>(
     tiso_func, tiso_broadcast_func, kernel, &kernel_data, options, std::move(input_shape_1),
-    std::move(input_shape_2));
+    std::move(input_shape_2), std::move(output_shape));
 
   BaseRuntimeGraph *runtime_graph = kernel->runtime_graph();
 
@@ -114,6 +113,14 @@ void evalTISOInplaceKernel(TISOFunc tiso_func, TISOBroadcastFunc tiso_broadcast_
   }
 }
 
+inline void CheckBinaryOpDataTypesEqual(const kernels::TISOKernel &kernel)
+{
+  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.output()));
+}
+
 #ifndef DIS_QUANT
 template <typename T, typename TISOFunc = nullptr_t, typename TISOBroadcastFunc = nullptr_t,
           typename Options = nullptr_t>
diff --git a/onert-micro/luci-interpreter/src/kernels/BroadcastTo.cpp b/onert-micro/luci-interpreter/src/kernels/BroadcastTo.cpp
new file mode 100644 (file)
index 0000000..e0c243e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PALBroadcastTo.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+constexpr int kMaxDims = 5;
+} // namespace
+
+void configure_kernel_CircleBroadcastTo(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.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32 or
+                         Tensor::element_type(kernel.input2()) == DataType::S64);
+
+  // Ensure output dims is not less than input dims.
+  int input_num_dims = Tensor::num_dims(kernel.input1());
+  int output_num_dims = Tensor::num_dims(kernel.output());
+  int shape_num_dims = Tensor::dim(kernel.input2(), 0);
+
+  LUCI_INTERPRETER_CHECK(output_num_dims == shape_num_dims);
+  LUCI_INTERPRETER_CHECK(input_num_dims <= output_num_dims);
+  LUCI_INTERPRETER_CHECK(output_num_dims <= kMaxDims);
+}
+
+void execute_kernel_CircleBroadcastTo(const circle::Operator *cur_op,
+                                      BaseRuntimeGraph *runtime_graph)
+{
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+  const auto *input_data = runtime_graph->getDataByTensor(kernel.input1());
+  assert(input_data);
+
+  auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+  luci_interpreter_pal::BroadcastTo<kMaxDims>(
+    kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph), input_data,
+    kernels::getTensorRuntimeShape(kernel.output(), runtime_graph), output_data,
+    Tensor::element_type(kernel.input1()));
+}
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/BroadcastTo.test.cpp b/onert-micro/luci-interpreter/src/kernels/BroadcastTo.test.cpp
new file mode 100644 (file)
index 0000000..2183259
--- /dev/null
@@ -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 "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/broadcast_to/FloatBroadcastToKernel.h"
+#include "luci_interpreter/test_models/broadcast_to/NegBroadcastToKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class BroadcastToTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T> std::vector<T> checkCeilKernel(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(BroadcastToTest, Float_P)
+{
+  test_kernel::TestDataFloatBroadcastTo test_data_kernel;
+  std::vector<float> output_data_vector = checkCeilKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(BroadcastToTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchBroadcastToKernel 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
index a49f71e..98dca06 100644 (file)
@@ -46,6 +46,21 @@ using BaseRuntimeGraph = RuntimeGraph;
 
 #undef REGISTER_KERNEL
 
+#ifdef ENABLE_TRAINING
+namespace training
+{
+#define REGISTER_TRAIN_KERNEL(builtin_operator, name)                                           \
+  Status train_kernel_Circle##name(                                                             \
+    const circle::Operator *op, CircleReader *reader,                                           \
+    GradientCalculationStorage *gradient_calculation_storage, const TrainingSettings &settings, \
+    TrainableWeightStorage *weight_storage, bool is_compute_gradient);
+
+#include "KernelsToTrain.lst"
+
+#undef REGISTER_TRAIN_KERNEL
+} // namespace training
+#endif // ENABLE_TRAINING
+
 } // namespace luci_interpreter
 
 #endif // LUCI_INTERPRETER_KERNELS_NODES_BUILDERS_H
index 66c0a9e..d0822bc 100644 (file)
@@ -8,12 +8,19 @@ set(SOURCES
         SISOKernel.h
         TISOKernel.h
         MISOKernel.h
-        PadCommon.cpp)
+        PadCommon.cpp
+        ConvolutionCommon.cpp)
 
 macro(REGISTER_KERNEL OPERATOR, NODE)
   list(APPEND SOURCES "${NODE}.cpp")
 endmacro(REGISTER_KERNEL)
 
+macro(REGISTER_TRAIN_KERNEL OPERATOR, NODE)
+  list(APPEND SOURCES "${NODE}.train.cpp")
+endmacro(REGISTER_TRAIN_KERNEL)
+
+include("${LUCI_INTERPRETER_PAL_DIR}/KernelsToTrain.lst")
+
 include(${KERNEL_REGISTER_FILE})
 
 add_library(${LUCI_INTERPRETER_KERNELS} STATIC ${SOURCES})
index 82b187a..c336c79 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Cast.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "SISOKernel.h"
 
+namespace luci_interpreter
+{
 namespace
 {
 
-using namespace luci_interpreter;
-using namespace luci_interpreter::kernels;
-
-template <typename InT, typename OutT>
-void cast_data(const InT *in_data, OutT *out_data, uint32_t elements_count)
+template <typename FromT, typename ToT> void copyCast(const FromT *in, ToT *out, int num_elements)
 {
-  std::transform(in_data, in_data + elements_count, out_data,
-                 [](InT a) { return static_cast<OutT>(a); });
+  std::transform(in, in + num_elements, out, [](FromT a) { return static_cast<ToT>(a); });
 }
 
-template <typename InT> void cast_from_pointer_to_tensor(const InT *in_data, Tensor *out_tensor)
-{
-  auto const out_type = out_tensor->element_type();
-  auto const elements_count = out_tensor->shape().num_elements();
-
-  switch (out_type)
-  {
-    case DataType::U8:
-      cast_data(in_data, getTensorData<uint8_t>(out_tensor), elements_count);
-      break;
-    case DataType::U16:
-      cast_data(in_data, getTensorData<uint16_t>(out_tensor), elements_count);
-      break;
-    case DataType::U32:
-      cast_data(in_data, getTensorData<uint32_t>(out_tensor), elements_count);
-      break;
-    case DataType::U64:
-      cast_data(in_data, getTensorData<uint64_t>(out_tensor), elements_count);
-      break;
-    case DataType::S8:
-      cast_data(in_data, getTensorData<int8_t>(out_tensor), elements_count);
-      break;
-    case DataType::S16:
-      cast_data(in_data, getTensorData<int16_t>(out_tensor), elements_count);
-      break;
-    case DataType::S32:
-      cast_data(in_data, getTensorData<int32_t>(out_tensor), elements_count);
-      break;
-    case DataType::S64:
-      cast_data(in_data, getTensorData<int64_t>(out_tensor), elements_count);
-      break;
-    case DataType::FLOAT32:
-      cast_data(in_data, getTensorData<float>(out_tensor), elements_count);
-      break;
-    case DataType::BOOL:
-      cast_data(in_data, getTensorData<bool>(out_tensor), elements_count);
-      break;
-    default:
-      assert(false && "Unsupported output type.");
-  }
-}
+} // namespace
 
-void cast_from_tensor_to_tensor(const Tensor *in_tensor, Tensor *out_tensor)
+void configure_kernel_CircleCast(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  auto in_type = in_tensor->element_type();
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-  switch (in_type)
-  {
-    case DataType::U8:
-      cast_from_pointer_to_tensor(getTensorData<uint8_t>(in_tensor), out_tensor);
-      break;
-    case DataType::U16:
-      cast_from_pointer_to_tensor(getTensorData<uint16_t>(in_tensor), out_tensor);
-      break;
-    case DataType::U32:
-      cast_from_pointer_to_tensor(getTensorData<uint32_t>(in_tensor), out_tensor);
-      break;
-    case DataType::U64:
-      cast_from_pointer_to_tensor(getTensorData<uint64_t>(in_tensor), out_tensor);
-      break;
-    case DataType::S8:
-      cast_from_pointer_to_tensor(getTensorData<int8_t>(in_tensor), out_tensor);
-      break;
-    case DataType::S16:
-      cast_from_pointer_to_tensor(getTensorData<int16_t>(in_tensor), out_tensor);
-      break;
-    case DataType::S32:
-      cast_from_pointer_to_tensor(getTensorData<int32_t>(in_tensor), out_tensor);
-      break;
-    case DataType::S64:
-      cast_from_pointer_to_tensor(getTensorData<int64_t>(in_tensor), out_tensor);
-      break;
-    case DataType::FLOAT32:
-      cast_from_pointer_to_tensor(getTensorData<float>(in_tensor), out_tensor);
-      break;
-    case DataType::BOOL:
-      cast_from_pointer_to_tensor(getTensorData<bool>(in_tensor), out_tensor);
-      break;
-    default:
-      assert(false && "Unsupported input type.");
-  }
+  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()));
 }
 
-} // namespace
-
-namespace luci_interpreter
-{
-namespace kernels
+void execute_kernel_CircleCast(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-Cast::Cast(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+  const auto *input_data = runtime_graph->getDataByTensor(kernel.input());
+  assert(input_data);
 
-void Cast::configure()
-{
-  LUCI_INTERPRETER_CHECK(input()->element_type() != DataType::Unknown);
-  LUCI_INTERPRETER_CHECK(output()->element_type() != DataType::Unknown);
-
-  const Shape &shape = input()->shape();
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(shape);
-}
+  auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+  assert(output_data);
 
-void Cast::execute() const
-{
-  assert(input()->shape().num_elements() == output()->shape().num_elements());
+  const int flat_size = kernels::getTensorRuntimeShape(kernel.input(), runtime_graph).flatSize();
 
-  cast_from_tensor_to_tensor(input(), output());
+  switch (Tensor::element_type(kernel.input()))
+  {
+#ifndef DIS_FLOAT
+    case DataType::FLOAT32:
+    {
+      const float *input_data_float = kernels::getTensorData<float>(input_data);
+
+      switch (Tensor::element_type(kernel.output()))
+      {
+        case DataType::S8:
+          copyCast(input_data_float, kernels::getTensorData<int8_t>(output_data), flat_size);
+          break;
+        case DataType::S16:
+          copyCast(input_data_float, kernels::getTensorData<int16_t>(output_data), flat_size);
+          break;
+        case DataType::S32:
+          copyCast(input_data_float, kernels::getTensorData<int32_t>(output_data), flat_size);
+          break;
+        default:
+          assert(false && "Not supported type");
+      }
+      break;
+    }
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
+  }
 }
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Cast.h b/onert-micro/luci-interpreter/src/kernels/Cast.h
deleted file mode 100644 (file)
index f0bd020..0000000
+++ /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.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_CAST_H
-#define LUCI_INTERPRETER_KERNELS_CAST_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Cast : public Kernel
-{
-public:
-  Cast(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;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_CAST_H
index 4713ad3..c352654 100644 (file)
@@ -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.
  * limitations under the License.
  */
 
-#include "kernels/Cast.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/cast/FloatCastKernel.h"
+#include "luci_interpreter/test_models/cast/NegCastKernel.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> shape, std::initializer_list<T1> input_data,
-           std::initializer_list<T2> output_data)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  constexpr DataType input_type = getElementType<T1>();
-  constexpr DataType output_type = getElementType<T2>();
-
-  Tensor input_tensor = makeInputTensor<input_type>(shape, input_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(output_type);
-
-  Cast kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<T2>(output_tensor), ::testing::ElementsAreArray(output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), shape);
-}
-
-template <typename T>
-void CheckBoolTo(std::initializer_list<int32_t> shape, std::initializer_list<bool> input_data,
-                 std::initializer_list<T> output_data)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  constexpr DataType input_type = loco::DataType::BOOL;
-  constexpr DataType output_type = getElementType<T>();
-  std::vector<typename DataTypeImpl<input_type>::Type> input_data_converted;
-  for (auto elem : input_data)
-  {
-    input_data_converted.push_back(elem);
-  }
-
-  Tensor input_tensor =
-    makeInputTensor<input_type>(shape, input_data_converted, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(output_type);
-
-  Cast kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), shape);
-}
-
-template <typename T> class CastTest : public ::testing::Test
+class CastTest : public ::testing::Test
 {
+  // Do nothing
 };
 
-using IntDataTypes =
-  ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t>;
-TYPED_TEST_SUITE(CastTest, IntDataTypes);
-
-TYPED_TEST(CastTest, FloatToInt)
-{
-  Check<float, TypeParam>(/*shape=*/{1, 1, 1, 4},
-                          /*input_data=*/
-                          {
-                            1.0f, 9.0f, 7.0f, 3.0f, //
-                          },
-                          /*output_data=*/
-                          {
-                            1, 9, 7, 3, //
-                          });
-  SUCCEED();
-}
-
-TYPED_TEST(CastTest, IntToFloat)
+template <typename T, typename U>
+std::vector<U> checkCastKernel(test_kernel::TestDataBase<T, U> *test_data_base)
 {
-  Check<TypeParam, float>(/*shape=*/{1, 1, 1, 4},
-                          /*input_data=*/
-                          {
-                            1, 9, 7, 3, //
-                          },
-                          /*output_data=*/
-                          {
-                            1.0f, 9.0f, 7.0f, 3.0f, //
-                          });
-  SUCCEED();
-}
-
-template <typename T1, typename T2> void check_int()
-{
-  Check<T1, T2>(/*shape=*/{1, 1, 1, 4},
-                /*input_data=*/
-                {
-                  1, 9, 7, 3, //
-                },
-                /*output_data=*/
-                {
-                  1, 9, 7, 3, //
-                });
-  SUCCEED();
-}
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-TYPED_TEST(CastTest, IntToInt)
-{
-  check_int<TypeParam, uint8_t>();
-  check_int<TypeParam, uint16_t>();
-  check_int<TypeParam, uint32_t>();
-  check_int<TypeParam, uint64_t>();
-  check_int<TypeParam, int8_t>();
-  check_int<TypeParam, int16_t>();
-  check_int<TypeParam, int32_t>();
-  check_int<TypeParam, int64_t>();
-  SUCCEED();
-}
+  // 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);
 
-TYPED_TEST(CastTest, IntToBool)
-{
-  Check<TypeParam, bool>(/*shape=*/{1, 1, 1, 4},
-                         /*input_data=*/
-                         {
-                           1, 0, 7, 0, //
-                         },
-                         /*output_data=*/
-                         {
-                           true, false, true, false, //
-                         });
-  SUCCEED();
-}
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-TYPED_TEST(CastTest, BoolToInt)
-{
-  CheckBoolTo<TypeParam>(/*shape=*/{1, 1, 1, 4},
-                         /*input_data=*/
-                         {
-                           true, false, false, true, //
-                         },
-                         /*output_data=*/
-                         {
-                           1, 0, 0, 1, //
-                         });
-  SUCCEED();
-}
+  // 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(CastTest, FloatToBool)
-{
-  Check<float, bool>(/*shape=*/{1, 1, 1, 4},
-                     /*input_data=*/
-                     {
-                       1.0f, 0.0f, 7.0f, 0.0f, //
-                     },
-                     /*output_data=*/
-                     {
-                       true, false, true, false, //
-                     });
-  SUCCEED();
-}
+  runtime_module.execute();
 
-TEST(CastTest, BoolToFloat)
-{
-  CheckBoolTo<float>(/*shape=*/{1, 1, 1, 4},
-                     /*input_data=*/
-                     {
-                       true, false, false, true, //
-                     },
-                     /*output_data=*/
-                     {
-                       1.0f, 0.0f, 0.0f, 1.0f, //
-                     });
-  SUCCEED();
-}
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-TEST(CastTest, FloatToFloat)
-{
-  Check<float, float>(/*shape=*/{1, 1, 1, 4},
-                      /*input_data=*/
-                      {
-                        1.0f, 0.0f, 7.0f, 0.0f, //
-                      },
-                      /*output_data=*/
-                      {
-                        1.0f, 0.0f, 7.0f, 0.0f, //
-                      });
-  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(CastTest, BoolToBool)
+TEST_F(CastTest, Float_P)
 {
-  CheckBoolTo<bool>(/*shape=*/{1, 1, 1, 4},
-                    /*input_data=*/
-                    {
-                      true, true, false, false, //
-                    },
-                    /*output_data=*/
-                    {
-                      true, true, false, false, //
-                    });
-  SUCCEED();
+  test_kernel::TestDataFloatCast test_data_kernel;
+  std::vector<int32_t> output_data_vector = checkCastKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
 }
 
-TEST(CastTest, UnsupportedType_NEG)
+TEST_F(CastTest, 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 output_tensor = makeOutputTensor(DataType::Unknown);
-
-  Cast kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-  SUCCEED();
+  test_kernel::NegTestDataInputOutputShapeMismatchCeilKernel 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/Ceil.cpp b/onert-micro/luci-interpreter/src/kernels/Ceil.cpp
new file mode 100644 (file)
index 0000000..970a901
--- /dev/null
@@ -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 "Builders.h"
+#include "kernels/Utils.h"
+#include "SISOKernel.h"
+
+#include "PALCeil.h"
+
+namespace luci_interpreter
+{
+
+void configure_kernel_CircleCeil(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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 execute_kernel_CircleCeil(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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:
+    {
+      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::Ceil(flat_size, input_data_float, output_data_float);
+      break;
+    }
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
+  }
+
+  if (is_inplace)
+    runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
+}
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Ceil.test.cpp b/onert-micro/luci-interpreter/src/kernels/Ceil.test.cpp
new file mode 100644 (file)
index 0000000..3e8e6b1
--- /dev/null
@@ -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 "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/ceil/FloatCeilKernel.h"
+#include "luci_interpreter/test_models/ceil/NegCeilKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class CeilTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T> std::vector<T> checkCeilKernel(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(CeilTest, Float_P)
+{
+  test_kernel::TestDataFloatCeil test_data_kernel;
+  std::vector<float> output_data_vector = checkCeilKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(CeilTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchCeilKernel 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/ComparisonCommon.h b/onert-micro/luci-interpreter/src/kernels/ComparisonCommon.h
new file mode 100644 (file)
index 0000000..f784acc
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_COMPARISONCOMMON_H
+#define LUCI_INTERPRETER_KERNELS_COMPARISONCOMMON_H
+
+#include "Builders.h"
+
+#include "kernels/Utils.h"
+#include "PALComparisons.h"
+
+namespace luci_interpreter
+{
+namespace kernels
+{
+
+template <typename T>
+void evalComparisonGeneric(const circle::Tensor *x, const circle::Tensor *y,
+                           const circle::Tensor *output, BaseRuntimeGraph *runtime_graph,
+                           bool F(T, T))
+{
+  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);
+
+  if (op_params.is_broadcast)
+  {
+    luci_interpreter_pal::BroadcastComparison4DSlowNoScaling<T>(
+      op_params, kernels::getTensorShape(x), x_data, kernels::getTensorShape(y), y_data,
+      kernels::getTensorShape(output), output_data, F);
+  }
+  else
+  {
+    const int64_t flat_size = kernels::getTensorShape(x).flatSize();
+    luci_interpreter_pal::ComparisonNoScaling<T>(flat_size, x_data, y_data, output_data, F);
+  }
+}
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_COMPARISONCOMMON_H
index 75bccbc..eb8714b 100644 (file)
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-#include "Builders.h"
+#include "ConvolutionCommon.h"
 #include "kernels/Utils.h"
 
 #include "PALConv2d.h"
@@ -26,55 +26,13 @@ namespace luci_interpreter
 namespace
 {
 
-int32_t compute_padding_h(const circle::Tensor *input, const circle::Tensor *filter,
-                          const circle::Conv2DOptions *options)
-{
-  const int32_t input_height = Tensor::dim(input, 1);
-  const int32_t filter_height = Tensor::dim(filter, 1);
-  const int32_t output_height =
-    kernels::computeOutputSize(luci_padding(options->padding()), input_height, filter_height,
-                               options->stride_h(), options->dilation_h_factor());
-
-  const auto padding_height = kernels::computePadding(
-    options->stride_h(), options->dilation_h_factor(), input_height, filter_height, output_height);
-  return padding_height;
-}
-
-int32_t compute_padding_w(const circle::Tensor *input, const circle::Tensor *filter,
-                          const circle::Conv2DOptions *options)
-{
-  const int32_t input_width = Tensor::dim(input, 2);
-  const int32_t filter_width = Tensor::dim(filter, 2);
-  const int32_t output_width =
-    kernels::computeOutputSize(luci_padding(options->padding()), input_width, filter_width,
-                               options->stride_w(), options->dilation_w_factor());
-
-  const auto padding_width = kernels::computePadding(
-    options->stride_w(), options->dilation_w_factor(), input_width, filter_width, output_width);
-
-  return padding_width;
-}
-
 #ifndef DIS_FLOAT
 
 void evalFloat(const circle::Tensor *input, const circle::Tensor *filter,
                const circle::Tensor *bias, const circle::Tensor *output,
                const circle::Conv2DOptions *options, BaseRuntimeGraph *runtime_graph)
 {
-  float activation_min{};
-  float activation_max{};
-  kernels::calculateActivationRange(luci_actfunc(options->fused_activation_function()),
-                                    &activation_min, &activation_max);
-
-  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();
-  params.stride_width = options->stride_w();
-  params.dilation_height_factor = options->dilation_h_factor();
-  params.dilation_width_factor = options->dilation_w_factor();
-  params.float_activation_min = activation_min;
-  params.float_activation_max = activation_max;
+  const auto params = createConv2DParams(input, filter, output, options);
 
   auto *input_data = runtime_graph->getDataByTensor(input);
   auto *output_data = runtime_graph->getDataByTensor(output);
@@ -105,35 +63,7 @@ void evalQuantized(const circle::Tensor *input, const circle::Tensor *filter,
                    const circle::Tensor *bias, const circle::Tensor *output,
                    const circle::Conv2DOptions *options, BaseRuntimeGraph *runtime_graph)
 {
-  const auto input_scale = static_cast<double>(Tensor::scale(input));
-  const auto filter_scale = static_cast<double>(Tensor::scale(filter));
-  const auto output_scale = static_cast<double>(Tensor::scale(output));
-
-  const double real_multiplier = input_scale * filter_scale / output_scale;
-  int32_t output_multiplier{};
-  int output_shift{};
-  kernels::quantizeMultiplier(real_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::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 input and filter zero points to be negated.
-  params.input_offset = -Tensor::zero_point(input);    // Note the '-'.
-  params.weights_offset = -Tensor::zero_point(filter); // Note the '-'.
-  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 auto params = createConv2DParams(input, filter, output, options);
 
   auto *input_data = runtime_graph->getDataByTensor(input);
   auto *output_data = runtime_graph->getDataByTensor(output);
@@ -158,7 +88,8 @@ void evalQuantized(const circle::Tensor *input, const circle::Tensor *filter,
 
 void evalQuantizedPerChannel(const circle::Tensor *input, const circle::Tensor *filter,
                              const circle::Tensor *bias, const circle::Tensor *output,
-                             const circle::Conv2DOptions *options, BaseRuntimeGraph *runtime_graph)
+                             const circle::Conv2DOptions *options, BaseRuntimeGraph *runtime_graph,
+                             DataType type)
 {
   auto *raw_input_data = runtime_graph->getDataByTensor(input);
   auto *raw_output_data = runtime_graph->getDataByTensor(output);
@@ -166,10 +97,27 @@ void evalQuantizedPerChannel(const circle::Tensor *input, const circle::Tensor *
   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 auto params = createConv2DParams(input, filter, output, options);
+
+  if (type == DataType::S8)
+  {
+    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::QuantizedConvPerChannel(
+      params, input_shape, kernels::getTensorData<int8_t>(raw_input_data), filter_shape,
+      kernels::getTensorData<int8_t>(raw_filter_data),
+      kernels::getTensorData<int32_t>(raw_bias_data), output_shape,
+      kernels::getTensorData<int8_t>(raw_output_data));
+
+    return;
+  }
 
   const int32_t batches = Tensor::dim(input, 0);
   const int32_t input_height = Tensor::dim(input, 1);
@@ -181,19 +129,30 @@ void evalQuantizedPerChannel(const circle::Tensor *input, const circle::Tensor *
   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();
+  const int32_t padding_h = params.padding_values.height;
+  const int32_t padding_w = params.padding_values.width;
+  const int32_t stride_height = params.stride_height;
+  const int32_t stride_width = params.stride_width;
+  const int32_t dilation_height_factor = params.dilation_height_factor;
+  const int32_t dilation_width_factor = params.dilation_width_factor;
 
-  int32_t activation_min{};
-  int32_t activation_max{};
-  kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
-                                             output, &activation_min, &activation_max);
+  const int32_t activation_min = params.quantized_activation_min;
+  const int32_t activation_max = params.quantized_activation_max;
 
   const std::vector<double> effective_output_scale = kernels::getQuantizedConvolutionMultiplers(
     Tensor::scale(input), Tensor::scales(filter), Tensor::scale(output));
 
+  // Type U8
+
+  const auto *input_data = kernels::getTensorData<uint8_t>(raw_input_data);
+  assert(input_data != nullptr);
+  const auto *filter_data = kernels::getTensorData<uint8_t>(raw_filter_data);
+  assert(filter_data != nullptr);
+  const auto *bias_data = kernels::getTensorData<int32_t>(raw_bias_data);
+  assert(bias_data != nullptr);
+  auto *output_data = kernels::getTensorData<uint8_t>(raw_output_data);
+  assert(output_data != nullptr);
+
   const std::vector<kernels::ChannelQuantMultipliers> multipliers_raw =
     kernels::quantizeMultipliers(effective_output_scale);
   kernels::BroadcastableWrapper<kernels::ChannelQuantMultipliers> quant_multipliers(
@@ -207,10 +166,8 @@ void evalQuantizedPerChannel(const circle::Tensor *input, const circle::Tensor *
       {
         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);
+          const int32_t in_y_origin = out_y * stride_height - padding_h;
+          const int32_t in_x_origin = out_x * stride_width - padding_w;
           int32_t acc = 0;
           for (int32_t filter_y = 0; filter_y < filter_height; ++filter_y)
           {
@@ -255,22 +212,12 @@ void evalQuantizedPerChannel(const circle::Tensor *input, const circle::Tensor *
 
 void configure_kernel_CircleConv2D(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  const auto input_index = cur_op->inputs()->operator[](0);
-  const auto filter_index = cur_op->inputs()->operator[](1);
-  const auto bias_index = cur_op->inputs()->operator[](2);
-  const auto output_index = cur_op->outputs()->operator[](0);
-
-  assert(input_index != -1);
-  assert(filter_index != -1);
-  assert(output_index != -1);
-
-  const auto input = runtime_graph->getCircleTensorByIndex(input_index);
-  const auto filter = runtime_graph->getCircleTensorByIndex(filter_index);
-  const auto bias = runtime_graph->getCircleTensorByIndex(bias_index);
-  const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+  kernels::DownsamplingConv2DKernel kernel(cur_op, runtime_graph);
 
-  assert(input != nullptr);
-  assert(filter != nullptr);
+  const auto input = kernel.input();
+  const auto filter = kernel.filter();
+  const auto bias = kernel.bias();
+  const auto output = kernel.output();
 
   auto filter_data = runtime_graph->getConstDataByTensor(filter);
 
@@ -334,27 +281,17 @@ void configure_kernel_CircleConv2D(const circle::Operator *cur_op, BaseRuntimeGr
 
 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);
-  const auto bias_index = cur_op->inputs()->operator[](2);
-  const auto output_index = cur_op->outputs()->operator[](0);
+  kernels::DownsamplingConv2DKernel kernel(cur_op, runtime_graph);
 
-  assert(input_index != -1);
-  assert(weight_index != -1);
-  assert(output_index != -1);
-
-  const auto input = runtime_graph->getCircleTensorByIndex(input_index);
-  const auto weights = runtime_graph->getCircleTensorByIndex(weight_index);
-  const auto bias = runtime_graph->getCircleTensorByIndex(bias_index);
-  const auto output = runtime_graph->getCircleTensorByIndex(output_index);
-
-  assert(input != nullptr);
-  assert(weights != nullptr);
-  assert(output != nullptr);
+  const auto input = kernel.input();
+  const auto weights = kernel.filter();
+  const auto bias = kernel.bias();
+  const auto output = kernel.output();
 
   const auto *options = cur_op->builtin_options_as_Conv2DOptions();
 
-  switch (Tensor::element_type(input))
+  const auto type = Tensor::element_type(input);
+  switch (type)
   {
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
@@ -366,7 +303,8 @@ void execute_kernel_CircleConv2D(const circle::Operator *cur_op, BaseRuntimeGrap
 #endif // DIS_FLOAT
 #ifndef DIS_QUANT
     case DataType::U8:
-      if (Tensor::scales(weights).size() == 1)
+    case DataType::S8:
+      if (Tensor::scales(weights).size() == 1 and type == DataType::U8)
       {
         evalQuantized(input, weights, bias, output, options, runtime_graph);
       }
@@ -375,7 +313,11 @@ void execute_kernel_CircleConv2D(const circle::Operator *cur_op, BaseRuntimeGrap
         LUCI_INTERPRETER_CHECK(Tensor::num_dims(weights) == 4);
         LUCI_INTERPRETER_CHECK(Tensor::scales(weights).size() ==
                                static_cast<size_t>(Tensor::dim(weights, 0)));
-        evalQuantizedPerChannel(input, weights, bias, output, options, runtime_graph);
+        evalQuantizedPerChannel(input, weights, bias, output, options, runtime_graph, type);
+      }
+      else
+      {
+        assert(false && "Unsupported yet.");
       }
       break;
 #endif // DIS_QUANT
index c373bd2..d05bd0a 100644 (file)
@@ -104,9 +104,9 @@ TEST_F(Conv2DTest, Wrong_bias_type_NEG)
                "");
 }
 
-TEST_F(Conv2DTest, Invalid_input_type_NEG)
+TEST_F(Conv2DTest, Invalid_input_shape_NEG)
 {
-  test_kernel::NegTestDataInvalidInputTypeConv2DKernel test_data_kernel;
+  test_kernel::NegTestDataInvalidInputShapeConv2DKernel test_data_kernel;
 
   MemoryManager memory_manager{};
   RuntimeModule runtime_module{};
diff --git a/onert-micro/luci-interpreter/src/kernels/ConvolutionCommon.cpp b/onert-micro/luci-interpreter/src/kernels/ConvolutionCommon.cpp
new file mode 100644 (file)
index 0000000..ef39c6e
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ConvolutionCommon.h"
+
+#include "Utils.h"
+
+namespace luci_interpreter
+{
+
+namespace
+{
+
+bool isSupportedQuantized(const circle::Tensor *input, const circle::Tensor *weights)
+{
+  return Tensor::element_type(input) == DataType::U8 and Tensor::scales(weights).size() == 1;
+}
+
+bool isSupportedQuantizedPerChannel(const circle::Tensor *input, const circle::Tensor *weights)
+{
+  return (Tensor::element_type(input) == DataType::U8 or
+          Tensor::element_type(input) == DataType::S8) and
+         Tensor::scales(weights).size() > 1;
+}
+
+} // namespace
+
+int32_t computeConvPadding(const circle::Tensor *input, const circle::Tensor *filter,
+                           circle::Padding padding_type, int32_t stride, int32_t dilation, int axis)
+{
+  const int32_t input_dim = Tensor::dim(input, axis);
+  const int32_t filter_dim = Tensor::dim(filter, axis);
+  const int32_t output_dim =
+    kernels::computeOutputSize(luci_padding(padding_type), input_dim, filter_dim, stride, dilation);
+
+  const auto padding = kernels::computePadding(stride, dilation, input_dim, filter_dim, output_dim);
+
+  return padding;
+}
+
+luci_interpreter_pal::ConvParams createConv2DParams(const circle::Tensor *input,
+                                                    const circle::Tensor *filter,
+                                                    const circle::Tensor *output,
+                                                    const circle::Conv2DOptions *options)
+{
+  luci_interpreter_pal::ConvParams params{};
+
+  if (isSupportedQuantized(input, filter))
+  {
+#ifndef DIS_QUANT
+    const auto input_scale = static_cast<double>(Tensor::scale(input));
+    const auto filter_scale = static_cast<double>(Tensor::scale(filter));
+    const auto output_scale = static_cast<double>(Tensor::scale(output));
+
+    const double real_multiplier = input_scale * filter_scale / output_scale;
+    int32_t output_multiplier{};
+    int output_shift{};
+    kernels::quantizeMultiplier(real_multiplier, &output_multiplier, &output_shift);
+
+    params.output_multiplier = output_multiplier;
+    params.output_shift = output_shift;
+
+    int32_t activation_min{};
+    int32_t activation_max{};
+    kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
+                                               output, &activation_min, &activation_max);
+
+    // The kernel expects input and filter zero points to be negated.
+    params.input_offset = -Tensor::zero_point(input);    // Note the '-'.
+    params.weights_offset = -Tensor::zero_point(filter); // Note the '-'.
+    params.output_offset = Tensor::zero_point(output);
+    params.quantized_activation_min = activation_min;
+    params.quantized_activation_max = activation_max;
+#endif // DIS_QUANT
+  }
+  else if (isSupportedQuantizedPerChannel(input, filter))
+  {
+#ifndef DIS_QUANT
+    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));
+
+    size_t n = effective_output_scale.size();
+    params.per_channel_output_shift.resize(n);
+    params.per_channel_output_multiplier.resize(n);
+    for (size_t i = 0; i < n; ++i)
+    {
+      kernels::quantizeMultiplier(effective_output_scale[i],
+                                  &params.per_channel_output_multiplier[i],
+                                  &params.per_channel_output_shift[i]);
+
+      // The kernel expects input and filter zero points to be negated.
+      params.input_offset = -Tensor::zero_point(input);    // Note the '-'.
+      params.weights_offset = -Tensor::zero_point(filter); // Note the '-'.
+      params.output_offset = Tensor::zero_point(output);
+      params.quantized_activation_min = activation_min;
+      params.quantized_activation_max = activation_max;
+    }
+#endif // DIS_QUANT
+  }
+  else if (Tensor::element_type(input) == DataType::FLOAT32 and
+           Tensor::element_type(filter) == DataType::FLOAT32)
+  {
+#ifndef DIS_FLOAT
+    float activation_min{};
+    float activation_max{};
+    kernels::calculateActivationRange(luci_actfunc(options->fused_activation_function()),
+                                      &activation_min, &activation_max);
+
+    params.float_activation_min = activation_min;
+    params.float_activation_max = activation_max;
+#endif // DIS_FLOAT
+  }
+  else
+  {
+    assert(false && "Not supported type");
+  }
+
+  const auto padding = options->padding();
+  const auto stride_height = options->stride_h();
+  const auto stride_width = options->stride_w();
+  const auto dilation_height_factor = options->dilation_h_factor();
+  const auto dilation_width_factor = options->dilation_h_factor();
+
+  params.padding_values.height =
+    computeConvPadding(input, filter, padding, stride_height, dilation_height_factor, 1);
+  params.padding_values.width =
+    computeConvPadding(input, filter, padding, stride_width, dilation_width_factor, 2);
+  params.stride_height = stride_height;
+  params.stride_width = stride_width;
+  params.dilation_height_factor = dilation_height_factor;
+  params.dilation_width_factor = dilation_width_factor;
+
+  return params;
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ConvolutionCommon.h b/onert-micro/luci-interpreter/src/kernels/ConvolutionCommon.h
new file mode 100644 (file)
index 0000000..4974433
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_CONVOLUTIONCOMMON_H
+#define LUCI_INTERPRETER_KERNELS_CONVOLUTIONCOMMON_H
+
+#include "Builders.h"
+#include "Utils.h"
+
+namespace luci_interpreter
+{
+
+int32_t computeConvPadding(const circle::Tensor *input, const circle::Tensor *filter,
+                           circle::Padding padding, int32_t stride, int32_t dilation, int axis);
+
+luci_interpreter_pal::ConvParams createConv2DParams(const circle::Tensor *input,
+                                                    const circle::Tensor *filter,
+                                                    const circle::Tensor *output,
+                                                    const circle::Conv2DOptions *options);
+
+namespace kernels
+{
+
+// Conv2D kernel for downsampling
+class DownsamplingConv2DKernel
+{
+public:
+  DownsamplingConv2DKernel() = delete;
+
+  explicit DownsamplingConv2DKernel(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+    : _runtime_graph(runtime_graph)
+  {
+    const auto input_index = cur_op->inputs()->operator[](0);
+    const auto filter_index = cur_op->inputs()->operator[](1);
+    const auto bias_index = cur_op->inputs()->operator[](2);
+    const auto output_index = cur_op->outputs()->operator[](0);
+
+    assert(input_index != -1);
+    assert(filter_index != -1);
+    assert(output_index != -1);
+
+    _input_tensor = _runtime_graph->getCircleTensorByIndex(input_index);
+    _filter_tensor = _runtime_graph->getCircleTensorByIndex(filter_index);
+    _bias_tensor = _runtime_graph->getCircleTensorByIndex(bias_index);
+    _output_tensor = _runtime_graph->getCircleTensorByIndex(output_index);
+
+    assert(_input_tensor != nullptr);
+    assert(_filter_tensor != nullptr);
+  }
+
+  const circle::Tensor *input() const { return _input_tensor; }
+  const circle::Tensor *filter() const { return _filter_tensor; }
+  const circle::Tensor *bias() const { return _bias_tensor; }
+  const circle::Tensor *output() const { return _output_tensor; }
+
+  BaseRuntimeGraph *runtime_graph() const { return _runtime_graph; }
+
+private:
+  const circle::Tensor *_input_tensor;
+  const circle::Tensor *_filter_tensor;
+  const circle::Tensor *_bias_tensor;
+  const circle::Tensor *_output_tensor;
+
+  BaseRuntimeGraph *_runtime_graph;
+};
+
+} // namespace kernels
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_CONVOLUTIONCOMMON_H
diff --git a/onert-micro/luci-interpreter/src/kernels/Cos.cpp b/onert-micro/luci-interpreter/src/kernels/Cos.cpp
new file mode 100644 (file)
index 0000000..73643de
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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 "Builders.h"
+#include "kernels/Utils.h"
+#include "SISOKernel.h"
+
+#include "PALCos.h"
+
+namespace luci_interpreter
+{
+
+void configure_kernel_CircleCos(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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 execute_kernel_CircleCos(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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:
+    {
+      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::Cos(flat_size, input_data_float, output_data_float);
+      break;
+    }
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
+  }
+
+  if (is_inplace)
+    runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
+}
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Cos.test.cpp b/onert-micro/luci-interpreter/src/kernels/Cos.test.cpp
new file mode 100644 (file)
index 0000000..2266ceb
--- /dev/null
@@ -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/cos/FloatCosKernel.h"
+#include "luci_interpreter/test_models/cos/NegCosKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class CosTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T> std::vector<T> checkCosKernel(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(CosTest, Float_P)
+{
+  test_kernel::TestDataFloatCos test_data_kernel;
+  std::vector<float> output_data_vector = checkCosKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(CosTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchCosKernel 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
index 937958b..f10e1ed 100644 (file)
  * limitations under the License.
  */
 
-#include "DepthToSpace.h"
-#include "Utils.h"
+#include "Builders.h"
+#include "kernels/Utils.h"
+#include "SISOKernel.h"
+
 #include "PALDepthToSpace.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 
-DepthToSpace::DepthToSpace(const Tensor *input, Tensor *output, const DepthToSpaceParams &params)
-  : KernelWithParams<DepthToSpaceParams>({input}, {output}, params)
+void configure_kernel_CircleDepthToSpace(const circle::Operator *cur_op,
+                                         BaseRuntimeGraph *runtime_graph)
 {
-}
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-void DepthToSpace::configure()
-{
-  LUCI_INTERPRETER_CHECK(input()->shape().num_dims() == 4);
-  LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::FLOAT32 ||
-                         output()->element_type() == DataType::U8)
-  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type())
-  const int block_size = params().block_size;
-  const int32_t input_height = input()->shape().dim(1);
-  const int32_t input_width = input()->shape().dim(2);
-  const int32_t input_channels = input()->shape().dim(3);
-  int32_t output_height = input_height * block_size;
-  int32_t output_width = input_width * block_size;
-  int32_t output_channels = input_channels / block_size / block_size;
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) ==
+                         Tensor::element_type(kernel.output()));
+
+  const auto *options = cur_op->builtin_options_as_DepthToSpaceOptions();
+
+  const int32_t block_size = options->block_size();
+  LUCI_INTERPRETER_CHECK(block_size > 0);
+
+  constexpr int kHeightRank = 1;
+  constexpr int kWidthRank = 2;
+  constexpr int kDepthRank = 3;
+
+  const int input_height = Tensor::dim(kernel.input(), kHeightRank);
+  const int input_width = Tensor::dim(kernel.input(), kWidthRank);
+  const int input_channels = Tensor::dim(kernel.input(), kDepthRank);
+  int output_height = input_height * block_size;
+  int output_width = input_width * block_size;
+  int output_channels = input_channels / block_size / block_size;
 
   LUCI_INTERPRETER_CHECK(input_height == output_height / block_size);
   LUCI_INTERPRETER_CHECK(input_width == output_width / block_size);
   LUCI_INTERPRETER_CHECK(input_channels == output_channels * block_size * block_size);
-
-  Shape output_shape(4);
-  output_shape.dim(0) = input()->shape().dim(0);
-  output_shape.dim(1) = output_height;
-  output_shape.dim(2) = output_width;
-  output_shape.dim(3) = output_channels;
-
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(output_shape);
 }
 
-void DepthToSpace::execute() const
+void execute_kernel_CircleDepthToSpace(const circle::Operator *cur_op,
+                                       BaseRuntimeGraph *runtime_graph)
 {
-  tflite::DepthToSpaceParams op_params;
-  op_params.block_size = params().block_size;
-  switch (input()->element_type())
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
+
+  const auto *options = cur_op->builtin_options_as_DepthToSpaceOptions();
+  const int32_t block_size = options->block_size();
+
+  switch (Tensor::element_type(kernel.input()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      luci_interpreter_pal::DepthToSpace(op_params, getTensorShape(input()),
-                                         getTensorData<float>(input()), getTensorShape(output()),
-                                         getTensorData<float>(output()));
-      break;
-    case DataType::U8:
-      luci_interpreter_pal::DepthToSpace(op_params, getTensorShape(input()),
-                                         getTensorData<uint8_t>(input()), getTensorShape(output()),
-                                         getTensorData<uint8_t>(output()));
+    {
+      assert(block_size != 0);
+      luci_interpreter_pal::DepthToSpace(
+        block_size, kernels::getTensorRuntimeShape(kernel.input(), runtime_graph),
+        kernels::getTensorData<float>(runtime_graph->getDataByTensor(kernel.input())),
+        kernels::getTensorRuntimeShape(kernel.output(), runtime_graph),
+        kernels::getTensorData<float>(runtime_graph->getDataByTensor(kernel.output())));
       break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported Type.");
+      assert(false && "Unsupported type");
   }
 }
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/DepthToSpace.h b/onert-micro/luci-interpreter/src/kernels/DepthToSpace.h
deleted file mode 100644 (file)
index 63ce376..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_DEPTHTOSPACE_H
-#define LUCI_INTERPRETER_KERNELS_DEPTHTOSPACE_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-#include <vector>
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class DepthToSpace : public KernelWithParams<DepthToSpaceParams>
-{
-public:
-  DepthToSpace(const Tensor *input, Tensor *output, const DepthToSpaceParams &params);
-
-  const Tensor *input() const { return _inputs[0]; }
-  Tensor *output() const { return _outputs[0]; }
-
-  void configure() override;
-  void execute() const override;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_DEPTHTOSPACE_H
index 88e6e07..f0dc2ce 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/DepthToSpace.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/depth_to_space/FloatDepthToSpaceKernel.h"
+#include "luci_interpreter/test_models/depth_to_space/NegDepthToSpaceKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
 using namespace testing;
 
-template <typename T> class DepthToSpaceTest : public ::testing::Test
+class DepthToSpaceTest : public ::testing::Test
 {
+  // Do nothing
 };
 
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(DepthToSpaceTest, DataTypes);
-
-TYPED_TEST(DepthToSpaceTest, SimpleCase)
+template <typename T>
+std::vector<T> checkDepthToSpaceKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<TypeParam> input_data{1, 2, 3, 4, 5, 6, 7, 8};
-  Shape input_shape{1, 1, 2, 4};
-  std::vector<TypeParam> output_data{1, 2, 5, 6, 3, 4, 7, 8};
-  std::vector<int32_t> output_shape{1, 2, 4, 1};
-
-  Tensor input_tensor =
-    makeInputTensor<getElementType<TypeParam>()>(input_shape, input_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(getElementType<TypeParam>());
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  DepthToSpaceParams params{};
-  params.block_size = 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);
 
-  DepthToSpace kernel = DepthToSpace(&input_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(extractTensorData<TypeParam>(output_tensor),
-              ::testing::ElementsAreArray(output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
-}
-
-TEST(DepthToSpaceTest, InvalidInputShape_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8};
-  Shape input_shape{1, 2, 4};
+  // 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::FLOAT32>(input_shape, input_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+  runtime_module.execute();
 
-  DepthToSpaceParams params{};
-  params.block_size = 2;
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  DepthToSpace kernel = DepthToSpace(&input_tensor, &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(DepthToSpaceTest, InOutTypeMismatch_NEG)
+TEST_F(DepthToSpaceTest, Float_P)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8};
-  Shape input_shape{1, 1, 2, 4};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8);
-
-  DepthToSpaceParams params{};
-  params.block_size = 2;
-
-  DepthToSpace kernel = DepthToSpace(&input_tensor, &output_tensor, params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::TestDataFloatDepthToSpace test_data_kernel;
+  std::vector<float> output_data_vector = checkDepthToSpaceKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST(DepthToSpaceTest, InvalidBlockSize_NEG)
+TEST_F(DepthToSpaceTest, 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, 7, 8};
-  Shape input_shape{1, 1, 2, 4};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  DepthToSpaceParams params{};
-  params.block_size = 3;
-
-  DepthToSpace kernel = DepthToSpace(&input_tensor, &output_tensor, params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputOutputTypeMismatchDepthToSpaceKernel 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
index 201eaf3..e6ee466 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * 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.
  * limitations under the License.
  */
 
-#include "kernels/DepthwiseConv2D.h"
-
+#include "ConvolutionCommon.h"
 #include "kernels/Utils.h"
 
-#include "PALDepthwiseConv2d.h"
+#include "PALDepthwiseConv2D.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
-
-DepthwiseConv2D::DepthwiseConv2D(const Tensor *input, const Tensor *filter, const Tensor *bias,
-                                 Tensor *output, Tensor *scratchpad,
-                                 const DepthwiseConv2DParams &params)
-  : KernelWithParams<DepthwiseConv2DParams>({input, filter, bias}, {output, scratchpad}, params)
-{
-}
 
-void DepthwiseConv2D::configure()
+namespace
 {
-  // TensorFlow Lite (as of v2.2.0) supports the following combinations of types:
-  //     | input filter bias  output |
-  // ----+---------------------------+
-  // (1) | float float  float float  |
-  // (2) | float int8   float float  | hybrid
-  // (3) | uint8 uint8  int32 uint8  | quantized
-  // (4) | int8  int8   int32 int8   | quantized per channel
-  // (5) | int16 int8   int64 int16  | quantized per channel 16x8
-  //
-  // We only support (1), (3) and (4) for now, and additionally the following:
-  //     | input filter bias  output |
-  // ----+---------------------------+
-  // (5) | int16 int16  int64 int16  |
-  //
-  if (input()->element_type() == DataType::FLOAT32 && filter()->element_type() == DataType::FLOAT32)
-  {
-    LUCI_INTERPRETER_CHECK(bias() == nullptr || bias()->element_type() == DataType::FLOAT32);
-  }
-  else if (input()->element_type() == DataType::U8 && filter()->element_type() == DataType::U8)
-  {
-    LUCI_INTERPRETER_CHECK(bias() == nullptr || bias()->element_type() == DataType::S32);
-  }
-  else if (input()->element_type() == DataType::S8 && filter()->element_type() == DataType::S8)
-  {
-    LUCI_INTERPRETER_CHECK(filter()->shape().num_dims() == 4);
-    LUCI_INTERPRETER_CHECK(static_cast<uint32_t>(filter()->shape().dim(3)) ==
-                           filter()->scales().size());
-    for (auto zerop : filter()->zero_points())
-    {
-      LUCI_INTERPRETER_CHECK(zerop == 0);
-    }
-    LUCI_INTERPRETER_CHECK(bias() == nullptr || bias()->element_type() == DataType::S32);
-  }
-  else if (input()->element_type() == DataType::S16 && filter()->element_type() == DataType::S16)
-  {
-    LUCI_INTERPRETER_CHECK(bias() == nullptr || bias()->element_type() == DataType::S64);
-  }
-  else
-  {
-    assert(false && "Unsupported type.");
-  }
-  LUCI_INTERPRETER_CHECK(output()->element_type() == input()->element_type());
-
-  const Shape &input_shape = input()->shape();
-  const Shape &filter_shape = filter()->shape();
-  LUCI_INTERPRETER_CHECK(input_shape.num_dims() == 4 && filter_shape.num_dims() == 4);
-
-  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);
-  // Filter format: [1, H, W, O].
-  LUCI_INTERPRETER_CHECK(filter_shape.dim(0) == 1);
-  const int32_t filter_height = filter_shape.dim(1);
-  const int32_t filter_width = filter_shape.dim(2);
-  const int32_t channels_out = filter_shape.dim(3);
-
-  LUCI_INTERPRETER_CHECK(bias() == nullptr || (bias()->shape().num_dims() == 1 &&
-                                               bias()->shape().dim(0) == channels_out));
-
-  const int32_t output_height =
-    computeOutputSize(_params.padding, input_height, filter_height, _params.stride_height,
-                      _params.dilation_height_factor);
-  const int32_t output_width =
-    computeOutputSize(_params.padding, input_width, filter_width, _params.stride_width,
-                      _params.dilation_width_factor);
 
-  _padding_height = computePadding(_params.stride_height, _params.dilation_height_factor,
-                                   input_height, filter_height, output_height);
-  _padding_width = computePadding(_params.stride_width, _params.dilation_width_factor, input_width,
-                                  filter_width, output_width);
-
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize({batches, output_height, output_width, channels_out});
-
-  tflite::DepthwiseParams params{};
-
-  params.dilation_height_factor = _params.dilation_height_factor;
-  params.dilation_width_factor = _params.dilation_width_factor;
-
-  auto scratchpad = getOutputTensors()[1];
-  luci_interpreter_pal::SetupScratchpadTensor(scratchpad, params, input()->element_type(),
-                                              getTensorShape(input()), getTensorShape(filter()),
-                                              getTensorShape(output()));
-}
-
-void DepthwiseConv2D::execute() const
-{
-  switch (input()->element_type())
-  {
-    case DataType::FLOAT32:
-      if (filter()->element_type() == DataType::FLOAT32)
-      {
-        evalFloat();
-        break;
-      }
-      assert(false && "Unsupported type.");
-    case DataType::U8:
-      if (filter()->scales().size() == 1)
-      {
-        evalQuantized();
-      }
-      else if (filter()->scales().size() > 1)
-      {
-        LUCI_INTERPRETER_CHECK(filter()->shape().num_dims() == 4);
-        LUCI_INTERPRETER_CHECK(filter()->scales().size() ==
-                               static_cast<size_t>(filter()->shape().dim(3)));
-        evalQuantizedPerChannel();
-      }
-      break;
-    case DataType::S8:
-      evalQuantizedS8PerChannel();
-      break;
-    case DataType::S16:
-      evalQuantizedS16();
-      break;
-    default:
-      assert(false && "Unsupported type.");
-  }
-}
+#ifndef DIS_FLOAT
 
-void DepthwiseConv2D::evalFloat() const
+void evalFloat(const circle::Tensor *input, const circle::Tensor *filter,
+               const circle::Tensor *bias, const circle::Tensor *output,
+               const circle::DepthwiseConv2DOptions *options, BaseRuntimeGraph *runtime_graph)
 {
   float activation_min{};
   float activation_max{};
-  calculateActivationRange(_params.activation, &activation_min, &activation_max);
-
-  tflite::DepthwiseParams 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.dilation_height_factor = _params.dilation_height_factor;
-  params.dilation_width_factor = _params.dilation_width_factor;
-  params.depth_multiplier = _params.depth_multiplier;
+  kernels::calculateActivationRange(luci_actfunc(options->fused_activation_function()),
+                                    &activation_min, &activation_max);
+
+  luci_interpreter_pal::ConvParams params{};
+  params.padding_values.height = computeConvPadding(
+    input, filter, options->padding(), options->stride_h(), options->dilation_h_factor(), 1);
+  params.padding_values.width = computeConvPadding(
+    input, filter, options->padding(), options->stride_w(), options->dilation_w_factor(), 2);
+  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.float_activation_min = activation_min;
   params.float_activation_max = activation_max;
+  params.depth_multiplier = options->depth_multiplier();
 
-  tflite::reference_ops::DepthwiseConv(
-    params, getTensorShape(input()), getTensorData<float>(input()), getTensorShape(filter()),
-    getTensorData<float>(filter()), getTensorShape(bias()), getTensorData<float>(bias()),
-    getTensorShape(output()), getTensorData<float>(output()));
-}
+  auto *input_data = runtime_graph->getDataByTensor(input);
+  auto *output_data = runtime_graph->getDataByTensor(output);
 
-void DepthwiseConv2D::evalQuantizedPerChannel() const
-{
-  const auto *input_data = getTensorData<uint8_t>(input());
-  const auto *filter_data = getTensorData<uint8_t>(filter());
-  const auto *bias_data = getTensorData<int32_t>(bias());
-  auto *output_data = getTensorData<uint8_t>(output());
-
-  const Shape &input_shape = input()->shape();
-  const Shape &filter_shape = filter()->shape();
-  const Shape &output_shape = output()->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 input_depth = input_shape.dim(3);
-  const int32_t filter_height = filter_shape.dim(1);
-  const int32_t filter_width = filter_shape.dim(2);
-  const int32_t output_height = output_shape.dim(1);
-  const int32_t output_width = output_shape.dim(2);
+  auto *filter_data = runtime_graph->getConstDataByTensor(filter);
+  auto *bias_data = runtime_graph->getConstDataByTensor(bias);
 
-  const int32_t stride_height = _params.stride_height;
-  const int32_t stride_width = _params.stride_width;
-  const int32_t dilation_height_factor = _params.dilation_height_factor;
-  const int32_t dilation_width_factor = _params.dilation_width_factor;
-  const int32_t depth_multiplier = _params.depth_multiplier;
+  int32_t input_shape[kMaxSmallSize];
+  kernels::getTensorDims(input, runtime_graph, input_shape);
 
-  int32_t activation_min{};
-  int32_t activation_max{};
-  calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
+  int32_t filter_shape[kMaxSmallSize];
+  kernels::getTensorDims(filter, runtime_graph, filter_shape);
 
-  const std::vector<double> effective_output_scales =
-    getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
+  int32_t output_shape[kMaxSmallSize];
+  kernels::getTensorDims(output, runtime_graph, output_shape);
 
-  std::vector<ChannelQuantMultipliers> quant_multipliers_raw =
-    quantizeMultipliers(effective_output_scales);
-  BroadcastableWrapper<ChannelQuantMultipliers> quant_multipliers(quant_multipliers_raw);
-
-  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) - _padding_width;
-            const int in_y_origin = (out_y * stride_height) - _padding_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[calcOffset(input_shape, batch, in_y, in_x, in_channel)];
-                  int32_t filter_val =
-                    filter_data[calcOffset(filter_shape, 0, filter_y, filter_x, output_channel)];
-                  acc += (filter_val - filter()->zero_points()[output_channel]) *
-                         (input_val - input()->zero_point());
-                }
-              }
-            }
-            if (bias_data)
-            {
-              acc += bias_data[output_channel];
-            }
-            int32_t output_multiplier = quant_multipliers[output_channel].multiplier;
-            int output_shift = quant_multipliers[output_channel].shift;
-            int32_t scaled_acc =
-              tflite::MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
-            scaled_acc += output()->zero_point();
-            scaled_acc = std::max(scaled_acc, activation_min);
-            scaled_acc = std::min(scaled_acc, activation_max);
-            output_data[calcOffset(output_shape, batch, out_y, out_x, output_channel)] =
-              static_cast<uint8_t>(scaled_acc);
-          }
-        }
-      }
-    }
-  }
+  luci_interpreter_pal::DepthwiseConv2D(
+    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));
 }
 
-void DepthwiseConv2D::evalQuantized() const
-{
-  const auto input_scale = static_cast<double>(input()->scale());
-  const auto filter_scale = static_cast<double>(filter()->scale());
-  const auto output_scale = static_cast<double>(output()->scale());
-
-  const double real_multiplier = input_scale * filter_scale / output_scale;
-  int32_t output_multiplier{};
-  int output_shift{};
-  quantizeMultiplier(real_multiplier, &output_multiplier, &output_shift);
+#endif // DIS_FLOAT
 
-  int32_t activation_min{};
-  int32_t activation_max{};
-  calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
+} // namespace
 
-  tflite::DepthwiseParams 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.dilation_height_factor = _params.dilation_height_factor;
-  params.dilation_width_factor = _params.dilation_width_factor;
-  params.depth_multiplier = _params.depth_multiplier;
-  // The kernel expects input and filter zero points to be negated.
-  params.input_offset = -input()->zero_point();    // Note the '-'.
-  params.weights_offset = -filter()->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;
-
-  tflite::reference_ops::DepthwiseConv(
-    params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(filter()),
-    getTensorData<uint8_t>(filter()), getTensorShape(bias()), getTensorData<int32_t>(bias()),
-    getTensorShape(output()), getTensorData<uint8_t>(output()));
-}
-
-void DepthwiseConv2D::evalQuantizedS8PerChannel() const
+void configure_kernel_CircleDepthwiseConv2D(const circle::Operator *cur_op,
+                                            BaseRuntimeGraph *runtime_graph)
 {
-  int32_t activation_min{};
-  int32_t activation_max{};
-  calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
+  kernels::DownsamplingConv2DKernel kernel(cur_op, runtime_graph);
 
-  tflite::DepthwiseParams params{};
+  const auto input = kernel.input();
+  const auto filter = kernel.filter();
+  const auto bias = kernel.bias();
+  const auto output = kernel.output();
 
-  params.padding_type = tflite::PaddingType::kSame;
-  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.dilation_height_factor = _params.dilation_height_factor;
-  params.dilation_width_factor = _params.dilation_width_factor;
-  params.depth_multiplier = _params.depth_multiplier;
-  // The kernel expects input and filter zero points to be negated.
-  params.input_offset = -input()->zero_point(); // Note the '-'.
-  params.weights_offset = 0;
-  params.output_offset = output()->zero_point();
-  params.output_multiplier = 1; // unused in tflite code
-  params.output_shift = 0;      // unused in tflite code
-  params.quantized_activation_min = activation_min;
-  params.quantized_activation_max = activation_max;
+  auto filter_data = runtime_graph->getConstDataByTensor(filter);
 
-  const std::vector<double> effective_output_scales =
-    getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
+  assert(filter_data != nullptr);
 
-  std::vector<ChannelQuantMultipliers> quant_multipliers =
-    quantizeMultipliers(effective_output_scales);
+  const auto *options = cur_op->builtin_options_as_DepthwiseConv2DOptions();
 
-  std::vector<int32_t> shifts;
-  std::transform(quant_multipliers.begin(), quant_multipliers.end(), std::back_inserter(shifts),
-                 [](ChannelQuantMultipliers cm) { return cm.shift; });
-  std::vector<int32_t> multipliers;
-  std::transform(quant_multipliers.begin(), quant_multipliers.end(),
-                 std::back_inserter(multipliers),
-                 [](ChannelQuantMultipliers cm) { return cm.multiplier; });
+  if (Tensor::element_type(input) == DataType::FLOAT32 &&
+      Tensor::element_type(filter) == DataType::FLOAT32)
+  {
+    LUCI_INTERPRETER_CHECK(bias == nullptr || Tensor::element_type(bias) == DataType::FLOAT32);
+  }
+  else
+  {
+    assert(false && "Unsupported type.");
+  }
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(output) == Tensor::element_type(input));
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(input) == 4 && Tensor::num_dims(filter) == 4);
 
-  auto scratchpad = getOutputTensors()[1];
-  int8_t *scratchpad_data = nullptr;
-  if (scratchpad->is_allocatable())
-    scratchpad_data = scratchpad->data<int8_t>();
+  const int32_t output_depth = Tensor::dim(output, 3);
+  LUCI_INTERPRETER_CHECK(bias == nullptr ||
+                         (Tensor::num_dims(bias) == 1 && Tensor::dim(bias, 0) == output_depth));
 
-  luci_interpreter_pal::DepthwiseConvPerChannel<int8_t>(
-    params, multipliers.data(), shifts.data(), getTensorShape(input()),
-    getTensorData<int8_t>(input()), getTensorShape(filter()), getTensorData<int8_t>(filter()),
-    getTensorShape(bias()), getTensorData<int32_t>(bias()), getTensorShape(output()),
-    getTensorData<int8_t>(output()), getTensorShape(scratchpad), scratchpad_data);
+  switch (options->fused_activation_function())
+  {
+    case circle::ActivationFunctionType_NONE:
+    case circle::ActivationFunctionType_RELU:
+    case circle::ActivationFunctionType_RELU6:
+    case circle::ActivationFunctionType_RELU_N1_TO_1:
+      break;
+    default:
+      assert(false && "Unsupported fused activation");
+  }
 }
 
-void DepthwiseConv2D::evalQuantizedS16() const
+void execute_kernel_CircleDepthwiseConv2D(const circle::Operator *cur_op,
+                                          BaseRuntimeGraph *runtime_graph)
 {
-  const auto *input_data = getTensorData<int16_t>(input());
-  const auto *filter_data = getTensorData<int16_t>(filter());
-  const auto *bias_data = getTensorData<int64_t>(bias());
-  auto *output_data = getTensorData<int16_t>(output());
-
-  const Shape &input_shape = input()->shape();
-  const Shape &filter_shape = filter()->shape();
-  const Shape &output_shape = output()->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 input_depth = input_shape.dim(3);
-  const int32_t filter_height = filter_shape.dim(1);
-  const int32_t filter_width = filter_shape.dim(2);
-  const int32_t output_height = output_shape.dim(1);
-  const int32_t output_width = output_shape.dim(2);
+  kernels::DownsamplingConv2DKernel kernel(cur_op, runtime_graph);
 
-  const int32_t stride_height = _params.stride_height;
-  const int32_t stride_width = _params.stride_width;
-  const int32_t dilation_height_factor = _params.dilation_height_factor;
-  const int32_t dilation_width_factor = _params.dilation_width_factor;
-  const int32_t depth_multiplier = _params.depth_multiplier;
+  const auto input = kernel.input();
+  const auto weights = kernel.filter();
+  const auto bias = kernel.bias();
+  const auto output = kernel.output();
 
-  const std::vector<double> effective_output_scales =
-    getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
+  const auto *options = cur_op->builtin_options_as_DepthwiseConv2DOptions();
 
-  std::vector<ChannelQuantMultipliers> quant_multipliers_raw =
-    quantizeMultipliers(effective_output_scales);
-
-  BroadcastableWrapper<ChannelQuantMultipliers> quant_multipliers(quant_multipliers_raw);
-
-  int32_t activation_min{};
-  int32_t activation_max{};
-  calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
-
-  for (int32_t batch = 0; batch < batches; ++batch)
+  switch (Tensor::element_type(input))
   {
-    for (int32_t out_y = 0; out_y < output_height; ++out_y)
-    {
-      for (int32_t out_x = 0; out_x < output_width; ++out_x)
+#ifndef DIS_FLOAT
+    case DataType::FLOAT32:
+      if (Tensor::element_type(weights) == DataType::FLOAT32)
       {
-        for (int32_t in_c = 0; in_c < input_depth; ++in_c)
-        {
-          for (int32_t m = 0; m < depth_multiplier; ++m)
-          {
-            const int32_t out_c = m + in_c * depth_multiplier;
-            const int32_t in_y_origin = out_y * stride_height - _padding_height;
-            const int32_t in_x_origin = out_x * stride_width - _padding_width;
-            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))
-                {
-                  const int16_t input_val =
-                    input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
-                  const int16_t filter_val =
-                    filter_data[calcOffset(filter_shape, 0, filter_y, filter_x, out_c)];
-                  acc += static_cast<int64_t>(input_val) * static_cast<int64_t>(filter_val);
-                }
-              }
-            }
-            if (bias_data != nullptr)
-            {
-              acc += bias_data[out_c];
-            }
-
-            int32_t output_multiplier = quant_multipliers[out_c].multiplier;
-            int output_shift = quant_multipliers[out_c].shift;
-            int32_t scaled_acc =
-              tflite::MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
-
-            scaled_acc = std::max(scaled_acc, activation_min);
-            scaled_acc = std::min(scaled_acc, activation_max);
-
-            output_data[calcOffset(output_shape, batch, out_y, out_x, out_c)] = scaled_acc;
-          }
-        }
+        evalFloat(input, weights, bias, output, options, 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/DepthwiseConv2D.h b/onert-micro/luci-interpreter/src/kernels/DepthwiseConv2D.h
deleted file mode 100644 (file)
index 3d1faf6..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_DEPTHWISECONV2D_H
-#define LUCI_INTERPRETER_KERNELS_DEPTHWISECONV2D_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class DepthwiseConv2D : public KernelWithParams<DepthwiseConv2DParams>
-{
-public:
-  DepthwiseConv2D(const Tensor *input, const Tensor *filter, const Tensor *bias, Tensor *output,
-                  Tensor *scratchpad, const DepthwiseConv2DParams &params);
-
-  const Tensor *input() const { return _inputs[0]; }
-  const Tensor *filter() const { return _inputs[1]; }
-  const Tensor *bias() const { return _inputs[2]; }
-  Tensor *output() const { return _outputs[0]; }
-
-  void configure() override;
-  void execute() const override;
-
-private:
-  void evalFloat() const;
-  void evalQuantized() const;
-  void evalQuantizedPerChannel() const;
-  void evalQuantizedS8PerChannel() const;
-  void evalQuantizedS16() const;
-
-private:
-  int32_t _padding_height{};
-  int32_t _padding_width{};
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_DEPTHWISECONV2D_H
index 6b4673f..f486a7f 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/DepthwiseConv2D.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/depthwise_conv_2d/FloatDepthwiseConv2DKernel.h"
+#include "luci_interpreter/test_models/depthwise_conv_2d/NegDepthwiseConv2DKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -29,594 +29,86 @@ using namespace testing;
 
 class DepthwiseConv2DTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(DepthwiseConv2DTest, Float)
-{
-  Shape input_shape{1, 4, 2, 2};
-  Shape filter_shape{1, 2, 2, 4};
-  Shape bias_shape{4};
-  std::vector<float> input_data{
-    1,  2,  7,  8,  //
-    3,  4,  9,  10, //
-    5,  6,  11, 12, //
-    13, 14, 15, 16, //
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<float> bias_data{1, 2, 3, 4};
-  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 scratchpad(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 2;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::RELU;
-
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_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{
-    71,  0, 99,  0,  //
-    167, 0, 227, 28, //
-  };
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 1, 4}));
-}
-
-TEST_F(DepthwiseConv2DTest, Uint8)
-{
-  std::vector<float> input_data{
-    1, 2, 7,  8,  // column 1
-    3, 4, 9,  10, // column 2
-    5, 6, 11, 12, // column 3
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<float> bias_data{1, 2, 3, 4};
-
-  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>({1, 3, 2, 2}, input_quant_param.first, input_quant_param.second,
-                                  input_data, _memory_manager.get());
-  Tensor filter_tensor =
-    makeInputTensor<DataType::U8>({1, 2, 2, 4}, input_quant_param.first, input_quant_param.second,
-                                  filter_data, _memory_manager.get());
-  Tensor bias_tensor = makeInputTensor<DataType::S32>(
-    {4}, 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);
-  Tensor scratchpad(DataType::FLOAT32, Shape({}), {}, "");
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 1;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::NONE;
-
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &scratchpad,
-                         params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  _memory_manager->allocate_memory(scratchpad);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{
-    71, -34, 99,  -20, //
-    91, -26, 127, -4,  //
-  };
-  EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 1, 4}));
-}
-
-TEST_F(DepthwiseConv2DTest, SInt16)
-{
-  Shape input_shape{1, 4, 2, 2};
-  Shape filter_shape{1, 2, 2, 4};
-  Shape bias_shape{4};
-  std::vector<int32_t> ref_output_shape{1, 2, 1, 4};
-
-  std::vector<float> input_data{
-    1,  2,  7,  8,  //
-    3,  4,  9,  10, //
-    5,  6,  11, 12, //
-    13, 14, 15, 16, //
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<float> bias_data{1, 2, 3, 4};
-  std::vector<float> ref_output_data{
-    71,  0, 99,  0,  //
-    167, 0, 227, 28, //
-  };
-
-  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 output_tensor = makeOutputTensor(DataType::S16, 0.5, 0);
-  Tensor scratchpad(DataType::S64, Shape({}), {}, "");
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 2;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::RELU;
-
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &scratchpad,
-                         params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  _memory_manager->allocate_memory(scratchpad);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-  EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
-}
-
-TEST_F(DepthwiseConv2DTest, SInt16_CWQ_weights)
+template <typename T>
+std::vector<T> checkDepthwiseConv2DKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  const int output_channels = 4;
-  Shape input_shape{1, 4, 2, 2};
-  Shape filter_shape{1, 2, 2, output_channels};
-  Shape bias_shape{4};
-  std::vector<int32_t> ref_output_shape{1, 2, 1, output_channels};
-
-  std::vector<float> input_data{
-    1,  2,  7,  8,  //
-    3,  4,  9,  10, //
-    5,  6,  11, 12, //
-    13, 14, 15, 16, //
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<float> bias_data{1, 2, 3, 4};
-  std::vector<float> ref_output_data{
-    71,  0, 99,  0,  //
-    167, 0, 227, 28, //
-  };
-
-  float input_scale = 0.25;
-  std::vector<float> filter_scales{0.2f, 1.f, 0.5f, 0.1f};
-  std::vector<float> bias_scales;
-  for (int i = 0; i < output_channels; ++i)
-    bias_scales.push_back(filter_scales[i] * input_scale);
-  std::vector<int32_t> zerop(4, 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, 3,
-                                                        filter_data, _memory_manager.get());
-  Tensor bias_tensor = makeInputTensor<DataType::S64>(bias_shape, bias_scales, zerop, 0, bias_data,
-                                                      _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, 0.5, 0);
-  Tensor scratchpad(DataType::S16, Shape({}), {}, "");
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 2;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::RELU;
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &scratchpad,
-                         params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  _memory_manager->allocate_memory(scratchpad);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-  EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
-}
-
-TEST_F(DepthwiseConv2DTest, Uint8_CWQ_weights)
-{
-  const int output_channels = 4;
-  Shape input_shape{1, 3, 2, 2};
-  Shape filter_shape{1, 2, 2, output_channels};
-  Shape bias_shape{4};
-  std::vector<int32_t> ref_output_shape{1, 2, 1, output_channels};
+  // 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> input_data{
-    1, 2, 7,  8,  //
-    3, 4, 9,  10, //
-    5, 6, 11, 12, //
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<float> bias_data{1, 2, 3, 4};
-  std::vector<float> ref_output_data{
-    71, -34, 99,  -20, //
-    91, -26, 127, -4,  //
-  };
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-  std::pair<float, int32_t> input_quant_param = quantizationParams<uint8_t>(0, 16);
-  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>(-9, 13));
-  filter_quant_params.push_back(quantizationParams<uint8_t>(-14, 10));
-  filter_quant_params.push_back(quantizationParams<uint8_t>(-11, 15));
-  filter_quant_params.push_back(quantizationParams<uint8_t>(-16, 12));
-
-  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::U8>(input_shape, 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,
-                                                       3, filter_data, _memory_manager.get());
-  Tensor bias_tensor = makeInputTensor<DataType::S32>(bias_shape, bias_scales, zerop, 0, bias_data,
-                                                      _memory_manager.get());
-  Tensor output_tensor =
-    makeOutputTensor(DataType::U8, output_quant_param.first, output_quant_param.second);
-  Tensor scratchpad(DataType::U8, Shape({}), {}, "");
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 1;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::NONE;
+  runtime_module.execute();
 
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &scratchpad,
-                         params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  _memory_manager->allocate_memory(scratchpad);
-  kernel.execute();
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(ref_output_data, output_quant_param.first));
+  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(DepthwiseConv2DTest, SInt8_CWQ_weights)
+TEST_F(DepthwiseConv2DTest, Float_P)
 {
-  const int output_channels = 4;
-  Shape input_shape{1, 3, 2, 2};
-  Shape filter_shape{1, 2, 2, output_channels};
-  Shape bias_shape{4};
-  std::vector<int32_t> ref_output_shape{1, 2, 1, output_channels};
-
-  std::vector<float> input_data{
-    1, 2, 7,  8,  //
-    3, 4, 9,  10, //
-    5, 6, 11, 12, //
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<float> bias_data{1, 2, 3, 4};
-  std::vector<float> ref_output_data{
-    71, -34, 99,  -20, //
-    91, -26, 127, -4,  //
-  };
-
-  std::pair<float, int32_t> input_quant_param = quantizationParams<int8_t>(-128, 127);
-  std::pair<float, int32_t> output_quant_param = quantizationParams<int8_t>(-127, 128);
-
-  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>(1, 0));
-  filter_quant_params.push_back(std::pair<float, int32_t>(0.125, 0));
-
-  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::S8>(input_shape, 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,
-                                                       3, filter_data, _memory_manager.get());
-  Tensor bias_tensor = makeInputTensor<DataType::S32>(bias_shape, bias_scales, zerop, 0, bias_data,
-                                                      _memory_manager.get());
-  Tensor output_tensor =
-    makeOutputTensor(DataType::S8, output_quant_param.first, output_quant_param.second);
-  Tensor scratchpad(DataType::S8, Shape({}), {}, "");
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 1;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::NONE;
-
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &scratchpad,
-                         params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  _memory_manager->allocate_memory(scratchpad);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(ref_output_data, output_quant_param.first));
+  test_kernel::TestDataFloatDepthwiseConv2D test_data_kernel;
+  std::vector<float> output_data_vector = checkDepthwiseConv2DKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST_F(DepthwiseConv2DTest, InvalidBiasType_NEG)
+TEST_F(DepthwiseConv2DTest, Input_type_mismatch_NEG)
 {
-  Shape input_shape{1, 4, 2, 2};
-  Shape filter_shape{1, 2, 2, 4};
-  Shape bias_shape{4};
-  std::vector<float> input_data{
-    1,  2,  7,  8,  //
-    3,  4,  9,  10, //
-    5,  6,  11, 12, //
-    13, 14, 15, 16, //
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<int32_t> bias_data{1, 2, 3, 4};
-  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::S32>(bias_shape, bias_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-  Tensor scratchpad(DataType::FLOAT32, Shape({}), {}, "");
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 2;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::RELU;
-
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &scratchpad,
-                         params);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(DepthwiseConv2DTest, InOutTypeMismatch_NEG)
-{
-  Shape input_shape{1, 4, 2, 2};
-  Shape filter_shape{1, 2, 2, 4};
-  Shape bias_shape{4};
-  std::vector<float> input_data{
-    1,  2,  7,  8,  //
-    3,  4,  9,  10, //
-    5,  6,  11, 12, //
-    13, 14, 15, 16, //
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<float> bias_data{1, 2, 3, 4};
-  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::U8);
-  Tensor scratchpad(DataType::U8, Shape({}), {}, "");
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 2;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::RELU;
-
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &scratchpad,
-                         params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputMismatchDepthwiseConv2DKernel 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(DepthwiseConv2DTest, InvalidInputShape_NEG)
+TEST_F(DepthwiseConv2DTest, Wrong_bias_type_NEG)
 {
-  Shape input_shape{4, 2, 2};
-  Shape filter_shape{2, 2, 4};
-  Shape bias_shape{4};
-  std::vector<float> input_data{
-    1,  2,  7,  8,  //
-    3,  4,  9,  10, //
-    5,  6,  11, 12, //
-    13, 14, 15, 16, //
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<float> bias_data{1, 2, 3, 4};
-  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 scratchpad(DataType::FLOAT32, Shape({}), {}, "");
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 2;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::RELU;
-
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &scratchpad,
-                         params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataWrongBiasTypeDepthwiseConv2DKernel 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(DepthwiseConv2DTest, InvalidFilterShape_NEG)
+TEST_F(DepthwiseConv2DTest, Invalid_input_type_NEG)
 {
-  Shape input_shape{1, 4, 2, 2};
-  Shape filter_shape{2, 1, 2, 4};
-  Shape bias_shape{4};
-  std::vector<float> input_data{
-    1,  2,  7,  8,  //
-    3,  4,  9,  10, //
-    5,  6,  11, 12, //
-    13, 14, 15, 16, //
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<float> bias_data{1, 2, 3, 4};
-  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 scratchpad(DataType::FLOAT32, Shape({}), {}, "");
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 2;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::RELU;
-
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &scratchpad,
-                         params);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(DepthwiseConv2DTest, InvalidBiasDim_NEG)
-{
-  Shape input_shape{1, 4, 2, 2};
-  Shape filter_shape{1, 2, 4, 2};
-  Shape bias_shape{4};
-  std::vector<float> input_data{
-    1,  2,  7,  8,  //
-    3,  4,  9,  10, //
-    5,  6,  11, 12, //
-    13, 14, 15, 16, //
-  };
-  std::vector<float> filter_data{
-    1,  2,   3,   4,   //
-    -9, 10,  -11, 12,  //
-    5,  6,   7,   8,   //
-    13, -14, 15,  -16, //
-  };
-  std::vector<float> bias_data{1, 2, 3, 4};
-  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 scratchpad(DataType::FLOAT32, Shape({}), {}, "");
-
-  DepthwiseConv2DParams params{};
-  params.padding = Padding::VALID;
-  params.depth_multiplier = 2;
-  params.stride_height = 2;
-  params.stride_width = 1;
-  params.dilation_height_factor = 1;
-  params.dilation_width_factor = 1;
-  params.activation = Activation::RELU;
-
-  DepthwiseConv2D kernel(&input_tensor, &filter_tensor, &bias_tensor, &output_tensor, &scratchpad,
-                         params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInvalidInputTypeDepthwiseConv2DKernel 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
index a097342..c378b68 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Dequantize.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "SISOKernel.h"
+
 #include "PALDequantize.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 
-Dequantize::Dequantize(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
-
-void Dequantize::configure()
+void configure_kernel_CircleDequantize(const circle::Operator *cur_op,
+                                       BaseRuntimeGraph *runtime_graph)
 {
-  LUCI_INTERPRETER_CHECK(input()->element_type() == DataType::S8 ||
-                         input()->element_type() == DataType::U8 ||
-                         input()->element_type() == DataType::S16);
+#ifndef DIS_QUANT
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-  LUCI_INTERPRETER_CHECK(input()->scales().size() == 1);
+  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()));
+  LUCI_INTERPRETER_CHECK(!Tensor::scales(kernel.input()).empty());
+  LUCI_INTERPRETER_CHECK(!Tensor::zero_points(kernel.input()).empty());
+#else
+  assert(false && "Remove DIS_QUANT flag");
+#endif // DIS_QUANT
+}
 
-  if (input()->element_type() == DataType::S16)
-    LUCI_INTERPRETER_CHECK(input()->zero_point() == 0);
+void execute_kernel_CircleDequantize(const circle::Operator *cur_op,
+                                     BaseRuntimeGraph *runtime_graph)
+{
+#ifndef DIS_QUANT
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-  LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::FLOAT32);
+  const auto *input_data = runtime_graph->getDataByTensor(kernel.input());
+  assert(input_data);
 
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(input()->shape());
-}
+  auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+  assert(output_data);
 
-void Dequantize::execute() const
-{
-  tflite::DequantizationParams op_params;
-  op_params.zero_point = input()->zero_point();
-  op_params.scale = input()->scale();
+  const int flat_size = kernels::getTensorRuntimeShape(kernel.input(), runtime_graph).flatSize();
 
-  switch (input()->element_type())
+  switch (Tensor::element_type(kernel.output()))
   {
-    case DataType::U8:
-    {
-      luci_interpreter_pal::Dequantize(op_params, getTensorShape(input()),
-                                       getTensorData<uint8_t>(input()), getTensorShape(output()),
-                                       getTensorData<float>(output()));
-      break;
-    }
-    case DataType::S8:
-    {
-      luci_interpreter_pal::Dequantize(op_params, getTensorShape(input()),
-                                       getTensorData<int8_t>(input()), getTensorShape(output()),
-                                       getTensorData<float>(output()));
-      break;
-    }
-    case DataType::S16:
+#ifndef DIS_FLOAT
+    case DataType::FLOAT32:
     {
-      luci_interpreter_pal::Dequantize(op_params, getTensorShape(input()),
-                                       getTensorData<int16_t>(input()), getTensorShape(output()),
-                                       getTensorData<float>(output()));
+      luci_interpreter_pal::QuantizationParams params{};
+      params.zero_point = Tensor::zero_point(kernel.input());
+      params.scale = Tensor::scale(kernel.input());
+      switch (Tensor::element_type(kernel.input()))
+      {
+        case DataType::S8:
+          luci_interpreter_pal::Dequantize(params, flat_size,
+                                           kernels::getTensorData<int8_t>(input_data),
+                                           kernels::getTensorData<float>(output_data));
+          break;
+        case DataType::U8:
+          luci_interpreter_pal::Dequantize(params, flat_size,
+                                           kernels::getTensorData<uint8_t>(input_data),
+                                           kernels::getTensorData<float>(output_data));
+          break;
+        case DataType::S16:
+          luci_interpreter_pal::Dequantize(params, flat_size,
+                                           kernels::getTensorData<int16_t>(input_data),
+                                           kernels::getTensorData<float>(output_data));
+          break;
+        default:
+          assert(false && "Unsupported type");
+      }
       break;
     }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
+#else
+  assert(false && "Remove DIS_QUANT flag");
+#endif // DIS_QUANT
 }
 
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Dequantize.h b/onert-micro/luci-interpreter/src/kernels/Dequantize.h
deleted file mode 100644 (file)
index 5565df0..0000000
+++ /dev/null
@@ -1,43 +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.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_DEQUANTIZE_H
-#define LUCI_INTERPRETER_KERNELS_DEQUANTIZE_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Dequantize : public Kernel
-{
-public:
-  Dequantize(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;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_DEQUANTIZE_H
index 0cab633..f8aa9a6 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Dequantize.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/dequantize/FloatDequantizeKernel.h"
+#include "luci_interpreter/test_models/dequantize/NegDequantizeKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -30,120 +30,59 @@ using namespace testing;
 
 class DequantizeTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(DequantizeTest, Uint8)
-{
-  std::vector<uint8_t> input_data{0, 1, 2, 3, 4, 251, 252, 253, 254, 255};
-
-  std::vector<float> ref_output_data{-63.5, -63, -62.5, -62, -61.5, 62, 62.5, 63, 63.5, 64};
-
-  Tensor input_tensor(loco::DataType::U8, {2, 5}, {{0.5}, {127}}, "");
-
-  _memory_manager->allocate_memory(input_tensor);
-  input_tensor.writeData(input_data.data(), input_data.size() * sizeof(uint8_t));
-
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Dequantize 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, 5}));
-}
-
-TEST_F(DequantizeTest, Sint8)
-{
-  std::vector<int8_t> input_data{-128, -127, -126, -125, -124, 123, 124, 125, 126, 127};
-
-  std::vector<float> ref_output_data{-63.5, -63, -62.5, -62, -61.5, 62, 62.5, 63, 63.5, 64};
-
-  Tensor input_tensor(loco::DataType::S8, {2, 5}, {{0.5}, {-1}}, "");
-
-  _memory_manager->allocate_memory(input_tensor);
-  input_tensor.writeData(input_data.data(), input_data.size() * sizeof(int8_t));
-
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Dequantize 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, 5}));
-}
-
-TEST_F(DequantizeTest, Sint16)
+template <typename T, typename U>
+std::vector<U> checkDequantizeKernel(test_kernel::TestDataBase<T, U> *test_data_base)
 {
-  std::vector<int16_t> input_data{-129, -126, -125, -124, -123, 124, 125, 126, 127, 131};
-
-  std::vector<float> ref_output_data{-64.5, -63, -62.5, -62, -61.5, 62, 62.5, 63, 63.5, 65.5};
-
-  Tensor input_tensor(loco::DataType::S16, {2, 5}, {{0.5}, {0}}, "");
-
-  _memory_manager->allocate_memory(input_tensor);
-  input_tensor.writeData(input_data.data(), input_data.size() * sizeof(int16_t));
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+  // 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);
 
-  Dequantize 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),
-              ::testing::ElementsAreArray(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 5}));
-}
+  // 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_F(DequantizeTest, InvalidInputType_NEG)
-{
-  std::vector<float> input_data{-129, -126, -125, -124, -123, 124, 125, 126, 127, 131};
+  runtime_module.execute();
 
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>({2, 5}, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  Dequantize kernel(&input_tensor, &output_tensor);
-  EXPECT_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(DequantizeTest, InvalidOutputType_NEG)
+TEST_F(DequantizeTest, Float_P)
 {
-  std::vector<int16_t> input_data{-129, -126, -125, -124, -123, 124, 125, 126, 127, 131};
-
-  Tensor input_tensor(loco::DataType::S16, {2, 5}, {{0.5}, {0}}, "");
-
-  _memory_manager->allocate_memory(input_tensor);
-  input_tensor.writeData(input_data.data(), input_data.size() * sizeof(int16_t));
-
-  Tensor output_tensor = makeOutputTensor(DataType::S8, /*scale*/ 0.5, /*zero_point*/ -1);
-
-  Dequantize kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::TestDataFloatDequantize test_data_kernel;
+  std::vector<float> output_data_vector = checkDequantizeKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST_F(DequantizeTest, InvalidInputZeroPoint_NEG)
+TEST_F(DequantizeTest, Input_output_shape_mismatch_NEG)
 {
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({2, 5}, 0.5, -1, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Dequantize kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputOutputShapeMismatchDequantizeKernel 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
index f8a4690..1e849ac 100644 (file)
@@ -48,6 +48,9 @@ void execute_kernel_CircleDiv(const circle::Operator *cur_op, BaseRuntimeGraph *
 
   bool is_inplace = runtime_graph->is_inplace_op(cur_op);
 
+  luci_interpreter::RuntimeShape output_shape =
+    kernels::getTensorRuntimeShape(kernel.output(), runtime_graph);
+
   switch (Tensor::element_type(kernel.input1()))
   {
 #ifndef DIS_FLOAT
@@ -58,13 +61,15 @@ void execute_kernel_CircleDiv(const circle::Operator *cur_op, BaseRuntimeGraph *
       if (is_inplace)
       {
         kernels::evalTISOInplaceKernel<float>(tiso_func, broadcast_tiso_func, &kernel, options,
-                                              std::move(input_shape1), std::move(input_shape2));
+                                              std::move(input_shape1), std::move(input_shape2),
+                                              std::move(output_shape));
       }
       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));
+                                       options, std::move(input_shape1), std::move(input_shape2),
+                                       std::move(output_shape));
       }
     }
     break;
index d601439..112a7da 100644 (file)
  * limitations under the License.
  */
 
+#include "BinaryOpCommon.h"
 #include "kernels/TestUtils.h"
 #include "luci_interpreter/test_models/div/FloatDivKernel.h"
 #include "luci_interpreter/test_models/div/NegDivKernel.h"
 
 #include "loader/ModuleLoader.h"
 
+#include "PALDiv.h"
+
+#include <array>
+#include <numeric>
+
 namespace luci_interpreter
 {
 namespace
@@ -120,3 +126,70 @@ TEST_F(DivTest, Wrong_Input2_Type_NEG)
 
 } // namespace
 } // namespace luci_interpreter
+
+namespace luci_interpreter
+{
+namespace
+{
+
+class PALDivTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(PALDivTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatDiv test_data_kernel(is_with_broadcast);
+
+    luci_interpreter_pal::ArithmeticParams params{};
+    kernels::fillArithmeticActivationRange<float>(params, kernels::Activation::NONE);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const auto num_elements = input1.size();
+    EXPECT_EQ(num_elements, input2.size());
+
+    std::vector<float> output = std::vector<float>(num_elements);
+    luci_interpreter_pal::Div<float>(params, num_elements, input1.data(), input2.data(),
+                                     const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, 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);
+
+    luci_interpreter_pal::ArithmeticParams params{};
+    kernels::fillArithmeticActivationRange<float>(params, kernels::Activation::NONE);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const int32_t shape[2] = {2, 5};
+    const int32_t shape_broadcast[2] = {2, 1};
+
+    assert(input1.size() ==
+           std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    assert(input2.size() == std::accumulate(std::begin(shape_broadcast), std::end(shape_broadcast),
+                                            1, std::multiplies<float>()));
+
+    std::vector<float> output = std::vector<float>(
+      std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    luci_interpreter_pal::BroadcastDiv4DSlow<float>(
+      params, RuntimeShape{2, shape}, input1.data(), RuntimeShape{2, shape_broadcast},
+      input2.data(), RuntimeShape{2, shape}, const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+} // namespace
+} // namespace luci_interpreter
index 76968a3..c7cbdce 100644 (file)
  */
 
 #include "Builders.h"
-#include "kernels/Utils.h"
+#include "ComparisonCommon.h"
 #include "TISOKernel.h"
 
-#include "PALComparisons.h"
-
 namespace luci_interpreter
 {
 
-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));
-
-  luci_interpreter_pal::ComparisonParams op_params;
-  op_params.is_broadcast = Tensor::num_elements(x) != Tensor::num_elements(y);
-
-  if (op_params.is_broadcast)
-  {
-    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
-  {
-    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);
-  }
-}
-
-} // namespace
-
 void configure_kernel_CircleEqual(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
   kernels::TISOKernel kernel(cur_op, runtime_graph);
@@ -79,14 +37,17 @@ void execute_kernel_CircleEqual(const circle::Operator *cur_op, BaseRuntimeGraph
   switch (Tensor::element_type(kernel.input1()))
   {
     case DataType::S64:
-      evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::EqualFn);
       break;
     case DataType::S32:
-      evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::EqualFn);
       break;
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(),
+                                            runtime_graph, luci_interpreter_pal::EqualFn);
       break;
 #endif // DIS_FLOAT
     default:
index f7871b5..6a45deb 100644 (file)
@@ -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");
  * limitations under the License.
  */
 
-#include "kernels/Floor.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
 
-#include <tensorflow/lite/kernels/internal/reference/floor.h>
+#include "PALFloor.h"
 
 namespace luci_interpreter
 {
-
-namespace kernels
+void configure_kernel_CircleFloor(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);
 
-Floor::Floor(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+  assert(input_index != -1);
+  assert(output_index != -1);
 
-void Floor::configure()
-{
-  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(input()->shape());
+  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));
+  // check that input and output dimensions are equal
+  int N = kernels::getTensorShape(input).dimensionsCount();
+  LUCI_INTERPRETER_CHECK(N == kernels::getTensorShape(output).dimensionsCount());
+
+  // check that sizes of all dimensions are equal
+  for (int i = 0; i < N; ++i)
+  {
+    LUCI_INTERPRETER_CHECK(kernels::getTensorShape(input).dims(i) ==
+                           kernels::getTensorShape(output).dims(i));
+  }
 }
 
-void Floor::execute() const
+void execute_kernel_CircleFloor(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();
-      break;
 
+      luci_interpreter_pal::Floor(
+        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 Floor::evalFloat() const
-{
-  tflite::reference_ops::Floor(getTensorShape(input()), getTensorData<float>(input()),
-                               getTensorShape(output()), getTensorData<float>(output()));
-}
-
-} // 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
deleted file mode 100644 (file)
index ca3ad59..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_FLOOR_H
-#define LUCI_INTERPRETER_KERNELS_FLOOR_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Floor : public Kernel
-{
-public:
-  Floor(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_FLOOR_H
index 30076fb..42765c7 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
+ * 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.
  * limitations under the License.
  */
 
-#include "kernels/Floor.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/floor/FloatFloorKernel.h"
+#include "luci_interpreter/test_models/floor/NegFloorKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -29,48 +30,71 @@ using namespace testing;
 
 class FloorTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(FloorTest, SimpleFloat)
+template <typename T> std::vector<T> checkFloorKernel(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(FloorTest, Float_P)
 {
-  std::initializer_list<int32_t> input_shape{1, 2, 4, 1};
-  std::vector<float> input_data{
-    0.2, 8.6, 2.4,  4.3,  // Row 1
-    3,   7.1, 10.5, -0.9, // Row 2
-  };
-
-  std::initializer_list<int32_t> ref_output_shape{1, 2, 4, 1};
-  std::vector<float> ref_output_data{
-    0, 8, 2,  4,  // Row 1
-    3, 7, 10, -1, // Row 2
-  };
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Floor 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(ref_output_shape));
+  test_kernel::TestDataFloatFloor test_data_kernel;
+  std::vector<float> output_data_vector = checkFloorKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(FloorTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchFloorKernel 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(FloorTest, Input_Output_Type_NEG)
+TEST_F(FloorTest, Invalid_input_output_shape_NEG)
 {
-  Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S32);
+  test_kernel::NegTestDataInvalidInputOutputShapeFloorKernel test_data_kernel;
 
-  Floor kernel(&input_tensor, &output_tensor);
-  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
index 6a8631a..36dc29e 100644 (file)
@@ -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.
  * limitations under the License.
  */
 
-#include "kernels/FloorDiv.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
 
-#include <tensorflow/lite/kernels/internal/reference/binary_function.h>
-#include <cmath>
+#include "kernels/BinaryOpCommon.h"
+
+#include "PALFloorDiv.h"
 
 namespace luci_interpreter
 {
 
-namespace kernels
+void configure_kernel_CircleFloorDiv(const circle::Operator *cur_op,
+                                     BaseRuntimeGraph *runtime_graph)
 {
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
 
-FloorDiv::FloorDiv(const Tensor *input, const Tensor *alpha, Tensor *output)
-  : Kernel({input, alpha}, {output})
-{
+  CheckBinaryOpDataTypesEqual(kernel);
 }
 
-void FloorDiv::configure()
+void execute_kernel_CircleFloorDiv(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  LUCI_INTERPRETER_CHECK(x()->element_type() == output()->element_type());
-  LUCI_INTERPRETER_CHECK(y()->element_type() == output()->element_type());
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
 
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(calculateShapeForBroadcast(x()->shape(), y()->shape()));
-}
+  const auto *options = cur_op->builtin_options_as_FloorDivOptions();
 
-void FloorDiv::execute() const
-{
-  switch (x()->element_type())
-  {
-    case DataType::FLOAT32:
-      evalFloat();
-      break;
-    default:
-      assert(false && "Unsupported type.");
-  }
-}
+  luci_interpreter::RuntimeShape input_shape1 =
+    kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph);
+  luci_interpreter::RuntimeShape input_shape2 =
+    kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph);
+  luci_interpreter::RuntimeShape output_shape =
+    kernels::getTensorRuntimeShape(kernel.output(), runtime_graph);
 
-void FloorDiv::evalFloat() const
-{
-  auto FloorDivFunc = [](float x, float y) -> float {
-    return std::floor(static_cast<double>(x) / static_cast<double>(y));
-  };
+  const uint8_t *input_data1 = runtime_graph->getDataByTensor(kernel.input1());
+  const uint8_t *input_data2 = runtime_graph->getDataByTensor(kernel.input2());
+  uint8_t *output_data = runtime_graph->getDataByTensor(kernel.output());
 
-  const auto x_data = getTensorData<float>(x());
-  const auto y_data = getTensorData<float>(y());
+  assert(input_data1 != nullptr);
+  assert(input_data2 != nullptr);
+  assert(output_data != nullptr);
 
-  // Check the denominator
-  for (int i = 0; i < getTensorShape(y()).FlatSize(); ++i)
+  switch (Tensor::element_type(kernel.input1()))
   {
-    LUCI_INTERPRETER_CHECK(y_data[i] != 0);
-  }
-
-  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);
-  }
-  else
-  {
-    tflite::reference_ops::BinaryFunction<float, float, float>(
-      getTensorShape(x()), x_data, getTensorShape(y()), y_data, getTensorShape(output()),
-      getTensorData<float>(output()), FloorDivFunc);
+#ifndef DIS_FLOAT
+    case DataType::FLOAT32:
+    {
+      // Check the denominator
+      for (int i = 0; i < input_shape2.flatSize(); ++i)
+      {
+        LUCI_INTERPRETER_CHECK(kernels::getTensorData<float>(input_data2)[i] != 0);
+      }
+      // check that input and output dimensions are equal
+      if (kernels::areShapesEqual(input_shape1, input_shape2))
+      {
+        const int flat_size = input_shape1.flatSize();
+        luci_interpreter_pal::FloorDiv(flat_size, kernels::getTensorData<float>(input_data1),
+                                       kernels::getTensorData<float>(input_data2),
+                                       kernels::getTensorData<float>(output_data));
+      }
+      else
+      {
+        luci_interpreter_pal::BroadcastFloorDiv4DSlow(
+          input_shape1, kernels::getTensorData<float>(input_data1), input_shape2,
+          kernels::getTensorData<float>(input_data2), output_shape,
+          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/FloorDiv.h b/onert-micro/luci-interpreter/src/kernels/FloorDiv.h
deleted file mode 100644 (file)
index e9c47d8..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_FLOOR_DIV_H
-#define LUCI_INTERPRETER_KERNELS_FLOOR_DIV_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class FloorDiv : public Kernel
-{
-public:
-  FloorDiv(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;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_FLOOR_DIV_H
index 3e1b5f1..cb1d043 100644 (file)
@@ -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");
  * limitations under the License.
  */
 
-#include "kernels/FloorDiv.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/floordiv/FloatFloorDivKernel.h"
+#include "luci_interpreter/test_models/floordiv/NegFloorDivKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -30,118 +30,160 @@ using namespace testing;
 
 class FloorDivTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(FloorDivTest, FloatSimple)
+template <typename T>
+std::vector<T> checkFloorDivKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  Shape x_shape{2, 3};
-  std::vector<float> x_data{
-    0.5, 2.4,  3.1,  // Row 1
-    1.9, -1.9, -2.8, // Row 2
-  };
-
-  Shape y_shape = x_shape;
-  std::vector<float> y_data{
-    2.0, 0.5,  3.0,  // Row 1
-    1.0, -1.0, -2.0, // Row 2
-  };
-
-  std::vector<int32_t> ref_output_shape{2, 3};
-  std::vector<float> ref_output_data{
-    0, 4, 1, // Row 1
-    1, 1, 1, // Row 2
-  };
-
-  Tensor x_tensor = makeInputTensor<DataType::FLOAT32>(x_shape, x_data, _memory_manager.get());
-  Tensor y_tensor = makeInputTensor<DataType::FLOAT32>(y_shape, y_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  FloorDiv kernel(&x_tensor, &y_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));
+  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(FloorDivTest, FloatBroadcast)
+TEST_F(FloorDivTest, Float_P)
 {
-  Shape x_shape{1, 3};
-  std::vector<float> x_data{
-    0.5, 2.4, -3.1, // Row 1
-  };
-
-  Shape y_shape{3, 3};
-  std::vector<float> y_data{
-    1.0, 1.0,  1.0,  // Row 1
-    2.0, -0.5, -2.0, // Row 2
-    0.3, 0.7,  0.9,  // Row 3
-  };
-
-  std::vector<int32_t> ref_output_shape{3, 3};
-  std::vector<float> ref_output_data{
-    0, 2,  -4, // Row 1
-    0, -5, 1,  // Row 2
-    1, 3,  -4, // Row 3
-  };
-
-  Tensor x_tensor = makeInputTensor<DataType::FLOAT32>(x_shape, x_data, _memory_manager.get());
-  Tensor y_tensor = makeInputTensor<DataType::FLOAT32>(y_shape, y_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  FloorDiv kernel(&x_tensor, &y_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));
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatFloorDiv test_data_kernel(is_with_broadcast);
+    std::vector<float> output_data_vector = checkFloorDivKernel(&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::TestDataFloatFloorDiv test_data_kernel(is_with_broadcast);
+    std::vector<float> output_data_vector = checkFloorDivKernel(&test_data_kernel);
+    EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                      test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
 }
 
-TEST_F(FloorDivTest, DivByZero_NEG)
+TEST_F(FloorDivTest, Wrong_Input1_Type_NEG)
 {
-  Shape shape{3};
-  std::vector<float> x_data{1, 0, -1};
-  std::vector<float> y_data{0, 0, 0};
+  test_kernel::NegTestDataInput1WrongTypeFloorDiv 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),
+               "");
+}
 
-  Tensor x_tensor = makeInputTensor<DataType::FLOAT32>(shape, x_data, _memory_manager.get());
-  Tensor y_tensor = makeInputTensor<DataType::FLOAT32>(shape, y_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+TEST_F(FloorDivTest, Wrong_Input2_Type_NEG)
+{
+  test_kernel::NegTestDataInput2WrongTypeFloorDiv 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),
+               "");
+}
 
-  FloorDiv kernel(&x_tensor, &y_tensor, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
+// TODO: add tests for inplace optimizations for all types
 
-  EXPECT_ANY_THROW(kernel.execute());
-}
+} // namespace
+} // namespace luci_interpreter
 
-TEST_F(FloorDivTest, Input_Output_Type_Mismatch_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::U8);
+#include "PALFloorDiv.h"
 
-  FloorDiv kernel(&x_tensor, &y_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
+#include <array>
+#include <numeric>
 
-TEST_F(FloorDivTest, Input_Type_Mismatch_NEG)
+namespace luci_interpreter
+{
+namespace
 {
-  Tensor x_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1}, _memory_manager.get());
-  Tensor y_tensor = makeInputTensor<DataType::U8>({1}, {1}, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
 
-  FloorDiv kernel(&x_tensor, &y_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+class PALFloorDivTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(PALFloorDivTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatFloorDiv test_data_kernel(is_with_broadcast);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const auto num_elements = input1.size();
+    EXPECT_EQ(num_elements, input2.size());
+
+    std::vector<float> output = std::vector<float>(num_elements);
+    luci_interpreter_pal::FloorDiv(num_elements, input1.data(), input2.data(),
+                                   const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_kernel::TestDataFloatFloorDiv test_data_kernel(is_with_broadcast);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const int32_t shape[2] = {2, 5};
+    const int32_t shape_broadcast[2] = {2, 1};
+
+    assert(input1.size() ==
+           std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    assert(input2.size() == std::accumulate(std::begin(shape_broadcast), std::end(shape_broadcast),
+                                            1, std::multiplies<float>()));
+
+    std::vector<float> output = std::vector<float>(
+      std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    luci_interpreter_pal::BroadcastFloorDiv4DSlow(
+      RuntimeShape{2, shape}, input1.data(), RuntimeShape{2, shape_broadcast}, input2.data(),
+      RuntimeShape{2, shape}, const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
 }
 
 } // namespace
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/FloorMod.cpp b/onert-micro/luci-interpreter/src/kernels/FloorMod.cpp
new file mode 100644 (file)
index 0000000..537744a
--- /dev/null
@@ -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 "Builders.h"
+#include "kernels/Utils.h"
+
+#include "kernels/BinaryOpCommon.h"
+
+#include "PALFloorMod.h"
+
+namespace luci_interpreter
+{
+
+void configure_kernel_CircleFloorMod(const circle::Operator *cur_op,
+                                     BaseRuntimeGraph *runtime_graph)
+{
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+  CheckBinaryOpDataTypesEqual(kernel);
+}
+
+void execute_kernel_CircleFloorMod(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+  const auto *options = cur_op->builtin_options_as_FloorModOptions();
+
+  luci_interpreter::RuntimeShape input_shape1 =
+    kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph);
+  luci_interpreter::RuntimeShape input_shape2 =
+    kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph);
+  luci_interpreter::RuntimeShape output_shape =
+    kernels::getTensorRuntimeShape(kernel.output(), runtime_graph);
+
+  const uint8_t *input_data1 = runtime_graph->getDataByTensor(kernel.input1());
+  const uint8_t *input_data2 = runtime_graph->getDataByTensor(kernel.input2());
+  uint8_t *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+  assert(input_data1 != nullptr);
+  assert(input_data2 != nullptr);
+  assert(output_data != nullptr);
+
+  switch (Tensor::element_type(kernel.input1()))
+  {
+#ifndef DIS_FLOAT
+    case DataType::FLOAT32:
+    {
+      // Check the denominator
+      for (int i = 0; i < input_shape2.flatSize(); ++i)
+      {
+        LUCI_INTERPRETER_CHECK(kernels::getTensorData<float>(input_data2)[i] != 0);
+      }
+      // check that input and output dimensions are equal
+      if (kernels::areShapesEqual(input_shape1, input_shape2))
+      {
+        const int flat_size = input_shape1.flatSize();
+        luci_interpreter_pal::FloorMod(flat_size, kernels::getTensorData<float>(input_data1),
+                                       kernels::getTensorData<float>(input_data2),
+                                       kernels::getTensorData<float>(output_data));
+      }
+      else
+      {
+        luci_interpreter_pal::BroadcastFloorMod4DSlow(
+          input_shape1, kernels::getTensorData<float>(input_data1), input_shape2,
+          kernels::getTensorData<float>(input_data2), output_shape,
+          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/kernels/FloorMod.test.cpp b/onert-micro/luci-interpreter/src/kernels/FloorMod.test.cpp
new file mode 100644 (file)
index 0000000..eaad79d
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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/TestUtils.h"
+#include "luci_interpreter/test_models/floormod/FloatFloorModKernel.h"
+#include "luci_interpreter/test_models/floormod/NegFloorModKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class FloorModTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T>
+std::vector<T> checkFloorModKernel(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() == 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(FloorModTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatFloorMod test_data_kernel(is_with_broadcast);
+    std::vector<float> output_data_vector = checkFloorModKernel(&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::TestDataFloatFloorMod test_data_kernel(is_with_broadcast);
+    std::vector<float> output_data_vector = checkFloorModKernel(&test_data_kernel);
+    EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                      test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(FloorModTest, Wrong_Input1_Type_NEG)
+{
+  test_kernel::NegTestDataInput1WrongTypeFloorMod 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(FloorModTest, Wrong_Input2_Type_NEG)
+{
+  test_kernel::NegTestDataInput2WrongTypeFloorMod 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
+
+#include "PALFloorMod.h"
+
+#include <array>
+#include <numeric>
+
+namespace luci_interpreter
+{
+namespace
+{
+
+class PALFloorModTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(PALFloorModTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatFloorMod test_data_kernel(is_with_broadcast);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const auto num_elements = input1.size();
+    EXPECT_EQ(num_elements, input2.size());
+
+    std::vector<float> output = std::vector<float>(num_elements);
+    luci_interpreter_pal::FloorMod(num_elements, input1.data(), input2.data(),
+                                   const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_kernel::TestDataFloatFloorMod test_data_kernel(is_with_broadcast);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const int32_t shape[2] = {2, 5};
+    const int32_t shape_broadcast[2] = {2, 1};
+
+    assert(input1.size() ==
+           std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    assert(input2.size() == std::accumulate(std::begin(shape_broadcast), std::end(shape_broadcast),
+                                            1, std::multiplies<float>()));
+
+    std::vector<float> output = std::vector<float>(
+      std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    luci_interpreter_pal::BroadcastFloorMod4DSlow(
+      RuntimeShape{2, shape}, input1.data(), RuntimeShape{2, shape_broadcast}, input2.data(),
+      RuntimeShape{2, shape}, const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+} // namespace
+} // namespace luci_interpreter
index 0493eaa..39462e0 100644 (file)
@@ -55,17 +55,71 @@ void evalFloat(const circle::Tensor *input, const circle::Tensor *weights,
 
   int32_t output_shape[kMaxSmallSize];
   kernels::getTensorDims(output, runtime_graph, output_shape);
+  // TODO remove code duplication, introduce func
+#ifndef DIS_DYN_SHAPES
+  // Dynamic shape case
+  if (output_shape[0] != input_shape[0] or output_shape[1] != weight_shape[1])
+  {
+    output_shape[0] = input_shape[0];
+    output_shape[1] = weight_shape[0];
+    uint32_t num_dims = Tensor::num_dims(output);
+    luci_interpreter::RuntimeShape dynamic_shape(num_dims);
+    int32_t data_size = 1;
+    for (int i = 0; i < num_dims; ++i)
+    {
+      dynamic_shape.setDim(i, output_shape[i]);
+      data_size *= output_shape[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);
+  }
+#endif // DIS_DYN_SHAPES
 
-  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));
+  switch (Tensor::element_type(weights))
+  {
+    case DataType::FLOAT32:
+    {
+      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), Tensor::num_dims(output),
+        Tensor::num_dims(weights));
+      break;
+    }
+    case DataType::S8:
+    {
+      // Hybrid mode
+      params.weights_scales =
+        reinterpret_cast<const float *>(weights->quantization()->scale()->data());
+      params.is_channel_wise_quant = weights->quantization()->scale()->size() > 1;
+      luci_interpreter_pal::FullyConnected(
+        params, input_shape, kernels::getTensorData<float>(input_data), weight_shape,
+        kernels::getTensorData<int8_t>(weights_data), kernels::getTensorData<float>(bias_data),
+        output_shape, kernels::getTensorData<float>(output_data), Tensor::num_dims(output),
+        Tensor::num_dims(weights));
+      break;
+    }
+    default:
+      assert(false && "Unsupported hybrid weight type");
+  }
 }
 
 #ifndef DIS_QUANT
 void evalQuantized(const circle::Tensor *input, const circle::Tensor *weights,
                    const circle::Tensor *bias, const circle::Tensor *output,
-                   const circle::FullyConnectedOptions *options, BaseRuntimeGraph *runtime_graph)
+                   const circle::FullyConnectedOptions *options, BaseRuntimeGraph *runtime_graph,
+                   DataType type)
 {
   double real_multiplier = 0.0;
   int output_shift;
@@ -80,7 +134,9 @@ void evalQuantized(const circle::Tensor *input, const circle::Tensor *weights,
                                              &output_activation_max);
 
   int32_t input_offset = -Tensor::zero_point(input);
-  int32_t filter_offset = -Tensor::zero_point(weights);
+  int32_t filter_offset = 0;
+  if (type == DataType::U8)
+    filter_offset = -Tensor::zero_point(weights);
   int32_t output_offset = Tensor::zero_point(output);
 
   luci_interpreter_pal::FullyConnectedParams op_params{};
@@ -112,11 +168,34 @@ void evalQuantized(const circle::Tensor *input, const circle::Tensor *weights,
 
   int32_t output_shape[kMaxSmallSize];
   kernels::getTensorDims(output, runtime_graph, output_shape);
-
-  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));
+  if (type == DataType::S8)
+  {
+    luci_interpreter_pal::FullyConnected<int8_t>(
+      op_params, input_shape, kernels::getTensorData<int8_t>(input_data), weights_shape,
+      kernels::getTensorData<int8_t>(weights_data), kernels::getTensorData<int32_t>(bias_data),
+      output_shape, kernels::getTensorData<int8_t>(output_data), Tensor::num_dims(output),
+      Tensor::num_dims(weights));
+  }
+  else if (type == DataType::U8)
+  {
+    luci_interpreter_pal::FullyConnected<uint8_t>(
+      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), Tensor::num_dims(output),
+      Tensor::num_dims(weights));
+  }
+  else if (type == DataType::S16)
+  {
+    luci_interpreter_pal::FullyConnected(
+      op_params, input_shape, kernels::getTensorData<int16_t>(input_data), weights_shape,
+      kernels::getTensorData<int8_t>(weights_data), kernels::getTensorData<int64_t>(bias_data),
+      output_shape, kernels::getTensorData<int16_t>(output_data), Tensor::num_dims(output),
+      Tensor::num_dims(weights));
+  }
+  else
+  {
+    assert(false && "Unsupported quantize type");
+  }
 }
 #endif
 
@@ -144,7 +223,14 @@ void configure_kernel_CircleFullyConnected(const circle::Operator *cur_op,
   assert(output != nullptr);
 
 #ifndef DIS_FLOAT
-  if (Tensor::element_type(weights) == DataType::FLOAT32)
+  if (Tensor::element_type(weights) == DataType::S8 and
+      Tensor::element_type(input) == DataType::FLOAT32)
+  {
+    // hybrid mode
+    LUCI_INTERPRETER_CHECK(Tensor::element_type(output) == DataType::FLOAT32);
+    LUCI_INTERPRETER_CHECK(!bias || Tensor::element_type(bias) == DataType::FLOAT32)
+  }
+  else if (Tensor::element_type(weights) == DataType::FLOAT32)
   {
     LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == DataType::FLOAT32);
     LUCI_INTERPRETER_CHECK(Tensor::element_type(output) == DataType::FLOAT32);
@@ -160,9 +246,19 @@ void configure_kernel_CircleFullyConnected(const circle::Operator *cur_op,
   }
   else if (Tensor::element_type(weights) == DataType::S8)
   {
-    LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == DataType::S8);
-    LUCI_INTERPRETER_CHECK(Tensor::element_type(output) == DataType::S8);
-    LUCI_INTERPRETER_CHECK(!bias || Tensor::element_type(bias) == DataType::S32)
+    LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == DataType::S8 ||
+                           Tensor::element_type(input) == DataType::FLOAT32);
+    LUCI_INTERPRETER_CHECK(Tensor::element_type(output) == DataType::S8 ||
+                           Tensor::element_type(output) == DataType::FLOAT32);
+    LUCI_INTERPRETER_CHECK(!bias || Tensor::element_type(bias) == DataType::S32 ||
+                           Tensor::element_type(bias) == DataType::S64 ||
+                           Tensor::element_type(bias) == DataType::FLOAT32)
+    if (Tensor::element_type(input) == DataType::FLOAT32)
+    {
+      // Check it is channel wise quantization
+      LUCI_INTERPRETER_CHECK(weights->quantization() != nullptr);
+      LUCI_INTERPRETER_CHECK(weights->quantization()->scale() != nullptr);
+    }
   }
 #endif // DIS_QUANT
   else
@@ -180,11 +276,6 @@ void configure_kernel_CircleFullyConnected(const circle::Operator *cur_op,
 
   if (bias)
     LUCI_INTERPRETER_CHECK(Tensor::num_elements(bias) == Tensor::dim(weights, 0));
-
-  const auto *options = cur_op->builtin_options_as_FullyConnectedOptions();
-
-  // TODO: handle with it
-  assert(options->keep_num_dims() == false);
 }
 
 // TODO think how remove unused param
@@ -210,12 +301,14 @@ void execute_kernel_CircleFullyConnected(const circle::Operator *cur_op,
   assert(output != nullptr);
 
   const auto *options = cur_op->builtin_options_as_FullyConnectedOptions();
-
-  switch (Tensor::element_type(input))
+  const auto input_type = Tensor::element_type(input);
+  switch (input_type)
   {
 #ifndef DIS_QUANT
     case DataType::U8:
-      evalQuantized(input, weights, bias, output, options, runtime_graph);
+    case DataType::S8:
+    case DataType::S16:
+      evalQuantized(input, weights, bias, output, options, runtime_graph, input_type);
       break;
 #endif // DIS_QUANT
 #ifndef DIS_FLOAT
diff --git a/onert-micro/luci-interpreter/src/kernels/FullyConnected.train.cpp b/onert-micro/luci-interpreter/src/kernels/FullyConnected.train.cpp
new file mode 100644 (file)
index 0000000..5432623
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
+#include "Builders.h"
+#include "kernels/Utils.h"
+
+namespace luci_interpreter
+{
+
+namespace training
+{
+
+namespace
+{
+
+Status computeGradients(const circle::Operator *op, CircleReader *reader,
+                        GradientCalculationStorage *gradient_calculation_storage,
+                        const circle::Tensor *weight, TrainableWeightStorage *weight_storage)
+{
+
+  const auto input_index = op->inputs()->operator[](0);
+  const auto output_index = op->outputs()->operator[](0);
+
+  assert(input_index != -1);
+  assert(output_index != -1);
+
+  const auto input = reader->tensors()[input_index];
+  const auto output = reader->tensors()[output_index];
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  uint8_t *input_data = nullptr;
+  Status status = gradient_calculation_storage->getDataByTensor(input, &input_data);
+
+  assert(input_data != nullptr);
+
+  float *input_data_float = reinterpret_cast<float *>(input_data);
+
+  if (status != Ok)
+    return status;
+
+  // output_data - save derivative of the error function by output activation for the current layer
+  uint8_t *output_data = nullptr;
+  status = gradient_calculation_storage->getDataByTensor(output, &output_data);
+
+  assert(input_data != nullptr);
+
+  float *output_data_float = reinterpret_cast<float *>(output_data);
+
+  if (status != Ok)
+    return status;
+
+  uint8_t *gradients_values = nullptr;
+
+  const auto rows = Tensor::dim(weight, 0);
+  const auto cols = Tensor::dim(weight, 1);
+
+  status = gradient_calculation_storage->getGradients(weight, &gradients_values);
+  float *gradient_values_float = reinterpret_cast<float *>(gradients_values);
+  assert(gradient_values_float != nullptr);
+
+  if (status != Ok or gradient_values_float == nullptr)
+    return status;
+
+  // Update output activation gradient with activations:
+  const auto options = op->builtin_options_as_FullyConnectedOptions();
+  const auto activation_type = luci_actfunc(options->fused_activation_function());
+  switch (activation_type)
+  {
+    case FusedActFunc::RELU:
+    {
+      for (int row = 0; row < rows; ++row)
+        output_data_float[row] = std::max(output_data_float[row], 0.f);
+    }
+    break;
+    case FusedActFunc::NONE:
+      break;
+    default:
+      assert(false && "Not supported type now");
+      return Error;
+  }
+
+  // Update weight gradients
+  for (int row = 0; row < rows; ++row)
+  {
+    for (int col = 0; col < cols; ++col)
+    {
+      gradient_values_float[col + row * cols] += output_data_float[row] * input_data_float[col];
+    }
+  }
+
+  uint8_t *weight_data = nullptr;
+
+  status = weight_storage->getTrainWeightDataByTensor(weight, &weight_data);
+  if (status != Ok)
+    return status;
+
+  assert(weight_data != nullptr);
+
+  float *weight_data_float = reinterpret_cast<float *>(weight_data);
+
+  // calculate derivative of the error function by input activation for the current layer
+  for (int col = 0; col < cols; ++col)
+  {
+    input_data_float[col] = 0;
+  }
+
+  for (int row = 0; row < rows; ++row)
+  {
+    for (int col = 0; col < cols; ++col)
+    {
+      input_data_float[row] += weight_data_float[row + col * rows] * output_data_float[col];
+    }
+  }
+
+  return Ok;
+}
+
+Status updateWeights(const circle::Operator *op, CircleReader *reader,
+                     GradientCalculationStorage *gradient_calculation_storage,
+                     const TrainingSettings &settings, TrainableWeightStorage *weight_storage,
+                     const circle::Tensor *weight)
+{
+  uint8_t *weight_data = nullptr;
+  Status status = weight_storage->getTrainWeightDataByTensor(weight, &weight_data);
+
+  assert(weight_data != nullptr);
+
+  float *weight_data_float = reinterpret_cast<float *>(weight_data);
+
+  if (status != Ok)
+    return status;
+
+  uint8_t *gradients_values = nullptr;
+
+  const auto rows = Tensor::dim(weight, 0);
+  const auto cols = Tensor::dim(weight, 1);
+
+  status = gradient_calculation_storage->getGradients(weight, &gradients_values);
+  float *gradient_values_float = nullptr;
+
+  gradient_values_float = reinterpret_cast<float *>(gradients_values);
+
+  assert(gradient_values_float != nullptr);
+
+  if (status != Ok or gradient_values_float == nullptr)
+    return status;
+
+  for (int row = 0; row < rows; ++row)
+  {
+    for (int col = 0; col < cols; ++col)
+    {
+      weight_data_float[col + row * cols] -=
+        settings.learning_rate * gradient_values_float[col + row * cols] / settings.batch_size;
+    }
+  }
+
+  return Ok;
+}
+
+} // namespace
+
+Status train_kernel_CircleFullyConnected(const circle::Operator *op, CircleReader *reader,
+                                         GradientCalculationStorage *gradient_calculation_storage,
+                                         const TrainingSettings &settings,
+                                         TrainableWeightStorage *weight_storage,
+                                         bool is_compute_gradient)
+{
+  const auto weight_index = op->inputs()->operator[](1);
+  assert(weight_index != -1);
+  const auto weights = reader->tensors()[weight_index];
+  assert(weights != nullptr);
+
+  // TODO add template and switch via type
+  if (is_compute_gradient)
+    return computeGradients(op, reader, gradient_calculation_storage, weights, weight_storage);
+
+  return updateWeights(op, reader, gradient_calculation_storage, settings, weight_storage, weights);
+}
+} // namespace training
+} // namespace luci_interpreter
+#endif // ENABLE_TRAINING
diff --git a/onert-micro/luci-interpreter/src/kernels/GatherND.cpp b/onert-micro/luci-interpreter/src/kernels/GatherND.cpp
new file mode 100644 (file)
index 0000000..c9c4139
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PALGatherND.h"
+
+#include <cassert>
+
+namespace luci_interpreter
+{
+
+void configure_kernel_CircleGatherND(const circle::Operator *cur_op,
+                                     BaseRuntimeGraph *runtime_graph)
+{
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+                         Tensor::element_type(kernel.output()));
+
+  const int params_rank = Tensor::num_dims(kernel.input1());
+  const int indices_rank = Tensor::num_dims(kernel.input2());
+  const int indices_nd = Tensor::dim(kernel.input2(), indices_rank - 1);
+
+  LUCI_INTERPRETER_CHECK(params_rank >= 1);
+  LUCI_INTERPRETER_CHECK(indices_rank >= 1);
+  LUCI_INTERPRETER_CHECK(indices_nd <= params_rank);
+  LUCI_INTERPRETER_CHECK(indices_nd <= luci_interpreter_pal::MAX_INDICES_ND);
+}
+
+void execute_kernel_CircleGatherND(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+  const uint8_t *params_data = runtime_graph->getDataByTensor(kernel.input1());
+  const uint8_t *indies_data = runtime_graph->getConstDataByTensor(kernel.input2());
+  uint8_t *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+  switch (Tensor::element_type(kernel.input1()))
+  {
+#ifndef DIS_FLOAT
+    case DataType::FLOAT32:
+      return luci_interpreter_pal::GatherND<float, int32_t>(
+        kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph),
+        kernels::getTensorData<float>(params_data),
+        kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph),
+        kernels::getTensorData<int32_t>(indies_data), kernels::getTensorData<float>(output_data));
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
+  }
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/GatherND.test.cpp b/onert-micro/luci-interpreter/src/kernels/GatherND.test.cpp
new file mode 100644 (file)
index 0000000..27080c0
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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 "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/gather_nd/FloatGatherNDKernel.h"
+#include "luci_interpreter/test_models/gather_nd/NegGatherNDKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class GatherNDTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T>
+std::vector<T> checkGatherNDKernel(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(GatherNDTest, Gather_Float_P)
+{
+  test_kernel::TestDataFloatGatherND test_data_float_gather;
+  std::vector<float> output_data_vector = checkGatherNDKernel(&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(GatherNDTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchGatherNDKernel 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
index b073a4a..04b7655 100644 (file)
  */
 
 #include "Builders.h"
-#include "kernels/Utils.h"
+#include "ComparisonCommon.h"
 #include "TISOKernel.h"
 
-#include "PALComparisons.h"
-
 namespace luci_interpreter
 {
 
-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));
-
-  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::GreaterFn);
-}
-
-} // namespace
-
 void configure_kernel_CircleGreater(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
   kernels::TISOKernel kernel(cur_op, runtime_graph);
@@ -70,14 +37,17 @@ void execute_kernel_CircleGreater(const circle::Operator *cur_op, BaseRuntimeGra
   switch (Tensor::element_type(kernel.input1()))
   {
     case DataType::S64:
-      evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::GreaterFn);
       break;
     case DataType::S32:
-      evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::GreaterFn);
       break;
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(),
+                                            runtime_graph, luci_interpreter_pal::GreaterFn);
       break;
 #endif // DIS_FLOAT
     default:
index dfb585d..76aecd9 100644 (file)
  */
 
 #include "Builders.h"
-#include "kernels/Utils.h"
+#include "ComparisonCommon.h"
 #include "TISOKernel.h"
 
-#include "PALComparisons.h"
-
 namespace luci_interpreter
 {
 
-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));
-
-  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);
-}
-
-} // namespace
-
 void configure_kernel_CircleGreaterEqual(const circle::Operator *cur_op,
                                          BaseRuntimeGraph *runtime_graph)
 {
@@ -72,14 +39,17 @@ void execute_kernel_CircleGreaterEqual(const circle::Operator *cur_op,
   switch (Tensor::element_type(kernel.input1()))
   {
     case DataType::S64:
-      evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::GreaterEqualFn);
       break;
     case DataType::S32:
-      evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::GreaterEqualFn);
       break;
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(),
+                                            runtime_graph, luci_interpreter_pal::GreaterEqualFn);
       break;
 #endif // DIS_FLOAT
     default:
index 971708b..73adbd7 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#include "kernels/If.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
 
 #include <cstring>
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 
-static std::vector<const Tensor *> joinInputs(const Tensor *cond,
-                                              const std::vector<const Tensor *> &inputs)
+void configure_kernel_CircleIf(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  std::vector<const Tensor *> result{cond};
-  result.insert(result.cend(), inputs.cbegin(), inputs.cend());
-  return result;
-}
+  auto *main_runtime_graph = runtime_graph;
 
-If::If(const Tensor *cond, const std::vector<const Tensor *> &inputs, std::vector<Tensor *> outputs,
-       RuntimeGraph *then_graph, RuntimeGraph *else_graph)
-  : Kernel(joinInputs(cond, inputs), std::move(outputs)), _then_graph(then_graph),
-    _else_graph(else_graph)
-{
-}
+  auto *runtime_module = runtime_graph->getRuntimeModule();
 
-void If::configure()
-{
-  LUCI_INTERPRETER_CHECK(cond()->element_type() == DataType::BOOL);
-  LUCI_INTERPRETER_CHECK(cond()->shape().num_elements() == 1);
+  const auto *options = cur_op->builtin_options_as_IfOptions();
+
+  const auto cond_index = cur_op->inputs()->operator[](0);
+  const auto output_index = cur_op->outputs()->operator[](0);
 
-  for (RuntimeGraph *graph : {_then_graph, _else_graph})
+  const auto then_subgraph_index = options->then_subgraph_index();
+  const auto else_subgraph_index = options->else_subgraph_index();
+
+  assert(cond_index != -1);
+  assert(output_index != -1);
+
+  assert(then_subgraph_index != -1);
+  assert(else_subgraph_index != -1);
+
+  const auto cond = runtime_graph->getCircleTensorByIndex(cond_index);
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(cond) == DataType::BOOL);
+  LUCI_INTERPRETER_CHECK(Tensor::num_elements(cond) == 1);
+
+  const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+  auto *then_subgraph = runtime_module->getRuntimeGraphAt(then_subgraph_index);
+  auto *else_subgraph = runtime_module->getRuntimeGraphAt(else_subgraph_index);
+  for (RuntimeGraph *graph : {then_subgraph, else_subgraph})
   {
-    (void)graph;
-    LUCI_INTERPRETER_CHECK(graph->getInputTensors().size() == getInputTensors().size() - 1);
-    LUCI_INTERPRETER_CHECK(graph->getOutputTensors().size() == getOutputTensors().size());
+    graph->selectOwnSubgraph();
+    const auto graph_input_size = graph->getNumOfInputTensors();
+    const auto graph_output_size = graph->getNumOfOutputTensors();
+    LUCI_INTERPRETER_CHECK(graph_input_size == cur_op->inputs()->size() - 1);
+    LUCI_INTERPRETER_CHECK(graph_output_size == cur_op->outputs()->size());
+    graph->invalidate();
+    graph->configure(false);
   }
+  main_runtime_graph->selectOwnSubgraph();
 }
 
-void If::execute() const
+void execute_kernel_CircleIf(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  const bool cond_value = cond()->data<bool>()[0];
+  auto *main_runtime_graph = runtime_graph;
+  auto *runtime_module = runtime_graph->getRuntimeModule();
+
+  const auto input_size = cur_op->inputs()->size() - 1;
+  const auto output_size = cur_op->outputs()->size();
+
+  std::vector<uint8_t *> operation_inputs_data(input_size);
+  std::vector<uint8_t *> operation_outputs_data(output_size);
 
-  RuntimeGraph *active_graph = cond_value ? _then_graph : _else_graph;
-  const auto &graph_inputs = active_graph->getInputTensors();
-  const auto &graph_outputs = active_graph->getOutputTensors();
+  std::vector<int32_t> input_sizes(input_size);
+  std::vector<int32_t> output_sizes(output_size);
 
-  // Copy kernel inputs to active graph inputs.
-  for (size_t i = 0; i < getInputTensors().size() - 1; ++i)
+  const auto *options = cur_op->builtin_options_as_IfOptions();
+  const auto cond_index = cur_op->inputs()->operator[](0);
+
+  const auto then_subgraph_index = options->then_subgraph_index();
+  const auto else_subgraph_index = options->else_subgraph_index();
+
+  auto *then_subgraph = runtime_module->getRuntimeGraphAt(then_subgraph_index);
+  auto *else_subgraph = runtime_module->getRuntimeGraphAt(else_subgraph_index);
+
+  const auto cond = runtime_graph->getCircleTensorByIndex(cond_index);
+
+  const uint8_t *cond_data = runtime_graph->getDataByTensor(cond);
+  const bool cond_value = kernels::getTensorData<bool>(cond_data)[0];
+
+  RuntimeGraph *active_graph = cond_value ? then_subgraph : else_subgraph;
+
+  for (int32_t i = 0; i < input_size; ++i)
   {
-    LUCI_INTERPRETER_CHECK(graph_inputs[i]->element_type() == input(i)->element_type());
-    graph_inputs[i]->resize(input(i)->shape());
-
-    const int32_t num_elements = input(i)->shape().num_elements();
-    const std::size_t element_size = getDataTypeSize(input(i)->element_type());
-    // TODO: Think about how allocate memory for output in main graph
-    active_graph->configureAllocations(graph_inputs[i]);
-    std::memcpy(graph_inputs[i]->data<void>(), input(i)->data<void>(), num_elements * element_size);
+    const auto op_input_index = cur_op->inputs()->operator[](i + 1);
+    assert(op_input_index != -1);
+    const auto input = main_runtime_graph->getCircleTensorByIndex(op_input_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 (input_data == nullptr)
+      input_data = main_runtime_graph->getConstDataByTensor(input);
+    assert(input_data != nullptr);
+    tensor_data = main_runtime_graph->getDataByTensor(input);
+    assert(tensor_data != nullptr);
+
+    operation_inputs_data[i] = tensor_data;
   }
+  for (int32_t i = 0; i < output_size; ++i)
+  {
+    const auto op_output_index = cur_op->outputs()->operator[](i);
+    assert(op_output_index != -1);
+    const auto output = main_runtime_graph->getCircleTensorByIndex(op_output_index);
+    output_sizes[i] = Tensor::num_elements(output) * size(Tensor::element_type(output));
 
+    auto *output_data = main_runtime_graph->getDataByTensor(output);
+
+    uint8_t *tensor_data = nullptr;
+    if (output_data == nullptr)
+      output_data = main_runtime_graph->getConstDataByTensor(output);
+    assert(output_data != nullptr);
+    tensor_data = main_runtime_graph->getDataByTensor(output);
+    assert(tensor_data != nullptr);
+
+    operation_outputs_data[i] = tensor_data;
+  }
+  active_graph->selectOwnSubgraph();
+  for (int32_t i = 0; i < input_size; ++i)
+    active_graph->configureGraphInput(i, operation_inputs_data[i]);
   active_graph->execute();
 
-  // Copy graph outputs to kernel outputs.
-  for (size_t i = 0; i < getOutputTensors().size(); ++i)
+  for (int32_t i = 0; i < output_size; ++i)
   {
-    LUCI_INTERPRETER_CHECK(graph_outputs[i]->element_type() == output(i)->element_type());
-    output(i)->resize(graph_outputs[i]->shape());
-    // TODO: Think about how allocate memory for output in main graph
-    active_graph->configureAllocations(output(i));
-
-    const int32_t num_elements = output(i)->shape().num_elements();
-    const std::size_t element_size = getDataTypeSize(output(i)->element_type());
-    std::memcpy(output(i)->data<void>(), graph_outputs[i]->data<void>(),
-                num_elements * element_size);
+    auto cur_output_active_data = active_graph->getOutputDataByIndex(i);
+    if (cur_output_active_data == nullptr)
+      continue;
+    std::memcpy(operation_outputs_data[i], cur_output_active_data, output_sizes[i]);
   }
+  active_graph->resetOutputTensorsData();
+  active_graph->clearTensors();
+  main_runtime_graph->selectOwnSubgraph();
 }
 
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/If.h b/onert-micro/luci-interpreter/src/kernels/If.h
deleted file mode 100644 (file)
index fa6ab37..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_IF_H
-#define LUCI_INTERPRETER_KERNELS_IF_H
-
-#include "core/Kernel.h"
-#include "core/RuntimeGraph.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class If : public Kernel
-{
-public:
-  If(const Tensor *cond, const std::vector<const Tensor *> &inputs, std::vector<Tensor *> outputs,
-     RuntimeGraph *then_graph, RuntimeGraph *else_graph);
-
-  const Tensor *cond() const { return _inputs[0]; }
-  const Tensor *input(int index) const { return _inputs[1 + index]; }
-  Tensor *output(int index) const { return _outputs[index]; }
-
-  void configure() override;
-  void execute() const override;
-
-private:
-  RuntimeGraph *const _then_graph;
-  RuntimeGraph *const _else_graph;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_IF_H
index c5f4faf..301ae14 100644 (file)
@@ -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");
  * limitations under the License.
  */
 
-#include "core/RuntimeModule.h"
-#include "kernels/Add.h"
-#include "kernels/If.h"
-#include "kernels/Mul.h"
 #include "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/if/IfKernel.h"
+#include "luci_interpreter/test_models/if/NegIfKernel.h"
 
-#include "luci_interpreter/TestMemoryManager.h"
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -34,128 +30,69 @@ using namespace testing;
 
 class IfTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-RuntimeGraph *buildAddSubgraph(RuntimeModule *module, IMemoryManager *memory_manager)
+template <typename T> std::vector<T> checkIfKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  RuntimeGraph *graph = module->addGraph(memory_manager);
-  Tensor *input1 = graph->addTensor(
-    std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
-  Tensor *input2 = graph->addTensor(
-    std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
-  Tensor *output = graph->addTensor(
-    std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
-
-  memory_manager->allocate_memory(*input1);
-  memory_manager->allocate_memory(*input2);
-  memory_manager->allocate_memory(*output);
-
-  graph->setInputTensors({input1, input2});
-  graph->setOutputTensors({output});
-
-  AddParams params{};
-  params.activation = Activation::NONE;
-  graph->addKernel(std::make_unique<Add>(input1, input2, output, params));
-
-  return graph;
+  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 cond input data
+  {
+    // assume that tensor is bool of size 1
+    bool *input_tensor_data = reinterpret_cast<bool *>(main_runtime_graph->configureGraphInput(0));
+    *input_tensor_data = static_cast<bool>(test_data_base->get_input_data_by_index(0)[0]);
+  }
+  // Set input1 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 input2 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;
 }
 
-RuntimeGraph *buildMulSubgraph(RuntimeModule *module, IMemoryManager *memory_manager)
+TEST_F(IfTest, MainTest_P)
 {
-  RuntimeGraph *graph = module->addGraph(memory_manager);
-  Tensor *input1 = graph->addTensor(
-    std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
-  Tensor *input2 = graph->addTensor(
-    std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
-  Tensor *output = graph->addTensor(
-    std::make_unique<Tensor>(DataType::FLOAT32, Shape{}, AffineQuantization{}, ""));
-
-  memory_manager->allocate_memory(*input1);
-  memory_manager->allocate_memory(*input2);
-  memory_manager->allocate_memory(*output);
-
-  graph->setInputTensors({input1, input2});
-  graph->setOutputTensors({output});
-
-  MulParams params{};
-  params.activation = Activation::NONE;
-  graph->addKernel(std::make_unique<Mul>(input1, input2, output, params));
-
-  return graph;
+  test_kernel::TestDataIfKernel<float> test_data_kernel;
+  std::vector<float> output_data_vector = checkIfKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
 }
 
-TEST_F(IfTest, CondTrue)
+TEST_F(IfTest, MainTest_NEG)
 {
-  Tensor cond = makeInputTensor<DataType::BOOL>({1}, {true}, _memory_manager.get());
-  Tensor input1 = makeInputTensor<DataType::FLOAT32>({2}, {5, 7}, _memory_manager.get());
-  Tensor input2 = makeInputTensor<DataType::FLOAT32>({1, 2}, {1, 2}, _memory_manager.get());
-  Tensor output = makeOutputTensor(DataType::FLOAT32);
-
-  RuntimeModule module(nullptr);
-  RuntimeGraph *then_graph = buildAddSubgraph(&module, _memory_manager.get());
-  RuntimeGraph *else_graph = buildMulSubgraph(&module, _memory_manager.get());
-
-  If kernel(&cond, {&input1, &input2}, {&output}, then_graph, else_graph);
-  kernel.configure();
-  _memory_manager->allocate_memory(output);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<float>(output), FloatArrayNear({6, 9}));
-}
-
-TEST_F(IfTest, CondFalse)
-{
-  Tensor cond = makeInputTensor<DataType::BOOL>({1}, {false}, _memory_manager.get());
-  Tensor input1 = makeInputTensor<DataType::FLOAT32>({2}, {5, 7}, _memory_manager.get());
-  Tensor input2 = makeInputTensor<DataType::FLOAT32>({1, 2}, {1, 2}, _memory_manager.get());
-  Tensor output = makeOutputTensor(DataType::FLOAT32);
-
-  RuntimeModule module(nullptr);
-  RuntimeGraph *then_graph = buildAddSubgraph(&module, _memory_manager.get());
-  RuntimeGraph *else_graph = buildMulSubgraph(&module, _memory_manager.get());
-
-  If kernel(&cond, {&input1, &input2}, {&output}, then_graph, else_graph);
-  kernel.configure();
-  _memory_manager->allocate_memory(output);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<float>(output), FloatArrayNear({5, 14}));
-}
-
-TEST_F(IfTest, InvalidCondType_NEG)
-{
-  Tensor cond = makeInputTensor<DataType::FLOAT32>({1}, {1}, _memory_manager.get());
-  Tensor input1 = makeInputTensor<DataType::FLOAT32>({2}, {5, 7}, _memory_manager.get());
-  Tensor input2 = makeInputTensor<DataType::FLOAT32>({1, 2}, {1, 2}, _memory_manager.get());
-  Tensor output = makeOutputTensor(DataType::FLOAT32);
-
-  RuntimeModule module(nullptr);
-  RuntimeGraph *then_graph = buildAddSubgraph(&module, _memory_manager.get());
-  RuntimeGraph *else_graph = buildMulSubgraph(&module, _memory_manager.get());
-
-  If kernel(&cond, {&input1, &input2}, {&output}, then_graph, else_graph);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(IfTest, InvalidCondElementNum_NEG)
-{
-  Tensor cond = makeInputTensor<DataType::BOOL>({2}, {false, true}, _memory_manager.get());
-  Tensor input1 = makeInputTensor<DataType::FLOAT32>({2}, {5, 7}, _memory_manager.get());
-  Tensor input2 = makeInputTensor<DataType::FLOAT32>({1, 2}, {1, 2}, _memory_manager.get());
-  Tensor output = makeOutputTensor(DataType::FLOAT32);
-
-  RuntimeModule module(nullptr);
-  RuntimeGraph *then_graph = buildAddSubgraph(&module, _memory_manager.get());
-  RuntimeGraph *else_graph = buildMulSubgraph(&module, _memory_manager.get());
-
-  If kernel(&cond, {&input1, &input2}, {&output}, then_graph, else_graph);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataIfKernel 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
index 5d1e885..ff49c28 100644 (file)
@@ -41,4 +41,21 @@ void KernelExecuteRegistry::execute_kernel(const circle::Operator *cur_op,
   specific_execute_func(cur_op, runtime_graph);
 }
 
+#ifdef ENABLE_TRAINING
+
+training::Status training::KernelTrainRegistry::train_kernel(
+  const circle::Operator *cur_op, circle::BuiltinOperator opcode, CircleReader *reader,
+  GradientCalculationStorage *gradient_calculation_storage, const TrainingSettings &settings,
+  TrainableWeightStorage *weight_storage, bool is_compute_gradient) const
+{
+  auto specific_train_func = get_kernel_train_func(opcode);
+  if (specific_train_func == nullptr)
+    assert(false && "Unsupported operator");
+
+  return specific_train_func(cur_op, reader, gradient_calculation_storage, settings, weight_storage,
+                             is_compute_gradient);
+}
+
+#endif // ENABLE_TRAINING
+
 } // namespace luci_interpreter
index 3d10f49..1db24e1 100644 (file)
@@ -142,6 +142,59 @@ private:
   KernelExecuteFunc *_operator_execute[size_t(BuilderID::Size)];
 };
 
+#ifdef ENABLE_TRAINING
+
+namespace training
+{
+class KernelTrainRegistry
+{
+public:
+  using KernelTrainFunc = Status(const circle::Operator *, CircleReader *,
+                                 GradientCalculationStorage *, const TrainingSettings &,
+                                 TrainableWeightStorage *, bool);
+
+  constexpr KernelTrainRegistry() : _operator_train()
+  {
+#define REGISTER_TRAIN_KERNEL(builtin_operator, name) \
+  register_kernel_train(BuilderID::BuiltinOperator_##builtin_operator, train_kernel_Circle##name);
+
+#if USE_GENERATED_LIST
+#include "GeneratedKernelsToBuild.lst"
+#else
+#include "KernelsToTrain.lst"
+#endif
+
+#undef REGISTER_TRAIN_KERNEL
+  }
+
+  Status train_kernel(const circle::Operator *cur_op, circle::BuiltinOperator opcode,
+                      CircleReader *reader,
+                      GradientCalculationStorage *gradient_calculation_storage,
+                      const TrainingSettings &settings, TrainableWeightStorage *weight_storage,
+                      bool is_compute_gradient) const;
+
+private:
+  constexpr KernelTrainFunc *get_kernel_train_func(circle::BuiltinOperator opcode) const
+  {
+    const auto tmp = size_t(get_builder_id(opcode));
+    assert(tmp < size_t(BuilderID::Size));
+    return _operator_train[tmp];
+  }
+
+  constexpr void register_kernel_train(BuilderID id, KernelTrainFunc *func)
+  {
+    assert(size_t(id) < size_t(BuilderID::Size));
+    _operator_train[size_t(id)] = func;
+  }
+
+private:
+  KernelTrainFunc *_operator_train[size_t(BuilderID::Size)];
+};
+
+constexpr KernelTrainRegistry kernel_train;
+} // namespace training
+#endif // ENABLE_TRAINING
+
 // Global constexpr kernel configure and kernel executor
 constexpr KernelConfigureRegistry kernel_configure;
 constexpr KernelExecuteRegistry kernel_executor;
index 97c9db8..f2178a7 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/L2Normalize.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "SISOKernel.h"
 
 #include "PALL2Normalize.h"
 
 namespace luci_interpreter
 {
 
-namespace kernels
+void configure_kernel_CircleL2Normalize(const circle::Operator *cur_op,
+                                        BaseRuntimeGraph *runtime_graph)
 {
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-L2Normalize::L2Normalize(const Tensor *input, Tensor *output, const L2NormParams &params)
-  : KernelWithParams<L2NormParams>({input}, {output}, params)
-{
+  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 L2Normalize::configure()
+void execute_kernel_CircleL2Normalize(const circle::Operator *cur_op,
+                                      BaseRuntimeGraph *runtime_graph)
 {
-  LUCI_INTERPRETER_CHECK(input()->shape().num_dims() <= 4);
-  LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::FLOAT32 ||
-                         output()->element_type() == DataType::U8);
-  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
-  if (output()->element_type() == DataType::U8)
-  {
-    LUCI_INTERPRETER_CHECK(output()->scale() == (1. / 128.));
-    LUCI_INTERPRETER_CHECK(output()->zero_point() == 128);
-  }
-  LUCI_INTERPRETER_CHECK(params().activation == Activation::NONE);
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(input()->shape());
-}
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-void L2Normalize::execute() const
-{
-  switch (output()->element_type())
+  const auto *input_data = runtime_graph->getDataByTensor(kernel.input());
+  assert(input_data);
+
+  auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+  switch (Tensor::element_type(kernel.input()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      eval<float>(0);
-      break;
-    case DataType::U8:
-      eval<uint8_t>(input()->zero_point());
+    {
+      const auto *input_data_float = kernels::getTensorData<float>(input_data);
+      auto *output_data_float = kernels::getTensorData<float>(output_data);
+
+      assert(output_data_float);
+
+      luci_interpreter_pal::L2Normalization(
+        kernels::getTensorRuntimeShape(kernel.input(), runtime_graph), input_data_float,
+        kernels::getTensorRuntimeShape(kernel.output(), runtime_graph), output_data_float);
       break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
 }
-
-template <typename T> void L2Normalize::eval(int32_t zero_point) const
-{
-  tflite::L2NormalizationParams op_params{};
-  op_params.input_zero_point = zero_point;
-  luci_interpreter_pal::L2Normalization(op_params, getTensorShape(input()),
-                                        getTensorData<T>(input()), getTensorShape(output()),
-                                        getTensorData<T>(output()));
-}
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/L2Normalize.h b/onert-micro/luci-interpreter/src/kernels/L2Normalize.h
deleted file mode 100644 (file)
index 6c7dac6..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_L2NORMALIZE_H
-#define LUCI_INTERPRETER_KERNELS_L2NORMALIZE_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class L2Normalize : public KernelWithParams<L2NormParams>
-{
-public:
-  L2Normalize(const Tensor *input, Tensor *output, const L2NormParams &params);
-
-  const Tensor *input() const { return _inputs[0]; }
-  Tensor *output() const { return _outputs[0]; }
-
-  void configure() override;
-  void execute() const override;
-
-private:
-  template <typename T> void eval(int32_t zero_point) const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_L2NORMALIZE_H
index 6f960e8..67da4bd 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "kernels/L2Normalize.h"
+
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/l2_normalization/FloatL2NormalizeKernel.h"
+#include "luci_interpreter/test_models/l2_normalization/NegL2NormalizeKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
 using namespace testing;
 
+class L2NormalizeTest : 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> checkL2NormalizeKernel(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 output_tensor = makeOutputTensor(DataType::FLOAT32);
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  L2NormParams 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);
 
-  L2Normalize kernel(&input_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(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> quant_param =
-    quantizationParams<uint8_t>(std::min(input_data) < 0 ? std::min(input_data) : 0.f,
-                                std::max(input_data) > 0 ? std::max(input_data) : 0.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, 1. / 128., 128);
-
-  L2NormParams params{};
-  params.activation = Activation::NONE;
-
-  L2Normalize kernel(&input_tensor, &output_tensor, params);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(output_data, output_tensor.scale()));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
-}
+  runtime_module.execute();
 
-template <typename T> class L2NormalizeTest : public ::testing::Test
-{
-};
-
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(L2NormalizeTest, DataTypes);
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-TYPED_TEST(L2NormalizeTest, Simple)
-{
-  Check<TypeParam>({1, 1, 1, 6}, {1, 1, 1, 6}, {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1},
-                   {-0.55, 0.3, 0.35, 0.6, -0.35, 0.05});
+  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(L2NormalizeTest, ActivationType_NEG)
+TEST_F(L2NormalizeTest, Float_P)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> input_data = {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>({1, 1, 1, 6}, input_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  L2NormParams params{};
-  params.activation = Activation::RELU6;
-
-  L2Normalize kernel(&input_tensor, &output_tensor, params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::TestDataFloatL2Normalization test_data_kernel;
+  std::vector<float> output_data_vector = checkL2NormalizeKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
 }
 
-TEST(L2NormalizeTest, InvalidOutputQuantParam_NEG)
+TEST_F(L2NormalizeTest, Input_output_type_mismatch_NEG)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> input_data = {-1.1, 0.6, 0.7, 1.2, -0.7, 0.1};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::U8>({1, 1, 1, 6}, 1. / 64., 127, input_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8, 1. / 64., 127);
-
-  L2NormParams params{};
-  params.activation = Activation::NONE;
-
-  L2Normalize kernel(&input_tensor, &output_tensor, params);
-  EXPECT_ANY_THROW(kernel.configure());
+  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),
+               "");
 }
 
 } // namespace
-} // namespace kernels
 } // namespace luci_interpreter
index e465c22..d272695 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/L2Pool2D.h"
-
-#include "kernels/Utils.h"
+#include "Pool2DCommon.h"
 
 #include "PALL2Pool2D.h"
 
 namespace luci_interpreter
 {
-
-namespace kernels
-{
-
-L2Pool2D::L2Pool2D(const Tensor *input, Tensor *output, const Pool2DParams &params)
-  : KernelWithParams<Pool2DParams>({input}, {output}, params)
+void configure_kernel_CircleL2Pool2D(const circle::Operator *cur_op,
+                                     BaseRuntimeGraph *runtime_graph)
 {
+  configure_kernel_CirclePool2DCommon(cur_op, runtime_graph);
 }
 
-void L2Pool2D::configure()
+void execute_kernel_CircleL2Pool2D(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  LUCI_INTERPRETER_CHECK(input()->shape().num_dims() == 4);
-  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
+  const kernels::SISOKernel siso_kernel(cur_op, runtime_graph);
 
-  int batches = input()->shape().dim(0);
-  int height = input()->shape().dim(1);
-  int width = input()->shape().dim(2);
-  int channels_out = input()->shape().dim(3);
+  const auto input = siso_kernel.input();
+  const auto output = siso_kernel.output();
 
-  // Matching GetWindowedOutputSize in TensorFlow.
-  auto padding = params().padding;
-  int out_width, out_height;
-  out_width = computeOutputSize(padding, width, params().filter_width, params().stride_width, 1);
-  out_height =
-    computeOutputSize(padding, height, params().filter_height, params().stride_height, 1);
-  _padding_width =
-    computePadding(params().stride_width, 1, width, params().filter_width, out_width);
-  _padding_height =
-    computePadding(params().stride_height, 1, height, params().filter_height, out_height);
+  const auto *input_data = runtime_graph->getDataByTensor(input);
+  auto *output_data = runtime_graph->getDataByTensor(output);
 
-  LUCI_INTERPRETER_CHECK(input()->element_type() == DataType::FLOAT32);
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize({batches, out_height, out_width, channels_out});
-}
+  const DataType input_type = Tensor::element_type(input);
 
-void L2Pool2D::execute() const
-{
-  switch (input()->element_type())
+  const auto params = createPoolParams(cur_op, siso_kernel);
+
+  switch (input_type)
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      float activation_min, activation_max;
-      calculateActivationRange(params().activation, &activation_min, &activation_max);
-      tflite::PoolParams op_params;
-      op_params.stride_height = params().stride_height;
-      op_params.stride_width = params().stride_width;
-      op_params.filter_height = params().filter_height;
-      op_params.filter_width = params().filter_width;
-      op_params.padding_values.height = _padding_height;
-      op_params.padding_values.width = _padding_width;
-      op_params.float_activation_min = activation_min;
-      op_params.float_activation_max = activation_max;
-      luci_interpreter_pal::L2Pool(op_params, getTensorShape(input()),
-                                   getTensorData<float>(input()), getTensorShape(output()),
-                                   getTensorData<float>(output()));
+      luci_interpreter_pal::L2Pool(
+        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/L2Pool2D.h b/onert-micro/luci-interpreter/src/kernels/L2Pool2D.h
deleted file mode 100644 (file)
index d40f5f4..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_L2POOL2D_H
-#define LUCI_INTERPRETER_KERNELS_L2POOL2D_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-#include <memory>
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class L2Pool2D : public KernelWithParams<Pool2DParams>
-{
-public:
-  L2Pool2D(const Tensor *input, Tensor *output, const Pool2DParams &params);
-
-  const Tensor *input() const { return _inputs[0]; }
-  Tensor *output() const { return _outputs[0]; }
-
-  void configure() override;
-  void execute() const override;
-
-private:
-  int32_t _padding_height = 0;
-  int32_t _padding_width = 0;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_L2POOL2D_H
index 7245456..a0984fb 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/L2Pool2D.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/l2_poop_2d/FloatL2Pool2DKernel.h"
+#include "luci_interpreter/test_models/l2_poop_2d/NegL2Pool2DKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -30,262 +30,59 @@ using namespace testing;
 
 class L2Pool2DTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(L2Pool2DTest, FloatNone)
-{
-  Shape input_shape{1, 2, 4, 1};
-  std::vector<float> input_data{
-    0, 6, 2,  4, //
-    3, 2, 10, 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.activation = Activation::NONE;
-  params.filter_height = 2;
-  params.filter_width = 2;
-  params.stride_height = 2;
-  params.stride_width = 2;
-
-  L2Pool2D kernel(&input_tensor, &output_tensor, params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{3.5, 6.5};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  // TODO make a Shape checking of output_tensor.
-}
-
-TEST_F(L2Pool2DTest, FloatRelu)
-{
-  Shape input_shape{1, 2, 4, 1};
-  std::vector<float> input_data{
-    -1, -6, 2,  4, //
-    -3, -2, 10, 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.activation = Activation::RELU;
-  params.filter_height = 2;
-  params.filter_width = 2;
-  params.stride_height = 2;
-  params.stride_width = 2;
-
-  L2Pool2D kernel(&input_tensor, &output_tensor, params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{3.53553, 6.5};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  // TODO make a Shape checking of output_tensor.
-}
-
-TEST_F(L2Pool2DTest, FloatRelu1)
-{
-  Shape input_shape{1, 2, 4, 1};
-  std::vector<float> input_data{
-    -0.1, -0.6, 2,  4, //
-    -0.3, -0.2, 10, 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.activation = Activation::RELU_N1_TO_1;
-  params.filter_height = 2;
-  params.filter_width = 2;
-  params.stride_height = 2;
-  params.stride_width = 2;
-
-  L2Pool2D kernel(&input_tensor, &output_tensor, params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{0.353553, 1.0};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  // TODO make a Shape checking of output_tensor.
-}
-
-TEST_F(L2Pool2DTest, FloatRelu6)
-{
-  Shape input_shape{1, 2, 4, 1};
-  std::vector<float> input_data{
-    -0.1, -0.6, 2,  4, //
-    -0.3, -0.2, 10, 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.activation = Activation::RELU6;
-  params.filter_height = 2;
-  params.filter_width = 2;
-  params.stride_height = 2;
-  params.stride_width = 2;
-
-  L2Pool2D kernel(&input_tensor, &output_tensor, params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{0.353553, 6.0};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  // TODO make a Shape checking of output_tensor.
-}
-
-TEST_F(L2Pool2DTest, FloatPaddingSame)
-{
-  Shape input_shape{1, 2, 4, 1};
-  std::vector<float> input_data{
-    0, 6, 2,  4, //
-    3, 2, 10, 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::SAME;
-  params.activation = Activation::NONE;
-  params.filter_height = 2;
-  params.filter_width = 2;
-  params.stride_height = 2;
-  params.stride_width = 2;
-
-  L2Pool2D kernel(&input_tensor, &output_tensor, params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{3.5, 6.5};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  // TODO make a Shape checking of output_tensor.
-}
-
-TEST_F(L2Pool2DTest, FloatPaddingSameStride)
+template <typename T>
+std::vector<T> checkL2Pool2DKernel(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, 7, //
-  };
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  Pool2DParams params{};
-  params.padding = Padding::SAME;
-  params.activation = Activation::NONE;
-  params.filter_height = 2;
-  params.filter_width = 2;
-  params.stride_height = 1;
-  params.stride_width = 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);
 
-  L2Pool2D kernel(&input_tensor, &output_tensor, params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{3.5, 6.0, 6.5, 5.70088, 2.54951, 7.2111, 8.63134, 7.0};
-  // NOTE with NEON+ruy, error is #1=-1.14441e-05, #6=-1.81198e-05
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data, 1.0e-4f));
-  // TODO make a Shape checking of output_tensor.
-}
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-TEST_F(L2Pool2DTest, FloatPaddingValidStride)
-{
-  Shape input_shape{1, 2, 4, 1};
-  std::vector<float> input_data{
-    0, 6, 2,  4, //
-    3, 2, 10, 7, //
-  };
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+  // 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);
+  }
 
-  Pool2DParams params{};
-  params.padding = Padding::VALID;
-  params.activation = Activation::NONE;
-  params.filter_height = 2;
-  params.filter_width = 2;
-  params.stride_height = 1;
-  params.stride_width = 1;
+  runtime_module.execute();
 
-  L2Pool2D kernel(&input_tensor, &output_tensor, params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  std::vector<float> ref_output_data{3.5, 6.0, 6.5};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  // TODO make a Shape checking of output_tensor.
+  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(L2Pool2DTest, InvalidInputShape_NEG)
+TEST_F(L2Pool2DTest, Float_P)
 {
-  Shape input_shape{1, 2, 4};
-  std::vector<float> input_data{
-    0, 6, 2,  4, //
-    3, 2, 10, 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.activation = Activation::NONE;
-  params.filter_height = 2;
-  params.filter_width = 2;
-  params.stride_height = 1;
-  params.stride_width = 1;
-
-  L2Pool2D kernel(&input_tensor, &output_tensor, params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::TestDataFloatL2Pool2D test_data_kernel;
+  std::vector<float> output_data_vector = checkL2Pool2DKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST_F(L2Pool2DTest, InvalidInputOutputType_NEG)
+TEST_F(L2Pool2DTest, Input_output_type_mismatch_NEG)
 {
-  Shape input_shape{1, 2, 4};
-  std::vector<float> input_data{
-    0, 6, 2,  4, //
-    3, 2, 10, 7, //
-  };
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8);
-
-  Pool2DParams params{};
-  params.padding = Padding::VALID;
-  params.activation = Activation::NONE;
-  params.filter_height = 2;
-  params.filter_width = 2;
-  params.stride_height = 1;
-  params.stride_width = 1;
-
-  L2Pool2D kernel(&input_tensor, &output_tensor, params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputOutputTypeMismatchL2Pool2DKernel 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
index 4a688e4..50dba5c 100644 (file)
  */
 
 #include "Builders.h"
-#include "kernels/Utils.h"
+#include "ComparisonCommon.h"
 #include "TISOKernel.h"
 
-#include "PALComparisons.h"
-
 namespace luci_interpreter
 {
 
@@ -77,41 +75,6 @@ void evalQuantized(const circle::Tensor *x, const circle::Tensor *y, const circl
 }
 #endif // DIS_QUANT
 
-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);
-
-  if (op_params.is_broadcast)
-  {
-    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
-  {
-    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);
-  }
-}
-
 } // namespace
 
 void configure_kernel_CircleLess(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
@@ -130,10 +93,12 @@ void execute_kernel_CircleLess(const circle::Operator *cur_op, BaseRuntimeGraph
   switch (Tensor::element_type(kernel.input1()))
   {
     case DataType::S64:
-      evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::LessFn);
       break;
     case DataType::S32:
-      evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::LessFn);
       break;
 #ifndef DIS_QUANT
     case DataType::U8:
@@ -142,7 +107,8 @@ void execute_kernel_CircleLess(const circle::Operator *cur_op, BaseRuntimeGraph
 #endif // DIS_QUANT
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(),
+                                            runtime_graph, luci_interpreter_pal::LessFn);
       break;
 #endif // DIS_FLOAT
     default:
index 8928ba4..c82558a 100644 (file)
  */
 
 #include "Builders.h"
-#include "kernels/Utils.h"
+#include "ComparisonCommon.h"
 #include "TISOKernel.h"
 
-#include "PALComparisons.h"
-
 namespace luci_interpreter
 {
 
-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));
-
-  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::LessEqualFn);
-}
-
-} // namespace
-
 void configure_kernel_CircleLessEqual(const circle::Operator *cur_op,
                                       BaseRuntimeGraph *runtime_graph)
 {
@@ -71,14 +38,17 @@ void execute_kernel_CircleLessEqual(const circle::Operator *cur_op, BaseRuntimeG
   switch (Tensor::element_type(kernel.input1()))
   {
     case DataType::S64:
-      evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::LessEqualFn);
       break;
     case DataType::S32:
-      evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::LessEqualFn);
       break;
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(),
+                                            runtime_graph, luci_interpreter_pal::LessEqualFn);
       break;
 #endif // DIS_FLOAT
     default:
diff --git a/onert-micro/luci-interpreter/src/kernels/Log.cpp b/onert-micro/luci-interpreter/src/kernels/Log.cpp
new file mode 100644 (file)
index 0000000..4650c40
--- /dev/null
@@ -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 "Builders.h"
+#include "kernels/Utils.h"
+#include "SISOKernel.h"
+
+#include "PALLog.h"
+
+namespace luci_interpreter
+{
+
+void configure_kernel_CircleLog(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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 execute_kernel_CircleLog(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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:
+    {
+      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::Log(flat_size, input_data_float, output_data_float);
+      break;
+    }
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
+  }
+
+  if (is_inplace)
+    runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Log.test.cpp b/onert-micro/luci-interpreter/src/kernels/Log.test.cpp
new file mode 100644 (file)
index 0000000..b055b0a
--- /dev/null
@@ -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 "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/log/FloatLogKernel.h"
+#include "luci_interpreter/test_models/log/NegLogKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class LogTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T> std::vector<T> checkLogKernel(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(LogTest, Float_P)
+{
+  test_kernel::TestDataFloatLog test_data_kernel;
+  std::vector<float> output_data_vector = checkLogKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(LogTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchLogKernel 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
index b467cb0..39f1226 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/LogSoftmax.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
-
-#include <tensorflow/lite/kernels/internal/reference/log_softmax.h>
+#include "SISOKernel.h"
 
 #include "PALLogSoftmax.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 
-LogSoftmax::LogSoftmax(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
-
-void LogSoftmax::configure()
+void configure_kernel_CircleLogSoftmax(const circle::Operator *cur_op,
+                                       BaseRuntimeGraph *runtime_graph)
 {
-  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
-  if (input()->element_type() == DataType::U8)
-  {
-    LUCI_INTERPRETER_CHECK(output()->scale() == 16. / 256);
-    LUCI_INTERPRETER_CHECK(output()->zero_point() == 255);
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-    tflite::SoftmaxParams params{};
-
-    params.table = _table;
-    params.beta = 1.0;
-    luci_interpreter_pal::PopulateSoftmaxLookupTable(&params, input()->scale(), params.beta);
-  }
-  // 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 LogSoftmax::execute() const
+void execute_kernel_CircleLogSoftmax(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());
+
+  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);
+      assert(output_data_float);
+
+      luci_interpreter_pal::LogSoftmax(
+        kernels::getTensorRuntimeShape(kernel.input(), runtime_graph), input_data_float,
+        kernels::getTensorRuntimeShape(kernel.output(), runtime_graph), output_data_float);
       break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
 }
-
-void LogSoftmax::evalFloat() const
-{
-  tflite::SoftmaxParams params{};
-  tflite::reference_ops::LogSoftmax(params, getTensorShape(input()), getTensorData<float>(input()),
-                                    getTensorShape(output()), getTensorData<float>(output()));
-}
-
-void LogSoftmax::evalQuantized() const
-{
-  const auto input_shape = getTensorShape(input());
-  const auto output_shape = getTensorShape(output());
-  const auto input_scale = input()->scale();
-  uint8_t *output_data = getTensorData<uint8_t>(output());
-  const uint8_t *input_data = getTensorData<uint8_t>(input());
-  const float beta = 1.0;
-
-  tflite::SoftmaxParams params{};
-
-  params.table = const_cast<float *>(_table);
-  params.zero_point = output()->zero_point();
-  params.scale = output()->scale();
-
-  luci_interpreter_pal::InitializeParams(&params, input_scale, beta);
-  luci_interpreter_pal::LogSoftmax(params, input_scale, input_shape, input_data, output_shape,
-                                   output_data);
-}
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/LogSoftmax.h b/onert-micro/luci-interpreter/src/kernels/LogSoftmax.h
deleted file mode 100644 (file)
index 18477fb..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_LOGSOFTMAX_H
-#define LUCI_INTERPRETER_KERNELS_LOGSOFTMAX_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class LogSoftmax : public Kernel
-{
-public:
-  LogSoftmax(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;
-
-  float _table[256];
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_LOGSOFTMAX_H
index 50dcd5c..423b603 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2020 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.
  * limitations under the License.
  */
 
-#include "kernels/LogSoftmax.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/log_softmax/FloatLogSoftmaxKernel.h"
+#include "luci_interpreter/test_models/log_softmax/NegLogSoftmaxKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -30,95 +29,59 @@ using namespace testing;
 
 class LogSoftmaxTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(LogSoftmaxTest, Float)
+template <typename T>
+std::vector<T> checkLogSoftmaxKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  Shape input_shape{2, 4};
-  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);
-
-  LogSoftmax kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{
-    -4.14297, -10.14297, -2.14297,   -.142971, //
-    -7.00104, -12.00104, -.00104087, -9.00104, //
-  };
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-}
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-TEST_F(LogSoftmaxTest, Uint8)
-{
-  float kMin = -10;
-  float kMax = 10;
-  float kLogSoftmaxQuantizedTolerance = 16. / 256;
-  std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(kMin, kMax);
-  std::vector<float> input_data{
-    0, -6, 2,  4, //
-    3, -2, 10, 1, //
-  };
-  Tensor input_tensor = makeInputTensor<DataType::U8>({2, 4}, quant_param.first, quant_param.second,
-                                                      input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8, 16. / 256, 255);
-
-  LogSoftmax kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{
-    -4.14297, -10.14297, -2.14297,   -.142971, //
-    -7.00104, -12.00104, -.00104087, -9.00104, //
-  };
-  std::vector<int32_t> ref_output_shape{2, 4};
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(ref_output_data, kLogSoftmaxQuantizedTolerance));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-  EXPECT_THAT(extractTensorData<uint8_t>(output_tensor),
-              ::testing::ElementsAreArray({189, 93, 221, 253, 142, 63, 255, 111}));
+  // 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(LogSoftmaxTest, InvalidInputOutputType_NEG)
+TEST_F(LogSoftmaxTest, Float_P)
 {
-  std::vector<float> input_data{
-    0, -6, 2,  4, //
-    3, -2, 10, 1, //
-  };
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>({2, 4}, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8, 16. / 256, 255);
-
-  LogSoftmax kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::TestDataFloatLogSoftmax test_data_kernel;
+  std::vector<float> output_data_vector = checkLogSoftmaxKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
 }
 
-TEST_F(LogSoftmaxTest, InvalidOutputQuantParam_NEG)
+TEST_F(LogSoftmaxTest, Input_output_type_mismatch_NEG)
 {
-  std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-10, 10);
-  std::vector<float> input_data{
-    0, -6, 2,  4, //
-    3, -2, 10, 1, //
-  };
-  Tensor input_tensor = makeInputTensor<DataType::U8>({2, 4}, quant_param.first, quant_param.second,
-                                                      input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8, 20. / 256, 255);
-
-  LogSoftmax kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputOutputTypeMismatchLogSoftmaxKernel 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
index 4ba4499..1ed6e1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 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.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#include "kernels/LogicalNot.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "SISOKernel.h"
 
-#include "kernels/BinaryOpCommon.h"
+#include "PALLogicalNot.h"
 
 namespace luci_interpreter
 {
-namespace kernels
+void configure_kernel_CircleLogicalNot(const circle::Operator *cur_op,
+                                       BaseRuntimeGraph *runtime_graph)
 {
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-LogicalNot::LogicalNot(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) == DataType::BOOL);
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.output()) == DataType::BOOL);
 
-void LogicalNot::configure()
-{
-  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(input()->shape());
-}
+  // check that input and output dimensions are equal
+  int N = Tensor::num_dims(kernel.input());
+  LUCI_INTERPRETER_CHECK(N == Tensor::num_dims(kernel.output()));
 
-void LogicalNot::execute() const
-{
-  switch (input()->element_type())
+  // check that sizes of all dimensions are equal
+  for (int i = 0; i < N; ++i)
   {
-    case DataType::BOOL:
-      evalLogicalNot();
-      break;
-    default:
-      assert(false && "Unsupported type.");
+    LUCI_INTERPRETER_CHECK(kernels::getTensorShape(kernel.input()).dims(i) ==
+                           kernels::getTensorShape(kernel.output()).dims(i));
   }
 }
 
-inline void LogicalNot::evalLogicalNot() const
+void execute_kernel_CircleLogicalNot(const circle::Operator *cur_op,
+                                     BaseRuntimeGraph *runtime_graph)
 {
-  const int size = tflite::MatchingFlatSize(getTensorShape(input()), getTensorShape(output()));
-  bool *output_data = getTensorData<bool>(output());
-  const bool *input_data = getTensorData<bool>(input());
-  for (int i = 0; i < size; ++i)
-  {
-    output_data[i] = !input_data[i];
-  }
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
+
+  auto data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(kernel.input()));
+  if (data == nullptr)
+    data = kernels::getTensorData<bool>(runtime_graph->getConstDataByTensor(kernel.input()));
+
+  assert(data != nullptr);
+
+  auto output_data = kernels::getTensorData<bool>(runtime_graph->getDataByTensor(kernel.output()));
+
+  const int64_t flat_size = kernels::getTensorShape(kernel.input()).flatSize();
+  luci_interpreter_pal::LogicalNot(flat_size, data, output_data);
 }
 
-} // namespace kernels
 } // namespace luci_interpreter
index 3cbf27f..6a9e0fa 100644 (file)
@@ -1,6 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2017 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.
  * limitations under the License.
  */
 
-#include "kernels/LogicalNot.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/logical_not/BoolLogicalNotKernel.h"
+#include "luci_interpreter/test_models/logical_not/NegLogicalNotKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -30,49 +29,72 @@ using namespace testing;
 
 class LogicalNotTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(LogicalNotTest, Basic)
+template <typename T>
+std::vector<T> checkLogicalNotKernel(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(LogicalNotTest, Bool_P)
 {
-  Shape input_shape{1, 1, 1, 4};
-  Tensor input_tensor =
-    makeInputTensor<DataType::BOOL>(input_shape, {true, false, false, true}, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::BOOL);
-
-  LogicalNot kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<bool>(output_tensor),
-              ::testing::ElementsAre(false, true, true, false));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAre(1, 1, 1, 4));
+  test_kernel::TestDataBoolLogicalNot test_data_kernel;
+  std::vector<bool> output_data_vector = checkLogicalNotKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
 }
 
-TEST_F(LogicalNotTest, OutputTypeInvalid_NEG)
+TEST_F(LogicalNotTest, Input_output_type_mismatch_NEG)
 {
-  Tensor input_tensor = makeInputTensor<DataType::BOOL>({1, 1, 1, 4}, {true, false, false, true},
-                                                        _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S32);
+  test_kernel::NegTestDataInputOutputTypeMismatchLogicalNotKernel test_data_kernel;
 
-  LogicalNot kernel(&input_tensor, &output_tensor);
-  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(LogicalNotTest, InputTypeInvalid_NEG)
+TEST_F(LogicalNotTest, Invalid_input_output_shape_NEG)
 {
-  Tensor input_tensor =
-    makeInputTensor<DataType::S32>({1, 1, 1, 4}, {1, 0, 0, 1}, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::BOOL);
+  test_kernel::NegTestDataInputOutputShapeMismatchLogicalNotKernel test_data_kernel;
 
-  LogicalNot kernel(&input_tensor, &output_tensor);
-  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
index 4dbc153..cdddeba 100644 (file)
@@ -17,6 +17,7 @@
 #include "Builders.h"
 #include "kernels/Utils.h"
 #include "PALLogistic.h"
+#include "SISOKernel.h"
 
 namespace luci_interpreter
 {
@@ -24,41 +25,25 @@ namespace luci_interpreter
 void configure_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);
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-  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::element_type(kernel.input()) ==
+                         Tensor::element_type(kernel.output()))
 
 #ifndef DIS_QUANT
-  if (Tensor::element_type(input) == DataType::U8)
+  if (Tensor::element_type(kernel.input()) == DataType::U8)
   {
-    LUCI_INTERPRETER_CHECK(Tensor::scale(output) == 1. / 256);
+    LUCI_INTERPRETER_CHECK(Tensor::scale(kernel.output()) == 1. / 256);
   }
 #endif // DIS_QUANT
 }
 
 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);
-
-  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);
+  const auto input = kernel.input();
+  const auto output = kernel.output();
 
   bool is_inplace = runtime_graph->is_inplace_op(cur_op);
 
index d85e8a9..5ae446c 100644 (file)
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-#include "Builders.h"
+#include "Pool2DCommon.h"
 
-#include "kernels/Utils.h"
 #include "PALMaxPool2D.h"
 
 namespace luci_interpreter
@@ -24,76 +23,24 @@ namespace luci_interpreter
 void configure_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);
-
-  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);
-
-#ifndef DIS_QUANT
-  if (Tensor::element_type(input) == DataType::U8)
-  {
-    LUCI_INTERPRETER_CHECK(std::abs(Tensor::scale(output) - Tensor::scale(input)) <= 1.0e-6);
-    LUCI_INTERPRETER_CHECK(Tensor::zero_point(output) == Tensor::zero_point(input));
-  }
-  else if (Tensor::element_type(input) == DataType::S16)
-  {
-    LUCI_INTERPRETER_CHECK(std::abs(Tensor::scale(output) - Tensor::scale(input)) <= 1.0e-6);
-    LUCI_INTERPRETER_CHECK(Tensor::zero_point(input) == 0 && Tensor::zero_point(output) == 0);
-  }
-#endif // DIS_QUANT
+  configure_kernel_CirclePool2DCommon(cur_op, runtime_graph);
 }
 
 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);
+  const kernels::SISOKernel siso_kernel(cur_op, runtime_graph);
 
-  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 = siso_kernel.input();
+  const auto output = siso_kernel.output();
 
   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;
+  const DataType input_type = Tensor::element_type(input);
 
-  switch (Tensor::element_type(input))
+  const auto params = createPoolParams(cur_op, siso_kernel);
+
+  switch (input_type)
   {
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
@@ -103,15 +50,11 @@ void execute_kernel_CircleMaxPool2D(const circle::Operator *cur_op, BaseRuntimeG
       break;
 #endif // DIS_FLOAT
 #ifndef DIS_QUANT
-    case DataType::U8:
-      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::S8:
     case DataType::S16:
       luci_interpreter_pal::MaxPool(
-        params, kernels::getTensorShape(input), kernels::getTensorData<int16_t>(input_data),
-        kernels::getTensorShape(output), kernels::getTensorData<int16_t>(output_data));
+        params, kernels::getTensorShape(input), kernels::getTensorData<uint8_t>(input_data),
+        kernels::getTensorShape(output), kernels::getTensorData<uint8_t>(output_data), input_type);
       break;
 #endif // DIS_QUANT
     default:
index 1a7ee4c..11edb3d 100644 (file)
@@ -1,6 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2018 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.
  * limitations under the License.
  */
 
-#include "kernels/Maximum.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
 
 #include "kernels/BinaryOpCommon.h"
 
+#include "PALMaximum.h"
+
 namespace luci_interpreter
 {
-namespace kernels
-{
 
-Maximum::Maximum(const Tensor *input1, const Tensor *input2, Tensor *output)
-  : Kernel({input1, input2}, {output})
+void configure_kernel_CircleMaximum(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-}
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
 
-void Maximum::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()));
+  kernels::CheckBinaryOpDataTypesEqual(kernel);
 }
 
-void Maximum::execute() const
+void execute_kernel_CircleMaximum(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  switch (input1()->element_type())
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+  luci_interpreter::RuntimeShape input_shape1 =
+    kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph);
+  luci_interpreter::RuntimeShape input_shape2 =
+    kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph);
+  luci_interpreter::RuntimeShape output_shape =
+    kernels::getTensorRuntimeShape(kernel.output(), runtime_graph);
+
+  const uint8_t *input_data1 = runtime_graph->getDataByTensor(kernel.input1());
+  const uint8_t *input_data2 = runtime_graph->getDataByTensor(kernel.input2());
+  uint8_t *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+  assert(input_data1 != nullptr);
+  assert(input_data2 != nullptr);
+  assert(output_data != nullptr);
+
+  switch (Tensor::element_type(kernel.input1()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalMaximum<float>();
-      break;
-    case DataType::U8:
-      evalMaximum<uint8_t>();
-      break;
+    {
+      // check that input and output dimensions are equal
+      if (kernels::areShapesEqual(input_shape1, input_shape2))
+      {
+        const int flat_size = input_shape1.flatSize();
+        luci_interpreter_pal::Maximum(flat_size, kernels::getTensorData<float>(input_data1),
+                                      kernels::getTensorData<float>(input_data2),
+                                      kernels::getTensorData<float>(output_data));
+      }
+      else
+      {
+        luci_interpreter_pal::BroadcastMaximum4DSlow(
+          input_shape1, kernels::getTensorData<float>(input_data1), input_shape2,
+          kernels::getTensorData<float>(input_data2), output_shape,
+          kernels::getTensorData<float>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
     default:
       assert(false && "Unsupported type.");
   }
 }
 
-template <typename T> inline void Maximum::evalMaximum() const
-{
-  BinaryOpBroadcastSlow(getTensorShape(input1()), getTensorData<T>(input1()),
-                        getTensorShape(input2()), getTensorData<T>(input2()),
-                        getTensorShape(output()), getTensorData<T>(output()),
-                        [](T x, T y) { return std::max(x, y); });
-}
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Maximum.h b/onert-micro/luci-interpreter/src/kernels/Maximum.h
deleted file mode 100644 (file)
index 3c99e69..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_MAXIMUM_H
-#define LUCI_INTERPRETER_KERNELS_MAXIMUM_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Maximum : public Kernel
-{
-public:
-  Maximum(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:
-  template <typename T> inline void evalMaximum() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_MAXIMUM_H
index e4a505b..2316f14 100644 (file)
@@ -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");
  * limitations under the License.
  */
 
-#include "kernels/Maximum.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/maximum/FloatMaximumKernel.h"
+#include "luci_interpreter/test_models/maximum/NegMaximumKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -30,53 +30,158 @@ using namespace testing;
 
 class MaximumTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(MaximumTest, Float)
+template <typename T>
+std::vector<T> checkMaximumKernel(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() == 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(MaximumTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatMaximum test_data_kernel(is_with_broadcast);
+    std::vector<float> output_data_vector = checkMaximumKernel(&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::TestDataFloatMaximum test_data_kernel(is_with_broadcast);
+    std::vector<float> output_data_vector = checkMaximumKernel(&test_data_kernel);
+    EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                      test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(MaximumTest, Wrong_Input1_Type_NEG)
 {
-  Shape input_shape{3, 1, 2};
-  std::vector<float> input_data1{1.0, 0.0, -1.0, 11.0, -2.0, -1.44};
-  std::vector<float> input_data2{-1.0, 0.0, 1.0, 12.0, -3.0, -1.43};
-  Tensor input_tensor1 =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data1, _memory_manager.get());
-  Tensor input_tensor2 =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data2, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Maximum kernel(&input_tensor1, &input_tensor2, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{1.0, 0.0, 1.0, 12.0, -2.0, -1.43};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+  test_kernel::NegTestDataInput1WrongTypeMaximum 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(MaximumTest, Uint8)
+TEST_F(MaximumTest, Wrong_Input2_Type_NEG)
+{
+  test_kernel::NegTestDataInput2WrongTypeMaximum 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
+
+#include "PALMaximum.h"
+
+#include <array>
+#include <numeric>
+
+namespace luci_interpreter
+{
+namespace
+{
+
+class PALMaximumTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(PALMaximumTest, Float_P)
 {
-  Shape input_shape{3, 1, 2};
-  std::vector<uint8_t> input_data1{1, 0, 2, 11, 2, 23};
-  std::vector<uint8_t> input_data2{0, 0, 1, 12, 255, 1};
-  Tensor input_tensor1 =
-    makeInputTensor<DataType::U8>(input_shape, input_data1, _memory_manager.get());
-  Tensor input_tensor2 =
-    makeInputTensor<DataType::U8>(input_shape, input_data2, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8);
-
-  Maximum kernel(&input_tensor1, &input_tensor2, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<int32_t> ref_output_shape{2, 4};
-  EXPECT_THAT(extractTensorData<uint8_t>(output_tensor),
-              ::testing::ElementsAreArray({1, 0, 2, 12, 255, 23}));
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatMaximum test_data_kernel(is_with_broadcast);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const auto num_elements = input1.size();
+    EXPECT_EQ(num_elements, input2.size());
+
+    std::vector<float> output = std::vector<float>(num_elements);
+    luci_interpreter_pal::Maximum(num_elements, input1.data(), input2.data(),
+                                  const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_kernel::TestDataFloatMaximum test_data_kernel(is_with_broadcast);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const int32_t shape[2] = {2, 5};
+    const int32_t shape_broadcast[2] = {2, 1};
+
+    assert(input1.size() ==
+           std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    assert(input2.size() == std::accumulate(std::begin(shape_broadcast), std::end(shape_broadcast),
+                                            1, std::multiplies<float>()));
+
+    std::vector<float> output = std::vector<float>(
+      std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    luci_interpreter_pal::BroadcastMaximum4DSlow(
+      RuntimeShape{2, shape}, input1.data(), RuntimeShape{2, shape_broadcast}, input2.data(),
+      RuntimeShape{2, shape}, const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
 }
 
 } // namespace
-} // namespace kernels
 } // namespace luci_interpreter
index 4128aa6..5639dd2 100644 (file)
@@ -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.
  * limitations under the License.
  */
 
-#include "kernels/Mean.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "TISOKernel.h"
+
+#include "PALMean.h"
 
-#include <tensorflow/lite/kernels/internal/reference/reduce.h>
+#include <cassert>
 
 namespace luci_interpreter
 {
-namespace kernels
+namespace
 {
+const int kMaxNumberOfAxis = 5;
+const int kMaxNumberOfReducedAxis = 2;
 
-static void resolveAxes(const int32_t *axes_data, int num_axes, tflite::MeanParams *params)
+void ResolveAxis(const int *axis_data, int axis_count, luci_interpreter_pal::MeanParams *op_params)
 {
-  params->axis_count = num_axes;
-  for (int i = 0; i < num_axes; ++i)
+  int i = 0;
+  for (; i < axis_count; ++i)
   {
-    params->axis[i] = static_cast<int16>(axes_data[i]);
+    op_params->axis[i] = static_cast<int16_t>(axis_data[i]);
   }
-  for (int i = num_axes; i < 4; ++i)
+  for (; i < 4; ++i)
   {
-    params->axis[i] = 1;
+    op_params->axis[i] = 1;
   }
+  op_params->axis_count = axis_count;
 }
 
-// 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;
-}
+} // namespace
 
-static Shape getOutputShape(const Shape &input_shape, const int32_t *axes_data, int num_axes,
-                            bool keep_dims)
+void configure_kernel_CircleMean(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  int input_num_dims = input_shape.num_dims();
-  if (input_num_dims == 0)
-  {
-    return Shape(0);
-  }
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
 
-  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;
-  }
-}
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+                         Tensor::element_type(kernel.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
 
-Mean::Mean(const Tensor *input, const Tensor *axes, Tensor *output, Tensor *temp_index,
-           Tensor *resolved_axes, Tensor *temp_sum, const ReducerParams &params)
-  : KernelWithParams<ReducerParams>({input, axes}, {output, temp_index, resolved_axes, temp_sum},
-                                    params)
-{
+  const int32_t axis_value =
+    kernels::getTensorData<int>(runtime_graph->getConstDataByTensor(kernel.input2()))[0];
+  LUCI_INTERPRETER_CHECK(axis_value >= 0);
 }
 
-void Mean::configure()
+void execute_kernel_CircleMean(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
-  LUCI_INTERPRETER_CHECK(axes()->element_type() == DataType::S32);
-  if (input()->element_type() == DataType::S16)
-  {
-    LUCI_INTERPRETER_CHECK(input()->zero_point() == 0 && output()->zero_point() == 0);
-  }
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+  kernels::TISOData tiso_data = kernel.readData();
 
-  const Shape &input_shape = input()->shape();
-  int input_num_dims = input_shape.num_dims();
+  const auto *input = kernel.input1();
+  const auto *axis = kernel.input2();
+  const auto *output = kernel.output();
 
-  const auto *axes_data = getTensorData<int32_t>(axes());
-  int num_axes = axes()->shape().num_elements();
-  assert(num_axes <= 4);
-  // TODO: enable it only if kernel with dynamic shapes
-  Shape output_shape = getOutputShape(input_shape, axes_data, num_axes, _params.keep_dims);
-  output()->resize(output_shape);
+  const auto *options = cur_op->builtin_options_as_ReducerOptions();
 
-  tflite::MeanParams params{};
-  resolveAxes(axes_data, num_axes, &params);
-  _need_temporaries = !(
-    _params.keep_dims && input_num_dims == 4 && params.axis_count == 2 &&
-    ((params.axis[0] == 1 && params.axis[1] == 2) || (params.axis[0] == 2 && params.axis[1] == 1)));
-  if (_need_temporaries)
-  {
-    auto temp_index = getOutputTensors()[1];
-    auto resolved_axes = getOutputTensors()[2];
-    auto temp_sum = getOutputTensors()[3];
+  int num_axis = static_cast<int>(Tensor::num_elements(axis));
+  int temp_index[kMaxNumberOfAxis];
+  int resolved_axis[kMaxNumberOfReducedAxis];
 
-    temp_index->resize(Shape(input_num_dims));
-    resolved_axes->resize(Shape(num_axes));
-    temp_sum->resize(output()->shape());
-  }
-  else
-  {
-    auto temp_index = getOutputTensors()[1];
-    auto resolved_axes = getOutputTensors()[2];
-    auto temp_sum = getOutputTensors()[3];
-
-    temp_index->set_allocatable(false);
-    resolved_axes->set_allocatable(false);
-    temp_sum->set_allocatable(false);
-  }
-}
-
-void Mean::execute() const
-{
-  switch (input()->element_type())
+  switch (Tensor::element_type(kernel.input1()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalFloat();
-      break;
-    case DataType::U8:
-      evalQuantized();
-      break;
-    case DataType::S16:
-      evalQuantizedS16();
-      break;
-    default:
-      assert(false && "Unsupported type.");
-  }
-}
-
-void Mean::evalFloat() const
-{
-  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();
-
-  tflite::MeanParams params{};
-  resolveAxes(axes_data, num_axes, &params);
-
-  auto temp_index = getOutputTensors()[1];
-  auto resolved_axes = getOutputTensors()[2];
-  auto temp_sum = getOutputTensors()[3];
-
-  // Defer to specialized implementation for 4D Mean across axes 1 & 2.
-  if (_params.keep_dims && input_num_dims == 4 && params.axis_count == 2 &&
-      ((params.axis[0] == 1 && params.axis[1] == 2) ||
-       (params.axis[0] == 2 && params.axis[1] == 1)))
-  {
-    tflite::reference_ops::Mean(params, getTensorShape(input()), getTensorData<float>(input()),
-                                getTensorShape(output()), getTensorData<float>(output()));
-  }
-  else
-  {
-    tflite::reference_ops::Mean(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),
-                                getTensorData<float>(temp_sum));
-  }
-}
-
-void Mean::evalQuantized() const
-{
-  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();
-
-  tflite::MeanParams params{};
-  resolveAxes(axes_data, num_axes, &params);
-
-  auto temp_index = getOutputTensors()[1];
-  auto resolved_axes = getOutputTensors()[2];
-  auto temp_sum = getOutputTensors()[3];
-
-  // Defer to specialized implementation for 4D Mean across axes 1 & 2.
-  if (_params.keep_dims && input_num_dims == 4 && params.axis_count == 2 &&
-      ((params.axis[0] == 1 && params.axis[1] == 2) ||
-       (params.axis[0] == 2 && params.axis[1] == 1)))
-  {
-    tflite::reference_ops::Mean(params, getTensorShape(input()), getTensorData<uint8_t>(input()),
-                                input()->zero_point(), input()->scale(), getTensorShape(output()),
-                                getTensorData<uint8_t>(output()), output()->zero_point(),
-                                output()->scale());
-  }
-  else if (input()->zero_point() == output()->zero_point() && input()->scale() == output()->scale())
-  {
-    tflite::reference_ops::Mean(getTensorData<uint8_t>(input()), getTensorShape(input()).DimsData(),
-                                input()->shape().num_dims(), getTensorData<uint8_t>(output()),
-                                getTensorShape(output()).DimsData(), output()->shape().num_dims(),
-                                axes_data, num_axes, _params.keep_dims,
-                                getTensorData<int>(temp_index), getTensorData<int>(resolved_axes),
-                                getTensorData<int>(temp_sum));
-  }
-  else
-  {
-    tflite::reference_ops::QuantizedMeanOrSum<>(
-      getTensorData<uint8_t>(input()), input()->zero_point(), input()->scale(),
-      getTensorShape(input()).DimsData(), input()->shape().num_dims(),
-      getTensorData<uint8_t>(output()), output()->zero_point(), output()->scale(),
-      getTensorShape(output()).DimsData(), output()->shape().num_dims(), axes_data, num_axes,
-      _params.keep_dims, getTensorData<int>(temp_index), getTensorData<int>(resolved_axes),
-      getTensorData<int>(temp_sum),
-      /*compute_sum=*/false);
-  }
-}
-
-void Mean::evalQuantizedS16() const
-{
-  const auto *input_data = getTensorData<int16_t>(input());
-  auto *output_data = getTensorData<int16_t>(output());
-
-  const Shape &input_shape = input()->shape();
-  const Shape &output_shape = output()->shape();
-
-  const auto *axes_data = getTensorData<int32_t>(axes());
-  const int num_axes = axes()->shape().num_elements();
-
-  constexpr int32_t output_min = -std::numeric_limits<int16_t>::max();
-  constexpr int32_t output_max = std::numeric_limits<int16_t>::max();
-
-  // Defer to specialized implementation for 4D Mean across axes 1 & 2.
-  if (_params.keep_dims && input_shape.num_dims() == 4 && num_axes == 2 &&
-      ((axes_data[0] == 1 && axes_data[1] == 2) || (axes_data[0] == 2 && axes_data[1] == 1)))
-  {
-    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);
-    assert(output_shape.num_dims() == 4);
-    assert(output_shape.dim(0) == batches);
-    assert(output_shape.dim(1) == 1);
-    assert(output_shape.dim(2) == 1);
-    assert(output_shape.dim(3) == depth);
-
-    const double real_multiplier =
-      static_cast<double>(input()->scale()) / static_cast<double>(output()->scale());
-
-    int32_t output_multiplier{};
-    int output_shift{};
-    quantizeMultiplier(real_multiplier, &output_multiplier, &output_shift);
-
-    const int32_t num_elements_in_axes = input_height * input_width;
-
-    for (int32_t batch = 0; batch < batches; ++batch)
     {
-      for (int32_t c = 0; c < depth; ++c)
+      luci_interpreter_pal::MeanParams op_params;
+      ResolveAxis(kernels::getTensorData<int>(tiso_data.input2_data), num_axis, &op_params);
+
+      // Special case mean implementation exists for 4D mean across axes 1
+      // and 2.
+      bool special_case_4d_axes_1_and_2 = Tensor::num_dims(input) == 4 &&
+                                          op_params.axis_count == 2 &&
+                                          ((op_params.axis[0] == 1 && op_params.axis[1] == 2) ||
+                                           (op_params.axis[0] == 2 && op_params.axis[1] == 1));
+
+      // Defer to specialized implementation for 4D Mean across axes 1 & 2.
+      if (options->keep_dims() && special_case_4d_axes_1_and_2)
       {
-        int32_t acc = 0;
-        for (int32_t in_y = 0; in_y < input_height; ++in_y)
-        {
-          for (int32_t in_x = 0; in_x < input_width; ++in_x)
-          {
-            acc += input_data[calcOffset(input_shape, batch, in_y, in_x, c)];
-          }
-        }
-        int32_t scaled_acc =
-          tflite::MultiplyByQuantizedMultiplier(acc, output_multiplier, output_shift);
-        // Divide by the number of elements rounding to the nearest integer.
-        scaled_acc = scaled_acc > 0
-                       ? (scaled_acc + num_elements_in_axes / 2) / num_elements_in_axes
-                       : (scaled_acc - num_elements_in_axes / 2) / num_elements_in_axes;
-
-        scaled_acc = std::max(scaled_acc, output_min);
-        scaled_acc = std::min(scaled_acc, output_max);
-
-        output_data[calcOffset(output_shape, batch, 0, 0, c)] = scaled_acc;
+        luci_interpreter_pal::Mean(op_params, kernels::getTensorShape(input),
+                                   kernels::getTensorData<float>(tiso_data.input1_data),
+                                   kernels::getTensorShape(output),
+                                   kernels::getTensorData<float>(tiso_data.output_data));
+      }
+      else
+      {
+        luci_interpreter_pal::Mean(
+          kernels::getTensorData<float>(tiso_data.input1_data),
+          reinterpret_cast<const int *>(wrap(input->shape()).data()), Tensor::num_dims(input),
+          kernels::getTensorData<float>(tiso_data.output_data),
+          reinterpret_cast<const int *>(wrap(output->shape()).data()), Tensor::num_dims(output),
+          kernels::getTensorData<int>(tiso_data.input2_data), num_axis, options->keep_dims(),
+          temp_index, resolved_axis, kernels::getTensorData<float>(tiso_data.output_data));
       }
     }
-  }
-  else
-  {
-    assert(false && "Unsupported configuration.");
+    break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
   }
 }
 
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Mean.h b/onert-micro/luci-interpreter/src/kernels/Mean.h
deleted file mode 100644 (file)
index ed07ae5..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_MEAN_H
-#define LUCI_INTERPRETER_KERNELS_MEAN_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-#include <memory>
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Mean : public KernelWithParams<ReducerParams>
-{
-public:
-  Mean(const Tensor *input, const Tensor *axes, Tensor *output, Tensor *temp_index,
-       Tensor *resolved_axes, Tensor *temp_sum, 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:
-  void evalFloat() const;
-  void evalQuantized() const;
-  void evalQuantizedS16() const;
-
-private:
-  bool _need_temporaries = false;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_MEAN_H
index d2c0093..bf03d4a 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Mean.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/mean/FloatMeanKernel.h"
+#include "luci_interpreter/test_models/mean/NegMeanKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -30,211 +30,58 @@ using namespace testing;
 
 class MeanTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(MeanTest, 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 temp_sum(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  ReducerParams params{};
-  params.keep_dims = true;
-
-  Mean kernel(&input_tensor, &axis_tensor, &output_tensor, &temp_index, &resolved_axes, &temp_sum,
-              params);
-  kernel.configure();
-  _memory_manager->allocate_memory(temp_index);
-  _memory_manager->allocate_memory(resolved_axes);
-  _memory_manager->allocate_memory(temp_sum);
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{10.5, 12.5, 14.5};
-  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(MeanTest, FloatKeepDims4DMean)
-{
-  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, 2};
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>({2, 2, 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 temp_sum(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  ReducerParams params{};
-  params.keep_dims = true;
-
-  Mean kernel(&input_tensor, &axis_tensor, &output_tensor, &temp_index, &resolved_axes, &temp_sum,
-              params);
-  kernel.configure();
-  _memory_manager->allocate_memory(temp_index);
-  _memory_manager->allocate_memory(resolved_axes);
-  _memory_manager->allocate_memory(temp_sum);
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{6, 7, 18, 19};
-  std::initializer_list<int32_t> ref_output_shape{2, 1, 1, 2};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(MeanTest, FloatNotKeepDims)
+template <typename T> std::vector<T> checkMeanKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  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, -3, -3};
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>({4, 3, 2}, input_data, _memory_manager.get());
-  Tensor axis_tensor = makeInputTensor<DataType::S32>({4}, axis_data, _memory_manager.get());
-  Tensor temp_index(DataType::S32, Shape({}), {}, "");
-  Tensor resolved_axes(DataType::S32, Shape({}), {}, "");
-  Tensor temp_sum(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  ReducerParams params{};
-  params.keep_dims = false;
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  Mean kernel(&input_tensor, &axis_tensor, &output_tensor, &temp_index, &resolved_axes, &temp_sum,
-              params);
-  kernel.configure();
-  _memory_manager->allocate_memory(temp_index);
-  _memory_manager->allocate_memory(resolved_axes);
-  _memory_manager->allocate_memory(temp_sum);
-  _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);
 
-  std::vector<float> ref_output_data{12, 13};
-  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(MeanTest, Uint8KeepDims)
-{
-  float kQuantizedTolerance = getTolerance(-1.0, 1.0, 255);
-  std::vector<float> input_data = {0.4, 0.2, 0.3, 0.4, 0.5, 0.6};
-  std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-1.0f, 1.0f);
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-  std::vector<int32_t> axis_data{1};
-  Tensor input_tensor = makeInputTensor<DataType::U8>({3, 2}, quant_param.first, quant_param.second,
-                                                      input_data, _memory_manager.get());
-  Tensor axis_tensor = makeInputTensor<DataType::S32>({1}, axis_data, _memory_manager.get());
-  Tensor temp_index(DataType::S32, Shape({}), {}, "");
-  Tensor resolved_axes(DataType::S32, Shape({}), {}, "");
-  Tensor temp_sum(DataType::U8, Shape({}), {}, "");
-  Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
+  // 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);
+  }
 
-  ReducerParams params{};
-  params.keep_dims = true;
+  runtime_module.execute();
 
-  Mean kernel(&input_tensor, &axis_tensor, &output_tensor, &temp_index, &resolved_axes, &temp_sum,
-              params);
-  kernel.configure();
-  _memory_manager->allocate_memory(temp_index);
-  _memory_manager->allocate_memory(resolved_axes);
-  _memory_manager->allocate_memory(temp_sum);
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  std::vector<float> ref_output_data{0.3, 0.35, 0.55};
-  std::initializer_list<int32_t> ref_output_shape{3, 1};
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(ref_output_data, kQuantizedTolerance));
-  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(MeanTest, Uint8NotKeepDims)
+TEST_F(MeanTest, Float_P)
 {
-  float kQuantizedTolerance = getTolerance(-1.0, 1.0, 255);
-  std::vector<float> input_data = {0.4, 0.2, 0.3, 0.4, 0.5, 0.6};
-  std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-1.0f, 1.0f);
-
-  std::vector<int32_t> axis_data{1};
-  Tensor input_tensor = makeInputTensor<DataType::U8>(
-    {1, 3, 2}, quant_param.first, quant_param.second, input_data, _memory_manager.get());
-  Tensor axis_tensor = makeInputTensor<DataType::S32>({1}, axis_data, _memory_manager.get());
-  Tensor temp_index(DataType::S32, Shape({}), {}, "");
-  Tensor resolved_axes(DataType::S32, Shape({}), {}, "");
-  Tensor temp_sum(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
-
-  ReducerParams params{};
-  params.keep_dims = false;
-
-  Mean kernel(&input_tensor, &axis_tensor, &output_tensor, &temp_index, &resolved_axes, &temp_sum,
-              params);
-  kernel.configure();
-  _memory_manager->allocate_memory(temp_index);
-  _memory_manager->allocate_memory(resolved_axes);
-  _memory_manager->allocate_memory(temp_sum);
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{0.4, 0.4};
-  std::initializer_list<int32_t> ref_output_shape{1, 2};
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(ref_output_data, kQuantizedTolerance));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
+  test_kernel::TestDataFloatMean test_data_kernel;
+  std::vector<float> output_data_vector = checkMeanKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST_F(MeanTest, SInt16KeepDims4D)
+TEST_F(MeanTest, Input_output_type_mismatch_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> axes_data{1, 2};
-  std::vector<float> ref_output_data{6, 7, 18, 19};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({2, 2, 3, 2}, 0.25, 0, input_data, _memory_manager.get());
-  Tensor axes_tensor = makeInputTensor<DataType::S32>({2}, axes_data, _memory_manager.get());
-  Tensor temp_index(DataType::S32, Shape({}), {}, "");
-  Tensor resolved_axes(DataType::S32, Shape({}), {}, "");
-  Tensor temp_sum(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor output_tensor = makeOutputTensor(DataType::S16, 0.2, 0);
-
-  ReducerParams params{};
-  params.keep_dims = true;
-
-  Mean kernel(&input_tensor, &axes_tensor, &output_tensor, &temp_index, &resolved_axes, &temp_sum,
-              params);
-  kernel.configure();
-  _memory_manager->allocate_memory(temp_index);
-  _memory_manager->allocate_memory(resolved_axes);
-  _memory_manager->allocate_memory(temp_sum);
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 1, 1, 2}));
-  EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
+  test_kernel::NegTestDataInputOutputTypeMismatchMeanKernel 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
index f74e6c0..9ed4841 100644 (file)
@@ -1,6 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2018 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.
  * limitations under the License.
  */
 
-#include "kernels/Minimum.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
 
 #include "kernels/BinaryOpCommon.h"
 
+#include "PALMinimum.h"
+
 namespace luci_interpreter
 {
-namespace kernels
-{
 
-Minimum::Minimum(const Tensor *input1, const Tensor *input2, Tensor *output)
-  : Kernel({input1, input2}, {output})
+void configure_kernel_CircleMinimum(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-}
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
 
-void Minimum::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()));
+  kernels::CheckBinaryOpDataTypesEqual(kernel);
 }
 
-void Minimum::execute() const
+void execute_kernel_CircleMinimum(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  switch (input1()->element_type())
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+  luci_interpreter::RuntimeShape input_shape1 =
+    kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph);
+  luci_interpreter::RuntimeShape input_shape2 =
+    kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph);
+  luci_interpreter::RuntimeShape output_shape =
+    kernels::getTensorRuntimeShape(kernel.output(), runtime_graph);
+
+  const uint8_t *input_data1 = runtime_graph->getDataByTensor(kernel.input1());
+  const uint8_t *input_data2 = runtime_graph->getDataByTensor(kernel.input2());
+  uint8_t *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+  assert(input_data1 != nullptr);
+  assert(input_data2 != nullptr);
+  assert(output_data != nullptr);
+
+  switch (Tensor::element_type(kernel.input1()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalMinimum<float>();
-      break;
-    case DataType::U8:
-      evalMinimum<uint8_t>();
-      break;
+    {
+      // check that input and output dimensions are equal
+      if (kernels::areShapesEqual(input_shape1, input_shape2))
+      {
+        const int flat_size = input_shape1.flatSize();
+        luci_interpreter_pal::Minimum(flat_size, kernels::getTensorData<float>(input_data1),
+                                      kernels::getTensorData<float>(input_data2),
+                                      kernels::getTensorData<float>(output_data));
+      }
+      else
+      {
+        luci_interpreter_pal::BroadcastMinimum4DSlow<float>(
+          input_shape1, kernels::getTensorData<float>(input_data1), input_shape2,
+          kernels::getTensorData<float>(input_data2), output_shape,
+          kernels::getTensorData<float>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
     default:
       assert(false && "Unsupported type.");
   }
 }
 
-template <typename T> inline void Minimum::evalMinimum() const
-{
-  BinaryOpBroadcastSlow(getTensorShape(input1()), getTensorData<T>(input1()),
-                        getTensorShape(input2()), getTensorData<T>(input2()),
-                        getTensorShape(output()), getTensorData<T>(output()),
-                        [](T x, T y) { return std::min(x, y); });
-}
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Minimum.h b/onert-micro/luci-interpreter/src/kernels/Minimum.h
deleted file mode 100644 (file)
index 5ff4035..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_MINIMUM_H
-#define LUCI_INTERPRETER_KERNELS_MINIMUM_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Minimum : public Kernel
-{
-public:
-  Minimum(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:
-  template <typename T> inline void evalMinimum() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_MINIMUM_H
index 9a14364..5f6d304 100644 (file)
@@ -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");
  * limitations under the License.
  */
 
-#include "kernels/Minimum.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/minimum/FloatMinimumKernel.h"
+#include "luci_interpreter/test_models/minimum/NegMinimumKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -30,53 +30,158 @@ using namespace testing;
 
 class MinimumTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(MinimumTest, Float)
+template <typename T>
+std::vector<T> checkMinimumKernel(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() == 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(MinimumTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatMinimum test_data_kernel(is_with_broadcast);
+    std::vector<float> output_data_vector = checkMinimumKernel(&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::TestDataFloatMinimum test_data_kernel(is_with_broadcast);
+    std::vector<float> output_data_vector = checkMinimumKernel(&test_data_kernel);
+    EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                      test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(MinimumTest, Wrong_Input1_Type_NEG)
 {
-  Shape input_shape{3, 1, 2};
-  std::vector<float> input_data1{1.0, 0.0, -1.0, 11.0, -2.0, -1.44};
-  std::vector<float> input_data2{-1.0, 0.0, 1.0, 12.0, -3.0, -1.43};
-  Tensor input_tensor1 =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data1, _memory_manager.get());
-  Tensor input_tensor2 =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data2, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Minimum kernel(&input_tensor1, &input_tensor2, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{-1.0, 0.0, -1.0, 11.0, -3.0, -1.44};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+  test_kernel::NegTestDataInput1WrongTypeMinimum 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(MinimumTest, Uint8)
+TEST_F(MinimumTest, Wrong_Input2_Type_NEG)
+{
+  test_kernel::NegTestDataInput2WrongTypeMinimum 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
+
+#include "PALMinimum.h"
+
+#include <array>
+#include <numeric>
+
+namespace luci_interpreter
+{
+namespace
+{
+
+class PALMinimumTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(PALMinimumTest, Float_P)
 {
-  Shape input_shape{3, 1, 2};
-  std::vector<uint8_t> input_data1{1, 0, 2, 11, 2, 23};
-  std::vector<uint8_t> input_data2{0, 0, 1, 12, 255, 1};
-  Tensor input_tensor1 =
-    makeInputTensor<DataType::U8>(input_shape, input_data1, _memory_manager.get());
-  Tensor input_tensor2 =
-    makeInputTensor<DataType::U8>(input_shape, input_data2, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8);
-
-  Minimum kernel(&input_tensor1, &input_tensor2, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<int32_t> ref_output_shape{2, 4};
-  EXPECT_THAT(extractTensorData<uint8_t>(output_tensor),
-              ::testing::ElementsAreArray({0, 0, 1, 11, 2, 1}));
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatMinimum test_data_kernel(is_with_broadcast);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const auto num_elements = input1.size();
+    EXPECT_EQ(num_elements, input2.size());
+
+    std::vector<float> output = std::vector<float>(num_elements);
+    luci_interpreter_pal::Minimum(num_elements, input1.data(), input2.data(),
+                                  const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_kernel::TestDataFloatMinimum test_data_kernel(is_with_broadcast);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const int32_t shape[2] = {2, 5};
+    const int32_t shape_broadcast[2] = {2, 1};
+
+    assert(input1.size() ==
+           std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    assert(input2.size() == std::accumulate(std::begin(shape_broadcast), std::end(shape_broadcast),
+                                            1, std::multiplies<float>()));
+
+    std::vector<float> output = std::vector<float>(
+      std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    luci_interpreter_pal::BroadcastMinimum4DSlow(
+      RuntimeShape{2, shape}, input1.data(), RuntimeShape{2, shape_broadcast}, input2.data(),
+      RuntimeShape{2, shape}, const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
 }
 
 } // namespace
-} // namespace kernels
 } // namespace luci_interpreter
index d9e60b0..fa12c90 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/MirrorPad.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "TISOKernel.h"
 
-#include <limits>
+#include "PALMirrorPad.h"
 
 namespace luci_interpreter
 {
-namespace kernels
+namespace
 {
+constexpr int maxInputSize = 5;
+}
 
-MirrorPad::MirrorPad(const Tensor *input, const Tensor *paddings, Tensor *output,
-                     const MirrorPadParams &params)
-  : KernelWithParams<MirrorPadParams>({input, paddings}, {output}, params)
+void configure_kernel_CircleMirrorPad(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.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input2()) == 2);
+  LUCI_INTERPRETER_CHECK(Tensor::dim(kernel.input2(), 0) == Tensor::num_dims(kernel.input1()));
 }
 
-void MirrorPad::configure()
+void execute_kernel_CircleMirrorPad(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)
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+  kernels::TISOData data = kernel.readData();
+
+  const auto *options = cur_op->builtin_options_as_MirrorPadOptions();
+
+  const auto offset = options->mode() != circle::MirrorPadMode_REFLECT ? 0 : 1;
+  const auto input_dims = Tensor::num_dims(kernel.input1());
+  const auto output_size = Tensor::num_elements(kernel.output());
+
+  int output_dims_num_elements[5];
+  int input_dims_num_elements[5];
+
+  for (int i = 0; i < input_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;
+    output_dims_num_elements[i] = 1;
+    input_dims_num_elements[i] = 1;
   }
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(output_shape);
-}
 
-template <typename T>
-inline void MirrorPadImpl(const Tensor &input, const Tensor &paddings, MirrorPadMode mode,
-                          Tensor &output);
+  for (int i = input_dims - 2; i >= 0; i--)
+  {
+    output_dims_num_elements[i] =
+      output_dims_num_elements[i + 1] * Tensor::dim(kernel.output(), i + 1);
 
-void MirrorPad::execute() const
-{
-  switch (input()->element_type())
+    input_dims_num_elements[i] =
+      input_dims_num_elements[i + 1] * Tensor::dim(kernel.input1(), i + 1);
+  }
+
+  switch (Tensor::element_type(kernel.input1()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
     {
-      MirrorPadImpl<float>(*input(), *paddings(), params().mode, *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());
+      luci_interpreter_pal::MirrorPad(
+        Tensor::element_type(kernel.input2()), data.input2_data,
+        wrap(kernel.input1()->shape()).data(), output_dims_num_elements, input_dims_num_elements,
+        kernels::getTensorData<float>(data.input1_data),
+        kernels::getTensorData<float>(data.output_data), offset, input_dims, output_size);
 
-      MirrorPadImpl<uint8_t>(*input(), *paddings(), params().mode, *output());
       break;
     }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
-  }
-}
-
-template <typename T>
-inline void MirrorPadImpl(const Tensor &input, const Tensor &paddings, MirrorPadMode mode,
-                          Tensor &output)
-{
-  auto const input_dims = input.shape().num_dims();
-  auto const input_data = input.data<T>();
-  auto const paddings_data = paddings.data<int32_t>();
-  auto const output_data = output.data<T>();
-
-  auto const input_b = input_dims > 3 ? input.shape().dim(input_dims - 4) : 1;
-  auto const input_h = input_dims > 2 ? input.shape().dim(input_dims - 3) : 1;
-  auto const input_w = input_dims > 1 ? input.shape().dim(input_dims - 2) : 1;
-  auto const input_d = input.shape().dim(input_dims - 1);
-
-  auto const input_h_offset = input_d * input_w;
-  auto const input_b_offset = input_h_offset * input_h;
-
-  auto const output_b = input_dims > 3 ? output.shape().dim(input_dims - 4) : 1;
-  auto const output_h = input_dims > 2 ? output.shape().dim(input_dims - 3) : 1;
-  auto const output_w = input_dims > 1 ? output.shape().dim(input_dims - 2) : 1;
-  auto const output_d = output.shape().dim(input_dims - 1);
-
-  auto const left_b_pad = paddings_data[2 * (input_dims - 4)];
-  auto const left_h_pad = paddings_data[2 * (input_dims - 3)];
-  auto const left_w_pad = paddings_data[2 * (input_dims - 2)];
-  auto const left_d_pad = paddings_data[2 * (input_dims - 1)];
-
-  auto const right_b_pad = paddings_data[2 * (input_dims - 4) + 1];
-  auto const right_h_pad = paddings_data[2 * (input_dims - 3) + 1];
-  auto const right_w_pad = paddings_data[2 * (input_dims - 2) + 1];
-  auto const right_d_pad = paddings_data[2 * (input_dims - 1) + 1];
-
-  const auto positive_mod = [](auto a, auto b) { return (a % b + b) % b; };
-  const auto offset_index = [input_d, input_h_offset, input_b_offset](auto d, auto w, auto h,
-                                                                      auto b) {
-    return d + w * input_d + h * input_h_offset + b * input_b_offset;
-  };
-
-  const auto symmetric_dim = [&positive_mod](auto i, auto left_pad, auto input) {
-    bool reflected = (((i < left_pad ? i + 1 - input : i) - left_pad) / input & 1) == 1;
-    return positive_mod(reflected ? input + left_pad - i - 1 : i - left_pad, input);
-  };
-
-  const T *in_ptr = input_data;
-  T *out_ptr = output_data;
-
-  for (int32_t b = 0; b < output_b; ++b)
-  {
-    for (int32_t h = 0; h < output_h; ++h)
-    {
-      for (int32_t w = 0; w < output_w; ++w)
-      {
-        for (int32_t d = 0; d < output_d; ++d)
-        {
-          if (b < left_b_pad || b >= output_b - right_b_pad || //
-              h < left_h_pad || h >= output_h - right_h_pad || //
-              w < left_w_pad || w >= output_w - right_w_pad || //
-              d < left_d_pad || d >= output_d - right_d_pad)
-          {
-            if (mode == MirrorPadMode::REFLECT)
-            {
-              *out_ptr++ = input_data[offset_index(
-                positive_mod(d - left_d_pad, input_d), positive_mod(w - left_w_pad, input_w),
-                positive_mod(h - left_h_pad, input_h), positive_mod(b - left_b_pad, input_b))];
-            }
-            else
-            {
-              *out_ptr++ = input_data[offset_index(
-                symmetric_dim(d, left_d_pad, input_d), symmetric_dim(w, left_w_pad, input_w),
-                symmetric_dim(h, left_h_pad, input_h), symmetric_dim(b, left_b_pad, input_b))];
-            }
-          }
-          else
-          {
-            *out_ptr++ = *in_ptr++;
-          }
-        }
-      }
-    }
+      assert(false && "Unsupported type");
   }
 }
 
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/MirrorPad.h b/onert-micro/luci-interpreter/src/kernels/MirrorPad.h
deleted file mode 100644 (file)
index d3e6e85..0000000
+++ /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.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_MIRROR_PAD_H
-#define LUCI_INTERPRETER_KERNELS_MIRROR_PAD_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class MirrorPad : public KernelWithParams<MirrorPadParams>
-{
-public:
-  MirrorPad(const Tensor *input, const Tensor *paddings, Tensor *output,
-            const MirrorPadParams &params);
-
-  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_MIRROR_PAD_H
index 740d8cb..ed207e5 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/MirrorPad.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/mirror_pad/FloatMirrorPadKernel.h"
+#include "luci_interpreter/test_models/mirror_pad/NegMirrorPadKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -29,197 +29,59 @@ using namespace testing;
 
 class MirrorPadTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  void Execute(const Tensor &input, const Tensor &padding, Tensor &output, MirrorPadMode mode)
-  {
-    MirrorPadParams params{};
-    params.mode = mode;
-
-    MirrorPad kernel(&input, &padding, &output, params);
-    kernel.configure();
-    _memory_manager->allocate_memory(output);
-    kernel.execute();
-  }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(MirrorPadTest, FloatReflect)
-{
-  Shape input_shape = {1, 2, 2, 1};
-  Shape padding_shape = {4, 2};
-
-  std::vector<float> input_data{1.0f, 2.0f,  //
-                                3.0f, 4.0f}; //
-  std::vector<int> padding_data{0, 0, 2, 1, 1, 2, 0, 0};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-  Tensor padding_tensor =
-    makeInputTensor<DataType::S32>(padding_shape, padding_data, _memory_manager.get());
-
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Execute(input_tensor, padding_tensor, output_tensor, MirrorPadMode::REFLECT);
-
-  std::vector<float> ref_output_data{2.0f, 1.0f, 2.0f, 1.0f, 2.0f,  //
-                                     4.0f, 3.0f, 4.0f, 3.0f, 4.0f,  //
-                                     2.0f, 1.0f, 2.0f, 1.0f, 2.0f,  //
-                                     4.0f, 3.0f, 4.0f, 3.0f, 4.0f,  //
-                                     2.0f, 1.0f, 2.0f, 1.0f, 2.0f}; //
-  std::initializer_list<int32_t> ref_output_shape{1, 5, 5, 1};
-
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(MirrorPadTest, FloatSymmetric)
+template <typename T>
+std::vector<T> checkMirrorPadKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  Shape input_shape = {1, 2, 2, 1};
-  Shape padding_shape = {4, 2};
-
-  std::vector<float> input_data{1.0f, 2.0f,  //
-                                3.0f, 4.0f}; //
-  std::vector<int> padding_data{0, 0, 2, 1, 1, 2, 0, 0};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-  Tensor padding_tensor =
-    makeInputTensor<DataType::S32>(padding_shape, padding_data, _memory_manager.get());
-
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Execute(input_tensor, padding_tensor, output_tensor, MirrorPadMode::SYMMETRIC);
-
-  std::vector<float> ref_output_data{3.0, 3.0, 4.0, 4.0, 3.0,  //
-                                     1.0, 1.0, 2.0, 2.0, 1.0,  //
-                                     1.0, 1.0, 2.0, 2.0, 1.0,  //
-                                     3.0, 3.0, 4.0, 4.0, 3.0,  //
-                                     3.0, 3.0, 4.0, 4.0, 3.0}; //
-  std::initializer_list<int32_t> ref_output_shape{1, 5, 5, 1};
-
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(MirrorPadTest, FloatSymmetric2Dim)
-{
-  Shape input_shape = {3, 1};
-  Shape padding_shape = {2, 2};
-
-  std::vector<float> input_data{1.0f, 2.0f, 3.0f};
-  std::vector<int> padding_data{1, 2, 0, 0};
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-  Tensor padding_tensor =
-    makeInputTensor<DataType::S32>(padding_shape, padding_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);
 
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-  Execute(input_tensor, padding_tensor, output_tensor, MirrorPadMode::SYMMETRIC);
-
-  std::vector<float> ref_output_data{1.0, 1.0, 2.0, 3.0, 3.0, 2.0};
-  std::initializer_list<int32_t> ref_output_shape{6, 1};
-
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(MirrorPadTest, Uint8Reflect)
-{
-  Shape input_shape = {1, 2, 3, 1};
-  Shape padding_shape = {4, 2};
-
-  float quant_tolerance = getTolerance(0.0f, 6.0f, 255);
-  std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(0.0f, 6.0f);
-
-  std::vector<float> input_data{1.0f, 2.0f, 3.0f,  //
-                                4.0f, 5.0f, 6.0f}; //
-  std::vector<int> padding_data{0, 0, 2, 1, 1, 3, 0, 0};
-
-  Tensor input_tensor = makeInputTensor<DataType::U8>(
-    input_shape, quant_param.first, quant_param.second, input_data, _memory_manager.get());
-
-  Tensor padding_tensor =
-    makeInputTensor<DataType::S32>(padding_shape, padding_data, _memory_manager.get());
-
-  Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
-
-  Execute(input_tensor, padding_tensor, output_tensor, MirrorPadMode::REFLECT);
-
-  std::vector<float> ref_output_data{
-    3.0f, 1.0f, 2.0f, 3.0f, 1.0f, 2.0f, 3.0f, //
-    6.0f, 4.0f, 5.0f, 6.0f, 4.0f, 5.0f, 6.0f, //
-    3.0f, 1.0f, 2.0f, 3.0f, 1.0f, 2.0f, 3.0f, //
-    6.0f, 4.0f, 5.0f, 6.0f, 4.0f, 5.0f, 6.0f, //
-    3.0f, 1.0f, 2.0f, 3.0f, 1.0f, 2.0f, 3.0f, //
-  };
-  std::initializer_list<int32_t> ref_output_shape{1, 5, 7, 1};
-
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(ref_output_data, quant_tolerance));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
-}
-
-TEST_F(MirrorPadTest, Uint8Symmetric)
-{
-  Shape input_shape = {1, 2, 3, 1};
-  Shape padding_shape = {4, 2};
-
-  float quant_tolerance = getTolerance(0.0f, 6.0f, 255);
-  std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(0.0f, 6.0f);
-
-  std::vector<float> input_data{1.0f, 2.0f, 3.0f,  //
-                                4.0f, 5.0f, 6.0f}; //
-  std::vector<int> padding_data{0, 0, 2, 1, 1, 3, 0, 0};
-
-  Tensor input_tensor = makeInputTensor<DataType::U8>(
-    input_shape, quant_param.first, quant_param.second, input_data, _memory_manager.get());
-
-  Tensor padding_tensor =
-    makeInputTensor<DataType::S32>(padding_shape, padding_data, _memory_manager.get());
-
-  Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
+  // 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);
+  }
 
-  Execute(input_tensor, padding_tensor, output_tensor, MirrorPadMode::SYMMETRIC);
+  runtime_module.execute();
 
-  std::vector<float> ref_output_data{
-    4.0f, 4.0f, 5.0f, 6.0f, 6.0f, 5.0f, 4.0f, //
-    1.0f, 1.0f, 2.0f, 3.0f, 3.0f, 2.0f, 1.0f, //
-    1.0f, 1.0f, 2.0f, 3.0f, 3.0f, 2.0f, 1.0f, //
-    4.0f, 4.0f, 5.0f, 6.0f, 6.0f, 5.0f, 4.0f, //
-    4.0f, 4.0f, 5.0f, 6.0f, 6.0f, 5.0f, 4.0f, //
-  };
-  std::initializer_list<int32_t> ref_output_shape{1, 5, 7, 1};
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(ref_output_data, quant_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(MirrorPadTest, UnsupportedDim_NEG)
+TEST_F(MirrorPadTest, Float_P)
 {
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>({1, 1, 1, 1, 1}, {1.0f}, _memory_manager.get());
-  Tensor padding_tensor =
-    makeInputTensor<DataType::S32>({5, 2}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  EXPECT_ANY_THROW(Execute(input_tensor, padding_tensor, output_tensor, MirrorPadMode::REFLECT));
+  test_kernel::TestDataFloatMirrorPad test_data_kernel;
+  std::vector<float> output_data_vector = checkMirrorPadKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST_F(MirrorPadTest, InvalidInputType_NEG)
+TEST_F(MirrorPadTest, Input_output_type_mismatch_NEG)
 {
-  Tensor input_tensor = makeInputTensor<DataType::S64>({1}, {1}, _memory_manager.get());
-  Tensor padding_tensor = makeInputTensor<DataType::S32>({1, 2}, {0, 0}, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S64);
-
-  EXPECT_ANY_THROW(Execute(input_tensor, padding_tensor, output_tensor, MirrorPadMode::REFLECT));
+  test_kernel::NegTestDataInputOutputTypeMismatchMirrorPadKernel 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
index 75f9b90..5425bae 100644 (file)
 namespace luci_interpreter
 {
 
+namespace
+{
+
+#ifndef DIS_QUANT
+void evalQuantized(const circle::Tensor *input1, const circle::Tensor *input2,
+                   const circle::Tensor *output, const circle::MulOptions *options,
+                   BaseRuntimeGraph *runtime_graph, DataType type)
+{
+  assert(type == DataType::S16 or type == DataType::S8 && "Wrong Type");
+
+  luci_interpreter_pal::ArithmeticParams params{};
+  luci_interpreter::RuntimeShape input_shape1 =
+    kernels::getTensorRuntimeShape(input1, runtime_graph);
+  luci_interpreter::RuntimeShape input_shape2 =
+    kernels::getTensorRuntimeShape(input2, runtime_graph);
+
+  const bool need_broadcast =
+    luci_interpreter_pal::ProcessBroadcastShapes(input_shape1, input_shape2, &params);
+
+  assert(need_broadcast == false && "Broadcast for INT8 and INT16 not supported now");
+
+  params.input1_offset = -Tensor::zero_point(input1);
+  params.input2_offset = -Tensor::zero_point(input2);
+  params.output_offset = Tensor::zero_point(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));
+
+  double real_multiplier = input1_scale * input2_scale / output_scale;
+
+  kernels::quantizeMultiplier(real_multiplier, &params.output_multiplier, &params.output_shift);
+
+  kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
+                                             output, &params.quantized_activation_min,
+                                             &params.quantized_activation_max);
+  if (type == DataType::S8)
+  {
+    luci_interpreter_pal::Mul(
+      params, input_shape1.flatSize(),
+      kernels::getTensorData<int8_t>(runtime_graph->getDataByTensor(input1)),
+      kernels::getTensorData<int8_t>(runtime_graph->getDataByTensor(input2)),
+      kernels::getTensorData<int8_t>(runtime_graph->getDataByTensor(output)));
+  }
+  else
+  {
+    luci_interpreter_pal::Mul(
+      params, input_shape1.flatSize(),
+      kernels::getTensorData<int16_t>(runtime_graph->getDataByTensor(input1)),
+      kernels::getTensorData<int16_t>(runtime_graph->getDataByTensor(input2)),
+      kernels::getTensorData<int16_t>(runtime_graph->getDataByTensor(output)));
+  }
+}
+#endif // DIS_QUANT
+
+} // namespace
+
 void configure_kernel_CircleMul(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
   kernels::TISOKernel kernel(cur_op, runtime_graph);
@@ -56,9 +113,12 @@ void execute_kernel_CircleMul(const circle::Operator *cur_op, BaseRuntimeGraph *
   luci_interpreter::RuntimeShape input_shape2 =
     kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph);
 
-  bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+  luci_interpreter::RuntimeShape output_shape =
+    kernels::getTensorRuntimeShape(kernel.output(), runtime_graph);
 
-  switch (Tensor::element_type(kernel.input1()))
+  bool is_inplace = runtime_graph->is_inplace_op(cur_op);
+  const auto type = Tensor::element_type(kernel.input1());
+  switch (type)
   {
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
@@ -68,13 +128,15 @@ void execute_kernel_CircleMul(const circle::Operator *cur_op, BaseRuntimeGraph *
       if (is_inplace)
       {
         kernels::evalTISOInplaceKernel<float>(tiso_func, broadcast_tiso_func, &kernel, options,
-                                              std::move(input_shape1), std::move(input_shape2));
+                                              std::move(input_shape1), std::move(input_shape2),
+                                              std::move(output_shape));
       }
       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));
+                                       options, std::move(input_shape1), std::move(input_shape2),
+                                       std::move(output_shape));
       }
     }
     break;
@@ -86,13 +148,15 @@ void execute_kernel_CircleMul(const circle::Operator *cur_op, BaseRuntimeGraph *
       if (is_inplace)
       {
         kernels::evalTISOInplaceKernel<int64_t>(tiso_func, broadcast_tiso_func, &kernel, options,
-                                                std::move(input_shape1), std::move(input_shape2));
+                                                std::move(input_shape1), std::move(input_shape2),
+                                                std::move(output_shape));
       }
       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));
+                                         options, std::move(input_shape1), std::move(input_shape2),
+                                         std::move(output_shape));
       }
     }
     break;
@@ -103,51 +167,27 @@ void execute_kernel_CircleMul(const circle::Operator *cur_op, BaseRuntimeGraph *
       if (is_inplace)
       {
         kernels::evalTISOInplaceKernel<int32_t>(tiso_func, broadcast_tiso_func, &kernel, options,
-                                                std::move(input_shape1), std::move(input_shape2));
+                                                std::move(input_shape1), std::move(input_shape2),
+                                                std::move(output_shape));
       }
       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));
+                                         options, std::move(input_shape1), std::move(input_shape2),
+                                         std::move(output_shape));
       }
     }
     break;
-#if 0
 #ifndef DIS_QUANT
-      // TODO: check quantize Mul
-    case DataType::U8:
+    case DataType::S8:
+    case DataType::S16:
     {
-      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);
-      }
+      evalQuantized(kernel.input1(), kernel.input2(), kernel.output(), options, runtime_graph,
+                    type);
     }
     break;
 #endif // DIS_QUANT
-#endif // 0
     default:
       assert(false && "Unsupported type.");
   }
index 391c783..ccd6c05 100644 (file)
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#include "BinaryOpCommon.h"
 #include "kernels/TestUtils.h"
 #include "luci_interpreter/test_models/mul/FloatMulKernel.h"
 #include "luci_interpreter/test_models/mul/IntMulKernel.h"
 
 #include "loader/ModuleLoader.h"
 
+#include "PALMul.h"
+
+#include <array>
+#include <numeric>
+
 namespace luci_interpreter
 {
 namespace
@@ -153,3 +159,70 @@ TEST_F(MulTest, Wrong_Ouput_Type_NEG)
 
 } // namespace
 } // namespace luci_interpreter
+
+namespace luci_interpreter
+{
+namespace
+{
+
+class PALMulTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(PALMulTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatMul test_data_kernel(is_with_broadcast);
+
+    luci_interpreter_pal::ArithmeticParams params{};
+    kernels::fillArithmeticActivationRange<float>(params, kernels::Activation::NONE);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const auto num_elements = input1.size();
+    EXPECT_EQ(num_elements, input2.size());
+
+    std::vector<float> output = std::vector<float>(num_elements);
+    luci_interpreter_pal::Mul<float>(params, num_elements, input1.data(), input2.data(),
+                                     const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_kernel::TestDataFloatMul test_data_kernel(is_with_broadcast);
+
+    luci_interpreter_pal::ArithmeticParams params{};
+    kernels::fillArithmeticActivationRange<float>(params, kernels::Activation::NONE);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const int32_t shape[2] = {2, 5};
+    const int32_t shape_broadcast[2] = {2, 1};
+
+    assert(input1.size() ==
+           std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    assert(input2.size() == std::accumulate(std::begin(shape_broadcast), std::end(shape_broadcast),
+                                            1, std::multiplies<float>()));
+
+    std::vector<float> output = std::vector<float>(
+      std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    luci_interpreter_pal::BroadcastMul4DSlow<float>(
+      params, RuntimeShape{2, shape}, input1.data(), RuntimeShape{2, shape_broadcast},
+      input2.data(), RuntimeShape{2, shape}, const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+} // namespace
+} // namespace luci_interpreter
index 92f646f..482fd8a 100644 (file)
  */
 
 #include "Builders.h"
-#include "kernels/Utils.h"
+#include "ComparisonCommon.h"
 #include "TISOKernel.h"
 
-#include "PALComparisons.h"
-
 namespace luci_interpreter
 {
 
-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));
-
-  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::NotEqualFn);
-}
-
-} // namespace
-
 void configure_kernel_CircleNotEqual(const circle::Operator *cur_op,
                                      BaseRuntimeGraph *runtime_graph)
 {
@@ -71,14 +38,17 @@ void execute_kernel_CircleNotEqual(const circle::Operator *cur_op, BaseRuntimeGr
   switch (Tensor::element_type(kernel.input1()))
   {
     case DataType::S64:
-      evalGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int64_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::NotEqualFn);
       break;
     case DataType::S32:
-      evalGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<int32_t>(kernel.input1(), kernel.input2(), kernel.output(),
+                                              runtime_graph, luci_interpreter_pal::NotEqualFn);
       break;
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(), runtime_graph);
+      kernels::evalComparisonGeneric<float>(kernel.input1(), kernel.input2(), kernel.output(),
+                                            runtime_graph, luci_interpreter_pal::NotEqualFn);
       break;
 #endif // DIS_FLOAT
     default:
index 3d64215..9ea7c70 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/PRelu.h"
-
-#include "kernels/BinaryOpCommon.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "TISOKernel.h"
 
-#include <tensorflow/lite/kernels/internal/reference/binary_function.h>
-#include <tensorflow/lite/kernels/internal/reference/prelu.h>
+#include "PALPreluCommon.h"
 
 namespace luci_interpreter
 {
 
-namespace kernels
+void configure_kernel_CirclePRelu(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
 
-PRelu::PRelu(const Tensor *input, const Tensor *alpha, Tensor *output)
-  : Kernel({input, alpha}, {output})
-{
-}
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+                         Tensor::element_type(kernel.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+                         Tensor::element_type(kernel.input2()));
 
-PRelu::~PRelu()
-{
-  // Destructor declared to delete vector of alpha quantized data properly
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) == Tensor::num_dims(kernel.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::num_elements(kernel.input1()) ==
+                         Tensor::num_elements(kernel.output()));
 }
 
-void PRelu::configure()
+void execute_kernel_CirclePRelu(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
-  LUCI_INTERPRETER_CHECK(alpha()->element_type() == output()->element_type());
-  LUCI_INTERPRETER_CHECK(input()->scales().size() <= 1);
-  LUCI_INTERPRETER_CHECK(output()->scales().size() <= 1);
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+  kernels::TISOData kernel_data = kernel.readData();
 
-  if (input()->element_type() == DataType::U8)
-  {
-    LUCI_INTERPRETER_CHECK(alpha()->scales().size() <= 1); // remove when CWQ kernel arrives
-    _alpha_multipliers.resize(1);
-    double alpha_multiplier = input()->scale() * alpha()->scale() / output()->scale();
-    quantizeMultiplier(alpha_multiplier, &_alpha_multipliers[0].multiplier,
-                       &_alpha_multipliers[0].shift);
-    double identity_multiplier = input()->scale() / output()->scale();
-    quantizeMultiplier(identity_multiplier, &_output_multiplier_identity, &_output_shift_identity);
-  }
-  else if (input()->element_type() == DataType::S16)
-  {
-    // Common check for correctness of quant params
-    LUCI_INTERPRETER_CHECK(input()->zero_point() == 0 && output()->zero_point() == 0);
-    for (size_t channel = 0; channel < alpha()->zero_points().size(); ++channel)
-    {
-      LUCI_INTERPRETER_CHECK(alpha()->zero_points()[channel] == 0);
-    }
-    // PRelu specific checks for CWQ
-    LUCI_INTERPRETER_CHECK(alpha()->quantized_dimension() == alpha()->shape().num_dims() - 1);
-    LUCI_INTERPRETER_CHECK(static_cast<int32_t>(alpha()->scales().size()) ==
-                           alpha()->shape().dim(alpha()->quantized_dimension()));
-    LUCI_INTERPRETER_CHECK(alpha()->shape().num_elements() ==
-                           input()->shape().dim(input()->shape().num_dims() - 1));
-
-    // all dimension of alpha except last one should be size 1
-    for (int dim = 0; dim < alpha()->shape().num_dims() - 1; ++dim)
-    {
-      LUCI_INTERPRETER_CHECK(alpha()->shape().dim(dim) == 1);
-    }
-
-    std::vector<double> real_multipliers =
-      getQuantizedConvolutionMultiplers(input()->scale(), alpha()->scales(), output()->scale());
-
-    _alpha_multipliers = quantizeMultipliers(real_multipliers);
-
-    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(calculateShapeForBroadcast(input()->shape(), alpha()->shape()));
-}
-
-void PRelu::execute() const
-{
-  switch (input()->element_type())
+  switch (Tensor::element_type(kernel.input1()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalFloat();
-      break;
-    case DataType::U8:
-      evalQuantized();
-      break;
-    case DataType::S16:
-      evalQuantizedS16();
-      break;
-    default:
-      assert(false && "Unsupported type.");
-  }
-}
-
-void PRelu::evalFloat() const
-{
-  const auto input_data = getTensorData<float>(input());
-  const auto alpha_data = getTensorData<float>(alpha());
-  const auto size = getTensorShape(input()).FlatSize();
-  auto output_data = getTensorData<float>(output());
-
-  auto PReluFunc = [](float input, float alpha) { return input >= 0.0 ? input : input * alpha; };
-
-  if (input()->shape() != alpha()->shape())
-  {
-    tflite::reference_ops::BroadcastBinaryFunction4DSlow<float, float, float>(
-      getTensorShape(input()), getTensorData<float>(input()), getTensorShape(alpha()),
-      getTensorData<float>(alpha()), getTensorShape(output()), getTensorData<float>(output()),
-      PReluFunc);
-  }
-  else
-  {
-    for (auto i = decltype(size){0}; i < size; ++i)
     {
-      if (input_data[i] >= 0)
-        output_data[i] = input_data[i];
-      else
-        output_data[i] = input_data[i] * alpha_data[i];
+      const float *input_data_float = kernels::getTensorData<float>(kernel_data.input1_data);
+      const float *alpha_data_float = kernels::getTensorData<float>(kernel_data.input2_data);
+      float *output_data_float = kernels::getTensorData<float>(kernel_data.output_data);
+      assert(output_data_float);
+      assert(input_data_float);
+      assert(alpha_data_float);
+
+      luci_interpreter_pal::BroadcastPrelu4DSlowFloat(
+        kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph), input_data_float,
+        kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph), alpha_data_float,
+        kernels::getTensorRuntimeShape(kernel.output(), runtime_graph), output_data_float);
+      break;
     }
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
   }
 }
 
-void PRelu::evalQuantized() const
-{
-  tflite::PreluParams op_params{};
-
-  op_params.input_offset = -input()->zero_point(); // Note the '-'.
-  op_params.alpha_offset = -alpha()->zero_point(); // Note the '-'.
-  op_params.output_offset = output()->zero_point();
-  op_params.output_shift_1 = _output_shift_identity;
-  op_params.output_multiplier_1 = _output_multiplier_identity;
-  op_params.output_shift_2 = _alpha_multipliers[0].shift;
-  op_params.output_multiplier_2 = _alpha_multipliers[0].multiplier;
-
-  if (input()->shape() != alpha()->shape())
-  {
-    tflite::reference_ops::BroadcastPrelu4DSlow(
-      op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(alpha()),
-      getTensorData<uint8_t>(alpha()), getTensorShape(output()), getTensorData<uint8_t>(output()));
-  }
-  else
-  {
-    tflite::reference_ops::Prelu<uint8_t>(
-      op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(alpha()),
-      getTensorData<uint8_t>(alpha()), getTensorShape(output()), getTensorData<uint8_t>(output()));
-  }
-}
-
-static inline int16_t evalElemS16PRelu(int16_t input_val, int16_t alpha_val,
-                                       const ChannelQuantMultipliers &identity_mult,
-                                       const ChannelQuantMultipliers &alpha_mult)
-{
-  constexpr int32_t quantized_min = std::numeric_limits<int16_t>::min();
-  constexpr int32_t quantized_max = std::numeric_limits<int16_t>::max();
-
-  const int32_t output_val =
-    input_val >= 0
-      ? tflite::MultiplyByQuantizedMultiplier(static_cast<int32_t>(input_val),
-                                              identity_mult.multiplier, identity_mult.shift)
-      : tflite::MultiplyByQuantizedMultiplier(static_cast<int32_t>(input_val * alpha_val),
-                                              alpha_mult.multiplier, alpha_mult.shift);
-  const int32_t clamped_output = std::min(quantized_max, std::max(quantized_min, output_val));
-  return clamped_output;
-}
-
-void PRelu::evalQuantizedS16() const
-{
-  // Note that this kernel assumes alpha is CWQ
-  tflite::RuntimeShape input_shape = getTensorShape(input());
-  const int16_t *input_data = input()->data<int16_t>();
-  const int16_t *alpha_data = alpha()->data<int16_t>();
-  int16_t *output_data = output()->data<int16_t>();
-
-  const ChannelQuantMultipliers pos_mult{_output_shift_identity, _output_multiplier_identity};
-
-  const int last_dim = input()->shape().num_dims() - 1;
-
-  int32_t outer_dims_size = 1;
-  for (int i = 0; i < last_dim; ++i)
-    outer_dims_size *= input_shape.Dims(i);
-  int32_t quant_dim_size = input_shape.Dims(last_dim);
-
-  for (int32_t outer_dims = 0; outer_dims < outer_dims_size; ++outer_dims)
-    for (int32_t quant_channel = 0; quant_channel < quant_dim_size; ++quant_channel)
-    {
-      const ChannelQuantMultipliers &neg_mult = _alpha_multipliers[quant_channel];
-      size_t offset = static_cast<size_t>(outer_dims) * static_cast<size_t>(quant_dim_size);
-      offset += quant_channel;
-
-      output_data[offset] =
-        evalElemS16PRelu(input_data[offset], alpha_data[quant_channel], pos_mult, neg_mult);
-    }
-}
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/PRelu.h b/onert-micro/luci-interpreter/src/kernels/PRelu.h
deleted file mode 100644 (file)
index f7735d4..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_PRELU_H
-#define LUCI_INTERPRETER_KERNELS_PRELU_H
-
-#include "core/Kernel.h"
-#include <vector>
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class ChannelQuantMultipliers;
-
-class PRelu : public Kernel
-{
-public:
-  PRelu(const Tensor *input, const Tensor *alpha, Tensor *output);
-
-  ~PRelu();
-
-  const Tensor *input() const { return _inputs[0]; }
-  const Tensor *alpha() const { return _inputs[1]; }
-  Tensor *output() const { return _outputs[0]; }
-
-  void configure() override;
-  void execute() const override;
-
-private:
-  void evalFloat() const;
-  void evalQuantized() const;
-  void evalQuantizedS16() const;
-
-private:
-  std::vector<ChannelQuantMultipliers> _alpha_multipliers;
-  // TODO merge this into one ChannelQuantMultiplier object
-  int32_t _output_multiplier_identity = 0;
-  int _output_shift_identity = 0;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_PRELU_H
index 6d97382..533bc81 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/PRelu.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/prelu/FloatPReluKernel.h"
+#include "luci_interpreter/test_models/prelu/NegPReluKernel.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> alpha_shape,
-           std::initializer_list<int32_t> output_shape, std::initializer_list<T> input_data,
-           std::initializer_list<T> alpha_data, std::initializer_list<T> output_data)
-{
-  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 alpha_tensor =
-    makeInputTensor<element_type>(alpha_shape, alpha_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(element_type);
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
-}
-
-TEST(PReluTest, FloatSimple)
-{
-  Check<float>(/*input_shape=*/{2, 3}, /*alpha_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
-               },
-               /*alpha_data=*/
-               {
-                 0.0f, 0.5f, 0.1f, // Row 1
-                 0.0f, 0.5f, 0.1f, // Row 2
-               },
-               /*output_data=*/
-               {
-                 0.0f, 1.0f, 3.0f,   // Row 1
-                 1.0f, -0.5f, -0.2f, // Row 2
-               });
-
-  SUCCEED();
-}
-
-TEST(PReluTest, FloatBroadcast)
-{
-  Check<float>(/*input_shape=*/{1, 2, 2, 3}, /*alpha_shape=*/{1, 1, 3},
-               /*output_shape=*/{1, 2, 2, 3},
-               /*input_data=*/
-               {
-                 0.0f, 0.0f, 0.0f,    // Row 1, Column 1
-                 1.0f, 1.0f, 1.0f,    // Row 1, Column 2
-                 -1.0f, -1.0f, -1.0f, // Row 2, Column 1
-                 -2.0f, -2.0f, -2.0f, // Row 2, Column 2
-               },
-               /*alpha_data=*/
-               {0.0f, 1.0f, 2.0f},
-               /*output_data=*/
-               {
-                 0.0f, 0.0f, 0.0f,   // Row 1, Column 1
-                 1.0f, 1.0f, 1.0f,   // Row 1, Column 2
-                 0.0f, -1.0f, -2.0f, // Row 2, Column 1
-                 0.0f, -2.0f, -4.0f, // Row 2, Column 2
-               });
-
-  SUCCEED();
-}
-
-float GetTolerance(float min, float max) { return (max - min) / 255.0; }
-
-TEST(PReluTest, Uint8Simple)
+class PReluTest : public ::testing::Test
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> input_data{-0.8f, 0.2f, 0.9f, 0.7f, 0.1f, -0.4f};
-  std::vector<float> alpha_data{0.5f, 0.5f, 0.5f, 0.25f, 1.0f, 0.25f};
-  std::vector<float> ref_output_data{-0.4f, 0.2f, 0.9f, 0.7f, 0.1f, -0.1f};
+  // Do nothing
+};
 
-  float kQuantizedTolerance = GetTolerance(-1.0, 1.0);
-  std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(-1.0f, 1.0f);
-
-  Tensor input_tensor = makeInputTensor<DataType::U8>(
-    {1, 2, 3, 1}, quant_param.first, quant_param.second, input_data, memory_manager.get());
-  Tensor alpha_tensor = makeInputTensor<DataType::U8>(
-    {1, 2, 3, 1}, quant_param.first, quant_param.second, alpha_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.second);
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(ref_output_data, kQuantizedTolerance));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 3, 1}));
-
-  SUCCEED();
-}
-
-TEST(PReluTest, Uint8Broadcast)
+template <typename T> std::vector<T> checkPReluKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  std::vector<float> input_data{
-    0.0f,   0.0f,   0.0f,   // Row 1, Column 1
-    0.5f,   0.5f,   0.5f,   // Row 1, Column 2
-    -1.0f,  -1.0f,  -1.0f,  // Row 2, Column 1
-    -0.25f, -0.25f, -0.25f, // Row 2, Column 2
-  };
-  std::vector<float> alpha_data{0.0f, 0.5f, -0.5f};
-  std::vector<float> ref_output_data{
-    0.0f, 0.0f,    0.0f,  // Row 1, Column 1
-    0.5f, 0.5f,    0.5f,  // Row 1, Column 2
-    0.0f, -0.5f,   0.5f,  // Row 2, Column 1
-    0.0f, -0.125f, 0.125f // Row 2, Column 2
-  };
-  std::vector<float> ref_quant_output_data{
-    128, 128, 128, // Row 1, Column 1
-    192, 192, 192, // Row 1, Column 2
-    128, 64,  192, // Row 2, Column 1
-    128, 112, 144  // Row 2, Column 2
-  };
-  float kQuantizedTolerance = 2 * (1. / 256);
-  const float kMin = -1;
-  const float kMax = 127.f / 128.f;
-  std::pair<float, int32_t> quant_param = quantizationParams<uint8_t>(kMin, kMax);
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  Tensor input_tensor = makeInputTensor<DataType::U8>(
-    {1, 2, 2, 3}, quant_param.first, quant_param.second, input_data, memory_manager.get());
-  Tensor alpha_tensor = makeInputTensor<DataType::U8>(
-    {1, 1, 3}, quant_param.first, quant_param.second, alpha_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);
 
-  PRelu kernel(&input_tensor, &alpha_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() == 2);
 
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(ref_output_data, kQuantizedTolerance));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 2, 3}));
-  EXPECT_THAT(extractTensorData<uint8_t>(output_tensor),
-              ::testing::ElementsAreArray(ref_quant_output_data));
-}
+  // 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(PReluTest, SInt16_LWQ_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  // Rewrite this test in case layer-wise quantization for sint16 is supported
-  std::vector<float> input_data(6); // data is not important
-  std::vector<float> alpha_data(6);
+  // 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 input_tensor =
-    makeInputTensor<DataType::S16>({1, 2, 3, 1}, 0.1, 0, input_data, memory_manager.get());
-  Tensor alpha_tensor =
-    makeInputTensor<DataType::S16>({1, 2, 3, 1}, 0.1, 0, alpha_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, 0.1, 0);
+  runtime_module.execute();
 
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-TEST(PReluTest, SInt16_CWQ_Simple)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> input_data{-0.8f, 0.2f, 0.9f, -0.7f, 0.1f, -0.4f};
-  std::vector<float> alpha_data{0.5f, 0.25f};
-  std::vector<float> ref_output_data{-0.4f, 0.2f, 0.9f, -0.175f, 0.1f, -0.1f};
-
-  std::vector<float> alpha_scales{0.05f, 0.025f};
-  std::vector<int32_t> zerop{0, 0};
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({1, 1, 3, 2}, 0.1, 0, input_data, memory_manager.get());
-  Tensor alpha_tensor =
-    makeInputTensor<DataType::S16>({2}, alpha_scales, zerop, 0, alpha_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, 0.025, 0);
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 3, 2}));
-  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(PReluTest, SInt16_CWQ_spatial_alpha_NEG)
+TEST_F(PReluTest, Float_P)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> input_data(6); // data is not important
-  std::vector<float> alpha_data(6);
-
-  std::vector<float> alpha_scales{0.25f, 0.05f};
-  std::vector<int32_t> zerop{0, 0};
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({1, 1, 3, 2}, 0.1, 0, input_data, memory_manager.get());
-  Tensor alpha_tensor = makeInputTensor<DataType::S16>({1, 1, 3, 2}, alpha_scales, zerop, 3,
-                                                       alpha_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, 0.1, 0);
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::TestDataFloatPRelu test_data_float_kernel;
+  std::vector<float> output_data_vector = checkPReluKernel(&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(PReluTest, SInt16_CWQ_wrong_dim_quant_NEG)
+TEST_F(PReluTest, Inputs_type_mismatch_NEG)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> input_data(6); // data is not important
-  std::vector<float> alpha_data(6);
-
-  std::vector<float> alpha_scales{0.25f};
-  std::vector<int32_t> zerop{0};
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({1, 1, 3, 2}, 0.1, 0, input_data, memory_manager.get());
-  Tensor alpha_tensor = makeInputTensor<DataType::S16>({1, 1, 1, 2}, alpha_scales, zerop, 1,
-                                                       alpha_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, 0.1, 0);
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputsTypeMismatchPReluKernel 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(PReluTest, SInt16_CWQ_uneven_shape1)
+TEST_F(PReluTest, Input_output_type_mismatch_NEG)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> input_data{-0.8f, 0.2f, 0.9f, -0.7f, 0.1f, -0.4f};
-  std::vector<float> alpha_data{0.5f, 0.25f};
-  std::vector<float> ref_output_data{-0.4f, 0.2f, 0.9f, -0.175f, 0.1f, -0.1f};
-
-  std::vector<float> alpha_scales{0.05f, 0.025f};
-  std::vector<int32_t> zerop{0, 0};
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({1, 1, 3, 2}, 0.1, 0, input_data, memory_manager.get());
-  Tensor alpha_tensor = makeInputTensor<DataType::S16>({1, 1, 2}, alpha_scales, zerop, 2,
-                                                       alpha_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, 0.025, 0);
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 3, 2}));
-  EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
-}
-
-TEST(PReluTest, SInt16_CWQ_uneven_shape2)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> input_data{
-    0.0f,   0.0f,   0.0f,   // Row 1, Column 1
-    0.5f,   0.5f,   0.5f,   // Row 1, Column 2
-    -1.0f,  -1.0f,  -1.0f,  // Row 2, Column 1
-    -0.25f, -0.25f, -0.25f, // Row 2, Column 2
-  };
-  std::vector<float> alpha_data{0.0f, 0.5f, -0.5f};
-  std::vector<float> ref_output_data{
-    0.0f, 0.0f,    0.0f,  // Row 1, Column 1
-    0.5f, 0.5f,    0.5f,  // Row 1, Column 2
-    0.0f, -0.5f,   0.5f,  // Row 2, Column 1
-    0.0f, -0.125f, 0.125f // Row 2, Column 2
-  };
-
-  std::vector<float> alpha_scales{1.f, 0.05f, 0.1f};
-  std::vector<int32_t> zerop{0, 0, 0};
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({1, 2, 2, 3}, 0.01, 0, input_data, memory_manager.get());
-  Tensor alpha_tensor = makeInputTensor<DataType::S16>({1, 1, 1, 3}, alpha_scales, zerop, 3,
-                                                       alpha_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, 0.001, 0);
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 2, 2, 3}));
-  EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
-}
-
-TEST(PReluTest, Input_Output_Type_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, memory_manager.get());
-  Tensor alpha_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8);
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST(PReluTest, Input_Alpha_Type_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, memory_manager.get());
-  Tensor alpha_tensor = makeInputTensor<DataType::U8>({1}, {1}, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST(PReluTest, Invalid_Input_Type_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  Tensor input_tensor = makeInputTensor<DataType::S64>({1}, {1}, memory_manager.get());
-  Tensor alpha_tensor = makeInputTensor<DataType::S64>({1}, {1}, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S64);
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  EXPECT_ANY_THROW(kernel.execute());
-}
-
-TEST(PReluTest, Input_Output_U8_CWQ_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> scales{1.f, 1.f};
-  std::vector<int32_t> zerop{0, 0};
-  std::vector<float> dummy_data(4, 0.f);
-  Tensor input_tensor =
-    makeInputTensor<DataType::U8>({2, 2}, scales, zerop, 0, dummy_data, memory_manager.get());
-  Tensor alpha_tensor =
-    makeInputTensor<DataType::U8>({2, 2}, scales, zerop, 0, dummy_data, memory_manager.get());
-  Tensor output_tensor =
-    makeInputTensor<DataType::U8>({2, 2}, scales, zerop, 0, dummy_data, memory_manager.get());
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST(PReluTest, Input_Output_S16_CWQ_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> scales{1.f, 1.f};
-  std::vector<int32_t> zerop{0, 0};
-  std::vector<float> dummy_data(4, 0.f);
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({2, 2}, scales, zerop, 0, dummy_data, memory_manager.get());
-  Tensor alpha_tensor =
-    makeInputTensor<DataType::S16>({2, 2}, scales, zerop, 0, dummy_data, memory_manager.get());
-  Tensor output_tensor =
-    makeInputTensor<DataType::S16>({2, 2}, scales, zerop, 0, dummy_data, memory_manager.get());
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST(PReluTest, Mixing_U8_S16_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  std::vector<float> dummy_data(4, 0.f);
-  Tensor input_tensor =
-    makeInputTensor<DataType::U8>({2, 2}, 1.f, 0, dummy_data, memory_manager.get());
-  Tensor alpha_tensor =
-    makeInputTensor<DataType::S16>({2, 2}, 1.f, 0, dummy_data, memory_manager.get());
-  Tensor output_tensor =
-    makeInputTensor<DataType::U8>({2, 2}, 1.f, 0, dummy_data, memory_manager.get());
-
-  PRelu kernel(&input_tensor, &alpha_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputOutputTypeMismatchPReluKernel 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
index 92cd117..8f9c07a 100644 (file)
 
 namespace luci_interpreter
 {
+namespace
+{
+class PadKernel
+{
+public:
+  PadKernel() = delete;
+
+  explicit PadKernel(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+    : _runtime_graph(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);
+
+    _input1_tensor = _runtime_graph->getCircleTensorByIndex(input1_index);
+    _input2_tensor = _runtime_graph->getCircleTensorByIndex(input2_index);
+    _input3_tensor =
+      num_inputs == 3 ? runtime_graph->getCircleTensorByIndex(input3_index) : nullptr;
+    _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 getPadParams()
+  {
+    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];
+    }
+
+    return pad_params;
+  }
+
+  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 *output() const { return _output_tensor; }
+
+  BaseRuntimeGraph *runtime_graph() const { return _runtime_graph; }
+
+private:
+  const circle::Tensor *_input1_tensor;
+  const circle::Tensor *_input2_tensor;
+  const circle::Tensor *_input3_tensor;
+  const circle::Tensor *_output_tensor;
+
+  BaseRuntimeGraph *_runtime_graph;
+};
+} // namespace
+
 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)
+  PadKernel kernel(cur_op, runtime_graph);
+
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+                         Tensor::element_type(kernel.output()));
+  if (kernel.input3() != nullptr)
+    PadKernel kernel(cur_op, runtime_graph);
+
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+                         Tensor::element_type(kernel.output()));
+  if (kernel.input3() != nullptr)
   {
-    LUCI_INTERPRETER_CHECK(Tensor::element_type(input3_tensor) ==
-                           Tensor::element_type(input1_tensor));
+    LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input3()) ==
+                           Tensor::element_type(kernel.input1()));
     // Value is scalar
-    LUCI_INTERPRETER_CHECK(Tensor::num_elements(input3_tensor) == 1);
+    LUCI_INTERPRETER_CHECK(Tensor::num_elements(kernel.input3()) == 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++)
+    kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(kernel.input2()));
+  for (int i = 0; i < Tensor::num_dims(kernel.output()); i++)
   {
-    int output_dim = Tensor::dim(output_tensor, i);
+    int output_dim = Tensor::dim(kernel.output(), i);
     int expected_dim =
-      Tensor::dim(input1_tensor, i) + paddings_data[i * 2] + paddings_data[i * 2 + 1];
+      Tensor::dim(kernel.input1(), 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;
+  PadKernel kernel(cur_op, runtime_graph);
 
-  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];
-  }
+  const auto input1_tensor = kernel.input1();
+  const auto input2_tensor = kernel.input2();
+  const auto input3_tensor = kernel.input3();
+  const auto output_tensor = kernel.output();
+
+  auto pad_params = kernel.getPadParams();
 
   auto *input1_data = runtime_graph->getDataByTensor(input1_tensor);
   if (input1_data == nullptr)
diff --git a/onert-micro/luci-interpreter/src/kernels/Pool2DCommon.h b/onert-micro/luci-interpreter/src/kernels/Pool2DCommon.h
new file mode 100644 (file)
index 0000000..a780c21
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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_POOL2DCOMMON_H
+#define LUCI_INTERPRETER_KERNELS_POOL2DCOMMON_H
+
+#include "Builders.h"
+#include "SISOKernel.h"
+#include "Utils.h"
+
+namespace luci_interpreter
+{
+
+inline void configure_kernel_CirclePool2DCommon(const circle::Operator *cur_op,
+                                                BaseRuntimeGraph *runtime_graph)
+{
+  const kernels::SISOKernel siso_kernel(cur_op, runtime_graph);
+
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(siso_kernel.input()) ==
+                         Tensor::element_type(siso_kernel.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(siso_kernel.input()) == 4);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(siso_kernel.input()) ==
+                         Tensor::num_dims(siso_kernel.output()));
+
+#ifndef DIS_QUANT
+  if (Tensor::element_type(siso_kernel.input()) == DataType::U8)
+  {
+    LUCI_INTERPRETER_CHECK(
+      std::abs(Tensor::scale(siso_kernel.output()) - Tensor::scale(siso_kernel.input())) <= 1.0e-6);
+    LUCI_INTERPRETER_CHECK(Tensor::zero_point(siso_kernel.output()) ==
+                           Tensor::zero_point(siso_kernel.input()));
+  }
+  else if (Tensor::element_type(siso_kernel.input()) == DataType::S16)
+  {
+    LUCI_INTERPRETER_CHECK(
+      std::abs(Tensor::scale(siso_kernel.output()) - Tensor::scale(siso_kernel.input())) <= 1.0e-6);
+    LUCI_INTERPRETER_CHECK(Tensor::zero_point(siso_kernel.input()) == 0 &&
+                           Tensor::zero_point(siso_kernel.output()) == 0);
+  }
+#endif // DIS_QUANT
+}
+
+inline luci_interpreter_pal::PoolParams createPoolParams(const circle::Operator *cur_op,
+                                                         const kernels::SISOKernel &siso_kernel)
+{
+  const auto input = siso_kernel.input();
+  const auto output = siso_kernel.output();
+
+  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 DataType input_type = Tensor::element_type(input);
+
+  float activation_min{};
+  float activation_max{};
+
+  int32_t quantized_activation_min{};
+  int32_t quantized_activation_max{};
+
+  if (input_type == DataType::S8 or input_type == DataType::S16)
+  {
+#ifndef DIS_QUANT
+    kernels::calculateActivationRangeQuantized(luci_actfunc(options->fused_activation_function()),
+                                               output, &quantized_activation_min,
+                                               &quantized_activation_max);
+#endif // DIS_QUANT
+  }
+  else if (input_type == DataType::FLOAT32)
+  {
+#ifndef DIS_FLOAT
+    kernels::calculateActivationRange(luci_actfunc(options->fused_activation_function()),
+                                      &activation_min, &activation_max);
+#endif // DIS_FLOAT
+  }
+  else
+  {
+    assert(false && "Not supported type");
+  }
+
+  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;
+  params.quantized_activation_max = quantized_activation_max;
+  params.quantized_activation_min = quantized_activation_min;
+
+  return params;
+}
+
+} // namespace luci_interpreter
+
+#endif // LUCI_INTERPRETER_KERNELS_POOL2DCOMMON_H
index 9f622d0..ab6d9a5 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Quantize.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "SISOKernel.h"
+
 #include "PALQuantize.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
-
-namespace
-{
 
-template <typename input_dtype> void call_requantize(const Tensor *input, Tensor *output)
+void configure_kernel_CircleQuantize(const circle::Operator *cur_op,
+                                     BaseRuntimeGraph *runtime_graph)
 {
-  int32_t multiplier;
-  int shift;
-
-  const double effective_output_scale = input->scale() / output->scale();
-  quantizeMultiplier(effective_output_scale, &multiplier, &shift);
-
-  const auto input_shape = getTensorShape(input);
-  const auto output_shape = getTensorShape(output);
-  const auto size = tflite::MatchingFlatSize(input_shape, output_shape);
-
-  const auto input_data = getTensorData<input_dtype>(input);
-
-  switch (output->element_type())
-  {
-    case DataType::S8:
-      luci_interpreter_pal::Requantize(input_data, size, multiplier, shift, input->zero_point(),
-                                       output->zero_point(), getTensorData<int8_t>(output));
-      break;
-    case DataType::U8:
-      luci_interpreter_pal::Requantize(input_data, size, multiplier, shift, input->zero_point(),
-                                       output->zero_point(), getTensorData<uint8_t>(output));
-      break;
-    case DataType::S16:
-      luci_interpreter_pal::Requantize(input_data, size, multiplier, shift, input->zero_point(),
-                                       output->zero_point(), getTensorData<int16_t>(output));
-      break;
-    default:
-      assert(false && "Unsupported quantized type, yet!");
-  }
+#ifndef DIS_QUANT
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
+
+  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()));
+  LUCI_INTERPRETER_CHECK(!Tensor::scales(kernel.output()).empty());
+  LUCI_INTERPRETER_CHECK(!Tensor::zero_points(kernel.output()).empty());
+#else
+  assert(false && "Remove DIS_QUANT flag");
+#endif // DIS_QUANT
 }
 
-} // namespace
-
-Quantize::Quantize(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
-
-void Quantize::configure()
+void execute_kernel_CircleQuantize(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
+#ifndef DIS_QUANT
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-  if (input()->element_type() == DataType::S16)
-    LUCI_INTERPRETER_CHECK(input()->zero_point() == 0);
+  const auto *input_data = runtime_graph->getDataByTensor(kernel.input());
+  assert(input_data);
 
-  switch (input()->element_type())
-  {
-    case DataType::FLOAT32:
-    {
-      LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::U8 ||
-                             output()->element_type() == DataType::S8 ||
-                             output()->element_type() == DataType::S16);
-      break;
-    }
-    case DataType::S16:
-    case DataType::S8:
-    case DataType::U8:
-    {
-      LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::S8 ||
-                             output()->element_type() == DataType::U8 ||
-                             output()->element_type() == DataType::S16);
-      if (output()->element_type() == DataType::S16)
-      {
-        LUCI_INTERPRETER_CHECK(output()->zero_point() == 0);
-      }
-      break;
-    }
-    default:
-      assert(false && "Unsupported type");
-  }
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(input()->shape());
-}
+  auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+  assert(output_data);
 
-void Quantize::execute() const
-{
-  switch (input()->element_type())
+  const int flat_size = kernels::getTensorRuntimeShape(kernel.input(), runtime_graph).flatSize();
+
+  switch (Tensor::element_type(kernel.input()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
     {
-      tflite::QuantizationParams op_params;
-      op_params.zero_point = output()->zero_point();
-      op_params.scale = output()->scale();
-      const auto input_data = getTensorData<float>(input());
-
-      switch (output()->element_type())
+      luci_interpreter_pal::QuantizationParams params{};
+      params.zero_point = Tensor::zero_point(kernel.output());
+      params.scale = Tensor::scale(kernel.output());
+      switch (Tensor::element_type(kernel.output()))
       {
         case DataType::S8:
-        {
-          luci_interpreter_pal::Quantize(op_params, getTensorShape(input()), input_data,
-                                         getTensorShape(output()), getTensorData<int8_t>(output()));
+          luci_interpreter_pal::Quantize(params, flat_size,
+                                         kernels::getTensorData<float>(input_data),
+                                         kernels::getTensorData<int8_t>(output_data));
           break;
-        }
         case DataType::U8:
-        {
-          luci_interpreter_pal::Quantize(op_params, getTensorShape(input()), input_data,
-                                         getTensorShape(output()),
-                                         getTensorData<uint8_t>(output()));
+          luci_interpreter_pal::Quantize(params, flat_size,
+                                         kernels::getTensorData<float>(input_data),
+                                         kernels::getTensorData<uint8_t>(output_data));
           break;
-        }
         case DataType::S16:
-        {
-          luci_interpreter_pal::Quantize(op_params, getTensorShape(input()), input_data,
-                                         getTensorShape(output()),
-                                         getTensorData<int16_t>(output()));
+          luci_interpreter_pal::Quantize(params, flat_size,
+                                         kernels::getTensorData<float>(input_data),
+                                         kernels::getTensorData<int16_t>(output_data));
           break;
-        }
         default:
-          assert(false && "Unsupported type.");
+          assert(false && "Unsupported type");
       }
       break;
     }
-    case DataType::S16:
-    {
-      call_requantize<int16_t>(input(), output());
-      break;
-    }
-    case DataType::S8:
-    {
-      call_requantize<int8_t>(input(), output());
-      break;
-    }
-    case DataType::U8:
-    {
-      call_requantize<uint8_t>(input(), output());
-      break;
-    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
+#else
+  assert(false && "Remove DIS_QUANT flag");
+#endif // DIS_QUANT
 }
 
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Quantize.h b/onert-micro/luci-interpreter/src/kernels/Quantize.h
deleted file mode 100644 (file)
index 006c536..0000000
+++ /dev/null
@@ -1,43 +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.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_QUANTIZE_H
-#define LUCI_INTERPRETER_KERNELS_QUANTIZE_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Quantize : public Kernel
-{
-public:
-  Quantize(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;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_QUANTIZE_H
index 22e67fe..8d6f37f 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Quantize.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/quantize/FloatQuantizeKernel.h"
+#include "luci_interpreter/test_models/quantize/NegQuantizeKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -30,225 +30,58 @@ using namespace testing;
 
 class QuantizeTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(QuantizeTest, FloatUint8)
-{
-  std::vector<float> input_data{-63.5, -63, -62.5, -62, -61.5, 62, 62.5, 63, 63.5, 64};
-
-  std::vector<uint8_t> ref_output_data{0, 1, 2, 3, 4, 251, 252, 253, 254, 255};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>({2, 5}, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8, /*scale*/ 0.5, /*zero_point*/ 127);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<uint8_t>(output_tensor),
-              ::testing::ElementsAreArray(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 5}));
-}
-
-TEST_F(QuantizeTest, FloatInt8)
-{
-  std::vector<float> input_data{-63.5, -63, -62.5, -62, -61.5, 62, 62.5, 63, 63.5, 64};
-
-  std::vector<int8_t> ref_output_data{-128, -127, -126, -125, -124, 123, 124, 125, 126, 127};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>({2, 5}, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S8, /*scale*/ 0.5, /*zero_point*/ -1);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<int8_t>(output_tensor),
-              ::testing::ElementsAreArray(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 5}));
-}
-
-TEST_F(QuantizeTest, FloatInt16)
+template <typename T, typename U>
+std::vector<U> checkQuantizeKernel(test_kernel::TestDataBase<T, U> *test_data_base)
 {
-  std::vector<float> input_data{-63.5, -63, -3, -2, -1, 1, 2, 3, 63.5, 64};
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  std::vector<int16_t> ref_output_data{-12700, -12600, -600, -400,  -200,
-                                       200,    400,    600,  12700, 12800};
+  // 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, 5}, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, /*scale*/ 0.005, /*zero_point*/ 0);
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-  Quantize kernel(&input_tensor, &output_tensor);
-  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(extractTensorData<int16_t>(output_tensor),
-              ::testing::ElementsAreArray(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({2, 5}));
-}
-
-TEST_F(QuantizeTest, Int16Int16)
-{
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  std::vector<int16_t> ref_output_data{2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
-
-  Tensor input_tensor = makeInputTensor<DataType::S16>(
-    {1, 1, 2, 5}, /*scale*/ 1.0, /*zero_point*/ 0, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, /*scale*/ 0.5, /*zero_point*/ 0);
+  runtime_module.execute();
 
-  Quantize kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  EXPECT_THAT(extractTensorData<int16_t>(output_tensor),
-              ::testing::ElementsAreArray(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 2, 5}));
+  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(QuantizeTest, Int8Int8)
+TEST_F(QuantizeTest, Float_P)
 {
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  std::vector<int8_t> ref_output_data{1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
-
-  Tensor input_tensor = makeInputTensor<DataType::S8>(
-    {1, 1, 2, 5}, /*scale*/ 0.5, /*zero_point*/ -1, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S8, /*scale*/ 0.5, /*zero_point*/ -1);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<int8_t>(output_tensor),
-              ::testing::ElementsAreArray(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 2, 5}));
+  test_kernel::TestDataFloatQuantize test_data_kernel;
+  std::vector<uint8_t> output_data_vector = checkQuantizeKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
 }
 
-TEST_F(QuantizeTest, Uint8Uint8)
+TEST_F(QuantizeTest, Input_output_shape_mismatch_NEG)
 {
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  std::vector<uint8_t> ref_output_data{129, 131, 133, 135, 137, 139, 141, 143, 145, 147};
-
-  Tensor input_tensor = makeInputTensor<DataType::U8>(
-    {1, 1, 2, 5}, /*scale*/ 0.5, /*zero_point*/ 127, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8, /*scale*/ 0.5, /*zero_point*/ 127);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<uint8_t>(output_tensor),
-              ::testing::ElementsAreArray(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 2, 5}));
-}
-
-TEST_F(QuantizeTest, Int16Int8)
-{
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  std::vector<int8_t> ref_output_data{1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
-
-  Tensor input_tensor = makeInputTensor<DataType::S16>(
-    {1, 1, 2, 5}, /*scale*/ 1.0, /*zero_point*/ 0, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S8, /*scale*/ 0.5, /*zero_point*/ -1);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorData<int8_t>(output_tensor),
-              ::testing::ElementsAreArray(ref_output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray({1, 1, 2, 5}));
-}
-
-TEST_F(QuantizeTest, InvalidInputType_NEG)
-{
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::S32>({1, 1, 2, 5}, 0.5, 0, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S8, /*scale*/ 0.5, /*zero_point*/ -1);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(QuantizeTest, InvalidOutputTypeForFloatInput_NEG)
-{
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>({1, 1, 2, 5}, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(QuantizeTest, InvalidOutputTypeForInt16Input_NEG)
-{
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({1, 1, 2, 5}, 0.5, 0, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(QuantizeTest, InvalidOutputTypeForInt8Input_NEG)
-{
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::S8>({1, 1, 2, 5}, 0.5, 0, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(QuantizeTest, InvalidOutputTypeForUint8Input_NEG)
-{
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::U8>({1, 1, 2, 5}, 0.5, 0, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S32);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(QuantizeTest, InvalidInputZeroPoint_NEG)
-{
-  std::vector<float> input_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({1, 1, 2, 5}, 0.5, -1, input_data, _memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, 0.5, 0);
-
-  Quantize kernel(&input_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputOutputShapeMismatchQuantizeKernel 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/ReduceMax.cpp b/onert-micro/luci-interpreter/src/kernels/ReduceMax.cpp
new file mode 100644 (file)
index 0000000..f1b3530
--- /dev/null
@@ -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.
+ */
+
+#include "Builders.h"
+#include "kernels/Utils.h"
+#include "TISOKernel.h"
+
+#include "PALReduceCommon.h"
+
+#include <cassert>
+
+namespace luci_interpreter
+{
+namespace
+{
+
+template <typename T>
+void reduceMaxGeneric(kernels::TISOData *tiso_data, const circle::Tensor *input,
+                      const circle::Tensor *axis, const circle::Tensor *output)
+{
+  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=*/std::numeric_limits<T>::lowest(), output_shape.flatSize(),
+    [](const float current, const float in) -> float { return (in > current) ? in : current; });
+}
+
+} // namespace
+
+void configure_kernel_CircleReduceMax(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.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) == Tensor::num_dims(kernel.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
+
+  const int32_t axis_value =
+    kernels::getTensorData<int>(runtime_graph->getConstDataByTensor(kernel.input2()))[0];
+  LUCI_INTERPRETER_CHECK(axis_value >= 0);
+}
+
+void execute_kernel_CircleReduceMax(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();
+
+  switch (Tensor::element_type(kernel.input1()))
+  {
+#ifndef DIS_FLOAT
+    case DataType::FLOAT32:
+      reduceMaxGeneric<float>(&tiso_data, input, axis, output);
+      break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
+  }
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ReduceMax.test.cpp b/onert-micro/luci-interpreter/src/kernels/ReduceMax.test.cpp
new file mode 100644 (file)
index 0000000..df122c8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2020 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/TestUtils.h"
+#include "luci_interpreter/test_models/reduce_max/FloatReduceMaxKernel.h"
+#include "luci_interpreter/test_models/reduce_max/NegReduceMaxKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class ReduceMaxTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T>
+std::vector<T> checkReduceMaxKernel(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(ReduceMaxTest, Float_P)
+{
+  test_kernel::TestDataFloatReduceMax test_data_kernel;
+  std::vector<float> output_data_vector = checkReduceMaxKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(ReduceMaxTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchReduceMaxKernel 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
index 7fe3e56..9565023 100644 (file)
@@ -57,6 +57,8 @@ void execute_kernel_CircleReshape(const circle::Operator *cur_op, BaseRuntimeGra
   assert(input_data != nullptr);
   assert(output_data != nullptr);
 
+  int32_t data_size = Tensor::num_elements(output) * getDataTypeSize(Tensor::element_type(output));
+
 #ifndef DIS_DYN_SHAPES
   if (shape_data == nullptr)
   {
@@ -66,11 +68,11 @@ void execute_kernel_CircleReshape(const circle::Operator *cur_op, BaseRuntimeGra
     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);
+    const auto num_dims = Tensor::num_dims(output);
 
-    luci_interpreter::RuntimeShape dynamic_shape(num_elements);
-    int32_t data_size = 1;
-    for (int i = 0; i < num_elements; ++i)
+    luci_interpreter::RuntimeShape dynamic_shape(num_dims);
+    data_size = 1;
+    for (int i = 0; i < num_dims; ++i)
     {
       dynamic_shape.setDim(i, shape_data_int[i]);
       data_size *= shape_data_int[i];
@@ -93,9 +95,7 @@ void execute_kernel_CircleReshape(const circle::Operator *cur_op, BaseRuntimeGra
   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);
+  std::memcpy(output_data, input_data, data_size);
 }
 
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.h b/onert-micro/luci-interpreter/src/kernels/ResizeBilinear.h
deleted file mode 100644 (file)
index b7bdc2a..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_RESIZEBILINEAR_H
-#define LUCI_INTERPRETER_KERNELS_RESIZEBILINEAR_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class ResizeBilinear : public KernelWithParams<ResizeBilinearParams>
-{
-public:
-  ResizeBilinear(const Tensor *input, const Tensor *shape, Tensor *output,
-                 const ResizeBilinearParams &params);
-
-  const Tensor *input() const { return _inputs[0]; }
-  const Tensor *size() 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_RESIZEBILINEAR_H
index 57ca4d5..2faea49 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2019 The TensorFlow Authors. 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.
  * limitations under the License.
  */
 
-#include "kernels/ResizeNearestNeighbor.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "TISOKernel.h"
 
-#include <tensorflow/lite/kernels/internal/reference/resize_nearest_neighbor.h>
 #include "PALResizeNearestNeighbor.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 
-ResizeNearestNeighbor::ResizeNearestNeighbor(const Tensor *input, const Tensor *size,
-                                             Tensor *output,
-                                             const ResizeNearestNeighborParams &params)
-  : KernelWithParams<ResizeNearestNeighborParams>({input, size}, {output}, params)
+void configure_kernel_CircleResizeNearestNeighbor(const circle::Operator *cur_op,
+                                                  BaseRuntimeGraph *runtime_graph)
 {
-}
+  // Check of the size of input. Should be 2
+  LUCI_INTERPRETER_CHECK(cur_op->inputs()->size() == 2);
+  const kernels::TISOKernel tiso_kernel(cur_op, runtime_graph);
 
-void ResizeNearestNeighbor::configure()
-{
-  LUCI_INTERPRETER_CHECK(input()->shape().num_dims() == 4);
-  LUCI_INTERPRETER_CHECK(size()->shape().num_dims() == 1);
-  LUCI_INTERPRETER_CHECK(size()->element_type() == DataType::S32);
-  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);
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(tiso_kernel.input1()) ==
+                         Tensor::element_type(tiso_kernel.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(tiso_kernel.input1()) == 4);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(tiso_kernel.input2()) == 1);
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(tiso_kernel.input2()) == DataType::S32);
+  LUCI_INTERPRETER_CHECK(Tensor::dim(tiso_kernel.input2(), 0) == 2);
+
+  const auto *params = cur_op->builtin_options_as_ResizeNearestNeighborOptions();
+  if (params->half_pixel_centers() && params->align_corners())
+    assert(false && "If half_pixel_centers is True, align_corners must be False.");
 }
 
-void ResizeNearestNeighbor::execute() const
+void execute_kernel_CircleResizeNearestNeighbor(const circle::Operator *cur_op,
+                                                BaseRuntimeGraph *runtime_graph)
 {
-  tflite::ResizeNearestNeighborParams op_params{};
-  op_params.align_corners = params().align_corners;
-  op_params.half_pixel_centers = params().half_pixel_centers;
-  switch (output()->element_type())
+  kernels::TISOKernel tiso_kernel(cur_op, runtime_graph);
+  kernels::TISOData tiso_data = tiso_kernel.readData();
+
+  // Get parameters
+  const auto *op_params = cur_op->builtin_options_as_ResizeNearestNeighborOptions();
+
+  luci_interpreter_pal::ResizeNearestNeighborParams params;
+  params.align_corners = op_params->align_corners();
+  params.half_pixel_centers = false;
+
+  const uint8_t *input_data = runtime_graph->getDataByTensor(tiso_kernel.input1());
+  const uint8_t *size_data = runtime_graph->getConstDataByTensor(tiso_kernel.input2());
+  uint8_t *output_data = runtime_graph->getDataByTensor(tiso_kernel.output());
+
+  switch (Tensor::element_type(tiso_kernel.output()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      tflite::reference_ops::ResizeNearestNeighbor(
-        op_params, getTensorShape(input()), getTensorData<int32_t>(input()), getTensorShape(size()),
-        getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<int32_t>(output()));
-      break;
-    case DataType::U8:
       luci_interpreter_pal::ResizeNearestNeighbor(
-        op_params, getTensorShape(input()), getTensorData<uint8_t>(input()), getTensorShape(size()),
-        getTensorData<int32_t>(size()), getTensorShape(output()), getTensorData<uint8_t>(output()));
+        params, kernels::getTensorRuntimeShape(tiso_kernel.input1(), runtime_graph),
+        kernels::getTensorData<float>(input_data),
+        kernels::getTensorRuntimeShape(tiso_kernel.input2(), runtime_graph),
+        kernels::getTensorData<int32_t>(size_data),
+        kernels::getTensorRuntimeShape(tiso_kernel.output(), runtime_graph),
+        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/ResizeNearestNeighbor.h b/onert-micro/luci-interpreter/src/kernels/ResizeNearestNeighbor.h
deleted file mode 100644 (file)
index 137d031..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_RESIZENEARESTNEIGHBOR_H
-#define LUCI_INTERPRETER_KERNELS_RESIZENEARESTNEIGHBOR_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class ResizeNearestNeighbor : public KernelWithParams<ResizeNearestNeighborParams>
-{
-public:
-  ResizeNearestNeighbor(const Tensor *input, const Tensor *shape, Tensor *output,
-                        const ResizeNearestNeighborParams &params);
-
-  const Tensor *input() const { return _inputs[0]; }
-  const Tensor *size() 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_RESIZENEARESTNEIGHBOR_H
index 7ade02a..44aa97e 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/ResizeNearestNeighbor.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/resize_nearest_neighbor/FloatResizeNearestNeighborKernel.h"
+#include "luci_interpreter/test_models/resize_nearest_neighbor/NegResizeNearestNeighborKernel.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> 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::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);
-
-  ResizeNearestNeighborParams params{};
-  params.align_corners = align_corners;
-  params.half_pixel_centers = half_pixel_centers;
-
-  ResizeNearestNeighbor 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));
-}
-
-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)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
-  std::pair<float, int32_t> quant_param =
-    quantizationParams<uint8_t>(std::min(input_data) < 0 ? std::min(input_data) : 0.f,
-                                std::max(input_data) > 0 ? std::max(input_data) : 0.f);
-  Tensor input_tensor = makeInputTensor<DataType::U8>(
-    input_shape, quant_param.first, quant_param.second, input_data, memory_manager.get());
-  Tensor size_tensor = makeInputTensor<DataType::S32>(size_shape, size_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8, quant_param.first, quant_param.first);
-
-  ResizeNearestNeighborParams params{};
-  params.align_corners = align_corners;
-  params.half_pixel_centers = half_pixel_centers;
-
-  ResizeNearestNeighbor 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()));
-}
-
-template <typename T> class ResizeNearestNeighborTest : public ::testing::Test
+class ResizeNearestNeighborTest : public ::testing::Test
 {
+  // Do nothing
 };
 
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(ResizeNearestNeighborTest, DataTypes);
-
-TYPED_TEST(ResizeNearestNeighborTest, SimpleTest)
+template <typename T>
+std::vector<T> checkResizeNearestNeighborKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  Check<TypeParam>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
-                   {
-                     3, 6,  //
-                     9, 12, //
-                     4, 10, //
-                     10, 16 //
-                   },
-                   {3, 3},
-                   {
-                     3, 3, 6,    //
-                     3, 3, 6,    //
-                     9, 9, 12,   //
-                     4, 4, 10,   //
-                     4, 4, 10,   //
-                     10, 10, 16, //
-                   },
-                   false, false);
-}
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-TYPED_TEST(ResizeNearestNeighborTest, AlignCenterTest)
-{
-  Check<TypeParam>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
-                   {
-                     3, 6,  //
-                     9, 12, //
-                     4, 10, //
-                     10, 16 //
-                   },
-                   {3, 3},
-                   {
-                     3, 6, 6,    //
-                     9, 12, 12,  //
-                     9, 12, 12,  //
-                     4, 10, 10,  //
-                     10, 16, 16, //
-                     10, 16, 16, //
-                   },
-                   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);
 
-TYPED_TEST(ResizeNearestNeighborTest, HalfPixelCenterTest)
-{
-  Check<TypeParam>({2, 2, 2, 1}, {2}, {2, 3, 3, 1},
-                   {
-                     3, 6,  //
-                     9, 12, //
-                     4, 10, //
-                     10, 16 //
-                   },
-                   {3, 3},
-                   {
-                     3, 6, 6,    //
-                     9, 12, 12,  //
-                     9, 12, 12,  //
-                     4, 10, 10,  //
-                     10, 16, 16, //
-                     10, 16, 16, //
-                   },
-                   false, true);
-}
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-TEST(ResizeNearestNeighborTest, InputShapeInvalid_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  // 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::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);
+  runtime_module.execute();
 
-  ResizeNearestNeighborParams params{};
-  params.align_corners = false;
-  params.half_pixel_centers = false;
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  ResizeNearestNeighbor kernel(&input_tensor, &size_tensor, &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(ResizeNearestNeighborTest, SizeShapeInvalid_NEG)
+TEST_F(ResizeNearestNeighborTest, Float_P)
 {
-  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);
-
-  ResizeNearestNeighborParams params{};
-  params.align_corners = false;
-  params.half_pixel_centers = false;
-
-  ResizeNearestNeighbor kernel(&input_tensor, &size_tensor, &output_tensor, params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::TestDataFloatResizeNearestNeighbor test_data_kernel;
+  std::vector<float> output_data_vector = checkResizeNearestNeighborKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST(ResizeNearestNeighborTest, SizeDimInvalid_NEG)
+TEST_F(ResizeNearestNeighborTest, Input_output_type_mismatch_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);
-
-  ResizeNearestNeighborParams params{};
-  params.align_corners = false;
-  params.half_pixel_centers = false;
-
-  ResizeNearestNeighbor kernel(&input_tensor, &size_tensor, &output_tensor, params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputOutputTypeMismatchResizeNearestNeighborKernel 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/Round.cpp b/onert-micro/luci-interpreter/src/kernels/Round.cpp
new file mode 100644 (file)
index 0000000..006e5f8
--- /dev/null
@@ -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 "Builders.h"
+#include "kernels/Utils.h"
+#include "SISOKernel.h"
+
+#include "PALRound.h"
+
+namespace luci_interpreter
+{
+
+void configure_kernel_CircleRound(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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 execute_kernel_CircleRound(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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:
+    {
+      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::Round(flat_size, input_data_float, output_data_float);
+      break;
+    }
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
+  }
+
+  if (is_inplace)
+    runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Round.test.cpp b/onert-micro/luci-interpreter/src/kernels/Round.test.cpp
new file mode 100644 (file)
index 0000000..a871cee
--- /dev/null
@@ -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 "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/round/FloatRoundKernel.h"
+#include "luci_interpreter/test_models/round/NegRoundKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class RoundTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T> std::vector<T> checkRoundKernel(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(RoundTest, Float_P)
+{
+  test_kernel::TestDataFloatRound test_data_kernel;
+  std::vector<float> output_data_vector = checkRoundKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(RoundTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchRoundKernel 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
index c45c3e4..7df4f92 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Rsqrt.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "SISOKernel.h"
 
-#include <cmath>
+#include "PALRsqrt.h"
 
 namespace luci_interpreter
 {
 
-namespace kernels
+void configure_kernel_CircleRsqrt(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-Rsqrt::Rsqrt(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
-
-void Rsqrt::configure()
-{
-  if (input()->element_type() != output()->element_type())
-  {
-    assert(false && "Input/output tensor data type mismatch.");
-  }
-  // 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 Rsqrt::execute() const
+void execute_kernel_CircleRsqrt(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();
-      break;
+    {
+      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::Rsqrt(flat_size, input_data_float, output_data_float);
+      break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
-}
 
-void Rsqrt::evalFloat() const
-{
-  auto in = getTensorData<float>(input());
-  auto out = getTensorData<float>(output());
-  auto size = getTensorShape(input()).FlatSize();
-  for (auto i = in; i != in + size; ++i)
-  {
-    *out = 1.f / std::sqrt(*i);
-    ++out;
-  }
+  if (is_inplace)
+    runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
 }
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Rsqrt.h b/onert-micro/luci-interpreter/src/kernels/Rsqrt.h
deleted file mode 100644 (file)
index adc5bcf..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_RSQRT_H
-#define LUCI_INTERPRETER_KERNELS_RSQRT_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Rsqrt : public Kernel
-{
-public:
-  Rsqrt(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_RSQRT_H
index 3c64942..84c08e6 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Rsqrt.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/rsqrt/FloatRsqrtKernel.h"
+#include "luci_interpreter/test_models/rsqrt/NegRsqrtKernel.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 RsqrtTest : public ::testing::Test
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  // Do nothing
+};
 
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+template <typename T> std::vector<T> checkRsqrtKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  Rsqrt kernel(&input_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<float>(output_tensor), FloatArrayNear(output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
-}
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-TEST(RsqrtTest, SimpleRsqrt)
-{
-  Check(
-    /*input_shape=*/{1, 2, 4, 1}, /*output_shape=*/{1, 2, 4, 1},
-    /*input_data=*/
-    {
-      5, 4, 8, 2,     //
-      6, 7.5, 9, 0.3, //
-    },
-    /*output_data=*/
-    {
-      0.44721360, 0.5, 0.35355339, 0.70710678,       //
-      0.40824829, 0.36514837, 0.33333333, 1.8257419, //
-    });
-}
+  // 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(RsqrtTest, Input_Output_Type_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  runtime_module.execute();
 
-  Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S32);
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  Rsqrt kernel(&input_tensor, &output_tensor);
-  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(RsqrtTest, Invalid_Input_Type_NEG)
+TEST_F(RsqrtTest, Float_P)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
-  Tensor input_tensor = makeInputTensor<DataType::S64>({1}, {1}, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S64);
+  test_kernel::TestDataFloatRsqrt test_data_kernel;
+  std::vector<float> output_data_vector = checkRsqrtKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
 
-  Rsqrt kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  EXPECT_ANY_THROW(kernel.execute());
+TEST_F(RsqrtTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchRsqrtKernel 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
index a0ff302..81ad446 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/SVDF.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
-#include "PALSVDF.h"
 
-#include <tensorflow/lite/kernels/internal/quantization_util.h>
+#include "PALSVDF.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 
 namespace
 {
-TfLiteFusedActivation get_tflite_activation(Activation activation)
-{
-  switch (activation)
-  {
-    case FusedActFunc::RELU:
-      return kTfLiteActRelu;
-    case FusedActFunc::RELU6:
-      return kTfLiteActRelu6;
-    case FusedActFunc::RELU_N1_TO_1:
-      return kTfLiteActReluN1To1;
-    case FusedActFunc::TANH:
-      return kTfLiteActTanh;
-    case FusedActFunc::SIGN_BIT:
-      return kTfLiteActSignBit;
-    case FusedActFunc::NONE:
-      return kTfLiteActNone;
-    default:
-      assert(false && "Unsupported activation type");
-  }
-}
+const int kSvdfInputTensor = 0;
+const int kSvdfWeightsFeatureTensor = 1;
+const int kSvdfWeightsTimeTensor = 2;
+const int kSvdfBiasTensor = 3;
+const int kSvdfInputActivationStateTensor =
+  4; // This is a variable tensor, and will be modified by this op.
+const int kSvdfOutputTensor = 0;
 } // namespace
 
-SVDF::SVDF(const Tensor *input, const Tensor *weight_feature, const Tensor *weight_time,
-           const Tensor *bias, const Tensor *input_activation_state, Tensor *output,
-           Tensor *scratchpad_activation_state, Tensor *scratchpad_1, Tensor *scratchpad_2,
-           Tensor *scratchpad_3, Tensor *scratchpad_4, Tensor *scratchpad_5, Tensor *scratchpad_6,
-           const SVDFParams &params)
-  : KernelWithParams<SVDFParams>({input, weight_feature, weight_time, bias, input_activation_state},
-                                 {output, scratchpad_activation_state, scratchpad_1, scratchpad_2,
-                                  scratchpad_3, scratchpad_4, scratchpad_5, scratchpad_6},
-                                 params)
+void configure_kernel_CircleSVDF(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  // Do nothing
-}
-
-void SVDF::configure()
-{
-  const Shape &input_shape = input()->shape();
-  const Shape &weight_features_shape = weight_feature()->shape();
-  const Shape &weight_time_shape = weight_time()->shape();
-
-  // Validate Input Tensor:
-  LUCI_INTERPRETER_CHECK(input()->element_type() == DataType::FLOAT32 ||
-                         input()->element_type() == DataType::S8);
-  LUCI_INTERPRETER_CHECK(input_shape.num_dims() == 2);
-
-  // Validate inputs and output types
-  if (input()->element_type() == DataType::S8)
-  {
-    LUCI_INTERPRETER_CHECK(weight_feature()->element_type() == DataType::S8);
-    LUCI_INTERPRETER_CHECK(weight_time()->element_type() == DataType::S16 ||
-                           weight_time()->element_type() == DataType::S8);
-    if (bias())
-      LUCI_INTERPRETER_CHECK(bias()->element_type() == DataType::S32);
-
-    LUCI_INTERPRETER_CHECK(input_activation_state()->element_type() == DataType::S16 ||
-                           input_activation_state()->element_type() == DataType::S8);
-    LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::S8);
-
-    // Note: now tflite support only ReLU activation for integer SVDF
-    LUCI_INTERPRETER_CHECK(params().activation == FusedActFunc::RELU);
-  }
-  else if (weight_feature()->element_type() == DataType::FLOAT32)
-  {
-    LUCI_INTERPRETER_CHECK(weight_feature()->element_type() == DataType::FLOAT32);
-    LUCI_INTERPRETER_CHECK(weight_time()->element_type() == DataType::FLOAT32);
-    LUCI_INTERPRETER_CHECK(input_activation_state()->element_type() == DataType::FLOAT32);
-    if (bias())
-      LUCI_INTERPRETER_CHECK(bias()->element_type() == DataType::FLOAT32);
-    LUCI_INTERPRETER_CHECK(output()->element_type() == DataType::FLOAT32);
-  }
-  else if ((weight_feature()->element_type() == DataType::U8 ||
-            weight_feature()->element_type() == DataType::S8) &&
-           input()->element_type() == DataType::FLOAT32)
-  {
-    // TODO:: support hybrid SVDF op
-    assert(false && "Hybrid type is not currently supported");
-  }
-  else
-  {
-    assert(false && "Unsupported type.");
-  }
-
-  // Check all the parameters of tensor match within themselves and match the
-  // input configuration.
-  const int rank = params().svdf_rank;
-  const int batch_size = input_shape.dim(0);
-  const int num_filters = weight_features_shape.dim(0);
-  LUCI_INTERPRETER_CHECK(rank != 0);
+  // Validate Tensor Inputs (dtype depends on quantization):
+  // [0] = Input, {2, batch_size, input_size}
+  // [1] = Weights Feature, {2, num_filters, input_size}
+  // [2] = Weights Time, {2, num_filters, memory_size}
+  // [3] = Bias (optional), {1, num_units}
+  // [4] = Activation State (variable),
+  //         {2, batch_size, memory_size * num_filters}
+  const auto input_index = cur_op->inputs()->operator[](kSvdfInputTensor);
+  const auto weights_feature_index = cur_op->inputs()->operator[](kSvdfWeightsFeatureTensor);
+  const auto weights_time_index = cur_op->inputs()->operator[](kSvdfWeightsTimeTensor);
+  const auto bias_index = cur_op->inputs()->operator[](kSvdfBiasTensor);
+  const auto activation_state_index = cur_op->inputs()->operator[](kSvdfInputActivationStateTensor);
+  const auto output_index = cur_op->outputs()->operator[](kSvdfOutputTensor);
+
+  assert(input_index != -1);
+  assert(weights_feature_index != -1);
+  assert(weights_time_index != -1);
+  assert(activation_state_index != -1);
+  assert(output_index != -1);
+
+  const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+  const auto weights_feature = runtime_graph->getCircleTensorByIndex(weights_feature_index);
+  const auto weights_time = runtime_graph->getCircleTensorByIndex(weights_time_index);
+  const auto bias = runtime_graph->getCircleTensorByIndex(bias_index);
+  const auto activation_state = runtime_graph->getCircleTensorByIndex(activation_state_index);
+  const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+  assert(input != nullptr);
+  assert(weights_feature != nullptr);
+  assert(weights_time != nullptr);
+  assert(activation_state != nullptr);
+  assert(output != nullptr);
+
+  const auto *options = cur_op->builtin_options_as_SVDFOptions();
+
+  // Define input constants based on input tensor definition above:
+  const int rank = options->rank();
+  const int input_size = Tensor::dim(input, 1);
+  const int batch_size = Tensor::dim(input, 0);
+  const int num_filters = Tensor::dim(weights_feature, 0);
   LUCI_INTERPRETER_CHECK(num_filters % rank == 0);
 
   const int num_units = num_filters / rank;
-  const int memory_size = weight_time_shape.dim(1);
+  const int memory_size = Tensor::dim(weights_time, 1);
 
-  // Validate Weight_Feature Input Tensor:
-  LUCI_INTERPRETER_CHECK(weight_features_shape.num_dims() == 2);
-  LUCI_INTERPRETER_CHECK(weight_features_shape.dim(1) == input_shape.dim(1));
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == DataType::FLOAT32 or
+                         Tensor::element_type(input) == DataType::S8);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(input) == 2);
 
-  // Validate Weight_Time Input Tensor:
-  LUCI_INTERPRETER_CHECK(weight_time_shape.num_dims() == 2);
-  LUCI_INTERPRETER_CHECK(weight_time_shape.dim(0) == num_filters);
+  // Validate Tensor Output:
+  // [0] = float/int8_t, {2, batch_size, num_units}
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(output) == 2);
+  LUCI_INTERPRETER_CHECK(Tensor::dim(output, 0) == batch_size);
+  LUCI_INTERPRETER_CHECK(Tensor::dim(output, 1) == num_units);
 
-  // Validate Bias
-  if (bias())
-    LUCI_INTERPRETER_CHECK(bias()->shape().dim(0) == num_units);
+  // Validate Weights Feature Input Tensor
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(weights_feature) == 2);
+  LUCI_INTERPRETER_CHECK(Tensor::dim(weights_feature, 1) == input_size);
 
-  // Validate Input Activation State
-  LUCI_INTERPRETER_CHECK(input_activation_state()->shape().num_dims() == 2);
-  LUCI_INTERPRETER_CHECK(input_activation_state()->shape().dim(0) == batch_size);
-  LUCI_INTERPRETER_CHECK(input_activation_state()->shape().dim(1) == memory_size * num_filters);
+  // Validate Weights Time Input Tensor:
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(weights_time) == 2);
+  LUCI_INTERPRETER_CHECK(Tensor::dim(weights_time, 0) == num_filters);
+  LUCI_INTERPRETER_CHECK(Tensor::dim(weights_time, 1) == memory_size);
 
-  // Resize scratchpad_state to input_activation_state
-  auto scratchpad_activation_state = getOutputTensors()[1];
-  scratchpad_activation_state->resize({batch_size, memory_size * num_filters});
+  // Validate Optional Bias Input Tensor:
+  if (bias != nullptr)
+  {
+    LUCI_INTERPRETER_CHECK(Tensor::dim(bias, 0) == num_units);
+  }
 
-  // TODO: enable it only if kernel with dynamic shapes
-  // Resize output tensor
-  output()->resize({batch_size, num_units});
+  // Validate Activation State Input Tensor:
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(activation_state) == 2);
+  LUCI_INTERPRETER_CHECK(Tensor::dim(activation_state, 0) == batch_size);
+  LUCI_INTERPRETER_CHECK(Tensor::dim(activation_state, 1) == memory_size * num_filters);
 
-  luci_interpreter_pal::SetupScratchpadTensor(
-    input()->element_type(), weight_feature()->element_type(), getOutputTensors()[2],
-    getOutputTensors()[3], getOutputTensors()[4], getOutputTensors()[5], getOutputTensors()[6],
-    getOutputTensors()[7], input_shape, weight_time_shape, batch_size, num_filters, num_units);
+  if (Tensor::element_type(input) == DataType::FLOAT32)
+  {
+    LUCI_INTERPRETER_CHECK(Tensor::element_type(weights_feature) == DataType::FLOAT32);
+    LUCI_INTERPRETER_CHECK(Tensor::element_type(weights_time) == DataType::FLOAT32);
+    LUCI_INTERPRETER_CHECK(Tensor::element_type(activation_state) == DataType::FLOAT32);
+    if (bias)
+      LUCI_INTERPRETER_CHECK(Tensor::element_type(bias) == DataType::FLOAT32);
+    LUCI_INTERPRETER_CHECK(Tensor::element_type(output) == DataType::FLOAT32);
+  }
 }
 
-void SVDF::execute() const
+void execute_kernel_CircleSVDF(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  switch (weight_feature()->element_type())
+  const auto input_index = cur_op->inputs()->operator[](kSvdfInputTensor);
+  const auto weights_feature_index = cur_op->inputs()->operator[](kSvdfWeightsFeatureTensor);
+  const auto weights_time_index = cur_op->inputs()->operator[](kSvdfWeightsTimeTensor);
+  const auto bias_index = cur_op->inputs()->operator[](kSvdfBiasTensor);
+  const auto activation_state_index = cur_op->inputs()->operator[](kSvdfInputActivationStateTensor);
+  const auto output_index = cur_op->outputs()->operator[](kSvdfOutputTensor);
+
+  assert(input_index != -1);
+  assert(weights_feature_index != -1);
+  assert(weights_time_index != -1);
+  assert(activation_state_index != -1);
+  assert(output_index != -1);
+
+  const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+  const auto weights_feature = runtime_graph->getCircleTensorByIndex(weights_feature_index);
+  const auto weights_time = runtime_graph->getCircleTensorByIndex(weights_time_index);
+  const auto bias = runtime_graph->getCircleTensorByIndex(bias_index);
+  const auto activation_state = runtime_graph->getCircleTensorByIndex(activation_state_index);
+  const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+  assert(input != nullptr);
+  assert(weights_feature != nullptr);
+  assert(weights_time != nullptr);
+  assert(activation_state != nullptr);
+  assert(output != nullptr);
+
+  const auto *options = cur_op->builtin_options_as_SVDFOptions();
+
+  // Define input constants based on input tensor definition above:
+  const int rank = options->rank();
+  const int input_size = Tensor::dim(input, 1);
+  const int batch_size = Tensor::dim(input, 0);
+  const int num_filters = Tensor::dim(weights_feature, 0);
+  LUCI_INTERPRETER_CHECK(num_filters % rank == 0);
+
+  const int num_units = num_filters / rank;
+  const int memory_size = Tensor::dim(weights_time, 1);
+
+  const uint8_t *input_data = runtime_graph->getDataByTensor(input);
+  const uint8_t *weights_feature_data = runtime_graph->getConstDataByTensor(weights_feature);
+  const uint8_t *weights_time_data = runtime_graph->getConstDataByTensor(weights_time);
+  const uint8_t *bias_data = runtime_graph->getConstDataByTensor(bias);
+  uint8_t *output_data = runtime_graph->getDataByTensor(output);
+
+  const auto type = Tensor::element_type(input);
+  switch (type)
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalFloat();
-      break;
-    case DataType::S8:
     {
-      if (input()->element_type() == DataType::S8)
-        evalInteger();
-      else
-        // TODO:: support hybrid SVDF op
-        assert(false && "Hybrid type is not currently supported");
-      break;
+      // Create and fill with 0 state tensor
+      auto state_data = std::make_unique<float[]>(Tensor::num_elements(activation_state));
+      std::fill_n(state_data.get(), Tensor::num_elements(activation_state), 0);
+
+      auto scratch_data = std::make_unique<uint8_t[]>(batch_size * num_filters * sizeof(float));
+
+      luci_interpreter_pal::SVDF(
+        kernels::getTensorData<float>(input_data),
+        kernels::getTensorData<float>(weights_feature_data),
+        kernels::getTensorData<float>(weights_time_data), kernels::getTensorData<float>(bias_data),
+        state_data.get(), kernels::getTensorData<float>(scratch_data.get()),
+        kernels::getTensorData<float>(output_data), rank, input_size, batch_size, num_filters,
+        num_units, memory_size, options->fused_activation_function());
     }
+    break;
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type");
+      assert(false && "Unsupported type.");
   }
 }
 
-void SVDF::evalInteger() const
-{
-  const auto effective_scale_1 = static_cast<double>(input()->scale() * weight_feature()->scale() /
-                                                     input_activation_state()->scale());
-  const auto effective_scale_2 = static_cast<double>(input_activation_state()->scale() *
-                                                     weight_time()->scale() / output()->scale());
-
-  int32_t effective_scale_1_a;
-  int effective_scale_1_b;
-  int32_t effective_scale_2_a;
-  int effective_scale_2_b;
-
-  tflite::QuantizeMultiplier(effective_scale_1, &effective_scale_1_a, &effective_scale_1_b);
-  tflite::QuantizeMultiplier(effective_scale_2, &effective_scale_2_a, &effective_scale_2_b);
-
-  TfLiteSVDFParams params_svdf{};
-  params_svdf.asymmetric_quantize_inputs = params().asymmetric_quantize_inputs;
-  params_svdf.rank = params().svdf_rank;
-  params_svdf.activation = get_tflite_activation(params().activation);
-
-  auto scratchpad_activation_state = getOutputTensors()[1];
-  // Note: it is expected that activation_state input variable tensor reset to zero,
-  // also expected that this variable tensor doesn't have buffer
-  auto scratchpad_data = getTensorData<int16_t>(scratchpad_activation_state);
-  std::fill_n(scratchpad_data, scratchpad_activation_state->shape().num_elements(), 0);
-
-  auto scratchpad = getOutputTensors()[2];
-  auto output_temp = getOutputTensors()[3];
-
-  int32_t input_zp = input()->zero_point();
-  int32_t output_zp = output()->zero_point();
-  luci_interpreter_pal::IntegerSVDF(
-    params_svdf, getTensorShape(input()), getTensorData<int8_t>(input()),
-    getTensorShape(weight_feature()), getTensorData<int8_t>(weight_feature()),
-    getTensorShape(weight_time()), getTensorData<int16_t>(weight_time()), getTensorShape(bias()),
-    getTensorData<int32_t>(bias()), scratchpad_data, getTensorShape(output()),
-    getTensorData<int8_t>(output()), getTensorData<int32_t>(scratchpad),
-    getTensorData<int32_t>(output_temp), effective_scale_1_a, effective_scale_1_b,
-    effective_scale_2_a, effective_scale_2_b, input_zp, output_zp);
-}
-
-void SVDF::evalFloat() const
-{
-  TfLiteSVDFParams params_svdf{};
-  params_svdf.asymmetric_quantize_inputs = params().asymmetric_quantize_inputs;
-  params_svdf.rank = params().svdf_rank;
-  params_svdf.activation = get_tflite_activation(params().activation);
-
-  auto scratchpad_activation_state = getOutputTensors()[1];
-  // Note: it is expected that activation_state input variable tensor reset to zero,
-  // also expected that this variable tensor doesn't have buffer
-  auto scratchpad_data = getTensorData<float>(scratchpad_activation_state);
-  std::fill_n(scratchpad_data, scratchpad_activation_state->shape().num_elements(), 0);
-
-  auto scratchpad_1 = getOutputTensors()[2];
-
-  luci_interpreter_pal::FloatSVDF(
-    params_svdf, getTensorShape(input()), getTensorData<float>(input()),
-    getTensorShape(weight_feature()), getTensorData<float>(weight_feature()),
-    getTensorShape(weight_time()), getTensorData<float>(weight_time()), getTensorShape(bias()),
-    getTensorData<float>(bias()), getTensorData<float>(scratchpad_1), scratchpad_data,
-    getTensorShape(output()), getTensorData<float>(output()));
-}
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/SVDF.h b/onert-micro/luci-interpreter/src/kernels/SVDF.h
deleted file mode 100644 (file)
index 335a6cd..0000000
+++ /dev/null
@@ -1,56 +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.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_SVDF_H
-#define LUCI_INTERPRETER_KERNELS_SVDF_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class SVDF : public KernelWithParams<SVDFParams>
-{
-public:
-  SVDF(const Tensor *input, const Tensor *weight_feature, const Tensor *weight_time,
-       const Tensor *bias, const Tensor *input_activation_state, Tensor *output,
-       Tensor *scratchpad_activation_state, Tensor *scratchpad_1, Tensor *scratchpad_2,
-       Tensor *scratchpad_3, Tensor *scratchpad_4, Tensor *scratchpad_5, Tensor *scratchpad_6,
-       const SVDFParams &params);
-
-  const Tensor *input() const { return _inputs[0]; }
-  const Tensor *weight_feature() const { return _inputs[1]; }
-  const Tensor *weight_time() const { return _inputs[2]; }
-  const Tensor *bias() const { return _inputs[3]; }
-  const Tensor *input_activation_state() const { return _inputs[4]; }
-
-  Tensor *output() const { return _outputs[0]; }
-
-  void configure() override;
-  void execute() const override;
-
-private:
-  void evalFloat() const;
-  void evalInteger() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_SVDF_H
index 82bd9b0..d53dac8 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/SVDF.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/svdf/FloatSVDFKernel.h"
+#include "luci_interpreter/test_models/svdf/NegSVDFKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
@@ -29,313 +29,58 @@ using namespace testing;
 
 class SVDFTest : public ::testing::Test
 {
-protected:
-  void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
-
-  std::unique_ptr<IMemoryManager> _memory_manager;
+  // Do nothing
 };
 
-TEST_F(SVDFTest, FullIntegerTest)
+template <typename T> std::vector<T> checkSVDFKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  const int32_t batches = 2;
-  const int32_t input_size = 3;
-  const int32_t units = 4;
-  const int32_t memory_size = 10;
-  const int32_t rank = 1;
-  const int32_t num_filters = units * rank;
-
-  Shape input_shape{batches, input_size};
-  Shape weight_feature_shape{num_filters, input_size};
-  Shape weight_time_shape{num_filters, memory_size};
-  Shape bias_shape{units};
-  Shape activation_state_shape{batches, memory_size * num_filters};
-
-  std::vector<float> input_data{0.49837467, 0.19278903, 0.26584083,
-                                0.17660543, 0.52949083, -0.77931279};
-
-  std::vector<float> weight_feature_data{-0.31930989, -0.36118156, 0.0079667,   0.37613347,
-                                         0.22197971,  0.12416199,  0.27901134,  0.27557442,
-                                         0.3905206,   -0.36137494, -0.06634006, -0.10640851};
-
-  std::vector<float> weight_time_data{
-    -0.31930989, 0.37613347,  0.27901134,  -0.36137494, -0.36118156,
-    0.22197971,  0.27557442,  -0.06634006, 0.0079667,   0.12416199,
-
-    0.3905206,   -0.10640851, -0.0976817,  0.15294972,  0.39635518,
-    -0.02702999, 0.39296314,  0.15785322,  0.21931258,  0.31053296,
-
-    -0.36916667, 0.38031587,  -0.21580373, 0.27072677,  0.23622236,
-    0.34936687,  0.18174365,  0.35907319,  -0.17493086, 0.324846,
-
-    -0.10781813, 0.27201805,  0.14324132,  -0.23681851, -0.27115166,
-    -0.01580888, -0.14943552, 0.15465137,  0.09784451,  -0.0337657};
-
-  std::vector<float> bias_data{-0.0976817, 0.15294972, 0.39635518, -0.02702999};
-
-  std::pair<float, int32_t> input_quant_param = quantizationParams<int8_t>(-1, 1);
-  std::pair<float, int32_t> weight_feature_quant_param = quantizationParams<int8_t>(-0.5, 0.5);
-  std::pair<float, int32_t> weight_time_quant_param = quantizationParams<int16_t>(-1, 1);
-  std::pair<float, int32_t> bias_quant_param = quantizationParams<int32_t>(-512, 512);
-  std::pair<float, int32_t> activation_state_quant_param = quantizationParams<int16_t>(-16, 16);
-
-  std::pair<float, int32_t> output_quant_param = quantizationParams<int8_t>(-0.5, 0.5);
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  Tensor input_tensor =
-    makeInputTensor<DataType::S8>(input_shape, input_quant_param.first, input_quant_param.second,
-                                  input_data, _memory_manager.get());
-  Tensor weight_feature_tensor = makeInputTensor<DataType::S8>(
-    weight_feature_shape, weight_feature_quant_param.first, weight_feature_quant_param.second,
-    weight_feature_data, _memory_manager.get());
-  Tensor weight_time_tensor = makeInputTensor<DataType::S16>(
-    weight_time_shape, weight_time_quant_param.first, weight_time_quant_param.second,
-    weight_time_data, _memory_manager.get());
-  Tensor bias_tensor = makeInputTensor<DataType::S32>(
-    bias_shape, bias_quant_param.first, bias_quant_param.second, bias_data, _memory_manager.get());
-  Tensor activation_state_tensor = makeOutputTensor(
-    DataType::S16, activation_state_quant_param.first, activation_state_quant_param.second);
-  activation_state_tensor.resize(activation_state_shape);
-  Tensor output_tensor =
-    makeOutputTensor(DataType::S8, output_quant_param.first, output_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);
 
-  Tensor scratchpad_activation_state(DataType::S16, Shape({}), {}, "");
-  Tensor scratchpad_1(DataType::S32, Shape({}), {}, "");
-  Tensor scratchpad_2(DataType::S32, Shape({}), {}, "");
-  Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_4(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_5(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_6(DataType::FLOAT32, Shape({}), {}, "");
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-  SVDFParams params{};
-  params.activation = Activation::RELU;
-  params.asymmetric_quantize_inputs = false;
-  params.svdf_rank = rank;
+  // 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);
+  }
 
-  SVDF kernel(&input_tensor, &weight_feature_tensor, &weight_time_tensor, &bias_tensor,
-              &activation_state_tensor, &output_tensor, &scratchpad_activation_state, &scratchpad_1,
-              &scratchpad_2, &scratchpad_3, &scratchpad_4, &scratchpad_5, &scratchpad_6, params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  _memory_manager->allocate_memory(scratchpad_activation_state);
-  _memory_manager->allocate_memory(scratchpad_1);
-  _memory_manager->allocate_memory(scratchpad_2);
-  _memory_manager->allocate_memory(scratchpad_3);
-  _memory_manager->allocate_memory(scratchpad_4);
-  _memory_manager->allocate_memory(scratchpad_5);
-  _memory_manager->allocate_memory(scratchpad_6);
-  kernel.execute();
+  runtime_module.execute();
 
-  std::vector<int8_t> ref_output_data{-9, 24, 31, 1, -10, 10, -3, 0};
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  std::vector<int32_t> ref_output_shape{batches, units};
-  EXPECT_THAT(extractTensorData<int8_t>(output_tensor), ref_output_data);
-  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(SVDFTest, FloatTest)
+TEST_F(SVDFTest, Float_P)
 {
-  const int32_t batches = 2;
-  const int32_t input_size = 3;
-  const int32_t units = 4;
-  const int32_t memory_size = 10;
-  const int32_t rank = 1;
-  const int32_t num_filters = units * rank;
-
-  Shape input_shape{batches, input_size};
-  Shape weight_feature_shape{num_filters, input_size};
-  Shape weight_time_shape{num_filters, memory_size};
-  Shape activation_state_shape{batches, memory_size * num_filters};
-
-  std::vector<float> input_data{0.12609188, -0.46347019, -0.89598465,
-                                0.35867718, 0.36897406,  0.73463392};
-
-  std::vector<float> weight_feature_data{-0.31930989, -0.36118156, 0.0079667,   0.37613347,
-                                         0.22197971,  0.12416199,  0.27901134,  0.27557442,
-                                         0.3905206,   -0.36137494, -0.06634006, -0.10640851};
-
-  std::vector<float> weight_time_data{
-    -0.31930989, 0.37613347,  0.27901134,  -0.36137494, -0.36118156,
-    0.22197971,  0.27557442,  -0.06634006, 0.0079667,   0.12416199,
-
-    0.3905206,   -0.10640851, -0.0976817,  0.15294972,  0.39635518,
-    -0.02702999, 0.39296314,  0.15785322,  0.21931258,  0.31053296,
-
-    -0.36916667, 0.38031587,  -0.21580373, 0.27072677,  0.23622236,
-    0.34936687,  0.18174365,  0.35907319,  -0.17493086, 0.324846,
-
-    -0.10781813, 0.27201805,  0.14324132,  -0.23681851, -0.27115166,
-    -0.01580888, -0.14943552, 0.15465137,  0.09784451,  -0.0337657};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-  Tensor weight_feature_tensor = makeInputTensor<DataType::FLOAT32>(
-    weight_feature_shape, weight_feature_data, _memory_manager.get());
-  Tensor weight_time_tensor =
-    makeInputTensor<DataType::FLOAT32>(weight_time_shape, weight_time_data, _memory_manager.get());
-  Tensor activation_state_tensor = makeOutputTensor(DataType::FLOAT32);
-  activation_state_tensor.resize(activation_state_shape);
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Tensor scratchpad_activation_state(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_2(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_4(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_5(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_6(DataType::FLOAT32, Shape({}), {}, "");
-
-  SVDFParams params{};
-  params.activation = Activation::NONE;
-  params.asymmetric_quantize_inputs = false;
-  params.svdf_rank = rank;
-
-  SVDF kernel(&input_tensor, &weight_feature_tensor, &weight_time_tensor, nullptr,
-              &activation_state_tensor, &output_tensor, &scratchpad_activation_state, &scratchpad_1,
-              &scratchpad_2, &scratchpad_3, &scratchpad_4, &scratchpad_5, &scratchpad_6, params);
-  kernel.configure();
-  _memory_manager->allocate_memory(output_tensor);
-  _memory_manager->allocate_memory(scratchpad_activation_state);
-  _memory_manager->allocate_memory(scratchpad_1);
-  _memory_manager->allocate_memory(scratchpad_2);
-  _memory_manager->allocate_memory(scratchpad_3);
-  _memory_manager->allocate_memory(scratchpad_4);
-  _memory_manager->allocate_memory(scratchpad_5);
-  _memory_manager->allocate_memory(scratchpad_6);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{0.014899,    -0.0517661, -0.143725, -0.00271883,
-                                     -0.03004015, 0.09565311, 0.1587342, 0.00784263};
-
-  std::vector<float> ref_output_shape{batches, units};
-  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::TestDataFloatSVDF test_data_kernel;
+  std::vector<float> output_data_vector = checkSVDFKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST_F(SVDFTest, Unsupported_Type_Configure_NEG)
+TEST_F(SVDFTest, Input_output_type_mismatch_NEG)
 {
-  const int32_t batches = 2;
-  const int32_t input_size = 3;
-  const int32_t units = 4;
-  const int32_t memory_size = 10;
-  const int32_t rank = 1;
-  const int32_t num_filters = units * rank;
-
-  Shape input_shape{batches, input_size};
-  Shape weight_feature_shape{num_filters, input_size};
-  Shape weight_time_shape{num_filters, memory_size};
-  Shape activation_state_shape{batches, memory_size * num_filters};
-
-  std::vector<int32_t> input_data{0, 1, 3, 4, 4, -2};
-
-  std::vector<float> weight_feature_data{-0.31930989, -0.36118156, 0.0079667,   0.37613347,
-                                         0.22197971,  0.12416199,  0.27901134,  0.27557442,
-                                         0.3905206,   -0.36137494, -0.06634006, -0.10640851};
-
-  std::vector<float> weight_time_data{
-    -0.31930989, 0.37613347,  0.27901134,  -0.36137494, -0.36118156,
-    0.22197971,  0.27557442,  -0.06634006, 0.0079667,   0.12416199,
-
-    0.3905206,   -0.10640851, -0.0976817,  0.15294972,  0.39635518,
-    -0.02702999, 0.39296314,  0.15785322,  0.21931258,  0.31053296,
-
-    -0.36916667, 0.38031587,  -0.21580373, 0.27072677,  0.23622236,
-    0.34936687,  0.18174365,  0.35907319,  -0.17493086, 0.324846,
-
-    -0.10781813, 0.27201805,  0.14324132,  -0.23681851, -0.27115166,
-    -0.01580888, -0.14943552, 0.15465137,  0.09784451,  -0.0337657};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::S32>(input_shape, input_data, _memory_manager.get());
-  Tensor weight_feature_tensor = makeInputTensor<DataType::FLOAT32>(
-    weight_feature_shape, weight_feature_data, _memory_manager.get());
-  Tensor weight_time_tensor =
-    makeInputTensor<DataType::FLOAT32>(weight_time_shape, weight_time_data, _memory_manager.get());
-  Tensor activation_state_tensor = makeOutputTensor(DataType::FLOAT32);
-  activation_state_tensor.resize(activation_state_shape);
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Tensor scratchpad_activation_state(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_2(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_4(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_5(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_6(DataType::FLOAT32, Shape({}), {}, "");
-
-  SVDFParams params{};
-  params.activation = Activation::NONE;
-  params.asymmetric_quantize_inputs = false;
-  params.svdf_rank = rank;
-
-  SVDF kernel(&input_tensor, &weight_feature_tensor, &weight_time_tensor, nullptr,
-              &activation_state_tensor, &output_tensor, &scratchpad_activation_state, &scratchpad_1,
-              &scratchpad_2, &scratchpad_3, &scratchpad_4, &scratchpad_5, &scratchpad_6, params);
-  EXPECT_ANY_THROW(kernel.configure());
-}
-
-TEST_F(SVDFTest, Invalid_Input_Shape_NEG)
-{
-  const int32_t batches = 2;
-  const int32_t right_input_size = 3;
-  const int32_t wrong_input_size = 4;
-  const int32_t units = 4;
-  const int32_t memory_size = 10;
-  const int32_t rank = 1;
-  const int32_t num_filters = units * rank;
-
-  Shape input_shape{batches, wrong_input_size};
-  Shape weight_feature_shape{num_filters, right_input_size};
-  Shape weight_time_shape{num_filters, memory_size};
-  Shape activation_state_shape{batches, memory_size * num_filters};
-
-  std::vector<float> input_data{0, 1, 3, 2, 4, 4, -2, 1};
-
-  std::vector<float> weight_feature_data{-0.31930989, -0.36118156, 0.0079667,   0.37613347,
-                                         0.22197971,  0.12416199,  0.27901134,  0.27557442,
-                                         0.3905206,   -0.36137494, -0.06634006, -0.10640851};
-
-  std::vector<float> weight_time_data{
-    -0.31930989, 0.37613347,  0.27901134,  -0.36137494, -0.36118156,
-    0.22197971,  0.27557442,  -0.06634006, 0.0079667,   0.12416199,
-
-    0.3905206,   -0.10640851, -0.0976817,  0.15294972,  0.39635518,
-    -0.02702999, 0.39296314,  0.15785322,  0.21931258,  0.31053296,
-
-    -0.36916667, 0.38031587,  -0.21580373, 0.27072677,  0.23622236,
-    0.34936687,  0.18174365,  0.35907319,  -0.17493086, 0.324846,
-
-    -0.10781813, 0.27201805,  0.14324132,  -0.23681851, -0.27115166,
-    -0.01580888, -0.14943552, 0.15465137,  0.09784451,  -0.0337657};
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
-  Tensor weight_feature_tensor = makeInputTensor<DataType::FLOAT32>(
-    weight_feature_shape, weight_feature_data, _memory_manager.get());
-  Tensor weight_time_tensor =
-    makeInputTensor<DataType::FLOAT32>(weight_time_shape, weight_time_data, _memory_manager.get());
-  Tensor activation_state_tensor = makeOutputTensor(DataType::FLOAT32);
-  activation_state_tensor.resize(activation_state_shape);
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  Tensor scratchpad_activation_state(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_2(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_4(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_5(DataType::FLOAT32, Shape({}), {}, "");
-  Tensor scratchpad_6(DataType::FLOAT32, Shape({}), {}, "");
-
-  SVDFParams params{};
-  params.activation = Activation::NONE;
-  params.asymmetric_quantize_inputs = false;
-  params.svdf_rank = rank;
-
-  SVDF kernel(&input_tensor, &weight_feature_tensor, &weight_time_tensor, nullptr,
-              &activation_state_tensor, &output_tensor, &scratchpad_activation_state, &scratchpad_1,
-              &scratchpad_2, &scratchpad_3, &scratchpad_4, &scratchpad_5, &scratchpad_6, params);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputOutputTypeMismatchSVDFKernel 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/SelectV2.cpp b/onert-micro/luci-interpreter/src/kernels/SelectV2.cpp
new file mode 100644 (file)
index 0000000..0864cf2
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PALSelectV2.h"
+
+namespace luci_interpreter
+{
+
+namespace
+{
+
+constexpr int kInputTensorCondition = 0;
+constexpr int kInputTensorX = 1;
+constexpr int kInputTensorY = 2;
+constexpr int kOutputTensor = 0;
+
+template <typename T>
+void CallSelect(const circle::Tensor *input_condition, const circle::Tensor *input_x,
+                const circle::Tensor *input_y, const circle::Tensor *output, bool need_broadcast,
+                RuntimeGraph *runtime_graph)
+{
+  using Func = decltype(luci_interpreter_pal::Select<bool, T>) *;
+  Func select_func;
+  if (need_broadcast)
+  {
+    assert(false && "Broadcast not supported now");
+  }
+  else
+  {
+    select_func = luci_interpreter_pal::Select<bool, T>;
+  }
+
+  select_func(kernels::getTensorRuntimeShape(input_condition, runtime_graph),
+              kernels::getTensorData<bool>(runtime_graph->getDataByTensor(input_condition)),
+              kernels::getTensorRuntimeShape(input_x, runtime_graph),
+              kernels::getTensorData<T>(runtime_graph->getDataByTensor(input_x)),
+              kernels::getTensorRuntimeShape(input_y, runtime_graph),
+              kernels::getTensorData<T>(runtime_graph->getDataByTensor(input_y)),
+              kernels::getTensorRuntimeShape(output, runtime_graph),
+              kernels::getTensorData<T>(runtime_graph->getDataByTensor(output)));
+}
+
+} // namespace
+
+void configure_kernel_CircleSelectV2(const circle::Operator *cur_op,
+                                     BaseRuntimeGraph *runtime_graph)
+{
+  const auto input_cond_index = cur_op->inputs()->operator[](kInputTensorCondition);
+  const auto input_x_index = cur_op->inputs()->operator[](kInputTensorX);
+  const auto input_y_index = cur_op->inputs()->operator[](kInputTensorY);
+  const auto output_index = cur_op->outputs()->operator[](kOutputTensor);
+
+  assert(input_cond_index != -1);
+  assert(input_x_index != -1);
+  assert(input_y_index != -1);
+  assert(output_index != -1);
+
+  const auto input_cond = runtime_graph->getCircleTensorByIndex(input_cond_index);
+  const auto input_x = runtime_graph->getCircleTensorByIndex(input_x_index);
+  const auto input_y = runtime_graph->getCircleTensorByIndex(input_y_index);
+  const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+  assert(input_cond != nullptr);
+  assert(input_x != nullptr);
+  assert(input_y != nullptr);
+
+  // Input condition should be bool
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(input_cond) == DataType::BOOL);
+
+  // X, Y and Output should be the same type
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(input_x) == Tensor::element_type(input_y));
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(input_x) == Tensor::element_type(output));
+
+  bool possible_mixed_scaler =
+    Tensor::num_elements(input_cond) == 1 && Tensor::num_elements(input_x) == 1 &&
+    Tensor::num_elements(input_y) == 1 && Tensor::num_elements(output) == 1;
+
+  bool same_shape = Tensor::num_elements(input_cond) == Tensor::num_elements(input_x) &&
+                    Tensor::num_elements(input_x) == Tensor::num_elements(input_y);
+
+  // Broadcast not supported now
+  if (not same_shape and not possible_mixed_scaler)
+  {
+    LUCI_INTERPRETER_CHECK(false);
+  }
+}
+
+void execute_kernel_CircleSelectV2(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  const auto input_cond_index = cur_op->inputs()->operator[](kInputTensorCondition);
+  const auto input_x_index = cur_op->inputs()->operator[](kInputTensorX);
+  const auto input_y_index = cur_op->inputs()->operator[](kInputTensorY);
+  const auto output_index = cur_op->outputs()->operator[](kOutputTensor);
+
+  assert(input_cond_index != -1);
+  assert(input_x_index != -1);
+  assert(input_y_index != -1);
+  assert(output_index != -1);
+
+  const auto input_cond = runtime_graph->getCircleTensorByIndex(input_cond_index);
+  const auto input_x = runtime_graph->getCircleTensorByIndex(input_x_index);
+  const auto input_y = runtime_graph->getCircleTensorByIndex(input_y_index);
+  const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+  assert(input_cond != nullptr);
+  assert(input_x != nullptr);
+  assert(input_y != nullptr);
+
+  bool possible_mixed_scaler =
+    Tensor::num_elements(input_cond) == 1 && Tensor::num_elements(input_x) == 1 &&
+    Tensor::num_elements(input_y) == 1 && Tensor::num_elements(output) == 1;
+
+  bool same_shape = Tensor::num_elements(input_cond) == Tensor::num_elements(input_x) &&
+                    Tensor::num_elements(input_x) == Tensor::num_elements(input_y);
+  bool is_broadcast = false;
+  if (not possible_mixed_scaler and not same_shape)
+    is_broadcast = true;
+
+  const auto type = Tensor::element_type(input_x);
+  switch (type)
+  {
+#ifndef DIS_FLOAT
+    case DataType::FLOAT32:
+      CallSelect<float>(input_cond, input_x, input_y, output, is_broadcast, runtime_graph);
+      break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/SelectV2.test.cpp b/onert-micro/luci-interpreter/src/kernels/SelectV2.test.cpp
new file mode 100644 (file)
index 0000000..851cf5c
--- /dev/null
@@ -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 "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/select_v2/FloatSelectV2Kernel.h"
+#include "luci_interpreter/test_models/select_v2/NegSelectV2Kernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class SelectV2Test : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T>
+std::vector<T> checkSelectV2Kernel(test_kernel::TestDataSelectV2Base<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 input data
+  {
+    auto *input_tensor_data_1 =
+      reinterpret_cast<bool *>(main_runtime_graph->configureGraphInput(0));
+    std::copy(test_data_base->get_cond_input().begin(), test_data_base->get_cond_input().end(),
+              input_tensor_data_1);
+
+    auto *input_tensor_data_2 = 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_2);
+
+    auto *input_tensor_data_3 = 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_3);
+  }
+
+  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(SelectV2Test, Float_P)
+{
+  test_kernel::TestDataFloatSelectV2 test_data_kernel;
+  std::vector<float> output_data_vector = checkSelectV2Kernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SelectV2Test, Input_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputMismatchSelectV2Kernel 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/Sin.cpp b/onert-micro/luci-interpreter/src/kernels/Sin.cpp
new file mode 100644 (file)
index 0000000..aa42f3d
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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 "Builders.h"
+#include "kernels/Utils.h"
+#include "SISOKernel.h"
+
+#include "PALSin.h"
+
+namespace luci_interpreter
+{
+
+void configure_kernel_CircleSin(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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 execute_kernel_CircleSin(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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:
+    {
+      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::Sin(flat_size, input_data_float, output_data_float);
+      break;
+    }
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
+  }
+
+  if (is_inplace)
+    runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
+}
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Sin.test.cpp b/onert-micro/luci-interpreter/src/kernels/Sin.test.cpp
new file mode 100644 (file)
index 0000000..5991c1a
--- /dev/null
@@ -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/sin/FloatSinKernel.h"
+#include "luci_interpreter/test_models/sin/NegSinKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class SinTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T> std::vector<T> checkSinKernel(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(SinTest, Float_P)
+{
+  test_kernel::TestDataFloatSin test_data_kernel;
+  std::vector<float> output_data_vector = checkSinKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SinTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchSinKernel 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
index 4647cc9..5126e66 100644 (file)
@@ -33,12 +33,91 @@ 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);
 
-  luci_interpreter_pal::Softmax(options->beta(), kernels::getTensorShape(input),
-                                kernels::getTensorData<float>(input_data),
+  const float beta = options->beta();
+
+  const auto trailing_dim = Tensor::num_dims(input) - 1;
+
+  int flat_size = 1;
+  for (int i = 0; i < Tensor::num_dims(input); ++i)
+  {
+    flat_size *= (i == trailing_dim) ? 1 : Tensor::dim(input, i);
+  }
+
+  luci_interpreter_pal::SoftmaxParams params;
+  params.beta = beta;
+  params.num_rows = flat_size;
+  params.row_size = std::min(Tensor::dim(input, trailing_dim), Tensor::dim(output, trailing_dim));
+
+  luci_interpreter_pal::Softmax(params, kernels::getTensorData<float>(input_data),
                                 kernels::getTensorData<float>(output_data));
 }
 #endif // DIS_FLOAT
 
+#ifndef DIS_QUANT
+void preprocessSoftmaxScaling(double beta, double input_scale, int input_integer_bits,
+                              int32_t *quantized_multiplier, int *left_shift)
+{
+  const double max_real_multiplier = (1LL << 31) - 1.0;
+  const double input_beta_real_multiplier =
+    std::min<double>(beta * input_scale * (1 << (31 - input_integer_bits)), max_real_multiplier);
+
+  kernels::quantizeMultiplier(input_beta_real_multiplier, quantized_multiplier, left_shift);
+}
+
+void evalQuantize(const circle::Tensor *input, const circle::Tensor *output,
+                  const circle::SoftmaxOptions *options, BaseRuntimeGraph *runtime_graph)
+{
+  static const int kScaledDiffIntegerBits = 5;
+
+  const float beta = options->beta();
+
+  const auto trailing_dim = Tensor::num_dims(input) - 1;
+
+  int flat_size = 1;
+  for (int i = 0; i < Tensor::num_dims(input); ++i)
+  {
+    flat_size *= (i == trailing_dim) ? 1 : Tensor::dim(input, i);
+  }
+
+  luci_interpreter_pal::SoftmaxParams params;
+  params.beta = beta;
+  params.num_rows = flat_size;
+  params.row_size = std::min(Tensor::dim(input, trailing_dim), Tensor::dim(output, trailing_dim));
+
+  if (Tensor::element_type(input) == DataType::S16)
+  {
+    int left_shift = 0;
+    double input_scale_beta_rescale =
+      static_cast<double>(Tensor::scale(input)) * static_cast<double>(beta) /
+      (10.0 / 65535.0); // scale the input_diff such that [-65535, 0]
+    // correspond to [-10.0, 0.0]
+    kernels::quantizeMultiplier(input_scale_beta_rescale, &params.input_multiplier, &left_shift);
+    params.input_left_shift = left_shift;
+    luci_interpreter_pal::Softmax(
+      params, kernels::getTensorData<int16_t>(runtime_graph->getDataByTensor(input)),
+      kernels::getTensorData<int16_t>(runtime_graph->getDataByTensor(output)));
+  }
+  else
+  {
+    int left_shift = 0;
+    preprocessSoftmaxScaling(static_cast<double>(params.beta),
+                             static_cast<double>(Tensor::scale(input)), kScaledDiffIntegerBits,
+                             &params.input_multiplier, &left_shift);
+    params.input_left_shift = left_shift;
+    params.diff_min =
+      -1.0 * kernels::calculateInputRadius(kScaledDiffIntegerBits, params.input_left_shift, 31);
+    if (Tensor::element_type(output) == DataType::S8)
+      luci_interpreter_pal::Softmax(
+        params, kernels::getTensorData<int8_t>(runtime_graph->getDataByTensor(input)),
+        kernels::getTensorData<int8_t>(runtime_graph->getDataByTensor(output)));
+    else if (Tensor::element_type(output) == DataType::S16)
+      luci_interpreter_pal::Softmax(
+        params, kernels::getTensorData<int8_t>(runtime_graph->getDataByTensor(input)),
+        kernels::getTensorData<int16_t>(runtime_graph->getDataByTensor(output)));
+  }
+}
+#endif // DIS_QUANT
+
 } // namespace
 
 void configure_kernel_CircleSoftmax(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
@@ -67,14 +146,20 @@ void execute_kernel_CircleSoftmax(const circle::Operator *cur_op, BaseRuntimeGra
   kernels::SISOKernel kernel(cur_op, runtime_graph);
 
   const auto *options = cur_op->builtin_options_as_SoftmaxOptions();
-
-  switch (Tensor::element_type(kernel.input()))
+  const auto input_type = Tensor::element_type(kernel.input());
+  switch (input_type)
   {
 #ifndef DIS_FLOAT
     case DataType::FLOAT32:
       evalFloat(kernel.input(), kernel.output(), options, runtime_graph);
       break;
 #endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case DataType::S8:
+    case DataType::S16:
+      evalQuantize(kernel.input(), kernel.output(), options, runtime_graph);
+      break;
+#endif
     default:
       assert(false && "Unsupported type.");
   }
index 0a5b447..59884e2 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/SpaceToBatchND.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "MISOKernel.h"
 
 #include "PALSpaceToBatchND.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
-namespace
-{
-
-const int kInputMinDimensionNum = 3;
-const int kInputMaxDimensionNum = 4;
-
-} // namespace
 
-SpaceToBatchND::SpaceToBatchND(const Tensor *input, const Tensor *block_shape,
-                               const Tensor *paddings, Tensor *output)
-  : Kernel({input, block_shape, paddings}, {output})
+void configure_kernel_CircleSpaceToBatchND(const circle::Operator *cur_op,
+                                           BaseRuntimeGraph *runtime_graph)
 {
-}
-
-void SpaceToBatchND::configure()
-{
-  const auto *block_shape_data = block_shape()->data<int32_t>();
-  const auto *paddings_data = paddings()->data<int32_t>();
-  LUCI_INTERPRETER_CHECK(input()->shape().num_dims() >= kInputMinDimensionNum);
-  LUCI_INTERPRETER_CHECK(input()->shape().num_dims() <= kInputMaxDimensionNum);
-  LUCI_INTERPRETER_CHECK(input()->element_type() == output()->element_type());
-
-  int spatial_dims_num = input()->shape().num_dims() - 2;
+  kernels::MISOKernel kernel(cur_op, runtime_graph);
 
-  LUCI_INTERPRETER_CHECK(block_shape()->shape().num_dims() == 1);
-  LUCI_INTERPRETER_CHECK(block_shape()->shape().dim(0) == spatial_dims_num);
-
-  LUCI_INTERPRETER_CHECK(paddings()->shape().num_dims() == 2);
-  LUCI_INTERPRETER_CHECK(paddings()->shape().dim(0) == spatial_dims_num);
-  LUCI_INTERPRETER_CHECK(paddings()->shape().dim(1) == 2);
-
-  Shape output_shape = Shape(input()->shape().num_dims());
-  int output_batch_size = input()->shape().dim(0);
-  for (int i = 0; i < spatial_dims_num; ++i)
-  {
-    int final_dim_size =
-      (input()->shape().dim(i + 1) + paddings_data[i * 2] + paddings_data[i * 2 + 1]);
-    LUCI_INTERPRETER_CHECK(final_dim_size % block_shape_data[i] == 0);
-    output_shape.dim(i + 1) = final_dim_size / block_shape_data[i];
-    output_batch_size = output_batch_size * block_shape_data[i];
-  }
-  output_shape.dim(0) = output_batch_size;
-  output_shape.dim(input()->shape().num_dims() - 1) =
-    input()->shape().dim(input()->shape().num_dims() - 1);
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(output_shape);
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+                         Tensor::element_type(kernel.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input3()) == DataType::S32);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.output()) >= 3);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) >= 3);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.output()) <= 4);
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(kernel.input1()) <= 4);
 }
 
-void SpaceToBatchND::execute() const
+void execute_kernel_CircleSpaceToBatchND(const circle::Operator *cur_op,
+                                         BaseRuntimeGraph *runtime_graph)
 {
-  switch (input()->element_type())
+  kernels::MISOKernel kernel(cur_op, runtime_graph);
+  const int32_t pad_value = 0;
+  switch (Tensor::element_type(kernel.input1()))
   {
-    tflite::SpaceToBatchParams op_params;
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      op_params.output_offset = 0;
+    {
       luci_interpreter_pal::SpaceToBatchND(
-        op_params, getTensorShape(input()), getTensorData<float>(input()),
-        getTensorShape(block_shape()), getTensorData<int32_t>(block_shape()),
-        getTensorShape(paddings()), getTensorData<int32_t>(paddings()), getTensorShape(output()),
-        getTensorData<float>(output()));
-      break;
-    case DataType::U8:
-      op_params.output_offset = output()->zero_point();
-      luci_interpreter_pal::SpaceToBatchND(
-        op_params, getTensorShape(input()), getTensorData<uint8_t>(input()),
-        getTensorShape(block_shape()), getTensorData<int32_t>(block_shape()),
-        getTensorShape(paddings()), getTensorData<int32_t>(paddings()), getTensorShape(output()),
-        getTensorData<uint8_t>(output()));
+        pad_value, kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph),
+        kernels::getTensorData<float>(runtime_graph->getDataByTensor(kernel.input1())),
+        kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph),
+        kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(kernel.input2())),
+        kernels::getTensorRuntimeShape(kernel.input3(), runtime_graph),
+        kernels::getTensorData<int32_t>(runtime_graph->getConstDataByTensor(kernel.input3())),
+        kernels::getTensorRuntimeShape(kernel.output(), runtime_graph),
+        kernels::getTensorData<float>(runtime_graph->getDataByTensor(kernel.output())));
       break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
 }
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.h b/onert-micro/luci-interpreter/src/kernels/SpaceToBatchND.h
deleted file mode 100644 (file)
index 0893003..0000000
+++ /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.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_SPACETOBATCHND_H
-#define LUCI_INTERPRETER_KERNELS_SPACETOBATCHND_H
-
-#include "core/Kernel.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class SpaceToBatchND : public Kernel
-{
-public:
-  SpaceToBatchND(const Tensor *input, const Tensor *block_shape, const Tensor *paddings,
-                 Tensor *output);
-
-  const Tensor *input() const { return _inputs[0]; }
-  const Tensor *block_shape() const { return _inputs[1]; }
-  const Tensor *paddings() 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_SPACETOBATCHND_H
index 3a8b0a8..88e93c5 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/SpaceToBatchND.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/space_to_batch_nd/FloatSpaceToBatchNDKernel.h"
+#include "luci_interpreter/test_models/space_to_batch_nd/NegSpaceToBatchNDKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
 using namespace testing;
 
+class SpaceToBatchNDTest : public ::testing::Test
+{
+  // Do nothing
+};
+
 template <typename T>
-void Check(std::initializer_list<int32_t> input_shape,
-           std::initializer_list<int32_t> block_shape_shape,
-           std::initializer_list<int32_t> paddings_shape,
-           std::initializer_list<int32_t> output_shape, std::initializer_list<float> input_data,
-           std::initializer_list<int32_t> block_shape_data,
-           std::initializer_list<int32_t> paddings_data, std::initializer_list<float> output_data)
+std::vector<T> checkSpaceToBatchNDKernel(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 block_shape_tensor =
-    makeInputTensor<DataType::S32>(block_shape_shape, block_shape_data, memory_manager.get());
-  Tensor paddings_tensor =
-    makeInputTensor<DataType::S32>(paddings_shape, paddings_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(element_type);
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  SpaceToBatchND kernel(&input_tensor, &block_shape_tensor, &paddings_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));
-  EXPECT_THAT(extractTensorShape(output_tensor), output_shape);
-}
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-template <>
-void Check<uint8_t>(
-  std::initializer_list<int32_t> input_shape, std::initializer_list<int32_t> block_shape_shape,
-  std::initializer_list<int32_t> paddings_shape, std::initializer_list<int32_t> output_shape,
-  std::initializer_list<float> input_data, std::initializer_list<int32_t> block_shape_data,
-  std::initializer_list<int32_t> paddings_data, std::initializer_list<float> output_data)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  // 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> 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 block_shape_tensor =
-    makeInputTensor<DataType::S32>(block_shape_shape, block_shape_data, memory_manager.get());
-  Tensor paddings_tensor =
-    makeInputTensor<DataType::S32>(paddings_shape, paddings_data, memory_manager.get());
-  Tensor output_tensor =
-    makeOutputTensor(DataType::U8, input_quant_param.first, input_quant_param.second);
+  runtime_module.execute();
 
-  SpaceToBatchND kernel(&input_tensor, &block_shape_tensor, &paddings_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  EXPECT_THAT(dequantizeTensorData(output_tensor),
-              FloatArrayNear(output_data, output_tensor.scale()));
-  EXPECT_THAT(extractTensorShape(output_tensor), 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 SpaceToBatchNDTest : public ::testing::Test
+TEST_F(SpaceToBatchNDTest, Float_P)
 {
-};
-
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(SpaceToBatchNDTest, DataTypes);
-
-TYPED_TEST(SpaceToBatchNDTest, Simple)
-{
-  Check<TypeParam>(/*input_shape=*/{1, 5, 2, 1}, /*block_shape_shape=*/{2},
-                   /*paddings_shape=*/{2, 2},
-                   /*output_shape=*/{6, 2, 2, 1},
-                   /*input_data=*/{-1.0, 0.2, -0.3, 0.4, -0.5, 0.6, -0.7, 0.8, -0.9, 1.0},
-                   /*block_shape_data=*/{3, 2}, /*paddings_data=*/{1, 0, 2, 0},
-                   /*output_data=*/{0, 0,   0, -0.5, 0, 0,    0, 0.6,  0, -1.0, 0, -0.7,
-                                    0, 0.2, 0, 0.8,  0, -0.3, 0, -0.9, 0, 0.4,  0, 1.0});
+  test_kernel::TestDataFloatSpaceToBatchND test_data_kernel;
+  std::vector<float> output_data_vector = checkSpaceToBatchNDKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST(SpaceToBatchNDTest, Invalid_Shape_NEG)
+TEST_F(SpaceToBatchNDTest, Input_output_type_mismatch_NEG)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
-  Tensor input_tensor = makeInputTensor<DataType::FLOAT32>(
-    {1, 3, 3, 1}, {1, 2, 3, 4, 5, 6, 7, 8, 9}, memory_manager.get());
-  Tensor block_shape_tensor = makeInputTensor<DataType::S32>({2}, {2, 2}, memory_manager.get());
-  Tensor paddings_tensor =
-    makeInputTensor<DataType::S32>({2, 2}, {0, 0, 0, 0}, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  SpaceToBatchND kernel(&input_tensor, &block_shape_tensor, &paddings_tensor, &output_tensor);
-  EXPECT_ANY_THROW(kernel.configure());
+  test_kernel::NegTestDataInputOutputTypeMismatchSpaceToBatchNDKernel 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
index 06cc5fa..cef8864 100644 (file)
  * limitations under the License.
  */
 
-#include "SpaceToDepth.h"
-#include "Utils.h"
+#include "Builders.h"
+#include "kernels/Utils.h"
+#include "SISOKernel.h"
+
 #include "PALSpaceToDepth.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 
-SpaceToDepth::SpaceToDepth(const Tensor *input, Tensor *output, const SpaceToDepthParams &params)
-  : KernelWithParams<SpaceToDepthParams>({input}, {output}, params)
+void configure_kernel_CircleSpaceToDepth(const circle::Operator *cur_op,
+                                         BaseRuntimeGraph *runtime_graph)
 {
-}
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-void SpaceToDepth::configure()
-{
-  assert(input()->shape().num_dims() == 4);
-  assert(output()->element_type() == DataType::FLOAT32 ||
-         output()->element_type() == DataType::U8 || output()->element_type() == DataType::S8 ||
-         output()->element_type() == DataType::S32 || output()->element_type() == DataType::S64);
-  assert(input()->element_type() == output()->element_type());
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) ==
+                         Tensor::element_type(kernel.output()));
+
+  const auto *options = cur_op->builtin_options_as_SpaceToDepthOptions();
 
-  const int block_size = params().block_size;
-  const int32_t input_height = input()->shape().dim(1);
-  const int32_t input_width = input()->shape().dim(2);
-  int32_t output_height = input_height / block_size;
-  int32_t output_width = input_width / block_size;
+  const int32_t block_size = options->block_size();
+  LUCI_INTERPRETER_CHECK(block_size > 0);
 
-  assert(input_height == output_height * block_size);
-  assert(input_width == output_width * block_size);
+  constexpr int kHeightRank = 1;
+  constexpr int kWidthRank = 2;
+  constexpr int kDepthRank = 3;
 
-  Shape output_shape(4);
-  output_shape.dim(0) = input()->shape().dim(0);
-  output_shape.dim(1) = output_height;
-  output_shape.dim(2) = output_width;
-  output_shape.dim(3) = input()->shape().dim(3) * block_size * block_size;
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(output_shape);
+  const int input_height = Tensor::dim(kernel.input(), kHeightRank);
+  const int input_width = Tensor::dim(kernel.input(), kWidthRank);
+  int output_height = input_height / block_size;
+  int output_width = input_width / block_size;
+
+  LUCI_INTERPRETER_CHECK(input_height == output_height * block_size);
+  LUCI_INTERPRETER_CHECK(input_width == output_width * block_size);
 }
 
-void SpaceToDepth::execute() const
+void execute_kernel_CircleSpaceToDepth(const circle::Operator *cur_op,
+                                       BaseRuntimeGraph *runtime_graph)
 {
-  tflite::SpaceToDepthParams op_params{};
-  op_params.block_size = params().block_size;
-  switch (input()->element_type())
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
+
+  const auto *options = cur_op->builtin_options_as_SpaceToDepthOptions();
+  const int32_t block_size = options->block_size();
+
+  switch (Tensor::element_type(kernel.input()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      luci_interpreter_pal::SpaceToDepth(op_params, getTensorShape(input()),
-                                         getTensorData<float>(input()), getTensorShape(output()),
-                                         getTensorData<float>(output()));
-      break;
-    case DataType::U8:
-      luci_interpreter_pal::SpaceToDepth(op_params, getTensorShape(input()),
-                                         getTensorData<uint8_t>(input()), getTensorShape(output()),
-                                         getTensorData<uint8_t>(output()));
+    {
+      assert(block_size != 0);
+      luci_interpreter_pal::SpaceToDepth(
+        block_size, kernels::getTensorRuntimeShape(kernel.input(), runtime_graph),
+        kernels::getTensorData<float>(runtime_graph->getDataByTensor(kernel.input())),
+        kernels::getTensorRuntimeShape(kernel.output(), runtime_graph),
+        kernels::getTensorData<float>(runtime_graph->getDataByTensor(kernel.output())));
       break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
 }
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.h b/onert-micro/luci-interpreter/src/kernels/SpaceToDepth.h
deleted file mode 100644 (file)
index e66316b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_SPACETODEPTH_H
-#define LUCI_INTERPRETER_KERNELS_SPACETODEPTH_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-#include <vector>
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class SpaceToDepth : public KernelWithParams<SpaceToDepthParams>
-{
-public:
-  SpaceToDepth(const Tensor *input, Tensor *output, const SpaceToDepthParams &params);
-
-  const Tensor *input() const { return _inputs[0]; }
-  Tensor *output() const { return _outputs[0]; }
-
-  void configure() override;
-  void execute() const override;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_SPACETODEPTH_H
index 4af4886..18a0350 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/SpaceToDepth.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/space_to_depth/FloatSpaceToDepthKernel.h"
+#include "luci_interpreter/test_models/space_to_depth/NegSpaceToDepthKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
 using namespace testing;
 
-template <typename T> class SpaceToDepthTest : public ::testing::Test
+class SpaceToDepthTest : public ::testing::Test
 {
+  // Do nothing
 };
 
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(SpaceToDepthTest, DataTypes);
-
-TYPED_TEST(SpaceToDepthTest, SimpleCase)
+template <typename T>
+std::vector<T> checkSpaceToDepthKernel(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<TypeParam>();
-  std::vector<TypeParam> input_data{1, 5, 6, 7, 2, 3, 4, 8};
-  Shape input_shape{1, 2, 2, 2};
-  Tensor input_tensor =
-    makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
-  std::vector<TypeParam> output_data{1, 5, 6, 7, 2, 3, 4, 8};
-  std::vector<int32_t> output_shape{1, 1, 1, 8};
-  Tensor output_tensor = makeOutputTensor(element_type);
+  // 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);
 
-  SpaceToDepthParams params{};
-  params.block_size = 2;
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-  SpaceToDepth kernel(&input_tensor, &output_tensor, params);
-  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(extractTensorData<TypeParam>(output_tensor),
-              ::testing::ElementsAreArray(output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+  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(SpaceToDepthTest, Float_P)
+{
+  test_kernel::TestDataFloatSpaceToDepth test_data_kernel;
+  std::vector<float> output_data_vector = checkSpaceToDepthKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SpaceToDepthTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchSpaceToDepthKernel 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
index eed50df..3e95160 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Sqrt.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "SISOKernel.h"
 
-#include <cmath>
+#include "PALSqrt.h"
 
 namespace luci_interpreter
 {
 
-namespace kernels
+void configure_kernel_CircleSqrt(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-Sqrt::Sqrt(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
-
-void Sqrt::configure()
-{
-  if (input()->element_type() != output()->element_type())
-  {
-    assert(false && "Input/output tensor data type mismatch.");
-  }
-  // 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 Sqrt::execute() const
+void execute_kernel_CircleSqrt(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();
-      break;
+    {
+      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::Sqrt(flat_size, input_data_float, output_data_float);
+      break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
-}
 
-void Sqrt::evalFloat() const
-{
-  auto in = getTensorData<float>(input());
-  auto out = getTensorData<float>(output());
-  auto size = getTensorShape(input()).FlatSize();
-  for (auto i = in; i != in + size; ++i)
-  {
-    *out = std::sqrt(*i);
-    ++out;
-  }
+  if (is_inplace)
+    runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
 }
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Sqrt.h b/onert-micro/luci-interpreter/src/kernels/Sqrt.h
deleted file mode 100644 (file)
index 4034655..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_SQRT_H
-#define LUCI_INTERPRETER_KERNELS_SQRT_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Sqrt : public Kernel
-{
-public:
-  Sqrt(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_SQRT_H
index 96835fb..27b1c50 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Sqrt.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/sqrt/FloatSqrtKernel.h"
+#include "luci_interpreter/test_models/sqrt/NegSqrtKernel.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 SqrtTest : public ::testing::Test
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  // Do nothing
+};
 
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+template <typename T> std::vector<T> checkSqrtKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  Sqrt kernel(&input_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<float>(output_tensor), FloatArrayNear(output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
-}
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-TEST(SqrtTest, SimpleSqrt)
-{
-  Check(
-    /*input_shape=*/{1, 2, 4, 1}, /*output_shape=*/{1, 2, 4, 1},
-    /*input_data=*/
-    {
-      0, 8, 2, 4,    //
-      3, 7, 10, 0.3, //
-    },
-    /*output_data=*/
-    {
-      0.0, 2.8284271, 1.4142136, 2,                //
-      1.7320508, 2.6457513, 3.1622777, 0.54772256, //
-    });
-}
+  // 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(SqrtTest, Input_Output_Type_NEG)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  runtime_module.execute();
 
-  Tensor input_tensor = makeInputTensor<DataType::FLOAT32>({1}, {1.f}, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S32);
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  Sqrt kernel(&input_tensor, &output_tensor);
-  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(SqrtTest, Invalid_Input_Type_NEG)
+TEST_F(SqrtTest, Float_P)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
-  Tensor input_tensor = makeInputTensor<DataType::S64>({1}, {1}, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S64);
+  test_kernel::TestDataFloatSqrt test_data_kernel;
+  std::vector<float> output_data_vector = checkSqrtKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
 
-  Sqrt kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  EXPECT_ANY_THROW(kernel.execute());
+TEST_F(SqrtTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchSqrtKernel 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
index 6386b91..71f3f8a 100644 (file)
@@ -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.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#include "kernels/Square.h"
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "SISOKernel.h"
 
-#include <cmath>
+#include "PALSquare.h"
 
 namespace luci_interpreter
 {
-
-namespace kernels
+void configure_kernel_CircleSquare(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-Square::Square(const Tensor *input, Tensor *output) : Kernel({input}, {output}) {}
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input()) ==
+                         Tensor::element_type(kernel.output()));
 
-void Square::configure()
-{
-  if (input()->element_type() != output()->element_type())
+  // check that input and output dimensions are equal
+  int N = Tensor::num_dims(kernel.input());
+  LUCI_INTERPRETER_CHECK(N == Tensor::num_dims(kernel.output()));
+
+  // check that sizes of all dimensions are equal
+  for (int i = 0; i < N; ++i)
   {
-    assert(false && "Input/output tensor data type mismatch.");
+    LUCI_INTERPRETER_CHECK(kernels::getTensorShape(kernel.input()).dims(i) ==
+                           kernels::getTensorShape(kernel.output()).dims(i));
   }
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(input()->shape());
 }
 
-void Square::execute() const
+void execute_kernel_CircleSquare(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();
-      break;
+    {
+      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::Square(flat_size, input_data_float, output_data_float);
+      break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
-}
 
-void Square::evalFloat() const
-{
-  auto in = getTensorData<float>(input());
-  auto out = getTensorData<float>(output());
-  auto size = getTensorShape(input()).FlatSize();
-  for (auto i = in; i != in + size; ++i)
-  {
-    *out = (*i) * (*i);
-    ++out;
-  }
+  if (is_inplace)
+    runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
 }
 
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Square.h b/onert-micro/luci-interpreter/src/kernels/Square.h
deleted file mode 100644 (file)
index 73ed5a7..0000000
+++ /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.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_SQUARE_H
-#define LUCI_INTERPRETER_KERNELS_SQUARE_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Square : public Kernel
-{
-public:
-  Square(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_SQUARE_H
index 51662de..e09332b 100644 (file)
@@ -1,6 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2017 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.
  * limitations under the License.
  */
 
-#include "kernels/Square.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/square/FloatSquareKernel.h"
+#include "luci_interpreter/test_models/square/NegSquareKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
 using namespace testing;
 
-TEST(SquareTest, Float)
+class SquareTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T> std::vector<T> checkSquareKernel(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;
+
+  // 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);
+  }
 
-  Shape input_shape{3, 1, 2};
-  std::vector<float> input_data1{1.0, 0.0, -1.0, 11.0, -2.0, -1.44};
-  Tensor input_tensor =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data1, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
+  runtime_module.execute();
 
-  Square kernel(&input_tensor, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  std::vector<float> ref_output_data{1.0, 0.0, 1.0, 121.0, 4.0, 2.0736};
-  EXPECT_THAT(extractTensorData<float>(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(SquareTest, Float_P)
+{
+  test_kernel::TestDataFloatSquare test_data_kernel;
+  std::vector<float> output_data_vector = checkSquareKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SquareTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchSquareKernel 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
index 27f395a..d7ad16b 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/SquaredDifference.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "TISOKernel.h"
 
-#include "kernels/BinaryOpCommon.h"
+#include "PALSquaredDifference.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 
-SquaredDifference::SquaredDifference(const Tensor *input1, const Tensor *input2, Tensor *output)
-  : Kernel({input1, input2}, {output})
+void configure_kernel_CircleSquaredDifference(const circle::Operator *cur_op,
+                                              BaseRuntimeGraph *runtime_graph)
 {
-}
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
 
-void SquaredDifference::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.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input1()) ==
+                         Tensor::element_type(kernel.input2()));
+  LUCI_INTERPRETER_CHECK(Tensor::num_elements(kernel.input1()) ==
+                         Tensor::num_elements(kernel.output()));
+  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.output()));
 }
 
-void SquaredDifference::execute() const
+void execute_kernel_CircleSquaredDifference(const circle::Operator *cur_op,
+                                            BaseRuntimeGraph *runtime_graph)
 {
-  switch (input1()->element_type())
+  kernels::TISOKernel kernel(cur_op, runtime_graph);
+
+  const auto *input_data_1 = runtime_graph->getDataByTensor(kernel.input1());
+  const auto *input_data_2 = runtime_graph->getDataByTensor(kernel.input2());
+  assert(input_data_1);
+  assert(input_data_2);
+
+  auto *output_data = runtime_graph->getDataByTensor(kernel.output());
+
+  switch (Tensor::element_type(kernel.input1()))
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      evalSquaredDifference<float>();
+    {
+      const float *input_data_1_float = kernels::getTensorData<float>(input_data_1);
+      const float *input_data_2_float = kernels::getTensorData<float>(input_data_2);
+      float *output_data_float = kernels::getTensorData<float>(output_data);
+
+      assert(output_data_float);
+
+      const int flat_size =
+        kernels::getTensorRuntimeShape(kernel.input1(), runtime_graph).flatSize();
+
+      luci_interpreter_pal::SquaredDifference(flat_size, input_data_1_float, input_data_2_float,
+                                              output_data_float);
       break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
 }
-
-template <typename T> inline void SquaredDifference::evalSquaredDifference() const
-{
-  BinaryOpBroadcastSlow(getTensorShape(input1()), getTensorData<T>(input1()),
-                        getTensorShape(input2()), getTensorData<T>(input2()),
-                        getTensorShape(output()), getTensorData<T>(output()), [](T x, T y) {
-                          const T difference = x - y;
-                          return difference * difference;
-                        });
-}
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/SquaredDifference.h b/onert-micro/luci-interpreter/src/kernels/SquaredDifference.h
deleted file mode 100644 (file)
index 9327caf..0000000
+++ /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.
- */
-
-#ifndef LUCI_INTERPRETER_KERNELS_SQUAREDDIFFERENCE_H
-#define LUCI_INTERPRETER_KERNELS_SQUAREDDIFFERENCE_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class SquaredDifference : public Kernel
-{
-public:
-  SquaredDifference(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:
-  template <typename T> inline void evalSquaredDifference() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_SQUAREDDIFFERENCE_H
index 2819c01..e45e675 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/SquaredDifference.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/squared_difference/FloatSquaredDifferenceKernel.h"
+#include "luci_interpreter/test_models/squared_difference/NegSquaredDifferenceKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
 using namespace testing;
 
-TEST(SquaredDifferenceTest, Float)
+class SquaredDifferenceTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T>
+std::vector<T> checkSquaredDifferenceKernel(test_kernel::TestDataBase<T> *test_data_base)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
-  Shape input_shape{3, 1, 2};
-  std::vector<float> input_data1{1.0, 0.0, -1.0, 11.0, -2.0, -1.44};
-  std::vector<float> input_data2{-1.0, 0.0, 1.0, 12.0, -3.0, -1.43};
-  Tensor input_tensor1 =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data1, memory_manager.get());
-  Tensor input_tensor2 =
-    makeInputTensor<DataType::FLOAT32>(input_shape, input_data2, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  SquaredDifference kernel(&input_tensor1, &input_tensor2, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{4.0, 0.0, 4.0, 1.0, 1.0, 0.0001};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_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() == 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(SquaredDifferenceTest, FloatBroadcast)
+TEST_F(SquaredDifferenceTest, Float_P)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
-  Shape input_shape1{3, 1, 2};
-  Shape input_shape2{1};
-  std::vector<float> input_data1{1.0, 0.0, -1.0, 11.0, -2.0, -1.44};
-  std::vector<float> input_data2{1.0};
-  Tensor input_tensor1 =
-    makeInputTensor<DataType::FLOAT32>(input_shape1, input_data1, memory_manager.get());
-  Tensor input_tensor2 =
-    makeInputTensor<DataType::FLOAT32>(input_shape2, input_data2, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
-
-  SquaredDifference kernel(&input_tensor1, &input_tensor2, &output_tensor);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
-
-  std::vector<float> ref_output_data{0.0, 1.0, 4.0, 100.0, 9.0, 5.9536};
-  EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data));
+  test_kernel::TestDataFloatSquaredDifference test_data_kernel;
+  std::vector<float> output_data_vector = checkSquaredDifferenceKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SquaredDifferenceTest, Inputs_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputsTypeMismatchSquaredDifference 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
index 9736dce..581b587 100644 (file)
@@ -1,6 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2018 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.
  * limitations under the License.
  */
 
-#include "kernels/Squeeze.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
+#include "SISOKernel.h"
+
+#include <cassert>
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 
-Squeeze::Squeeze(const Tensor *input, Tensor *output, const SqueezeParams &params)
-  : KernelWithParams<SqueezeParams>({input}, {output}, params)
+void configure_kernel_CircleSqueeze(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-}
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
 
-void Squeeze::configure()
-{
-  int input_num_dims = input()->shape().num_dims();
-  int num_squeeze_dims = params().squeeze_dims.size();
+  assert(cur_op->inputs()->size() == 1);
+
+  const circle::Tensor *input = kernel.input();
+  const circle::Tensor *output = kernel.output();
+
+  assert(Tensor::num_elements(input) == Tensor::num_elements(output));
+
+  const uint8_t *input_data = runtime_graph->getDataByTensor(input);
+  uint8_t *output_data = runtime_graph->getDataByTensor(output);
+
+  int input_num_dims = kernels::getTensorShape(input).dimensionsCount();
+
+  // Get parameters
+  const circle::SqueezeOptions *op_params = cur_op->builtin_options_as_SqueezeOptions();
+
+  // Verification of the Squeeze parameters
+  int num_squeeze_dims = op_params->squeeze_dims()->size();
   assert(input_num_dims <= 8);
   bool should_squeeze[8] = {false};
   int num_squeezed_dims = 0;
@@ -40,7 +51,8 @@ void Squeeze::configure()
   {
     for (int idx = 0; idx < input_num_dims; ++idx)
     {
-      if (input()->shape().dim(idx) == 1)
+
+      if (kernels::getTensorShape(input).dims(idx) == 1)
       {
         should_squeeze[idx] = true;
         ++num_squeezed_dims;
@@ -51,35 +63,37 @@ void Squeeze::configure()
   {
     for (int idx = 0; idx < num_squeeze_dims; ++idx)
     {
-      int current = params().squeeze_dims[idx] < 0 ? params().squeeze_dims[idx] + input_num_dims
-                                                   : params().squeeze_dims[idx];
-      assert(current >= 0 && current < input_num_dims && input()->shape().dim(current) == 1);
+      int current = (*op_params->squeeze_dims())[idx] < 0
+                      ? (*op_params->squeeze_dims())[idx] + input_num_dims
+                      : (*op_params->squeeze_dims())[idx];
+      assert(current >= 0 && current < input_num_dims &&
+             kernels::getTensorShape(input).dims(current) == 1);
       if (!should_squeeze[current])
         ++num_squeezed_dims;
       should_squeeze[current] = true;
     }
   }
-  // TODO: enable it only if kernel with dynamic shapes
-  Shape output_shape(input_num_dims - num_squeezed_dims);
-  for (int in_idx = 0, out_idx = 0; in_idx < input_num_dims; ++in_idx)
-  {
-    if (!should_squeeze[in_idx])
-    {
-      output_shape.dim(out_idx++) = input()->shape().dim(in_idx);
-    }
-  }
-  output()->resize(output_shape);
 }
 
-void Squeeze::execute() const
+void execute_kernel_CircleSqueeze(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  assert(input()->shape().num_elements() == output()->shape().num_elements());
+  kernels::SISOKernel kernel(cur_op, runtime_graph);
+
+  assert(cur_op->inputs()->size() == 1);
+
+  const circle::Tensor *input = kernel.input();
+  const circle::Tensor *output = kernel.output();
+
+  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);
+
+  assert(Tensor::num_elements(input) == Tensor::num_elements(output));
 
-  const auto *input_data = input()->data<void>();
-  auto *output_data = output()->data<void>();
   std::memcpy(output_data, input_data,
-              getDataTypeSize(input()->element_type()) * input()->shape().num_elements());
+              getDataTypeSize(Tensor::element_type(input)) * Tensor::num_elements(input));
 }
 
-} // namespace kernels
 } // namespace luci_interpreter
index 1bc0b64..8aff882 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Squeeze.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "loader/ModuleLoader.h"
+#include "luci_interpreter/test_models/squeeze/FloatSqueezeKernel.h"
+#include "luci_interpreter/test_models/squeeze/NegSqueezeKernel.h"
 
 namespace luci_interpreter
 {
@@ -27,46 +28,82 @@ 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,
-           std::initializer_list<int32_t> squeeze_dims)
+class SqueezeTest : public ::testing::Test
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  // Do nothing
+};
+
+template <typename T> std::vector<T> checkKernel(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);
 
-  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);
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-  SqueezeParams params{};
-  params.squeeze_dims = squeeze_dims;
+  // 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);
+  }
 
-  Squeeze kernel(&input_tensor, &output_tensor, params);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  kernel.execute();
+  runtime_module.execute();
 
-  EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape));
+  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 <typename T> class SqueezeTest : public ::testing::Test
+TEST_F(SqueezeTest, Float_P)
 {
-};
+  test_kernel::TestDataFloatSqueeze test_data_kernel(false);
+  std::vector<float> output_data_vector = checkKernel(&test_data_kernel);
 
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(SqueezeTest, DataTypes);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
 
-TYPED_TEST(SqueezeTest, TotalTest)
+TEST_F(SqueezeTest, Float_No_Param_P)
 {
-  Check<TypeParam>(
-    /*input_shape=*/{1, 24, 1}, /*output_shape=*/{24},
-    /*input_data=*/{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12,
-                    13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24},
-    /*output_data=*/{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12,
-                     13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24},
-    {-1, 0});
+  test_kernel::TestDataFloatSqueeze test_data_kernel(true);
+  std::vector<float> output_data_vector = checkKernel(&test_data_kernel);
+
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SqueezeTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestIOMismatchParamFloatSqueeze 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(SqueezeTest, Wrong_Param_NEG)
+{
+  test_kernel::NegTestDataWrongParamFloatSqueeze 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
index 5eaed32..b820882 100644 (file)
@@ -55,6 +55,9 @@ void execute_kernel_CircleSub(const circle::Operator *cur_op, BaseRuntimeGraph *
   luci_interpreter::RuntimeShape input_shape2 =
     kernels::getTensorRuntimeShape(kernel.input2(), runtime_graph);
 
+  luci_interpreter::RuntimeShape output_shape =
+    kernels::getTensorRuntimeShape(kernel.output(), runtime_graph);
+
   bool is_inplace = runtime_graph->is_inplace_op(cur_op);
 
   switch (Tensor::element_type(kernel.input1()))
@@ -68,13 +71,15 @@ void execute_kernel_CircleSub(const circle::Operator *cur_op, BaseRuntimeGraph *
       if (is_inplace)
       {
         kernels::evalTISOInplaceKernel<float>(tiso_func, broadcast_tiso_func, &kernel, options,
-                                              std::move(input_shape1), std::move(input_shape2));
+                                              std::move(input_shape1), std::move(input_shape2),
+                                              std::move(output_shape));
       }
       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));
+                                       options, std::move(input_shape1), std::move(input_shape2),
+                                       std::move(output_shape));
       }
     }
     break;
@@ -88,13 +93,15 @@ void execute_kernel_CircleSub(const circle::Operator *cur_op, BaseRuntimeGraph *
       if (is_inplace)
       {
         kernels::evalTISOInplaceKernel<int64_t>(tiso_func, broadcast_tiso_func, &kernel, options,
-                                                std::move(input_shape1), std::move(input_shape2));
+                                                std::move(input_shape1), std::move(input_shape2),
+                                                std::move(output_shape));
       }
       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));
+                                         options, std::move(input_shape1), std::move(input_shape2),
+                                         std::move(output_shape));
       }
     }
     break;
@@ -107,13 +114,15 @@ void execute_kernel_CircleSub(const circle::Operator *cur_op, BaseRuntimeGraph *
       if (is_inplace)
       {
         kernels::evalTISOInplaceKernel<int32_t>(tiso_func, broadcast_tiso_func, &kernel, options,
-                                                std::move(input_shape1), std::move(input_shape2));
+                                                std::move(input_shape1), std::move(input_shape2),
+                                                std::move(output_shape));
       }
       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));
+                                         options, std::move(input_shape1), std::move(input_shape2),
+                                         std::move(output_shape));
       }
     }
     break;
index ff267b1..b3fe6af 100644 (file)
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+#include "BinaryOpCommon.h"
 #include "kernels/TestUtils.h"
 #include "luci_interpreter/test_models/sub/FloatSubKernel.h"
 #include "luci_interpreter/test_models/sub/IntSubKernel.h"
 
 #include "loader/ModuleLoader.h"
 
+#include "PALSub.h"
+
+#include <array>
+#include <numeric>
+
 namespace luci_interpreter
 {
 namespace
@@ -150,3 +156,70 @@ TEST_F(SubTest, No_quant_params_NEG)
 
 } // namespace
 } // namespace luci_interpreter
+
+namespace luci_interpreter
+{
+namespace
+{
+
+class PALSubTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(PALSubTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_kernel::TestDataFloatSub test_data_kernel(is_with_broadcast);
+
+    luci_interpreter_pal::ArithmeticParams params{};
+    kernels::fillArithmeticActivationRange<float>(params, kernels::Activation::NONE);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const auto num_elements = input1.size();
+    EXPECT_EQ(num_elements, input2.size());
+
+    std::vector<float> output = std::vector<float>(num_elements);
+    luci_interpreter_pal::Sub<float>(params, num_elements, input1.data(), input2.data(),
+                                     const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_kernel::TestDataFloatSub test_data_kernel(is_with_broadcast);
+
+    luci_interpreter_pal::ArithmeticParams params{};
+    kernels::fillArithmeticActivationRange<float>(params, kernels::Activation::NONE);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const int32_t shape[2] = {2, 5};
+    const int32_t shape_broadcast[2] = {2, 1};
+
+    assert(input1.size() ==
+           std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    assert(input2.size() == std::accumulate(std::begin(shape_broadcast), std::end(shape_broadcast),
+                                            1, std::multiplies<float>()));
+
+    std::vector<float> output = std::vector<float>(
+      std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    luci_interpreter_pal::BroadcastSub4DSlow<float>(
+      params, RuntimeShape{2, shape}, input1.data(), RuntimeShape{2, shape_broadcast},
+      input2.data(), RuntimeShape{2, shape}, const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, kernels::testing::FloatArrayNear(
+                          test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+} // namespace
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Sum.cpp b/onert-micro/luci-interpreter/src/kernels/Sum.cpp
new file mode 100644 (file)
index 0000000..a5cb82d
--- /dev/null
@@ -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.
+ */
+
+#include "Builders.h"
+#include "kernels/Utils.h"
+#include "TISOKernel.h"
+
+#include "PALReduceCommon.h"
+
+#include <cassert>
+
+namespace luci_interpreter
+{
+namespace
+{
+
+template <typename T>
+void sumGeneric(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(0), output_shape.flatSize(),
+    [](const float current, const float in) -> float { return in + current; });
+}
+
+} // namespace
+
+void configure_kernel_CircleSum(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.output()));
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(kernel.input2()) == DataType::S32);
+
+  const int32_t axis_value =
+    kernels::getTensorData<int>(runtime_graph->getConstDataByTensor(kernel.input2()))[0];
+  LUCI_INTERPRETER_CHECK(axis_value >= 0);
+}
+
+void execute_kernel_CircleSum(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:
+      sumGeneric<float>(&tiso_data, input, axis, output, options->keep_dims());
+      break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
+  }
+}
+
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Sum.test.cpp b/onert-micro/luci-interpreter/src/kernels/Sum.test.cpp
new file mode 100644 (file)
index 0000000..4a186be
--- /dev/null
@@ -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 "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/sum/FloatSumKernel.h"
+#include "luci_interpreter/test_models/sum/NegSumKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class SumTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T> std::vector<T> checkSumKernel(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(SumTest, Float_P)
+{
+  test_kernel::TestDataFloatSum test_data_kernel;
+  std::vector<float> output_data_vector = checkSumKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SumTest, Input_output_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputOutputTypeMismatchSumKernel 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
index f8483ea..82c6aef 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
- * Copyright 2017 The TensorFlow Authors. 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.
  * limitations under the License.
  */
 
-#include "kernels/TransposeConv.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
 
-#include <tensorflow/lite/kernels/internal/reference/transpose_conv.h>
+#include "PALTransposeConv.h"
 
 namespace luci_interpreter
 {
 
-namespace kernels
+namespace
 {
 
-TransposeConv::TransposeConv(const Tensor *output_shape, const Tensor *filter, const Tensor *input,
-                             const Tensor *bias, Tensor *output, Tensor *scratch_tensor,
-                             const TransposeConvParams &params)
-  : KernelWithParams<TransposeConvParams>({output_shape, filter, input, bias},
-                                          {output, scratch_tensor}, params)
+// For the TfLite transpose_conv implementation, input tensor 0 corresponds to
+// the OutputShapeTensor. However, since TFLM does not support dynamic tensors,
+// the TFLM implementation ignores input tensor 0 and the only inputs we care
+// about are kFilterTensor, kInputTensor and kBiasTensor.
+constexpr int kFilterTensor = 1;
+constexpr int kInputTensor = 2;
+constexpr int kBiasTensor = 3;
+constexpr int kOutputTensor = 0;
+
+// TODO: reduce code duplication with Conv
+int32_t compute_padding_h(const circle::Tensor *input, const circle::Tensor *filter,
+                          const circle::TransposeConvOptions *options)
 {
+  // Note: Dilation height and width are always 1 for transpose_conv
+  const int32_t input_height = Tensor::dim(input, 1);
+  const int32_t filter_height = Tensor::dim(filter, 1);
+  const int32_t output_height = kernels::computeOutputSize(
+    luci_padding(options->padding()), input_height, filter_height, options->stride_h(), 1);
+
+  const auto padding_height =
+    kernels::computePadding(options->stride_h(), 1, input_height, filter_height, output_height);
+  return padding_height;
 }
 
-TransposeConv::~TransposeConv()
+int32_t compute_padding_w(const circle::Tensor *input, const circle::Tensor *filter,
+                          const circle::TransposeConvOptions *options)
 {
-  // Define destructor here, to delete vector of qunatized multipliers properly
-}
+  // Note: Dilation height and width are always 1 for transpose_conv
+  const int32_t input_width = Tensor::dim(input, 2);
+  const int32_t filter_width = Tensor::dim(filter, 2);
+  const int32_t output_width = kernels::computeOutputSize(
+    luci_padding(options->padding()), input_width, filter_width, options->stride_w(), 1);
 
-void TransposeConv::configure()
-{
-  assert(output_shape()->shape().num_dims() == 1);
-  assert(input()->shape().num_dims() == 4);
-  assert(filter()->shape().num_dims() == 4);
-  assert(input()->element_type() == DataType::FLOAT32 || input()->element_type() == DataType::U8 ||
-         input()->element_type() == DataType::S16);
-  assert(input()->element_type() == output()->element_type());
-  assert(input()->shape().dim(3) == filter()->shape().dim(3));
-
-  const int num_dims = output_shape()->shape().dim(0);
-  Shape out_shape(num_dims);
-  const auto *shape_data = getTensorData<int32_t>(output_shape());
-  for (int i = 0; i < num_dims; i++)
-    out_shape.dim(i) = shape_data[i];
-  // TODO: enable it only if kernel with dynamic shapes
-  output()->resize(out_shape);
-
-  const int32_t filter_height = filter()->shape().dim(1);
-  const int32_t filter_width = filter()->shape().dim(2);
-  const int32_t output_height = out_shape.dim(1);
-  const int32_t output_width = out_shape.dim(2);
-
-  const int32_t unused_output_height =
-    computeOutputSize(params().padding, output_height, filter_height, params().stride_height, 1);
-  const int32_t unused_output_width =
-    computeOutputSize(params().padding, output_width, filter_width, params().stride_width, 1);
-
-  _padding_height =
-    computePadding(params().stride_height, 1, output_height, filter_height, unused_output_height);
-  _padding_width =
-    computePadding(params().stride_width, 1, output_width, filter_width, unused_output_width);
-
-  if (input()->element_type() == DataType::U8 || input()->element_type() == DataType::S16)
-  {
-    auto scratch_tensor = getOutputTensors()[1];
-    scratch_tensor->resize(output()->shape());
-    const std::vector<double> real_multipliers =
-      getQuantizedConvolutionMultiplers(input()->scale(), filter()->scales(), output()->scale());
+  const auto padding_width =
+    kernels::computePadding(options->stride_w(), 1, input_width, filter_width, output_width);
 
-    _quant_multipliers = quantizeMultipliers(real_multipliers);
-  }
-  else
-  {
-    auto scratch_tensor = getOutputTensors()[1];
-    scratch_tensor->set_allocatable(false);
-  }
+  return padding_width;
 }
 
-void TransposeConv::execute() const
-{
-  switch (input()->element_type())
-  {
-    case DataType::FLOAT32:
-      evalFloat();
-      break;
-    case DataType::U8:
-      if (filter()->scales().size() == 1)
-      {
-        evalQuantized();
-      }
-      else if (filter()->scales().size() > 1)
-      {
-        LUCI_INTERPRETER_CHECK(filter()->shape().num_dims() == 4);
-        LUCI_INTERPRETER_CHECK(filter()->scales().size() ==
-                               static_cast<size_t>(filter()->shape().dim(0)));
-        evalQuantizedPerChannel();
-      }
-      break;
-    case DataType::S16:
-      evalQuantizedS16();
-      break;
-    default:
-      assert(false && "Unsupported type.");
-  }
-}
+#ifndef DIS_FLOAT
 
-void TransposeConv::evalFloat() const
+void evalFloat(const circle::Tensor *input, const circle::Tensor *filter,
+               const circle::Tensor *bias, const circle::Tensor *output,
+               const circle::TransposeConvOptions *options, BaseRuntimeGraph *runtime_graph)
 {
-  tflite::ConvParams op_params{};
-  op_params.padding_type = tflite::PaddingType::kSame;
-  op_params.padding_values.height = _padding_height;
-  op_params.padding_values.width = _padding_width;
-  op_params.stride_height = params().stride_height;
-  op_params.stride_width = params().stride_width;
-  tflite::reference_ops::TransposeConv(op_params,                                                //
-                                       getTensorShape(input()), getTensorData<float>(input()),   //
-                                       getTensorShape(filter()), getTensorData<float>(filter()), //
-                                       getTensorShape(bias()), getTensorData<float>(bias()),     //
-                                       getTensorShape(output()), getTensorData<float>(output()), //
-                                       tflite::RuntimeShape(), nullptr);
+  float activation_min{};
+  float activation_max{};
+  kernels::calculateActivationRange(FusedActFunc::NONE, &activation_min, &activation_max);
+
+  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();
+  params.stride_width = options->stride_w();
+  params.dilation_height_factor = 1;
+  params.dilation_width_factor = 1;
+  params.float_activation_min = activation_min;
+  params.float_activation_max = activation_max;
+
+  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::TransposeConv(
+    params, kernels::getTensorRuntimeShape(input, runtime_graph),
+    kernels::getTensorData<float>(input_data),
+    kernels::getTensorRuntimeShape(filter, runtime_graph),
+    kernels::getTensorData<float>(filter_data), kernels::getTensorRuntimeShape(bias, runtime_graph),
+    kernels::getTensorData<float>(bias_data), kernels::getTensorRuntimeShape(output, runtime_graph),
+    kernels::getTensorData<float>(output_data));
 }
 
-void TransposeConv::evalQuantized() const
-{
-  tflite::ConvParams op_params{};
-  op_params.padding_type = tflite::PaddingType::kSame;
-  op_params.padding_values.height = _padding_height;
-  op_params.padding_values.width = _padding_width;
-  op_params.stride_height = params().stride_height;
-  op_params.stride_width = params().stride_width;
-  // The kernel expects input and filter zero points to be negated.
-  op_params.input_offset = -input()->zero_point();    // Note the '-'.
-  op_params.weights_offset = -filter()->zero_point(); // Note the '-'.
-  op_params.output_offset = output()->zero_point();
-  op_params.output_multiplier = _quant_multipliers[0].multiplier;
-  op_params.output_shift = _quant_multipliers[0].shift;
-  op_params.quantized_activation_min = std::numeric_limits<uint8_t>::min();
-  op_params.quantized_activation_max = std::numeric_limits<uint8_t>::max();
-
-  auto scratch_tensor = getOutputTensors()[1];
-
-  tflite::reference_ops::TransposeConv(
-    op_params,                                                  //
-    getTensorShape(input()), getTensorData<uint8_t>(input()),   //
-    getTensorShape(filter()), getTensorData<uint8_t>(filter()), //
-    getTensorShape(bias()), getTensorData<int32_t>(bias()),     //
-    getTensorShape(output()), getTensorData<uint8_t>(output()), //
-    tflite::RuntimeShape(), nullptr,                            //
-    getTensorData<int32_t>(scratch_tensor));
-}
+#endif // DIS_FLOAT
 
-void TransposeConv::evalQuantizedPerChannel() const
+} // namespace
+
+void configure_kernel_CircleTransposeConv(const circle::Operator *cur_op,
+                                          BaseRuntimeGraph *runtime_graph)
 {
-  const auto *input_data = getTensorData<uint8_t>(input());
-  const auto *filter_data = getTensorData<uint8_t>(filter());
-  const auto *bias_data = getTensorData<int32_t>(bias());
-  auto *output_data = getTensorData<uint8_t>(output());
-
-  auto scratch_tensor = getOutputTensors()[1];
-  auto *scratch_data = getTensorData<int32_t>(scratch_tensor);
-
-  const Shape &input_shape = input()->shape();
-  const Shape &filter_shape = filter()->shape();
-  const Shape &output_shape = output()->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 input_depth = input_shape.dim(3);
-  const int32_t output_depth = filter_shape.dim(0);
-  const int32_t filter_height = filter_shape.dim(1);
-  const int32_t filter_width = filter_shape.dim(2);
-  const int32_t output_height = output_shape.dim(1);
-  const int32_t output_width = output_shape.dim(2);
-
-  const int32_t stride_height = _params.stride_height;
-  const int32_t stride_width = _params.stride_width;
-
-  int32_t activation_min{};
-  int32_t activation_max{};
-  calculateActivationRangeQuantized(Activation::NONE, output(), &activation_min, &activation_max);
-
-  std::memset(scratch_data, 0, scratch_tensor->shape().num_elements() * sizeof(int32_t));
-
-  BroadcastableWrapper<ChannelQuantMultipliers> output_multipliers(_quant_multipliers);
-  for (int32_t batch = 0; batch < batches; ++batch)
-  {
-    for (int32_t in_y = 0; in_y < input_height; ++in_y)
-    {
-      for (int32_t in_x = 0; in_x < input_width; ++in_x)
-      {
-        for (int32_t in_c = 0; in_c < input_depth; ++in_c)
-        {
-          const int32_t out_y_origin = in_y * stride_height - _padding_height;
-          const int32_t out_x_origin = in_x * stride_width - _padding_width;
-          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 out_x = out_x_origin + filter_x;
-              const int32_t out_y = out_y_origin + filter_y;
-              if ((out_y >= 0 && out_y < output_height) && (out_x >= 0 && out_x < output_width))
-              {
-                for (int32_t out_c = 0; out_c < output_depth; ++out_c)
-                {
-                  const uint8_t input_val =
-                    input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
-                  const uint8_t filter_val =
-                    filter_data[calcOffset(filter_shape, out_c, filter_y, filter_x, in_c)];
-                  scratch_data[calcOffset(output_shape, batch, out_y, out_x, out_c)] +=
-                    static_cast<int32_t>(input_val - input()->zero_point()) *
-                    static_cast<int32_t>(filter_val - filter()->zero_points()[out_c]);
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-    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)
-        {
-          int32_t acc = scratch_data[calcOffset(output_shape, batch, out_y, out_x, out_c)];
-          if (bias_data)
-          {
-            acc += bias_data[out_c];
-          }
-
-          int32_t scaled_acc = tflite::MultiplyByQuantizedMultiplier(
-            acc, output_multipliers[out_c].multiplier, output_multipliers[out_c].shift);
-
-          scaled_acc += output()->zero_point();
-          scaled_acc = std::max(scaled_acc, activation_min);
-          scaled_acc = std::min(scaled_acc, activation_max);
-
-          output_data[calcOffset(output_shape, batch, out_y, out_x, out_c)] = scaled_acc;
-        }
-      }
-    }
-  }
+  const auto input_index = cur_op->inputs()->operator[](kInputTensor);
+  const auto filter_index = cur_op->inputs()->operator[](kFilterTensor);
+  const auto output_index = cur_op->outputs()->operator[](kOutputTensor);
+
+  assert(input_index != -1);
+  assert(filter_index != -1);
+  assert(output_index != -1);
+
+  const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+  const auto filter = runtime_graph->getCircleTensorByIndex(filter_index);
+  const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+  assert(input != nullptr);
+  assert(filter != nullptr);
+
+  auto filter_data = runtime_graph->getConstDataByTensor(filter);
+
+  assert(filter_data != nullptr);
+
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(output) == Tensor::element_type(input));
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(filter) == Tensor::element_type(input));
+
+  LUCI_INTERPRETER_CHECK(Tensor::num_dims(input) == 4 && Tensor::num_dims(filter) == 4);
 }
 
-void TransposeConv::evalQuantizedS16() const
+void execute_kernel_CircleTransposeConv(const circle::Operator *cur_op,
+                                        BaseRuntimeGraph *runtime_graph)
 {
-  const auto *input_data = getTensorData<int16_t>(input());
-  const auto *filter_data = getTensorData<int16_t>(filter());
-  const auto *bias_data = getTensorData<int64_t>(bias());
-  auto *output_data = getTensorData<int16_t>(output());
-
-  auto scratch_tensor = getOutputTensors()[1];
-  auto *scratch_data = getTensorData<int64_t>(scratch_tensor);
-
-  const Shape &input_shape = input()->shape();
-  const Shape &filter_shape = filter()->shape();
-  const Shape &output_shape = output()->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 input_depth = input_shape.dim(3);
-  const int32_t output_depth = filter_shape.dim(0);
-  const int32_t filter_height = filter_shape.dim(1);
-  const int32_t filter_width = filter_shape.dim(2);
-  const int32_t output_height = output_shape.dim(1);
-  const int32_t output_width = output_shape.dim(2);
-
-  const int32_t stride_height = _params.stride_height;
-  const int32_t stride_width = _params.stride_width;
-
-  int32_t activation_min{};
-  int32_t activation_max{};
-  calculateActivationRangeQuantized(Activation::NONE, output(), &activation_min, &activation_max);
-
-  std::memset(scratch_data, 0, scratch_tensor->shape().num_elements() * sizeof(int64_t));
-
-  BroadcastableWrapper<ChannelQuantMultipliers> output_multipliers(_quant_multipliers);
-  for (int32_t batch = 0; batch < batches; ++batch)
+  const auto input_index = cur_op->inputs()->operator[](kInputTensor);
+  const auto weight_index = cur_op->inputs()->operator[](kFilterTensor);
+  const auto bias_index =
+    cur_op->inputs()->size() == 4 ? cur_op->inputs()->operator[](kBiasTensor) : -1;
+  const auto output_index = cur_op->outputs()->operator[](kOutputTensor);
+
+  assert(input_index != -1);
+  assert(weight_index != -1);
+  assert(output_index != -1);
+
+  const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+  const auto weights = runtime_graph->getCircleTensorByIndex(weight_index);
+  const auto bias = runtime_graph->getCircleTensorByIndex(bias_index);
+  const auto output = runtime_graph->getCircleTensorByIndex(output_index);
+
+  assert(input != nullptr);
+  assert(weights != nullptr);
+  assert(output != nullptr);
+
+  const auto *options = cur_op->builtin_options_as_TransposeConvOptions();
+
+  const auto type = Tensor::element_type(input);
+  switch (type)
   {
-    for (int32_t in_y = 0; in_y < input_height; ++in_y)
-    {
-      for (int32_t in_x = 0; in_x < input_width; ++in_x)
-      {
-        for (int32_t in_c = 0; in_c < input_depth; ++in_c)
-        {
-          const int32_t out_y_origin = in_y * stride_height - _padding_height;
-          const int32_t out_x_origin = in_x * stride_width - _padding_width;
-          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 out_x = out_x_origin + filter_x;
-              const int32_t out_y = out_y_origin + filter_y;
-              if ((out_y >= 0 && out_y < output_height) && (out_x >= 0 && out_x < output_width))
-              {
-                for (int32_t out_c = 0; out_c < output_depth; ++out_c)
-                {
-                  const int16_t input_val =
-                    input_data[calcOffset(input_shape, batch, in_y, in_x, in_c)];
-                  const int16_t filter_val =
-                    filter_data[calcOffset(filter_shape, out_c, filter_y, filter_x, in_c)];
-                  scratch_data[calcOffset(output_shape, batch, out_y, out_x, out_c)] +=
-                    static_cast<int64_t>(input_val) * static_cast<int64_t>(filter_val);
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-    for (int32_t out_y = 0; out_y < output_height; ++out_y)
-    {
-      for (int32_t out_x = 0; out_x < output_width; ++out_x)
+#ifndef DIS_FLOAT
+    case DataType::FLOAT32:
+      if (Tensor::element_type(weights) == DataType::FLOAT32)
       {
-        for (int32_t out_c = 0; out_c < output_depth; ++out_c)
-        {
-          int64_t acc = scratch_data[calcOffset(output_shape, batch, out_y, out_x, out_c)];
-          if (bias_data)
-          {
-            acc += bias_data[out_c];
-          }
-          int32_t scaled_acc = tflite::MultiplyByQuantizedMultiplier(
-            acc, output_multipliers[out_c].multiplier, output_multipliers[out_c].shift);
-
-          scaled_acc = std::max(scaled_acc, activation_min);
-          scaled_acc = std::min(scaled_acc, activation_max);
-
-          output_data[calcOffset(output_shape, batch, out_y, out_x, out_c)] = scaled_acc;
-        }
+        evalFloat(input, weights, bias, output, options, 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/TransposeConv.h b/onert-micro/luci-interpreter/src/kernels/TransposeConv.h
deleted file mode 100644 (file)
index cea0cf3..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_TRANSPOSECONV_H
-#define LUCI_INTERPRETER_KERNELS_TRANSPOSECONV_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class ChannelQuantMultipliers;
-
-class TransposeConv : public KernelWithParams<TransposeConvParams>
-{
-public:
-  TransposeConv(const Tensor *output_shape, const Tensor *filter, const Tensor *input,
-                const Tensor *bias, Tensor *output, Tensor *scratch_tensor,
-                const TransposeConvParams &params);
-
-  ~TransposeConv();
-
-  const Tensor *output_shape() const { return _inputs[0]; }
-  const Tensor *filter() const { return _inputs[1]; }
-  const Tensor *input() const { return _inputs[2]; }
-  const Tensor *bias() const { return _inputs[3]; }
-  Tensor *output() const { return _outputs[0]; }
-
-  void configure() override;
-  void execute() const override;
-
-private:
-  void evalFloat() const;
-  void evalQuantized() const;
-  void evalQuantizedPerChannel() const;
-  void evalQuantizedS16() const;
-
-private:
-  int32_t _padding_height{};
-  int32_t _padding_width{};
-  // The scaling factor from input to output (aka the 'real multiplier') can
-  // be represented as a fixed point multiplier plus a left shift.
-  std::vector<ChannelQuantMultipliers> _quant_multipliers;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_TRANSPOSECONV_H
index 4856e1b..fa81a83 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/TransposeConv.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/transpose_conv/FloatTransposeConvKernel.h"
+#include "luci_interpreter/test_models/transpose_conv/NegTransposeConvKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
 using namespace testing;
 
-template <typename T, typename B>
-void Check(std::initializer_list<int32_t> output_shape_shape,
-           std::initializer_list<int32_t> weight_shape, std::initializer_list<int32_t> input_shape,
-           std::initializer_list<int32_t> bias_shape, std::initializer_list<int32_t> output_shape,
-           std::initializer_list<int32_t> output_shape_data, std::initializer_list<T> weight_data,
-           std::initializer_list<T> input_data, std::initializer_list<B> bias_data,
-           std::initializer_list<T> output_data, luci::Padding padding, int32_t stride_height,
-           int32_t stride_width)
+class TransposeConvTest : public ::testing::Test
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
+  // Do nothing
+};
 
-  constexpr DataType element_type = getElementType<T>();
-  Tensor output_shape_tensor =
-    makeInputTensor<DataType::S32>(output_shape_shape, output_shape_data, memory_manager.get());
-  Tensor weight_tensor =
-    makeInputTensor<element_type>(weight_shape, weight_data, memory_manager.get());
-  Tensor input_data_tensor =
-    makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
+template <typename T>
+std::vector<T> checkTransposeConvKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  DataType scratch_data_type = element_type == DataType::S16 ? DataType::S64 : DataType::S32;
-  Tensor scratch_tensor(scratch_data_type, Shape({}), {}, "");
-  Tensor output_tensor = makeOutputTensor(element_type);
+  // 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);
 
-  TransposeConvParams params{};
-  params.padding = padding;
-  params.stride_height = stride_height;
-  params.stride_width = stride_width;
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-  if (bias_data.size() != 0)
+  // set input data
   {
-    Tensor bias_tensor =
-      makeInputTensor<getElementType<B>()>(bias_shape, bias_data, memory_manager.get());
-    TransposeConv kernel(&output_shape_tensor, &weight_tensor, &input_data_tensor, &bias_tensor,
-                         &output_tensor, &scratch_tensor, params);
-    kernel.configure();
-    memory_manager->allocate_memory(output_tensor);
-    memory_manager->allocate_memory(scratch_tensor);
-    kernel.execute();
+    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
-  {
-    TransposeConv kernel(&output_shape_tensor, &weight_tensor, &input_data_tensor, nullptr,
-                         &output_tensor, &scratch_tensor, params);
-    kernel.configure();
-    memory_manager->allocate_memory(output_tensor);
-    memory_manager->allocate_memory(scratch_tensor);
-    kernel.execute();
-  }
-  EXPECT_THAT(extractTensorData<T>(output_tensor), ::testing::ElementsAreArray(output_data));
-}
 
-TEST(TransposeConvTest, FloatSimple)
-{
-  Check<float, float>(
-    /*output_shape_shape=*/{4}, /*weight_shape=*/{1, 3, 3, 1}, /*input_shape=*/{1, 4, 4, 1},
-    /*bias_shape=*/{}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 4, 4, 1},
-    /*weight_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9},
-    /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
-    /*bias_data=*/{},
-    /*output_data=*/{29, 62, 83, 75, 99, 192, 237, 198, 207, 372, 417, 330, 263, 446, 485, 365},
-    /*params.padding=*/luci::Padding::SAME, /*stride_height=*/1, /*stride_width=*/1);
+  runtime_module.execute();
 
-  SUCCEED();
-}
-
-TEST(TransposeConvTest, FloatTwoFiltersTest)
-{
-  Check<float, float>(
-    /*output_shape_shape=*/{4}, /*weight_shape=*/{1, 3, 3, 2}, /*input_shape=*/{1, 4, 4, 2},
-    /*bias_shape=*/{}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 4, 4, 1},
-    /*weight_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18},
-    /*input_data=*/{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},
-    /*bias_data=*/{},
-    /*output_data=*/
-    {184, 412, 568, 528, 678, 1347, 1689, 1434, 1494, 2715, 3057, 2442, 1968, 3352, 3652, 2760},
-    /*params.padding=*/luci::Padding::SAME, /*stride_height=*/1, /*stride_width=*/1);
+  assert(main_runtime_graph->getNumOfOutputTensors() == 1);
 
-  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(TransposeConvTest, SimpleBiasTest)
+TEST_F(TransposeConvTest, Float_P)
 {
-  Check<float, float>(
-    /*output_shape_shape=*/{4}, /*weight_shape=*/{2, 3, 3, 1},
-    /*input_shape=*/{1, 2, 2, 1},
-    /*bias_shape=*/{2}, /*output_shape=*/{1, 4, 4, 1}, /*output_shape_data=*/{1, 5, 5, 2},
-    /*weight_data=*/{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18},
-    /*input_data=*/{1, 2, 3, 4},
-    /*bias_data=*/{3, 4},
-    /*output_data=*/{4,  6,  6,  8,  10, 14, 9,  12, 13, 16, 10,  12,  12, 14, 28, 32, 21,
-                     24, 25, 28, 19, 24, 27, 32, 65, 76, 45, 52,  57,  64, 24, 28, 30, 34,
-                     64, 72, 39, 44, 47, 52, 42, 46, 48, 52, 106, 114, 63, 68, 71, 76},
-    /*params.padding=*/luci::Padding::VALID, /*stride_height=*/2, /*stride_width=*/2);
-
-  SUCCEED();
+  test_kernel::TestDataFloatTransposeConv test_data_kernel;
+  std::vector<float> output_data_vector = checkTransposeConvKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
 }
 
-TEST(TransposeConvTest, UInt8)
+TEST_F(TransposeConvTest, Input_type_mismatch_NEG)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
-  std::vector<float> input_data{1, 2, 3, 4};
-  std::vector<float> filter_data{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18};
-  std::vector<float> bias_data{3, 4};
-  std::vector<int32_t> output_shape_data{1, 5, 5, 2};
-  std::vector<float> ref_output_data{
-    4,  6,  6,  8,  10,  14,  9,  12, 13, 16, //
-    10, 12, 12, 14, 28,  32,  21, 24, 25, 28, //
-    19, 24, 27, 32, 65,  76,  45, 52, 57, 64, //
-    24, 28, 30, 34, 64,  72,  39, 44, 47, 52, //
-    42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
-  };
-
-  // Choose quantization parameters carefully.
-  auto input_quant = quantizationParams<uint8_t>(-8.0, 7.9375);  // s = 1 / 16, zp = 128
-  auto filter_quant = quantizationParams<uint8_t>(-24.0, 39.75); // s = 1 / 4, zp = 96
-  auto output_quant = quantizationParams<uint8_t>(-64.0, 191.0); // s = 1, zp = 64
-
-  Tensor input_tensor = makeInputTensor<DataType::U8>(
-    {1, 2, 2, 1}, input_quant.first, input_quant.second, input_data, memory_manager.get());
-  Tensor filter_tensor = makeInputTensor<DataType::U8>(
-    {2, 3, 3, 1}, filter_quant.first, filter_quant.second, filter_data, memory_manager.get());
-  Tensor bias_tensor = makeInputTensor<DataType::S32>({2}, input_quant.first * filter_quant.first,
-                                                      0, bias_data, memory_manager.get());
-  Tensor output_shape_tensor =
-    makeInputTensor<DataType::S32>({4}, output_shape_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8, output_quant.first, output_quant.second);
-
-  DataType scratch_data_type =
-    input_tensor.element_type() == DataType::S16 ? DataType::S64 : DataType::S32;
-  Tensor scratch_tensor(scratch_data_type, Shape({}), {}, "");
-
-  TransposeConvParams params{};
-  params.padding = Padding::VALID;
-  params.stride_height = 2;
-  params.stride_width = 2;
-
-  TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
-                       &output_tensor, &scratch_tensor, params);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  memory_manager->allocate_memory(scratch_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape_data));
-  EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
+  test_kernel::NegTestDataInputMismatchTransposeConvKernel 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(TransposeConvTest, UInt8_CWQ)
+TEST_F(TransposeConvTest, Invalid_input_shape_NEG)
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
-  const int32_t output_channels = 2;
-  std::vector<float> input_data{1, 2, 3, 4};
-  std::vector<float> filter_data{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18};
-  std::vector<float> bias_data{3, 4};
-  std::vector<int32_t> output_shape_data{1, 5, 5, 2};
-  std::vector<float> ref_output_data{
-    4,  6,  6,  8,  10,  14,  9,  12, 13, 16, //
-    10, 12, 12, 14, 28,  32,  21, 24, 25, 28, //
-    19, 24, 27, 32, 65,  76,  45, 52, 57, 64, //
-    24, 28, 30, 34, 64,  72,  39, 44, 47, 52, //
-    42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
-  };
-
-  // Choose quantization parameters carefully.
-  auto input_quant = quantizationParams<uint8_t>(-8.0, 7.9375);  // s = 1 / 16, zp = 128
-  auto output_quant = quantizationParams<uint8_t>(-64.0, 191.0); // s = 1, zp = 64
-
-  std::vector<std::pair<float, int32_t>> filter_quant_params;
-  filter_quant_params.push_back(quantizationParams<uint8_t>(0, 17));
-  filter_quant_params.push_back(quantizationParams<uint8_t>(0, 18));
-
-  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.first);
-  std::vector<int32_t> zerop(output_channels, 0);
-
-  Tensor input_tensor = makeInputTensor<DataType::U8>(
-    {1, 2, 2, 1}, input_quant.first, input_quant.second, input_data, memory_manager.get());
-  Tensor filter_tensor = makeInputTensor<DataType::U8>(
-    {output_channels, 3, 3, 1}, 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 output_shape_tensor =
-    makeInputTensor<DataType::S32>({4}, output_shape_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::U8, output_quant.first, output_quant.second);
-
-  DataType scratch_data_type =
-    input_tensor.element_type() == DataType::S16 ? DataType::S64 : DataType::S32;
-  Tensor scratch_tensor(scratch_data_type, Shape({}), {}, "");
-
-  TransposeConvParams params{};
-  params.padding = Padding::VALID;
-  params.stride_height = 2;
-  params.stride_width = 2;
-
-  TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
-                       &output_tensor, &scratch_tensor, params);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  memory_manager->allocate_memory(scratch_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape_data));
-  EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
-}
-
-TEST(TransposeConvTest, SInt16)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
-  std::vector<float> input_data{1, 2, 3, 4};
-  std::vector<float> filter_data{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18};
-  std::vector<float> bias_data{3, 4};
-  std::vector<int32_t> output_shape_data{1, 5, 5, 2};
-  std::vector<float> ref_output_data{
-    4,  6,  6,  8,  10,  14,  9,  12, 13, 16, //
-    10, 12, 12, 14, 28,  32,  21, 24, 25, 28, //
-    19, 24, 27, 32, 65,  76,  45, 52, 57, 64, //
-    24, 28, 30, 34, 64,  72,  39, 44, 47, 52, //
-    42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
-  };
-
-  Tensor input_tensor =
-    makeInputTensor<DataType::S16>({1, 2, 2, 1}, 0.25, 0, input_data, memory_manager.get());
-  Tensor filter_tensor =
-    makeInputTensor<DataType::S16>({2, 3, 3, 1}, 0.2, 0, filter_data, memory_manager.get());
-  Tensor bias_tensor =
-    makeInputTensor<DataType::S64>({2}, 0.25 * 0.2, 0, bias_data, memory_manager.get());
-  Tensor output_shape_tensor =
-    makeInputTensor<DataType::S32>({4}, output_shape_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, 0.5, 0);
-
-  DataType scratch_data_type =
-    input_tensor.element_type() == DataType::S16 ? DataType::S64 : DataType::S32;
-  Tensor scratch_tensor(scratch_data_type, Shape({}), {}, "");
-
-  TransposeConvParams params{};
-  params.padding = Padding::VALID;
-  params.stride_height = 2;
-  params.stride_width = 2;
-
-  TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
-                       &output_tensor, &scratch_tensor, params);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  memory_manager->allocate_memory(scratch_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape_data));
-  EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
-}
-
-TEST(TransposeConvTest, SInt16_CWQ_weights)
-{
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-
-  const int output_channels = 2;
-  const Shape input_shape{1, 2, 2, 1};
-  const Shape filter_shape{output_channels, 3, 3, 1};
-  const Shape bias_shape{output_channels};
-  std::vector<int32_t> output_shape_data{1, 5, 5, output_channels};
-
-  std::vector<float> input_data{1, 2, 3, 4};
-  std::vector<float> filter_data{1, 3, 5, 7, 9, 11, 13, 15, 17, 2, 4, 6, 8, 10, 12, 14, 16, 18};
-  std::vector<float> bias_data{3, 4};
-
-  std::vector<float> ref_output_data{
-    4,  6,  6,  8,  10,  14,  9,  12, 13, 16, //
-    10, 12, 12, 14, 28,  32,  21, 24, 25, 28, //
-    19, 24, 27, 32, 65,  76,  45, 52, 57, 64, //
-    24, 28, 30, 34, 64,  72,  39, 44, 47, 52, //
-    42, 46, 48, 52, 106, 114, 63, 68, 71, 76, //
-  };
-
-  const float input_scale = 0.25;
-  const float output_scale = 0.5;
-  const std::vector<float> filter_scales{0.2f, 0.5f};
-  std::vector<float> bias_scales{filter_scales[0] * input_scale, filter_scales[1] * input_scale};
-  const std::vector<int32_t> zerop(2, 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 output_shape_tensor =
-    makeInputTensor<DataType::S32>({4}, output_shape_data, memory_manager.get());
-  Tensor output_tensor = makeOutputTensor(DataType::S16, output_scale, 0);
-
-  DataType scratch_data_type =
-    input_tensor.element_type() == DataType::S16 ? DataType::S64 : DataType::S32;
-  Tensor scratch_tensor(scratch_data_type, Shape({}), {}, "");
-
-  TransposeConvParams params{};
-  params.padding = Padding::VALID;
-  params.stride_height = 2;
-  params.stride_width = 2;
-
-  TransposeConv kernel(&output_shape_tensor, &filter_tensor, &input_tensor, &bias_tensor,
-                       &output_tensor, &scratch_tensor, params);
-  kernel.configure();
-  memory_manager->allocate_memory(output_tensor);
-  memory_manager->allocate_memory(scratch_tensor);
-  kernel.execute();
-
-  EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(output_shape_data));
-  EXPECT_THAT(dequantizeTensorData(output_tensor), FloatArrayNear(ref_output_data));
+  test_kernel::NegTestDataInvalidInputShapeTransposeConvKernel 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
index 80f4d1f..31f08a5 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Unpack.h"
-
+#include "Builders.h"
 #include "kernels/Utils.h"
 
-#include <tensorflow/lite/kernels/internal/reference/reference_ops.h>
-
 namespace luci_interpreter
 {
-
-namespace kernels
+namespace
 {
 
-Unpack::Unpack(const Tensor *input, std::vector<Tensor *> outputs, const UnpackParams &params)
-  : KernelWithParams<UnpackParams>({input}, std::move(outputs), params)
-{
-}
+constexpr int kInputTensor = 0;
 
-void Unpack::configure()
+template <typename T>
+void UnpackImpl(const circle::Operator *cur_op, const circle::Tensor *input, int output_count,
+                int axis, RuntimeGraph *runtime_graph)
 {
-  const Shape &input_shape = input()->shape();
+  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 auto input_dims = Tensor::tensor_shape(input);
+  const auto output_dims = Tensor::tensor_shape(output0);
+  const int dimensions = input_dims.size();
 
-  int axis = _params.axis;
   if (axis < 0)
-    axis += input()->shape().num_dims();
-  assert(axis >= 0 && axis < input_shape.num_dims());
+  {
+    axis += input_dims.size();
+  }
 
-  Shape output_shape(input_shape.num_dims() - 1);
-  int out_index = 0;
-  for (int in_index = 0; in_index < input_shape.num_dims(); ++in_index)
+  int outer_size = 1;
+  for (int i = 0; i < axis; ++i)
+  {
+    outer_size *= input_dims[i];
+  }
+  int copy_size = 1;
+  for (int i = axis + 1; i < dimensions; ++i)
   {
-    if (in_index != axis)
-      output_shape.dim(out_index++) = input_shape.dim(in_index);
+    copy_size *= input_dims[i];
   }
+  int output_size = 1;
+  for (int i = 0; i < output_dims.size(); ++i)
+  {
+    output_size *= output_dims[i];
+  }
+
+  const T *input_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(input));
 
-  // TODO: enable it only if kernel with dynamic shapes
-  for (Tensor *output : _outputs)
+  for (int i = 0; i < output_count; ++i)
   {
-    assert(output->element_type() == input()->element_type());
-    output->resize(output_shape);
+    const auto output_index = cur_op->outputs()->operator[](i);
+    assert(output_index != -1);
+
+    const auto t = runtime_graph->getCircleTensorByIndex(output_index);
+    assert(output0 != nullptr);
+    T *output_data = kernels::getTensorData<T>(runtime_graph->getDataByTensor(t));
+    for (int k = 0; k < outer_size; ++k)
+    {
+      T *output_ptr = output_data + copy_size * k;
+      int loc = k * output_count * copy_size + i * copy_size;
+      const T *input_ptr = input_data + loc;
+      for (int j = 0; j < copy_size; ++j)
+        output_ptr[j] = input_ptr[j];
+    }
   }
 }
+} // namespace
 
-template <typename T> void Unpack::executeImpl() const
+void configure_kernel_CircleUnpack(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  tflite::UnpackParams params{};
-  params.axis = _params.axis;
-  params.num_split = _outputs.size();
-  VectorOfTensors<T, false> all_outputs(_outputs);
-  tflite::reference_ops::Unpack<T>(params, getTensorShape(input()), getTensorData<T>(input()),
-                                   **all_outputs.shapes(), all_outputs.data());
+  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);
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  const auto *options = cur_op->builtin_options_as_UnpackOptions();
+
+  LUCI_INTERPRETER_CHECK(cur_op->outputs()->size() == options->num());
+  LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == Tensor::element_type(output));
+
+  for (int i = 0; i < Tensor::num_dims(input); ++i)
+  {
+    if (i == options->axis())
+      continue;
+
+    if (i < options->axis())
+    {
+      LUCI_INTERPRETER_CHECK(Tensor::dim(input, i) == Tensor::dim(output, i));
+    }
+    else
+    {
+      LUCI_INTERPRETER_CHECK(Tensor::dim(input, i) == Tensor::dim(output, i - 1));
+    }
+  }
 }
 
-void Unpack::execute() const
+void execute_kernel_CircleUnpack(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
 {
-  switch (input()->element_type())
+  const auto input_index = cur_op->inputs()->operator[](0);
+  assert(input_index != -1);
+
+  const auto input = runtime_graph->getCircleTensorByIndex(input_index);
+  assert(input != nullptr);
+
+  const auto type = Tensor::element_type(input);
+
+  const auto *options = cur_op->builtin_options_as_UnpackOptions();
+
+  switch (type)
   {
+#ifndef DIS_FLOAT
     case DataType::FLOAT32:
-      return executeImpl<float>();
-    case DataType::U8:
-      return executeImpl<uint8_t>();
+    {
+      UnpackImpl<float>(cur_op, input, options->num(), options->axis(), runtime_graph);
+      break;
+    }
+#endif // DIS_FLOAT
     default:
-      assert(false && "Unsupported type.");
+      assert(false && "Unsupported type");
   }
 }
-
-} // namespace kernels
 } // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/Unpack.h b/onert-micro/luci-interpreter/src/kernels/Unpack.h
deleted file mode 100644 (file)
index f4a44ec..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 LUCI_INTERPRETER_KERNELS_UNPACK_H
-#define LUCI_INTERPRETER_KERNELS_UNPACK_H
-
-#include "core/Kernel.h"
-#include "core/KernelParams.h"
-
-namespace luci_interpreter
-{
-namespace kernels
-{
-
-class Unpack : public KernelWithParams<UnpackParams>
-{
-public:
-  Unpack(const Tensor *input, std::vector<Tensor *> outputs, const UnpackParams &params);
-
-  const Tensor *input() const { return _inputs[0]; }
-  Tensor *output(int index) const { return _outputs[index]; }
-
-  void configure() override;
-  void execute() const override;
-
-private:
-  template <typename T> void executeImpl() const;
-};
-
-} // namespace kernels
-} // namespace luci_interpreter
-
-#endif // LUCI_INTERPRETER_KERNELS_UNPACK_H
index 9384ddc..738051b 100644 (file)
  * limitations under the License.
  */
 
-#include "kernels/Unpack.h"
 #include "kernels/TestUtils.h"
-#include "luci_interpreter/TestMemoryManager.h"
+#include "luci_interpreter/test_models/unpack/FloatUnpackKernel.h"
+#include "luci_interpreter/test_models/unpack/NegUnpackKernel.h"
+
+#include "loader/ModuleLoader.h"
 
 namespace luci_interpreter
 {
-namespace kernels
-{
 namespace
 {
 
 using namespace testing;
 
-template <typename T>
-void Check(int axis, Shape input_shape, std::initializer_list<T> input_data,
-           const std::vector<std::initializer_list<int32_t>> &exp_output_shape,
-           std::vector<std::initializer_list<T>> exp_output_data)
+class UnpackTest : public ::testing::Test
 {
-  std::unique_ptr<IMemoryManager> memory_manager = std::make_unique<TestMemoryManager>();
-  constexpr DataType element_type = getElementType<T>();
-  const int num_outputs = input_shape.dim(axis < 0 ? axis + input_shape.num_dims() : axis);
-
-  Tensor input_tensor =
-    makeInputTensor<element_type>(input_shape, input_data, memory_manager.get());
-  std::vector<Tensor> output_tensors;
-  output_tensors.reserve(num_outputs);
-  for (int i = 0; i < num_outputs; ++i)
-  {
-    output_tensors.push_back(makeOutputTensor(element_type));
-  }
+  // Do nothing
+};
 
-  std::vector<Tensor *> output_tensor_ptrs(num_outputs);
-  for (int i = 0; i < num_outputs; ++i)
-  {
-    output_tensor_ptrs[i] = &output_tensors[i];
-  }
+template <typename T>
+std::vector<std::vector<T>> checkUnpackKernel(test_kernel::TestDataBase<T> *test_data_base)
+{
+  MemoryManager memory_manager{};
+  RuntimeModule runtime_module{};
+  bool dealloc_input = true;
 
-  UnpackParams params{};
-  params.axis = axis;
+  // 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);
 
-  Unpack kernel(&input_tensor, std::move(output_tensor_ptrs), params);
-  kernel.configure();
-  for (int i = 0; i < num_outputs; i++)
-  {
-    memory_manager->allocate_memory(output_tensors[i]);
-  }
-  kernel.execute();
+  auto *main_runtime_graph = runtime_module.getMainGraph();
+  assert(main_runtime_graph->getNumOfInputTensors() == 1);
 
-  for (int i = 0; i < num_outputs; ++i)
+  // set input data
   {
-    EXPECT_THAT(extractTensorData<T>(output_tensors[i]),
-                ::testing::ElementsAreArray(exp_output_data[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);
   }
-}
-
-template <typename T> class UnpackTest : public ::testing::Test
-{
-};
 
-using DataTypes = ::testing::Types<float, uint8_t>;
-TYPED_TEST_SUITE(UnpackTest, DataTypes);
+  runtime_module.execute();
 
-TYPED_TEST(UnpackTest, ThreeOutputs)
-{
-  Check<TypeParam>(/*axis=*/0, /*input_shape=*/{3, 2},
-                   /*input_data=*/{1, 2, 3, 4, 5, 6},
-                   /*exp_output_shape=*/{{2}, {2}, {2}},
-                   /*exp_output_data=*/{{1, 2}, {3, 4}, {5, 6}});
-}
-
-TYPED_TEST(UnpackTest, ThreeOutputsAxisOne)
-{
-  Check<TypeParam>(/*axis=*/1, /*input_shape=*/{3, 2},
-                   /*input_data=*/{1, 2, 3, 4, 5, 6},
-                   /*exp_output_shape=*/{{3}, {3}},
-                   /*exp_output_data=*/{{1, 3, 5}, {2, 4, 6}});
-}
+  assert(main_runtime_graph->getNumOfOutputTensors() == 2);
 
-TYPED_TEST(UnpackTest, ThreeOutputsNegativeAxisOne)
-{
-  Check<TypeParam>(/*axis=*/-1, /*input_shape=*/{3, 2},
-                   /*input_data=*/{1, 2, 3, 4, 5, 6},
-                   /*exp_output_shape=*/{{3}, {3}},
-                   /*exp_output_data=*/{{1, 3, 5}, {2, 4, 6}});
-}
+  std::vector<std::vector<T>> res;
 
-TYPED_TEST(UnpackTest, ThreeOutputsNegativeAxisTwo)
-{
-  Check<TypeParam>(/*axis=*/-2, /*input_shape=*/{3, 2},
-                   /*input_data=*/{1, 2, 3, 4, 5, 6},
-                   /*exp_output_shape=*/{{2}, {2}, {2}},
-                   /*exp_output_data=*/{{1, 2}, {3, 4}, {5, 6}});
-}
+  T *output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(0));
+  size_t num_elements = (main_runtime_graph->getOutputDataSizeByIndex(0) / sizeof(T));
+  std::vector<T> output_data_vector(output_data, output_data + num_elements);
+  res.push_back(output_data_vector);
 
-TYPED_TEST(UnpackTest, OneOutput)
-{
-  Check<TypeParam>(/*axis=*/0, /*input_shape=*/{1, 6},
-                   /*input_data=*/{1, 2, 3, 4, 5, 6},
-                   /*exp_output_shape=*/{{6}},
-                   /*exp_output_data=*/{{1, 2, 3, 4, 5, 6}});
-}
+  output_data = reinterpret_cast<T *>(main_runtime_graph->getOutputDataByIndex(1));
+  num_elements = (main_runtime_graph->getOutputDataSizeByIndex(1) / sizeof(T));
+  std::vector<T> output_data_vector_1(output_data, output_data + num_elements);
+  res.push_back(output_data_vector_1);
 
-TYPED_TEST(UnpackTest, ThreeDimensionsTwoOutputs)
-{
-  Check<TypeParam>(/*axis=*/2, /*input_shape=*/{2, 2, 2},
-                   /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8},
-                   /*exp_output_shape=*/{{2, 2}, {2, 2}},
-                   /*exp_output_data=*/{{1, 3, 5, 7}, {2, 4, 6, 8}});
+  return res;
 }
 
-TYPED_TEST(UnpackTest, FiveDimensionsTwoOutputs)
+TEST_F(UnpackTest, Float_P)
 {
-  Check<TypeParam>(
-    /*axis=*/2, /*input_shape=*/{2, 2, 2, 2, 1},
-    /*input_data=*/{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
-    /*exp_output_shape=*/{{2, 2, 2, 1}, {2, 2, 2, 1}},
-    /*exp_output_data=*/
-    {{1, 2, 5, 6, 9, 10, 13, 14}, {3, 4, 7, 8, 11, 12, 15, 16}});
+  test_kernel::TestDataFloatUnpack test_data_kernel;
+  std::vector<std::vector<float>> output_data_vector = checkUnpackKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector[0], kernels::testing::FloatArrayNear(
+                                       test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  EXPECT_THAT(output_data_vector[1], kernels::testing::FloatArrayNear(
+                                       test_data_kernel.get_output_data_by_index(1), 0.0001f));
 }
 
-TYPED_TEST(UnpackTest, VectorToScalar)
+TEST_F(UnpackTest, Input_type_mismatch_NEG)
 {
-  Check<TypeParam>(/*axis=*/0, /*input_shape=*/{5},
-                   /*input_data=*/{1, 2, 3, 4, 5},
-                   /*exp_output_shape=*/{{}, {}, {}, {}, {}},
-                   /*exp_output_data=*/{{1}, {2}, {3}, {4}, {5}});
+  test_kernel::NegTestDataInputMismatchUnpackKernel 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
index 35ab821..6085071 100644 (file)
@@ -86,6 +86,22 @@ void matrixScalarMultiplyAccumulate(const int8_t *matrix, int32_t scalar, int32_
   }
 }
 
+bool areShapesEqual(const luci_interpreter::RuntimeShape &input_shape1,
+                    const luci_interpreter::RuntimeShape &input_shape2)
+{
+  if (input_shape1.dimensionsCount() == input_shape2.dimensionsCount())
+  {
+    int N = input_shape1.dimensionsCount();
+    for (int i = 0; i < N; ++i)
+    {
+      if (input_shape1.dims(i) != input_shape2.dims(i))
+        return false;
+    }
+    return true;
+  }
+  return false;
+}
+
 template void calculateActivationRange(Activation activation, float *activation_min,
                                        float *activation_max);
 template void calculateActivationRange(Activation activation, int32_t *activation_min,
index a01d72d..ce5f763 100644 (file)
@@ -228,6 +228,10 @@ 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);
 
+// Checks if input and output dimensions are equal
+bool areShapesEqual(const luci_interpreter::RuntimeShape &input_shape1,
+                    const luci_interpreter::RuntimeShape &input_shape2);
+
 #ifndef DIS_QUANT
 bool checkedLog2(const float x, int *log2_result);
 
diff --git a/onert-micro/luci-interpreter/src/kernels/ZerosLike.cpp b/onert-micro/luci-interpreter/src/kernels/ZerosLike.cpp
new file mode 100644 (file)
index 0000000..d758049
--- /dev/null
@@ -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.
+ */
+
+#include "Builders.h"
+#include "kernels/Utils.h"
+#include "SISOKernel.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+template <typename T> void resetZeros(T *out, const int num_elements)
+{
+  for (int i = 0; i < num_elements; ++i)
+  {
+    out[i] = static_cast<T>(0);
+  }
+}
+} // namespace
+
+void configure_kernel_CircleZerosLike(const circle::Operator *cur_op,
+                                      BaseRuntimeGraph *runtime_graph)
+{
+  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 execute_kernel_CircleZerosLike(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
+{
+  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);
+
+  if (is_inplace)
+    output_data = const_cast<uint8_t *>(input_data);
+
+  const int flat_size = kernels::getTensorRuntimeShape(kernel.input(), runtime_graph).flatSize();
+
+  assert(output_data);
+
+  switch (Tensor::element_type(kernel.input()))
+  {
+#ifndef DIS_FLOAT
+    case DataType::FLOAT32:
+    {
+      resetZeros(kernels::getTensorData<float>(output_data), flat_size);
+      break;
+    }
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type");
+  }
+
+  if (is_inplace)
+    runtime_graph->makeInplaceOperation(kernel.input(), kernel.output());
+}
+} // namespace luci_interpreter
diff --git a/onert-micro/luci-interpreter/src/kernels/ZerosLike.test.cpp b/onert-micro/luci-interpreter/src/kernels/ZerosLike.test.cpp
new file mode 100644 (file)
index 0000000..6bd6f52
--- /dev/null
@@ -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.
+ */
+
+#include "kernels/TestUtils.h"
+#include "luci_interpreter/test_models/zeros_like/FloatZerosLikeKernel.h"
+#include "luci_interpreter/test_models/zeros_like/NegZerosLikeKernel.h"
+
+#include "loader/ModuleLoader.h"
+
+namespace luci_interpreter
+{
+namespace
+{
+
+using namespace testing;
+
+class ZerosLikeTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+template <typename T>
+std::vector<T> checkZerosLikeKernel(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(ZerosLikeTest, Float_P)
+{
+  test_kernel::TestDataFloatZerosLike test_data_kernel;
+  std::vector<float> output_data_vector = checkZerosLikeKernel(&test_data_kernel);
+  EXPECT_THAT(output_data_vector, kernels::testing::FloatArrayNear(
+                                    test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(ZerosLikeTest, Input_type_mismatch_NEG)
+{
+  test_kernel::NegTestDataInputMismatchZerosLikeKernel 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
index 26e207a..f68adba 100644 (file)
@@ -26,6 +26,7 @@ bool isInplaceOperation(const circle::BuiltinOperator &op)
   switch (op)
   {
     case circle::BuiltinOperator_ABS:
+    case circle::BuiltinOperator_CEIL:
     case circle::BuiltinOperator_LOGISTIC:
     case circle::BuiltinOperator_RESHAPE:
     case circle::BuiltinOperator_ELU:
@@ -33,12 +34,15 @@ bool isInplaceOperation(const circle::BuiltinOperator &op)
     case circle::BuiltinOperator_EXP:
     case circle::BuiltinOperator_TANH:
     case circle::BuiltinOperator_LEAKY_RELU:
+    case circle::BuiltinOperator_LOG:
     case circle::BuiltinOperator_RELU:
     case circle::BuiltinOperator_RELU6:
+    case circle::BuiltinOperator_ROUND:
     case circle::BuiltinOperator_ADD:
     case circle::BuiltinOperator_MUL:
     case circle::BuiltinOperator_SUB:
     case circle::BuiltinOperator_WHILE:
+    case circle::BuiltinOperator_ZEROS_LIKE:
       return true;
     default:
       return false;
diff --git a/onert-micro/onert-micro/CMakeLists.txt b/onert-micro/onert-micro/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a48ad16
--- /dev/null
@@ -0,0 +1,58 @@
+set(OM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
+set(OM_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
+set(OM_PAL_COMMON_DIR "${OM_INCLUDE_DIR}/pal/common")
+# if no path is specified, use classic to mcu
+if (NOT OM_PAL_DIR)
+    set(OM_PAL_DIR "${OM_INCLUDE_DIR}/pal/mcu")
+endif()
+
+# if no path is specified, use classic to KernelsToBuild list, else use generated one
+if (NOT OM_KERNELS_BUILD_LIST)
+    set(KERNEL_REGISTER_FILE "${OM_PAL_DIR}/KernelsToBuild.lst")
+else()
+    set(KERNEL_REGISTER_FILE ${OM_KERNELS_BUILD_LIST})
+endif()
+
+# if no path is specified, use classic to KernelsToBuild list, else use generated one
+if (NOT OM_KERNELS_TRAIN_LIST)
+    set(KERNEL_TRAIN_REGISTER_FILE "${OM_PAL_DIR}/KernelsToTrain.lst")
+else()
+    set(KERNEL_TRAIN_REGISTER_FILE ${OM_KERNELS_TRAIN_LIST})
+endif()
+
+set(PASS_REGISTER_FILE "${OM_INCLUDE_DIR}/optimize/BuildPass.lst")
+set(CUSTOM_KERNEL_REGISTER_FILE "${OM_PAL_DIR}/CustomKernelsToBuild.lst")
+
+# To build onert-micro for eval-driver x86-64 version (to avoid name conflicts)
+if (NOT DEFINED CUSTOM_OM_SUFFIX)
+    set(OM_SUFFIX "")
+else()
+    set(OM_SUFFIX ${CUSTOM_OM_SUFFIX})
+endif()
+
+# To disable quantize kernels
+if (DIS_QUANT)
+    add_definitions(-DDIS_QUANT)
+endif()
+
+# To disable float kernels
+if (DIS_FLOAT)
+    add_definitions(-DDIS_FLOAT)
+endif()
+
+# To enable training part
+if (ENABLE_TRAINING)
+    add_definitions(-DENABLE_TRAINING)
+endif()
+
+# TODO move it to specific cmake for platforms
+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/onert-micro/include/OMConfig.h b/onert-micro/onert-micro/include/OMConfig.h
new file mode 100644 (file)
index 0000000..0ffbf02
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CONFIG_H
+#define ONERT_MICRO_CONFIG_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+namespace onert_micro
+{
+
+/*
+ * OMTrainOptimizer - enum to store optimizers supported by training with onert-micro
+ */
+enum OMTrainOptimizer
+{
+  SGD,
+  ADAM,
+};
+
+/*
+ * OMMetrics - enum to store metrics supported by training with onert-micro
+ */
+enum OMMetrics
+{
+  MSE_METRICS,
+  MAE_METRICS,
+  CROSS_ENTROPY_METRICS,
+  ACCURACY,
+};
+
+/*
+ * OMLoss - enum to store loss supported by training with onert-micro
+ */
+enum OMLoss
+{
+  BINARY_CROSS_ENTROPY,
+  CROSS_ENTROPY,
+  MSE,
+  MAE,
+};
+
+/*
+ * OMTrainingContext contains training specific parameters
+ * batch_size - batch size for training (Note: 1 - default one)
+ * num_of_train_layers - number of trainable last layers (Note: 0 - all layers will be trained)
+ * optimizer - optimizer which onert-micro training will be used (Note: SGD - default one)
+ * loss - loss which onert-micro training will be used (Note: CROSS_ENTROPY - default one)
+ * learning_rate - used by all optimizers
+ * beta - used by ADAM optimizer
+ * beta_squares - used by ADAM optimizer
+ * epsilon - used by ADAM optimizer
+ * num_Step - used by ADAM optimizer
+ */
+struct OMTrainingContext
+{
+  uint32_t batch_size = 1;
+  uint32_t num_of_train_layers = 0;
+  OMTrainOptimizer optimizer = SGD;
+  OMLoss loss = MSE;
+  float learning_rate = 0.001f;
+  float beta = 0.9f;
+  float beta_squares = 0.9f;
+  float epsilon = 10e-8;
+  uint32_t num_step = 0;
+  uint32_t num_epoch = 0;
+  uint32_t epochs = 0;
+};
+
+/*
+ * OMConfig - main config to store information for runtime and for training runtime
+ * keep_input - will the allocated memory be saved for the input data, or can it be deleted after
+ * use cmsis_nn - will CMSIS NN kernels be used or not (needed to some internal settings) wof_ptr -
+ * a pointer to the data that stores weights separate from the model train_mode - a flag to indicate
+ * whether we are currently in training mode or not
+ */
+struct OMConfig
+{
+  bool keep_input = false;
+  bool cmsis_nn = false;
+  // For case with divided weights and circle file
+  char *wof_ptr = nullptr;
+  bool train_mode = false;
+  char *model_ptr = nullptr;
+  size_t model_size = 0;
+  OMTrainingContext training_context = {};
+};
+
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CONFIG_H
diff --git a/onert-micro/onert-micro/include/OMInterpreter.h b/onert-micro/onert-micro/include/OMInterpreter.h
new file mode 100644 (file)
index 0000000..d450c34
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_INTERPRETER_H
+#define ONERT_MICRO_INTERPRETER_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+
+#include "core/OMRuntimeModule.h"
+
+namespace onert_micro
+{
+
+class OMInterpreter
+{
+private:
+  core::OMRuntimeModule _runtime_module;
+
+public:
+  OMInterpreter() = default;
+  OMInterpreter(const OMInterpreter &) = delete;
+  OMInterpreter(OMInterpreter &&) = delete;
+  OMInterpreter &operator=(const OMInterpreter &) = delete;
+  OMInterpreter &&operator=(const OMInterpreter &&) = delete;
+  ~OMInterpreter() = default;
+
+  OMStatus importModel(const char *model_ptr, const OMConfig &config);
+
+  OMStatus run();
+
+  OMStatus reset();
+
+  uint32_t getNumberOfInputs();
+  uint32_t getNumberOfOutputs();
+
+  OMStatus allocateInputs();
+
+  uint32_t getInputSizeAt(uint32_t position);
+  uint32_t getOutputSizeAt(uint32_t position);
+
+  void *getInputDataAt(uint32_t position);
+  void *getOutputDataAt(uint32_t position);
+};
+
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_INTERPRETER_H
diff --git a/onert-micro/onert-micro/include/OMStatus.h b/onert-micro/onert-micro/include/OMStatus.h
new file mode 100644 (file)
index 0000000..66005fb
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_STATUS_H
+#define ONERT_MICRO_STATUS_H
+
+namespace onert_micro
+{
+
+enum OMStatus
+{
+  Ok,
+  UnsupportedType,
+  UnsupportedQuantizationType,
+  UnsupportedActivation,
+  UnsupportedOp,
+  UnknownError,
+  ModelNotImport,
+  FailedCheckCondition,
+  NoQuantization,
+  UnsupportedDynamicShapeCase,
+  FailReadWOFFile,
+  FailReadCheckpointFile,
+  CmsisNNError,
+};
+
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_STATUS_H
diff --git a/onert-micro/onert-micro/include/OMTrainingInterpreter.h b/onert-micro/onert-micro/include/OMTrainingInterpreter.h
new file mode 100644 (file)
index 0000000..0c1a35d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAINING_INTERPRETER_H
+#define ONERT_MICRO_TRAINING_INTERPRETER_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+
+#include "core/OMTrainingRuntimeModule.h"
+
+namespace onert_micro
+{
+
+class OMTrainingInterpreter
+{
+private:
+  core::OMTrainingRuntimeModule _training_runtime_module;
+
+public:
+  OMTrainingInterpreter() = default;
+  OMTrainingInterpreter(const OMTrainingInterpreter &) = delete;
+  OMTrainingInterpreter(OMTrainingInterpreter &&) = delete;
+  OMTrainingInterpreter &operator=(const OMTrainingInterpreter &) = delete;
+  OMTrainingInterpreter &&operator=(const OMTrainingInterpreter &&) = delete;
+  ~OMTrainingInterpreter() = default;
+
+  // Import train model with current config settings
+  // Note: model ptr should be non-const to save result
+  OMStatus importTrainModel(char *model_ptr, const OMConfig &config);
+
+  // Set input data for input with input_index
+  // Note: number of the samples in data should be equal to the batch_size in config structure
+  void setInput(uint8_t *data, uint32_t input_index)
+  {
+    _training_runtime_module.setInputData(data, input_index);
+  }
+  // Set target data for output with target_index
+  // Note: number of the samples in data should be equal to the batch_size in config structure
+  void setTarget(uint8_t *data, uint32_t target_index)
+  {
+    _training_runtime_module.setTargetData(data, target_index);
+  }
+
+  // Train single step: run forward graph (with data which was set in SetInput) ->
+  // -> calculate error (with target data which was set in SetTarget) ->
+  // -> run backward graph -> update optimizer state -> after batch_size steps update weights
+  // Warning: before using trainSingleStep call: 1) importTrainModel; 2) setInput; 3) setTarget
+  OMStatus trainSingleStep(OMConfig &config);
+
+  // Reset all states and data saved into OMTrainingInterpreter (trained weights will not be reset)
+  OMStatus reset();
+
+  // Calculate and save metric into metric_val: run forward graph -> calculate metric
+  // Note: calculation will be done on test_size number of test samples
+  // Warning: before using evaluateMetric call: 1) importTrainModel; 2) setInput; 3) setTarget
+  // Note: number of the samples in data should be equal to the test_size
+  OMStatus evaluateMetric(OMMetrics metric, void *metric_val, uint32_t test_size)
+  {
+    return _training_runtime_module.evaluateMetric(metric, metric_val, test_size);
+  }
+
+  // To get input and output flat size
+  uint32_t getInputSizeAt(uint32_t position);
+  uint32_t getOutputSizeAt(uint32_t position);
+
+  // Save current model
+  OMStatus saveModel(const OMConfig &config, const char *save_path);
+
+  // Save current status as checkpoint
+  OMStatus saveCheckpoint(const OMConfig &config, const char *save_path);
+
+  // Load current status from checkpoint and save it in current model and in current config
+  OMStatus loadCheckpoint(OMConfig &config, const char *load_path);
+
+  OMStatus run() { return _training_runtime_module.run(); }
+  OMStatus allocateInputs() { return _training_runtime_module.allocateInputs(); }
+
+  void *getInputData(uint32_t position);
+  void *getInputDataAt(uint32_t position);
+  void *getOutputDataAt(uint32_t position);
+};
+
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAINING_INTERPRETER_H
diff --git a/onert-micro/onert-micro/include/core/OMDataType.h b/onert-micro/onert-micro/include/core/OMDataType.h
new file mode 100644 (file)
index 0000000..a6f5e06
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_OM_DATA_TYPE_H
+#define ONERT_MICRO_CORE_OM_DATA_TYPE_H
+
+#include "core/reader/OMCircleReader.h"
+
+#include <cstdint>
+#include <cstddef>
+#include <string>
+#include <cassert>
+
+namespace onert_micro
+{
+namespace core
+{
+/**
+ * @brief "scalar" value type
+ */
+enum class OMDataType
+{
+  Unknown, // Unknown type (serves as a default value)
+
+  U8,  // 8-bit unsigned integer
+  U16, // 16-bit unsigned integer
+  U32, // 32-bit unsigned integer
+  U64, // 64-bit unsigned integer
+
+  S8,  // 8-bit signed integer
+  S16, // 16-bit signed integer
+  S32, // 32-bit signed integer
+  S64, // 64-bit signed integer
+
+  FLOAT16, // IEEE 16-bit floating-point
+  FLOAT32, // IEEE 32-bit floating-point
+  FLOAT64, // IEEE 64-bit floating-point
+
+  BOOL, // Boolean
+};
+
+OMDataType onertMicroDatatype(const circle::TensorType type);
+
+/**
+ * @brief C++ scalar type corresponding to each OMDataType
+ */
+template <OMDataType DT> struct OMDataTypeImpl
+{
+  // using Type = ...
+};
+
+// TODO Support other enum values
+template <> struct OMDataTypeImpl<OMDataType::S8>
+{
+  // Use C++ int8_t type for 8bit integer
+  using Type = int8_t;
+};
+
+template <> struct OMDataTypeImpl<OMDataType::U8>
+{
+  // Use C++ uint8_t type for unsigned 8bit integer
+  using Type = uint8_t;
+};
+
+template <> struct OMDataTypeImpl<OMDataType::S16>
+{
+  // Use C++ int16_t type for 16bit integer
+  using Type = int16_t;
+};
+
+template <> struct OMDataTypeImpl<OMDataType::U16>
+{
+  // Use C++ uint16_t type for unsigned 16bit integer
+  using Type = uint16_t;
+};
+
+template <> struct OMDataTypeImpl<OMDataType::S32>
+{
+  // Use C++ int32_t type for 32bit integer
+  using Type = int32_t;
+};
+
+template <> struct OMDataTypeImpl<OMDataType::U32>
+{
+  // Use C++ uint32_t type for unsigned 32bit integer
+  using Type = uint32_t;
+};
+
+template <> struct OMDataTypeImpl<OMDataType::S64>
+{
+  // Use C++ int64_t type for 64bit integer
+  using Type = int64_t;
+};
+
+template <> struct OMDataTypeImpl<OMDataType::U64>
+{
+  // Use C++ uint64_t type for unsigned 64bit integer
+  using Type = uint64_t;
+};
+
+template <> struct OMDataTypeImpl<OMDataType::FLOAT16>
+{
+  // float16 type with 16bit value, encoded with help of FP16 library
+  // https://github.com/Maratyszcza/FP16/
+  using Type = uint16_t;
+};
+
+template <> struct OMDataTypeImpl<OMDataType::FLOAT32>
+{
+  // Use C++ float type for IEEE 32-bit floating-point numbers
+  using Type = float;
+};
+
+template <> struct OMDataTypeImpl<OMDataType::FLOAT64>
+{
+  // Use C++ double type for IEEE 64-bit floating-point numbers
+  using Type = double;
+};
+
+// NOTE OMDataTypeImpl for BOOL is subject to change
+template <> struct OMDataTypeImpl<OMDataType::BOOL>
+{
+  // Use C++ uint8_t type for bool
+  using Type = uint8_t;
+};
+
+/**
+ * @brief Returns the size of the data type.
+ * @note If you need the size at compile time, use `sizeof(typename OMDataTypeImpl<DT>::Type)`.
+ */
+inline uint32_t size(OMDataType data_type)
+{
+  switch (data_type)
+  {
+    case OMDataType::S8:
+      return sizeof(OMDataTypeImpl<OMDataType::S8>::Type);
+    case OMDataType::U8:
+      return sizeof(OMDataTypeImpl<OMDataType::U8>::Type);
+    case OMDataType::S16:
+      return sizeof(OMDataTypeImpl<OMDataType::S16>::Type);
+    case OMDataType::U16:
+      return sizeof(OMDataTypeImpl<OMDataType::U16>::Type);
+    case OMDataType::S32:
+      return sizeof(OMDataTypeImpl<OMDataType::S32>::Type);
+    case OMDataType::U32:
+      return sizeof(OMDataTypeImpl<OMDataType::U32>::Type);
+    case OMDataType::S64:
+      return sizeof(OMDataTypeImpl<OMDataType::S64>::Type);
+    case OMDataType::U64:
+      return sizeof(OMDataTypeImpl<OMDataType::U64>::Type);
+    case OMDataType::FLOAT16:
+      return sizeof(OMDataTypeImpl<OMDataType::FLOAT16>::Type);
+    case OMDataType::FLOAT32:
+      return sizeof(OMDataTypeImpl<OMDataType::FLOAT32>::Type);
+    case OMDataType::FLOAT64:
+      return sizeof(OMDataTypeImpl<OMDataType::FLOAT64>::Type);
+    case OMDataType::BOOL:
+      return sizeof(OMDataTypeImpl<OMDataType::BOOL>::Type);
+    default:
+      // TODO Support remaining data types.
+      assert(false);
+      return 1; // Avoid compiler warning.
+  }
+}
+
+inline size_t getOMDataTypeSize(OMDataType data_type) { return size(data_type); }
+
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_OM_DATA_TYPE_H
diff --git a/onert-micro/onert-micro/include/core/OMKernelData.h b/onert-micro/onert-micro/include/core/OMKernelData.h
new file mode 100644 (file)
index 0000000..784f68e
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_KERNEL_DATA_H
+#define ONERT_MICRO_CORE_KERNEL_DATA_H
+
+#include "OMStatus.h"
+#include "reader/OMCircleReader.h"
+
+namespace onert_micro
+{
+namespace core
+{
+
+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
+{
+  uint32_t num_inputs;
+  uint32_t axis;
+};
+
+struct SoftmaxParams
+{
+  float beta;
+  int32_t input_multiplier;
+  int32_t input_left_shift;
+  int diff_min;
+  int num_rows;
+  int row_size;
+  int32_t input_zp;
+  int32_t output_zp;
+  float input_scale;
+  float output_scale;
+};
+
+struct LogSoftmaxParams
+{
+  int num_rows;
+  int row_size;
+};
+
+struct L2NormalizationParams
+{
+  int num_rows;
+  int row_size;
+  float epsilon = 1e-6;
+};
+
+struct Pool2DParams
+{
+  int32_t stride_w;
+  int32_t stride_h;
+  int32_t dilation_width_factor;
+  int32_t dilation_height_factor;
+  int32_t filter_h;
+  int32_t filter_w;
+  int32_t pad_h;
+  int32_t pad_w;
+  float activation_min;
+  float activation_max;
+  int32_t quantized_activation_min;
+  int32_t quantized_activation_max;
+};
+
+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;
+};
+
+struct TransposeParams
+{
+  int32_t perm_count;
+  int32_t perm[5];
+};
+
+struct ArithmeticQuantParams
+{
+  int32_t input1_offset;
+  int32_t input2_offset;
+  int left_shift;
+  int32_t input1_multiplier;
+  int32_t input2_multiplier;
+  int input1_shift;
+  int input2_shift;
+  int32_t output_multiplier;
+  int output_shift;
+  int32_t output_offset;
+  int32_t quantized_activation_max;
+  int32_t quantized_activation_min;
+};
+
+struct BinaryArithmeticBroadcastParams
+{
+  // float activation params.
+  float float_activation_min;
+  float float_activation_max;
+  int32_t int32_activation_min;
+  int32_t int32_activation_max;
+  int64_t int64_activation_min;
+  int64_t int64_activation_max;
+  BroadcastableOpCategory broadcast_category;
+};
+
+struct ConvQuant
+{
+  int32_t pad_h;
+  int32_t pad_w;
+  int32_t stride_w;
+  int32_t stride_h;
+  int32_t stride_width;
+  int32_t stride_height;
+  int32_t dilation_width_factor;
+  int32_t dilation_height_factor;
+  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 depth_multiplier;
+  std::vector<int32_t> per_channel_output_multiplier;
+  std::vector<int> per_channel_output_shift;
+};
+
+struct SplitParams
+{
+  uint8_t *output_data[5];
+  uint32_t num_outputs;
+};
+
+struct FloatConv2D
+{
+  int32_t stride_w;
+  int32_t stride_h;
+  int32_t dilation_width_factor;
+  int32_t dilation_height_factor;
+  int32_t depth_multiplier;
+  int32_t pad_h;
+  int32_t pad_w;
+  float activation_min;
+  float activation_max;
+};
+
+struct FullyConnectedParams
+{
+  // float activation params.
+  float float_activation_min;
+  float float_activation_max;
+
+  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;
+};
+
+struct PadParams
+{
+  int32_t left_padding_count;
+  int32_t left_padding[5];
+  int32_t right_padding_count;
+  int32_t right_padding[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 QuantizationParams
+{
+  float scale;
+  int32_t zero_point;
+};
+
+struct SliceParams
+{
+  int8_t begin_count;
+  int32_t begin[5];
+  int8_t size_count;
+  int32_t size[5];
+};
+
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_KERNEL_DATA_H
diff --git a/onert-micro/onert-micro/include/core/OMKernelType.h b/onert-micro/onert-micro/include/core/OMKernelType.h
new file mode 100644 (file)
index 0000000..229c96e
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_KERNEL_TYPE_H
+#define ONERT_MICRO_CORE_KERNEL_TYPE_H
+
+#include "OMStatus.h"
+#include "reader/OMCircleReader.h"
+
+namespace onert_micro
+{
+namespace core
+{
+
+enum OMKernelType
+{
+  Normal,
+  Inplace,
+};
+
+enum OMBuilderCustomID
+{
+  CUSTOM_custom_gru,
+};
+
+#define REGISTER_KERNEL(builtin_operator, name) BuiltinOperator_##builtin_operator,
+#define REGISTER_CUSTOM_KERNEL(name, string_name) CUSTOM_##name,
+enum class OMBuilderID
+{
+#include "KernelsToBuild.lst"
+  BuiltinOperatorsSize, // casts to count of values in BuilderId enum
+#include "CustomKernelsToBuild.lst"
+  Size
+};
+#undef REGISTER_CUSTOM_KERNEL
+#undef REGISTER_KERNEL
+
+OMStatus getBuiltinOperatorBuilderId(const circle::BuiltinOperator &opcode,
+                                     core::OMBuilderID &builderID);
+
+OMStatus getCustomOperatorBuilderId(const flatbuffers::String *custom_opcode,
+                                    core::OMBuilderID &builderID);
+
+OMStatus getCustomOperatorByBuilderId(core::OMBuilderID &builderID, OMBuilderCustomID &opcode);
+
+OMStatus getBuilderId(const circle::OperatorCode *opcode, core::OMBuilderID &builderID);
+
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_KERNEL_TYPE_H
diff --git a/onert-micro/onert-micro/include/core/OMRuntimeContext.h b/onert-micro/onert-micro/include/core/OMRuntimeContext.h
new file mode 100644 (file)
index 0000000..1a54c37
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_RUNTIME_CONTEXT_H
+#define ONERT_MICRO_CORE_RUNTIME_CONTEXT_H
+
+#include "OMStatus.h"
+
+#include "reader/OMCircleReader.h"
+#include "reader/OMWeightOnlyFormatReader.h"
+
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace core
+{
+
+class OMRuntimeContext
+{
+private:
+  reader::OMCircleReader _reader;
+  reader::OMWeightOnlyFormatReader _wof_reader;
+
+public:
+  OMRuntimeContext() = default;
+  OMRuntimeContext(const OMRuntimeContext &) = delete;
+  OMRuntimeContext &operator=(const OMRuntimeContext &) = delete;
+  OMRuntimeContext &&operator=(const OMRuntimeContext &&) = delete;
+  OMRuntimeContext(OMRuntimeContext &&) = default;
+  ~OMRuntimeContext() = default;
+
+  OMStatus setModel(const char *model_ptr, uint32_t graph_index)
+  {
+    OMStatus status;
+    status = _reader.parse(model_ptr);
+    if (status != Ok)
+      return status;
+    status = _reader.select_subgraph(graph_index);
+    if (status != Ok)
+      return status;
+    return Ok;
+  }
+
+  OMStatus setWofFile(char *wof_ptr)
+  {
+    OMStatus status;
+    _wof_reader.parse(wof_ptr);
+
+    status = _wof_reader.validate(&_reader);
+    if (status != Ok)
+      return status;
+    return Ok;
+  }
+
+  const bool isConstTensor(uint32_t tensor_index) { return _reader.isConstTensor(tensor_index); }
+
+  const reader::CircleValues *getCircleOutputs() { return _reader.outputs(); }
+  const reader::CircleValues *getCircleInputs() { return _reader.inputs(); }
+  const reader::CircleTensors *getCircleTensors() { return _reader.tensors(); }
+
+  const reader::CircleOperators *getCircleOperators();
+
+  const reader::CircleOperatorCodes *getCircleOpcodes() { return _reader.opcodes(); }
+
+  const circle::Operator *getCircleOperatorAt(uint16_t index);
+  const circle::Tensor *getTensorByIndex(int32_t tensor_index);
+
+  uint32_t getGraphInputTensorIndex(uint32_t index);
+  uint32_t getGraphOutputTensorIndex(uint32_t index);
+
+  OMStatus getConstDataByTensorIndex(uint8_t **data, uint16_t tensor_index);
+};
+
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_RUNTIME_CONTEXT_H
diff --git a/onert-micro/onert-micro/include/core/OMRuntimeGraph.h b/onert-micro/onert-micro/include/core/OMRuntimeGraph.h
new file mode 100644 (file)
index 0000000..410f5c7
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_RUNTIME_GRAPH_H
+#define ONERT_MICRO_CORE_RUNTIME_GRAPH_H
+
+#include "OMStatus.h"
+
+#include "OMRuntimeContext.h"
+#include "OMRuntimeStorage.h"
+#include "memory/OMRuntimeAllocator.h"
+
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace core
+{
+
+class OMRuntimeGraph
+{
+private:
+  OMRuntimeContext _context{};
+  OMRuntimeStorage _storage{};
+  memory::OMRuntimeAllocator _allocator{};
+
+public:
+  OMRuntimeGraph() = default;
+  OMRuntimeGraph(const OMRuntimeGraph &) = delete;
+  OMRuntimeGraph(OMRuntimeGraph &&) = default;
+  OMRuntimeGraph &operator=(const OMRuntimeGraph &) = delete;
+  OMRuntimeGraph &&operator=(const OMRuntimeGraph &&) = delete;
+  ~OMRuntimeGraph();
+
+  uint32_t getNumberOfInputs();
+  uint32_t getNumberOfOutputs();
+
+  uint32_t getInputSizeAt(uint32_t position);
+  uint32_t getOutputSizeAt(uint32_t position);
+
+  void *getInputDataAt(uint32_t position);
+  void *getOutputDataAt(uint32_t position);
+
+  size_t getInputDataTypeSize(uint32_t position);
+  size_t getOutputDataTypeSize(uint32_t position);
+
+  OMStatus allocateGraphInputs();
+
+  OMStatus reset();
+
+  OMRuntimeStorage &getRuntimeStorage() { return _storage; }
+
+  memory::OMRuntimeAllocator &getRuntimeAllocator() { return _allocator; }
+
+  OMRuntimeContext &getRuntimeContext() { return _context; }
+};
+
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_RUNTIME_GRAPH_H
diff --git a/onert-micro/onert-micro/include/core/OMRuntimeModule.h b/onert-micro/onert-micro/include/core/OMRuntimeModule.h
new file mode 100644 (file)
index 0000000..53ba519
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_RUNTIME_MODULE_H
+#define ONERT_MICRO_CORE_RUNTIME_MODULE_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+#include "OMRuntimeGraph.h"
+#include "core/reader/OMCircleReader.h"
+
+#include <vector>
+
+namespace onert_micro
+{
+namespace core
+{
+
+class OMRuntimeModule
+{
+protected:
+  std::vector<OMRuntimeGraph> _graphs;
+
+public:
+  OMRuntimeModule() = default;
+  OMRuntimeModule(const OMRuntimeModule &) = delete;
+  OMRuntimeModule(OMRuntimeModule &&) = delete;
+  OMRuntimeModule &operator=(const OMRuntimeModule &) = delete;
+  OMRuntimeModule &&operator=(const OMRuntimeModule &&) = delete;
+  ~OMRuntimeModule() = default;
+
+  OMStatus importModel(const char *model_ptr, const OMConfig &config);
+  OMStatus run();
+  OMStatus reset();
+
+  uint32_t getNumberOfInputs();
+  uint32_t getNumberOfOutputs();
+
+  uint32_t getInputSizeAt(uint32_t position);
+  uint32_t getOutputSizeAt(uint32_t position);
+
+  void *getInputDataAt(uint32_t position);
+  void *getOutputDataAt(uint32_t position);
+
+  OMStatus getRuntimeGraphAt(uint32_t pos, OMRuntimeGraph **runtime_graph);
+
+  OMStatus allocateInputs();
+};
+
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_RUNTIME_MODULE_H
diff --git a/onert-micro/onert-micro/include/core/OMRuntimeShape.h b/onert-micro/onert-micro/include/core/OMRuntimeShape.h
new file mode 100644 (file)
index 0000000..32d193b
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_RUNTIME_SHAPE_H
+#define ONERT_MICRO_CORE_RUNTIME_SHAPE_H
+
+#include "core/reader/OMCircleReader.h"
+
+#include <cstring>
+#include <cstdint>
+#include <cassert>
+
+namespace onert_micro
+{
+namespace core
+{
+
+static constexpr int maxTensorShapeSize = 6;
+
+class OMRuntimeShape
+{
+private:
+  int32_t _size = 0;
+  int32_t _dims[maxTensorShapeSize] = {0};
+
+public:
+  OMRuntimeShape(const OMRuntimeShape &other) : _size(other.dimensionsCount())
+  {
+    std::memcpy(dimsData(), other.dimsData(), sizeof(int32_t) * _size);
+  }
+
+  OMRuntimeShape(const circle::Tensor *tensor)
+  {
+    if (tensor == nullptr)
+      return;
+
+    _size = tensor->shape()->size();
+    std::memcpy(_dims, tensor->shape()->data(), 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; }
+
+  OMRuntimeShape() : _size(0) {}
+
+  explicit OMRuntimeShape(int dimensions_count) : _size(dimensions_count)
+  {
+    assert(dimensions_count <= maxTensorShapeSize);
+    assert(dimensions_count >= 0);
+  }
+
+  OMRuntimeShape(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));
+  }
+
+  OMRuntimeShape(int new_shape_size, const OMRuntimeShape &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());
+  }
+
+  OMRuntimeShape(int shape_size, int32_t value) : _size(0)
+  {
+    resize(shape_size);
+    for (int i = 0; i < shape_size; ++i)
+    {
+      setDim(i, value);
+    }
+  }
+
+  inline static OMRuntimeShape extendedShape(int new_shape_size, const OMRuntimeShape &shape)
+  {
+    return OMRuntimeShape(new_shape_size, shape, 1);
+  }
+
+  bool operator==(const OMRuntimeShape &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 <= maxTensorShapeSize);
+    assert(dimensions_count >= 0);
+    _size = dimensions_count;
+  }
+};
+
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_RUNTIME_SHAPE_H
diff --git a/onert-micro/onert-micro/include/core/OMRuntimeStorage.h b/onert-micro/onert-micro/include/core/OMRuntimeStorage.h
new file mode 100644 (file)
index 0000000..0a1e259
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_RUNTIME_STORAGE_H
+#define ONERT_MICRO_CORE_RUNTIME_STORAGE_H
+
+#include "OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "OMKernelType.h"
+
+#include <vector>
+#include <unordered_map>
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace core
+{
+
+class OMRuntimeStorage
+{
+private:
+#ifndef DIS_DYN_SHAPES
+  std::unordered_map<uint16_t, uint32_t> _tensor_index_to_dynamic_tensor_size;
+#endif
+  std::unordered_map<uint16_t, uint8_t *> _tensor_index_to_data;
+  std::unordered_map<uint16_t, OMKernelType> _operator_index_to_kernel_type;
+
+public:
+  OMRuntimeStorage() = default;
+  OMRuntimeStorage(const OMRuntimeStorage &) = delete;
+  OMRuntimeStorage(OMRuntimeStorage &&) = default;
+  OMRuntimeStorage &operator=(const OMRuntimeStorage &) = delete;
+  OMRuntimeStorage &&operator=(const OMRuntimeStorage &&) = delete;
+  ~OMRuntimeStorage() = default;
+
+  std::unordered_map<uint16_t, uint8_t *> &getTensorIndexToData() { return _tensor_index_to_data; }
+
+  OMStatus saveDataToTensorIndex(uint8_t *data, uint16_t tensor_index);
+
+  OMStatus removeTensorFromTensorIndexToData(uint16_t tensor_index);
+
+  OMStatus getDataByTensorIndex(uint8_t **data, uint16_t tensor_index);
+
+  OMKernelType getKernelType(uint16_t op_index)
+  {
+    auto it = _operator_index_to_kernel_type.find(op_index);
+    if (it == _operator_index_to_kernel_type.end())
+      return Normal;
+
+    return it->second;
+  }
+
+  OMStatus setKernelType(uint16_t op_index, OMKernelType type)
+  {
+    _operator_index_to_kernel_type[op_index] = type;
+    return Ok;
+  }
+#ifndef DIS_DYN_SHAPES
+  int32_t getDynamicTensorSize(uint16_t tensor_index)
+  {
+    auto it = _tensor_index_to_dynamic_tensor_size.find(tensor_index);
+    if (it == _tensor_index_to_dynamic_tensor_size.end())
+      return -1;
+
+    return it->second;
+  }
+
+  OMStatus setDynamicTensorSize(uint16_t tensor_index, uint32_t dynamic_size)
+  {
+    _tensor_index_to_dynamic_tensor_size[tensor_index] = dynamic_size;
+    return Ok;
+  }
+#endif // DIS_DYN_SHAPES
+
+  void clearTensorIndexToData() { _tensor_index_to_data.clear(); }
+};
+
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_RUNTIME_STORAGE_H
diff --git a/onert-micro/onert-micro/include/core/OMTrainingRuntimeModule.h b/onert-micro/onert-micro/include/core/OMTrainingRuntimeModule.h
new file mode 100644 (file)
index 0000000..d920137
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_TRAINING_RUNTIME_MODULE_H
+#define ONERT_MICRO_CORE_TRAINING_RUNTIME_MODULE_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+#include "core/OMRuntimeModule.h"
+#include "core/train/OMTrainingHandler.h"
+
+#include <vector>
+
+namespace onert_micro
+{
+namespace core
+{
+/*
+ * Class to handle all training process
+ */
+class OMTrainingRuntimeModule : public OMRuntimeModule
+{
+private:
+  // Store backwards graphs
+  std::vector<OMRuntimeGraph> _backward_graphs;
+  // Store training handler
+  train::OMTrainingHandler _training_handler;
+
+public:
+  OMTrainingRuntimeModule() = default;
+  OMTrainingRuntimeModule(const OMTrainingRuntimeModule &) = delete;
+  OMTrainingRuntimeModule(OMTrainingRuntimeModule &&) = delete;
+  OMTrainingRuntimeModule &operator=(const OMTrainingRuntimeModule &) = delete;
+  OMTrainingRuntimeModule &&operator=(const OMTrainingRuntimeModule &&) = delete;
+  ~OMTrainingRuntimeModule() = default;
+
+  // Import train model with current config settings
+  // Note: model ptr should be non-const to save result
+  OMStatus importTrainModel(char *model_ptr, const OMConfig &config);
+
+  // Train single step: run forward graph (with data which was set in SetInput) ->
+  // -> calculate error (with target data which was set in SetTarget) ->
+  // -> run backward graph -> update optimizer state -> after batch_size steps update weights
+  // Warning: before using trainSingleStep call: 1) importTrainModel; 2) setInput; 3) setTarget
+  OMStatus trainSingleStep(OMConfig &config);
+
+  // Reset all states and data saved into OMTrainingInterpreter (trained weights will not be reset)
+  OMStatus reset();
+
+  // Calculate and save metric into metric_val: run forward graph -> calculate metric
+  // Note: calculation will be done on test_size number of test samples
+  // Warning: before using evaluateMetric call: 1) importTrainModel; 2) setInput; 3) setTarget
+  // Note: number of the samples in data should be equal to the test_size
+  // Warning: 1) assume that all metric_val for all OMMetrics types actually are float values.
+  //          2) metric_val should be initialized with some value before calling this method due to
+  //             after calculation for current batch_num (the sequence number of the current sample)
+  //             this value is added to metric_val
+  OMStatus evaluateMetric(OMMetrics metric, void *metric_val, uint32_t test_size);
+
+  // Set input data for input with input_index
+  // Note: number of the samples in data should be equal to the batch_size in config structure
+  void setInputData(uint8_t *data, uint32_t input_index)
+  {
+    _training_handler.setInputData(data, input_index);
+  }
+  // Set target data for output with target_index
+  // Note: number of the samples in data should be equal to the batch_size in config structure
+  void setTargetData(uint8_t *data, uint32_t target_index)
+  {
+    _training_handler.setTargetData(data, target_index);
+  }
+
+  // Create and save checkpoint data into data_buffer vector
+  // To check checkpoint file format please see https://github.com/Samsung/ONE/discussions/13037
+  OMStatus createCheckpointFile(const OMConfig &config, std::vector<char> &data_buffer);
+
+  // Load checkpoints data and save it in model data and in config
+  // To check checkpoint file format please see https://github.com/Samsung/ONE/discussions/13037
+  OMStatus loadCheckpointData(OMConfig &config, const char *data);
+
+  void *getInputData(int32_t index);
+};
+
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_TRAINING_RUNTIME_MODULE_H
diff --git a/onert-micro/onert-micro/include/core/OMUtils.h b/onert-micro/onert-micro/include/core/OMUtils.h
new file mode 100644 (file)
index 0000000..7435796
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_UTILS_H
+#define ONERT_MICRO_CORE_UTILS_H
+
+#include "OMStatus.h"
+#include "core/reader/OMCircleReader.h"
+#include "core/OMRuntimeShape.h"
+
+#include <cassert>
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace core
+{
+namespace utils
+{
+
+OMStatus checkCondition(bool cond);
+
+template <typename T> const T *castInputData(uint8_t *tensor_data)
+{
+  return tensor_data != nullptr ? reinterpret_cast<const T *>(tensor_data) : nullptr;
+}
+
+template <typename T> T *castOutputData(uint8_t *tensor_data)
+{
+  return tensor_data != nullptr ? reinterpret_cast<T *>(tensor_data) : nullptr;
+}
+
+} // namespace utils
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_UTILS_H
diff --git a/onert-micro/onert-micro/include/core/memory/OMMemoryManager.h b/onert-micro/onert-micro/include/core/memory/OMMemoryManager.h
new file mode 100644 (file)
index 0000000..61fc8f8
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_MEMORY_MEMORY_MANAGER_H
+#define ONERT_MICRO_CORE_MEMORY_MEMORY_MANAGER_H
+
+#include "OMStatus.h"
+
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace core
+{
+namespace memory
+{
+
+struct OMMemoryManager
+{
+  static OMStatus allocateMemory(uint32_t size, uint8_t **data);
+  static OMStatus deallocateMemory(uint8_t *data);
+};
+
+} // namespace memory
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_MEMORY_MEMORY_MANAGER_H
diff --git a/onert-micro/onert-micro/include/core/memory/OMRuntimeAllocator.h b/onert-micro/onert-micro/include/core/memory/OMRuntimeAllocator.h
new file mode 100644 (file)
index 0000000..1e9d29a
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_MEMORY_RUNTIME_ALLOCATOR_H
+#define ONERT_MICRO_CORE_MEMORY_RUNTIME_ALLOCATOR_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeStorage.h"
+
+#include <vector>
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace core
+{
+namespace memory
+{
+
+class OMRuntimeAllocator
+{
+private:
+  std::vector<std::vector<uint16_t>> _alloc_plan;
+  std::vector<std::vector<uint16_t>> _dealloc_plan;
+
+public:
+  OMRuntimeAllocator() = default;
+  OMRuntimeAllocator(const OMRuntimeAllocator &) = delete;
+  OMRuntimeAllocator &operator=(const OMRuntimeAllocator &) = delete;
+  OMRuntimeAllocator &&operator=(const OMRuntimeAllocator &&) = delete;
+  OMRuntimeAllocator(OMRuntimeAllocator &&) = default;
+  ~OMRuntimeAllocator() = default;
+
+  void saveAllocPlan(std::vector<std::vector<uint16_t>> &&alloc_plan)
+  {
+    _alloc_plan.clear();
+    _alloc_plan = std::move(alloc_plan);
+  }
+
+  void saveDeallocPlan(std::vector<std::vector<uint16_t>> &&dealloc_plan)
+  {
+    _dealloc_plan.clear();
+    _dealloc_plan = std::move(dealloc_plan);
+  }
+
+  std::vector<std::vector<uint16_t>> &getAllocPlan() { return _alloc_plan; }
+
+  std::vector<std::vector<uint16_t>> &getDeallocPlan() { return _dealloc_plan; }
+
+  OMStatus allocateGraphInputs(OMRuntimeContext *context, OMRuntimeStorage *storage);
+
+  OMStatus clearAllTensorsData(OMRuntimeContext *context, OMRuntimeStorage *storage);
+
+  OMStatus allocate(size_t kernel_index, OMRuntimeContext *context, OMRuntimeStorage *storage);
+  OMStatus deallocate(size_t kernel_index, OMRuntimeStorage *storage);
+};
+
+} // namespace memory
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_MEMORY_RUNTIME_ALLOCATOR_H
diff --git a/onert-micro/onert-micro/include/core/reader/OMCircleReader.h b/onert-micro/onert-micro/include/core/reader/OMCircleReader.h
new file mode 100644 (file)
index 0000000..90c1d8a
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_READER_CIRCLE_READER_H
+#define ONERT_MICRO_CORE_READER_CIRCLE_READER_H
+
+#include "OMStatus.h"
+
+#include <circle-generated/circle/schema_generated.h>
+
+namespace onert_micro
+{
+namespace core
+{
+namespace reader
+{
+
+using CircleBuffers = flatbuffers::Vector<flatbuffers::Offset<circle::Buffer>>;
+using CircleTensors = flatbuffers::Vector<flatbuffers::Offset<circle::Tensor>>;
+using CircleOperators = flatbuffers::Vector<flatbuffers::Offset<circle::Operator>>;
+using CircleOperatorCodes = flatbuffers::Vector<flatbuffers::Offset<circle::OperatorCode>>;
+using CircleMetadataSet = flatbuffers::Vector<flatbuffers::Offset<circle::Metadata>>;
+using CircleValues = flatbuffers::Vector<int32_t>;
+
+/**
+ * @brief Loads Circle file and provides helpers to access attributes
+ */
+class OMCircleReader
+{
+public:
+  OMCircleReader() = default;
+  OMCircleReader(const OMCircleReader &) = delete;
+  OMCircleReader(OMCircleReader &&) = default;
+  OMCircleReader &operator=(const OMCircleReader &) = delete;
+  OMCircleReader &&operator=(const OMCircleReader &&) = delete;
+  ~OMCircleReader() = default;
+
+public: // direct API
+  const CircleOperatorCodes *opcodes() const { return _model->operator_codes(); }
+  const CircleBuffers *buffers() const { return _model->buffers(); }
+  const CircleTensors *tensors() const { return _current_subgraph->tensors(); }
+  const CircleOperators *operators() const { return _current_subgraph->operators(); }
+  const CircleValues *inputs() const { return _current_subgraph->inputs(); }
+  const CircleValues *outputs() const { return _current_subgraph->outputs(); }
+  const circle::DataFormat data_format() const { return _current_subgraph->data_format(); }
+  const CircleMetadataSet *metadata() const { return _model->metadata(); }
+
+  uint32_t num_subgraph() const { return _model->subgraphs()->size(); }
+  circle::BuiltinOperator builtin_code(const circle::Operator *op) const;
+
+public:
+  OMStatus parse(const char *model_ptr);
+  OMStatus select_subgraph(uint32_t subgraph);
+  uint32_t get_current_subgraph_index() const { return _current_subgraph_index; }
+
+  // helpers
+public:
+  bool isConstTensor(uint32_t tensor_index);
+
+private:
+  const circle::Model *_model{nullptr};
+  const circle::SubGraph *_current_subgraph{nullptr};
+  uint32_t _current_subgraph_index{0};
+};
+
+} // namespace reader
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_READER_CIRCLE_READER_H
diff --git a/onert-micro/onert-micro/include/core/reader/OMWeightOnlyFormatReader.h b/onert-micro/onert-micro/include/core/reader/OMWeightOnlyFormatReader.h
new file mode 100644 (file)
index 0000000..eee99de
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_READER_WEIGHT_ONLY_FORMAT_READER_H
+#define ONERT_MICRO_CORE_READER_WEIGHT_ONLY_FORMAT_READER_H
+
+#include "OMStatus.h"
+#include "OMCircleReader.h"
+
+namespace onert_micro
+{
+namespace core
+{
+namespace reader
+{
+namespace
+{
+
+enum WOFFieldsOffsets
+{
+  MAGIC_NUMBER = 0,
+  SCHEMA_VERSION = 2,
+  NUM_BUFFERS = 4,
+  FIRST_OFFSET = 8
+};
+
+} // namespace
+
+constexpr uint16_t wof_magic_number = 429;
+constexpr uint8_t schema_version = 1;
+
+/**
+ * @brief Loads Weight Only Format files and provides helpers functions
+ */
+class OMWeightOnlyFormatReader
+{
+public:
+  OMWeightOnlyFormatReader() = default;
+  OMWeightOnlyFormatReader(const OMWeightOnlyFormatReader &) = delete;
+  OMWeightOnlyFormatReader(OMWeightOnlyFormatReader &&) = default;
+  OMWeightOnlyFormatReader &operator=(const OMWeightOnlyFormatReader &) = delete;
+  OMWeightOnlyFormatReader &&operator=(const OMWeightOnlyFormatReader &&) = delete;
+  ~OMWeightOnlyFormatReader() = default;
+
+public: // direct API
+  // To validate _wof_ptr and compare with circle model saved in reader.
+  OMStatus validate(OMCircleReader *reader);
+
+  void parse(char *ptr) { _wof_ptr = ptr; }
+
+  // Find pointer to buffer in wof_ptr file for tensor with tensor_index.
+  // If tensor_index is not const, then return nullptr.
+  char *buffer(const uint32_t tensor_index);
+
+private:
+  char *_wof_ptr = nullptr;
+};
+
+} // namespace reader
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_READER_WEIGHT_ONLY_FORMAT_READER_H
diff --git a/onert-micro/onert-micro/include/core/train/OMCheckpointLoader.h b/onert-micro/onert-micro/include/core/train/OMCheckpointLoader.h
new file mode 100644 (file)
index 0000000..626c61e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_TRAIN_CHECKPOINT_LOADER_H
+#define ONERT_MICRO_CORE_TRAIN_CHECKPOINT_LOADER_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/train/OMTrainingStorage.h"
+
+namespace onert_micro
+{
+namespace core
+{
+namespace train
+{
+
+/*
+ * Class to load checkpoints files
+ * Note: class is stateless
+ */
+class OMCheckpointLoader
+{
+public:
+  OMCheckpointLoader() = default;
+  OMCheckpointLoader(const OMCheckpointLoader &) = delete;
+  OMCheckpointLoader(OMCheckpointLoader &&) = delete;
+  OMCheckpointLoader &operator=(const OMCheckpointLoader &) = delete;
+  OMCheckpointLoader &&operator=(const OMCheckpointLoader &&) = delete;
+  ~OMCheckpointLoader() = default;
+
+  // Load and save states from checkpoint data in model and in config
+  // To check checkpoint file format please see https://github.com/Samsung/ONE/discussions/13037
+  static OMStatus loadCheckpointData(core::OMRuntimeContext &context,
+                                     OMTrainingStorage &train_storage, const char *data,
+                                     OMConfig &config);
+
+private:
+  static OMStatus validateCheckpointData(core::OMRuntimeContext &context, const char *data,
+                                         OMConfig &config);
+
+  static OMStatus loadBuffers(core::OMRuntimeContext &context, OMTrainingStorage &train_storage,
+                              const char *data, OMConfig &config);
+};
+
+} // namespace train
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_TRAIN_CHECKPOINT_LOADER_H
diff --git a/onert-micro/onert-micro/include/core/train/OMCheckpointSaver.h b/onert-micro/onert-micro/include/core/train/OMCheckpointSaver.h
new file mode 100644 (file)
index 0000000..fbce18e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_TRAIN_CHECKPOINT_SAVER_H
+#define ONERT_MICRO_CORE_TRAIN_CHECKPOINT_SAVER_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/train/OMTrainingStorage.h"
+
+namespace onert_micro
+{
+namespace core
+{
+namespace train
+{
+
+/*
+ * Class to save checkpoints
+ * Note: class is stateless
+ */
+class OMCheckpointSaver
+{
+public:
+  OMCheckpointSaver() = default;
+  OMCheckpointSaver(const OMCheckpointSaver &) = delete;
+  OMCheckpointSaver(OMCheckpointSaver &&) = delete;
+  OMCheckpointSaver &operator=(const OMCheckpointSaver &) = delete;
+  OMCheckpointSaver &&operator=(const OMCheckpointSaver &&) = delete;
+  ~OMCheckpointSaver() = default;
+
+  // Create checkpoint data for current state
+  // To check checkpoint file format please see https://github.com/Samsung/ONE/discussions/13037
+  static OMStatus createCheckpointData(core::OMRuntimeContext &context,
+                                       OMTrainingStorage &train_storage, std::vector<char> &data,
+                                       const OMConfig &config);
+
+private:
+  static size_t calculateFileSize(core::OMRuntimeContext &context, OMTrainingStorage &train_storage,
+                                  const OMConfig &config);
+
+  static OMStatus writeOffsetsAndBuffers(core::OMRuntimeContext &context,
+                                         OMTrainingStorage &train_storage, const OMConfig &config,
+                                         std::vector<char> &data);
+};
+
+} // namespace train
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_TRAIN_CHECKPOINT_SAVER_H
diff --git a/onert-micro/onert-micro/include/core/train/OMTrainingHandler.h b/onert-micro/onert-micro/include/core/train/OMTrainingHandler.h
new file mode 100644 (file)
index 0000000..08efc77
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_TRAIN_TRAINING_HANDLER_H
+#define ONERT_MICRO_CORE_TRAIN_TRAINING_HANDLER_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/train/OMTrainingStorage.h"
+
+namespace onert_micro
+{
+namespace core
+{
+namespace train
+{
+
+/*
+ * Class to handle training process
+ */
+class OMTrainingHandler
+{
+  OMTrainingStorage _training_storage;
+
+public:
+  OMTrainingHandler() = default;
+  OMTrainingHandler(const OMTrainingHandler &) = delete;
+  OMTrainingHandler(OMTrainingHandler &&) = delete;
+  OMTrainingHandler &operator=(const OMTrainingHandler &) = delete;
+  OMTrainingHandler &&operator=(const OMTrainingHandler &&) = delete;
+  ~OMTrainingHandler() = default;
+
+  // Save input and target data in OMTrainingStorage
+  void setInputData(uint8_t *data, uint32_t input_index)
+  {
+    _training_storage.setInputData(data, input_index);
+  }
+  void setTargetData(uint8_t *data, uint32_t target_index)
+  {
+    _training_storage.setTargetData(data, target_index);
+  }
+
+  // Get input and target data from OMTrainingStorage
+  uint8_t *getInputData(uint32_t input_index)
+  {
+    return _training_storage.getInputData(input_index);
+  }
+  uint8_t *getTargetData(uint32_t target_index)
+  {
+    return _training_storage.getTargetData(target_index);
+  }
+
+  // Handle with current error function (defined in config).
+  // Calculate backpropagation error between target and calculated data.
+  // Batch_num - number of current sample in current batch (needed to calculate offset to get
+  // current target sample)
+  OMStatus handleError(const OMConfig &config, OMRuntimeStorage &forward_storage,
+                       OMRuntimeStorage &backward_storage, OMRuntimeContext &context,
+                       uint32_t batch_num);
+  // Handle with updating optimizer state
+  OMStatus updateOptimizerState(const OMConfig &config, OMRuntimeStorage &backward_storage,
+                                OMRuntimeContext &context);
+
+  // Handle with updating weights with current optimizer
+  OMStatus updateWeights(const OMConfig &config, OMRuntimeContext &context);
+
+  // Evaluate metric and save result in metric_val
+  // Warning: 1) assume that all metric_val for all OMMetrics types actually are float values.
+  //          2) metric_val should be initialized with some value before calling this method due to
+  //             after calculation for current batch_num (the sequence number of the current sample)
+  //             this value is added to metric_val
+  OMStatus evaluateMetric(OMMetrics metric, void *metric_val, OMRuntimeStorage &storage,
+                          OMRuntimeContext &context, uint32_t batch_num);
+
+  // Save optimizer in OMTrainingStorage
+  OMStatus setOptimizer(const OMConfig &config) { return _training_storage.setOptimizer(config); }
+
+  // Get training storage
+  OMTrainingStorage &getTrainingStorage() { return _training_storage; }
+
+  // Reset and deallocate all internal states
+  void reset();
+};
+
+} // namespace train
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_TRAIN_TRAINING_HANDLER_H
diff --git a/onert-micro/onert-micro/include/core/train/OMTrainingStorage.h b/onert-micro/onert-micro/include/core/train/OMTrainingStorage.h
new file mode 100644 (file)
index 0000000..55f7f11
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CORE_TRAIN_TRAINING_STORAGE_H
+#define ONERT_MICRO_CORE_TRAIN_TRAINING_STORAGE_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+#include "train/train_optimizers/SGD.h"
+#include "train/train_optimizers/Adam.h"
+
+#include <unordered_map>
+#include <memory>
+
+namespace onert_micro
+{
+namespace core
+{
+namespace train
+{
+
+/*
+ * Class to store training specific information
+ */
+class OMTrainingStorage
+{
+  // Store mapping between input tensor (its input_index) and its current input data.
+  // The input data must have a number of samples equal to batch_size
+  std::unordered_map<uint32_t, uint8_t *> _input_index_to_input_data;
+  // Store mapping between output tensor (its output_index) and its current target data.
+  // The target data must have a number of samples equal to batch_size
+  std::unordered_map<uint32_t, uint8_t *> _target_index_to_target_data;
+
+  // Store SGD optimizer with its own internal states
+  // Note: initial its null
+  std::unique_ptr<onert_micro::train::optimizers::SGD> _sgd_optimizer = nullptr;
+  // Store Adam optimizer with its own internal states
+  // Note: initial its null
+  std::unique_ptr<onert_micro::train::optimizers::Adam> _adam_optimizer = nullptr;
+
+public:
+  OMTrainingStorage() = default;
+  OMTrainingStorage(const OMTrainingStorage &) = delete;
+  OMTrainingStorage(OMTrainingStorage &&) = delete;
+  OMTrainingStorage &operator=(const OMTrainingStorage &) = delete;
+  OMTrainingStorage &&operator=(const OMTrainingStorage &&) = delete;
+  ~OMTrainingStorage() = default;
+
+  // Set input data for current input tensor
+  void setInputData(uint8_t *data, uint32_t input_index)
+  {
+    _input_index_to_input_data[input_index] = data;
+  }
+  // Set target data for current output tensor
+  void setTargetData(uint8_t *data, uint32_t target_index)
+  {
+    _target_index_to_target_data[target_index] = data;
+  }
+
+  // Choose and set optimizer defined in config
+  OMStatus setOptimizer(const OMConfig &config);
+
+  // Get pointer to SGD optimizer
+  // Note: can return nullptr
+  onert_micro::train::optimizers::SGD *getSGD() { return _sgd_optimizer.get(); }
+  // Get pointer to Adam optimizer
+  // Note: can return nullptr
+  onert_micro::train::optimizers::Adam *getAdam() { return _adam_optimizer.get(); }
+
+  // Get pointer to saved input data for current input tensor
+  uint8_t *getInputData(uint32_t input_index) { return _input_index_to_input_data[input_index]; }
+  // Get pointer to saved target data for current output tensor
+  uint8_t *getTargetData(uint32_t target_index)
+  {
+    return _target_index_to_target_data[target_index];
+  }
+
+  // Reset and deallocate all states
+  void reset();
+};
+
+} // namespace train
+} // namespace core
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_CORE_TRAIN_TRAINING_STORAGE_H
diff --git a/onert-micro/onert-micro/include/execute/OMExecuteArgs.h b/onert-micro/onert-micro/include/execute/OMExecuteArgs.h
new file mode 100644 (file)
index 0000000..196f68a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_EXECUTE_ARGS_H
+#define ONERT_MICRO_EXECUTE_EXECUTE_ARGS_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeModule.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+
+struct OMExecuteArgs
+{
+  core::OMRuntimeStorage &runtime_storage;
+  core::OMRuntimeContext &runtime_context;
+  uint16_t kernel_index;
+  core::OMRuntimeModule &runtime_module;
+};
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_EXECUTE_ARGS_H
diff --git a/onert-micro/onert-micro/include/execute/OMKernelExecute.h b/onert-micro/onert-micro/include/execute/OMKernelExecute.h
new file mode 100644 (file)
index 0000000..9ba9491
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNEL_EXECUTE_H
+#define ONERT_MICRO_EXECUTE_KERNEL_EXECUTE_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeStorage.h"
+#include "execute/OMExecuteArgs.h"
+#include "core/memory/OMRuntimeAllocator.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+
+struct OMKernelExecute
+{
+  static OMStatus runForward(OMExecuteArgs &, core::memory::OMRuntimeAllocator &allocator);
+};
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNEL_EXECUTE_H
diff --git a/onert-micro/onert-micro/include/execute/OMKernelExecutionBuilder.h b/onert-micro/onert-micro/include/execute/OMKernelExecutionBuilder.h
new file mode 100644 (file)
index 0000000..1281b65
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNEL_EXECUTION_BUILDER_H
+#define ONERT_MICRO_EXECUTE_KERNEL_EXECUTION_BUILDER_H
+
+#include "core/reader/OMCircleReader.h"
+#include "core/OMKernelType.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeContext.h"
+#include "execute/OMExecuteArgs.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+
+using KernelExecuteFunc = OMStatus(const OMExecuteArgs &);
+
+#define REGISTER_KERNEL(builtin_operator, name) \
+  OMStatus execute_kernel_Circle##name(const OMExecuteArgs &);
+#include "KernelsToBuild.lst"
+#undef REGISTER_KERNEL
+
+#define REGISTER_CUSTOM_KERNEL(name, string_name) \
+  OMStatus execute_kernel_Circle##name(const OMExecuteArgs &);
+#include "CustomKernelsToBuild.lst"
+#undef REGISTER_CUSTOM_KERNEL
+
+class KernelBuiltinExecuteRegistry
+{
+public:
+  constexpr KernelBuiltinExecuteRegistry() : _operator_execute()
+  {
+#define REGISTER_KERNEL(builtin_operator, name)                                \
+  registerKernelExecute(core::OMBuilderID::BuiltinOperator_##builtin_operator, \
+                        execute_kernel_Circle##name);
+
+#include "KernelsToBuild.lst"
+
+#undef REGISTER_KERNEL
+  }
+
+public:
+  OMStatus getKernelExecuteFunc(core::OMBuilderID builderID, KernelExecuteFunc **execute_func) const
+  {
+    const auto builder_id_opcode = size_t(builderID);
+    assert(builder_id_opcode < size_t(core::OMBuilderID::BuiltinOperatorsSize));
+    if (builder_id_opcode >= size_t(core::OMBuilderID::BuiltinOperatorsSize))
+    {
+      *execute_func = nullptr;
+      return UnknownError;
+    }
+    *execute_func = _operator_execute[builder_id_opcode];
+    return Ok;
+  }
+
+private:
+  constexpr void registerKernelExecute(core::OMBuilderID id, KernelExecuteFunc *func)
+  {
+    assert(size_t(id) < size_t(core::OMBuilderID::BuiltinOperatorsSize));
+    _operator_execute[size_t(id)] = func;
+  }
+
+private:
+  KernelExecuteFunc *_operator_execute[size_t(core::OMBuilderID::BuiltinOperatorsSize)];
+};
+
+class KernelCustomExecuteRegistry
+{
+public:
+  constexpr KernelCustomExecuteRegistry() : _operator_execute()
+  {
+#define REGISTER_CUSTOM_KERNEL(name, string_name) \
+  registerKernelExecute(core::OMBuilderID::CUSTOM_##name, execute_kernel_Circle##name);
+
+#include "CustomKernelsToBuild.lst"
+
+#undef REGISTER_CUSTOM_KERNEL
+  }
+
+public:
+  OMStatus getKernelExecuteFunc(core::OMBuilderID builderID, KernelExecuteFunc **execute_func) const
+  {
+    auto builder_id_opcode = size_t(builderID);
+    if (builder_id_opcode >= size_t(core::OMBuilderID::Size))
+    {
+      *execute_func = nullptr;
+      return UnknownError;
+    }
+    const auto builder_id_offset = size_t(core::OMBuilderID::BuiltinOperatorsSize);
+    builder_id_opcode -= builder_id_offset - 1;
+
+    *execute_func = _operator_execute[builder_id_opcode];
+    return Ok;
+  }
+
+private:
+  constexpr void registerKernelExecute(core::OMBuilderID id, KernelExecuteFunc *func)
+  {
+    auto builder_id_opcode = size_t(id);
+    const auto builder_id_offset = size_t(core::OMBuilderID::BuiltinOperatorsSize);
+    builder_id_opcode = builder_id_opcode - builder_id_offset - 1;
+    _operator_execute[builder_id_opcode] = func;
+  }
+
+private:
+  KernelExecuteFunc *_operator_execute[size_t(core::OMBuilderID::Size) -
+                                       size_t(core::OMBuilderID::BuiltinOperatorsSize) - 1];
+};
+
+// Global constexpr kernel builtin and custom execute
+constexpr KernelBuiltinExecuteRegistry kernel_builtin_execute;
+constexpr KernelCustomExecuteRegistry kernel_custom_execute;
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNEL_EXECUTION_BUILDER_H
diff --git a/onert-micro/onert-micro/include/execute/OMRuntimeKernel.h b/onert-micro/onert-micro/include/execute/OMRuntimeKernel.h
new file mode 100644 (file)
index 0000000..b6f63cd
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_RUNTIME_KERNEL_H
+#define ONERT_MICRO_EXECUTE_RUNTIME_KERNEL_H
+
+#include "core/reader/OMCircleReader.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeStorage.h"
+
+#include <cstdint>
+
+constexpr static uint32_t maxInputSize = 5;
+constexpr static uint32_t maxOutputSize = 5;
+
+namespace onert_micro
+{
+namespace execute
+{
+
+class OMRuntimeKernel
+{
+public:
+  OMRuntimeKernel() = default;
+  OMRuntimeKernel(const OMRuntimeKernel &) = delete;
+  OMRuntimeKernel(OMRuntimeKernel &&) = delete;
+  ~OMRuntimeKernel() = default;
+  OMRuntimeKernel &operator=(const OMRuntimeKernel &) = delete;
+  OMRuntimeKernel &&operator=(const OMRuntimeKernel &&) = delete;
+
+public:
+  OMStatus readKernel(uint16_t op_index, core::OMRuntimeContext &runtime_context);
+
+  OMStatus getDataFromStorage(uint16_t op_index, core::OMRuntimeStorage &storage,
+                              core::OMRuntimeContext &context);
+
+public:
+  const circle::Tensor *inputs[maxInputSize] = {nullptr};
+  const circle::Tensor *outputs[maxOutputSize] = {nullptr};
+
+  uint8_t *inputs_data[maxInputSize] = {nullptr};
+  uint8_t *outputs_data[maxOutputSize] = {nullptr};
+
+  int32_t inputs_index[maxInputSize] = {-1};
+  int32_t outputs_index[maxOutputSize] = {-1};
+
+  uint32_t outputs_num = 0;
+  uint32_t inputs_num = 0;
+
+  const circle::Operator *first_operator = nullptr;
+};
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_RUNTIME_KERNEL_H
diff --git a/onert-micro/onert-micro/include/execute/OMTestUtils.h b/onert-micro/onert-micro/include/execute/OMTestUtils.h
new file mode 100644 (file)
index 0000000..70a2302
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_TESTUTILS_H
+#define ONERT_MICRO_EXECUTE_TESTUTILS_H
+
+#include "test_models/TestDataBase.h"
+#include "OMInterpreter.h"
+
+#include <type_traits>
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+// 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, typename U = T>
+std::vector<U> checkKernel(uint32_t num_inputs,
+                           onert_micro::test_model::TestDataBase<T, U> *test_data_base)
+{
+  onert_micro::OMInterpreter interpreter;
+  onert_micro::OMConfig config;
+
+  interpreter.importModel(reinterpret_cast<const char *>(test_data_base->get_model_ptr()), config);
+
+  assert(num_inputs == interpreter.getNumberOfInputs());
+
+  for (uint32_t i = 0; i < num_inputs; ++i)
+  {
+    T *input_data = reinterpret_cast<T *>(interpreter.getInputDataAt(i));
+
+    // Set input data
+    {
+      std::copy(test_data_base->get_input_data_by_index(i).begin(),
+                test_data_base->get_input_data_by_index(i).end(), input_data);
+    }
+  }
+
+  interpreter.run();
+
+  U *output_data = reinterpret_cast<U *>(interpreter.getOutputDataAt(0));
+  const size_t num_elements = interpreter.getOutputSizeAt(0);
+  std::vector<U> output_data_vector(output_data, output_data + num_elements);
+  return output_data_vector;
+}
+
+void checkNEGSISOKernel(onert_micro::test_model::NegTestDataBase *test_data_base);
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_TESTUTILS_H
diff --git a/onert-micro/onert-micro/include/execute/OMUtils.h b/onert-micro/onert-micro/include/execute/OMUtils.h
new file mode 100644 (file)
index 0000000..abb7a80
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_UTILS_H
+#define ONERT_MICRO_EXECUTE_UTILS_H
+
+#include <cmath>
+#include "OMStatus.h"
+#include "core/reader/OMCircleReader.h"
+#include "core/OMRuntimeShape.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+
+void readQuantParams(const circle::Tensor *tensor, long &zero_point, float &scale);
+template <typename T>
+OMStatus calculateActivationRange(circle::ActivationFunctionType activation, T *activation_min,
+                                  T *activation_max)
+{
+  switch (activation)
+  {
+    case circle::ActivationFunctionType::ActivationFunctionType_NONE:
+      *activation_min = std::numeric_limits<T>::lowest();
+      *activation_max = std::numeric_limits<T>::max();
+      break;
+    case circle::ActivationFunctionType::ActivationFunctionType_RELU:
+      *activation_min = 0;
+      *activation_max = std::numeric_limits<T>::max();
+      break;
+    case circle::ActivationFunctionType::ActivationFunctionType_RELU_N1_TO_1:
+      *activation_min = -1;
+      *activation_max = 1;
+      break;
+    case circle::ActivationFunctionType::ActivationFunctionType_RELU6:
+      *activation_min = 0;
+      *activation_max = 6;
+      break;
+    default:
+      assert(false && "Unsupported activation.");
+      return UnsupportedActivation;
+  }
+
+  return Ok;
+}
+
+inline double getQuantizedConvolutionMultipler(float input_scale, float filter_scale,
+                                               float output_scale)
+{
+  const double input_product_scale = static_cast<double>(input_scale * filter_scale);
+
+  assert(input_product_scale >= 0);
+
+  assert(output_scale != 0.f);
+
+  return input_product_scale / static_cast<double>(output_scale);
+}
+
+// Decompose a double multiplier into a Q0.31 int32 representation of its
+// significand, and shift representation of its exponent.
+//
+// Handles an arbitrary positive multiplier. The 'shift' output-value is
+// basically the 'floating-point exponent' of the multiplier:
+// Negative for a right-shift (when the multiplier is <1), positive for a
+// left-shift (when the multiplier is >1)
+void quantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift);
+
+// Decompose a double multiplier into a Q0.31 int32 representation of its
+// significand, and shift representation of NEGATIVE its exponent ---
+// this is intended as a RIGHT-shift.
+//
+// Restricted to the case where the multiplier < 1 (and non-negative).
+void quantizeMultiplierSmallerThanOneExp(double double_multiplier, int32_t *quantized_multiplier,
+                                         int *left_shift);
+
+inline std::vector<double>
+getQuantizedConvolutionMultiplers(float input_scale, const flatbuffers::Vector<float> *filter_scale,
+                                  float output_scale)
+{
+  std::vector<double> effective_output_scales;
+  size_t n = filter_scale->size();
+  effective_output_scales.reserve(n);
+  for (size_t i = 0; i < n; ++i)
+  {
+    effective_output_scales.push_back(
+      getQuantizedConvolutionMultipler(input_scale, filter_scale->operator[](i), output_scale));
+  }
+  return effective_output_scales;
+}
+
+OMStatus calculateActivationRangeQuantized(circle::ActivationFunctionType activation,
+                                           int32_t output_zero_point, float output_scale,
+                                           circle::TensorType data_type, int32_t *activation_min,
+                                           int32_t *activation_max);
+
+inline int computeOutSize(circle::Padding padding, int image_size, int filter_size, int stride,
+                          int dilation_rate = 1)
+{
+  int effective_filter_size = (filter_size - 1) * dilation_rate + 1;
+
+  if (stride == 0)
+    return 0;
+
+  switch (padding)
+  {
+    case circle::Padding_SAME:
+      return (image_size + stride - 1) / stride;
+    case circle::Padding_VALID:
+      return (image_size + stride - effective_filter_size) / stride;
+    default:
+      return 0;
+  }
+}
+
+inline int computePadding(int32_t stride, int32_t dilation_rate, int32_t in_size,
+                          int32_t filter_size, int32_t out_size)
+{
+  int32_t effective_filter_size = (filter_size - 1) * dilation_rate + 1;
+  int32_t padding = ((out_size - 1) * stride + effective_filter_size - in_size) / 2;
+  return padding > 0 ? padding : 0;
+}
+
+inline void computePaddingHeightWidth(int32_t stride_height, int32_t stride_width,
+                                      int32_t dilation_rate_height, int32_t dilation_rate_width,
+                                      int32_t in_height, int32_t in_width, int32_t filter_height,
+                                      int32_t filter_width, circle::Padding padding,
+                                      int32_t *padding_h, int32_t *padding_w)
+{
+
+  int out_width =
+    computeOutSize(padding, in_width, filter_width, stride_width, dilation_rate_width);
+  int out_height =
+    computeOutSize(padding, in_height, filter_height, stride_height, dilation_rate_height);
+
+  *padding_h =
+    computePadding(stride_height, dilation_rate_height, in_height, filter_height, out_height);
+
+  *padding_w = computePadding(stride_width, dilation_rate_width, in_width, filter_width, out_width);
+}
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_UTILS_H
diff --git a/onert-micro/onert-micro/include/execute/kernels/ArgCommon.h b/onert-micro/onert-micro/include/execute/kernels/ArgCommon.h
new file mode 100644 (file)
index 0000000..7dd3b26
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNELS_ARG_COMMON_H
+#define ONERT_MICRO_EXECUTE_KERNELS_ARG_COMMON_H
+
+#include "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+#include <functional>
+
+namespace onert_micro
+{
+namespace execute
+{
+
+OMStatus execute_arg_common(
+  const OMExecuteArgs &execute_args,
+  const std::function<OMStatus(const core::OMRuntimeShape &input1_shape, const float *input1_data,
+                               const int *input2_data, const core::OMRuntimeShape &output_shape,
+                               int *output_data)> &f_float);
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNELS_ARG_COMMON_H
diff --git a/onert-micro/onert-micro/include/execute/kernels/ComparisonCommon.h b/onert-micro/onert-micro/include/execute/kernels/ComparisonCommon.h
new file mode 100644 (file)
index 0000000..5aea894
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNELS_COMPARISONCOMMON_H
+#define ONERT_MICRO_EXECUTE_KERNELS_COMPARISONCOMMON_H
+
+#include "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "execute/OMUtils.h"
+#include "core/OMKernelData.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALComparisons.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+template <typename T>
+void readDataKernel(OMRuntimeKernel *runtime_kernel, const T *&cast_input_data1,
+                    const T *&cast_input_data2, bool *&cast_output_data,
+                    core::OMRuntimeShape &input1_shape_ref, core::OMRuntimeShape &input2_shape_ref,
+                    core::OMRuntimeShape &output_shape_ref)
+{
+  const circle::Tensor *input1 = nullptr;
+  const circle::Tensor *input2 = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input_data1 = nullptr;
+  uint8_t *input_data2 = nullptr;
+  uint8_t *output_data = nullptr;
+
+  input1 = runtime_kernel->inputs[input1TensorIdx];
+  input2 = runtime_kernel->inputs[input2TensorIdx];
+  output = runtime_kernel->outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  input_data1 = runtime_kernel->inputs_data[input1TensorIdx];
+  input_data2 = runtime_kernel->inputs_data[input2TensorIdx];
+  output_data = runtime_kernel->outputs_data[outputTensorIdx];
+
+  assert(input_data1 != nullptr);
+  assert(input_data2 != nullptr);
+  assert(output_data != nullptr);
+
+  cast_input_data1 = core::utils::castInputData<T>(input_data1);
+  cast_input_data2 = core::utils::castInputData<T>(input_data2);
+  cast_output_data = core::utils::castOutputData<bool>(output_data);
+
+  input1_shape_ref = std::move(core::OMRuntimeShape(input1));
+  input2_shape_ref = std::move(core::OMRuntimeShape(input2));
+  output_shape_ref = std::move(core::OMRuntimeShape(output));
+}
+
+template <typename T> void evalComparisonGeneric(OMRuntimeKernel *runtime_kernel, bool F(T, T))
+{
+
+  const T *cast_input_data1 = nullptr;
+  const T *cast_input_data2 = nullptr;
+  bool *cast_output_data = nullptr;
+
+  core::OMRuntimeShape input1_shape;
+  core::OMRuntimeShape input2_shape;
+  core::OMRuntimeShape output_shape;
+
+  readDataKernel(runtime_kernel, cast_input_data1, cast_input_data2, cast_output_data, input1_shape,
+                 input2_shape, output_shape);
+
+  onert_micro::core::ComparisonParams op_params;
+  op_params.is_broadcast = input1_shape.flatSize() != input2_shape.flatSize();
+
+  if (op_params.is_broadcast)
+  {
+    onert_micro::execute::pal::BroadcastComparison4DSlowNoScaling<T>(
+      op_params, input1_shape, cast_input_data1, input2_shape, cast_input_data2, output_shape,
+      cast_output_data, F);
+  }
+  else
+  {
+    const int64_t flat_size = input1_shape.flatSize();
+    onert_micro::execute::pal::ComparisonNoScaling<T>(flat_size, cast_input_data1, cast_input_data2,
+                                                      cast_output_data, F);
+  }
+}
+
+template <typename T>
+void evalQuantizedComparisonGeneric(OMRuntimeKernel *runtime_kernel, bool F(T, T))
+{
+  const circle::Tensor *input1 = nullptr;
+  const circle::Tensor *input2 = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  input1 = runtime_kernel->inputs[input1TensorIdx];
+  input2 = runtime_kernel->inputs[input2TensorIdx];
+  output = runtime_kernel->outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  const T *cast_input_data1 = nullptr;
+  const T *cast_input_data2 = nullptr;
+  bool *cast_output_data = nullptr;
+
+  core::OMRuntimeShape input1_shape;
+  core::OMRuntimeShape input2_shape;
+  core::OMRuntimeShape output_shape;
+
+  readDataKernel(runtime_kernel, cast_input_data1, cast_input_data2, cast_output_data, input1_shape,
+                 input2_shape, output_shape);
+
+  assert(input1->quantization() != nullptr);
+  assert(input1->quantization()->scale() != nullptr);
+  assert(input1->quantization()->scale()->size() == 1);
+  assert(input1->quantization()->zero_point() != nullptr);
+  assert(input1->quantization()->zero_point()->size() == 1);
+
+  auto input1_scale = *input1->quantization()->scale()->begin();
+  auto input2_scale = *input2->quantization()->scale()->begin();
+
+  auto input1_zero_point = *input1->quantization()->zero_point()->begin();
+  auto input2_zero_point = *input2->quantization()->zero_point()->begin();
+
+  int32_t x_multiplier;
+  int x_shift;
+
+  int32_t y_multiplier;
+  int y_shift;
+
+  onert_micro::execute::quantizeMultiplierSmallerThanOneExp(input1_scale, &x_multiplier, &x_shift);
+  onert_micro::execute::quantizeMultiplierSmallerThanOneExp(input2_scale, &y_multiplier, &y_shift);
+
+  onert_micro::core::ComparisonParams op_params;
+  op_params.left_shift = 8;
+  op_params.input1_offset = -input1_zero_point; // Note the '-'
+  op_params.input1_shift = x_shift;
+  op_params.input1_multiplier = x_multiplier;
+  op_params.input2_offset = -input2_zero_point; // Note the '-'
+  op_params.input2_shift = y_shift;
+  op_params.input2_multiplier = y_multiplier;
+  op_params.is_broadcast = input1_shape.flatSize() != input2_shape.flatSize();
+  ;
+
+  if (op_params.is_broadcast)
+  {
+    onert_micro::execute::pal::BroadcastComparison4DSlowWithScaling<T>(
+      op_params, input1_shape, cast_input_data1, input2_shape, cast_input_data2, output_shape,
+      cast_output_data, F);
+  }
+  else
+  {
+    const int64_t flat_size = input1_shape.flatSize();
+    onert_micro::execute::pal::ComparisonWithScaling<T>(op_params, flat_size, cast_input_data1,
+                                                        cast_input_data2, cast_output_data, F);
+  }
+}
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNELS_COMPARISONCOMMON_H
diff --git a/onert-micro/onert-micro/include/execute/kernels/ConvolutionCommon.h b/onert-micro/onert-micro/include/execute/kernels/ConvolutionCommon.h
new file mode 100644 (file)
index 0000000..355ea3c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNELS_CONVOLUTION_COMMON_H
+#define ONERT_MICRO_EXECUTE_KERNELS_CONVOLUTION_COMMON_H
+
+#include "OMStatus.h"
+
+#include "core/OMKernelData.h"
+#include "core/OMRuntimeShape.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+
+OMStatus createConvParams(core::ConvQuant &params, const circle::Tensor *input,
+                          const circle::Tensor *filter, const circle::Tensor *output,
+                          circle::ActivationFunctionType act_type);
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNELS_CONVOLUTION_COMMON_H
diff --git a/onert-micro/onert-micro/include/execute/kernels/MathCommon.h b/onert-micro/onert-micro/include/execute/kernels/MathCommon.h
new file mode 100644 (file)
index 0000000..433437b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNELS_MATH_COMMON_H
+#define ONERT_MICRO_EXECUTE_KERNELS_MATH_COMMON_H
+
+#include "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+#include "core/OMDataType.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+#include <functional>
+
+namespace onert_micro
+{
+namespace execute
+{
+
+OMStatus execute_math_common(
+  const OMExecuteArgs &execute_args,
+  const std::function<OMStatus(const core::OMRuntimeShape &input_shape, const float *input_data,
+                               const core::OMRuntimeShape &output_shape, float *output_data)>
+    &f_float);
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNELS_MATH_COMMON_H
diff --git a/onert-micro/onert-micro/include/execute/kernels/PoolingCommon.h b/onert-micro/onert-micro/include/execute/kernels/PoolingCommon.h
new file mode 100644 (file)
index 0000000..0e8da8e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNELS_POOLING_COMMON_H
+#define ONERT_MICRO_EXECUTE_KERNELS_POOLING_COMMON_H
+
+#include "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+#include <functional>
+
+namespace onert_micro
+{
+namespace execute
+{
+
+OMStatus execute_pooling_common(
+  const OMExecuteArgs &execute_args,
+  const std::function<OMStatus(const core::Pool2DParams &params,
+                               const core::OMRuntimeShape &input_shape, const float *input_data,
+                               const core::OMRuntimeShape &output_shape, float *output_data)>
+    &f_float,
+  const std::function<OMStatus(const core::Pool2DParams &params,
+                               const core::OMRuntimeShape &input_shape, const int8_t *input_data,
+                               const core::OMRuntimeShape &output_shape, int8_t *output_data)>
+    &f_int8);
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNELS_POOLING_COMMON_H
diff --git a/onert-micro/onert-micro/include/execute/kernels/ReadKernelDataCommon.h b/onert-micro/onert-micro/include/execute/kernels/ReadKernelDataCommon.h
new file mode 100644 (file)
index 0000000..754250a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNELS_READDATACOMMON_H
+#define ONERT_MICRO_EXECUTE_KERNELS_READDATACOMMON_H
+
+#include "OMStatus.h"
+#include "core/OMKernelData.h"
+#include "core/OMRuntimeShape.h"
+#include "execute/OMRuntimeKernel.h"
+#include "execute/OMKernelExecutionBuilder.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+
+OMStatus readKernelDataTISO(const OMExecuteArgs &execute_args, uint8_t *&input_data1,
+                            uint8_t *&input_data2, uint8_t *&output_data,
+                            core::OMRuntimeShape &input1_shape_ref,
+                            core::OMRuntimeShape &input2_shape_ref,
+                            core::OMRuntimeShape &output_shape_ref,
+                            circle::TensorType &tensor_type);
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNELS_READDATACOMMON_H
diff --git a/onert-micro/onert-micro/include/execute/kernels/ReluCommon.h b/onert-micro/onert-micro/include/execute/kernels/ReluCommon.h
new file mode 100644 (file)
index 0000000..17edf38
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNELS_RESHAPE_COMMON_H
+#define ONERT_MICRO_EXECUTE_KERNELS_RESHAPE_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMUtils.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+
+OMStatus execute_relu_common(const OMExecuteArgs &execute_args, bool is_relu_6);
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNELS_RESHAPE_COMMON_H
diff --git a/onert-micro/onert-micro/include/execute/kernels/ReshapeCommon.h b/onert-micro/onert-micro/include/execute/kernels/ReshapeCommon.h
new file mode 100644 (file)
index 0000000..d637361
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNELS_RESHAPE_COMMON_H
+#define ONERT_MICRO_EXECUTE_KERNELS_RESHAPE_COMMON_H
+
+#include "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+#include "core/OMDataType.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+#include <functional>
+
+namespace onert_micro
+{
+namespace execute
+{
+
+OMStatus execute_reshape_common(const OMExecuteArgs &execute_args);
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNELS_RESHAPE_COMMON_H
diff --git a/onert-micro/onert-micro/include/execute/kernels/SpacesBatchesNDCommon.h b/onert-micro/onert-micro/include/execute/kernels/SpacesBatchesNDCommon.h
new file mode 100644 (file)
index 0000000..482f0d9
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_KERNELS_SPACES_BATCHES_ND_COMMON_H
+#define ONERT_MICRO_EXECUTE_KERNELS_SPACES_BATCHES_ND_COMMON_H
+
+#include "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+#include <functional>
+
+namespace onert_micro
+{
+namespace execute
+{
+
+OMStatus execute_spaces_batches_nd_common(
+  const OMExecuteArgs &execute_args,
+  const std::function<
+    OMStatus(const core::OMRuntimeShape &unextended_input1_shape, const float *input1_data,
+             const core::OMRuntimeShape &unextended_input2_shape, const int32_t *block_shape_data,
+             const core::OMRuntimeShape &unextended_input3_shape, const int32_t *crops_data,
+             const core::OMRuntimeShape &unextended_output_shape, float *output_data)> &f);
+
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_KERNELS_SPACES_BATCHES_ND_COMMON_H
diff --git a/onert-micro/onert-micro/include/import/OMConfigureArgs.h b/onert-micro/onert-micro/include/import/OMConfigureArgs.h
new file mode 100644 (file)
index 0000000..119ca59
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_IMPORT_CONFIGURE_ARGS_H
+#define ONERT_MICRO_IMPORT_CONFIGURE_ARGS_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeModule.h"
+
+namespace onert_micro
+{
+namespace import
+{
+
+struct OMConfigureArgs
+{
+  core::OMRuntimeStorage &runtime_storage;
+  core::OMRuntimeContext &runtime_context;
+  uint16_t kernel_index;
+  const OMConfig &configs;
+  core::OMRuntimeModule &runtime_module;
+};
+
+} // namespace import
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_IMPORT_CONFIGURE_ARGS_H
diff --git a/onert-micro/onert-micro/include/import/OMExecutionPlanCreator.h b/onert-micro/onert-micro/include/import/OMExecutionPlanCreator.h
new file mode 100644 (file)
index 0000000..9385ae6
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_IMPORT_EXECUTION_PLAN_CREATOR_H
+#define ONERT_MICRO_IMPORT_EXECUTION_PLAN_CREATOR_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeContext.h"
+#include "core/memory/OMRuntimeAllocator.h"
+
+namespace onert_micro
+{
+namespace import
+{
+
+struct OMExecutionPlanCreator
+{
+
+  // Create execution plan for forward graph
+  static OMStatus createExecutionPlan(core::OMRuntimeStorage &runtime_storage,
+                                      core::OMRuntimeContext &runtime_context,
+                                      core::memory::OMRuntimeAllocator &allocator,
+                                      const OMConfig &configs);
+
+  // Create execution plan for backward graph
+  static OMStatus createBackwardExecutionPlan(core::OMRuntimeStorage &runtime_storage,
+                                              core::OMRuntimeContext &runtime_context,
+                                              core::memory::OMRuntimeAllocator &allocator,
+                                              const OMConfig &configs);
+};
+
+} // namespace import
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_IMPORT_EXECUTION_PLAN_CREATOR_H
diff --git a/onert-micro/onert-micro/include/import/OMKernelConfiguration.h b/onert-micro/onert-micro/include/import/OMKernelConfiguration.h
new file mode 100644 (file)
index 0000000..d0e1c3b
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_IMPORT_KERNEL_CONFIGURATION_H
+#define ONERT_MICRO_IMPORT_KERNEL_CONFIGURATION_H
+
+#include "OMStatus.h"
+#include "OMConfig.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeContext.h"
+#include "import/OMConfigureArgs.h"
+
+namespace onert_micro
+{
+namespace import
+{
+
+struct OMKernelConfiguration
+{
+  static OMStatus configureKernels(OMConfigureArgs &);
+};
+
+} // namespace import
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_IMPORT_KERNEL_CONFIGURATION_H
diff --git a/onert-micro/onert-micro/include/import/OMKernelConfigureBuilder.h b/onert-micro/onert-micro/include/import/OMKernelConfigureBuilder.h
new file mode 100644 (file)
index 0000000..2348911
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_IMPORT_KERNEL_CONFIGURE_BUILDER_H
+#define ONERT_MICRO_IMPORT_KERNEL_CONFIGURE_BUILDER_H
+
+#include "core/reader/OMCircleReader.h"
+#include "core/OMKernelType.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeModule.h"
+#include "import/OMConfigureArgs.h"
+#include "OMConfig.h"
+
+namespace onert_micro
+{
+namespace import
+{
+
+using KernelConfigureFunc = OMStatus(const OMConfigureArgs &);
+
+#define REGISTER_KERNEL(builtin_operator, name) \
+  OMStatus configure_kernel_Circle##name(const OMConfigureArgs &);
+#include "KernelsToBuild.lst"
+#undef REGISTER_KERNEL
+
+#define REGISTER_CUSTOM_KERNEL(name, string_name) \
+  OMStatus configure_kernel_Circle##name(const OMConfigureArgs &);
+#include "CustomKernelsToBuild.lst"
+#undef REGISTER_CUSTOM_KERNEL
+
+class KernelBuiltinConfigureRegistry
+{
+public:
+  constexpr KernelBuiltinConfigureRegistry() : _operator_configure()
+  {
+#define REGISTER_KERNEL(builtin_operator, name)                                  \
+  registerKernelConfigure(core::OMBuilderID::BuiltinOperator_##builtin_operator, \
+                          configure_kernel_Circle##name);
+
+#include "KernelsToBuild.lst"
+
+#undef REGISTER_KERNEL
+  }
+
+public:
+  OMStatus getKernelConfigureFunc(core::OMBuilderID builderID,
+                                  KernelConfigureFunc **configure_func) const
+  {
+    const auto builder_id_opcode = size_t(builderID);
+    assert(builder_id_opcode < size_t(core::OMBuilderID::BuiltinOperatorsSize));
+    if (builder_id_opcode >= size_t(core::OMBuilderID::BuiltinOperatorsSize))
+    {
+      *configure_func = nullptr;
+      return UnknownError;
+    }
+    *configure_func = _operator_configure[builder_id_opcode];
+    return Ok;
+  }
+
+private:
+  constexpr void registerKernelConfigure(core::OMBuilderID id, KernelConfigureFunc *func)
+  {
+    assert(size_t(id) < size_t(core::OMBuilderID::BuiltinOperatorsSize));
+    _operator_configure[size_t(id)] = func;
+  }
+
+private:
+  KernelConfigureFunc *_operator_configure[size_t(core::OMBuilderID::BuiltinOperatorsSize)];
+};
+
+class KernelCustomConfigureRegistry
+{
+public:
+  constexpr KernelCustomConfigureRegistry() : _operator_configure()
+  {
+#define REGISTER_CUSTOM_KERNEL(name, string_name) \
+  registerKernelConfigure(core::OMBuilderID::CUSTOM_##name, configure_kernel_Circle##name);
+
+#include "CustomKernelsToBuild.lst"
+
+#undef REGISTER_CUSTOM_KERNEL
+  }
+
+public:
+  OMStatus getKernelConfigureFunc(core::OMBuilderID builderID,
+                                  KernelConfigureFunc **configure_func) const
+  {
+    auto builder_id_opcode = size_t(builderID);
+    if (builder_id_opcode >= size_t(core::OMBuilderID::Size))
+    {
+      *configure_func = nullptr;
+      return UnknownError;
+    }
+    const auto builder_id_offset = size_t(core::OMBuilderID::BuiltinOperatorsSize);
+    builder_id_opcode -= builder_id_offset - 1;
+
+    *configure_func = _operator_configure[builder_id_opcode];
+    return Ok;
+  }
+
+private:
+  constexpr void registerKernelConfigure(core::OMBuilderID id, KernelConfigureFunc *func)
+  {
+    auto builder_id_opcode = size_t(id);
+    const auto builder_id_offset = size_t(core::OMBuilderID::BuiltinOperatorsSize);
+    builder_id_opcode = builder_id_opcode - builder_id_offset - 1;
+    _operator_configure[builder_id_opcode] = func;
+  }
+
+private:
+  KernelConfigureFunc *_operator_configure[size_t(core::OMBuilderID::Size) -
+                                           size_t(core::OMBuilderID::BuiltinOperatorsSize) - 1];
+};
+
+// Global constexpr kernel builtin and custom configure
+constexpr KernelBuiltinConfigureRegistry kernel_builtin_configure;
+constexpr KernelCustomConfigureRegistry kernel_custom_configure;
+
+} // namespace import
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_IMPORT_KERNEL_CONFIGURE_BUILDER_H
diff --git a/onert-micro/onert-micro/include/import/helpers/OMArgCommon.h b/onert-micro/onert-micro/include/import/helpers/OMArgCommon.h
new file mode 100644 (file)
index 0000000..eff7eb7
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_IMPORT_HELPERS_CONFIGURE_ARG_KERNEL_COMMON_H
+#define ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_ARG_KERNEL_COMMON_H
+
+#include "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+namespace onert_micro
+{
+namespace import
+{
+namespace helpers
+{
+
+OMStatus configure_arg_kernel_common(const OMConfigureArgs &config_args);
+
+} // namespace helpers
+} // namespace import
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_ARG_KERNEL_COMMON_H
diff --git a/onert-micro/onert-micro/include/import/helpers/OMConfigureSISOKernel.h b/onert-micro/onert-micro/include/import/helpers/OMConfigureSISOKernel.h
new file mode 100644 (file)
index 0000000..0189655
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_IMPORT_HELPERS_CONFIGURE_SISO_KERNEL_H
+#define ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_SISO_KERNEL_H
+
+#include "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+namespace onert_micro
+{
+namespace import
+{
+namespace helpers
+{
+OMStatus configure_SISO_kernel(const OMConfigureArgs &config_args);
+
+} // namespace helpers
+} // namespace import
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_SISO_KERNEL_H
diff --git a/onert-micro/onert-micro/include/import/helpers/OMConfigureTISOKernel.h b/onert-micro/onert-micro/include/import/helpers/OMConfigureTISOKernel.h
new file mode 100644 (file)
index 0000000..2ab7f4a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_IMPORT_HELPERS_CONFIGURE_TISO_KERNEL_H
+#define ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_TISO_KERNEL_H
+
+#include "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+namespace onert_micro
+{
+namespace import
+{
+namespace helpers
+{
+OMStatus configure_TISO_kernel(const OMConfigureArgs &config_args);
+
+} // namespace helpers
+} // namespace import
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_TISO_KERNEL_H
diff --git a/onert-micro/onert-micro/include/import/helpers/OMPadCommon.h b/onert-micro/onert-micro/include/import/helpers/OMPadCommon.h
new file mode 100644 (file)
index 0000000..eff666f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_IMPORT_HELPERS_CONFIGURE_PAD_KERNEL_COMMON_H
+#define ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_PAD_KERNEL_COMMON_H
+
+#include "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+namespace onert_micro
+{
+namespace import
+{
+namespace helpers
+{
+
+OMStatus configure_pad_kernel_common(const OMConfigureArgs &config_args);
+
+} // namespace helpers
+} // namespace import
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_PAD_KERNEL_COMMON_H
diff --git a/onert-micro/onert-micro/include/import/helpers/OMPooingCommon.h b/onert-micro/onert-micro/include/import/helpers/OMPooingCommon.h
new file mode 100644 (file)
index 0000000..82d9355
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_IMPORT_HELPERS_CONFIGURE_POOLING_KERNEL_COMMON_H
+#define ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_POOLING_KERNEL_COMMON_H
+
+#include "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+namespace onert_micro
+{
+namespace import
+{
+namespace helpers
+{
+
+OMStatus configure_pooling_kernel_common(const OMConfigureArgs &config_args);
+
+} // namespace helpers
+} // namespace import
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_POOLING_KERNEL_COMMON_H
diff --git a/onert-micro/onert-micro/include/import/helpers/OMSpacesBatchesNDCommon.h b/onert-micro/onert-micro/include/import/helpers/OMSpacesBatchesNDCommon.h
new file mode 100644 (file)
index 0000000..b7db4f9
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_IMPORT_HELPERS_CONFIGURE_SPACES_BATCHES_ND_COMMON_H
+#define ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_SPACES_BATCHES_ND_COMMON_H
+
+#include "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+namespace onert_micro
+{
+namespace import
+{
+namespace helpers
+{
+
+OMStatus configure_spaces_batches_nd_kernel_common(const OMConfigureArgs &config_args);
+
+} // namespace helpers
+} // namespace import
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_IMPORT_HELPERS_CONFIGURE_SPACES_BATCHES_ND_COMMON_H
diff --git a/onert-micro/onert-micro/include/onert-micro-version.h b/onert-micro/onert-micro/include/onert-micro-version.h
new file mode 100644 (file)
index 0000000..4429a06
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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 0x02000000
+
+#endif // __ONERT_MICRO_VERSION_H__
diff --git a/onert-micro/onert-micro/include/onert-micro.h b/onert-micro/onert-micro/include/onert-micro.h
new file mode 100644 (file)
index 0000000..e340e81
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_H_
+#define _ONERT_MICRO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * typical training flow in onert-micro
+ *
+ * 1. load model or checkpoint
+ *   1-1. (optional) configure training options
+ * 2. feed training input / output(e.g. label) data (cf. unit of a step)
+ * 3. train a step
+ * 4. check loss
+ *   4-0. save checkpoint for recovery/resume training
+ *   4-1. no more traning -> go to 5
+ *   4-2. more training -> go to 2
+ * 5. save current state to inference model
+ * 6. inference with inference model
+// sample example
+// 0. create context
+nnfw_session *session;
+nnfw_create_session(&session);
+// 1. load model (and checkpoint if continue training)
+nnfw_load_model_from_file(session, MODEL_PATH);
+// 1-1. (optional, TBD) configure training options
+nnfw_load_ckpt_from_file(session, CKPT_PATH);
+nnfw_train_prepare(session);
+float training_input[BATCH_SIZE*INPUT_SIZE];
+float training_label[BATCH_SIZE*OUTPUT_SIZE];
+// main training loop
+for(int epoch=0; epoch < NUM_EPOCHS; epoch++) {
+  for(int step=0; step < NUM_BATCHES ; step++) {
+    // prepare this steps's intput/label
+    memcpy(training_input, train_input_data + THIS_BATCH_OFFSET, BATCH_SIZE*INPUT_SIZE);
+    memcpy(training_output, train_output_data + THIS_BATCH_OFFSET, BATCH_SIZE*OUTPUT_SIZE);
+    // 2. feed training input / expected output
+    nnfw_train_set_input(session, 0 , training_input, NULL);
+    nnfw_train_set_expected(session, 0 , training_output, NULL);
+    // 3. train a step
+    nnfw_train(session);
+  }
+  // 4. check loss
+  float loss;
+  nnfw_train_get_loss(ctx, 0, &loss);
+  if(loss > TARGET_LOSS) {
+    nnfw_train_save_as_checkpoint(ctx, CKPT_PATH);
+  }
+  else {
+    nnfw_train_export_circle(ctx, CIRCLE_PATH);
+  }
+}
+*/
+
+typedef struct nnfw_session nnfw_session;
+
+typedef enum
+{
+  /** A tensor of 32 bit floating point */
+  NNFW_TYPE_TENSOR_FLOAT32 = 0,
+  /** A tensor of 32 bit signed integer */
+  NNFW_TYPE_TENSOR_INT32 = 1,
+} NNFW_TYPE;
+
+/**
+ * @brief Result values returned from a call to an API function
+ */
+typedef enum
+{
+  /** Successful */
+  NNFW_STATUS_NO_ERROR = 0,
+  /**
+   * An error code for general use.
+   * Mostly used when there is no specific value for that certain situation.
+   */
+  NNFW_STATUS_ERROR = 1,
+  /** Unexpected null argument is given. */
+  NNFW_STATUS_UNEXPECTED_NULL = 2,
+  /** When a function was called but it is not valid for the current session state. */
+  NNFW_STATUS_INVALID_STATE = 3,
+  /** When it is out of memory */
+  NNFW_STATUS_OUT_OF_MEMORY = 4,
+  /** When it was given an insufficient output buffer */
+  NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE = 5,
+  /** When API is deprecated */
+  NNFW_STATUS_DEPRECATED_API = 6,
+} NNFW_STATUS;
+
+/**
+ * @brief Maximum rank expressible with nnfw
+ */
+#define NNFW_MAX_RANK (6)
+
+/**
+ * @brief tensor info describes the type and shape of tensors
+ *
+ * <p>This structure is used to describe input and output tensors.
+ * Application can get input and output tensor type and shape described in model by using
+ * {@link nnfw_input_tensorinfo} and {@link nnfw_output_tensorinfo}
+ *
+ * <p>Maximum rank is 6 (NNFW_MAX_RANK). And tensor's dimension value is filled in 'dims' field from
+ * index 0.
+ * For example, if tensor's rank is 4,
+ * application can get dimension value from dims[0], dims[1], dims[2], and dims[3]
+ */
+typedef struct nnfw_tensorinfo
+{
+  /** The data type */
+  NNFW_TYPE dtype;
+  /** The number of dimensions (rank) */
+  int32_t rank;
+  /**
+   * The dimension of tensor.
+   * Maximum rank is 6 (NNFW_MAX_RANK).
+   */
+  int32_t dims[NNFW_MAX_RANK];
+} nnfw_tensorinfo;
+
+//////////////////////////////////////////////
+// Essential APIs for training
+//////////////////////////////////////////////
+typedef enum
+{
+  NNFW_TRAIN_LOSS_UNDEFINED = 0,
+  NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR = 1,
+  NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY = 2,
+} NNFW_TRAIN_LOSS;
+
+typedef enum
+{
+  /** Undefined */
+  NNFW_TRAIN_LOSS_REDUCTION_UNDEFINED = 0,
+  /** Scalar sum divided by number of elements in losses */
+  NNFW_TRAIN_LOSS_REDUCTION_SUM_OVER_BATCH_SIZE = 1,
+  /** Scalar sum of weighted losses */
+  NNFW_TRAIN_LOSS_REDUCTION_SUM = 2,
+} NNFW_TRAIN_LOSS_REDUCTION;
+
+typedef enum
+{
+  NNFW_TRAIN_OPTIMIZER_UNDEFINED = 0,
+  NNFW_TRAIN_OPTIMIZER_SGD = 1,
+  NNFW_TRAIN_OPTIMIZER_ADAM = 2,
+} NNFW_TRAIN_OPTIMIZER;
+
+typedef struct nnfw_loss_info
+{
+  NNFW_TRAIN_LOSS loss;
+  NNFW_TRAIN_LOSS_REDUCTION reduction_type;
+} nnfw_loss_info;
+
+typedef struct nnfw_adam_option
+{
+  float beta;
+  float beta2;
+  float epsilon;
+} nnfw_adam_option;
+
+/**
+ * @brief Maximum numer of trainable operations
+ */
+#define NNFW_TRAINABLE_OPS_MAX_SIZE (256)
+
+/**
+ * @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 info */
+  nnfw_loss_info loss_info{.loss = NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY,
+                           .reduction_type = NNFW_TRAIN_LOSS_REDUCTION_SUM_OVER_BATCH_SIZE};
+  /** optimizer type */
+  NNFW_TRAIN_OPTIMIZER opt = NNFW_TRAIN_OPTIMIZER_ADAM;
+
+  uint32_t num_trainble_ops = 0;
+
+  nnfw_adam_option adam_opt{.beta = 0.9f,
+
+                            .beta2 = 0.999f,
+                            .epsilon = 1e-7f};
+} nnfw_train_info;
+
+/**
+ * @brief Set training information
+ * @note  This function should be called after calling {@link nnfw_load_model_from_file}
+ *        and before calling {@link nnfw_train_prepare}
+ *
+ * @param[in] session The session to be set training information
+ * @param[in] info    The training information
+ *
+ *  @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_set_traininfo(nnfw_session *session, const nnfw_train_info *info);
+
+/**
+ * @brief Create a new session instance.
+ *
+ * <p>This only creates a session.
+ * Model is loaded after {@link nnfw_load_model_from_file} is invoked.
+ * And inference is performed after {@link nnfw_run} is invoked.
+ *
+ * <p>{@link nnfw_close_session} should be called once
+ * if session is no longer needed
+ *
+ * @param[out]  session The session to be created
+ * @return      NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_create_session(nnfw_session **session);
+
+/**
+ * @brief Close a session instance
+ *
+ * After called, access to closed session by application will be invalid
+ *
+ * @param[in] session The session to be closed
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_close_session(nnfw_session *session);
+
+/**
+ * @brief     Load model from nnpackage file or directory
+ *
+ * The length of \p package_file_path must not exceed 1024 bytes including zero at the end.
+ *
+ * @param[in] session           nnfw_session loading the given nnpackage file/dir
+ * @param[in] package_file_path Path to the nnpackage file or unzipped directory to be loaded
+ *
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *package_file_path);
+
+/**
+ * @brief Prepare session to be ready for training
+ * @note  The session will be entered into training mode
+ *
+ *        If training info is NOT set in session, this function returns @c NNFW_STATUS_ERROR .
+ *        You should set training info using {@link nnfw_train_set_traininfo}.
+ *
+ * @param[in] session The session to be prepared for training
+ *
+ * @return  @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_prepare(nnfw_session *session);
+
+/**
+ * @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
+ *
+ *        In order to use \p update_weights as false, it should be called after
+ *        {@link nnfw_train_set_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 Export current training model into 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);
+
+NNFW_STATUS nnfw_train_export_checkpoint(nnfw_session *session, const char *path);
+NNFW_STATUS nnfw_train_import_checkpoint(nnfw_session *session, const char *path);
+
+/**
+ * @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, 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, void *expected,
+                                    const nnfw_tensorinfo *expected_info);
+
+/**
+ * @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 Set training output buffer
+ *
+ * This function must be called after {@link nnfw_train_prepare}, \p buffer given to this function
+ * can be reused for training. \p length must be greater or equal than the operand requires.
+ * An output operand can have unspecified shape and deduced dynamically during the execution. You
+ * must provide \p buffer large enough.
+ *
+ * @param[in]   session Session from inference output is to be extracted
+ * @param[in]   index   Index of output to be set (0-indexed)
+ * @param[in]   type    Type of the output
+ * @param[out]  buffer  Raw buffer for output
+ * @param[in]   length  Size of bytes of output buffer
+ *
+ * @return      @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_set_output(nnfw_session *session, uint32_t index, NNFW_TYPE type,
+                                  void *buffer, size_t length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_ONERT_MICRO_H_
diff --git a/onert-micro/onert-micro/include/optimize/BuildPass.lst b/onert-micro/onert-micro/include/optimize/BuildPass.lst
new file mode 100644 (file)
index 0000000..377ea62
--- /dev/null
@@ -0,0 +1 @@
+REGISTER_PASS(FindInplaceOpPass)
diff --git a/onert-micro/onert-micro/include/optimize/OMGraphStatus.h b/onert-micro/onert-micro/include/optimize/OMGraphStatus.h
new file mode 100644 (file)
index 0000000..e8bac00
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_OPTIMIZE_GRAPH_STATUS_H
+#define ONERT_MICRO_OPTIMIZE_GRAPH_STATUS_H
+
+#include "OMStatus.h"
+
+namespace onert_micro
+{
+namespace optimize
+{
+
+enum OMGraphOptimizationStatus
+{
+  Changed,
+  Unchanged,
+};
+
+struct OMGraphStatus
+{
+  OMGraphOptimizationStatus graph_status;
+  OMStatus main_status;
+};
+
+} // namespace optimize
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_OPTIMIZE_GRAPH_STATUS_H
diff --git a/onert-micro/onert-micro/include/optimize/OMOptimizePassesBuilder.h b/onert-micro/onert-micro/include/optimize/OMOptimizePassesBuilder.h
new file mode 100644 (file)
index 0000000..18f12cf
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_OPTIMIZE_PASSES_BUILDER_H
+#define ONERT_MICRO_OPTIMIZE_PASSES_BUILDER_H
+
+#include "OMConfig.h"
+#include "core/reader/OMCircleReader.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeContext.h"
+#include "optimize/OMGraphStatus.h"
+
+namespace onert_micro
+{
+namespace optimize
+{
+
+#define REGISTER_PASS(name) PASS_##name,
+enum class OMPassBuilderID
+{
+#include "BuildPass.lst"
+  Size
+};
+#undef REGISTER_PASS
+
+using OptimizePassFunc = OMGraphStatus(core::OMRuntimeStorage &storage,
+                                       core::OMRuntimeContext &context, const OMConfig &configs);
+
+#define REGISTER_PASS(name)                                         \
+  OMGraphStatus onert_micro_##name(core::OMRuntimeStorage &storage, \
+                                   core::OMRuntimeContext &context, const OMConfig &configs);
+#include "BuildPass.lst"
+#undef REGISTER_PASS
+
+class OptimizePassRegistry
+{
+public:
+  constexpr OptimizePassRegistry() : _optimize_passes()
+  {
+#define REGISTER_PASS(name) \
+  registerOptimizePasses(optimize::OMPassBuilderID::PASS_##name, onert_micro_##name);
+
+#include "BuildPass.lst"
+
+#undef REGISTER_PASS
+  }
+
+  OMStatus getOptimizeFunc(uint32_t idx, OptimizePassFunc **optimize_func) const
+  {
+    assert(idx < size_t(optimize::OMPassBuilderID::Size));
+    if (idx >= size_t(optimize::OMPassBuilderID::Size))
+    {
+      *optimize_func = nullptr;
+      return UnknownError;
+    }
+    *optimize_func = _optimize_passes[idx];
+    return Ok;
+  }
+
+  constexpr uint32_t getPassNumber() const { return size_t(optimize::OMPassBuilderID::Size); }
+
+private:
+  constexpr void registerOptimizePasses(optimize::OMPassBuilderID id, OptimizePassFunc *func)
+  {
+    assert(size_t(id) < size_t(optimize::OMPassBuilderID::Size));
+    _optimize_passes[size_t(id)] = func;
+  }
+
+private:
+  OptimizePassFunc *_optimize_passes[size_t(optimize::OMPassBuilderID::Size)];
+};
+
+// Global constexpr kernel builtin and custom configure
+constexpr OptimizePassRegistry optimize_passes;
+
+} // namespace optimize
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_OPTIMIZE_PASSES_BUILDER_H
diff --git a/onert-micro/onert-micro/include/optimize/OMOptimizer.h b/onert-micro/onert-micro/include/optimize/OMOptimizer.h
new file mode 100644 (file)
index 0000000..314a5f1
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_OPTIMIZE_OPTIMIZER_H
+#define ONERT_MICRO_OPTIMIZE_OPTIMIZER_H
+
+#include "OMGraphStatus.h"
+#include "OMConfig.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeStorage.h"
+
+namespace onert_micro
+{
+namespace optimize
+{
+
+struct OMOptimizer
+{
+  static OMStatus optimize(core::OMRuntimeStorage &storage, core::OMRuntimeContext &context,
+                           const OMConfig &configs);
+};
+
+} // namespace optimize
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_OPTIMIZE_OPTIMIZER_H
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/CustomKernelsToBuild.lst b/onert-micro/onert-micro/include/pal/cmsisnn/CustomKernelsToBuild.lst
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/KernelsToBuild.lst b/onert-micro/onert-micro/include/pal/cmsisnn/KernelsToBuild.lst
new file mode 100644 (file)
index 0000000..56c7822
--- /dev/null
@@ -0,0 +1,87 @@
+#/*REGISTER_KERNEL(ABS, Abs)*/
+REGISTER_KERNEL(ADD, Add)
+#/*REGISTER_KERNEL(ADD_N, AddN)*/
+REGISTER_KERNEL(AVERAGE_POOL_2D, AveragePool2D)
+#/*REGISTER_KERNEL(ARG_MAX, ArgMax)*/
+#/*REGISTER_KERNEL(ARG_MIN, ArgMin)*/
+#/*REGISTER_KERNEL(CONCATENATION, Concatenation)*/
+#/*REGISTER_KERNEL(CUSTOM, BroadcastTo)*/
+#/*REGISTER_KERNEL(BATCH_TO_SPACE_ND, BatchToSpaceND)*/
+#/*REGISTER_KERNEL(CEIL, Ceil)*/
+#/*REGISTER_KERNEL(COS, Cos)*/
+#/*REGISTER_KERNEL(CAST, Cast)*/
+#/*REGISTER_KERNEL(DIV, Div)*/
+REGISTER_KERNEL(DEPTHWISE_CONV_2D, DepthwiseConv2D)
+#/*REGISTER_KERNEL(DEPTH_TO_SPACE, DepthToSpace)*/
+#/*REGISTER_KERNEL(DEQUANTIZE, Dequantize)*/
+REGISTER_KERNEL(FULLY_CONNECTED, FullyConnected)
+REGISTER_KERNEL(CONV_2D, Conv2D)
+#/*REGISTER_KERNEL(LOGISTIC, Logistic)*/
+#/*REGISTER_KERNEL(LOG, Log)*/
+#/*REGISTER_KERNEL(GATHER, Gather)*/
+#/*REGISTER_KERNEL(GATHER_ND, GatherND)*/
+#/*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(FLOOR, Floor)*/
+#/*REGISTER_KERNEL(FLOOR_DIV, FloorDiv)*/
+#/*REGISTER_KERNEL(FLOOR_MOD, FloorMod)*/
+#/*REGISTER_KERNEL(PACK, Pack)*/
+#/*REGISTER_KERNEL(PAD, Pad)*/
+#/*REGISTER_KERNEL(PADV2, PadV2)*/
+#/*REGISTER_KERNEL(PRELU, PRelu)*/
+#/*REGISTER_KERNEL(RESHAPE, Reshape)*/
+#/*REGISTER_KERNEL(RELU, Relu)*/
+#/*REGISTER_KERNEL(RELU6, Relu6)*/
+#/*REGISTER_KERNEL(REDUCE_PROD, ReduceCommon)*/
+#/*REGISTER_KERNEL(REDUCE_MAX, ReduceMax)*/
+#/*REGISTER_KERNEL(ROUND, Round)*/
+#/*REGISTER_KERNEL(LESS, Less)*/
+#/*REGISTER_KERNEL(L2_NORMALIZATION, L2Normalize)*/
+#/*REGISTER_KERNEL(L2_POOL_2D, L2Pool2D)*/
+#/*REGISTER_KERNEL(LESS_EQUAL, LessEqual)*/
+#/*REGISTER_KERNEL(LOGICAL_AND, LogicalAnd)*/
+#/*REGISTER_KERNEL(LOGICAL_NOT, LogicalNot)*/
+#/*REGISTER_KERNEL(LOGICAL_OR, LogicalOr)*/
+#/*REGISTER_KERNEL(LEAKY_RELU, LeakyRelu)*/
+#/*REGISTER_KERNEL(LOG_SOFTMAX, LogSoftmax)*/
+REGISTER_KERNEL(MUL, Mul)
+#/*REGISTER_KERNEL(MIRROR_PAD, MirrorPad)*/
+#/*REGISTER_KERNEL(MAXIMUM, Maximum)*/
+#/*REGISTER_KERNEL(MEAN, Mean)*/
+REGISTER_KERNEL(MAX_POOL_2D, MaxPool2D)
+#/*REGISTER_KERNEL(MINIMUM, Minimum)*/
+#/*REGISTER_KERNEL(SHAPE, Shape)*/
+#/*REGISTER_KERNEL(NOT_EQUAL, NotEqual)*/
+#/*REGISTER_KERNEL(SIN, Sin)*/
+#/*REGISTER_KERNEL(SQUARED_DIFFERENCE, SquaredDifference)*/
+#/*REGISTER_KERNEL(SLICE, Slice)*/
+#/*REGISTER_KERNEL(SUB, Sub)*/
+#/*REGISTER_KERNEL(SPLIT, Split)*/
+#/*REGISTER_KERNEL(SPACE_TO_BATCH_ND, SpaceToBatchND)*/
+#/*REGISTER_KERNEL(STRIDED_SLICE, StridedSlice)*/
+#/*REGISTER_KERNEL(SPLIT_V, SplitV)*/
+#/*REGISTER_KERNEL(SQUARE, Square)*/
+#/*REGISTER_KERNEL(SQRT, Sqrt)*/
+#/*REGISTER_KERNEL(SPACE_TO_DEPTH, SpaceToDepth)*/
+#/*REGISTER_KERNEL(QUANTIZE, Quantize)*/
+#/*REGISTER_KERNEL(TANH, Tanh)*/
+#/*REGISTER_KERNEL(TRANSPOSE, Transpose)*/
+#/*REGISTER_KERNEL(TRANSPOSE_CONV, TransposeConv)*/
+REGISTER_KERNEL(SOFTMAX, Softmax)
+#/*REGISTER_KERNEL(SUM, Sum)*/
+#/*REGISTER_KERNEL(SELECT_V2, SelectV2)*/
+#/*REGISTER_KERNEL(SVDF, SVDF)*/
+#/*REGISTER_KERNEL(WHILE, While)*/
+#/*REGISTER_KERNEL(UNIDIRECTIONAL_SEQUENCE_LSTM, UnidirectionalSequenceLSTM)*/
+#/*REGISTER_KERNEL(RESIZE_BILINEAR, ResizeBilinear)*/
+#/*REGISTER_KERNEL(RESIZE_NEAREST_NEIGHBOR, ResizeNearestNeighbor)*/
+#/*REGISTER_KERNEL(RSQRT, Rsqrt)*/
+#/*REGISTER_KERNEL(NEG, Neg)*/
+#/*REGISTER_KERNEL(ZEROS_LIKE, ZerosLike)*/
+#/*REGISTER_KERNEL(SQUEEZE, Squeeze)*/
+#/*REGISTER_KERNEL(UNPACK, Unpack)*/
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/KernelsToTrain.lst b/onert-micro/onert-micro/include/pal/cmsisnn/KernelsToTrain.lst
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/PALAdd.h b/onert-micro/onert-micro/include/pal/cmsisnn/PALAdd.h
new file mode 100644 (file)
index 0000000..3a3fdf5
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_ADD_H
+#define ONERT_MICRO_EXECUTE_PAL_ADD_H
+
+#include "PALAddCommon.h"
+#include "PALUtils.h"
+
+#include "arm_nnfunctions.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+OMStatus Add(const core::ArithmeticQuantParams &params, const uint32_t flat_size,
+             const int8_t *input1_data, const int8_t *input2_data, int8_t *output_data)
+{
+  auto status = arm_elementwise_add_s8(
+    input1_data, input2_data, params.input1_offset, params.input1_multiplier, params.input1_shift,
+    params.input2_offset, params.input2_multiplier, params.input2_shift, params.left_shift,
+    output_data, params.output_offset, params.output_multiplier, params.output_shift,
+    params.quantized_activation_min, params.quantized_activation_max, flat_size);
+
+  assert(status == ARM_CMSIS_NN_SUCCESS);
+  if (status != ARM_CMSIS_NN_SUCCESS)
+    return UnknownError;
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ADD_H
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/PALAveragePool2D.h b/onert-micro/onert-micro/include/pal/cmsisnn/PALAveragePool2D.h
new file mode 100644 (file)
index 0000000..ad18687
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_AVERAGE_POOL_2D_H
+#define ONERT_MICRO_EXECUTE_PAL_AVERAGE_POOL_2D_H
+
+#include "PALAveragePool2DCommon.h"
+
+#include <arm_nnfunctions.h>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+OMStatus AveragePool(const core::Pool2DParams &params, const core::OMRuntimeShape &input_shape,
+                     const int8_t *input_data, const core::OMRuntimeShape &output_shape,
+                     int8_t *output_data)
+{
+  cmsis_nn_dims input_dims;
+  cmsis_nn_dims output_dims;
+  cmsis_nn_pool_params pool_params;
+  cmsis_nn_dims filter_dims;
+  cmsis_nn_context ctx;
+
+  const int depth = input_shape.dims(3);
+  const int output_width = output_shape.dims(2);
+
+  input_dims.n = 1;
+  input_dims.h = input_shape.dims(1);
+  input_dims.w = input_shape.dims(2);
+  input_dims.c = depth;
+
+  output_dims.n = 1;
+  output_dims.h = output_shape.dims(1);
+  output_dims.w = output_width;
+  output_dims.c = depth;
+
+  pool_params.stride.h = params.stride_h;
+  pool_params.stride.w = params.stride_w;
+  pool_params.padding.h = params.pad_h;
+  pool_params.padding.w = params.pad_w;
+  pool_params.activation.min = params.quantized_activation_min;
+  pool_params.activation.max = params.quantized_activation_max;
+
+  filter_dims.n = 1;
+  filter_dims.h = params.filter_h;
+  filter_dims.w = params.filter_w;
+  filter_dims.c = 1;
+
+  const int32_t buffer_size = arm_avgpool_s8_get_buffer_size(output_width, depth);
+  int8_t *buffer = nullptr;
+  if (buffer_size > 0)
+  {
+    buffer = new int8_t[buffer_size];
+  }
+
+  ctx.buf = buffer;
+  ctx.size = buffer_size;
+
+  auto res = arm_avgpool_s8(&ctx, &pool_params, &input_dims, input_data, &filter_dims, &output_dims,
+                            output_data);
+
+  if (buffer_size > 0)
+    delete[] buffer;
+
+  assert(res == ARM_CMSIS_NN_SUCCESS);
+  if (res != ARM_CMSIS_NN_SUCCESS)
+    return CmsisNNError;
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_AVERAGE_POOL_2D_H
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/PALConv2D.h b/onert-micro/onert-micro/include/pal/cmsisnn/PALConv2D.h
new file mode 100644 (file)
index 0000000..fe45806
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_CONV_2D_H
+#define ONERT_MICRO_EXECUTE_PAL_CONV_2D_H
+
+#include "PALConv2DCommon.h"
+#include "core/OMKernelData.h"
+#include "core/OMRuntimeShape.h"
+#include "PALUtils.h"
+
+#include <arm_nnfunctions.h>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+// Fixed-point per-channel-quantization convolution reference kernel.
+OMStatus ConvPerChannel(const core::ConvQuant &params, const core::OMRuntimeShape &input_shape,
+                        const int8_t *input_data, const core::OMRuntimeShape &filter_shape,
+                        const int8_t *filter_data, const int32_t *bias_data,
+                        const core::OMRuntimeShape &output_shape, int8_t *output_data)
+{
+  cmsis_nn_conv_params conv_params;
+  conv_params.dilation.h = params.dilation_height_factor;
+  conv_params.dilation.w = params.dilation_width_factor;
+
+  assert(conv_params.dilation.h == 1);
+  assert(conv_params.dilation.w == 1);
+
+  conv_params.input_offset = params.input_offset;
+  conv_params.output_offset = params.output_offset;
+  conv_params.stride.h = params.stride_height;
+  conv_params.stride.w = params.stride_width;
+  conv_params.padding.h = params.pad_h;
+  conv_params.padding.w = params.pad_w;
+  conv_params.activation.min = params.quantized_activation_min;
+  conv_params.activation.max = params.quantized_activation_max;
+
+  cmsis_nn_per_channel_quant_params quant_params;
+  quant_params.multiplier = const_cast<int32_t *>(params.per_channel_output_multiplier.data());
+  quant_params.shift = const_cast<int32_t *>(
+    reinterpret_cast<const int32_t *>(params.per_channel_output_shift.data()));
+
+  assert(conv_params.activation.min <= conv_params.activation.max);
+  const int batch_size = input_shape.dims(0);
+  const int input_depth = input_shape.dims(3);
+  const int output_depth = filter_shape.dims(0);
+
+  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_depth;
+
+  cmsis_nn_dims filter_dims;
+  filter_dims.n = output_depth;
+  filter_dims.h = filter_shape.dims(1);
+  filter_dims.w = filter_shape.dims(2);
+  filter_dims.c = input_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;
+
+  auto buf_size =
+    arm_convolve_wrapper_s8_get_buffer_size(&conv_params, &input_dims, &filter_dims, &output_dims);
+
+  auto buffer = std::make_unique<int8_t[]>(buf_size);
+  assert(buffer != nullptr);
+
+  cmsis_nn_context ctx;
+  ctx.buf = buffer.get();
+  ctx.size = buf_size;
+
+  auto res = arm_convolve_wrapper_s8(&ctx, &conv_params, &quant_params, &input_dims, input_data,
+                                     &filter_dims, filter_data, &bias_dims, bias_data, &output_dims,
+                                     output_data);
+
+  assert(res == ARM_CMSIS_NN_SUCCESS);
+  if (res != ARM_CMSIS_NN_SUCCESS)
+    return CmsisNNError;
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_CONV_2D_H
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/PALDepthwiseConv2D.h b/onert-micro/onert-micro/include/pal/cmsisnn/PALDepthwiseConv2D.h
new file mode 100644 (file)
index 0000000..e8077ab
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_DEPTHWISE_CONV_2D_H
+#define ONERT_MICRO_EXECUTE_PAL_DEPTHWISE_CONV_2D_H
+
+#include "PALDepthwiseConv2DCommon.h"
+#include "core/OMKernelData.h"
+#include "core/OMRuntimeShape.h"
+#include "PALUtils.h"
+
+#include <arm_nnfunctions.h>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+// Fixed-point per-channel-quantization deptwise_conv2D reference kernel.
+OMStatus DepthwiseConvPerChannel(const core::ConvQuant &params,
+                                 const core::OMRuntimeShape &input_shape, const int8_t *input_data,
+                                 const core::OMRuntimeShape &filter_shape,
+                                 const int8_t *filter_data, const int32_t *bias_data,
+                                 const core::OMRuntimeShape &output_shape, int8_t *output_data)
+{
+  cmsis_nn_dw_conv_params conv_params;
+  conv_params.dilation.h = params.dilation_height_factor;
+  conv_params.dilation.w = params.dilation_width_factor;
+
+  assert(conv_params.dilation.h == 1);
+  assert(conv_params.dilation.w == 1);
+
+  conv_params.input_offset = params.input_offset;
+  conv_params.output_offset = params.output_offset;
+  conv_params.stride.h = params.stride_height;
+  conv_params.stride.w = params.stride_width;
+  conv_params.padding.h = params.pad_h;
+  conv_params.padding.w = params.pad_w;
+  conv_params.activation.min = params.quantized_activation_min;
+  conv_params.activation.max = params.quantized_activation_max;
+  conv_params.ch_mult = params.depth_multiplier;
+
+  cmsis_nn_per_channel_quant_params quant_params;
+  quant_params.multiplier = const_cast<int32_t *>(params.per_channel_output_multiplier.data());
+  quant_params.shift = const_cast<int32_t *>(
+    reinterpret_cast<const int32_t *>(params.per_channel_output_shift.data()));
+
+  assert(conv_params.activation.min <= conv_params.activation.max);
+  const int batch_size = input_shape.dims(0);
+  const int input_depth = input_shape.dims(3);
+  const int output_depth = filter_shape.dims(0);
+
+  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_depth;
+
+  cmsis_nn_dims filter_dims;
+  filter_dims.n = output_depth;
+  filter_dims.h = filter_shape.dims(1);
+  filter_dims.w = filter_shape.dims(2);
+  filter_dims.c = input_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;
+
+  auto buf_size = arm_depthwise_conv_wrapper_s8_get_buffer_size(&conv_params, &input_dims,
+                                                                &filter_dims, &output_dims);
+
+  auto buffer = std::make_unique<int8_t[]>(buf_size);
+  assert(buffer != nullptr);
+
+  cmsis_nn_context ctx;
+  ctx.buf = buffer.get();
+  ctx.size = buf_size;
+
+  auto res = arm_depthwise_conv_wrapper_s8(&ctx, &conv_params, &quant_params, &input_dims,
+                                           input_data, &filter_dims, filter_data, &bias_dims,
+                                           bias_data, &output_dims, output_data);
+
+  assert(res == ARM_CMSIS_NN_SUCCESS);
+  if (res != ARM_CMSIS_NN_SUCCESS)
+    return CmsisNNError;
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_DEPTHWISE_CONV_2D_H
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/PALFullyConnected.h b/onert-micro/onert-micro/include/pal/cmsisnn/PALFullyConnected.h
new file mode 100644 (file)
index 0000000..cbd8510
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_FULLY_CONNECTED_H
+#define ONERT_MICRO_EXECUTE_PAL_FULLY_CONNECTED_H
+
+#include "PALFullyConnectedCommon.h"
+
+#include <arm_nnfunctions.h>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <>
+OMStatus FullyConnected<int8_t>(const core::FullyConnectedParams &params, const int8_t *input_data,
+                                const core::OMRuntimeShape &filter_shape, const int8_t *filter_data,
+                                const int32_t *bias_data, const core::OMRuntimeShape &output_shape,
+                                int8_t *output_data)
+{
+  const int filter_dim_count = filter_shape.dimensionsCount();
+  const int output_dim_count = output_shape.dimensionsCount();
+  const int batches =
+    flatSizeSkipDim(output_shape.dimsData(), output_dim_count - 1, output_dim_count);
+  const int output_depth = output_shape.dims(output_dim_count - 1);
+  const int accum_depth = filter_shape.dims(filter_dim_count - 1);
+
+  cmsis_nn_fc_params fc_params;
+  fc_params.input_offset = params.input_offset;
+  fc_params.output_offset = params.output_offset;
+  fc_params.filter_offset = params.weights_offset;
+  fc_params.activation.min = params.quantized_activation_min;
+  fc_params.activation.max = params.quantized_activation_max;
+
+  cmsis_nn_per_tensor_quant_params quant_params;
+  quant_params.multiplier = params.output_multiplier;
+  quant_params.shift = params.output_shift;
+
+  cmsis_nn_dims input_dims;
+  input_dims.n = batches;
+  input_dims.h = 1;
+  input_dims.w = 1;
+  input_dims.c = accum_depth;
+
+  cmsis_nn_dims filter_dims;
+  filter_dims.n = accum_depth;
+  filter_dims.h = 1;
+  filter_dims.w = 1;
+  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 = batches;
+  output_dims.h = 1;
+  output_dims.w = 1;
+  output_dims.c = output_depth;
+
+  int32_t buf_size = arm_fully_connected_s8_get_buffer_size(&filter_dims);
+  auto buffer = std::make_unique<int8_t[]>(buf_size);
+  assert(buffer != nullptr);
+
+  cmsis_nn_context ctx;
+  ctx.buf = buffer.get();
+  ctx.size = buf_size;
+
+  auto res =
+    arm_fully_connected_s8(&ctx, &fc_params, &quant_params, &input_dims, input_data, &filter_dims,
+                           filter_data, &bias_dims, bias_data, &output_dims, output_data);
+  assert(res == ARM_CMSIS_NN_SUCCESS);
+  if (res != ARM_CMSIS_NN_SUCCESS)
+    return CmsisNNError;
+
+  return Ok;
+}
+
+template <>
+OMStatus FullyConnected(const core::FullyConnectedParams &params, const int16_t *input_data,
+                        const core::OMRuntimeShape &filter_shape, const int8_t *filter_data,
+                        const int64_t *bias_data, const core::OMRuntimeShape &output_shape,
+                        int16_t *output_data)
+{
+  const int filter_dim_count = filter_shape.dimensionsCount();
+  const int output_dim_count = output_shape.dimensionsCount();
+  const int batches =
+    flatSizeSkipDim(output_shape.dimsData(), output_dim_count - 1, output_dim_count);
+  const int output_depth = output_shape.dims(output_dim_count - 1);
+  const int accum_depth = filter_shape.dims(filter_dim_count - 1);
+
+  cmsis_nn_fc_params fc_params;
+  fc_params.input_offset = params.input_offset;
+  fc_params.output_offset = params.output_offset;
+  fc_params.filter_offset = params.weights_offset;
+  fc_params.activation.min = params.quantized_activation_min;
+  fc_params.activation.max = params.quantized_activation_max;
+
+  cmsis_nn_per_tensor_quant_params quant_params;
+  quant_params.multiplier = params.output_multiplier;
+  quant_params.shift = params.output_shift;
+
+  cmsis_nn_dims input_dims;
+  input_dims.n = batches;
+  input_dims.h = 1;
+  input_dims.w = 1;
+  input_dims.c = accum_depth;
+
+  cmsis_nn_dims filter_dims;
+  filter_dims.n = accum_depth;
+  filter_dims.h = 1;
+  filter_dims.w = 1;
+  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 = batches;
+  output_dims.h = 1;
+  output_dims.w = 1;
+  output_dims.c = output_depth;
+
+  int32_t buf_size = arm_fully_connected_s16_get_buffer_size(&filter_dims);
+  auto buffer = std::make_unique<int8_t[]>(buf_size);
+  assert(buffer != nullptr);
+
+  cmsis_nn_context ctx;
+  ctx.buf = buffer.get();
+  ctx.size = buf_size;
+
+  auto res =
+    arm_fully_connected_s16(&ctx, &fc_params, &quant_params, &input_dims, input_data, &filter_dims,
+                            filter_data, &bias_dims, bias_data, &output_dims, output_data);
+  assert(res == ARM_CMSIS_NN_SUCCESS);
+
+  if (res != ARM_CMSIS_NN_SUCCESS)
+    return CmsisNNError;
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_FULLY_CONNECTED_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/PALMaxPool2D.h b/onert-micro/onert-micro/include/pal/cmsisnn/PALMaxPool2D.h
new file mode 100644 (file)
index 0000000..ae4d2ef
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_H
+#define ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_H
+
+#include "PALMaxPool2DCommon.h"
+
+#include <arm_nnfunctions.h>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+OMStatus MaxPool(const core::Pool2DParams &params, const core::OMRuntimeShape &input_shape,
+                 const int8_t *input_data, const core::OMRuntimeShape &output_shape,
+                 int8_t *output_data)
+{
+  cmsis_nn_dims input_dims;
+  cmsis_nn_dims output_dims;
+  cmsis_nn_pool_params pool_params;
+  cmsis_nn_dims filter_dims;
+  cmsis_nn_context ctx;
+
+  const int depth = input_shape.dims(3);
+  const int output_width = output_shape.dims(2);
+
+  input_dims.n = 1;
+  input_dims.h = input_shape.dims(1);
+  input_dims.w = input_shape.dims(2);
+  input_dims.c = depth;
+
+  output_dims.n = 1;
+  output_dims.h = output_shape.dims(1);
+  output_dims.w = output_width;
+  output_dims.c = depth;
+
+  pool_params.stride.h = params.stride_h;
+  pool_params.stride.w = params.stride_w;
+  pool_params.padding.h = params.pad_h;
+  pool_params.padding.w = params.pad_w;
+  pool_params.activation.min = params.quantized_activation_min;
+  pool_params.activation.max = params.quantized_activation_max;
+
+  filter_dims.n = 1;
+  filter_dims.h = params.filter_h;
+  filter_dims.w = params.filter_w;
+  filter_dims.c = 1;
+
+  auto res = arm_max_pool_s8(&ctx, &pool_params, &input_dims, input_data, &filter_dims,
+                             &output_dims, output_data);
+
+  assert(res == ARM_CMSIS_NN_SUCCESS);
+  if (res != ARM_CMSIS_NN_SUCCESS)
+    return CmsisNNError;
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_H
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/PALMul.h b/onert-micro/onert-micro/include/pal/cmsisnn/PALMul.h
new file mode 100644 (file)
index 0000000..4da6a3f
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_MUL_H
+#define ONERT_MICRO_EXECUTE_PAL_MUL_H
+
+#include "PALMulCommon.h"
+#include "PALUtils.h"
+
+#include "arm_nnfunctions.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+OMStatus Mul(const core::ArithmeticQuantParams &params, const uint32_t flat_size,
+             const int8_t *input1_data, const int8_t *input2_data, int8_t *output_data)
+{
+  auto status = arm_elementwise_mul_s8(
+    input1_data, input2_data, params.input1_offset, params.input2_offset, output_data,
+    params.output_offset, params.output_multiplier, params.output_shift,
+    params.quantized_activation_min, params.quantized_activation_max, flat_size);
+  assert(status == ARM_CMSIS_NN_SUCCESS);
+
+  if (status != ARM_CMSIS_NN_SUCCESS)
+    return UnknownError;
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ADD_H
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/PALSoftmax.h b/onert-micro/onert-micro/include/pal/cmsisnn/PALSoftmax.h
new file mode 100644 (file)
index 0000000..a7c18a6
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_SOFTMAX_H
+#define ONERT_MICRO_EXECUTE_PAL_SOFTMAX_H
+
+#include "PALSoftmaxCommon.h"
+
+#include <arm_nnfunctions.h>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <>
+OMStatus Softmax<int8_t, int8_t>(const core::SoftmaxParams &params, const int8_t *input_data,
+                                 int8_t *output_data)
+{
+  arm_softmax_s8(input_data, params.num_rows, params.row_size, params.input_multiplier,
+                 params.input_left_shift, params.diff_min, output_data);
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SOFTMAX_H
diff --git a/onert-micro/onert-micro/include/pal/cmsisnn/pal.cmake b/onert-micro/onert-micro/include/pal/cmsisnn/pal.cmake
new file mode 100644 (file)
index 0000000..441b47f
--- /dev/null
@@ -0,0 +1,33 @@
+macro(initialize_pal)
+    nnas_find_package(CMSIS-NN EXACT 4.1.0 REQUIRED)
+
+    if (NOT CMSIS_NNSource_FOUND)
+        message(STATUS "Skipping luci-interpreter: CMSIS-NN not found")
+        return()
+    endif ()
+
+    set(PAL_INITIALIZED TRUE)
+endmacro()
+
+macro(add_pal_to_target TGT)
+    target_include_directories(${TGT} PUBLIC ${OM_PAL_DIR})
+
+    file(GLOB_RECURSE PAL_SOURCES "${CMSIS_NNSource_DIR}/Source/ActivationFunctions/*.c"
+            "${CMSIS_NNSource_DIR}/Source/BasicMathFunctions/*.c"
+            "${CMSIS_NNSource_DIR}/Source/ConcatenationFunctions/*.c"
+            "${CMSIS_NNSource_DIR}/Source/ConvolutionFunctions/*.c"
+            "${CMSIS_NNSource_DIR}/Source/FullyConnectedFunctions/*.c"
+            "${CMSIS_NNSource_DIR}/Source/LSTMFunctions/*.c"
+            "${CMSIS_NNSource_DIR}/Source/NNSupportFunctions/*.c"
+            "${CMSIS_NNSource_DIR}/Source/PoolingFunctions/*.c"
+            "${CMSIS_NNSource_DIR}/Source/ReshapeFunctions/*.c"
+            "${CMSIS_NNSource_DIR}/Source/SoftmaxFunctions/*.c")
+    add_library(${OM_PAL_LIB} STATIC ${PAL_SOURCES})
+    set_property(TARGET ${OM_PAL_LIB} PROPERTY POSITION_INDEPENDENT_CODE ON)
+    target_include_directories(${OM_PAL_LIB} PRIVATE
+            "${CMSIS_NNSource_DIR}")
+    add_subdirectory(${CMSIS_NNSource_DIR} ${CMAKE_CURRENT_BINARY_DIR}/CMSISNN)
+    target_include_directories(${OM_PAL_LIB} PUBLIC
+            "${CMSIS_NNSource_DIR}/Include")
+    target_link_libraries(${TGT} PRIVATE ${OM_PAL_LIB})
+endmacro()
diff --git a/onert-micro/onert-micro/include/pal/common/PALAbs.h b/onert-micro/onert-micro/include/pal/common/PALAbs.h
new file mode 100644 (file)
index 0000000..fbb29f4
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_ABS_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_ABS_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Abs(const core::OMRuntimeShape &shape, const T *input_data, T *output_data)
+{
+  const uint32_t flat_size = shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  for (uint32_t i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = std::abs(input_data[i]);
+  }
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ABS_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALAddCommon.h b/onert-micro/onert-micro/include/pal/common/PALAddCommon.h
new file mode 100644 (file)
index 0000000..fb65c0e
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_ADD_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_ADD_COMMON_H
+
+#include "PALArithmeticOpCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+int8_t AddFunc(int8_t x, int8_t y, const core::ArithmeticQuantParams &params)
+{
+  const int32_t input1_val = params.input1_offset + x;
+  const int32_t input2_val = params.input2_offset + y;
+  const int32_t shifted_input1_val = input1_val * (1 << params.left_shift);
+  const int32_t shifted_input2_val = input2_val * (1 << params.left_shift);
+  const int32_t scaled_input1_val = multiplyByQuantizedMultiplierSmallerThanOneExp(
+    shifted_input1_val, params.input1_multiplier, params.input1_shift);
+  const int32_t scaled_input2_val = multiplyByQuantizedMultiplierSmallerThanOneExp(
+    shifted_input2_val, params.input2_multiplier, params.input2_shift);
+  const int32_t raw_sum = scaled_input1_val + scaled_input2_val;
+  const int32_t raw_output = multiplyByQuantizedMultiplierSmallerThanOneExp(
+                               raw_sum, params.output_multiplier, params.output_shift) +
+                             params.output_offset;
+  const int32_t clamped_output = std::min(params.quantized_activation_max,
+                                          std::max(params.quantized_activation_min, raw_output));
+  return static_cast<int8_t>(clamped_output);
+}
+
+template <typename T>
+OMStatus Add(const core::BinaryArithmeticBroadcastParams &params, const int flat_size,
+             const T *input1_data, const T *input2_data, T *output_data)
+{
+  ArithmeticOp<T, AddFn<T>>(params, flat_size, input1_data, input2_data, output_data);
+  return Ok;
+}
+
+template <typename T>
+OMStatus BroadcastAdd4DSlow(const core::BinaryArithmeticBroadcastParams &params,
+                            const core::OMRuntimeShape &input1_shape, const T *input1_data,
+                            const core::OMRuntimeShape &input2_shape, const T *input2_data,
+                            const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  BroadcastArithmeticOp4DSlow<T, AddFn<T>>(params, input1_shape, input1_data, input2_shape,
+                                           input2_data, output_shape, output_data);
+  return Ok;
+}
+
+OMStatus BroadcastAdd4DSlow(const core::ArithmeticQuantParams &params,
+                            const core::OMRuntimeShape &input1_shape, const int8_t *input1_data,
+                            const core::OMRuntimeShape &input2_shape, const int8_t *input2_data,
+                            const core::OMRuntimeShape &output_shape, int8_t *output_data)
+{
+  BroadcastBinaryFunction6DSlow(params, input1_shape, input1_data, input2_shape, input2_data,
+                                output_shape, output_data, AddFunc);
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ADD_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALAddNCommon.h b/onert-micro/onert-micro/include/pal/common/PALAddNCommon.h
new file mode 100644 (file)
index 0000000..7f13eb6
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_ADD_N_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_ADD_N_COMMON_H
+
+#include "PALArithmeticOpCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+// T is expected to be either float or int.
+template <typename T>
+OMStatus 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;
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ADD_N_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALArgMinMaxCommon.h b/onert-micro/onert-micro/include/pal/common/PALArgMinMaxCommon.h
new file mode 100644 (file)
index 0000000..8f57a3a
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_ARG_MIN_MAX_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_ARG_MIN_MAX_COMMON_H
+#include "PALUtils.h"
+#include "core/OMRuntimeShape.h"
+#include "core/OMKernelData.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T1, typename T2, typename T3, typename Cmp>
+OMStatus ArgMinMax(const core::OMRuntimeShape &input1_shape, const T1 *input1_data,
+                   const T3 *input2_data, const core::OMRuntimeShape &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;
+    }
+  }
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ARG_MIN_MAX_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALArithmeticOpCommon.h b/onert-micro/onert-micro/include/pal/common/PALArithmeticOpCommon.h
new file mode 100644 (file)
index 0000000..608cbd7
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_ARITHMETIC_OP_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_ARITHMETIC_OP_COMMON_H
+
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+
+#include "core/OMKernelData.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T> struct AddFn
+{
+  T operator()(T lhs, T rhs) { return lhs + rhs; }
+};
+template <typename T> struct SubFn
+{
+  T operator()(T lhs, T rhs) { return lhs - rhs; }
+};
+template <typename T> struct MulFn
+{
+  T operator()(T lhs, T rhs) { return lhs * rhs; }
+};
+template <typename T> struct DivFn
+{
+  T operator()(T lhs, T rhs) { return lhs / rhs; }
+};
+template <typename T> struct SquaredDifferenceFn
+{
+  T operator()(T lhs, T rhs) { return (lhs - rhs) * (lhs - rhs); }
+};
+template <typename T, typename Fn>
+OMStatus ArithmeticOp(const core::BinaryArithmeticBroadcastParams &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);
+
+  Fn func;
+  for (int i = 0; i < flat_size; ++i)
+    output_data[i] =
+      std::min(std::max(func(input1_data[i], input2_data[i]), activation_min), activation_max);
+
+  return Ok;
+}
+
+template <typename T>
+void ElementWise(const uint32_t size, const core::ArithmeticQuantParams &params,
+                 const T *input1_data, const T *input2_data, T *output_data,
+                 T (*binary_func)(T, T, const core::ArithmeticQuantParams &))
+{
+  for (int i = 0; i < size; ++i)
+  {
+    output_data[i] = binary_func(input1_data[i], input2_data[i], params);
+  }
+}
+
+template <typename T, typename Fn>
+inline void ArithmeticOpScalar(const core::BinaryArithmeticBroadcastParams &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(func(input_data[i], scalar_value), activation_min), activation_max);
+}
+
+template <typename T, typename Fn>
+OMStatus BroadcastArithmeticOp4DSlow(const core::BinaryArithmeticBroadcastParams &params,
+                                     const core::OMRuntimeShape &input1_shape, const T *input1_data,
+                                     const core::OMRuntimeShape &input2_shape, const T *input2_data,
+                                     const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  NdArrayDesc<4> desc1;
+  NdArrayDesc<4> desc2;
+  NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, &desc2);
+  const core::OMRuntimeShape extended_output_shape =
+    core::OMRuntimeShape::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.
+  Fn func;
+  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(func(input1_data[subscriptToIndex(desc1, b, y, x, c)],
+                                   input2_data[subscriptToIndex(desc2, b, y, x, c)]),
+                              activation_min),
+                     activation_max);
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+template <typename T>
+void BroadcastInput1(int size, const core::ArithmeticQuantParams &params, const T *input1_data,
+                     const T *input2_data, T *output_data,
+                     T (*binary_func)(T, T, const core::ArithmeticQuantParams &))
+{
+  for (int i = 0; i < size; ++i)
+  {
+    output_data[i] = binary_func(input1_data[0], input2_data[i], params);
+  }
+}
+
+template <typename T>
+void BroadcastInput2(int size, const core::ArithmeticQuantParams &params, const T *input1_data,
+                     const T *input2_data, T *output_data,
+                     T (*binary_func)(T, T, const core::ArithmeticQuantParams &))
+{
+  for (int i = 0; i < size; ++i)
+  {
+    output_data[i] = binary_func(input1_data[i], input2_data[0], params);
+  }
+}
+
+template <typename T>
+void BroadcastRecursiveDimensions(const core::ArithmeticQuantParams &params, int dimension,
+                                  size_t *input1_offset_p, size_t *input2_offset_p,
+                                  size_t *output_offset, size_t *compressed_input1_stride,
+                                  size_t *compressed_input2_stride, size_t *compressed_output_shape,
+                                  const T *input1_data, const T *input2_data, T *output_data,
+                                  T (*binary_func)(T, T, const core::ArithmeticQuantParams &))
+{
+  if (dimension > 0)
+  {
+    for (size_t c = 0; c < compressed_output_shape[dimension]; ++c)
+    {
+      size_t input1_offset_c = *input1_offset_p;
+      size_t input2_offset_c = *input2_offset_p;
+      BroadcastRecursiveDimensions(params, dimension - 1, &input1_offset_c, &input2_offset_c,
+                                   output_offset, compressed_input1_stride,
+                                   compressed_input2_stride, compressed_output_shape, input1_data,
+                                   input2_data, output_data, binary_func);
+      *input1_offset_p += compressed_input1_stride[dimension];
+      *input2_offset_p += compressed_input2_stride[dimension];
+    }
+  }
+  else
+  {
+    assert(dimension == 0);
+    bool input1_is_broadcast = compressed_input1_stride[dimension] == 0;
+    bool input2_is_broadcast = compressed_input2_stride[dimension] == 0;
+    assert(!(input1_is_broadcast && input2_is_broadcast));
+    const T *input1_data_ptr = input1_data + *input1_offset_p;
+    const T *input2_data_ptr = input2_data + *input2_offset_p;
+    T *output_data_ptr = output_data + *output_offset;
+    if (input1_is_broadcast)
+    {
+      // input1 is broadcast.
+      BroadcastInput1<T>(compressed_output_shape[dimension], params, input1_data_ptr,
+                         input2_data_ptr, output_data_ptr, binary_func);
+      *input2_offset_p += compressed_output_shape[dimension];
+    }
+    else if (input2_is_broadcast)
+    {
+      // input2 is broadcast.
+      BroadcastInput2<T>(compressed_output_shape[dimension], params, input1_data_ptr,
+                         input2_data_ptr, output_data_ptr, binary_func);
+      *input1_offset_p += compressed_output_shape[dimension];
+    }
+    else
+    {
+      // Add element-wise.
+      ElementWise<T>(compressed_output_shape[dimension], params, input1_data_ptr, input2_data_ptr,
+                     output_data_ptr, binary_func);
+      *input1_offset_p += compressed_output_shape[dimension];
+      *input2_offset_p += compressed_output_shape[dimension];
+    }
+    *output_offset += compressed_output_shape[dimension];
+  }
+}
+
+template <typename T>
+void BroadcastBinaryFunction6DSlow(const core::ArithmeticQuantParams &params,
+                                   const core::OMRuntimeShape &input1_shape, const T *input1_data,
+                                   const core::OMRuntimeShape &input2_shape, const T *input2_data,
+                                   const core::OMRuntimeShape &output_shape, T *output_data,
+                                   T (*binary_func)(T, T, const core::ArithmeticQuantParams &))
+{
+  constexpr int kMaxBroadcastDim = 6;
+
+  // 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.
+  size_t compressed_input1_stride[kMaxBroadcastDim];
+  size_t compressed_input2_stride[kMaxBroadcastDim];
+  size_t compressed_output_shape[kMaxBroadcastDim];
+  bool broadcastable_shape = ReduceDimensionsForBroadcast<kMaxBroadcastDim>(
+    input1_shape, input2_shape, compressed_input1_stride, compressed_input2_stride,
+    compressed_output_shape);
+  // Skip broadcasting for degenerate shapes.
+  if (!broadcastable_shape)
+  {
+    return;
+  }
+
+  size_t input1_offset = 0;
+  size_t input2_offset = 0;
+  size_t output_offset = 0;
+  BroadcastRecursiveDimensions(params, kMaxBroadcastDim - 1, &input1_offset, &input2_offset,
+                               &output_offset, compressed_input1_stride, compressed_input2_stride,
+                               compressed_output_shape, input1_data, input2_data, output_data,
+                               binary_func);
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ARITHMETIC_OP_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALAveragePool2DCommon.h b/onert-micro/onert-micro/include/pal/common/PALAveragePool2DCommon.h
new file mode 100644 (file)
index 0000000..1657955
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_AVERAGE_POOL_2D_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_AVERAGE_POOL_2D_COMMON_H
+
+#include "PALUtils.h"
+
+#include "core/OMKernelData.h"
+#include "core/OMRuntimeShape.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+// TODO: Reduce code duplication with other pools
+OMStatus AveragePool(const core::Pool2DParams &params, const core::OMRuntimeShape &input_shape,
+                     const float *input_data, const core::OMRuntimeShape &output_shape,
+                     float *output_data)
+{
+  const int32_t batches = input_shape.dims(0);
+  const int32_t depth = output_shape.dims(3);
+  const int32_t input_height = input_shape.dims(1);
+  const int32_t input_width = input_shape.dims(2);
+  const int32_t output_height = output_shape.dims(1);
+  const int32_t output_width = output_shape.dims(2);
+  const int32_t stride_height = params.stride_h;
+  const int32_t stride_width = params.stride_w;
+  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.pad_w;
+          const int in_y_origin = (out_y * stride_height) - params.pad_h;
+          // 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(static_cast<int32_t>(params.filter_w),
+                                            static_cast<int32_t>(input_width - in_x_origin));
+          const int filter_y_start = std::max(0, -in_y_origin);
+          const int filter_y_end = std::min(static_cast<int32_t>(params.filter_h),
+                                            static_cast<int32_t>(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.activation_min), params.activation_max);
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_AVERAGE_POOL_2D_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALBatchToSpaceNDCommon.h b/onert-micro/onert-micro/include/pal/common/PALBatchToSpaceNDCommon.h
new file mode 100644 (file)
index 0000000..89820a9
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_BATCH_TO_SPACE_ND_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_BATCH_TO_SPACE_ND_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+namespace
+{
+inline core::OMRuntimeShape extendShapeBatchToSpace(const core::OMRuntimeShape &shape)
+{
+  if (shape.dimensionsCount() == 4)
+  {
+    return shape;
+  }
+  core::OMRuntimeShape new_shape(4, 1);
+  new_shape.setDim(0, shape.dims(0));
+  new_shape.setDim(1, shape.dims(1));
+  new_shape.setDim(3, shape.dims(2));
+  return new_shape;
+}
+} // namespace
+
+template <typename T>
+inline OMStatus
+BatchToSpaceND(const core::OMRuntimeShape &unextended_input1_shape, const T *input1_data,
+               const core::OMRuntimeShape &unextended_input2_shape, const int32_t *block_shape_data,
+               const core::OMRuntimeShape &unextended_input3_shape, const int32_t *crops_data,
+               const core::OMRuntimeShape &unextended_output_shape, T *output_data)
+{
+  const core::OMRuntimeShape input1_shape = extendShapeBatchToSpace(unextended_input1_shape);
+  const core::OMRuntimeShape output_shape = extendShapeBatchToSpace(unextended_output_shape);
+
+  const int output_width = output_shape.dims(2);
+  const int output_height = output_shape.dims(1);
+  const int output_batch_size = output_shape.dims(0);
+
+  const int depth = input1_shape.dims(3);
+  const int input_width = input1_shape.dims(2);
+  const int input_height = input1_shape.dims(1);
+  const int input_batch_size = input1_shape.dims(0);
+
+  const int block_shape_height = block_shape_data[0];
+  const int block_shape_width =
+    unextended_input1_shape.dimensionsCount() == 4 ? block_shape_data[1] : 1;
+  const int crops_top = crops_data[0];
+  const int crops_left = unextended_input1_shape.dimensionsCount() == 4 ? crops_data[2] : 0;
+  for (int in_batch = 0; in_batch < input_batch_size; ++in_batch)
+  {
+    const int out_batch = in_batch % output_batch_size;
+    const int spatial_offset = in_batch / output_batch_size;
+    for (int in_h = 0; in_h < input_height; ++in_h)
+    {
+      const int out_h = in_h * block_shape_height + spatial_offset / block_shape_width - crops_top;
+      if (out_h < 0 || out_h >= output_height)
+      {
+        continue;
+      }
+      for (int in_w = 0; in_w < input_width; ++in_w)
+      {
+        const int out_w =
+          in_w * block_shape_width + spatial_offset % block_shape_width - crops_left;
+
+        if (out_w < 0 || out_w >= output_width)
+        {
+          continue;
+        }
+        T *out = output_data + offset(output_shape.dimsData(), out_batch, out_h, out_w, 0);
+        const T *in = input1_data + offset(input1_shape.dimsData(), in_batch, in_h, in_w, 0);
+        memcpy(out, in, depth * sizeof(T));
+      }
+    }
+  }
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_BATCH_TO_SPACE_ND_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALBinaryOpCommon.h b/onert-micro/onert-micro/include/pal/common/PALBinaryOpCommon.h
new file mode 100644 (file)
index 0000000..ade2e28
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_BINARYOP_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_BINARYOP_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
+struct FloorDivFn
+{
+  T operator()(T lhs, T rhs)
+  {
+    return std::floor(static_cast<double>(lhs) / static_cast<double>(rhs));
+  }
+};
+template <typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
+struct FloorModFn
+{
+  T operator()(T lhs, T rhs)
+  {
+    T trunc_mod = std::fmod(lhs, rhs);
+    return (trunc_mod != 0) && ((rhs < 0) != (trunc_mod < 0)) ? (trunc_mod + rhs) : trunc_mod;
+  }
+};
+template <typename T> struct MaximumFn
+{
+  T operator()(T lhs, T rhs) { return std::max(lhs, rhs); }
+};
+template <typename T> struct MinimumFn
+{
+  T operator()(T lhs, T rhs) { return std::min(lhs, rhs); }
+};
+
+// TODO: check if there real activation value
+template <typename T, typename Fn>
+inline OMStatus BinaryOp(const int flat_size, const T *input1_data, const T *input2_data,
+                         T *output_data)
+{
+  Fn func;
+  for (int i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = func(input1_data[i], input2_data[i]);
+  }
+  return Ok;
+}
+
+template <typename T, typename Fn>
+inline OMStatus
+BroadcastBinaryOp4DSlow(const core::OMRuntimeShape &input1_shape, const float *input1_data,
+                        const core::OMRuntimeShape &input2_shape, const float *input2_data,
+                        const core::OMRuntimeShape &output_shape, float *output_data)
+{
+  NdArrayDesc<4> desc1;
+  NdArrayDesc<4> desc2;
+  NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, &desc2);
+
+  const core::OMRuntimeShape extended_output_shape =
+    core::OMRuntimeShape::extendedShape(4, output_shape);
+
+  // 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.
+
+  Fn func;
+  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] = func(input1_data[subscriptToIndex(desc1, b, y, x, c)],
+                                                 input2_data[subscriptToIndex(desc2, b, y, x, c)]);
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_BINARYOP_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALComparisons.h b/onert-micro/onert-micro/include/pal/common/PALComparisons.h
new file mode 100644 (file)
index 0000000..0f37d2f
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_COMPARISONS_H
+#define ONERT_MICRO_EXECUTE_PAL_COMPARISONS_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+namespace
+{
+
+struct BroadcastComparison4DSlowCommon
+{
+  const core::OMRuntimeShape output_shape;
+  NdArrayDesc<4> desc1;
+  NdArrayDesc<4> desc2;
+};
+
+inline BroadcastComparison4DSlowCommon
+BroadcastComparison4DSlowPreprocess(const core::OMRuntimeShape &unextended_input1_shape,
+                                    const core::OMRuntimeShape &unextended_input2_shape,
+                                    const core::OMRuntimeShape &unextended_output_shape)
+{
+  NdArrayDesc<4> desc1;
+  NdArrayDesc<4> desc2;
+  NdArrayDescsForElementwiseBroadcast(unextended_input1_shape, unextended_input2_shape, &desc1,
+                                      &desc2);
+  return {core::OMRuntimeShape::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 core::ComparisonParams &op_params, const core::OMRuntimeShape &unextended_input1_shape,
+  const T *input1_data, const core::OMRuntimeShape &unextended_input2_shape, const T *input2_data,
+  const core::OMRuntimeShape &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 core::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 core::ComparisonParams &op_params, const core::OMRuntimeShape &unextended_input1_shape,
+  const T *input1_data, const core::OMRuntimeShape &unextended_input2_shape, const T *input2_data,
+  const core::OMRuntimeShape &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 pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_BINARYOP_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALConcatenation.h b/onert-micro/onert-micro/include/pal/common/PALConcatenation.h
new file mode 100644 (file)
index 0000000..dccfe18
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_CONCATENATION_H
+#define ONERT_MICRO_EXECUTE_PAL_CONCATENATION_H
+
+#include "PALUtils.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <typename Scalar>
+OMStatus Concatenation(core::ConcatenationParams &params, std::vector<uint32_t> &input_shapes,
+                       std::vector<const Scalar *> &input_data,
+                       const core::OMRuntimeShape &output_shape, Scalar *output_data)
+{
+  int axis = params.axis;
+  int inputs_count = params.num_inputs;
+  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];
+  }
+  int64_t outer_size = 1;
+  for (int i = 0; i < axis; ++i)
+  {
+    outer_size *= output_shape.dims(i);
+  }
+  // For all input arrays,
+  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] * 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;
+    }
+  }
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_CONCATENATION_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALConv2DCommon.h b/onert-micro/onert-micro/include/pal/common/PALConv2DCommon.h
new file mode 100644 (file)
index 0000000..970230b
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_CONV2D_COMMON_H
+#define ONERT_MICRO_PAL_CONV2D_COMMON_H
+
+#include "PALUtils.h"
+
+#include "OMStatus.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+OMStatus ConvFloat(const core::FloatConv2D *params, const core::OMRuntimeShape &input_shape,
+                   const float *input_data, const core::OMRuntimeShape &filter_shape,
+                   const float *filter_data, const float *bias_data,
+                   const core::OMRuntimeShape &output_shape, float *output_data)
+{
+  const int stride_width = params->stride_w;
+  const int stride_height = params->stride_h;
+  const int dilation_width_factor = params->dilation_width_factor;
+  const int dilation_height_factor = params->dilation_height_factor;
+  const int pad_width = params->pad_w;
+  const int pad_height = params->pad_h;
+  const float output_activation_min = params->activation_min;
+  const float output_activation_max = params->activation_max;
+
+  const auto batches = input_shape.dims(0);
+  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 output_depth = filter_shape.dims(0);
+  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);
+  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);
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_PAL_CONV2D_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALConv2DInputGrad.h b/onert-micro/onert-micro/include/pal/common/PALConv2DInputGrad.h
new file mode 100644 (file)
index 0000000..7405f76
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_COMMON_CONV2D_INPUT_GRAD_H
+#define ONERT_MICRO_PAL_COMMON_CONV2D_INPUT_GRAD_H
+
+#include "PALUtils.h"
+#include "core/OMKernelData.h"
+#include "OMStatus.h"
+
+namespace onert_micro
+{
+namespace train
+{
+namespace pal
+{
+
+namespace
+{
+
+/*
+ * Rotate square 2D weights by 180 degrees
+ */
+void rotate_180(float *weights, uint32_t num_rows, uint32_t num_cols, uint32_t oc, uint32_t ic,
+                uint32_t num_input_channels)
+{
+  for (int row = 0; row < num_rows; ++row)
+  {
+    for (int col = 0; col < num_cols / 2; ++col)
+    {
+      uint32_t offset = ic + col * num_input_channels + row * num_cols * num_input_channels +
+                        oc * num_cols * num_input_channels * num_rows;
+      uint32_t rotated_offset = ic + (num_cols - col - 1) * num_input_channels +
+                                row * num_cols * num_input_channels +
+                                oc * num_cols * num_input_channels * num_rows;
+
+      float tmp_value = weights[offset];
+      weights[offset] = weights[rotated_offset];
+      weights[rotated_offset] = tmp_value;
+    }
+  }
+}
+
+} // namespace
+
+void Conv2DInputGrad(const core::FloatConv2D &params, const core::OMRuntimeShape &weight_shape,
+                     const float *weight_data, const core::OMRuntimeShape &dloss_doutput_shape,
+                     const float *dloss_doutput_data,
+                     const core::OMRuntimeShape &dloss_dinput_shape, float *dloss_dinput_data)
+{
+  const int stride_width = params.stride_w;
+  const int stride_height = params.stride_h;
+  const int dilation_width_factor = params.dilation_width_factor;
+  const int dilation_height_factor = params.dilation_height_factor;
+  const int pad_width = 0;
+  const int pad_height = 0;
+
+  const int weight_h = weight_shape.dims(1);
+  const int weight_w = weight_shape.dims(2);
+  const int weight_d = weight_shape.dims(3);
+  const int dloss_doutput_h = dloss_doutput_shape.dims(1);
+  const int dloss_doutput_w = dloss_doutput_shape.dims(2);
+  const int dloss_doutput_d = dloss_doutput_shape.dims(3);
+  const int dloss_dinput_h = dloss_dinput_shape.dims(1);
+  const int dloss_dinput_w = dloss_dinput_shape.dims(2);
+  const int dloss_dinput_d = dloss_dinput_shape.dims(3);
+
+  auto *n_c_weight_data = const_cast<float *>(weight_data);
+
+  for (uint32_t oc = 0; oc < dloss_dinput_d; ++oc)
+  {
+    for (uint32_t ic = 0; ic < dloss_doutput_d; ++ic)
+    {
+      rotate_180(n_c_weight_data, weight_h, weight_w, ic, oc, dloss_dinput_d);
+      for (int out_y = 0; out_y < dloss_dinput_h; ++out_y)
+      {
+        for (int out_x = 0; out_x < dloss_dinput_w; ++out_x)
+        {
+          const int in_x_origin = (out_x * stride_width) - pad_width;
+          const int in_y_origin = (out_y * stride_height) - pad_height;
+          float total = 0.f;
+
+          for (int filter_y = 0; filter_y < weight_h; ++filter_y)
+          {
+            for (int filter_x = 0; filter_x < weight_w; ++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;
+              // If the location is outside the bounds of the input image,
+              // use zero as a default value.
+              if ((in_x >= 0) && (in_x < dloss_doutput_w) && (in_y >= 0) &&
+                  (in_y < dloss_doutput_h))
+              {
+                uint32_t input_offset =
+                  in_x * dloss_doutput_d + in_y * dloss_doutput_w * dloss_doutput_d + ic;
+                uint32_t filter_offset = oc + filter_x * dloss_dinput_d +
+                                         filter_y * weight_w * dloss_dinput_d +
+                                         ic * weight_w * dloss_dinput_d * weight_h;
+                assert(input_offset < dloss_doutput_shape.flatSize());
+                assert(filter_offset < weight_shape.flatSize());
+                float input_value = dloss_doutput_data[input_offset];
+                float filter_value = n_c_weight_data[filter_offset];
+                total += (input_value * filter_value);
+              }
+            }
+          }
+          uint32_t output_offset =
+            oc + dloss_dinput_d * out_x + out_y * dloss_dinput_d * dloss_dinput_w;
+          assert(output_offset < dloss_dinput_shape.flatSize());
+          dloss_dinput_data[output_offset] = total;
+        }
+      }
+      // Rotate back
+      rotate_180(n_c_weight_data, weight_h, weight_w, ic, oc, dloss_dinput_d);
+    }
+  }
+}
+
+} // namespace pal
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_PAL_COMMON_CONV2D_INPUT_GRAD_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALConv2DWeightGrad.h b/onert-micro/onert-micro/include/pal/common/PALConv2DWeightGrad.h
new file mode 100644 (file)
index 0000000..9a75ccb
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_COMMON_CONV2D_WEIGHT_GRAD_H
+#define ONERT_MICRO_PAL_COMMON_CONV2D_WEIGHT_GRAD_H
+
+#include "PALUtils.h"
+#include "core/OMKernelData.h"
+#include "OMStatus.h"
+
+namespace onert_micro
+{
+namespace train
+{
+namespace pal
+{
+void Conv2DBiasGrad(const core::OMRuntimeShape &dloss_doutput_shape,
+                    const float *dloss_doutput_data, float *dloss_dbias_data)
+{
+  assert(dloss_doutput_shape.dimensionsCount() == 4);
+  assert(dloss_doutput_shape.dims(0) == 1);
+  const int dloss_doutput_h = dloss_doutput_shape.dims(1);
+  const int dloss_doutput_w = dloss_doutput_shape.dims(2);
+  const int dloss_doutput_d = dloss_doutput_shape.dims(3);
+
+  // Reduce sum over last dim
+  for (uint32_t oc = 0; oc < dloss_doutput_d; ++oc)
+  {
+    float total = 0.f;
+    for (uint32_t h = 0; h < dloss_doutput_h; ++h)
+    {
+      for (uint32_t w = 0; w < dloss_doutput_w; ++w)
+      {
+        uint32_t offset = oc + w * dloss_doutput_d + h * dloss_doutput_w * dloss_doutput_d;
+        assert(offset < dloss_doutput_shape.flatSize());
+        total +=
+          dloss_doutput_data[oc + w * dloss_doutput_d + h * dloss_doutput_w * dloss_doutput_d];
+      }
+    }
+    dloss_dbias_data[oc] = total;
+  }
+}
+
+void Conv2DWeightGrad(const core::FloatConv2D &params, const core::OMRuntimeShape &input_shape,
+                      const float *input_data, const core::OMRuntimeShape &dloss_doutput_shape,
+                      const float *dloss_doutput_data,
+                      const core::OMRuntimeShape &dloss_dweight_shape, float *dloss_dweight_data)
+{
+  const int stride_width = params.stride_w;
+  const int stride_height = params.stride_h;
+  const int dilation_width_factor = params.dilation_width_factor;
+  const int dilation_height_factor = params.dilation_height_factor;
+  const int pad_width = 0;
+  const int pad_height = 0;
+
+  const int batches = dloss_doutput_shape.dims(0);
+  const int input_h = input_shape.dims(1);
+  const int input_w = input_shape.dims(2);
+  const int input_d = input_shape.dims(3);
+  const int dloss_doutput_h = dloss_doutput_shape.dims(1);
+  const int dloss_doutput_w = dloss_doutput_shape.dims(2);
+  const int dloss_doutput_d = dloss_doutput_shape.dims(3);
+  const int dloss_dweight_h = dloss_dweight_shape.dims(1);
+  const int dloss_dweight_w = dloss_dweight_shape.dims(2);
+  const int dloss_dweight_d = dloss_dweight_shape.dims(3);
+
+  for (uint32_t oc = 0; oc < dloss_doutput_d; ++oc)
+  {
+    for (uint32_t ic = 0; ic < input_d; ++ic)
+    {
+      for (int out_y = 0; out_y < dloss_dweight_h; ++out_y)
+      {
+        for (int out_x = 0; out_x < dloss_dweight_w; ++out_x)
+        {
+          const int in_x_origin = (out_x * stride_width) - pad_width;
+          const int in_y_origin = (out_y * stride_height) - pad_height;
+          float total = 0.f;
+
+          for (int filter_y = 0; filter_y < dloss_doutput_h; ++filter_y)
+          {
+            for (int filter_x = 0; filter_x < dloss_doutput_w; ++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;
+              // If the location is outside the bounds of the input image,
+              // use zero as a default value.
+              if ((in_x >= 0) && (in_x < input_w) && (in_y >= 0) && (in_y < input_h))
+              {
+                uint32_t input_offset = in_x * input_d + in_y * input_w * input_d + ic;
+                uint32_t filter_offset =
+                  oc + filter_x * dloss_doutput_d + filter_y * dloss_doutput_w * dloss_doutput_d;
+                assert(input_offset < input_shape.flatSize());
+                assert(filter_offset < dloss_doutput_shape.flatSize());
+                float input_value = input_data[input_offset];
+                float filter_value = dloss_doutput_data[filter_offset];
+                total += (input_value * filter_value);
+              }
+            }
+          }
+          uint32_t output_offset = ic + input_d * out_x + input_d * dloss_dweight_w * out_y +
+                                   input_d * dloss_dweight_w * dloss_dweight_h * oc;
+          assert(output_offset < dloss_dweight_shape.flatSize());
+          dloss_dweight_data[output_offset] = total;
+        }
+      }
+    }
+  }
+}
+
+} // namespace pal
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_PAL_COMMON_CONV2D_WEIGHT_GRAD_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALCosCommon.h b/onert-micro/onert-micro/include/pal/common/PALCosCommon.h
new file mode 100644 (file)
index 0000000..99bc161
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_COS_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_COS_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "PALSISOOperation.h"
+#include "PALUtils.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Cos(const core::OMRuntimeShape &input_shape, const T *input_data,
+                    const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    output_data[i] = std::cos(input_data[i]);
+  }
+
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_COS_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALDepthwiseConv2DCommon.h b/onert-micro/onert-micro/include/pal/common/PALDepthwiseConv2DCommon.h
new file mode 100644 (file)
index 0000000..1b00652
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_DEPTHWISE_CONV_2D_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_DEPTHWISE_CONV_2D_COMMON_H
+
+#include "PALUtils.h"
+#include "core/OMKernelData.h"
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include <cassert>
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <typename T>
+inline OMStatus
+DepthwiseConv2D(const core::FloatConv2D *params, const core::OMRuntimeShape &input_shape,
+                const T *input_data, const core::OMRuntimeShape &filter_shape, const T *filter_data,
+                const T *bias_data, const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  assert(false && "Not IMPL yet");
+}
+template <>
+inline OMStatus
+DepthwiseConv2D<float>(const core::FloatConv2D *params, const core::OMRuntimeShape &input_shape,
+                       const float *input_data, const core::OMRuntimeShape &filter_shape,
+                       const float *filter_data, const float *bias_data,
+                       const core::OMRuntimeShape &output_shape, float *output_data)
+{
+  const int stride_width = params->stride_w;
+  const int stride_height = params->stride_h;
+  const int dilation_width_factor = params->dilation_width_factor;
+  const int dilation_height_factor = params->dilation_height_factor;
+  const int pad_width = params->pad_w;
+  const int pad_height = params->pad_h;
+  const int depth_multiplier = params->depth_multiplier;
+  const float output_activation_min = params->activation_min;
+  const float output_activation_max = params->activation_max;
+
+  const auto batches = input_shape.dims(0);
+  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 output_depth = filter_shape.dims(0);
+  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);
+  for (int b = 0; b < batches; ++b)
+  {
+    for (int out_y = 0; out_y < output_height; ++out_y)
+    {
+      for (int out_x = 0; out_x < output_width; ++out_x)
+      {
+        for (int ic = 0; ic < input_depth; ++ic)
+        {
+          for (int m = 0; m < depth_multiplier; m++)
+          {
+            const int oc = m + ic * depth_multiplier;
+            const int in_x_origin = (out_x * stride_width) - pad_width;
+            const int in_y_origin = (out_y * stride_height) - pad_height;
+            float total = 0.f;
+            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;
+                // 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))
+                {
+                  float input_value = input_data[offset(input_shape.dimsData(), b, in_y, in_x, ic)];
+                  float filter_value =
+                    filter_data[offset(filter_shape.dimsData(), 0, filter_y, filter_x, oc)];
+                  total += (input_value * filter_value);
+                }
+              }
+            }
+            float bias_value = 0.0f;
+            if (bias_data)
+            {
+              bias_value = bias_data[oc];
+            }
+            output_data[offset(output_shape.dimsData(), b, out_y, out_x, oc)] =
+              activationFunctionWithMinMax(total + bias_value, output_activation_min,
+                                           output_activation_max);
+          }
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+#endif // ONERT_MICRO_EXECUTE_PAL_DEPTHWISE_CONV_2D_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALDequantize.h b/onert-micro/onert-micro/include/pal/common/PALDequantize.h
new file mode 100644 (file)
index 0000000..6e6cd27
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_DEQUANTIZE_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_DEQUANTIZE_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "core/OMKernelData.h"
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename InputT, typename OutputT>
+OMStatus Dequantize(const core::QuantizationParams op_params, const uint32_t flat_size,
+                    const InputT *input_data, OutputT *output_data)
+{
+  const int32_t zero_point = op_params.zero_point;
+  const double scale = op_params.scale;
+
+  for (uint32_t i = 0; i < flat_size; i++)
+  {
+    const int32_t val = input_data[i];
+    const auto result = static_cast<OutputT>(scale * (val - zero_point));
+    output_data[i] = result;
+  }
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_DEQUANTIZE_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALDivCommon.h b/onert-micro/onert-micro/include/pal/common/PALDivCommon.h
new file mode 100644 (file)
index 0000000..a54b8eb
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_DIV_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_DIV_COMMON_H
+
+#include "PALArithmeticOpCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+OMStatus Div(const core::BinaryArithmeticBroadcastParams &params, const int flat_size,
+             const T *input1_data, const T *input2_data, T *output_data)
+{
+  ArithmeticOp<T, DivFn<T>>(params, flat_size, input1_data, input2_data, output_data);
+  return Ok;
+}
+
+template <typename T>
+OMStatus BroadcastDiv4DSlow(const core::BinaryArithmeticBroadcastParams &params,
+                            const core::OMRuntimeShape &input1_shape, const T *input1_data,
+                            const core::OMRuntimeShape &input2_shape, const T *input2_data,
+                            const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  BroadcastArithmeticOp4DSlow<T, DivFn<T>>(params, input1_shape, input1_data, input2_shape,
+                                           input2_data, output_shape, output_data);
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_MUL_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALExpCommon.h b/onert-micro/onert-micro/include/pal/common/PALExpCommon.h
new file mode 100644 (file)
index 0000000..19b629c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_EXP_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_EXP_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "PALSISOOperation.h"
+#include "PALUtils.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Exp(const core::OMRuntimeShape &input_shape, const T *input_data,
+                    const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    output_data[i] = std::exp(input_data[i]);
+  }
+
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_EXP_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALFloorCommon.h b/onert-micro/onert-micro/include/pal/common/PALFloorCommon.h
new file mode 100644 (file)
index 0000000..84e32e3
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_FLOOR_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_FLOOR_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Floor(const core::OMRuntimeShape &input_shape, const T *input_data,
+                      const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  // 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));
+  }
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    output_data[i] = std::floor(input_data[i]);
+  }
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_FLOOR_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALFloorDivCommon.h b/onert-micro/onert-micro/include/pal/common/PALFloorDivCommon.h
new file mode 100644 (file)
index 0000000..2acace5
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_FLOORDIV_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_FLOORDIV_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+#include "PALBinaryOpCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+inline void FloorDiv(const int flat_size, const float *input1_data, const float *input2_data,
+                     float *output_data)
+{
+  BinaryOp<float, FloorDivFn<float>>(flat_size, input1_data, input2_data, output_data);
+}
+
+inline void
+
+BroadcastFloorDiv4DSlow(const core::OMRuntimeShape &input1_shape, const float *input1_data,
+                        const core::OMRuntimeShape &input2_shape, const float *input2_data,
+                        const core::OMRuntimeShape &output_shape, float *output_data)
+{
+  BroadcastBinaryOp4DSlow<float, FloorDivFn<float>>(input1_shape, input1_data, input2_shape,
+                                                    input2_data, output_shape, output_data);
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_FLOORDIV_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALFloorModCommon.h b/onert-micro/onert-micro/include/pal/common/PALFloorModCommon.h
new file mode 100644 (file)
index 0000000..93aa971
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_FLOORMOD_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_FLOORMOD_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+#include "PALBinaryOpCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+inline void FloorMod(const int flat_size, const float *input1_data, const float *input2_data,
+                     float *output_data)
+{
+  BinaryOp<float, FloorModFn<float>>(flat_size, input1_data, input2_data, output_data);
+}
+
+inline void
+
+BroadcastFloorMod4DSlow(const core::OMRuntimeShape &input1_shape, const float *input1_data,
+                        const core::OMRuntimeShape &input2_shape, const float *input2_data,
+                        const core::OMRuntimeShape &output_shape, float *output_data)
+{
+  BroadcastBinaryOp4DSlow<float, FloorModFn<float>>(input1_shape, input1_data, input2_shape,
+                                                    input2_data, output_shape, output_data);
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_FLOORMOD_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALFullyConnectedCommon.h b/onert-micro/onert-micro/include/pal/common/PALFullyConnectedCommon.h
new file mode 100644 (file)
index 0000000..e0cd74c
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_FULLY_CONNECTED_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_FULLY_CONNECTED_COMMON_H
+
+#include "OMStatus.h"
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename InputType, typename WeightType, typename OutputType, typename BiasType>
+OMStatus FullyConnected(const core::FullyConnectedParams &params, const InputType *input_data,
+                        const core::OMRuntimeShape &filter_shape, const WeightType *filter_data,
+                        const BiasType *bias_data, const core::OMRuntimeShape &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 filter_dim_count = filter_shape.dimensionsCount();
+  const int output_dim_count = output_shape.dimensionsCount();
+  const int batches =
+    flatSizeSkipDim(output_shape.dimsData(), output_dim_count - 1, output_dim_count);
+  const int output_depth = output_shape.dims(output_dim_count - 1);
+
+  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);
+    }
+  }
+  return Ok;
+}
+
+template <>
+OMStatus inline FullyConnected<float>(const core::FullyConnectedParams &params,
+                                      const float *input_data,
+                                      const core::OMRuntimeShape &filter_shape,
+                                      const float *filter_data, const float *bias_data,
+                                      const core::OMRuntimeShape &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 = flatSizeSkipDim(output_shape.dimsData(), output_shape.dimensionsCount() - 1,
+                                      output_shape.dimensionsCount());
+  const int output_depth = output_shape.dims(output_shape.dimensionsCount() - 1);
+  const int accum_depth = filter_shape.dims(filter_shape.dimensionsCount() - 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);
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_FULLY_CONNECTED_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALFullyConnectedInputGrad.h b/onert-micro/onert-micro/include/pal/common/PALFullyConnectedInputGrad.h
new file mode 100644 (file)
index 0000000..16335ba
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_COMMON_FULLY_CONNECTED_INPUT_GRAD_H
+#define ONERT_MICRO_EXECUTE_PAL_COMMON_FULLY_CONNECTED_INPUT_GRAD_H
+
+#include "OMStatus.h"
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace pal
+{
+
+void inline FullyConnectedInputGrad(const float *dloss_doutput_data,
+                                    const core::OMRuntimeShape &dloss_doutput_shape,
+                                    const float *weight_data,
+                                    const core::OMRuntimeShape &weight_shape,
+                                    float *dloss_dinput_data)
+{
+  const uint32_t input_rows = dloss_doutput_shape.dims(0);
+  const uint32_t input_col = weight_shape.dims(1);
+  const uint32_t output_cols = dloss_doutput_shape.dims(1);
+
+  for (uint32_t i = 0; i < input_rows; ++i)
+  {
+    for (uint32_t j = 0; j < input_col; ++j)
+    {
+      float total = 0.f;
+      for (uint32_t o = 0; o < output_cols; ++o)
+      {
+        total += weight_data[o * input_col + j] * dloss_doutput_data[o + i * output_cols];
+      }
+      dloss_dinput_data[j + i * input_col] = total;
+    }
+  }
+}
+
+} // namespace pal
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_COMMON_FULLY_CONNECTED_WEIGHT_GRAD_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALFullyConnectedWeightGrad.h b/onert-micro/onert-micro/include/pal/common/PALFullyConnectedWeightGrad.h
new file mode 100644 (file)
index 0000000..1152649
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_COMMON_FULLY_CONNECTED_WEIGHT_GRAD_H
+#define ONERT_MICRO_EXECUTE_PAL_COMMON_FULLY_CONNECTED_WEIGHT_GRAD_H
+
+#include "OMStatus.h"
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace pal
+{
+
+void inline FullyConnectedWeightGrad(const float *dloss_doutput_data,
+                                     const core::OMRuntimeShape &dloss_doutput_shape,
+                                     const float *input_data,
+                                     const core::OMRuntimeShape &input_shape,
+                                     float *dloss_dweight_data)
+{
+  const uint32_t batches = input_shape.dims(0);
+  const uint32_t output_depth = dloss_doutput_shape.dims(1);
+  const uint32_t accum_depth = input_shape.dims(1);
+
+  for (uint32_t o = 0; o < output_depth; ++o)
+  {
+    float cur_dloss_doutput = dloss_doutput_data[o];
+    for (uint32_t i = 0; i < accum_depth; ++i)
+    {
+      dloss_dweight_data[i + o * accum_depth] = cur_dloss_doutput * input_data[i];
+    }
+  }
+
+  for (int b = 1; b < batches; ++b)
+  {
+    for (uint32_t o = 0; o < output_depth; ++o)
+    {
+      float cur_dloss_doutput = dloss_doutput_data[o + b * output_depth];
+      for (uint32_t i = 0; i < accum_depth; ++i)
+      {
+        dloss_dweight_data[i + o * accum_depth] +=
+          cur_dloss_doutput * input_data[i + b * accum_depth];
+      }
+    }
+  }
+}
+
+} // namespace pal
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_COMMON_FULLY_CONNECTED_WEIGHT_GRAD_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALGatherND.h b/onert-micro/onert-micro/include/pal/common/PALGatherND.h
new file mode 100644 (file)
index 0000000..ca636bb
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_GATHER_ND_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_GATHER_ND_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+constexpr int MAX_INDICES_ND = 5;
+
+template <typename ParamsT, typename IndicesT>
+inline OMStatus GatherND(core::OMRuntimeShape params_shape, const ParamsT *param_data,
+                         core::OMRuntimeShape indices_shape, const IndicesT *index_data,
+                         ParamsT *output_data)
+{
+  const int indices_dims = indices_shape.dimensionsCount();
+  const int indices_nd = indices_shape.dims(indices_dims - 1);
+  const int params_dims = params_shape.dimensionsCount();
+
+  int n_slices = 1;
+  for (int i = 0; i < indices_dims - 1; ++i)
+  {
+    n_slices *= indices_shape.dims(i);
+  }
+
+  // If indices[-1] == params.rank, fetch single elements.
+  // If indices[-1] < params.rank, fetch slices.
+  int slice_size = 1;
+  for (int i = indices_nd; i < params_dims; ++i)
+  {
+    slice_size *= params_shape.dims(i);
+  }
+
+  int params_flat_size = params_shape.flatSize();
+  int remain_flat_size = params_flat_size;
+
+  // Number of elements per dimension
+  int dims_to_count[MAX_INDICES_ND];
+  for (int i = 0; i < indices_nd; ++i)
+  {
+    dims_to_count[i] = remain_flat_size / params_shape.dims(i);
+    remain_flat_size = dims_to_count[i];
+  }
+
+  for (int i = 0; i < n_slices; ++i)
+  {
+    int from_pos = 0;
+    for (int j = 0; j < indices_nd; ++j)
+    {
+      int offset = i * indices_nd + j;
+      IndicesT index = index_data[offset];
+      from_pos += index * dims_to_count[j];
+    }
+    if (from_pos < 0 || from_pos + slice_size > params_flat_size)
+    {
+      assert(false && "GatherND error");
+      return UnknownError;
+    }
+    std::memcpy(output_data + i * slice_size, param_data + from_pos, sizeof(ParamsT) * slice_size);
+  }
+
+  return Ok;
+}
+
+} // namespace pal
+
+} // namespace execute
+
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_GATHER_ND_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALL2Normalize.h b/onert-micro/onert-micro/include/pal/common/PALL2Normalize.h
new file mode 100644 (file)
index 0000000..0f0b9f4
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_L2_NORMALIZE_COMMON_H
+#define ONERT_MICRO_L2_NORMALIZE_COMMON_H
+
+#include "core/OMKernelData.h"
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+inline OMStatus L2Normalization(const core::L2NormalizationParams &params, const float *input_data,
+                                float *output_data)
+{
+
+  const int outer_size = params.num_rows;
+  const int depth = params.row_size;
+  const int epsilon = params.epsilon;
+
+  for (int i = 0; i < outer_size; ++i)
+  {
+    float squared_l2_norm = 0;
+    for (int c = 0; c < depth; ++c)
+    {
+      const float val = input_data[depth * i + c];
+      squared_l2_norm += val * val;
+    }
+    float l2_norm = std::sqrt(squared_l2_norm);
+    l2_norm = std::fmax(l2_norm, epsilon);
+    for (int c = 0; c < depth; ++c)
+    {
+      output_data[depth * i + c] = input_data[depth * i + c] / l2_norm;
+    }
+  }
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_L2_NORMALIZE_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALL2Pool2DCommon.h b/onert-micro/onert-micro/include/pal/common/PALL2Pool2DCommon.h
new file mode 100644 (file)
index 0000000..917522c
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_L2_POOL_2D_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_L2_POOL_2D_COMMON_H
+
+#include "PALUtils.h"
+
+#include "core/OMKernelData.h"
+#include "core/OMRuntimeShape.h"
+#include <cmath>
+#include <iostream>
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+// TODO: Reduce code duplication with other pools
+OMStatus L2Pool(const core::Pool2DParams &params, const core::OMRuntimeShape &input_shape,
+                const float *input_data, const core::OMRuntimeShape &output_shape,
+                float *output_data)
+{
+  const int32_t batches = input_shape.dims(0);
+  const int32_t depth = output_shape.dims(3);
+  const int32_t input_height = input_shape.dims(1);
+  const int32_t input_width = input_shape.dims(2);
+  const int32_t output_height = output_shape.dims(1);
+  const int32_t output_width = output_shape.dims(2);
+  const int32_t stride_height = params.stride_h;
+  const int32_t stride_width = params.stride_w;
+  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.pad_w;
+          const int in_y_origin = (out_y * stride_height) - params.pad_h;
+          // 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_w, 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_h, input_height - in_y_origin);
+          float sum_squares = 0.f;
+          int 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 float val =
+                input_data[offset(input_shape.dimsData(), batch, in_y, in_x, channel)];
+              sum_squares += val * val;
+              filter_count++;
+            }
+          }
+          assert(filter_count != 0);
+          if (filter_count == 0)
+          {
+            std::cerr << "filter_count is zero" << std::endl;
+            return FailedCheckCondition;
+          }
+          const float l2pool_result = std::sqrt(sum_squares / filter_count);
+          output_data[offset(output_shape.dimsData(), batch, out_y, out_x, channel)] =
+            activationFunctionWithMinMax(l2pool_result, params.activation_min,
+                                         params.activation_max);
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_L2_POOL_2D_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALLogCommon.h b/onert-micro/onert-micro/include/pal/common/PALLogCommon.h
new file mode 100644 (file)
index 0000000..619865a
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_LOG_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_LOG_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "PALSISOOperation.h"
+#include "PALUtils.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Log(const core::OMRuntimeShape &input_shape, const T *input_data,
+                    const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    output_data[i] = std::log(input_data[i]);
+  }
+
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_LOG_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALLogSoftmax.h b/onert-micro/onert-micro/include/pal/common/PALLogSoftmax.h
new file mode 100644 (file)
index 0000000..0070d55
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_LOG_SOFTMAX_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_LOG_SOFTMAX_COMMON_H
+
+#include "core/OMKernelData.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+inline OMStatus LogSoftmax(const core::LogSoftmaxParams &params, const float *input_data,
+                           float *output_data)
+{
+  const int outer_size = params.num_rows;
+  const int depth = params.row_size;
+
+  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:
+    // log(exp(x[i])/sum(exp(x[i]))) == log(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)
+    {
+      sum += std::exp(input_data[i * depth + c] - max);
+    }
+
+    // Compute result.
+    const float log_sum = std::log(sum);
+    for (int c = 0; c < depth; ++c)
+    {
+      output_data[i * depth + c] = input_data[i * depth + c] - max - log_sum;
+    }
+  }
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_LOG_SOFTMAX_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALLogistic.h b/onert-micro/onert-micro/include/pal/common/PALLogistic.h
new file mode 100644 (file)
index 0000000..de0f4f9
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_LOGISTIC_H
+#define ONERT_MICRO_EXECUTE_PAL_LOGISTIC_H
+
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+OMStatus inline 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;
+  }
+  return Ok;
+}
+
+OMStatus inline 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;
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_LOGISTIC_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALMaxPool2DCommon.h b/onert-micro/onert-micro/include/pal/common/PALMaxPool2DCommon.h
new file mode 100644 (file)
index 0000000..e0bba4f
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_COMMON_H
+
+#include "PALUtils.h"
+
+#include "core/OMKernelData.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+OMStatus MaxPool(const core::Pool2DParams &params, const core::OMRuntimeShape &input_shape,
+                 const float *input_data, const core::OMRuntimeShape &output_shape,
+                 float *output_data)
+{
+  const int32_t batches = input_shape.dims(0);
+  const int32_t depth = output_shape.dims(3);
+  const int32_t input_height = input_shape.dims(1);
+  const int32_t input_width = input_shape.dims(2);
+  const int32_t output_height = output_shape.dims(1);
+  const int32_t output_width = output_shape.dims(2);
+  const int32_t stride_height = params.stride_h;
+  const int32_t stride_width = params.stride_w;
+  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.pad_w;
+          const int in_y_origin = (out_y * stride_height) - params.pad_h;
+          // 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_w, 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_h, 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.activation_min), params.activation_max);
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALMaxPool2DInputGrad.h b/onert-micro/onert-micro/include/pal/common/PALMaxPool2DInputGrad.h
new file mode 100644 (file)
index 0000000..6ebc56c
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_COMMON_MAX_POOL_2D_INPUT_GRAD_H
+#define ONERT_MICRO_EXECUTE_PAL_COMMON_MAX_POOL_2D_INPUT_GRAD_H
+
+#include "OMStatus.h"
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace pal
+{
+
+void inline MaxPool2D(const core::Pool2DParams &params, const core::OMRuntimeShape &input_shape,
+                      const float *input_data, const core::OMRuntimeShape &dloss_doutput_shape,
+                      const float *dloss_doutput_data, float *dloss_dinput_data)
+{
+  const int32_t batches = input_shape.dims(0);
+  const int32_t depth = dloss_doutput_shape.dims(3);
+  const int32_t input_height = input_shape.dims(1);
+  const int32_t input_width = input_shape.dims(2);
+  const int32_t output_height = dloss_doutput_shape.dims(1);
+  const int32_t output_width = dloss_doutput_shape.dims(2);
+  const int32_t stride_height = params.stride_h;
+  const int32_t stride_width = params.stride_w;
+  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.pad_w;
+          const int in_y_origin = (out_y * stride_height) - params.pad_h;
+          // 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_w, 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_h, input_height - in_y_origin);
+
+          const int output_data_offset =
+            ((batch * output_height + out_y) * output_width + out_x) * depth + channel;
+
+          float max = std::numeric_limits<float>::lowest();
+          int max_index = 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_height + in_y) * input_width + in_x) * depth + channel;
+
+              if (input_data[input_data_offset] > max)
+              {
+                max = input_data[input_data_offset];
+                max_index = input_data_offset;
+              }
+            }
+          }
+          dloss_dinput_data[max_index] = dloss_doutput_data[output_data_offset];
+        }
+      }
+    }
+  }
+}
+
+} // namespace pal
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_COMMON_MAX_POOL_2D_INPUT_GRAD_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALMaximumCommon.h b/onert-micro/onert-micro/include/pal/common/PALMaximumCommon.h
new file mode 100644 (file)
index 0000000..ea3a574
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_MAXIMUM_COMMON_H
+#define ONERT_MICRO_PAL_MAXIMUM_COMMON_H
+
+#include "PALBinaryOpCommon.h"
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+inline OMStatus Maximum(const int flat_size, const float *input1_data, const float *input2_data,
+                        float *output_data)
+{
+  return BinaryOp<float, MaximumFn<float>>(flat_size, input1_data, input2_data, output_data);
+}
+
+inline OMStatus BroadcastMaximum4DSlow(const core::OMRuntimeShape &input1_shape,
+                                       const float *input1_data,
+                                       const core::OMRuntimeShape &input2_shape,
+                                       const float *input2_data,
+                                       const core::OMRuntimeShape &output_shape, float *output_data)
+{
+  return BroadcastBinaryOp4DSlow<float, MaximumFn<float>>(input1_shape, input1_data, input2_shape,
+                                                          input2_data, output_shape, output_data);
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_PAL_MAXIMUM_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALMinimumCommon.h b/onert-micro/onert-micro/include/pal/common/PALMinimumCommon.h
new file mode 100644 (file)
index 0000000..697c6a5
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_MINIMUM_COMMON_H
+#define ONERT_MICRO_PAL_MINIMUM_COMMON_H
+
+#include "PALBinaryOpCommon.h"
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+inline OMStatus Minimum(const int flat_size, const float *input1_data, const float *input2_data,
+                        float *output_data)
+{
+  return BinaryOp<float, MinimumFn<float>>(flat_size, input1_data, input2_data, output_data);
+}
+
+template <typename T>
+inline OMStatus
+BroadcastMinimum4DSlow(const core::OMRuntimeShape &input1_shape, const T *input1_data,
+                       const core::OMRuntimeShape &input2_shape, const T *input2_data,
+                       const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  return BroadcastBinaryOp4DSlow<float, MinimumFn<float>>(input1_shape, input1_data, input2_shape,
+                                                          input2_data, output_shape, output_data);
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_PAL_MINIMUM_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALMulCommon.h b/onert-micro/onert-micro/include/pal/common/PALMulCommon.h
new file mode 100644 (file)
index 0000000..f71f187
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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 ONERT_MICRO_EXECUTE_PAL_MUL_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_MUL_COMMON_H
+
+#include "PALArithmeticOpCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+namespace
+{
+// Maximum dimension supported by the broadcast mul operation.
+constexpr int kMaxMulBroadcastDim = 6;
+} // namespace
+
+template <typename T>
+OMStatus Mul(const core::BinaryArithmeticBroadcastParams &params, const int flat_size,
+             const T *input1_data, const T *input2_data, T *output_data)
+{
+  ArithmeticOp<T, MulFn<T>>(params, flat_size, input1_data, input2_data, output_data);
+  return Ok;
+}
+
+template <typename T>
+OMStatus BroadcastMul4DSlow(const core::BinaryArithmeticBroadcastParams &params,
+                            const core::OMRuntimeShape &input1_shape, const T *input1_data,
+                            const core::OMRuntimeShape &input2_shape, const T *input2_data,
+                            const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  BroadcastArithmeticOp4DSlow<T, MulFn<T>>(params, input1_shape, input1_data, input2_shape,
+                                           input2_data, output_shape, output_data);
+  return Ok;
+}
+
+template <typename T>
+OMStatus BroadcastMul6DSlow(const core::ArithmeticQuantParams &params,
+                            const core::OMRuntimeShape &input1_shape, const T *input1_data,
+                            const core::OMRuntimeShape &input2_shape, const T *input2_data,
+                            const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  NdArrayDesc<kMaxMulBroadcastDim> desc1{};
+  NdArrayDesc<kMaxMulBroadcastDim> desc2{};
+  // The input shapes are extended as part of NdArrayDesc initialization.
+  NdArrayDescsForElementwiseBroadcast(input1_shape, input2_shape, &desc1, &desc2);
+  const core::OMRuntimeShape extended_output_shape =
+    core::OMRuntimeShape::extendedShape(kMaxMulBroadcastDim, output_shape);
+  // Cache output shape dimensions.
+  int32_t extended_output_shape_dims[kMaxMulBroadcastDim];
+  std::memcpy(extended_output_shape_dims, extended_output_shape.dimsData(),
+              sizeof(extended_output_shape_dims));
+
+  size_t input1_offset_a = 0;
+  size_t input2_offset_a = 0;
+  size_t output_offset_a = 0;
+  for (int a = 0; a < extended_output_shape_dims[0]; ++a)
+  {
+    size_t input1_offset_d = input1_offset_a;
+    size_t input2_offset_d = input2_offset_a;
+    size_t output_offset_d = output_offset_a;
+    for (int d = 0; d < extended_output_shape_dims[1]; ++d)
+    {
+      size_t input1_offset_b = input1_offset_d;
+      size_t input2_offset_b = input2_offset_d;
+      size_t output_offset_b = output_offset_d;
+      for (int b = 0; b < extended_output_shape_dims[2]; ++b)
+      {
+        size_t input1_offset_y = input1_offset_b;
+        size_t input2_offset_y = input2_offset_b;
+        size_t output_offset_y = output_offset_b;
+        for (int y = 0; y < extended_output_shape_dims[3]; ++y)
+        {
+          size_t input1_offset_x = input1_offset_y;
+          size_t input2_offset_x = input2_offset_y;
+          size_t output_offset_x = output_offset_y;
+          for (int x = 0; x < extended_output_shape_dims[4]; ++x)
+          {
+            size_t input1_offset_c = input1_offset_x;
+            size_t input2_offset_c = input2_offset_x;
+            size_t output_offset_c = output_offset_x;
+            for (int c = 0; c < extended_output_shape_dims[5]; ++c)
+            {
+              const int32_t input1_val = params.input1_offset + input1_data[input1_offset_c];
+              const int32_t input2_val = params.input2_offset + input2_data[input2_offset_c];
+              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[output_offset_c] = static_cast<T>(clamped_output);
+              input1_offset_c += desc1.strides[5];
+              input2_offset_c += desc2.strides[5];
+              ++output_offset_c;
+            }
+            input1_offset_x += desc1.strides[4];
+            input2_offset_x += desc2.strides[4];
+            output_offset_x += extended_output_shape_dims[5];
+          }
+          input1_offset_y += desc1.strides[3];
+          input2_offset_y += desc2.strides[3];
+          output_offset_y += extended_output_shape_dims[4] * extended_output_shape_dims[5];
+        }
+        input1_offset_b += desc1.strides[2];
+        input2_offset_b += desc2.strides[2];
+        output_offset_b += extended_output_shape_dims[3] * extended_output_shape_dims[4] *
+                           extended_output_shape_dims[5];
+      }
+      input1_offset_d += desc1.strides[1];
+      input2_offset_d += desc2.strides[1];
+      output_offset_d += extended_output_shape_dims[2] * extended_output_shape_dims[3] *
+                         extended_output_shape_dims[4] * extended_output_shape_dims[5];
+    }
+    input1_offset_a += desc1.strides[0];
+    input2_offset_a += desc2.strides[0];
+    output_offset_a += extended_output_shape_dims[1] * extended_output_shape_dims[2] *
+                       extended_output_shape_dims[3] * extended_output_shape_dims[4] *
+                       extended_output_shape_dims[5];
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_MUL_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALNegCommon.h b/onert-micro/onert-micro/include/pal/common/PALNegCommon.h
new file mode 100644 (file)
index 0000000..5853c6a
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_NEG_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_NEG_COMMON_H
+
+#include "PALSISOOperation.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Neg(const core::OMRuntimeShape &input_shape, const T *input_data,
+                    const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    output_data[i] = -(input_data[i]);
+  }
+
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_NEG_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALPad.h b/onert-micro/onert-micro/include/pal/common/PALPad.h
new file mode 100644 (file)
index 0000000..11ec1b3
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_PAD_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_PAD_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "core/OMKernelData.h"
+#include "OMStatus.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+namespace
+{
+constexpr int padKernelMaxDimensionCount = 5;
+} // namespace
+
+OMStatus Pad(const core::PadParams &op_params, const core::OMRuntimeShape &input_shape,
+             const float *input_data, const float pad_value,
+             const core::OMRuntimeShape &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 : 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 : 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 =
+    core::OMRuntimeShape::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 *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++;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_NEG_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALReluCommon.h b/onert-micro/onert-micro/include/pal/common/PALReluCommon.h
new file mode 100644 (file)
index 0000000..6490824
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_RELU_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_RELU_COMMON_H
+
+#include "core/OMKernelData.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+inline OMStatus 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;
+  }
+
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_RELU_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALReluInputGrad.h b/onert-micro/onert-micro/include/pal/common/PALReluInputGrad.h
new file mode 100644 (file)
index 0000000..e8a1282
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_COMMON_RELU_INPUT_GRAD_H
+#define ONERT_MICRO_EXECUTE_PAL_COMMON_RELU_INPUT_GRAD_H
+
+#include "OMStatus.h"
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace pal
+{
+
+// Note: Perform inplace calculation
+void inline ReluInputGrad(const float *input_relu_data, float *dloss_doutput_data,
+                          const core::OMRuntimeShape &dloss_doutput_shape)
+{
+  const uint32_t flat_size = dloss_doutput_shape.flatSize();
+
+  for (uint32_t i = 0; i < flat_size; ++i)
+  {
+    dloss_doutput_data[i] = input_relu_data[i] > 0 ? dloss_doutput_data[i] : 0.f;
+  }
+}
+
+} // namespace pal
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_COMMON_RELU_INPUT_GRAD_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALRoundCommon.h b/onert-micro/onert-micro/include/pal/common/PALRoundCommon.h
new file mode 100644 (file)
index 0000000..8fb3afd
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_ROUND_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_ROUND_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "PALSISOOperation.h"
+#include "PALUtils.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Round(const core::OMRuntimeShape &input_shape, const T *input_data,
+                      const core::OMRuntimeShape &output_shape, T *output_data);
+
+template <>
+inline OMStatus Round<float>(const core::OMRuntimeShape &input_shape, const float *input_data,
+                             const core::OMRuntimeShape &output_shape, float *output_data)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    // Note that this implementation matches that of tensorFlow tf.round
+    // and corresponds to the bankers rounding method.
+    auto floor_val = std::floor(input_data[i]);
+    auto diff = input_data[i] - floor_val;
+    if ((diff < 0.5f) || ((diff == 0.5f) && (static_cast<int>(floor_val) % 2 == 0)))
+    {
+      output_data[i] = floor_val;
+    }
+    else
+    {
+      output_data[i] = floor_val + 1.0f;
+    }
+  }
+
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ROUND_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALRsqrtCommon.h b/onert-micro/onert-micro/include/pal/common/PALRsqrtCommon.h
new file mode 100644 (file)
index 0000000..75d42a7
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_RSQRT_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_RSQRT_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "PALSISOOperation.h"
+#include "PALUtils.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Rsqrt(const core::OMRuntimeShape &input_shape, const T *input_data,
+                      const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  return SISOOperation<T>(input_shape, input_data, output_shape, output_data,
+                          [](T arg) -> T { return 1.f / std::sqrt(arg); });
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_RSQRT_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSISOOperation.h b/onert-micro/onert-micro/include/pal/common/PALSISOOperation.h
new file mode 100644 (file)
index 0000000..671fb2d
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_SISO_OPERATION_H
+#define ONERT_MICRO_EXECUTE_PAL_SISO_OPERATION_H
+
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include <functional>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <typename T>
+inline OMStatus SISOOperation(const core::OMRuntimeShape &input_shape, const T *input_data,
+                              const core::OMRuntimeShape &output_shape, T *output_data,
+                              std::function<T(T)> const &func)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    output_data[i] = func(input_data[i]);
+  }
+
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SISO_OPERATION_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSinCommon.h b/onert-micro/onert-micro/include/pal/common/PALSinCommon.h
new file mode 100644 (file)
index 0000000..aa7b9c7
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_SIN_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_SIN_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "PALSISOOperation.h"
+#include "PALUtils.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Sin(const core::OMRuntimeShape &input_shape, const T *input_data,
+                    const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    output_data[i] = std::sin(input_data[i]);
+  }
+
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SIN_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSlice.h b/onert-micro/onert-micro/include/pal/common/PALSlice.h
new file mode 100644 (file)
index 0000000..234fd9e
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_SLICE_H
+#define ONERT_MICRO_EXECUTE_PAL_SLICE_H
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+OMStatus Slice(const core::SliceParams &op_params, const core::OMRuntimeShape &input_shape,
+               const T *input_data, T *output_data)
+{
+  const core::OMRuntimeShape ext_shape = core::OMRuntimeShape::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)
+  {
+    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)
+          {
+            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];
+          }
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SLICE_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSoftmaxCommon.h b/onert-micro/onert-micro/include/pal/common/PALSoftmaxCommon.h
new file mode 100644 (file)
index 0000000..6e4881e
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_SOFTMAX_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_SOFTMAX_COMMON_H
+
+#include "core/OMKernelData.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T, typename U>
+OMStatus Softmax(const core::SoftmaxParams &params, const T *input_data, U *output_data)
+{
+  const int outer_size = params.num_rows;
+  const int depth = params.row_size;
+  const double beta = params.beta;
+
+  const float input_scale = params.input_scale;
+  const float output_scale = params.output_scale;
+
+  const int input_zp = params.input_zp;
+  const int output_zp = params.output_zp;
+
+  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)
+    {
+      auto t = input_data[i * depth + c] - input_zp;
+      auto t_f = static_cast<float>(input_data[i * depth + c] - input_zp);
+      float cur_val = static_cast<float>(input_data[i * depth + c] - input_zp) * input_scale;
+      max = std::max(max, cur_val);
+    }
+
+    static constexpr int32_t min_val = std::numeric_limits<U>::min();
+    static constexpr int32_t max_val = std::numeric_limits<U>::max();
+    // Compute sum.
+    float sum = 0.f;
+    for (int c = 0; c < depth; ++c)
+    {
+      float cur_val = static_cast<float>(input_data[i * depth + c] - input_zp) * input_scale;
+      const auto exp_c = static_cast<float>(std::exp((cur_val - max) * beta));
+      sum += exp_c;
+    }
+
+    // Compute result.
+    for (int c = 0; c < depth; ++c)
+    {
+      float cur_val = static_cast<float>(input_data[i * depth + c] - input_zp) * input_scale;
+      const auto exp_c = static_cast<float>(std::exp((cur_val - max) * beta));
+      float softmax_val = exp_c / sum;
+      auto unclamped = static_cast<int32_t>(std::round(softmax_val / output_scale) +
+                                            static_cast<float>(output_zp));
+      int32_t clamped = std::min(std::max(unclamped, min_val), max_val);
+      output_data[i * depth + c] = static_cast<U>(clamped);
+    }
+  }
+  return Ok;
+}
+
+template <>
+OMStatus Softmax<float, float>(const core::SoftmaxParams &params, const float *input_data,
+                               float *output_data)
+{
+  const int outer_size = params.num_rows;
+  const int depth = params.row_size;
+  const double beta = params.beta;
+
+  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;
+    }
+
+    assert(sum != 0);
+
+    if (sum == 0)
+      return UnknownError;
+
+    // Compute result.
+    for (int c = 0; c < depth; ++c)
+    {
+      output_data[i * depth + c] = output_data[i * depth + c] / sum;
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SOFTMAX_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSoftmaxInputGrad.h b/onert-micro/onert-micro/include/pal/common/PALSoftmaxInputGrad.h
new file mode 100644 (file)
index 0000000..172a19c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_COMMON_SOFTMAX_INPUT_GRAD_H
+#define ONERT_MICRO_EXECUTE_PAL_COMMON_SOFTMAX_INPUT_GRAD_H
+
+#include "OMStatus.h"
+#include "PALUtils.h"
+
+#include <cmath>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace pal
+{
+
+void inline SoftmaxInputGrad(const float *dloss_doutput_data,
+                             const core::OMRuntimeShape &dloss_doutput_shape,
+                             const float *calculated_data, float *jacobian_row_data,
+                             float *dloss_dinput_data)
+{
+  assert(dloss_doutput_shape.dimensionsCount() == 2);
+  assert(dloss_doutput_shape.dims(0) == 1);
+  const uint32_t output_dim = dloss_doutput_shape.dims(dloss_doutput_shape.dimensionsCount() - 1);
+  for (int i = 0; i < output_dim; ++i)
+  {
+    for (int j = 0; j < output_dim; ++j)
+    {
+      jacobian_row_data[j] = -calculated_data[i] * calculated_data[j];
+    }
+    jacobian_row_data[i] += calculated_data[i];
+    float total = 0.f;
+    for (int j = 0; j < output_dim; ++j)
+    {
+      total += jacobian_row_data[j] * dloss_doutput_data[j];
+    }
+    dloss_dinput_data[i] = total;
+  }
+}
+
+} // namespace pal
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_COMMON_SOFTMAX_INPUT_GRAD_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSpaceToBatchNDCommon.h b/onert-micro/onert-micro/include/pal/common/PALSpaceToBatchNDCommon.h
new file mode 100644 (file)
index 0000000..1fcf0e2
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_SPACE_TO_BATCH_ND_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_SPACE_TO_BATCH_ND_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+#include "PALUtils.h"
+#include "ProcessBroadcastShapes.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+namespace
+{
+inline core::OMRuntimeShape extendShapeSpaceToBatch(const core::OMRuntimeShape &shape)
+{
+  if (shape.dimensionsCount() == 4)
+  {
+    return shape;
+  }
+  core::OMRuntimeShape new_shape(4, 1);
+  new_shape.setDim(0, shape.dims(0));
+  new_shape.setDim(1, shape.dims(1));
+  new_shape.setDim(3, shape.dims(2));
+  return new_shape;
+}
+} // namespace
+
+template <typename T>
+inline OMStatus
+SpaceToBatchND(const core::OMRuntimeShape &unextended_input1_shape, const T *input1_data,
+               const core::OMRuntimeShape &unextended_input2_shape, const int32_t *block_shape_data,
+               const core::OMRuntimeShape &unextended_input3_shape, const int32_t *paddings_data,
+               const core::OMRuntimeShape &unextended_output_shape, T *output_data)
+{
+  // Extends the input/output shape from 3D to 4D if needed, NHC -> NH1C.
+  const core::OMRuntimeShape input1_shape = extendShapeSpaceToBatch(unextended_input1_shape);
+  const core::OMRuntimeShape output_shape = extendShapeSpaceToBatch(unextended_output_shape);
+
+  const int depth = input1_shape.dims(3);
+  const int input_width = input1_shape.dims(2);
+  const int input_height = input1_shape.dims(1);
+  const int input_batch_size = input1_shape.dims(0);
+
+  const int output_width = output_shape.dims(2);
+  const int output_height = output_shape.dims(1);
+  const int output_batch_size = output_shape.dims(0);
+
+  const int block_shape_height = block_shape_data[0];
+  const int block_shape_width =
+    unextended_input1_shape.dimensionsCount() == 4 ? block_shape_data[1] : 1;
+  const int padding_top = paddings_data[0];
+  const int padding_left = unextended_input1_shape.dimensionsCount() == 4 ? paddings_data[2] : 0;
+
+  const int32_t pad_value = 0;
+
+  for (int out_b = 0; out_b < output_batch_size; ++out_b)
+  {
+    int input_batch = out_b % input_batch_size;
+    int shift_w = (out_b / input_batch_size) % block_shape_width;
+    int shift_h = (out_b / input_batch_size) / block_shape_width;
+    for (int out_h = 0; out_h < output_height; ++out_h)
+    {
+      for (int out_w = 0; out_w < output_width; ++out_w)
+      {
+        T *out = output_data + offset(output_shape.dimsData(), out_b, out_h, out_w, 0);
+        if (out_h * block_shape_height + shift_h < padding_top ||
+            out_h * block_shape_height + shift_h >= padding_top + input_height ||
+            out_w * block_shape_width + shift_w < padding_left ||
+            out_w * block_shape_width + shift_w >= padding_left + input_width)
+        {
+          // This may not execute correctly when pad_value != 0 and T != uint8.
+          memset(out, pad_value, depth * sizeof(T));
+        }
+        else
+        {
+          const T *in =
+            input1_data + offset(input1_shape.dimsData(), input_batch,
+                                 (out_h * block_shape_height + shift_h) - padding_top,
+                                 (out_w * block_shape_width + shift_w) - padding_left, 0);
+          memcpy(out, in, depth * sizeof(T));
+        }
+      }
+    }
+  }
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SPACE_TO_BATCH_ND_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSpaceToDepthCommon.h b/onert-micro/onert-micro/include/pal/common/PALSpaceToDepthCommon.h
new file mode 100644 (file)
index 0000000..c3e7d4d
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_SPACE_TO_DEPTH_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_SPACE_TO_DEPTH_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+#include "PALUtils.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <typename T>
+inline OMStatus SpaceToDepth(const int32_t block_size,
+                             const core::OMRuntimeShape &unextended_input_shape,
+                             const T *input_data,
+                             const core::OMRuntimeShape &unextended_output_shape, T *output_data)
+{
+  if (block_size == 0)
+  {
+    return FailedCheckCondition;
+  }
+
+  const core::OMRuntimeShape input_shape =
+    core::OMRuntimeShape::extendedShape(4, unextended_input_shape);
+  const core::OMRuntimeShape output_shape =
+    core::OMRuntimeShape::extendedShape(4, unextended_output_shape);
+
+  const int input_depth = input_shape.dims(3);
+  const int input_width = input_shape.dims(2);
+  const int input_height = input_shape.dims(1);
+  const int input_batch = input_shape.dims(0);
+
+  for (int in_b = 0; in_b < input_batch; ++in_b)
+  {
+    for (int in_h = 0; in_h < input_height; ++in_h)
+    {
+      for (int in_w = 0; in_w < input_width; ++in_w)
+      {
+        for (int in_d = 0; in_d < input_depth; ++in_d)
+        {
+          const int out_d =
+            in_d + ((in_h % block_size) * block_size + in_w % block_size) * input_depth;
+          const int out_w = in_w / block_size;
+          const int out_h = in_h / block_size;
+          const int out_b = in_b;
+
+          const int input_index = offset(input_shape.dimsData(), in_b, in_h, in_w, in_d);
+          const int output_index = offset(output_shape.dimsData(), out_b, out_h, out_w, out_d);
+
+          output_data[output_index] = input_data[input_index];
+        }
+      }
+    }
+  }
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SPACE_TO_DEPTH_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSplit.h b/onert-micro/onert-micro/include/pal/common/PALSplit.h
new file mode 100644 (file)
index 0000000..3265f9d
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_SPLIT_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_SPLIT_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "core/OMKernelData.h"
+#include "execute/OMRuntimeKernel.h"
+#include "OMStatus.h"
+#include "PALSISOOperation.h"
+#include "PALUtils.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+OMStatus Split(const core::SplitParams &params, const core::OMRuntimeShape &input_shape,
+               const T *input_data, const core::OMRuntimeShape &output_shape, int32_t axis_value)
+{
+  const auto output_count = params.num_outputs;
+
+  const auto split_dimensions = input_shape.dimensionsCount();
+
+  assert(axis_value < split_dimensions);
+  assert(output_shape.dimensionsCount() == split_dimensions);
+
+  int64_t outer_size = 1;
+  for (uint32_t i = 0; i < axis_value; ++i)
+  {
+    outer_size *= input_shape.dims(i);
+  }
+
+  int64_t base_inner_size = 1;
+  for (uint32_t i = axis_value + 1; i < split_dimensions; ++i)
+  {
+    base_inner_size *= input_shape.dims(i);
+  }
+
+  assert(input_data != nullptr);
+  for (int64_t k = 0; k < outer_size; ++k)
+  {
+    for (uint32_t i = 0; i < output_count; ++i)
+    {
+      T *output_data = core::utils::castOutputData<T>(params.output_data[i]);
+      assert(output_data != nullptr);
+      const auto copy_size = output_shape.dims(axis_value) * base_inner_size;
+      T *output_ptr = output_data + k * copy_size;
+      assert(output_ptr != nullptr);
+      for (int64_t j = 0; j < copy_size; ++j)
+        output_ptr[j] = input_data[j];
+      input_data += copy_size;
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SPLIT_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSqrtCommon.h b/onert-micro/onert-micro/include/pal/common/PALSqrtCommon.h
new file mode 100644 (file)
index 0000000..2a8d331
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_SQRT_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_SQRT_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "PALSISOOperation.h"
+#include "PALUtils.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Sqrt(const core::OMRuntimeShape &input_shape, const T *input_data,
+                     const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    output_data[i] = std::sqrt(input_data[i]);
+  }
+
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SQRT_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSquareCommon.h b/onert-micro/onert-micro/include/pal/common/PALSquareCommon.h
new file mode 100644 (file)
index 0000000..50f0807
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_SQUARE_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_SQUARE_COMMON_H
+
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "PALSISOOperation.h"
+#include "PALUtils.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+inline OMStatus Square(const core::OMRuntimeShape &input_shape, const T *input_data,
+                       const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    output_data[i] = (input_data[i]) * (input_data[i]);
+  }
+
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_LOG_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSquaredDifferenceCommon.h b/onert-micro/onert-micro/include/pal/common/PALSquaredDifferenceCommon.h
new file mode 100644 (file)
index 0000000..84e97e3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_SQUARED_DIFFERENCE_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_SQUARED_DIFFERENCE_COMMON_H
+
+#include "PALArithmeticOpCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <typename T>
+OMStatus SquaredDifference(const core::BinaryArithmeticBroadcastParams &params, const int flat_size,
+                           const T *input1_data, const T *input2_data, T *output_data)
+{
+  ArithmeticOp<T, SquaredDifferenceFn<T>>(params, flat_size, input1_data, input2_data, output_data);
+  return Ok;
+}
+
+template <typename T>
+OMStatus
+BroadcastSquaredDifference4DSlow(const core::BinaryArithmeticBroadcastParams &params,
+                                 const core::OMRuntimeShape &input1_shape, const T *input1_data,
+                                 const core::OMRuntimeShape &input2_shape, const T *input2_data,
+                                 const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  BroadcastArithmeticOp4DSlow<T, SquaredDifferenceFn<T>>(
+    params, input1_shape, input1_data, input2_shape, input2_data, output_shape, output_data);
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SQUARED_DIFFERENCE_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALStridedSlice.h b/onert-micro/onert-micro/include/pal/common/PALStridedSlice.h
new file mode 100644 (file)
index 0000000..dd622b9
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_STRIDED_SLICE_H
+#define ONERT_MICRO_EXECUTE_PAL_STRIDED_SLICE_H
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace 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 core::StridedSliceParams &params,
+                       const core::OMRuntimeShape &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 core::StridedSliceParams &params,
+                        const core::OMRuntimeShape &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(core::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>
+OMStatus StridedSlice(core::StridedSliceParams &op_params,
+                      const core::OMRuntimeShape &unextended_input_shape, const T *input_data,
+                      T *output_data)
+{
+  const core::OMRuntimeShape input_shape =
+    core::OMRuntimeShape::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];
+          }
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_STRIDED_SLICE_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALSubCommon.h b/onert-micro/onert-micro/include/pal/common/PALSubCommon.h
new file mode 100644 (file)
index 0000000..1df3370
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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 ONERT_MICRO_EXECUTE_PAL_SUB_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_SUB_COMMON_H
+
+#include "PALArithmeticOpCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <typename T>
+OMStatus Sub(const core::BinaryArithmeticBroadcastParams &params, const int flat_size,
+             const T *input1_data, const T *input2_data, T *output_data)
+{
+  ArithmeticOp<T, SubFn<T>>(params, flat_size, input1_data, input2_data, output_data);
+  return Ok;
+}
+
+template <typename T>
+OMStatus BroadcastSub4DSlow(const core::BinaryArithmeticBroadcastParams &params,
+                            const core::OMRuntimeShape &input1_shape, const T *input1_data,
+                            const core::OMRuntimeShape &input2_shape, const T *input2_data,
+                            const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  BroadcastArithmeticOp4DSlow<T, SubFn<T>>(params, input1_shape, input1_data, input2_shape,
+                                           input2_data, output_shape, output_data);
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SUB_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALTanhCommon.h b/onert-micro/onert-micro/include/pal/common/PALTanhCommon.h
new file mode 100644 (file)
index 0000000..0d5e372
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_TANH_COMMON_H
+#define ONERT_MICRO_PAL_TANH_COMMON_H
+
+#include "PALUnaryOpCommon.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <typename T>
+inline OMStatus Tanh(const core::OMRuntimeShape &input_shape, const T *input_data,
+                     const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+
+  for (int i = 0; i < flat_size; i++)
+  {
+    output_data[i] = std::tanh(input_data[i]);
+  }
+
+  return Ok;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_PAL_TANH_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALTransposeCommon.h b/onert-micro/onert-micro/include/pal/common/PALTransposeCommon.h
new file mode 100644 (file)
index 0000000..4b09e10
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_TRANSPOSE_COMMON_H
+#define ONERT_MICRO_PAL_TRANSPOSE_COMMON_H
+
+#include "PALUtils.h"
+#include "core/OMKernelData.h"
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include "ProcessBroadcastShapes.h"
+
+#include <cassert>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <typename T, int N>
+inline OMStatus TransposeImpl(const core::TransposeParams &params,
+                              const core::OMRuntimeShape &unextended_input_shape,
+                              const T *input_data,
+                              const core::OMRuntimeShape &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(core::OMRuntimeShape::extendedShape(N, unextended_input_shape), &input_desc);
+  copyDimsToDesc(core::OMRuntimeShape::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);
+  return Ok;
+}
+
+template <typename T, int N = 5>
+inline OMStatus Transpose(const core::TransposeParams &params,
+                          const core::OMRuntimeShape &unextended_input_shape, const T *input_data,
+                          const core::OMRuntimeShape &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.
+  OMStatus status;
+  switch (sizeof(T))
+  {
+    case 1:
+      status = 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:
+      status = 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:
+      status = 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:
+      status = 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;
+    default:
+      status = UnknownError;
+      break;
+  }
+  return status;
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_PAL_TRANSPOSE_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALTransposeConvCommon.h b/onert-micro/onert-micro/include/pal/common/PALTransposeConvCommon.h
new file mode 100644 (file)
index 0000000..a75d380
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_TRANSPOSE_CONV_COMMON_H
+#define ONERT_MICRO_PAL_TRANSPOSE_CONV_COMMON_H
+
+#include "PALUtils.h"
+#include "core/OMKernelData.h"
+#include "core/OMRuntimeShape.h"
+#include "OMStatus.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <typename T>
+inline OMStatus
+TransposeConv(const core::FloatConv2D *params, const core::OMRuntimeShape &input_shape,
+              const T *input_data, const core::OMRuntimeShape &filter_shape, const T *filter_data,
+              const T *bias_data, const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  assert(false && "Not IMPL yet");
+}
+template <>
+inline OMStatus
+TransposeConv<float>(const core::FloatConv2D *params, const core::OMRuntimeShape &input_shape,
+                     const float *input_data, const core::OMRuntimeShape &filter_shape,
+                     const float *filter_data, const float *bias_data,
+                     const core::OMRuntimeShape &output_shape, float *output_data)
+{
+  const int stride_width = params->stride_w;
+  const int stride_height = params->stride_h;
+  const int pad_width = params->pad_w;
+  const int pad_height = params->pad_h;
+
+  const int batches = input_shape.dims(0);
+  const int input_depth = input_shape.dims(3);
+  const int output_depth = filter_shape.dims(0);
+  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 output_height = output_shape.dims(1);
+  const int output_width = output_shape.dims(2);
+  const float output_activation_min = params->activation_min;
+  const float output_activation_max = params->activation_max;
+
+  // Although transpose convolution simplifies to convolution with transposed
+  // weights for strides of 1, non-unitary striding complicates matters. To
+  // keep this reference implementation as clear as possible, we use a
+  // "scatter" access pattern, where we loop through all the input elements,
+  // computing their influence on the output, rather than looping through the
+  // output elements in the typical "gather" access pattern of a conv. We
+  // therefore must initialize the output array to zero.
+  const int num_elements = output_shape.flatSize();
+  for (int i = 0; i < num_elements; i++)
+  {
+    output_data[i] = 0.0f;
+  }
+
+  // Loop through input elements one at a time.
+  for (int batch = 0; batch < batches; ++batch)
+  {
+    for (int in_y = 0; in_y < input_height; ++in_y)
+    {
+      for (int in_x = 0; in_x < input_width; ++in_x)
+      {
+        for (int in_channel = 0; in_channel < input_depth; ++in_channel)
+        {
+          // Loop through the output elements it will influence
+          const int out_x_origin = (in_x * stride_width) - pad_width;
+          const int out_y_origin = (in_y * stride_height) - pad_height;
+          for (int filter_y = 0; filter_y < filter_height; ++filter_y)
+          {
+            for (int filter_x = 0; filter_x < filter_width; ++filter_x)
+            {
+              for (int out_channel = 0; out_channel < output_depth; ++out_channel)
+              {
+                // Compute output element location
+                const int out_x = out_x_origin + filter_x;
+                const int out_y = out_y_origin + filter_y;
+                // We cannot accumulate out of bounds
+                if ((out_x >= 0) && (out_x < output_width) && (out_y >= 0) &&
+                    (out_y < output_height))
+                {
+                  float input_value =
+                    input_data[offset(input_shape.dimsData(), batch, in_y, in_x, in_channel)];
+                  float filter_value = filter_data[offset(filter_shape.dimsData(), out_channel,
+                                                          filter_y, filter_x, in_channel)];
+                  output_data[offset(output_shape.dimsData(), batch, out_y, out_x, out_channel)] +=
+                    input_value * filter_value;
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  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)
+        {
+          float acc =
+            output_data[offset(output_shape.dimsData(), batch, out_y, out_x, out_channel)];
+          if (bias_data)
+            acc += bias_data[out_channel];
+
+          output_data[offset(output_shape.dimsData(), batch, out_y, out_x, out_channel)] =
+            activationFunctionWithMinMax(acc, output_activation_min, output_activation_max);
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_PAL_CONV2D_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALUnaryOpCommon.h b/onert-micro/onert-micro/include/pal/common/PALUnaryOpCommon.h
new file mode 100644 (file)
index 0000000..0acf099
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_UNARY_OP_COMMON_H
+#define ONERT_MICRO_EXECUTE_PAL_UNARY_OP_COMMON_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeShape.h"
+#include "PALUtils.h"
+#include <cmath>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
+struct TanhFunctor
+{
+  T operator()(T value) { return std::tanh(value); }
+};
+
+template <typename T, typename Fn>
+inline OMStatus UnaryOp(const core::OMRuntimeShape &input_shape, const T *input_data,
+                        const core::OMRuntimeShape &output_shape, T *output_data)
+{
+  Fn func;
+  const uint32_t flat_size = input_shape.flatSize();
+
+  if (flat_size == -1)
+    return UnknownError;
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(input_shape == output_shape);
+  for (int i = 0; i < flat_size; ++i)
+  {
+    output_data[i] = func(input_data[i]);
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_UNARY_OP_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALUnpack.h b/onert-micro/onert-micro/include/pal/common/PALUnpack.h
new file mode 100644 (file)
index 0000000..1bbdcd8
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_UNPACK_COMMON_H
+#define ONERT_MICRO_PAL_UNPACK_COMMON_H
+
+#include "core/OMKernelData.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T>
+OMStatus Unpack(const core::SplitParams &params, const core::OMRuntimeShape &input_shape,
+                const T *input_data, const core::OMRuntimeShape &output_shape, int32_t axis_value)
+{
+  const auto dimensions = input_shape.dimensionsCount();
+
+  if (axis_value < 0)
+  {
+    axis_value += dimensions;
+  }
+
+  int outer_size = 1;
+  for (int i = 0; i < axis_value; ++i)
+  {
+    outer_size *= input_shape.dims(i);
+  }
+  int copy_size = 1;
+  for (int i = axis_value + 1; i < dimensions; ++i)
+  {
+    copy_size *= input_shape.dims(i);
+  }
+  int output_size = 1;
+  for (int i = 0; i < output_shape.dimensionsCount(); ++i)
+  {
+    output_size *= output_shape.dims(i);
+  }
+
+  for (int i = 0; i < params.num_outputs; ++i)
+  {
+    T *output_data = core::utils::castOutputData<T>(params.output_data[i]);
+    assert(output_data != nullptr);
+    for (int k = 0; k < outer_size; ++k)
+    {
+      T *output_ptr = output_data + copy_size * k;
+      int loc = k * params.num_outputs * copy_size + i * copy_size;
+      const T *input_ptr = input_data + loc;
+      for (int j = 0; j < copy_size; ++j)
+        output_ptr[j] = input_ptr[j];
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_PAL_UNPACK_COMMON_H
diff --git a/onert-micro/onert-micro/include/pal/common/PALUtils.h b/onert-micro/onert-micro/include/pal/common/PALUtils.h
new file mode 100644 (file)
index 0000000..d2f0220
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_UTILS_H
+#define ONERT_MICRO_EXECUTE_PAL_UTILS_H
+
+#include <cassert>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace 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.int32_activation_min;
+  *max = params.int32_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 int32_t num_dims, const int32_t *dims, const int32_t *index,
+                                  const int32_t num_axis, const int32_t *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 int32_t num_dims, const int32_t *dims, int32_t *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 core::OMRuntimeShape &shape1, int index1,
+                       const core::OMRuntimeShape &shape2, int index2)
+{
+  assert(shape1.dims(index1) == shape2.dims(index2));
+  return shape1.dims(index1);
+}
+
+// Data is required to be contiguous, and so many operators can use either the
+// full array flat size or the flat size with one dimension skipped (commonly
+// the depth).
+inline int flatSizeSkipDim(const int32_t *dims_data, int skip_dim, int num_dims)
+{
+  int flat_size = 1;
+  for (int i = 0; i < num_dims; ++i)
+  {
+    flat_size *= (i == skip_dim) ? 1 : dims_data[i];
+  }
+  return flat_size;
+}
+
+inline int offset(const int32_t *dims_data, int i0, int i1, int i2, int i3)
+{
+  return ((i0 * dims_data[1] + i1) * dims_data[2] + i2) * dims_data[3] + i3;
+}
+
+inline int offset(const int32_t *dims_data, int i0, int i1, int i2, int i3, int i4)
+{
+  return (((i0 * dims_data[1] + i1) * dims_data[2] + i2) * dims_data[3] + i3) * dims_data[4] + i4;
+}
+
+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);
+}
+
+// Reduces and compresses dimensions so that broadcast handling becomes more
+// efficient. Returns true if the output shape is broadcastable; it doesn't
+// contain any degenerate dimension, i.e. shape dimension = 0. False otherwise.
+template <int MAX_DIM = 6>
+bool ReduceDimensionsForBroadcast(const core::OMRuntimeShape &input1_shape,
+                                  const core::OMRuntimeShape &input2_shape,
+                                  size_t *compressed_input1_stride,
+                                  size_t *compressed_input2_stride, size_t *compressed_output_shape)
+{
+  size_t num_compressed_dims = 0;
+  size_t compressed_input1_shape[MAX_DIM];
+  size_t compressed_input2_shape[MAX_DIM];
+  std::fill(compressed_input1_shape, compressed_input1_shape + MAX_DIM, 1);
+  std::fill(compressed_input2_shape, compressed_input2_shape + MAX_DIM, 1);
+  std::fill(compressed_output_shape, compressed_output_shape + MAX_DIM, 1);
+  bool broadcast_input1 = false;
+  bool broadcast_input2 = false;
+  bool first_nonunit = true;
+
+  if (input1_shape.dimensionsCount() < 0 || input2_shape.dimensionsCount() < 0)
+  {
+    return false;
+  }
+  const size_t num_input1_dims = input1_shape.dimensionsCount();
+  const size_t num_input2_dims = input2_shape.dimensionsCount();
+  const int32_t *input1_dims = input1_shape.dimsData();
+  const int32_t *input2_dims = input2_shape.dimsData();
+  const size_t num_common_dims = std::min(num_input1_dims, num_input2_dims);
+  for (size_t i = 1; i <= num_common_dims; i++)
+  {
+    if (input1_dims[num_input1_dims - i] < 0 || input2_dims[num_input2_dims - i] < 0)
+    {
+      return false;
+    }
+    const size_t input1_dim = input1_dims[num_input1_dims - i];
+    const size_t input2_dim = input2_dims[num_input2_dims - i];
+    if (input1_dim == 0 || input2_dim == 0)
+    {
+      return false;
+    }
+    if (input1_dim == 1 && input2_dim == 1)
+    {
+      continue;
+    }
+    assert(!broadcast_input1 || !broadcast_input2);
+
+    if (input1_dim == 1)
+    {
+      if (!broadcast_input1)
+      {
+        broadcast_input1 = true;
+        broadcast_input2 = false;
+        num_compressed_dims++;
+      }
+      compressed_input2_shape[num_compressed_dims - 1] *= input2_dim;
+      compressed_output_shape[num_compressed_dims - 1] *= input2_dim;
+    }
+    else if (input2_dim == 1)
+    {
+      if (!broadcast_input2)
+      {
+        broadcast_input1 = false;
+        broadcast_input2 = true;
+        num_compressed_dims++;
+      }
+      compressed_input1_shape[num_compressed_dims - 1] *= input1_dim;
+      compressed_output_shape[num_compressed_dims - 1] *= input1_dim;
+    }
+    else
+    {
+      assert(input1_dim == input2_dim);
+      if (broadcast_input1 || broadcast_input2 || first_nonunit)
+      {
+        broadcast_input1 = false;
+        broadcast_input2 = false;
+        num_compressed_dims++;
+      }
+      compressed_input1_shape[num_compressed_dims - 1] *= input1_dim;
+      compressed_input2_shape[num_compressed_dims - 1] *= input1_dim;
+      compressed_output_shape[num_compressed_dims - 1] *= input1_dim;
+    }
+    first_nonunit = false;
+  }
+  if (num_input1_dims > num_input2_dims)
+  {
+    if (!broadcast_input2)
+    {
+      num_compressed_dims++;
+    }
+    for (size_t i = 0; i < num_input1_dims - num_input2_dims; i++)
+    {
+      if (input1_dims[i] < 0)
+        return false;
+      const size_t input1_dim = input1_dims[i];
+      if (input1_dim == 0)
+      {
+        return false;
+      }
+      compressed_input1_shape[num_compressed_dims - 1] *= input1_dim;
+      compressed_output_shape[num_compressed_dims - 1] *= input1_dim;
+    }
+  }
+  else if (num_input2_dims > num_input1_dims)
+  {
+    if (!broadcast_input1)
+    {
+      num_compressed_dims++;
+    }
+    for (size_t i = 0; i < num_input2_dims - num_input1_dims; i++)
+    {
+      if (input2_dims[i] < 0)
+        return false;
+      const size_t input2_dim = input2_dims[i];
+      if (input2_dim == 0)
+      {
+        return false;
+      }
+      compressed_input2_shape[num_compressed_dims - 1] *= input2_dim;
+      compressed_output_shape[num_compressed_dims - 1] *= input2_dim;
+    }
+  }
+  num_compressed_dims = (num_compressed_dims > 1) ? num_compressed_dims : 1;
+
+  int input1_stride = 1;
+  int input2_stride = 1;
+  for (int i = 0; i < MAX_DIM; ++i)
+  {
+    compressed_input1_stride[i] = input1_stride;
+    input1_stride *= compressed_input1_shape[i];
+    compressed_input2_stride[i] = input2_stride;
+    input2_stride *= compressed_input2_shape[i];
+  }
+  for (int i = 0; i < MAX_DIM; ++i)
+  {
+    if (compressed_input1_shape[i] != compressed_input2_shape[i])
+    {
+      if (compressed_input1_shape[i] == 1)
+      {
+        compressed_input1_stride[i] = 0;
+      }
+      else
+      {
+        assert(compressed_input2_shape[i] == 1);
+        compressed_input2_stride[i] = 0;
+      }
+    }
+  }
+  return true;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_UTILS_H
diff --git a/onert-micro/onert-micro/include/pal/common/ProcessBroadcastShapes.h b/onert-micro/onert-micro/include/pal/common/ProcessBroadcastShapes.h
new file mode 100644 (file)
index 0000000..77ab74c
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_PROCESS_BROADCAST_SHAPES_H
+#define ONERT_MICRO_EXECUTE_PAL_PROCESS_BROADCAST_SHAPES_H
+
+#include "core/OMRuntimeShape.h"
+#include "core/OMKernelData.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace 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 core::OMRuntimeShape &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 core::OMRuntimeShape &input0_shape,
+                                                const core::OMRuntimeShape &input1_shape,
+                                                NdArrayDesc<N> *desc0_out,
+                                                NdArrayDesc<N> *desc1_out)
+{
+
+  auto extended_input0_shape = core::OMRuntimeShape::extendedShape(N, input0_shape);
+  auto extended_input1_shape = core::OMRuntimeShape::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 core::OMRuntimeShape &shape0,
+                                   const core::OMRuntimeShape &shape1,
+                                   core::BinaryArithmeticBroadcastParams *params)
+{
+  const int dims_count = std::max(shape0.dimensionsCount(), shape1.dimensionsCount());
+
+  params->broadcast_category = core::BroadcastableOpCategory::kGenericBroadcast;
+
+  auto extended_shape0 = core::OMRuntimeShape::extendedShape(dims_count, shape0);
+  auto extended_shape1 = core::OMRuntimeShape::extendedShape(dims_count, shape1);
+
+  // Check for "exact" match, implicitly accepting any scalar shapes.
+  if (extended_shape0 == extended_shape1)
+  {
+    params->broadcast_category = core::BroadcastableOpCategory::kNonBroadcast;
+    return false;
+  }
+
+  if (shape0.flatSize() == 1)
+  {
+    params->broadcast_category = core::BroadcastableOpCategory::kScalarFirstBroadcast;
+    return true;
+  }
+  else if (shape1.flatSize() == 1)
+  {
+    params->broadcast_category = core::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 = core::BroadcastableOpCategory::kFirstInputBroadcastsFast;
+      return true;
+    }
+    else if (extended_shape1.dims(i) == 1)
+    {
+      params->broadcast_category = core::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 = core::BroadcastableOpCategory::kGenericBroadcast;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_PROCESS_BROADCAST_SHAPES_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/CustomKernelsToBuild.lst b/onert-micro/onert-micro/include/pal/mcu/CustomKernelsToBuild.lst
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst b/onert-micro/onert-micro/include/pal/mcu/KernelsToBuild.lst
new file mode 100644 (file)
index 0000000..9581aa7
--- /dev/null
@@ -0,0 +1,87 @@
+REGISTER_KERNEL(ABS, Abs)
+REGISTER_KERNEL(ADD, Add)
+REGISTER_KERNEL(ADD_N, AddN)
+REGISTER_KERNEL(AVERAGE_POOL_2D, AveragePool2D)
+REGISTER_KERNEL(ARG_MAX, ArgMax)
+REGISTER_KERNEL(ARG_MIN, ArgMin)
+REGISTER_KERNEL(CONCATENATION, Concatenation)
+#/*REGISTER_KERNEL(CUSTOM, BroadcastTo)*/
+REGISTER_KERNEL(BATCH_TO_SPACE_ND, BatchToSpaceND)
+#/*REGISTER_KERNEL(CEIL, Ceil)*/
+REGISTER_KERNEL(COS, Cos)
+#/*REGISTER_KERNEL(CAST, Cast)*/
+REGISTER_KERNEL(DIV, Div)
+REGISTER_KERNEL(DEPTHWISE_CONV_2D, DepthwiseConv2D)
+#/*REGISTER_KERNEL(DEPTH_TO_SPACE, DepthToSpace)*/
+REGISTER_KERNEL(DEQUANTIZE, Dequantize)
+REGISTER_KERNEL(FULLY_CONNECTED, FullyConnected)
+REGISTER_KERNEL(CONV_2D, Conv2D)
+REGISTER_KERNEL(LOGISTIC, Logistic)
+REGISTER_KERNEL(LOG, Log)
+REGISTER_KERNEL(GATHER, Gather)
+REGISTER_KERNEL(GATHER_ND, GatherND)
+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(FLOOR, Floor)
+REGISTER_KERNEL(FLOOR_DIV, FloorDiv)
+REGISTER_KERNEL(FLOOR_MOD, FloorMod)
+#/*REGISTER_KERNEL(PACK, Pack)*/
+REGISTER_KERNEL(PAD, Pad)
+#/*REGISTER_KERNEL(PADV2, PadV2)*/
+#/*REGISTER_KERNEL(PRELU, PRelu)*/
+REGISTER_KERNEL(RESHAPE, Reshape)
+REGISTER_KERNEL(RELU, Relu)
+REGISTER_KERNEL(RELU6, Relu6)
+#/*REGISTER_KERNEL(REDUCE_PROD, ReduceCommon)*/
+#/*REGISTER_KERNEL(REDUCE_MAX, ReduceMax)*/
+REGISTER_KERNEL(ROUND, Round)
+REGISTER_KERNEL(LESS, Less)
+REGISTER_KERNEL(L2_NORMALIZATION, L2Normalize)
+REGISTER_KERNEL(L2_POOL_2D, L2Pool2D)
+REGISTER_KERNEL(LESS_EQUAL, LessEqual)
+#/*REGISTER_KERNEL(LOGICAL_AND, LogicalAnd)*/
+#/*REGISTER_KERNEL(LOGICAL_NOT, LogicalNot)*/
+#/*REGISTER_KERNEL(LOGICAL_OR, LogicalOr)*/
+REGISTER_KERNEL(LEAKY_RELU, LeakyRelu)
+REGISTER_KERNEL(LOG_SOFTMAX, LogSoftmax)
+REGISTER_KERNEL(MUL, Mul)
+#/*REGISTER_KERNEL(MIRROR_PAD, MirrorPad)*/
+REGISTER_KERNEL(MAXIMUM, Maximum)
+#/*REGISTER_KERNEL(MEAN, Mean)*/
+REGISTER_KERNEL(MAX_POOL_2D, MaxPool2D)
+REGISTER_KERNEL(MINIMUM, Minimum)
+#/*REGISTER_KERNEL(SHAPE, Shape)*/
+REGISTER_KERNEL(NOT_EQUAL, NotEqual)
+REGISTER_KERNEL(SIN, Sin)
+REGISTER_KERNEL(SQUARED_DIFFERENCE, SquaredDifference)
+REGISTER_KERNEL(SLICE, Slice)
+REGISTER_KERNEL(SUB, Sub)
+REGISTER_KERNEL(SPLIT, Split)
+REGISTER_KERNEL(SPACE_TO_BATCH_ND, SpaceToBatchND)
+REGISTER_KERNEL(STRIDED_SLICE, StridedSlice)
+#/*REGISTER_KERNEL(SPLIT_V, SplitV)*/
+REGISTER_KERNEL(SQUARE, Square)
+REGISTER_KERNEL(SQRT, Sqrt)
+REGISTER_KERNEL(SPACE_TO_DEPTH, SpaceToDepth)
+#/*REGISTER_KERNEL(QUANTIZE, Quantize)*/
+REGISTER_KERNEL(TANH, Tanh)
+REGISTER_KERNEL(TRANSPOSE, Transpose)
+REGISTER_KERNEL(TRANSPOSE_CONV, TransposeConv)
+REGISTER_KERNEL(SOFTMAX, Softmax)
+#/*REGISTER_KERNEL(SUM, Sum)*/
+#/*REGISTER_KERNEL(SELECT_V2, SelectV2)*/
+#/*REGISTER_KERNEL(SVDF, SVDF)*/
+REGISTER_KERNEL(WHILE, While)
+#/*REGISTER_KERNEL(UNIDIRECTIONAL_SEQUENCE_LSTM, UnidirectionalSequenceLSTM)*/
+#/*REGISTER_KERNEL(RESIZE_BILINEAR, ResizeBilinear)*/
+#/*REGISTER_KERNEL(RESIZE_NEAREST_NEIGHBOR, ResizeNearestNeighbor)*/
+REGISTER_KERNEL(RSQRT, Rsqrt)
+REGISTER_KERNEL(NEG, Neg)
+#/*REGISTER_KERNEL(ZEROS_LIKE, ZerosLike)*/
+#/*REGISTER_KERNEL(SQUEEZE, Squeeze)*/
+REGISTER_KERNEL(UNPACK, Unpack)
diff --git a/onert-micro/onert-micro/include/pal/mcu/KernelsToTrain.lst b/onert-micro/onert-micro/include/pal/mcu/KernelsToTrain.lst
new file mode 100644 (file)
index 0000000..26476df
--- /dev/null
@@ -0,0 +1,5 @@
+REGISTER_TRAIN_KERNEL(FULLY_CONNECTED, FullyConnected)
+REGISTER_TRAIN_KERNEL(SOFTMAX, Softmax)
+REGISTER_TRAIN_KERNEL(RESHAPE, Reshape)
+REGISTER_TRAIN_KERNEL(CONV_2D, Conv2D)
+REGISTER_TRAIN_KERNEL(MAX_POOL_2D, MaxPool2D)
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALAdd.h b/onert-micro/onert-micro/include/pal/mcu/PALAdd.h
new file mode 100644 (file)
index 0000000..3f13e78
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_ADD_H
+#define ONERT_MICRO_EXECUTE_PAL_ADD_H
+
+#include "PALAddCommon.h"
+#include "PALUtils.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+OMStatus Add(const core::ArithmeticQuantParams &params, const uint32_t flat_size,
+             const int8_t *input1_data, const int8_t *input2_data, int8_t *output_data)
+{
+  ElementWise(flat_size, params, input1_data, input2_data, output_data, AddFunc);
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ADD_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALAddN.h b/onert-micro/onert-micro/include/pal/mcu/PALAddN.h
new file mode 100644 (file)
index 0000000..35dd84e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_ADD_N_H
+#define ONERT_MICRO_EXECUTE_PAL_ADD_N_H
+
+#include "PALAddNCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+template <>
+OMStatus AddN<int8_t>(const size_t flat_size, const size_t num_inputs,
+                      const int8_t *const *input_data, int8_t *output_data)
+{
+  assert(false && "Not IMPL yet");
+  return UnsupportedOp;
+}
+
+template <>
+OMStatus AddN<int16_t>(const size_t flat_size, const size_t num_inputs,
+                       const int16_t *const *input_data, int16_t *output_data)
+{
+  assert(false && "Not IMPL yet");
+  return UnsupportedOp;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ADD_N_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALArgMax.h b/onert-micro/onert-micro/include/pal/mcu/PALArgMax.h
new file mode 100644 (file)
index 0000000..67efc05
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_ARG_MAX_H
+#define ONERT_MICRO_EXECUTE_PAL_ARG_MAX_H
+
+#include "PALArgMinMaxCommon.h"
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T1, typename T2, typename T3>
+OMStatus ArgMax(const core::OMRuntimeShape &input1_shape, const T1 *input1_data,
+                const T3 *input2_data, const core::OMRuntimeShape &output_shape, T2 *output_data)
+{
+  return ArgMinMax(input1_shape, input1_data, input2_data, output_shape, output_data,
+                   std::greater<T1>());
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+#endif // ONERT_MICRO_EXECUTE_PAL_ARG_MAX_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALArgMin.h b/onert-micro/onert-micro/include/pal/mcu/PALArgMin.h
new file mode 100644 (file)
index 0000000..780b485
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_ARG_MIN_H
+#define ONERT_MICRO_EXECUTE_PAL_ARG_MIN_H
+
+#include "PALArgMinMaxCommon.h"
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename T1, typename T2, typename T3>
+OMStatus ArgMin(const core::OMRuntimeShape &input1_shape, const T1 *input1_data,
+                const T3 *input2_data, const core::OMRuntimeShape &output_shape, T2 *output_data)
+{
+  return ArgMinMax(input1_shape, input1_data, input2_data, output_shape, output_data,
+                   std::less<T1>());
+}
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+#endif // ONERT_MICRO_EXECUTE_PAL_ARG_MIN_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALAveragePool2D.h b/onert-micro/onert-micro/include/pal/mcu/PALAveragePool2D.h
new file mode 100644 (file)
index 0000000..62fe460
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_AVERAGE_POOL_2D_H
+#define ONERT_MICRO_EXECUTE_PAL_AVERAGE_POOL_2D_H
+
+#include "PALAveragePool2DCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+OMStatus AveragePool(const core::Pool2DParams &params, const core::OMRuntimeShape &input_shape,
+                     const int8_t *input_data, const core::OMRuntimeShape &output_shape,
+                     int8_t *output_data)
+{
+  assert(input_shape.dimensionsCount() == 4);
+  assert(output_shape.dimensionsCount() == 4);
+  const int batches = MatchingDim(input_shape, 0, output_shape, 0);
+  const int depth = MatchingDim(input_shape, 3, output_shape, 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_h;
+  const int stride_width = params.stride_w;
+  const int pad_w = params.pad_w;
+  const int pad_h = params.pad_h;
+  const int filter_h = params.filter_h;
+  const int filter_w = params.filter_w;
+  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.pad_w;
+          const int in_y_origin = (out_y * stride_height) - params.pad_h;
+          // 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(static_cast<int32_t>(params.filter_w),
+                                            static_cast<int32_t>(input_width - in_x_origin));
+          const int filter_y_start = std::max(0, -in_y_origin);
+          const int filter_y_end = std::min(static_cast<int32_t>(params.filter_h),
+                                            static_cast<int32_t>(input_height - in_y_origin));
+          int32_t acc = 0;
+          int 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;
+              acc += input_data[offset(input_shape.dimsData(), batch, in_y, in_x, channel)];
+              filter_count++;
+            }
+          }
+          if (filter_count == 0)
+            return UnknownError;
+          // Round to the closest integer value.
+          acc = acc > 0 ? (acc + filter_count / 2) / filter_count
+                        : (acc - filter_count / 2) / filter_count;
+          acc = std::max(acc, params.quantized_activation_min);
+          acc = std::min(acc, params.quantized_activation_max);
+          output_data[offset(output_shape.dimsData(), batch, out_y, out_x, channel)] =
+            static_cast<int8_t>(acc);
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_AVERAGE_POOL_2D_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALBatchToSpaceND.h b/onert-micro/onert-micro/include/pal/mcu/PALBatchToSpaceND.h
new file mode 100644 (file)
index 0000000..9e3fcb2
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_BATCH_TO_SPACE_ND_H
+#define ONERT_MICRO_EXECUTE_PAL_BATCH_TO_SPACE_ND_H
+
+#include "PALBatchToSpaceNDCommon.h"
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+#endif // ONERT_MICRO_EXECUTE_PAL_BATCH_TO_SPACE_ND_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALConv2D.h b/onert-micro/onert-micro/include/pal/mcu/PALConv2D.h
new file mode 100644 (file)
index 0000000..3bca5a9
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_CONV_2D_H
+#define ONERT_MICRO_EXECUTE_PAL_CONV_2D_H
+
+#include "PALConv2DCommon.h"
+#include "core/OMKernelData.h"
+#include "core/OMRuntimeShape.h"
+#include "PALUtils.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+// Fixed-point per-channel-quantization convolution reference kernel.
+OMStatus ConvPerChannel(const core::ConvQuant &params, const core::OMRuntimeShape &input_shape,
+                        const int8_t *input_data, const core::OMRuntimeShape &filter_shape,
+                        const int8_t *filter_data, const int32_t *bias_data,
+                        const core::OMRuntimeShape &output_shape, int8_t *output_data)
+{
+  // Get parameters.
+  const int32_t input_offset = params.input_offset; // r = s(q - Z)
+  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.pad_w;
+  const int pad_height = params.pad_h;
+  const int32_t output_offset = params.output_offset;
+
+  const auto &output_multiplier = params.per_channel_output_multiplier;
+  const auto &output_shift = params.per_channel_output_shift;
+
+  // Set min and max value of the output.
+  const int32_t output_activation_min = params.quantized_activation_min;
+  const int32_t output_activation_max = params.quantized_activation_max;
+
+  // Consistency check.
+  assert(output_activation_max >= output_activation_min);
+  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);
+
+  // Check dimensions of the tensors.
+  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(groups != 0);
+  assert(input_depth % filter_input_depth == 0);
+  const int filters_per_group = output_depth / groups;
+  assert(filters_per_group != 0);
+  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)
+    {
+      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)
+        {
+          auto group = out_channel / filters_per_group;
+          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 < filter_input_depth; ++in_channel)
+              {
+                int32_t input_val = input_data[offset(input_shape.dimsData(), batch, in_y, in_x,
+                                                      in_channel + group * filter_input_depth)];
+                int32_t filter_val = filter_data[offset(filter_shape.dimsData(), out_channel,
+                                                        filter_y, filter_x, in_channel)];
+                // Accumulate with 32 bits accumulator.
+                // In the nudging process during model quantization, we force
+                // real value of 0.0 be represented by a quantized value. This
+                // guarantees that the input_offset is a int8_t, even though
+                // it is represented using int32_t. int32_t += int8_t *
+                // (int8_t - int8_t) so the highest value we can get from each
+                // accumulation is [-127, 127] * ([-128, 127] -
+                // [-128, 127]), which is [-32512, 32512]. log2(32512)
+                // = 14.98, which means we can accumulate at least 2^16
+                // multiplications without overflow. The accumulator is
+                // applied to a filter so the accumulation logic will hold as
+                // long as the filter size (filter_y * filter_x * in_channel)
+                // does not exceed 2^16, which is the case in all the models
+                // we have seen so far.
+                // accumulator depth is smaller than 2^16.
+                acc += filter_val * (input_val + input_offset);
+              }
+            }
+          }
+
+          if (bias_data)
+          {
+            acc += bias_data[out_channel];
+          }
+          acc = multiplyByQuantizedMultiplier(acc, output_multiplier[out_channel],
+                                              output_shift[out_channel]);
+          acc += output_offset;
+          acc = std::max(acc, output_activation_min);
+          acc = std::min(acc, output_activation_max);
+          output_data[offset(output_shape.dimsData(), batch, out_y, out_x, out_channel)] =
+            static_cast<int8_t>(acc);
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_CONV_2D_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALCos.h b/onert-micro/onert-micro/include/pal/mcu/PALCos.h
new file mode 100644 (file)
index 0000000..7bb6f98
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_COS_H
+#define ONERT_MICRO_EXECUTE_PAL_COS_H
+
+#include "PALCosCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_COS_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALDepthwiseConv2D.h b/onert-micro/onert-micro/include/pal/mcu/PALDepthwiseConv2D.h
new file mode 100644 (file)
index 0000000..ddb0323
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_DEPTHWISE_CONV_2D_H
+#define ONERT_MICRO_EXECUTE_PAL_DEPTHWISE_CONV_2D_H
+
+#include "PALDepthwiseConv2DCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+OMStatus DepthwiseConvPerChannel(const core::ConvQuant &params,
+                                 const core::OMRuntimeShape &input_shape, const int8_t *input_data,
+                                 const core::OMRuntimeShape &filter_shape,
+                                 const int8_t *filter_data, const int32_t *bias_data,
+                                 const core::OMRuntimeShape &output_shape, int8_t *output_data)
+{
+  // Get parameters.
+  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.pad_w;
+  const int pad_height = params.pad_h;
+  const int depth_multiplier = params.depth_multiplier;
+  const int32_t input_offset = params.input_offset;
+  const int32_t output_offset = params.output_offset;
+  const int32_t output_activation_min = params.quantized_activation_min;
+  const int32_t output_activation_max = params.quantized_activation_max;
+
+  const auto &output_multiplier = params.per_channel_output_multiplier;
+  const auto &output_shift = params.per_channel_output_shift;
+
+  // 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);
+  assert(output_depth == input_depth * depth_multiplier);
+
+  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.dimsData(), batch, in_y, in_x, in_channel)];
+                  int32_t filter_val = filter_data[offset(filter_shape.dimsData(), 0, filter_y,
+                                                          filter_x, output_channel)];
+                  // Accumulate with 32 bits accumulator.
+                  // In the nudging process during model quantization, we force
+                  // real value of 0.0 be represented by a quantized value. This
+                  // guarantees that the input_offset is a int8_t, even though
+                  // it is represented using int32_t. int32_t += int8_t *
+                  // (int8_t - int8_t) so the highest value we can get from each
+                  // accumulation is [-127, 127] * ([-128, 127] -
+                  // [-128, 127]), which is [-32512, 32512]. log2(32512)
+                  // = 14.98, which means we can accumulate at least 2^16
+                  // multiplications without overflow. The accumulator is
+                  // applied to a filter so the accumulation logic will hold as
+                  // long as the filter size (filter_y * filter_x * in_channel)
+                  // does not exceed 2^16, which is the case in all the models
+                  // we have seen so far.
+                  // accumulator depth is smaller than 2^16.
+                  acc += filter_val * (input_val + input_offset);
+                }
+              }
+            }
+            if (bias_data)
+            {
+              acc += bias_data[output_channel];
+            }
+            acc = multiplyByQuantizedMultiplier(acc, output_multiplier[output_channel],
+                                                output_shift[output_channel]);
+            acc += output_offset;
+            acc = std::max(acc, output_activation_min);
+            acc = std::min(acc, output_activation_max);
+            output_data[offset(output_shape.dimsData(), batch, out_y, out_x, output_channel)] =
+              static_cast<int8_t>(acc);
+          }
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+#endif // ONERT_MICRO_EXECUTE_PAL_ARG_MAX_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALDiv.h b/onert-micro/onert-micro/include/pal/mcu/PALDiv.h
new file mode 100644 (file)
index 0000000..74859c2
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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 ONERT_MICRO_EXECUTE_PAL_DIV_H
+#define ONERT_MICRO_EXECUTE_PAL_DIV_H
+
+#include "PALDivCommon.h"
+
+#endif // ONERT_MICRO_EXECUTE_PAL_MUL_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALExp.h b/onert-micro/onert-micro/include/pal/mcu/PALExp.h
new file mode 100644 (file)
index 0000000..6ecbdf9
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_EXP_H
+#define ONERT_MICRO_EXECUTE_PAL_EXP_H
+
+#include "PALExpCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_EXP_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALFloor.h b/onert-micro/onert-micro/include/pal/mcu/PALFloor.h
new file mode 100644 (file)
index 0000000..b282c43
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_FLOOR_H
+#define ONERT_MICRO_EXECUTE_PAL_FLOOR_H
+
+#include "PALFloorCommon.h"
+
+#endif // ONERT_MICRO_EXECUTE_PAL_FLOOR_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALFloorDiv.h b/onert-micro/onert-micro/include/pal/mcu/PALFloorDiv.h
new file mode 100644 (file)
index 0000000..506d85c
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_FLOORDIV_H
+#define ONERT_MICRO_EXECUTE_PAL_FLOORDIV_H
+
+#include "PALFloorDivCommon.h"
+
+#endif // ONERT_MICRO_EXECUTE_PAL_FLOORDIV_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALFloorMod.h b/onert-micro/onert-micro/include/pal/mcu/PALFloorMod.h
new file mode 100644 (file)
index 0000000..af643ec
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_FLOORMOD_H
+#define ONERT_MICRO_EXECUTE_PAL_FLOORMOD_H
+
+#include "PALFloorModCommon.h"
+
+#endif // ONERT_MICRO_EXECUTE_PAL_FLOORMOD_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALFullyConnected.h b/onert-micro/onert-micro/include/pal/mcu/PALFullyConnected.h
new file mode 100644 (file)
index 0000000..458a910
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_FULLY_CONNECTED_H
+#define ONERT_MICRO_EXECUTE_PAL_FULLY_CONNECTED_H
+
+#include "PALFullyConnectedCommon.h"
+
+#endif // ONERT_MICRO_EXECUTE_PAL_FULLY_CONNECTED_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALL2Pool2D.h b/onert-micro/onert-micro/include/pal/mcu/PALL2Pool2D.h
new file mode 100644 (file)
index 0000000..55f0a14
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_L2_POOL_2D_H
+#define ONERT_MICRO_EXECUTE_PAL_L2_POOL_2D_H
+
+#include "PALL2Pool2DCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_L2_POOL_2D_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALLog.h b/onert-micro/onert-micro/include/pal/mcu/PALLog.h
new file mode 100644 (file)
index 0000000..1a0dde9
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_LOG_H
+#define ONERT_MICRO_EXECUTE_PAL_LOG_H
+
+#include "PALLogCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_LOG_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALMaxPool2D.h b/onert-micro/onert-micro/include/pal/mcu/PALMaxPool2D.h
new file mode 100644 (file)
index 0000000..66d4523
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_H
+#define ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_H
+
+#include "PALMaxPool2DCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+OMStatus MaxPool(const core::Pool2DParams &params, const core::OMRuntimeShape &input_shape,
+                 const int8_t *input_data, const core::OMRuntimeShape &output_shape,
+                 int8_t *output_data)
+{
+  assert(input_shape.dimensionsCount() == 4);
+  assert(output_shape.dimensionsCount() == 4);
+  const int batches = MatchingDim(input_shape, 0, output_shape, 0);
+  const int depth = MatchingDim(input_shape, 3, output_shape, 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_h;
+  const int stride_width = params.stride_w;
+  const int pad_w = params.pad_w;
+  const int pad_h = params.pad_h;
+  const int filter_h = params.filter_h;
+  const int filter_w = params.filter_w;
+  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) - pad_w;
+          const int in_y_origin = (out_y * stride_height) - pad_h;
+          // 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(filter_w, input_width - in_x_origin);
+          const int filter_y_start = std::max(0, -in_y_origin);
+          const int filter_y_end = std::min(filter_h, input_height - in_y_origin);
+          int8_t max = std::numeric_limits<int8_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;
+              max = std::max(
+                max, input_data[offset(input_shape.dimsData(), batch, in_y, in_x, channel)]);
+            }
+          }
+          max = std::max<int8_t>(max, params.quantized_activation_min);
+          max = std::min<int8_t>(max, params.quantized_activation_max);
+          output_data[offset(output_shape.dimsData(), batch, out_y, out_x, channel)] =
+            static_cast<int8_t>(max);
+        }
+      }
+    }
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_MAX_POOL_2D_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALMaximum.h b/onert-micro/onert-micro/include/pal/mcu/PALMaximum.h
new file mode 100644 (file)
index 0000000..01aebe3
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_MAXIMUM_H
+#define ONERT_MICRO_PAL_MAXIMUM_H
+
+#include "PALMaximumCommon.h"
+
+#endif // ONERT_MICRO_PAL_MAXIMUM_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALMinimum.h b/onert-micro/onert-micro/include/pal/mcu/PALMinimum.h
new file mode 100644 (file)
index 0000000..80d5560
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_PAL_MINIMUM_H
+#define ONERT_MICRO_PAL_MINIMUM_H
+
+#include "PALMinimumCommon.h"
+
+#endif // ONERT_MICRO_PAL_MINIMUM_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALMul.h b/onert-micro/onert-micro/include/pal/mcu/PALMul.h
new file mode 100644 (file)
index 0000000..3e9f01d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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 ONERT_MICRO_EXECUTE_PAL_MUL_H
+#define ONERT_MICRO_EXECUTE_PAL_MUL_H
+
+#include "PALMulCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+template <typename InputType, typename OutputType>
+OMStatus Mul(const core::ArithmeticQuantParams &params, uint32_t size, 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);
+  }
+  return Ok;
+}
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_MUL_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALNeg.h b/onert-micro/onert-micro/include/pal/mcu/PALNeg.h
new file mode 100644 (file)
index 0000000..9a623eb
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_NEG_H
+#define ONERT_MICRO_EXECUTE_PAL_NEG_H
+
+#include "PALNegCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_NEG_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALRound.h b/onert-micro/onert-micro/include/pal/mcu/PALRound.h
new file mode 100644 (file)
index 0000000..df66c0a
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_ROUND_H
+#define ONERT_MICRO_EXECUTE_PAL_ROUND_H
+
+#include "PALRoundCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_ROUND_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALRsqrt.h b/onert-micro/onert-micro/include/pal/mcu/PALRsqrt.h
new file mode 100644 (file)
index 0000000..18ea7b5
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_RSQRT_H
+#define ONERT_MICRO_EXECUTE_PAL_RSQRT_H
+
+#include "PALRsqrtCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_RSQRT_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALSin.h b/onert-micro/onert-micro/include/pal/mcu/PALSin.h
new file mode 100644 (file)
index 0000000..8141c76
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_SIN_H
+#define ONERT_MICRO_EXECUTE_PAL_SIN_H
+
+#include "PALSinCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SIN_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALSoftmax.h b/onert-micro/onert-micro/include/pal/mcu/PALSoftmax.h
new file mode 100644 (file)
index 0000000..31150f8
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_SOFTMAX_H
+#define ONERT_MICRO_EXECUTE_PAL_SOFTMAX_H
+
+#include "PALSoftmaxCommon.h"
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SOFTMAX_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALSpaceToBatchND.h b/onert-micro/onert-micro/include/pal/mcu/PALSpaceToBatchND.h
new file mode 100644 (file)
index 0000000..864f6ca
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_SPACE_TO_BATCH_ND_H
+#define ONERT_MICRO_EXECUTE_PAL_SPACE_TO_BATCH_ND_H
+
+#include "PALSpaceToBatchNDCommon.h"
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+#endif // ONERT_MICRO_EXECUTE_PAL_SPACE_TO_BATCH_ND_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALSpaceToDepth.h b/onert-micro/onert-micro/include/pal/mcu/PALSpaceToDepth.h
new file mode 100644 (file)
index 0000000..381fea9
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_SPACE_TO_DEPTH_ND_H
+#define ONERT_MICRO_EXECUTE_PAL_SPACE_TO_DEPTH_ND_H
+
+#include "PALSpaceToDepthCommon.h"
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+#endif // ONERT_MICRO_EXECUTE_PAL_SPACE_TO_DEPTH_ND_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALSqrt.h b/onert-micro/onert-micro/include/pal/mcu/PALSqrt.h
new file mode 100644 (file)
index 0000000..deae727
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_SQRT_H
+#define ONERT_MICRO_EXECUTE_PAL_SQRT_H
+
+#include "PALSqrtCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SQRT_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALSquare.h b/onert-micro/onert-micro/include/pal/mcu/PALSquare.h
new file mode 100644 (file)
index 0000000..76d9dc9
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_SQUARE_H
+#define ONERT_MICRO_EXECUTE_PAL_SQUARE_H
+
+#include "PALSquareCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SQUARE_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALSquaredDifference.h b/onert-micro/onert-micro/include/pal/mcu/PALSquaredDifference.h
new file mode 100644 (file)
index 0000000..e6aeeab
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_SQUARED_DIFFERENCE_H
+#define ONERT_MICRO_EXECUTE_PAL_SQUARED_DIFFERENCE_H
+
+#include "PALSquaredDifferenceCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_SQUARED_DIFFERENCE_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALSub.h b/onert-micro/onert-micro/include/pal/mcu/PALSub.h
new file mode 100644 (file)
index 0000000..a3bd4b7
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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 ONERT_MICRO_EXECUTE_PAL_SUB_H
+#define ONERT_MICRO_EXECUTE_PAL_SUB_H
+
+#include "PALSubCommon.h"
+
+#endif // ONERT_MICRO_EXECUTE_PAL_MUL_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALTanh.h b/onert-micro/onert-micro/include/pal/mcu/PALTanh.h
new file mode 100644 (file)
index 0000000..0f953ce
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTE_PAL_TANH_H
+#define ONERT_MICRO_EXECUTE_PAL_TANH_H
+
+#include "PALTanhCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_TANH_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALTranspose.h b/onert-micro/onert-micro/include/pal/mcu/PALTranspose.h
new file mode 100644 (file)
index 0000000..c1f602c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_TRANSPOSE_H
+#define ONERT_MICRO_EXECUTE_PAL_TRANSPOSE_H
+
+#include "PALTransposeCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_TRANSPOSE_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/PALTransposeConv.h b/onert-micro/onert-micro/include/pal/mcu/PALTransposeConv.h
new file mode 100644 (file)
index 0000000..4a870ec
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 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 ONERT_MICRO_EXECUTE_PAL_TRANSPOSE_CONV_H
+#define ONERT_MICRO_EXECUTE_PAL_TRANSPOSE_CONV_H
+
+#include "PALTransposeConvCommon.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace pal
+{
+
+} // namespace pal
+} // namespace execute
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_EXECUTE_PAL_TRANSPOSE_CONV_H
diff --git a/onert-micro/onert-micro/include/pal/mcu/pal.cmake b/onert-micro/onert-micro/include/pal/mcu/pal.cmake
new file mode 100644 (file)
index 0000000..3725e22
--- /dev/null
@@ -0,0 +1,7 @@
+macro(initialize_pal)
+    set(PAL_INITIALIZED TRUE)
+endmacro()
+
+macro(add_pal_to_target TGT)
+    target_include_directories(${TGT} PUBLIC ${OM_PAL_DIR})
+endmacro()
diff --git a/onert-micro/onert-micro/include/test_models/TestDataBase.h b/onert-micro/onert-micro/include/test_models/TestDataBase.h
new file mode 100644 (file)
index 0000000..4fc6373
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_TEST_DATA_BASE_H
+#define ONERT_MICRO_TEST_MODELS_TEST_DATA_BASE_H
+
+#include <vector>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_TEST_DATA_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/abs/FloatAbsKernel.h b/onert-micro/onert-micro/include/test_models/abs/FloatAbsKernel.h
new file mode 100644 (file)
index 0000000..535966d
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_ABS_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_ABS_KERNEL_H
+
+#include "TestDataAbsBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_ABS_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/abs/NegAbsKernel.h b/onert-micro/onert-micro/include/test_models/abs/NegAbsKernel.h
new file mode 100644 (file)
index 0000000..aa53b30
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_ABS_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_ABS_KERNEL_H
+
+#include "TestDataAbsBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_ABS_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/abs/TestDataAbsBase.h b/onert-micro/onert-micro/include/test_models/abs/TestDataAbsBase.h
new file mode 100644 (file)
index 0000000..5a8d395
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_ABS_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_ABS_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_ABS_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/add/FloatAddKernel.h b/onert-micro/onert-micro/include/test_models/add/FloatAddKernel.h
new file mode 100644 (file)
index 0000000..368e26d
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_ADD_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_ADD_KERNEL_FLOAT_H
+
+#include "TestDataAddBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_ADD_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/add/IntAddKernel.h b/onert-micro/onert-micro/include/test_models/add/IntAddKernel.h
new file mode 100644 (file)
index 0000000..a9b6e99
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_ADD_KERNEL_INT_H
+#define ONERT_MICRO_TEST_MODELS_ADD_KERNEL_INT_H
+
+#include "TestDataAddBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_ADD_KERNEL_INT_H
diff --git a/onert-micro/onert-micro/include/test_models/add/NegAddKernel.h b/onert-micro/onert-micro/include/test_models/add/NegAddKernel.h
new file mode 100644 (file)
index 0000000..3d8476b
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_ADD_KERNEl_H
+#define ONERT_MICRO_TEST_MODELS_NEG_ADD_KERNEl_H
+
+#include "TestDataAddBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_scale_output
+{
+/*
+ * Quantize Add Kernel with output without scale:
+ *
+ * Input_1(1, 4, 4, 3) - Int8   Input_2(1, 4, 4, 1) - Int8
+ *       \                    /
+ *           Add(with broadcast)
+ *              |
+ *          Output(1, 4, 4, 3) - no scale and zero_point
+ */
+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, 0x30, 0x02, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xe4, 0xfd, 0xff, 0xff, 0xe8, 0xfd, 0xff, 0xff, 0xec, 0xfd, 0xff, 0xff,
+  0xf0, 0xfd, 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, 0x5c, 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, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+  0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x00,
+  0x1c, 0xff, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x09, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x39, 0xb4, 0x3c, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x01, 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, 0x09,
+  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, 0xf4, 0xfd, 0x54, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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_scale_output
+
+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 NegTestQuantAddNoScaleKernel : public NegTestDataBase
+{
+public:
+  NegTestQuantAddNoScaleKernel()
+  {
+    _test_kernel_model_circle = neg_add_no_scale_output::test_kernel_model_circle;
+  }
+
+  ~NegTestQuantAddNoScaleKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_ADD_KERNEl_H
diff --git a/onert-micro/onert-micro/include/test_models/add/QuantAddKernel.h b/onert-micro/onert-micro/include/test_models/add/QuantAddKernel.h
new file mode 100644 (file)
index 0000000..85a8443
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_ADD_KERNEL_QUANT_H
+#define ONERT_MICRO_TEST_MODELS_ADD_KERNEL_QUANT_H
+
+#include "TestDataAddBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace add_int8_no_broadcasting
+{
+
+/*
+ * Add Kernel:
+ *
+ * Input_1(1, 4, 4, 3)   Input_2(1, 4, 4, 3)
+ *       \             /
+ *        Add(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, 0x40, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xd4, 0xfd, 0xff, 0xff, 0xd8, 0xfd, 0xff, 0xff, 0xdc, 0xfd, 0xff, 0xff,
+  0xe0, 0xfd, 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, 0x4c, 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, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x78, 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, 0x09, 0x48, 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, 0x6f, 0x12, 0x83, 0x3a, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x09, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x39, 0xb4, 0x3c, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x09,
+  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, 0xf4, 0xfd, 0x54, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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};
+
+const std::vector<int8_t> input1_data = {
+  0, 7,   -3, 7, -9, 2, -5, 0,  9,  -8, 1, 4,  -2, -6, -2, -7, -10, -10, -8, 1,  -8, 0, 2, -5,
+  7, -10, -7, 9, 4,  7, -1, -1, -9, -9, 2, -9, 8,  5,  1,  -3, 4,   7,   0,  -7, 1,  4, 7, 0};
+const std::vector<int8_t> input2_data = {
+  3, -6, 5, -6, 3, -7, 3, -7, 5,  5,  -9, 8, -7, -9, -1, -5, -4, 7,  2,  -3, 2,  7,  -3, 0,
+  2, -9, 4, 7,  2, 1,  7, 3,  -5, -3, 7,  9, 7,  1,  8,  3,  -6, -6, -3, 8,  -7, -7, 4,  1};
+const std::vector<int8_t> reference_output_data = {
+  66,   -41,  71,  -41, -51, -128, 1,   -128, 127, 6,    -128, 127, -128, -128, -48, -128,
+  -128, 24,   -60, -53, -60, 127,  -40, -65,  127, -128, -3,   127, 96,   113,  127, 53,
+  -128, -128, 127, 81,  127, 87,   127, 27,   -80, -41,  -66,  85,  -128, -102, 127, 22};
+
+} // namespace add_int8_no_broadcasting
+
+namespace add_int8_with_broadcasting
+{
+/*
+ * Add Kernel:
+ *
+ * Input_1(1, 4, 4, 3)   Input_2(1, 4, 4, 1)
+ *       \             /
+ *        Add(with 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, 0x40, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xd4, 0xfd, 0xff, 0xff, 0xd8, 0xfd, 0xff, 0xff, 0xdc, 0xfd, 0xff, 0xff,
+  0xe0, 0xfd, 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, 0x4c, 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, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x78, 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, 0x09, 0x48, 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, 0x6f, 0x12, 0x83, 0x3a, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x09, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x39, 0xb4, 0x3c, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x01, 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, 0x09,
+  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, 0xf4, 0xfd, 0x54, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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};
+
+std::vector<int8_t> input1_data = {5,  0,  2,  -9, -3, 2,  1,  -1, 8,   5,  -5, 2, -4, 9,  7,   9,
+                                   4,  -8, -3, 4,  -5, 0,  4,  -4, -2,  -9, -8, 4, -5, -9, -10, 4,
+                                   -8, -1, 1,  1,  4,  -3, -1, -7, -10, 5,  5,  3, -9, 9,  0,   8};
+std::vector<int8_t> input2_data = {-8, 0, 0, -8, -4, 8, 1, -2, -5, -1, 6, -9, -6, -1, 6, -10};
+std::vector<int8_t> reference_output_data = {
+  -111, -128, -128, -117, -39, 26,   13,   -13,  104,  -111, -128, -128, -128, 29,   3,    127,
+  127,  72,   -17,  74,   -43, -44,  8,    -96,  -128, -128, -128, 30,   -87,  -128, 2,    127,
+  28,   -128, -128, -128, -80, -128, -128, -113, -128, 43,   127,  127,  15,   -103, -128, -116};
+
+} // namespace add_int8_with_broadcasting
+
+class TestDataInt8Add : public TestDataAddBase<int8_t>
+{
+public:
+  explicit TestDataInt8Add(bool is_with_broadcast) : TestDataAddBase<int8_t>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = add_int8_with_broadcasting::input1_data;
+      _input2_data = add_int8_with_broadcasting::input2_data;
+      _reference_output_data = add_int8_with_broadcasting::reference_output_data;
+      _test_add_kernel_model_circle = add_int8_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = add_int8_no_broadcasting::input1_data;
+      _input2_data = add_int8_no_broadcasting::input2_data;
+      _reference_output_data = add_int8_no_broadcasting::reference_output_data;
+      _test_add_kernel_model_circle = add_int8_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataInt8Add() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_ADD_KERNEL_QUANT_H
diff --git a/onert-micro/onert-micro/include/test_models/add/TestDataAddBase.h b/onert-micro/onert-micro/include/test_models/add/TestDataAddBase.h
new file mode 100644 (file)
index 0000000..fd53c70
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_ADD_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_ADD_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_ADD_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/add_n/FloatAddNKernel.h b/onert-micro/onert-micro/include/test_models/add_n/FloatAddNKernel.h
new file mode 100644 (file)
index 0000000..d324590
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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 onert_micro
+{
+namespace test_model
+{
+namespace add_n_float
+{
+/*
+ * AddN Kernel:
+ *
+ * Input_1(1, 4, 4, 3)  Input_2(1, 4, 4, 3)  Input_3(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_model
+} // namespace onert_micro
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ADD_N_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/add_n/NegAddNKernel.h b/onert-micro/onert-micro/include/test_models/add_n/NegAddNKernel.h
new file mode 100644 (file)
index 0000000..5df307c
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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 onert_micro
+{
+namespace test_model
+{
+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_3(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_model
+} // namespace onert_micro
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_NEG_ADD_N_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/add_n/TestDataAddNBase.h b/onert-micro/onert-micro/include/test_models/add_n/TestDataAddNBase.h
new file mode 100644 (file)
index 0000000..a35870e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR 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 "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // LUCI_INTERPRETER_TEST_MODELS_ADD_N_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/arg_max/FloatArgMaxKernel.h b/onert-micro/onert-micro/include/test_models/arg_max/FloatArgMaxKernel.h
new file mode 100644 (file)
index 0000000..442f5ba
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_ARG_MAX_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_ARG_MAX_KERNEL_FLOAT_H
+
+#include "TestDataArgMaxBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace arg_max_float
+{
+/*
+ * ArgMax Kernel:
+ *
+ * Input_1(4)       Input_2()
+ *       \             /
+ *            ArgMax
+ *              |
+ *            Output()
+ */
+const unsigned char test_arg_max_kernel_float_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, 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, 0x00, 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, 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, 0x6c, 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, 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, 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, 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};
+
+std::vector<float> input1_data = {10.01877692, 12.34111536, 1.85959512, 10.60881439};
+std::vector<int> input2_data = {};
+std::vector<int> reference_output_data = {1};
+} // namespace arg_max_float
+
+class TestDataFloatArgMax : public TestDataArgMaxBase<float, int>
+{
+public:
+  explicit TestDataFloatArgMax()
+  {
+    _input1_data = arg_max_float::input1_data;
+    _input2_data = {};
+    _reference_output_data = arg_max_float::reference_output_data;
+    _test_arg_max_kernel_model_circle = arg_max_float::test_arg_max_kernel_float_model_circle;
+  }
+
+  ~TestDataFloatArgMax() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_ARG_MAX_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/arg_max/NegArgMaxKernel.h b/onert-micro/onert-micro/include/test_models/arg_max/NegArgMaxKernel.h
new file mode 100644 (file)
index 0000000..bc805c8
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_ARG_MAX_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_ARG_MAX_KERNEL_H
+
+#include "TestDataArgMaxBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_arg_max_axis_output_type_mismatch
+{
+/*
+ * Add Kernel with mismatching axis and output type:
+ *
+ * Input_1(4) - Float       Input_2() - Int32
+ *       \             /
+ *            ArgMax
+ *              |
+ *            Output() - Int64
+ */
+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, 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, 0x00, 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,
+  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, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x6f, 0x66, 0x6d, 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, 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, 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 neg_arg_max_axis_output_type_mismatch
+
+class TestDataAxisOutputTypeMismatchArgMax : public NegTestDataBase
+{
+public:
+  TestDataAxisOutputTypeMismatchArgMax()
+  {
+    _test_kernel_model_circle = neg_arg_max_axis_output_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~TestDataAxisOutputTypeMismatchArgMax() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_ARG_MAX_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/arg_max/TestDataArgMaxBase.h b/onert-micro/onert-micro/include/test_models/arg_max/TestDataArgMaxBase.h
new file mode 100644 (file)
index 0000000..4b05558
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_ARG_MAX_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_ARG_MAX_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T, typename U> class TestDataArgMaxBase : public TestDataBase<T, U>
+{
+public:
+  explicit TestDataArgMaxBase()
+  {
+    // Do nothing
+  }
+
+  const unsigned char *get_model_ptr() override final { return _test_arg_max_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_arg_max_kernel_model_circle;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_ARG_MAX_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/arg_min/FloatArgMinKernel.h b/onert-micro/onert-micro/include/test_models/arg_min/FloatArgMinKernel.h
new file mode 100644 (file)
index 0000000..41e99b8
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_ARG_MIN_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_ARG_MIN_KERNEL_FLOAT_H
+
+#include "TestDataArgMinBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace arg_min_float
+{
+/*
+ * ArgMin Kernel:
+ *
+ * Input_1(4)       Input_2()
+ *       \             /
+ *            ArgMin
+ *              |
+ *            Output()
+ */
+const unsigned char test_arg_min_kernel_float_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, 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, 0x00, 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, 0x6c, 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, 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, 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, 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};
+
+std::vector<float> input1_data = {10.01877692, 12.34111536, 1.85959512, 10.60881439};
+std::vector<int> input2_data = {};
+std::vector<int> reference_output_data = {2};
+} // namespace arg_min_float
+
+class TestDataFloatArgMin : public TestDataArgMinBase<float, int>
+{
+public:
+  explicit TestDataFloatArgMin()
+  {
+    _input1_data = arg_min_float::input1_data;
+    _input2_data = {};
+    _reference_output_data = arg_min_float::reference_output_data;
+    _test_arg_min_kernel_model_circle = arg_min_float::test_arg_min_kernel_float_model_circle;
+  }
+
+  ~TestDataFloatArgMin() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_ARG_MIN_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/arg_min/NegArgMinKernel.h b/onert-micro/onert-micro/include/test_models/arg_min/NegArgMinKernel.h
new file mode 100644 (file)
index 0000000..4e6900a
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_ARG_MIN_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_ARG_MIN_KERNEL_H
+
+#include "TestDataArgMinBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_arg_min_axis_output_type_mismatch
+{
+/*
+ * Add Kernel with mismatching axis and output type:
+ *
+ * Input_1(4) - Float       Input_2() - Int32
+ *       \             /
+ *            ArgMin
+ *              |
+ *            Output() - Int64
+ */
+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, 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, 0x00, 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, 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,
+  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, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x6f, 0x66, 0x6d, 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, 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, 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 neg_arg_min_axis_output_type_mismatch
+
+class TestDataAxisOutputTypeMismatchArgMin : public NegTestDataBase
+{
+public:
+  TestDataAxisOutputTypeMismatchArgMin()
+  {
+    _test_kernel_model_circle = neg_arg_min_axis_output_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~TestDataAxisOutputTypeMismatchArgMin() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_ARG_MIN_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/arg_min/TestDataArgMinBase.h b/onert-micro/onert-micro/include/test_models/arg_min/TestDataArgMinBase.h
new file mode 100644 (file)
index 0000000..bba683e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_ARG_MIN_KERNEL_BASE_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_ARG_MIN_KERNEL_BASE_FLOAT_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T, typename U> class TestDataArgMinBase : public TestDataBase<T, U>
+{
+public:
+  explicit TestDataArgMinBase()
+  {
+    // Do nothing
+  }
+
+  const unsigned char *get_model_ptr() override final { return _test_arg_min_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_arg_min_kernel_model_circle;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_ARG_MIN_KERNEL_BASE_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/averagepool2d/FloatAveragePool2DKernel.h b/onert-micro/onert-micro/include/test_models/averagepool2d/FloatAveragePool2DKernel.h
new file mode 100644 (file)
index 0000000..ede65b7
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_AVERAGEPOOL2D_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_AVERAGEPOOL2D_KERNEL_H
+
+#include "TestDataAveragePool2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace averagepool2d_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 = {
+  12.10053719, 7.72285052,  9.68137431,  11.75806343, 13.15526008, 8.84076114,  3.89649012,
+  5.08537657,  5.83701651,  6.76013136,  12.7101313,  12.78361385, 9.54081657,  13.08970747,
+  5.33034769,  8.86342716,  13.01502028, 9.97710148,  6.87673408,  2.52509585,  1.54685839,
+  3.8311655,   11.54457301, 5.35917021,  4.56748259,  9.03648093,  8.39788966,  6.45449342,
+  1.51089027,  7.12564391,  10.90150032, 5.39767168,  8.99330195,  5.60324272,  12.0761712,
+  1.60046693,  11.42969327, 7.53880683,  1.14423351,  6.36556104,  10.32055668, 11.55385514,
+  8.57127856,  3.37820787,  1.64478344,  12.19396693, 8.30985251,  3.69866267,  3.78378227,
+  1.86568852,  7.82041004,  4.8020888,   4.41597821,  6.58942329,  6.68898032,  8.79502599,
+  7.55499098,  5.02695743,  8.41237828,  10.76109451, 9.11473488,  6.82893955,  10.6362216,
+  9.19960882};
+const std::vector<float> reference_output_data{
+  8.105134,  9.218622, 11.733296, 11.809439, 11.156636, 7.789326,  5.79391,   8.897317,  9.081025,
+  8.723894,  6.599096, 7.0021367, 8.448948,  7.7743797, 9.149021,  8.572052,  6.063554,  3.0093343,
+  3.5036395, 8.35072,  8.300729,  7.0501275, 8.778446,  7.1322556, 5.248886,  6.9012585, 6.6775465,
+  5.9522414, 9.11774,  9.451137,  6.4065313, 4.5132875, 8.201813,  7.296715,  4.8795776, 6.880971,
+  7.452808,  6.142997, 3.5602646, 6.2110386, 8.445556,  6.87313,   4.5578547, 5.7813587, 7.9489927,
+  7.2734737, 6.737269, 7.685891,  8.829959};
+
+} // namespace averagepool2d_float
+
+class TestDataFloatAveragePool2D : public TestDataAveragePool2DBase<float>
+{
+public:
+  TestDataFloatAveragePool2D()
+  {
+    _input_data = averagepool2d_float::input_data;
+    _reference_output_data = averagepool2d_float::reference_output_data;
+    _test_kernel_model_circle = averagepool2d_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatAveragePool2D() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_AVERAGEPOOL2D_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/averagepool2d/NegAveragePool2DKernel.h b/onert-micro/onert-micro/include/test_models/averagepool2d/NegAveragePool2DKernel.h
new file mode 100644 (file)
index 0000000..0871236
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_AVERAGEPOOL2D_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_AVERAGEPOOL2D_KERNEL_H
+
+#include "TestDataAveragePool2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_averagepool2d_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_averagepool2d_kernel
+
+namespace neg_averagepool2d_no_quant_params
+{
+/*
+ * S8 AveragePool2D Kernel (no quant params):
+ *
+ *              Input(1, 8, 8, 1) - Int8
+ *                    |
+ *                 AvgPool2D - Int8
+ *                     |
+ *                Output(1, 7, 7, 1) - Int8
+ */
+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_averagepool2d_no_quant_params
+
+class NegTestDataInputOutputTypeMismatchAveragePool2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchAveragePool2DKernel()
+  {
+    _test_kernel_model_circle = neg_averagepool2d_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;
+};
+
+class NegTestDataNoQuantParamsAveragePool2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataNoQuantParamsAveragePool2DKernel()
+  {
+    _test_kernel_model_circle = neg_averagepool2d_no_quant_params::test_kernel_model_circle;
+  }
+
+  ~NegTestDataNoQuantParamsAveragePool2DKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_AVERAGEPOOL2D_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/averagepool2d/QuantAveragePool2DKernel.h b/onert-micro/onert-micro/include/test_models/averagepool2d/QuantAveragePool2DKernel.h
new file mode 100644 (file)
index 0000000..2466921
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_QUANT_AVERAGE_POOL_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_QUANT_AVERAGE_POOL_KERNEL_H
+
+#include "TestDataAveragePool2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace s8_avg_pool
+{
+
+/*
+ * S8 AveragePool2D Kernel:
+ *
+ *              Input(1, 8, 8, 1) - Int8
+ *                    |
+ *                 AvgPool2D - Int8
+ *                     |
+ *                Output(1, 7, 7, 1) - Int8
+ */
+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, 0xdc, 0x01, 0x00, 0x00, 0xf8, 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,
+  0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 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, 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, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 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, 0x20, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 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,
+  0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x43, 0x01, 0x00, 0x00, 0x00,
+  0x00, 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<int8_t> input_data = {
+  -10, -5, -5, -6, -8, -5, 6,  -10, -4, 5,  -4,  -3, 5,  0,  -8, -6, 0, 7,  1,  -5, -10, 8,
+  0,   -2, -9, 5,  -1, -7, -3, 3,   6,  -1, -8,  -9, -1, 8,  -2, -3, 1, -8, -1, 3,  2,   5,
+  1,   -8, -1, -6, 6,  -6, 5,  9,   -4, 5,  -10, -8, -3, -9, 9,  4,  3, 0,  0,  -10};
+
+const std::vector<int8_t> reference_output_data = {
+  -4, -2, -5, -3, -2, -2, -5, 2,  2,  -3, -3, 1, 0, -4, 1,  3,  -3, -6, -1, 4, 1, -5, -2, 0, -1,
+  -1, 2,  -1, -4, -1, 4,  3,  -3, -3, -4, 1,  1, 5, 3,  -2, -4, -6, -3, 0,  7, 3, 1,  -1, -7};
+
+} // namespace s8_avg_pool
+
+class TestDataS8AveragePool2D : public TestDataAveragePool2DBase<int8_t>
+{
+public:
+  TestDataS8AveragePool2D()
+  {
+    _input_data = s8_avg_pool::input_data;
+    _reference_output_data = s8_avg_pool::reference_output_data;
+    _test_kernel_model_circle = s8_avg_pool::test_kernel_model_circle;
+  }
+
+  ~TestDataS8AveragePool2D() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_QUANT_AVERAGE_POOL_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/averagepool2d/TestDataAveragePool2DBase.h b/onert-micro/onert-micro/include/test_models/averagepool2d/TestDataAveragePool2DBase.h
new file mode 100644 (file)
index 0000000..afa6ec8
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_AVERAGEPOOL2D_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_AVERAGEPOOL2D_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_AVERAGEPOOL2D_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h b/onert-micro/onert-micro/include/test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h
new file mode 100644 (file)
index 0000000..3e6409d
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_BATCH_TO_SPACE_ND_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_BATCH_TO_SPACE_ND_KERNEL_H
+
+#include "TestDataBatchToSpaceNDBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace batch_to_space_nd_float
+{
+/*
+ * BatchToSpaceND Kernel:
+ *
+ *      Input(4, 1, 1, 1)
+ *            |
+ *       BatchToSpaceND
+ *            |
+ *      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,
+  0x68, 0x00, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 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, 0x18, 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, 0x02, 0x00, 0x00, 0x00, 0x01, 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, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x68,
+  0x61, 0x70, 0x65, 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,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x63, 0x72, 0x6f, 0x70, 0x73, 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, 0x04, 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, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 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 = {13.344007, 88.19333, -0.350749, 45.71498};
+const std::vector<float> reference_output_data = {13.344007, 88.19333, -0.350749, 45.71498};
+
+} // namespace batch_to_space_nd_float
+
+class TestDataFloatBatchToSpaceND : public TestDataBatchToSpaceNDBase<float>
+{
+public:
+  TestDataFloatBatchToSpaceND()
+  {
+    _input_data = batch_to_space_nd_float::input_data;
+    _reference_output_data = batch_to_space_nd_float::reference_output_data;
+    _test_kernel_model_circle = batch_to_space_nd_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatBatchToSpaceND() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_BATCH_TO_SPACE_ND_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h b/onert-micro/onert-micro/include/test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h
new file mode 100644 (file)
index 0000000..e29b82e
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_BATCH_TO_SPACE_ND_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_BATCH_TO_SPACE_ND_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_batch_to_space_nd_kernel
+{
+/*
+ * BatchToSpaceND kernel with input output type mismatch:
+ *
+ *      Input(4, 1, 1, 1) - Float32
+ *            |
+ *        BatchToSpaceND
+ *            |
+ *      Output(1, 2, 2 , 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,
+  0x68, 0x00, 0x00, 0x00, 0xdc, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 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, 0x18, 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, 0x02, 0x00, 0x00, 0x00, 0x01, 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, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x6f, 0x63,
+  0x6b, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 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, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x63, 0x72, 0x6f, 0x70, 0x73, 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,
+  0x04, 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, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25,
+  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_batch_to_space_nd_kernel
+
+class NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_batch_to_space_nd_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_BATCH_TO_SPACE_ND_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/batch_to_space_nd/TestDataBatchToSpaceNDBase.h b/onert-micro/onert-micro/include/test_models/batch_to_space_nd/TestDataBatchToSpaceNDBase.h
new file mode 100644 (file)
index 0000000..b4e96f6
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_BATCH_TO_SPACE_ND_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_BATCH_TO_SPACE_ND_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataBatchToSpaceNDBase : public TestDataBase<T>
+{
+public:
+  TestDataBatchToSpaceNDBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_BATCH_TO_SPACE_ND_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/concatenation/FloatConcatenationKernel.h b/onert-micro/onert-micro/include/test_models/concatenation/FloatConcatenationKernel.h
new file mode 100644 (file)
index 0000000..65fb2f2
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_CONCATENATION_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_FLOAT_H
+
+#include "TestDataConcatenationBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/concatenation/IntConcatenationKernel.h b/onert-micro/onert-micro/include/test_models/concatenation/IntConcatenationKernel.h
new file mode 100644 (file)
index 0000000..8e8995c
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_CONCATENATION_KERNEL_INT_H
+#define ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_INT_H
+
+#include "TestDataConcatenationBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_INT_H
diff --git a/onert-micro/onert-micro/include/test_models/concatenation/NegConcatenationKernel.h b/onert-micro/onert-micro/include/test_models/concatenation/NegConcatenationKernel.h
new file mode 100644 (file)
index 0000000..add38b4
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_CONCATENATION_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_CONCATENATION_KERNEL_H
+
+#include "TestDataConcatenationBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_CONCATENATION_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/concatenation/TestDataConcatenationBase.h b/onert-micro/onert-micro/include/test_models/concatenation/TestDataConcatenationBase.h
new file mode 100644 (file)
index 0000000..c76bca0
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_CONCATENATION_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_CONCATENATION_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/conv2d/FloatConv2DKernel.h b/onert-micro/onert-micro/include/test_models/conv2d/FloatConv2DKernel.h
new file mode 100644 (file)
index 0000000..316e832
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_CONV_2D_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_CONV_2D_KERNEL_FLOAT_H
+
+#include "TestDataConv2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_CONV_2D_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/conv2d/NegConv2DKernel.h b/onert-micro/onert-micro/include/test_models/conv2d/NegConv2DKernel.h
new file mode 100644 (file)
index 0000000..04f48b6
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_CONV_2D_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_CONV_2D_KERNEL_H
+
+#include "TestDataConv2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_no_quant_params
+{
+
+/*
+ * S8 Conv2D Kernel:
+ *
+ * Input(1, 3, 3, 2) - Int8   Weight(2, 2, 2, 2) - Int8 (No quant params)
+ *                  \         /
+ *                   \       /
+ *                     Conv2D ---- Bias(2) - Int32
+ *                       |
+ *                Output(1, 2, 2, 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, 0x6c, 0x00, 0x00, 0x00, 0xc0, 0x02, 0x00, 0x00, 0xdc, 0x02, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x30, 0xfb, 0xff, 0xff, 0x0b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+  0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x00, 0xed, 0xc2, 0xf1, 0x2c, 0xee, 0x36, 0xfe, 0x0d, 0x18, 0x32, 0x14, 0x00, 0x23, 0xe6, 0xf5,
+  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,
+  0x2c, 0x01, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0xf2, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x09, 0x48, 0x00, 0x00, 0x00, 0xe4, 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,
+  0xb7, 0x7d, 0x49, 0x39, 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, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x62, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x00, 0x54, 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, 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, 0x09, 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, 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, 0x09,
+  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, 0x7c, 0x7b, 0xd7, 0x39, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x20, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xc1, 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_no_quant_params
+
+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 NegTestDataInvalidInputShapeConv2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInvalidInputShapeConv2DKernel()
+  {
+    _test_kernel_model_circle = neg_conv2d_invalid_input_shape::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInvalidInputShapeConv2DKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataNoQuantParamsConv2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataNoQuantParamsConv2DKernel()
+  {
+    _test_kernel_model_circle = neg_conv2d_no_quant_params::test_kernel_model_circle;
+  }
+
+  ~NegTestDataNoQuantParamsConv2DKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_CONV_2D_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/conv2d/QuantConv2DKernel.h b/onert-micro/onert-micro/include/test_models/conv2d/QuantConv2DKernel.h
new file mode 100644 (file)
index 0000000..f5cc7d4
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_QUANT_CONV2D_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_QUANT_CONV2D_KERNEL_H
+
+#include "TestDataConv2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace s8_conv_2d
+{
+
+/*
+ * S8 Conv2D Kernel:
+ *
+ * Input(1, 3, 3, 2) - Int8   Weight(2, 2, 2, 2) - Int8
+ *                  \         /
+ *                   \       /
+ *                     Conv2D ---- Bias(2) - Int32
+ *                       |
+ *                Output(1, 2, 2, 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, 0x6c, 0x00, 0x00, 0x00, 0x30, 0x03, 0x00, 0x00, 0x4c, 0x03, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0xb0, 0x03, 0x00, 0x00, 0x12, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x06, 0x00,
+  0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x0d, 0x11, 0xf8, 0xf8, 0x01, 0x54, 0x21, 0x35, 0xe6, 0x1a, 0xf2, 0xff, 0x17, 0x3b, 0x1c, 0xf8,
+  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, 0x01, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x82, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x09, 0x48, 0x00, 0x00, 0x00, 0x74, 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,
+  0xb7, 0x7d, 0x49, 0x39, 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, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0xf2, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x00, 0xe4, 0xfe, 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, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x0e, 0x00, 0x1a, 0x00, 0x14, 0x00, 0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x09, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x18, 0x00, 0x04, 0x00,
+  0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x44, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0xa6, 0x11, 0xd0, 0x39, 0x96, 0x6c, 0xa1, 0x3a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40,
+  0x00, 0x00, 0x60, 0x41, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0xa0, 0xc1,
+  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, 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, 0x09,
+  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, 0x7c, 0x7b, 0xd7, 0x39, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x20, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xc1, 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<int8_t> input_data = {9,  9, -7, -6, -2, 2,  -10, 7,  -5,
+                                        -5, 1, 1,  6,  -8, -6, -3,  -9, 0};
+
+const std::vector<int8_t> reference_output_data = {103, 99, 102, 98, 102, 99, 102, 97};
+
+} // namespace s8_conv_2d
+
+class TestDataS8Conv2D : public TestDataConv2DBase<int8_t>
+{
+public:
+  TestDataS8Conv2D()
+  {
+    _input_data = s8_conv_2d::input_data;
+    _reference_output_data = s8_conv_2d::reference_output_data;
+    _test_kernel_model_circle = s8_conv_2d::test_kernel_model_circle;
+  }
+
+  ~TestDataS8Conv2D() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_QUANT_CONV2D_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/conv2d/TestDataConv2DBase.h b/onert-micro/onert-micro/include/test_models/conv2d/TestDataConv2DBase.h
new file mode 100644 (file)
index 0000000..7681363
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_CONV_2D_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_CONV_2D_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_CONV_2D_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/cos/FloatCosKernel.h b/onert-micro/onert-micro/include/test_models/cos/FloatCosKernel.h
new file mode 100644 (file)
index 0000000..a5fdc5a
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_COS_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_COS_KERNEL_H
+
+#include "TestDataCosBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace cos_float
+{
+/*
+ * Cos Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Cos
+ *            |
+ *      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, 0x54, 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,
+  0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 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.387439727783203,  9.756175994873047,   -3.3056538105010986,
+                                       -6.788370609283447, 3.284966468811035,   8.500691413879395,
+                                       7.117439270019531,  -1.2989126443862915, -6.051342964172363,
+                                       3.2069919109344482, -5.918918609619141,  2.415487051010132,
+                                       5.600773811340332,  8.547533988952637,   3.106605052947998,
+                                       7.0716776847839355, -2.9120774269104004, -9.454291343688965};
+
+const std::vector<float> reference_output_data = {
+  -0.31926071643829346, -0.9455884099006653, -0.9865721464157104, 0.8750848174095154,
+  -0.9897395968437195,  -0.6025638580322266, 0.6717305183410645,  0.2685464024543762,
+  0.9732447266578674,   -0.9978622198104858, 0.9343852400779724,  -0.7477657794952393,
+  0.7760541439056396,   -0.639272928237915,  -0.9993879795074463, 0.7049154043197632,
+  -0.9737768173217773,  -0.999564528465271};
+} // namespace cos_float
+
+class TestDataFloatCos : public TestDataCosBase<float>
+{
+public:
+  TestDataFloatCos()
+  {
+    _input_data = cos_float::input_data;
+    _reference_output_data = cos_float::reference_output_data;
+    _test_kernel_model_circle = cos_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatCos() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_COS_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/cos/NegCosKernel.h b/onert-micro/onert-micro/include/test_models/cos/NegCosKernel.h
new file mode 100644 (file)
index 0000000..e6e1ac4
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_COS_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_COS_KERNEL_H
+
+#include "TestDataCosBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Cos Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Cos
+ *            |
+ *      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, 0x54, 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,
+  0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 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 NegTestDataInputOutputTypeMismatchCosKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchCosKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchCosKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_COS_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/cos/TestDataCosBase.h b/onert-micro/onert-micro/include/test_models/cos/TestDataCosBase.h
new file mode 100644 (file)
index 0000000..2fada3d
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_COS_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_COS_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataCosBase : public TestDataBase<T>
+{
+public:
+  TestDataCosBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_COS_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/depthwise_conv_2d/FloatDepthwiseConv2DKernel.h b/onert-micro/onert-micro/include/test_models/depthwise_conv_2d/FloatDepthwiseConv2DKernel.h
new file mode 100644 (file)
index 0000000..57f46b6
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_FLOAT_H
+
+#include "TestDataDepthwiseConv2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace depthwiseconv2d_float
+{
+
+/*
+ * DepthwiseConv2D Kernel:
+ *
+ * Input(1, 4, 2, 2)   Weight(1, 2, 2, 4)   Bias(4)
+ *              \            |             /
+ *               \           |            /
+ *                    DepthwiseConv2D
+ *                           |
+ *                    Output(1, 2, 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,
+  0xa4, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x7c, 0x00, 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, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 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, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x10, 0xc1, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x30, 0xc1,
+  0x00, 0x00, 0x40, 0x41, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0x60, 0xc1, 0x00, 0x00, 0x70, 0x41,
+  0x00, 0x00, 0x80, 0xc1, 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, 0x84, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x8c, 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, 0x02,
+  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, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 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, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 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.5529652, 4.395708,  7.810858,  0.8234205, 8.967432, 0.8667908, 9.755089,  -1.0849819,
+  3.721611,   6.6046314, -5.122017, -7.123464, 8.446955, 1.757657,  16.904526, 4.1345367};
+
+const std::vector<float> reference_output_data = {99.80263,  0.0, 0.0,       55.757915,
+                                                  312.81335, 0.0, 175.49365, 0.0};
+
+} // namespace depthwiseconv2d_float
+
+class TestDataFloatDepthwiseConv2D : public TestDataDepthwiseConv2DBase<float>
+{
+public:
+  TestDataFloatDepthwiseConv2D()
+  {
+    _input_data = depthwiseconv2d_float::input_data;
+    _reference_output_data = depthwiseconv2d_float::reference_output_data;
+    _test_kernel_model_circle = depthwiseconv2d_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatDepthwiseConv2D() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/depthwise_conv_2d/NegDepthwiseConv2DKernel.h b/onert-micro/onert-micro/include/test_models/depthwise_conv_2d/NegDepthwiseConv2DKernel.h
new file mode 100644 (file)
index 0000000..58e8b79
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_DEPTHWISE_CONV_2D_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_DEPTHWISE_CONV_2D_KERNEL_H
+
+#include "TestDataDepthwiseConv2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_depthwise_conv2d_input_type_mismatch
+{
+
+/*
+ * DepthwiseConv2D Kernel with input type mismatch (input_type should be equal to weight_type):
+ *
+ * Input(1, 4, 2, 2) - Float32   Weight(1, 2, 2, 4) - Int32   Bias(4)- FLOAT32
+ *              \                       |                   /
+ *               \                      |                  /
+ *                               DepthwiseConv2D
+ *                                     |
+ *                             Output(1, 2, 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,
+  0xa4, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x7c, 0x00, 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, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00, 0xf5, 0xff, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xf2, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0xf0, 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, 0x84, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x8c, 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, 0x02,
+  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, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 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,
+  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,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 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, 0x0c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 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_depthwise_conv2d_input_type_mismatch
+
+namespace neg_depthwise_conv2d_bias_wrong_type
+{
+/*
+ * DepthwiseConv2D 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
+ *              \                       |                   /
+ *               \                      |                  /
+ *                                DepthwiseConv2D
+ *                                     |
+ *                             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,
+  0xa4, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x7c, 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,
+  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x10, 0xc1, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x30, 0xc1,
+  0x00, 0x00, 0x40, 0x41, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0x60, 0xc1, 0x00, 0x00, 0x70, 0x41,
+  0x00, 0x00, 0x80, 0xc1, 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, 0x84, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x8c, 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, 0x02,
+  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, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 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,
+  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,
+  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,
+  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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 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_depthwise_conv2d_bias_wrong_type
+
+namespace neg_depthwise_conv2d_invalid_input_shape
+{
+/*
+ * DepthwiseConv2D Kernel with invalid input shape (rank should be == 4):
+ *
+ * Input(1, 1, 3, 3, 2) - Float32   Weight(1, 1, 1, 2) - Float32   Bias(1) - Float32
+ *              \                       |                   /
+ *               \                      |                  /
+ *                                DepthwiseConv2D
+ *                                     |
+ *                             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,
+  0xa4, 0x00, 0x00, 0x00, 0x24, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x90, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x7c, 0x00, 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, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 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, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x10, 0xc1, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x30, 0xc1,
+  0x00, 0x00, 0x40, 0x41, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0x60, 0xc1, 0x00, 0x00, 0x70, 0x41,
+  0x00, 0x00, 0x80, 0xc1, 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, 0x84, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x8c, 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, 0x02,
+  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, 0x07, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 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, 0x01, 0x00, 0x00, 0x00, 0x04, 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, 0x04, 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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 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,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 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_depthwise_conv2d_invalid_input_shape
+
+namespace neg_depthwise_conv2d_no_quant_params
+{
+/*
+ * DepthwiseConv2D Kernel with no quant params:
+ *
+ * Input(1, 5, 5, 3)-Int8   Weight(1, 3, 3, 3) -Int8   Bias(3)-Int32
+ *              \            |             /
+ *               \           |            /
+ *                    DepthwiseConv2D
+ *                           |
+ *                    Output(1, 5, 5, 3)-Int8
+ */
+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, 0x7c, 0x00, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0xff, 0x02, 0x00, 0x01, 0x00,
+  0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfe, 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, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+  0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00,
+  0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x01, 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,
+  0x44, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0xda, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x09, 0x48, 0x00, 0x00, 0x00, 0xcc, 0xfe, 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,
+  0xba, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x4a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x5c, 0x00, 0x00, 0x00, 0x3c, 0xff, 0xff, 0xff, 0x44, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xee, 0x25, 0x2a, 0x25, 0xbb, 0x32, 0x04, 0x38, 0xbe, 0x1f, 0xb9, 0x37, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x61, 0x73, 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, 0x09, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 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, 0x09, 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,
+  0xba, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 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, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+  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_depthwise_conv2d_no_quant_params
+
+class NegTestDataNoQuantParamsDepthwiseConv2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataNoQuantParamsDepthwiseConv2DKernel()
+  {
+    _test_kernel_model_circle = neg_depthwise_conv2d_no_quant_params::test_kernel_model_circle;
+  }
+
+  ~NegTestDataNoQuantParamsDepthwiseConv2DKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInputMismatchDepthwiseConv2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputMismatchDepthwiseConv2DKernel()
+  {
+    _test_kernel_model_circle = neg_depthwise_conv2d_input_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputMismatchDepthwiseConv2DKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataWrongBiasTypeDepthwiseConv2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataWrongBiasTypeDepthwiseConv2DKernel()
+  {
+    _test_kernel_model_circle = neg_depthwise_conv2d_bias_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataWrongBiasTypeDepthwiseConv2DKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputShapeDepthwiseConv2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInvalidInputShapeDepthwiseConv2DKernel()
+  {
+    _test_kernel_model_circle = neg_depthwise_conv2d_invalid_input_shape::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInvalidInputShapeDepthwiseConv2DKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_DEPTHWISE_CONV_2D_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/depthwise_conv_2d/QuantDepthwiseConv2DKernel.h b/onert-micro/onert-micro/include/test_models/depthwise_conv_2d/QuantDepthwiseConv2DKernel.h
new file mode 100644 (file)
index 0000000..53938d5
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_QUANT_H
+#define ONERT_MICRO_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_QUANT_H
+
+#include "TestDataDepthwiseConv2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace depthwiseconv2d_int8
+{
+
+/*
+ * DepthwiseConv2D Kernel:
+ *
+ * Input(1, 5, 5, 3)-Int8   Weight(1, 3, 3, 3) -Int8   Bias(3)-Int32
+ *              \            |             /
+ *               \           |            /
+ *                    DepthwiseConv2D
+ *                           |
+ *                    Output(1, 5, 5, 3)-Int8
+ */
+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, 0x7c, 0x00, 0x00, 0x00, 0x50, 0x03, 0x00, 0x00, 0x6c, 0x03, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x1b, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 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, 0x14, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+  0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00,
+  0x08, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x01, 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, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x72, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x09, 0x48, 0x00, 0x00, 0x00, 0x64, 0xfe, 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,
+  0xba, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xe2, 0xfe, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x5c, 0x00, 0x00, 0x00, 0xd4, 0xfe, 0xff, 0xff, 0x44, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xee, 0x25, 0x2a, 0x25, 0xbb, 0x32, 0x04, 0x38, 0xbe, 0x1f, 0xb9, 0x37, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x62, 0x69, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x1a, 0x00, 0x14, 0x00,
+  0x13, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+  0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x6c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x12, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x43, 0x37, 0x0b, 0x3e,
+  0xea, 0x15, 0x60, 0x3c, 0xb5, 0x15, 0xab, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x03, 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, 0x09,
+  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, 0xba, 0xc0, 0xc0, 0x3c, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x05, 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,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 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 = {
+  -5, 43, -44, 2,   -13, -22, -28, -27, -34, 35,  -37, -47, -22, 49,  -36, 0,   -9,  9,  45,
+  20, 28, 43,  32,  -30, 5,   5,   23,  0,   -16, -24, -18, -21, 38,  5,   -40, -12, 6,  -36,
+  4,  4,  -14, -22, 42,  39,  -8,  -16, 47,  19,  -3,  -20, -38, -4,  23,  13,  -26, 46, -36,
+  -4, -4, -31, 46,  -44, -44, 21,  11,  48,  1,   -38, 17,  -42, -29, 3,   8,   -32, -41};
+
+const std::vector<int8_t> reference_output_data = {
+  6, 0,  -2, 6,  -1, -3, 1,  0,  -4, 0,  0, -3,  0,  1,  0,  1, 0,  2,  1, 1, -3, 0,  1,  2, 10,
+  0, -2, -5, 0,  0,  -1, 0,  -1, -1, -1, 0, -10, -1, -2, -7, 0, -1, -1, 1, 0, 3,  1,  -3, 3, 0,
+  1, -7, 1,  -3, 0,  1,  -3, -1, 0,  0,  0, -1,  4,  2,  0,  1, 0,  -1, 0, 1, 0,  -4, 4,  0, 0};
+
+} // namespace depthwiseconv2d_int8
+
+class TestDataInt8DepthwiseConv2D : public TestDataDepthwiseConv2DBase<int8_t>
+{
+public:
+  TestDataInt8DepthwiseConv2D()
+  {
+    _input_data = depthwiseconv2d_int8::input_data;
+    _reference_output_data = depthwiseconv2d_int8::reference_output_data;
+    _test_kernel_model_circle = depthwiseconv2d_int8::test_kernel_model_circle;
+  }
+
+  ~TestDataInt8DepthwiseConv2D() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_QUANT_H
diff --git a/onert-micro/onert-micro/include/test_models/depthwise_conv_2d/TestDataDepthwiseConv2DBase.h b/onert-micro/onert-micro/include/test_models/depthwise_conv_2d/TestDataDepthwiseConv2DBase.h
new file mode 100644 (file)
index 0000000..728aa8e
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataDepthwiseConv2DBase : 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_DEPTHWISE_CONV_2D_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/dequantize/FloatDequantizeKernel.h b/onert-micro/onert-micro/include/test_models/dequantize/FloatDequantizeKernel.h
new file mode 100644 (file)
index 0000000..aaee41b
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_DEQUANTIZE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_DEQUANTIZE_KERNEL_H
+
+#include "TestDataDequantizeBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace dequantize_float
+{
+/*
+ * Dequantize Kernel:
+ *
+ *         Input(4)
+ *            |
+ *         Dequantize
+ *            |
+ *         Output(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, 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, 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, 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, 0x01, 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, 0x4c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x48, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+  0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x28, 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, 0x7f, 0x6a, 0xbc, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 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,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 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 = {-18, 22, -34, -16};
+
+const std::vector<float> reference_output_data = {-0.414, 0.506, -0.782, -0.368};
+} // namespace dequantize_float
+
+class TestDataFloatDequantize : public TestDataDequantizeBase<int8_t, float>
+{
+public:
+  TestDataFloatDequantize()
+  {
+    _input_data = dequantize_float::input_data;
+    _reference_output_data = dequantize_float::reference_output_data;
+    _test_kernel_model_circle = dequantize_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatDequantize() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_DEQUANTIZE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/dequantize/NegDequantizeKernel.h b/onert-micro/onert-micro/include/test_models/dequantize/NegDequantizeKernel.h
new file mode 100644 (file)
index 0000000..5ebafd3
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_DEQUANTIZE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_DEQUANTIZE_KERNEL_H
+
+#include "TestDataDequantizeBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_invalid_output_shape_dequantize_kernel
+{
+/*
+ * Dequantize Kernel with invalid output shape - should be float32:
+ *
+ *         Input(4)
+ *            |
+ *         Dequantize
+ *            |
+ *         Output(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,
+  0x2c, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x70, 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, 0x48, 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, 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, 0x4c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x48, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00,
+  0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x28, 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, 0x7f, 0x6a, 0xbc, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 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,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 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_output_shape_dequantize_kernel
+
+class NegTestDataWithInvalidOutputShapeDequantizeKernel : public NegTestDataBase
+{
+public:
+  NegTestDataWithInvalidOutputShapeDequantizeKernel()
+  {
+    _test_kernel_model_circle =
+      neg_invalid_output_shape_dequantize_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataWithInvalidOutputShapeDequantizeKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_DEQUANTIZE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/dequantize/TestDataDequantizeBase.h b/onert-micro/onert-micro/include/test_models/dequantize/TestDataDequantizeBase.h
new file mode 100644 (file)
index 0000000..19e47c7
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_DEQUANTIZE_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_DEQUANTIZE_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T, typename O> class TestDataDequantizeBase : public TestDataBase<T, O>
+{
+public:
+  TestDataDequantizeBase() = 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<O> &get_output_data_by_index(int i) override final
+  {
+    assert(i == 0);
+    return _reference_output_data;
+  }
+
+protected:
+  std::vector<T> _input_data;
+  std::vector<O> _reference_output_data;
+  const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_DEQUANTIZE_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/div/FloatDivKernel.h b/onert-micro/onert-micro/include/test_models/div/FloatDivKernel.h
new file mode 100644 (file)
index 0000000..bc76d2d
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_DIV_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_DIV_KERNEL_FLOAT_H
+
+#include "TestDataDivBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace div_float_with_broadcasting
+{
+
+/*
+ * div Kernel:
+ *
+ * Input_1(1, 4, 4, 3)   Input_2(1, 4, 4, 1)
+ *       \             /
+ *     Div(with 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, 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,
+  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,
+  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,
+  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, 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 = {
+  0.53560877, -1.8867658, -8.832248,  5.859678,   -5.1357374, -7.014421,  2.8209867,  -4.6921616,
+  8.162995,   -2.6120718, -0.8869447, -2.3489552, -6.208182,  -2.2264383, 6.55287,    -5.3615203,
+  -2.7882025, 1.1029396,  -9.950372,  0.1670622,  3.533298,   2.606648,   7.126593,   -3.6454842,
+  2.637641,   -6.7670174, 5.8970585,  8.792766,   -6.63798,   -1.1457828, 9.122211,   -3.2186837,
+  -8.038172,  3.3369763,  0.89376354, -7.979661,  -4.241393,  -3.4046402, 6.1339216,  7.767886,
+  5.7856345,  8.147999,   9.79144,    8.312661,   -4.9722652, 3.0038614,  -5.3218126, -6.5680394};
+const std::vector<float> input2_data = {
+  -8.79469,  -0.2644837, -1.6307421, 2.0497515, -1.5460981, 1.3044068, 7.1843495, 1.1402534,
+  0.2102437, 4.253287,   7.076496,   1.3749583, 6.6056423,  4.4962177, 3.9589605, -1.8852876};
+const std::vector<float> reference_output_data = {
+  -0.06090138, 0.21453466,  1.0042704,   -22.155157,  19.417974,  26.521185,   -1.7298791,
+  2.8773167,   -5.005694,   -1.2743359,  -0.4327084,  -1.1459707, 4.0153866,   1.4400369,
+  -4.2383275,  -4.110313,   -2.1375253,  0.8455488,   -1.3850067, 0.023253629, 0.49180487,
+  2.286025,    6.250008,    -3.1970825,  12.545636,   -32.18654,  28.048681,   2.0672872,
+  -1.5606706,  -0.26938763, 1.2890859,   -0.45484143, -1.1358972, 2.4269655,   0.6500296,
+  -5.803566,   -0.6420864,  -0.51541394, 0.9285882,   1.727649,   1.2867781,   1.8121896,
+  2.4732351,   2.099708,    -1.2559522,  -1.5933173,  2.822812,   3.4838395};
+
+} // namespace div_float_with_broadcasting
+
+namespace div_float_no_broadcasting
+{
+/*
+ * div Kernel:
+ *
+ * Input_1(1, 4, 4, 3)   Input_2(1, 4, 4, 3)
+ *       \             /
+ *     Div(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, 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,
+  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, 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 = {
+  -0.45486993, 7.7920837,  2.458276,   -9.338201, 2.132607,   7.5134172,   -7.3420544, -6.390925,
+  1.456884,    -1.8421048, 2.4459255,  -3.930421, 5.439674,   -0.3640652,  -4.5039334, -8.457781,
+  3.8367634,   -6.271797,  -3.6314914, 7.7209616, 0.7935352,  -6.561332,   0.77153474, 8.639922,
+  0.15612718,  5.9307566,  0.71869296, 5.4473047, -7.4552007, -2.4453044,  -5.7700257, 7.9675865,
+  4.7339244,   1.3709338,  6.940702,   2.7984607, 9.185996,   8.848705,    -4.7602606, -3.887096,
+  4.807505,    2.9972825,  5.416388,   5.6682634, -5.875255,  -0.29188222, 7.522483,   -6.873605};
+std::vector<float> input2_data = {
+  1.5015899,  9.9904785,  -5.368375,  -3.0589666, 1.4541256,  3.0067844,  -1.0564902,  3.4706006,
+  4.3666296,  9.586457,   -4.497033,  -9.208905,  -6.8920064, 6.2652717,  -0.60215276, 7.8108196,
+  -7.7110577, -4.182856,  6.8893385,  9.817479,   -9.451469,  -2.0223913, 5.1733356,   5.4378557,
+  4.1402535,  -4.4087567, 0.16630036, -8.007953,  4.7895074,  -3.2770896, 4.013145,    2.2894316,
+  5.74741,    -9.481342,  3.194859,   9.471764,   -7.8339133, -8.103412,  -3.8862576,  9.901491,
+  5.358148,   -2.7227716, -5.84558,   9.881574,   3.5261114,  3.4573863,  8.221204,    -3.6716719};
+std::vector<float> reference_output_data = {
+  -0.30292553, 0.779951,   -0.4579181,  3.0527303,   1.4665906,   2.4988215,   6.949477,
+  -1.8414464,  0.3336404,  -0.19215699, -0.54389757, 0.42680657,  -0.7892729,  -0.058108445,
+  7.4797187,   -1.0828289, -0.49756643, 1.4994054,   -0.52711755, 0.7864505,   -0.083958924,
+  3.2443435,   0.14913681, 1.5888473,   0.03770957,  -1.345222,   4.321656,    -0.6802369,
+  -1.5565695,  0.7461817,  -1.4377816,  3.4801593,   0.8236622,   -0.14459279, 2.1724596,
+  0.29545298,  -1.1725935, -1.0919728,  1.2248958,   -0.3925768,  0.8972326,   -1.1008204,
+  -0.92657834, 0.5736195,  -1.6662138,  -0.0844228,  0.9150099,   1.872064};
+
+} // 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_MUL_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/div/IntDivKernel.h b/onert-micro/onert-micro/include/test_models/div/IntDivKernel.h
new file mode 100644 (file)
index 0000000..4967215
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_DIV_KERNEL_INT_H
+#define ONERT_MICRO_TEST_MODELS_DIV_KERNEL_INT_H
+
+#include "TestDataDivBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace div_int_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, 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, 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, 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, 0x02, 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, 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,
+  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,
+  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, 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<int32_t> input1_data = {7, -17};
+const std::vector<int32_t> input2_data = {12, 4, -7, -10, -10, -16, -17, 1, 15, 4};
+const std::vector<int32_t> reference_output_data = {0, 1, -1, 0, 0, 1, 1, -17, -1, -4};
+
+} // namespace div_int_with_broadcasting
+
+namespace div_int_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, 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, 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, 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, 0x02, 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, 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,
+  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, 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<int32_t> input1_data = {-4, 19, -4, -9, 17, 12, 17, -15, -10, -14};
+std::vector<int32_t> input2_data = {-18, -16, -17, -9, -6, -1, 7, -2, -15, -3};
+std::vector<int32_t> reference_output_data = {0, -1, 0, 1, -2, -12, 2, 7, 0, 4};
+
+} // namespace div_int_no_broadcasting
+
+namespace div_int64_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, 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, 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, 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, 0x04, 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, 0x04,
+  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, 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, 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, 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<int64_t> input1_data = {7, -17};
+const std::vector<int64_t> input2_data = {12, 4, -7, -10, -10, -16, -17, 1, 15, 4};
+const std::vector<int64_t> reference_output_data = {0, 1, -1, 0, 0, 1, 1, -17, -1, -4};
+
+} // namespace div_int64_with_broadcasting
+
+namespace div_int64_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, 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, 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, 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, 0x04, 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, 0x04,
+  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, 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, 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<int64_t> input1_data = {-4, 19, -4, -9, 17, 12, 17, -15, -10, -14};
+std::vector<int64_t> input2_data = {-18, -16, -17, -9, -6, -1, 7, -2, -15, -3};
+std::vector<int64_t> reference_output_data = {0, -1, 0, 1, -2, -12, 2, 7, 0, 4};
+
+} // namespace div_int64_no_broadcasting
+
+class TestDataIntDiv : public TestDataDivBase<int32_t>
+{
+public:
+  explicit TestDataIntDiv(bool is_with_broadcast) : TestDataDivBase<int32_t>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = div_int_with_broadcasting::input1_data;
+      _input2_data = div_int_with_broadcasting::input2_data;
+      _reference_output_data = div_int_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = div_int_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = div_int_no_broadcasting::input1_data;
+      _input2_data = div_int_no_broadcasting::input2_data;
+      _reference_output_data = div_int_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = div_int_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataIntDiv() override = default;
+};
+
+class TestDataInt64Div : public TestDataDivBase<int64_t>
+{
+public:
+  explicit TestDataInt64Div(bool is_with_broadcast) : TestDataDivBase<int64_t>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = div_int64_with_broadcasting::input1_data;
+      _input2_data = div_int64_with_broadcasting::input2_data;
+      _reference_output_data = div_int64_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = div_int64_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = div_int64_no_broadcasting::input1_data;
+      _input2_data = div_int64_no_broadcasting::input2_data;
+      _reference_output_data = div_int64_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = div_int64_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataInt64Div() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_DIV_KERNEL_INT_H
diff --git a/onert-micro/onert-micro/include/test_models/div/NegDivKernel.h b/onert-micro/onert-micro/include/test_models/div/NegDivKernel.h
new file mode 100644 (file)
index 0000000..7170d56
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_DIV_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_DIV_KERNEL_H
+
+#include "TestDataDivBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace input_1_wrong_type_div
+{
+
+/*
+ * 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_div
+
+namespace input_2_wrong_type_div
+{
+
+/*
+ * 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_div
+
+class NegTestDataInput1WrongTypeDiv : public NegTestDataBase
+{
+public:
+  NegTestDataInput1WrongTypeDiv()
+  {
+    _test_kernel_model_circle = input_1_wrong_type_div::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_div::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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_DIV_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/div/TestDataDivBase.h b/onert-micro/onert-micro/include/test_models/div/TestDataDivBase.h
new file mode 100644 (file)
index 0000000..785a37d
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_DIV_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_DIV_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_DIV_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/equal/FloatEqualKernel.h b/onert-micro/onert-micro/include/test_models/equal/FloatEqualKernel.h
new file mode 100644 (file)
index 0000000..98c3cb8
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_EQUAL_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_EQUAL_KERNEL_FLOAT_H
+
+#include "TestDataEqualBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_EQUAL_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/equal/IntEqualKernel.h b/onert-micro/onert-micro/include/test_models/equal/IntEqualKernel.h
new file mode 100644 (file)
index 0000000..4c1b078
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_EQUAL_KERNEL_INT_H
+#define ONERT_MICRO_TEST_MODELS_EQUAL_KERNEL_INT_H
+
+#include "TestDataEqualBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_EQUAL_KERNEL_INT_H
diff --git a/onert-micro/onert-micro/include/test_models/equal/TestDataEqualBase.h b/onert-micro/onert-micro/include/test_models/equal/TestDataEqualBase.h
new file mode 100644 (file)
index 0000000..9d2f173
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_EQUAL_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_EQUAL_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_EQUAL_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/exp/FloatExpKernel.h b/onert-micro/onert-micro/include/test_models/exp/FloatExpKernel.h
new file mode 100644 (file)
index 0000000..aad4d31
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_EXP_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_EXP_KERNEL_H
+
+#include "TestDataExpBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_EXP_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/exp/NegExpKernel.h b/onert-micro/onert-micro/include/test_models/exp/NegExpKernel.h
new file mode 100644 (file)
index 0000000..df2b769
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_EXP_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_EXP_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_EXP_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/exp/TestDataExpBase.h b/onert-micro/onert-micro/include/test_models/exp/TestDataExpBase.h
new file mode 100644 (file)
index 0000000..e3677fa
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_EXP_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_EXP_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_EXP_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/expand_dims/ExpandDimsKernel.h b/onert-micro/onert-micro/include/test_models/expand_dims/ExpandDimsKernel.h
new file mode 100644 (file)
index 0000000..f523651
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_EXPAND_DIMS_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_EXPAND_DIMS_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_EXPAND_DIMS_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/floor/FloatFloorKernel.h b/onert-micro/onert-micro/include/test_models/floor/FloatFloorKernel.h
new file mode 100644 (file)
index 0000000..78e5e60
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_FLOOR_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_FLOOR_KERNEL_H
+
+#include "TestDataFloorBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+namespace floor_float
+{
+/*
+ * Floor Kernel:
+ *
+ *        Input(2, 3)
+ *            |
+ *          Floor
+ *            |
+ *        Output(2, 3)
+ */
+unsigned char test_kernel_model_circle[] = {
+  0x1c, 0x00, 0x00, 0x00, 0x43, 0x49, 0x52, 0x30, 0x00, 0x00, 0x12, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00,
+  0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6e, 0x6e, 0x70, 0x61,
+  0x63, 0x6b, 0x61, 0x67, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x64, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xd8, 0xff, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00, 0xbc, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0xf0, 0xff, 0xff, 0xff,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+  0x04, 0x00, 0x00, 0x00};
+
+const std::vector<float> input_data = {7.297842,   30.999863, 15.692827,
+                                       -18.824865, 22.614136, 5.7466774};
+
+const std::vector<float> reference_output_data = {7, 30, 15, -19, 22, 5};
+
+} // namespace floor_float
+
+class TestDataFloatFloor : public TestDataFloorBase<float>
+{
+public:
+  TestDataFloatFloor()
+  {
+    _input_data = floor_float::input_data;
+    _reference_output_data = floor_float::reference_output_data;
+    _test_kernel_model_circle = floor_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatFloor() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_FLOOR_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/floor/NegFloorKernel.h b/onert-micro/onert-micro/include/test_models/floor/NegFloorKernel.h
new file mode 100644 (file)
index 0000000..ac9ec37
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_FLOOR_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_FLOOR_KERNEL_H
+
+#include "TestDataFloorBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_floor_kernel
+{
+/*
+ * Floor Kernel with input output type mismatch (should be equal):
+ *
+ *      Input(2, 3) - Uint8
+ *            |
+ *           Floor
+ *            |
+ *      Output(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,
+  0x2c, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x80, 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, 0x48, 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, 0x02, 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, 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, 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, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x02, 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,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 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_floor_kernel
+
+namespace neg_invalid_input_output_shape_floor_kernel
+{
+/*
+ * Floor Kernel with different input output shapes:
+ *
+ *      Input(1, 2, 3)
+ *            |
+ *           Floor
+ *            |
+ *      Output(2, 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, 0x08, 0x01, 0x00, 0x00, 0x24, 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, 0x38, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xdc, 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,
+  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,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 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, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 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_output_shape_floor_kernel
+
+class NegTestDataInputOutputTypeMismatchFloorKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchFloorKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_floor_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchFloorKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputOutputShapeFloorKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInvalidInputOutputShapeFloorKernel()
+  {
+    _test_kernel_model_circle =
+      neg_invalid_input_output_shape_floor_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInvalidInputOutputShapeFloorKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_FLOOR_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/floor/TestDataFloorBase.h b/onert-micro/onert-micro/include/test_models/floor/TestDataFloorBase.h
new file mode 100644 (file)
index 0000000..a10d060
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOOR_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_FLOOR_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataFloorBase : public TestDataBase<T>
+{
+public:
+  TestDataFloorBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOOR_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/floordiv/FloatFloorDivKernel.h b/onert-micro/onert-micro/include/test_models/floordiv/FloatFloorDivKernel.h
new file mode 100644 (file)
index 0000000..144300a
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_FLOORDIV_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_FLOORDIV_KERNEL_H
+
+#include "TestDataFloorDivBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace floordiv_float_with_broadcasting
+{
+
+/*
+ * FloorDiv Kernel:
+ *
+ * Input_1(2, 5)   Input_2(2, 1)
+ *       \             /
+ *     FloorDiv(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, 0x41, 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,
+  0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 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 = {-5, -3, -9, 4, 6, -2, 0, 0, -2, 1};
+
+} // namespace floordiv_float_with_broadcasting
+
+namespace floordiv_float_no_broadcasting
+{
+/*
+ * FloorDiv Kernel:
+ *
+ * Input_1(2, 3)   Input_2(2, 3)
+ *              \             /
+ *          FloorDiv(no broadcast)
+ *                     |
+ *            Output(2, 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, 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, 0x41, 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, 0x03, 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,
+  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, 0x02, 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,
+  0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 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};
+std::vector<float> input2_data = {-0.62832826, 7.937863,   -14.899745,
+                                  0.2819096,   -5.8306913, 8.6010685};
+std::vector<float> reference_output_data = {-6, 1, -1, 39, -1, 1};
+
+} // namespace floordiv_float_no_broadcasting
+
+class TestDataFloatFloorDiv : public TestDataFloorDivBase<float>
+{
+public:
+  explicit TestDataFloatFloorDiv(bool is_with_broadcast)
+    : TestDataFloorDivBase<float>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = floordiv_float_with_broadcasting::input1_data;
+      _input2_data = floordiv_float_with_broadcasting::input2_data;
+      _reference_output_data = floordiv_float_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = floordiv_float_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = floordiv_float_no_broadcasting::input1_data;
+      _input2_data = floordiv_float_no_broadcasting::input2_data;
+      _reference_output_data = floordiv_float_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = floordiv_float_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataFloatFloorDiv() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_FLOORDIV_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/floordiv/NegFloorDivKernel.h b/onert-micro/onert-micro/include/test_models/floordiv/NegFloorDivKernel.h
new file mode 100644 (file)
index 0000000..b43b01d
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_NEG_FLOORDIV_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_NEG_FLOORDIV_KERNEL_H
+
+#include "TestDataFloorDivBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+namespace input_1_wrong_type
+{
+
+/*
+ * FloorDiv Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Int32   Input_2(2, 1) - Float
+ *               \             /
+ *           FloorDiv(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, 0x41, 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,
+  0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 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
+{
+
+/*
+ * FloorDiv Kernel with input2 type mismatch:
+ *
+ * Input_1(2, 5)- Float   Input_2(2, 1) - Int32
+ *       \             /
+ *     FloorDiv(with broadcast)
+ *              |
+ *          Output(2, 5) - 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, 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, 0x41, 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,
+  0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 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 NegTestDataInput1WrongTypeFloorDiv : public NegTestDataBase
+{
+public:
+  NegTestDataInput1WrongTypeFloorDiv()
+  {
+    _test_kernel_model_circle = input_1_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput1WrongTypeFloorDiv() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInput2WrongTypeFloorDiv : public NegTestDataBase
+{
+public:
+  NegTestDataInput2WrongTypeFloorDiv()
+  {
+    _test_kernel_model_circle = input_2_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput2WrongTypeFloorDiv() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_NEG_FLOORDIV_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/floordiv/TestDataFloorDivBase.h b/onert-micro/onert-micro/include/test_models/floordiv/TestDataFloorDivBase.h
new file mode 100644 (file)
index 0000000..3ef650e
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOORDIV_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_FLOORDIV_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataFloorDivBase : public TestDataBase<T>
+{
+public:
+  explicit TestDataFloorDivBase(bool)
+  {
+    // Do nothing
+  }
+
+  TestDataFloorDivBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOORDIV_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/floormod/FloatFloorModKernel.h b/onert-micro/onert-micro/include/test_models/floormod/FloatFloorModKernel.h
new file mode 100644 (file)
index 0000000..eb4fa87
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOORMOD_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_FLOORMOD_KERNEL_FLOAT_H
+
+#include "TestDataFloorModBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace floormod_float_with_broadcasting
+{
+
+/*
+ * FloorMod Kernel:
+ *
+ * Input_1(2, 5)   Input_2(2, 1)
+ *       \             /
+ *     FloorMod(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, 0x48, 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,
+  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 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 = {-1.7485305, -0.6419221, -1.4687741, -1.8597124,
+                                                  -1.9120156, -6.361024,  -7.5779333, -1.1460792,
+                                                  -3.481703,  -3.142033};
+
+} // namespace floormod_float_with_broadcasting
+
+namespace floormod_float_no_broadcasting
+{
+/*
+ * FloorMod Kernel:
+ *
+ * Input_1(2, 3)   Input_2(2, 3)
+ *              \             /
+ *          FloorMod(no broadcast)
+ *                     |
+ *            Output(2, 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, 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, 0x48, 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, 0x03, 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,
+  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, 0x02, 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,
+  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 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};
+std::vector<float> input2_data = {-0.62832826, 7.937863,   -14.899745,
+                                  0.2819096,   -5.8306913, 8.6010685};
+std::vector<float> reference_output_data = {-0.20693356, 5.707271,   -14.472599,
+                                            0.0384486,   -5.4117867, 7.1362065};
+
+} // namespace floormod_float_no_broadcasting
+
+class TestDataFloatFloorMod : public TestDataFloorModBase<float>
+{
+public:
+  explicit TestDataFloatFloorMod(bool is_with_broadcast)
+    : TestDataFloorModBase<float>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = floormod_float_with_broadcasting::input1_data;
+      _input2_data = floormod_float_with_broadcasting::input2_data;
+      _reference_output_data = floormod_float_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = floormod_float_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = floormod_float_no_broadcasting::input1_data;
+      _input2_data = floormod_float_no_broadcasting::input2_data;
+      _reference_output_data = floormod_float_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = floormod_float_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataFloatFloorMod() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOORMOD_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/floormod/NegFloorModKernel.h b/onert-micro/onert-micro/include/test_models/floormod/NegFloorModKernel.h
new file mode 100644 (file)
index 0000000..63d5409
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_FLOORMOD_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_FLOORMOD_KERNEL_H
+
+#include "TestDataFloorModBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+namespace input_1_wrong_type
+{
+
+/*
+ * FloorMod Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Int32   Input_2(2, 1) - Float
+ *               \             /
+ *           FloorMod(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, 0x48, 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,
+  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 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
+{
+
+/*
+ * FloorMod Kernel with input2  type mismatch:
+ *
+ * Input_1(2, 5)- Float   Input_2(2, 1) - Int32
+ *       \             /
+ *     FloorMod(with broadcast)
+ *              |
+ *          Output(2, 5) - 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, 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, 0x48, 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, 0x02, 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,
+  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 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 NegTestDataInput1WrongTypeFloorMod : public NegTestDataBase
+{
+public:
+  NegTestDataInput1WrongTypeFloorMod()
+  {
+    _test_kernel_model_circle = input_1_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput1WrongTypeFloorMod() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInput2WrongTypeFloorMod : public NegTestDataBase
+{
+public:
+  NegTestDataInput2WrongTypeFloorMod()
+  {
+    _test_kernel_model_circle = input_2_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput2WrongTypeFloorMod() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_FLOORMOD_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/floormod/TestDataFloorModBase.h b/onert-micro/onert-micro/include/test_models/floormod/TestDataFloorModBase.h
new file mode 100644 (file)
index 0000000..9711a69
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOORMOD_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_FLOORMOD_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataFloorModBase : public TestDataBase<T>
+{
+public:
+  explicit TestDataFloorModBase(bool)
+  {
+    // Do nothing
+  }
+
+  TestDataFloorModBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOORMOD_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/fully_connected/FloatFullyConnectedKernel.h b/onert-micro/onert-micro/include/test_models/fully_connected/FloatFullyConnectedKernel.h
new file mode 100644 (file)
index 0000000..00442fa
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FULLY_CONNECTED_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_FULLY_CONNECTED_KERNEL_FLOAT_H
+
+#include "TestDataFullyConnectedBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FULLY_CONNECTED_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/fully_connected/NegFullyConnectedKernel.h b/onert-micro/onert-micro/include/test_models/fully_connected/NegFullyConnectedKernel.h
new file mode 100644 (file)
index 0000000..aa2465b
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_FULLY_CONNECTED_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_FULLY_CONNECTED_KERNEL_H
+
+#include "TestDataFullyConnectedBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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
+
+namespace neg_fully_connected_no_zero_points
+{
+/*
+ * FullyConnected Kernel with quantize type and without zero points
+ *
+ * Input(1, 64)-Int16   Weight(8, 64) - Int16
+ *            \           |
+ *             \          |
+ *               FullyConnected --- Bias (8) - Int32
+ *                     |
+ *                Output(1, 8) - 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,
+  0x70, 0x04, 0x00, 0x00, 0x80, 0x06, 0x00, 0x00, 0x9c, 0x06, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x5c, 0x04, 0x00, 0x00, 0x54, 0x04, 0x00, 0x00, 0x4c, 0x04, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xd2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff,
+  0xf9, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0xfc, 0xff, 0xfa, 0xff, 0x03, 0x00, 0xff, 0xff,
+  0x03, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x02, 0x00, 0xfc, 0xff, 0x08, 0x00,
+  0xfd, 0xff, 0x05, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xfc, 0xff, 0xfb, 0xff, 0x04, 0x00, 0xfa, 0xff,
+  0xf8, 0xff, 0x01, 0x00, 0xfc, 0xff, 0xfb, 0xff, 0x00, 0x00, 0xfb, 0xff, 0x01, 0x00, 0x04, 0x00,
+  0x04, 0x00, 0xfd, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xfe, 0xff, 0x01, 0x00, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfd, 0xff, 0x04, 0x00, 0xf6, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0x05, 0x00,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xfd, 0xff, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00,
+  0xfd, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0xfb, 0xff, 0x04, 0x00,
+  0xfd, 0xff, 0x02, 0x00, 0x05, 0x00, 0x04, 0x00, 0xfd, 0xff, 0x04, 0x00, 0xfa, 0xff, 0x03, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xfb, 0xff, 0x08, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0xf8, 0xff, 0x05, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x03, 0x00, 0xf7, 0xff,
+  0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0xfb, 0xff, 0xff, 0xff,
+  0x00, 0x00, 0x04, 0x00, 0xf9, 0xff, 0xfb, 0xff, 0xfd, 0xff, 0xf5, 0xff, 0x07, 0x00, 0x04, 0x00,
+  0x01, 0x00, 0xf6, 0xff, 0xfa, 0xff, 0x02, 0x00, 0x07, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
+  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0xff, 0xff, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00,
+  0x05, 0x00, 0x07, 0x00, 0xf7, 0xff, 0x09, 0x00, 0x00, 0x00, 0xfd, 0xff, 0x06, 0x00, 0x05, 0x00,
+  0x00, 0x00, 0xfb, 0xff, 0x01, 0x00, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfd, 0xff, 0x00, 0x00,
+  0x07, 0x00, 0xff, 0xff, 0x00, 0x00, 0x03, 0x00, 0xfd, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf9, 0xff,
+  0x06, 0x00, 0x00, 0x00, 0xfb, 0xff, 0x00, 0x00, 0xff, 0xff, 0xfb, 0xff, 0x04, 0x00, 0xfd, 0xff,
+  0x02, 0x00, 0xfa, 0xff, 0x01, 0x00, 0xf9, 0xff, 0xfa, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf2, 0xff,
+  0xf3, 0xff, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0xff, 0xff, 0xfd, 0xff, 0x04, 0x00, 0x05, 0x00,
+  0x03, 0x00, 0x06, 0x00, 0xfb, 0xff, 0xfc, 0xff, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfe, 0xff,
+  0xfe, 0xff, 0x01, 0x00, 0xf9, 0xff, 0x08, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0xfd, 0xff,
+  0xfe, 0xff, 0xfd, 0xff, 0x03, 0x00, 0xfe, 0xff, 0x02, 0x00, 0xfa, 0xff, 0x04, 0x00, 0x00, 0x00,
+  0xfb, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0x04, 0x00, 0xff, 0xff, 0x02, 0x00, 0x0b, 0x00, 0x01, 0x00,
+  0x07, 0x00, 0xfe, 0xff, 0x06, 0x00, 0xf2, 0xff, 0x02, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00,
+  0xfc, 0xff, 0x0a, 0x00, 0x03, 0x00, 0x02, 0x00, 0xf7, 0xff, 0x00, 0x00, 0xfb, 0xff, 0x01, 0x00,
+  0xfb, 0xff, 0x01, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00,
+  0xfc, 0xff, 0x05, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xf9, 0xff, 0x05, 0x00, 0xff, 0xff,
+  0x07, 0x00, 0xff, 0xff, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xf7, 0xff, 0x01, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 0xf7, 0xff, 0xff, 0xff, 0x04, 0x00, 0x04, 0x00,
+  0x02, 0x00, 0x03, 0x00, 0xfd, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xfd, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xf8, 0xff, 0x05, 0x00, 0xff, 0xff,
+  0xfb, 0xff, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x02, 0x00, 0xfb, 0xff, 0x04, 0x00, 0xff, 0xff,
+  0x00, 0x00, 0xf7, 0xff, 0xf0, 0xff, 0x00, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
+  0x05, 0x00, 0x01, 0x00, 0x04, 0x00, 0xfe, 0xff, 0xfa, 0xff, 0x07, 0x00, 0xfb, 0xff, 0xf6, 0xff,
+  0xff, 0xff, 0x07, 0x00, 0xfd, 0xff, 0x02, 0x00, 0x0b, 0x00, 0x04, 0x00, 0xff, 0xff, 0xfb, 0xff,
+  0x02, 0x00, 0x03, 0x00, 0xfd, 0xff, 0x02, 0x00, 0x0a, 0x00, 0x05, 0x00, 0xff, 0xff, 0x05, 0x00,
+  0x09, 0x00, 0xfc, 0xff, 0xfd, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
+  0xfd, 0xff, 0x03, 0x00, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0xfd, 0xff, 0x01, 0x00, 0xfe, 0xff,
+  0x06, 0x00, 0xff, 0xff, 0x05, 0x00, 0xfe, 0xff, 0xfd, 0xff, 0x03, 0x00, 0x01, 0x00, 0x04, 0x00,
+  0x03, 0x00, 0x0b, 0x00, 0xfa, 0xff, 0xfe, 0xff, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, 0xfd, 0xff,
+  0xfe, 0xff, 0x02, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xfd, 0xff, 0xff, 0xff,
+  0xfc, 0xff, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0xfb, 0xff, 0x02, 0x00, 0x03, 0x00, 0x06, 0x00,
+  0xfc, 0xff, 0xfe, 0xff, 0x01, 0x00, 0x07, 0x00, 0xfc, 0xff, 0xfd, 0xff, 0x02, 0x00, 0x05, 0x00,
+  0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0xfc, 0xff,
+  0x02, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xfd, 0xff, 0x00, 0x00, 0xf5, 0xff,
+  0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00,
+  0xfd, 0xff, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0xfa, 0xff, 0xfd, 0xff, 0x05, 0x00, 0x02, 0x00,
+  0xf9, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0xfd, 0xff, 0xfc, 0xff, 0x07, 0x00, 0x03, 0x00,
+  0xfd, 0xff, 0xfd, 0xff, 0x09, 0x00, 0x00, 0x00, 0xfb, 0xff, 0x02, 0x00, 0x02, 0x00, 0x07, 0x00,
+  0xfb, 0xff, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, 0x03, 0x00, 0x06, 0x00, 0xff, 0xff,
+  0x00, 0x00, 0xff, 0xff, 0xfc, 0xff, 0xfe, 0xff, 0x02, 0x00, 0x03, 0x00, 0xf6, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0xfd, 0xff, 0x04, 0x00, 0xfe, 0xff, 0xfd, 0xff, 0x03, 0x00, 0xff, 0xff, 0x05, 0x00,
+  0x00, 0x00, 0xfe, 0xff, 0xfd, 0xff, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00,
+  0x05, 0x00, 0x07, 0x00, 0xf4, 0xff, 0x0a, 0x00, 0x06, 0x00, 0x07, 0x00, 0x02, 0x00, 0x03, 0x00,
+  0xfd, 0xff, 0x08, 0x00, 0xfb, 0xff, 0x04, 0x00, 0x07, 0x00, 0x0a, 0x00, 0xfb, 0xff, 0x03, 0x00,
+  0x04, 0x00, 0x04, 0x00, 0xfe, 0xff, 0x02, 0x00, 0x00, 0x00, 0xf7, 0xff, 0x02, 0x00, 0x01, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0xfd, 0xff, 0x04, 0x00, 0xfd, 0xff, 0x00, 0x00,
+  0xfb, 0xff, 0xf7, 0xff, 0xfa, 0xff, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x05, 0x00,
+  0xfe, 0xff, 0xfb, 0xff, 0xf8, 0xff, 0x0b, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00,
+  0x01, 0x00, 0x09, 0x00, 0x0c, 0x00, 0x05, 0x00, 0x01, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0x01, 0x00, 0x07, 0x00, 0x04, 0x00, 0x07, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xfb, 0xff,
+  0xfb, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0xff, 0xff,
+  0x00, 0x00, 0x04, 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, 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, 0x10, 0x01, 0x00, 0x00,
+  0x9c, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0e, 0xff, 0xff, 0xff,
+  0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x3c, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xb8, 0x19, 0x85, 0x39, 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, 0x08, 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, 0x08, 0x00, 0x00, 0x00, 0x9e, 0xff, 0xff, 0xff,
+  0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x40, 0x00, 0x00, 0x00, 0x90, 0xff, 0xff, 0xff, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xdd, 0x58, 0xa4, 0x3a, 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, 0x08, 0x00, 0x00, 0x00, 0x40, 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, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x48, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7e, 0x87, 0xb9, 0x39,
+  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,
+  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_no_zero_points
+
+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;
+};
+
+class NegTestDataNoZeroPointsFullyConnectedKernel : public NegTestDataBase
+{
+public:
+  NegTestDataNoZeroPointsFullyConnectedKernel()
+  {
+    _test_kernel_model_circle = neg_fully_connected_no_zero_points::test_kernel_model_circle;
+  }
+
+  ~NegTestDataNoZeroPointsFullyConnectedKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_FULLY_CONNECTED_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/fully_connected/QuantFullyConnectedKernel.h b/onert-micro/onert-micro/include/test_models/fully_connected/QuantFullyConnectedKernel.h
new file mode 100644 (file)
index 0000000..043aae4
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_QUANT_FULLY_CONNECTED_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_QUANT_FULLY_CONNECTED_KERNEL_H
+
+#include "TestDataFullyConnectedBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace s8_fully_connected
+{
+
+/*
+ * S8 FullyConnected Kernel:
+ *
+ * Input(1, 64)   Weight(8, 64)
+ *            \        |
+ *             \       |
+ *               FullyConnected
+ *                     |
+ *                Output(1, 8)
+ */
+
+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, 0x40, 0x02, 0x00, 0x00, 0x38, 0x04, 0x00, 0x00, 0x54, 0x04, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, 0x00, 0x1c, 0x02, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x14, 0x21, 0x0e, 0x08, 0x13, 0x09, 0x0c, 0x08,
+  0x0a, 0x1d, 0x13, 0x1e, 0x00, 0x09, 0x06, 0x0a, 0x20, 0x06, 0x16, 0x07, 0x26, 0xf8, 0x00, 0x15,
+  0x18, 0x04, 0x0d, 0xff, 0x11, 0x0d, 0x11, 0x04, 0x16, 0x0d, 0x18, 0xec, 0x13, 0x07, 0x07, 0x0b,
+  0xff, 0x10, 0x10, 0x00, 0x06, 0xff, 0x0b, 0x10, 0xfe, 0x06, 0x26, 0x11, 0xfd, 0x03, 0x00, 0x16,
+  0x0f, 0x26, 0x14, 0x13, 0x12, 0x09, 0x00, 0x08, 0x0c, 0x10, 0x06, 0xee, 0x12, 0x01, 0x13, 0x08,
+  0x0e, 0x1b, 0x0a, 0x02, 0x08, 0x0a, 0xff, 0x00, 0x0a, 0x0f, 0x20, 0x00, 0x08, 0x14, 0x08, 0x08,
+  0xff, 0x06, 0x05, 0x04, 0x09, 0x16, 0x1e, 0x1b, 0x10, 0x03, 0x03, 0x19, 0x1c, 0x0f, 0x00, 0x07,
+  0x17, 0x0e, 0x16, 0x01, 0x1a, 0x0b, 0xfd, 0x0c, 0x0a, 0x14, 0x0b, 0x13, 0x11, 0x07, 0xfa, 0xf4,
+  0xf8, 0x0b, 0x11, 0x06, 0x10, 0x12, 0x11, 0x0d, 0xfa, 0x20, 0xfb, 0xf5, 0x12, 0xf7, 0x0e, 0x12,
+  0x0a, 0x15, 0x0e, 0xfd, 0x06, 0x09, 0x18, 0x01, 0x07, 0x0c, 0x04, 0x0a, 0x0e, 0xfc, 0x24, 0xfa,
+  0x08, 0x11, 0x02, 0x08, 0x0d, 0x16, 0x00, 0xf4, 0x22, 0x04, 0x09, 0x15, 0xfa, 0x00, 0xfe, 0x0f,
+  0xfa, 0xfa, 0xf8, 0x06, 0x00, 0x0c, 0x15, 0x19, 0x0b, 0x0a, 0x04, 0x0d, 0x0e, 0x12, 0x07, 0x0f,
+  0x08, 0x04, 0x08, 0x00, 0x0b, 0x02, 0x12, 0x17, 0xfa, 0x06, 0x0d, 0x0a, 0x0f, 0x10, 0x0d, 0x05,
+  0x0d, 0x06, 0xf8, 0x11, 0x0a, 0x09, 0x0a, 0x0a, 0x04, 0x10, 0x11, 0x16, 0x17, 0x02, 0x03, 0x0d,
+  0x0b, 0x1a, 0x06, 0x0e, 0x1c, 0x05, 0x07, 0x1e, 0x0e, 0xf3, 0x0c, 0x1a, 0x20, 0x00, 0x14, 0x01,
+  0x11, 0x04, 0x02, 0x08, 0x0c, 0x09, 0x10, 0x12, 0x18, 0x0d, 0x04, 0x15, 0x0c, 0x0d, 0xfe, 0x16,
+  0x0a, 0x0e, 0x0c, 0xff, 0xf9, 0x15, 0x07, 0x02, 0x11, 0x0d, 0x1b, 0x02, 0x0c, 0x0e, 0x1a, 0x01,
+  0x11, 0x05, 0x0b, 0x02, 0x0a, 0x1f, 0x06, 0x07, 0x02, 0x09, 0x0e, 0xfe, 0x05, 0x06, 0x11, 0x14,
+  0x0e, 0x11, 0x02, 0x06, 0x0c, 0x19, 0x15, 0x0e, 0x09, 0x13, 0x01, 0x0b, 0xfc, 0xfb, 0x0f, 0x13,
+  0xff, 0x03, 0x04, 0x0d, 0xfe, 0x0a, 0x09, 0x15, 0x07, 0x0c, 0xf9, 0x0f, 0x02, 0xfd, 0x10, 0x12,
+  0x09, 0x00, 0x0a, 0x0f, 0x0f, 0x02, 0x04, 0x0f, 0x00, 0x18, 0x00, 0x11, 0x02, 0xfe, 0x13, 0x0a,
+  0x0f, 0x02, 0x14, 0x11, 0x0b, 0x16, 0x07, 0x14, 0x22, 0x1d, 0x0f, 0x18, 0x05, 0x08, 0x04, 0x02,
+  0x0e, 0x07, 0x03, 0x00, 0x00, 0x03, 0x07, 0x18, 0x10, 0x0b, 0x1b, 0x10, 0x07, 0x02, 0x0e, 0x07,
+  0x0d, 0x09, 0x15, 0x1f, 0xf9, 0xfe, 0xfb, 0x15, 0x14, 0x12, 0x17, 0x03, 0x05, 0x04, 0xfe, 0x0b,
+  0x01, 0x00, 0x16, 0x0f, 0x0b, 0x00, 0x0b, 0x26, 0x03, 0x1f, 0xfe, 0x0c, 0xff, 0x1f, 0x15, 0xfd,
+  0x02, 0xff, 0x08, 0xfc, 0x03, 0x00, 0x0f, 0x06, 0x01, 0x01, 0x12, 0x0d, 0x12, 0x0a, 0xfd, 0x03,
+  0xfd, 0x0b, 0x06, 0x1d, 0x14, 0x02, 0x04, 0x10, 0x0f, 0x00, 0x04, 0x04, 0x17, 0x15, 0x1c, 0x0a,
+  0x0e, 0x12, 0x12, 0x04, 0x01, 0x02, 0x0f, 0x11, 0xf8, 0xfa, 0x05, 0x07, 0x12, 0x06, 0xfc, 0x0a,
+  0x1a, 0x14, 0x06, 0x13, 0x0e, 0x18, 0x03, 0x0c, 0xfd, 0x1c, 0x09, 0x12, 0x04, 0xfe, 0x0d, 0xfb,
+  0x05, 0x02, 0x1b, 0x02, 0x06, 0x0e, 0x10, 0x10, 0x0a, 0x00, 0x00, 0x11, 0x0e, 0x16, 0x0c, 0x0c,
+  0x02, 0x01, 0x05, 0x05, 0x0b, 0xf3, 0x14, 0x0f, 0x0f, 0x0e, 0x14, 0x08, 0x01, 0xef, 0x11, 0x13,
+  0xff, 0x02, 0x01, 0x07, 0x0b, 0x19, 0x12, 0x04, 0xf5, 0x10, 0x18, 0xff, 0x08, 0x03, 0x03, 0x14,
+  0x01, 0x0a, 0xfb, 0x0d, 0x0e, 0x03, 0x10, 0x06, 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, 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, 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, 0xf0, 0x00, 0x00, 0x00,
+  0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x48, 0x00, 0x00, 0x00,
+  0x1c, 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, 0xc0, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x03, 0x00, 0x00, 0x00,
+  0x6f, 0x75, 0x74, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x09, 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,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xd4, 0x59, 0x81, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xc1, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x20, 0x41, 0x06, 0x00, 0x00, 0x00, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 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, 0x09,
+  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, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x20, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xc1, 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};
+
+const std::vector<int8_t> input_data = {-5, 0, -5, 4, -3, 4,  5, 2,  -3, -1, 5,  0, -4, -1, 2,  5,
+                                        0,  0, -5, 0, -4, 2,  2, -2, -1, 5,  -2, 3, 4,  4,  -1, 3,
+                                        0,  5, -2, 3, -3, -5, 1, 3,  2,  5,  -5, 0, -3, 3,  -3, 0,
+                                        -3, 2, 0,  4, -1, -3, 1, 5,  -5, 2,  -5, 2, -5, -2, -4, 5};
+
+const std::vector<int8_t> reference_output_data = {-128, -128, 127, 96, 127, 127, 127, 127};
+
+} // namespace s8_fully_connected
+
+namespace s16_fully_connected
+{
+
+/*
+ * S16 FullyConnected Kernel:
+ *
+ * Input(1, 64)-Int16   Weight(8, 64) - Int16
+ *            \           |
+ *             \          |
+ *               FullyConnected --- Bias (8) - Int32
+ *                     |
+ *                Output(1, 8) - Int16
+ */
+
+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, 0x04, 0x00, 0x00, 0xa0, 0x06, 0x00, 0x00, 0xbc, 0x06, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x5c, 0x04, 0x00, 0x00, 0x54, 0x04, 0x00, 0x00, 0x4c, 0x04, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xfe, 0xff, 0x02, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0xfe, 0xff, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0xfb, 0xff, 0xf7, 0xff, 0x02, 0x00, 0xf9, 0xff,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x06, 0x00, 0x01, 0x00, 0xf7, 0xff,
+  0x06, 0x00, 0x04, 0x00, 0x06, 0x00, 0xfe, 0xff, 0x05, 0x00, 0xfa, 0xff, 0xfd, 0xff, 0xff, 0xff,
+  0xfd, 0xff, 0xfc, 0xff, 0xfe, 0xff, 0x03, 0x00, 0xfa, 0xff, 0x0a, 0x00, 0xfe, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0xfa, 0xff, 0x00, 0x00, 0xfd, 0xff, 0x01, 0x00, 0x02, 0x00, 0x0f, 0x00, 0xff, 0xff,
+  0xfd, 0xff, 0x03, 0x00, 0x09, 0x00, 0xfe, 0xff, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x03, 0x00, 0xf6, 0xff, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00,
+  0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0xfa, 0xff, 0x04, 0x00, 0x05, 0x00, 0xfe, 0xff,
+  0x01, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x08, 0x00,
+  0xfa, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xf9, 0xff, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00,
+  0x02, 0x00, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0xfd, 0xff, 0xfd, 0xff, 0xf9, 0xff, 0x01, 0x00,
+  0x04, 0x00, 0x03, 0x00, 0xf4, 0xff, 0xff, 0xff, 0x05, 0x00, 0xf9, 0xff, 0x01, 0x00, 0x01, 0x00,
+  0x09, 0x00, 0xf8, 0xff, 0x00, 0x00, 0xf8, 0xff, 0x04, 0x00, 0xf8, 0xff, 0x08, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0xf8, 0xff,
+  0x01, 0x00, 0x01, 0x00, 0xf5, 0xff, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0xff, 0xff, 0x02, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xf6, 0xff, 0x05, 0x00, 0xfd, 0xff, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x01, 0x00, 0xfd, 0xff, 0xff, 0xff, 0x02, 0x00,
+  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xfb, 0xff, 0xfc, 0xff, 0x00, 0x00, 0xfa, 0xff, 0xfd, 0xff,
+  0x00, 0x00, 0x02, 0x00, 0xfa, 0xff, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff,
+  0xfe, 0xff, 0x02, 0x00, 0xf8, 0xff, 0x04, 0x00, 0xf9, 0xff, 0x08, 0x00, 0x02, 0x00, 0x05, 0x00,
+  0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xff, 0x06, 0x00, 0x02, 0x00,
+  0x08, 0x00, 0x0a, 0x00, 0x05, 0x00, 0xfd, 0xff, 0xfd, 0xff, 0xfe, 0xff, 0x02, 0x00, 0xfe, 0xff,
+  0xfc, 0xff, 0xfc, 0xff, 0xfa, 0xff, 0x05, 0x00, 0x01, 0x00, 0x04, 0x00, 0xfc, 0xff, 0xfd, 0xff,
+  0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x06, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x01, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0xfb, 0xff, 0x01, 0x00, 0xfa, 0xff, 0x00, 0x00, 0xfb, 0xff, 0x03, 0x00,
+  0x05, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xfd, 0xff, 0x02, 0x00, 0xfe, 0xff,
+  0xfd, 0xff, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0xfa, 0xff, 0xfd, 0xff, 0x03, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xfe, 0xff, 0xfa, 0xff, 0x01, 0x00,
+  0xf8, 0xff, 0xf8, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0xfa, 0xff, 0x05, 0x00, 0x04, 0x00,
+  0x03, 0x00, 0xfa, 0xff, 0x05, 0x00, 0xfb, 0xff, 0x07, 0x00, 0xfc, 0xff, 0xfd, 0xff, 0x05, 0x00,
+  0x00, 0x00, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xfc, 0xff, 0x05, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x05, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xfe, 0xff, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00,
+  0xfd, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0xfb, 0xff, 0xfc, 0xff,
+  0xfe, 0xff, 0x01, 0x00, 0xfd, 0xff, 0xfe, 0xff, 0x04, 0x00, 0x06, 0x00, 0x04, 0x00, 0xfd, 0xff,
+  0x02, 0x00, 0x01, 0x00, 0xff, 0xff, 0x02, 0x00, 0xf9, 0xff, 0x03, 0x00, 0x04, 0x00, 0xff, 0xff,
+  0x00, 0x00, 0xfd, 0xff, 0x01, 0x00, 0xfd, 0xff, 0x02, 0x00, 0x0a, 0x00, 0xfa, 0xff, 0x03, 0x00,
+  0xfe, 0xff, 0xfd, 0xff, 0xf5, 0xff, 0x04, 0x00, 0x07, 0x00, 0xfc, 0xff, 0x0b, 0x00, 0x05, 0x00,
+  0xff, 0xff, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0xff, 0xff, 0x0c, 0x00, 0xfc, 0xff,
+  0xfc, 0xff, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xfe, 0xff,
+  0x04, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
+  0xfe, 0xff, 0x00, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0xf4, 0xff,
+  0xfe, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xfa, 0xff, 0xfb, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x01, 0x00, 0xfe, 0xff, 0xf7, 0xff, 0xfc, 0xff,
+  0xff, 0xff, 0x00, 0x00, 0xf9, 0xff, 0xfa, 0xff, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00, 0xfe, 0xff,
+  0x02, 0x00, 0xfa, 0xff, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0xfe, 0xff, 0xf8, 0xff,
+  0x01, 0x00, 0xff, 0xff, 0xf9, 0xff, 0x03, 0x00, 0x0c, 0x00, 0x01, 0x00, 0xfe, 0xff, 0x03, 0x00,
+  0xff, 0xff, 0xfe, 0xff, 0xfc, 0xff, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x04, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0xfd, 0xff, 0x02, 0x00,
+  0xfe, 0xff, 0x0a, 0x00, 0x01, 0x00, 0xff, 0xff, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0xfb, 0xff,
+  0x03, 0x00, 0x02, 0x00, 0x06, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x02, 0x00,
+  0xff, 0xff, 0x06, 0x00, 0xfc, 0xff, 0xfc, 0xff, 0x04, 0x00, 0x00, 0x00, 0xfa, 0xff, 0x06, 0x00,
+  0xfe, 0xff, 0xfd, 0xff, 0x09, 0x00, 0x01, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x03, 0x00, 0xfd, 0xff, 0x00, 0x00, 0xfb, 0xff, 0x03, 0x00, 0xff, 0xff, 0x03, 0x00,
+  0x00, 0x00, 0xfe, 0xff, 0xfa, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+  0xf9, 0xff, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff, 0xfd, 0xff, 0x01, 0x00, 0xfc, 0xff,
+  0x06, 0x00, 0xf8, 0xff, 0x00, 0x00, 0xf7, 0xff, 0xff, 0xff, 0xfa, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0xff, 0x06, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xf9, 0xff, 0xfa, 0xff, 0xf9, 0xff, 0xfe, 0xff,
+  0xff, 0xff, 0xfc, 0xff, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
+  0x03, 0x00, 0x0a, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf5, 0xff, 0x05, 0x00,
+  0xfd, 0xff, 0xfe, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xfd, 0xff, 0x02, 0x00, 0x01, 0x00,
+  0xff, 0xff, 0x01, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfa, 0xff, 0xfe, 0xff,
+  0x02, 0x00, 0x03, 0x00, 0xfd, 0xff, 0x05, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xf7, 0xff, 0xff, 0xff,
+  0xfb, 0xff, 0xf8, 0xff, 0xfe, 0xff, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0xff, 0xff,
+  0xf5, 0xff, 0xf8, 0xff, 0xfc, 0xff, 0x02, 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, 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, 0x07, 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,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x19, 0x85, 0x39,
+  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,
+  0x08, 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, 0x08, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xdd, 0x58, 0xa4, 0x3a, 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, 0x08, 0x00, 0x00, 0x00,
+  0x40, 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, 0x07, 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,
+  0x7e, 0x87, 0xb9, 0x39, 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, 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};
+
+const std::vector<int16_t> input_data = {
+  -39, 0,   107, -69, 99,  27,  80,  52,  -5,  29,  38,  23,  -123, -46,  -40,  -89,
+  -32, -89, -30, 79,  60,  49,  51,  70,  -82, 78,  14,  2,   -86,  -115, -121, 32,
+  97,  56,  55,  -98, 40,  111, -12, 27,  15,  -7,  39,  87,  -67,  -25,  86,   30,
+  17,  25,  -73, 108, -93, -78, 41,  106, 117, -74, -79, -31, 0,    -98,  56,   -81};
+
+const std::vector<int16_t> reference_output_data = {2, 3, 10, 2, 3, 4, 1, -2};
+
+} // namespace s16_fully_connected
+
+class TestDataS8FullyConnected : public TestDataFullyConnectedBase<int8_t>
+{
+public:
+  TestDataS8FullyConnected()
+  {
+    _input_data = s8_fully_connected::input_data;
+    _reference_output_data = s8_fully_connected::reference_output_data;
+    _test_kernel_model_circle = s8_fully_connected::test_kernel_model_circle;
+  }
+
+  ~TestDataS8FullyConnected() override = default;
+};
+
+class TestDataS16FullyConnected : public TestDataFullyConnectedBase<int16_t>
+{
+public:
+  TestDataS16FullyConnected()
+  {
+    _input_data = s16_fully_connected::input_data;
+    _reference_output_data = s16_fully_connected::reference_output_data;
+    _test_kernel_model_circle = s16_fully_connected::test_kernel_model_circle;
+  }
+
+  ~TestDataS16FullyConnected() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_QUANT_FULLY_CONNECTED_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/fully_connected/TestDataFullyConnectedBase.h b/onert-micro/onert-micro/include/test_models/fully_connected/TestDataFullyConnectedBase.h
new file mode 100644 (file)
index 0000000..86ae1e5
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FULLY_CONNECTED_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_FULLY_CONNECTED_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FULLY_CONNECTED_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/gather/FloatGatherKernel.h b/onert-micro/onert-micro/include/test_models/gather/FloatGatherKernel.h
new file mode 100644 (file)
index 0000000..ac205d2
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_GATHER_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_GATHER_KERNEL_H
+
+#include "TestDataGatherBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_GATHER_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/gather/IntGatherKernel.h b/onert-micro/onert-micro/include/test_models/gather/IntGatherKernel.h
new file mode 100644 (file)
index 0000000..34a213c
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_GATHER_INT_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_GATHER_INT_KERNEL_H
+
+#include "TestDataGatherBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_GATHER_INT_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/gather/NegGatherKernel.h b/onert-micro/onert-micro/include/test_models/gather/NegGatherKernel.h
new file mode 100644 (file)
index 0000000..a240cdf
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_GATHER_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_GATHER_KERNEL_H
+
+#include "TestDataGatherBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_GATHER_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/gather/TestDataGatherBase.h b/onert-micro/onert-micro/include/test_models/gather/TestDataGatherBase.h
new file mode 100644 (file)
index 0000000..202b4fe
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_GATHER_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_GATHER_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_GATHER_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/gather_nd/FloatGatherNDKernel.h b/onert-micro/onert-micro/include/test_models/gather_nd/FloatGatherNDKernel.h
new file mode 100644 (file)
index 0000000..3aca113
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_GATHER_ND_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_GATHER_ND_KERNEL_H
+
+#include "TestDataGatherNDBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+namespace gather_nd_float
+{
+/*
+ * GatherND Kernel:
+ *
+ *      Input(1, 4, 4, 3)
+ *            |
+ *           GatherND
+ *            |
+ *      Output(1, 2, 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,
+  0x50, 0x00, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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, 0x53, 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, 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,
+  0x02, 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, 0x69, 0x6e, 0x64, 0x69,
+  0x63, 0x65, 0x73, 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, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x70, 0x61, 0x72, 0x61, 0x6d, 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,
+  0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 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 = {-63.555645, 32.902435,  -61.76536, 28.280264,
+                                       66.80893,   -13.163652, -66.06793, -15.827837};
+const std::vector<float> reference_output_data = {-61.76536, 28.280264, 66.80893, -13.163652};
+
+} // namespace gather_nd_float
+
+class TestDataFloatGatherND : public TestDataGatherNDBase<float>
+{
+public:
+  TestDataFloatGatherND()
+  {
+    _input_data = gather_nd_float::input_data;
+    _reference_output_data = gather_nd_float::reference_output_data;
+    _test_kernel_model_circle = gather_nd_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatGatherND() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_GATHER_ND_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/gather_nd/NegGatherNDKernel.h b/onert-micro/onert-micro/include/test_models/gather_nd/NegGatherNDKernel.h
new file mode 100644 (file)
index 0000000..3af55d8
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_NEG_GATHER_ND_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_NEG_GATHER_ND_KERNEL_H
+
+#include "TestDataGatherNDBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_gather_nd_mismatch_input_output_type
+{
+/*
+ * GatherND Kernel with input output type mismatch (should be equal):
+ *
+ * Input(1, 4, 4, 3) - FLOAT32   Indices(1, 2, 1)
+ *       \                 /
+ *           GatherND
+ *                 |
+ *          Output(1, 2, 2, 4) - 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,
+  0x50, 0x00, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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, 0x53, 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, 0x3c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xd8, 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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 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, 0x10, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 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, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 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_nd_mismatch_input_output_type
+
+class NegTestDataInputOutputTypeMismatchGatherNDKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchGatherNDKernel()
+  {
+    _test_kernel_model_circle = neg_gather_nd_mismatch_input_output_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchGatherNDKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_NEG_GATHER_ND_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/gather_nd/TestDataGatherNDBase.h b/onert-micro/onert-micro/include/test_models/gather_nd/TestDataGatherNDBase.h
new file mode 100644 (file)
index 0000000..12ec8ca
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_GATHER_ND_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_GATHER_ND_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataGatherNDBase : public TestDataBase<T>
+{
+public:
+  TestDataGatherNDBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_GATHER_ND_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/greater/FloatGreaterKernel.h b/onert-micro/onert-micro/include/test_models/greater/FloatGreaterKernel.h
new file mode 100644 (file)
index 0000000..e6df16e
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_GREATER_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_GREATER_KERNEL_FLOAT_H
+
+#include "TestDataGreaterBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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
+
+class TestDataFloatGreater : public TestDataGreaterBase<float, bool>
+{
+public:
+  explicit TestDataFloatGreater(bool is_with_broadcast)
+    : TestDataGreaterBase<float, bool>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      assert(false && "Not impl yet");
+    }
+    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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_GREATER_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/greater/NegGreaterKernel.h b/onert-micro/onert-micro/include/test_models/greater/NegGreaterKernel.h
new file mode 100644 (file)
index 0000000..2d6853c
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_GREATER_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_NEG_GREATER_KERNEL_FLOAT_H
+
+#include "TestDataGreaterBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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 NegTestDataFloatGreaterTypeMishmach : public NegTestDataBase
+{
+public:
+  NegTestDataFloatGreaterTypeMishmach()
+  {
+    _test_kernel_model_circle = neg_greater_float_with_no_broadcasting::test_kernel_model_circle;
+  }
+
+  ~NegTestDataFloatGreaterTypeMishmach() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_GREATER_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/greater/TestDataGreaterBase.h b/onert-micro/onert-micro/include/test_models/greater/TestDataGreaterBase.h
new file mode 100644 (file)
index 0000000..9c67470
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_GREATER_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_GREATER_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_GREATER_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/greater_equal/FloatGreaterEqualKernel.h b/onert-micro/onert-micro/include/test_models/greater_equal/FloatGreaterEqualKernel.h
new file mode 100644 (file)
index 0000000..b9e37ca
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_GREATER_EQUAL_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_GREATER_EQUAL_KERNEL_FLOAT_H
+
+#include "TestDataGreaterEqualBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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
+
+class TestDataFloatGreaterEqual : public TestDataGreaterEqualBase<float, bool>
+{
+public:
+  explicit TestDataFloatGreaterEqual(bool is_with_broadcast)
+    : TestDataGreaterEqualBase<float, bool>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      assert(false && "Not impl yet");
+    }
+    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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_GREATER_EQUAL_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/greater_equal/NegGreaterEqualKernel.h b/onert-micro/onert-micro/include/test_models/greater_equal/NegGreaterEqualKernel.h
new file mode 100644 (file)
index 0000000..3be2655
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_GREATER_EQUAL_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_NEG_GREATER_EQUAL_KERNEL_FLOAT_H
+
+#include "TestDataGreaterEqualBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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[] = {
+  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, 0xdc, 0x01, 0x00, 0x00, 0xf8, 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, 0xe4, 0x00, 0x00, 0x00,
+  0x54, 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, 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, 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,
+  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, 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 = {};
+
+const std::vector<float> input2_data = {};
+
+const std::vector<bool> reference_output_data = {};
+
+} // namespace neg_greater_equal_float_with_no_broadcasting
+
+class NegTestDataFloatGreaterEqualTypeMishmach : public NegTestDataBase
+{
+public:
+  NegTestDataFloatGreaterEqualTypeMishmach()
+  {
+    _test_kernel_model_circle =
+      neg_greater_equal_float_with_no_broadcasting::test_kernel_model_circle;
+  }
+
+  ~NegTestDataFloatGreaterEqualTypeMishmach() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_GREATER_EQUAL_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/greater_equal/TestDataGreaterEqualBase.h b/onert-micro/onert-micro/include/test_models/greater_equal/TestDataGreaterEqualBase.h
new file mode 100644 (file)
index 0000000..a80522a
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_GATHER_EQUAL_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_GATHER_EQUAL_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_GATHER_EQUAL_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/l2_normalization/FloatL2NormalizeKernel.h b/onert-micro/onert-micro/include/test_models/l2_normalization/FloatL2NormalizeKernel.h
new file mode 100644 (file)
index 0000000..8999965
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_L2_NORMALIZATION_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_L2_NORMALIZATION_KERNEL_H
+
+#include "TestDataL2NormalizeBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace l2_normalization_float
+{
+/*
+ * L2Normalization Kernel:
+ *
+ *      Input(1, 4, 4, 3)
+ *            |
+ *      L2Normalization
+ *            |
+ *      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,
+  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, 0x0c, 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, 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, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 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.992603,  8.346985,  22.960445, 45.584763, 26.916512, 33.256886, 12.787039, 40.30215,
+  32.26641,  13.645262, 36.445396, 33.06842,  37.449368, 14.05669,  17.87454,  7.8050013,
+  5.6068754, 17.868938, 40.134842, 24.222584, 42.0985,   26.406887, 11.48271,  33.00633,
+  39.676426, 46.740967, 38.20928,  45.924362, 39.70501,  32.05231,  41.742085, 29.257357,
+  42.27183,  35.843292, 28.056007, 31.480331, 34.84266,  34.666496, 26.273453, 33.72813,
+  23.426928, 14.348057, 52.57121,  17.464836, 33.1741,   29.476301, 22.09747,  32.685722};
+
+const std::vector<float> reference_output_data = {
+  0.3785766,  0.31623122, 0.86987215, 0.72914726, 0.4305408,  0.53195775, 0.24041508, 0.75773954,
+  0.60665584, 0.26719585, 0.71365863, 0.64753205, 0.8547623,  0.32083663, 0.40797707, 0.38468635,
+  0.27634698, 0.8807093,  0.63699496, 0.3844456,  0.66816086, 0.6028728,  0.2621518,  0.7535389,
+  0.54921657, 0.6470067,  0.5289077,  0.66895926, 0.5783648,  0.46689144, 0.6303393,  0.4418098,
+  0.6383389,  0.6476525,  0.506944,   0.56881815, 0.6251807,  0.6220198,  0.47142372, 0.77535427,
+  0.53854656, 0.32983825, 0.81417507, 0.2704795,  0.5137703,  0.59851044, 0.44868472, 0.6636771};
+
+} // namespace l2_normalization_float
+
+class TestDataFloatL2Normalization : public TestDataL2NormalizationBase<float>
+{
+public:
+  TestDataFloatL2Normalization()
+  {
+    _input_data = l2_normalization_float::input_data;
+    _reference_output_data = l2_normalization_float::reference_output_data;
+    _test_kernel_model_circle = l2_normalization_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatL2Normalization() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_L2_NORMALIZATION_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/l2_normalization/NegL2NormalizeKernel.h b/onert-micro/onert-micro/include/test_models/l2_normalization/NegL2NormalizeKernel.h
new file mode 100644 (file)
index 0000000..c25b257
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_L2_NORMALIZE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_L2_NORMALIZE_KERNEL_H
+
+#include "TestDataL2NormalizeBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_l2_normalization_kernel
+{
+/*
+ * L2Normalization Kernel with input output type mismatch (should be equal):
+ *
+ *      Input(1, 4, 4, 3) - Float
+ *            |
+ *           L2Normalization
+ *            |
+ *      Output(1, 4, 4, 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,
+  0x28, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x54, 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, 0x0c, 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, 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, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 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_l2_normalization_kernel
+
+class NegTestDataInputOutputTypeMismatchNegKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchNegKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_l2_normalization_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;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_L2_NORMALIZE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/l2_normalization/TestDataL2NormalizeBase.h b/onert-micro/onert-micro/include/test_models/l2_normalization/TestDataL2NormalizeBase.h
new file mode 100644 (file)
index 0000000..4a4a153
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_L2_NORMALIZATION_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_L2_NORMALIZATION_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataL2NormalizationBase : public TestDataBase<T>
+{
+public:
+  TestDataL2NormalizationBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_L2_NORMALIZATION_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/l2pool2d/FloatL2Pool2DKernel.h b/onert-micro/onert-micro/include/test_models/l2pool2d/FloatL2Pool2DKernel.h
new file mode 100644 (file)
index 0000000..120d3bc
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_L2POOL2D_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_L2POOL2D_KERNEL_H
+
+#include "TestDataL2Pool2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace l2pool2d_float
+{
+/*
+ * L2Pool2D Kernel:
+ *
+ *      Input(1, 8, 8, 1)
+ *            |
+ *           L2Pool2D
+ *            |
+ *      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, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 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 = {
+  67.38262,   67.41811,   1.2834148,  -98.304276, -79.165695, 15.270965,  3.746103,   -54.763,
+  -42.926304, -23.553911, -19.94737,  47.355026,  31.100943,  8.447245,   -75.31512,  -16.644464,
+  22.489397,  -39.29673,  -98.54282,  -85.136086, 41.03638,   -37.152763, -79.57822,  -68.96887,
+  11.1106205, -10.539243, -8.441398,  -52.19395,  6.378709,   9.458231,   -77.18643,  99.294,
+  76.699104,  45.281494,  -19.284706, 65.62093,   -66.792015, -1.4548094, -82.337814, -73.516815,
+  5.0163054,  80.22257,   15.349068,  19.546398,  24.824991,  16.236868,  92.39976,   76.70845,
+  -36.775307, -12.240916, 59.4311,    60.621857,  11.79261,   -64.71309,  -63.46639,  -33.302174,
+  -36.784237, -40.939827, 15.621524,  -90.70094,  29.704996,  -71.49415,  14.5302105, -17.651545};
+const std::vector<float> reference_output_data = {
+  53.57955,  37.07942,  55.465694, 69.174965, 43.413803, 38.700638, 47.33504,  33.34464,  55.244015,
+  69.998634, 55.095154, 32.02708,  58.0016,   65.26638,  23.898365, 53.472546, 70.27501,  54.07641,
+  28.25977,  58.65199,  82.015915, 45.18763,  25.517868, 43.224625, 53.693985, 33.887444, 56.632225,
+  83.667915, 59.987476, 47.6801,   36.385647, 49.41058,  36.54862,  62.415905, 81.55694,  44.618065,
+  50.875214, 44.228725, 34.68579,  36.07896,  65.22483,  69.9266,   33.657883, 37.423244, 62.605423,
+  56.839954, 50.79529,  58.17711,  37.61556};
+
+} // namespace l2pool2d_float
+
+class TestDataFloatL2Pool2D : public TestDataL2Pool2DBase<float>
+{
+public:
+  TestDataFloatL2Pool2D()
+  {
+    _input_data = l2pool2d_float::input_data;
+    _reference_output_data = l2pool2d_float::reference_output_data;
+    _test_kernel_model_circle = l2pool2d_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatL2Pool2D() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_L2POOL2D_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/l2pool2d/NegL2Pool2DKernel.h b/onert-micro/onert-micro/include/test_models/l2pool2d/NegL2Pool2DKernel.h
new file mode 100644 (file)
index 0000000..1492c88
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_L2POOL2D_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_L2POOL2D_KERNEL_H
+
+#include "TestDataL2Pool2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_l2pool2d_kernel
+{
+/*
+ * L2Pool2D Kernel with input output type mismatch:
+ *
+ *      Input(1, 8, 8, 1) - Float32
+ *            |
+ *           L2Pool2D
+ *            |
+ *      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, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 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_l2pool2d_kernel
+
+class NegTestDataInputOutputTypeMismatchL2Pool2DKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchL2Pool2DKernel()
+  {
+    _test_kernel_model_circle = neg_l2pool2d_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchL2Pool2DKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_L2POOL2D_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/l2pool2d/TestDataL2Pool2DBase.h b/onert-micro/onert-micro/include/test_models/l2pool2d/TestDataL2Pool2DBase.h
new file mode 100644 (file)
index 0000000..042de5b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_L2POOL2D_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_L2POOL2D_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataL2Pool2DBase : public TestDataBase<T>
+{
+public:
+  TestDataL2Pool2DBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_L2POOL2D_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/leaky_relu/FloatLeakyReLUKernel.h b/onert-micro/onert-micro/include/test_models/leaky_relu/FloatLeakyReLUKernel.h
new file mode 100644 (file)
index 0000000..b9477d9
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_LEAKY_RELU_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_LEAKY_RELU_KERNEL_H
+
+#include "TestDataLeakyReLUBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_LEAKY_RELU_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/leaky_relu/NegLeakyReLUKernel.h b/onert-micro/onert-micro/include/test_models/leaky_relu/NegLeakyReLUKernel.h
new file mode 100644 (file)
index 0000000..d9f7fa7
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_LEAKY_RELU_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_LEAKY_RELU_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_LEAKY_RELU_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/leaky_relu/TestDataLeakyReLUBase.h b/onert-micro/onert-micro/include/test_models/leaky_relu/TestDataLeakyReLUBase.h
new file mode 100644 (file)
index 0000000..8c502c2
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_LEAKY_RELU_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_LEAKY_RELU_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_LEAKY_RELU_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/less/FloatLessKernel.h b/onert-micro/onert-micro/include/test_models/less/FloatLessKernel.h
new file mode 100644 (file)
index 0000000..ddb8ab3
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_LESS_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_LESS_KERNEL_FLOAT_H
+
+#include "TestDataLessBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_LESS_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/less/IntLessKernel.h b/onert-micro/onert-micro/include/test_models/less/IntLessKernel.h
new file mode 100644 (file)
index 0000000..6f6df65
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_LESS_KERNEL_INT_H
+#define ONERT_MICRO_TEST_MODELS_LESS_KERNEL_INT_H
+
+#include "TestDataLessBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_LESS_KERNEL_INT_H
diff --git a/onert-micro/onert-micro/include/test_models/less/NegTestDataLessKernel.h b/onert-micro/onert-micro/include/test_models/less/NegTestDataLessKernel.h
new file mode 100644 (file)
index 0000000..9802b95
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_NEG_TEST_MODELS_LESS_KERNEL_H
+#define ONERT_MICRO_NEG_TEST_MODELS_LESS_KERNEL_H
+
+#include "TestDataLessBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_NEG_TEST_MODELS_LESS_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/less/QuantLessKernel.h b/onert-micro/onert-micro/include/test_models/less/QuantLessKernel.h
new file mode 100644 (file)
index 0000000..718793c
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_LESS_KERNEL_QUANT_H
+#define ONERT_MICRO_TEST_MODELS_LESS_KERNEL_QUANT_H
+
+#include "TestDataLessBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_LESS_KERNEL_QUANT_H
diff --git a/onert-micro/onert-micro/include/test_models/less/TestDataLessBase.h b/onert-micro/onert-micro/include/test_models/less/TestDataLessBase.h
new file mode 100644 (file)
index 0000000..c59651d
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_LESS_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_LESS_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_LESS_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/less_equal/FloatLessEqualKernel.h b/onert-micro/onert-micro/include/test_models/less_equal/FloatLessEqualKernel.h
new file mode 100644 (file)
index 0000000..a544b87
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_LESS_EQUAL_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_LESS_EQUAL_KERNEL_FLOAT_H
+
+#include "TestDataLessEqualBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_LESS_EQUAL_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/less_equal/TestDataLessEqualBase.h b/onert-micro/onert-micro/include/test_models/less_equal/TestDataLessEqualBase.h
new file mode 100644 (file)
index 0000000..98a1d07
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_LESS_EQUAL_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_LESS_EQUAL_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_LESS_EQUAL_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/log/FloatLogKernel.h b/onert-micro/onert-micro/include/test_models/log/FloatLogKernel.h
new file mode 100644 (file)
index 0000000..a88c9c8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_LOG_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_LOG_KERNEL_H
+
+#include "TestDataLogBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace log_float
+{
+/*
+ * Log Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Log
+ *            |
+ *      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,
+  0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 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.9393284, 12.591625, 14.310633, 4.178408, 9.743034, 7.6983232, 10.804855,  2.9712732, 13.964229,
+  8.660442,  12.715771, 12.287443, 11.55983, 6.143016, 1.032474,  10.3692465, 13.885086, 12.157783};
+const std::vector<float> reference_output_data = {
+  1.0781811, 2.533032,  2.6610029,   1.4299303, 2.2765527, 2.0410025,
+  2.3799956, 1.0889906, 2.636499,    2.1587658, 2.542843,  2.5085778,
+  2.4475362, 1.8153158, 0.031957902, 2.3388443, 2.6308153, 2.4979694};
+
+} // namespace log_float
+
+class TestDataFloatLog : public TestDataLogBase<float>
+{
+public:
+  TestDataFloatLog()
+  {
+    _input_data = log_float::input_data;
+    _reference_output_data = log_float::reference_output_data;
+    _test_kernel_model_circle = log_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatLog() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_LOG_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/log/NegLogKernel.h b/onert-micro/onert-micro/include/test_models/log/NegLogKernel.h
new file mode 100644 (file)
index 0000000..4676a40
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_LOG_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_LOG_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Log Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Log
+ *            |
+ *      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,
+  0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 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 NegTestDataInputOutputTypeMismatchLogKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchLogKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchLogKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_LOG_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/log/TestDataLogBase.h b/onert-micro/onert-micro/include/test_models/log/TestDataLogBase.h
new file mode 100644 (file)
index 0000000..1a6aa79
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_LOG_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_LOG_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataLogBase : public TestDataBase<T>
+{
+public:
+  TestDataLogBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_LOG_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/log_softmax/FloatLogSoftmaxKernel.h b/onert-micro/onert-micro/include/test_models/log_softmax/FloatLogSoftmaxKernel.h
new file mode 100644 (file)
index 0000000..3eec267
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_LOG_SOFTMAX_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_LOG_SOFTMAX_KERNEL_H
+
+#include "TestDataLogSoftmaxBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace log_softmax_float
+{
+/*
+ * LogSoftmax Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *        LogSoftmax
+ *            |
+ *      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, 0x24, 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,
+  0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 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 = {
+  -98.99295, 67.388435, 48.43881, -61.26518, 35.86871, 22.69142,  -61.265385, -87.11669, -20.316734,
+  50.533947, -93.46988, 75.58928, -36.26448, 96.57878, 63.916878, -87.25623,  30.606735, 65.762665};
+const std::vector<float> reference_output_data = {
+  -166.38138, 0.0,        0.0,       -109.70399, -1.9073468e-06, -13.177292,
+  0.0,        -25.851307, -70.85068, 0.0,        -169.05916,     0.0,
+  -132.84326, 0.0,        0.0,       -151.17311, -35.15593,      0.0};
+
+} // namespace log_softmax_float
+
+class TestDataFloatLogSoftmax : public TestDataLogSoftmaxBase<float>
+{
+public:
+  TestDataFloatLogSoftmax()
+  {
+    _input_data = log_softmax_float::input_data;
+    _reference_output_data = log_softmax_float::reference_output_data;
+    _test_kernel_model_circle = log_softmax_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatLogSoftmax() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_LOG_SOFTMAX_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/log_softmax/NegLogSoftmaxKernel.h b/onert-micro/onert-micro/include/test_models/log_softmax/NegLogSoftmaxKernel.h
new file mode 100644 (file)
index 0000000..c5f36f3
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_LOG_SOFTMAX_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_LOG_SOFTMAX_KERNEL_H
+
+#include "TestDataLogSoftmaxBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_log_softmax_kernel
+{
+/*
+ * LogSoftmax Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           LogSoftmax
+ *            |
+ *      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, 0x24, 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,
+  0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 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_log_softmax_kernel
+
+class NegTestDataInputOutputTypeMismatchLogSoftmaxKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchLogSoftmaxKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_log_softmax_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchLogSoftmaxKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_LOG_SOFTMAX_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/log_softmax/TestDataLogSoftmaxBase.h b/onert-micro/onert-micro/include/test_models/log_softmax/TestDataLogSoftmaxBase.h
new file mode 100644 (file)
index 0000000..5149322
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_LOG_SOFTMAX_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_LOG_SOFTMAX_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataLogSoftmaxBase : public TestDataBase<T>
+{
+public:
+  TestDataLogSoftmaxBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_LOG_SOFTMAX_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/logistic/FloatLogisticKernel.h b/onert-micro/onert-micro/include/test_models/logistic/FloatLogisticKernel.h
new file mode 100644 (file)
index 0000000..88a1f12
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_LOGISTIC_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_LOGISTIC_KERNEL_H
+
+#include "TestDataLogisticBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_LOGISTIC_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/logistic/NegLogisticKernel.h b/onert-micro/onert-micro/include/test_models/logistic/NegLogisticKernel.h
new file mode 100644 (file)
index 0000000..5963758
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_LOGISTIC_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_LOGISTIC_KERNEL_H
+
+#include "TestDataLogisticBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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 INT16 type and without quant params:
+ *
+ *      Input(1, 3, 3, 2) - INT16
+ *            |
+ *         Logistic (no quant params)
+ *            |
+ *      Output(1, 3, 3, 2) - 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, 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, 0x07, 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, 0x07,
+  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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_LOGISTIC_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/logistic/TestDataLogisticBase.h b/onert-micro/onert-micro/include/test_models/logistic/TestDataLogisticBase.h
new file mode 100644 (file)
index 0000000..d972ff8
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_LOGISTIC_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_LOGISTIC_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_LOGISTIC_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/maximum/FloatMaximumKernel.h b/onert-micro/onert-micro/include/test_models/maximum/FloatMaximumKernel.h
new file mode 100644 (file)
index 0000000..027b65b
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_MAXIMUM_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_MAXIMUM_KERNEL_FLOAT_H
+
+#include "TestDataMaximumBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace maximum_float_with_broadcasting
+{
+
+/*
+ * Maximum Kernel:
+ *
+ * Input_1(2, 5)   Input_2(2, 1)
+ *       \             /
+ *     Maximum(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, 0x27, 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,
+  0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 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 = {3.6702812, 3.9503734, 6.2998962, -1.8228233, 1.0596895,
+                                        6.8552585, 6.7857623, 5.0216885, 5.6108203,  -7.2084064};
+const std::vector<float> input2_data = {-7.1075683, 0.7976927};
+const std::vector<float> reference_output_data = {3.6702812, 3.9503734, 6.2998962, -1.8228233,
+                                                  1.0596895, 6.8552585, 6.7857623, 5.0216885,
+                                                  5.6108203, 0.7976927};
+
+} // namespace maximum_float_with_broadcasting
+
+namespace maximum_float_no_broadcasting
+{
+/*
+ * Maximum Kernel:
+ *
+ * Input_1(2, 3)   Input_2(2, 3)
+ *              \             /
+ *          Maximum(no broadcast)
+ *                     |
+ *            Output(2, 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, 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, 0x27, 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, 0x03, 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,
+  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, 0x02, 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,
+  0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 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 = {0.68642193, 1.5050905,   -2.4937015,
+                                  -3.9648914, -0.54440844, 0.884532};
+std::vector<float> input2_data = {-3.052149,  6.7323585,  -7.5222282,
+                                  -7.1619887, -4.9076447, -1.6525323};
+std::vector<float> reference_output_data = {0.68642193, 6.7323585,   -2.4937015,
+                                            -3.9648914, -0.54440844, 0.884532};
+
+} // namespace maximum_float_no_broadcasting
+
+class TestDataFloatMaximum : public TestDataMaximumBase<float>
+{
+public:
+  explicit TestDataFloatMaximum(bool is_with_broadcast)
+    : TestDataMaximumBase<float>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = maximum_float_with_broadcasting::input1_data;
+      _input2_data = maximum_float_with_broadcasting::input2_data;
+      _reference_output_data = maximum_float_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = maximum_float_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = maximum_float_no_broadcasting::input1_data;
+      _input2_data = maximum_float_no_broadcasting::input2_data;
+      _reference_output_data = maximum_float_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = maximum_float_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataFloatMaximum() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_MAXIMUM_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/maximum/NegMaximumKernel.h b/onert-micro/onert-micro/include/test_models/maximum/NegMaximumKernel.h
new file mode 100644 (file)
index 0000000..61d6c68
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_MAXIMUM_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_MAXIMUM_KERNEL_H
+
+#include "TestDataMaximumBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace input_1_wrong_type
+{
+
+/*
+ * Maximum Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Int32   Input_2(2, 1) - Float
+ *               \             /
+ *           Maximum(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, 0x27, 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,
+  0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 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
+{
+
+/*
+ * Maximum Kernel with input2  type mismatch:
+ *
+ * Input_1(2, 5)- Float   Input_2(2, 1) - Int32
+ *       \             /
+ *     Maximum(with broadcast)
+ *              |
+ *          Output(2, 5) - 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, 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, 0x27, 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,
+  0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 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 NegTestDataInput1WrongTypeMaximum : public NegTestDataBase
+{
+public:
+  NegTestDataInput1WrongTypeMaximum()
+  {
+    _test_kernel_model_circle = input_1_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput1WrongTypeMaximum() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInput2WrongTypeMaximum : public NegTestDataBase
+{
+public:
+  NegTestDataInput2WrongTypeMaximum()
+  {
+    _test_kernel_model_circle = input_2_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput2WrongTypeMaximum() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_MAXIMUM_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/maximum/TestDataMaximumBase.h b/onert-micro/onert-micro/include/test_models/maximum/TestDataMaximumBase.h
new file mode 100644 (file)
index 0000000..7e40275
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_MAXIMUM_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_MAXIMUM_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataMaximumBase : public TestDataBase<T>
+{
+public:
+  explicit TestDataMaximumBase(bool)
+  {
+    // Do nothing
+  }
+
+  TestDataMaximumBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_MAXIMUM_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/maxpool2d/FloatMaxPool2DKernel.h b/onert-micro/onert-micro/include/test_models/maxpool2d/FloatMaxPool2DKernel.h
new file mode 100644 (file)
index 0000000..5363991
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_MAXPOOL2D_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_MAXPOOL2D_KERNEL_H
+
+#include "TestDataMaxPool2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_MAXPOOL2D_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/maxpool2d/NegMaxPool2DKernel.h b/onert-micro/onert-micro/include/test_models/maxpool2d/NegMaxPool2DKernel.h
new file mode 100644 (file)
index 0000000..a0c4fda
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_MAXPOOL2D_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_MAXPOOL2D_KERNEL_H
+
+#include "TestDataMaxPool2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_MAXPOOL2D_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/maxpool2d/QuantMaxPool2DKernel.h b/onert-micro/onert-micro/include/test_models/maxpool2d/QuantMaxPool2DKernel.h
new file mode 100644 (file)
index 0000000..de8e225
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_QUANT_MAX_POOL_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_QUANT_MAX_POOL_KERNEL_H
+
+#include "TestDataMaxPool2DBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace s8_max_pool
+{
+
+/*
+ * S8 MaxPool2D Kernel:
+ *
+ *              Input(1, 8, 8, 1) - Int8
+ *                    |
+ *                 MaxPool2D - Int8
+ *                     |
+ *                Output(1, 7, 7, 1) - Int8
+ */
+
+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, 0xdc, 0x01, 0x00, 0x00, 0xf8, 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,
+  0x84, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x92, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 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, 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, 0x6f, 0x66, 0x6d, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 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, 0x20, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 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, 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};
+
+const std::vector<int8_t> input_data = {
+  -10, -5, -5, -6, -8, -5, 6,  -10, -4, 5,  -4,  -3, 5,  0,  -8, -6, 0, 7,  1,  -5, -10, 8,
+  0,   -2, -9, 5,  -1, -7, -3, 3,   6,  -1, -8,  -9, -1, 8,  -2, -3, 1, -8, -1, 3,  2,   5,
+  1,   -8, -1, -6, 6,  -6, 5,  9,   -4, 5,  -10, -8, -3, -9, 9,  4,  3, 0,  0,  -10};
+
+const std::vector<int8_t> reference_output_data = {
+  5, 5, -3, 5, 5, 6, 6, 7, 7, 1, 5, 8, 8, 0, 7, 7, 1,  -3, 8, 8, 6, 5, 5, 8, 8,
+  3, 6, 6,  3, 3, 8, 8, 1, 1, 1, 6, 5, 9, 9, 5, 5, -1, 6,  9, 9, 9, 5, 5, 0};
+
+} // namespace s8_max_pool
+
+class TestDataS8MaxPool2D : public TestDataMaxPool2DBase<int8_t>
+{
+public:
+  TestDataS8MaxPool2D()
+  {
+    _input_data = s8_max_pool::input_data;
+    _reference_output_data = s8_max_pool::reference_output_data;
+    _test_kernel_model_circle = s8_max_pool::test_kernel_model_circle;
+  }
+
+  ~TestDataS8MaxPool2D() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_QUANT_MAX_POOL_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/maxpool2d/TestDataMaxPool2DBase.h b/onert-micro/onert-micro/include/test_models/maxpool2d/TestDataMaxPool2DBase.h
new file mode 100644 (file)
index 0000000..1acb897
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_MAXPOOL2D_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_MAXPOOL2D_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_MAXPOOL2D_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/minimum/FloatMinimumKernel.h b/onert-micro/onert-micro/include/test_models/minimum/FloatMinimumKernel.h
new file mode 100644 (file)
index 0000000..a320572
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_MINIMUM_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_MINIMUM_KERNEL_FLOAT_H
+
+#include "TestDataMinimumBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace minimum_float_with_broadcasting
+{
+
+/*
+ * Minimum Kernel:
+ *
+ * Input_1(2, 5)   Input_2(2, 1)
+ *       \             /
+ *     Minimum(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, 0x27, 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,
+  0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 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 = {3.9078786, 4.825119,   -6.9444265, 0.5244622,  -5.321703,
+                                        -9.686515, -1.3499693, -5.8468533, -0.5371767, 8.364615};
+const std::vector<float> input2_data = {-7.73631, 1.0758704};
+const std::vector<float> reference_output_data = {-7.73631,   -7.73631,  -7.73631,   -7.73631,
+                                                  -7.73631,   -9.686515, -1.3499693, -5.8468533,
+                                                  -0.5371767, 1.0758704};
+
+} // namespace minimum_float_with_broadcasting
+
+namespace minimum_float_no_broadcasting
+{
+/*
+ * Minimum Kernel:
+ *
+ * Input_1(2, 3)   Input_2(2, 3)
+ *              \             /
+ *          Minimum(no broadcast)
+ *                     |
+ *            Output(2, 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, 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, 0x27, 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, 0x03, 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,
+  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, 0x02, 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,
+  0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 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 = {7.1328354,  -3.694989,  -7.1043596,
+                                  -7.4285483, -7.1077704, 3.0919213};
+std::vector<float> input2_data = {-0.31031138, 4.8659816, -9.223121,
+                                  -9.779761,   -4.288633, -3.4242167};
+std::vector<float> reference_output_data = {-0.31031138, -3.694989,  -9.223121,
+                                            -9.779761,   -7.1077704, -3.4242167};
+
+} // namespace minimum_float_no_broadcasting
+
+class TestDataFloatMinimum : public TestDataMinimumBase<float>
+{
+public:
+  explicit TestDataFloatMinimum(bool is_with_broadcast)
+    : TestDataMinimumBase<float>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = minimum_float_with_broadcasting::input1_data;
+      _input2_data = minimum_float_with_broadcasting::input2_data;
+      _reference_output_data = minimum_float_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = minimum_float_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = minimum_float_no_broadcasting::input1_data;
+      _input2_data = minimum_float_no_broadcasting::input2_data;
+      _reference_output_data = minimum_float_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = minimum_float_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataFloatMinimum() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_MINIMUM_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/minimum/NegMinimumKernel.h b/onert-micro/onert-micro/include/test_models/minimum/NegMinimumKernel.h
new file mode 100644 (file)
index 0000000..8cbc7e0
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_MINIMUM_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_MINIMUM_KERNEL_H
+
+#include "TestDataMinimumBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace input_1_wrong_type
+{
+
+/*
+ * Minimum Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Int32   Input_2(2, 1) - Float
+ *               \             /
+ *           Minimum(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, 0x27, 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,
+  0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 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
+{
+
+/*
+ * Minimum Kernel with input2  type mismatch:
+ *
+ * Input_1(2, 5)- Float   Input_2(2, 1) - Int32
+ *       \             /
+ *     Minimum(with broadcast)
+ *              |
+ *          Output(2, 5) - 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, 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, 0x27, 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,
+  0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 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 NegTestDataInput1WrongTypeMinimum : public NegTestDataBase
+{
+public:
+  NegTestDataInput1WrongTypeMinimum()
+  {
+    _test_kernel_model_circle = input_1_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput1WrongTypeMinimum() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInput2WrongTypeMinimum : public NegTestDataBase
+{
+public:
+  NegTestDataInput2WrongTypeMinimum()
+  {
+    _test_kernel_model_circle = input_2_wrong_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInput2WrongTypeMinimum() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_MINIMUM_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/minimum/TestDataMinimumBase.h b/onert-micro/onert-micro/include/test_models/minimum/TestDataMinimumBase.h
new file mode 100644 (file)
index 0000000..35a9a49
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_MINIMUM_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_MINIMUM_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataMinimumBase : public TestDataBase<T>
+{
+public:
+  explicit TestDataMinimumBase(bool)
+  {
+    // Do nothing
+  }
+
+  TestDataMinimumBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_MINIMUM_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/mul/FloatMulKernel.h b/onert-micro/onert-micro/include/test_models/mul/FloatMulKernel.h
new file mode 100644 (file)
index 0000000..4be767d
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_MUL_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_MUL_KERNEL_FLOAT_H
+
+#include "TestDataMulBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_MUL_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/mul/IntMulKernel.h b/onert-micro/onert-micro/include/test_models/mul/IntMulKernel.h
new file mode 100644 (file)
index 0000000..b01407e
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_MUL_KERNEL_INT_H
+#define ONERT_MICRO_TEST_MODELS_MUL_KERNEL_INT_H
+
+#include "TestDataMulBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_MUL_KERNEL_INT_H
diff --git a/onert-micro/onert-micro/include/test_models/mul/NegMulKernel.h b/onert-micro/onert-micro/include/test_models/mul/NegMulKernel.h
new file mode 100644 (file)
index 0000000..e1f8ee5
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_MUL_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_MUL_KERNEL_H
+
+#include "TestDataMulBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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 neg_mul_no_scale_output
+{
+/*
+ * Quantize Mul Kernel with output without scale:
+ *
+ * Input_1(1, 4, 4, 3) - Int8   Input_2(1, 4, 4, 3) - Int8
+ *       \                    /
+ *           Mul(with broadcast)
+ *              |
+ *          Output(1, 4, 4, 3) - no scale and zero_point
+ */
+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, 0x30, 0x02, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xe4, 0xfd, 0xff, 0xff, 0xe8, 0xfd, 0xff, 0xff, 0xec, 0xfd, 0xff, 0xff,
+  0xf0, 0xfd, 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, 0x5c, 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, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+  0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x2a, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x38, 0x00, 0x00, 0x00,
+  0x1c, 0xff, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x09, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x39, 0xb4, 0x3c, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x01, 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, 0x09,
+  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, 0xf4, 0xfd, 0x54, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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_mul_no_scale_output
+
+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;
+};
+
+class NegTestQuantMulNoScaleKernel : public NegTestDataBase
+{
+public:
+  NegTestQuantMulNoScaleKernel()
+  {
+    _test_kernel_model_circle = neg_mul_no_scale_output::test_kernel_model_circle;
+  }
+
+  ~NegTestQuantMulNoScaleKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_MUL_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/mul/QuantMulKernel.h b/onert-micro/onert-micro/include/test_models/mul/QuantMulKernel.h
new file mode 100644 (file)
index 0000000..e2cee42
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_MUL_KERNEL_QUANT_H
+#define ONERT_MICRO_TEST_MODELS_MUL_KERNEL_QUANT_H
+
+#include "TestDataMulBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace mul_int8_no_broadcasting
+{
+
+/*
+ * Mul Kernel:
+ *
+ * Input_1(1, 4, 4, 3)   Input_2(1, 4, 4, 3)
+ *       \             /
+ *        Mul(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, 0x44, 0x02, 0x00, 0x00, 0x60, 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, 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, 0x00, 0x01, 0x00, 0x00,
+  0x78, 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, 0x09, 0x48, 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, 0xe0, 0x2d, 0x90, 0x3a, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x09, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x1d, 0xa7, 0x3b, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x09,
+  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, 0x0a, 0xd7, 0xa3, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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,
+  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<int8_t> input1_data = {
+  3,  3, -8, -3, -4, -1, 5,  7, -4, 5,  9, -3, -8, -8,  -4, -10, -8, 0, 8,  6,  -1, 0, -2, 1,
+  -1, 7, -6, -9, 4,  -2, -9, 0, 6,  -1, 9, 3,  -1, -10, -1, -9,  6,  5, -4, -2, 0,  0, -3, -6};
+const std::vector<int8_t> input2_data = {
+  6, -9, -3, -4, -7, -10, -2, -8,  7, -7, 8, 9,  -4, 3, -4, -4, -2, -3, -4, 5,  -5, -2, -7, 1,
+  6, 4,  -5, -8, 7,  9,   1,  -10, 2, 8,  5, -3, 1,  8, 3,  3,  9,  -2, -1, -1, -7, 9,  -3, 3};
+const std::vector<int8_t> reference_output_data = {
+  2,  -3, 2, 1, 3, 1,  -1, -5, -3, -3, 7, -3, 3, -2, 2, 4,  2, 0,  -3, 3, 1, 0, 1, 0,
+  -1, 3,  3, 7, 3, -2, -1, 0,  1,  -1, 4, -1, 0, -7, 0, -3, 5, -1, 0,  0, 0, 0, 1, -2};
+
+} // namespace mul_int8_no_broadcasting
+
+namespace mul_int8_with_broadcasting
+{
+/*
+ * Mul Kernel:
+ *
+ * Input_1(1, 4, 4, 1)   Input_2(1, 4, 4, 3)
+ *       \             /
+ *        Mul(with 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, 0x44, 0x02, 0x00, 0x00, 0x60, 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, 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, 0x00, 0x01, 0x00, 0x00,
+  0x78, 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, 0x09, 0x48, 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, 0xe0, 0x2d, 0x90, 0x3a, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x09, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe7, 0x1d, 0xa7, 0x3b, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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, 0x09,
+  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, 0x0a, 0xd7, 0xa3, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 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,
+  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<int8_t> input1_data = {-1, 2, 9, 2, 5, 9, 2, -9, -5, -5, -8, 3, -8, -8, 4, -3};
+std::vector<int8_t> input2_data = {0,  8, 0,  -5, 2,  2,  4,  -8, 9, -8, -4, 4,  -8, 9,  -1, 4,
+                                   -1, 0, -5, 6,  -7, 1,  0,  -1, 4, -8, -5, 9,  1,  -1, 0,  -9,
+                                   3,  9, -4, 7,  5,  -7, -8, 5,  5, 3,  -3, -5, -1, 3,  -4, 4};
+std::vector<int8_t> reference_output_data = {
+  0,  -1, 0, -1, 0,  0, 3, -7, 8,  -2, -1, 1, -4, 4, -1, 3,  -1, 0,  -1, 1,  -1, -1, 0, 1,
+  -2, 4,  2, -4, -1, 1, 0, 7,  -2, 3,  -1, 2, -4, 5, 6,  -4, -4, -2, -1, -2, 0,  -1, 1, -1};
+
+} // namespace mul_int8_with_broadcasting
+
+class TestDataInt8Mul : public TestDataMulBase<int8_t>
+{
+public:
+  explicit TestDataInt8Mul(bool is_with_broadcast) : TestDataMulBase<int8_t>(is_with_broadcast)
+  {
+    if (is_with_broadcast)
+    {
+      _input1_data = mul_int8_with_broadcasting::input1_data;
+      _input2_data = mul_int8_with_broadcasting::input2_data;
+      _reference_output_data = mul_int8_with_broadcasting::reference_output_data;
+      _test_kernel_model_circle = mul_int8_with_broadcasting::test_kernel_model_circle;
+    }
+    else
+    {
+      _input1_data = mul_int8_no_broadcasting::input1_data;
+      _input2_data = mul_int8_no_broadcasting::input2_data;
+      _reference_output_data = mul_int8_no_broadcasting::reference_output_data;
+      _test_kernel_model_circle = mul_int8_no_broadcasting::test_kernel_model_circle;
+    }
+  }
+
+  ~TestDataInt8Mul() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_MUL_KERNEL_QUANT_H
diff --git a/onert-micro/onert-micro/include/test_models/mul/TestDataMulBase.h b/onert-micro/onert-micro/include/test_models/mul/TestDataMulBase.h
new file mode 100644 (file)
index 0000000..6143500
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_MUL_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_MUL_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_MUL_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/neg/FloatNegKernel.h b/onert-micro/onert-micro/include/test_models/neg/FloatNegKernel.h
new file mode 100644 (file)
index 0000000..7fd0891
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_NEG_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_NEG_KERNEL_H
+
+#include "TestDataNegBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_NEG_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/neg/NegNegKernel.h b/onert-micro/onert-micro/include/test_models/neg/NegNegKernel.h
new file mode 100644 (file)
index 0000000..e13651d
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_NEG_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_NEG_KERNEL_H
+
+#include "TestDataNegBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_NEG_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/neg/TestDataNegBase.h b/onert-micro/onert-micro/include/test_models/neg/TestDataNegBase.h
new file mode 100644 (file)
index 0000000..859274b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_NEG_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/notequal/FloatNotEqualKernel.h b/onert-micro/onert-micro/include/test_models/notequal/FloatNotEqualKernel.h
new file mode 100644 (file)
index 0000000..c7243e0
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NOT_EQUAL_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_NOT_EQUAL_KERNEL_FLOAT_H
+
+#include "TestDataNotEqualBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NOT_EQUAL_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/notequal/TestDataNotEqualBase.h b/onert-micro/onert-micro/include/test_models/notequal/TestDataNotEqualBase.h
new file mode 100644 (file)
index 0000000..e5d2fcd
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NOT_EQUAL_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_NOT_EQUAL_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NOT_EQUAL_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/pack/PackKernel.h b/onert-micro/onert-micro/include/test_models/pack/PackKernel.h
new file mode 100644 (file)
index 0000000..e2896d4
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_PACK_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_PACK_KERNEL_H
+
+#include "TestDataPackBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_PACK_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/pack/TestDataPackBase.h b/onert-micro/onert-micro/include/test_models/pack/TestDataPackBase.h
new file mode 100644 (file)
index 0000000..80ff8d3
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_PACK_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_PACK_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_PACK_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/pad/FloatPadKernel.h b/onert-micro/onert-micro/include/test_models/pad/FloatPadKernel.h
new file mode 100644 (file)
index 0000000..e8dac6e
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_PAD_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_PAD_KERNEL_H
+
+#include "TestDataPadBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_PAD_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/pad/NegPadKernel.h b/onert-micro/onert-micro/include/test_models/pad/NegPadKernel.h
new file mode 100644 (file)
index 0000000..69453ad
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_PAD_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_PAD_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_pad_kernel
+{
+/*
+ * 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_input_output_type_mismatch_pad_kernel
+
+class NegTestDataInputOutputTypeMismatchPadKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchPadKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_pad_kernel::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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_PAD_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/pad/TestDataPadBase.h b/onert-micro/onert-micro/include/test_models/pad/TestDataPadBase.h
new file mode 100644 (file)
index 0000000..49de36a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_PAD_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_PAD_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_PAD_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/relu/FloatReLUKernel.h b/onert-micro/onert-micro/include/test_models/relu/FloatReLUKernel.h
new file mode 100644 (file)
index 0000000..f7b678a
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_RELU_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_RELU_KERNEL_H
+
+#include "TestDataReLUBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_RELU_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/relu/NegReLUKernel.h b/onert-micro/onert-micro/include/test_models/relu/NegReLUKernel.h
new file mode 100644 (file)
index 0000000..26b0353
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_RELU_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_RELU_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_RELU_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/relu/TestDataReLUBase.h b/onert-micro/onert-micro/include/test_models/relu/TestDataReLUBase.h
new file mode 100644 (file)
index 0000000..c62df23
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_RELU_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_RELU_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_RELU_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/relu6/FloatReLU6Kernel.h b/onert-micro/onert-micro/include/test_models/relu6/FloatReLU6Kernel.h
new file mode 100644 (file)
index 0000000..ef007ff
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_RELU6_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_RELU6_KERNEL_H
+
+#include "TestDataReLU6Base.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_RELU6_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/relu6/NegReLU6Kernel.h b/onert-micro/onert-micro/include/test_models/relu6/NegReLU6Kernel.h
new file mode 100644 (file)
index 0000000..d048e24
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_RELU6_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_RELU6_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_RELU6_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/relu6/TestDataReLU6Base.h b/onert-micro/onert-micro/include/test_models/relu6/TestDataReLU6Base.h
new file mode 100644 (file)
index 0000000..f509e53
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_RELU6_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_RELU6_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_RELU6_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/reshape/ReshapeKernel.h b/onert-micro/onert-micro/include/test_models/reshape/ReshapeKernel.h
new file mode 100644 (file)
index 0000000..d0c9c76
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_RESHAPE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_RESHAPE_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_RESHAPE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/round/FloatRoundKernel.h b/onert-micro/onert-micro/include/test_models/round/FloatRoundKernel.h
new file mode 100644 (file)
index 0000000..43d65f2
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_ROUND_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_ROUND_KERNEL_H
+
+#include "TestDataRoundBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace round_float
+{
+/*
+ * Round Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Round
+ *            |
+ *      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,
+  0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 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 = {-80.601204, 72.38307,  -22.146687, 2.6873038, -7.440473,
+                                       27.860895,  -79.27248, -61.29374,  90.22741,  89.19607,
+                                       31.390116,  50.23514,  60.073032,  61.747887, -72.03697,
+                                       96.049965,  88.859566, -68.925575};
+
+const std::vector<float> reference_output_data = {-81.0, 72.0,  -22.0, 3.0,  -7.0, 28.0,
+                                                  -79.0, -61.0, 90.0,  89.0, 31.0, 50.0,
+                                                  60.0,  62.0,  -72.0, 96.0, 89.0, -69.0};
+
+} // namespace round_float
+
+class TestDataFloatRound : public TestDataRoundBase<float>
+{
+public:
+  TestDataFloatRound()
+  {
+    _input_data = round_float::input_data;
+    _reference_output_data = round_float::reference_output_data;
+    _test_kernel_model_circle = round_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatRound() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_ROUND_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/round/NegRoundKernel.h b/onert-micro/onert-micro/include/test_models/round/NegRoundKernel.h
new file mode 100644 (file)
index 0000000..ccde1bf
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_ROUND_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_ROUND_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_round_kernel
+{
+/*
+ * Round Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Round
+ *            |
+ *      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,
+  0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 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_round_kernel
+
+class NegTestDataInputOutputTypeMismatchRoundKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchRoundKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_round_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchRoundKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_ROUND_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/round/TestDataRoundBase.h b/onert-micro/onert-micro/include/test_models/round/TestDataRoundBase.h
new file mode 100644 (file)
index 0000000..47f3371
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_TANH_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_TANH_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataRoundBase : public TestDataBase<T>
+{
+public:
+  TestDataRoundBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_ROUND_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/rsqrt/FloatRsqrtKernel.h b/onert-micro/onert-micro/include/test_models/rsqrt/FloatRsqrtKernel.h
new file mode 100644 (file)
index 0000000..2418b12
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_RSQRT_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_RSQRT_KERNEL_H
+
+#include "TestDataRsqrtBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace rsqrt_float
+{
+/*
+ * Rsqrt Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Rsqrt
+ *            |
+ *      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,
+  0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 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 = {
+  23.484858, 44.7245,   37.12629,  48.7498,  22.87489, 38.79412, 16.368074, 17.066277, 21.366201,
+  22.673359, 42.429207, 45.798313, 29.01582, 32.38278, 24.38851, 32.807495, 24.529152, 41.338783};
+
+const std::vector<float> reference_output_data = {
+  0.20635073, 0.14952964, 0.16411914, 0.14322327, 0.20908386, 0.16055249,
+  0.2471731,  0.24206422, 0.21633977, 0.21001102, 0.15352091, 0.14776625,
+  0.18564472, 0.17572881, 0.20249178, 0.17458762, 0.2019104,  0.1555325};
+
+} // namespace rsqrt_float
+
+class TestDataFloatRsqrt : public TestDataRsqrtBase<float>
+{
+public:
+  TestDataFloatRsqrt()
+  {
+    _input_data = rsqrt_float::input_data;
+    _reference_output_data = rsqrt_float::reference_output_data;
+    _test_kernel_model_circle = rsqrt_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatRsqrt() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_RSQRT_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/rsqrt/NegRsqrtKernel.h b/onert-micro/onert-micro/include/test_models/rsqrt/NegRsqrtKernel.h
new file mode 100644 (file)
index 0000000..fa1a2a0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_RSQRT_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_RSQRT_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Rsqrt Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Rsqrt
+ *            |
+ *      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,
+  0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 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 NegTestDataInputOutputTypeMismatchRsqrtKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchRsqrtKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchRsqrtKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_RSQRT_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/rsqrt/TestDataRsqrtBase.h b/onert-micro/onert-micro/include/test_models/rsqrt/TestDataRsqrtBase.h
new file mode 100644 (file)
index 0000000..a55ef7d
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_RSQRT_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_RSQRT_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataRsqrtBase : public TestDataBase<T>
+{
+public:
+  TestDataRsqrtBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_RSQRT_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/shape/NegShapeKernel.h b/onert-micro/onert-micro/include/test_models/shape/NegShapeKernel.h
new file mode 100644 (file)
index 0000000..dd069cd
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SHAPE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SHAPE_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SHAPE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/shape/ShapeKernel.h b/onert-micro/onert-micro/include/test_models/shape/ShapeKernel.h
new file mode 100644 (file)
index 0000000..654a01f
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SHAPE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_SHAPE_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SHAPE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/sin/FloatSinKernel.h b/onert-micro/onert-micro/include/test_models/sin/FloatSinKernel.h
new file mode 100644 (file)
index 0000000..0aeffcf
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_SIN_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_SIN_KERNEL_H
+
+#include "TestDataSinBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace sin_float
+{
+/*
+ * Sin Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Sin
+ *            |
+ *      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,
+  0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 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.893156051635742,   1.95573091506958,    -5.393098831176758,   -1.6336439847946167,
+  -9.043712615966797,  -0.7334932088851929, 7.328176975250244,    1.0357639789581299,
+  9.292394638061523,   -1.3363385200500488, 7.083470821380615,    -6.271344184875488,
+  -2.0852465629577637, 9.942416191101074,   -0.12190937995910645, 7.505262851715088,
+  5.940338611602783,   5.232614040374756};
+
+const std::vector<float> reference_output_data = {
+  -0.45143964886665344, 0.9268230199813843,  0.7771261930465698,   -0.9980257153511047,
+  -0.37190958857536316, -0.6694685816764832, 0.8649203777313232,   0.8602521419525146,
+  0.1319969743490219,   -0.9726404547691345, 0.7175549864768982,   0.011840845458209515,
+  -0.8705633878707886,  -0.4948291480541229, -0.12160763889551163, 0.9398112893104553,
+  -0.3361694812774658,  -0.8677073121070862};
+
+} // namespace sin_float
+
+class TestDataFloatSin : public TestDataSinBase<float>
+{
+public:
+  TestDataFloatSin()
+  {
+    _input_data = sin_float::input_data;
+    _reference_output_data = sin_float::reference_output_data;
+    _test_kernel_model_circle = sin_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSin() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_SIN_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/sin/NegSinKernel.h b/onert-micro/onert-micro/include/test_models/sin/NegSinKernel.h
new file mode 100644 (file)
index 0000000..7a0b6d6
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SIN_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SIN_KERNEL_H
+
+#include "TestDataSinBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Sin Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Sin
+ *            |
+ *      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,
+  0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 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 NegTestDataInputOutputTypeMismatchSinKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSinKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSinKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SIN_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/sin/TestDataSinBase.h b/onert-micro/onert-micro/include/test_models/sin/TestDataSinBase.h
new file mode 100644 (file)
index 0000000..d56b683
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SIN_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_SIN_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataSinBase : public TestDataBase<T>
+{
+public:
+  TestDataSinBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SIN_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/slice/FloatSliceKernel.h b/onert-micro/onert-micro/include/test_models/slice/FloatSliceKernel.h
new file mode 100644 (file)
index 0000000..0907cf1
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_SLICE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_SLICE_KERNEL_H
+
+#include "TestDataSliceBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace slice_float
+{
+/*
+ * Slice Kernel:
+ *
+ *     Input(3, 2, 3)       Begin([1, 0, 0])      Size([1, 1, 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_SLICE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/slice/IntSliceKernel.h b/onert-micro/onert-micro/include/test_models/slice/IntSliceKernel.h
new file mode 100644 (file)
index 0000000..7edf3e1
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_INT_SLICE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_INT_SLICE_KERNEL_H
+
+#include "TestDataSliceBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace slice_int32
+{
+/*
+ * Slice Kernel:
+ *
+ *     Input(3, 2, 3)       Begin([1, 0, 0])      Size([1, 1, 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, 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,
+  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, 0x98, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x84, 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,
+  0xb0, 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, 0xd8, 0xff, 0xff, 0xff, 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, 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, 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<int32_t> input_data = {8, 1,   4,   -15, -1, -9, -12, 5,   5,
+                                         4, -12, -16, -2,  11, 17, -5,  -17, -19};
+
+const std::vector<int32_t> reference_output_data = {-12, 5, 5};
+
+} // namespace slice_int32
+
+namespace slice_int64
+{
+/*
+ * Slice Kernel:
+ *
+ *     Input(3, 2, 3)       Begin([1, 0, 0])      Size([1, 1, 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, 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,
+  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, 0x98, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x84, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 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,
+  0xb0, 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, 0xd8, 0xff, 0xff, 0xff, 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, 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, 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<int64_t> input_data = {8, 1,   4,   -15, -1, -9, -12, 5,   5,
+                                         4, -12, -16, -2,  11, 17, -5,  -17, -19};
+
+const std::vector<int64_t> reference_output_data = {-12, 5, 5};
+
+} // namespace slice_int64
+
+class TestDataInt32Slice : public TestDataSliceBase<int32_t>
+{
+public:
+  TestDataInt32Slice()
+  {
+    _input_data = slice_int32::input_data;
+    _reference_output_data = slice_int32::reference_output_data;
+    _test_kernel_model_circle = slice_int32::test_kernel_model_circle;
+  }
+
+  ~TestDataInt32Slice() override = default;
+};
+
+class TestDataInt64Slice : public TestDataSliceBase<int64_t>
+{
+public:
+  TestDataInt64Slice()
+  {
+    _input_data = slice_int64::input_data;
+    _reference_output_data = slice_int64::reference_output_data;
+    _test_kernel_model_circle = slice_int64::test_kernel_model_circle;
+  }
+
+  ~TestDataInt64Slice() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_INT_SLICE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/slice/NegSliceKernel.h b/onert-micro/onert-micro/include/test_models/slice/NegSliceKernel.h
new file mode 100644 (file)
index 0000000..cb6c4f8
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SLICE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SLICE_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SLICE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/slice/TestDataSliceBase.h b/onert-micro/onert-micro/include/test_models/slice/TestDataSliceBase.h
new file mode 100644 (file)
index 0000000..c255e38
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SLICE_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_SLICE_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SLICE_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/softmax/FloatSoftmaxKernel.h b/onert-micro/onert-micro/include/test_models/softmax/FloatSoftmaxKernel.h
new file mode 100644 (file)
index 0000000..d1ca66f
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_SOFTMAX_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_SOFTMAX_KERNEL_H
+
+#include "TestDataSoftmaxBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace softmax_float
+{
+/*
+ * Softmax Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *         Softmax (beta = 1.0)
+ *            |
+ *      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, 0x09, 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, 0x80, 0x3f, 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, 0x19, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x19, 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.5079355, 4.0126457, 4.491231,  4.8917847, 5.4335933,
+                                       0.3851775, 5.5928035, 1.9821982, 1.5670413, 3.9429772,
+                                       2.0674324, 5.3034077, 1.8939269, 1.2043927, 1.0215454,
+                                       0.9565499, 2.418452,  0.38287657};
+
+const std::vector<float> reference_output_data = {
+  0.6213518, 0.3786482,   0.4011793,  0.5988207,  0.9936214,  0.0063785487,
+  0.9736762, 0.026323803, 0.0850262,  0.9149738,  0.03783413, 0.96216595,
+  0.6658633, 0.3341367,   0.51624316, 0.48375684, 0.8844819,  0.11551804};
+
+} // namespace softmax_float
+
+class TestDataFloatSoftmax : public TestDataSoftmaxBase<float>
+{
+public:
+  TestDataFloatSoftmax()
+  {
+    _input_data = softmax_float::input_data;
+    _reference_output_data = softmax_float::reference_output_data;
+    _test_kernel_model_circle = softmax_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSoftmax() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_SOFTMAX_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/softmax/NegSoftmaxKernel.h b/onert-micro/onert-micro/include/test_models/softmax/NegSoftmaxKernel.h
new file mode 100644 (file)
index 0000000..20fc403
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SOFTMAX_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SOFTMAX_KERNEL_H
+
+#include "TestDataSoftmaxBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_softmax_input_output_type_mismatch
+{
+/*
+ * Softmax Kernel with input output type mismatch (should be equal):
+ *
+ *      Input(1, 3, 3, 2) - Float
+ *            |
+ *         Softmax
+ *            |
+ *      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, 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, 0x09, 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, 0x80, 0x3f, 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, 0x19, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x19, 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_softmax_input_output_type_mismatch
+
+namespace neg_softmax_no_quant_params
+{
+/*
+ * Softmax Kernel with INT16 type and without quant params:
+ *
+ *      Input(1, 3, 3, 2) - INT16
+ *            |
+ *         Softmax (no quant params)
+ *            |
+ *      Output(1, 3, 3, 2) - 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, 0x38, 0x01, 0x00, 0x00, 0x54, 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, 0x09, 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, 0x80, 0x3f, 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, 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, 0x07, 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, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 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_softmax_no_quant_params
+
+namespace neg_softmax_no_scale_output
+{
+/*
+ * Softmax Kernel - without output scale:
+ *
+ *      Input(1, 10) - Int8
+ *            |
+ *         Softmax (beta = 1.0)
+ *            |
+ *      Output(1, 10) - Int8 (no output scale)
+ */
+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, 0xa4, 0x01, 0x00, 0x00, 0xc0, 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, 0x09, 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, 0x80, 0x3f, 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, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0xa2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x09, 0x3c, 0x00, 0x00, 0x00, 0x94, 0xff, 0xff, 0xff, 0x28, 0x00, 0x00, 0x00,
+  0x20, 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, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 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, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+  0x4c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xc8, 0x99, 0x3c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x02, 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,
+  0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 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_softmax_no_scale_output
+
+class NegTestDataInputOutputTypeMismatchSoftmaxKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSoftmaxKernel()
+  {
+    _test_kernel_model_circle = neg_softmax_input_output_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSoftmaxKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataNoQuantParamsSoftmaxKernel : public NegTestDataBase
+{
+public:
+  NegTestDataNoQuantParamsSoftmaxKernel()
+  {
+    _test_kernel_model_circle = neg_softmax_no_quant_params::test_kernel_model_circle;
+  }
+
+  ~NegTestDataNoQuantParamsSoftmaxKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SOFTMAX_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/softmax/QuantSoftmaxKernel.h b/onert-micro/onert-micro/include/test_models/softmax/QuantSoftmaxKernel.h
new file mode 100644 (file)
index 0000000..ef5b465
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_QUANT_SOFTMAX_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_QUANT_SOFTMAX_KERNEL_H
+
+#include "TestDataSoftmaxBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace softmax_s8
+{
+/*
+ * Softmax Kernel:
+ *
+ *      Input(1, 10) - Int8
+ *            |
+ *         Softmax (beta = 1.0)
+ *            |
+ *      Output(1, 10) - Int8
+ */
+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, 0xa4, 0x01, 0x00, 0x00, 0xc0, 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, 0x09, 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, 0x80, 0x3f, 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, 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0xa2, 0xff, 0xff, 0xff, 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x09, 0x3c, 0x00, 0x00, 0x00, 0x94, 0xff, 0xff, 0xff, 0x28, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3b,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 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, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+  0x4c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xc8, 0x99, 0x3c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x02, 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,
+  0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 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 = {0, 1, 1, 3, 7, 2, 2, 12, 1, -1};
+
+const std::vector<int8_t> reference_output_data = {-104, -103, -103, -102, -100,
+                                                   -103, -103, -98,  -103, -104};
+
+} // namespace softmax_s8
+
+class TestDataInt8Softmax : public TestDataSoftmaxBase<int8_t>
+{
+public:
+  TestDataInt8Softmax()
+  {
+    _input_data = softmax_s8::input_data;
+    _reference_output_data = softmax_s8::reference_output_data;
+    _test_kernel_model_circle = softmax_s8::test_kernel_model_circle;
+  }
+
+  ~TestDataInt8Softmax() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_QUANT_SOFTMAX_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/softmax/TestDataSoftmaxBase.h b/onert-micro/onert-micro/include/test_models/softmax/TestDataSoftmaxBase.h
new file mode 100644 (file)
index 0000000..7e4938d
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SOFTMAX_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_SOFTMAX_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataSoftmaxBase : public TestDataBase<T>
+{
+public:
+  TestDataSoftmaxBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SOFTMAX_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/space_to_batch_nd/FloatSpaceToBatchNDKernel.h b/onert-micro/onert-micro/include/test_models/space_to_batch_nd/FloatSpaceToBatchNDKernel.h
new file mode 100644 (file)
index 0000000..a5d27b1
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_SPACE_TO_BATCH_ND_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_SPACE_TO_BATCH_ND_KERNEL_H
+
+#include "TestDataSpaceToBatchNDBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace space_to_batch_nd_float
+{
+/*
+ * SpaceToBatchND Kernel:
+ *
+ *      Input(1, 2, 2, 1)
+ *            |
+ *       SpaceToBatchND
+ *            |
+ *      Output(4, 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, 0xdc, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x54, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xe2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x02, 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, 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, 0x19, 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, 0x34, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6c, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x73,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 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, 0x14, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 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, 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, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26,
+  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 = {32.4077, -66.77965, 47.65211, 75.57922};
+const std::vector<float> reference_output_data = {32.4077, -66.77965, 47.65211, 75.57922};
+
+} // namespace space_to_batch_nd_float
+
+class TestDataFloatSpaceToBatchND : public TestDataSpaceToBatchNDBase<float>
+{
+public:
+  TestDataFloatSpaceToBatchND()
+  {
+    _input_data = space_to_batch_nd_float::input_data;
+    _reference_output_data = space_to_batch_nd_float::reference_output_data;
+    _test_kernel_model_circle = space_to_batch_nd_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSpaceToBatchND() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_SPACE_TO_BATCH_ND_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/space_to_batch_nd/NegSpaceToBatchNDKernel.h b/onert-micro/onert-micro/include/test_models/space_to_batch_nd/NegSpaceToBatchNDKernel.h
new file mode 100644 (file)
index 0000000..d46aaf1
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SPACE_TO_BATCH_ND_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SPACE_TO_BATCH_ND_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_space_to_batch_nd_kernel
+{
+/*
+ * SpaceToBatchND kernel with input output type mismatch:
+ *
+ *      Input(1, 2, 2, 1) - Float32
+ *            |
+ *        SpaceToBatchND
+ *            |
+ *      Output(4, 1, 1 , 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,
+  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, 0x2c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xe2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x02, 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, 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, 0x19, 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, 0xb4, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xa0, 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, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64,
+  0x69, 0x6e, 0x67, 0x73, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 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,
+  0x14, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x68,
+  0x61, 0x70, 0x65, 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, 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, 0x26, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x26, 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_space_to_batch_nd_kernel
+
+class NegTestDataInputOutputTypeMismatchSpaceToBatchNDKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSpaceToBatchNDKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_space_to_batch_nd_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSpaceToBatchNDKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SPACE_TO_BATCH_ND_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/space_to_batch_nd/TestDataSpaceToBatchNDBase.h b/onert-micro/onert-micro/include/test_models/space_to_batch_nd/TestDataSpaceToBatchNDBase.h
new file mode 100644 (file)
index 0000000..534af28
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SPACE_TO_BATCH_ND_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_SPACE_TO_BATCH_ND_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataSpaceToBatchNDBase : public TestDataBase<T>
+{
+public:
+  TestDataSpaceToBatchNDBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SPACE_TO_BATCH_ND_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/space_to_depth/FloatSpaceToDepthKernel.h b/onert-micro/onert-micro/include/test_models/space_to_depth/FloatSpaceToDepthKernel.h
new file mode 100644 (file)
index 0000000..7741868
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_SPACE_TO_DEPTH_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_SPACE_TO_DEPTH_KERNEL_H
+
+#include "TestDataSpaceToDepthBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace space_to_depth_float
+{
+/*
+ * SpaceToDepth Kernel:
+ *
+ *      Input(1, 4, 4, 3)
+ *            |
+ *       SpaceToDepth
+ *            |
+ *      Output(1, 2, 2, 12)
+ */
+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, 0x13, 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, 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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 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, 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, 0x1a, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1a, 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 = {
+  30.991892,  47.0218,    -96.94782,  41.75081,   13.22614,   60.732224, 55.300236,  4.7265563,
+  -96.22574,  -60.987602, -12.473722, -92.82498,  37.063133,  53.67425,  74.06907,   14.154034,
+  -69.062805, 78.23639,   46.7026,    19.651571,  -59.871742, -38.91334, 95.758804,  85.42076,
+  6.2756233,  26.522488,  60.209923,  78.387436,  87.826294,  -61.8489,  -22.721363, 41.05879,
+  76.31915,   17.438269,  54.071205,  -27.286413, 5.965944,   20.973064, -3.8931062, 26.459524,
+  -22.902449, -75.43978,  11.68149,   -78.51755,  10.050673,  86.07591,  5.0900855,  -72.07779};
+
+const std::vector<float> reference_output_data = {
+  30.991892,  47.0218,    -96.94782,  41.75081,  13.22614,   60.732224, 37.063133, 53.67425,
+  74.06907,   14.154034,  -69.062805, 78.23639,  55.300236,  4.7265563, -96.22574, -60.987602,
+  -12.473722, -92.82498,  46.7026,    19.651571, -59.871742, -38.91334, 95.758804, 85.42076,
+  6.2756233,  26.522488,  60.209923,  78.387436, 87.826294,  -61.8489,  5.965944,  20.973064,
+  -3.8931062, 26.459524,  -22.902449, -75.43978, -22.721363, 41.05879,  76.31915,  17.438269,
+  54.071205,  -27.286413, 11.68149,   -78.51755, 10.050673,  86.07591,  5.0900855, -72.07779};
+
+} // namespace space_to_depth_float
+
+class TestDataFloatSpaceToDepth : public TestDataSpaceToDepthBase<float>
+{
+public:
+  TestDataFloatSpaceToDepth()
+  {
+    _input_data = space_to_depth_float::input_data;
+    _reference_output_data = space_to_depth_float::reference_output_data;
+    _test_kernel_model_circle = space_to_depth_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSpaceToDepth() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_SPACE_TO_DEPTH_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/space_to_depth/NegSpaceToDepthKernel.h b/onert-micro/onert-micro/include/test_models/space_to_depth/NegSpaceToDepthKernel.h
new file mode 100644 (file)
index 0000000..c36b24d
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SPACE_TO_DEPTH_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SPACE_TO_DEPTH_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_space_to_depth_kernel
+{
+/*
+ * SpaceToDepth kernel with input output type mismatch:
+ *
+ *      Input(1, 4, 4, 3) - Float32
+ *            |
+ *        SpaceToDepth
+ *            |
+ *      Output(1, 2, 2, 12) - 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, 0x13, 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, 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,
+  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 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, 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, 0x1a, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1a, 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_space_to_depth_kernel
+
+class NegTestDataInputOutputTypeMismatchSpaceToDepthKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSpaceToDepthKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_space_to_depth_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSpaceToDepthKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SPACE_TO_DEPTH_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/space_to_depth/TestDataSpaceToDepthBase.h b/onert-micro/onert-micro/include/test_models/space_to_depth/TestDataSpaceToDepthBase.h
new file mode 100644 (file)
index 0000000..d84981b
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SPACE_TO_DEPTH_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_SPACE_TO_DEPTH_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataSpaceToDepthBase : public TestDataBase<T>
+{
+public:
+  TestDataSpaceToDepthBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SPACE_TO_DEPTH_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/split/FloatSplitKernel.h b/onert-micro/onert-micro/include/test_models/split/FloatSplitKernel.h
new file mode 100644 (file)
index 0000000..29a0bc1
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_SQRT_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_SQRT_KERNEL_H
+
+#include "TestDataSplitBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_SQRT_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/split/NegSplitKernel.h b/onert-micro/onert-micro/include/test_models/split/NegSplitKernel.h
new file mode 100644 (file)
index 0000000..8e3483b
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SPLIT_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SPLIT_KERNEL_H
+
+#include "TestDataSplitBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_split_kernel
+{
+/*
+ * Split Kernel with input output mismatch:
+ *
+ *      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, 0xc0, 0x01, 0x00, 0x00, 0xdc, 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, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0xd4, 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, 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, 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};
+
+} // namespace neg_input_output_type_mismatch_split_kernel
+
+class NegTestDataInputOutputTypeMismatchSplitKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSplitKernel()
+  {
+    _test_kernel_model_circle =
+      neg_input_output_type_mismatch_split_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSplitKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SPLIT_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/split/TestDataSplitBase.h b/onert-micro/onert-micro/include/test_models/split/TestDataSplitBase.h
new file mode 100644 (file)
index 0000000..dbf2766
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SPLIT_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_SPLIT_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SPLIT_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/sqrt/FloatSqrtKernel.h b/onert-micro/onert-micro/include/test_models/sqrt/FloatSqrtKernel.h
new file mode 100644 (file)
index 0000000..ef7d730
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_SQRT_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_SQRT_KERNEL_H
+
+#include "TestDataSqrtBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace sqrt_float
+{
+/*
+ * Sqrt Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Sqrt
+ *            |
+ *      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,
+  0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 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 = {
+  14.583464, 44.010857, 30.89816,  52.36842, 31.285244, 46.0197,  30.435776, 27.172525, 41.825855,
+  27.010614, 21.654316, 12.085457, 34.82241, 34.682625, 26.42978, 36.799065, 16.062561, 40.312984};
+
+const std::vector<float> reference_output_data = {
+  3.8188303, 6.634068, 5.5586114, 7.236603,  5.5933213, 6.783782,  5.516863, 5.212727,  6.4672914,
+  5.1971736, 4.65342,  3.4764144, 5.9010515, 5.8891954, 5.1409903, 6.066223, 4.0078125, 6.349251};
+
+} // namespace sqrt_float
+
+class TestDataFloatSqrt : public TestDataSqrtBase<float>
+{
+public:
+  TestDataFloatSqrt()
+  {
+    _input_data = sqrt_float::input_data;
+    _reference_output_data = sqrt_float::reference_output_data;
+    _test_kernel_model_circle = sqrt_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSqrt() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_SQRT_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/sqrt/NegSqrtKernel.h b/onert-micro/onert-micro/include/test_models/sqrt/NegSqrtKernel.h
new file mode 100644 (file)
index 0000000..b7716ab
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SQRT_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SQRT_KERNEL_H
+
+#include "TestDataSqrtBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Sqrt Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Sqrt
+ *            |
+ *      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,
+  0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 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 NegTestDataInputOutputTypeMismatchSqrtKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSqrtKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSqrtKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SQRT_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/sqrt/TestDataSqrtBase.h b/onert-micro/onert-micro/include/test_models/sqrt/TestDataSqrtBase.h
new file mode 100644 (file)
index 0000000..ca8b54a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SQRT_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_SQRT_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataSqrtBase : public TestDataBase<T>
+{
+public:
+  TestDataSqrtBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SQRT_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/square/FloatSquareKernel.h b/onert-micro/onert-micro/include/test_models/square/FloatSquareKernel.h
new file mode 100644 (file)
index 0000000..7be1d90
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_SQUARE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_SQUARE_KERNEL_H
+
+#include "TestDataSquareBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace square_float
+{
+/*
+ * Square Kernel:
+ *
+ *      Input(1, 3, 3, 2)
+ *            |
+ *           Square
+ *            |
+ *      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, 0x42, 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,
+  0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 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.40094518661499,    -2.4671132564544678, -1.7699997425079346,  -9.150614738464355,
+  2.7930896282196045,  -2.115478992462158,  -2.631648302078247,   -2.829446792602539,
+  -4.645663261413574,  9.3477144241333,     -0.36478859186172485, 7.513015270233154,
+  6.249550819396973,   -4.590481281280518,  9.549201965332031,    7.113796234130859,
+  -3.2525429725646973, 4.204875946044922};
+
+const std::vector<float> reference_output_data = {
+  19.368318557739258,  6.086647987365723,  3.132899045944214, 83.73374938964844,  7.801349639892578,
+  4.475251197814941,   6.925572872161865,  8.005768775939941, 21.58218765258789,  87.37976837158203,
+  0.13307072222232819, 56.44540023803711,  39.056884765625,   21.072519302368164, 91.187255859375,
+  50.60609817504883,   10.579035758972168, 17.68098258972168};
+
+} // namespace square_float
+
+class TestDataFloatSquare : public TestDataSquareBase<float>
+{
+public:
+  TestDataFloatSquare()
+  {
+    _input_data = square_float::input_data;
+    _reference_output_data = square_float::reference_output_data;
+    _test_kernel_model_circle = square_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSquare() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_SQUARE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/square/NegSquareKernel.h b/onert-micro/onert-micro/include/test_models/square/NegSquareKernel.h
new file mode 100644 (file)
index 0000000..178ba6a
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SQUARE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SQUARE_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_input_output_type_mismatch_kernel
+{
+/*
+ * Square Kernel with input output type mismatch:
+ *
+ *      Input(1, 3, 3, 2) - Float32
+ *            |
+ *           Square
+ *            |
+ *      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, 0x42, 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,
+  0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 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 NegTestDataInputOutputTypeMismatchSquareKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchSquareKernel()
+  {
+    _test_kernel_model_circle = neg_input_output_type_mismatch_kernel::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchSquareKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SQUARE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/square/TestDataSquareBase.h b/onert-micro/onert-micro/include/test_models/square/TestDataSquareBase.h
new file mode 100644 (file)
index 0000000..232fa2e
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SQUARE_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_SQUARE_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataSquareBase : public TestDataBase<T>
+{
+public:
+  TestDataSquareBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SQUARE_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/squared_difference/FloatSquaredDifferenceKernel.h b/onert-micro/onert-micro/include/test_models/squared_difference/FloatSquaredDifferenceKernel.h
new file mode 100644 (file)
index 0000000..2a0d255
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SQUARED_DIFFERENCE_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_SQUARED_DIFFERENCE_KERNEL_FLOAT_H
+
+#include "TestDataSquaredDifferenceBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace squared_difference_float_with_broadcasting
+{
+
+/*
+ * SquaredDifference Kernel:
+ *
+ * Input_1(1, 4, 4, 3)   Input_2(1, 4, 4, 3)
+ *       \             /
+ *     SquaredDifference(with 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, 0x4c, 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, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63,
+  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 = {
+  33.44,     44.74834,  42.31354,  17.271736,  46.138657, 42.50795,  9.75354,   11.343542,
+  25.705894, 36.687202, 17.357473, 29.17235,   34.9576,   34.23016,  22.528538, 25.484097,
+  38.542297, 32.78322,  31.368523, 52.47518,   29.052322, 35.70844,  19.942907, 30.840899,
+  45.22654,  22.581013, 24.37784,  -7.1113133, 44.58411,  42.722954, 20.67068,  47.006798,
+  40.08999,  25.972889, 51.532227, 15.329674,  22.725258, 37.83095,  24.72808,  32.937607,
+  39.836365, 11.756248, 8.707649,  42.69889,   22.493517, 26.656416, 19.543903, 38.58926};
+const std::vector<float> input2_data = {
+  45.496315, 47.277058, 43.62587,  25.520176, 26.66666,  21.242783, 38.55497,  29.928194,
+  32.247902, 5.110588,  35.261402, 35.692963, 30.808405, 30.916706, 38.445484, 32.367344,
+  20.506172, 21.414955, 39.93972,  34.694054, 36.724403, 17.250431, 34.863686, 32.42676,
+  31.634842, 44.39825,  31.116629, 18.85633,  19.150063, 33.974716, 26.233631, 29.054287,
+  29.618658, 38.05911,  54.44181,  28.360674, 15.703876, 39.576363, 29.899979, 26.719788,
+  56.03285,  50.236435, 41.24733,  31.759392, 47.402603, 34.884254, 38.37292,  18.049467};
+const std::vector<float> reference_output_data = {
+  145.35477,  6.3944097, 1.7222056, 68.03676,  379.15863, 452.20734, 829.52234, 345.38928,
+  42.797863,  997.0826,  320.55066, 42.51839,  17.215816, 10.978975, 253.34918, 47.379093,
+  325.30182,  129.23741, 73.46542,  316.16852, 58.86083,  340.69806, 222.62962, 2.5149617,
+  184.73425,  475.99188, 45.41127,  674.31854, 646.8908,  76.53166,  30.946436, 322.29263,
+  109.648766, 146.0767,  8.465679,  169.80696, 49.29981,  3.0464592, 26.748528, 38.661274,
+  262.32608,  1480.7247, 1058.8308, 119.67264, 620.4626,  67.69733,  354.5319,  421.8831};
+
+} // namespace squared_difference_float_with_broadcasting
+
+class TestDataFloatSquaredDifference : public TestDataSquaredDifferenceBase<float>
+{
+public:
+  TestDataFloatSquaredDifference()
+  {
+
+    _input1_data = squared_difference_float_with_broadcasting::input1_data;
+    _input2_data = squared_difference_float_with_broadcasting::input2_data;
+    _reference_output_data = squared_difference_float_with_broadcasting::reference_output_data;
+    _test_kernel_model_circle =
+      squared_difference_float_with_broadcasting::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatSquaredDifference() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SQUARED_DIFFERENCE_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/squared_difference/NegSquaredDifferenceKernel.h b/onert-micro/onert-micro/include/test_models/squared_difference/NegSquaredDifferenceKernel.h
new file mode 100644 (file)
index 0000000..5ba4d3b
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SQUARED_DIFFERENCE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SQUARED_DIFFERENCE_KERNEL_H
+
+#include "TestDataSquaredDifferenceBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace inputs_type_mismatch
+{
+
+/*
+ * SquaredDifference Kernel with input type mismatch:
+ *
+ * Input_1(2, 5) - Float   Input_2(2, 1) - Int
+ *       \             /
+ *       SquaredDifference
+ *              |
+ *          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, 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, 0x4c, 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, 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, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63,
+  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 inputs_type_mismatch
+
+class NegTestDataInputsTypeMismatchSquaredDifference : public NegTestDataBase
+{
+public:
+  NegTestDataInputsTypeMismatchSquaredDifference()
+  {
+    _test_kernel_model_circle = inputs_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputsTypeMismatchSquaredDifference() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SQUARED_DIFFERENCE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/squared_difference/TestDataSquaredDifferenceBase.h b/onert-micro/onert-micro/include/test_models/squared_difference/TestDataSquaredDifferenceBase.h
new file mode 100644 (file)
index 0000000..dc4f533
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SQUARED_DIFFERENCE_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_SQUARED_DIFFERENCE_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataSquaredDifferenceBase : public TestDataBase<T>
+{
+public:
+  TestDataSquaredDifferenceBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SQUARED_DIFFERENCE_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/strided_slice/StridedSliceKernel.h b/onert-micro/onert-micro/include/test_models/strided_slice/StridedSliceKernel.h
new file mode 100644 (file)
index 0000000..e0a9330
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_STRIDED_SLICE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_STRIDED_SLICE_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_STRIDED_SLICE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/sub/FloatSubKernel.h b/onert-micro/onert-micro/include/test_models/sub/FloatSubKernel.h
new file mode 100644 (file)
index 0000000..d843bc2
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SUB_KERNEL_FLOAT_H
+#define ONERT_MICRO_TEST_MODELS_SUB_KERNEL_FLOAT_H
+
+#include "TestDataSubBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SUB_KERNEL_FLOAT_H
diff --git a/onert-micro/onert-micro/include/test_models/sub/IntSubKernel.h b/onert-micro/onert-micro/include/test_models/sub/IntSubKernel.h
new file mode 100644 (file)
index 0000000..11c3412
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SUB_KERNEL_INT_H
+#define ONERT_MICRO_TEST_MODELS_SUB_KERNEL_INT_H
+
+#include "TestDataSubBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SUB_KERNEL_INT_H
diff --git a/onert-micro/onert-micro/include/test_models/sub/NegSubKernel.h b/onert-micro/onert-micro/include/test_models/sub/NegSubKernel.h
new file mode 100644 (file)
index 0000000..6f32438
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_SUB_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_SUB_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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() final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_SUB_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/sub/TestDataSubBase.h b/onert-micro/onert-micro/include/test_models/sub/TestDataSubBase.h
new file mode 100644 (file)
index 0000000..ea7d3a8
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_SUB_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_SUB_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_SUB_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/tanh/FloatTanhKernel.h b/onert-micro/onert-micro/include/test_models/tanh/FloatTanhKernel.h
new file mode 100644 (file)
index 0000000..4e9d957
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_TANH_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_TANH_KERNEL_H
+
+#include "TestDataTanhBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_TANH_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/tanh/NegTanhKernel.h b/onert-micro/onert-micro/include/test_models/tanh/NegTanhKernel.h
new file mode 100644 (file)
index 0000000..cf12778
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_TANH_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_TANH_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_TANH_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/tanh/TestDataTanhBase.h b/onert-micro/onert-micro/include/test_models/tanh/TestDataTanhBase.h
new file mode 100644 (file)
index 0000000..0b7725e
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_TANH_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_TANH_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_TANH_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/transpose/NegTransposeKernel.h b/onert-micro/onert-micro/include/test_models/transpose/NegTransposeKernel.h
new file mode 100644 (file)
index 0000000..750960b
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_TRANSPOSE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_TRANSPOSE_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_transpose_wrong_perm_type
+{
+
+/*
+ * Transpose Kernel:
+ *
+ *  Input(3, 8, 1) FLOAT32   Perm([1, 2, 0]) UINT8
+ *               \                /
+ *                   Transpose
+ *                      |
+ *                Output(8, 1, 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,
+  0x44, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, 0x90, 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,
+  0x03, 0x00, 0x00, 0x00, 0x01, 0x02, 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, 0x03, 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};
+} // namespace neg_transpose_wrong_perm_type
+
+class NegTestDataWrongPermTypeTransposeKernel : public NegTestDataBase
+{
+public:
+  NegTestDataWrongPermTypeTransposeKernel()
+  {
+    _test_kernel_model_circle = neg_transpose_wrong_perm_type::test_kernel_model_circle;
+  }
+
+  ~NegTestDataWrongPermTypeTransposeKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_TRANSPOSE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/transpose/TransposeKernel.h b/onert-micro/onert-micro/include/test_models/transpose/TransposeKernel.h
new file mode 100644 (file)
index 0000000..73408c7
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_TRANSPOSE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_TRANSPOSE_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_TRANSPOSE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/transpose_conv/FloatTransposeConvKernel.h b/onert-micro/onert-micro/include/test_models/transpose_conv/FloatTransposeConvKernel.h
new file mode 100644 (file)
index 0000000..6c30b3f
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_TRANSPOSE_CONV_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_TRANSPOSE_CONV_KERNEL_H
+
+#include "TestDataTransposeConvBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace transpose_conv_float
+{
+/*
+ * TransposeConv Kernel:
+ *
+ * Input(1, 4, 4, 2)      Weights(1, 3, 3, 2)
+ *            |           |
+ *            TransposeConv
+ *                  |
+ *           Output(1, 4, 4, 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,
+  0xac, 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x48, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x98, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x80, 0xc0,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x00, 0x10, 0xc1, 0x00, 0x00, 0x20, 0xc1, 0x00, 0x00, 0x30, 0x41, 0x00, 0x00, 0x40, 0xc1,
+  0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0x60, 0x41, 0x00, 0x00, 0x70, 0xc1, 0x00, 0x00, 0x80, 0xc1,
+  0x00, 0x00, 0x88, 0x41, 0x00, 0x00, 0x90, 0xc1, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 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,
+  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, 0x31, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
+  0x34, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 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, 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, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x6b, 0x65, 0x72, 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, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x5f,
+  0x73, 0x68, 0x61, 0x70, 0x65, 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, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+  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.050506,   24.50502,  -2.1620092, -10.667578, -6.026517,    0.45524502, -9.493163, 11.918655,
+  0.89637375, 4.3721895, 15.263344,  4.124815,   -0.085579395, 12.434898,  8.761413,  -0.016460419,
+  14.467015,  7.194871,  8.063942,   -1.125905,  -3.0618992,   7.227646,   9.65494,   -7.4324093,
+  1.7922368,  2.179245,  2.5192776,  -8.438859,  5.4460173,    3.9627461,  5.714366,  -0.14670324};
+const std::vector<float> reference_output_data = {
+  -423.64435, -166.1708,  193.6256,  -206.75839, -683.60583, -257.56488, 359.98495, -445.70508,
+  -10.393387, -102.10723, 203.30502, -502.5265,  -330.8531,  199.97214,  188.26364, -245.66447};
+
+} // namespace transpose_conv_float
+
+class TestDataFloatTransposeConv : public TestDataTransposeConvBase<float>
+{
+public:
+  TestDataFloatTransposeConv()
+  {
+    _input_data = transpose_conv_float::input_data;
+    _reference_output_data = transpose_conv_float::reference_output_data;
+    _test_kernel_model_circle = transpose_conv_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatTransposeConv() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_TRANSPOSE_CONV_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/transpose_conv/NegTransposeConvKernel.h b/onert-micro/onert-micro/include/test_models/transpose_conv/NegTransposeConvKernel.h
new file mode 100644 (file)
index 0000000..c38ce61
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_TRANSPOSE_CONV_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_TRANSPOSE_CONV_KERNEL_H
+
+#include "TestDataTransposeConvBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_transpose_conv_input_type_mismatch
+{
+
+/*
+ * TransposeConv Kernel with input type mismatch (input_type should be equal to weight_type):
+ *
+ * Input(1, 4, 4, 2) - Float32   Weight(1, 3, 3, 2) - Int32
+ *                 \                       /
+ *                  \                     /
+ *                       TransposeConv
+ *                             |
+ *                      Output(1, 4, 4, 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,
+  0xac, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x98, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff,
+  0x05, 0x00, 0x00, 0x00, 0xfa, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0xf7, 0xff, 0xff, 0xff, 0xf6, 0xff, 0xff, 0xff, 0x0b, 0x00, 0x00, 0x00, 0xf4, 0xff, 0xff, 0xff,
+  0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf1, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff,
+  0x11, 0x00, 0x00, 0x00, 0xee, 0xff, 0xff, 0xff, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 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,
+  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, 0x31, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x70, 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, 0x04, 0x00, 0x00, 0x00, 0x04, 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,
+  0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff,
+  0x10, 0x00, 0x00, 0x00, 0x04, 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,
+  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,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x6f, 0x75, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 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, 0x43, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 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_transpose_conv_input_type_mismatch
+
+namespace neg_transpose_conv_invalid_input_shape
+{
+/*
+ * TransposeConv Kernel with invalid input shape (rank > 4):
+ *
+ * Input(1, 1, 4, 4, 2) - Float32   Weight(1, 3, 3, 2) - Float32
+ *                 \                       /
+ *                  \                     /
+ *                       TransposeConv
+ *                             |
+ *                      Output(1, 4, 4, 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,
+  0xac, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, 0x4c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x98, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xaa, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x80, 0xc0,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x00, 0x10, 0xc1, 0x00, 0x00, 0x20, 0xc1, 0x00, 0x00, 0x30, 0x41, 0x00, 0x00, 0x40, 0xc1,
+  0x00, 0x00, 0x50, 0x41, 0x00, 0x00, 0x60, 0x41, 0x00, 0x00, 0x70, 0xc1, 0x00, 0x00, 0x80, 0xc1,
+  0x00, 0x00, 0x88, 0x41, 0x00, 0x00, 0x90, 0xc1, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 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,
+  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, 0x31, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+  0x34, 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,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 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, 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, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x6b, 0x65, 0x72, 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,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x6f, 0x75, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x70, 0x65, 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, 0x43, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x43, 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_transpose_conv_invalid_input_shape
+
+class NegTestDataInputMismatchTransposeConvKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputMismatchTransposeConvKernel()
+  {
+    _test_kernel_model_circle = neg_transpose_conv_input_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputMismatchTransposeConvKernel() override = default;
+
+  const unsigned char *get_model_ptr() override final { return _test_kernel_model_circle; }
+
+protected:
+  const unsigned char *_test_kernel_model_circle;
+};
+
+class NegTestDataInvalidInputShapeTransposeConvKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInvalidInputShapeTransposeConvKernel()
+  {
+    _test_kernel_model_circle = neg_transpose_conv_invalid_input_shape::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInvalidInputShapeTransposeConvKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_TRANSPOSE_CONV_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/transpose_conv/TestDataTransposeConvBase.h b/onert-micro/onert-micro/include/test_models/transpose_conv/TestDataTransposeConvBase.h
new file mode 100644 (file)
index 0000000..3f99dc2
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_TRANSPOSE_CONV_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_TRANSPOSE_CONV_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataTransposeConvBase : public TestDataBase<T>
+{
+public:
+  TestDataTransposeConvBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_TRANSPOSE_CONV_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/unpack/FloatUnpackKernel.h b/onert-micro/onert-micro/include/test_models/unpack/FloatUnpackKernel.h
new file mode 100644 (file)
index 0000000..806f82d
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_FLOAT_SQRT_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_FLOAT_SQRT_KERNEL_H
+
+#include "TestDataUnpackBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace unpack_float
+{
+/*
+ * Unpack Kernel:
+ *
+ *        Input(2, 2, 3, 4)
+ *          |
+ *     Unpack(num=2, axis=0)
+ *     /                  \
+ * Output1(2, 3, 4)        Output1(2, 3, 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,
+  0x34, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0x88, 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, 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, 0x16, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+  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,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xac, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x3a, 0x31, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 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, 0x02, 0x00, 0x00, 0x00,
+  0x03, 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, 0x04, 0x00, 0x00, 0x00,
+  0x02, 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, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58,
+  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 = {
+  80.8925,     -4.4767537, 38.051624,  69.14668,  -23.124884,  -8.138234,  79.53351,   40.877926,
+  -12.0593405, 41.621094,  69.482895,  7.9741273, 3.7500796,   -80.87057,  10.576268,  -16.321995,
+  -12.388415,  -20.782156, 47.479202,  -56.73159, 81.99104,    70.61185,   32.652695,  -93.72114,
+  -75.67862,   -70.78546,  -42.199966, -12.66376, 21.785488,   -7.168219,  -19.772392, -17.600962,
+  64.1301,     -4.7490916, 76.81972,   -41.70657, -83.13318,   45.003937,  85.05216,   -29.184652,
+  40.685417,   -35.482887, -60.648735, -0.268777, -0.59301615, -19.212725, 87.67197,   -37.269848};
+const std::vector<float> reference_output_data_1 = {
+  80.8925,     -4.4767537, 38.051624, 69.14668,  -23.124884, -8.138234, 79.53351,  40.877926,
+  -12.0593405, 41.621094,  69.482895, 7.9741273, 3.7500796,  -80.87057, 10.576268, -16.321995,
+  -12.388415,  -20.782156, 47.479202, -56.73159, 81.99104,   70.61185,  32.652695, -93.72114};
+const std::vector<float> reference_output_data_2 = {
+  -75.67862, -70.78546,  -42.199966, -12.66376, 21.785488,   -7.168219,  -19.772392, -17.600962,
+  64.1301,   -4.7490916, 76.81972,   -41.70657, -83.13318,   45.003937,  85.05216,   -29.184652,
+  40.685417, -35.482887, -60.648735, -0.268777, -0.59301615, -19.212725, 87.67197,   -37.269848};
+
+} // namespace unpack_float
+
+class TestDataFloatUnpack : public TestDataUnpackBase<float>
+{
+public:
+  TestDataFloatUnpack()
+  {
+    _input_data = unpack_float::input_data;
+    _reference_output_data_1 = unpack_float::reference_output_data_1;
+    _reference_output_data_2 = unpack_float::reference_output_data_2;
+    _test_kernel_model_circle = unpack_float::test_kernel_model_circle;
+  }
+
+  ~TestDataFloatUnpack() override = default;
+};
+
+} // namespace test_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_FLOAT_SQRT_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/unpack/NegUnpackKernel.h b/onert-micro/onert-micro/include/test_models/unpack/NegUnpackKernel.h
new file mode 100644 (file)
index 0000000..1ea99db
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_UNPACK_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_UNPACK_KERNEL_H
+
+#include "TestDataUnpackBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+namespace neg_unpack_input_type_mismatch
+{
+
+/*
+ * Unpack Kernel with input type mismatch (input_type should be equal to output_type):
+ *
+ *        Input(2, 2, 3, 4) - Int32
+ *                  |
+ *         Unpack(num=2, axis=0)
+ *     /                        \
+ * Output1(2, 3, 4)-Float32        Output1(2, 3, 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,
+  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, 0x68, 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, 0x16, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+  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,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 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, 0xd4, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x6f, 0x66, 0x6d, 0x3a, 0x31, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 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, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x6f, 0x66, 0x6d, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x69, 0x66, 0x6d, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 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, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58,
+  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_unpack_input_type_mismatch
+
+class NegTestDataInputOutputTypeMismatchUnpackKernel : public NegTestDataBase
+{
+public:
+  NegTestDataInputOutputTypeMismatchUnpackKernel()
+  {
+    _test_kernel_model_circle = neg_unpack_input_type_mismatch::test_kernel_model_circle;
+  }
+
+  ~NegTestDataInputOutputTypeMismatchUnpackKernel() 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_UNPACK_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/unpack/TestDataUnpackBase.h b/onert-micro/onert-micro/include/test_models/unpack/TestDataUnpackBase.h
new file mode 100644 (file)
index 0000000..b7840c6
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_UNPACK_KERNEL_BASE_H
+#define ONERT_MICRO_TEST_MODELS_UNPACK_KERNEL_BASE_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+template <typename T> class TestDataUnpackBase : public TestDataBase<T>
+{
+public:
+  TestDataUnpackBase() = 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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_UNPACK_KERNEL_BASE_H
diff --git a/onert-micro/onert-micro/include/test_models/while/NegWhileKernel.h b/onert-micro/onert-micro/include/test_models/while/NegWhileKernel.h
new file mode 100644 (file)
index 0000000..ae775cb
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_NEG_WHILE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_NEG_WHILE_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_NEG_WHILE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/test_models/while/WhileKernel.h b/onert-micro/onert-micro/include/test_models/while/WhileKernel.h
new file mode 100644 (file)
index 0000000..3809381
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TEST_MODELS_WHILE_KERNEL_H
+#define ONERT_MICRO_TEST_MODELS_WHILE_KERNEL_H
+
+#include "test_models/TestDataBase.h"
+#include <cassert>
+
+namespace onert_micro
+{
+namespace test_model
+{
+
+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_model
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TEST_MODELS_WHILE_KERNEL_H
diff --git a/onert-micro/onert-micro/include/train/OMBackpropExecute.h b/onert-micro/onert-micro/include/train/OMBackpropExecute.h
new file mode 100644 (file)
index 0000000..01c4f70
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_BACKPROP_EXECUTE_H
+#define ONERT_MICRO_TRAIN_BACKPROP_EXECUTE_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeStorage.h"
+#include "train/OMBackpropExecuteArgs.h"
+#include "core/memory/OMRuntimeAllocator.h"
+
+namespace onert_micro
+{
+namespace train
+{
+
+struct OMBackpropExecute
+{
+  // Start execution of the backward graph
+  static OMStatus runBackward(const OMConfig &config, OMBackpropExecuteArgs &args,
+                              core::memory::OMRuntimeAllocator &allocator);
+};
+
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_BACKPROP_EXECUTE_H
diff --git a/onert-micro/onert-micro/include/train/OMBackpropExecuteArgs.h b/onert-micro/onert-micro/include/train/OMBackpropExecuteArgs.h
new file mode 100644 (file)
index 0000000..8e91d42
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_BACKPROP_ARGS_H
+#define ONERT_MICRO_TRAIN_BACKPROP_ARGS_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeContext.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeModule.h"
+#include "core/train/OMTrainingStorage.h"
+
+namespace onert_micro
+{
+namespace train
+{
+
+/*
+ * Args to execute backpropagation graph
+ */
+struct OMBackpropExecuteArgs
+{
+  core::OMRuntimeStorage &forward_storage;
+  core::OMRuntimeStorage &backward_storage;
+  core::OMRuntimeContext &backward_context;
+  bool is_last_layer;
+  uint16_t kernel_index;
+};
+
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_BACKPROP_ARGS_H
diff --git a/onert-micro/onert-micro/include/train/OMBackpropExecutionBuilder.h b/onert-micro/onert-micro/include/train/OMBackpropExecutionBuilder.h
new file mode 100644 (file)
index 0000000..c50b6ed
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_BACKPROP_EXECUTION_BUILDER_H
+#define ONERT_MICRO_BACKPROP_EXECUTION_BUILDER_H
+
+#include "core/reader/OMCircleReader.h"
+#include "core/OMKernelType.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeContext.h"
+#include "train/OMBackpropExecuteArgs.h"
+
+namespace onert_micro
+{
+namespace train
+{
+
+using KernelTrainFunc = OMStatus(const OMBackpropExecuteArgs &);
+
+#define REGISTER_TRAIN_KERNEL(builtin_operator, name) \
+  OMStatus train_kernel_Circle##name(const OMBackpropExecuteArgs &);
+#include "KernelsToTrain.lst"
+#undef REGISTER_TRAIN_KERNEL
+
+/*
+ * Class to registry kernels for execution of backward graph (calculation backpropagation)
+ * Kernels which will be register define in KernelsToTrain.lst current pal directory
+ */
+class KernelBuiltinTrainRegistry
+{
+public:
+  constexpr KernelBuiltinTrainRegistry() : _operator_train()
+  {
+#define REGISTER_TRAIN_KERNEL(builtin_operator, name)                        \
+  registerKernelTrain(core::OMBuilderID::BuiltinOperator_##builtin_operator, \
+                      train_kernel_Circle##name);
+
+#include "KernelsToTrain.lst"
+
+#undef REGISTER_TRAIN_KERNEL
+  }
+
+public:
+  OMStatus getKernelTrainFunc(core::OMBuilderID builderID, KernelTrainFunc **train_func) const
+  {
+    const auto builder_id_opcode = size_t(builderID);
+    assert(builder_id_opcode < size_t(core::OMBuilderID::BuiltinOperatorsSize));
+    if (builder_id_opcode >= size_t(core::OMBuilderID::BuiltinOperatorsSize))
+    {
+      *train_func = nullptr;
+      return UnknownError;
+    }
+    *train_func = _operator_train[builder_id_opcode];
+    return Ok;
+  }
+
+private:
+  constexpr void registerKernelTrain(core::OMBuilderID id, KernelTrainFunc *func)
+  {
+    assert(size_t(id) < size_t(core::OMBuilderID::BuiltinOperatorsSize));
+    _operator_train[size_t(id)] = func;
+  }
+
+private:
+  KernelTrainFunc *_operator_train[size_t(core::OMBuilderID::BuiltinOperatorsSize)];
+};
+
+// Global constexpr kernel builtin train
+constexpr KernelBuiltinTrainRegistry kernel_builtin_train;
+
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_BACKPROP_EXECUTION_BUILDER_H
diff --git a/onert-micro/onert-micro/include/train/losses_functions/CrossEntropy.h b/onert-micro/onert-micro/include/train/losses_functions/CrossEntropy.h
new file mode 100644 (file)
index 0000000..1b43aab
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_LOSSES_FUNCTIONS_CROSS_ENTROPY_H
+#define ONERT_MICRO_TRAIN_LOSSES_FUNCTIONS_CROSS_ENTROPY_H
+
+#include "OMStatus.h"
+
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace losses_functions
+{
+
+// Cross Entropy
+struct CrossEntropy
+{
+  // Calculate cross entropy error backpropagation between calculated and target data
+  static void calculateErrorBackpropagation(const uint32_t flat_size, const float *calculated_data,
+                                            const float *target_data, float *output_grad);
+};
+
+} // namespace losses_functions
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_LOSSES_FUNCTIONS_CROSS_ENTROPY_H
diff --git a/onert-micro/onert-micro/include/train/losses_functions/MSE.h b/onert-micro/onert-micro/include/train/losses_functions/MSE.h
new file mode 100644 (file)
index 0000000..52590ec
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_LOSSES_FUNCTIONS_MSE_H
+#define ONERT_MICRO_TRAIN_LOSSES_FUNCTIONS_MSE_H
+
+#include "OMStatus.h"
+
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace losses_functions
+{
+
+// MSE- Mean Square Error
+struct MSE
+{
+  // Calculate mean square error backpropagation between calculated and target data
+  static void calculateErrorBackpropagation(const uint32_t flat_size, const float *calculated_data,
+                                            const float *target_data, float *output_grad);
+};
+
+} // namespace losses_functions
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_LOSSES_FUNCTIONS_MSE_H
diff --git a/onert-micro/onert-micro/include/train/metrics/Accuracy.h b/onert-micro/onert-micro/include/train/metrics/Accuracy.h
new file mode 100644 (file)
index 0000000..5c54d65
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_METRICS_ACCURACY_H
+#define ONERT_MICRO_TRAIN_METRICS_ACCURACY_H
+
+#include "OMStatus.h"
+
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace metrics
+{
+
+// Accuracy metric
+struct Accuracy
+{
+  // Calculate accuracy metric between calculated and target data
+  static float calculateValue(const uint32_t flat_size, const float *calculated_data,
+                              const float *target_data);
+};
+
+} // namespace metrics
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_METRICS_ACCURACY_H
diff --git a/onert-micro/onert-micro/include/train/metrics/CrossEntropy.h b/onert-micro/onert-micro/include/train/metrics/CrossEntropy.h
new file mode 100644 (file)
index 0000000..207c413
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_METRICS_CROSS_ENTROPY_H
+#define ONERT_MICRO_TRAIN_METRICS_CROSS_ENTROPY_H
+
+#include "OMStatus.h"
+
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace metrics
+{
+
+struct CrossEntropy
+{
+  // Calculate cross entropy metric between calculated and target data
+  static float calculateValue(const uint32_t flat_size, const float *calculated_data,
+                              const float *target_data);
+};
+
+} // namespace metrics
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_METRICS_CROSS_ENTROPY_H
diff --git a/onert-micro/onert-micro/include/train/metrics/MAE.h b/onert-micro/onert-micro/include/train/metrics/MAE.h
new file mode 100644 (file)
index 0000000..2d37a50
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_METRICS_MAE_H
+#define ONERT_MICRO_TRAIN_METRICS_MAE_H
+
+#include "OMStatus.h"
+
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace metrics
+{
+
+struct MAE
+{
+  // Calculate mae metric between calculated and target data
+  static float calculateValue(const uint32_t flat_size, const float *calculated_data,
+                              const float *target_data);
+};
+
+} // namespace metrics
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_METRICS_MAE_H
diff --git a/onert-micro/onert-micro/include/train/metrics/MSE.h b/onert-micro/onert-micro/include/train/metrics/MSE.h
new file mode 100644 (file)
index 0000000..5d7a74f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_METRICS_MSE_H
+#define ONERT_MICRO_TRAIN_METRICS_MSE_H
+
+#include "OMStatus.h"
+
+#include <cstdint>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace metrics
+{
+
+struct MSE
+{
+  // Calculate mse metric between calculated and target data
+  static float calculateValue(const uint32_t flat_size, const float *calculated_data,
+                              const float *target_data);
+};
+
+} // namespace metrics
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_METRICS_MSE_H
diff --git a/onert-micro/onert-micro/include/train/tests/OMTestTrainBase.h b/onert-micro/onert-micro/include/train/tests/OMTestTrainBase.h
new file mode 100644 (file)
index 0000000..6a13c64
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_TEST_TRAIN_BASE_H
+#define ONERT_MICRO_TRAIN_TESTS_TEST_TRAIN_BASE_H
+
+#include <vector>
+#include <cstddef>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+
+template <typename T, typename U = T> class OMTestTrainBase
+{
+public:
+  virtual ~OMTestTrainBase() = default;
+
+  // Get ptr to trained model
+  virtual char *getModelPtr() = 0;
+
+  // Return model size
+  virtual size_t getModelSize() = 0;
+
+  // Return num train samples
+  virtual size_t getTrainNumSamples() = 0;
+
+  // Return num test samples
+  virtual size_t getTestNumSamples() = 0;
+
+  // Read train input data with cur size and cur offset
+  virtual std::vector<T> readTrainInputData(size_t size, size_t offset) = 0;
+
+  // Read train target data with cur size and cur offset
+  virtual std::vector<U> readTrainTargetData(size_t size, size_t offset) = 0;
+
+  // Read test input data with cur size and cur offset
+  virtual std::vector<T> readTestInputData(size_t size, size_t offset) = 0;
+
+  // Read test target data with cur size and cur offset
+  virtual std::vector<T> readTestTargetData(size_t size, size_t offset) = 0;
+};
+
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_TEST_TRAIN_BASE_H
diff --git a/onert-micro/onert-micro/include/train/tests/OMTestUtils.h b/onert-micro/onert-micro/include/train/tests/OMTestUtils.h
new file mode 100644 (file)
index 0000000..f92f600
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_TEST_UTILS_H
+#define ONERT_MICRO_TRAIN_TESTS_TEST_UTILS_H
+
+#include "OMTrainingInterpreter.h"
+#include "train/tests/OMTestTrainBase.h"
+
+#include <vector>
+#include <numeric>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+
+// Train training_interpreter using config params and OMTestTrainBase to obtain data
+template <typename T, typename U = T>
+OMStatus train(OMTrainingInterpreter &train_interpreter, OMConfig &config,
+               OMTestTrainBase<T, U> &test_base)
+{
+  OMStatus status = Ok;
+  const uint32_t training_epochs = config.training_context.epochs;
+  const uint32_t num_train_data_samples = test_base.getTrainNumSamples();
+  const uint32_t batch_size = config.training_context.batch_size;
+  const uint32_t input_size = train_interpreter.getInputSizeAt(0);
+  const uint32_t target_size = train_interpreter.getOutputSizeAt(0);
+  for (uint32_t e = 0; e < training_epochs; ++e)
+  {
+    config.training_context.num_epoch = e + 1;
+    uint32_t num_steps = num_train_data_samples / batch_size;
+    for (int i = 0; i < num_steps; ++i)
+    {
+      // Set batch size
+      uint32_t cur_batch_size = std::min(batch_size, num_train_data_samples - batch_size * i - 1);
+      cur_batch_size = std::max(1u, cur_batch_size);
+
+      config.training_context.batch_size = cur_batch_size;
+
+      // Read current input and target data
+      const uint32_t cur_input_size = sizeof(T) * input_size * cur_batch_size;
+      const uint32_t cur_target_size = sizeof(U) * target_size * cur_batch_size;
+      const uint32_t cur_input_offset = sizeof(T) * input_size * i * batch_size;
+      const uint32_t cur_target_offset = sizeof(U) * target_size * i * batch_size;
+
+      // Read input and target
+      std::vector<T> input_data = test_base.readTrainInputData(cur_input_size, cur_input_offset);
+      std::vector<U> target_data =
+        test_base.readTrainTargetData(cur_target_size, cur_target_offset);
+
+      // Set input and target
+      train_interpreter.setInput(reinterpret_cast<uint8_t *>(input_data.data()), 0);
+      train_interpreter.setTarget(reinterpret_cast<uint8_t *>(target_data.data()), 0);
+
+      // Train with current batch size
+      status = train_interpreter.trainSingleStep(config);
+      assert(status == Ok);
+      if (status != Ok)
+        return status;
+    }
+  }
+
+  return status;
+}
+
+// Evaluate trained model using metric and save result in metric_res
+template <typename T, typename U = T>
+OMStatus evaluate(OMTrainingInterpreter &train_interpreter, OMConfig &config,
+                  OMTestTrainBase<T, U> &test_base, OMMetrics metric, U *metric_res)
+{
+  OMStatus status = Ok;
+
+  // To store all calculated metrics values
+  std::vector<U> result_v;
+
+  const uint32_t num_test_data_samples = test_base.getTestNumSamples();
+  const uint32_t batch_size = 1;
+  const uint32_t input_size = train_interpreter.getInputSizeAt(0);
+  const uint32_t target_size = train_interpreter.getOutputSizeAt(0);
+  for (int i = 0; i < num_test_data_samples; ++i)
+  {
+    // Read current input and target data
+    const uint32_t cur_input_size = sizeof(T) * input_size;
+    const uint32_t cur_target_size = sizeof(U) * target_size;
+    const uint32_t cur_input_offset = sizeof(T) * input_size * i;
+    const uint32_t cur_target_offset = sizeof(U) * target_size * i;
+
+    // Read input and target
+    std::vector<T> input_data = test_base.readTestInputData(cur_input_size, cur_input_offset);
+    std::vector<U> target_data = test_base.readTestTargetData(cur_target_size, cur_target_offset);
+
+    // Set input and target
+    train_interpreter.setInput(reinterpret_cast<uint8_t *>(input_data.data()), 0);
+    train_interpreter.setTarget(reinterpret_cast<uint8_t *>(target_data.data()), 0);
+
+    U result = U(0);
+
+    status =
+      train_interpreter.evaluateMetric(metric, reinterpret_cast<void *>(&result), batch_size);
+    assert(status == Ok);
+    result_v.push_back(result);
+  }
+  // Calculate and save average values
+  *metric_res =
+    static_cast<U>(std::accumulate(result_v.begin(), result_v.end(), U(0)) / result_v.size());
+
+  return status;
+}
+
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_TEST_UTILS_H
diff --git a/onert-micro/onert-micro/include/train/tests/boston_housing_task/BostonHousingTask.h b/onert-micro/onert-micro/include/train/tests/boston_housing_task/BostonHousingTask.h
new file mode 100644 (file)
index 0000000..3cfc126
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_BOSTON_HOUSING_TASK_H
+#define ONERT_MICRO_TRAIN_TESTS_BOSTON_HOUSING_TASK_H
+
+#include "train/tests/OMTestTrainBase.h"
+#include "train/tests/models/boston_housing.h"
+#include "train/tests/boston_housing_task/data/test_target.h"
+#include "train/tests/boston_housing_task/data/test_input.h"
+#include "train/tests/boston_housing_task/data/train_target.h"
+#include "train/tests/boston_housing_task/data/train_input.h"
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+
+namespace
+{
+
+const size_t NUM_TRAIN_SAMPLES = 404;
+const size_t NUM_TEST_SAMPLES = 102;
+
+} // namespace
+
+template <typename T, typename U = T> class BostonHousingTask : public OMTestTrainBase<T, U>
+{
+public:
+  BostonHousingTask()
+  {
+    // Set model
+    _train_model_ptr.resize(models::boston_housing_model_size);
+    std::memcpy(_train_model_ptr.data(), models::boston_housing_model,
+                models::boston_housing_model_size);
+  }
+
+  // Get ptr to trained model
+  char *getModelPtr() final { return _train_model_ptr.data(); }
+
+  // Return model size
+  size_t getModelSize() final { return _train_model_ptr.size(); }
+
+  // Return num train samples
+  size_t getTrainNumSamples() final { return NUM_TRAIN_SAMPLES; };
+
+  // Return num test samples
+  size_t getTestNumSamples() final { return NUM_TEST_SAMPLES; }
+
+  // Read train input data with cur size and cur offset
+  std::vector<T> readTrainInputData(size_t size, size_t offset) final
+  {
+    std::vector<T> result(size);
+
+    auto *cur_ptr = data::train_input + offset;
+
+    std::memcpy(result.data(), cur_ptr, size);
+    return result;
+  }
+  // Read train target data with cur size and cur offset
+  std::vector<U> readTrainTargetData(size_t size, size_t offset) final
+  {
+    std::vector<T> result(size);
+
+    auto *cur_ptr = data::train_target + offset;
+
+    std::memcpy(result.data(), cur_ptr, size);
+    return result;
+  }
+
+  // Read test input data with cur size and cur offset
+  std::vector<T> readTestInputData(size_t size, size_t offset) final
+  {
+    std::vector<T> result(size);
+
+    auto *cur_ptr = data::test_input + offset;
+
+    std::memcpy(result.data(), cur_ptr, size);
+    return result;
+  }
+
+  // Read test target data with cur size and cur offset
+  std::vector<T> readTestTargetData(size_t size, size_t offset) final
+  {
+    std::vector<T> result(size);
+
+    auto *cur_ptr = data::test_target + offset;
+
+    std::memcpy(result.data(), cur_ptr, size);
+    return result;
+  }
+
+private:
+  std::vector<char> _train_model_ptr = {};
+};
+
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_BOSTON_HOUSING_TASK_H
diff --git a/onert-micro/onert-micro/include/train/tests/boston_housing_task/data/test_input.h b/onert-micro/onert-micro/include/train/tests/boston_housing_task/data/test_input.h
new file mode 100644 (file)
index 0000000..58d54ec
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TEST_INPUT_H
+#define ONERT_MICRO_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TEST_INPUT_H
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+namespace data
+{
+
+unsigned char test_input[] = {
+  0x43, 0xad, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xf2, 0xd2, 0x2d, 0x3f, 0x54, 0xe3, 0xcd, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x73, 0xd7, 0xea, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x00, 0x00, 0xda, 0x41,
+  0x66, 0x66, 0xe8, 0x41, 0x78, 0x7f, 0xfc, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0x20, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x31, 0x08, 0x0c, 0x3f, 0x4c, 0x37, 0xbd, 0x40, 0xcd, 0xcc, 0xb9, 0x42,
+  0x1b, 0x9e, 0x16, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xd8, 0x43, 0x66, 0x66, 0x8e, 0x41,
+  0x9a, 0x79, 0xc5, 0x43, 0x14, 0xae, 0x81, 0x41, 0x39, 0x28, 0x61, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x7b, 0x14, 0xa6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x03, 0x3f, 0x1f, 0x85, 0xbf, 0x40,
+  0x9a, 0x99, 0x35, 0x42, 0x8b, 0xfd, 0x99, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x60, 0x43,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x0a, 0xd7, 0x1b, 0x41, 0xbd, 0x00, 0xa3, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x80, 0x3f, 0x48, 0xe1, 0x1a, 0x3f,
+  0x00, 0x00, 0xc8, 0x40, 0x33, 0x33, 0xb9, 0x42, 0xf9, 0x31, 0xe6, 0x3f, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0xc3, 0x75, 0xa9, 0x43, 0x00, 0x00, 0xb0, 0x40,
+  0xd6, 0x73, 0x92, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x14, 0xae, 0x8f, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0xe3, 0xe5, 0x3e, 0x3b, 0xdf, 0xc3, 0x40, 0x33, 0x33, 0x63, 0x42, 0xae, 0xd8, 0x6f, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x77, 0x43, 0x00, 0x00, 0x94, 0x41, 0x33, 0x93, 0xc5, 0x43,
+  0x3d, 0x0a, 0x07, 0x41, 0xcd, 0x23, 0x8f, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x0a, 0x1b, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x8f, 0xc2, 0x15, 0x3f, 0xcb, 0xa1, 0xbd, 0x40, 0x66, 0x66, 0x2a, 0x42,
+  0xc6, 0x6d, 0x18, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x80, 0xc3, 0x43, 0x9a, 0x99, 0x99, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xa4, 0x70, 0x59, 0x41, 0x2a, 0xc6, 0xf9, 0x3c, 0x00, 0x00, 0x5c, 0x42,
+  0x85, 0xeb, 0x71, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xce, 0xf7, 0x3e, 0xcf, 0xf7, 0xdb, 0x40,
+  0xcd, 0xcc, 0xe0, 0x41, 0x8f, 0xe4, 0xce, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xb9, 0x43,
+  0xcd, 0xcc, 0x8c, 0x41, 0x29, 0xfc, 0xc1, 0x43, 0x1f, 0x85, 0x93, 0x40, 0xef, 0x72, 0x11, 0x3d,
+  0x00, 0x00, 0xc8, 0x41, 0x1f, 0x85, 0x9b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xac, 0x1c, 0xda, 0x3e,
+  0x10, 0x58, 0xc5, 0x40, 0xcd, 0xcc, 0x3a, 0x42, 0x89, 0xd2, 0xac, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x8c, 0x43, 0x00, 0x00, 0x98, 0x41, 0xec, 0x51, 0xc3, 0x43, 0xec, 0x51, 0xf0, 0x40,
+  0x8b, 0x71, 0xbe, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0xcd, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x6a, 0xbc, 0x14, 0x3f, 0x83, 0xc0, 0xbe, 0x40, 0xcd, 0xcc, 0xb9, 0x42, 0xc5, 0x8f, 0x05, 0x40,
+  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3c, 0x43, 0xcd, 0xcc, 0x98, 0x41, 0x85, 0x0b, 0xbd, 0x43,
+  0xa4, 0x70, 0x8f, 0x41, 0x41, 0x65, 0x64, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xe1, 0x7a, 0x14, 0x3f, 0xe7, 0xfb, 0xcd, 0x40, 0x00, 0x00, 0x96, 0x42,
+  0x42, 0x60, 0x39, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x5c, 0xaf, 0xc4, 0x43, 0x8f, 0xc2, 0x65, 0x41, 0x10, 0x40, 0x6a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xc3, 0xf5, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0x05, 0x3f, 0xc3, 0xf5, 0xcc, 0x40,
+  0xcd, 0xcc, 0xaa, 0x42, 0xa5, 0xbd, 0x2d, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x43,
+  0x33, 0x33, 0xa7, 0x41, 0x9a, 0x99, 0x8d, 0x42, 0x7b, 0x14, 0x2a, 0x41, 0x77, 0x67, 0xad, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0xd3, 0x4d, 0xc2, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x9a, 0x99, 0x85, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0x71, 0x5d, 0xbc, 0x43, 0xd7, 0xa3, 0x50, 0x41,
+  0xaa, 0x65, 0x0b, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x77, 0xbe, 0x1f, 0x3f, 0xfe, 0xd4, 0xc4, 0x40, 0xcd, 0xcc, 0xc3, 0x42, 0xf6, 0x97, 0xd5, 0x3f,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x14, 0xae, 0x93, 0x41, 0x3a, 0x75, 0x65, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x1d, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x23, 0xdb, 0xf9, 0x3e, 0x8d, 0x97, 0xfa, 0x40, 0x66, 0x66, 0x56, 0x42,
+  0xb1, 0xbf, 0x4c, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x41, 0x43, 0x66, 0x66, 0x8e, 0x41,
+  0xa4, 0x50, 0xc4, 0x43, 0x66, 0x66, 0x8e, 0x40, 0x6d, 0xc5, 0x40, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x2f, 0x1d, 0x3f, 0x6a, 0xbc, 0xb4, 0x40,
+  0x33, 0x33, 0xaf, 0x42, 0xec, 0xc0, 0xf9, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x66, 0xc6, 0x91, 0x43, 0x9a, 0x99, 0x61, 0x41, 0x33, 0xfe, 0xad, 0x3e,
+  0x00, 0x00, 0xb0, 0x41, 0x1f, 0x85, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0xac, 0xdc, 0x3e,
+  0xbc, 0x74, 0xc3, 0x40, 0x9a, 0x99, 0x0b, 0x42, 0x54, 0xe3, 0x00, 0x41, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0xa5, 0x43, 0xcd, 0xcc, 0x98, 0x41, 0x0a, 0x17, 0xc3, 0x43, 0x5c, 0x8f, 0x12, 0x41,
+  0xa9, 0xc1, 0xb4, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x2c, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xbc, 0x74, 0xd3, 0x3e, 0x10, 0x58, 0xcd, 0x40, 0x33, 0x33, 0xd3, 0x40, 0x90, 0x31, 0xa9, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x98, 0x43, 0x9a, 0x99, 0x99, 0x41, 0x71, 0xdd, 0xbf, 0x43,
+  0x3d, 0x0a, 0xd7, 0x40, 0x4b, 0x1f, 0x3a, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x29, 0x5c, 0x4f, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x1f, 0x85, 0xeb, 0x3e, 0xa6, 0x9b, 0xc4, 0x40, 0xcd, 0xcc, 0x00, 0x42,
+  0x88, 0xf4, 0xbb, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0xd7, 0x43, 0x33, 0x33, 0x87, 0x41,
+  0xf6, 0x48, 0xb8, 0x43, 0xa4, 0x70, 0x11, 0x41, 0xd1, 0x22, 0xb6, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x3f, 0x15, 0x3f, 0xe3, 0xa5, 0xc3, 0x40,
+  0x9a, 0x99, 0x9f, 0x42, 0x07, 0xf0, 0x62, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x0a, 0x57, 0xc4, 0x43, 0x14, 0xae, 0x6f, 0x41, 0xe6, 0x74, 0xa6, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x80, 0x3f, 0xb8, 0x1e, 0x45, 0x3f,
+  0x62, 0x10, 0xc4, 0x40, 0xcd, 0xcc, 0xa6, 0x42, 0xb8, 0x40, 0x2e, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x0a, 0xb7, 0xc5, 0x43, 0x14, 0xae, 0x37, 0x41,
+  0xd9, 0x5f, 0x70, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x1b, 0x2f, 0x1d, 0x3f, 0x5e, 0xba, 0xa9, 0x40, 0x9a, 0x99, 0xc2, 0x42, 0xde, 0x71, 0x06, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x71, 0xbd, 0xae, 0x43,
+  0xae, 0x47, 0xc7, 0x41, 0x88, 0xf4, 0x43, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x06, 0x81, 0x15, 0x3f, 0xb4, 0xc8, 0xba, 0x40, 0xcd, 0xcc, 0x6e, 0x42,
+  0x5b, 0xb1, 0xff, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x33, 0x33, 0xc5, 0x41, 0x3d, 0x0a, 0x7b, 0x41, 0x9f, 0x8e, 0xc7, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x52, 0xb8, 0xbe, 0x40, 0x00, 0x00, 0x00, 0x00, 0xee, 0x7c, 0xff, 0x3e, 0x79, 0xe9, 0xba, 0x40,
+  0x9a, 0x99, 0x75, 0x42, 0x83, 0x2f, 0x58, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x8b, 0x43,
+  0x9a, 0x99, 0x99, 0x41, 0xae, 0xc7, 0xbc, 0x43, 0x5c, 0x8f, 0x36, 0x41, 0x03, 0xec, 0x43, 0x3e,
+  0x00, 0x00, 0xb0, 0x41, 0x1f, 0x85, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0xac, 0xdc, 0x3e,
+  0x29, 0x5c, 0xb3, 0x40, 0x66, 0x66, 0x8c, 0x42, 0x8a, 0x8e, 0xfe, 0x40, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0xa5, 0x43, 0xcd, 0xcc, 0x98, 0x41, 0xa4, 0x90, 0xc2, 0x43, 0x14, 0xae, 0x93, 0x41,
+  0x7a, 0x53, 0x11, 0x3d, 0x00, 0x00, 0xa0, 0x42, 0xc3, 0xf5, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x39, 0xb4, 0xc8, 0x3e, 0x31, 0x08, 0xbc, 0x40, 0xcd, 0xcc, 0x98, 0x41, 0x59, 0x86, 0x13, 0x41,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x80, 0x9d, 0x43, 0x33, 0x33, 0x83, 0x41, 0x0a, 0x97, 0xc5, 0x43,
+  0x00, 0x00, 0x14, 0x41, 0x4a, 0x5e, 0xba, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x27, 0x31, 0x08, 0x3f, 0x77, 0xbe, 0xc7, 0x40, 0x66, 0x66, 0x81, 0x42,
+  0x18, 0x26, 0x5b, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x0a, 0xd7, 0x2b, 0x41, 0xa1, 0xa1, 0x1f, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x80, 0x3f, 0xc1, 0xca, 0x01, 0x3f, 0xc5, 0x20, 0xdc, 0x40,
+  0x66, 0x66, 0x9b, 0x42, 0x16, 0x6a, 0x51, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43,
+  0x33, 0x33, 0x8b, 0x41, 0xec, 0x31, 0xc3, 0x43, 0x48, 0xe1, 0x1e, 0x41, 0x54, 0x00, 0x8c, 0x3c,
+  0x00, 0x00, 0xb4, 0x42, 0xae, 0x47, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0xd1, 0x3e,
+  0xc7, 0x4b, 0xd7, 0x40, 0x66, 0x66, 0x10, 0x42, 0x25, 0x06, 0x42, 0x41, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0x3b, 0x43, 0x00, 0x00, 0x88, 0x41, 0xe1, 0x3a, 0xc0, 0x43, 0x00, 0x00, 0x90, 0x40,
+  0x18, 0x6c, 0x15, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xf2, 0xd2, 0x2d, 0x3f, 0xf6, 0x28, 0xcc, 0x40, 0x33, 0x33, 0xbf, 0x42, 0xfa, 0xed, 0xfb, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x48, 0xe1, 0x72, 0x42,
+  0xd7, 0xa3, 0xc0, 0x41, 0x11, 0x1e, 0x6d, 0x3d, 0x00, 0x00, 0x48, 0x41, 0x71, 0x3d, 0xc2, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0xd1, 0x3e, 0x93, 0x18, 0xbc, 0x40, 0x33, 0x33, 0xab, 0x41,
+  0x9e, 0xef, 0xcf, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xac, 0x43, 0x33, 0x33, 0x97, 0x41,
+  0xe1, 0x1a, 0xc6, 0x43, 0x9a, 0x99, 0x01, 0x41, 0xe8, 0xbc, 0x06, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xf6, 0x28, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x31, 0x08, 0x0c, 0x3f, 0xcb, 0xa1, 0xc5, 0x40,
+  0x00, 0x00, 0x91, 0x42, 0xf5, 0xb9, 0x2e, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xd8, 0x43,
+  0x66, 0x66, 0x8e, 0x41, 0x66, 0xa6, 0xc4, 0x43, 0xd7, 0xa3, 0x40, 0x41, 0x2e, 0xff, 0x20, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x06, 0x81, 0x15, 0x3f,
+  0xf0, 0xa7, 0xda, 0x40, 0x9a, 0x99, 0xbc, 0x42, 0x12, 0xa5, 0x05, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xf6, 0xa8, 0xa2, 0x42, 0x1f, 0x85, 0x9d, 0x41,
+  0x40, 0xf6, 0x7a, 0x3d, 0x00, 0x00, 0x20, 0x42, 0xb8, 0x1e, 0xcd, 0x40, 0x00, 0x00, 0x80, 0x3f,
+  0x2f, 0xdd, 0xe4, 0x3e, 0x98, 0x6e, 0xda, 0x40, 0xcd, 0xcc, 0xdc, 0x41, 0x0f, 0x9c, 0x9b, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x7e, 0x43, 0xcd, 0xcc, 0x8c, 0x41, 0x9a, 0xb9, 0xc4, 0x43,
+  0xb8, 0x1e, 0x85, 0x40, 0x51, 0x14, 0x48, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x2c, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xbc, 0x74, 0xd3, 0x3e, 0x0a, 0xd7, 0xc7, 0x40, 0x66, 0x66, 0xc6, 0x40,
+  0x90, 0x31, 0xa9, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x98, 0x43, 0x9a, 0x99, 0x99, 0x41,
+  0xc3, 0x95, 0xbc, 0x43, 0xae, 0x47, 0xf1, 0x40, 0x9c, 0x33, 0x51, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x7a, 0x14, 0x3f, 0xe5, 0xd0, 0xb6, 0x40,
+  0xcd, 0xcc, 0x62, 0x42, 0x80, 0xb7, 0x34, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xf6, 0x28, 0x6c, 0x41, 0xdc, 0xc6, 0xb4, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xb3, 0x42, 0xee, 0x5a, 0xc2, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x85, 0xeb, 0xff, 0x41,
+  0x5d, 0xf9, 0x2e, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xdb, 0xf9, 0x5e, 0x3f, 0xa0, 0x1a, 0xb3, 0x40, 0xcd, 0xcc, 0xbd, 0x42, 0x23, 0x4a, 0xc3, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0xcd, 0xec, 0xaf, 0x43,
+  0x9a, 0x99, 0xab, 0x41, 0x93, 0x6f, 0xe6, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x1a, 0x3f, 0x62, 0x10, 0xbc, 0x40, 0x66, 0x66, 0x9e, 0x42,
+  0xf2, 0x41, 0x1b, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41,
+  0x29, 0x9c, 0x63, 0x43, 0x71, 0x3d, 0x42, 0x41, 0xbd, 0xfb, 0xe3, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x85, 0xeb, 0xdd, 0x41, 0x00, 0x00, 0x00, 0x00, 0x6d, 0xe7, 0x1b, 0x3f, 0xbc, 0x74, 0xbf, 0x40,
+  0x00, 0x00, 0xa7, 0x42, 0x9a, 0x08, 0x07, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0xc0, 0x31, 0x44,
+  0xcd, 0xcc, 0xa0, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x9a, 0x99, 0x55, 0x41, 0x81, 0xec, 0x75, 0x3c,
+  0x00, 0x00, 0xa0, 0x42, 0xd7, 0xa3, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x52, 0xb8, 0xde, 0x3e,
+  0xec, 0x51, 0xd4, 0x40, 0x9a, 0x99, 0xed, 0x41, 0x06, 0x81, 0x05, 0x41, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x8c, 0x43, 0x00, 0x00, 0x88, 0x41, 0x52, 0x78, 0xc3, 0x43, 0x14, 0xae, 0xbf, 0x40,
+  0x6f, 0xd3, 0x9f, 0x3c, 0x00, 0x00, 0x8c, 0x41, 0xd7, 0xa3, 0xb0, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x0f, 0x0b, 0xd5, 0x3e, 0xf8, 0x53, 0xe3, 0x40, 0x00, 0x00, 0x6e, 0x42, 0x00, 0x91, 0x13, 0x41,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x58, 0x43, 0xcd, 0xcc, 0x94, 0x41, 0xb8, 0x9e, 0xc4, 0x43,
+  0xcd, 0xcc, 0x00, 0x41, 0x1c, 0xf0, 0xf9, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x38, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0xe3, 0x3e, 0x00, 0x00, 0xd4, 0x40, 0x33, 0x33, 0x67, 0x42,
+  0x5b, 0xb1, 0x5f, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x8a, 0x43, 0x00, 0x00, 0x90, 0x41,
+  0x71, 0xfd, 0xb2, 0x43, 0xcd, 0xcc, 0xd4, 0x40, 0xf4, 0x43, 0x15, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f, 0x85, 0xeb, 0xc5, 0x40,
+  0x66, 0x66, 0xc5, 0x42, 0x0e, 0xbe, 0x10, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x3d, 0x0a, 0x91, 0x41, 0x5c, 0xac, 0x98, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x25, 0x06, 0x01, 0x3f,
+  0xb6, 0xf3, 0xf5, 0x40, 0x00, 0x00, 0x88, 0x41, 0xa3, 0x01, 0x58, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0x48, 0xc1, 0xbc, 0x43, 0x48, 0xe1, 0x7a, 0x40,
+  0xbe, 0xf6, 0xcc, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x1d, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x23, 0xdb, 0xf9, 0x3e, 0x19, 0x04, 0xd2, 0x40, 0x33, 0x33, 0xbf, 0x42, 0x3f, 0x35, 0x36, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x41, 0x43, 0x66, 0x66, 0x8e, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x8f, 0xc2, 0xb5, 0x40, 0x64, 0xaf, 0x77, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x1d, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x23, 0xdb, 0xf9, 0x3e, 0x60, 0xe5, 0xc4, 0x40, 0x9a, 0x99, 0x89, 0x42,
+  0x9b, 0xe6, 0x51, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x41, 0x43, 0x66, 0x66, 0x8e, 0x41,
+  0x14, 0x8e, 0xc1, 0x43, 0x66, 0x66, 0x52, 0x41, 0x7b, 0x6b, 0x60, 0x3d, 0x00, 0x00, 0x04, 0x42,
+  0x1f, 0x85, 0x0b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xa9, 0xf1, 0x3e, 0x46, 0xb6, 0xd3, 0x40,
+  0x66, 0x66, 0x68, 0x42, 0x14, 0xae, 0x57, 0x40, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0x5e, 0x43,
+  0x33, 0x33, 0x93, 0x41, 0x14, 0xae, 0xc4, 0x43, 0x48, 0xe1, 0x0e, 0x41, 0xf4, 0x1a, 0x7b, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f,
+  0x25, 0x06, 0xb9, 0x40, 0x66, 0x66, 0x8f, 0x42, 0xb0, 0x03, 0x81, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x98, 0x43, 0x33, 0x33, 0x93, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x3d, 0x0a, 0x7f, 0x41,
+  0xdc, 0x46, 0xba, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x2b, 0x87, 0x36, 0x3f, 0x7f, 0x6a, 0xd0, 0x40, 0xcd, 0xcc, 0xb3, 0x42, 0x6a, 0x4d, 0x33, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xf6, 0xe8, 0xc4, 0x43,
+  0xd7, 0xa3, 0x24, 0x41, 0xc1, 0xc5, 0x4a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x29, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x35, 0x5e, 0xfa, 0x3e, 0xf2, 0xd2, 0xc5, 0x40, 0x9a, 0x99, 0x29, 0x42,
+  0x6f, 0x81, 0x7c, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x8a, 0x43, 0xcd, 0xcc, 0x94, 0x41,
+  0xa4, 0xd0, 0xc4, 0x43, 0x1f, 0x85, 0x17, 0x41, 0x53, 0xcb, 0x56, 0x3c, 0x00, 0x00, 0xb4, 0x42,
+  0xf6, 0x28, 0x9c, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x04, 0x56, 0xce, 0x3e, 0xcf, 0xf7, 0xe7, 0x40,
+  0x33, 0x33, 0xaf, 0x41, 0x46, 0x25, 0x0b, 0x41, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x62, 0x43,
+  0x33, 0x33, 0x8f, 0x41, 0x0a, 0xf7, 0xc5, 0x43, 0x85, 0xeb, 0x99, 0x40, 0x2b, 0x6a, 0x10, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x52, 0xb8, 0x5e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e,
+  0xae, 0x47, 0xb9, 0x40, 0x00, 0x00, 0x68, 0x42, 0x71, 0x3d, 0xca, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x90, 0x43, 0x00, 0x00, 0x80, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xa4, 0x70, 0x7d, 0x41,
+  0x14, 0x3f, 0x39, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x33, 0x33, 0x33, 0x3f, 0xe9, 0x26, 0xa1, 0x40, 0x00, 0x00, 0xc2, 0x42, 0x5c, 0x8f, 0xe2, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xa4, 0x70, 0xcd, 0x41, 0xc0, 0x09, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f, 0x19, 0x04, 0xba, 0x40, 0x00, 0x00, 0xc8, 0x42,
+  0xe1, 0x0b, 0x83, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41,
+  0x1f, 0x45, 0xc5, 0x43, 0x3d, 0x0a, 0x9f, 0x41, 0xe8, 0x6a, 0xab, 0x3d, 0x00, 0x00, 0x34, 0x42,
+  0xf6, 0x28, 0x5c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e, 0x85, 0xeb, 0xe5, 0x40,
+  0x9a, 0x99, 0x1b, 0x42, 0x68, 0x22, 0x92, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc7, 0x43,
+  0x33, 0x33, 0x73, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xe1, 0x7a, 0xac, 0x40, 0xd5, 0xe7, 0x6a, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x14, 0xae, 0x8f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x54, 0xe3, 0xe5, 0x3e,
+  0xf6, 0x28, 0xd4, 0x40, 0x66, 0x66, 0x60, 0x42, 0xa3, 0x01, 0x8e, 0x40, 0x00, 0x00, 0x40, 0x40,
+  0x00, 0x00, 0x77, 0x43, 0x00, 0x00, 0x94, 0x41, 0x66, 0x26, 0xc4, 0x43, 0xc3, 0xf5, 0xd0, 0x40,
+  0x7a, 0xc7, 0x63, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x73, 0x68, 0x31, 0x3f, 0xdb, 0xf9, 0xca, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x1c, 0x7c, 0xc9, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x5c, 0x8f, 0xa2, 0x41, 0x17, 0x0e, 0x14, 0x3f, 0x00, 0x00, 0xa0, 0x41, 0x7b, 0x14, 0x7e, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x13, 0x3f, 0x83, 0xc0, 0x04, 0x41, 0x00, 0x00, 0x86, 0x42,
+  0x7f, 0xfb, 0x1a, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x84, 0x43, 0x00, 0x00, 0x50, 0x41,
+  0x1f, 0x45, 0xc0, 0x43, 0x7b, 0x14, 0xee, 0x40, 0xa1, 0x2d, 0x67, 0x3d, 0x00, 0x00, 0x20, 0x42,
+  0xb8, 0x1e, 0xcd, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x2f, 0xdd, 0xe4, 0x3e, 0x89, 0x41, 0xd8, 0x40,
+  0x9a, 0x99, 0x03, 0x42, 0xb3, 0x7b, 0x82, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x7e, 0x43,
+  0xcd, 0xcc, 0x8c, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x85, 0xeb, 0x61, 0x40, 0x39, 0xb9, 0xdf, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0xe2, 0x40, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x20, 0xf0, 0x3e,
+  0xd5, 0x78, 0xcd, 0x40, 0xcd, 0xcc, 0x9d, 0x42, 0x7c, 0xf2, 0x9e, 0x40, 0x00, 0x00, 0x00, 0x40,
+  0x00, 0x00, 0x72, 0x43, 0x66, 0x66, 0x8e, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x71, 0x3d, 0x12, 0x41,
+  0x53, 0xb3, 0x94, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x1b, 0x2f, 0x1d, 0x3f, 0x29, 0x5c, 0xdf, 0x40, 0x33, 0x33, 0x87, 0x42, 0x09, 0x1b, 0x22, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x0a, 0x57, 0xbb, 0x43,
+  0x5c, 0x8f, 0x3a, 0x41, 0xcf, 0x77, 0x0b, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f, 0x6f, 0x12, 0xcf, 0x40, 0x9a, 0x99, 0xc5, 0x42,
+  0xbd, 0xe3, 0xdc, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x71, 0xfd, 0xc3, 0x43, 0xc3, 0xf5, 0x88, 0x41, 0x47, 0x03, 0x67, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xd4, 0x18, 0x3f, 0x96, 0x43, 0xdb, 0x40,
+  0x00, 0x00, 0xc8, 0x42, 0x81, 0x95, 0xbb, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x29, 0x5c, 0x33, 0x43, 0x71, 0x3d, 0x9e, 0x41, 0xe0, 0xdb, 0x74, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x3d, 0x0a, 0x1b, 0x41, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xc2, 0x15, 0x3f,
+  0xa6, 0x9b, 0xc0, 0x40, 0x9a, 0x99, 0x82, 0x42, 0xb2, 0x2e, 0x1a, 0x40, 0x00, 0x00, 0xc0, 0x40,
+  0x00, 0x80, 0xc3, 0x43, 0x9a, 0x99, 0x99, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x52, 0xb8, 0x4e, 0x41,
+  0xbb, 0xf2, 0x39, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0xec, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x7f, 0x6a, 0xfc, 0x3e, 0x31, 0x08, 0xcc, 0x40, 0x33, 0x33, 0x59, 0x42, 0xf5, 0x4a, 0x91, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x8f, 0x43, 0xcd, 0xcc, 0x9c, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x0a, 0xd7, 0xdb, 0x40, 0xe1, 0x62, 0x45, 0x3d, 0x00, 0x00, 0xa0, 0x42, 0xc3, 0xf5, 0x68, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x39, 0xb4, 0xc8, 0x3e, 0xbc, 0x74, 0xc3, 0x40, 0x00, 0x00, 0x00, 0x42,
+  0x59, 0x86, 0x13, 0x41, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x80, 0x9d, 0x43, 0x33, 0x33, 0x83, 0x41,
+  0xec, 0x71, 0xc4, 0x43, 0x71, 0x3d, 0xd2, 0x40, 0x13, 0xd5, 0xf0, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f, 0x10, 0x58, 0xcd, 0x40,
+  0x9a, 0x99, 0xc4, 0x42, 0x0a, 0xd7, 0x0b, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0xe1, 0x1a, 0x98, 0x43, 0xe1, 0x7a, 0x9a, 0x41, 0x61, 0x8e, 0x1e, 0x3d,
+  0x00, 0x00, 0x52, 0x42, 0x71, 0x3d, 0xaa, 0x40, 0x00, 0x00, 0x00, 0x00, 0x29, 0x5c, 0xcf, 0x3e,
+  0x21, 0xb0, 0xc6, 0x40, 0x66, 0x66, 0xfa, 0x41, 0x81, 0x26, 0xea, 0x40, 0x00, 0x00, 0xc0, 0x40,
+  0x00, 0x80, 0x92, 0x43, 0xcd, 0xcc, 0x84, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xe1, 0x7a, 0xe4, 0x40,
+  0x65, 0x70, 0x54, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0xdd, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x6d, 0xe7, 0x1b, 0x3f, 0xdb, 0xf9, 0xa2, 0x40, 0x00, 0x00, 0xc4, 0x42, 0xf5, 0x4a, 0xe9, 0x3f,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0xc0, 0x31, 0x44, 0xcd, 0xcc, 0xa0, 0x41, 0x0a, 0x37, 0x9f, 0x43,
+  0xa4, 0x70, 0xed, 0x41, 0x6a, 0x5e, 0xc8, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f, 0x81, 0x95, 0xbf, 0x40, 0x00, 0x00, 0xc8, 0x42,
+  0xcc, 0x5d, 0xcb, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xf6, 0x28, 0xd6, 0x41, 0x7c, 0x61, 0x76, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x80, 0x3f, 0xb8, 0x1e, 0x45, 0x3f, 0xd7, 0xa3, 0xcc, 0x40,
+  0x00, 0x00, 0xb6, 0x42, 0x32, 0x55, 0x20, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x85, 0xab, 0xc3, 0x43, 0xec, 0x51, 0x54, 0x41, 0xb7, 0x5d, 0xa8, 0x3d,
+  0x00, 0x00, 0xb0, 0x41, 0x1f, 0x85, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0xac, 0xdc, 0x3e,
+  0xbe, 0x9f, 0xde, 0x40, 0x9a, 0x99, 0xd9, 0x40, 0xd8, 0x81, 0x0e, 0x41, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0xa5, 0x43, 0xcd, 0xcc, 0x98, 0x41, 0x85, 0x0b, 0xc1, 0x43, 0x85, 0xeb, 0x61, 0x40,
+  0xa8, 0x3a, 0x81, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x27, 0x31, 0x08, 0x3f, 0xf8, 0x53, 0xc7, 0x40, 0x66, 0x66, 0xb5, 0x42, 0xee, 0x5a, 0x46, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x3d, 0xaa, 0xc5, 0x43,
+  0x85, 0xeb, 0x4d, 0x41, 0x58, 0xc5, 0x3b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0xdd, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x6d, 0xe7, 0x1b, 0x3f, 0x7d, 0x3f, 0xad, 0x40, 0x9a, 0x99, 0xc4, 0x42,
+  0xf2, 0xb0, 0xe0, 0x3f, 0x00, 0x00, 0x80, 0x40, 0x00, 0xc0, 0x31, 0x44, 0xcd, 0xcc, 0xa0, 0x41,
+  0x66, 0x06, 0xac, 0x43, 0x8f, 0xc2, 0xbf, 0x41, 0x87, 0xc4, 0xbd, 0x3d, 0x00, 0x00, 0x08, 0x42,
+  0x48, 0xe1, 0xc2, 0x40, 0x00, 0x00, 0x00, 0x00, 0x2d, 0xb2, 0xdd, 0x3e, 0x0a, 0xd7, 0xcf, 0x40,
+  0x33, 0x33, 0x93, 0x41, 0x02, 0xbc, 0xaf, 0x40, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x80, 0xa4, 0x43,
+  0xcd, 0xcc, 0x80, 0x41, 0x14, 0xce, 0xbf, 0x43, 0x52, 0xb8, 0x0a, 0x41, 0x1d, 0x94, 0xf0, 0x3d,
+  0x00, 0x00, 0x48, 0x41, 0x0a, 0xd7, 0xfb, 0x40, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x24, 0x06, 0x3f,
+  0xba, 0x49, 0xc0, 0x40, 0xcd, 0xcc, 0xa5, 0x42, 0x20, 0x41, 0xc7, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0x9b, 0x43, 0x33, 0x33, 0x73, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xec, 0x51, 0x54, 0x41,
+  0x60, 0x3c, 0x03, 0x3e, 0x00, 0x00, 0x48, 0x41, 0x71, 0x3d, 0xc2, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x73, 0x68, 0xd1, 0x3e, 0xec, 0x51, 0xbc, 0x40, 0x00, 0x00, 0x04, 0x42, 0x9e, 0xef, 0xcf, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xac, 0x43, 0x33, 0x33, 0x97, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xd7, 0xa3, 0x0c, 0x41, 0x7a, 0xe4, 0x0f, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x29, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x35, 0x5e, 0xfa, 0x3e, 0x00, 0x00, 0xcc, 0x40, 0x33, 0x33, 0x01, 0x42,
+  0x6f, 0x81, 0x7c, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x8a, 0x43, 0xcd, 0xcc, 0x94, 0x41,
+  0xae, 0xe7, 0xc0, 0x43, 0x7b, 0x14, 0x16, 0x41, 0xbe, 0xc1, 0x17, 0x3d, 0x00, 0x00, 0xa0, 0x41,
+  0xb8, 0x1e, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0xca, 0xc3, 0xe2, 0x3e, 0xdb, 0xf9, 0xde, 0x40,
+  0xcd, 0xcc, 0x14, 0x42, 0x95, 0xd4, 0xa7, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x58, 0x43,
+  0x66, 0x66, 0x6e, 0x41, 0x71, 0x1d, 0xc4, 0x43, 0x48, 0xe1, 0x92, 0x40, 0xd6, 0x56, 0x65, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3f,
+  0xf6, 0x28, 0x9c, 0x40, 0x00, 0x00, 0xc8, 0x42, 0xbc, 0x74, 0xcb, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xc3, 0x75, 0xba, 0x43, 0xc3, 0xf5, 0xf4, 0x41,
+  0xd5, 0x78, 0x09, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x25, 0x06, 0x01, 0x3f, 0x5a, 0x64, 0xbf, 0x40, 0x33, 0x33, 0x88, 0x42, 0xdb, 0xf9, 0x6a, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0xcd, 0x2c, 0xbd, 0x43,
+  0x66, 0x66, 0x3a, 0x41, 0x17, 0xbc, 0x08, 0x3f, 0x00, 0x00, 0xa0, 0x41, 0x7b, 0x14, 0x7e, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcb, 0xa1, 0x25, 0x3f, 0xd7, 0xa3, 0xf0, 0x40, 0xcd, 0xcc, 0xb2, 0x42,
+  0x7c, 0xf2, 0x08, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x84, 0x43, 0x00, 0x00, 0x50, 0x41,
+  0x5c, 0x2f, 0xc2, 0x43, 0xec, 0x51, 0xe8, 0x40, 0xa3, 0x06, 0x53, 0x3e, 0x00, 0x00, 0xb0, 0x41,
+  0x1f, 0x85, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0xac, 0xdc, 0x3e, 0xdb, 0xf9, 0xb2, 0x40,
+  0x00, 0x00, 0x99, 0x42, 0x8a, 0x8e, 0xfe, 0x40, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0xa5, 0x43,
+  0xcd, 0xcc, 0x98, 0x41, 0xb8, 0x3e, 0xba, 0x43, 0x00, 0x00, 0x48, 0x41, 0xf3, 0x76, 0x1f, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x3d, 0x3f,
+  0x1f, 0x85, 0xcf, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x36, 0x3c, 0xfd, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x71, 0x5d, 0xc1, 0x43, 0xcd, 0xcc, 0x96, 0x41,
+  0x9e, 0xd2, 0x81, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x96, 0x43, 0x0b, 0x3f, 0x5c, 0x8f, 0xb6, 0x40, 0x66, 0x66, 0x9b, 0x42, 0xe1, 0x7a, 0x7c, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x98, 0x43, 0x33, 0x33, 0x93, 0x41, 0xc3, 0x35, 0xc6, 0x43,
+  0x00, 0x00, 0x38, 0x41, 0xea, 0x04, 0x14, 0x3e, 0x00, 0x00, 0x48, 0x41, 0x0a, 0xd7, 0xfb, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xdd, 0x24, 0x06, 0x3f, 0x06, 0x81, 0xc5, 0x40, 0x33, 0x33, 0xc0, 0x42,
+  0x7f, 0x6a, 0xbe, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x9b, 0x43, 0x33, 0x33, 0x73, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x33, 0x33, 0x99, 0x41, 0xd6, 0x56, 0x65, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x2f, 0x1d, 0x3f, 0xf8, 0x53, 0xc7, 0x40,
+  0x00, 0x00, 0xb0, 0x42, 0xec, 0xc0, 0xf9, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0xf6, 0xa8, 0xbf, 0x43, 0x8f, 0xc2, 0x51, 0x41, 0x70, 0xb1, 0xe2, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x5e, 0x41, 0x00, 0x00, 0x80, 0x3f, 0xcd, 0xcc, 0x0c, 0x3f,
+  0x98, 0x6e, 0xbe, 0x40, 0x9a, 0x99, 0xbb, 0x42, 0x4b, 0xea, 0x38, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0x8a, 0x43, 0x33, 0x33, 0x83, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x29, 0x5c, 0x8f, 0x41,
+  0x28, 0x44, 0x80, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x3e, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x21, 0xb0, 0x12, 0x3f, 0xdb, 0xf9, 0xd2, 0x40, 0x33, 0x33, 0x8a, 0x42, 0x62, 0xa1, 0x1e, 0x40,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x80, 0x88, 0x43, 0x00, 0x00, 0xa8, 0x41, 0xb8, 0xfe, 0xc3, 0x43,
+  0x52, 0xb8, 0x1a, 0x41, 0xaa, 0x65, 0xb7, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x27, 0x31, 0x08, 0x3f, 0xb6, 0xf3, 0xe1, 0x40, 0x00, 0x00, 0x9a, 0x42,
+  0x45, 0x47, 0x5a, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0xd7, 0xa3, 0xc5, 0x43, 0xec, 0x51, 0xe0, 0x40, 0xc1, 0xc5, 0x6a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x1e, 0xdd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x42, 0x60, 0xe5, 0x3e, 0xc3, 0xf5, 0xc0, 0x40,
+  0x00, 0x00, 0xab, 0x42, 0x91, 0x0f, 0xb6, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x69, 0x43,
+  0x33, 0x33, 0x8f, 0x41, 0xb8, 0x5e, 0xc4, 0x43, 0x66, 0x66, 0x96, 0x41, 0x6c, 0x5b, 0x94, 0x3d,
+  0x00, 0x00, 0x70, 0x42, 0xec, 0x51, 0xd8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x98, 0x6e, 0xd2, 0x3e,
+  0xba, 0x49, 0xbc, 0x40, 0x00, 0x00, 0x94, 0x41, 0x64, 0x5d, 0x2b, 0x41, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0xcd, 0x43, 0x66, 0x66, 0x92, 0x41, 0x3d, 0x2a, 0xc4, 0x43, 0xae, 0x47, 0xf9, 0x40,
+  0x96, 0x04, 0xe8, 0x3d, 0x00, 0x00, 0xf0, 0x41, 0x8f, 0xc2, 0x9d, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xd1, 0x22, 0xdb, 0x3e, 0x39, 0xb4, 0xdc, 0x40, 0x33, 0x33, 0x59, 0x42, 0x55, 0xc1, 0xca, 0x40,
+  0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x96, 0x43, 0xcd, 0xcc, 0x84, 0x41, 0x00, 0xa0, 0xc3, 0x43,
+  0x7b, 0x14, 0x36, 0x41, 0xb4, 0xe5, 0xbc, 0x3e, 0x00, 0x00, 0xb0, 0x41, 0x1f, 0x85, 0xbb, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0xac, 0xdc, 0x3e, 0xdd, 0x24, 0x04, 0x41, 0x66, 0x66, 0x06, 0x41,
+  0xd8, 0x81, 0x0e, 0x41, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0xa5, 0x43, 0xcd, 0xcc, 0x98, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x5c, 0x8f, 0x62, 0x40, 0xdb, 0x6d, 0x57, 0x3e, 0x00, 0x00, 0xa0, 0x41,
+  0xb8, 0x1e, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0xca, 0xc3, 0xe2, 0x3e, 0xe7, 0xfb, 0xd9, 0x40,
+  0xcd, 0xcc, 0x00, 0x42, 0xef, 0x38, 0x83, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x58, 0x43,
+  0x66, 0x66, 0x6e, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x33, 0x33, 0x9b, 0x40, 0x78, 0x0b, 0xd4, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xf9, 0x5e, 0x3f,
+  0x6d, 0xe7, 0xc3, 0x40, 0x9a, 0x99, 0xc2, 0x42, 0xa0, 0x1a, 0xcf, 0x3f, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0x66, 0x66, 0xba, 0x43, 0x9a, 0x99, 0x61, 0x41,
+  0xcb, 0xdb, 0x29, 0x3f, 0x00, 0x00, 0xa0, 0x41, 0x7b, 0x14, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcb, 0xa1, 0x25, 0x3f, 0xf0, 0xa7, 0xea, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x41, 0x82, 0xf2, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x84, 0x43, 0x00, 0x00, 0x50, 0x41, 0x1f, 0xa5, 0xbf, 0x43,
+  0xae, 0x47, 0xf9, 0x40, 0x9b, 0x5a, 0x5e, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x80, 0x3f, 0xd9, 0xce, 0x37, 0x3f, 0xe1, 0x7a, 0x0c, 0x41, 0xcd, 0xcc, 0xa5, 0x42,
+  0x36, 0xcd, 0xf3, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x66, 0x46, 0xb1, 0x43, 0xae, 0x47, 0xa9, 0x40, 0xc8, 0xb5, 0xa1, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0xae, 0x47, 0x4d, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e, 0x6a, 0xbc, 0xc8, 0x40,
+  0x00, 0x00, 0xc0, 0x40, 0x4a, 0x0c, 0x88, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc7, 0x43,
+  0x9a, 0x99, 0x95, 0x41, 0xc3, 0x75, 0xc5, 0x43, 0xc3, 0xf5, 0xd8, 0x40, 0xfa, 0xb8, 0xea, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x80, 0x3f, 0x48, 0xe1, 0x1a, 0x3f,
+  0xfc, 0xa9, 0xf9, 0x40, 0x66, 0x66, 0xc4, 0x42, 0xd4, 0x9a, 0x02, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0x14, 0xce, 0xc2, 0x43, 0x8f, 0xc2, 0xf5, 0x3f,
+  0x93, 0x57, 0xb7, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x80, 0x3f,
+  0xc1, 0xca, 0x01, 0x3f, 0x98, 0x6e, 0xde, 0x40, 0x00, 0x00, 0xb1, 0x42, 0x18, 0x26, 0x37, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0x9a, 0xd9, 0xc3, 0x43,
+  0x29, 0x5c, 0x1b, 0x41, 0xd1, 0x22, 0x3b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x1a, 0x3f, 0x64, 0x3b, 0xc3, 0x40, 0x00, 0x00, 0xba, 0x42,
+  0x3a, 0x23, 0x12, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41,
+  0xf6, 0x28, 0x70, 0x43, 0xc3, 0xf5, 0x1c, 0x41};
+
+} // namespace data
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TEST_INPUT_H
diff --git a/onert-micro/onert-micro/include/train/tests/boston_housing_task/data/test_target.h b/onert-micro/onert-micro/include/train/tests/boston_housing_task/data/test_target.h
new file mode 100644 (file)
index 0000000..8b7633c
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TEST_TARGET_H
+#define ONERT_MICRO_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TEST_TARGET_H
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+namespace data
+{
+
+unsigned char test_target[] = {
+  0x66, 0x66, 0xe6, 0x40, 0x66, 0x66, 0x96, 0x41, 0x00, 0x00, 0x98, 0x41, 0x00, 0x00, 0xd8, 0x41,
+  0x9a, 0x99, 0xb1, 0x41, 0x00, 0x00, 0xc4, 0x41, 0x9a, 0x99, 0xf9, 0x41, 0x33, 0x33, 0xb7, 0x41,
+  0x00, 0x00, 0xa4, 0x41, 0x9a, 0x99, 0xb9, 0x41, 0xcd, 0xcc, 0x94, 0x41, 0x00, 0x00, 0x68, 0x41,
+  0x66, 0x66, 0x8e, 0x41, 0x00, 0x00, 0x48, 0x42, 0x66, 0x66, 0xa6, 0x41, 0x66, 0x66, 0xc2, 0x41,
+  0x9a, 0x99, 0xc1, 0x41, 0x66, 0x66, 0x9e, 0x41, 0xcd, 0xcc, 0x98, 0x41, 0x9a, 0x99, 0xb5, 0x41,
+  0x00, 0x00, 0x40, 0x41, 0x33, 0x33, 0x23, 0x41, 0x00, 0x00, 0xa0, 0x41, 0x00, 0x00, 0x94, 0x41,
+  0x33, 0x33, 0xa7, 0x41, 0x00, 0x00, 0xb8, 0x41, 0x00, 0x00, 0xdc, 0x41, 0xcd, 0xcc, 0xf0, 0x41,
+  0x00, 0x00, 0x18, 0x41, 0x00, 0x00, 0xb0, 0x41, 0x9a, 0x99, 0xa9, 0x41, 0x9a, 0x99, 0x61, 0x41,
+  0x66, 0x66, 0x04, 0x42, 0x33, 0x33, 0xbb, 0x41, 0xcd, 0xcc, 0xa0, 0x41, 0xcd, 0xcc, 0xec, 0x40,
+  0x66, 0x66, 0x76, 0x41, 0x66, 0x66, 0xbe, 0x41, 0xcd, 0xcc, 0xa0, 0x41, 0x00, 0x00, 0xc4, 0x41,
+  0x00, 0x00, 0x04, 0x42, 0x33, 0x33, 0xe3, 0x41, 0x9a, 0x99, 0x61, 0x41, 0xcd, 0xcc, 0x3a, 0x42,
+  0x00, 0x00, 0x02, 0x42, 0xcd, 0xcc, 0xec, 0x41, 0x33, 0x33, 0xe3, 0x41, 0x66, 0x66, 0x9e, 0x41,
+  0x9a, 0x99, 0xa1, 0x41, 0x00, 0x00, 0xc8, 0x41, 0x9a, 0x99, 0x0d, 0x42, 0x66, 0x66, 0xa2, 0x41,
+  0x33, 0x33, 0x1b, 0x41, 0x00, 0x00, 0x68, 0x41, 0x9a, 0x99, 0x0b, 0x42, 0xcd, 0xcc, 0xd4, 0x41,
+  0x66, 0x66, 0xe6, 0x40, 0x00, 0x00, 0x48, 0x42, 0x9a, 0x99, 0x01, 0x42, 0xcd, 0xcc, 0xac, 0x41,
+  0x66, 0x66, 0xee, 0x41, 0x9a, 0x99, 0x51, 0x41, 0x00, 0x00, 0xdc, 0x41, 0x9a, 0x99, 0xa9, 0x41,
+  0xcd, 0xcc, 0xb8, 0x41, 0x33, 0x33, 0xaf, 0x41, 0x00, 0x00, 0x50, 0x41, 0x9a, 0x99, 0xb9, 0x41,
+  0x9a, 0x99, 0x01, 0x41, 0x33, 0x33, 0xb3, 0x40, 0x9a, 0x99, 0xad, 0x41, 0xcd, 0xcc, 0xec, 0x41,
+  0xcd, 0xcc, 0x9c, 0x41, 0x00, 0x00, 0xe0, 0x40, 0x33, 0x33, 0xd3, 0x41, 0x33, 0x33, 0x97, 0x41,
+  0x33, 0x33, 0xa7, 0x41, 0xcd, 0xcc, 0xe0, 0x41, 0x9a, 0x99, 0x0d, 0x42, 0x33, 0x33, 0x23, 0x41,
+  0x66, 0x66, 0xc2, 0x41, 0x66, 0x66, 0x2c, 0x42, 0xcd, 0xcc, 0x8c, 0x41, 0x66, 0x66, 0x76, 0x41,
+  0x9a, 0x99, 0x81, 0x41, 0xcd, 0xcc, 0xd8, 0x41, 0x33, 0x33, 0xab, 0x41, 0x00, 0x00, 0xac, 0x41,
+  0x33, 0x33, 0xb3, 0x41, 0x00, 0x00, 0xc8, 0x41, 0xcd, 0xcc, 0x84, 0x41, 0xcd, 0xcc, 0x94, 0x41,
+  0x00, 0x00, 0xb0, 0x41, 0x33, 0x33, 0x2b, 0x42, 0x66, 0x66, 0x0c, 0x42, 0x00, 0x00, 0xac, 0x41,
+  0x00, 0x00, 0x10, 0x42, 0x33, 0x33, 0xaf, 0x41, 0xcd, 0xcc, 0xc0, 0x41, 0x00, 0x00, 0x48, 0x42,
+  0x9a, 0x99, 0xd5, 0x41, 0x00, 0x00, 0xc8, 0x41};
+
+} // namespace data
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TEST_TARGET_H
diff --git a/onert-micro/onert-micro/include/train/tests/boston_housing_task/data/train_input.h b/onert-micro/onert-micro/include/train/tests/boston_housing_task/data/train_input.h
new file mode 100644 (file)
index 0000000..cdc8919
--- /dev/null
@@ -0,0 +1,1352 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TRAIN_INPUT_H
+#define ONERT_MICRO_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TRAIN_INPUT_H
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+namespace data
+{
+
+unsigned char train_input[] = {
+  0x62, 0xbe, 0x90, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x5e, 0xba, 0x09, 0x3f, 0xe5, 0xd0, 0xb6, 0x40, 0x33, 0x33, 0xbc, 0x42, 0xbc, 0x74, 0x87, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0xc3, 0x15, 0xb4, 0x43,
+  0xcd, 0xcc, 0xb4, 0x41, 0x80, 0x2b, 0x59, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x5a, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x35, 0x5e, 0xfa, 0x3e, 0x2b, 0x87, 0xe2, 0x40, 0x66, 0x66, 0x7c, 0x42,
+  0x2b, 0x87, 0x5a, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x87, 0x43, 0x66, 0x66, 0x8e, 0x41,
+  0xae, 0x07, 0xc6, 0x43, 0x66, 0x66, 0xb6, 0x40, 0x99, 0x64, 0xb4, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0x1f, 0x3f, 0x2b, 0x87, 0xce, 0x40,
+  0xcd, 0xcc, 0xc4, 0x42, 0x3f, 0xc6, 0xec, 0x3f, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xda, 0x43,
+  0x9a, 0x99, 0xa9, 0x41, 0x3d, 0x0a, 0xc5, 0x43, 0xa4, 0x70, 0x69, 0x41, 0x35, 0x5e, 0x0a, 0x3f,
+  0x00, 0x00, 0xa0, 0x41, 0x7b, 0x14, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x13, 0x3f,
+  0x3d, 0x0a, 0xef, 0x40, 0x66, 0x66, 0x52, 0x42, 0xd9, 0xce, 0x37, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0x84, 0x43, 0x00, 0x00, 0x50, 0x41, 0x66, 0x26, 0xc3, 0x43, 0x71, 0x3d, 0x4a, 0x40,
+  0xce, 0xaa, 0x0f, 0x3e, 0x00, 0x00, 0xb0, 0x41, 0x1f, 0x85, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0xac, 0xdc, 0x3e, 0x81, 0x95, 0xcf, 0x40, 0x00, 0x00, 0x50, 0x41, 0xc4, 0xb1, 0xec, 0x40,
+  0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0xa5, 0x43, 0xcd, 0xcc, 0x98, 0x41, 0xd7, 0x23, 0xc6, 0x43,
+  0xcd, 0xcc, 0xbc, 0x40, 0xc3, 0xb6, 0x05, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0x20, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x31, 0x08, 0x0c, 0x3f, 0x6d, 0xe7, 0xbb, 0x40, 0x33, 0x33, 0x92, 0x42,
+  0x5c, 0x8f, 0x1e, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xd8, 0x43, 0x66, 0x66, 0x8e, 0x41,
+  0xa4, 0x50, 0xa9, 0x43, 0x85, 0xeb, 0x75, 0x41, 0x8f, 0xe4, 0xb2, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x66, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f, 0xa0, 0x1a, 0xbf, 0x40,
+  0x66, 0x66, 0x99, 0x42, 0x5c, 0x8f, 0x46, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x98, 0x43,
+  0x33, 0x33, 0x93, 0x41, 0xb8, 0x1e, 0xc6, 0x43, 0x1f, 0x85, 0x1f, 0x41, 0xa7, 0x5c, 0x88, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0x45, 0x3f,
+  0x81, 0x95, 0xc3, 0x40, 0x9a, 0x99, 0xa2, 0x42, 0x18, 0x95, 0x20, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xb8, 0x5e, 0xc3, 0x43, 0x52, 0xb8, 0x4a, 0x41,
+  0x69, 0x57, 0x91, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x1e, 0x45, 0x3f, 0x6a, 0xbc, 0xcc, 0x40, 0x00, 0x00, 0xb0, 0x42, 0x30, 0x2a, 0x21, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xae, 0x47, 0xbb, 0x43,
+  0xae, 0x47, 0xf9, 0x40, 0x58, 0xad, 0x74, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f, 0x06, 0x81, 0xc1, 0x40, 0x9a, 0x99, 0xb1, 0x42,
+  0x41, 0x82, 0x8e, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41,
+  0xa4, 0x30, 0x99, 0x43, 0x71, 0x3d, 0x8a, 0x41, 0x0a, 0x9d, 0xe1, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x2f, 0x1d, 0x3f, 0xc7, 0x4b, 0xc3, 0x40,
+  0x33, 0x33, 0xaa, 0x42, 0x2c, 0x65, 0x01, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0xae, 0x47, 0x21, 0x40, 0xec, 0x51, 0xba, 0x41, 0x61, 0x4f, 0xbb, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x1a, 0x3f,
+  0xe3, 0xa5, 0xef, 0x40, 0x9a, 0x99, 0xb5, 0x42, 0x74, 0x46, 0xfc, 0x3f, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0x0a, 0x37, 0xbb, 0x43, 0xa4, 0x70, 0xdd, 0x3f,
+  0x67, 0x7e, 0x4d, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x5e, 0xba, 0x09, 0x3f, 0x8d, 0x97, 0xae, 0x40, 0x66, 0x66, 0x12, 0x42, 0xdb, 0xf9, 0x72, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0xb8, 0x7e, 0x90, 0x43,
+  0x3d, 0x0a, 0x3b, 0x41, 0x3c, 0xbd, 0x92, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0xcd, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x6a, 0xbc, 0x14, 0x3f, 0xc5, 0x20, 0xc0, 0x40, 0x33, 0x33, 0xa8, 0x42,
+  0x34, 0xa2, 0x0c, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3c, 0x43, 0xcd, 0xcc, 0x98, 0x41,
+  0xc3, 0xd5, 0xbc, 0x43, 0xec, 0x51, 0x64, 0x41, 0x18, 0x3e, 0x22, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x7b, 0x14, 0xa6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x03, 0x3f, 0x1b, 0x2f, 0xc1, 0x40,
+  0x00, 0x00, 0x0a, 0x42, 0x94, 0x87, 0xbf, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x60, 0x43,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xf6, 0x28, 0x00, 0x41, 0x67, 0x0a, 0xdd, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0x05, 0x3f,
+  0x71, 0x3d, 0xc6, 0x40, 0x9a, 0x99, 0x59, 0x42, 0x7a, 0xc7, 0x31, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0xc0, 0x43, 0x33, 0x33, 0xa7, 0x41, 0xb8, 0xbe, 0xc4, 0x43, 0x00, 0x00, 0x50, 0x41,
+  0x20, 0x98, 0xb2, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x2b, 0x87, 0x36, 0x3f, 0xb6, 0xf3, 0xcd, 0x40, 0xcd, 0xcc, 0xaf, 0x42, 0x11, 0x36, 0x14, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x48, 0x61, 0xc8, 0x42,
+  0x8f, 0xc2, 0x81, 0x41, 0x41, 0x2b, 0x30, 0x3d, 0x00, 0x00, 0xa0, 0x42, 0xe1, 0x7a, 0xf4, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xbc, 0x74, 0xd3, 0x3e, 0x4c, 0x37, 0xb5, 0x40, 0x33, 0x33, 0xaf, 0x41,
+  0x07, 0x5f, 0x29, 0x41, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0xa7, 0x43, 0x00, 0x00, 0xb0, 0x41,
+  0x66, 0x66, 0xbf, 0x43, 0xcd, 0xcc, 0x00, 0x41, 0xf0, 0x50, 0x0a, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f, 0x0e, 0x2d, 0xc6, 0x40,
+  0x33, 0x33, 0xb9, 0x42, 0x0b, 0x46, 0xe5, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x52, 0xb8, 0x72, 0x41, 0x4b, 0x02, 0x2c, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0x19, 0x04, 0xba, 0x40, 0x9a, 0x99, 0xb4, 0x42, 0xf2, 0xd2, 0x95, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0xa4, 0x70, 0xbc, 0x43, 0xc3, 0xf5, 0x6c, 0x41,
+  0x2a, 0x8c, 0x09, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xdb, 0xf9, 0x5e, 0x3f, 0x21, 0xb0, 0xb6, 0x40, 0x00, 0x00, 0xc5, 0x42, 0x05, 0xc5, 0xcf, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0x9a, 0xf9, 0x82, 0x43,
+  0xd7, 0xa3, 0x7c, 0x41, 0x9b, 0xfe, 0xac, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x81, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x5c, 0x8f, 0x02, 0x3f, 0xee, 0x7c, 0xbb, 0x40, 0x66, 0x66, 0x89, 0x42,
+  0xee, 0xeb, 0x2c, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x94, 0x43, 0xcd, 0xcc, 0x84, 0x41,
+  0x71, 0x9d, 0xc4, 0x43, 0x71, 0x3d, 0x1a, 0x41, 0x45, 0x9e, 0x9c, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x1a, 0x3f, 0x0e, 0x2d, 0xde, 0x40,
+  0xcd, 0xcc, 0xc2, 0x42, 0x5e, 0x4b, 0xf0, 0x3f, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43,
+  0x33, 0x33, 0x6b, 0x41, 0x0a, 0xb7, 0xb5, 0x43, 0x48, 0xe1, 0x92, 0x40, 0xef, 0xc9, 0xde, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3f,
+  0xe5, 0xd0, 0xb6, 0x40, 0x00, 0x00, 0xc2, 0x42, 0x8d, 0x97, 0xf6, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x0a, 0x37, 0xc5, 0x43, 0x48, 0xe1, 0x88, 0x41,
+  0xa1, 0x4a, 0x8d, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0xcd, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x6a, 0xbc, 0x14, 0x3f, 0x0a, 0xd7, 0xbb, 0x40, 0x66, 0x66, 0x8b, 0x42, 0x28, 0x7e, 0x10, 0x40,
+  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3c, 0x43, 0xcd, 0xcc, 0x98, 0x41, 0x33, 0x93, 0xc2, 0x43,
+  0x85, 0xeb, 0x65, 0x41, 0x5d, 0xbf, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40,
+  0x00, 0x00, 0x80, 0x3f, 0xc1, 0xca, 0x01, 0x3f, 0x7d, 0x3f, 0xc5, 0x40, 0x9a, 0x99, 0xb6, 0x42,
+  0x6f, 0x12, 0x43, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41,
+  0xb8, 0x9e, 0xc5, 0x43, 0x14, 0xae, 0xab, 0x41, 0x58, 0x56, 0x1a, 0x3d, 0x00, 0x00, 0xa0, 0x42,
+  0x5c, 0x8f, 0xc2, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x17, 0xd9, 0xce, 0x3e, 0x9c, 0xc4, 0xe8, 0x40,
+  0x33, 0x33, 0x19, 0x42, 0x54, 0xe3, 0xe9, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x80, 0xa4, 0x43,
+  0x9a, 0x99, 0x49, 0x41, 0x9a, 0x19, 0xc4, 0x43, 0x0a, 0xd7, 0xd3, 0x40, 0xa2, 0x9c, 0x20, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0x21, 0xb0, 0xba, 0x40, 0x00, 0x00, 0x62, 0x42, 0x88, 0xf4, 0x8f, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0x5c, 0xcf, 0xc5, 0x43, 0x1f, 0x85, 0x07, 0x41,
+  0xbe, 0x30, 0xa9, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xc1, 0xca, 0x01, 0x3f, 0x83, 0xc0, 0xc2, 0x40, 0x00, 0x00, 0x76, 0x42, 0xbb, 0xb8, 0x69, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0x00, 0x60, 0xbc, 0x43,
+  0x7b, 0x14, 0x2e, 0x41, 0xc7, 0xba, 0x31, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x2b, 0x3f, 0xf4, 0xfd, 0x9c, 0x40, 0x00, 0x00, 0xc8, 0x42,
+  0x30, 0x4c, 0x96, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x7b, 0x14, 0x0b, 0x42, 0x30, 0xaa, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f, 0x96, 0x43, 0xbb, 0x40,
+  0x9a, 0x99, 0x9b, 0x42, 0x1b, 0x0d, 0xc0, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x7b, 0x14, 0xa9, 0x43, 0x8f, 0xc2, 0xef, 0x41, 0x65, 0x70, 0x14, 0x3c,
+  0x00, 0x00, 0xb4, 0x42, 0x7b, 0x14, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0xcc, 0x3e,
+  0xe5, 0xd0, 0xe2, 0x40, 0x66, 0x66, 0xa6, 0x41, 0x67, 0xd5, 0xe9, 0x40, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x80, 0x8e, 0x43, 0xcd, 0xcc, 0x74, 0x41, 0x29, 0x5c, 0xc5, 0x43, 0x33, 0x33, 0xfb, 0x40,
+  0x6a, 0x87, 0xbf, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xdb, 0xf9, 0x5e, 0x3f, 0x91, 0xed, 0xac, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x8c, 0xb9, 0xcb, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0xcd, 0xcc, 0xaa, 0x43,
+  0xe1, 0x7a, 0x54, 0x41, 0x0e, 0x67, 0x5e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x29, 0x41,
+  0x00, 0x00, 0x80, 0x3f, 0x35, 0x5e, 0xfa, 0x3e, 0xf2, 0xd2, 0xb9, 0x40, 0x33, 0x33, 0x57, 0x42,
+  0x33, 0xc4, 0x69, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x8a, 0x43, 0xcd, 0xcc, 0x94, 0x41,
+  0x52, 0x78, 0xc3, 0x43, 0x71, 0x3d, 0x80, 0x41, 0x07, 0x88, 0x19, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f, 0x91, 0xed, 0xcc, 0x40,
+  0x00, 0x00, 0xc8, 0x42, 0xc1, 0xca, 0xd1, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x14, 0x0e, 0xbc, 0x43, 0xe1, 0x7a, 0xa2, 0x41, 0x59, 0x86, 0xcf, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xf2, 0xd2, 0x2d, 0x3f,
+  0x5e, 0xba, 0xa9, 0x40, 0x33, 0x33, 0xb2, 0x42, 0x48, 0xe1, 0xd2, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x52, 0xb8, 0xfe, 0x42, 0xb8, 0x1e, 0xd5, 0x41,
+  0xf8, 0xfc, 0x99, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x2b, 0x87, 0x36, 0x3f, 0x98, 0x6e, 0xd6, 0x40, 0x00, 0x00, 0xb4, 0x42, 0x71, 0x3d, 0x26, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xe1, 0x3a, 0x7f, 0x43,
+  0x29, 0x5c, 0x83, 0x41, 0x63, 0xd1, 0xb4, 0x3d, 0x00, 0x00, 0x48, 0x41, 0x0a, 0xd7, 0xfb, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xdd, 0x24, 0x06, 0x3f, 0x4e, 0x62, 0xc0, 0x40, 0x33, 0x33, 0x85, 0x42,
+  0x9e, 0xef, 0xb1, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x9b, 0x43, 0x33, 0x33, 0x73, 0x41,
+  0xcd, 0xcc, 0xc5, 0x43, 0x48, 0xe1, 0x46, 0x41, 0x65, 0xc2, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3f, 0xd7, 0xa3, 0xb0, 0x40,
+  0x00, 0x00, 0xc8, 0x42, 0x9f, 0x3c, 0xc4, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xe1, 0x7a, 0xc4, 0x41, 0x2d, 0xf8, 0x03, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f,
+  0x75, 0x93, 0xec, 0x40, 0x9a, 0x99, 0xc6, 0x42, 0x09, 0xf9, 0x1c, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x5c, 0xef, 0xbb, 0x43, 0x85, 0xeb, 0x85, 0x41,
+  0x7a, 0x70, 0xb5, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x80, 0x3f,
+  0x37, 0x89, 0x21, 0x3f, 0x23, 0xdb, 0xd5, 0x40, 0x9a, 0x99, 0xc1, 0x42, 0x58, 0xa8, 0xad, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x3d, 0xaa, 0xbb, 0x43,
+  0x52, 0xb8, 0x6e, 0x40, 0x39, 0xd6, 0x4c, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x3d, 0x3f, 0xf8, 0x53, 0xbb, 0x40, 0x33, 0x33, 0xc1, 0x42,
+  0x05, 0xa3, 0xf2, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x1f, 0x85, 0x70, 0x43, 0xec, 0x51, 0xbe, 0x41, 0x74, 0x46, 0x94, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x3d, 0x0a, 0x1b, 0x41, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xc2, 0x15, 0x3f, 0xe1, 0x7a, 0xac, 0x40,
+  0xcd, 0xcc, 0x91, 0x42, 0x43, 0x1c, 0x33, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x80, 0xc3, 0x43,
+  0x9a, 0x99, 0x99, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xb8, 0x1e, 0xa9, 0x41, 0x73, 0xd7, 0x87, 0x42,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f,
+  0x23, 0xdb, 0xb5, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x82, 0x73, 0xb6, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x29, 0x7c, 0xc0, 0x43, 0x0a, 0xd7, 0xb7, 0x41,
+  0xb0, 0xc9, 0x91, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xd9, 0xce, 0x37, 0x3f, 0x6d, 0xe7, 0x63, 0x40, 0xcd, 0xcc, 0xaf, 0x42, 0x56, 0x7d, 0xce, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x9a, 0x59, 0xb1, 0x43,
+  0x0a, 0xd7, 0xe3, 0x40, 0x28, 0x7e, 0x8c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x38, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0xe3, 0x3e, 0xdf, 0x4f, 0xed, 0x40, 0x00, 0x00, 0x7a, 0x42,
+  0x5b, 0xb1, 0x5f, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x8a, 0x43, 0x00, 0x00, 0x90, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x7b, 0x14, 0xc6, 0x40, 0x0d, 0x8e, 0x12, 0x3d, 0x00, 0x00, 0xa0, 0x41,
+  0xb8, 0x1e, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00, 0xca, 0xc3, 0xe2, 0x3e, 0x71, 0x3d, 0xfa, 0x40,
+  0x00, 0x00, 0x81, 0x42, 0xfb, 0x3a, 0x96, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x58, 0x43,
+  0x66, 0x66, 0x6e, 0x41, 0xae, 0xa7, 0xc1, 0x43, 0xd7, 0xa3, 0x70, 0x40, 0x58, 0x1c, 0xae, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0x1f, 0x3f,
+  0xf0, 0xa7, 0xce, 0x40, 0xcd, 0xcc, 0xc5, 0x42, 0x81, 0x95, 0x07, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x1f, 0x85, 0xc5, 0x43, 0x9a, 0x99, 0x49, 0x41,
+  0xf5, 0x67, 0x6b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x1e, 0x45, 0x3f, 0x81, 0x95, 0xab, 0x40, 0x66, 0x66, 0xc0, 0x42, 0x62, 0xa1, 0x06, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x1f, 0x65, 0xbe, 0x43,
+  0x3d, 0x0a, 0x23, 0x41, 0x23, 0x84, 0x87, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x29, 0x5c, 0x4f, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x1f, 0x85, 0xeb, 0x3e, 0xa8, 0xc6, 0xbb, 0x40, 0x66, 0x66, 0xce, 0x41,
+  0x01, 0xde, 0xa6, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0xd7, 0x43, 0x33, 0x33, 0x87, 0x41,
+  0x52, 0x38, 0xbf, 0x43, 0x1f, 0x85, 0x1f, 0x41, 0x9f, 0xb0, 0xc4, 0x3d, 0x00, 0x00, 0x20, 0x42,
+  0xb8, 0x1e, 0xcd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xdd, 0xe4, 0x3e, 0xf8, 0x53, 0xdb, 0x40,
+  0x33, 0x33, 0x2b, 0x42, 0xb9, 0x8d, 0x88, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x7e, 0x43,
+  0xcd, 0xcc, 0x8c, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x52, 0xb8, 0x3e, 0x40, 0x6d, 0x73, 0x63, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x31, 0x08, 0x0c, 0x3f,
+  0xaa, 0xf1, 0xc2, 0x40, 0xcd, 0xcc, 0xbe, 0x42, 0x6f, 0x12, 0x23, 0x40, 0x00, 0x00, 0xc0, 0x40,
+  0x00, 0x00, 0xd8, 0x43, 0x66, 0x66, 0x8e, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x52, 0xb8, 0x88, 0x41,
+  0x75, 0xab, 0xa7, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x38, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x0a, 0xd7, 0xe3, 0x3e, 0x71, 0x3d, 0xfa, 0x40, 0x9a, 0x99, 0x13, 0x42, 0x5b, 0xb1, 0x5f, 0x40,
+  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x8a, 0x43, 0x00, 0x00, 0x90, 0x41, 0xd7, 0xc3, 0xc4, 0x43,
+  0xe1, 0x7a, 0x64, 0x40, 0xd8, 0xf0, 0x94, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0x1f, 0x3f, 0x68, 0x91, 0xc5, 0x40, 0x33, 0x33, 0xbb, 0x42,
+  0xbd, 0x52, 0xce, 0x3f, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41,
+  0x3d, 0x0a, 0xc2, 0x43, 0xae, 0x47, 0xc1, 0x41, 0x20, 0x7b, 0xbd, 0x3d, 0x00, 0x00, 0xf0, 0x41,
+  0x8f, 0xc2, 0x9d, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x22, 0xdb, 0x3e, 0x5a, 0x64, 0xd3, 0x40,
+  0xcd, 0xcc, 0x28, 0x42, 0xa9, 0x13, 0xc6, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x96, 0x43,
+  0xcd, 0xcc, 0x84, 0x41, 0xd7, 0xe3, 0xbf, 0x43, 0x0a, 0xd7, 0xeb, 0x40, 0xb9, 0x88, 0x2f, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xdd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x42, 0x60, 0xe5, 0x3e,
+  0xf2, 0xd2, 0xb5, 0x40, 0x33, 0x33, 0x07, 0x42, 0x7a, 0x36, 0xa3, 0x40, 0x00, 0x00, 0x40, 0x40,
+  0x00, 0x00, 0x69, 0x43, 0x33, 0x33, 0x8f, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x29, 0x5c, 0x23, 0x41,
+  0x2d, 0x78, 0x31, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x0a, 0x1b, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x8f, 0xc2, 0x15, 0x3f, 0xbe, 0x9f, 0xb6, 0x40, 0x00, 0x00, 0x58, 0x42, 0xc6, 0x6d, 0x18, 0x40,
+  0x00, 0x00, 0xc0, 0x40, 0x00, 0x80, 0xc3, 0x43, 0x9a, 0x99, 0x99, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xf6, 0x28, 0x40, 0x41, 0x28, 0x49, 0x37, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x0a, 0x1b, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x8f, 0xc2, 0x15, 0x3f, 0xa4, 0x70, 0xb5, 0x40, 0x66, 0x66, 0xe6, 0x41,
+  0x43, 0x1c, 0x33, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x80, 0xc3, 0x43, 0x9a, 0x99, 0x99, 0x41,
+  0x1f, 0xa5, 0xc4, 0x43, 0xcd, 0xcc, 0x8c, 0x41, 0xf7, 0x1e, 0x2e, 0x3e, 0x00, 0x00, 0x48, 0x41,
+  0x0a, 0xd7, 0xfb, 0x40, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x24, 0x06, 0x3f, 0xc5, 0x20, 0xc0, 0x40,
+  0xcd, 0xcc, 0xab, 0x42, 0x7c, 0xf2, 0xd2, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x9b, 0x43,
+  0x33, 0x33, 0x73, 0x41, 0xe1, 0x5a, 0xc1, 0x43, 0xcd, 0xcc, 0x88, 0x41, 0x81, 0xec, 0x75, 0x3c,
+  0x00, 0x00, 0xb4, 0x42, 0x48, 0xe1, 0x9a, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0xdf, 0x4f, 0xcd, 0x3e,
+  0x37, 0x89, 0xfd, 0x40, 0x66, 0x66, 0xc6, 0x41, 0xec, 0x51, 0xbc, 0x40, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x46, 0x43, 0x9a, 0x99, 0x59, 0x41, 0x8f, 0xc2, 0xc5, 0x43, 0x71, 0x3d, 0x4a, 0x40,
+  0x14, 0x3f, 0xe5, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xd4, 0x18, 0x3f, 0xc3, 0xf5, 0xa4, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x76, 0x71, 0xcb, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x52, 0xf8, 0x52, 0x43,
+  0xd7, 0xa3, 0xa0, 0x41, 0x1f, 0x85, 0xeb, 0x3c, 0x00, 0x00, 0xe0, 0x41, 0xd7, 0xa3, 0x70, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x68, 0x91, 0xed, 0x3e, 0x83, 0xc0, 0xc6, 0x40, 0x33, 0x33, 0xe7, 0x41,
+  0x1b, 0x9e, 0x6a, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x87, 0x43, 0x9a, 0x99, 0x91, 0x41,
+  0x3d, 0x2a, 0xc6, 0x43, 0x52, 0xb8, 0xc6, 0x40, 0x7f, 0xd9, 0x5a, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x3d, 0x3f, 0x85, 0xeb, 0xbd, 0x40,
+  0xcd, 0xcc, 0xaf, 0x42, 0x6c, 0x09, 0xe9, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x66, 0xe6, 0x89, 0x42, 0x7b, 0x14, 0x08, 0x42, 0xc4, 0xdf, 0x07, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x06, 0x81, 0x15, 0x3f,
+  0xd1, 0x22, 0xcb, 0x40, 0x33, 0x33, 0xac, 0x42, 0x70, 0x5f, 0x03, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x66, 0xe6, 0xa6, 0x42, 0xb8, 0x1e, 0x8d, 0x41,
+  0x37, 0x8e, 0xd8, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0xdd, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x6d, 0xe7, 0x1b, 0x3f, 0xbc, 0x74, 0xbf, 0x40, 0x9a, 0x99, 0xc5, 0x42, 0xe7, 0x1d, 0xef, 0x3f,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0xc0, 0x31, 0x44, 0xcd, 0xcc, 0xa0, 0x41, 0x14, 0x0e, 0xc3, 0x43,
+  0x5c, 0x8f, 0x90, 0x41, 0xb5, 0x37, 0x3f, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x39, 0xb4, 0x28, 0x3f, 0xbc, 0x74, 0xb3, 0x40, 0x00, 0x00, 0xc8, 0x42,
+  0x6f, 0x81, 0xa4, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x85, 0x0b, 0xa6, 0x43, 0x7b, 0x14, 0x42, 0x41, 0xb6, 0xa1, 0x02, 0x3e, 0x00, 0x00, 0xf0, 0x41,
+  0x8f, 0xc2, 0x9d, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x22, 0xdb, 0x3e, 0x75, 0x93, 0xcc, 0x40,
+  0x9a, 0x99, 0xf9, 0x40, 0xd1, 0x22, 0xe1, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x96, 0x43,
+  0xcd, 0xcc, 0x84, 0x41, 0xe1, 0x5a, 0xbb, 0x43, 0x7b, 0x14, 0xa6, 0x40, 0xe9, 0xf1, 0x7b, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x7b, 0x14, 0xa6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x03, 0x3f,
+  0xdb, 0xf9, 0xbe, 0x40, 0x00, 0x00, 0x6a, 0x42, 0x8b, 0xfd, 0x99, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0x60, 0x43, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xd7, 0xa3, 0x14, 0x41,
+  0xad, 0x17, 0x03, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x1e, 0x05, 0x3f, 0x02, 0x2b, 0xcf, 0x40, 0x33, 0x33, 0xc2, 0x42, 0xa2, 0xb4, 0x1b, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x43, 0x33, 0x33, 0xa7, 0x41, 0xb8, 0x9e, 0xc5, 0x43,
+  0xec, 0x51, 0x44, 0x41, 0x59, 0x51, 0x23, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f, 0x6f, 0x12, 0xc3, 0x40, 0x00, 0x00, 0xa9, 0x42,
+  0xe3, 0xc7, 0x8e, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41,
+  0x8f, 0x02, 0xbe, 0x43, 0xf6, 0x28, 0x24, 0x41, 0x90, 0x6b, 0x93, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f, 0x98, 0x6e, 0xb6, 0x40,
+  0x00, 0x00, 0xbe, 0x42, 0x7c, 0x61, 0x72, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43,
+  0x00, 0x00, 0xa8, 0x41, 0x8f, 0x62, 0xb3, 0x43, 0xcd, 0xcc, 0x92, 0x41, 0x49, 0x9d, 0x5e, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f,
+  0xf0, 0xa7, 0xc6, 0x40, 0x00, 0x00, 0xbe, 0x42, 0x86, 0x38, 0x0e, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x8f, 0x42, 0xc9, 0x42, 0x52, 0xb8, 0x72, 0x41,
+  0x16, 0x6a, 0x8d, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x85, 0x0b, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xfa, 0x7e, 0xea, 0x3e, 0x39, 0xb4, 0xe4, 0x40, 0xcd, 0xcc, 0x58, 0x42, 0x8b, 0xfd, 0xc1, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x5e, 0x43, 0x9a, 0x99, 0x95, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x5c, 0x8f, 0xaa, 0x40, 0xc9, 0x8e, 0x75, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0x45, 0x3f, 0x31, 0x08, 0xc8, 0x40, 0x33, 0x33, 0xb6, 0x42,
+  0x79, 0xe9, 0x12, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x33, 0x53, 0xaf, 0x43, 0x3d, 0x0a, 0x63, 0x41, 0x68, 0x96, 0x04, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x1f, 0x85, 0x0b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x7e, 0xea, 0x3e, 0x9e, 0xef, 0xdf, 0x40,
+  0x33, 0x33, 0x37, 0x42, 0x8b, 0xfd, 0xc1, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x5e, 0x43,
+  0x9a, 0x99, 0x95, 0x41, 0xa4, 0x50, 0xc5, 0x43, 0xf6, 0x28, 0x3c, 0x40, 0x4a, 0x29, 0x8b, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x7a, 0x14, 0x3f,
+  0x10, 0x58, 0xc5, 0x40, 0x00, 0x00, 0xa8, 0x42, 0x3a, 0x23, 0x42, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xec, 0x51, 0x82, 0x41,
+  0xef, 0x72, 0xa1, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x25, 0x06, 0x01, 0x3f, 0x89, 0x41, 0x04, 0x41, 0x9a, 0x99, 0x9c, 0x42, 0xd9, 0x3d, 0x39, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0x66, 0x86, 0xc0, 0x43,
+  0xe1, 0x7a, 0x84, 0x40, 0x42, 0xb2, 0x98, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0x1f, 0x3f, 0x98, 0x6e, 0xca, 0x40, 0x66, 0x66, 0xc3, 0x42,
+  0x10, 0x58, 0x11, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xf6, 0x28, 0x44, 0x41, 0x4f, 0x58, 0xe2, 0x3c, 0x00, 0x00, 0x96, 0x42,
+  0xcd, 0xcc, 0x3c, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x22, 0xdb, 0x3e, 0x3d, 0x0a, 0xd3, 0x40,
+  0x66, 0x66, 0xae, 0x41, 0xd0, 0xd5, 0xac, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x7c, 0x43,
+  0x66, 0x66, 0x92, 0x41, 0xa4, 0xd0, 0xc5, 0x43, 0x71, 0x3d, 0x8a, 0x40, 0xe3, 0x70, 0xce, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0x6f, 0x12, 0xc3, 0x40, 0xcd, 0xcc, 0xc1, 0x42, 0x90, 0xa0, 0x70, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0x5c, 0x4f, 0x78, 0x43, 0x52, 0xb8, 0xa2, 0x41,
+  0xd5, 0xe7, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x73, 0x68, 0x31, 0x3f, 0xc3, 0xf5, 0xcc, 0x40, 0x00, 0x00, 0xc0, 0x42, 0x62, 0xa1, 0xd6, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xc3, 0xf5, 0x9a, 0x41, 0x2d, 0xec, 0x89, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x1e, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f, 0x12, 0x83, 0xc8, 0x40, 0x9a, 0x99, 0xa5, 0x42,
+  0xb7, 0xd1, 0x50, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x98, 0x43, 0x33, 0x33, 0x93, 0x41,
+  0xec, 0xb1, 0xc4, 0x43, 0xcd, 0xcc, 0xfc, 0x40, 0x5d, 0xbf, 0xeb, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xf2, 0xd2, 0x2d, 0x3f, 0x0e, 0x2d, 0xc6, 0x40,
+  0x33, 0x33, 0x9c, 0x42, 0xbe, 0xc1, 0xf7, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0xc3, 0x75, 0xc1, 0x42, 0xf6, 0x28, 0xac, 0x41, 0xbe, 0xc1, 0x55, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f,
+  0x4e, 0x62, 0xbc, 0x40, 0x66, 0x66, 0xbd, 0x42, 0xda, 0x1b, 0xe4, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xcd, 0xcc, 0x82, 0x41,
+  0x09, 0xf9, 0xa0, 0x3c, 0x00, 0x00, 0xa0, 0x42, 0xae, 0x47, 0xe1, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x1e, 0xc5, 0x3e, 0x29, 0x5c, 0xc7, 0x40, 0x00, 0x00, 0xfc, 0x41, 0x5d, 0x6d, 0x11, 0x41,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x71, 0x43, 0x9a, 0x99, 0x91, 0x41, 0xcd, 0xcc, 0xaa, 0x43,
+  0x48, 0xe1, 0x4e, 0x41, 0xbd, 0x52, 0xc6, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0xcd, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x6a, 0xbc, 0x14, 0x3f, 0xb2, 0x9d, 0xb3, 0x40, 0x33, 0x33, 0xbf, 0x42,
+  0xee, 0xeb, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3c, 0x43, 0xcd, 0xcc, 0x98, 0x41,
+  0x1f, 0xa5, 0xb3, 0x43, 0x7b, 0x14, 0xda, 0x41, 0x63, 0xd1, 0x0c, 0x3f, 0x00, 0x00, 0xa0, 0x41,
+  0x7b, 0x14, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcb, 0xa1, 0x25, 0x3f, 0x8d, 0x97, 0xe6, 0x40,
+  0x33, 0x33, 0xb7, 0x42, 0x84, 0x0d, 0xf7, 0x3f, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x84, 0x43,
+  0x00, 0x00, 0x50, 0x41, 0xec, 0xf1, 0xc1, 0x43, 0x9a, 0x99, 0x01, 0x41, 0x1b, 0x47, 0x18, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xf9, 0x5e, 0x3f,
+  0xf6, 0x28, 0xc4, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x12, 0xa5, 0xb5, 0x3f, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0xf6, 0xe8, 0x2c, 0x43, 0x66, 0x66, 0xde, 0x41,
+  0x64, 0x1e, 0xf9, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x14, 0xa6, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x0a, 0xd7, 0x03, 0x3f, 0xd7, 0xa3, 0xbc, 0x40, 0x66, 0x66, 0x6e, 0x42, 0x14, 0xae, 0xb3, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x60, 0x43, 0x9a, 0x99, 0xa1, 0x41, 0xae, 0x67, 0xc5, 0x43,
+  0xc3, 0xf5, 0x28, 0x41, 0x93, 0x35, 0x03, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f, 0xb6, 0xf3, 0xbd, 0x40, 0x9a, 0x99, 0xa0, 0x42,
+  0x6a, 0xde, 0x31, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x00, 0x00, 0x60, 0x40, 0x1f, 0x85, 0x87, 0x41, 0x69, 0x3a, 0x5b, 0x3e, 0x00, 0x00, 0xb0, 0x41,
+  0x1f, 0x85, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0xac, 0xdc, 0x3e, 0x19, 0x04, 0xce, 0x40,
+  0x66, 0x66, 0x0e, 0x41, 0xc4, 0xb1, 0xec, 0x40, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0xa5, 0x43,
+  0xcd, 0xcc, 0x98, 0x41, 0xf6, 0x88, 0xbc, 0x43, 0x8f, 0xc2, 0x65, 0x40, 0xa7, 0x68, 0xb0, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x3d, 0x3f,
+  0x0e, 0x2d, 0xba, 0x40, 0xcd, 0xcc, 0xb8, 0x42, 0xa4, 0xdf, 0xee, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x9a, 0xb9, 0xc3, 0x43, 0x48, 0xe1, 0xb0, 0x41,
+  0xe5, 0x27, 0x55, 0x3c, 0x00, 0x00, 0x0c, 0x42, 0x5c, 0x8f, 0xc2, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0xd3, 0x4d, 0xe2, 0x3e, 0x46, 0xb6, 0xe7, 0x40, 0x33, 0x33, 0x45, 0x42, 0x7a, 0x36, 0xe1, 0x40,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x8e, 0x43, 0x00, 0x00, 0x78, 0x41, 0xb8, 0x5e, 0xc5, 0x43,
+  0x14, 0xae, 0xaf, 0x40, 0xfb, 0x5c, 0x1d, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xc1, 0xca, 0x01, 0x3f, 0xa8, 0xc6, 0xd3, 0x40, 0x9a, 0x99, 0xa1, 0x42,
+  0x16, 0x6a, 0x51, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x33, 0x33, 0xf3, 0x40, 0xab, 0xec, 0xec, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xd4, 0x18, 0x3f, 0x77, 0xbe, 0xb3, 0x40,
+  0xcd, 0xcc, 0xc3, 0x42, 0x9c, 0x33, 0xba, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0xec, 0x51, 0x9d, 0x43, 0x33, 0x33, 0xd3, 0x41, 0xac, 0xe2, 0xa2, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f,
+  0x06, 0x81, 0xc9, 0x40, 0x9a, 0x99, 0xb7, 0x42, 0x97, 0x90, 0x17, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x85, 0x8b, 0xc0, 0x43, 0xf6, 0x28, 0x8a, 0x41,
+  0xdb, 0xa7, 0xc3, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x25, 0x06, 0x01, 0x3f, 0xd7, 0xa3, 0x00, 0x41, 0x00, 0x00, 0xad, 0x42, 0x07, 0xce, 0x4d, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0xa4, 0xb0, 0xc1, 0x43,
+  0xec, 0x51, 0x48, 0x40, 0x18, 0x09, 0xed, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x25, 0x06, 0x01, 0x3f, 0x1b, 0x2f, 0xed, 0x40, 0xcd, 0xcc, 0x99, 0x42,
+  0xdb, 0xf9, 0x6a, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41,
+  0xec, 0x11, 0xbc, 0x43, 0x00, 0x00, 0xa8, 0x40, 0xb9, 0x70, 0xe0, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0xe1, 0x3e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x21, 0xb0, 0x12, 0x3f, 0x73, 0x68, 0xd9, 0x40,
+  0x9a, 0x99, 0xb2, 0x42, 0xbd, 0xe3, 0x18, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x80, 0x88, 0x43,
+  0x00, 0x00, 0xa8, 0x41, 0x9a, 0xb9, 0xc4, 0x43, 0x29, 0x5c, 0xcf, 0x40, 0x4d, 0xf3, 0x0e, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0x05, 0x3f,
+  0x10, 0x58, 0xc5, 0x40, 0x00, 0x00, 0xb4, 0x42, 0xaa, 0xf1, 0x1a, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0xc0, 0x43, 0x33, 0x33, 0xa7, 0x41, 0x52, 0x58, 0xc4, 0x43, 0xae, 0x47, 0x45, 0x41,
+  0x0e, 0x67, 0x7e, 0x3d, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0xa0, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0xe3, 0xa5, 0xdb, 0x3e, 0x14, 0xae, 0xcf, 0x40, 0x9a, 0x99, 0x31, 0x42, 0x71, 0xac, 0x0c, 0x41,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x80, 0xa7, 0x43, 0x9a, 0x99, 0x9d, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x29, 0x5c, 0xbf, 0x40, 0xc9, 0xa5, 0x16, 0x42, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xf2, 0xd2, 0x2d, 0x3f, 0xc9, 0x76, 0xc6, 0x40, 0x66, 0x66, 0x9d, 0x42,
+  0x82, 0x73, 0xee, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x5c, 0x8f, 0x96, 0x41, 0xec, 0x51, 0x68, 0x41, 0x18, 0xec, 0x86, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0xa4, 0x70, 0x1d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x23, 0xdb, 0xf9, 0x3e, 0xe1, 0x7a, 0xf8, 0x40,
+  0x9a, 0x99, 0xa6, 0x42, 0x8b, 0x6c, 0x2f, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x41, 0x43,
+  0x66, 0x66, 0x8e, 0x41, 0xae, 0xc7, 0xc5, 0x43, 0x85, 0xeb, 0xf1, 0x40, 0x92, 0xcb, 0x7f, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0x1f, 0x3f,
+  0x8b, 0x6c, 0xbb, 0x40, 0x66, 0x66, 0xc4, 0x42, 0xaf, 0x94, 0xd5, 0x3f, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x1f, 0x05, 0xc4, 0x43, 0x5c, 0x8f, 0xaa, 0x41,
+  0x57, 0x04, 0xff, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x7a, 0x8c, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xd3, 0x4d, 0xe2, 0x3e, 0xb0, 0x72, 0xc0, 0x40, 0x00, 0x00, 0x42, 0x42, 0xb5, 0x37, 0x00, 0x41,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0xb0, 0x43, 0x66, 0x66, 0x96, 0x41, 0xec, 0xd1, 0xc0, 0x43,
+  0xe1, 0x7a, 0x28, 0x41, 0x09, 0x6d, 0x39, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x3e, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x21, 0xb0, 0x12, 0x3f, 0x0a, 0xd7, 0xc3, 0x40, 0x66, 0x66, 0x99, 0x42,
+  0x66, 0x66, 0x12, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x80, 0x88, 0x43, 0x00, 0x00, 0xa8, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xae, 0x47, 0x11, 0x41, 0xbd, 0x8c, 0x9a, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x1a, 0x3f, 0x00, 0x00, 0xbc, 0x40,
+  0x33, 0x33, 0xbd, 0x42, 0xf2, 0x41, 0x1b, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43,
+  0x33, 0x33, 0x6b, 0x41, 0x1f, 0x25, 0x92, 0x43, 0x48, 0xe1, 0x66, 0x41, 0xc7, 0xba, 0xa5, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x39, 0xb4, 0x28, 0x3f,
+  0x7f, 0x6a, 0x84, 0x40, 0x00, 0x00, 0xc8, 0x42, 0xfb, 0xcb, 0x96, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x29, 0x1c, 0xb9, 0x43, 0x52, 0xb8, 0xba, 0x41,
+  0xa2, 0x7f, 0x02, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xdd, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x42, 0x60, 0xe5, 0x3e, 0xd7, 0xa3, 0xd8, 0x40, 0x9a, 0x99, 0x39, 0x40, 0x9d, 0x11, 0xb7, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x69, 0x43, 0x33, 0x33, 0x8f, 0x41, 0x7b, 0xb4, 0xc0, 0x43,
+  0x48, 0xe1, 0x9a, 0x40, 0x34, 0x85, 0xce, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0x20, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x31, 0x08, 0x0c, 0x3f, 0x48, 0xe1, 0xd6, 0x40, 0x33, 0x33, 0xa3, 0x42,
+  0x29, 0x5c, 0x2b, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xd8, 0x43, 0x66, 0x66, 0x8e, 0x41,
+  0x85, 0xcb, 0xc5, 0x43, 0x5c, 0x8f, 0x22, 0x41, 0x25, 0x5d, 0x33, 0x3d, 0x00, 0x00, 0xa0, 0x42,
+  0x14, 0xae, 0x57, 0x40, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xc6, 0xcb, 0x3e, 0x1b, 0x2f, 0xb9, 0x40,
+  0xcd, 0xcc, 0xf8, 0x41, 0x68, 0x91, 0xd3, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xa8, 0x43,
+  0xcd, 0xcc, 0x80, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x0a, 0xd7, 0x23, 0x41, 0x50, 0x01, 0x30, 0x3d,
+  0x00, 0x00, 0x52, 0x42, 0x71, 0x3d, 0xaa, 0x40, 0x00, 0x00, 0x00, 0x00, 0x29, 0x5c, 0xcf, 0x3e,
+  0x7b, 0x14, 0xd2, 0x40, 0x33, 0x33, 0xb7, 0x41, 0x81, 0x26, 0xea, 0x40, 0x00, 0x00, 0xc0, 0x40,
+  0x00, 0x80, 0x92, 0x43, 0xcd, 0xcc, 0x84, 0x41, 0x29, 0xdc, 0xb9, 0x43, 0xf6, 0x28, 0x18, 0x41,
+  0x50, 0xfc, 0x93, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x02, 0x2b, 0x3f, 0x7f, 0x6a, 0x84, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x37, 0x89, 0x91, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x48, 0xe1, 0x17, 0x42, 0x50, 0x70, 0xb1, 0x3d, 0x00, 0x00, 0x34, 0x42, 0xf6, 0x28, 0x5c, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e, 0x2d, 0xb2, 0xe5, 0x40, 0x66, 0x66, 0xd2, 0x41,
+  0x86, 0x5a, 0xcf, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc7, 0x43, 0x33, 0x33, 0x73, 0x41,
+  0xb8, 0x3e, 0xc3, 0x43, 0x14, 0xae, 0x37, 0x40, 0x3c, 0x66, 0xc0, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xa4, 0x70, 0x29, 0x41, 0x00, 0x00, 0x80, 0x3f, 0x35, 0x5e, 0xfa, 0x3e, 0x91, 0xed, 0xac, 0x40,
+  0x33, 0x33, 0xb1, 0x42, 0x5c, 0x8f, 0x6a, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x8a, 0x43,
+  0xcd, 0xcc, 0x94, 0x41, 0xb8, 0x9e, 0xc5, 0x43, 0x0a, 0xd7, 0xbf, 0x41, 0xa4, 0xa5, 0x32, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x29, 0x41, 0x00, 0x00, 0x80, 0x3f, 0x35, 0x5e, 0xfa, 0x3e,
+  0x52, 0xb8, 0xbe, 0x40, 0x33, 0x33, 0xb8, 0x42, 0x68, 0x22, 0x78, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x8a, 0x43, 0xcd, 0xcc, 0x94, 0x41, 0x00, 0xa0, 0xc4, 0x43, 0xf6, 0x28, 0x8a, 0x41,
+  0x84, 0xe4, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x81, 0x15, 0x3f, 0xfc, 0xa9, 0xad, 0x40, 0xcd, 0xcc, 0xbe, 0x42, 0xd8, 0x81, 0x1b, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x3d, 0x4a, 0xb0, 0x43,
+  0xb8, 0x1e, 0x91, 0x41, 0xd4, 0x9a, 0x6c, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xd9, 0xce, 0x37, 0x3f, 0xe5, 0xd0, 0x9e, 0x40, 0xcd, 0xcc, 0xb6, 0x42,
+  0x5e, 0x4b, 0xe0, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0xd7, 0x03, 0x9e, 0x43, 0x00, 0x00, 0x60, 0x41, 0xa6, 0x44, 0x0a, 0x3f, 0x00, 0x00, 0xa0, 0x41,
+  0x7b, 0x14, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcb, 0xa1, 0x25, 0x3f, 0xfa, 0x7e, 0xe6, 0x40,
+  0x9a, 0x99, 0xa3, 0x42, 0xa5, 0x2c, 0x07, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x84, 0x43,
+  0x00, 0x00, 0x50, 0x41, 0x66, 0x66, 0xc4, 0x43, 0xa4, 0x70, 0x19, 0x41, 0x9a, 0x99, 0x61, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0x1f, 0x3f,
+  0x4e, 0x62, 0xb4, 0x40, 0x66, 0x66, 0xbd, 0x42, 0x5d, 0x6d, 0xfd, 0x3f, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x52, 0xb8, 0x92, 0x41,
+  0x4f, 0x40, 0x33, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x52, 0xb8, 0xbe, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xee, 0x7c, 0xff, 0x3e, 0x79, 0xe9, 0xbe, 0x40, 0x9a, 0x99, 0xf1, 0x41, 0x2a, 0x3a, 0x76, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x8b, 0x43, 0x9a, 0x99, 0x99, 0x41, 0x0a, 0xb7, 0xc4, 0x43,
+  0x7b, 0x14, 0x22, 0x41, 0x57, 0xec, 0x09, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xdb, 0xf9, 0x5e, 0x3f, 0x93, 0x18, 0xb4, 0x40, 0x00, 0x00, 0xc8, 0x42,
+  0xf3, 0x1f, 0xc2, 0x3f, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41,
+  0x1f, 0x45, 0x29, 0x43, 0x33, 0x33, 0x85, 0x41, 0x71, 0x55, 0xd9, 0x3d, 0x00, 0x00, 0xf0, 0x41,
+  0x8f, 0xc2, 0x9d, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x22, 0xdb, 0x3e, 0x3d, 0x0a, 0xc3, 0x40,
+  0x33, 0x33, 0x82, 0x42, 0x55, 0xc1, 0xca, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x96, 0x43,
+  0xcd, 0xcc, 0x84, 0x41, 0x5c, 0x4f, 0xc5, 0x43, 0x66, 0x66, 0x46, 0x41, 0x8b, 0x89, 0x8d, 0x3d,
+  0x00, 0x00, 0x34, 0x42, 0xf6, 0x28, 0x5c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e,
+  0xe3, 0xa5, 0xd7, 0x40, 0x66, 0x66, 0xf6, 0x41, 0x86, 0x5a, 0xcf, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0xc7, 0x43, 0x33, 0x33, 0x73, 0x41, 0xe1, 0xda, 0xc2, 0x43, 0x7b, 0x14, 0x96, 0x40,
+  0x1e, 0x33, 0x50, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x14, 0xa6, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x0a, 0xd7, 0x03, 0x3f, 0xac, 0x1c, 0xca, 0x40, 0x66, 0x66, 0x18, 0x42, 0x36, 0xab, 0xce, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x60, 0x43, 0x9a, 0x99, 0xa1, 0x41, 0xe1, 0xda, 0xc2, 0x43,
+  0x8f, 0xc2, 0xb5, 0x40, 0x3c, 0xbd, 0xd2, 0x3d, 0x00, 0x00, 0xf0, 0x41, 0x8f, 0xc2, 0x9d, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xd1, 0x22, 0xdb, 0x3e, 0xbc, 0x74, 0xcb, 0x40, 0x9a, 0x99, 0x53, 0x42,
+  0xd1, 0x22, 0xe1, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x96, 0x43, 0xcd, 0xcc, 0x84, 0x41,
+  0x00, 0x60, 0xba, 0x43, 0x1f, 0x85, 0x33, 0x41, 0x45, 0x12, 0xf8, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f, 0xcb, 0xa1, 0xc9, 0x40,
+  0x66, 0x66, 0xa7, 0x42, 0x4f, 0x1e, 0x32, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0xe1, 0x1a, 0x88, 0x43, 0x0a, 0xd7, 0x81, 0x41, 0x90, 0x6b, 0x83, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x52, 0xb8, 0xbe, 0x40, 0x00, 0x00, 0x00, 0x00, 0xee, 0x7c, 0xff, 0x3e,
+  0x23, 0xdb, 0xbd, 0x40, 0x66, 0x66, 0x88, 0x42, 0x28, 0x0f, 0x57, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0x8b, 0x43, 0x9a, 0x99, 0x99, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x48, 0xe1, 0x1a, 0x41,
+  0x00, 0x91, 0x32, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xa4, 0x70, 0x3d, 0x3f, 0xc5, 0x20, 0xd4, 0x40, 0x33, 0x33, 0xbd, 0x42, 0x16, 0xfb, 0x07, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0xb3, 0xdb, 0x42,
+  0xf6, 0x28, 0xba, 0x41, 0xc1, 0x39, 0x13, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x1a, 0x3f, 0x3f, 0x35, 0xca, 0x40, 0x33, 0x33, 0xc0, 0x42,
+  0x66, 0x66, 0x06, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41,
+  0x85, 0x8b, 0x94, 0x43, 0x9a, 0x99, 0x31, 0x41, 0x9f, 0xc8, 0xb3, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xf6, 0x28, 0xec, 0x40, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x6a, 0xfc, 0x3e, 0xdf, 0x4f, 0xc1, 0x40,
+  0x9a, 0x99, 0x47, 0x42, 0x40, 0x13, 0x97, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x8f, 0x43,
+  0xcd, 0xcc, 0x9c, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x66, 0x66, 0xf6, 0x40, 0xac, 0xe2, 0x45, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0x0a, 0xd7, 0xcf, 0x40, 0xcd, 0xcc, 0xbc, 0x42, 0xe7, 0x8c, 0x8e, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0x52, 0xf8, 0xc1, 0x43, 0xcd, 0xcc, 0x4c, 0x41,
+  0x9b, 0x20, 0xea, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x1e, 0x05, 0x3f, 0xf4, 0xfd, 0xd8, 0x40, 0x9a, 0x99, 0x8e, 0x42, 0x58, 0xca, 0x36, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x43, 0x33, 0x33, 0xa7, 0x41, 0x3d, 0xca, 0xc5, 0x43,
+  0xa4, 0x70, 0xf5, 0x40, 0xbe, 0xa4, 0x31, 0x3d, 0x00, 0x00, 0xa8, 0x41, 0xe1, 0x7a, 0xb4, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x9c, 0xc4, 0xe0, 0x3e, 0x14, 0xae, 0xc3, 0x40, 0x00, 0x00, 0x7c, 0x42,
+  0x06, 0x12, 0xda, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x73, 0x43, 0x66, 0x66, 0x86, 0x41,
+  0x29, 0xfc, 0xc4, 0x43, 0x48, 0xe1, 0x16, 0x41, 0xe7, 0x1d, 0x83, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xf9, 0x5e, 0x3f, 0xdb, 0xf9, 0xae, 0x40,
+  0x00, 0x00, 0xc8, 0x42, 0xdd, 0xb5, 0xb4, 0x3f, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43,
+  0x33, 0x33, 0x6b, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x29, 0x5c, 0xd3, 0x41, 0xf9, 0xbd, 0x4d, 0x3d,
+  0x00, 0x00, 0x0c, 0x42, 0x85, 0xeb, 0xc1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x34, 0xe0, 0x3e,
+  0x8d, 0x97, 0xb6, 0x40, 0x33, 0x33, 0xe3, 0x41, 0x9d, 0x80, 0xd4, 0x40, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x98, 0x43, 0x33, 0x33, 0x87, 0x41, 0x8f, 0x02, 0xc5, 0x43, 0x48, 0xe1, 0x46, 0x41,
+  0x81, 0x09, 0x5c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x52, 0xb8, 0x5e, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x77, 0xbe, 0xdf, 0x3e, 0x68, 0x91, 0xd1, 0x40, 0x00, 0x00, 0x4c, 0x42, 0x99, 0xbb, 0xbe, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x90, 0x43, 0x00, 0x00, 0x80, 0x41, 0xcd, 0x6c, 0xc4, 0x43,
+  0xe1, 0x7a, 0xec, 0x40, 0xfb, 0x91, 0x22, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x2c, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xbc, 0x74, 0xd3, 0x3e, 0x83, 0xc0, 0xbe, 0x40, 0x00, 0x00, 0x8c, 0x41,
+  0x90, 0x31, 0xa9, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x98, 0x43, 0x9a, 0x99, 0x99, 0x41,
+  0x52, 0x78, 0xbc, 0x43, 0x7b, 0x14, 0x1e, 0x41, 0xbf, 0xd4, 0x2f, 0x3e, 0x00, 0x00, 0xc8, 0x41,
+  0xf6, 0x28, 0xa4, 0x40, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xef, 0xe7, 0x3e, 0x79, 0xe9, 0xbe, 0x40,
+  0xcd, 0xcc, 0xba, 0x42, 0x27, 0x31, 0xda, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x8e, 0x43,
+  0x9a, 0x99, 0x9d, 0x41, 0x3d, 0x0a, 0xbd, 0x43, 0x3d, 0x0a, 0x67, 0x41, 0x70, 0xb6, 0xb9, 0x3d,
+  0x00, 0x00, 0x34, 0x42, 0xf6, 0x28, 0x5c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e,
+  0x98, 0x6e, 0xde, 0x40, 0x00, 0x00, 0xac, 0x41, 0x86, 0x5a, 0xcf, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0xc7, 0x43, 0x33, 0x33, 0x73, 0x41, 0x0a, 0xd7, 0xbc, 0x43, 0x33, 0x33, 0xa3, 0x40,
+  0xe2, 0xe4, 0x06, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x25, 0x06, 0x01, 0x3f, 0x9a, 0x99, 0x0b, 0x41, 0x00, 0x00, 0xa6, 0x42, 0xd9, 0x3d, 0x39, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0x00, 0x00, 0xbf, 0x43,
+  0xf6, 0x28, 0x94, 0x40, 0x8b, 0xfd, 0x7d, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xa8, 0xc6, 0x2b, 0x3f, 0xa4, 0x70, 0xd1, 0x40, 0x33, 0x33, 0xc6, 0x42,
+  0x25, 0x75, 0xc2, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xd7, 0xa3, 0xa8, 0x41, 0x4d, 0xd6, 0xa8, 0x3d, 0x00, 0x00, 0xf0, 0x41,
+  0x8f, 0xc2, 0x9d, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x22, 0xdb, 0x3e, 0x5a, 0x64, 0xcf, 0x40,
+  0x00, 0x00, 0x94, 0x41, 0xa9, 0x13, 0xc6, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0x96, 0x43,
+  0xcd, 0xcc, 0x84, 0x41, 0x7b, 0xb4, 0xbd, 0x43, 0x1f, 0x85, 0xcb, 0x40, 0xc1, 0xad, 0xbb, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x2c, 0x41, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x74, 0xd3, 0x3e,
+  0x7b, 0x14, 0xc2, 0x40, 0x9a, 0x99, 0xf9, 0x40, 0x90, 0x31, 0xa9, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x98, 0x43, 0x9a, 0x99, 0x99, 0x41, 0x7b, 0x74, 0xc3, 0x43, 0xd7, 0xa3, 0xb0, 0x40,
+  0x39, 0x0b, 0x7b, 0x3d, 0x00, 0x00, 0xa0, 0x41, 0xb8, 0x1e, 0x55, 0x40, 0x00, 0x00, 0x80, 0x3f,
+  0xca, 0xc3, 0xe2, 0x3e, 0xd7, 0xa3, 0xf4, 0x40, 0xcd, 0xcc, 0x46, 0x42, 0xe3, 0xc7, 0xa6, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x58, 0x43, 0x66, 0x66, 0x6e, 0x41, 0xf6, 0x88, 0xbc, 0x43,
+  0xd7, 0xa3, 0x40, 0x40, 0x07, 0xce, 0x39, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f, 0x96, 0x43, 0xb7, 0x40, 0x00, 0x00, 0x8b, 0x42,
+  0xdb, 0xf9, 0x72, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41,
+  0x9a, 0x79, 0xc3, 0x43, 0xe1, 0x7a, 0x34, 0x41, 0x83, 0x2f, 0xbd, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xc6, 0x2b, 0x3f, 0xf6, 0x28, 0xcc, 0x40,
+  0x66, 0x66, 0xc0, 0x42, 0xba, 0x6b, 0xb1, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x1f, 0x85, 0xbd, 0x41, 0x6e, 0x51, 0x06, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0x05, 0x3f,
+  0x62, 0x10, 0xc4, 0x40, 0x66, 0x66, 0xaa, 0x42, 0x67, 0xd5, 0x07, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0xc0, 0x43, 0x33, 0x33, 0xa7, 0x41, 0x52, 0xd8, 0xc1, 0x43, 0xa4, 0x70, 0x61, 0x41,
+  0xb1, 0xbf, 0x6c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x1d, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x23, 0xdb, 0xf9, 0x3e, 0x29, 0x5c, 0xdf, 0x40, 0x9a, 0x99, 0x69, 0x42, 0x56, 0x0e, 0x35, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x41, 0x43, 0x66, 0x66, 0x8e, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xae, 0x47, 0xa1, 0x40, 0x8a, 0xcd, 0x07, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x08, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0x05, 0x3f, 0x64, 0x3b, 0xbb, 0x40, 0x66, 0x66, 0xc1, 0x42,
+  0x73, 0xd7, 0x06, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x43, 0x33, 0x33, 0xa7, 0x41,
+  0x66, 0x06, 0xc5, 0x43, 0x8f, 0xc2, 0x83, 0x41, 0xbb, 0x44, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x80, 0x3f, 0xc1, 0xca, 0x01, 0x3f, 0x27, 0x31, 0xd4, 0x40,
+  0x00, 0x00, 0x99, 0x42, 0x6a, 0xbc, 0x84, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43,
+  0x33, 0x33, 0x8b, 0x41, 0x9a, 0x39, 0xc2, 0x43, 0xd7, 0xa3, 0x18, 0x41, 0xee, 0x77, 0x28, 0x3d,
+  0x00, 0x00, 0xc8, 0x41, 0x1f, 0x85, 0x9b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xac, 0x1c, 0xda, 0x3e,
+  0x96, 0x43, 0xd7, 0x40, 0x00, 0x00, 0x06, 0x42, 0x89, 0xd2, 0xac, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x8c, 0x43, 0x00, 0x00, 0x98, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xae, 0x47, 0xa9, 0x40,
+  0xe5, 0xd0, 0xa2, 0x3d, 0x00, 0x00, 0x70, 0x42, 0xec, 0x51, 0xd8, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x98, 0x6e, 0xd2, 0x3e, 0x2b, 0x87, 0xd2, 0x40, 0x9a, 0x99, 0x0f, 0x42, 0x64, 0x5d, 0x2b, 0x41,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xcd, 0x43, 0x66, 0x66, 0x92, 0x41, 0xd7, 0x63, 0xb9, 0x43,
+  0x14, 0xae, 0xaf, 0x40, 0x76, 0x6c, 0x84, 0x3d, 0x00, 0x00, 0x8c, 0x42, 0x29, 0x5c, 0x0f, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0xcc, 0x3e, 0x3d, 0x0a, 0xcb, 0x40, 0xcd, 0xcc, 0xa0, 0x41,
+  0x56, 0x7d, 0xfa, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xb3, 0x43, 0xcd, 0xcc, 0x6c, 0x41,
+  0xb8, 0x1e, 0xb8, 0x43, 0x3d, 0x0a, 0x9f, 0x40, 0xf7, 0xcc, 0x12, 0x3d, 0x00, 0x00, 0xa0, 0x42,
+  0x14, 0xae, 0x57, 0x40, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xc6, 0xcb, 0x3e, 0xae, 0x47, 0xc9, 0x40,
+  0x66, 0x66, 0x8e, 0x41, 0x68, 0x91, 0xd3, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xa8, 0x43,
+  0xcd, 0xcc, 0x80, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xa4, 0x70, 0x95, 0x40, 0xfd, 0x87, 0xf4, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x1f, 0x85, 0x0b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xfa, 0x7e, 0xea, 0x3e,
+  0x8f, 0xc2, 0xcd, 0x40, 0xcd, 0xcc, 0x6a, 0x42, 0x8b, 0xfd, 0xc1, 0x40, 0x00, 0x00, 0x40, 0x40,
+  0x00, 0x00, 0x5e, 0x43, 0x9a, 0x99, 0x95, 0x41, 0x5c, 0x0f, 0xc5, 0x43, 0x52, 0xb8, 0xa6, 0x40,
+  0x0e, 0x4f, 0x2f, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x1e, 0x05, 0x3f, 0x83, 0xc0, 0xba, 0x40, 0xcd, 0xcc, 0xb7, 0x42, 0x06, 0x81, 0x0d, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x43, 0x33, 0x33, 0xa7, 0x41, 0xc3, 0xd5, 0xc5, 0x43,
+  0xae, 0x47, 0x95, 0x41, 0x5d, 0xa7, 0x91, 0x3c, 0x00, 0x00, 0xbe, 0x42, 0xf6, 0x28, 0xbc, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x04, 0x56, 0xce, 0x3e, 0xec, 0x51, 0xe4, 0x40, 0x66, 0x66, 0x5e, 0x41,
+  0xa7, 0xe8, 0xf4, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0xc9, 0x43, 0x00, 0x00, 0x88, 0x41,
+  0x66, 0x26, 0xc0, 0x43, 0x66, 0x66, 0x8e, 0x40, 0xc8, 0x07, 0xbd, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x66, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f, 0xdd, 0x24, 0xd2, 0x40,
+  0x9a, 0x99, 0xae, 0x42, 0x15, 0x8c, 0x66, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x98, 0x43,
+  0x33, 0x33, 0x93, 0x41, 0x52, 0xd8, 0xc5, 0x43, 0xe1, 0x7a, 0x14, 0x41, 0xf5, 0x10, 0x8d, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x1d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x23, 0xdb, 0xf9, 0x3e,
+  0xa6, 0x9b, 0xc4, 0x40, 0xcd, 0xcc, 0x78, 0x42, 0xfe, 0x43, 0x26, 0x40, 0x00, 0x00, 0x40, 0x40,
+  0x00, 0x00, 0x41, 0x43, 0x66, 0x66, 0x8e, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x33, 0x33, 0x17, 0x41,
+  0x09, 0xc4, 0xab, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xae, 0x47, 0x4d, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x77, 0xbe, 0xdf, 0x3e, 0xcf, 0xf7, 0xbb, 0x40, 0x66, 0x66, 0x12, 0x42, 0x4d, 0x15, 0x90, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc7, 0x43, 0x9a, 0x99, 0x95, 0x41, 0xae, 0x07, 0xc6, 0x43,
+  0x9a, 0x99, 0x11, 0x41, 0x49, 0xf4, 0xa2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x1e, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f, 0x7d, 0x3f, 0xbd, 0x40, 0x66, 0x66, 0xa6, 0x42,
+  0x10, 0xe9, 0x7f, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x98, 0x43, 0x33, 0x33, 0x93, 0x41,
+  0x9a, 0x59, 0xc3, 0x43, 0xd7, 0xa3, 0x92, 0x41, 0x09, 0xc4, 0x6b, 0x3c, 0x00, 0x00, 0x70, 0x42,
+  0x1f, 0x85, 0x3b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x4f, 0xcd, 0x3e, 0xf8, 0x53, 0xd3, 0x40,
+  0x66, 0x66, 0x96, 0x41, 0xf7, 0x06, 0xc7, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x80, 0x84, 0x43,
+  0x9a, 0x99, 0x79, 0x41, 0x9a, 0x59, 0xbc, 0x43, 0xf6, 0x28, 0x8c, 0x40, 0x69, 0x1d, 0x6b, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x3f, 0x15, 0x3f,
+  0xe7, 0xfb, 0xc9, 0x40, 0x9a, 0x99, 0x4f, 0x42, 0x03, 0x78, 0x7f, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x5c, 0x4f, 0xc2, 0x43, 0xae, 0x47, 0x29, 0x41,
+  0x2b, 0xde, 0xa8, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x77, 0xbe, 0x1f, 0x3f, 0xd3, 0x4d, 0xba, 0x40, 0xcd, 0xcc, 0xbe, 0x42, 0xd7, 0x12, 0x1e, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x52, 0x58, 0xc2, 0x43,
+  0xe1, 0x7a, 0x70, 0x41, 0x68, 0x96, 0x1c, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xdb, 0xf9, 0x5e, 0x3f, 0x39, 0xb4, 0xa8, 0x40, 0x00, 0x00, 0xbc, 0x42,
+  0x5b, 0x42, 0xde, 0x3f, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41,
+  0x8f, 0x42, 0xb1, 0x42, 0xb8, 0x1e, 0x81, 0x41, 0x2f, 0xa3, 0xd9, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f, 0x8d, 0x97, 0xc2, 0x40,
+  0xcd, 0xcc, 0xa8, 0x42, 0x85, 0xeb, 0x2d, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x33, 0x33, 0x6b, 0x41, 0xf6, 0xee, 0xcf, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0xae, 0x47, 0x4d, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e,
+  0x91, 0xed, 0xc8, 0x40, 0x00, 0x00, 0x95, 0x42, 0x9f, 0xab, 0x81, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0xc7, 0x43, 0x9a, 0x99, 0x95, 0x41, 0x7b, 0xd4, 0xba, 0x43, 0x1f, 0x85, 0x3f, 0x41,
+  0xd2, 0x1d, 0xae, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x2b, 0x87, 0x36, 0x3f, 0xc3, 0xf5, 0xd4, 0x40, 0x66, 0x66, 0xc4, 0x42, 0x99, 0xbb, 0x16, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x1f, 0xa5, 0xb1, 0x43,
+  0x0a, 0xd7, 0x8d, 0x41, 0x22, 0xe0, 0x10, 0x3d, 0x00, 0x00, 0x08, 0x42, 0x48, 0xe1, 0xc2, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x2d, 0xb2, 0xdd, 0x3e, 0x48, 0xe1, 0xd2, 0x40, 0x9a, 0x99, 0x21, 0x42,
+  0x02, 0xbc, 0xaf, 0x40, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x80, 0xa4, 0x43, 0xcd, 0xcc, 0x80, 0x41,
+  0x00, 0xe0, 0xc5, 0x43, 0x00, 0x00, 0x18, 0x41, 0xf3, 0x76, 0x44, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xf6, 0x28, 0xec, 0x40, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x6a, 0xfc, 0x3e, 0xc1, 0xca, 0xcd, 0x40,
+  0x33, 0x33, 0x6b, 0x41, 0x0e, 0x4f, 0xad, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x8f, 0x43,
+  0xcd, 0xcc, 0x9c, 0x41, 0x0a, 0xd7, 0xc4, 0x43, 0x5c, 0x8f, 0xa2, 0x40, 0x58, 0xe7, 0x18, 0x3e,
+  0x00, 0x00, 0xc8, 0x41, 0xf6, 0x28, 0xa4, 0x40, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xef, 0xe7, 0x3e,
+  0x46, 0xb6, 0xb7, 0x40, 0x66, 0x66, 0x84, 0x42, 0x7a, 0x36, 0xe7, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x00, 0x8e, 0x43, 0x9a, 0x99, 0x9d, 0x41, 0x14, 0x8e, 0xc5, 0x43, 0x66, 0x66, 0x52, 0x41,
+  0x92, 0x05, 0x4c, 0x3d, 0x00, 0x00, 0xa8, 0x41, 0xe1, 0x7a, 0xb4, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x9c, 0xc4, 0xe0, 0x3e, 0x9e, 0xef, 0xbf, 0x40, 0x33, 0x33, 0xab, 0x41, 0x06, 0x12, 0xda, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x73, 0x43, 0x66, 0x66, 0x86, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x48, 0xe1, 0x06, 0x41, 0x81, 0x26, 0xc3, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3f, 0x2f, 0xdd, 0x94, 0x40, 0x00, 0x00, 0xc8, 0x42,
+  0x36, 0xcd, 0xbb, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x71, 0x3d, 0xe2, 0x41, 0x18, 0xcf, 0x00, 0x3e, 0x00, 0x00, 0x34, 0x42,
+  0xf6, 0x28, 0x5c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e, 0xc1, 0xca, 0xd1, 0x40,
+  0xcd, 0xcc, 0xe8, 0x41, 0x68, 0x22, 0x92, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc7, 0x43,
+  0x33, 0x33, 0x73, 0x41, 0x85, 0x6b, 0xbf, 0x43, 0x85, 0xeb, 0x91, 0x40, 0xb2, 0x63, 0xa3, 0x3d,
+  0x00, 0x00, 0x20, 0x42, 0xb8, 0x1e, 0xcd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xdd, 0xe4, 0x3e,
+  0x8b, 0x6c, 0xcf, 0x40, 0x66, 0x66, 0x00, 0x42, 0x56, 0x7d, 0x84, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x7e, 0x43, 0xcd, 0xcc, 0x8c, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x7b, 0x14, 0xe6, 0x40,
+  0x47, 0xe6, 0x79, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x77, 0xbe, 0x1f, 0x3f, 0x58, 0x39, 0xb8, 0x40, 0xcd, 0xcc, 0xc4, 0x42, 0xdd, 0x24, 0x16, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x48, 0x61, 0x83, 0x43,
+  0xe1, 0x7a, 0x8a, 0x41, 0xdc, 0x4b, 0xda, 0x3d, 0x00, 0x00, 0xa0, 0x42, 0xe1, 0x7a, 0xf4, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xbc, 0x74, 0xd3, 0x3e, 0xb6, 0xf3, 0xbd, 0x40, 0x00, 0x00, 0x9c, 0x41,
+  0x07, 0x5f, 0x29, 0x41, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0xa7, 0x43, 0x00, 0x00, 0xb0, 0x41,
+  0x1f, 0x05, 0xbc, 0x43, 0x71, 0x3d, 0xb2, 0x40, 0x6c, 0x78, 0x4a, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x14, 0xae, 0x27, 0x3f, 0xba, 0x49, 0xb8, 0x40,
+  0xcd, 0xcc, 0x40, 0x42, 0x89, 0x41, 0x44, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x33, 0xa7, 0x43, 0x7b, 0x14, 0x62, 0x41, 0x11, 0xc7, 0x3a, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x5e, 0x41, 0x00, 0x00, 0x80, 0x3f, 0xcd, 0xcc, 0x0c, 0x3f,
+  0x7f, 0x6a, 0xbc, 0x40, 0x00, 0x00, 0x60, 0x42, 0xa5, 0x2c, 0x47, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0x8a, 0x43, 0x33, 0x33, 0x83, 0x41, 0x66, 0x66, 0xc4, 0x43, 0xf6, 0x28, 0x58, 0x41,
+  0x76, 0x11, 0x93, 0x42, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xf2, 0xd2, 0x2d, 0x3f, 0xbe, 0x9f, 0xbe, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x99, 0xbb, 0xe6, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x9a, 0x99, 0x83, 0x41,
+  0xc3, 0xf5, 0xa4, 0x41, 0xa3, 0x01, 0x3c, 0x3d, 0x00, 0x00, 0x52, 0x42, 0x71, 0x3d, 0xaa, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x29, 0x5c, 0xcf, 0x3e, 0x7b, 0x14, 0xca, 0x40, 0x66, 0x66, 0x36, 0x42,
+  0x81, 0x26, 0xea, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x80, 0x92, 0x43, 0xcd, 0xcc, 0x84, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x33, 0x33, 0xf3, 0x40, 0xb3, 0x5e, 0x0c, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x7b, 0x14, 0xa6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x03, 0x3f, 0xd9, 0xce, 0xbb, 0x40,
+  0x33, 0x33, 0x39, 0x42, 0x2c, 0x65, 0xa7, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x60, 0x43,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xcd, 0xcc, 0x1c, 0x41, 0xf4, 0x37, 0x21, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0x35, 0x5e, 0xbe, 0x40, 0x33, 0x33, 0x77, 0x42, 0xd7, 0xa3, 0x96, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xf6, 0x28, 0x04, 0x41,
+  0x56, 0x9f, 0x2b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0xec, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x7f, 0x6a, 0xfc, 0x3e, 0xcb, 0xa1, 0xcd, 0x40, 0x33, 0x33, 0x51, 0x42, 0xf5, 0x4a, 0x91, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x8f, 0x43, 0xcd, 0xcc, 0x9c, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x66, 0x66, 0xe6, 0x40, 0x72, 0xe1, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xdd, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x42, 0x60, 0xe5, 0x3e, 0xe9, 0x26, 0xb9, 0x40, 0x33, 0x33, 0x05, 0x42,
+  0x7a, 0x36, 0xa3, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x69, 0x43, 0x33, 0x33, 0x8f, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x66, 0x66, 0x62, 0x41, 0xea, 0x5b, 0x6c, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f, 0x31, 0x08, 0xcc, 0x40,
+  0xcd, 0xcc, 0xb0, 0x42, 0x5e, 0x4b, 0x24, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x0a, 0xb7, 0xc3, 0x43, 0x66, 0x66, 0x6a, 0x41, 0x37, 0x89, 0x01, 0x3e,
+  0x00, 0x00, 0xc8, 0x41, 0xf6, 0x28, 0xa4, 0x40, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xef, 0xe7, 0x3e,
+  0x4e, 0x62, 0xd8, 0x40, 0x9a, 0x99, 0x2d, 0x42, 0x88, 0x63, 0xff, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x00, 0x8e, 0x43, 0x9a, 0x99, 0x9d, 0x41, 0x3d, 0xca, 0xc5, 0x43, 0x00, 0x00, 0x18, 0x41,
+  0xb5, 0xa6, 0xb9, 0x3d, 0x00, 0x00, 0xa0, 0x41, 0x52, 0xb8, 0xde, 0x40, 0x00, 0x00, 0x80, 0x3f,
+  0x68, 0x91, 0xed, 0x3e, 0xa4, 0x70, 0xbd, 0x40, 0x00, 0x00, 0x76, 0x42, 0x52, 0xb8, 0x7a, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x5f, 0x43, 0xcd, 0xcc, 0x94, 0x41, 0x85, 0xab, 0xc3, 0x43,
+  0x66, 0x66, 0x5a, 0x41, 0x79, 0x58, 0xa8, 0x3c, 0x00, 0x00, 0xaa, 0x42, 0xa4, 0x70, 0x3d, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0xd1, 0x3e, 0x89, 0x41, 0xcc, 0x40, 0xcd, 0xcc, 0x0e, 0x42,
+  0x69, 0x00, 0x13, 0x41, 0x00, 0x00, 0x00, 0x40, 0x00, 0x80, 0x9c, 0x43, 0x66, 0x66, 0x8a, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xd7, 0xa3, 0xb8, 0x40, 0xec, 0x69, 0x07, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x7b, 0x14, 0xa6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x03, 0x3f, 0x54, 0xe3, 0xc1, 0x40,
+  0x33, 0x33, 0x15, 0x42, 0x8b, 0xfd, 0x99, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x60, 0x43,
+  0x9a, 0x99, 0xa1, 0x41, 0xec, 0x11, 0xc6, 0x43, 0xf6, 0x28, 0x08, 0x41, 0x80, 0xb7, 0x13, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x37, 0x89, 0x21, 0x3f,
+  0x79, 0xe9, 0xc6, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x12, 0xa5, 0x95, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x13, 0xb7, 0x43, 0xe1, 0x7a, 0x18, 0x41,
+  0x0b, 0x7b, 0x1a, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0xdd, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x6d, 0xe7, 0x1b, 0x3f, 0x2b, 0x87, 0xae, 0x40, 0x66, 0x66, 0xb9, 0x42, 0x40, 0x13, 0xe9, 0x3f,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0xc0, 0x31, 0x44, 0xcd, 0xcc, 0xa0, 0x41, 0x85, 0x8b, 0xc5, 0x43,
+  0xe1, 0x7a, 0x90, 0x41, 0x76, 0x6c, 0x04, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x52, 0xb8, 0x5e, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e, 0x2d, 0xb2, 0xd5, 0x40, 0xcd, 0xcc, 0xf8, 0x41,
+  0x99, 0xbb, 0xbe, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x90, 0x43, 0x00, 0x00, 0x80, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xd7, 0xa3, 0xc8, 0x40, 0xf1, 0x2e, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xf9, 0x5e, 0x3f, 0xb6, 0xf3, 0xa5, 0x40,
+  0x9a, 0x99, 0xbb, 0x42, 0xef, 0xc9, 0xc3, 0x3f, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43,
+  0x33, 0x33, 0x6b, 0x41, 0xb8, 0x7e, 0xb2, 0x43, 0x5c, 0x8f, 0xe2, 0x41, 0x79, 0x23, 0xd3, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x25, 0x06, 0x01, 0x3f,
+  0x4c, 0x37, 0xe5, 0x40, 0xcd, 0xcc, 0x9f, 0x42, 0x07, 0xce, 0x4d, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0x3d, 0x0a, 0xba, 0x43, 0x1f, 0x85, 0xcb, 0x40,
+  0xc3, 0x9e, 0xa6, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x77, 0xbe, 0x1f, 0x3f, 0xc1, 0xca, 0xcd, 0x40, 0x9a, 0x99, 0xc5, 0x42, 0x00, 0x00, 0xe8, 0x3f,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x71, 0x3d, 0x76, 0x41, 0x76, 0xc3, 0x36, 0x3d, 0x00, 0x00, 0xc8, 0x41, 0x1f, 0x85, 0x9b, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xac, 0x1c, 0xda, 0x3e, 0xd9, 0xce, 0xd3, 0x40, 0xcd, 0xcc, 0x8c, 0x42,
+  0x89, 0xd2, 0xac, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x8c, 0x43, 0x00, 0x00, 0x98, 0x41,
+  0xa4, 0xd0, 0xc5, 0x43, 0x3d, 0x0a, 0xe7, 0x40, 0x38, 0xbe, 0x9c, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x37, 0x89, 0x21, 0x3f, 0x3d, 0x0a, 0x9f, 0x40,
+  0x00, 0x00, 0xc8, 0x42, 0x5c, 0x8f, 0xaa, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x8f, 0xc2, 0xbb, 0x43, 0xd7, 0xa3, 0x50, 0x40, 0x84, 0x0d, 0x17, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0x1f, 0x3f,
+  0x6d, 0xe7, 0xcb, 0x40, 0xcd, 0xcc, 0xc3, 0x42, 0x1f, 0xf4, 0x14, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x48, 0xe1, 0xc0, 0x43, 0x85, 0xeb, 0x31, 0x41,
+  0x43, 0xe7, 0x31, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xdb, 0xf9, 0x5e, 0x3f, 0x60, 0xe5, 0x9c, 0x40, 0x9a, 0x99, 0xc3, 0x42, 0x74, 0x46, 0xac, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xec, 0x51, 0xea, 0x41, 0x7a, 0xdf, 0x78, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x3e, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x21, 0xb0, 0x12, 0x3f, 0x64, 0x3b, 0xdf, 0x40, 0x00, 0x00, 0xb6, 0x42,
+  0x52, 0xb8, 0x0a, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x80, 0x88, 0x43, 0x00, 0x00, 0xa8, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xe1, 0x7a, 0xb4, 0x40, 0x04, 0x2d, 0x1d, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xc6, 0x2b, 0x3f, 0x73, 0x68, 0xd9, 0x40,
+  0x9a, 0x99, 0xc5, 0x42, 0xf2, 0xd2, 0xad, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x85, 0xeb, 0xa9, 0x41, 0xaf, 0xb1, 0x0b, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x29, 0x41, 0x00, 0x00, 0x00, 0x00, 0x35, 0x5e, 0xfa, 0x3e,
+  0x12, 0x83, 0xbc, 0x40, 0x66, 0x66, 0xb2, 0x41, 0x6f, 0x81, 0x7c, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x8a, 0x43, 0xcd, 0xcc, 0x94, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x85, 0xeb, 0x2d, 0x41,
+  0x11, 0x36, 0x79, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xe1, 0x7a, 0x14, 0x3f, 0xcb, 0xa1, 0xbd, 0x40, 0x00, 0x00, 0x8e, 0x42, 0x3a, 0x23, 0x3a, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xb8, 0x5e, 0xb8, 0x43,
+  0x3d, 0x0a, 0x91, 0x41, 0x01, 0x18, 0xcf, 0x3b, 0x00, 0x00, 0x90, 0x41, 0x0a, 0xd7, 0x13, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f, 0x66, 0x66, 0xd2, 0x40, 0x66, 0x66, 0x82, 0x42,
+  0x48, 0xe1, 0x82, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x94, 0x43, 0xcd, 0xcc, 0x74, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x29, 0x5c, 0x9f, 0x40, 0xd4, 0x82, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x1a, 0x3f, 0xf8, 0x53, 0xbb, 0x40,
+  0x9a, 0x99, 0xb7, 0x42, 0x0c, 0x02, 0x1b, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43,
+  0x33, 0x33, 0x6b, 0x41, 0x14, 0x8e, 0xc5, 0x43, 0x71, 0x3d, 0x3a, 0x41, 0x19, 0xc5, 0x1c, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x1a, 0x3f,
+  0x2f, 0xdd, 0xcc, 0x40, 0x66, 0x66, 0xbe, 0x42, 0xcd, 0xcc, 0x10, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0x1f, 0x05, 0xa5, 0x43, 0xb8, 0x1e, 0x35, 0x41,
+  0x86, 0x3d, 0xd1, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x80, 0x3f,
+  0x37, 0x89, 0x21, 0x3f, 0x12, 0x83, 0xe0, 0x40, 0x00, 0x00, 0xc3, 0x42, 0x3e, 0xe8, 0x99, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x66, 0x06, 0xc4, 0x43,
+  0xa4, 0x70, 0x3d, 0x40, 0x80, 0x2b, 0x99, 0x3e, 0x00, 0x00, 0xa0, 0x41, 0x52, 0xb8, 0xde, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x68, 0x91, 0xed, 0x3e, 0x5a, 0x64, 0xbb, 0x40, 0x66, 0x66, 0x28, 0x42,
+  0x5e, 0xba, 0x8d, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x5f, 0x43, 0xcd, 0xcc, 0x94, 0x41,
+  0x33, 0x53, 0xc2, 0x43, 0x00, 0x00, 0x50, 0x41, 0xc5, 0x1b, 0x19, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x7b, 0x14, 0xa6, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0x03, 0x3f, 0x85, 0xeb, 0xc9, 0x40,
+  0x00, 0x00, 0x1a, 0x42, 0x36, 0xab, 0xce, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x60, 0x43,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0xb3, 0xc2, 0x43, 0x00, 0x00, 0xd8, 0x40, 0x05, 0x40, 0x16, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x3d, 0x3f,
+  0x62, 0x10, 0xb4, 0x40, 0xcd, 0xcc, 0xbb, 0x42, 0x02, 0x9a, 0xe8, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x3d, 0x0a, 0xb7, 0x41,
+  0xf0, 0x6d, 0xba, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x1d, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x23, 0xdb, 0xf9, 0x3e, 0xc3, 0xf5, 0xe4, 0x40, 0x66, 0x66, 0xb8, 0x42, 0xa1, 0xd6, 0x2c, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x41, 0x43, 0x66, 0x66, 0x8e, 0x41, 0x5c, 0x0f, 0xc5, 0x43,
+  0x71, 0x3d, 0x9a, 0x40, 0xc2, 0x51, 0xb2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xae, 0x47, 0x4d, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e, 0xe1, 0x7a, 0xc4, 0x40, 0x33, 0x33, 0x37, 0x42,
+  0x60, 0xe5, 0x82, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc7, 0x43, 0x9a, 0x99, 0x95, 0x41,
+  0xe1, 0x7a, 0xc1, 0x43, 0xec, 0x51, 0x24, 0x41, 0x1a, 0x69, 0x89, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x3d, 0x0a, 0x1b, 0x41, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xc2, 0x15, 0x3f, 0x73, 0x68, 0xb9, 0x40,
+  0x33, 0x33, 0x8d, 0x42, 0xff, 0x21, 0x39, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x80, 0xc3, 0x43,
+  0x9a, 0x99, 0x99, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x9a, 0x99, 0x61, 0x41, 0x55, 0xc1, 0x48, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0x14, 0xae, 0xbf, 0x40, 0x66, 0x66, 0xa3, 0x42, 0xb8, 0x40, 0x88, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0x00, 0x60, 0xc1, 0x43, 0x52, 0xb8, 0x6a, 0x41,
+  0x09, 0xfe, 0x12, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x33, 0x33, 0x33, 0x3f, 0xe9, 0x26, 0xb1, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x8c, 0x4a, 0xca, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xcd, 0xcc, 0xbc, 0x41, 0x86, 0xac, 0x0c, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x06, 0x81, 0x15, 0x3f, 0x7b, 0x14, 0xb2, 0x40, 0x33, 0x33, 0x8d, 0x42,
+  0x62, 0x10, 0x04, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x9a, 0x99, 0x69, 0x40, 0xae, 0x47, 0x89, 0x41, 0x9a, 0xeb, 0x34, 0x3d, 0x00, 0x00, 0x8c, 0x42,
+  0x29, 0x5c, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0xcc, 0x3e, 0x3b, 0xdf, 0xdb, 0x40,
+  0x9a, 0x99, 0x3d, 0x42, 0x56, 0x7d, 0xfa, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xb3, 0x43,
+  0xcd, 0xcc, 0x6c, 0x41, 0x14, 0x6e, 0xc3, 0x43, 0x71, 0x3d, 0xc2, 0x40, 0xe6, 0x3f, 0x94, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x29, 0x41, 0x00, 0x00, 0x00, 0x00, 0x35, 0x5e, 0xfa, 0x3e,
+  0x1b, 0x2f, 0xad, 0x40, 0xcd, 0xcc, 0x1c, 0x41, 0x9a, 0x99, 0x65, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x8a, 0x43, 0xcd, 0xcc, 0x94, 0x41, 0x0a, 0x77, 0xae, 0x43, 0x66, 0x66, 0xec, 0x41,
+  0x15, 0x8c, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x80, 0x3f,
+  0xdb, 0xf9, 0x5e, 0x3f, 0x60, 0xe5, 0xac, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x30, 0x2a, 0xa9, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x5c, 0x8f, 0xd6, 0x41, 0x57, 0x60, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x27, 0x31, 0x08, 0x3f, 0x4e, 0x62, 0xb8, 0x40, 0x33, 0x33, 0x21, 0x42,
+  0x46, 0x25, 0x83, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0xc3, 0x75, 0xc4, 0x43, 0x52, 0xb8, 0x26, 0x41, 0xa1, 0x2d, 0x57, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f, 0x02, 0x2b, 0xb3, 0x40,
+  0x66, 0x66, 0xab, 0x42, 0x15, 0x8c, 0x8e, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43,
+  0x00, 0x00, 0xa8, 0x41, 0xc3, 0xb5, 0x97, 0x43, 0x7b, 0x14, 0x84, 0x41, 0x60, 0xe5, 0x10, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xdd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x42, 0x60, 0xe5, 0x3e,
+  0x73, 0x68, 0xc5, 0x40, 0x33, 0x33, 0xd3, 0x40, 0x9d, 0x11, 0xb7, 0x40, 0x00, 0x00, 0x40, 0x40,
+  0x00, 0x00, 0x69, 0x43, 0x33, 0x33, 0x8f, 0x41, 0x5c, 0xaf, 0xbf, 0x43, 0x85, 0xeb, 0xb9, 0x40,
+  0xb1, 0xbf, 0x2a, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xa4, 0x70, 0x3d, 0x3f, 0x21, 0xb0, 0xce, 0x40, 0x9a, 0x99, 0xbd, 0x42, 0x82, 0x73, 0xfe, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x71, 0x3d, 0x2c, 0x42,
+  0x0a, 0xd7, 0xbf, 0x41, 0x54, 0xa9, 0x99, 0x3d, 0x00, 0x00, 0x04, 0x42, 0x1f, 0x85, 0x0b, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0xa9, 0xf1, 0x3e, 0xa4, 0x70, 0xed, 0x40, 0xcd, 0xcc, 0x8f, 0x42,
+  0x4b, 0x59, 0x46, 0x40, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0x5e, 0x43, 0x33, 0x33, 0x93, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x3d, 0x0a, 0xcf, 0x40, 0x50, 0xc7, 0x63, 0x3d, 0x00, 0x00, 0x8c, 0x42,
+  0x29, 0x5c, 0x0f, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0xcc, 0x3e, 0xdf, 0x4f, 0xe1, 0x40,
+  0x00, 0x00, 0x20, 0x41, 0x56, 0x7d, 0xfa, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xb3, 0x43,
+  0xcd, 0xcc, 0x6c, 0x41, 0x3d, 0xca, 0xb9, 0x43, 0x14, 0xae, 0x97, 0x40, 0xf0, 0x16, 0x14, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00, 0x48, 0xe1, 0x1a, 0x3f,
+  0xf6, 0x28, 0xbc, 0x40, 0x9a, 0x99, 0xc2, 0x42, 0x76, 0xe0, 0x18, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0xa4, 0x10, 0xae, 0x43, 0xe1, 0x7a, 0x40, 0x41,
+  0x81, 0x21, 0x0b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x29, 0x41, 0x00, 0x00, 0x80, 0x3f,
+  0x35, 0x5e, 0xfa, 0x3e, 0x4a, 0x0c, 0xc2, 0x40, 0x66, 0x66, 0x6c, 0x42, 0x87, 0xa7, 0x87, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x8a, 0x43, 0xcd, 0xcc, 0x94, 0x41, 0xf6, 0xa8, 0xbe, 0x43,
+  0x5c, 0x8f, 0x6a, 0x41, 0xd5, 0x04, 0x81, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x29, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x35, 0x5e, 0xfa, 0x3e, 0x56, 0x0e, 0xb9, 0x40, 0x66, 0x66, 0x91, 0x42,
+  0x57, 0x5b, 0x8b, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x8a, 0x43, 0xcd, 0xcc, 0x94, 0x41,
+  0x0a, 0xb7, 0xc2, 0x43, 0xe1, 0x7a, 0x90, 0x41, 0xcd, 0xcc, 0xcc, 0x3d, 0x00, 0x00, 0x08, 0x42,
+  0x48, 0xe1, 0xc2, 0x40, 0x00, 0x00, 0x00, 0x00, 0x2d, 0xb2, 0xdd, 0x3e, 0x8b, 0x6c, 0xdf, 0x40,
+  0x9a, 0x99, 0x8d, 0x41, 0x02, 0xbc, 0xaf, 0x40, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x80, 0xa4, 0x43,
+  0xcd, 0xcc, 0x80, 0x41, 0x0a, 0x37, 0xc3, 0x43, 0x1f, 0x85, 0x9b, 0x40, 0x3e, 0x68, 0x19, 0x42,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f,
+  0xfa, 0x7e, 0xae, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x36, 0xab, 0xbe, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x52, 0xb8, 0xf4, 0x41,
+  0xa5, 0xf7, 0x0d, 0x3d, 0x00, 0x00, 0x0c, 0x42, 0x85, 0xeb, 0xc1, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x6e, 0x34, 0xe0, 0x3e, 0xf4, 0xfd, 0xc0, 0x40, 0x66, 0x66, 0xba, 0x41, 0x9d, 0x80, 0xd4, 0x40,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x98, 0x43, 0x33, 0x33, 0x87, 0x41, 0x00, 0x20, 0xb5, 0x43,
+  0x5c, 0x8f, 0xfa, 0x40, 0x05, 0xc5, 0x0f, 0x3d, 0x00, 0x00, 0xbe, 0x42, 0x1f, 0x85, 0x2b, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0xd5, 0x3e, 0xc7, 0x4b, 0xfb, 0x40, 0xcd, 0xcc, 0x04, 0x42,
+  0xa8, 0xc6, 0xa3, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x60, 0x43, 0x33, 0x33, 0x6b, 0x41,
+  0xd7, 0x63, 0xc4, 0x43, 0x0a, 0xd7, 0x73, 0x40, 0x0f, 0x8b, 0x4c, 0x42, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xd4, 0x18, 0x3f, 0x58, 0x39, 0xb8, 0x40,
+  0x00, 0x00, 0xc8, 0x42, 0x2f, 0xdd, 0xb4, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x66, 0x66, 0x26, 0x40, 0x8f, 0xc2, 0x21, 0x41, 0x90, 0xf7, 0xd6, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f,
+  0xcf, 0xf7, 0xd7, 0x40, 0x33, 0x33, 0xb9, 0x42, 0xdd, 0xb5, 0x14, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x0a, 0xd7, 0xa3, 0x3e, 0x1f, 0x85, 0x8b, 0x41,
+  0xe3, 0x8d, 0x1c, 0x3f, 0x00, 0x00, 0xa0, 0x41, 0x7b, 0x14, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcb, 0xa1, 0x25, 0x3f, 0x96, 0x43, 0x0b, 0x41, 0xcd, 0xcc, 0xad, 0x42, 0x2b, 0x87, 0xe6, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x84, 0x43, 0x00, 0x00, 0x50, 0x41, 0x9a, 0xd9, 0xc2, 0x43,
+  0x0a, 0xd7, 0xa3, 0x40, 0x30, 0xcc, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x3d, 0x3f, 0x31, 0x08, 0xc8, 0x40, 0x33, 0x33, 0xc1, 0x42,
+  0x08, 0xac, 0x0c, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x8f, 0x42, 0xc2, 0x43, 0x1f, 0x85, 0x83, 0x41, 0x4a, 0x07, 0x03, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xca, 0x01, 0x3f, 0xbc, 0x74, 0xeb, 0x40,
+  0x33, 0x33, 0x8f, 0x42, 0x6a, 0xbc, 0x84, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43,
+  0x33, 0x33, 0x8b, 0x41, 0xf6, 0x08, 0xc3, 0x43, 0x29, 0x5c, 0x97, 0x40, 0xda, 0xe1, 0x2f, 0x3d,
+  0x00, 0x00, 0xe0, 0x41, 0xd7, 0xa3, 0x70, 0x41, 0x00, 0x00, 0x00, 0x00, 0x68, 0x91, 0xed, 0x3e,
+  0xcf, 0xf7, 0xc7, 0x40, 0x9a, 0x99, 0x9a, 0x42, 0x29, 0x5c, 0x67, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x87, 0x43, 0x9a, 0x99, 0x91, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xa4, 0x70, 0x29, 0x41,
+  0x94, 0x13, 0x2d, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0xcd, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x6a, 0xbc, 0x14, 0x3f, 0x50, 0x8d, 0xbf, 0x40, 0xcd, 0xcc, 0xb0, 0x42, 0x59, 0x17, 0xff, 0x3f,
+  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3c, 0x43, 0xcd, 0xcc, 0x98, 0x41, 0x8f, 0x82, 0xc0, 0x43,
+  0xc3, 0xf5, 0x6c, 0x41, 0xdb, 0xa2, 0xcc, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x85, 0xeb, 0xf1, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xa6, 0x9b, 0x04, 0x3f, 0xae, 0x47, 0xd1, 0x40, 0xcd, 0xcc, 0x6e, 0x42,
+  0x72, 0x8a, 0xc8, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0xd3, 0x43, 0x66, 0x66, 0x7e, 0x41,
+  0xe1, 0xfa, 0xc2, 0x43, 0x66, 0x66, 0x0a, 0x41, 0xe0, 0xad, 0xa0, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3f, 0xa8, 0xc6, 0x8b, 0x40,
+  0x66, 0x66, 0xb6, 0x42, 0x89, 0x41, 0xb8, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x3d, 0xea, 0x8e, 0x43, 0x3d, 0x0a, 0xf5, 0x41, 0x94, 0xc1, 0x9d, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0x44, 0x8b, 0xc4, 0x40, 0x66, 0x66, 0xb7, 0x42, 0x88, 0x85, 0x7e, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x8f, 0xc2, 0x95, 0x41,
+  0x78, 0x97, 0x17, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xdb, 0xf9, 0x5e, 0x3f, 0xcb, 0xa1, 0x9d, 0x40, 0x66, 0x66, 0xbf, 0x42, 0x7f, 0xfb, 0xba, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0xe1, 0xda, 0xc3, 0x43,
+  0x71, 0x3d, 0xec, 0x41, 0x20, 0xb5, 0xc9, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0xcd, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x6a, 0xbc, 0x14, 0x3f, 0xc5, 0x20, 0xbc, 0x40, 0x9a, 0x99, 0xbf, 0x42,
+  0x38, 0x67, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3c, 0x43, 0xcd, 0xcc, 0x98, 0x41,
+  0xa4, 0xb0, 0xbd, 0x43, 0xd7, 0xa3, 0x8c, 0x41, 0xd0, 0xf3, 0xb1, 0x42, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xc6, 0x2b, 0x3f, 0xdb, 0xf9, 0xde, 0x40,
+  0xcd, 0xcc, 0xb7, 0x42, 0xdf, 0x4f, 0xb5, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x14, 0xae, 0x89, 0x41, 0x3f, 0x35, 0x5e, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x81, 0x40, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x8f, 0x02, 0x3f,
+  0x7b, 0x14, 0xca, 0x40, 0xcd, 0xcc, 0x92, 0x42, 0xec, 0x51, 0x54, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0x94, 0x43, 0xcd, 0xcc, 0x84, 0x41, 0xcd, 0xcc, 0xc5, 0x43, 0xae, 0x47, 0xc9, 0x40,
+  0x35, 0x07, 0x88, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x81, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x5c, 0x8f, 0x02, 0x3f, 0x1f, 0x85, 0xdb, 0x40, 0xcd, 0xcc, 0x94, 0x42, 0x46, 0x94, 0x3a, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x94, 0x43, 0xcd, 0xcc, 0x84, 0x41, 0x8f, 0xa2, 0xc3, 0x43,
+  0xa4, 0x70, 0xdd, 0x40, 0x54, 0x3a, 0x18, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x08, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0x05, 0x3f, 0x96, 0x43, 0xd7, 0x40, 0xcd, 0xcc, 0x9f, 0x42,
+  0x7a, 0xc7, 0x31, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x43, 0x33, 0x33, 0xa7, 0x41,
+  0x48, 0x61, 0xc5, 0x43, 0x52, 0xb8, 0x16, 0x41, 0xe0, 0x67, 0xfc, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x66, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f, 0xec, 0x51, 0xd4, 0x40,
+  0x00, 0x00, 0xa5, 0x42, 0xec, 0x51, 0x54, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x98, 0x43,
+  0x33, 0x33, 0x93, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xae, 0x47, 0x91, 0x40, 0x77, 0x84, 0xd3, 0x3d,
+  0x00, 0x00, 0xc8, 0x41, 0xf6, 0x28, 0xa4, 0x40, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xef, 0xe7, 0x3e,
+  0xfc, 0xa9, 0xbd, 0x40, 0xcd, 0xcc, 0x3c, 0x42, 0xf2, 0xd2, 0xdd, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x00, 0x8e, 0x43, 0x9a, 0x99, 0x9d, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x1f, 0x85, 0x13, 0x41,
+  0x76, 0x54, 0xe5, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x80, 0x3f,
+  0xc1, 0xca, 0x01, 0x3f, 0x64, 0x3b, 0xd7, 0x40, 0x00, 0x00, 0x85, 0x42, 0xbb, 0xb8, 0x69, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0x9a, 0x19, 0xb4, 0x43,
+  0xcd, 0xcc, 0x00, 0x41, 0xac, 0xca, 0x0e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0x1f, 0x3f, 0x52, 0xb8, 0xca, 0x40, 0x66, 0x66, 0xc4, 0x42,
+  0xb5, 0x15, 0x07, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41,
+  0xc3, 0x55, 0xc5, 0x43, 0x14, 0xae, 0x87, 0x41, 0xa5, 0x49, 0x49, 0x3e, 0x00, 0x00, 0xb0, 0x41,
+  0x1f, 0x85, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0xac, 0xdc, 0x3e, 0x64, 0x3b, 0xc7, 0x40,
+  0x66, 0x66, 0x9e, 0x42, 0x54, 0xe3, 0x00, 0x41, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0xa5, 0x43,
+  0xcd, 0xcc, 0x98, 0x41, 0xec, 0x11, 0xbc, 0x43, 0x66, 0x66, 0x22, 0x41, 0xdf, 0x37, 0xc9, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x3d, 0x3f,
+  0x79, 0xe9, 0xca, 0x40, 0xcd, 0xcc, 0xc0, 0x42, 0xa6, 0x9b, 0x04, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x48, 0x01, 0x9f, 0x43, 0xec, 0x51, 0x8e, 0x41,
+  0x60, 0xea, 0xa7, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x52, 0xb8, 0x5e, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x77, 0xbe, 0xdf, 0x3e, 0xba, 0x49, 0xc0, 0x40, 0x33, 0x33, 0x29, 0x42, 0x1e, 0x16, 0xb0, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x90, 0x43, 0x00, 0x00, 0x80, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x66, 0x66, 0x26, 0x41, 0x6f, 0x9e, 0x6a, 0x3c, 0x00, 0x00, 0xc8, 0x42, 0xc3, 0xf5, 0xa8, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x98, 0x6e, 0xd2, 0x3e, 0xac, 0x1c, 0xda, 0x40, 0x00, 0x00, 0x22, 0x42,
+  0x61, 0x32, 0x05, 0x41, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x80, 0x43, 0x9a, 0x99, 0x71, 0x41,
+  0x33, 0x73, 0xc4, 0x43, 0xcd, 0xcc, 0x7c, 0x40, 0x65, 0xfc, 0x7b, 0x3c, 0x00, 0x00, 0xb4, 0x42,
+  0x00, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0xc9, 0x3e, 0x2b, 0x87, 0xee, 0x40,
+  0xcd, 0xcc, 0x08, 0x42, 0x55, 0xc1, 0xca, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x74, 0x43,
+  0x66, 0x66, 0x7e, 0x41, 0x85, 0x2b, 0xc1, 0x43, 0x3d, 0x0a, 0x47, 0x40, 0xb7, 0x28, 0xb3, 0x3c,
+  0x00, 0x00, 0x70, 0x42, 0x1f, 0x85, 0x3b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xdf, 0x4f, 0xcd, 0x3e,
+  0x9a, 0x99, 0xd9, 0x40, 0x66, 0x66, 0x1e, 0x41, 0xf7, 0x06, 0xc7, 0x40, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x80, 0x84, 0x43, 0x9a, 0x99, 0x79, 0x41, 0x5c, 0xaf, 0xc4, 0x43, 0xc3, 0xf5, 0xa0, 0x40,
+  0x6a, 0x13, 0x98, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x2b, 0x87, 0x36, 0x3f, 0xcd, 0xcc, 0xd0, 0x40, 0x00, 0x00, 0xad, 0x42, 0x26, 0xe4, 0x1b, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x14, 0xae, 0x4b, 0x42,
+  0x3d, 0x0a, 0x91, 0x41, 0xaa, 0x60, 0xa9, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3f, 0xcb, 0xa1, 0xc1, 0x40, 0x00, 0x00, 0xa5, 0x42,
+  0x3c, 0xbd, 0x0a, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0xa4, 0x30, 0xbd, 0x43, 0x7b, 0x14, 0x96, 0x41, 0x67, 0xd5, 0x67, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x3d, 0x5a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x35, 0x5e, 0xfa, 0x3e, 0x58, 0x39, 0xe0, 0x40,
+  0x9a, 0x99, 0xac, 0x42, 0x22, 0xfd, 0x5a, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x87, 0x43,
+  0x66, 0x66, 0x8e, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x00, 0x00, 0xb0, 0x40, 0xe5, 0x44, 0xfb, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xdd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x42, 0x60, 0xe5, 0x3e,
+  0x3f, 0x35, 0xc2, 0x40, 0x00, 0x00, 0x20, 0x42, 0x9d, 0x11, 0xb7, 0x40, 0x00, 0x00, 0x40, 0x40,
+  0x00, 0x00, 0x69, 0x43, 0x33, 0x33, 0x8f, 0x41, 0xec, 0xb1, 0xc2, 0x43, 0xcd, 0xcc, 0x18, 0x41,
+  0xd0, 0xd5, 0x72, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xa4, 0x70, 0x3d, 0x3f, 0x2f, 0xdd, 0xc4, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x81, 0x04, 0xf5, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xb8, 0x1e, 0x15, 0x41,
+  0x9a, 0x99, 0xd3, 0x41, 0x6b, 0x60, 0x9b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0xec, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x7f, 0x6a, 0xfc, 0x3e, 0xe7, 0xfb, 0xc9, 0x40, 0x33, 0x33, 0xe7, 0x41,
+  0x0e, 0x4f, 0xad, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x8f, 0x43, 0xcd, 0xcc, 0x9c, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xcd, 0xcc, 0xc4, 0x40, 0x71, 0x20, 0xa4, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x52, 0xb8, 0xbe, 0x40, 0x00, 0x00, 0x00, 0x00, 0xee, 0x7c, 0xff, 0x3e, 0x33, 0x33, 0xbb, 0x40,
+  0x00, 0x00, 0x26, 0x42, 0xef, 0xc9, 0x7b, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x8b, 0x43,
+  0x9a, 0x99, 0x99, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xec, 0x51, 0x0c, 0x41, 0x7e, 0x3a, 0x18, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x3f, 0x15, 0x3f,
+  0x3b, 0xdf, 0xbb, 0x40, 0x9a, 0x99, 0x27, 0x42, 0x04, 0x56, 0x6e, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x71, 0x5d, 0xb9, 0x43, 0xa4, 0x70, 0x55, 0x41,
+  0xa8, 0x35, 0xce, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x81, 0x15, 0x3f, 0x9a, 0x99, 0xcd, 0x40, 0x9a, 0x99, 0x95, 0x42, 0x5b, 0xd3, 0x0c, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x66, 0xe6, 0xc3, 0x42,
+  0xe1, 0x7a, 0x40, 0x41, 0x2a, 0x00, 0x26, 0x3e, 0x00, 0x00, 0xa0, 0x41, 0x52, 0xb8, 0xde, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x68, 0x91, 0xed, 0x3e, 0x14, 0xae, 0xc7, 0x40, 0x66, 0x66, 0x82, 0x41,
+  0x5e, 0xba, 0x8d, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x5f, 0x43, 0xcd, 0xcc, 0x94, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x48, 0xe1, 0xd2, 0x40, 0xb8, 0x75, 0xf7, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0xc3, 0xf5, 0x38, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xd7, 0xe3, 0x3e, 0xa0, 0x1a, 0x01, 0x41,
+  0x00, 0x00, 0x98, 0x42, 0x5b, 0xb1, 0x5f, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x8a, 0x43,
+  0x00, 0x00, 0x90, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x52, 0xb8, 0x86, 0x40, 0x59, 0xa3, 0xae, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0xec, 0x40, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x6a, 0xfc, 0x3e,
+  0xae, 0x47, 0xcd, 0x40, 0x66, 0x66, 0x20, 0x42, 0x40, 0x13, 0x97, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0x8f, 0x43, 0xcd, 0xcc, 0x9c, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x0a, 0xd7, 0xc3, 0x40,
+  0x5a, 0x81, 0xa1, 0x3d, 0x00, 0x00, 0xa0, 0x42, 0x66, 0x66, 0x9e, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x98, 0x6e, 0xd2, 0x3e, 0x6a, 0xbc, 0xe4, 0x40, 0x9a, 0x99, 0xdd, 0x41, 0x02, 0xbc, 0xa3, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x75, 0x43, 0x9a, 0x99, 0x99, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x0a, 0xd7, 0x63, 0x40, 0x37, 0x1a, 0x28, 0x3f, 0x00, 0x00, 0xa0, 0x41, 0x7b, 0x14, 0x7e, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcb, 0xa1, 0x25, 0x3f, 0xaa, 0xf1, 0xda, 0x40, 0x00, 0x00, 0xc8, 0x42,
+  0x4f, 0xaf, 0x00, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x84, 0x43, 0x00, 0x00, 0x50, 0x41,
+  0x0a, 0xf7, 0xc3, 0x43, 0xcd, 0xcc, 0xdc, 0x40, 0xae, 0x47, 0xa1, 0x3d, 0x00, 0x00, 0x34, 0x42,
+  0xf6, 0x28, 0x5c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e, 0x25, 0x06, 0xd9, 0x40,
+  0x66, 0x66, 0x24, 0x42, 0x6c, 0x78, 0x72, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc7, 0x43,
+  0x33, 0x33, 0x73, 0x41, 0x5c, 0xef, 0xc4, 0x43, 0x8f, 0xc2, 0xd5, 0x40, 0x70, 0x94, 0xcc, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x06, 0x81, 0x15, 0x3f,
+  0x1b, 0x2f, 0xc5, 0x40, 0xcd, 0xcc, 0xc2, 0x42, 0x1b, 0x2f, 0x0d, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x48, 0x61, 0x97, 0x43, 0xcd, 0xcc, 0xc0, 0x41,
+  0x17, 0x9a, 0xeb, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x38, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x0a, 0xd7, 0xe3, 0x3e, 0x4c, 0x37, 0xc5, 0x40, 0x33, 0x33, 0x8b, 0x42, 0x5b, 0xb1, 0x5f, 0x40,
+  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x8a, 0x43, 0x00, 0x00, 0x90, 0x41, 0x3d, 0xea, 0xc3, 0x43,
+  0xa4, 0x70, 0x35, 0x41, 0x91, 0xd0, 0x76, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0xec, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x7f, 0x6a, 0xfc, 0x3e, 0xf0, 0xa7, 0xc2, 0x40, 0xcd, 0xcc, 0x2e, 0x42,
+  0x0e, 0x4f, 0xad, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x8f, 0x43, 0xcd, 0xcc, 0x9c, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xd7, 0xa3, 0x4c, 0x41, 0xa3, 0x23, 0x49, 0x3f, 0x00, 0x00, 0xa0, 0x41,
+  0x7b, 0x14, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcb, 0xa1, 0x25, 0x3f, 0xb0, 0x72, 0xe0, 0x40,
+  0x33, 0x33, 0xa9, 0x42, 0x6f, 0x81, 0x08, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x84, 0x43,
+  0x00, 0x00, 0x50, 0x41, 0xf6, 0x08, 0xc0, 0x43, 0xd7, 0xa3, 0x6c, 0x41, 0x3d, 0x44, 0x53, 0x3f,
+  0x00, 0x00, 0xa0, 0x41, 0x7b, 0x14, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcb, 0xa1, 0x25, 0x3f,
+  0xc9, 0x76, 0xea, 0x40, 0x00, 0x00, 0xbd, 0x42, 0x0f, 0x0b, 0x05, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0x84, 0x43, 0x00, 0x00, 0x50, 0x41, 0xc3, 0xb5, 0xc4, 0x43, 0x00, 0x00, 0x34, 0x41,
+  0x81, 0xcf, 0x8f, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x81, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x5c, 0x8f, 0x02, 0x3f, 0xd7, 0xa3, 0xc0, 0x40, 0xcd, 0xcc, 0x3c, 0x42, 0x7b, 0x83, 0x63, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x94, 0x43, 0xcd, 0xcc, 0x84, 0x41, 0x71, 0x9d, 0xc4, 0x43,
+  0x8f, 0xc2, 0x21, 0x41, 0x40, 0xfb, 0x81, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xdd, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x42, 0x60, 0xe5, 0x3e, 0x9c, 0xc4, 0xac, 0x40, 0x9a, 0x99, 0xbe, 0x42,
+  0x0a, 0xd7, 0xbb, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x69, 0x43, 0x33, 0x33, 0x8f, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xe1, 0x7a, 0xf6, 0x41, 0x99, 0xbb, 0x66, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x3d, 0x3f, 0x83, 0xc0, 0xce, 0x40,
+  0x9a, 0x99, 0xba, 0x42, 0x99, 0x2a, 0x00, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x85, 0xeb, 0xdb, 0x41, 0x66, 0x66, 0x90, 0x41, 0x90, 0x49, 0x66, 0x3e,
+  0x00, 0x00, 0x48, 0x41, 0x0a, 0xd7, 0xfb, 0x40, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x24, 0x06, 0x3f,
+  0x62, 0x10, 0xcc, 0x40, 0x9a, 0x99, 0xbc, 0x42, 0x2b, 0x18, 0xcb, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x80, 0x9b, 0x43, 0x33, 0x33, 0x73, 0x41, 0x8f, 0x42, 0xc4, 0x43, 0x9a, 0x99, 0xa3, 0x41,
+  0xf4, 0xa6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0xe1, 0x1a, 0x3f, 0x5e, 0xba, 0xfd, 0x40, 0x66, 0x66, 0xc0, 0x42, 0x07, 0xf0, 0x02, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0x66, 0xa6, 0xb8, 0x43,
+  0xcd, 0xcc, 0x6c, 0x40, 0x3f, 0x6f, 0xc2, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41,
+  0x00, 0x00, 0x80, 0x3f, 0x48, 0xe1, 0x1a, 0x3f, 0x00, 0x00, 0x06, 0x41, 0xcd, 0xcc, 0xbb, 0x42,
+  0x35, 0x5e, 0x0a, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41,
+  0x9a, 0x39, 0xc2, 0x43, 0xe1, 0x7a, 0x54, 0x40, 0xee, 0x7c, 0x96, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xd4, 0x18, 0x3f, 0x93, 0x18, 0x94, 0x40,
+  0x00, 0x00, 0xc8, 0x42, 0x32, 0xe6, 0xc6, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0xec, 0x51, 0xe6, 0x41, 0xe1, 0x7a, 0x09, 0x42, 0x4b, 0x1f, 0x5a, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0x48, 0xe1, 0xbe, 0x40, 0x66, 0x66, 0xb2, 0x42, 0xc3, 0x64, 0x80, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0xd7, 0x43, 0xc4, 0x43, 0xae, 0x47, 0x5d, 0x41,
+  0x5e, 0xba, 0x23, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x1b, 0x2f, 0x1d, 0x3f, 0x85, 0xeb, 0xc5, 0x40, 0x66, 0x66, 0xc1, 0x42, 0x79, 0xe9, 0x0a, 0x40,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x9a, 0xd9, 0xbd, 0x43,
+  0x71, 0x3d, 0x90, 0x41, 0x02, 0xfc, 0x36, 0x42, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f, 0xa6, 0x9b, 0x90, 0x40, 0x00, 0x00, 0xc8, 0x42,
+  0xe6, 0x3f, 0xd4, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x3d, 0x8a, 0xb0, 0x42, 0x85, 0xeb, 0x13, 0x42, 0xa8, 0xa9, 0xb1, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f, 0x66, 0x66, 0xbe, 0x40,
+  0x00, 0x00, 0xa4, 0x42, 0x29, 0x5c, 0x7f, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43,
+  0x00, 0x00, 0xa8, 0x41, 0x9a, 0x99, 0x68, 0x43, 0x14, 0xae, 0xdd, 0x41, 0xbe, 0x30, 0x99, 0x3c,
+  0x00, 0x00, 0xaa, 0x42, 0xcd, 0xcc, 0x84, 0x40, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xa5, 0xdb, 0x3e,
+  0x12, 0x83, 0xd0, 0x40, 0x9a, 0x99, 0xdd, 0x41, 0x97, 0x90, 0x08, 0x41, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0xaf, 0x43, 0x33, 0x33, 0x8f, 0x41, 0x0a, 0x37, 0xc4, 0x43, 0x1f, 0x85, 0xcb, 0x40,
+  0x4d, 0xdb, 0x3f, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x5a, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x35, 0x5e, 0xfa, 0x3e, 0x10, 0x58, 0xcd, 0x40, 0x33, 0x33, 0x84, 0x42, 0x3e, 0xe8, 0x45, 0x40,
+  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x87, 0x43, 0x66, 0x66, 0x8e, 0x41, 0x0a, 0x17, 0xc4, 0x43,
+  0xc3, 0xf5, 0x0c, 0x41, 0x11, 0x19, 0x36, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x0a, 0x1b, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x8f, 0xc2, 0x15, 0x3f, 0x3f, 0x35, 0xb2, 0x40, 0x00, 0x00, 0x93, 0x42,
+  0xf6, 0x97, 0x19, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x80, 0xc3, 0x43, 0x9a, 0x99, 0x99, 0x41,
+  0x8f, 0xe2, 0xc5, 0x43, 0x9a, 0x99, 0x71, 0x41, 0x0a, 0x11, 0x40, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f, 0x68, 0x91, 0xbd, 0x40,
+  0x33, 0x33, 0xbc, 0x42, 0x86, 0xc9, 0x8c, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43,
+  0x00, 0x00, 0xa8, 0x41, 0x3d, 0x2a, 0xc5, 0x43, 0x66, 0x66, 0x82, 0x41, 0x62, 0x4a, 0x24, 0x3d,
+  0x00, 0x00, 0xa0, 0x42, 0x5c, 0x8f, 0xc2, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x17, 0xd9, 0xce, 0x3e,
+  0x1b, 0x2f, 0xe9, 0x40, 0x66, 0x66, 0x08, 0x42, 0x54, 0xe3, 0xe9, 0x40, 0x00, 0x00, 0x00, 0x40,
+  0x00, 0x80, 0xa4, 0x43, 0x9a, 0x99, 0x49, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x5c, 0x8f, 0x82, 0x40,
+  0x2e, 0xe2, 0xab, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0xe1, 0x1a, 0x3f, 0xac, 0x1c, 0xc2, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x35, 0xef, 0xe0, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0xec, 0xf1, 0xb0, 0x43,
+  0x8f, 0xc2, 0xcd, 0x40, 0xb6, 0xdb, 0xfa, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x14, 0xae, 0x27, 0x3f, 0x21, 0xb0, 0xc6, 0x40, 0xcd, 0xcc, 0x82, 0x42,
+  0x58, 0xa8, 0x3d, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x1f, 0x85, 0x53, 0x41, 0x71, 0x1b, 0x0d, 0x3d, 0x00, 0x00, 0xa5, 0x42,
+  0x85, 0xeb, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x7a, 0xd4, 0x3e, 0x1b, 0x2f, 0xc5, 0x40,
+  0x9a, 0x99, 0x19, 0x42, 0xd7, 0xa3, 0xc8, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xae, 0x43,
+  0x33, 0x33, 0x6b, 0x41, 0x8f, 0xe2, 0xc4, 0x43, 0x8f, 0xc2, 0xed, 0x40, 0xfe, 0x65, 0x31, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xce, 0x37, 0x3f,
+  0xe9, 0x26, 0xcd, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x6f, 0xf0, 0xed, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x00, 0x60, 0x9f, 0x43, 0xec, 0x51, 0x70, 0x41,
+  0xc6, 0x33, 0x90, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x80, 0x3f,
+  0xdb, 0xf9, 0x5e, 0x3f, 0x4e, 0x62, 0xa0, 0x40, 0x00, 0x00, 0xb0, 0x42, 0x09, 0x1b, 0xce, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41, 0xd7, 0xa3, 0xab, 0x43,
+  0x85, 0xeb, 0x41, 0x41, 0x46, 0x99, 0x71, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x14, 0xae, 0x27, 0x3f, 0xc9, 0x76, 0xbe, 0x40, 0x66, 0x66, 0xa9, 0x42,
+  0xa8, 0xc6, 0x37, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x7b, 0x14, 0xb0, 0x41, 0x33, 0x33, 0x89, 0x41, 0xa6, 0x9b, 0x74, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xc6, 0x2b, 0x3f, 0x9c, 0xc4, 0xd4, 0x40,
+  0x9a, 0x99, 0xba, 0x42, 0xaf, 0x25, 0xac, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x8f, 0x82, 0xb5, 0x43, 0x85, 0xeb, 0xb9, 0x41, 0xb6, 0x67, 0xd6, 0x3d,
+  0x00, 0x00, 0x20, 0x42, 0xb8, 0x1e, 0xcd, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x2f, 0xdd, 0xe4, 0x3e,
+  0x44, 0x8b, 0xe8, 0x40, 0x00, 0x00, 0x44, 0x42, 0xbe, 0x30, 0x99, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x7e, 0x43, 0xcd, 0xcc, 0x8c, 0x41, 0x00, 0xa0, 0xc2, 0x43, 0x9a, 0x99, 0xc1, 0x40,
+  0x9a, 0x42, 0x67, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xae, 0x47, 0x4d, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x77, 0xbe, 0xdf, 0x3e, 0x8b, 0x6c, 0xc7, 0x40, 0xcd, 0xcc, 0x56, 0x42, 0x82, 0x73, 0xa0, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc7, 0x43, 0x9a, 0x99, 0x95, 0x41, 0x33, 0x33, 0xc1, 0x43,
+  0xa4, 0x70, 0x45, 0x41, 0xab, 0x95, 0x09, 0x3d, 0x00, 0x00, 0x96, 0x42, 0xcd, 0xcc, 0x3c, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xd1, 0x22, 0xdb, 0x3e, 0x9c, 0xc4, 0xe0, 0x40, 0xcd, 0xcc, 0x7c, 0x41,
+  0xd0, 0xd5, 0xac, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x7c, 0x43, 0x66, 0x66, 0x92, 0x41,
+  0x5c, 0xcf, 0xc5, 0x43, 0xa4, 0x70, 0xfd, 0x3f, 0x47, 0x8f, 0xdf, 0x3c, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x3d, 0xe2, 0x40, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x20, 0xf0, 0x3e, 0x85, 0xeb, 0xe5, 0x40,
+  0x66, 0x66, 0x74, 0x42, 0x7c, 0xf2, 0x9e, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x72, 0x43,
+  0x66, 0x66, 0x8e, 0x41, 0x3d, 0x6a, 0xc4, 0x43, 0xc3, 0xf5, 0x80, 0x40, 0xa6, 0x27, 0x2c, 0x3d,
+  0x00, 0x00, 0xe0, 0x41, 0xd7, 0xa3, 0x70, 0x41, 0x00, 0x00, 0x00, 0x00, 0x68, 0x91, 0xed, 0x3e,
+  0xdd, 0x24, 0xce, 0x40, 0x66, 0x66, 0x56, 0x42, 0x1b, 0x9e, 0x6a, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x87, 0x43, 0x9a, 0x99, 0x91, 0x41, 0x48, 0x81, 0xc5, 0x43, 0x5c, 0x8f, 0x02, 0x41,
+  0xe2, 0x69, 0xc6, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x73, 0x68, 0x31, 0x3f, 0x02, 0x2b, 0xab, 0x40, 0x00, 0x00, 0xc0, 0x42, 0x5a, 0xf5, 0xd9, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xf6, 0x28, 0x9e, 0x41, 0xd4, 0x37, 0x18, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f, 0xc7, 0x4b, 0xd7, 0x40, 0x33, 0x33, 0xbc, 0x42,
+  0x1a, 0xc0, 0x1f, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x8f, 0xc2, 0xd5, 0x40, 0x14, 0xae, 0x95, 0x41, 0x83, 0xfa, 0x86, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xc3, 0xf5, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0x05, 0x3f, 0xf8, 0x53, 0xc7, 0x40,
+  0x66, 0x66, 0xb6, 0x42, 0xeb, 0xe2, 0x22, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x43,
+  0x33, 0x33, 0xa7, 0x41, 0x71, 0x9d, 0xc3, 0x43, 0xcd, 0xcc, 0x78, 0x41, 0x3d, 0xd5, 0xe1, 0x3d,
+  0x00, 0x00, 0xc8, 0x41, 0xf6, 0x28, 0xa4, 0x40, 0x00, 0x00, 0x00, 0x00, 0x9e, 0xef, 0xe7, 0x3e,
+  0x8d, 0x97, 0xce, 0x40, 0x9a, 0x99, 0x87, 0x42, 0x4c, 0x37, 0xe7, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x00, 0x8e, 0x43, 0x9a, 0x99, 0x9d, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x29, 0x5c, 0xd7, 0x40,
+  0x06, 0x12, 0x14, 0x3d, 0x00, 0x00, 0xa0, 0x42, 0x66, 0x66, 0x9e, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x98, 0x6e, 0xd2, 0x3e, 0xf6, 0x28, 0xd4, 0x40, 0x33, 0x33, 0xbb, 0x41, 0x02, 0xbc, 0xa3, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x75, 0x43, 0x9a, 0x99, 0x99, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x66, 0x66, 0x96, 0x40, 0xca, 0xc3, 0x7d, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xf2, 0xd2, 0x2d, 0x3f, 0x08, 0xac, 0xbc, 0x40, 0xcd, 0xcc, 0xbe, 0x42,
+  0xc6, 0x6d, 0xf4, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x8f, 0xc2, 0xf5, 0x40, 0xb8, 0x1e, 0xc3, 0x41, 0x0f, 0xb9, 0xe0, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xce, 0x37, 0x3f, 0x27, 0x31, 0xc0, 0x40,
+  0x9a, 0x99, 0xbe, 0x42, 0xe5, 0xf2, 0xef, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x71, 0xfd, 0x9f, 0x43, 0x33, 0x33, 0x7b, 0x41, 0x3b, 0xfc, 0x85, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f,
+  0x6a, 0xbc, 0xc0, 0x40, 0xcd, 0xcc, 0xb4, 0x42, 0x42, 0x60, 0x35, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x98, 0x43, 0x33, 0x33, 0x93, 0x41, 0x66, 0x26, 0xc6, 0x43, 0x1f, 0x85, 0x3b, 0x41,
+  0xee, 0x5a, 0x58, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x37, 0x89, 0x21, 0x3f, 0x64, 0x3b, 0x77, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x57, 0x5b, 0xc1, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x85, 0x6b, 0x03, 0x43,
+  0xae, 0x47, 0x55, 0x41, 0xb4, 0xab, 0x28, 0x40, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x1e, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f, 0xd1, 0x22, 0x9f, 0x40, 0x33, 0x33, 0x17, 0x42,
+  0xd9, 0x3d, 0x21, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x98, 0x43, 0x33, 0x33, 0x93, 0x41,
+  0x9a, 0x39, 0xaf, 0x43, 0x71, 0x3d, 0x4a, 0x41, 0xe5, 0x27, 0x05, 0x3f, 0x00, 0x00, 0xa0, 0x41,
+  0x7b, 0x14, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcb, 0xa1, 0x25, 0x3f, 0x35, 0x5e, 0x06, 0x41,
+  0x00, 0x00, 0xb7, 0x42, 0xc9, 0x76, 0x12, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x84, 0x43,
+  0x00, 0x00, 0x50, 0x41, 0x14, 0x6e, 0xc1, 0x43, 0xb8, 0x1e, 0xbd, 0x40, 0x45, 0x2f, 0x23, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xdd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x42, 0x60, 0xe5, 0x3e,
+  0x83, 0xc0, 0xc6, 0x40, 0x00, 0x00, 0xd0, 0x40, 0x9d, 0x11, 0xb7, 0x40, 0x00, 0x00, 0x40, 0x40,
+  0x00, 0x00, 0x69, 0x43, 0x33, 0x33, 0x8f, 0x41, 0xe1, 0x3a, 0xc5, 0x43, 0x7b, 0x14, 0xee, 0x40,
+  0x4b, 0xb0, 0x58, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xf5, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x1e, 0x05, 0x3f, 0x4e, 0x62, 0xc4, 0x40, 0xcd, 0xcc, 0xae, 0x42, 0xa5, 0xbd, 0x2d, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc0, 0x43, 0x33, 0x33, 0xa7, 0x41, 0x29, 0x3c, 0xc5, 0x43,
+  0x3d, 0x0a, 0x57, 0x41, 0x0e, 0x67, 0xb6, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xa3, 0x9c, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xdb, 0xf9, 0x5e, 0x3f, 0xec, 0x51, 0xd0, 0x40, 0x00, 0x00, 0xc8, 0x42,
+  0x03, 0x09, 0xe2, 0x3f, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43, 0x33, 0x33, 0x6b, 0x41,
+  0xae, 0x27, 0xb6, 0x43, 0xe1, 0x7a, 0xec, 0x40, 0x57, 0x43, 0x62, 0x3c, 0x00, 0x00, 0xa0, 0x42,
+  0x1f, 0x85, 0xeb, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x62, 0x10, 0xd8, 0x3e, 0x00, 0x00, 0xfc, 0x40,
+  0x00, 0x00, 0x00, 0x42, 0xb1, 0xbf, 0xb4, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x7f, 0x43,
+  0x66, 0x66, 0x66, 0x41, 0x71, 0x1d, 0xc5, 0x43, 0x7b, 0x14, 0x3e, 0x40, 0xdf, 0xc3, 0x65, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x3d, 0x0a, 0x1b, 0x41, 0x00, 0x00, 0x00, 0x00, 0x8f, 0xc2, 0x15, 0x3f,
+  0x2f, 0xdd, 0xc0, 0x40, 0x66, 0x66, 0x9f, 0x42, 0x82, 0xe2, 0x1f, 0x40, 0x00, 0x00, 0xc0, 0x40,
+  0x00, 0x80, 0xc3, 0x43, 0x9a, 0x99, 0x99, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xae, 0x47, 0x65, 0x41,
+  0x89, 0xd2, 0x5e, 0x3c, 0x00, 0x00, 0x96, 0x42, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x85, 0xeb, 0xd1, 0x3e, 0x7f, 0x6a, 0xbc, 0x40, 0x66, 0x66, 0x3e, 0x42, 0xfb, 0x3a, 0xea, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x80, 0xea, 0x43, 0xcd, 0xcc, 0xa8, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xcd, 0xcc, 0x6c, 0x41, 0x46, 0xce, 0xc2, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xae, 0x47, 0x4d, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e, 0xe9, 0x26, 0xc9, 0x40, 0x00, 0x00, 0x34, 0x42,
+  0x4d, 0x15, 0x90, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xc7, 0x43, 0x9a, 0x99, 0x95, 0x41,
+  0x71, 0x9d, 0xbf, 0x43, 0x3d, 0x0a, 0x0f, 0x41, 0x67, 0x44, 0xa9, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x52, 0xb8, 0x5e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0xdf, 0x3e, 0x62, 0x10, 0xc4, 0x40,
+  0x33, 0x33, 0x93, 0x41, 0x1e, 0x16, 0xb0, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x90, 0x43,
+  0x00, 0x00, 0x80, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xae, 0x47, 0x09, 0x41, 0x3e, 0x96, 0x1b, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x3d, 0x3f,
+  0xf4, 0xfd, 0xcc, 0x40, 0x66, 0x66, 0xc2, 0x42, 0x99, 0x2a, 0x04, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xe1, 0xfa, 0xc0, 0x43, 0xf6, 0x28, 0x9c, 0x41,
+  0xac, 0x8b, 0x5b, 0x3d, 0x00, 0x00, 0xa8, 0x41, 0xe1, 0x7a, 0xb4, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x9c, 0xc4, 0xe0, 0x3e, 0x1d, 0x5a, 0xd0, 0x40, 0xcd, 0xcc, 0xa8, 0x41, 0x06, 0x12, 0xda, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x73, 0x43, 0x66, 0x66, 0x86, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xc3, 0xf5, 0xa8, 0x40, 0xcf, 0xbd, 0x9a, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x7d, 0x3f, 0x15, 0x3f, 0xc3, 0xf5, 0xbc, 0x40, 0xcd, 0xcc, 0x54, 0x42,
+  0x48, 0xbf, 0x49, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x29, 0x1c, 0xc2, 0x43, 0x33, 0x33, 0x37, 0x41, 0x9b, 0x3d, 0x62, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x80, 0x3f, 0xdb, 0xf9, 0x5e, 0x3f, 0x2f, 0xdd, 0xc4, 0x40,
+  0x33, 0x33, 0xa5, 0x42, 0x8b, 0x6c, 0xdf, 0x3f, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43,
+  0x33, 0x33, 0x6b, 0x41, 0x1f, 0x05, 0xb0, 0x42, 0xec, 0x51, 0x70, 0x41, 0xc5, 0x03, 0x4a, 0x3d,
+  0x00, 0x00, 0x04, 0x42, 0x1f, 0x85, 0x0b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xa9, 0xf1, 0x3e,
+  0x02, 0x2b, 0xdb, 0x40, 0x9a, 0x99, 0x8c, 0x42, 0x5b, 0xb1, 0x4b, 0x40, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0x5e, 0x43, 0x33, 0x33, 0x93, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xc3, 0xf5, 0xf0, 0x40,
+  0xd9, 0x25, 0xaa, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x1d, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x23, 0xdb, 0xf9, 0x3e, 0xf8, 0x53, 0xb3, 0x40, 0x9a, 0x99, 0xb3, 0x42, 0xc1, 0x39, 0x3f, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x41, 0x43, 0x66, 0x66, 0x8e, 0x41, 0x00, 0x80, 0xc3, 0x43,
+  0x14, 0xae, 0x5f, 0x41, 0xe7, 0x1d, 0x26, 0x42, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f, 0xf4, 0xfd, 0xb0, 0x40, 0xcd, 0xcc, 0xaa, 0x42,
+  0x48, 0xbf, 0xcd, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0xe1, 0xba, 0xa4, 0x43, 0x3d, 0x0a, 0xdb, 0x41, 0x70, 0xdf, 0x9c, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xc6, 0x2b, 0x3f, 0x19, 0x04, 0xea, 0x40,
+  0xcd, 0xcc, 0xc3, 0x42, 0x85, 0x7c, 0xa8, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x3d, 0x0a, 0x57, 0x41, 0x20, 0xb5, 0x89, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x29, 0x5c, 0x4f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x85, 0xeb, 0x3e,
+  0xf0, 0xa7, 0xca, 0x40, 0x9a, 0x99, 0x89, 0x41, 0x01, 0xde, 0xa6, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0xd7, 0x43, 0x33, 0x33, 0x87, 0x41, 0xe1, 0x9a, 0xbb, 0x43, 0x48, 0xe1, 0xea, 0x40,
+  0xb7, 0x7a, 0x0e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x81, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x5c, 0x8f, 0x02, 0x3f, 0xd3, 0x4d, 0xb2, 0x40, 0x00, 0x00, 0xb1, 0x42, 0x81, 0x26, 0x26, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x94, 0x43, 0xcd, 0xcc, 0x84, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x3d, 0x0a, 0x6b, 0x41, 0x35, 0x46, 0x13, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xc1, 0xca, 0x01, 0x3f, 0x5a, 0x64, 0x05, 0x41, 0x9a, 0x99, 0x92, 0x42,
+  0x58, 0xa8, 0x75, 0x40, 0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41,
+  0x7b, 0xf4, 0xc0, 0x43, 0x7b, 0x14, 0x1e, 0x40, 0x2e, 0xe7, 0x86, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f, 0x85, 0xeb, 0xbd, 0x40,
+  0x66, 0x66, 0xea, 0x41, 0x88, 0xf4, 0x8f, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x99, 0x43,
+  0x00, 0x00, 0xa8, 0x41, 0xcd, 0x6c, 0xc1, 0x43, 0x5c, 0x8f, 0xd2, 0x40, 0x51, 0xa0, 0x8f, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x5e, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x0c, 0x3f,
+  0x44, 0x8b, 0xd4, 0x40, 0x33, 0x33, 0xaa, 0x42, 0x4d, 0xf3, 0x5a, 0x40, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0x8a, 0x43, 0x33, 0x33, 0x83, 0x41, 0xd7, 0x63, 0xc4, 0x43, 0x3d, 0x0a, 0x1b, 0x41,
+  0x4f, 0xaf, 0x84, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x77, 0xbe, 0x1f, 0x3f, 0x0e, 0x2d, 0xb6, 0x40, 0x00, 0x00, 0xc0, 0x42, 0x04, 0xe7, 0xe4, 0x3f,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x14, 0x0e, 0xc4, 0x43,
+  0x1f, 0x85, 0x89, 0x41, 0xff, 0xca, 0x0a, 0x3e, 0x00, 0x00, 0x48, 0x41, 0x71, 0x3d, 0xc2, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0xd1, 0x3e, 0x0c, 0x02, 0xb3, 0x40, 0x33, 0x33, 0x13, 0x42,
+  0x9e, 0xef, 0xcf, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xac, 0x43, 0x33, 0x33, 0x97, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xa4, 0x70, 0x51, 0x41, 0x92, 0x91, 0x33, 0x3c, 0x00, 0x00, 0x5c, 0x42,
+  0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x02, 0x2b, 0xc7, 0x3e, 0xfa, 0x7e, 0xce, 0x40,
+  0x33, 0x33, 0xff, 0x41, 0x67, 0xd5, 0xe9, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x96, 0x43,
+  0xcd, 0xcc, 0x74, 0x41, 0x29, 0x5c, 0xc5, 0x43, 0x14, 0xae, 0x03, 0x41, 0x83, 0x34, 0x63, 0x3e,
+  0x00, 0x00, 0xa0, 0x41, 0x52, 0xb8, 0xde, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x68, 0x91, 0xed, 0x3e,
+  0xac, 0x1c, 0xf6, 0x40, 0x33, 0x33, 0x4f, 0x42, 0x5e, 0xba, 0x8b, 0x40, 0x00, 0x00, 0x40, 0x40,
+  0x00, 0x00, 0x5f, 0x43, 0xcd, 0xcc, 0x94, 0x41, 0x8f, 0x62, 0xc3, 0x43, 0x5c, 0x8f, 0xd2, 0x40,
+  0x41, 0x65, 0x7c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x7a, 0x8c, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xd3, 0x4d, 0xe2, 0x3e, 0x6a, 0xbc, 0xbc, 0x40, 0x33, 0x33, 0x51, 0x42, 0xb5, 0x37, 0x00, 0x41,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0xb0, 0x43, 0x66, 0x66, 0x96, 0x41, 0x14, 0x4e, 0xb6, 0x43,
+  0x52, 0xb8, 0x4a, 0x41, 0x27, 0xf7, 0xbb, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x81, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x5c, 0x8f, 0x02, 0x3f, 0xdf, 0x4f, 0xcd, 0x40, 0x33, 0x33, 0xa8, 0x42,
+  0xfb, 0x5c, 0x29, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x94, 0x43, 0xcd, 0xcc, 0x84, 0x41,
+  0x00, 0xc0, 0xc5, 0x43, 0xd7, 0xa3, 0x10, 0x41, 0x02, 0x0e, 0x21, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x3d, 0x5a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x35, 0x5e, 0xfa, 0x3e, 0xc3, 0xf5, 0xcc, 0x40,
+  0xcd, 0xcc, 0x93, 0x42, 0xf7, 0xe4, 0x45, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x87, 0x43,
+  0x66, 0x66, 0x8e, 0x41, 0x66, 0xc6, 0xc4, 0x43, 0x33, 0x33, 0x03, 0x41, 0xe2, 0x58, 0x2d, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xf2, 0xd2, 0x2d, 0x3f,
+  0x25, 0x06, 0xd9, 0x40, 0x9a, 0x99, 0xb5, 0x42, 0x60, 0xe5, 0xe8, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x5c, 0x8f, 0xac, 0x41, 0xec, 0x51, 0xce, 0x41,
+  0xd2, 0x1d, 0x87, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x80, 0x3f,
+  0xb8, 0x1e, 0x45, 0x3f, 0x2d, 0xb2, 0xb9, 0x40, 0x00, 0x00, 0xb2, 0x42, 0x36, 0xcd, 0xf3, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x1f, 0x85, 0xb0, 0x43,
+  0x71, 0x3d, 0x6a, 0x41, 0x0e, 0x67, 0x95, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f, 0x64, 0x3b, 0xbf, 0x40, 0xcd, 0xcc, 0xaf, 0x42,
+  0x8d, 0x28, 0x25, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x14, 0xae, 0x27, 0x41, 0x7b, 0x14, 0x98, 0x41, 0x91, 0xd5, 0xcd, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x66, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f, 0x58, 0x39, 0xcc, 0x40,
+  0x66, 0x66, 0x86, 0x42, 0x7b, 0x14, 0x62, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x98, 0x43,
+  0x33, 0x33, 0x93, 0x41, 0xe1, 0x9a, 0xc5, 0x43, 0x8f, 0xc2, 0x25, 0x41, 0x91, 0x7e, 0x86, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3f,
+  0x2f, 0xdd, 0xa8, 0x40, 0x33, 0x33, 0xc4, 0x42, 0x72, 0x8a, 0xb6, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xe1, 0x7a, 0xf6, 0x41,
+  0xda, 0x55, 0x28, 0x3e, 0x00, 0x00, 0xb0, 0x41, 0x1f, 0x85, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0xac, 0xdc, 0x3e, 0x23, 0xdb, 0xcd, 0x40, 0x66, 0x66, 0x44, 0x42, 0xb0, 0x72, 0xfa, 0x40,
+  0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0xa5, 0x43, 0xcd, 0xcc, 0x98, 0x41, 0xe1, 0x5a, 0xbb, 0x43,
+  0xec, 0x51, 0x18, 0x41, 0x69, 0xa9, 0xb6, 0x40, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x27, 0x31, 0x08, 0x3f, 0x00, 0x00, 0xd8, 0x40, 0xcd, 0xcc, 0x95, 0x42,
+  0x93, 0x3a, 0x55, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0xf6, 0x88, 0xc4, 0x43, 0x14, 0xae, 0xf7, 0x40, 0xf6, 0x5d, 0x91, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xf6, 0x28, 0xec, 0x40, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x6a, 0xfc, 0x3e, 0xf0, 0xa7, 0xb6, 0x40,
+  0x9a, 0x99, 0x94, 0x42, 0x40, 0x13, 0x97, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x8f, 0x43,
+  0xcd, 0xcc, 0x9c, 0x41, 0xa4, 0x90, 0xc3, 0x43, 0x0a, 0xd7, 0x3b, 0x41, 0xe7, 0x52, 0xb5, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x3d, 0x3f,
+  0x0c, 0x02, 0xc7, 0x40, 0x00, 0x00, 0xc8, 0x42, 0xa5, 0x4e, 0x00, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x52, 0xd8, 0xc5, 0x43, 0x52, 0xb8, 0x84, 0x41,
+  0x87, 0xf9, 0x42, 0x3f, 0x00, 0x00, 0xa0, 0x41, 0x7b, 0x14, 0x7e, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcb, 0xa1, 0x25, 0x3f, 0x85, 0xeb, 0xb1, 0x40, 0x33, 0x33, 0x7b, 0x42, 0xa2, 0x45, 0xfe, 0x3f,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x84, 0x43, 0x00, 0x00, 0x50, 0x41, 0x33, 0x33, 0xc4, 0x43,
+  0x33, 0x33, 0x27, 0x41, 0xe7, 0xfb, 0xe9, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x5e, 0x41,
+  0x00, 0x00, 0x80, 0x3f, 0xcd, 0xcc, 0x0c, 0x3f, 0x9e, 0xef, 0xcb, 0x40, 0xcd, 0xcc, 0xb8, 0x42,
+  0x4f, 0x40, 0x57, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x8a, 0x43, 0x33, 0x33, 0x83, 0x41,
+  0xb8, 0xde, 0xc4, 0x43, 0x00, 0x00, 0x28, 0x41, 0xce, 0x70, 0xf3, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x66, 0x66, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f, 0xb2, 0x9d, 0xc3, 0x40,
+  0x33, 0x33, 0x6b, 0x42, 0x91, 0x0f, 0x80, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x98, 0x43,
+  0x33, 0x33, 0x93, 0x41, 0x71, 0x1d, 0xc6, 0x43, 0x14, 0xae, 0x4b, 0x41, 0xf7, 0xe4, 0x61, 0x3d,
+  0x00, 0x00, 0x04, 0x42, 0x1f, 0x85, 0x0b, 0x40, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xa9, 0xf1, 0x3e,
+  0x50, 0x8d, 0xe7, 0x40, 0x66, 0x66, 0x24, 0x42, 0x39, 0xb4, 0x80, 0x40, 0x00, 0x00, 0xe0, 0x40,
+  0x00, 0x00, 0x5e, 0x43, 0x33, 0x33, 0x93, 0x41, 0x0a, 0xd7, 0xc4, 0x43, 0x8f, 0xc2, 0xdd, 0x40,
+  0x22, 0x71, 0x0f, 0x3d, 0x00, 0x00, 0xa0, 0x42, 0x66, 0x66, 0x9e, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x98, 0x6e, 0xd2, 0x3e, 0x50, 0x8d, 0xdb, 0x40, 0x33, 0x33, 0xdf, 0x41, 0x02, 0xbc, 0xa3, 0x40,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x75, 0x43, 0x9a, 0x99, 0x99, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xb8, 0x1e, 0x55, 0x40, 0x34, 0xba, 0x0f, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x80, 0x3f, 0xb8, 0x1e, 0x45, 0x3f, 0xb4, 0xc8, 0xc6, 0x40, 0xcd, 0xcc, 0xc2, 0x42,
+  0x20, 0xd2, 0x07, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x71, 0xdd, 0xbc, 0x43, 0xcd, 0xcc, 0x8c, 0x41, 0x63, 0x0b, 0x61, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xb8, 0x1e, 0xdd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x42, 0x60, 0xe5, 0x3e, 0x96, 0x43, 0xb3, 0x40,
+  0x00, 0x00, 0x78, 0x42, 0x70, 0xce, 0xc2, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x69, 0x43,
+  0x33, 0x33, 0x8f, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x9a, 0x99, 0x81, 0x41, 0x70, 0xb6, 0xa9, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xca, 0x01, 0x3f,
+  0xb6, 0xf3, 0x03, 0x41, 0xcd, 0xcc, 0x8c, 0x42, 0xbb, 0xb8, 0x69, 0x40, 0x00, 0x00, 0x00, 0x41,
+  0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0x9a, 0x79, 0xbd, 0x43, 0xcd, 0xcc, 0x7c, 0x40,
+  0x37, 0xfd, 0x19, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0xcd, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x6a, 0xbc, 0x14, 0x3f, 0x5a, 0x64, 0xbb, 0x40, 0x00, 0x00, 0xc2, 0x42, 0x19, 0xe2, 0xf8, 0x3f,
+  0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3c, 0x43, 0xcd, 0xcc, 0x98, 0x41, 0xae, 0x27, 0xb9, 0x43,
+  0xae, 0x47, 0xcb, 0x41, 0x87, 0x6d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x3f, 0xe1, 0x7a, 0xac, 0x40, 0xcd, 0xcc, 0xc5, 0x42,
+  0x61, 0x32, 0xdd, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0xcd, 0xcc, 0xa6, 0x41, 0x97, 0xe2, 0x9b, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x2f, 0x1d, 0x3f, 0xee, 0x7c, 0xcf, 0x40,
+  0x33, 0x33, 0xbb, 0x42, 0x09, 0x8a, 0x13, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0xe1, 0x1a, 0xc6, 0x43, 0xa4, 0x70, 0x95, 0x41, 0x30, 0x81, 0xf5, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x73, 0x68, 0x31, 0x3f,
+  0x6d, 0xe7, 0xb7, 0x40, 0xcd, 0xcc, 0xc5, 0x42, 0x40, 0x13, 0xd1, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xcd, 0x8c, 0xc4, 0x43, 0x29, 0x5c, 0x9f, 0x41,
+  0x93, 0x52, 0xd0, 0x3c, 0x00, 0x00, 0x5c, 0x42, 0x85, 0xeb, 0x71, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xd9, 0xce, 0xf7, 0x3e, 0xa2, 0x45, 0xd6, 0x40, 0x9a, 0x99, 0x61, 0x42, 0x5d, 0x6d, 0xb7, 0x40,
+  0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0xb9, 0x43, 0xcd, 0xcc, 0x8c, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x8f, 0xc2, 0xe5, 0x40, 0x68, 0xb3, 0xea, 0x3d, 0x00, 0x00, 0xa0, 0x41, 0x52, 0xb8, 0xde, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x68, 0x91, 0xed, 0x3e, 0x4c, 0x37, 0xd1, 0x40, 0xcd, 0xcc, 0x6a, 0x42,
+  0x52, 0xb8, 0x7a, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x5f, 0x43, 0xcd, 0xcc, 0x94, 0x41,
+  0xe1, 0x7a, 0xc5, 0x43, 0x29, 0x5c, 0xf7, 0x40, 0xfd, 0x30, 0x42, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0xe1, 0x3e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x21, 0xb0, 0x12, 0x3f, 0xc3, 0xf5, 0xc0, 0x40,
+  0x9a, 0x99, 0xa1, 0x42, 0xec, 0x51, 0x20, 0x40, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x80, 0x88, 0x43,
+  0x00, 0x00, 0xa8, 0x41, 0x33, 0x73, 0xc6, 0x43, 0xf6, 0x28, 0xfc, 0x40, 0x4f, 0x58, 0x4a, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x1e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x96, 0x43, 0x0b, 0x3f,
+  0x6d, 0xe7, 0xc3, 0x40, 0x33, 0x33, 0x53, 0x42, 0xad, 0xfa, 0x28, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x98, 0x43, 0x33, 0x33, 0x93, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x29, 0x5c, 0xbf, 0x40,
+  0x00, 0xef, 0x8e, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xa8, 0xc6, 0x2b, 0x3f, 0xd1, 0x22, 0xc7, 0x40, 0x00, 0x00, 0xc8, 0x42, 0xba, 0x6b, 0xb1, 0x3f,
+  0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xb8, 0xde, 0xc4, 0x43,
+  0x71, 0x3d, 0xae, 0x41, 0x70, 0x7c, 0xed, 0x3c, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0xa0, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xe3, 0xa5, 0xdb, 0x3e, 0x4a, 0x0c, 0xde, 0x40, 0x00, 0x00, 0x0a, 0x42,
+  0x71, 0xac, 0x0c, 0x41, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x80, 0xa7, 0x43, 0x9a, 0x99, 0x9d, 0x41,
+  0xcd, 0xec, 0xc2, 0x43, 0xe1, 0x7a, 0xbc, 0x40, 0x13, 0xb8, 0xb5, 0x3d, 0x00, 0x00, 0xa8, 0x41,
+  0xe1, 0x7a, 0xb4, 0x40, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xc4, 0xe0, 0x3e, 0xe5, 0xd0, 0xbe, 0x40,
+  0xcd, 0xcc, 0x36, 0x42, 0x06, 0x12, 0xda, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x73, 0x43,
+  0x66, 0x66, 0x86, 0x41, 0xae, 0xc7, 0xc5, 0x43, 0x33, 0x33, 0x57, 0x41, 0x00, 0x57, 0xb2, 0x3c,
+  0x00, 0x00, 0xa5, 0x42, 0x85, 0xeb, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x7a, 0xd4, 0x3e,
+  0x1f, 0x85, 0xf3, 0x40, 0x33, 0x33, 0x7b, 0x41, 0xd7, 0xa3, 0xc8, 0x40, 0x00, 0x00, 0x00, 0x40,
+  0x00, 0x00, 0xae, 0x43, 0x33, 0x33, 0x6b, 0x41, 0xa4, 0xb0, 0xc5, 0x43, 0x3d, 0x0a, 0x47, 0x40,
+  0x24, 0x28, 0x1e, 0x3e, 0x00, 0x00, 0xc8, 0x41, 0xf6, 0x28, 0xa4, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x9e, 0xef, 0xe7, 0x3e, 0xd7, 0xa3, 0xc4, 0x40, 0x9a, 0x99, 0xe9, 0x41, 0xd7, 0x12, 0xfa, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x8e, 0x43, 0x9a, 0x99, 0x9d, 0x41, 0x0a, 0x57, 0xc3, 0x43,
+  0x1f, 0x85, 0xdb, 0x40, 0xbb, 0x0f, 0xc0, 0x3d, 0x00, 0x00, 0x48, 0x41, 0x0a, 0xd7, 0xfb, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xdd, 0x24, 0x06, 0x3f, 0xb0, 0x72, 0xbc, 0x40, 0x00, 0x00, 0x1c, 0x42,
+  0xc6, 0x6d, 0xae, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x9b, 0x43, 0x33, 0x33, 0x73, 0x41,
+  0x00, 0x40, 0xc3, 0x43, 0x29, 0x5c, 0x7b, 0x41, 0xab, 0xcf, 0x60, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xd4, 0x18, 0x3f, 0x25, 0x06, 0xd5, 0x40,
+  0x00, 0x00, 0xc8, 0x42, 0x1f, 0x85, 0xc3, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x33, 0x33, 0x0c, 0x42, 0x8f, 0xc2, 0xa9, 0x41, 0xb6, 0xb9, 0x11, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x31, 0x08, 0x0c, 0x3f,
+  0xc5, 0x20, 0xc8, 0x40, 0x66, 0x66, 0xa8, 0x42, 0x7f, 0x6a, 0x10, 0x40, 0x00, 0x00, 0xc0, 0x40,
+  0x00, 0x00, 0xd8, 0x43, 0x66, 0x66, 0x8e, 0x41, 0xb8, 0x5e, 0xc2, 0x43, 0x33, 0x33, 0x27, 0x41,
+  0x25, 0x06, 0x01, 0x3d, 0x00, 0x00, 0xbe, 0x42, 0xf6, 0x28, 0xbc, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x56, 0xce, 0x3e, 0x33, 0x33, 0xdf, 0x40, 0xcd, 0xcc, 0x74, 0x41, 0xa7, 0xe8, 0xf4, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0xc9, 0x43, 0x00, 0x00, 0x88, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x85, 0xeb, 0x91, 0x40, 0x8e, 0x1e, 0x3f, 0x3d, 0x00, 0x00, 0xa0, 0x42, 0x5c, 0x8f, 0xc2, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x17, 0xd9, 0xce, 0x3e, 0x8b, 0x6c, 0xe3, 0x40, 0x66, 0x66, 0x12, 0x42,
+  0x54, 0xe3, 0xe9, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x80, 0xa4, 0x43, 0x9a, 0x99, 0x49, 0x41,
+  0xae, 0x27, 0xb1, 0x43, 0x8f, 0xc2, 0x09, 0x41, 0x09, 0xf9, 0xb4, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0xd7, 0xa3, 0x9c, 0x41, 0x00, 0x00, 0x80, 0x3f, 0xdb, 0xf9, 0x5e, 0x3f, 0xc5, 0x20, 0xc4, 0x40,
+  0x00, 0x00, 0xc0, 0x42, 0x57, 0xec, 0xdf, 0x3f, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0xc9, 0x43,
+  0x33, 0x33, 0x6b, 0x41, 0x8f, 0x82, 0xa0, 0x43, 0x85, 0xeb, 0x71, 0x41, 0xa8, 0x3a, 0xa0, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0x71, 0x3d, 0xb2, 0x40, 0x33, 0x33, 0xc4, 0x42, 0xcb, 0x10, 0x73, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0xf6, 0x48, 0xbc, 0x43, 0xf6, 0x28, 0xa8, 0x41,
+  0x47, 0x77, 0xd0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x77, 0xbe, 0x1f, 0x3f, 0xa6, 0x9b, 0xa0, 0x40, 0x00, 0x00, 0xc8, 0x42, 0x42, 0x3e, 0xb8, 0x3f,
+  0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0xd7, 0xa3, 0x09, 0x42, 0x65, 0xdf, 0x15, 0x3d, 0x00, 0x00, 0xc8, 0x41, 0x1f, 0x85, 0x9b, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xac, 0x1c, 0xda, 0x3e, 0xfc, 0xa9, 0xc9, 0x40, 0xcd, 0xcc, 0x00, 0x42,
+  0x89, 0xd2, 0xac, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x8c, 0x43, 0x00, 0x00, 0x98, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x3d, 0x0a, 0xd7, 0x40, 0x51, 0x83, 0x8d, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x06, 0x81, 0x15, 0x3f, 0x93, 0x18, 0xc0, 0x40,
+  0x00, 0x00, 0xbd, 0x42, 0x46, 0x94, 0x22, 0x40, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44,
+  0x9a, 0x99, 0xa1, 0x41, 0x1f, 0xa5, 0xa5, 0x43, 0x5c, 0x8f, 0xaa, 0x41, 0x2e, 0xff, 0x3c, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xce, 0x37, 0x3f,
+  0x35, 0x5e, 0xda, 0x40, 0x00, 0x00, 0x99, 0x42, 0xcb, 0xa1, 0xe5, 0x3f, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0xcd, 0xcc, 0x41, 0x42, 0x85, 0xeb, 0xb5, 0x41,
+  0xf7, 0x3b, 0x14, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x31, 0x08, 0x0c, 0x3f, 0x5a, 0x64, 0xb7, 0x40, 0x66, 0x66, 0x82, 0x42, 0xbc, 0x96, 0x30, 0x40,
+  0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xd8, 0x43, 0x66, 0x66, 0x8e, 0x41, 0x00, 0xc0, 0xc3, 0x43,
+  0x8f, 0xc2, 0x59, 0x41, 0x62, 0x15, 0xdf, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x29, 0x41,
+  0x00, 0x00, 0x80, 0x3f, 0x35, 0x5e, 0xfa, 0x3e, 0x0c, 0x02, 0xab, 0x40, 0x00, 0x00, 0xc8, 0x42,
+  0x00, 0x00, 0x78, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x8a, 0x43, 0xcd, 0xcc, 0x94, 0x41,
+  0x33, 0x73, 0xc6, 0x43, 0x52, 0xb8, 0xb8, 0x41, 0xba, 0x4e, 0x43, 0x3e, 0x00, 0x00, 0xb0, 0x41,
+  0x1f, 0x85, 0xbb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0xac, 0xdc, 0x3e, 0xdb, 0xf9, 0xd6, 0x40,
+  0x00, 0x00, 0x8c, 0x41, 0xb0, 0x72, 0xfa, 0x40, 0x00, 0x00, 0xe0, 0x40, 0x00, 0x00, 0xa5, 0x43,
+  0xcd, 0xcc, 0x98, 0x41, 0xb8, 0xde, 0xc4, 0x43, 0x85, 0xeb, 0xd1, 0x40, 0x12, 0x31, 0xa5, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0xb8, 0x1e, 0xaf, 0x41, 0x00, 0x00, 0x00, 0x00, 0x77, 0xbe, 0x1f, 0x3f,
+  0xdd, 0x24, 0xbe, 0x40, 0x00, 0x00, 0xbb, 0x42, 0x61, 0xc3, 0xfb, 0x3f, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0xda, 0x43, 0x9a, 0x99, 0xa9, 0x41, 0x00, 0x20, 0xbd, 0x43, 0x33, 0x33, 0x87, 0x41,
+  0xc1, 0x73, 0x2f, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x28, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x31, 0x08, 0x0c, 0x3f, 0x2d, 0xb2, 0xbd, 0x40, 0x66, 0x66, 0xb0, 0x42, 0x6e, 0xa3, 0x1d, 0x40,
+  0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xd8, 0x43, 0x66, 0x66, 0x8e, 0x41, 0x7b, 0x74, 0xac, 0x43,
+  0xf6, 0x28, 0x7c, 0x41, 0xa8, 0x46, 0x04, 0x41, 0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41,
+  0x00, 0x00, 0x80, 0x3f, 0x0c, 0x02, 0x2b, 0x3f, 0x00, 0x00, 0xbc, 0x40, 0x33, 0x33, 0xb3, 0x42,
+  0xbc, 0x96, 0x90, 0x3f, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41,
+  0xa4, 0xf0, 0xad, 0x43, 0x7b, 0x14, 0x0e, 0x41, 0x4c, 0x4f, 0x58, 0x3e, 0x00, 0x00, 0x48, 0x41,
+  0x0a, 0xd7, 0xfb, 0x40, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x24, 0x06, 0x3f, 0x27, 0x31, 0xb4, 0x40,
+  0x00, 0x00, 0xc8, 0x42, 0x90, 0xa0, 0xc2, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x80, 0x9b, 0x43,
+  0x33, 0x33, 0x73, 0x41, 0xa4, 0x50, 0xc1, 0x43, 0xa4, 0x70, 0xef, 0x41, 0xc9, 0x93, 0xa4, 0x3c,
+  0x00, 0x00, 0xbe, 0x42, 0x1f, 0x85, 0x2b, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0b, 0xd5, 0x3e,
+  0x44, 0x8b, 0x00, 0x41, 0x33, 0x33, 0xff, 0x41, 0xa8, 0xc6, 0xa3, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x00, 0x60, 0x43, 0x33, 0x33, 0x6b, 0x41, 0x66, 0x46, 0xc3, 0x43, 0xec, 0x51, 0x38, 0x40,
+  0x76, 0x37, 0x4f, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x14, 0xae, 0x8f, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0xe3, 0xe5, 0x3e, 0xb0, 0x72, 0xcc, 0x40, 0x00, 0x00, 0x40, 0x42, 0xd8, 0xf0, 0x98, 0x40,
+  0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x77, 0x43, 0x00, 0x00, 0x94, 0x41, 0x33, 0x73, 0xc6, 0x43,
+  0x85, 0xeb, 0x19, 0x41, 0xdb, 0x33, 0x6b, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x70, 0x29, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x35, 0x5e, 0xfa, 0x3e, 0x98, 0x6e, 0xca, 0x40, 0x00, 0x00, 0x52, 0x42,
+  0x57, 0x5b, 0x8b, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x80, 0x8a, 0x43, 0xcd, 0xcc, 0x94, 0x41,
+  0x5c, 0x6f, 0xc5, 0x43, 0x1f, 0x85, 0x2f, 0x41, 0x80, 0x9a, 0x1a, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xf6, 0x28, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x31, 0x08, 0x0c, 0x3f, 0x08, 0xac, 0xc0, 0x40,
+  0x33, 0x33, 0xa5, 0x42, 0x67, 0xd5, 0x2f, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xd8, 0x43,
+  0x66, 0x66, 0x8e, 0x41, 0x48, 0x41, 0xc5, 0x43, 0xcd, 0xcc, 0x24, 0x41, 0x48, 0x50, 0x80, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x3d, 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0x5e, 0xba, 0x09, 0x3f,
+  0x68, 0x91, 0xd5, 0x40, 0x9a, 0x99, 0xae, 0x42, 0xe3, 0xa5, 0x87, 0x40, 0x00, 0x00, 0x80, 0x40,
+  0x00, 0x80, 0x99, 0x43, 0x00, 0x00, 0xa8, 0x41, 0x71, 0x1d, 0xbe, 0x43, 0x14, 0xae, 0x3f, 0x41,
+  0xfd, 0x30, 0xe2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0xc6, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x25, 0x06, 0x01, 0x3f, 0xfc, 0xa9, 0xd1, 0x40, 0x33, 0x33, 0xab, 0x41, 0xa3, 0x01, 0x58, 0x40,
+  0x00, 0x00, 0x00, 0x41, 0x00, 0x80, 0x99, 0x43, 0x33, 0x33, 0x8b, 0x41, 0x85, 0x2b, 0xbe, 0x43,
+  0xd7, 0xa3, 0x70, 0x40, 0x8d, 0x7a, 0x88, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x81, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x5c, 0x8f, 0x02, 0x3f, 0xd5, 0x78, 0xd1, 0x40, 0x66, 0x66, 0x04, 0x42,
+  0x9a, 0x77, 0x48, 0x40, 0x00, 0x00, 0xa0, 0x40, 0x00, 0x00, 0x94, 0x43, 0xcd, 0xcc, 0x84, 0x41,
+  0xe1, 0x7a, 0xc3, 0x43, 0x5c, 0x8f, 0xaa, 0x40, 0x1f, 0x80, 0x54, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x14, 0xae, 0x8f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x54, 0xe3, 0xe5, 0x3e, 0xe1, 0x7a, 0xc0, 0x40,
+  0x66, 0x66, 0x34, 0x42, 0x9f, 0xab, 0x8d, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x77, 0x43,
+  0x00, 0x00, 0x94, 0x41, 0xb8, 0xfe, 0xc5, 0x43, 0x8f, 0xc2, 0x4d, 0x41, 0x1b, 0xf5, 0xd4, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x87, 0x36, 0x3f,
+  0xdd, 0x24, 0xca, 0x40, 0x00, 0x00, 0xa6, 0x42, 0x69, 0x00, 0x2f, 0x40, 0x00, 0x00, 0xc0, 0x41,
+  0x00, 0x80, 0x26, 0x44, 0x9a, 0x99, 0xa1, 0x41, 0x33, 0x73, 0xc6, 0x43, 0x0a, 0xd7, 0x5f, 0x41};
+
+} // namespace data
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TRAIN_INPUT_H
diff --git a/onert-micro/onert-micro/include/train/tests/boston_housing_task/data/train_target.h b/onert-micro/onert-micro/include/train/tests/boston_housing_task/data/train_target.h
new file mode 100644 (file)
index 0000000..096fa45
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TRAIN_TARGET_H
+#define ONERT_MICRO_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TRAIN_TARGET_H
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+namespace data
+{
+
+unsigned char train_target[] = {
+  0x33, 0x33, 0x4b, 0x41, 0x9a, 0x99, 0xe5, 0x41, 0xcd, 0xcc, 0x88, 0x41, 0x00, 0x00, 0x2e, 0x42,
+  0x33, 0x33, 0xc3, 0x41, 0x33, 0x33, 0xa3, 0x41, 0x66, 0x66, 0xa2, 0x41, 0xcd, 0xcc, 0xb4, 0x41,
+  0x00, 0x00, 0xc8, 0x41, 0xcd, 0xcc, 0x6c, 0x41, 0x66, 0x66, 0x56, 0x41, 0x00, 0x00, 0x48, 0x42,
+  0x9a, 0x99, 0xa1, 0x41, 0x66, 0x66, 0xa2, 0x41, 0xcd, 0xcc, 0xa8, 0x41, 0x9a, 0x99, 0xad, 0x41,
+  0xcd, 0xcc, 0x64, 0x41, 0x9a, 0x99, 0x91, 0x41, 0xcd, 0xcc, 0x5c, 0x41, 0xcd, 0xcc, 0x84, 0x41,
+  0x33, 0x33, 0x9b, 0x41, 0xcd, 0xcc, 0xb4, 0x41, 0x33, 0x33, 0x25, 0x42, 0x9a, 0x99, 0x71, 0x41,
+  0x00, 0x00, 0xb0, 0x41, 0x9a, 0x99, 0xad, 0x41, 0x66, 0x66, 0x0a, 0x42, 0x33, 0x33, 0x9f, 0x41,
+  0x00, 0x00, 0xc0, 0x41, 0xcd, 0xcc, 0x5c, 0x41, 0x9a, 0x99, 0xc9, 0x40, 0xcd, 0xcc, 0x00, 0x42,
+  0xcd, 0xcc, 0x9c, 0x41, 0x33, 0x33, 0xb3, 0x41, 0x9a, 0x99, 0x41, 0x41, 0x66, 0x66, 0x26, 0x41,
+  0x33, 0x33, 0x83, 0x41, 0x33, 0x33, 0xb7, 0x41, 0xcd, 0xcc, 0x44, 0x41, 0x66, 0x66, 0x8e, 0x41,
+  0x00, 0x00, 0x48, 0x42, 0xcd, 0xcc, 0x2c, 0x41, 0x9a, 0x99, 0x9d, 0x41, 0x00, 0x00, 0xa0, 0x40,
+  0x00, 0x00, 0xdc, 0x41, 0xcd, 0xcc, 0x04, 0x42, 0x9a, 0x99, 0x35, 0x42, 0x9a, 0x99, 0x99, 0x41,
+  0x66, 0x66, 0xa6, 0x41, 0x66, 0x66, 0x9a, 0x41, 0x00, 0x00, 0x00, 0x42, 0x9a, 0x99, 0x95, 0x41,
+  0x33, 0x33, 0x2f, 0x42, 0x00, 0x00, 0x60, 0x41, 0x66, 0x66, 0xba, 0x41, 0x66, 0x66, 0x9a, 0x41,
+  0x66, 0x66, 0xae, 0x41, 0xcd, 0xcc, 0xb8, 0x41, 0x33, 0x33, 0x97, 0x41, 0x00, 0x00, 0x48, 0x42,
+  0x66, 0x66, 0x82, 0x41, 0x00, 0x00, 0xc8, 0x41, 0x66, 0x66, 0x06, 0x41, 0x00, 0x00, 0x68, 0x41,
+  0x9a, 0x99, 0x59, 0x41, 0x33, 0x33, 0xdf, 0x41, 0x9a, 0x99, 0xbd, 0x41, 0x9a, 0x99, 0x95, 0x41,
+  0x66, 0x66, 0x9e, 0x41, 0x9a, 0x99, 0x91, 0x41, 0x9a, 0x99, 0x51, 0x41, 0x33, 0x33, 0x3b, 0x41,
+  0xcd, 0xcc, 0x10, 0x42, 0x33, 0x33, 0x9f, 0x41, 0x9a, 0x99, 0x05, 0x42, 0x33, 0x33, 0x9f, 0x41,
+  0x33, 0x33, 0x33, 0x42, 0xcd, 0xcc, 0x9c, 0x41, 0x66, 0x66, 0xf6, 0x41, 0x00, 0x00, 0x58, 0x41,
+  0x00, 0x00, 0x48, 0x41, 0xcd, 0xcc, 0xac, 0x41, 0x00, 0x00, 0x30, 0x41, 0x33, 0x33, 0x4b, 0x41,
+  0xcd, 0xcc, 0xa0, 0x41, 0x33, 0x33, 0x7b, 0x41, 0x00, 0x00, 0x12, 0x42, 0xcd, 0xcc, 0x5c, 0x41,
+  0x00, 0x00, 0x94, 0x41, 0x00, 0x00, 0x58, 0x41, 0x66, 0x66, 0xc6, 0x41, 0x00, 0x00, 0x28, 0x41,
+  0xcd, 0xcc, 0x02, 0x42, 0xcd, 0xcc, 0xf0, 0x41, 0x9a, 0x99, 0x89, 0x41, 0xcd, 0xcc, 0x80, 0x41,
+  0x66, 0x66, 0x16, 0x42, 0x9a, 0x99, 0xfd, 0x41, 0x00, 0x00, 0xb0, 0x41, 0xcd, 0xcc, 0xa0, 0x41,
+  0x33, 0x33, 0xb7, 0x41, 0x66, 0x66, 0x2e, 0x41, 0x33, 0x33, 0x1f, 0x42, 0xcd, 0xcc, 0x54, 0x41,
+  0x00, 0x00, 0x8c, 0x41, 0xcd, 0xcc, 0xa4, 0x41, 0x33, 0x33, 0x8b, 0x41, 0x66, 0x66, 0x3e, 0x41,
+  0xcd, 0xcc, 0xd4, 0x41, 0x66, 0x66, 0xb6, 0x41, 0x33, 0x33, 0x9b, 0x41, 0x66, 0x66, 0xc6, 0x41,
+  0xcd, 0xcc, 0x5c, 0x41, 0x9a, 0x99, 0x11, 0x42, 0x66, 0x66, 0x9a, 0x41, 0x9a, 0x99, 0xad, 0x41,
+  0xcd, 0xcc, 0x5c, 0x41, 0x33, 0x33, 0xaf, 0x41, 0x33, 0x33, 0x07, 0x42, 0xcd, 0xcc, 0x64, 0x41,
+  0x9a, 0x99, 0xc5, 0x41, 0x9a, 0x99, 0x79, 0x41, 0xcd, 0xcc, 0xa0, 0x41, 0x00, 0x00, 0xf4, 0x41,
+  0x9a, 0x99, 0xb1, 0x41, 0x9a, 0x99, 0xb1, 0x41, 0x66, 0x66, 0x6e, 0x41, 0x33, 0x33, 0x97, 0x41,
+  0x66, 0x66, 0x56, 0x41, 0x66, 0x66, 0xbe, 0x41, 0x33, 0x33, 0xa3, 0x41, 0x33, 0x33, 0x93, 0x41,
+  0x00, 0x00, 0xd4, 0x41, 0x00, 0x00, 0xa4, 0x41, 0x9a, 0x99, 0x79, 0x41, 0xcd, 0xcc, 0x88, 0x41,
+  0xcd, 0xcc, 0xd8, 0x41, 0x9a, 0x99, 0xad, 0x41, 0x00, 0x00, 0x80, 0x41, 0x00, 0x00, 0x14, 0x42,
+  0x00, 0x00, 0x48, 0x42, 0x66, 0x66, 0x2e, 0x41, 0x9a, 0x99, 0xbd, 0x41, 0x66, 0x66, 0xb6, 0x41,
+  0x00, 0x00, 0x38, 0x42, 0x9a, 0x99, 0x91, 0x41, 0x9a, 0x99, 0x51, 0x41, 0x33, 0x33, 0xa3, 0x41,
+  0xcd, 0xcc, 0x14, 0x42, 0x00, 0x00, 0x9c, 0x41, 0xcd, 0xcc, 0xc8, 0x41, 0x00, 0x00, 0xe0, 0x41,
+  0xcd, 0xcc, 0xc0, 0x41, 0x00, 0x00, 0xb4, 0x41, 0x00, 0x00, 0xbc, 0x41, 0x9a, 0x99, 0xe5, 0x41,
+  0x00, 0x00, 0x9c, 0x41, 0x9a, 0x99, 0x03, 0x42, 0x66, 0x66, 0xbe, 0x41, 0xcd, 0xcc, 0x10, 0x42,
+  0x66, 0x66, 0xa2, 0x41, 0x66, 0x66, 0x8e, 0x41, 0xcd, 0xcc, 0xe8, 0x41, 0x9a, 0x99, 0xa9, 0x41,
+  0x33, 0x33, 0x93, 0x41, 0x9a, 0x99, 0x51, 0x41, 0x00, 0x00, 0xa0, 0x41, 0x00, 0x00, 0xa0, 0x41,
+  0x33, 0x33, 0x73, 0x41, 0x00, 0x00, 0xb0, 0x41, 0xcd, 0xcc, 0xc4, 0x41, 0x9a, 0x99, 0x95, 0x41,
+  0x33, 0x33, 0xbb, 0x41, 0x00, 0x00, 0x28, 0x41, 0x66, 0x66, 0xee, 0x41, 0xcd, 0xcc, 0xe8, 0x41,
+  0x9a, 0x99, 0x79, 0x41, 0xcd, 0xcc, 0xa4, 0x41, 0x33, 0x33, 0x9f, 0x41, 0x66, 0x66, 0xba, 0x41,
+  0xcd, 0xcc, 0x0c, 0x41, 0x66, 0x66, 0xb2, 0x41, 0x00, 0x00, 0x9c, 0x41, 0x33, 0x33, 0xa3, 0x41,
+  0x66, 0x66, 0xbe, 0x41, 0x00, 0x00, 0xa0, 0x41, 0x9a, 0x99, 0x8d, 0x41, 0x00, 0x00, 0xc8, 0x41,
+  0x9a, 0x99, 0xa5, 0x41, 0x9a, 0x99, 0xc5, 0x41, 0xcd, 0xcc, 0xa4, 0x41, 0x00, 0x00, 0x48, 0x42,
+  0x33, 0x33, 0x73, 0x41, 0xcd, 0xcc, 0xe4, 0x41, 0x66, 0x66, 0x8e, 0x41, 0xcd, 0xcc, 0xfc, 0x41,
+  0x00, 0x00, 0x90, 0x41, 0x33, 0x33, 0xbf, 0x41, 0x00, 0x00, 0x48, 0x42, 0x00, 0x00, 0xb8, 0x41,
+  0xcd, 0xcc, 0x3c, 0x41, 0x33, 0x33, 0xbf, 0x41, 0xcd, 0xcc, 0x54, 0x41, 0xcd, 0xcc, 0xb4, 0x41,
+  0xcd, 0xcc, 0x98, 0x41, 0x00, 0x00, 0xc0, 0x41, 0x9a, 0x99, 0xb5, 0x41, 0x66, 0x66, 0xb2, 0x41,
+  0x00, 0x00, 0x48, 0x42, 0xcd, 0xcc, 0xa8, 0x41, 0x9a, 0x99, 0xa5, 0x41, 0xcd, 0xcc, 0x4c, 0x41,
+  0x9a, 0x99, 0x17, 0x42, 0x66, 0x66, 0xa6, 0x41, 0x66, 0x66, 0x92, 0x41, 0x00, 0x00, 0x8c, 0x41,
+  0xcd, 0xcc, 0x34, 0x41, 0x33, 0x33, 0x3b, 0x41, 0x66, 0x66, 0xc6, 0x41, 0x9a, 0x99, 0xbd, 0x41,
+  0x66, 0x66, 0x56, 0x41, 0x66, 0x66, 0xae, 0x41, 0x66, 0x66, 0x5e, 0x41, 0x66, 0x66, 0xca, 0x41,
+  0xcd, 0xcc, 0x3c, 0x41, 0x9a, 0x99, 0x05, 0x42, 0x00, 0x00, 0xe8, 0x41, 0xcd, 0xcc, 0x98, 0x41,
+  0x33, 0x33, 0xc3, 0x41, 0x00, 0x00, 0xb4, 0x41, 0x66, 0x66, 0x04, 0x42, 0x00, 0x00, 0xa0, 0x40,
+  0x33, 0x33, 0x9b, 0x41, 0x00, 0x00, 0x42, 0x42, 0x00, 0x00, 0x70, 0x41, 0x66, 0x66, 0x56, 0x41,
+  0x00, 0x00, 0x48, 0x42, 0x9a, 0x99, 0x49, 0x41, 0x00, 0x00, 0xfc, 0x41, 0xcd, 0xcc, 0xa4, 0x41,
+  0x33, 0x33, 0xab, 0x41, 0x00, 0x00, 0x84, 0x41, 0xcd, 0xcc, 0x0c, 0x41, 0x33, 0x33, 0x73, 0x41,
+  0x9a, 0x99, 0x69, 0x41, 0x66, 0x66, 0x96, 0x41, 0x66, 0x66, 0x26, 0x41, 0xcd, 0xcc, 0xc4, 0x41,
+  0x33, 0x33, 0xef, 0x41, 0x00, 0x00, 0xdc, 0x41, 0x66, 0x66, 0xb6, 0x41, 0xcd, 0xcc, 0x9c, 0x41,
+  0x00, 0x00, 0xe8, 0x41, 0xcd, 0xcc, 0x90, 0x41, 0x00, 0x00, 0xa4, 0x41, 0x66, 0x66, 0x6e, 0x41,
+  0x9a, 0x99, 0xad, 0x41, 0xcd, 0xcc, 0xfc, 0x41, 0x00, 0x00, 0x30, 0x42, 0xcd, 0xcc, 0xf8, 0x41,
+  0x9a, 0x99, 0x61, 0x41, 0x9a, 0x99, 0xb9, 0x41, 0xcd, 0xcc, 0xbc, 0x41, 0x9a, 0x99, 0xa9, 0x41,
+  0x33, 0x33, 0x0b, 0x41, 0x00, 0x00, 0xb8, 0x41, 0x00, 0x00, 0xa8, 0x41, 0xcd, 0xcc, 0xa4, 0x41,
+  0xcd, 0xcc, 0x80, 0x41, 0x9a, 0x99, 0xc9, 0x41, 0xcd, 0xcc, 0x1a, 0x42, 0x00, 0x00, 0xc8, 0x41,
+  0x33, 0x33, 0x15, 0x42, 0xcd, 0xcc, 0xf0, 0x41, 0x00, 0x00, 0x00, 0x42, 0xcd, 0xcc, 0x54, 0x41,
+  0x33, 0x33, 0xab, 0x41, 0x9a, 0x99, 0xb1, 0x41, 0x9a, 0x99, 0xf5, 0x41, 0x00, 0x00, 0xf8, 0x41,
+  0x9a, 0x99, 0xb9, 0x41, 0x66, 0x66, 0x66, 0x41, 0x9a, 0x99, 0x19, 0x41, 0x00, 0x00, 0x70, 0x41,
+  0x00, 0x00, 0x48, 0x42, 0x00, 0x00, 0x48, 0x42, 0x33, 0x33, 0x8f, 0x41, 0xcd, 0xcc, 0x9c, 0x41,
+  0x9a, 0x99, 0x69, 0x41, 0x00, 0x00, 0xe0, 0x40, 0x33, 0x33, 0x53, 0x41, 0xcd, 0xcc, 0xb8, 0x41,
+  0xcd, 0xcc, 0xb4, 0x41, 0x00, 0x00, 0x8c, 0x41, 0x9a, 0x99, 0x79, 0x41, 0x33, 0x33, 0x05, 0x42,
+  0x66, 0x66, 0xc2, 0x41, 0x33, 0x33, 0xab, 0x41, 0xcd, 0xcc, 0xc0, 0x41, 0x9a, 0x99, 0x85, 0x41,
+  0xcd, 0xcc, 0x74, 0x41, 0x00, 0x00, 0x98, 0x41, 0x66, 0x66, 0x5e, 0x41, 0xcd, 0xcc, 0x04, 0x42,
+  0x9a, 0x99, 0xa9, 0x41, 0x9a, 0x99, 0x0b, 0x42, 0xcd, 0xcc, 0x0a, 0x42, 0x33, 0x33, 0xb7, 0x41,
+  0xcd, 0xcc, 0x04, 0x41, 0x66, 0x66, 0x6e, 0x41, 0x33, 0x33, 0x9b, 0x41, 0x9a, 0x99, 0xb1, 0x41,
+  0x33, 0x33, 0xdf, 0x41, 0xcd, 0xcc, 0x04, 0x41, 0x33, 0x33, 0x63, 0x41, 0x33, 0x33, 0x9b, 0x41,
+  0xcd, 0xcc, 0xb8, 0x41, 0xcd, 0xcc, 0x80, 0x41, 0x33, 0x33, 0x43, 0x42, 0x9a, 0x99, 0xc5, 0x41,
+  0x66, 0x66, 0x9a, 0x41, 0x66, 0x66, 0xba, 0x41, 0x00, 0x00, 0x48, 0x42, 0x66, 0x66, 0x86, 0x41,
+  0x33, 0x33, 0x97, 0x41, 0x33, 0x33, 0xab, 0x41, 0x33, 0x33, 0xbf, 0x41, 0xcd, 0xcc, 0x88, 0x41,
+  0x00, 0x00, 0xc8, 0x41, 0xcd, 0xcc, 0xa4, 0x41, 0x9a, 0x99, 0x79, 0x41, 0x9a, 0x99, 0xe1, 0x41,
+  0x33, 0x33, 0xd3, 0x41, 0x00, 0x00, 0x08, 0x41, 0x00, 0x00, 0x70, 0x41, 0xcd, 0xcc, 0xb4, 0x41,
+  0xcd, 0xcc, 0xb8, 0x41, 0xcd, 0xcc, 0x26, 0x42, 0xcd, 0xcc, 0xb8, 0x41, 0x9a, 0x99, 0xe5, 0x41,
+  0x9a, 0x99, 0x81, 0x41, 0x33, 0x33, 0x8b, 0x41, 0x00, 0x00, 0xb0, 0x41, 0xcd, 0xcc, 0x0c, 0x42,
+  0x9a, 0x99, 0x89, 0x41, 0xcd, 0xcc, 0xbc, 0x41, 0x00, 0x00, 0xb0, 0x41, 0x00, 0x00, 0xf0, 0x40,
+  0x66, 0x66, 0x86, 0x41, 0x33, 0x33, 0x4b, 0x41, 0xcd, 0xcc, 0xb8, 0x41, 0x66, 0x66, 0xe6, 0x40,
+  0x00, 0x00, 0xc4, 0x41, 0x9a, 0x99, 0xbd, 0x41, 0x00, 0x00, 0x94, 0x41, 0x33, 0x33, 0x93, 0x41,
+  0x66, 0x66, 0xb6, 0x41, 0x00, 0x00, 0xb8, 0x41, 0x00, 0x00, 0xa8, 0x41, 0x66, 0x66, 0x10, 0x42,
+  0x00, 0x00, 0xe4, 0x41, 0x66, 0x66, 0x8e, 0x41, 0x33, 0x33, 0x9b, 0x41, 0x33, 0x33, 0x41, 0x42,
+  0x66, 0x66, 0x8a, 0x41, 0x00, 0x00, 0x38, 0x41, 0x9a, 0x99, 0x85, 0x41, 0x00, 0x00, 0x08, 0x41,
+  0x33, 0x33, 0xbf, 0x41, 0x33, 0x33, 0xc3, 0x41, 0x66, 0x66, 0x3e, 0x41, 0xcd, 0xcc, 0xb0, 0x41,
+  0x33, 0x33, 0x23, 0x41, 0xcd, 0xcc, 0xd4, 0x41, 0x9a, 0x99, 0x9d, 0x41, 0x33, 0x33, 0x29, 0x42,
+  0x66, 0x66, 0xba, 0x41, 0x9a, 0x99, 0xad, 0x41, 0x9a, 0x99, 0x89, 0x41, 0x00, 0x00, 0x94, 0x41,
+  0x9a, 0x99, 0x0b, 0x42, 0x66, 0x66, 0xf2, 0x41, 0x00, 0x00, 0x88, 0x41, 0x9a, 0x99, 0x59, 0x41,
+  0x66, 0x66, 0x66, 0x41, 0x66, 0x66, 0xc6, 0x41, 0xcd, 0xcc, 0x98, 0x41, 0x66, 0x66, 0x06, 0x41,
+  0x66, 0x66, 0x9a, 0x41, 0x00, 0x00, 0xa0, 0x41, 0x9a, 0x99, 0xd1, 0x41, 0x33, 0x33, 0x8b, 0x41,
+  0x66, 0x66, 0x92, 0x41, 0x00, 0x00, 0x48, 0x42, 0x00, 0x00, 0x84, 0x41, 0x00, 0x00, 0x48, 0x42,
+  0x33, 0x33, 0xbf, 0x41, 0x33, 0x33, 0xc3, 0x41, 0x9a, 0x99, 0x99, 0x41, 0x00, 0x00, 0xa8, 0x41,
+  0x00, 0x00, 0xfc, 0x41, 0x33, 0x33, 0xeb, 0x41, 0x00, 0x00, 0xb4, 0x41, 0x00, 0x00, 0x9c, 0x41};
+
+} // namespace data
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_BOSTON_HOUSING_TASK_DATA_TRAIN_TARGET_H
diff --git a/onert-micro/onert-micro/include/train/tests/models/boston_housing.h b/onert-micro/onert-micro/include/train/tests/models/boston_housing.h
new file mode 100644 (file)
index 0000000..d62c1d2
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_MODELS_BOSTON_HOUSING_H
+#define ONERT_MICRO_TRAIN_TESTS_MODELS_BOSTON_HOUSING_H
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+namespace models
+{
+
+unsigned char boston_housing_model[] = {
+  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,
+  0xdc, 0x07, 0x00, 0x00, 0x5c, 0x0a, 0x00, 0x00, 0x78, 0x0a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0xc8, 0x07, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
+  0x90, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0xee, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+  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, 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x33, 0x2e, 0x31, 0x00, 0x00,
+  0x4e, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x35, 0x2e,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf6, 0xff, 0xff,
+  0x7c, 0xf6, 0xff, 0xff, 0x72, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x9c, 0xe2, 0x3c, 0x3e, 0x58, 0xe6, 0x55, 0x3e, 0x7a, 0x51, 0xce, 0x3e, 0xdd, 0x3d, 0x98, 0xbe,
+  0x40, 0x98, 0xf7, 0xbd, 0xfc, 0x33, 0x70, 0x3e, 0xe7, 0x7a, 0x47, 0xbe, 0xa8, 0x1e, 0xbd, 0xbe,
+  0x57, 0x17, 0xa7, 0xbe, 0xf0, 0x98, 0x08, 0x3e, 0x98, 0xfb, 0xc6, 0x3e, 0x34, 0xb0, 0xc9, 0xbd,
+  0x19, 0xf1, 0xa6, 0xbe, 0xe0, 0x39, 0x6a, 0xbc, 0x10, 0xba, 0x0b, 0x3e, 0xc5, 0xb5, 0xd4, 0xbe,
+  0x82, 0x29, 0xd3, 0xbe, 0x0c, 0xc7, 0x69, 0x3e, 0x48, 0x86, 0x6e, 0x3d, 0x83, 0x90, 0x8d, 0xbe,
+  0x9c, 0x1b, 0x8a, 0xbd, 0x70, 0x01, 0x12, 0x3e, 0xf0, 0x89, 0xcd, 0x3c, 0xe1, 0x8f, 0x85, 0xbe,
+  0x48, 0xd2, 0xdc, 0x3d, 0x1a, 0xac, 0x27, 0xbe, 0x50, 0xf6, 0xf0, 0x3d, 0x81, 0x27, 0xbc, 0xbe,
+  0x92, 0xdb, 0xc0, 0xbe, 0xaa, 0x81, 0x60, 0xbe, 0x30, 0x9b, 0x56, 0x3e, 0x60, 0xce, 0xcb, 0x3e,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x80, 0x06, 0x00, 0x00, 0x44, 0xdd, 0x88, 0xbd, 0x20, 0xba, 0x3a, 0xbd, 0x74, 0x3a, 0x65, 0x3e,
+  0xb0, 0x40, 0xb6, 0x3e, 0x73, 0x3a, 0x51, 0xbe, 0x64, 0x00, 0xe5, 0xbd, 0x1e, 0xb2, 0x23, 0xbe,
+  0x58, 0x4e, 0xaf, 0x3e, 0x9c, 0x47, 0xab, 0xbd, 0x00, 0xf3, 0x87, 0x3e, 0xc0, 0x18, 0x4c, 0x3c,
+  0x18, 0xbf, 0xa7, 0xbd, 0xe6, 0x1f, 0xaf, 0x3e, 0xb8, 0xc2, 0x95, 0x3e, 0xd8, 0x64, 0xa0, 0x3e,
+  0xd4, 0xb3, 0x84, 0xbe, 0x60, 0x32, 0x0a, 0x3e, 0x80, 0xef, 0x1f, 0xbb, 0x50, 0x95, 0x3e, 0x3d,
+  0xe0, 0x7b, 0x1d, 0x3e, 0xc8, 0xa1, 0x39, 0x3e, 0x43, 0x46, 0x20, 0xbe, 0x18, 0x9f, 0xb1, 0x3e,
+  0xe3, 0x42, 0x1a, 0xbe, 0x53, 0xd2, 0x17, 0xbe, 0xd2, 0x96, 0xa3, 0x3e, 0x70, 0x54, 0x5a, 0xbd,
+  0x50, 0xb1, 0x61, 0x3e, 0x88, 0xbf, 0xe1, 0x3d, 0x40, 0x26, 0xc1, 0xbd, 0x88, 0xd0, 0xa4, 0x3e,
+  0x4c, 0x65, 0x8d, 0x3e, 0x38, 0xce, 0x6c, 0x3d, 0x7d, 0x7d, 0x98, 0xbe, 0xe8, 0xc4, 0x00, 0x3e,
+  0x36, 0x33, 0x4c, 0xbe, 0x80, 0xa4, 0xf2, 0x3c, 0xa4, 0x5f, 0xe5, 0xbd, 0x74, 0x3e, 0x13, 0x3e,
+  0x4c, 0x98, 0x45, 0x3e, 0x40, 0x8e, 0x2c, 0xbc, 0xdc, 0xdf, 0x9f, 0xbe, 0xe6, 0xad, 0x89, 0x3e,
+  0xb8, 0x69, 0x75, 0x3e, 0x04, 0xbe, 0x8a, 0xbe, 0xdf, 0x27, 0x14, 0xbe, 0xfa, 0xbe, 0x8a, 0xbe,
+  0xda, 0x95, 0x51, 0xbe, 0x80, 0x4d, 0x99, 0x3b, 0x04, 0x50, 0xd1, 0xbd, 0xc0, 0xec, 0x62, 0x3e,
+  0x90, 0xe2, 0x6e, 0x3e, 0x58, 0x12, 0x8b, 0xbe, 0xa0, 0x1c, 0x96, 0x3d, 0xe0, 0xc6, 0x2d, 0x3e,
+  0x20, 0x49, 0x22, 0xbd, 0x00, 0xc9, 0xbf, 0x3b, 0x6e, 0x46, 0x5f, 0xbe, 0xfc, 0x63, 0x85, 0xbd,
+  0x1c, 0xa7, 0x37, 0x3e, 0x52, 0x4b, 0xfd, 0xbd, 0xfe, 0x38, 0x9a, 0x3e, 0xd8, 0xac, 0xa8, 0x3d,
+  0x32, 0x41, 0xaf, 0x3e, 0xd9, 0xe3, 0x88, 0xbe, 0x4a, 0x50, 0x5f, 0xbe, 0x9e, 0x83, 0x5f, 0xbe,
+  0x40, 0x67, 0xf5, 0xbc, 0x20, 0x45, 0xa7, 0xbd, 0xb5, 0xba, 0x98, 0xbe, 0xcc, 0x4f, 0xb1, 0x3e,
+  0x36, 0xd7, 0x87, 0xbe, 0x33, 0x41, 0x36, 0xbe, 0xd4, 0x40, 0x6f, 0x3e, 0xa8, 0x81, 0x4e, 0xbe,
+  0x6e, 0x28, 0xa9, 0xbe, 0xed, 0xad, 0x9f, 0xbe, 0x10, 0xa8, 0x70, 0x3e, 0xff, 0xbf, 0x09, 0xbe,
+  0x40, 0x80, 0xf8, 0xbb, 0xe0, 0xfd, 0x15, 0x3c, 0x65, 0x13, 0x25, 0xbe, 0x68, 0x69, 0x33, 0x3e,
+  0x58, 0xa6, 0x7d, 0xbd, 0xec, 0x9a, 0x82, 0x3e, 0x15, 0xe3, 0x4b, 0xbe, 0xc0, 0x90, 0x72, 0xbc,
+  0xcc, 0xad, 0x48, 0x3e, 0x11, 0xad, 0xb3, 0xbe, 0x74, 0xcf, 0x8a, 0xbe, 0x08, 0xa2, 0x72, 0x3d,
+  0xa0, 0xd3, 0x3c, 0x3e, 0x35, 0xa4, 0x0e, 0xbe, 0xc0, 0x53, 0x70, 0x3d, 0x08, 0x52, 0x55, 0xbd,
+  0x18, 0xce, 0x0c, 0x3e, 0xa4, 0xba, 0xa0, 0x3e, 0x58, 0x8f, 0x0b, 0x3e, 0x4a, 0x69, 0xb0, 0xbe,
+  0xe6, 0x79, 0x64, 0xbe, 0x10, 0x1d, 0xff, 0x3d, 0xa4, 0x6a, 0xa0, 0xbe, 0x28, 0x50, 0x88, 0xbe,
+  0xa8, 0x1c, 0x98, 0xbe, 0x60, 0xe7, 0x37, 0x3e, 0xf8, 0x9f, 0x1d, 0x3e, 0x4c, 0x81, 0x82, 0xbd,
+  0x88, 0x11, 0x5a, 0x3d, 0x10, 0x27, 0x58, 0xbe, 0xa0, 0xa2, 0x45, 0xbc, 0xd0, 0x29, 0x8d, 0x3c,
+  0x7c, 0x3d, 0x6b, 0x3e, 0xec, 0x23, 0x11, 0x3e, 0xd2, 0x71, 0x56, 0xbe, 0x55, 0x22, 0x2c, 0xbe,
+  0xfe, 0xe1, 0x02, 0x3e, 0xf0, 0x5c, 0x6f, 0x3e, 0x87, 0x57, 0xb6, 0xbe, 0x3c, 0xec, 0x31, 0x3e,
+  0xac, 0x4d, 0x2c, 0xbe, 0x62, 0xf5, 0xf3, 0xbd, 0x84, 0xe6, 0xae, 0xbe, 0x56, 0x30, 0x90, 0xbe,
+  0x19, 0x6c, 0x91, 0xbe, 0xcc, 0x22, 0x39, 0xbe, 0xcc, 0xb0, 0x90, 0x3e, 0x9a, 0xfc, 0x6f, 0xbe,
+  0x18, 0x6e, 0xc1, 0xbd, 0x39, 0xe0, 0x30, 0xbe, 0xcc, 0x72, 0xae, 0x3e, 0xab, 0x9c, 0x8c, 0xbe,
+  0x30, 0xf2, 0xb3, 0x3c, 0x3d, 0x56, 0x0c, 0xbe, 0x4f, 0xe7, 0x56, 0xbe, 0x2b, 0x23, 0x49, 0xbe,
+  0xc0, 0x29, 0xbe, 0xbc, 0x9c, 0x23, 0xe4, 0x3d, 0x9c, 0x65, 0x7d, 0xbe, 0xcc, 0x19, 0x81, 0x3e,
+  0x90, 0xfc, 0xcc, 0xbd, 0x8a, 0x00, 0x83, 0xbe, 0xa4, 0x74, 0x9e, 0x3e, 0x88, 0x13, 0x54, 0x3e,
+  0xdc, 0x0a, 0x80, 0x3d, 0x3c, 0x51, 0x71, 0x3e, 0x04, 0xf4, 0x89, 0x3d, 0x0c, 0x6b, 0x12, 0x3e,
+  0xb3, 0xed, 0x53, 0xbe, 0x64, 0x7b, 0x9c, 0xbe, 0x4d, 0xaf, 0x88, 0xbe, 0xa2, 0xc9, 0x03, 0xbe,
+  0x82, 0xe8, 0x8a, 0xbe, 0x14, 0x4b, 0x8e, 0x3e, 0xc0, 0x08, 0x47, 0x3c, 0x70, 0xf7, 0xa9, 0xbc,
+  0x32, 0x3b, 0x99, 0x3e, 0x24, 0x62, 0xa4, 0xbe, 0x28, 0xb6, 0x62, 0x3d, 0x9c, 0x03, 0xdd, 0xbd,
+  0x20, 0x52, 0xb1, 0x3e, 0x63, 0xc3, 0x0d, 0xbe, 0x5a, 0xbe, 0xae, 0x3e, 0x64, 0x20, 0x85, 0xbd,
+  0xa6, 0x54, 0x94, 0x3e, 0x98, 0x4d, 0x3a, 0xbd, 0x19, 0xfc, 0xac, 0xbe, 0x38, 0x77, 0x8f, 0xbd,
+  0x58, 0x41, 0xd9, 0x3d, 0x60, 0x4e, 0x18, 0xbd, 0xcc, 0x3b, 0x22, 0x3e, 0x51, 0x2d, 0x84, 0xbe,
+  0xde, 0xe7, 0x65, 0xbe, 0xb6, 0x87, 0x26, 0xbe, 0x28, 0x15, 0x8c, 0x3e, 0x58, 0x8b, 0x2c, 0x3e,
+  0x52, 0x09, 0x21, 0xbe, 0xaa, 0xf0, 0x64, 0xbe, 0xec, 0x91, 0x89, 0x3d, 0x91, 0xd1, 0x39, 0xbe,
+  0x20, 0x5a, 0x84, 0xbc, 0xf0, 0xca, 0xb2, 0x3e, 0x37, 0x99, 0x5e, 0xbe, 0xf8, 0x14, 0xa9, 0x3d,
+  0xc2, 0x00, 0x8f, 0xbe, 0x0c, 0x48, 0x22, 0x3e, 0x60, 0x78, 0x1f, 0xbc, 0xea, 0x55, 0x8e, 0x3e,
+  0x6a, 0xc5, 0x95, 0x3e, 0x27, 0xa0, 0x8d, 0xbe, 0x4a, 0x00, 0x20, 0xbe, 0xae, 0xb3, 0x4e, 0xbe,
+  0xb0, 0xaa, 0x24, 0x3e, 0x68, 0x1b, 0x18, 0x3d, 0x6f, 0xa4, 0x51, 0xbe, 0xea, 0xda, 0xa0, 0x3e,
+  0x8c, 0x9d, 0x1e, 0xbe, 0x38, 0x7e, 0x08, 0xbd, 0xf4, 0xe0, 0xad, 0xbd, 0xa7, 0x36, 0x8b, 0xbe,
+  0xf4, 0x6d, 0xab, 0x3e, 0x1c, 0xd4, 0x8b, 0x3e, 0x00, 0xf2, 0x37, 0x3d, 0xa8, 0x63, 0x94, 0xbd,
+  0x8c, 0x5b, 0x15, 0x3e, 0x3a, 0xf4, 0x6f, 0xbe, 0xe9, 0xfc, 0x4c, 0xbe, 0x62, 0xc9, 0x54, 0xbe,
+  0xe4, 0x8d, 0x88, 0x3e, 0x6e, 0xa9, 0x9e, 0x3e, 0xd0, 0xdc, 0x52, 0x3e, 0x8c, 0xe6, 0x8d, 0x3e,
+  0xb0, 0x48, 0x86, 0x3e, 0x38, 0x7b, 0xa8, 0x3e, 0x40, 0xd1, 0xcf, 0xbd, 0x00, 0xf7, 0xcf, 0xbd,
+  0xec, 0xb8, 0xc3, 0x3d, 0x04, 0x96, 0x9a, 0x3e, 0x6e, 0xf3, 0xa6, 0x3e, 0x6c, 0x58, 0x89, 0x3e,
+  0x06, 0x33, 0xaf, 0x3e, 0x00, 0x0d, 0x22, 0xbb, 0xc0, 0x30, 0x94, 0xbc, 0x80, 0x0b, 0x8c, 0xbd,
+  0x68, 0xfc, 0x30, 0x3e, 0xe0, 0x4f, 0xba, 0x3e, 0xc0, 0xd4, 0xb6, 0x3e, 0x32, 0xba, 0x2e, 0xbe,
+  0xbe, 0x3f, 0x06, 0xbe, 0x3d, 0x70, 0xb4, 0xbe, 0xa2, 0x6b, 0x75, 0xbe, 0x54, 0xc6, 0x2c, 0x3e,
+  0xa8, 0x1d, 0x14, 0x3d, 0x04, 0xd3, 0xaf, 0xbe, 0x88, 0xa2, 0xa4, 0x3e, 0x7a, 0x98, 0x9c, 0xbe,
+  0xf8, 0x73, 0x65, 0xbd, 0x3e, 0x55, 0x95, 0xbe, 0x80, 0x9e, 0x7c, 0xbb, 0x50, 0xdd, 0xae, 0x3d,
+  0xf5, 0xa9, 0x83, 0xbe, 0x1b, 0xf6, 0x0c, 0xbe, 0x5e, 0xf6, 0xae, 0x3e, 0x04, 0x42, 0x9d, 0x3e,
+  0x50, 0x1d, 0x38, 0x3e, 0x33, 0x25, 0x54, 0xbe, 0xfc, 0x5f, 0x89, 0xbd, 0xde, 0xc7, 0x2b, 0xbe,
+  0xae, 0x25, 0xb5, 0x3e, 0xbc, 0x8e, 0x9c, 0xbd, 0x70, 0xce, 0xc1, 0x3d, 0x2c, 0xa5, 0xae, 0x3d,
+  0x3c, 0xcb, 0x4b, 0xbe, 0xd8, 0xe7, 0xac, 0xbe, 0xf0, 0xd4, 0x6a, 0x3e, 0xf6, 0x8b, 0x28, 0xbe,
+  0xf4, 0xaf, 0x69, 0x3e, 0xed, 0xed, 0xb0, 0xbe, 0x68, 0x4d, 0xa4, 0xbe, 0x00, 0x21, 0x6a, 0x3d,
+  0x78, 0x96, 0xd3, 0x3d, 0xea, 0x7c, 0x08, 0x3e, 0x78, 0xd4, 0x79, 0xbd, 0xf4, 0x00, 0x87, 0x3e,
+  0x64, 0xd9, 0x58, 0x3e, 0x68, 0xea, 0x4b, 0x3e, 0xe0, 0x93, 0xa1, 0xbd, 0x8c, 0x8a, 0xee, 0x3d,
+  0x68, 0xd1, 0x87, 0x3e, 0x79, 0x2f, 0xaa, 0xbe, 0xf0, 0xbc, 0x94, 0xbd, 0x48, 0x21, 0x38, 0x3d,
+  0x9c, 0xf2, 0xd2, 0x3d, 0x0c, 0xc2, 0x7d, 0x3e, 0x84, 0x19, 0x83, 0xbd, 0xa8, 0x3a, 0xc1, 0xbd,
+  0x65, 0xa1, 0x9b, 0xbe, 0x9c, 0xe4, 0x7a, 0x3e, 0xd6, 0xbc, 0x1e, 0xbe, 0xb8, 0x32, 0xb8, 0xbd,
+  0x08, 0x0f, 0xf4, 0x3d, 0x3c, 0xc0, 0x8c, 0x3e, 0x40, 0x68, 0xb0, 0xbc, 0xf8, 0xa3, 0x12, 0x3e,
+  0x14, 0xfe, 0x08, 0x3e, 0xb0, 0x2d, 0x83, 0x3d, 0xc0, 0xe6, 0x10, 0x3c, 0x85, 0x72, 0x14, 0xbe,
+  0x52, 0x13, 0xb7, 0x3e, 0xf4, 0xdd, 0xab, 0xbd, 0x48, 0x80, 0x1c, 0x3e, 0x9c, 0x9f, 0x36, 0x3e,
+  0x88, 0x11, 0x48, 0x3e, 0xc6, 0x49, 0x80, 0xbe, 0x0d, 0x5b, 0xb8, 0xbe, 0x6a, 0x80, 0x04, 0x3e,
+  0x68, 0x3e, 0x0d, 0xbe, 0xba, 0xd7, 0xb8, 0xbe, 0x88, 0x68, 0x99, 0xbd, 0x23, 0x44, 0x91, 0xbe,
+  0xc8, 0xa9, 0xec, 0xbd, 0x9e, 0xf1, 0x99, 0xbe, 0x39, 0xf2, 0xb8, 0xbe, 0xa8, 0xbd, 0x35, 0x3d,
+  0xe0, 0x1d, 0x64, 0xbc, 0xe8, 0xac, 0xc8, 0xbd, 0x88, 0xe6, 0x21, 0x3d, 0x3a, 0xaf, 0x95, 0xbe,
+  0x74, 0x8b, 0xcf, 0x3d, 0xd8, 0x3d, 0xb2, 0x3e, 0x98, 0x86, 0x24, 0x3d, 0xd6, 0x9b, 0x82, 0x3e,
+  0xa0, 0x37, 0x50, 0x3e, 0x44, 0xef, 0x00, 0x3e, 0xb8, 0x70, 0x56, 0x3e, 0xbc, 0x10, 0x51, 0x3e,
+  0x66, 0xcb, 0x69, 0xbe, 0xa0, 0xdd, 0x11, 0x3e, 0x70, 0x73, 0xbb, 0x3d, 0xbe, 0xdf, 0x81, 0xbe,
+  0xe9, 0x22, 0xab, 0xbe, 0x80, 0x11, 0xf9, 0x3b, 0x14, 0xba, 0x80, 0x3e, 0x76, 0x33, 0x0c, 0xbe,
+  0x64, 0xe2, 0x65, 0xbe, 0x72, 0x23, 0x96, 0x3e, 0x0c, 0x60, 0x45, 0x3e, 0xf6, 0x4d, 0x91, 0x3e,
+  0x3c, 0x9a, 0x59, 0xbe, 0x96, 0x6d, 0xff, 0xbd, 0x52, 0x45, 0xac, 0xbe, 0x57, 0xed, 0x47, 0xbe,
+  0xa0, 0xfb, 0xa3, 0x3c, 0x7e, 0x1a, 0x36, 0xbe, 0xd8, 0x77, 0xb7, 0x3d, 0xe0, 0xd8, 0x0f, 0xbc,
+  0xec, 0x47, 0xa4, 0xbd, 0x1c, 0x06, 0x14, 0x3e, 0x05, 0xb4, 0x83, 0xbe, 0x28, 0x6d, 0xa4, 0xbd,
+  0x98, 0xeb, 0x87, 0xbe, 0xde, 0xb4, 0x5f, 0xbe, 0x04, 0x53, 0xd3, 0x3d, 0xd3, 0xd0, 0x43, 0xbe,
+  0xd0, 0xa3, 0x29, 0xbd, 0x70, 0xce, 0x12, 0xbe, 0xb4, 0x1f, 0x00, 0xbe, 0xd0, 0x5b, 0x41, 0x3e,
+  0x2c, 0x70, 0x84, 0x3e, 0x98, 0x0c, 0x57, 0xbd, 0xc8, 0x8e, 0x1f, 0x3d, 0xb4, 0xa9, 0x9e, 0x3e,
+  0xbc, 0x8a, 0x94, 0x3e, 0x80, 0x03, 0x86, 0x3e, 0xa4, 0x67, 0xae, 0x3e, 0x00, 0x72, 0xf6, 0xbc,
+  0xac, 0xb1, 0x8c, 0x3e, 0x87, 0xf2, 0x83, 0xbe, 0x0c, 0x3c, 0x80, 0xbe, 0x14, 0xa5, 0xaa, 0xbd,
+  0x0c, 0x07, 0x81, 0xbe, 0x04, 0x9f, 0xbe, 0x3d, 0x10, 0xa3, 0x2d, 0x3e, 0x07, 0x8c, 0xa0, 0xbe,
+  0x78, 0xa7, 0x38, 0xbe, 0xac, 0xae, 0x86, 0x3d, 0xa1, 0x65, 0xaa, 0xbe, 0x14, 0x87, 0x5e, 0x3e,
+  0x2e, 0x56, 0xae, 0xbe, 0xd9, 0x44, 0xa4, 0xbe, 0x10, 0x1b, 0x4c, 0x3e, 0xb8, 0xff, 0x19, 0x3e,
+  0x7a, 0x57, 0xb0, 0x3e, 0xf8, 0xe7, 0x01, 0xbd, 0x28, 0x41, 0x26, 0x3d, 0xb4, 0x33, 0x90, 0x3e,
+  0xc8, 0x56, 0xe8, 0x3d, 0x4e, 0xe0, 0x1b, 0xbe, 0x60, 0xef, 0x71, 0x3e, 0xc0, 0xc8, 0xe4, 0xbd,
+  0x58, 0xc2, 0x68, 0x3e, 0x74, 0xf0, 0x11, 0x3e, 0x4d, 0x0f, 0xa9, 0xbe, 0x5f, 0x73, 0x40, 0xbe,
+  0x90, 0x80, 0x1f, 0x3e, 0x96, 0x71, 0x8d, 0xbe, 0x08, 0x20, 0x51, 0xbd, 0xf8, 0xd7, 0x16, 0xbe,
+  0x50, 0x3b, 0x1c, 0x3e, 0x12, 0xef, 0x80, 0x3e, 0x54, 0xe1, 0xf8, 0x3d, 0xa4, 0x12, 0x85, 0x3e,
+  0xd6, 0xb5, 0x94, 0x3e, 0x18, 0xd7, 0xb0, 0xbd, 0xa4, 0xc0, 0x33, 0x3e, 0x28, 0x83, 0xa8, 0x3e,
+  0x40, 0x46, 0x88, 0xbc, 0x18, 0xbb, 0xc8, 0x3d, 0x3c, 0x50, 0x55, 0xbe, 0x2c, 0x51, 0x4c, 0x3e,
+  0xb0, 0x62, 0x8e, 0x3e, 0xca, 0x36, 0x93, 0x3e, 0xd8, 0x18, 0x9c, 0xbe, 0xcc, 0x8a, 0x52, 0xbe,
+  0xc7, 0x07, 0x5d, 0xbe, 0x00, 0x50, 0x95, 0xba, 0xf4, 0x9b, 0x12, 0x3e, 0xfc, 0x6a, 0xb0, 0x3e,
+  0x66, 0xcb, 0xa5, 0xbe, 0xa0, 0x9d, 0x18, 0x3e, 0x30, 0x8e, 0xf3, 0x3c, 0xce, 0xac, 0x98, 0x3e,
+  0x71, 0x55, 0x79, 0xbe, 0x10, 0x9e, 0xb8, 0x3c, 0xd2, 0x42, 0x41, 0xbe, 0xbb, 0xda, 0x24, 0xbe,
+  0x00, 0x7d, 0x67, 0x3e, 0xa0, 0xfd, 0xff, 0xff, 0xa4, 0xfd, 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,
+  0xb0, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x58, 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, 0x0c, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0c, 0x00,
+  0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 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, 0x01, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xc6, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xb8, 0xfe, 0xff, 0xff,
+  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,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0xff, 0xff, 0xff,
+  0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0xfc, 0xfe, 0xff, 0xff, 0x39, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69,
+  0x61, 0x6c, 0x5f, 0x32, 0x33, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x35, 0x31, 0x2f, 0x4d,
+  0x61, 0x74, 0x4d, 0x75, 0x6c, 0x3b, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
+  0x5f, 0x32, 0x33, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x35, 0x31, 0x2f, 0x52, 0x65, 0x6c,
+  0x75, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x6e, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x60, 0xff, 0xff, 0xff, 0x1d, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75,
+  0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x32, 0x33, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f,
+  0x35, 0x32, 0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xb6, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0xa8, 0xff, 0xff, 0xff,
+  0x1d, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x32,
+  0x33, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x35, 0x31, 0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75,
+  0x6c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0d, 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, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 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};
+unsigned int boston_housing_model_size = 2744;
+
+} // namespace models
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_MODELS_BOSTON_HOUSING_H
diff --git a/onert-micro/onert-micro/include/train/tests/models/checkoint_simple_example_model.h b/onert-micro/onert-micro/include/train/tests/models/checkoint_simple_example_model.h
new file mode 100644 (file)
index 0000000..8125be2
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_MODELS_CHECKPOINT_SIMPLE_EXAMPLE_MODEL_H
+#define ONERT_MICRO_TRAIN_TESTS_MODELS_CHECKPOINT_SIMPLE_EXAMPLE_MODEL_H
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+namespace models
+{
+
+unsigned char checkpoint_simple_example_model_data[] = {
+  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,
+  0x94, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x80, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xe2, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x53, 0xb4, 0x05, 0x3f, 0x5f, 0x52, 0x80, 0xbe, 0xea, 0xe9, 0xc6, 0x3e, 0xa1, 0x01, 0x96, 0xbf,
+  0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0xfa, 0x82, 0xe5, 0xbf, 0xbd, 0xb5, 0x33, 0xbf, 0x48, 0x23, 0x30, 0xbe,
+  0xa2, 0x01, 0x35, 0xbe, 0xac, 0x06, 0x1f, 0x3f, 0x29, 0x81, 0x14, 0xc0, 0xa9, 0x0b, 0xd7, 0x3f,
+  0xcd, 0x58, 0xd5, 0x3f, 0x5d, 0x9d, 0xb8, 0x3f, 0x3e, 0xe8, 0x1e, 0xbe, 0x2d, 0xaa, 0xe0, 0xbf,
+  0x56, 0x65, 0x26, 0xbf, 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, 0x70, 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, 0x08,
+  0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x0a, 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, 0x90, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x8c, 0xff, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x6f, 0x75, 0x74, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 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, 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, 0x02, 0x00, 0x00, 0x00,
+  0x69, 0x6e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 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, 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};
+unsigned int checkpoint_simple_example_model_size = 588;
+
+} // namespace models
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_MODELS_CHECKPOINT_SIMPLE_EXAMPLE_MODEL_H
diff --git a/onert-micro/onert-micro/include/train/tests/models/numbers_classification_model.h b/onert-micro/onert-micro/include/train/tests/models/numbers_classification_model.h
new file mode 100644 (file)
index 0000000..5e03eac
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_MODELS_NUMBERS_CLASSIFICATION_MODEL_H
+#define ONERT_MICRO_TRAIN_TESTS_MODELS_NUMBERS_CLASSIFICATION_MODEL_H
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+namespace models
+{
+unsigned char numbers_classification_model[] = {
+  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,
+  0xec, 0x01, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, 0x74, 0x07, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+  0xd8, 0x01, 0x00, 0x00, 0xd0, 0x01, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00,
+  0x20, 0x01, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
+  0x98, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xea, 0xfd, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 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, 0x06, 0x00, 0x00, 0x00, 0x32, 0x2e, 0x31, 0x33,
+  0x2e, 0x31, 0x00, 0x00, 0x4a, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x31, 0x2e, 0x35, 0x2e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xd8, 0xf9, 0xff, 0xff, 0xdc, 0xf9, 0xff, 0xff, 0xe0, 0xf9, 0xff, 0xff, 0xe4, 0xf9, 0xff, 0xff,
+  0xe8, 0xf9, 0xff, 0xff, 0x7a, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+  0x9e, 0xa4, 0x82, 0x3e, 0x14, 0x12, 0x7d, 0xbe, 0xd8, 0x20, 0x49, 0x3e, 0x7a, 0x2e, 0x8c, 0x3e,
+  0x58, 0x5a, 0x11, 0xbe, 0xc0, 0xa4, 0xa2, 0x3e, 0x70, 0xcd, 0xd0, 0x3e, 0xba, 0x4e, 0xcb, 0xbe,
+  0xe8, 0x97, 0x10, 0x3f, 0x7c, 0x0b, 0x0d, 0xbf, 0xf8, 0x4e, 0x9c, 0x3e, 0x6a, 0x60, 0x7b, 0xbe,
+  0x14, 0xc6, 0xee, 0x3e, 0xa8, 0xba, 0x71, 0x3e, 0x30, 0x6a, 0x1e, 0x3f, 0x88, 0xb7, 0xe3, 0x3e,
+  0x90, 0xc1, 0x9b, 0xbe, 0x3c, 0xbd, 0x43, 0x3e, 0x36, 0x3a, 0x95, 0x3e, 0x30, 0xf2, 0x8b, 0x3e,
+  0x02, 0xc3, 0x16, 0x3f, 0x80, 0x27, 0xc6, 0x3e, 0x87, 0x30, 0x1e, 0xbf, 0x20, 0xff, 0xc6, 0x3e,
+  0xe6, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x0c, 0x00, 0x00, 0x00, 0xfa, 0xfe, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
+  0xd2, 0x7a, 0xac, 0xbe, 0x73, 0x88, 0xbe, 0xbe, 0xd0, 0x74, 0x75, 0xbe, 0x40, 0x74, 0xc8, 0x3d,
+  0x16, 0xea, 0x9d, 0x3e, 0xe4, 0xc9, 0x10, 0x3e, 0x78, 0xeb, 0x8a, 0xbe, 0x07, 0x2e, 0xae, 0xbe,
+  0xee, 0x46, 0x8a, 0xbe, 0x64, 0xf2, 0xb8, 0x3e, 0x44, 0xc5, 0x88, 0x3e, 0x6d, 0x83, 0x78, 0xbe,
+  0xc8, 0x14, 0x6c, 0xbd, 0x64, 0x5f, 0xdd, 0xbd, 0x08, 0xbb, 0x6e, 0x3e, 0x8c, 0x54, 0xa4, 0xbe,
+  0xa0, 0xe6, 0x83, 0x3e, 0x36, 0x1d, 0x87, 0x3e, 0x54, 0xd3, 0x44, 0x3e, 0xd8, 0x45, 0xa1, 0x3d,
+  0x94, 0x21, 0x7d, 0x3e, 0x52, 0x5f, 0xcb, 0xbe, 0xec, 0x35, 0x8b, 0x3e, 0xd9, 0x2d, 0x41, 0xbe,
+  0x4c, 0x30, 0xcb, 0xbd, 0x30, 0x5a, 0xe1, 0xbc, 0x7a, 0x6b, 0xd0, 0x3e, 0x72, 0xff, 0xff, 0xff,
+  0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0xfa, 0xff, 0xff, 0x00, 0xfb, 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,
+  0x98, 0x01, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00,
+  0xcc, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x52, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x09, 0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x08, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x08, 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, 0x08,
+  0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xb8, 0xfb, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0a, 0x00,
+  0x10, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00,
+  0x1a, 0x00, 0x14, 0x00, 0x10, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+  0x01, 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,
+  0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 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, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00,
+  0xb0, 0x02, 0x00, 0x00, 0x5c, 0x02, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0xb4, 0x01, 0x00, 0x00,
+  0x44, 0x01, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x1e, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0xfd, 0xff, 0xff, 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, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x62, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x54, 0xfd, 0xff, 0xff,
+  0x1e, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x38,
+  0x30, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x38, 0x38, 0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75,
+  0x6c, 0x32, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0xaa, 0xfd, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x9c, 0xfd, 0xff, 0xff, 0x20, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75,
+  0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x38, 0x30, 0x2f, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65,
+  0x6e, 0x5f, 0x38, 0x30, 0x2f, 0x52, 0x65, 0x73, 0x68, 0x61, 0x70, 0x65, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xf6, 0xfd, 0xff, 0xff,
+  0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0xe8, 0xfd, 0xff, 0xff, 0x26, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69,
+  0x61, 0x6c, 0x5f, 0x38, 0x30, 0x2f, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x69, 0x6e,
+  0x67, 0x32, 0x64, 0x5f, 0x38, 0x34, 0x2f, 0x4d, 0x61, 0x78, 0x50, 0x6f, 0x6f, 0x6c, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x4e, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x40, 0xfe, 0xff, 0xff, 0x3b, 0x00, 0x00, 0x00,
+  0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x38, 0x30, 0x2f, 0x63, 0x6f,
+  0x6e, 0x76, 0x32, 0x64, 0x5f, 0x38, 0x34, 0x2f, 0x52, 0x65, 0x6c, 0x75, 0x3b, 0x73, 0x65, 0x71,
+  0x75, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x38, 0x30, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x32,
+  0x64, 0x5f, 0x38, 0x34, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xba, 0xfe, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0xac, 0xfe, 0xff, 0xff, 0x1e, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75,
+  0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x38, 0x30, 0x2f, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x5f,
+  0x38, 0x38, 0x2f, 0x4d, 0x61, 0x74, 0x4d, 0x75, 0x6c, 0x31, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x0c, 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, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x00,
+  0x08, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x69,
+  0x61, 0x6c, 0x5f, 0x38, 0x30, 0x2f, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x5f, 0x38, 0x30,
+  0x2f, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x5a, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x4c, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75,
+  0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x38, 0x30, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64,
+  0x5f, 0x38, 0x34, 0x2f, 0x43, 0x6f, 0x6e, 0x76, 0x32, 0x44, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0xaa, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x9c, 0xff, 0xff, 0xff, 0x2e, 0x00, 0x00, 0x00, 0x73, 0x65, 0x71, 0x75,
+  0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x38, 0x30, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x32, 0x64,
+  0x5f, 0x38, 0x34, 0x2f, 0x42, 0x69, 0x61, 0x73, 0x41, 0x64, 0x64, 0x2f, 0x52, 0x65, 0x61, 0x64,
+  0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x4f, 0x70, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x03, 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,
+  0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0xd0, 0xff, 0xff, 0xff, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
+  0xdc, 0xff, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xe8, 0xff, 0xff, 0xff,
+  0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xf4, 0xff, 0xff, 0xff, 0x11, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x11, 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};
+unsigned int numbers_classification_model_size = 1972;
+
+} // namespace models
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_MODELS_NUMBERS_CLASSIFICATION_MODEL_H
diff --git a/onert-micro/onert-micro/include/train/tests/models/saved_checkpoint_example.h b/onert-micro/onert-micro/include/train/tests/models/saved_checkpoint_example.h
new file mode 100644 (file)
index 0000000..c021957
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_MODELS_SAVED_CHECKPOINT_EXAMPLE_H
+#define ONERT_MICRO_TRAIN_TESTS_MODELS_SAVED_CHECKPOINT_EXAMPLE_H
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+namespace models
+{
+
+unsigned char saved_checkpoint_example[] = {
+  0xad, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfa, 0x82, 0xe5, 0xbf, 0xbd, 0xb5, 0x33, 0xbf, 0x48, 0x23, 0x30, 0xbe,
+  0xa2, 0x01, 0x35, 0xbe, 0xac, 0x06, 0x1f, 0x3f, 0x29, 0x81, 0x14, 0xc0, 0xa9, 0x0b, 0xd7, 0x3f,
+  0xcd, 0x58, 0xd5, 0x3f, 0x5d, 0x9d, 0xb8, 0x3f, 0x3e, 0xe8, 0x1e, 0xbe, 0x2d, 0xaa, 0xe0, 0xbf,
+  0x56, 0x65, 0x26, 0xbf, 0x53, 0xb4, 0x05, 0x3f, 0x5f, 0x52, 0x80, 0xbe, 0xea, 0xe9, 0xc6, 0x3e,
+  0xa1, 0x01, 0x96, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+unsigned char saved_checkpoint_example_with_wrong_magic_num[] = {
+  0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfa, 0x82, 0xe5, 0xbf, 0xbd, 0xb5, 0x33, 0xbf, 0x48, 0x23, 0x30, 0xbe,
+  0xa2, 0x01, 0x35, 0xbe, 0xac, 0x06, 0x1f, 0x3f, 0x29, 0x81, 0x14, 0xc0, 0xa9, 0x0b, 0xd7, 0x3f,
+  0xcd, 0x58, 0xd5, 0x3f, 0x5d, 0x9d, 0xb8, 0x3f, 0x3e, 0xe8, 0x1e, 0xbe, 0x2d, 0xaa, 0xe0, 0xbf,
+  0x56, 0x65, 0x26, 0xbf, 0x53, 0xb4, 0x05, 0x3f, 0x5f, 0x52, 0x80, 0xbe, 0xea, 0xe9, 0xc6, 0x3e,
+  0xa1, 0x01, 0x96, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+unsigned int saved_checkpoint_example_size = 108;
+
+} // namespace models
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_MODELS_SAVED_CHECKPOINT_EXAMPLE_H
diff --git a/onert-micro/onert-micro/include/train/tests/numbers_classification_task/NumbersClassificationTask.h b/onert-micro/onert-micro/include/train/tests/numbers_classification_task/NumbersClassificationTask.h
new file mode 100644 (file)
index 0000000..c077f05
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_NUMBERS_CLASSIFICATION_TASK_H
+#define ONERT_MICRO_TRAIN_TESTS_NUMBERS_CLASSIFICATION_TASK_H
+
+#include "train/tests/OMTestTrainBase.h"
+#include "train/tests/models/numbers_classification_model.h"
+#include "train/tests/numbers_classification_task/data/train_input.h"
+#include "train/tests/numbers_classification_task/data/train_target.h"
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+
+namespace
+{
+
+// Note: use only one dataset - train will be also for test
+const size_t NUM_SAMPLES = 20;
+
+} // namespace
+
+template <typename T, typename U = T> class NumbersClassificationTask : public OMTestTrainBase<T, U>
+{
+public:
+  NumbersClassificationTask()
+  {
+    // Set model
+    _train_model_ptr.resize(models::numbers_classification_model_size);
+    std::memcpy(_train_model_ptr.data(), models::numbers_classification_model,
+                models::numbers_classification_model_size);
+  }
+
+  // Get ptr to trained model
+  char *getModelPtr() final { return _train_model_ptr.data(); }
+
+  // Return model size
+  size_t getModelSize() final { return _train_model_ptr.size(); }
+
+  // Return num train samples
+  size_t getTrainNumSamples() final { return NUM_SAMPLES; };
+
+  // Return num test samples
+  size_t getTestNumSamples() final { return NUM_SAMPLES; }
+
+  // Read train input data with cur size and cur offset
+  std::vector<T> readTrainInputData(size_t size, size_t offset) final
+  {
+    std::vector<T> result(size);
+
+    auto *cur_ptr = data::numbers_classification_task_input_data + offset;
+
+    std::memcpy(result.data(), cur_ptr, size);
+    return result;
+  }
+  // Read train target data with cur size and cur offset
+  std::vector<U> readTrainTargetData(size_t size, size_t offset) final
+  {
+    std::vector<T> result(size);
+
+    auto *cur_ptr = data::numbers_classification_task_target_data + offset;
+
+    std::memcpy(result.data(), cur_ptr, size);
+    return result;
+  }
+
+  // Read test input data with cur size and cur offset
+  // Note: use only one dataset - train will be also for test
+  std::vector<T> readTestInputData(size_t size, size_t offset) final
+  {
+    std::vector<T> result(size);
+
+    auto *cur_ptr = data::numbers_classification_task_input_data + offset;
+
+    std::memcpy(result.data(), cur_ptr, size);
+    return result;
+  }
+
+  // Read test target data with cur size and cur offset
+  // Note: use only one dataset - train will be also for test
+  std::vector<T> readTestTargetData(size_t size, size_t offset) final
+  {
+    std::vector<T> result(size);
+
+    auto *cur_ptr = data::numbers_classification_task_target_data + offset;
+
+    std::memcpy(result.data(), cur_ptr, size);
+    return result;
+  }
+
+private:
+  std::vector<char> _train_model_ptr = {};
+};
+
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_NUMBERS_CLASSIFICATION_TASK_H
diff --git a/onert-micro/onert-micro/include/train/tests/numbers_classification_task/data/train_input.h b/onert-micro/onert-micro/include/train/tests/numbers_classification_task/data/train_input.h
new file mode 100644 (file)
index 0000000..ac3c9e6
--- /dev/null
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_NUMBERS_CLASSIFICATION_TASK_DATA_TRAIN_INPUT_H
+#define ONERT_MICRO_TRAIN_TESTS_NUMBERS_CLASSIFICATION_TASK_DATA_TRAIN_INPUT_H
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+namespace data
+{
+
+unsigned char numbers_classification_task_input_data[] = {
+  0x00, 0x00, 0x80, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xc3, 0xc2, 0x42, 0x3f, 0xd1, 0xd0, 0x50, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xd1, 0xd0, 0x50, 0x3d, 0xd0, 0xcf, 0x4f, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xf8, 0xf7, 0x77, 0x3f,
+  0xf3, 0xf2, 0xf2, 0x3e, 0x99, 0x98, 0x98, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xa5, 0xa4, 0xa4, 0x3e, 0xf1, 0xf0, 0x70, 0x3f, 0xbc, 0xbb, 0x3b, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc6, 0xc5, 0x45, 0x3f, 0xd1, 0xd0, 0x50, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc2, 0xc2, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x98, 0x98, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe5, 0xe4, 0xe4, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xa0, 0x20, 0x3d, 0xbd, 0xbc, 0x3c, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xab, 0xaa, 0xaa, 0x3e, 0xf8, 0xf7, 0x77, 0x3f, 0x85, 0x84, 0x84, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xab, 0xaa, 0xaa, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc0, 0xbf, 0x3f, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x81, 0x80, 0x00, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xbf, 0x3f, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x80, 0x3f, 0xc0, 0xbf, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x81, 0x80, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0xc0, 0xbf, 0x3f, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x80, 0x3e, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x80, 0x3f, 0xc0, 0xbf, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x80, 0x3e,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x81, 0x80, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x80, 0x3e, 0xc0, 0xbf, 0x3f, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0x81, 0x80, 0x80, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x81, 0x80, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x81, 0x80, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x80, 0x3f, 0x81, 0x80, 0x80, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x81, 0x80, 0x80, 0x3e, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3f, 0xc0, 0xbf, 0x3f, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x80, 0x3e, 0x81, 0x80, 0x00, 0x3f, 0xc0, 0xbf, 0x3f, 0x3f,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x80, 0x3f, 0xc0, 0xbf, 0x3f, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xb1, 0xb0, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0xb8, 0x38, 0x3e,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xb3, 0xb2, 0xb2, 0x3e,
+  0xb3, 0xb2, 0xb2, 0x3e, 0xae, 0xad, 0x2d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0xb0, 0xb0, 0x3d, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xef, 0xee, 0x6e, 0x3f, 0x91, 0x90, 0x90, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xa6, 0x26, 0x3f, 0xed, 0xec, 0x6c, 0x3f,
+  0x87, 0x86, 0x86, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0xa8, 0x3e, 0xc7, 0xc6, 0x46, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x81, 0x80, 0x00, 0x3e, 0xc8, 0xc7, 0x47, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3e,
+  0xaa, 0xa9, 0x29, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0xe0, 0x60, 0x3e, 0xb1, 0xb0, 0xb0, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe1, 0xe0, 0x60, 0x3e, 0xc3, 0xc2, 0x42, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3c,
+  0xaa, 0xa9, 0x29, 0x3f, 0xc7, 0xc6, 0x46, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0xb8, 0xb8, 0x3d, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xc7, 0xc6, 0x46, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x8d, 0x8c, 0x0c, 0x3e, 0x98, 0x97, 0x17, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0x00, 0x00, 0x80, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0x8e, 0x8d, 0x0d, 0x3f, 0xfd, 0xfc, 0xfc, 0x3e, 0xe6, 0xe5, 0x65, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xbd, 0xbc, 0xbc, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xdd, 0xdc, 0x5c, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd1, 0xd0, 0x50, 0x3d, 0x9c, 0x9b, 0x1b, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfa, 0xf9, 0x79, 0x3f, 0xc7, 0xc6, 0xc6, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe9, 0xe8, 0xe8, 0x3d, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xe0, 0xdf, 0x5f, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe9, 0xe8, 0xe8, 0x3d, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xaf, 0xae, 0x2e, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0xe8, 0xe8, 0x3d,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xf2, 0xf1, 0x71, 0x3f,
+  0x91, 0x90, 0x90, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xe9, 0xe8, 0xe8, 0x3d, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x99, 0x98, 0x98, 0x3e, 0xaf, 0xae, 0xae, 0x3e,
+  0xc4, 0xc3, 0x43, 0x3f, 0xe4, 0xe3, 0x63, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xea, 0xe9, 0x69, 0x3f,
+  0xa6, 0xa5, 0x25, 0x3f, 0x9d, 0x9c, 0x1c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xd9, 0xd8, 0xd8, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfd, 0xfc, 0xfc, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xd5, 0xd4, 0xd4, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0xb1, 0xb0, 0x30, 0x3e, 0xf8, 0xf7, 0x77, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xce, 0xcd, 0x4d, 0x3f, 0x90, 0x8f, 0x0f, 0x3f, 0xf4, 0xf3, 0x73, 0x3f,
+  0xb5, 0xb4, 0x34, 0x3f, 0x8c, 0x8b, 0x0b, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0xeb, 0xea, 0xea, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xc8, 0xc7, 0x47, 0x3f,
+  0xa9, 0xa8, 0xa8, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x88, 0x87, 0x07, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xb9, 0xb8, 0xb8, 0x3e, 0xe8, 0xe7, 0x67, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xf9, 0xf8, 0x78, 0x3f, 0xf1, 0xf0, 0x70, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x87, 0x07, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xaf, 0xae, 0x2e, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0x83, 0x82, 0x02, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x87, 0x07, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xec, 0xeb, 0x6b, 0x3f, 0x89, 0x88, 0x88, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x88, 0x87, 0x07, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0x81, 0x80, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x88, 0x87, 0x07, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xe5, 0xe4, 0x64, 0x3f,
+  0xe9, 0xe8, 0xe8, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xbf, 0x3f, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xb4, 0xb3, 0x33, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x83, 0x82, 0x82, 0x3e, 0xfb, 0xfa, 0x7a, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xc3, 0xc2, 0xc2, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xba, 0xb9, 0x39, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xf9, 0xf8, 0x78, 0x3f,
+  0xb5, 0xb4, 0x34, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0x40, 0x3d, 0xa2, 0xa1, 0x21, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xf7, 0xf6, 0x76, 0x3f, 0xa9, 0xa8, 0x28, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3d,
+  0x81, 0x80, 0x00, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xa1, 0xa0, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3e,
+  0xd9, 0xd8, 0xd8, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfa, 0xf9, 0x79, 0x3f, 0x9c, 0x9b, 0x1b, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xe7, 0x67, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xdc, 0xdb, 0x5b, 0x3f, 0xd9, 0xd8, 0x58, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xcd, 0xcc, 0xcc, 0x3e, 0xff, 0xfe, 0x7e, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xc7, 0xc6, 0xc6, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0x3f,
+  0xff, 0xfe, 0x7e, 0x3f, 0xbc, 0xbb, 0x3b, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe9, 0xe8, 0x68, 0x3e, 0xe8, 0xe7, 0x67, 0x3f, 0xf5, 0xf4, 0x74, 0x3f,
+  0x83, 0x82, 0x02, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xa0, 0xa0, 0x3d,
+  0xda, 0xd9, 0x59, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfb, 0xfa, 0xfa, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xd8, 0xd8, 0x3e, 0x00, 0x00, 0x80, 0x3f,
+  0xff, 0xfe, 0x7e, 0x3f, 0xc5, 0xc4, 0x44, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x95, 0x94, 0x14, 0x3e, 0xe1, 0xe0, 0x60, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xc4, 0xc3, 0x43, 0x3f,
+  0xc5, 0xc4, 0x44, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x8c, 0x0c, 0x3e, 0xae, 0xad, 0x2d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xe0, 0xdf, 0x5f, 0x3f, 0xa1, 0xa0, 0xa0, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf1, 0xf0, 0xf0, 0x3d, 0x89, 0x88, 0x08, 0x3f, 0xf5, 0xf4, 0x74, 0x3f, 0xdd, 0xdc, 0x5c, 0x3f,
+  0xa9, 0xa8, 0xa8, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3e,
+  0xe7, 0xe6, 0x66, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xac, 0xab, 0x2b, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xef, 0xee, 0xee, 0x3e, 0xff, 0xfe, 0x7e, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xd3, 0xd2, 0x52, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0xb0, 0x30, 0x3e,
+  0xf8, 0xf7, 0x77, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0xa3, 0xa2, 0xa2, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0xac, 0x2c, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xff, 0xfe, 0x7e, 0x3f, 0xcc, 0xcb, 0x4b, 0x3f, 0x91, 0x90, 0x10, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xad, 0xac, 0xac, 0x3e, 0xff, 0xfe, 0x7e, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xb1, 0xb0, 0xb0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xd8, 0x58, 0x3e, 0xec, 0xeb, 0x6b, 0x3f,
+  0xff, 0xfe, 0x7e, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0x8a, 0x89, 0x09, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc1, 0xc0, 0x40, 0x3c, 0xc4, 0xc3, 0x43, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xb4, 0xb3, 0x33, 0x3f, 0x91, 0x90, 0x10, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xa7, 0x27, 0x3f,
+  0xff, 0xfe, 0x7e, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0xd6, 0xd5, 0x55, 0x3f, 0x81, 0x80, 0x00, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0xa8, 0x3e, 0xf6, 0xf5, 0x75, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xff, 0xfe, 0x7e, 0x3f, 0x86, 0x85, 0x05, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0xe0, 0xe0, 0x3d,
+  0xfa, 0xf9, 0x79, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0xcb, 0xca, 0x4a, 0x3f,
+  0x81, 0x80, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xb9, 0xb8, 0xb8, 0x3d, 0xcd, 0xcc, 0x4c, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xff, 0xfe, 0x7e, 0x3f, 0xba, 0xb9, 0x39, 0x3f, 0xb5, 0xb4, 0x34, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x83, 0x82, 0x02, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0xbf, 0xbe, 0x3e, 0x3f,
+  0xa1, 0xa0, 0x20, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xc4, 0x44, 0x3f,
+  0x00, 0x00, 0x80, 0x3f, 0xfa, 0xf9, 0x79, 0x3f, 0xf1, 0xf0, 0x70, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x89, 0x88, 0x08, 0x3e, 0xf5, 0xf4, 0x74, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xea, 0xe9, 0x69, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xa1, 0xa0, 0x20, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0xcc, 0xcb, 0x4b, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xa0, 0x20, 0x3e,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0x88, 0x87, 0x07, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xa0, 0x20, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xff, 0xfe, 0x7e, 0x3f, 0xc7, 0xc6, 0xc6, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x8a, 0x89, 0x09, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0x9d, 0x9c, 0x1c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x89, 0x88, 0x08, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0x9d, 0x9c, 0x1c, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xa6, 0x26, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0x9d, 0x9c, 0x1c, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0xea, 0x6a, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xdf, 0xde, 0x5e, 0x3f, 0x91, 0x90, 0x90, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf5, 0xf4, 0x74, 0x3e, 0xf9, 0xf8, 0x78, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x9e, 0x9d, 0x1d, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, 0x9e, 0x9e, 0x3e,
+  0xff, 0xfe, 0x7e, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0x99, 0x98, 0x98, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f,
+  0xfc, 0xfb, 0x7b, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f,
+  0xfc, 0xfb, 0x7b, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xc2, 0xc1, 0x41, 0x3f,
+  0xa0, 0x9f, 0x1f, 0x3f, 0x9f, 0x9e, 0x1e, 0x3f, 0x9f, 0x9e, 0x9e, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0xa0, 0x9f, 0x1f, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xf8, 0xf7, 0x77, 0x3f,
+  0xdd, 0xdc, 0x5c, 0x3f, 0xa3, 0xa2, 0xa2, 0x3e, 0xb9, 0xb8, 0xb8, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x9c, 0x1c, 0x3e,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x8d, 0x8c, 0x0c, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0x7d, 0x3f,
+  0x82, 0x81, 0x01, 0x3f, 0x81, 0x80, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x99, 0x19, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xf0, 0x70, 0x3e,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3d, 0xab, 0xaa, 0x2a, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x80, 0x3e,
+  0x9f, 0x9e, 0x1e, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xa1, 0xa0, 0x20, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xa0, 0x20, 0x3e, 0xa1, 0xa0, 0x20, 0x3e,
+  0x81, 0x80, 0x80, 0x3e, 0x81, 0x80, 0x80, 0x3e, 0x9f, 0x9e, 0x1e, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f,
+  0xfc, 0xfb, 0x7b, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xdb, 0xda, 0x5a, 0x3f, 0x9f, 0x9e, 0x1e, 0x3f,
+  0x9f, 0x9e, 0x1e, 0x3f, 0xda, 0xd9, 0x59, 0x3f, 0xda, 0xd9, 0x59, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfc, 0xfb, 0x7b, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0xca, 0xca, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xf2, 0xf1, 0x71, 0x3f, 0x85, 0x84, 0x04, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe8, 0xe7, 0x67, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0x9a, 0x99, 0x19, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xf0, 0xf0, 0x3d, 0xf0, 0xef, 0x6f, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xa9, 0xa8, 0xa8, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc9, 0xc8, 0x48, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xcb, 0xca, 0x4a, 0x3f, 0xb9, 0xb8, 0xb8, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xba, 0xb9, 0x39, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xd1, 0xd0, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xdb, 0x5b, 0x3f, 0xf8, 0xf7, 0x77, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x8d, 0x8c, 0x0c, 0x3f,
+  0xc1, 0xc0, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xd1, 0xd0, 0x50, 0x3d, 0xf1, 0xf0, 0x70, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f, 0xed, 0xec, 0xec, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x8b, 0x0b, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0x9b, 0x9a, 0x1a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xb1, 0xb0, 0x30, 0x3d, 0xab, 0xaa, 0x2a, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xba, 0xb9, 0x39, 0x3f, 0x91, 0x90, 0x10, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x8f, 0x8e, 0x0e, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xa7, 0xa6, 0x26, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc1, 0x41, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xc2, 0xc1, 0x41, 0x3f,
+  0xc1, 0xc0, 0x40, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x97, 0x96, 0x16, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xb1, 0xb0, 0x30, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3e, 0xeb, 0xea, 0x6a, 0x3f,
+  0xac, 0xab, 0x2b, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x9c, 0x9b, 0x1b, 0x3f, 0xff, 0xfe, 0x7e, 0x3f, 0x87, 0x86, 0x86, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbc, 0x3c, 0x3e,
+  0xff, 0xfe, 0x7e, 0x3f, 0xb1, 0xb0, 0x30, 0x3f, 0xb1, 0xb0, 0x30, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xeb, 0xea, 0x6a, 0x3f, 0xb6, 0xb5, 0x35, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0xd2, 0xd2, 0x3e,
+  0xff, 0xfe, 0x7e, 0x3f, 0x8c, 0x8b, 0x0b, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0xe0, 0xdf, 0x5f, 0x3f, 0xe5, 0xe4, 0x64, 0x3f,
+  0xb1, 0xb0, 0x30, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x9d, 0x9c, 0x9c, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0x87, 0x86, 0x06, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x96, 0x16, 0x3f,
+  0xff, 0xfe, 0x7e, 0x3f, 0x81, 0x80, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0xab, 0x2b, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xb1, 0xb0, 0x30, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xd4, 0x54, 0x3e,
+  0xf1, 0xf0, 0x70, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xff, 0xfe, 0x7e, 0x3f, 0x8f, 0x8e, 0x0e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd3, 0x53, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xdb, 0xda, 0x5a, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfc, 0xfb, 0x7b, 0x3f,
+  0x9d, 0x9c, 0x9c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x87, 0x86, 0x06, 0x3f,
+  0xe5, 0xe4, 0xe4, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xd1, 0xd0, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xfd, 0x7d, 0x3f, 0x87, 0x86, 0x06, 0x3f, 0xa1, 0xa0, 0xa0, 0x3c, 0x81, 0x80, 0x80, 0x3d,
+  0x98, 0x97, 0x17, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xbb, 0x3b, 0x3f,
+  0xa1, 0xa0, 0xa0, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x95, 0x94, 0x14, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x8d, 0x8c, 0x0c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0x40, 0x3c, 0x8c, 0x8b, 0x0b, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0xc0, 0x3c, 0xf1, 0xf0, 0x70, 0x3e,
+  0xe3, 0xe2, 0x62, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xa1, 0xa0, 0xa0, 0x3c, 0x89, 0x88, 0x08, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xf0, 0xef, 0x6f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf8, 0x78, 0x3e, 0x8a, 0x89, 0x09, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x98, 0x97, 0x17, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x98, 0x18, 0x3e, 0xea, 0xe9, 0x69, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0xc5, 0xc4, 0x44, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x8f, 0x8e, 0x0e, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xa6, 0xa5, 0x25, 0x3f, 0x85, 0x84, 0x04, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa1, 0xa0, 0xa0, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x85, 0x84, 0x84, 0x3e,
+  0xeb, 0xea, 0x6a, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xde, 0xdd, 0x5d, 0x3f, 0x81, 0x80, 0x00, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc1, 0xc0, 0xc0, 0x3d, 0x99, 0x98, 0x98, 0x3d, 0xed, 0xec, 0x6c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xad, 0xac, 0x2c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x84, 0x84, 0x3e,
+  0xea, 0xe9, 0x69, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xe9, 0xe8, 0xe8, 0x3e,
+  0x81, 0x80, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd5, 0xd4, 0x54, 0x3e, 0xc0, 0xbf, 0x3f, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xae, 0xad, 0x2d, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x90, 0x10, 0x3d,
+  0xb6, 0xb5, 0x35, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xcb, 0xca, 0x4a, 0x3f,
+  0xc9, 0xc8, 0xc8, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd1, 0xd0, 0x50, 0x3d, 0xaf, 0xae, 0x2e, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xf0, 0xef, 0x6f, 0x3f, 0xce, 0xcd, 0x4d, 0x3f, 0xc9, 0xc8, 0xc8, 0x3d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd0, 0x50, 0x3d,
+  0xad, 0xac, 0x2c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xde, 0xdd, 0x5d, 0x3f, 0xe7, 0xe6, 0xe6, 0x3e,
+  0xa9, 0xa8, 0xa8, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x91, 0x90, 0x10, 0x3d, 0xaf, 0xae, 0x2e, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xc1, 0xc0, 0xc0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xb6, 0xb5, 0x35, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xe9, 0xe8, 0xe8, 0x3e,
+  0x81, 0x80, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe1, 0xe0, 0xe0, 0x3c, 0x85, 0x84, 0x84, 0x3e, 0xf4, 0xf3, 0x73, 0x3f, 0x00, 0x00, 0x80, 0x3f,
+  0xdb, 0xda, 0x5a, 0x3f, 0x81, 0x80, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa1, 0xa0, 0x20, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xa5, 0xa4, 0x24, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xdf, 0xde, 0xde, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xb7, 0xb6, 0xb6, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x28, 0x3e,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x9f, 0x9e, 0x1e, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x28, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0x9f, 0x9e, 0x1e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x28, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0x9f, 0x9e, 0x1e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x8d, 0x8c, 0x8c, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x99, 0x98, 0x98, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xfa, 0xfa, 0x3e,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xa5, 0xa4, 0x24, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x28, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xa5, 0xa4, 0x24, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xbf, 0xbe, 0xbe, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xa5, 0xa4, 0x24, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xa1, 0xa0, 0x20, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xa5, 0xa4, 0x24, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xa0, 0x20, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xa5, 0xa4, 0x24, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xd0, 0xd0, 0x3d, 0xe2, 0xe1, 0x61, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xc1, 0xc0, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x99, 0x98, 0x98, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xf3, 0xf2, 0x72, 0x3f, 0x9d, 0x9c, 0x1c, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xa3, 0xa2, 0x22, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xc3, 0xc2, 0x42, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3d, 0xd0, 0xcf, 0x4f, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x8d, 0x8c, 0x0c, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xad, 0xac, 0xac, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xf1, 0xf0, 0x70, 0x3f, 0xf9, 0xf8, 0xf8, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xd3, 0xd2, 0x52, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xe9, 0xe8, 0x68, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0xe9, 0x69, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xf3, 0xf2, 0xf2, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe9, 0xe8, 0x68, 0x3e, 0xf7, 0xf6, 0x76, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xe9, 0xe8, 0x68, 0x3f, 0xc1, 0xc0, 0x40, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x98, 0x98, 0x3d,
+  0xc6, 0xc5, 0x45, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xa2, 0xa1, 0x21, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xc4, 0x44, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xd1, 0xd0, 0xd0, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x9b, 0x9a, 0x9a, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xf1, 0xf0, 0x70, 0x3f, 0xa1, 0xa0, 0x20, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf9, 0xf8, 0xf8, 0x3d, 0xd6, 0xd5, 0x55, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xcc, 0xcb, 0x4b, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x98, 0x97, 0x17, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xfb, 0xfa, 0x7a, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xcb, 0xca, 0x4a, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x97, 0x17, 0x3f,
+  0xfb, 0xfa, 0x7a, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xfb, 0xfa, 0x7a, 0x3f, 0xcb, 0xca, 0x4a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x97, 0x17, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xcb, 0xca, 0x4a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x99, 0x98, 0x18, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xcc, 0xcb, 0x4b, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x98, 0x97, 0x17, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xfb, 0xfa, 0x7a, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xcb, 0xca, 0x4a, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x97, 0x17, 0x3f,
+  0xfb, 0xfa, 0x7a, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xfb, 0xfa, 0x7a, 0x3f, 0xcb, 0xca, 0x4a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x97, 0x17, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xcb, 0xca, 0x4a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x99, 0x98, 0x18, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xcc, 0xcb, 0x4b, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xb7, 0xb6, 0xb6, 0x3e, 0xe8, 0xe7, 0x67, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xfb, 0xfa, 0x7a, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xf3, 0xf2, 0xf2, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xcb, 0xca, 0x4a, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f,
+  0xfb, 0xfa, 0x7a, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x83, 0x82, 0x02, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0x82, 0x81, 0x01, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xbb, 0xba, 0x3a, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x82, 0x81, 0x01, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x88, 0x88, 0x3e, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xf7, 0xf6, 0x76, 0x3f, 0xc1, 0xc0, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x81, 0x80, 0x00, 0x3e, 0xd2, 0xd1, 0x51, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xf4, 0xf3, 0x73, 0x3f,
+  0xab, 0xaa, 0xaa, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xb4, 0xb4, 0x3e,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xe3, 0xe2, 0x62, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 0xbe, 0x3e, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfb, 0xfa, 0xfa, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x91, 0x90, 0x90, 0x3e, 0xf5, 0xf4, 0x74, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xf9, 0xf8, 0x78, 0x3f,
+  0x9f, 0x9e, 0x9e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbc, 0x3c, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xff, 0xfe, 0xfe, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf8, 0x78, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0x89, 0x88, 0x88, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf9, 0xf8, 0x78, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0x89, 0x88, 0x88, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0xac, 0x2c, 0x3e,
+  0xfa, 0xf9, 0x79, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xc2, 0xc1, 0x41, 0x3f, 0x91, 0x90, 0x10, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbc, 0x3c, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0x95, 0x94, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x99, 0x98, 0x18, 0x3e, 0xf1, 0xf0, 0x70, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0x95, 0x94, 0x94, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa5, 0xa4, 0xa4, 0x3e, 0xf1, 0xf0, 0x70, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xc8, 0xc7, 0x47, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd0, 0xcf, 0x4f, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xf0, 0xef, 0x6f, 0x3f,
+  0x89, 0x88, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xcf, 0xce, 0xce, 0x3e, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xc5, 0xc4, 0x44, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xa9, 0xa8, 0x28, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x8b, 0x8a, 0x8a, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0xe8, 0xe8, 0x3e,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0x8e, 0x8d, 0x0d, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x00, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xeb, 0xea, 0x6a, 0x3f, 0x85, 0x84, 0x04, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x9f, 0x1f, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xb1, 0xb0, 0xb0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xad, 0xac, 0xac, 0x3e, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xa1, 0xa0, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc1, 0xc0, 0xc0, 0x3d, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xd4, 0xd3, 0x53, 0x3f,
+  0xd1, 0xd0, 0x50, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x80, 0x80, 0x3c, 0xa5, 0xa4, 0x24, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xa1, 0xa0, 0xa0, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc1, 0xc0, 0xc0, 0x3c, 0x81, 0x80, 0x80, 0x3e, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xa5, 0xa4, 0x24, 0x3f, 0xe1, 0xe0, 0x60, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc0, 0x40, 0x3e,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xee, 0xed, 0x6d, 0x3f, 0x85, 0x84, 0x04, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xdf, 0xde, 0xde, 0x3e, 0xdb, 0xda, 0x5a, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0x9f, 0x9e, 0x1e, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x9c, 0x1c, 0x3e,
+  0xdc, 0xdb, 0x5b, 0x3f, 0xfb, 0xfa, 0x7a, 0x3f, 0xef, 0xee, 0x6e, 0x3f, 0xb0, 0xaf, 0x2f, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0x98, 0x97, 0x17, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x91, 0x90, 0x10, 0x3e, 0xde, 0xdd, 0x5d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xe2, 0xe1, 0x61, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x86, 0x85, 0x05, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xd1, 0xd0, 0xd0, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x83, 0x82, 0x02, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xa4, 0xa3, 0x23, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x87, 0x86, 0x06, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0xcb, 0xca, 0x4a, 0x3f,
+  0xe1, 0xe0, 0x60, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0xc8, 0x48, 0x3f,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xec, 0xeb, 0x6b, 0x3f, 0xd9, 0xd8, 0x58, 0x3e, 0xc1, 0xc0, 0xc0, 0x3c,
+  0xb8, 0xb7, 0x37, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x92, 0x91, 0x11, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xdb, 0x5b, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xbb, 0xba, 0xba, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfc, 0x7c, 0x3e, 0xfd, 0xfc, 0x7c, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xd1, 0xd0, 0xd0, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xec, 0xeb, 0x6b, 0x3f, 0xec, 0xeb, 0x6b, 0x3f, 0xd9, 0xd8, 0x58, 0x3e,
+  0x91, 0x90, 0x10, 0x3d, 0xb5, 0xb4, 0x34, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f,
+  0xd1, 0xd0, 0x50, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xa9, 0xa8, 0x28, 0x3e, 0xa9, 0xa8, 0x28, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xd8, 0xd8, 0x3d,
+  0xfd, 0xfc, 0x7c, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xd1, 0xd0, 0x50, 0x3d,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa4, 0x24, 0x3e, 0xf4, 0xf3, 0x73, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xae, 0xad, 0x2d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xea, 0xe9, 0x69, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0xa8, 0x3d, 0x8f, 0x8e, 0x0e, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xdf, 0xde, 0xde, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xa9, 0xa8, 0xa8, 0x3d, 0xae, 0xad, 0x2d, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xa5, 0xa4, 0xa4, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xb7, 0x37, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0xb5, 0xb4, 0xb4, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe3, 0xe2, 0xe2, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xa5, 0xa4, 0xa4, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa4, 0xa4, 0x3e,
+  0xea, 0xe9, 0x69, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xea, 0xe9, 0x69, 0x3f, 0xdf, 0xde, 0xde, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe3, 0xe2, 0xe2, 0x3e, 0xfe, 0xfd, 0x7d, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xf7, 0xf6, 0xf6, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa4, 0x24, 0x3e,
+  0xea, 0xe9, 0x69, 0x3f, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x83, 0x82, 0x02, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xad, 0x2d, 0x3f, 0xff, 0xfe, 0x7e, 0x3f,
+  0xfe, 0xfd, 0x7d, 0x3f, 0xa5, 0xa4, 0xa4, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfd, 0xfc, 0x7c, 0x3f, 0xfe, 0xfd, 0x7d, 0x3f, 0x83, 0x82, 0x02, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+} // namespace data
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_NUMBERS_CLASSIFICATION_TASK_DATA_TRAIN_INPUT_H
diff --git a/onert-micro/onert-micro/include/train/tests/numbers_classification_task/data/train_target.h b/onert-micro/onert-micro/include/train/tests/numbers_classification_task/data/train_target.h
new file mode 100644 (file)
index 0000000..c3f01c4
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TESTS_NUMBERS_CLASSIFICATION_TASK_DATA_TRAIN_TARGET_H
+#define ONERT_MICRO_TRAIN_TESTS_NUMBERS_CLASSIFICATION_TASK_DATA_TRAIN_TARGET_H
+
+#include <vector>
+#include <cstring>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+namespace data
+{
+
+unsigned char numbers_classification_task_target_data[] = {
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f};
+unsigned int numbers_classification_task_target_size = 320;
+
+} // namespace data
+} // namespace test
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TESTS_NUMBERS_CLASSIFICATION_TASK_DATA_TRAIN_TARGET_H
diff --git a/onert-micro/onert-micro/include/train/train_optimizers/Adam.h b/onert-micro/onert-micro/include/train/train_optimizers/Adam.h
new file mode 100644 (file)
index 0000000..0e5ac4f
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TRAIN_OPTIMIZERS_ADAM_H
+#define ONERT_MICRO_TRAIN_TRAIN_OPTIMIZERS_ADAM_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeContext.h"
+
+#include <cstdint>
+#include <unordered_map>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace optimizers
+{
+
+/*
+ * Class to handle Adam optimizer
+ */
+class Adam
+{
+private:
+  // Save mapping between tensor index and internal state data with calculated exponent average
+  // squares
+  std::unordered_map<uint16_t, uint8_t *> _tensor_to_exponent_avg_squares;
+  // Save mapping between tensor index and internal state data with calculated exponent average
+  std::unordered_map<uint16_t, uint8_t *> _tensor_to_exponent_avg;
+  // Save mapping between tensor index and internal state data with calculated gradients
+  std::unordered_map<uint16_t, uint8_t *> _tensor_index_to_gradient;
+
+public:
+  Adam() = default;
+  Adam(const Adam &) = delete;
+  Adam(Adam &&) = delete;
+  Adam &operator=(const Adam &) = delete;
+  Adam &&operator=(const Adam &&) = delete;
+  ~Adam() { fullReset(); }
+
+  // Reset and deallocate all internal states
+  void fullReset();
+
+  // Reset only gradients
+  void reset();
+
+  // Check is contains current state or not
+  // Needed for saving checkpoints
+  bool isReset()
+  {
+    return _tensor_to_exponent_avg_squares.empty() or _tensor_to_exponent_avg.empty();
+  }
+
+  // Get exponent and exponent squares data be tensor index
+  uint8_t *getExponentAvgDataByTensorIndex(uint16_t tensor_index);
+  uint8_t *getExponentAvgSquaresDataByTensorIndex(uint16_t tensor_index);
+  // Set exponent and exponent squares data be tensor index
+  void setExponentAvgDataByTensorIndex(uint16_t tensor_index, uint8_t *data);
+  void setExponentAvgSquaresDataByTensorIndex(uint16_t tensor_index, uint8_t *data);
+
+  // Update internal states according to Adam theory
+  OMStatus handle(core::OMRuntimeStorage &backward_storage, core::OMRuntimeContext &context);
+
+  // Update weights according to Adam theory
+  OMStatus updateWeights(const OMTrainingContext &training_config, core::OMRuntimeContext &context);
+};
+
+} // namespace optimizers
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TRAIN_OPTIMIZERS_ADAM_H
diff --git a/onert-micro/onert-micro/include/train/train_optimizers/SGD.h b/onert-micro/onert-micro/include/train/train_optimizers/SGD.h
new file mode 100644 (file)
index 0000000..7b3f133
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TRAIN_TRAIN_OPTIMIZERS_SGD_H
+#define ONERT_MICRO_TRAIN_TRAIN_OPTIMIZERS_SGD_H
+
+#include "OMStatus.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeContext.h"
+
+#include <cstdint>
+#include <unordered_map>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace optimizers
+{
+
+/*
+ * Class to handle Adam optimizer
+ */
+class SGD
+{
+private:
+  // Save mapping between tensor index and internal state data with calculated gradients
+  std::unordered_map<uint16_t, uint8_t *> _tensor_index_to_gradient;
+
+public:
+  SGD() = default;
+  SGD(const SGD &) = delete;
+  SGD(SGD &&) = delete;
+  SGD &operator=(const SGD &) = delete;
+  SGD &&operator=(const SGD &&) = delete;
+  ~SGD() { reset(); }
+
+  // Reset and deallocate all internal states
+  void reset();
+
+  // Update internal states according to SGD theory
+  OMStatus handle(core::OMRuntimeStorage &backward_storage, core::OMRuntimeContext &context);
+
+  // Update weights according to SGD theory
+  OMStatus updateWeights(const OMTrainingContext &training_config, core::OMRuntimeContext &context);
+};
+
+} // namespace optimizers
+} // namespace train
+} // namespace onert_micro
+
+#endif // ONERT_MICRO_TRAIN_TRAIN_OPTIMIZERS_SGD_H
diff --git a/onert-micro/onert-micro/src/CMakeLists.txt b/onert-micro/onert-micro/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6c2d7a8
--- /dev/null
@@ -0,0 +1,77 @@
+#define core path
+set(OM_SOURCE_CORE_DIR "${OM_SOURCE_DIR}/core")
+set(OM_INCLUDE_CORE_DIR "${OM_INCLUDE_DIR}/core")
+#define execute path
+set(OM_SOURCE_EXECUTE_DIR "${OM_SOURCE_DIR}/execute")
+set(OM_INCLUDE_EXECUTE_DIR "${OM_INCLUDE_DIR}/execute")
+#define import path
+set(OM_SOURCE_IMPORT_DIR "${OM_SOURCE_DIR}/import")
+set(OM_INCLUDE_IMPORT_DIR "${OM_INCLUDE_DIR}/import")
+#define optimize path
+set(OM_SOURCE_OPTIMIZE_DIR "${OM_SOURCE_DIR}/optimize")
+set(OM_INCLUDE_OPTIMIZE_DIR "${OM_INCLUDE_DIR}/optimize")
+#define train path
+set(OM_SOURCE_TRAIN_DIR "${OM_SOURCE_DIR}/train")
+set(OM_INCLUDE_TRAIN_DIR "${OM_INCLUDE_DIR}/train")
+#define train path
+set(OM_SOURCE_DEV_DIR "${OM_SOURCE_DIR}/api")
+
+#OM_Interpreter lib binary name
+set(OM_INTERPRETER_LIB "onert_micro_interpreter")
+#OM_Training_Interpreter lib binary name
+set(OM_TRAINING_INTERPRETER_LIB "onert_micro_training_interpreter")
+#Core lib binary name
+set(OM_CORE_LIB "onert_micro_core${OM_SUFFIX}")
+#Execute lib binary name
+set(OM_EXECUTE_LIB "onert_micro_execute${OM_SUFFIX}")
+#Import lib binary name
+set(OM_IMPORT_LIB "onert_micro_import${OM_SUFFIX}")
+#Optimize lib binary name
+set(OM_OPTIMIZE_LIB "onert_micro_optimize${OM_SUFFIX}")
+#PAL lib binary name
+set(OM_PAL_LIB "onert_micro_pal${OM_SUFFIX}")
+#Train lib binary name
+set(OM_TRAIN_LIB "onert_micro_train${OM_SUFFIX}")
+#dev name
+set(OM_DEV_LIB "onert_micro_dev${OM_SUFFIX}")
+
+message(STATUS "ONERT MICRO BEGIN")
+
+#build core lib
+add_subdirectory(${OM_SOURCE_CORE_DIR})
+#build import lib
+add_subdirectory(${OM_SOURCE_IMPORT_DIR})
+#build execute lib
+add_subdirectory(${OM_SOURCE_EXECUTE_DIR})
+#build optimize lib
+add_subdirectory(${OM_SOURCE_OPTIMIZE_DIR})
+#build dev lib
+add_subdirectory(${OM_SOURCE_DEV_DIR})
+
+target_link_libraries(${OM_CORE_LIB} PUBLIC ${OM_CIRCLE_SCHEMA})
+target_link_libraries(${OM_CORE_LIB} PUBLIC ${OM_IMPORT_LIB})
+target_link_libraries(${OM_CORE_LIB} PUBLIC ${OM_EXECUTE_LIB})
+target_link_libraries(${OM_CORE_LIB} PUBLIC ${OM_OPTIMIZE_LIB})
+
+add_library(${OM_INTERPRETER_LIB} STATIC OMInterpreter.cpp)
+
+target_include_directories(${OM_INTERPRETER_LIB} PUBLIC "${OM_INCLUDE_DIR}")
+target_link_libraries(${OM_INTERPRETER_LIB} PUBLIC ${OM_CORE_LIB})
+
+# Training part
+message (STATUS "ONERT MICRO TRAINING BEGIN")
+
+#build train lib
+add_subdirectory(${OM_SOURCE_TRAIN_DIR})
+
+target_link_libraries(${OM_CORE_LIB} PUBLIC ${OM_TRAIN_LIB})
+
+add_library(${OM_TRAINING_INTERPRETER_LIB} STATIC OMTrainingInterpreter.cpp)
+
+target_include_directories(${OM_TRAINING_INTERPRETER_LIB} PUBLIC "${OM_INCLUDE_DIR}")
+target_link_libraries(${OM_TRAINING_INTERPRETER_LIB} PUBLIC ${OM_CORE_LIB})
+target_link_libraries(${OM_TRAINING_INTERPRETER_LIB} PUBLIC ${OM_TRAIN_LIB})
+
+message (STATUS "ONERT MICRO TRAINING END")
+
+message(STATUS "ONERT MICRO FINISHED")
diff --git a/onert-micro/onert-micro/src/OMInterpreter.cpp b/onert-micro/onert-micro/src/OMInterpreter.cpp
new file mode 100644 (file)
index 0000000..1e7ee42
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMInterpreter.h"
+
+using namespace onert_micro;
+
+OMStatus OMInterpreter::importModel(const char *model_ptr, const OMConfig &config)
+{
+  assert(model_ptr != nullptr && "Model ptr shouldn't be nullptr");
+  if (model_ptr == nullptr)
+    return UnknownError;
+
+  return _runtime_module.importModel(model_ptr, config);
+}
+
+OMStatus OMInterpreter::run() { return _runtime_module.run(); }
+
+OMStatus OMInterpreter::reset() { return _runtime_module.reset(); }
+
+uint32_t OMInterpreter::getNumberOfInputs() { return _runtime_module.getNumberOfInputs(); }
+
+uint32_t OMInterpreter::getNumberOfOutputs() { return _runtime_module.getNumberOfOutputs(); }
+
+void *OMInterpreter::getInputDataAt(uint32_t position)
+{
+  return _runtime_module.getInputDataAt(position);
+}
+
+void *OMInterpreter::getOutputDataAt(uint32_t position)
+{
+  return _runtime_module.getOutputDataAt(position);
+}
+
+uint32_t OMInterpreter::getInputSizeAt(uint32_t position)
+{
+  return _runtime_module.getInputSizeAt(position);
+}
+
+uint32_t OMInterpreter::getOutputSizeAt(uint32_t position)
+{
+  return _runtime_module.getOutputSizeAt(position);
+}
+
+OMStatus OMInterpreter::allocateInputs() { return _runtime_module.allocateInputs(); }
diff --git a/onert-micro/onert-micro/src/OMTrainingInterpreter.cpp b/onert-micro/onert-micro/src/OMTrainingInterpreter.cpp
new file mode 100644 (file)
index 0000000..e542090
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMTrainingInterpreter.h"
+
+#ifndef DIS_STREAM
+#include <fstream>
+#endif // DIS_STREAM
+
+using namespace onert_micro;
+
+OMStatus OMTrainingInterpreter::importTrainModel(char *model_ptr, const OMConfig &config)
+{
+  assert(model_ptr != nullptr && "Model ptr shouldn't be nullptr");
+  if (model_ptr == nullptr)
+    return UnknownError;
+
+  return _training_runtime_module.importTrainModel(model_ptr, config);
+}
+
+OMStatus OMTrainingInterpreter::trainSingleStep(OMConfig &config)
+{
+  return _training_runtime_module.trainSingleStep(config);
+}
+
+OMStatus OMTrainingInterpreter::reset() { return _training_runtime_module.reset(); }
+
+uint32_t OMTrainingInterpreter::getInputSizeAt(uint32_t position)
+{
+  return _training_runtime_module.getInputSizeAt(position);
+}
+
+uint32_t OMTrainingInterpreter::getOutputSizeAt(uint32_t position)
+{
+  return _training_runtime_module.getOutputSizeAt(position);
+}
+
+OMStatus OMTrainingInterpreter::saveModel(const OMConfig &config, const char *save_path)
+{
+  if (save_path == nullptr or config.model_size == 0 or config.model_ptr == nullptr)
+    return UnknownError;
+
+#ifndef DIS_STREAM
+  // Open or create file
+  // Note: if the file existed, it will be overwritten
+  std::ofstream out_file(save_path, std::ios::binary | std::ios::trunc);
+  if (not out_file.is_open())
+    return UnknownError;
+
+  // Write data
+  out_file.write(config.model_ptr, config.model_size);
+
+  // Close file
+  out_file.close();
+#else
+  assert(false && "Not supported");
+  return UnknownError;
+#endif // DIS_STREAM
+
+  // Saving done
+  return Ok;
+}
+
+OMStatus OMTrainingInterpreter::loadCheckpoint(OMConfig &config, const char *load_path)
+{
+  // Not imported or path is empty
+  if (load_path == nullptr or config.model_ptr == nullptr or config.model_size == 0)
+    return UnknownError;
+
+  // Get DataBuffer (vector of chars) of checkpoints
+  std::vector<char> checkpoint_data;
+
+  // Read data
+#ifndef DIS_STREAM
+  std::ifstream file(load_path, std::ios::binary | std::ios::in);
+  if (!file.good())
+  {
+    assert(false && "Fail to open");
+    return UnknownError;
+  }
+
+  file.seekg(0, std::ios::end);
+  auto fileSize = file.tellg();
+  file.seekg(0, std::ios::beg);
+
+  // reserve capacity
+  checkpoint_data.resize(fileSize);
+
+  // read the data
+  file.read(checkpoint_data.data(), fileSize);
+  if (file.fail())
+  {
+    assert(false && "Fail to read");
+    return UnknownError;
+  }
+#else
+  assert(false && "Not supported");
+  return UnknownError;
+#endif // DIS_STREAM
+
+  // Load data
+  OMStatus status = _training_runtime_module.loadCheckpointData(config, checkpoint_data.data());
+
+  return status;
+}
+
+OMStatus OMTrainingInterpreter::saveCheckpoint(const OMConfig &config, const char *save_path)
+{
+  // Not imported or path is empty
+  if (save_path == nullptr or config.model_ptr == nullptr or config.model_size == 0)
+    return UnknownError;
+
+  // Get DataBuffer (vector of chars) of checkpoints
+  std::vector<char> checkpoint_data;
+
+  OMStatus status = _training_runtime_module.createCheckpointFile(config, checkpoint_data);
+
+  assert(status == Ok);
+  if (status != Ok)
+    return status;
+
+    // Save it into save_path
+#ifndef DIS_STREAM
+  // Open or create file
+  // Note: if the file existed, it will be overwritten
+  std::ofstream out_file(save_path, std::ios::binary | std::ios::trunc);
+  if (not out_file.is_open())
+    return UnknownError;
+
+  // Write data
+  out_file.write(checkpoint_data.data(), checkpoint_data.size());
+
+  // Close file
+  out_file.close();
+#else
+  assert(false && "Not supported");
+  return UnknownError;
+#endif // DIS_STREAM
+
+  return Ok;
+}
+
+void *OMTrainingInterpreter::getInputDataAt(uint32_t position)
+{
+  return _training_runtime_module.getInputDataAt(position);
+}
+
+void *OMTrainingInterpreter::getOutputDataAt(uint32_t position)
+{
+  return _training_runtime_module.getOutputDataAt(position);
+}
+
+void *OMTrainingInterpreter::getInputData(uint32_t position)
+{
+  return _training_runtime_module.getInputData(position);
+}
diff --git a/onert-micro/onert-micro/src/api/CMakeLists.txt b/onert-micro/onert-micro/src/api/CMakeLists.txt
new file mode 100644 (file)
index 0000000..98baf6e
--- /dev/null
@@ -0,0 +1,14 @@
+message(STATUS "ONERT MICRO DEV BUILD BEGIN")
+
+set(SOURCES
+    onert-micro.cpp)
+
+add_library(${OM_DEV_LIB} STATIC ${SOURCES})
+target_compile_options(${OM_DEV_LIB} PRIVATE "-fexceptions")
+target_link_libraries(${OM_DEV_LIB} PUBLIC ${OM_TRAININFO_SCHEMA})
+target_include_directories(${OM_DEV_LIB} PUBLIC "${OM_INCLUDE_DIR}")
+target_link_libraries(${OM_DEV_LIB} PUBLIC ${OM_INTERPRETER_LIB})
+target_link_libraries(${OM_DEV_LIB} PUBLIC ${OM_TRAINING_INTERPRETER_LIB})
+target_link_libraries(${OM_DEV_LIB} PUBLIC onert_micro_coverage)
+
+message(STATUS "ONERT MICRO DEV BUILD FINISHED")
diff --git a/onert-micro/onert-micro/src/api/onert-micro.cpp b/onert-micro/onert-micro/src/api/onert-micro.cpp
new file mode 100644 (file)
index 0000000..538529b
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <string>
+#include <memory>
+#include <thread>
+#include <vector>
+#include <iostream>
+#include <fstream>
+
+#include "OMTrainingInterpreter.h"
+#include "onert-micro.h"
+#include <circle-generated/circle/schema_generated.h>
+#include <circle-generated/circle/traininfo_generated.h>
+
+#define NNFW_RETURN_ERROR_IF_NULL(p)      \
+  do                                      \
+  {                                       \
+    if ((p) == NULL)                      \
+      return NNFW_STATUS_UNEXPECTED_NULL; \
+  } while (0)
+
+// helper for file processing
+using DataBuffer = std::vector<char>;
+
+DataBuffer readFile(const char *path)
+{
+  std::ifstream file(path, std::ios::binary | std::ios::in);
+  if (!file.good())
+  {
+    std::string errmsg = "Failed to open file";
+    std::cerr << errmsg << std::endl;
+    exit(-1); // FIXME: proper way
+  }
+
+  file.seekg(0, std::ios::end);
+  auto fileSize = file.tellg();
+  file.seekg(0, std::ios::beg);
+
+  // reserve capacity
+  DataBuffer model_data(fileSize);
+
+  // read the data
+  file.read(model_data.data(), fileSize);
+  if (file.fail())
+  {
+    std::string errmsg = "Failed to read file";
+    std::cerr << errmsg << std::endl;
+    exit(-1); // FIXME: proper way
+  }
+
+  return model_data;
+}
+
+struct nnfw_session
+{
+private:
+public:
+  /**
+   * @brief Factory method. It creates and initialize nnfw_session
+   *
+   * @note  Use factory instead of constructor to get status
+   */
+  static NNFW_STATUS create(nnfw_session **session);
+
+private:
+  nnfw_session();
+
+public:
+  ~nnfw_session();
+
+  NNFW_STATUS load_model_from_file(const char *package_file_path);
+
+  NNFW_STATUS train_set_traininfo(const nnfw_train_info *info);
+  NNFW_STATUS train_prepare();
+  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, void *input);
+  NNFW_STATUS train_set_expected(uint32_t index, void *expected);
+  NNFW_STATUS train_set_output(uint32_t index, NNFW_TYPE type, void *buffer, size_t length);
+  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);
+
+  NNFW_STATUS train_export_checkpoint(const char *path);
+  NNFW_STATUS train_import_checkpoint(const char *path);
+
+private:
+  uint32_t getInputSize();
+  uint32_t getOutputSize();
+  NNFW_STATUS loadTrainingInfo(char *buf_ptr);
+  NNFW_STATUS loadOptimizerInfo(const circle::ModelTraining *circle_model);
+  NNFW_STATUS loadLossInfo(const circle::ModelTraining *circle_model);
+  NNFW_STATUS loadTrainableOps(const circle::ModelTraining *circle_model, int num_ops);
+
+private:
+  onert_micro::OMTrainingInterpreter *_train_interpreter;
+  onert_micro::OMConfig _config;
+  DataBuffer _model_buf;
+  std::string _model_path;
+  uint8_t *outputbuf;
+};
+
+nnfw_session::nnfw_session() : _train_interpreter{new onert_micro::OMTrainingInterpreter()}
+{
+  // TODO: Remove after implementing train_set_traininfo
+  // Set user defined training settings
+  const uint32_t training_epochs = 10;
+  const float learning_rate = 0.001f;
+  const uint32_t num_train_layers = 10;
+  const onert_micro::OMLoss loss = onert_micro::CROSS_ENTROPY;
+  const onert_micro::OMTrainOptimizer train_optim = onert_micro::ADAM;
+  const float beta = 0.9;
+  const float beta_squares = 0.999;
+  const float epsilon = 1e-07;
+
+  _config.train_mode = true;
+  {
+    onert_micro::OMTrainingContext train_context;
+    train_context.batch_size = 32;
+    train_context.num_of_train_layers = num_train_layers;
+    train_context.learning_rate = learning_rate;
+    train_context.loss = loss;
+    train_context.optimizer = train_optim;
+    train_context.beta = beta;
+    train_context.beta_squares = beta_squares;
+    train_context.epsilon = epsilon;
+    train_context.num_step = 0;
+
+    _config.training_context = train_context;
+  }
+
+  outputbuf = nullptr;
+}
+
+NNFW_STATUS nnfw_session::create(nnfw_session **session)
+{
+  if (session == nullptr)
+    return NNFW_STATUS_UNEXPECTED_NULL;
+
+  auto new_session = std::unique_ptr<nnfw_session>(new nnfw_session());
+  *session = new_session.release();
+
+  if (*session == nullptr)
+  {
+    return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+nnfw_session::~nnfw_session() { delete _train_interpreter; }
+
+NNFW_STATUS nnfw_session::loadOptimizerInfo(const circle::ModelTraining *circle_model)
+{
+  assert(circle_model != nullptr);
+
+  const circle::Optimizer circle_opt = circle_model->optimizer();
+
+  switch (circle_opt)
+  {
+    case circle::Optimizer_SGD:
+      _config.training_context.optimizer = onert_micro::SGD;
+      _config.training_context.learning_rate =
+        circle_model->optimizer_opt_as_SGDOptions()->learning_rate();
+      break;
+    case circle::Optimizer_ADAM:
+      _config.training_context.optimizer = onert_micro::ADAM;
+      _config.training_context.learning_rate =
+        circle_model->optimizer_opt_as_AdamOptions()->learning_rate();
+      _config.training_context.beta = circle_model->optimizer_opt_as_AdamOptions()->beta_1();
+      _config.training_context.beta_squares =
+        circle_model->optimizer_opt_as_AdamOptions()->beta_2();
+      _config.training_context.epsilon = circle_model->optimizer_opt_as_AdamOptions()->epsilon();
+      break;
+    default:
+      std::cerr << "unknown optimzer" << std::endl;
+      return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::loadLossInfo(const circle::ModelTraining *circle_model)
+{
+  assert(circle_model != nullptr);
+  NNFW_RETURN_ERROR_IF_NULL(circle_model);
+
+  const circle::LossFn circle_loss = circle_model->lossfn();
+
+  switch (circle_loss)
+  {
+    case circle::LossFn::LossFn_CATEGORICAL_CROSSENTROPY:
+      _config.training_context.loss = onert_micro::CROSS_ENTROPY;
+      break;
+    case circle::LossFn::LossFn_MEAN_SQUARED_ERROR:
+      _config.training_context.loss = onert_micro::MSE;
+      break;
+    case circle::LossFn::LossFn_SPARSE_CATEGORICAL_CROSSENTROPY:
+      // TODO enable this conversion after core support sparse_categorial_crossentropy
+      std::cerr << "'sparse_categorical_crossentropy' is not supported yet" << std::endl;
+      return NNFW_STATUS_ERROR;
+    default:
+      std::cerr << "unknown loss function" << std::endl;
+      return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::loadTrainableOps(const circle::ModelTraining *circle_model, int num_ops)
+{
+  assert(circle_model != nullptr);
+  NNFW_RETURN_ERROR_IF_NULL(circle_model);
+
+  auto ops_list = circle_model->trainable_ops();
+  if (ops_list != nullptr)
+    _config.training_context.num_of_train_layers =
+      num_ops - ops_list->data()[0]; // simply assume ops[0] is the least node number
+  else
+    _config.training_context.num_of_train_layers = num_ops;
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::loadTrainingInfo(char *buf)
+{
+  auto model = circle::GetModel(buf);
+  auto num_ops = model->subgraphs()->Get(0)->operators()->size();
+  // Load Metadata
+  auto const metadata_list = model->metadata();
+  const uint8_t *data = nullptr;
+  if (metadata_list != nullptr)
+  {
+    for (uint32_t i = 0; i < metadata_list->size(); ++i)
+    {
+      const auto metadata = metadata_list->Get(i);
+      if (strcmp(metadata->name()->c_str(), "CIRCLE_TRAINING") != 0)
+        continue;
+      data = (model->buffers()->Get(metadata->buffer()))->data()->data();
+    }
+    NNFW_RETURN_ERROR_IF_NULL(data);
+
+    const circle::ModelTraining *traininfo_model =
+      circle::GetModelTraining(static_cast<const void *>(data));
+    _config.training_context.batch_size = traininfo_model->batch_size();
+    NNFW_STATUS status = loadOptimizerInfo(traininfo_model);
+    if (status != NNFW_STATUS_NO_ERROR)
+      return status;
+
+    status = loadLossInfo(traininfo_model);
+    if (status != NNFW_STATUS_NO_ERROR)
+      return status;
+
+    status = loadTrainableOps(traininfo_model, num_ops);
+    if (status != NNFW_STATUS_NO_ERROR)
+      return status;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::load_model_from_file(const char *file_path)
+{
+  _model_buf = readFile(file_path);
+  _config.model_ptr = _model_buf.data();
+  _config.model_size = _model_buf.size();
+  // load training info
+  loadTrainingInfo(_config.model_ptr);
+  // TODO: this import should start on nnfw_prepare if inference_interpreter is introduced
+  _train_interpreter->importTrainModel(_config.model_ptr, _config);
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_prepare()
+{
+  // TODO: Implement remaining jobs if inference_interpreter is introduced
+  // maybe interpreter initialization ?
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_run(bool update_weights)
+{
+  if (update_weights)
+  {
+    // TOOD: micro support update_weights ???
+    // Here we use this flag for distinguish inference and train in trainaing interpreter
+    _train_interpreter->trainSingleStep(_config);
+    _config.training_context.num_epoch =
+      _config.training_context.num_step / _config.training_context.batch_size + 1;
+  }
+  else
+  {
+    // TODO: support multiple input/output
+    assert(outputbuf != nullptr);
+    _train_interpreter->allocateInputs();
+    float *allocated_input_data = (float *)_train_interpreter->getInputDataAt(0);
+    float *user_input_data = (float *)_train_interpreter->getInputData(0);
+    memcpy(allocated_input_data, user_input_data,
+           sizeof(float) * _train_interpreter->getInputSizeAt(0));
+    _train_interpreter->run();
+    float *calculated_ptr = (float *)_train_interpreter->getOutputDataAt(0);
+    memcpy(outputbuf, calculated_ptr, sizeof(float) * _train_interpreter->getOutputSizeAt(0));
+    _train_interpreter->reset();
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_export_circle(const char *path)
+{
+  _train_interpreter->saveModel(_config, path);
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_export_checkpoint(const char *path)
+{
+  _train_interpreter->saveCheckpoint(_config, path);
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_import_checkpoint(const char *path)
+{
+  _train_interpreter->loadCheckpoint(_config, path);
+  return NNFW_STATUS_NO_ERROR;
+}
+
+// TODO: onert's this function takes const type input
+NNFW_STATUS nnfw_session::train_set_input(uint32_t index, void *input)
+{
+  _train_interpreter->setInput((uint8_t *)input, index);
+  return NNFW_STATUS_NO_ERROR;
+}
+
+// TODO: onert's this function takes const type expected
+NNFW_STATUS nnfw_session::train_set_expected(uint32_t index, void *expected)
+{
+  _train_interpreter->setTarget((uint8_t *)expected, index);
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_set_output(uint32_t index, NNFW_TYPE type, void *buffer,
+                                           size_t length)
+{
+  outputbuf = (uint8_t *)buffer;
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_set_traininfo(const nnfw_train_info *info)
+{
+  _config.training_context.learning_rate = info->learning_rate;
+  _config.training_context.batch_size = info->batch_size;
+  _config.training_context.optimizer =
+    (info->opt == NNFW_TRAIN_OPTIMIZER_ADAM) ? onert_micro::ADAM : onert_micro::SGD;
+  _config.training_context.beta = info->adam_opt.beta;
+  _config.training_context.beta_squares = info->adam_opt.beta2;
+  _config.training_context.beta = info->adam_opt.epsilon;
+  _config.training_context.num_of_train_layers = info->num_trainble_ops;
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_get_loss(uint32_t index, float *loss)
+{
+  onert_micro::OMMetrics m;
+  switch (_config.training_context.loss)
+  {
+    case onert_micro::CROSS_ENTROPY:
+      m = onert_micro::CROSS_ENTROPY_METRICS;
+      break;
+    default:
+      m = onert_micro::CROSS_ENTROPY_METRICS;
+      break;
+  }
+
+  _train_interpreter->evaluateMetric(m, reinterpret_cast<void *>(loss),
+                                     _config.training_context.batch_size);
+  return NNFW_STATUS_NO_ERROR;
+}
+
+// onert-micr.h implementation
+
+NNFW_STATUS nnfw_create_session(nnfw_session **session) { return nnfw_session::create(session); }
+
+NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *package_file_path)
+{
+  return session->load_model_from_file(package_file_path);
+}
+
+NNFW_STATUS nnfw_train_prepare(nnfw_session *session) { return session->train_prepare(); }
+
+NNFW_STATUS nnfw_train(nnfw_session *session, bool update_weights)
+{
+  return session->train_run(update_weights);
+}
+
+NNFW_STATUS nnfw_train_export_circle(nnfw_session *session, const char *path)
+{
+  return session->train_export_circle(path);
+}
+
+NNFW_STATUS nnfw_train_export_checkpoint(nnfw_session *session, const char *path)
+{
+  return session->train_export_checkpoint(path);
+}
+
+NNFW_STATUS nnfw_train_import_checkpoint(nnfw_session *session, const char *path)
+{
+  return session->train_import_checkpoint(path);
+}
+
+NNFW_STATUS nnfw_train_set_input(nnfw_session *session, uint32_t index, void *input,
+                                 const nnfw_tensorinfo *input_info)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->train_set_input(index, input);
+}
+
+NNFW_STATUS nnfw_train_set_expected(nnfw_session *session, uint32_t index, void *expected,
+                                    const nnfw_tensorinfo *expected_info)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->train_set_expected(index, expected);
+}
+
+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_set_traininfo(nnfw_session *session, const nnfw_train_info *info)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->train_set_traininfo(info);
+}
+
+NNFW_STATUS nnfw_train_set_output(nnfw_session *session, uint32_t index, NNFW_TYPE type,
+                                  void *buffer, size_t length)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->train_set_output(index, type, buffer, length);
+}
diff --git a/onert-micro/onert-micro/src/core/CMakeLists.txt b/onert-micro/onert-micro/src/core/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4ed5c11
--- /dev/null
@@ -0,0 +1,26 @@
+message(STATUS "ONERT MICRO CORE BUILD BEGIN")
+
+set(SOURCES
+        OMKernelType.cpp
+        OMRuntimeContext.cpp
+        OMRuntimeStorage.cpp
+        OMTrainingRuntimeModule.cpp
+        OMRuntimeGraph.cpp
+        OMRuntimeModule.cpp
+        OMUtils.cpp
+        OMDataType.cpp
+        train/OMTrainingHandler.cpp
+        train/OMTrainingStorage.cpp
+        train/OMCheckpointSaver.cpp
+        train/OMCheckpointLoader.cpp
+        memory/OMMemoryManager.cpp
+        memory/OMRuntimeAllocator.cpp
+        reader/OMCircleReader.cpp
+        reader/OMWeightOnlyFormatReader.cpp)
+
+add_library(${OM_CORE_LIB} STATIC ${SOURCES})
+
+target_include_directories(${OM_CORE_LIB} PUBLIC "${OM_INCLUDE_DIR}")
+target_include_directories(${OM_CORE_LIB} PUBLIC "${GENERATED_INCLUDE_DIR}")
+
+message(STATUS "ONERT MICRO CORE BUILD FINISHED")
diff --git a/onert-micro/onert-micro/src/core/OMDataType.cpp b/onert-micro/onert-micro/src/core/OMDataType.cpp
new file mode 100644 (file)
index 0000000..b0d4a6c
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMDataType.h"
+
+onert_micro::core::OMDataType onert_micro::core::onertMicroDatatype(const circle::TensorType type)
+{
+  switch (type)
+  {
+    case circle::TensorType_FLOAT32:
+      return OMDataType::FLOAT32;
+    case circle::TensorType_FLOAT16:
+      return OMDataType::FLOAT16;
+    case circle::TensorType_INT32:
+      return OMDataType::S32;
+    case circle::TensorType_UINT8:
+      return OMDataType::U8;
+    case circle::TensorType_INT64:
+      return OMDataType::S64;
+    case circle::TensorType_BOOL:
+      return OMDataType::BOOL;
+    case circle::TensorType_INT16:
+      return OMDataType::S16;
+    case circle::TensorType_COMPLEX64:
+      break;
+    case circle::TensorType_INT8:
+      return OMDataType::S8;
+    default:
+      break;
+  }
+  assert(false);
+  return OMDataType::Unknown;
+}
diff --git a/onert-micro/onert-micro/src/core/OMKernelType.cpp b/onert-micro/onert-micro/src/core/OMKernelType.cpp
new file mode 100644 (file)
index 0000000..7256b54
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMKernelType.h"
+
+using namespace onert_micro::core;
+using namespace onert_micro;
+
+OMStatus onert_micro::core::getBuiltinOperatorBuilderId(const circle::BuiltinOperator &opcode,
+                                                        core::OMBuilderID &builderID)
+{
+  switch (opcode)
+  {
+#define REGISTER_KERNEL(builtin_operator, name)                        \
+  case circle::BuiltinOperator_##builtin_operator:                     \
+    builderID = core::OMBuilderID::BuiltinOperator_##builtin_operator; \
+    break;
+#include "KernelsToBuild.lst"
+#undef REGISTER_KERNEL
+    default:
+      assert(false && "Unsupported operation");
+      return UnsupportedOp;
+  }
+  return Ok;
+}
+
+OMStatus onert_micro::core::getCustomOperatorByBuilderId(core::OMBuilderID &builderID,
+                                                         OMBuilderCustomID &opcode)
+{
+  switch (builderID)
+  {
+#define REGISTER_CUSTOM_KERNEL(name, string_name)    \
+  case core::OMBuilderID::CUSTOM_##name:             \
+    opcode = core::OMBuilderCustomID::CUSTOM_##name; \
+    break;
+#include "CustomKernelsToBuild.lst"
+#undef REGISTER_CUSTOM_KERNEL
+    default:
+      assert(false && "Unsupported operation");
+      return UnsupportedOp;
+  }
+  return Ok;
+}
+
+OMStatus onert_micro::core::getBuilderId(const circle::OperatorCode *opcode,
+                                         core::OMBuilderID &builderID)
+{
+  OMStatus status;
+
+  if (opcode->builtin_code() == circle::BuiltinOperator_CUSTOM)
+    status = core::getCustomOperatorBuilderId(opcode->custom_code(), builderID);
+  else
+    status = core::getBuiltinOperatorBuilderId(opcode->builtin_code(), builderID);
+
+  assert(status == Ok && "Unknown operation");
+  if (status == UnsupportedOp or builderID == core::OMBuilderID::Size)
+    return UnsupportedOp;
+
+  return status;
+}
+
+OMStatus onert_micro::core::getCustomOperatorBuilderId(const flatbuffers::String *custom_opcode,
+                                                       core::OMBuilderID &builderID)
+{
+#define REGISTER_CUSTOM_KERNEL(name, string_name)    \
+  const char arr[] = string_name;                    \
+  if (std::strcmp(custom_opcode->c_str(), arr) == 0) \
+  {                                                  \
+    builderID = core::OMBuilderID::CUSTOM_##name;    \
+    return Ok;                                       \
+  }
+#include "CustomKernelsToBuild.lst"
+#undef REGISTER_CUSTOM_KERNEL
+  assert(false && "Unsupported custom operation");
+  return UnsupportedOp;
+}
diff --git a/onert-micro/onert-micro/src/core/OMRuntimeContext.cpp b/onert-micro/onert-micro/src/core/OMRuntimeContext.cpp
new file mode 100644 (file)
index 0000000..e746d4c
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMRuntimeContext.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+const circle::Operator *OMRuntimeContext::getCircleOperatorAt(uint16_t index)
+{
+  const auto *operators = _reader.operators();
+
+  return operators->operator[](index);
+}
+
+const reader::CircleOperators *OMRuntimeContext::getCircleOperators()
+{
+  return _reader.operators();
+}
+
+const circle::Tensor *OMRuntimeContext::getTensorByIndex(int32_t tensor_index)
+{
+  if (tensor_index == -1)
+    return nullptr;
+  return _reader.tensors()->operator[](tensor_index);
+}
+
+uint32_t OMRuntimeContext::getGraphInputTensorIndex(uint32_t index)
+{
+  auto *inputs = _reader.inputs();
+  return inputs->operator[](index);
+}
+
+uint32_t OMRuntimeContext::getGraphOutputTensorIndex(uint32_t index)
+{
+  auto *outputs = _reader.outputs();
+  return outputs->operator[](index);
+}
+
+OMStatus OMRuntimeContext::getConstDataByTensorIndex(uint8_t **data, uint16_t tensor_index)
+{
+  auto *tensor = getTensorByIndex(tensor_index);
+
+  if (tensor == nullptr)
+    return UnknownError;
+
+  // To handle with separated weights:
+  // 1) first we try to get weigths from wof file (using wof_reader)
+  // 2) If it is not null -> return it
+  // 3) It it is null try to get it from main circle file
+  uint8_t *buffer_data = reinterpret_cast<uint8_t *>(_wof_reader.buffer(tensor_index));
+
+  if (buffer_data != nullptr)
+  {
+    *data = buffer_data;
+    return Ok;
+  }
+
+  auto const *buffer = _reader.buffers()->operator[](tensor->buffer())->data();
+
+  if (buffer == nullptr)
+    return Ok;
+
+  *data = const_cast<uint8_t *>(buffer->data());
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/core/OMRuntimeGraph.cpp b/onert-micro/onert-micro/src/core/OMRuntimeGraph.cpp
new file mode 100644 (file)
index 0000000..1d7fb20
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMRuntimeGraph.h"
+#include "core/OMDataType.h"
+#include "OMStatus.h"
+
+using namespace onert_micro::core;
+using namespace onert_micro;
+
+OMStatus OMRuntimeGraph::reset()
+{
+  OMStatus status = _allocator.clearAllTensorsData(&_context, &_storage);
+  _storage.clearTensorIndexToData();
+
+  return status;
+}
+
+OMRuntimeGraph::~OMRuntimeGraph() { reset(); }
+
+void *OMRuntimeGraph::getInputDataAt(uint32_t position)
+{
+  const auto input_index = _context.getGraphInputTensorIndex(position);
+
+  uint8_t *data;
+  _storage.getDataByTensorIndex(&data, input_index);
+
+  if (data == nullptr)
+  {
+    _allocator.allocateGraphInputs(&_context, &_storage);
+    _storage.getDataByTensorIndex(&data, input_index);
+  }
+
+  return reinterpret_cast<void *>(data);
+}
+
+void *OMRuntimeGraph::getOutputDataAt(uint32_t position)
+{
+  const auto output_index = _context.getGraphOutputTensorIndex(position);
+
+  uint8_t *data;
+  _storage.getDataByTensorIndex(&data, output_index);
+  return reinterpret_cast<void *>(data);
+}
+
+OMStatus OMRuntimeGraph::allocateGraphInputs()
+{
+  return _allocator.allocateGraphInputs(&_context, &_storage);
+}
+
+uint32_t OMRuntimeGraph::getOutputSizeAt(uint32_t position)
+{
+  const auto output_index = _context.getGraphOutputTensorIndex(position);
+  const circle::Tensor *output_tensor = _context.getTensorByIndex(output_index);
+
+  OMRuntimeShape shape(output_tensor);
+  return shape.flatSize();
+}
+
+size_t OMRuntimeGraph::getInputDataTypeSize(uint32_t position)
+{
+  const auto input_index = _context.getGraphInputTensorIndex(position);
+  const circle::Tensor *input_tensor = _context.getTensorByIndex(static_cast<int32_t>(input_index));
+
+  auto type = input_tensor->type();
+  return sizeof(OMDataType(type));
+}
+
+size_t OMRuntimeGraph::getOutputDataTypeSize(uint32_t position)
+{
+  const auto output_index = _context.getGraphOutputTensorIndex(position);
+  const circle::Tensor *output_tensor =
+    _context.getTensorByIndex(static_cast<int32_t>(output_index));
+
+  auto type = output_tensor->type();
+  return sizeof(OMDataType(type));
+}
+
+uint32_t OMRuntimeGraph::getInputSizeAt(uint32_t position)
+{
+  const auto input_index = _context.getGraphInputTensorIndex(position);
+  const circle::Tensor *input_tensor = _context.getTensorByIndex(input_index);
+
+  OMRuntimeShape shape(input_tensor);
+  return shape.flatSize();
+}
+
+uint32_t OMRuntimeGraph::getNumberOfOutputs()
+{
+  auto *outputs = _context.getCircleOutputs();
+  if (outputs == nullptr)
+    return 0;
+
+  return outputs->size();
+}
+
+uint32_t OMRuntimeGraph::getNumberOfInputs()
+{
+  auto *inputs = _context.getCircleInputs();
+  if (inputs == nullptr)
+    return 0;
+
+  return inputs->size();
+}
diff --git a/onert-micro/onert-micro/src/core/OMRuntimeModule.cpp b/onert-micro/onert-micro/src/core/OMRuntimeModule.cpp
new file mode 100644 (file)
index 0000000..166d2e8
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMRuntimeModule.h"
+#include "optimize/OMOptimizer.h"
+#include "import/OMExecutionPlanCreator.h"
+#include "import/OMKernelConfiguration.h"
+#include "import/OMConfigureArgs.h"
+#include "execute/OMKernelExecute.h"
+
+using namespace onert_micro::core;
+using namespace onert_micro;
+
+uint32_t OMRuntimeModule::getNumberOfInputs() { return _graphs.at(0).getNumberOfInputs(); }
+
+uint32_t OMRuntimeModule::getNumberOfOutputs() { return _graphs.at(0).getNumberOfOutputs(); }
+
+uint32_t OMRuntimeModule::getInputSizeAt(uint32_t position)
+{
+  return _graphs.at(0).getInputSizeAt(position);
+}
+
+uint32_t OMRuntimeModule::getOutputSizeAt(uint32_t position)
+{
+  return _graphs.at(0).getOutputSizeAt(position);
+}
+
+void *OMRuntimeModule::getInputDataAt(uint32_t position)
+{
+  return _graphs.at(0).getInputDataAt(position);
+}
+
+void *OMRuntimeModule::getOutputDataAt(uint32_t position)
+{
+  return _graphs.at(0).getOutputDataAt(position);
+}
+
+OMStatus OMRuntimeModule::importModel(const char *model_ptr, const OMConfig &config)
+{
+  assert(model_ptr != nullptr && "Model ptr shouldn't be nullptr");
+  if (model_ptr == nullptr)
+    return UnknownError;
+
+  // 1 - parse reader
+  // 2 - load default graph
+  // 3 - optimize it until can
+  // 4 - AllocDeallocPlan creation
+  // 5 - KernelConfigure
+  // 6 - Allocate inputs
+
+  OMStatus status;
+  // First - parse reader
+  uint32_t num_subgraph = 0;
+  {
+    reader::OMCircleReader reader;
+    status = reader.parse(model_ptr);
+    if (status != Ok)
+      return status;
+    num_subgraph = reader.num_subgraph();
+  }
+
+  assert(num_subgraph >= 1);
+  if (num_subgraph == 0)
+    return UnknownError;
+
+  _graphs.resize(num_subgraph);
+
+  for (uint32_t i = 0; i < num_subgraph; ++i)
+  {
+    // Second - load default graph
+    OMRuntimeGraph &graph = _graphs.at(i);
+
+    OMRuntimeContext &runtime_context = graph.getRuntimeContext();
+    OMRuntimeStorage &runtime_storage = graph.getRuntimeStorage();
+    memory::OMRuntimeAllocator &runtime_allocator = graph.getRuntimeAllocator();
+
+    runtime_context.setModel(model_ptr, i);
+
+    // Parse and validate WOF file if it is exist
+    // WARNING: setWofFile method of RuntimeContext should follow after setModel.
+    if (config.wof_ptr != nullptr)
+      runtime_context.setWofFile(config.wof_ptr);
+
+    // Third - optimize it until can
+    status = optimize::OMOptimizer::optimize(runtime_storage, runtime_context, config);
+    if (status != Ok)
+      return status;
+
+    // 4 - AllocDeallocPlan creation
+    import::OMExecutionPlanCreator::createExecutionPlan(runtime_storage, runtime_context,
+                                                        runtime_allocator, config);
+  }
+  for (uint32_t i = 0; i < num_subgraph; ++i)
+  {
+    // Second - load default graph
+    OMRuntimeGraph &graph = _graphs.at(i);
+
+    OMRuntimeContext &runtime_context = graph.getRuntimeContext();
+    OMRuntimeStorage &runtime_storage = graph.getRuntimeStorage();
+    memory::OMRuntimeAllocator &runtime_allocator = graph.getRuntimeAllocator();
+    // 5 - KernelConfigure
+    import::OMConfigureArgs configure_args = {runtime_storage, runtime_context, 0, config, *this};
+
+    status = import::OMKernelConfiguration::configureKernels(configure_args);
+    if (status != Ok)
+      return status;
+  }
+  // Done!
+
+  return Ok;
+}
+
+OMStatus OMRuntimeModule::allocateInputs()
+{
+  assert(_graphs.size() > 0);
+  if (_graphs.size() == 0)
+    return ModelNotImport;
+  return _graphs.at(0).allocateGraphInputs();
+}
+
+OMStatus OMRuntimeModule::run()
+{
+  OMStatus status = Ok;
+
+  if (_graphs.empty())
+    return ModelNotImport;
+
+  core::OMRuntimeGraph &main_graph = _graphs.at(0);
+
+  execute::OMExecuteArgs execute_args = {main_graph.getRuntimeStorage(),
+                                         main_graph.getRuntimeContext(), 0, *this};
+
+  status = execute::OMKernelExecute::runForward(execute_args, main_graph.getRuntimeAllocator());
+  if (status != Ok)
+    return status;
+
+  return status;
+}
+
+OMStatus OMRuntimeModule::reset()
+{
+  OMStatus status = Ok;
+
+  if (_graphs.empty())
+    return ModelNotImport;
+
+  for (auto &graph : _graphs)
+  {
+    graph.reset();
+  }
+
+  return status;
+}
+
+OMStatus OMRuntimeModule::getRuntimeGraphAt(uint32_t pos, OMRuntimeGraph **runtime_graph)
+{
+  if (pos >= _graphs.size())
+    return UnknownError;
+
+  *runtime_graph = &_graphs.at(pos);
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/core/OMRuntimeStorage.cpp b/onert-micro/onert-micro/src/core/OMRuntimeStorage.cpp
new file mode 100644 (file)
index 0000000..e2da287
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMRuntimeStorage.h"
+
+using namespace onert_micro::core;
+using namespace onert_micro;
+
+OMStatus OMRuntimeStorage::saveDataToTensorIndex(uint8_t *data, uint16_t tensor_index)
+{
+  _tensor_index_to_data[tensor_index] = data;
+
+  return Ok;
+}
+
+OMStatus OMRuntimeStorage::removeTensorFromTensorIndexToData(uint16_t tensor_index)
+{
+  auto tensor_to_data_it = _tensor_index_to_data.find(tensor_index);
+  assert(tensor_to_data_it != _tensor_index_to_data.end() && "No data");
+
+  if (tensor_to_data_it == _tensor_index_to_data.end())
+    return UnknownError;
+
+  _tensor_index_to_data.erase(tensor_to_data_it);
+
+  return Ok;
+}
+
+OMStatus OMRuntimeStorage::getDataByTensorIndex(uint8_t **data, uint16_t tensor_index)
+{
+  auto tensor_to_data_it = _tensor_index_to_data.find(tensor_index);
+
+  if (tensor_to_data_it != _tensor_index_to_data.end())
+    *data = tensor_to_data_it->second;
+  else
+    *data = nullptr;
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/core/OMTrainingRuntimeModule.cpp b/onert-micro/onert-micro/src/core/OMTrainingRuntimeModule.cpp
new file mode 100644 (file)
index 0000000..35ee91a
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMTrainingRuntimeModule.h"
+#include "import/OMExecutionPlanCreator.h"
+#include "train/OMBackpropExecute.h"
+#include "core/train/OMCheckpointSaver.h"
+#include "core/train/OMCheckpointLoader.h"
+
+using namespace onert_micro::core;
+using namespace onert_micro;
+
+/*
+ * Import train model, validate it, prepare necessary structures and data for future calculations
+ */
+OMStatus OMTrainingRuntimeModule::importTrainModel(char *model_ptr, const OMConfig &config)
+{
+  // 1 - Import main model
+  // 2 - Import and create training entities
+
+  // 1 - Import main model
+  OMStatus status = importModel(model_ptr, config);
+  if (status != Ok)
+    return status;
+
+  // 2 - Import and create training entities
+  _backward_graphs.resize(_graphs.size());
+  for (uint32_t i = 0; i < _backward_graphs.size(); ++i)
+  {
+    // load default backward graph
+    OMRuntimeGraph &graph = _backward_graphs.at(i);
+
+    OMRuntimeContext &runtime_context = graph.getRuntimeContext();
+    OMRuntimeStorage &runtime_storage = graph.getRuntimeStorage();
+    memory::OMRuntimeAllocator &runtime_allocator = graph.getRuntimeAllocator();
+
+    runtime_context.setModel(model_ptr, i);
+
+    // Parse and validate WOF file if it is exist
+    // WARNING: setWofFile method of RuntimeContext should follow after setModel.
+    if (config.wof_ptr != nullptr)
+      runtime_context.setWofFile(config.wof_ptr);
+
+    // AllocDeallocPlan backward graph creation
+    status = import::OMExecutionPlanCreator::createBackwardExecutionPlan(
+      runtime_storage, runtime_context, runtime_allocator, config);
+    if (status != Ok)
+      return status;
+  }
+
+  // Set current optimizer
+  _training_handler.setOptimizer(config);
+
+  return Ok;
+}
+
+/*
+ *  Train single step: run forward graph (with data which was set in SetInput) ->
+ *  -> calculate error (with target data which was set in SetTarget) ->
+ *  -> run backward graph -> update optimizer state -> after batch_size steps update weights
+ *  Warning: before using trainSingleStep call: 1) importTrainModel; 2) setInput; 3) setTarget
+ */
+OMStatus OMTrainingRuntimeModule::trainSingleStep(OMConfig &config)
+{
+  OMStatus status = Ok;
+  uint32_t batch_size = config.training_context.batch_size;
+  config.training_context.num_step += 1;
+
+  // A - Run and update optimizers state batch_size times
+  //  a. Allocate forward inputs and memcopy current sample (in current batch) into forward inputs
+  //  b. Run forward graph
+  //  c. Handle (calculate) current error backpropagation function result
+  //  d. Run backward graph (calculate backpropagation values)
+  //  e. Update optimization state
+  //  f. Reset runtime graphs (to deallocate forward outputs)
+  // B - Update weights according chosen optimization strategy (after batch_size times)
+
+  // A
+  for (uint32_t b = 0; b < batch_size; ++b)
+  {
+    //  a. Allocate forward inputs and memcopy current sample (in current batch) into forward inputs
+    {
+      OMRuntimeGraph &forward_main_graph = _graphs.at(0);
+      forward_main_graph.allocateGraphInputs();
+      uint32_t input_nums = forward_main_graph.getNumberOfInputs();
+      for (uint32_t i = 0; i < input_nums; ++i)
+      {
+        uint8_t *allocated_input_data =
+          reinterpret_cast<uint8_t *>(forward_main_graph.getInputDataAt(i));
+        size_t type_size = forward_main_graph.getInputDataTypeSize(i);
+        size_t tensor_size = forward_main_graph.getInputSizeAt(i);
+        size_t offset = b * type_size * tensor_size;
+
+        uint8_t *input_data = _training_handler.getInputData(i);
+        std::memcpy(allocated_input_data, input_data + offset, tensor_size * type_size);
+      }
+    }
+
+    //  b. Run forward graph
+    {
+      status = run();
+      assert(status == Ok);
+      if (status != Ok)
+        return status;
+    }
+
+    if (_backward_graphs.empty())
+      return ModelNotImport;
+
+    for (uint32_t i = 0; i < _graphs.size(); ++i)
+    {
+      // Get forward entities
+      OMRuntimeGraph &forward_graph = _graphs.at(i);
+      OMRuntimeContext &forward_context = forward_graph.getRuntimeContext();
+      OMRuntimeStorage &forward_storage = forward_graph.getRuntimeStorage();
+
+      // Get backward entities
+      OMRuntimeGraph &backward_graph = _backward_graphs.at(i);
+      OMRuntimeContext &backward_context = backward_graph.getRuntimeContext();
+      OMRuntimeStorage &backward_storage = backward_graph.getRuntimeStorage();
+
+      //  c. Handle (calculate) current error backpropagation function result
+      {
+        status = _training_handler.handleError(config, forward_storage, backward_storage,
+                                               backward_context, b);
+        assert(status == Ok);
+        if (status != Ok)
+          return status;
+      }
+
+      //  d. Run backward graph
+      {
+        onert_micro::train::OMBackpropExecuteArgs backprop_execute_args = {
+          forward_storage, backward_storage, backward_context, false, 0};
+
+        status = onert_micro::train::OMBackpropExecute::runBackward(
+          config, backprop_execute_args, backward_graph.getRuntimeAllocator());
+        assert(status == Ok);
+        if (status != Ok)
+          return status;
+      }
+
+      //  e. Update optimization state
+      {
+        status = _training_handler.updateOptimizerState(config, backward_storage, backward_context);
+        assert(status == Ok);
+        if (status != Ok)
+          return status;
+      }
+
+      //  f. Reset runtime graphs
+      backward_graph.reset();
+      forward_graph.reset();
+    }
+  }
+
+  // B - Update weights according chosen optimization strategy
+  for (uint32_t i = 0; i < _graphs.size(); ++i)
+  {
+    // Get backward context
+    OMRuntimeGraph &backward_graph = _backward_graphs.at(i);
+    OMRuntimeContext &backward_context = backward_graph.getRuntimeContext();
+    status = _training_handler.updateWeights(config, backward_context);
+  }
+
+  return status;
+}
+
+/*
+ * Evaluate metrics
+ *
+ *  Warning: 1) assume that all metric_val for all OMMetrics types actually are float values.
+ *           2) metric_val should be initialized with some value before calling this method due to
+ *              after calculation for current batch_num (the sequence number of the current sample)
+ *              this value is added to metric_val
+ */
+OMStatus OMTrainingRuntimeModule::evaluateMetric(OMMetrics metric, void *metric_val,
+                                                 uint32_t test_size)
+{
+  OMStatus status = Ok;
+  OMRuntimeGraph &forward_main_graph = _graphs.at(0);
+
+  assert(test_size > 0);
+  if (test_size == 0)
+    return UnknownError;
+
+  uint32_t input_nums = forward_main_graph.getNumberOfInputs();
+  for (uint32_t b = 0; b < test_size; ++b)
+  {
+    //  a. Allocate forward inputs and memcopy current sample (in current batch) into forward inputs
+    {
+      forward_main_graph.allocateGraphInputs();
+      for (uint32_t i = 0; i < input_nums; ++i)
+      {
+        uint8_t *allocated_input_data =
+          reinterpret_cast<uint8_t *>(forward_main_graph.getInputDataAt(i));
+        size_t type_size = forward_main_graph.getInputDataTypeSize(i);
+        size_t tensor_size = forward_main_graph.getInputSizeAt(i);
+        size_t offset = b * type_size * tensor_size;
+
+        uint8_t *input_data = _training_handler.getInputData(i);
+        std::memcpy(allocated_input_data, input_data + offset, tensor_size * type_size);
+      }
+    }
+
+    //  b. Run forward graph
+    {
+      status = run();
+      assert(status == Ok);
+      if (status != Ok)
+        return status;
+    }
+
+    // c. Calculate loss on test_size data
+    _training_handler.evaluateMetric(metric, metric_val, forward_main_graph.getRuntimeStorage(),
+                                     forward_main_graph.getRuntimeContext(), b);
+
+    // Reset values
+    forward_main_graph.reset();
+  }
+
+  // Averaged result
+  {
+    float *f_metric_val = reinterpret_cast<float *>(metric_val);
+    *f_metric_val /= test_size;
+  }
+
+  return Ok;
+}
+
+/*
+ * Reset all forward and backward graphs
+ */
+OMStatus OMTrainingRuntimeModule::reset()
+{
+  OMStatus status = Ok;
+
+  if (_graphs.empty())
+    return ModelNotImport;
+
+  for (auto &graph : _graphs)
+  {
+    graph.reset();
+  }
+
+  for (auto &graph : _backward_graphs)
+  {
+    graph.reset();
+  }
+
+  _training_handler.reset();
+
+  return status;
+}
+
+/*
+ * Create and save checkpoint data into data_buffer vector
+ */
+OMStatus OMTrainingRuntimeModule::createCheckpointFile(const OMConfig &config,
+                                                       std::vector<char> &data_buffer)
+{
+  // Model wasn't imported
+  if (_backward_graphs.size() == 0 or _graphs.size() == 0)
+    return UnknownError;
+
+  OMRuntimeContext &context = _backward_graphs.at(0).getRuntimeContext();
+  train::OMTrainingStorage &train_storage = _training_handler.getTrainingStorage();
+
+  OMStatus status =
+    train::OMCheckpointSaver::createCheckpointData(context, train_storage, data_buffer, config);
+
+  return status;
+}
+
+/*
+ * Load checkpoint data and save in model data and config
+ */
+OMStatus OMTrainingRuntimeModule::loadCheckpointData(OMConfig &config, const char *data)
+{
+  // Model wasn't imported
+  if (_backward_graphs.size() == 0 or _graphs.size() == 0)
+    return UnknownError;
+
+  OMRuntimeContext &context = _backward_graphs.at(0).getRuntimeContext();
+  train::OMTrainingStorage &train_storage = _training_handler.getTrainingStorage();
+
+  OMStatus status =
+    train::OMCheckpointLoader::loadCheckpointData(context, train_storage, data, config);
+
+  return status;
+}
+
+void *OMTrainingRuntimeModule::getInputData(int32_t index)
+{
+  return _training_handler.getInputData(index);
+}
diff --git a/onert-micro/onert-micro/src/core/OMUtils.cpp b/onert-micro/onert-micro/src/core/OMUtils.cpp
new file mode 100644 (file)
index 0000000..d2db74d
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMUtils.h"
+
+using namespace onert_micro::core::utils;
+using namespace onert_micro;
+
+OMStatus onert_micro::core::utils::checkCondition(bool cond)
+{
+  if (cond)
+    return Ok;
+
+  assert(cond && "check condition failed");
+
+  return FailedCheckCondition;
+}
diff --git a/onert-micro/onert-micro/src/core/memory/OMMemoryManager.cpp b/onert-micro/onert-micro/src/core/memory/OMMemoryManager.cpp
new file mode 100644 (file)
index 0000000..7ecbae1
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/memory/OMMemoryManager.h"
+
+using namespace onert_micro::core::memory;
+using namespace onert_micro;
+
+OMStatus OMMemoryManager::allocateMemory(uint32_t size, uint8_t **data)
+{
+  if (size == 0)
+    return UnknownError;
+  auto data_tmp = new uint8_t[size];
+
+  *data = data_tmp;
+
+  return Ok;
+}
+
+OMStatus OMMemoryManager::deallocateMemory(uint8_t *data)
+{
+  delete[] data;
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/core/memory/OMRuntimeAllocator.cpp b/onert-micro/onert-micro/src/core/memory/OMRuntimeAllocator.cpp
new file mode 100644 (file)
index 0000000..fbb89a1
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/memory/OMRuntimeAllocator.h"
+#include "core/memory/OMMemoryManager.h"
+
+#include "core/OMDataType.h"
+#include <limits>
+
+using namespace onert_micro::core::memory;
+using namespace onert_micro;
+
+OMStatus OMRuntimeAllocator::clearAllTensorsData(OMRuntimeContext *context,
+                                                 OMRuntimeStorage *storage)
+{
+  auto tensor_index_to_data = storage->getTensorIndexToData();
+
+  for (auto &cur_tensor_index_data : tensor_index_to_data)
+  {
+    auto tensor_index = cur_tensor_index_data.first;
+    uint8_t *allocated_data = cur_tensor_index_data.second;
+
+    OMMemoryManager::deallocateMemory(allocated_data);
+  }
+
+  return Ok;
+}
+
+OMStatus OMRuntimeAllocator::allocate(size_t kernel_index, OMRuntimeContext *context,
+                                      OMRuntimeStorage *storage)
+{
+  assert(kernel_index < _alloc_plan.size() && "Wrong kernel index");
+  if (kernel_index >= _alloc_plan.size())
+    return UnknownError;
+
+  const std::vector<uint16_t> &current_allocate_plan = _alloc_plan[kernel_index];
+
+  for (const uint16_t tensor_index : current_allocate_plan)
+  {
+    const circle::Tensor *tensor = context->getTensorByIndex(tensor_index);
+    const OMRuntimeShape tensor_shape(tensor);
+
+    int32_t num_elements = tensor_shape.flatSize();
+
+#ifndef DIS_DYN_SHAPES
+    int32_t dynamic_tensor_size = storage->getDynamicTensorSize(tensor_index);
+    if (dynamic_tensor_size != -1)
+      num_elements = dynamic_tensor_size;
+#endif // DIS_DYN_SHAPES
+
+    assert(num_elements >= 0 && "Num elements should be positive");
+    if (num_elements < 0)
+      return UnknownError;
+    const auto casted_num_elements = static_cast<uint32_t>(num_elements);
+    const auto type_size =
+      static_cast<uint32_t>(getOMDataTypeSize(onertMicroDatatype(tensor->type())));
+    if (casted_num_elements > std::numeric_limits<uint32_t>::max() / type_size)
+    {
+      return FailedCheckCondition;
+    }
+    // allocate data
+    uint8_t *allocated_data = nullptr;
+    assert(storage->getDataByTensorIndex(&allocated_data, tensor_index) == Ok &&
+           allocated_data == nullptr && "Double allocate, memory leak");
+    OMStatus status =
+      OMMemoryManager::allocateMemory(casted_num_elements * type_size, &allocated_data);
+    if (status != Ok)
+      return status;
+
+    storage->saveDataToTensorIndex(allocated_data, tensor_index);
+  }
+
+  return Ok;
+}
+
+OMStatus OMRuntimeAllocator::deallocate(size_t kernel_index, OMRuntimeStorage *storage)
+{
+  assert(kernel_index < _alloc_plan.size() && "Wrong kernel index");
+  if (kernel_index >= _alloc_plan.size())
+    return UnknownError;
+
+  const std::vector<uint16_t> &current_deallocate_plan = _dealloc_plan[kernel_index];
+
+  for (const uint16_t tensor_index : current_deallocate_plan)
+  {
+    uint8_t *allocated_data = nullptr;
+    OMStatus status = storage->getDataByTensorIndex(&allocated_data, tensor_index);
+    assert(status == Ok); // note that status always 0
+
+    // To continue deallocate due to current tensor is not saved in storage
+    if (allocated_data == nullptr)
+      continue;
+
+    status = OMMemoryManager::deallocateMemory(allocated_data);
+    assert(status == Ok); // note that status always 0
+
+    status = storage->removeTensorFromTensorIndexToData(tensor_index);
+    if (status != Ok)
+      return status;
+  }
+
+  return Ok;
+}
+
+OMStatus OMRuntimeAllocator::allocateGraphInputs(OMRuntimeContext *context,
+                                                 OMRuntimeStorage *storage)
+{
+  OMStatus status = Ok;
+  const auto &graph_inputs = context->getCircleInputs();
+
+  for (uint i = 0; i < graph_inputs->size(); ++i)
+  {
+    auto tensor_index = graph_inputs->operator[](i);
+    const circle::Tensor *tensor = context->getTensorByIndex(tensor_index);
+    const OMRuntimeShape tensor_shape(tensor);
+
+    int32_t num_elements = tensor_shape.flatSize();
+    assert(num_elements >= 0 && "Num elements should be positive");
+    if (num_elements < 0)
+      return UnknownError;
+    const auto casted_num_elements = static_cast<uint32_t>(num_elements);
+    const auto type_size =
+      static_cast<uint32_t>(getOMDataTypeSize(onertMicroDatatype(tensor->type())));
+
+    uint8_t *allocated_data = nullptr;
+    // First clear if already allocated
+    status = storage->getDataByTensorIndex(&allocated_data, tensor_index);
+
+    OMMemoryManager::deallocateMemory(allocated_data);
+
+    // Then Allocate
+    status = OMMemoryManager::allocateMemory(casted_num_elements * type_size, &allocated_data);
+    if (status != Ok)
+      return status;
+
+    storage->saveDataToTensorIndex(allocated_data, tensor_index);
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/core/reader/OMCircleReader.cpp b/onert-micro/onert-micro/src/core/reader/OMCircleReader.cpp
new file mode 100644 (file)
index 0000000..092e9b6
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/reader/OMCircleReader.h"
+
+using namespace onert_micro::core::reader;
+using namespace onert_micro;
+
+namespace
+{
+
+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());
+}
+
+} // namespace
+
+circle::BuiltinOperator OMCircleReader::builtin_code(const circle::Operator *op) const
+{
+  assert(op != nullptr);
+
+  const auto op_codes = opcodes();
+  uint32_t index = op->opcode_index();
+
+  assert(index < op_codes->size());
+
+  const auto opcode = op_codes->operator[](index);
+  assert(opcode != nullptr);
+
+  return builtin_code_neutral(opcode);
+}
+
+OMStatus OMCircleReader::parse(const char *model_ptr)
+{
+  assert(_model == nullptr && "Already init _model");
+  assert(model_ptr != nullptr && "Model pointer cannot be null");
+  if (model_ptr == nullptr or _model != nullptr)
+  {
+    return UnknownError;
+  }
+
+  _model = circle::GetModel(model_ptr);
+
+  return Ok;
+}
+
+OMStatus OMCircleReader::select_subgraph(uint32_t sgindex)
+{
+  if (num_subgraph() <= sgindex)
+    return UnknownError;
+
+  auto subgraphs = _model->subgraphs();
+  if (subgraphs == nullptr)
+    return UnknownError;
+
+  _current_subgraph = subgraphs->Get(sgindex);
+  if (_current_subgraph == nullptr)
+    return UnknownError;
+
+  _current_subgraph_index = sgindex;
+
+  return Ok;
+}
+
+bool OMCircleReader::isConstTensor(uint32_t tensor_index)
+{
+  if (tensor_index == -1)
+    return false;
+
+  const auto tmp_tensor = _current_subgraph->tensors()->operator[](tensor_index);
+  return _model->buffers()->operator[](tmp_tensor->buffer())->data() != nullptr;
+}
diff --git a/onert-micro/onert-micro/src/core/reader/OMWeightOnlyFormatReader.cpp b/onert-micro/onert-micro/src/core/reader/OMWeightOnlyFormatReader.cpp
new file mode 100644 (file)
index 0000000..5af39c8
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/reader/OMWeightOnlyFormatReader.h"
+
+using namespace onert_micro::core::reader;
+using namespace onert_micro;
+
+/*
+ * Validate method for Weight Only Format file to check its correctness
+ */
+OMStatus OMWeightOnlyFormatReader::validate(OMCircleReader *reader)
+{
+  OMStatus status = Ok;
+
+  // Validate magic number
+  uint16_t mag_num = 0;
+  std::memcpy(&mag_num, &_wof_ptr[MAGIC_NUMBER], sizeof(mag_num));
+  assert(mag_num == wof_magic_number && "False MAGIC NUMBER, check correctness of wof file");
+  if (mag_num != wof_magic_number)
+    return FailReadWOFFile;
+
+  // Validate schema version
+  uint8_t version = 0;
+  std::memcpy(&version, &_wof_ptr[SCHEMA_VERSION], sizeof(version));
+  assert(version == schema_version && "False MAGIC NUMBER, check correctness of wof file");
+  if (version != schema_version)
+    return FailReadWOFFile;
+
+  // Validate count of tensors
+  assert(reader != nullptr && "Reader should exist");
+  if (reader == nullptr)
+    return ModelNotImport;
+  uint32_t num_tensors = reader->tensors()->size();
+  uint32_t num_tensors_in_wof_file = 0;
+  std::memcpy(&num_tensors_in_wof_file, &_wof_ptr[NUM_BUFFERS], sizeof(num_tensors_in_wof_file));
+  assert(num_tensors == num_tensors_in_wof_file &&
+         "Number of tensors in circle and in wof file should be the same");
+  if (num_tensors != num_tensors_in_wof_file)
+    return FailReadWOFFile;
+
+  return status;
+}
+
+/*
+ * Get pointer to saved data (weights data) for tensor with tensor index.
+ * If tensor index not save in wof file return nullptr
+ */
+char *OMWeightOnlyFormatReader::buffer(const uint32_t tensor_index)
+{
+  if (_wof_ptr == nullptr)
+    return nullptr;
+
+  uint32_t buffer_offset = 0;
+  uint32_t offset_offset = FIRST_OFFSET + tensor_index * sizeof(uint32_t);
+
+  std::memcpy(&buffer_offset, &_wof_ptr[offset_offset], sizeof(buffer_offset));
+
+  if (buffer_offset == 0)
+    return nullptr;
+
+  return _wof_ptr + buffer_offset;
+}
diff --git a/onert-micro/onert-micro/src/core/train/OMCheckpointLoader.cpp b/onert-micro/onert-micro/src/core/train/OMCheckpointLoader.cpp
new file mode 100644 (file)
index 0000000..db61df5
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMDataType.h"
+#include "core/memory/OMMemoryManager.h"
+#include "core/train/OMCheckpointLoader.h"
+
+using namespace onert_micro::core::train;
+using namespace onert_micro::core;
+using namespace onert_micro::train;
+using namespace onert_micro;
+
+namespace
+{
+
+constexpr uint16_t MAGIC_NUMBER = 429;
+constexpr uint8_t SCHEMA_VERSION = 1;
+
+enum WOFFieldsOffsets
+{
+  MAGIC_NUMBER_OFFSET = 0,
+  SCHEMA_VERSION_OFFSET = 2,
+  M_OFFSET = 4,
+  V_OFFSET = 8,
+  OTHER_PARAMS_OFFSET = 12,
+  NUM_BUFFERS_OFFSET = 16,
+  WEIGHT_OFFSET = 20,
+};
+
+// Layers with trainable weights
+// Note: needed not to store some layers with const intputs but it is not trainable (for example
+// Reshape)
+bool isTrainableWeights(const circle::OperatorCode *opcode)
+{
+  switch (opcode->builtin_code())
+  {
+    case circle::BuiltinOperator_FULLY_CONNECTED:
+    case circle::BuiltinOperator_CONV_2D:
+      return true;
+    default:
+      return false;
+  }
+}
+
+} // namespace
+
+OMStatus OMCheckpointLoader::validateCheckpointData(core::OMRuntimeContext &context,
+                                                    const char *data, OMConfig &config)
+{
+  OMStatus status = Ok;
+
+  // Validate magic number
+  uint16_t mag_num = 0;
+  std::memcpy(&mag_num, &data[MAGIC_NUMBER_OFFSET], sizeof(mag_num));
+  assert(mag_num == MAGIC_NUMBER && "False MAGIC NUMBER, check correctness of checkpoint file");
+  if (mag_num != MAGIC_NUMBER)
+    return FailReadCheckpointFile;
+
+  // Validate schema version
+  uint8_t version = 0;
+  std::memcpy(&version, &data[SCHEMA_VERSION_OFFSET], sizeof(version));
+  assert(version == SCHEMA_VERSION &&
+         "False SCHEMA_VERSION NUMBER, check correctness of checkpoint file");
+  if (version != SCHEMA_VERSION)
+    return FailReadCheckpointFile;
+
+  // Validate count of tensors
+  uint32_t num_tensors = context.getCircleTensors()->size();
+  uint32_t num_tensors_in_file = 0;
+  std::memcpy(&num_tensors_in_file, &data[NUM_BUFFERS_OFFSET], sizeof(num_tensors_in_file));
+  assert(num_tensors == num_tensors_in_file &&
+         "Number of tensors in circle and in checkpoint file should be the same");
+  if (num_tensors != num_tensors_in_file)
+    return FailReadCheckpointFile;
+
+  // Validate m, v and other parameters offset
+  uint32_t m_offset;
+  uint32_t v_offset;
+  uint32_t other_params_offset;
+  std::memcpy(&m_offset, &data[M_OFFSET], sizeof(m_offset));
+  std::memcpy(&v_offset, &data[V_OFFSET], sizeof(v_offset));
+  std::memcpy(&other_params_offset, &data[OTHER_PARAMS_OFFSET], sizeof(other_params_offset));
+
+  assert(other_params_offset > 0);
+  if (other_params_offset == 0)
+    return FailReadCheckpointFile;
+
+  if (config.training_context.optimizer == SGD)
+  {
+    assert(m_offset == 0 and v_offset == 0);
+    if (m_offset != 0 or v_offset != 0)
+      return FailReadCheckpointFile;
+  }
+
+  return Ok;
+}
+
+OMStatus OMCheckpointLoader::loadBuffers(core::OMRuntimeContext &context,
+                                         OMTrainingStorage &train_storage, const char *data,
+                                         OMConfig &config)
+{
+  OMStatus status = Ok;
+
+  // Read v, m and other params offsets
+  uint32_t m_offset;
+  uint32_t v_offset;
+  uint32_t other_params_offset;
+  std::memcpy(&m_offset, &data[M_OFFSET], sizeof(m_offset));
+  std::memcpy(&v_offset, &data[V_OFFSET], sizeof(v_offset));
+  std::memcpy(&other_params_offset, &data[OTHER_PARAMS_OFFSET], sizeof(other_params_offset));
+
+  uint32_t weight_offset_pos = WEIGHT_OFFSET;
+
+  // If optimizer is Adam then reset its state
+  optimizers::Adam *adam_opt = nullptr;
+  if (config.training_context.optimizer == ADAM)
+  {
+    adam_opt = train_storage.getAdam();
+    assert(adam_opt != nullptr);
+
+    adam_opt->fullReset();
+  }
+
+  auto tensors = context.getCircleTensors();
+  auto tensors_size = tensors->size();
+  const auto *operators = context.getCircleOperators();
+  const auto num_kernels = operators->size();
+  uint32_t num_train_layers = config.training_context.num_of_train_layers == 0
+                                ? num_kernels
+                                : config.training_context.num_of_train_layers;
+  uint32_t last_node_pos = std::min(num_kernels, num_train_layers);
+  // Goes among trainable ops
+  const auto *op_codes = context.getCircleOpcodes();
+  for (uint32_t index = 0; index < last_node_pos; ++index)
+  {
+    uint32_t cur_op_index = num_kernels - index - 1;
+    auto *cur_op = operators->operator[](cur_op_index);
+
+    auto input_tensors = cur_op->inputs();
+
+    for (uint32_t i = 0; i < input_tensors->size(); ++i)
+    {
+      const auto input_tensor_index = input_tensors->operator[](i);
+      // Check is const
+      if (not context.isConstTensor(input_tensor_index))
+        continue;
+
+      uint32_t cur_opcode_index = cur_op->opcode_index();
+
+      assert(cur_opcode_index < op_codes->size());
+
+      const auto opcode = op_codes->operator[](cur_opcode_index);
+
+      // Check it is trainable const
+      if (not isTrainableWeights(opcode))
+        continue;
+
+      // Get current weight file pos
+      uint32_t cur_weight_offset_pos = weight_offset_pos + input_tensor_index * 4;
+
+      // Read current tensor offset
+      uint32_t cur_tensor_offset;
+      std::memcpy(&cur_tensor_offset, &data[cur_weight_offset_pos], sizeof(cur_tensor_offset));
+
+      // Check is it save data or not
+      // Note: zero means there are no data - it is error
+      if (cur_tensor_offset == 0)
+        return FailReadCheckpointFile;
+
+      // Read weight data and save it
+      const auto tensor = tensors->operator[](input_tensor_index);
+      assert(tensor != nullptr);
+
+      OMRuntimeShape shape(tensor);
+      auto type_size = sizeof(OMDataType(tensor->type()));
+
+      size_t buffer_size = shape.flatSize() * type_size;
+      // Get pointer to the data in model
+      uint8_t *weight_data_in_model_ptr;
+
+      status = context.getConstDataByTensorIndex(&weight_data_in_model_ptr, input_tensor_index);
+      assert(status == Ok);
+      assert(weight_data_in_model_ptr != nullptr);
+      if (status != Ok or weight_data_in_model_ptr == nullptr)
+        return status;
+
+      std::memcpy(weight_data_in_model_ptr, &data[cur_tensor_offset], buffer_size);
+
+      if (config.training_context.optimizer == SGD)
+        continue;
+
+      // For Adam read m and v buffer
+      assert(config.training_context.optimizer == ADAM);
+
+      // If no saved Adam state then continue
+      if (m_offset == 0 or v_offset == 0)
+      {
+        assert(v_offset == 0);
+        assert(m_offset == 0);
+        continue;
+      }
+
+      // Get current v and m file pos
+      uint32_t cur_m_offset_pos = m_offset + input_tensor_index * 4;
+      uint32_t cur_v_offset_pos = v_offset + input_tensor_index * 4;
+
+      // Read current v and m offset
+      uint32_t cur_m_offset;
+      uint32_t cur_v_offset;
+      std::memcpy(&cur_m_offset, &data[cur_m_offset_pos], sizeof(cur_m_offset));
+      std::memcpy(&cur_v_offset, &data[cur_v_offset_pos], sizeof(cur_v_offset));
+
+      // Cannot be zero due to weight already not zero
+      assert(cur_m_offset != 0 and cur_v_offset != 0);
+      if (cur_m_offset == 0 or cur_v_offset == 0)
+        return FailReadCheckpointFile;
+
+      assert(adam_opt != nullptr);
+
+      // Allocate memory for m and v current buffer
+      uint8_t *m_buffer = nullptr;
+      uint8_t *v_buffer = nullptr;
+      status = memory::OMMemoryManager::allocateMemory(buffer_size, &m_buffer);
+      assert(status == Ok);
+      assert(m_buffer != nullptr);
+      status = memory::OMMemoryManager::allocateMemory(buffer_size, &v_buffer);
+      assert(status == Ok);
+      assert(v_buffer != nullptr);
+
+      // Read m and v buffer
+      std::memcpy(m_buffer, &data[cur_m_offset], buffer_size);
+      std::memcpy(v_buffer, &data[cur_v_offset], buffer_size);
+
+      // Save m and v buffer in adam optimizer state
+      adam_opt->setExponentAvgDataByTensorIndex(input_tensor_index, m_buffer);
+      adam_opt->setExponentAvgSquaresDataByTensorIndex(input_tensor_index, v_buffer);
+    }
+  }
+
+  // Read other parameters: cur step num and cur epoch num
+  uint32_t cur_step_offset = other_params_offset;
+  uint32_t cur_epoch_offset = other_params_offset + 4;
+
+  uint32_t cur_step;
+  std::memcpy(&cur_step, &data[cur_step_offset], sizeof(cur_step));
+
+  uint32_t cur_epoch;
+  std::memcpy(&cur_epoch, &data[cur_epoch_offset], sizeof(cur_epoch));
+
+  // Save it in config
+  config.training_context.num_step = cur_step;
+  config.training_context.num_epoch = cur_epoch;
+
+  return status;
+}
+
+// To check checkpoint file format please see https://github.com/Samsung/ONE/discussions/13037
+OMStatus OMCheckpointLoader::loadCheckpointData(core::OMRuntimeContext &context,
+                                                OMTrainingStorage &train_storage, const char *data,
+                                                OMConfig &config)
+{
+
+  // Validate current checkpoint file data
+  OMStatus status = validateCheckpointData(context, data, config);
+  assert(status == Ok);
+  if (status != Ok)
+    return status;
+
+  // Read and save buffer
+  status = loadBuffers(context, train_storage, data, config);
+  assert(status == Ok);
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/core/train/OMCheckpointSaver.cpp b/onert-micro/onert-micro/src/core/train/OMCheckpointSaver.cpp
new file mode 100644 (file)
index 0000000..ca32c5e
--- /dev/null
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMDataType.h"
+#include "core/train/OMCheckpointSaver.h"
+
+using namespace onert_micro::core::train;
+using namespace onert_micro::core;
+using namespace onert_micro::train;
+using namespace onert_micro;
+
+namespace
+{
+
+// Layers with trainable weights
+// Note: needed not to store some layers with const intputs but it is not trainable (for example
+// Reshape)
+bool isTrainableWeights(const circle::OperatorCode *opcode)
+{
+  switch (opcode->builtin_code())
+  {
+    case circle::BuiltinOperator_FULLY_CONNECTED:
+    case circle::BuiltinOperator_CONV_2D:
+      return true;
+    default:
+      return false;
+  }
+}
+
+constexpr uint16_t MAGIC_NUMBER = 429;
+constexpr uint8_t SCHEMA_VERSION = 1;
+
+} // namespace
+
+/**
+ * Calculate result buffer size
+ **/
+size_t OMCheckpointSaver::calculateFileSize(core::OMRuntimeContext &context,
+                                            OMTrainingStorage &train_storage,
+                                            const OMConfig &config)
+{
+  size_t result = 0;
+
+  // 2 bytes for Magic Number
+  result += 2;
+
+  // 1 byte for Schema version
+  result += 1;
+
+  // 1 byte for Reserved field
+  result += 1;
+
+  // 4 bytes for Adam's state m buffers offset value
+  result += 4;
+
+  // 4 bytes for Adam's state v buffers offset value
+  result += 4;
+
+  // 4 bytes for others parameters offset value
+  result += 4;
+
+  // 4 bytes for number of tensors
+  result += 4;
+
+  auto tensors = context.getCircleTensors();
+
+  auto tensors_size = tensors->size();
+
+  // tensors_size * 4 bytes for buffers offsets
+  result += tensors_size * 4;
+
+  const auto *operators = context.getCircleOperators();
+  const auto num_kernels = operators->size();
+  uint32_t num_train_layers = config.training_context.num_of_train_layers == 0
+                                ? num_kernels
+                                : config.training_context.num_of_train_layers;
+  uint32_t last_node_pos = std::min(num_kernels, num_train_layers);
+  // Goes among trainable ops
+  size_t buffer_size = 0;
+  const auto *op_codes = context.getCircleOpcodes();
+  for (uint32_t index = 0; index < last_node_pos; ++index)
+  {
+    uint32_t cur_op_index = num_kernels - index - 1;
+    auto *cur_op = operators->operator[](cur_op_index);
+
+    auto input_tensors = cur_op->inputs();
+
+    for (uint32_t i = 0; i < input_tensors->size(); ++i)
+    {
+      const auto input_tensor_index = input_tensors->operator[](i);
+      // Check is const
+      if (not context.isConstTensor(input_tensor_index))
+        continue;
+
+      uint32_t cur_opcode_index = cur_op->opcode_index();
+
+      assert(cur_opcode_index < op_codes->size());
+
+      const auto opcode = op_codes->operator[](cur_opcode_index);
+
+      // Check it is trainable const
+      if (not isTrainableWeights(opcode))
+        continue;
+
+      const auto tensor = context.getTensorByIndex(input_tensor_index);
+      OMRuntimeShape shape(tensor);
+
+      auto type_size = sizeof(OMDataType(tensor->type()));
+
+      buffer_size += type_size * shape.flatSize();
+    }
+  }
+
+  // If we use Adam optimizer then need to add Adam specific buffers
+  assert(config.training_context.optimizer == SGD or
+         config.training_context.optimizer == ADAM && "Unsupported type");
+  if (config.training_context.optimizer == ADAM)
+  {
+    // Check is it save any state
+    if (not train_storage.getAdam()->isReset())
+    {
+      // If yes - then just buffer_size = buffer_size * 3 (original weights and two buffers from
+      // Adam state)
+      buffer_size *= 3;
+
+      // Add offsets for m
+      result += tensors_size * 4;
+      // Add offsets for v
+      result += tensors_size * 4;
+    }
+  }
+
+  // Add buffer size
+  result += buffer_size;
+
+  // 4 bytes to save information about current step
+  result += 4;
+
+  // 4 bytes to save information about current epoch
+  result += 4;
+
+  return result;
+}
+
+OMStatus OMCheckpointSaver::writeOffsetsAndBuffers(core::OMRuntimeContext &context,
+                                                   OMTrainingStorage &train_storage,
+                                                   const OMConfig &config, std::vector<char> &data)
+{
+  // Point to start of the buffer
+  char *cur_ptr = data.data();
+
+  // Set to the n_buffers field
+  cur_ptr += 16;
+
+  auto tensors = context.getCircleTensors();
+  auto tensors_size = tensors->size();
+
+  // Write number of buffers
+  std::memcpy(cur_ptr, &tensors_size, sizeof(tensors_size));
+
+  // Calculate buffers offsets, set all to zeros
+  // Zero value means that there is no buffer for this tensor
+  std::vector<uint32_t> offsets(tensors_size, 0);
+  // Start offset for buffers
+  uint32_t cur_offset = 20 + tensors_size * 4;
+
+  // To calculate sum of saved buffers sizes
+  uint32_t acc_buffer_size = 0;
+
+  const auto *operators = context.getCircleOperators();
+  const auto num_kernels = operators->size();
+  uint32_t num_train_layers = config.training_context.num_of_train_layers == 0
+                                ? num_kernels
+                                : config.training_context.num_of_train_layers;
+  uint32_t last_node_pos = std::min(num_kernels, num_train_layers);
+  // Goes among trainable ops
+
+  const auto *op_codes = context.getCircleOpcodes();
+
+  for (uint32_t index = 0; index < last_node_pos; ++index)
+  {
+    uint32_t cur_op_index = num_kernels - index - 1;
+    auto *cur_op = operators->operator[](cur_op_index);
+
+    auto input_tensors = cur_op->inputs();
+
+    for (uint32_t i = 0; i < input_tensors->size(); ++i)
+    {
+      const auto input_tensor_index = input_tensors->operator[](i);
+      // Check is const
+      if (not context.isConstTensor(input_tensor_index))
+        continue;
+
+      uint32_t cur_opcode_index = cur_op->opcode_index();
+
+      assert(cur_opcode_index < op_codes->size());
+
+      const auto opcode = op_codes->operator[](cur_opcode_index);
+
+      // Check it is trainable const
+      if (not isTrainableWeights(opcode))
+        continue;
+
+      // Found trainable weight tensor, lets calculate its size and save offset for current buffer
+      const auto tensor = context.getTensorByIndex(input_tensor_index);
+      OMRuntimeShape shape(tensor);
+
+      auto type_size = sizeof(OMDataType(tensor->type()));
+
+      size_t buffer_size = type_size * shape.flatSize();
+      // Save for current tensor index its offset
+      offsets[input_tensor_index] = cur_offset;
+      // Get buffer data
+      uint8_t *tensor_data;
+      OMStatus status = context.getConstDataByTensorIndex(&tensor_data, input_tensor_index);
+      assert(status == Ok);
+      if (status != Ok)
+        return status;
+      assert(tensor_data != nullptr);
+
+      // Write buffer data into vector
+      cur_ptr = data.data() + cur_offset;
+      std::memcpy(cur_ptr, tensor_data, buffer_size);
+      // Move offset
+      cur_offset += buffer_size;
+      // Save buffers size
+      acc_buffer_size += buffer_size;
+    }
+  }
+
+  // Now cur_offset points to last position after adding all buffers
+  // Let's handle with Adam buffers offsets
+  assert(config.training_context.optimizer == ADAM or
+         config.training_context.optimizer == SGD && "Unsupported type");
+  if (config.training_context.optimizer == ADAM and not train_storage.getAdam()->isReset())
+  {
+    // Move pointer to m offset field
+    cur_ptr = data.data() + 4;
+    // Save offset for the m offset field
+    uint32_t m_offset = cur_offset;
+    std::memcpy(cur_ptr, &m_offset, sizeof(m_offset));
+    // Move pointer to the v offset field
+    cur_ptr += 4;
+    // Calculate offset for the v offset field
+    uint32_t v_offset = m_offset + acc_buffer_size + tensors_size * 4;
+    // Save it
+    std::memcpy(cur_ptr, &v_offset, sizeof(v_offset));
+
+    // Let's write offsets and buffers
+    const auto adam_opt = train_storage.getAdam();
+    assert(adam_opt != nullptr);
+
+    // Move m and v to buffers offsets
+    uint32_t m_buffer_offset = m_offset + tensors_size * 4;
+    uint32_t v_buffer_offset = v_offset + tensors_size * 4;
+
+    // Adam buffers
+    std::vector<uint32_t> m_offsets(tensors_size, 0);
+    std::vector<uint32_t> v_offsets(tensors_size, 0);
+
+    // Goes among trainable ops
+    for (uint32_t index = 0; index < last_node_pos; ++index)
+    {
+      uint32_t cur_op_index = num_kernels - index - 1;
+      auto *cur_op = operators->operator[](cur_op_index);
+
+      auto input_tensors = cur_op->inputs();
+
+      for (uint32_t i = 0; i < input_tensors->size(); ++i)
+      {
+        const auto input_tensor_index = input_tensors->operator[](i);
+        // Check is const
+        if (not context.isConstTensor(input_tensor_index))
+          continue;
+
+        uint32_t cur_opcode_index = cur_op->opcode_index();
+
+        assert(cur_opcode_index < op_codes->size());
+
+        const auto opcode = op_codes->operator[](cur_opcode_index);
+
+        // Check it is trainable const
+        if (not isTrainableWeights(opcode))
+          continue;
+
+        // Found trainable weight tensor, lets calculate its size and save offset for current buffer
+        const auto tensor = context.getTensorByIndex(input_tensor_index);
+        OMRuntimeShape shape(tensor);
+
+        auto type_size = sizeof(OMDataType(tensor->type()));
+
+        size_t buffer_size = type_size * shape.flatSize();
+        // Save for current tensor index its offset
+        m_offsets[input_tensor_index] = m_buffer_offset;
+        v_offsets[input_tensor_index] = v_buffer_offset;
+
+        // Obtain m and v data from train storage
+        uint8_t *m_data = adam_opt->getExponentAvgDataByTensorIndex(input_tensor_index);
+        assert(m_data != nullptr);
+        uint8_t *v_data = adam_opt->getExponentAvgSquaresDataByTensorIndex(input_tensor_index);
+        assert(v_data != nullptr);
+
+        // Write m data
+        cur_ptr = data.data() + m_buffer_offset;
+        std::memcpy(cur_ptr, m_data, buffer_size);
+        // Write v data
+        cur_ptr = data.data() + v_buffer_offset;
+        std::memcpy(cur_ptr, v_data, buffer_size);
+
+        // Move m and v buffers offsets
+        m_buffer_offset += buffer_size;
+        v_buffer_offset += buffer_size;
+      }
+    }
+
+    // Set pointer to the m offset field start
+    char *m_offset_start = data.data() + m_offset;
+    // Set pointer to the v offset field start
+    char *v_offset_start = data.data() + v_offset;
+    // Write m and v offsets
+    for (uint32_t i = 0; i < tensors_size; ++i)
+    {
+      // Save m buffer offset
+      uint32_t cur_m_offset = m_offsets[i];
+      std::memcpy(m_offset_start, &cur_m_offset, sizeof(cur_m_offset));
+      m_offset_start += 4;
+
+      // Save v buffer offset
+      uint32_t cur_v_offset = v_offsets[i];
+      std::memcpy(v_offset_start, &cur_v_offset, sizeof(cur_v_offset));
+      v_offset_start += 4;
+    }
+  }
+  else
+  {
+    // Note: offset = 0 - means there are no such buffers
+    // Move pointer to m offset field
+    cur_ptr = data.data() + 4;
+    // Save offset for the m offset field
+    uint32_t m_offset = 0;
+    std::memcpy(cur_ptr, &m_offset, sizeof(m_offset));
+
+    // Move pointer to the v offset field
+    cur_ptr += 4;
+    // Save offset for the v offset field
+    uint32_t v_offset = 0;
+    std::memcpy(cur_ptr, &v_offset, sizeof(v_offset));
+  }
+
+  // Move cur_ptr to the start of the offsets field
+  cur_ptr = data.data() + 20;
+  // Write offsets
+  for (uint32_t i = 0; i < tensors_size; ++i)
+  {
+    uint32_t offset = offsets[i];
+    std::memcpy(cur_ptr, &offset, sizeof(offset));
+    cur_ptr += 4;
+  }
+
+  // Save other parameters offset: 20 initial bytes + tensors_size * 4 bytes for buffer offsets +
+  // buffer size
+  uint32_t other_parameters_offset = 20 + tensors_size * 4 + acc_buffer_size;
+  // Adam case need add two more acc_buffer_size
+  if (config.training_context.optimizer == ADAM and not train_storage.getAdam()->isReset())
+  {
+    other_parameters_offset += acc_buffer_size * 2;
+    other_parameters_offset += tensors_size * 4 * 2;
+  }
+
+  // Write this offset
+  cur_ptr = data.data() + 12;
+  std::memcpy(cur_ptr, &other_parameters_offset, sizeof(other_parameters_offset));
+
+  // Move pointer to other parameters offset
+  cur_ptr = data.data() + other_parameters_offset;
+
+  // Write current step
+  std::memcpy(cur_ptr, &config.training_context.num_step, sizeof(config.training_context.num_step));
+
+  cur_ptr += 4;
+  // Write current epoch
+  std::memcpy(cur_ptr, &config.training_context.num_epoch,
+              sizeof(config.training_context.num_epoch));
+
+  return Ok;
+}
+
+// To check checkpoint file format please see https://github.com/Samsung/ONE/discussions/13037
+OMStatus OMCheckpointSaver::createCheckpointData(core::OMRuntimeContext &context,
+                                                 OMTrainingStorage &train_storage,
+                                                 std::vector<char> &data, const OMConfig &config)
+{
+  // Clear data
+  data.clear();
+
+  // Obtain file size and resize vector
+  const size_t data_size = calculateFileSize(context, train_storage, config);
+  data.resize(data_size);
+
+  // Point to start of the buffer
+  char *cur_ptr = data.data();
+
+  // Write MAGIC_NUMBER
+  std::memcpy(cur_ptr, &MAGIC_NUMBER, sizeof(MAGIC_NUMBER));
+  cur_ptr += 2;
+
+  // Write SCHEMA_VERSION
+  std::memcpy(cur_ptr, &SCHEMA_VERSION, sizeof(SCHEMA_VERSION));
+  cur_ptr += 1;
+
+  // Miss RESERVED field
+  cur_ptr += 1;
+
+  // Writes buffers and offsets
+  OMStatus status = writeOffsetsAndBuffers(context, train_storage, config, data);
+
+  assert(status == Ok);
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/core/train/OMTrainingHandler.cpp b/onert-micro/onert-micro/src/core/train/OMTrainingHandler.cpp
new file mode 100644 (file)
index 0000000..2453562
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMDataType.h"
+#include "core/memory/OMMemoryManager.h"
+#include "core/train/OMTrainingHandler.h"
+#include "train/losses_functions/MSE.h"
+#include "train/losses_functions/CrossEntropy.h"
+#include "train/metrics/MSE.h"
+#include "train/metrics/CrossEntropy.h"
+#include "train/metrics/Accuracy.h"
+#include "train/metrics/MAE.h"
+
+using namespace onert_micro::core::train;
+using namespace onert_micro::core;
+using namespace onert_micro::train;
+using namespace onert_micro;
+
+/*
+ * Calculate backpropagation error between calculated data in forward graph and target data
+ */
+OMStatus OMTrainingHandler::handleError(const OMConfig &config, OMRuntimeStorage &forward_storage,
+                                        OMRuntimeStorage &backward_storage,
+                                        OMRuntimeContext &context, uint32_t batch_num)
+{
+  auto forward_outputs = context.getCircleOutputs();
+  // Go over all outputs
+  for (uint32_t i = 0; i < forward_outputs->size(); ++i)
+  {
+    const auto forward_output_index = forward_outputs->operator[](i);
+    const auto forward_output_tensor = context.getTensorByIndex(forward_output_index);
+
+    OMRuntimeShape shape(forward_output_tensor);
+    const auto flat_size = shape.flatSize();
+
+    // Check type
+    assert(forward_output_tensor->type() == circle::TensorType_FLOAT32 && "Unsupported type");
+    if (forward_output_tensor->type() != circle::TensorType_FLOAT32)
+      return UnsupportedType;
+
+    // Get calculated data
+    uint8_t *calculated_data = nullptr;
+    OMStatus status = forward_storage.getDataByTensorIndex(&calculated_data, forward_output_index);
+    assert(calculated_data != nullptr);
+
+    // Get target data
+    auto data_type_size = sizeof(core::OMDataType(forward_output_tensor->type()));
+    size_t offset = batch_num * data_type_size * flat_size;
+    uint8_t *target_data = _training_storage.getTargetData(i) + offset;
+    OMLoss loss_type = config.training_context.loss;
+
+    // Allocate data for error gradient for current calculated data and target data
+    uint8_t *output_grad_data;
+    core::memory::OMMemoryManager::allocateMemory(flat_size * data_type_size, &output_grad_data);
+    // Save error gradient into backward storage associated with current output tensor index
+    backward_storage.saveDataToTensorIndex(output_grad_data, forward_output_index);
+
+    // Handle different loss types
+    switch (loss_type)
+    {
+      case MSE:
+      {
+        losses_functions::MSE::calculateErrorBackpropagation(
+          flat_size, reinterpret_cast<float *>(calculated_data),
+          reinterpret_cast<float *>(target_data), reinterpret_cast<float *>(output_grad_data));
+        break;
+      }
+      case CROSS_ENTROPY:
+      {
+        losses_functions::CrossEntropy::calculateErrorBackpropagation(
+          flat_size, reinterpret_cast<float *>(calculated_data),
+          reinterpret_cast<float *>(target_data), reinterpret_cast<float *>(output_grad_data));
+        break;
+      }
+      default:
+      {
+        assert(false && "Unsupported loss type");
+        return UnsupportedType;
+      }
+    }
+  }
+
+  return Ok;
+}
+
+/*
+ * Update weights with current optimizer logic
+ */
+OMStatus OMTrainingHandler::updateWeights(const OMConfig &config, OMRuntimeContext &context)
+{
+  OMStatus status = Ok;
+
+  // Chose optimizer type
+  switch (config.training_context.optimizer)
+  {
+    case SGD:
+    {
+      auto *sgd_optimizer = _training_storage.getSGD();
+      assert(sgd_optimizer != nullptr);
+      if (sgd_optimizer == nullptr)
+        return UnknownError;
+
+      status = sgd_optimizer->updateWeights(config.training_context, context);
+      assert(status == Ok);
+      // Reset values
+      sgd_optimizer->reset();
+      break;
+    }
+    case ADAM:
+    {
+      auto *adam_optimizer = _training_storage.getAdam();
+      assert(adam_optimizer != nullptr);
+      if (adam_optimizer == nullptr)
+        return UnknownError;
+
+      status = adam_optimizer->updateWeights(config.training_context, context);
+      assert(status == Ok);
+      // Reset values
+      adam_optimizer->reset();
+      break;
+    }
+    default:
+    {
+      assert(false && "Unsupported type");
+      return UnsupportedType;
+    }
+  }
+
+  return status;
+}
+
+/*
+ * Update optimizer state
+ *
+ * WARNING: It is assumed that the backward_storage contains only calculated gradients (this
+ * execution plane creator work).
+ */
+OMStatus OMTrainingHandler::updateOptimizerState(const OMConfig &config,
+                                                 OMRuntimeStorage &backward_storage,
+                                                 OMRuntimeContext &context)
+{
+  OMStatus status = Ok;
+
+  switch (config.training_context.optimizer)
+  {
+    case SGD:
+    {
+      auto *sgd_optimizer = _training_storage.getSGD();
+      assert(sgd_optimizer != nullptr);
+      if (sgd_optimizer == nullptr)
+        return UnknownError;
+
+      sgd_optimizer->handle(backward_storage, context);
+      break;
+    }
+    case ADAM:
+    {
+      auto *adam_optimizer = _training_storage.getAdam();
+      assert(adam_optimizer != nullptr);
+      if (adam_optimizer == nullptr)
+        return UnknownError;
+
+      adam_optimizer->handle(backward_storage, context);
+      break;
+    }
+    default:
+    {
+      assert(false && "Unsupported type");
+      return UnsupportedType;
+    }
+  }
+
+  return status;
+}
+
+void OMTrainingHandler::reset() { _training_storage.reset(); }
+
+/*
+ * Evaluate metric according OMMetrics and save it into metric_val
+ *
+ * Warning: 1) assume that all metric_val for all OMMetrics types actually are float values.
+ *          2) metric_val should be initialized with some value before calling this method due to
+ *             after calculation for current batch_num (the sequence number of the current sample)
+ *             this value is added to metric_val
+ */
+OMStatus OMTrainingHandler::evaluateMetric(OMMetrics metric, void *metric_val,
+                                           OMRuntimeStorage &storage, OMRuntimeContext &context,
+                                           uint32_t batch_num)
+{
+  // Go over all outputs and calculate metric
+  auto forward_outputs = context.getCircleOutputs();
+  for (uint32_t i = 0; i < forward_outputs->size(); ++i)
+  {
+    // Get output tensor
+    const auto forward_output_index = forward_outputs->operator[](i);
+    const auto forward_output_tensor = context.getTensorByIndex(forward_output_index);
+
+    OMRuntimeShape shape(forward_output_tensor);
+    const auto flat_size = shape.flatSize();
+
+    // Check type
+    assert(forward_output_tensor->type() == circle::TensorType_FLOAT32 && "Unsupported type");
+    if (forward_output_tensor->type() != circle::TensorType_FLOAT32)
+      return UnsupportedType;
+
+    // Get calculated data
+    uint8_t *calculated_data = nullptr;
+    OMStatus status = storage.getDataByTensorIndex(&calculated_data, forward_output_index);
+    assert(calculated_data != nullptr);
+
+    // Get target data
+    size_t offset = batch_num * sizeof(core::OMDataType(forward_output_tensor->type())) * flat_size;
+    uint8_t *target_data = _training_storage.getTargetData(i) + offset;
+
+    // Note: always cast it to float
+    float *f_metric_val = reinterpret_cast<float *>(metric_val);
+    switch (metric)
+    {
+      case MSE_METRICS:
+      {
+        // Note: sum up new calculated value for current sample
+        *f_metric_val +=
+          metrics::MSE::calculateValue(flat_size, reinterpret_cast<float *>(calculated_data),
+                                       reinterpret_cast<float *>(target_data));
+        break;
+      }
+      case MAE_METRICS:
+      {
+        // Note: sum up new calculated value for current sample
+        *f_metric_val +=
+          metrics::MAE::calculateValue(flat_size, reinterpret_cast<float *>(calculated_data),
+                                       reinterpret_cast<float *>(target_data));
+        break;
+      }
+      case CROSS_ENTROPY_METRICS:
+      {
+        // Note: sum up new calculated value for current sample
+        *f_metric_val += metrics::CrossEntropy::calculateValue(
+          flat_size, reinterpret_cast<float *>(calculated_data),
+          reinterpret_cast<float *>(target_data));
+        break;
+      }
+      case ACCURACY:
+      {
+        // Note: sum up new calculated value for current sample
+        *f_metric_val +=
+          metrics::Accuracy::calculateValue(flat_size, reinterpret_cast<float *>(calculated_data),
+                                            reinterpret_cast<float *>(target_data));
+        break;
+      }
+      default:
+      {
+        assert(false && "Unsupported loss type");
+        return UnsupportedType;
+      }
+    }
+  }
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/core/train/OMTrainingStorage.cpp b/onert-micro/onert-micro/src/core/train/OMTrainingStorage.cpp
new file mode 100644 (file)
index 0000000..b3167fa
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/train/OMTrainingStorage.h"
+
+#include <cassert>
+
+using namespace onert_micro::core::train;
+using namespace onert_micro::train;
+using namespace onert_micro;
+
+OMStatus OMTrainingStorage::setOptimizer(const OMConfig &config)
+{
+  switch (config.training_context.optimizer)
+  {
+    case SGD:
+    {
+      if (_sgd_optimizer != nullptr)
+      {
+        return UnknownError;
+      }
+      _sgd_optimizer = std::make_unique<optimizers::SGD>();
+      break;
+    }
+    case ADAM:
+    {
+      if (_adam_optimizer != nullptr)
+      {
+        return UnknownError;
+      }
+      _adam_optimizer = std::make_unique<optimizers::Adam>();
+      break;
+    }
+    default:
+      assert(false && "Unsupported Optimizer type");
+  }
+  return Ok;
+}
+
+void OMTrainingStorage::reset()
+{
+  if (_sgd_optimizer)
+    _sgd_optimizer->reset();
+
+  _target_index_to_target_data.clear();
+  _input_index_to_input_data.clear();
+}
diff --git a/onert-micro/onert-micro/src/execute/CMakeLists.txt b/onert-micro/onert-micro/src/execute/CMakeLists.txt
new file mode 100644 (file)
index 0000000..621b54a
--- /dev/null
@@ -0,0 +1,77 @@
+message(STATUS "ONERT MICRO EXECUTE BUILD BEGIN")
+
+include("${OM_PAL_DIR}/pal.cmake")
+
+initialize_pal()
+
+if (NOT PAL_INITIALIZED)
+    message(STATUS "ERROR: PAL Failed to initialize, skip BUILD EXECUTE")
+    return()
+endif()
+
+set(SOURCES
+        OMKernelExecute.cpp
+        OMKernelExecutionBuilder.cpp
+        OMRuntimeKernel.cpp
+        OMUtils.cpp
+        kernels/ReluCommon.cpp
+        kernels/ConvolutionCommon.cpp
+        kernels/MathCommon.cpp
+        kernels/PoolingCommon.cpp
+        kernels/ArgCommon.cpp
+        kernels/ReadKernelDataCommon.cpp
+        kernels/ReshapeCommon.cpp
+        kernels/SpacesBatchesNDCommon.cpp
+        )
+
+# Add configure kernels
+macro(REGISTER_KERNEL OPERATOR, NODE)
+    list(APPEND SOURCES "kernels/${NODE}.cpp")
+endmacro(REGISTER_KERNEL)
+
+# To add REGISTER_KERNEL list
+include(${KERNEL_REGISTER_FILE})
+
+macro(REGISTER_CUSTOM_KERNEL NODE)
+    list(APPEND SOURCES "kernels/${NODE}.cpp")
+endmacro(REGISTER_CUSTOM_KERNEL)
+
+# To add CUSTOM_REGISTER_KERNEL list
+include(${CUSTOM_KERNEL_REGISTER_FILE})
+
+add_library(${OM_EXECUTE_LIB} STATIC ${SOURCES})
+
+target_include_directories(${OM_EXECUTE_LIB} PUBLIC "${OM_INCLUDE_DIR}")
+target_link_libraries(${OM_EXECUTE_LIB} PUBLIC ${OM_CORE_LIB})
+
+target_include_directories(${OM_EXECUTE_LIB} PUBLIC ${OM_PAL_COMMON_DIR})
+add_pal_to_target(${OM_EXECUTE_LIB})
+
+message(STATUS "ONERT MICRO EXECUTE BUILD FINISHED")
+
+if(NOT ENABLE_TEST)
+    return()
+endif(NOT ENABLE_TEST)
+
+nnas_find_package(GTest REQUIRED)
+
+macro(REGISTER_KERNEL OPERATOR, NODE)
+    list(APPEND TEST_SOURCES "kernels/tests/${NODE}.test.cpp")
+endmacro(REGISTER_KERNEL)
+
+include(${KERNEL_REGISTER_FILE})
+
+macro(REGISTER_CUSTOM_KERNEL NODE)
+    list(APPEND TEST_SOURCES "kernels/tests/${NODE}.test.cpp")
+endmacro(REGISTER_CUSTOM_KERNEL)
+
+# To add CUSTOM_REGISTER_KERNEL list
+include(${CUSTOM_KERNEL_REGISTER_FILE})
+
+list(APPEND TEST_SOURCES OMTestUtils.cpp)
+
+GTest_AddTest(${OM_EXECUTE_LIB}_kernels_test ${TEST_SOURCES})
+target_include_directories(${OM_EXECUTE_LIB}_kernels_test PUBLIC "${OM_INCLUDE_DIR}")
+target_link_libraries(${OM_EXECUTE_LIB}_kernels_test ${OM_INTERPRETER_LIB})
+target_link_libraries(${OM_EXECUTE_LIB}_kernels_test onert_micro_coverage)
+target_link_libraries(${OM_EXECUTE_LIB} PUBLIC onert_micro_coverage)
diff --git a/onert-micro/onert-micro/src/execute/OMKernelExecute.cpp b/onert-micro/onert-micro/src/execute/OMKernelExecute.cpp
new file mode 100644 (file)
index 0000000..b01ba22
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecute.h"
+#include "core/OMKernelType.h"
+#include "execute/OMKernelExecutionBuilder.h"
+
+using namespace onert_micro::execute;
+using namespace onert_micro;
+
+OMStatus OMKernelExecute::runForward(OMExecuteArgs &execute_args,
+                                     core::memory::OMRuntimeAllocator &allocator)
+{
+  OMStatus status = Ok;
+
+  core::OMRuntimeContext &context = execute_args.runtime_context;
+  core::OMRuntimeStorage &storage = execute_args.runtime_storage;
+
+  const core::reader::CircleOperators *operators = context.getCircleOperators();
+
+  const auto num_operators = static_cast<uint16_t>(operators->size());
+  const auto *op_codes = context.getCircleOpcodes();
+
+  for (uint16_t i = 0; i < num_operators; ++i)
+  {
+    status = allocator.allocate(i, &context, &storage);
+
+    if (status != Ok)
+      return status;
+
+    core::OMBuilderID builder_id = core::OMBuilderID::Size;
+    const circle::Operator *op = operators->operator[](i);
+    uint32_t index = op->opcode_index();
+
+    assert(index < op_codes->size());
+
+    const auto opcode = op_codes->operator[](index);
+
+    status = core::getBuilderId(opcode, builder_id);
+
+    assert(status == Ok);
+    if (status != Ok)
+      return status;
+
+    execute_args.kernel_index = i;
+
+    KernelExecuteFunc *execute_func = nullptr;
+    if (size_t(builder_id) < size_t(core::OMBuilderID::BuiltinOperatorsSize))
+    {
+      // Builtin operator
+      status = kernel_builtin_execute.getKernelExecuteFunc(builder_id, &execute_func);
+    }
+    else
+    {
+      // Custom
+      status = kernel_custom_execute.getKernelExecuteFunc(builder_id, &execute_func);
+    }
+
+    assert(execute_func != nullptr);
+
+    if (status != Ok)
+      return status;
+
+    status = execute_func(execute_args);
+
+    assert(status == Ok);
+
+    if (status != Ok)
+      return status;
+
+    status = allocator.deallocate(i, &storage);
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/OMKernelExecutionBuilder.cpp b/onert-micro/onert-micro/src/execute/OMKernelExecutionBuilder.cpp
new file mode 100644 (file)
index 0000000..630c9cf
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
diff --git a/onert-micro/onert-micro/src/execute/OMRuntimeKernel.cpp b/onert-micro/onert-micro/src/execute/OMRuntimeKernel.cpp
new file mode 100644 (file)
index 0000000..afa3d64
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro::execute;
+using namespace onert_micro;
+
+OMStatus onert_micro::execute::OMRuntimeKernel::readKernel(uint16_t op_index,
+                                                           core::OMRuntimeContext &runtime_context)
+{
+  first_operator = runtime_context.getCircleOperatorAt(op_index);
+  const circle::Operator *last_operator = runtime_context.getCircleOperatorAt(op_index);
+
+  inputs_num = first_operator->inputs()->size();
+  assert(inputs_num <= maxInputSize);
+
+  if (inputs_num > maxInputSize)
+    return UnknownError;
+
+  outputs_num = last_operator->outputs()->size();
+  assert(outputs_num <= maxOutputSize);
+
+  if (outputs_num > maxOutputSize)
+    return UnknownError;
+
+  assert(inputs_num > 0 and outputs_num > 0);
+
+  // Read inputs
+  {
+    const auto *inputs_op = first_operator->inputs();
+    for (uint32_t i = 0; i < inputs_num; ++i)
+    {
+      inputs_index[i] = inputs_op->operator[](i);
+      if (inputs_index[i] != -1)
+        inputs[i] = runtime_context.getTensorByIndex(inputs_index[i]);
+    }
+  }
+  // Read outputs
+  {
+    const auto *outputs_op = last_operator->outputs();
+    for (uint32_t i = 0; i < outputs_num; ++i)
+    {
+      outputs_index[i] = outputs_op->operator[](i);
+      if (outputs_index[i] != -1)
+        outputs[i] = runtime_context.getTensorByIndex(outputs_index[i]);
+    }
+  }
+
+  return Ok;
+}
+
+// Note: if inplace then first input and first output will be inplace
+OMStatus onert_micro::execute::OMRuntimeKernel::getDataFromStorage(uint16_t op_index,
+                                                                   core::OMRuntimeStorage &storage,
+                                                                   core::OMRuntimeContext &context)
+{
+  OMStatus status = Ok;
+
+  for (uint32_t i = 0; i < inputs_num; ++i)
+  {
+    if (inputs_index[i] == -1)
+      continue;
+    status = storage.getDataByTensorIndex(&inputs_data[i], inputs_index[i]);
+    if (inputs_data[i] == nullptr)
+      status = context.getConstDataByTensorIndex(&inputs_data[i], inputs_index[i]);
+    if (status != Ok)
+      return status;
+  }
+
+  for (uint32_t i = 0; i < outputs_num; ++i)
+  {
+    if (outputs_index[i] == -1)
+      continue;
+    status = storage.getDataByTensorIndex(&outputs_data[i], outputs_index[i]);
+
+    if (storage.getKernelType(op_index) == core::Inplace)
+    {
+      outputs_data[i] = inputs_data[i];
+      status = storage.removeTensorFromTensorIndexToData(inputs_index[i]);
+
+      if (status != Ok)
+        return status;
+
+      status = storage.saveDataToTensorIndex(outputs_data[i], outputs_index[i]);
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/OMTestUtils.cpp b/onert-micro/onert-micro/src/execute/OMTestUtils.cpp
new file mode 100644 (file)
index 0000000..cae389e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+
+#include "OMInterpreter.h"
+
+using ::testing::FloatNear;
+using ::testing::Matcher;
+
+using namespace onert_micro;
+
+Matcher<std::vector<float>> execute::testing::FloatArrayNear(const std::vector<float> &values,
+                                                             float max_abs_error)
+{
+  std::vector<Matcher<float>> matchers;
+  matchers.reserve(values.size());
+  for (const float v : values)
+  {
+    matchers.emplace_back(FloatNear(v, max_abs_error));
+  }
+  return ElementsAreArray(matchers);
+}
+
+void execute::testing::checkNEGSISOKernel(onert_micro::test_model::NegTestDataBase *test_data_base)
+{
+  onert_micro::OMInterpreter interpreter;
+  onert_micro::OMConfig config;
+
+  interpreter.importModel(reinterpret_cast<const char *>(test_data_base->get_model_ptr()), config);
+}
diff --git a/onert-micro/onert-micro/src/execute/OMUtils.cpp b/onert-micro/onert-micro/src/execute/OMUtils.cpp
new file mode 100644 (file)
index 0000000..a207083
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMUtils.h"
+#include <cmath>
+
+using namespace onert_micro::execute;
+using namespace onert_micro;
+
+void onert_micro::execute::quantizeMultiplier(double double_multiplier,
+                                              int32_t *quantized_multiplier, int *shift)
+{
+  if (double_multiplier == 0.0)
+  {
+    *quantized_multiplier = 0;
+    *shift = 0;
+    return;
+  }
+
+  const double q = std::frexp(double_multiplier, shift);
+  auto q_fixed = static_cast<int64_t>(std::round(q * (int64_t(1) << 31)));
+
+  if (q_fixed == (int64_t(1) << 31))
+  {
+    q_fixed /= 2;
+    ++*shift;
+  }
+  assert(q_fixed <= std::numeric_limits<int32_t>::max());
+  // A shift amount smaller than -31 would cause all bits to be shifted out
+  // and thus all results would be zero. We implement that instead with
+  // q_fixed==0, so as to avoid hitting issues with right-shift
+  // operations with shift amounts greater than 31. Note that this happens
+  // roughly when abs(double_multiplier) < 2^-31 and the present handling means
+  // that we're effectively flushing tiny double_multiplier's to zero.
+  // We could conceivably handle values in the range (roughly) [32, 63]
+  // as 'denormals' i.e. (shift==0, q_fixed < 2^30). In that point of view
+  // the present handling is just doing 'flush denormals to zero'. We could
+  // reconsider and actually generate nonzero denormals if a need arises.
+  if (*shift < -31)
+  {
+    *shift = 0;
+    q_fixed = 0;
+  }
+  *quantized_multiplier = static_cast<int32_t>(q_fixed);
+}
+
+void onert_micro::execute::quantizeMultiplierSmallerThanOneExp(double double_multiplier,
+                                                               int32_t *quantized_multiplier,
+                                                               int *left_shift)
+{
+  assert(double_multiplier < 1.0);
+  assert(double_multiplier > 0.0);
+  int shift;
+  onert_micro::execute::quantizeMultiplier(double_multiplier, quantized_multiplier, &shift);
+  assert(shift <= 0);
+  *left_shift = shift;
+}
+
+namespace
+{
+OMStatus calculateActivationRangeQuantizedImpl(circle::ActivationFunctionType activation,
+                                               int32_t qmin, int32_t qmax, int32_t zero_point,
+                                               float scale, int32_t *activation_min,
+                                               int32_t *activation_max)
+{
+  assert(scale != 0.f);
+
+  auto quantize = [scale, zero_point](float x) {
+    return zero_point + static_cast<int32_t>(std::round(x / scale));
+  };
+
+  switch (activation)
+  {
+    case circle::ActivationFunctionType::ActivationFunctionType_NONE:
+    case circle::ActivationFunctionType::ActivationFunctionType_TANH:
+      *activation_min = qmin;
+      *activation_max = qmax;
+      break;
+    case circle::ActivationFunctionType::ActivationFunctionType_RELU:
+      *activation_min = std::max(qmin, quantize(0.0f));
+      *activation_max = qmax;
+      break;
+    case circle::ActivationFunctionType::ActivationFunctionType_RELU_N1_TO_1:
+      *activation_min = std::max(qmin, quantize(-1.0f));
+      *activation_max = std::min(qmax, quantize(1.0f));
+      break;
+    case circle::ActivationFunctionType::ActivationFunctionType_RELU6:
+      *activation_min = std::max(qmin, quantize(0.0f));
+      *activation_max = std::min(qmax, quantize(6.0f));
+      break;
+    default:
+      assert(false && "Unsupported activation.");
+      return UnsupportedActivation;
+  }
+  return Ok;
+}
+} // namespace
+
+OMStatus onert_micro::execute::calculateActivationRangeQuantized(
+  circle::ActivationFunctionType activation, int32_t output_zero_point, float output_scale,
+  circle::TensorType data_type, int32_t *activation_min, int32_t *activation_max)
+{
+  int32_t qmin;
+  int32_t qmax;
+  switch (data_type)
+  {
+    case circle::TensorType_UINT8:
+      qmin = 0;
+      qmax = std::numeric_limits<uint8_t>::max();
+      break;
+    case circle::TensorType_INT8:
+      qmin = std::numeric_limits<int8_t>::min();
+      qmax = std::numeric_limits<int8_t>::max();
+      break;
+    case circle::TensorType_INT16:
+      // For now, assume that signed int16 type implies signed symmetric quantization.
+      assert(output_zero_point == 0);
+      qmin = std::numeric_limits<int16_t>::min();
+      qmax = std::numeric_limits<int16_t>::max();
+      break;
+    default:
+      assert(false && "Unsupported type.");
+      return UnsupportedType;
+  }
+
+  return calculateActivationRangeQuantizedImpl(activation, qmin, qmax, output_zero_point,
+                                               output_scale, activation_min, activation_max);
+}
+
+void onert_micro::execute::readQuantParams(const circle::Tensor *tensor, long &zero_point,
+                                           float &scale)
+{
+  // additional check
+  assert(tensor->quantization() != nullptr); // Fix caller
+  assert(tensor->quantization()->scale() != nullptr and
+         tensor->quantization()->scale()->size() == 1); // Fix caller
+  assert(tensor->quantization()->zero_point() != nullptr and
+         tensor->quantization()->zero_point()->size() == 1); // Fix caller
+
+  // read zero point
+  zero_point = tensor->quantization()->zero_point()->operator[](0);
+  // read scale
+  scale = tensor->quantization()->scale()->operator[](0);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Abs.cpp b/onert-micro/onert-micro/src/execute/kernels/Abs.cpp
new file mode 100644 (file)
index 0000000..4d86106
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALAbs.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleAbs(const OMExecuteArgs &execute_args)
+{
+  auto abs_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                             const core::OMRuntimeShape &output_shape, float *output_data) {
+    assert(input_shape == output_shape);
+    return pal::Abs(input_shape, input_data, output_data);
+  };
+
+  return execute_math_common(execute_args, abs_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Add.cpp b/onert-micro/onert-micro/src/execute/kernels/Add.cpp
new file mode 100644 (file)
index 0000000..c08f9c4
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMUtils.h"
+#include "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/OMUtils.h"
+
+#include "core/OMRuntimeShape.h"
+#include "PALAdd.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+void calculateQuantParams(core::ArithmeticQuantParams &params, const circle::Tensor *input1,
+                          const circle::Tensor *input2, const circle::Tensor *output,
+                          circle::ActivationFunctionType act)
+{
+  long input1_zp;
+  long input2_zp;
+  long output_zp;
+
+  float input1_scale;
+  float input2_scale;
+  float output_scale;
+
+  // Read input1 quant params
+  readQuantParams(input1, input1_zp, input1_scale);
+  // Read input2 quant params
+  readQuantParams(input2, input2_zp, input2_scale);
+  // Read output quant params
+  readQuantParams(output, output_zp, output_scale);
+
+  params.input1_offset = -static_cast<int32_t>(input1_zp);
+  params.input2_offset = -static_cast<int32_t>(input2_zp);
+  params.output_offset = static_cast<int32_t>(output_zp);
+  params.left_shift = (output->type() == circle::TensorType_INT16) ? 15 : 20;
+  const double twice_max_input_scale =
+    2 * static_cast<double>(std::max(input1_scale, input2_scale));
+  const double real_input1_multiplier = static_cast<double>(input1_scale) / twice_max_input_scale;
+  const double real_input2_multiplier = static_cast<double>(input2_scale) / twice_max_input_scale;
+  const double real_output_multiplier =
+    twice_max_input_scale / ((1 << params.left_shift) * static_cast<double>(output_scale));
+
+  quantizeMultiplierSmallerThanOneExp(real_input1_multiplier, &params.input1_multiplier,
+                                      &params.input1_shift);
+
+  quantizeMultiplierSmallerThanOneExp(real_input2_multiplier, &params.input2_multiplier,
+                                      &params.input2_shift);
+
+  quantizeMultiplierSmallerThanOneExp(real_output_multiplier, &params.output_multiplier,
+                                      &params.output_shift);
+
+  calculateActivationRangeQuantized(act, output_zp, output_scale, output->type(),
+                                    &params.quantized_activation_min,
+                                    &params.quantized_activation_max);
+}
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+// TODO: reduce code duplication with Mul, Sub
+OMStatus onert_micro::execute::execute_kernel_CircleAdd(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input1;
+  const circle::Tensor *input2;
+  const circle::Tensor *output;
+
+  uint8_t *input1_data;
+  uint8_t *input2_data;
+  uint8_t *output_data;
+
+  uint16_t input1_index = 0;
+  uint16_t input2_index = 0;
+
+  const circle::AddOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input1 = runtime_kernel.inputs[input1TensorIdx];
+    input2 = runtime_kernel.inputs[input2TensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input1 != nullptr);
+    assert(input2 != nullptr);
+    assert(output != nullptr);
+
+    runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+
+    input1_data = runtime_kernel.inputs_data[input1TensorIdx];
+    input2_data = runtime_kernel.inputs_data[input2TensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+    assert(input1_data != nullptr);
+    assert(input2_data != nullptr);
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_AddOptions();
+
+    input1_index = runtime_kernel.inputs_index[input1TensorIdx];
+    input2_index = runtime_kernel.inputs_index[input2TensorIdx];
+  }
+
+  OMStatus status;
+
+  core::OMRuntimeShape input1_shape(input1);
+  core::OMRuntimeShape input2_shape(input2);
+  core::OMRuntimeShape output_shape(output);
+
+#ifndef DIS_DYN_SHAPES
+  // Check dynamic shapes
+  if (runtime_storage.getDynamicTensorSize(input1_index) != -1)
+    input1_shape = output_shape;
+
+  if (runtime_storage.getDynamicTensorSize(input2_index) != -1)
+    input2_shape = output_shape;
+#endif // DIS_DYN_SHAPES
+
+  // Check broadcast property
+  core::BinaryArithmeticBroadcastParams params{};
+  const bool need_broadcast = pal::processBroadcastShapes(input1_shape, input2_shape, &params);
+  switch (input1->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      execute::calculateActivationRange(options->fused_activation_function(),
+                                        &params.float_activation_min, &params.float_activation_max);
+      if (need_broadcast)
+      {
+        status = pal::BroadcastAdd4DSlow(
+          params, input1_shape, core::utils::castInputData<float>(input1_data), input2_shape,
+          core::utils::castInputData<float>(input2_data), output_shape,
+          core::utils::castOutputData<float>(output_data));
+      }
+      else
+      {
+        status =
+          pal::Add(params, output_shape.flatSize(), core::utils::castInputData<float>(input1_data),
+                   core::utils::castInputData<float>(input2_data),
+                   core::utils::castOutputData<float>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
+    case circle::TensorType_INT64:
+    {
+      execute::calculateActivationRange(options->fused_activation_function(),
+                                        &params.int64_activation_min, &params.int64_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastAdd4DSlow(
+          params, input1_shape, core::utils::castInputData<int64_t>(input1_data), input2_shape,
+          core::utils::castInputData<int64_t>(input2_data), output_shape,
+          core::utils::castOutputData<int64_t>(output_data));
+      }
+      else
+      {
+        status = pal::Add(params, input1_shape.flatSize(),
+                          core::utils::castInputData<int64_t>(input1_data),
+                          core::utils::castInputData<int64_t>(input2_data),
+                          core::utils::castOutputData<int64_t>(output_data));
+      }
+    }
+    break;
+    case circle::TensorType_INT32:
+    {
+      execute::calculateActivationRange(options->fused_activation_function(),
+                                        &params.int32_activation_min, &params.int32_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastAdd4DSlow(
+          params, input1_shape, core::utils::castInputData<int32_t>(input1_data), input2_shape,
+          core::utils::castInputData<int32_t>(input2_data), output_shape,
+          core::utils::castOutputData<int32_t>(output_data));
+      }
+      else
+      {
+        status = pal::Add(params, input1_shape.flatSize(),
+                          core::utils::castInputData<int32_t>(input1_data),
+                          core::utils::castInputData<int32_t>(input2_data),
+                          core::utils::castOutputData<int32_t>(output_data));
+      }
+    }
+    break;
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+    {
+      core::ArithmeticQuantParams add_params{};
+
+      calculateQuantParams(add_params, input1, input2, output,
+                           options->fused_activation_function());
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastAdd4DSlow(
+          add_params, input1_shape, core::utils::castInputData<int8_t>(input1_data), input2_shape,
+          core::utils::castInputData<int8_t>(input2_data), output_shape,
+          core::utils::castOutputData<int8_t>(output_data));
+      }
+      else
+      {
+        status = pal::Add(add_params, input1_shape.flatSize(),
+                          core::utils::castInputData<int8_t>(input1_data),
+                          core::utils::castInputData<int8_t>(input2_data),
+                          core::utils::castOutputData<int8_t>(output_data));
+      }
+    }
+    break;
+#endif // DIF_QUANT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/AddN.cpp b/onert-micro/onert-micro/src/execute/kernels/AddN.cpp
new file mode 100644 (file)
index 0000000..5ab3241
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "core/OMRuntimeShape.h"
+#include "PALAddN.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+constexpr uint32_t outputTensorIdx = 0;
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleAddN(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+  const circle::Tensor *output;
+
+  uint8_t *output_data;
+
+  // Read kernel
+  execute::OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  output = runtime_kernel.outputs[outputTensorIdx];
+  assert(output != nullptr);
+
+  runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  output_data = runtime_kernel.outputs_data[outputTensorIdx];
+  assert(output_data != nullptr);
+
+  OMStatus status;
+
+  core::OMRuntimeShape output_shape(output);
+  switch (output->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status = onert_micro::execute::pal::AddN<float>(
+        output_shape.flatSize(), runtime_kernel.inputs_num,
+        reinterpret_cast<const float *const *>(runtime_kernel.inputs_data),
+        reinterpret_cast<float *>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/ArgCommon.cpp b/onert-micro/onert-micro/src/execute/kernels/ArgCommon.cpp
new file mode 100644 (file)
index 0000000..eb82073
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ArgCommon.h"
+#include "PALArgMax.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_arg_common(
+  const OMExecuteArgs &execute_args,
+  const std::function<OMStatus(const core::OMRuntimeShape &input1_shape, const float *input1_data,
+                               const int *input2_data, const core::OMRuntimeShape &output_shape,
+                               int *output_data)> &f_float)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+  const circle::Tensor *output;
+  const circle::Tensor *input1;
+  const circle::Tensor *input2;
+
+  uint8_t *output_data;
+  uint8_t *input_data;
+  uint8_t *axis_data;
+
+  // Read kernel
+  execute::OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  output = runtime_kernel.outputs[outputTensorIdx];
+  assert(output != nullptr);
+
+  input1 = runtime_kernel.inputs[input1TensorIdx];
+  assert(input1 != nullptr);
+
+  input2 = runtime_kernel.inputs[input2TensorIdx];
+  assert(input2 != nullptr);
+
+  runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+
+  output_data = runtime_kernel.outputs_data[outputTensorIdx];
+  assert(output_data != nullptr);
+
+  input_data = runtime_kernel.inputs_data[input1TensorIdx];
+  assert(input_data != nullptr);
+
+  axis_data = runtime_kernel.inputs_data[input2TensorIdx];
+  assert(axis_data != nullptr);
+
+  OMStatus status;
+  const core::OMRuntimeShape input1_shape(input1);
+  const core::OMRuntimeShape output_shape(output);
+  switch (input1->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status = f_float(input1_shape, reinterpret_cast<const float *>(input_data),
+                       reinterpret_cast<const int *>(axis_data), output_shape,
+                       reinterpret_cast<int *>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/ArgMax.cpp b/onert-micro/onert-micro/src/execute/kernels/ArgMax.cpp
new file mode 100644 (file)
index 0000000..dcf08be
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ArgCommon.h"
+#include "PALArgMax.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+OMStatus onert_micro::execute::execute_kernel_CircleArgMax(const OMExecuteArgs &execute_args)
+{
+  auto arg_max_float_lambda = [](const core::OMRuntimeShape &input1_shape, const float *input1_data,
+                                 const int *input2_data, const core::OMRuntimeShape &output_shape,
+                                 int *output_data) {
+    return onert_micro::execute::pal::ArgMax(input1_shape, input1_data, input2_data, output_shape,
+                                             output_data);
+  };
+
+  return execute_arg_common(execute_args, arg_max_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/ArgMin.cpp b/onert-micro/onert-micro/src/execute/kernels/ArgMin.cpp
new file mode 100644 (file)
index 0000000..a4afc72
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ArgCommon.h"
+#include "PALArgMin.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+OMStatus onert_micro::execute::execute_kernel_CircleArgMin(const OMExecuteArgs &execute_args)
+{
+  auto arg_max_float_lambda = [](const core::OMRuntimeShape &input1_shape, const float *input1_data,
+                                 const int *input2_data, const core::OMRuntimeShape &output_shape,
+                                 int *output_data) {
+    return onert_micro::execute::pal::ArgMin(input1_shape, input1_data, input2_data, output_shape,
+                                             output_data);
+  };
+
+  return execute_arg_common(execute_args, arg_max_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/AveragePool2D.cpp b/onert-micro/onert-micro/src/execute/kernels/AveragePool2D.cpp
new file mode 100644 (file)
index 0000000..671b005
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/PoolingCommon.h"
+#include "PALAveragePool2D.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleAveragePool2D(const OMExecuteArgs &execute_args)
+{
+  auto avg_pool_float_lambda = [](const core::Pool2DParams &params,
+                                  const core::OMRuntimeShape &input_shape, const float *input_data,
+                                  const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::AveragePool(params, input_shape, input_data, output_shape, output_data);
+  };
+
+#ifndef DIS_QUANT
+  auto avg_pool_int8_lambda = [](const core::Pool2DParams &params,
+                                 const core::OMRuntimeShape &input_shape, const int8_t *input_data,
+                                 const core::OMRuntimeShape &output_shape, int8_t *output_data) {
+    return pal::AveragePool(params, input_shape, input_data, output_shape, output_data);
+  };
+#else
+  auto avg_pool_int8_lambda = [](const core::Pool2DParams &params,
+                                 const core::OMRuntimeShape &input_shape, const int8_t *input_data,
+                                 const core::OMRuntimeShape &output_shape,
+                                 int8_t *output_data) { return UnsupportedType; };
+#endif // DIS_QUANT
+
+  return execute_pooling_common(execute_args, avg_pool_float_lambda, avg_pool_int8_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/BatchToSpaceND.cpp b/onert-micro/onert-micro/src/execute/kernels/BatchToSpaceND.cpp
new file mode 100644 (file)
index 0000000..c54a547
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/SpacesBatchesNDCommon.h"
+#include "PALBatchToSpaceND.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+OMStatus onert_micro::execute::execute_kernel_CircleBatchToSpaceND(
+  const onert_micro::execute::OMExecuteArgs &execute_args)
+{
+  auto batch_to_space_float_lambda =
+    [](const core::OMRuntimeShape &input1_shape, const float *input1_data,
+       const core::OMRuntimeShape &input2_shape, const int32_t *block_shape_data,
+       const core::OMRuntimeShape &input3_shape, const int32_t *crops_data,
+       const core::OMRuntimeShape &output_shape, float *output_data) {
+      return pal::BatchToSpaceND<float>(input1_shape, input1_data, input2_shape, block_shape_data,
+                                        input3_shape, crops_data, output_shape, output_data);
+    };
+
+  return execute_spaces_batches_nd_common(execute_args, batch_to_space_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Concatenation.cpp b/onert-micro/onert-micro/src/execute/kernels/Concatenation.cpp
new file mode 100644 (file)
index 0000000..b4ed31e
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "core/OMUtils.h"
+#include "core/OMRuntimeShape.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMUtils.h"
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "OMStatus.h"
+#include "PALConcatenation.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t numOutput = 1;
+
+template <typename T> OMStatus evalGeneric(OMRuntimeKernel &runtime_kernel)
+{
+  auto output = runtime_kernel.outputs[0];
+
+  const auto *options = runtime_kernel.first_operator->builtin_options_as_ConcatenationOptions();
+
+  core::OMRuntimeShape output_shape(output);
+
+  int axis = options->axis();
+  if (axis < 0)
+    axis += output_shape.dimensionsCount();
+
+  const auto input_size = runtime_kernel.inputs_num;
+
+  std::vector<const T *> all_input_data(input_size);
+  std::vector<uint32_t> all_shape(input_size);
+
+  OMStatus status = Ok;
+  for (int32_t i = 0; i < input_size; ++i)
+  {
+    const auto *tensor = runtime_kernel.inputs[i];
+    core::OMRuntimeShape shape(tensor);
+
+    uint8_t *tensor_data = runtime_kernel.inputs_data[i];
+    all_input_data[i] = core::utils::castInputData<T>(tensor_data);
+    all_shape[i] = shape.dims(axis);
+  }
+
+  auto *output_data = core::utils::castOutputData<T>(runtime_kernel.outputs_data[0]);
+
+  core::ConcatenationParams params{};
+  params.axis = axis;
+  params.num_inputs = input_size;
+  status = pal::Concatenation<T>(params, all_shape, all_input_data, output_shape, output_data);
+
+  return status;
+}
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleConcatenation(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  execute::OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  const auto *t0 = runtime_kernel.inputs[0];
+  OMStatus status = Ok;
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+
+  if (status != Ok)
+    return status;
+
+  switch (t0->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      status = evalGeneric<float>(runtime_kernel);
+      break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+      status = evalGeneric<int8_t>(runtime_kernel);
+      break;
+#endif // DIS_QUANT
+    case circle::TensorType_INT32:
+      status = evalGeneric<int32_t>(runtime_kernel);
+      break;
+    case circle::TensorType_INT64:
+      status = evalGeneric<int64_t>(runtime_kernel);
+      break;
+    default:
+      assert(false && "Unsupported type.");
+      status = UnsupportedType;
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Conv2D.cpp b/onert-micro/onert-micro/src/execute/kernels/Conv2D.cpp
new file mode 100644 (file)
index 0000000..63a4f3f
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+#include "execute/kernels/ConvolutionCommon.h"
+
+#include "PALConv2D.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t weightTensorIdx = 1;
+constexpr uint32_t biasTensorIdx = 2;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesn't currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleConv2D(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *weight;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *weight_data;
+  uint8_t *bias_data;
+  uint8_t *output_data;
+
+  const circle::Conv2DOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    weight = runtime_kernel.inputs[weightTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(weight != nullptr);
+    // Bias can be nullptr
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    weight_data = runtime_kernel.inputs_data[weightTensorIdx];
+    bias_data = runtime_kernel.inputs_data[biasTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+    assert(input_data != nullptr);
+    assert(weight_data != nullptr);
+    // Bias can be nullptr
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_Conv2DOptions();
+  }
+
+  OMStatus status;
+
+  int32_t padding_h = 0;
+  int32_t padding_w = 0;
+
+  OMRuntimeShape weight_shape(weight);
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  const int input_width = input_shape.dims(2);
+  const int input_height = input_shape.dims(1);
+  const int weight_width = weight_shape.dims(2);
+  const int weight_height = weight_shape.dims(1);
+  execute::computePaddingHeightWidth(options->stride_h(), options->stride_w(),
+                                     options->dilation_h_factor(), options->dilation_w_factor(),
+                                     input_height, input_width, weight_height, weight_width,
+                                     options->padding(), &padding_h, &padding_w);
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      FloatConv2D params{};
+      status = calculateActivationRange(options->fused_activation_function(),
+                                        &params.activation_min, &params.activation_max);
+      params.stride_w = options->stride_w();
+      params.stride_h = options->stride_h();
+      params.dilation_width_factor = options->dilation_w_factor();
+      params.dilation_height_factor = options->dilation_h_factor();
+      params.pad_h = padding_h;
+      params.pad_w = padding_w;
+
+      if (status != Ok)
+        return status;
+
+      status = pal::ConvFloat(&params, input_shape, core::utils::castInputData<float>(input_data),
+                              weight_shape, core::utils::castInputData<float>(weight_data),
+                              core::utils::castInputData<float>(bias_data), output_shape,
+                              core::utils::castOutputData<float>(output_data));
+      assert(status == Ok);
+    }
+    break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+    {
+      ConvQuant params{};
+      params.pad_h = padding_h;
+      params.pad_w = padding_w;
+
+      const auto padding = options->padding();
+      const auto stride_height = options->stride_h();
+      const auto stride_width = options->stride_w();
+      const auto dilation_height_factor = options->dilation_h_factor();
+      const auto dilation_width_factor = options->dilation_h_factor();
+
+      params.stride_height = stride_height;
+      params.stride_width = stride_width;
+      params.dilation_height_factor = dilation_height_factor;
+      params.dilation_width_factor = dilation_width_factor;
+
+      status =
+        createConvParams(params, input, weight, output, options->fused_activation_function());
+      assert(status == Ok);
+      if (status != Ok)
+        return status;
+
+      status =
+        pal::ConvPerChannel(params, input_shape, core::utils::castInputData<int8_t>(input_data),
+                            weight_shape, core::utils::castInputData<int8_t>(weight_data),
+                            core::utils::castInputData<int32_t>(bias_data), output_shape,
+                            core::utils::castOutputData<int8_t>(output_data));
+    }
+    break;
+#endif // DIS_QUANT
+    default:
+    {
+      status = UnsupportedActivation;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/ConvolutionCommon.cpp b/onert-micro/onert-micro/src/execute/kernels/ConvolutionCommon.cpp
new file mode 100644 (file)
index 0000000..b670ed1
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ConvolutionCommon.h"
+#include "execute/OMUtils.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::execute::createConvParams(core::ConvQuant &params,
+                                                const circle::Tensor *input,
+                                                const circle::Tensor *filter,
+                                                const circle::Tensor *output,
+                                                circle::ActivationFunctionType act_type)
+{
+  assert(input->quantization() != nullptr);  // Fix caller
+  assert(filter->quantization() != nullptr); // Fix caller
+  assert(output->quantization() != nullptr); // Fix caller
+
+  const auto *input_scales = input->quantization()->scale();
+  const auto *filter_scales = filter->quantization()->scale();
+  const auto *output_scales = output->quantization()->scale();
+
+  assert(input_scales != nullptr);  // Fix caller
+  assert(filter_scales != nullptr); // Fix caller
+  assert(output_scales != nullptr); // Fix caller
+
+  assert(input_scales->size() != 0);  // Fix caller
+  assert(filter_scales->size() != 0); // Fix caller
+  assert(output_scales->size() != 0); // Fix caller
+
+  const auto input_zero_points = input->quantization()->zero_point();
+  const auto filter_zero_points = filter->quantization()->zero_point();
+  const auto output_zero_points = output->quantization()->zero_point();
+
+  assert(input_zero_points != nullptr);  // Fix caller
+  assert(filter_zero_points != nullptr); // Fix caller
+  assert(output_zero_points != nullptr); // Fix caller
+
+  assert(input_zero_points->size() != 0);  // Fix caller
+  assert(filter_zero_points->size() != 0); // Fix caller
+  assert(output_zero_points->size() != 0); // Fix caller
+
+  const auto input_zp = input_zero_points->operator[](0);
+  const auto filter_zp = filter_zero_points->operator[](0);
+  const auto output_zp = output_zero_points->operator[](0);
+
+  const auto output_scale = output_scales->operator[](0);
+
+  int32_t activation_min{};
+  int32_t activation_max{};
+  OMStatus status = execute::calculateActivationRangeQuantized(
+    act_type, static_cast<int32_t>(output_zp), output_scale, output->type(), &activation_min,
+    &activation_max);
+  assert(status == Ok);
+  if (status != Ok)
+    return status;
+
+  // The kernel expects input and filter zero points to be negated.
+  params.input_offset = -static_cast<int32_t>(input_zp);    // Note the '-'.
+  params.weights_offset = -static_cast<int32_t>(filter_zp); // Note the '-'.
+  params.output_offset = static_cast<int32_t>(output_zp);
+  params.quantized_activation_min = activation_min;
+  params.quantized_activation_max = activation_max;
+
+  assert(filter_scales->size() > 1); // Support only channel-wise quantization
+  // Channel-wise quantization
+  const auto input_scale = input_scales->operator[](0);
+  const std::vector<double> effective_output_scale =
+    execute::getQuantizedConvolutionMultiplers(input_scale, filter_scales, output_scale);
+
+  size_t n = effective_output_scale.size();
+  params.per_channel_output_shift.resize(n);
+  params.per_channel_output_multiplier.resize(n);
+  for (size_t i = 0; i < n; ++i)
+  {
+    execute::quantizeMultiplier(effective_output_scale[i], &params.per_channel_output_multiplier[i],
+                                &params.per_channel_output_shift[i]);
+  }
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Cos.cpp b/onert-micro/onert-micro/src/execute/kernels/Cos.cpp
new file mode 100644 (file)
index 0000000..ac14f8e
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALCos.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleCos(const OMExecuteArgs &execute_args)
+{
+  auto cos_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                             const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Cos(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, cos_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/DepthwiseConv2D.cpp b/onert-micro/onert-micro/src/execute/kernels/DepthwiseConv2D.cpp
new file mode 100644 (file)
index 0000000..23c6e9d
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+#include "execute/kernels/ConvolutionCommon.h"
+
+#include "PALDepthwiseConv2D.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t weightTensorIdx = 1;
+constexpr uint32_t biasTensorIdx = 2;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesn't currently support dynamic shapes
+OMStatus
+onert_micro::execute::execute_kernel_CircleDepthwiseConv2D(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *weight;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *weight_data;
+  uint8_t *bias_data;
+  uint8_t *output_data;
+
+  const circle::DepthwiseConv2DOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    weight = runtime_kernel.inputs[weightTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(weight != nullptr);
+    // Bias can be nullptr
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    weight_data = runtime_kernel.inputs_data[weightTensorIdx];
+    bias_data = runtime_kernel.inputs_data[biasTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+    assert(input_data != nullptr);
+    assert(weight_data != nullptr);
+    // Bias can be nullptr
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_DepthwiseConv2DOptions();
+  }
+
+  OMStatus status;
+
+  int32_t padding_h = 0;
+  int32_t padding_w = 0;
+
+  OMRuntimeShape weight_shape(weight);
+  OMRuntimeShape input_shape(input);
+
+  const int input_width = input_shape.dims(2);
+  const int input_height = input_shape.dims(1);
+  const int weight_width = weight_shape.dims(2);
+  const int weight_height = weight_shape.dims(1);
+  execute::computePaddingHeightWidth(options->stride_h(), options->stride_w(),
+                                     options->dilation_h_factor(), options->dilation_w_factor(),
+                                     input_height, input_width, weight_height, weight_width,
+                                     options->padding(), &padding_h, &padding_w);
+
+  const auto output_shape = OMRuntimeShape(output);
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+
+      FloatConv2D params{};
+      status = calculateActivationRange(options->fused_activation_function(),
+                                        &params.activation_min, &params.activation_max);
+      params.stride_w = options->stride_w();
+      params.stride_h = options->stride_h();
+      params.dilation_width_factor = options->dilation_w_factor();
+      params.dilation_height_factor = options->dilation_h_factor();
+      params.depth_multiplier = options->depth_multiplier();
+      params.pad_h = padding_h;
+      params.pad_w = padding_w;
+
+      if (status != Ok)
+        return status;
+
+      status = execute::pal::DepthwiseConv2D<float>(
+        &params, input_shape, core::utils::castInputData<float>(input_data), weight_shape,
+        core::utils::castInputData<float>(weight_data),
+        core::utils::castInputData<float>(bias_data), output_shape,
+        core::utils::castOutputData<float>(output_data));
+      assert(status == Ok);
+    }
+    break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+    {
+      ConvQuant params{};
+      params.pad_h = padding_h;
+      params.pad_w = padding_w;
+      params.depth_multiplier = options->depth_multiplier();
+
+      const auto padding = options->padding();
+      const auto stride_height = options->stride_h();
+      const auto stride_width = options->stride_w();
+      const auto dilation_height_factor = options->dilation_h_factor();
+      const auto dilation_width_factor = options->dilation_h_factor();
+
+      params.stride_height = stride_height;
+      params.stride_width = stride_width;
+      params.dilation_height_factor = dilation_height_factor;
+      params.dilation_width_factor = dilation_width_factor;
+
+      status =
+        createConvParams(params, input, weight, output, options->fused_activation_function());
+      assert(status == Ok);
+      if (status != Ok)
+        return status;
+
+      status = pal::DepthwiseConvPerChannel(
+        params, input_shape, core::utils::castInputData<int8_t>(input_data), weight_shape,
+        core::utils::castInputData<int8_t>(weight_data),
+        core::utils::castInputData<int32_t>(bias_data), output_shape,
+        core::utils::castOutputData<int8_t>(output_data));
+    }
+    break;
+#endif // DIS_QUANT
+    default:
+    {
+      status = UnsupportedActivation;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Dequantize.cpp b/onert-micro/onert-micro/src/execute/kernels/Dequantize.cpp
new file mode 100644 (file)
index 0000000..8e0e6a1
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/OMUtils.h"
+#include "PALDequantize.h"
+#include "core/OMRuntimeShape.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleDequantize(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input_data = nullptr;
+  uint8_t *output_data = nullptr;
+
+  OMStatus status = Ok;
+
+  {
+    OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+
+    assert(input != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+  }
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  assert(output->type() == circle::TensorType_FLOAT32);
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_INT8:
+    {
+      assert(input->quantization() != nullptr);
+      assert(input->quantization()->scale() != nullptr and
+             input->quantization()->scale()->size() == 1);
+      assert(input->quantization()->zero_point() != nullptr and
+             input->quantization()->zero_point()->size() == 1);
+      core::QuantizationParams params{};
+      params.zero_point = input->quantization()->zero_point()->operator[](0);
+      params.scale = input->quantization()->scale()->operator[](0);
+
+      status = pal::Dequantize(params, core::OMRuntimeShape(input).flatSize(),
+                               core::utils::castInputData<int8_t>(input_data),
+                               core::utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Div.cpp b/onert-micro/onert-micro/src/execute/kernels/Div.cpp
new file mode 100644 (file)
index 0000000..0395878
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMUtils.h"
+#include "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/OMUtils.h"
+
+#include "core/OMRuntimeShape.h"
+#include "PALDiv.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+// TODO: reduce code duplication with Add, Sub
+OMStatus onert_micro::execute::execute_kernel_CircleDiv(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input1;
+  const circle::Tensor *input2;
+  const circle::Tensor *output;
+
+  uint8_t *input1_data;
+  uint8_t *input2_data;
+  uint8_t *output_data;
+
+  const circle::DivOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input1 = runtime_kernel.inputs[input1TensorIdx];
+    input2 = runtime_kernel.inputs[input2TensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input1 != nullptr);
+    assert(input2 != nullptr);
+    assert(output != nullptr);
+
+    runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+
+    input1_data = runtime_kernel.inputs_data[input1TensorIdx];
+    input2_data = runtime_kernel.inputs_data[input2TensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+    assert(input1_data != nullptr);
+    assert(input2_data != nullptr);
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_DivOptions();
+  }
+
+  OMStatus status;
+
+  core::OMRuntimeShape input1_shape(input1);
+  core::OMRuntimeShape input2_shape(input2);
+  core::OMRuntimeShape output_shape(output);
+
+  core::BinaryArithmeticBroadcastParams params{};
+  const bool need_broadcast = pal::processBroadcastShapes(input1_shape, input2_shape, &params);
+
+  switch (input1->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status = execute::calculateActivationRange(options->fused_activation_function(),
+                                                 &params.float_activation_min,
+                                                 &params.float_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastDiv4DSlow(
+          params, input1_shape, core::utils::castInputData<float>(input1_data), input2_shape,
+          core::utils::castInputData<float>(input2_data), output_shape,
+          core::utils::castOutputData<float>(output_data));
+      }
+      else
+      {
+        status =
+          pal::Div(params, input1_shape.flatSize(), core::utils::castInputData<float>(input1_data),
+                   core::utils::castInputData<float>(input2_data),
+                   core::utils::castOutputData<float>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
+    case circle::TensorType_INT64:
+    {
+      status = execute::calculateActivationRange(options->fused_activation_function(),
+                                                 &params.int64_activation_min,
+                                                 &params.int64_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastDiv4DSlow(
+          params, input1_shape, core::utils::castInputData<int64_t>(input1_data), input2_shape,
+          core::utils::castInputData<int64_t>(input2_data), output_shape,
+          core::utils::castOutputData<int64_t>(output_data));
+      }
+      else
+      {
+        status = pal::Div(params, input1_shape.flatSize(),
+                          core::utils::castInputData<int64_t>(input1_data),
+                          core::utils::castInputData<int64_t>(input2_data),
+                          core::utils::castOutputData<int64_t>(output_data));
+      }
+    }
+    break;
+    case circle::TensorType_INT32:
+    {
+      status = execute::calculateActivationRange(options->fused_activation_function(),
+                                                 &params.int32_activation_min,
+                                                 &params.int32_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastDiv4DSlow(
+          params, input1_shape, core::utils::castInputData<int32_t>(input1_data), input2_shape,
+          core::utils::castInputData<int32_t>(input2_data), output_shape,
+          core::utils::castOutputData<int32_t>(output_data));
+      }
+      else
+      {
+        status = pal::Div(params, input1_shape.flatSize(),
+                          core::utils::castInputData<int32_t>(input1_data),
+                          core::utils::castInputData<int32_t>(input2_data),
+                          core::utils::castOutputData<int32_t>(output_data));
+      }
+    }
+    break;
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Equal.cpp b/onert-micro/onert-micro/src/execute/kernels/Equal.cpp
new file mode 100644 (file)
index 0000000..0ff8ca8
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/OMUtils.h"
+#include "execute/kernels/ComparisonCommon.h"
+#include "PALComparisons.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleEqual(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  OMStatus status = Ok;
+
+  const circle::Tensor *input1 = nullptr;
+  const circle::Tensor *input2 = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input1 = runtime_kernel.inputs[input1TensorIdx];
+  input2 = runtime_kernel.inputs[input2TensorIdx];
+  output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  switch (input1->type())
+  {
+    case circle::TensorType_INT64:
+      onert_micro::execute::evalComparisonGeneric<int64_t>(&runtime_kernel,
+                                                           onert_micro::execute::pal::EqualFn);
+      break;
+    case circle::TensorType_INT32:
+      onert_micro::execute::evalComparisonGeneric<int32_t>(&runtime_kernel,
+                                                           onert_micro::execute::pal::EqualFn);
+      break;
+
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      onert_micro::execute::evalComparisonGeneric<float>(&runtime_kernel,
+                                                         onert_micro::execute::pal::EqualFn);
+      break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Exp.cpp b/onert-micro/onert-micro/src/execute/kernels/Exp.cpp
new file mode 100644 (file)
index 0000000..cc9d319
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALExp.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleExp(const OMExecuteArgs &execute_args)
+{
+  auto exp_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                             const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Exp(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, exp_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/ExpandDims.cpp b/onert-micro/onert-micro/src/execute/kernels/ExpandDims.cpp
new file mode 100644 (file)
index 0000000..ee52d5b
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ReshapeCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleExpandDims(const OMExecuteArgs &execute_args)
+{
+  return execute_reshape_common(execute_args);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Floor.cpp b/onert-micro/onert-micro/src/execute/kernels/Floor.cpp
new file mode 100644 (file)
index 0000000..7bdd1dd
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALFloor.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleFloor(const OMExecuteArgs &execute_args)
+{
+  auto floor_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                               const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Floor(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, floor_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/FloorDiv.cpp b/onert-micro/onert-micro/src/execute/kernels/FloorDiv.cpp
new file mode 100644 (file)
index 0000000..ccff542
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "execute/kernels/ReadKernelDataCommon.h"
+#include "PALComparisons.h"
+#include "core/OMUtils.h"
+#include "PALFloorDiv.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleFloorDiv(const OMExecuteArgs &execute_args)
+{
+  uint8_t *input_data1;
+  uint8_t *input_data2;
+  uint8_t *output_data;
+
+  core::OMRuntimeShape input_shape1;
+  core::OMRuntimeShape input_shape2;
+  core::OMRuntimeShape output_shape;
+
+  circle::TensorType input1_type;
+
+  OMStatus status =
+    execute::readKernelDataTISO(execute_args, input_data1, input_data2, output_data, input_shape1,
+                                input_shape2, output_shape, input1_type);
+
+  switch (input1_type)
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      // Check the denominator
+      for (int i = 0; i < input_shape2.flatSize(); ++i)
+      {
+        status = utils::checkCondition(core::utils::castInputData<float>(input_data2)[i] != 0);
+        if (status != Ok)
+          return status;
+      }
+      // check that input and output dimensions are equal
+      if (input_shape1 == input_shape2)
+      {
+        const int flat_size = input_shape1.flatSize();
+        pal::FloorDiv(flat_size, core::utils::castInputData<float>(input_data1),
+                      core::utils::castInputData<float>(input_data2),
+                      core::utils::castOutputData<float>(output_data));
+      }
+      else
+      {
+        pal::BroadcastFloorDiv4DSlow(input_shape1, core::utils::castInputData<float>(input_data1),
+                                     input_shape2, core::utils::castInputData<float>(input_data2),
+                                     output_shape, core::utils::castOutputData<float>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/FloorMod.cpp b/onert-micro/onert-micro/src/execute/kernels/FloorMod.cpp
new file mode 100644 (file)
index 0000000..73b3c8b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "execute/kernels/ReadKernelDataCommon.h"
+#include "core/OMUtils.h"
+#include "PALFloorMod.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleFloorMod(const OMExecuteArgs &execute_args)
+{
+  uint8_t *input_data1;
+  uint8_t *input_data2;
+  uint8_t *output_data;
+
+  core::OMRuntimeShape input_shape1;
+  core::OMRuntimeShape input_shape2;
+  core::OMRuntimeShape output_shape;
+
+  circle::TensorType input1_type;
+
+  OMStatus status =
+    execute::readKernelDataTISO(execute_args, input_data1, input_data2, output_data, input_shape1,
+                                input_shape2, output_shape, input1_type);
+
+  switch (input1_type)
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      // Check the denominator
+      for (int i = 0; i < input_shape2.flatSize(); ++i)
+      {
+        utils::checkCondition(core::utils::castInputData<float>(input_data2)[i] != 0);
+      }
+      // check that input and output dimensions are equal
+      if (input_shape1 == input_shape2)
+      {
+        const int flat_size = input_shape1.flatSize();
+        pal::FloorMod(flat_size, core::utils::castInputData<float>(input_data1),
+                      core::utils::castInputData<float>(input_data2),
+                      core::utils::castOutputData<float>(output_data));
+      }
+      else
+      {
+        pal::BroadcastFloorMod4DSlow(input_shape1, core::utils::castInputData<float>(input_data1),
+                                     input_shape2, core::utils::castInputData<float>(input_data2),
+                                     output_shape, core::utils::castOutputData<float>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/FullyConnected.cpp b/onert-micro/onert-micro/src/execute/kernels/FullyConnected.cpp
new file mode 100644 (file)
index 0000000..981e93d
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALFullyConnected.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t weightTensorIdx = 1;
+constexpr uint32_t biasTensorIdx = 2;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+#ifndef DIS_QUANT
+void calculateOpDataFullyConnected(const circle::Tensor *input, const circle::Tensor *weights,
+                                   const circle::Tensor *output,
+                                   circle::ActivationFunctionType activation,
+                                   FullyConnectedParams &params)
+{
+  double real_multiplier = 0.0;
+  int output_shift;
+  int32_t output_activation_min;
+  int32_t output_activation_max;
+  int32_t output_multiplier;
+
+  assert(input->quantization() != nullptr);                 // Fix caller
+  assert(input->quantization()->scale()->size() == 1);      // Fix caller
+  assert(input->quantization()->zero_point()->size() == 1); // Fix caller
+
+  assert(weights->quantization() != nullptr);                 // Fix caller
+  assert(weights->quantization()->scale()->size() == 1);      // Fix caller
+  assert(weights->quantization()->zero_point()->size() == 1); // Fix caller
+
+  assert(output->quantization() != nullptr);                 // Fix caller
+  assert(output->quantization()->scale()->size() == 1);      // Fix caller
+  assert(output->quantization()->zero_point()->size() == 1); // Fix caller
+
+  const float input_scale = *input->quantization()->scale()->begin();
+  const float weight_scale = *weights->quantization()->scale()->begin();
+  const float output_scale = *output->quantization()->scale()->begin();
+
+  const long input_zero_point = *input->quantization()->zero_point()->begin();
+  const long weights_zero_point = *weights->quantization()->zero_point()->begin();
+  const long output_zero_point = *output->quantization()->zero_point()->begin();
+
+  real_multiplier =
+    execute::getQuantizedConvolutionMultipler(input_scale, weight_scale, output_scale);
+  execute::quantizeMultiplier(real_multiplier, &output_multiplier, &output_shift);
+  execute::calculateActivationRangeQuantized(activation, output_zero_point, output_scale,
+                                             output->type(), &output_activation_min,
+                                             &output_activation_max);
+
+  params.output_shift = output_shift;
+  params.output_multiplier = output_multiplier;
+  params.input_offset = -input_zero_point;
+  params.weights_offset = -weights_zero_point;
+  params.output_offset = output_zero_point;
+  params.quantized_activation_max = output_activation_max;
+  params.quantized_activation_min = output_activation_min;
+}
+#endif
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus
+onert_micro::execute::execute_kernel_CircleFullyConnected(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *weight;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *weight_data;
+  uint8_t *bias_data;
+  uint8_t *output_data;
+
+  const circle::FullyConnectedOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    weight = runtime_kernel.inputs[weightTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(weight != nullptr);
+    // Bias can be nullptr
+    assert(output != nullptr);
+
+    runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    weight_data = runtime_kernel.inputs_data[weightTensorIdx];
+    bias_data = runtime_kernel.inputs_data[biasTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+    assert(input_data != nullptr);
+    assert(weight_data != nullptr);
+    // Bias can be nullptr
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_FullyConnectedOptions();
+  }
+
+  OMStatus status;
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      FullyConnectedParams params{};
+      status = calculateActivationRange(options->fused_activation_function(),
+                                        &params.float_activation_min, &params.float_activation_max);
+      if (status != Ok)
+        return status;
+
+      status =
+        pal::FullyConnected(params, core::utils::castInputData<float>(input_data),
+                            OMRuntimeShape(weight), core::utils::castInputData<float>(weight_data),
+                            core::utils::castInputData<float>(bias_data), OMRuntimeShape(output),
+                            core::utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+    {
+      FullyConnectedParams op_params{};
+
+      calculateOpDataFullyConnected(input, weight, output, options->fused_activation_function(),
+                                    op_params);
+
+      status =
+        pal::FullyConnected(op_params, core::utils::castInputData<int8_t>(input_data),
+                            OMRuntimeShape(weight), core::utils::castInputData<int8_t>(weight_data),
+                            core::utils::castInputData<int32_t>(bias_data), OMRuntimeShape(output),
+                            core::utils::castOutputData<int8_t>(output_data));
+    }
+    break;
+    case circle::TensorType_INT16:
+    {
+      FullyConnectedParams op_params{};
+
+      calculateOpDataFullyConnected(input, weight, output, options->fused_activation_function(),
+                                    op_params);
+
+      status =
+        pal::FullyConnected(op_params, core::utils::castInputData<int16_t>(input_data),
+                            OMRuntimeShape(weight), core::utils::castInputData<int8_t>(weight_data),
+                            core::utils::castInputData<int32_t>(bias_data), OMRuntimeShape(output),
+                            core::utils::castOutputData<int16_t>(output_data));
+    }
+    break;
+#endif // DIS_QUANT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Gather.cpp b/onert-micro/onert-micro/src/execute/kernels/Gather.cpp
new file mode 100644 (file)
index 0000000..5b220ba
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t positionsTensorIdx = 1;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+template <typename InputT, typename CoordsT = int32_t>
+void gather(const InputT *input_data, const CoordsT *coords_data, InputT *output_data,
+            int32_t axis_size, int32_t batch_size, int32_t outer_size, int32_t inner_size,
+            int32_t coord_size)
+{
+
+  for (int batch = 0; batch < batch_size; ++batch)
+  {
+    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);
+      }
+    }
+  }
+}
+
+} // namespace
+
+// NOTE: doesn't currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleGather(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *position;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *position_data;
+  uint8_t *output_data;
+
+  const circle::GatherOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    position = runtime_kernel.inputs[positionsTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(position != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    position_data = runtime_kernel.inputs_data[positionsTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+    assert(input_data != nullptr);
+    assert(position_data != nullptr);
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_GatherOptions();
+  }
+
+  OMStatus status = Ok;
+
+  OMRuntimeShape position_shape(position);
+  OMRuntimeShape input_shape(input);
+
+  const int input_dims_size = input_shape.dimensionsCount();
+  int axis = options->axis();
+  if (axis < 0)
+  {
+    axis += input_dims_size;
+  }
+
+  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 = position_shape.dimensionsCount();
+  if (batch_dims < 0)
+  {
+    batch_dims += coords_dims_size;
+  }
+
+  const int axis_size = input_shape.dims(axis);
+
+  int batch_size = 1;
+  for (int i = 0; i < batch_dims; ++i)
+  {
+    batch_size *= input_shape.dims(i);
+  }
+  int outer_size = 1;
+  for (int i = batch_dims; i < axis; ++i)
+  {
+    outer_size *= input_shape.dims(i);
+  }
+  int inner_size = 1;
+  for (int i = axis + 1; i < input_dims_size; ++i)
+  {
+    inner_size *= input_shape.dims(i);
+  }
+  int coord_size = 1;
+  for (int i = batch_dims; i < coords_dims_size; ++i)
+  {
+    coord_size *= position_shape.dims(i);
+  }
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      gather<float, int32_t>(utils::castInputData<float>(input_data),
+                             utils::castInputData<int32_t>(position_data),
+                             utils::castOutputData<float>(output_data), axis_size, batch_size,
+                             outer_size, inner_size, coord_size);
+    }
+    break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+    {
+      gather<int8_t, int32_t>(utils::castInputData<int8_t>(input_data),
+                              utils::castInputData<int32_t>(position_data),
+                              utils::castOutputData<int8_t>(output_data), axis_size, batch_size,
+                              outer_size, inner_size, coord_size);
+    }
+    break;
+#endif // DIS_QUANT
+    case circle::TensorType_INT32:
+    {
+      gather<int32_t, int32_t>(utils::castInputData<int32_t>(input_data),
+                               utils::castInputData<int32_t>(position_data),
+                               utils::castOutputData<int32_t>(output_data), axis_size, batch_size,
+                               outer_size, inner_size, coord_size);
+    }
+    break;
+    default:
+    {
+      status = UnsupportedActivation;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/GatherND.cpp b/onert-micro/onert-micro/src/execute/kernels/GatherND.cpp
new file mode 100644 (file)
index 0000000..e5f3571
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+#include "execute/kernels/ReadKernelDataCommon.h"
+#include "PALGatherND.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+// NOTE: doesn't currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleGatherND(const OMExecuteArgs &execute_args)
+{
+
+  uint8_t *input_data;
+  uint8_t *position_data;
+  uint8_t *output_data;
+
+  core::OMRuntimeShape input_shape;
+  core::OMRuntimeShape position_shape;
+  core::OMRuntimeShape output_shape;
+
+  circle::TensorType inputType;
+
+  OMStatus status =
+    execute::readKernelDataTISO(execute_args, input_data, position_data, output_data, input_shape,
+                                position_shape, output_shape, inputType);
+
+  switch (inputType)
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      pal::GatherND<float, int32_t>(input_shape, utils::castInputData<float>(input_data),
+                                    position_shape, utils::castInputData<int32_t>(position_data),
+                                    utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedActivation;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Greater.cpp b/onert-micro/onert-micro/src/execute/kernels/Greater.cpp
new file mode 100644 (file)
index 0000000..5f95c0e
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/OMUtils.h"
+#include "execute/kernels/ComparisonCommon.h"
+#include "PALComparisons.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleGreater(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  OMStatus status = Ok;
+
+  const circle::Tensor *input1 = nullptr;
+  const circle::Tensor *input2 = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input1 = runtime_kernel.inputs[input1TensorIdx];
+  input2 = runtime_kernel.inputs[input2TensorIdx];
+  output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  switch (input1->type())
+  {
+    case circle::TensorType_INT64:
+      onert_micro::execute::evalComparisonGeneric<int64_t>(&runtime_kernel,
+                                                           onert_micro::execute::pal::GreaterFn);
+      break;
+    case circle::TensorType_INT32:
+      onert_micro::execute::evalComparisonGeneric<int32_t>(&runtime_kernel,
+                                                           onert_micro::execute::pal::GreaterFn);
+      break;
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      onert_micro::execute::evalComparisonGeneric<float>(&runtime_kernel,
+                                                         onert_micro::execute::pal::GreaterFn);
+      break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/GreaterEqual.cpp b/onert-micro/onert-micro/src/execute/kernels/GreaterEqual.cpp
new file mode 100644 (file)
index 0000000..325e332
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/OMUtils.h"
+#include "execute/kernels/ComparisonCommon.h"
+#include "PALComparisons.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleGreaterEqual(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  OMStatus status = Ok;
+
+  const circle::Tensor *input1 = nullptr;
+  const circle::Tensor *input2 = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input1 = runtime_kernel.inputs[input1TensorIdx];
+  input2 = runtime_kernel.inputs[input2TensorIdx];
+  output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  switch (input1->type())
+  {
+    case circle::TensorType_INT64:
+      onert_micro::execute::evalComparisonGeneric<int64_t>(
+        &runtime_kernel, onert_micro::execute::pal::GreaterEqualFn);
+      break;
+    case circle::TensorType_INT32:
+      onert_micro::execute::evalComparisonGeneric<int32_t>(
+        &runtime_kernel, onert_micro::execute::pal::GreaterEqualFn);
+      break;
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      onert_micro::execute::evalComparisonGeneric<float>(&runtime_kernel,
+                                                         onert_micro::execute::pal::GreaterEqualFn);
+      break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/L2Normalize.cpp b/onert-micro/onert-micro/src/execute/kernels/L2Normalize.cpp
new file mode 100644 (file)
index 0000000..3b7aac5
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALL2Normalize.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleL2Normalize(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input_data = nullptr;
+  uint8_t *output_data = nullptr;
+
+  OMStatus status = Ok;
+
+  {
+    OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+
+    assert(input != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+  }
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+
+      core::OMRuntimeShape inputs_shape(input);
+      core::OMRuntimeShape outputs_shape(output);
+
+      const auto trailing_dim = inputs_shape.dimensionsCount() - 1;
+
+      core::L2NormalizationParams params;
+      params.num_rows =
+        pal::flatSizeSkipDim(inputs_shape.dimsData(), trailing_dim, inputs_shape.dimensionsCount());
+
+      assert(inputs_shape.dims(trailing_dim) == outputs_shape.dims(trailing_dim));
+      params.row_size = inputs_shape.dims(trailing_dim);
+
+      status = pal::L2Normalization(params, core::utils::castInputData<float>(input_data),
+                                    core::utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/L2Pool2D.cpp b/onert-micro/onert-micro/src/execute/kernels/L2Pool2D.cpp
new file mode 100644 (file)
index 0000000..032652a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/PoolingCommon.h"
+#include "PALL2Pool2D.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleL2Pool2D(const OMExecuteArgs &execute_args)
+{
+  auto l2_pool_float_lambda = [](const core::Pool2DParams &params,
+                                 const core::OMRuntimeShape &input_shape, const float *input_data,
+                                 const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::L2Pool(params, input_shape, input_data, output_shape, output_data);
+  };
+
+#ifndef DIS_QUANT
+  auto l2_pool_int8_lambda = [](const core::Pool2DParams &params,
+                                const core::OMRuntimeShape &input_shape, const int8_t *input_data,
+                                const core::OMRuntimeShape &output_shape,
+                                int8_t *output_data) { return UnsupportedType; };
+#else
+  auto l2_pool_int8_lambda = [](const core::Pool2DParams &params,
+                                const core::OMRuntimeShape &input_shape, const int8_t *input_data,
+                                const core::OMRuntimeShape &output_shape,
+                                int8_t *output_data) { return UnsupportedType; };
+#endif // DIS_QUANT
+
+  return execute_pooling_common(execute_args, l2_pool_float_lambda, l2_pool_int8_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/LeakyRelu.cpp b/onert-micro/onert-micro/src/execute/kernels/LeakyRelu.cpp
new file mode 100644 (file)
index 0000000..d2b6467
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ReluCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleLeakyRelu(const OMExecuteArgs &execute_args)
+{
+  bool is_relu_6 = false;
+  return execute_relu_common(execute_args, is_relu_6);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Less.cpp b/onert-micro/onert-micro/src/execute/kernels/Less.cpp
new file mode 100644 (file)
index 0000000..6d27f66
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/OMUtils.h"
+#include "execute/kernels/ComparisonCommon.h"
+#include "PALComparisons.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleLess(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  OMStatus status = Ok;
+
+  const circle::Tensor *input1 = nullptr;
+  const circle::Tensor *input2 = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input1 = runtime_kernel.inputs[input1TensorIdx];
+  input2 = runtime_kernel.inputs[input2TensorIdx];
+  output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  switch (input1->type())
+  {
+    case circle::TensorType_INT64:
+      onert_micro::execute::evalComparisonGeneric<int64_t>(&runtime_kernel,
+                                                           onert_micro::execute::pal::LessFn);
+      break;
+    case circle::TensorType_INT32:
+      onert_micro::execute::evalComparisonGeneric<int32_t>(&runtime_kernel,
+                                                           onert_micro::execute::pal::LessFn);
+      break;
+#ifndef DIS_QUANT
+    case circle::TensorType_UINT8:
+      evalQuantizedComparisonGeneric<uint8_t>(&runtime_kernel, onert_micro::execute::pal::LessFn);
+      break;
+#endif // DIS_QUANT
+
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      onert_micro::execute::evalComparisonGeneric<float>(&runtime_kernel,
+                                                         onert_micro::execute::pal::LessFn);
+      break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/LessEqual.cpp b/onert-micro/onert-micro/src/execute/kernels/LessEqual.cpp
new file mode 100644 (file)
index 0000000..a45b0cf
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/OMUtils.h"
+#include "execute/kernels/ComparisonCommon.h"
+#include "PALComparisons.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleLessEqual(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  OMStatus status = Ok;
+
+  const circle::Tensor *input1 = nullptr;
+  const circle::Tensor *input2 = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input1 = runtime_kernel.inputs[input1TensorIdx];
+  input2 = runtime_kernel.inputs[input2TensorIdx];
+  output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  switch (input1->type())
+  {
+    case circle::TensorType_INT64:
+      onert_micro::execute::evalComparisonGeneric<int64_t>(&runtime_kernel,
+                                                           onert_micro::execute::pal::LessEqualFn);
+      break;
+    case circle::TensorType_INT32:
+      onert_micro::execute::evalComparisonGeneric<int32_t>(&runtime_kernel,
+                                                           onert_micro::execute::pal::LessEqualFn);
+      break;
+
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      onert_micro::execute::evalComparisonGeneric<float>(&runtime_kernel,
+                                                         onert_micro::execute::pal::LessEqualFn);
+      break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Log.cpp b/onert-micro/onert-micro/src/execute/kernels/Log.cpp
new file mode 100644 (file)
index 0000000..93c862e
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALLog.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleLog(const OMExecuteArgs &execute_args)
+{
+  auto log_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                             const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Log(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, log_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/LogSoftmax.cpp b/onert-micro/onert-micro/src/execute/kernels/LogSoftmax.cpp
new file mode 100644 (file)
index 0000000..fbbf253
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALLogSoftmax.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleLogSoftmax(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input_data = nullptr;
+  uint8_t *output_data = nullptr;
+
+  OMStatus status = Ok;
+
+  {
+    OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+
+    assert(input != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+  }
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+
+      core::OMRuntimeShape inputs_shape(input);
+      core::OMRuntimeShape outputs_shape(output);
+
+      const auto dim_count = inputs_shape.dimensionsCount();
+
+      const auto trailing_dim = dim_count - 1;
+
+      int flat_size = 1;
+      for (int i = 0; i < inputs_shape.dimensionsCount(); ++i)
+      {
+        flat_size *= (i == trailing_dim) ? 1 : inputs_shape.dims(i);
+      }
+
+      core::LogSoftmaxParams params;
+      params.num_rows = flat_size;
+
+      assert(inputs_shape.dims(trailing_dim) == outputs_shape.dims(trailing_dim));
+      params.row_size = inputs_shape.dims(trailing_dim);
+
+      status = pal::LogSoftmax(params, core::utils::castInputData<float>(input_data),
+                               core::utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Logistic.cpp b/onert-micro/onert-micro/src/execute/kernels/Logistic.cpp
new file mode 100644 (file)
index 0000000..adf05d2
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALLogistic.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleLogistic(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input_data = nullptr;
+  uint8_t *output_data = nullptr;
+
+  OMStatus status = Ok;
+
+  {
+    OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+
+    assert(input != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+  }
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status = pal::Logistic(core::OMRuntimeShape(input).flatSize(),
+                             core::utils::castInputData<float>(input_data),
+                             core::utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+    {
+      assert(input->quantization() != nullptr);
+      assert(input->quantization()->scale() != nullptr);
+      assert(input->quantization()->scale()->size() == 1);
+      assert(input->quantization()->zero_point() != nullptr);
+      assert(input->quantization()->zero_point()->size() == 1);
+
+      assert(output->quantization() != nullptr);
+      assert(output->quantization()->scale() != nullptr);
+      assert(output->quantization()->scale()->size() == 1);
+      assert(output->quantization()->zero_point() != nullptr);
+      assert(output->quantization()->zero_point()->size() == 1);
+
+      auto input_scale = *input->quantization()->scale()->begin();
+      auto input_zero_point = *input->quantization()->zero_point()->begin();
+      auto output_scale = *input->quantization()->scale()->begin();
+      auto output_zero_point = *input->quantization()->zero_point()->begin();
+
+      status = pal::Logistic(core::OMRuntimeShape(input).flatSize(),
+                             core::utils::castInputData<int8_t>(input_data), input_scale,
+                             input_zero_point, core::utils::castOutputData<int8_t>(output_data),
+                             output_scale, output_zero_point);
+    }
+    break;
+#endif // DIS_QUANT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/MathCommon.cpp b/onert-micro/onert-micro/src/execute/kernels/MathCommon.cpp
new file mode 100644 (file)
index 0000000..b18642f
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_math_common(
+  const OMExecuteArgs &execute_args,
+  const std::function<OMStatus(const core::OMRuntimeShape &, const float *,
+                               const core::OMRuntimeShape &, float *)> &f_float)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input_data = nullptr;
+  uint8_t *output_data = nullptr;
+
+  OMStatus status = Ok;
+
+  {
+    OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+
+    assert(input != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+  }
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+
+    case circle::TensorType_FLOAT32:
+      status =
+        f_float(core::OMRuntimeShape(input), core::utils::castInputData<float>(input_data),
+                core::OMRuntimeShape(output), core::utils::castOutputData<float>(output_data));
+      break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp b/onert-micro/onert-micro/src/execute/kernels/MaxPool2D.cpp
new file mode 100644 (file)
index 0000000..b27e3fc
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/PoolingCommon.h"
+#include "PALMaxPool2D.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleMaxPool2D(const OMExecuteArgs &execute_args)
+{
+  auto max_pool_float_lambda = [](const core::Pool2DParams &params,
+                                  const core::OMRuntimeShape &input_shape, const float *input_data,
+                                  const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::MaxPool(params, input_shape, input_data, output_shape, output_data);
+  };
+
+#ifndef DIS_QUANT
+  auto max_pool_int8_lambda = [](const core::Pool2DParams &params,
+                                 const core::OMRuntimeShape &input_shape, const int8_t *input_data,
+                                 const core::OMRuntimeShape &output_shape, int8_t *output_data) {
+    return pal::MaxPool(params, input_shape, input_data, output_shape, output_data);
+  };
+#else
+  auto max_pool_int8_lambda = [](const core::Pool2DParams &params,
+                                 const core::OMRuntimeShape &input_shape, const int8_t *input_data,
+                                 const core::OMRuntimeShape &output_shape,
+                                 int8_t *output_data) { return UnsupportedType; };
+#endif // DIS_QUANT
+
+  return execute_pooling_common(execute_args, max_pool_float_lambda, max_pool_int8_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Maximum.cpp b/onert-micro/onert-micro/src/execute/kernels/Maximum.cpp
new file mode 100644 (file)
index 0000000..73a10b6
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "execute/kernels/ReadKernelDataCommon.h"
+#include "core/OMUtils.h"
+#include "PALMaximum.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+OMStatus onert_micro::execute::execute_kernel_CircleMaximum(const OMExecuteArgs &execute_args)
+{
+
+  uint8_t *input_data1;
+  uint8_t *input_data2;
+  uint8_t *output_data;
+
+  core::OMRuntimeShape input_shape1;
+  core::OMRuntimeShape input_shape2;
+  core::OMRuntimeShape output_shape;
+
+  circle::TensorType input1_type;
+
+  OMStatus status =
+    execute::readKernelDataTISO(execute_args, input_data1, input_data2, output_data, input_shape1,
+                                input_shape2, output_shape, input1_type);
+
+  switch (input1_type)
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      // check that input and output dimensions are equal
+      if (input_shape1 == input_shape2)
+      {
+        const int flat_size = input_shape1.flatSize();
+        status = pal::Maximum(flat_size, utils::castInputData<float>(input_data1),
+                              utils::castInputData<float>(input_data2),
+                              utils::castOutputData<float>(output_data));
+      }
+      else
+      {
+        status =
+          pal::BroadcastMaximum4DSlow(input_shape1, utils::castInputData<float>(input_data1),
+                                      input_shape2, utils::castInputData<float>(input_data2),
+                                      output_shape, utils::castOutputData<float>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Minimum.cpp b/onert-micro/onert-micro/src/execute/kernels/Minimum.cpp
new file mode 100644 (file)
index 0000000..e5c4e7c
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "execute/kernels/ReadKernelDataCommon.h"
+#include "core/OMUtils.h"
+#include "PALMinimum.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+OMStatus onert_micro::execute::execute_kernel_CircleMinimum(const OMExecuteArgs &execute_args)
+{
+
+  uint8_t *input_data1;
+  uint8_t *input_data2;
+  uint8_t *output_data;
+
+  core::OMRuntimeShape input_shape1;
+  core::OMRuntimeShape input_shape2;
+  core::OMRuntimeShape output_shape;
+
+  circle::TensorType input1_type;
+
+  OMStatus status =
+    execute::readKernelDataTISO(execute_args, input_data1, input_data2, output_data, input_shape1,
+                                input_shape2, output_shape, input1_type);
+
+  switch (input1_type)
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      // check that input and output dimensions are equal
+      if (input_shape1 == input_shape2)
+      {
+        const int flat_size = input_shape1.flatSize();
+        status = pal::Minimum(flat_size, utils::castInputData<float>(input_data1),
+                              utils::castInputData<float>(input_data2),
+                              utils::castOutputData<float>(output_data));
+      }
+      else
+      {
+        status =
+          pal::BroadcastMinimum4DSlow(input_shape1, utils::castInputData<float>(input_data1),
+                                      input_shape2, utils::castInputData<float>(input_data2),
+                                      output_shape, utils::castOutputData<float>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Mul.cpp b/onert-micro/onert-micro/src/execute/kernels/Mul.cpp
new file mode 100644 (file)
index 0000000..2f7fbec
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMRuntimeShape.h"
+
+#include "execute/OMUtils.h"
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+#include "PALMul.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+void calculateQuantParams(core::ArithmeticQuantParams &params, const circle::Tensor *input1,
+                          const circle::Tensor *input2, const circle::Tensor *output,
+                          circle::ActivationFunctionType act)
+{
+  long input1_zp;
+  long input2_zp;
+  long output_zp;
+
+  float input1_scale;
+  float input2_scale;
+  float output_scale;
+
+  // Read input1 quant params
+  readQuantParams(input1, input1_zp, input1_scale);
+  // Read input2 quant params
+  readQuantParams(input2, input2_zp, input2_scale);
+  // Read output quant params
+  readQuantParams(output, output_zp, output_scale);
+
+  params.input1_offset = static_cast<int32_t>(input1_zp);
+  params.input2_offset = static_cast<int32_t>(input2_zp);
+  params.output_offset = static_cast<int32_t>(output_zp);
+  params.left_shift = (output->type() == circle::TensorType_INT16) ? 15 : 20;
+
+  double real_multiplier = static_cast<double>(input1_scale) * static_cast<double>(input2_scale) /
+                           static_cast<double>(output_scale);
+  quantizeMultiplier(real_multiplier, &params.output_multiplier, &params.output_shift);
+
+  calculateActivationRangeQuantized(act, output_zp, output_scale, output->type(),
+                                    &params.quantized_activation_min,
+                                    &params.quantized_activation_max);
+}
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+// TODO: reduce code duplication with Add, Sub
+OMStatus onert_micro::execute::execute_kernel_CircleMul(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input1;
+  const circle::Tensor *input2;
+  const circle::Tensor *output;
+
+  uint8_t *input1_data;
+  uint8_t *input2_data;
+  uint8_t *output_data;
+
+  const circle::MulOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input1 = runtime_kernel.inputs[input1TensorIdx];
+    input2 = runtime_kernel.inputs[input2TensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input1 != nullptr);
+    assert(input2 != nullptr);
+    assert(output != nullptr);
+
+    runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+
+    input1_data = runtime_kernel.inputs_data[input1TensorIdx];
+    input2_data = runtime_kernel.inputs_data[input2TensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+    assert(input1_data != nullptr);
+    assert(input2_data != nullptr);
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_MulOptions();
+  }
+
+  OMStatus status;
+
+  core::OMRuntimeShape input1_shape(input1);
+  core::OMRuntimeShape input2_shape(input2);
+  core::OMRuntimeShape output_shape(output);
+
+  core::BinaryArithmeticBroadcastParams params{};
+  const bool need_broadcast = pal::processBroadcastShapes(input1_shape, input2_shape, &params);
+
+  switch (input1->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status = execute::calculateActivationRange(options->fused_activation_function(),
+                                                 &params.float_activation_min,
+                                                 &params.float_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastMul4DSlow(
+          params, input1_shape, core::utils::castInputData<float>(input1_data), input2_shape,
+          core::utils::castInputData<float>(input2_data), output_shape,
+          core::utils::castOutputData<float>(output_data));
+      }
+      else
+      {
+        status =
+          pal::Mul(params, input1_shape.flatSize(), core::utils::castInputData<float>(input1_data),
+                   core::utils::castInputData<float>(input2_data),
+                   core::utils::castOutputData<float>(output_data));
+      }
+    }
+    break;
+    case circle::TensorType_INT64:
+    {
+      status = execute::calculateActivationRange(options->fused_activation_function(),
+                                                 &params.int64_activation_min,
+                                                 &params.int64_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastMul4DSlow(
+          params, input1_shape, core::utils::castInputData<int64_t>(input1_data), input2_shape,
+          core::utils::castInputData<int64_t>(input2_data), output_shape,
+          core::utils::castOutputData<int64_t>(output_data));
+      }
+      else
+      {
+        status = pal::Mul(params, input1_shape.flatSize(),
+                          core::utils::castInputData<int64_t>(input1_data),
+                          core::utils::castInputData<int64_t>(input2_data),
+                          core::utils::castOutputData<int64_t>(output_data));
+      }
+    }
+    break;
+    case circle::TensorType_INT32:
+    {
+      status = execute::calculateActivationRange(options->fused_activation_function(),
+                                                 &params.int32_activation_min,
+                                                 &params.int32_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastMul4DSlow(
+          params, input1_shape, core::utils::castInputData<int32_t>(input1_data), input2_shape,
+          core::utils::castInputData<int32_t>(input2_data), output_shape,
+          core::utils::castOutputData<int32_t>(output_data));
+      }
+      else
+      {
+        status = pal::Mul(params, input1_shape.flatSize(),
+                          core::utils::castInputData<int32_t>(input1_data),
+                          core::utils::castInputData<int32_t>(input2_data),
+                          core::utils::castOutputData<int32_t>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+    {
+      core::ArithmeticQuantParams add_params{};
+
+      calculateQuantParams(add_params, input1, input2, output,
+                           options->fused_activation_function());
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastMul6DSlow(
+          add_params, input1_shape, core::utils::castInputData<int8_t>(input1_data), input2_shape,
+          core::utils::castInputData<int8_t>(input2_data), output_shape,
+          core::utils::castOutputData<int8_t>(output_data));
+      }
+      else
+      {
+        assert(input1_shape.flatSize() == input2_shape.flatSize());
+        assert(input1_shape.flatSize() == output_shape.flatSize());
+        status = pal::Mul(add_params, input1_shape.flatSize(),
+                          core::utils::castInputData<int8_t>(input1_data),
+                          core::utils::castInputData<int8_t>(input2_data),
+                          core::utils::castOutputData<int8_t>(output_data));
+      }
+    }
+    break;
+#endif // DIF_QUANT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Neg.cpp b/onert-micro/onert-micro/src/execute/kernels/Neg.cpp
new file mode 100644 (file)
index 0000000..53c1b0c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALNeg.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleNeg(const OMExecuteArgs &execute_args)
+{
+  auto neg_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                             const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Neg(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, neg_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/NotEqual.cpp b/onert-micro/onert-micro/src/execute/kernels/NotEqual.cpp
new file mode 100644 (file)
index 0000000..5591c3e
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/OMUtils.h"
+#include "execute/kernels/ComparisonCommon.h"
+#include "PALComparisons.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleNotEqual(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  OMStatus status = Ok;
+
+  const circle::Tensor *input1 = nullptr;
+  const circle::Tensor *input2 = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input1 = runtime_kernel.inputs[input1TensorIdx];
+  input2 = runtime_kernel.inputs[input2TensorIdx];
+  output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  switch (input1->type())
+  {
+    case circle::TensorType_INT64:
+      onert_micro::execute::evalComparisonGeneric<int64_t>(&runtime_kernel,
+                                                           onert_micro::execute::pal::NotEqualFn);
+      break;
+    case circle::TensorType_INT32:
+      onert_micro::execute::evalComparisonGeneric<int32_t>(&runtime_kernel,
+                                                           onert_micro::execute::pal::NotEqualFn);
+      break;
+
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      onert_micro::execute::evalComparisonGeneric<float>(&runtime_kernel,
+                                                         onert_micro::execute::pal::NotEqualFn);
+      break;
+#endif // DIS_FLOAT
+    default:
+      assert(false && "Unsupported type.");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Pack.cpp b/onert-micro/onert-micro/src/execute/kernels/Pack.cpp
new file mode 100644 (file)
index 0000000..91db95f
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMRuntimeShape.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+template <typename T> void packImpl(OMRuntimeKernel &runtime_kernel)
+{
+  const auto *options = runtime_kernel.first_operator->builtin_options_as_PackOptions();
+
+  core::OMRuntimeShape input_shape(runtime_kernel.inputs[0]);
+  core::OMRuntimeShape output_shape(runtime_kernel.outputs[0]);
+
+  const int values_count = options->values_count();
+  int axis = options->axis();
+  const int dimensions = output_shape.dimensionsCount();
+
+  if (axis < 0)
+  {
+    axis += dimensions;
+  }
+
+  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);
+
+  int input_size = 1;
+  for (int i = 0; i < input_shape.dimensionsCount(); ++i)
+    input_size *= input_shape.dims(i);
+
+  assert(input_size == copy_size * outer_size);
+
+  T *output_data = core::utils::castOutputData<T>(runtime_kernel.outputs_data[0]);
+  assert(output_data != nullptr);
+
+  for (int i = 0; i < values_count; ++i)
+  {
+    auto input_data = core::utils::castInputData<T>(runtime_kernel.inputs_data[i]);
+    assert(input_data != nullptr);
+    for (int k = 0; k < outer_size; ++k)
+    {
+      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];
+    }
+  }
+}
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CirclePack(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  execute::OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  const auto type = runtime_kernel.inputs[0]->type();
+  OMStatus status = Ok;
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+
+  if (status != Ok)
+    return status;
+
+  switch (type)
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      packImpl<float>(runtime_kernel);
+      break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+      packImpl<int8_t>(runtime_kernel);
+      break;
+#endif // DIS_QUANT
+    case circle::TensorType_INT32:
+      packImpl<int32_t>(runtime_kernel);
+      break;
+    case circle::TensorType_INT64:
+      packImpl<int64_t>(runtime_kernel);
+      break;
+    default:
+      assert(false && "Unsupported type.");
+      status = UnsupportedType;
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Pad.cpp b/onert-micro/onert-micro/src/execute/kernels/Pad.cpp
new file mode 100644 (file)
index 0000000..586d2e4
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMRuntimeShape.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALPad.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t input3TensorIdx = 2;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CirclePad(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input1;
+  const circle::Tensor *input2;
+  const circle::Tensor *input3;
+  const circle::Tensor *output;
+
+  uint8_t *input1_data;
+  uint8_t *input2_data;
+  uint8_t *input3_data;
+  uint8_t *output_data;
+
+  const circle::PadOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input1 = runtime_kernel.inputs[input1TensorIdx];
+    input2 = runtime_kernel.inputs[input2TensorIdx];
+    input3 = runtime_kernel.inputs[input3TensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input1 != nullptr);
+    assert(input2 != nullptr);
+    // input3 - can be nullptr
+    assert(output != nullptr);
+
+    runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+
+    input1_data = runtime_kernel.inputs_data[input1TensorIdx];
+    input2_data = runtime_kernel.inputs_data[input2TensorIdx];
+    input3_data = runtime_kernel.inputs_data[input3TensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+    assert(input1_data != nullptr);
+    assert(input2_data != nullptr);
+    // input3_data can be nullptr
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_PadOptions();
+  }
+
+  OMStatus status = Ok;
+
+  core::OMRuntimeShape input1_shape(input1);
+  core::OMRuntimeShape input2_shape(input2);
+  core::OMRuntimeShape output_shape(output);
+
+  // Create PadParams
+  core::PadParams pad_params{};
+  const auto num_input_dimensions = input1_shape.dimensionsCount();
+  assert(num_input_dimensions <= 5);
+
+  if (num_input_dimensions > 5)
+    return UnsupportedType;
+
+  pad_params.left_padding_count = num_input_dimensions;
+  pad_params.right_padding_count = num_input_dimensions;
+
+  auto *paddings_data = reinterpret_cast<int32_t *>(input2_data);
+  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];
+  }
+
+  switch (input1->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      float pad_value = input3_data == nullptr ? 0.f : *reinterpret_cast<float *>(input3_data[0]);
+      status = pal::Pad(pad_params, input1_shape, core::utils::castInputData<float>(input1_data),
+                        pad_value, output_shape, core::utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/PoolingCommon.cpp b/onert-micro/onert-micro/src/execute/kernels/PoolingCommon.cpp
new file mode 100644 (file)
index 0000000..be762b9
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/PoolingCommon.h"
+#include "execute/OMUtils.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_pooling_common(
+  const OMExecuteArgs &execute_args,
+  const std::function<OMStatus(const core::Pool2DParams &, const core::OMRuntimeShape &,
+                               const float *, const core::OMRuntimeShape &, float *)> &f_float,
+  const std::function<OMStatus(const core::Pool2DParams &, const core::OMRuntimeShape &,
+                               const int8_t *, const core::OMRuntimeShape &, int8_t *)> &f_int8)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input_data = nullptr;
+  uint8_t *output_data = nullptr;
+
+  OMStatus status = Ok;
+
+  const circle::Pool2DOptions *options = nullptr;
+  {
+    OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+
+    assert(input != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+
+    options = runtime_kernel.first_operator->builtin_options_as_Pool2DOptions();
+  }
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+  assert(options != nullptr);
+
+  core::OMRuntimeShape input_shape(input);
+
+  int32_t padding_h = 0;
+  int32_t padding_w = 0;
+
+  const int input_width = input_shape.dims(2);
+  const int input_height = input_shape.dims(1);
+  execute::computePaddingHeightWidth(
+    options->stride_h(), options->stride_w(), 1 /* dilation_rate_height */,
+    1 /* dilation_rate_width */, input_height, input_width, options->filter_height(),
+    options->filter_width(), options->padding(), &padding_h, &padding_w);
+
+  core::Pool2DParams params{};
+  params.pad_h = padding_h;
+  params.pad_w = padding_w;
+  params.stride_h = options->stride_h();
+  params.stride_w = options->stride_w();
+  params.filter_h = options->filter_height();
+  params.filter_w = options->filter_width();
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      calculateActivationRange(options->fused_activation_function(), &params.activation_min,
+                               &params.activation_max);
+      status =
+        f_float(params, input_shape, core::utils::castInputData<float>(input_data),
+                core::OMRuntimeShape(output), core::utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+    {
+      assert(output->quantization() != nullptr);
+      assert(output->quantization()->scale() != nullptr);
+      assert(output->quantization()->scale()->size() == 1);
+      const auto output_scale = output->quantization()->scale()->operator[](0);
+
+      assert(output->quantization()->zero_point() != nullptr);
+      assert(output->quantization()->zero_point()->size() == 1);
+      const auto output_zp = output->quantization()->zero_point()->operator[](0);
+
+      calculateActivationRangeQuantized(
+        options->fused_activation_function(), output_zp, output_scale, output->type(),
+        &params.quantized_activation_min, &params.quantized_activation_max);
+      status =
+        f_int8(params, input_shape, core::utils::castInputData<int8_t>(input_data),
+               core::OMRuntimeShape(output), core::utils::castOutputData<int8_t>(output_data));
+    }
+    break;
+#endif // DIS_QUANT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/ReadKernelDataCommon.cpp b/onert-micro/onert-micro/src/execute/kernels/ReadKernelDataCommon.cpp
new file mode 100644 (file)
index 0000000..791fc97
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ReadKernelDataCommon.h"
+#include "execute/OMUtils.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace TensorIndexTISO
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace TensorIndexTISO
+
+OMStatus onert_micro::execute::readKernelDataTISO(const OMExecuteArgs &execute_args,
+                                                  uint8_t *&input_data1, uint8_t *&input_data2,
+                                                  uint8_t *&output_data,
+                                                  core::OMRuntimeShape &input1_shape_ref,
+                                                  core::OMRuntimeShape &input2_shape_ref,
+                                                  core::OMRuntimeShape &output_shape_ref,
+                                                  circle::TensorType &tensor_type)
+
+{
+
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  OMStatus status = Ok;
+
+  OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = nullptr;
+  const circle::Tensor *input2 = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  input1 = runtime_kernel.inputs[TensorIndexTISO::input1TensorIdx];
+  input2 = runtime_kernel.inputs[TensorIndexTISO::input2TensorIdx];
+  output = runtime_kernel.outputs[TensorIndexTISO::outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  input_data1 = runtime_kernel.inputs_data[TensorIndexTISO::input1TensorIdx];
+  input_data2 = runtime_kernel.inputs_data[TensorIndexTISO::input2TensorIdx];
+  output_data = runtime_kernel.outputs_data[TensorIndexTISO::outputTensorIdx];
+
+  input1_shape_ref = std::move(core::OMRuntimeShape(input1));
+  input2_shape_ref = std::move(core::OMRuntimeShape(input2));
+  output_shape_ref = std::move(core::OMRuntimeShape(output));
+
+  tensor_type = input1->type();
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Relu.cpp b/onert-micro/onert-micro/src/execute/kernels/Relu.cpp
new file mode 100644 (file)
index 0000000..2c8fbb9
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ReluCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleRelu(const OMExecuteArgs &execute_args)
+{
+  bool is_relu_6 = false;
+  return execute_relu_common(execute_args, is_relu_6);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Relu6.cpp b/onert-micro/onert-micro/src/execute/kernels/Relu6.cpp
new file mode 100644 (file)
index 0000000..f501ad3
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ReluCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleRelu6(const OMExecuteArgs &execute_args)
+{
+  bool is_relu_6 = true;
+  return execute_relu_common(execute_args, is_relu_6);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/ReluCommon.cpp b/onert-micro/onert-micro/src/execute/kernels/ReluCommon.cpp
new file mode 100644 (file)
index 0000000..ae464bf
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ReluCommon.h"
+#include "PALReluCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_relu_common(const OMExecuteArgs &execute_args,
+                                                   bool is_relu_6)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input_data = nullptr;
+  uint8_t *output_data = nullptr;
+
+  OMStatus status = Ok;
+
+  OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  input = runtime_kernel.inputs[inputTensorIdx];
+  output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input_data = runtime_kernel.inputs_data[inputTensorIdx];
+  output_data = runtime_kernel.outputs_data[outputTensorIdx];
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  float alpha = 0.f;
+  auto options = runtime_kernel.first_operator->builtin_options_as_LeakyReluOptions();
+  if (options != nullptr)
+    alpha = options->alpha();
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      core::OMRuntimeShape input_shape(input);
+      core::OMRuntimeShape output_shape(output);
+
+      const auto *input_data_float = core::utils::castInputData<float>(input_data);
+      auto *output_data_float = core::utils::castOutputData<float>(output_data);
+
+      assert(output_data_float);
+      const int flat_size = input_shape.flatSize();
+
+      status = pal::ReLUCommon(flat_size, input_data_float, output_data_float, alpha, is_relu_6);
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+      break;
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Reshape.cpp b/onert-micro/onert-micro/src/execute/kernels/Reshape.cpp
new file mode 100644 (file)
index 0000000..5ddc9b0
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ReshapeCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleReshape(const OMExecuteArgs &execute_args)
+{
+  return execute_reshape_common(execute_args);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/ReshapeCommon.cpp b/onert-micro/onert-micro/src/execute/kernels/ReshapeCommon.cpp
new file mode 100644 (file)
index 0000000..ad15cce
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/ReshapeCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_reshape_common(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  OMStatus status = Ok;
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  uint8_t *input_data = runtime_kernel.inputs_data[inputTensorIdx];
+  uint8_t *output_data = runtime_kernel.outputs_data[outputTensorIdx];
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  // Check is it inplace kernel
+  if (input_data == output_data)
+    return Ok;
+
+  const core::OMRuntimeShape shape(input);
+
+  const size_t element_size =
+    static_cast<uint32_t>(getOMDataTypeSize(core::onertMicroDatatype(input->type())));
+  const int32_t num_elements = shape.flatSize();
+  std::memcpy(output_data, input_data, num_elements * element_size);
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Round.cpp b/onert-micro/onert-micro/src/execute/kernels/Round.cpp
new file mode 100644 (file)
index 0000000..753d7cc
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALRound.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleRound(const OMExecuteArgs &execute_args)
+{
+  auto round_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                               const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Round(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, round_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Rsqrt.cpp b/onert-micro/onert-micro/src/execute/kernels/Rsqrt.cpp
new file mode 100644 (file)
index 0000000..3e757b4
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALRsqrt.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleRsqrt(const OMExecuteArgs &execute_args)
+{
+  auto rsqrt_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                               const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Rsqrt(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, rsqrt_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Shape.cpp b/onert-micro/onert-micro/src/execute/kernels/Shape.cpp
new file mode 100644 (file)
index 0000000..1838a76
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleShape(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input = nullptr;
+  uint8_t *output_data = nullptr;
+
+  OMStatus status = Ok;
+  {
+    OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+
+    assert(input != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+  }
+
+  assert(output_data != nullptr);
+
+  core::OMRuntimeShape input_shape(input);
+
+  const auto rank = input_shape.dimensionsCount();
+
+  auto output_data_int = core::utils::castOutputData<int32_t>(output_data);
+
+  for (int i = 0; i < rank; ++i)
+  {
+    output_data_int[i] = input_shape.dims(i);
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Sin.cpp b/onert-micro/onert-micro/src/execute/kernels/Sin.cpp
new file mode 100644 (file)
index 0000000..7134bb0
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALSin.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleSin(const OMExecuteArgs &execute_args)
+{
+  auto sin_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                             const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Sin(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, sin_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Slice.cpp b/onert-micro/onert-micro/src/execute/kernels/Slice.cpp
new file mode 100644 (file)
index 0000000..c675a15
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALSlice.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+const int MAX_DIM = 5;
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t input3TensorIdx = 2;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+void getBeginAndSizeVectors(int dimensions, const int32_t *begin_data, const int32_t *size_data,
+                            int32_t *begins, int32_t *sizes)
+{
+  int offset = MAX_DIM - dimensions;
+  for (int idx = 0; idx < dimensions; ++idx)
+  {
+    begins[offset + idx] = begin_data[idx];
+    sizes[offset + idx] = size_data[idx];
+  }
+}
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleSlice(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input1 = nullptr;
+  const circle::Tensor *input2 = nullptr;
+  const circle::Tensor *input3 = nullptr;
+
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input1_data;
+  const int32_t *input2_data;
+  const int32_t *input3_data;
+  uint8_t *output_data;
+
+  OMStatus status = Ok;
+  const circle::SliceOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input1 = runtime_kernel.inputs[input1TensorIdx];
+    input2 = runtime_kernel.inputs[input2TensorIdx];
+    input3 = runtime_kernel.inputs[input3TensorIdx];
+
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input1 != nullptr);
+    assert(input2 != nullptr);
+    assert(input3 != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input1_data = runtime_kernel.inputs_data[input1TensorIdx];
+    input2_data = utils::castInputData<int32_t>(runtime_kernel.inputs_data[input2TensorIdx]);
+    input3_data = utils::castInputData<int32_t>(runtime_kernel.inputs_data[input3TensorIdx]);
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+
+    assert(input1_data != nullptr);
+    assert(input2_data != nullptr);
+    assert(input3_data != nullptr);
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_SliceOptions();
+  }
+
+  OMRuntimeShape input_shape(input1);
+
+  SliceParams op_params{};
+  op_params.begin_count = MAX_DIM;
+  op_params.size_count = MAX_DIM;
+  for (int i = 0; i < MAX_DIM; i++)
+  {
+    op_params.begin[i] = 0;
+    op_params.size[i] = 1;
+  }
+  auto num_dim = input_shape.dimensionsCount();
+
+  getBeginAndSizeVectors(num_dim, input2_data, input3_data, op_params.begin, op_params.size);
+
+  switch (input1->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status = pal::Slice(op_params, input_shape, utils::castInputData<float>(input1_data),
+                          utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+    case circle::TensorType_INT32:
+    {
+      status = pal::Slice(op_params, input_shape, utils::castInputData<int32_t>(input1_data),
+                          utils::castOutputData<int32_t>(output_data));
+    }
+    break;
+    case circle::TensorType_INT64:
+    {
+      status = pal::Slice(op_params, input_shape, utils::castInputData<int64_t>(input1_data),
+                          utils::castOutputData<int64_t>(output_data));
+    }
+    break;
+    default:
+    {
+      status = UnsupportedActivation;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Softmax.cpp b/onert-micro/onert-micro/src/execute/kernels/Softmax.cpp
new file mode 100644 (file)
index 0000000..6b868be
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALSoftmax.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleSoftmax(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input = nullptr;
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input_data = nullptr;
+  uint8_t *output_data = nullptr;
+
+  OMStatus status = Ok;
+
+  const circle::SoftmaxOptions *options;
+  {
+    OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+
+    assert(input != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+
+    options = runtime_kernel.first_operator->builtin_options_as_SoftmaxOptions();
+  }
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  const float beta = options->beta();
+
+  core::OMRuntimeShape inputs_shape(input);
+  core::OMRuntimeShape outputs_shape(output);
+
+  const auto dim_count = inputs_shape.dimensionsCount();
+
+  const auto trailing_dim = dim_count - 1;
+
+  int flat_size = 1;
+  for (int i = 0; i < inputs_shape.dimensionsCount(); ++i)
+  {
+    flat_size *= (i == trailing_dim) ? 1 : inputs_shape.dims(i);
+  }
+
+  core::SoftmaxParams params{};
+  params.beta = beta;
+  params.num_rows = flat_size;
+  params.row_size = std::min(inputs_shape.dims(trailing_dim), outputs_shape.dims(trailing_dim));
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+
+      status = pal::Softmax(params, core::utils::castInputData<float>(input_data),
+                            core::utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+    {
+      assert(output->type() == circle::TensorType_INT8);
+      if (output->type() != circle::TensorType_INT8)
+        return UnsupportedType;
+
+      assert(input->quantization() != nullptr and output->quantization() != nullptr);
+      assert(input->quantization()->scale() != nullptr and
+             output->quantization()->scale() != nullptr);
+      assert(input->quantization()->zero_point() != nullptr and
+             output->quantization()->zero_point() != nullptr);
+      assert(input->quantization()->scale()->size() == 1 and
+             output->quantization()->scale()->size() == 1);
+      assert(input->quantization()->zero_point()->size() == 1 and
+             output->quantization()->zero_point()->size() == 1);
+
+      params.output_scale = output->quantization()->scale()->operator[](0);
+      params.input_scale = input->quantization()->scale()->operator[](0);
+      params.output_zp = output->quantization()->zero_point()->operator[](0);
+      params.input_zp = input->quantization()->zero_point()->operator[](0);
+
+      status = pal::Softmax(params, core::utils::castInputData<int8_t>(input_data),
+                            core::utils::castOutputData<int8_t>(output_data));
+    }
+    break;
+#endif // DIS_QUANT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/SpaceToBatchND.cpp b/onert-micro/onert-micro/src/execute/kernels/SpaceToBatchND.cpp
new file mode 100644 (file)
index 0000000..dfa1934
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/SpacesBatchesNDCommon.h"
+#include "PALSpaceToBatchND.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+OMStatus onert_micro::execute::execute_kernel_CircleSpaceToBatchND(
+  const onert_micro::execute::OMExecuteArgs &execute_args)
+{
+  auto batch_to_space_float_lambda =
+    [](const core::OMRuntimeShape &input1_shape, const float *input1_data,
+       const core::OMRuntimeShape &input2_shape, const int32_t *block_shape_data,
+       const core::OMRuntimeShape &input3_shape, const int32_t *crops_data,
+       const core::OMRuntimeShape &output_shape, float *output_data) {
+      return pal::SpaceToBatchND<float>(input1_shape, input1_data, input2_shape, block_shape_data,
+                                        input3_shape, crops_data, output_shape, output_data);
+    };
+
+  return execute_spaces_batches_nd_common(execute_args, batch_to_space_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/SpaceToDepth.cpp b/onert-micro/onert-micro/src/execute/kernels/SpaceToDepth.cpp
new file mode 100644 (file)
index 0000000..313b80f
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "core/OMRuntimeShape.h"
+#include "PALSpaceToDepth.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+OMStatus onert_micro::execute::execute_kernel_CircleSpaceToDepth(
+  const onert_micro::execute::OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *output_data;
+
+  // Read kernel
+  execute::OMRuntimeKernel runtime_kernel;
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input = runtime_kernel.inputs[inputTensorIdx];
+  output = runtime_kernel.outputs[outputTensorIdx];
+
+  core::OMRuntimeShape input_shape(input);
+  core::OMRuntimeShape output_shape(output);
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input_data = runtime_kernel.inputs_data[inputTensorIdx];
+  output_data = runtime_kernel.outputs_data[outputTensorIdx];
+  const auto *options = runtime_kernel.first_operator->builtin_options_as_SpaceToDepthOptions();
+  const int32_t block_size = options->block_size();
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status =
+        pal::SpaceToDepth<float>(block_size, input_shape, reinterpret_cast<float *>(input_data),
+                                 output_shape, reinterpret_cast<float *>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/SpacesBatchesNDCommon.cpp b/onert-micro/onert-micro/src/execute/kernels/SpacesBatchesNDCommon.cpp
new file mode 100644 (file)
index 0000000..d93c4d0
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/SpacesBatchesNDCommon.h"
+#include "execute/OMUtils.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t input3TensorIdx = 2;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_spaces_batches_nd_common(
+  const OMExecuteArgs &execute_args,
+  const std::function<
+    OMStatus(const core::OMRuntimeShape &unextended_input1_shape, const float *input1_data,
+             const core::OMRuntimeShape &unextended_input2_shape, const int32_t *block_shape_data,
+             const core::OMRuntimeShape &unextended_input3_shape, const int32_t *crops_data,
+             const core::OMRuntimeShape &unextended_output_shape, float *output_data)> &func)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input1;
+  const circle::Tensor *input2;
+  const circle::Tensor *input3;
+  const circle::Tensor *output;
+
+  uint8_t *input1_data;
+  uint8_t *input2_data;
+  uint8_t *input3_data;
+  uint8_t *output_data;
+
+  uint16_t input1_index = 0;
+  uint16_t input2_index = 0;
+
+  // Read kernel
+
+  execute::OMRuntimeKernel runtime_kernel;
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input1 = runtime_kernel.inputs[input1TensorIdx];
+  input2 = runtime_kernel.inputs[input2TensorIdx];
+  input3 = runtime_kernel.inputs[input3TensorIdx];
+  output = runtime_kernel.outputs[outputTensorIdx];
+
+  core::OMRuntimeShape input1_shape(input1);
+  core::OMRuntimeShape input2_shape(input1);
+  core::OMRuntimeShape input3_shape(input1);
+  core::OMRuntimeShape output_shape(output);
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(input3 != nullptr);
+  assert(output != nullptr);
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  input1_data = runtime_kernel.inputs_data[input1TensorIdx];
+  input2_data = runtime_kernel.inputs_data[input2TensorIdx];
+  input3_data = runtime_kernel.inputs_data[input3TensorIdx];
+  output_data = runtime_kernel.outputs_data[outputTensorIdx];
+
+  switch (input1->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status = func(input1_shape, reinterpret_cast<float *>(input1_data), input2_shape,
+                    reinterpret_cast<int32_t *>(input2_data), input3_shape,
+                    reinterpret_cast<int32_t *>(input3_data), output_shape,
+                    reinterpret_cast<float *>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Split.cpp b/onert-micro/onert-micro/src/execute/kernels/Split.cpp
new file mode 100644 (file)
index 0000000..982566b
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALSplit.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t axisTensorIdx = 0;
+constexpr uint32_t inputTensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleSplit(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *axis;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *axis_data;
+
+  // Read kernel
+  const circle::SplitOptions *options;
+
+  core::SplitParams params{};
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    axis = runtime_kernel.inputs[axisTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(axis != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    axis_data = runtime_kernel.inputs_data[axisTensorIdx];
+    assert(input_data != nullptr);
+    assert(axis_data != nullptr);
+    options = runtime_kernel.first_operator->builtin_options_as_SplitOptions();
+
+    params.num_outputs = options->num_splits();
+
+    for (uint32_t i = 0; i < params.num_outputs; ++i)
+    {
+      params.output_data[i] = runtime_kernel.outputs_data[i];
+    }
+  }
+  OMStatus status;
+  OMRuntimeShape axis_shape(axis);
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  int32_t axis_value = utils::castInputData<int32_t>(axis_data)[0];
+  if (axis_value < 0)
+  {
+    axis_value += input_shape.dimensionsCount() + 1;
+  }
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      status = pal::Split<float>(params, input_shape, core::utils::castInputData<float>(input_data),
+                                 output_shape, axis_value);
+      break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedActivation;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Sqrt.cpp b/onert-micro/onert-micro/src/execute/kernels/Sqrt.cpp
new file mode 100644 (file)
index 0000000..f2fe8b8
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALSqrt.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleSqrt(const OMExecuteArgs &execute_args)
+{
+  auto sqrt_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                              const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Sqrt(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, sqrt_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Square.cpp b/onert-micro/onert-micro/src/execute/kernels/Square.cpp
new file mode 100644 (file)
index 0000000..776552b
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALSquare.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleSquare(const OMExecuteArgs &execute_args)
+{
+  auto square_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                                const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Square(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, square_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/SquaredDifference.cpp b/onert-micro/onert-micro/src/execute/kernels/SquaredDifference.cpp
new file mode 100644 (file)
index 0000000..6ccb2fa
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMRuntimeShape.h"
+
+#include "execute/OMUtils.h"
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALSquaredDifference.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t numInput = 2;
+constexpr uint32_t numOutput = 1;
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+// TODO: reduce code duplication with Add, Mul
+OMStatus
+onert_micro::execute::execute_kernel_CircleSquaredDifference(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input1;
+  const circle::Tensor *input2;
+  const circle::Tensor *output;
+
+  uint8_t *input1_data;
+  uint8_t *input2_data;
+  uint8_t *output_data;
+
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input1 = runtime_kernel.inputs[input1TensorIdx];
+    input2 = runtime_kernel.inputs[input2TensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input1 != nullptr);
+    assert(input2 != nullptr);
+    assert(output != nullptr);
+
+    runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+
+    input1_data = runtime_kernel.inputs_data[input1TensorIdx];
+    input2_data = runtime_kernel.inputs_data[input2TensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+    assert(input1_data != nullptr);
+    assert(input2_data != nullptr);
+    assert(output_data != nullptr);
+  }
+
+  OMStatus status;
+
+  core::OMRuntimeShape input1_shape(input1);
+  core::OMRuntimeShape input2_shape(input2);
+  core::OMRuntimeShape output_shape(output);
+
+  core::BinaryArithmeticBroadcastParams params{};
+  const bool need_broadcast = pal::processBroadcastShapes(input1_shape, input2_shape, &params);
+
+  switch (input1->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status = execute::calculateActivationRange(
+        circle::ActivationFunctionType::ActivationFunctionType_NONE, &params.float_activation_min,
+        &params.float_activation_max);
+      if (need_broadcast)
+      {
+        status = pal::BroadcastSquaredDifference4DSlow(
+          params, input1_shape, core::utils::castInputData<float>(input1_data), input2_shape,
+          core::utils::castInputData<float>(input2_data), output_shape,
+          core::utils::castOutputData<float>(output_data));
+      }
+      else
+      {
+        status = pal::SquaredDifference(params, input1_shape.flatSize(),
+                                        core::utils::castInputData<float>(input1_data),
+                                        core::utils::castInputData<float>(input2_data),
+                                        core::utils::castOutputData<float>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/StridedSlice.cpp b/onert-micro/onert-micro/src/execute/kernels/StridedSlice.cpp
new file mode 100644 (file)
index 0000000..b814586
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALStridedSlice.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t beginTensorIdx = 1;
+constexpr uint32_t endTensorIdx = 2;
+constexpr uint32_t stridesTensorIdx = 3;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+core::StridedSliceParams buildStridedSliceParams(int32_t dims, const int32_t *begin,
+                                                 const int32_t *end, const int32_t *strides,
+                                                 const circle::StridedSliceOptions *options)
+{
+  core::StridedSliceParams op_params;
+  op_params.start_indices_count = dims;
+  op_params.stop_indices_count = dims;
+  op_params.strides_count = dims;
+
+  for (int i = 0; i < dims; ++i)
+  {
+    op_params.start_indices[i] = begin[i];
+    op_params.stop_indices[i] = end[i];
+    op_params.strides[i] = strides[i];
+  }
+
+  op_params.begin_mask = options->begin_mask();
+  op_params.ellipsis_mask = 0;
+  op_params.end_mask = options->end_mask();
+  op_params.new_axis_mask = 0;
+  op_params.shrink_axis_mask = options->shrink_axis_mask();
+  return op_params;
+}
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleStridedSlice(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input = nullptr;
+  const circle::Tensor *begin = nullptr;
+  const circle::Tensor *end = nullptr;
+  const circle::Tensor *strides = nullptr;
+
+  const circle::Tensor *output = nullptr;
+
+  uint8_t *input_data;
+  const int32_t *begin_data;
+  const int32_t *end_data;
+  const int32_t *strides_data;
+  uint8_t *output_data;
+
+  OMStatus status = Ok;
+  const circle::StridedSliceOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    begin = runtime_kernel.inputs[beginTensorIdx];
+    end = runtime_kernel.inputs[endTensorIdx];
+    strides = runtime_kernel.inputs[stridesTensorIdx];
+
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(begin != nullptr);
+    assert(end != nullptr);
+    assert(strides != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    begin_data = utils::castInputData<int32_t>(runtime_kernel.inputs_data[beginTensorIdx]);
+    end_data = utils::castInputData<int32_t>(runtime_kernel.inputs_data[endTensorIdx]);
+    strides_data = utils::castInputData<int32_t>(runtime_kernel.inputs_data[stridesTensorIdx]);
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+
+    assert(input_data != nullptr);
+    assert(begin_data != nullptr);
+    assert(end_data != nullptr);
+    assert(strides_data != nullptr);
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_StridedSliceOptions();
+  }
+
+  core::OMRuntimeShape input_shape(input);
+
+  auto op_params = buildStridedSliceParams(input_shape.dimensionsCount(), begin_data, end_data,
+                                           strides_data, options);
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status = pal::StridedSlice(op_params, input_shape, utils::castInputData<float>(input_data),
+                                 utils::castOutputData<float>(output_data));
+    }
+    break;
+#endif // DIS_FLOAT
+#ifndef DIS_QUANT
+    case circle::TensorType_INT8:
+    {
+      status = pal::StridedSlice(op_params, input_shape, utils::castInputData<int8_t>(input_data),
+                                 utils::castOutputData<int8_t>(output_data));
+    }
+    break;
+#endif // DIS_QUANT
+    case circle::TensorType_INT32:
+    {
+      status = pal::StridedSlice(op_params, input_shape, utils::castInputData<int32_t>(input_data),
+                                 utils::castOutputData<int32_t>(output_data));
+    }
+    break;
+    default:
+    {
+      status = UnsupportedActivation;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Sub.cpp b/onert-micro/onert-micro/src/execute/kernels/Sub.cpp
new file mode 100644 (file)
index 0000000..6e32e88
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMRuntimeShape.h"
+
+#include "execute/OMUtils.h"
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALSub.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t numInput = 2;
+constexpr uint32_t numOutput = 1;
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesnt currently support dynamic shapes
+// TODO: reduce code duplication with Add, Mul
+OMStatus onert_micro::execute::execute_kernel_CircleSub(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input1;
+  const circle::Tensor *input2;
+  const circle::Tensor *output;
+
+  uint8_t *input1_data;
+  uint8_t *input2_data;
+  uint8_t *output_data;
+
+  const circle::SubOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, runtime_context);
+
+    input1 = runtime_kernel.inputs[input1TensorIdx];
+    input2 = runtime_kernel.inputs[input2TensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input1 != nullptr);
+    assert(input2 != nullptr);
+    assert(output != nullptr);
+
+    runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+
+    input1_data = runtime_kernel.inputs_data[input1TensorIdx];
+    input2_data = runtime_kernel.inputs_data[input2TensorIdx];
+    output_data = runtime_kernel.outputs_data[outputTensorIdx];
+    assert(input1_data != nullptr);
+    assert(input2_data != nullptr);
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_SubOptions();
+  }
+
+  OMStatus status;
+
+  core::OMRuntimeShape input1_shape(input1);
+  core::OMRuntimeShape input2_shape(input2);
+  core::OMRuntimeShape output_shape(output);
+
+  core::BinaryArithmeticBroadcastParams params{};
+  const bool need_broadcast = pal::processBroadcastShapes(input1_shape, input2_shape, &params);
+
+  switch (input1->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+      status = execute::calculateActivationRange(options->fused_activation_function(),
+                                                 &params.float_activation_min,
+                                                 &params.float_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastSub4DSlow(
+          params, input1_shape, core::utils::castInputData<float>(input1_data), input2_shape,
+          core::utils::castInputData<float>(input2_data), output_shape,
+          core::utils::castOutputData<float>(output_data));
+      }
+      else
+      {
+        status =
+          pal::Sub(params, input1_shape.flatSize(), core::utils::castInputData<float>(input1_data),
+                   core::utils::castInputData<float>(input2_data),
+                   core::utils::castOutputData<float>(output_data));
+      }
+    }
+    break;
+    case circle::TensorType_INT64:
+    {
+      status = execute::calculateActivationRange(options->fused_activation_function(),
+                                                 &params.int64_activation_min,
+                                                 &params.int64_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastSub4DSlow(
+          params, input1_shape, core::utils::castInputData<int64_t>(input1_data), input2_shape,
+          core::utils::castInputData<int64_t>(input2_data), output_shape,
+          core::utils::castOutputData<int64_t>(output_data));
+      }
+      else
+      {
+        status = pal::Sub(params, input1_shape.flatSize(),
+                          core::utils::castInputData<int64_t>(input1_data),
+                          core::utils::castInputData<int64_t>(input2_data),
+                          core::utils::castOutputData<int64_t>(output_data));
+      }
+    }
+    break;
+    case circle::TensorType_INT32:
+    {
+      status = execute::calculateActivationRange(options->fused_activation_function(),
+                                                 &params.int32_activation_min,
+                                                 &params.int32_activation_max);
+
+      if (need_broadcast)
+      {
+        status = pal::BroadcastSub4DSlow(
+          params, input1_shape, core::utils::castInputData<int32_t>(input1_data), input2_shape,
+          core::utils::castInputData<int32_t>(input2_data), output_shape,
+          core::utils::castOutputData<int32_t>(output_data));
+      }
+      else
+      {
+        status = pal::Sub(params, input1_shape.flatSize(),
+                          core::utils::castInputData<int32_t>(input1_data),
+                          core::utils::castInputData<int32_t>(input2_data),
+                          core::utils::castOutputData<int32_t>(output_data));
+      }
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedType;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Tanh.cpp b/onert-micro/onert-micro/src/execute/kernels/Tanh.cpp
new file mode 100644 (file)
index 0000000..52d4954
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/kernels/MathCommon.h"
+#include "PALTanh.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleTanh(const OMExecuteArgs &execute_args)
+{
+  auto tanh_float_lambda = [](const core::OMRuntimeShape &input_shape, const float *input_data,
+                              const core::OMRuntimeShape &output_shape, float *output_data) {
+    return pal::Tanh(input_shape, input_data, output_shape, output_data);
+  };
+
+  return execute_math_common(execute_args, tanh_float_lambda);
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Transpose.cpp b/onert-micro/onert-micro/src/execute/kernels/Transpose.cpp
new file mode 100644 (file)
index 0000000..cc11c4f
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALTranspose.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+constexpr int kInputTensorIdx = 0;
+constexpr int kPermTensorIdx = 1;
+constexpr int kOutputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleTranspose(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *perm;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *perm_data;
+  uint8_t *output_data;
+
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input = runtime_kernel.inputs[kInputTensorIdx];
+    perm = runtime_kernel.inputs[kPermTensorIdx];
+    output = runtime_kernel.outputs[kOutputTensorIdx];
+    assert(input != nullptr);
+    assert(perm != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[kInputTensorIdx];
+    perm_data = runtime_kernel.inputs_data[kPermTensorIdx];
+    output_data = runtime_kernel.outputs_data[kOutputTensorIdx];
+    assert(input_data != nullptr);
+    assert(perm_data != nullptr);
+    assert(output_data != nullptr);
+  }
+  OMStatus status;
+  OMRuntimeShape perm_shape(perm);
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  for (int idx = 0; idx < input_shape.dimensionsCount(); ++idx)
+    assert(reinterpret_cast<int32_t *>(perm_data)[idx] >= 0 and
+           perm_data[idx] < input_shape.dimensionsCount());
+
+  core::TransposeParams params;
+  params.perm_count = perm_shape.dims(0);
+  for (int i = 0; i < params.perm_count; ++i)
+    params.perm[i] = reinterpret_cast<int32_t *>(perm_data)[i];
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      status = pal::Transpose<float>(params, input_shape, reinterpret_cast<float *>(input_data),
+                                     output_shape, reinterpret_cast<float *>(output_data));
+      break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedActivation;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/TransposeConv.cpp b/onert-micro/onert-micro/src/execute/kernels/TransposeConv.cpp
new file mode 100644 (file)
index 0000000..d780328
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALTransposeConv.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+// For the TfLite transpose_conv implementation, input tensor 0 corresponds to
+// the OutputShapeTensor. However, since TFLM does not support dynamic tensors,
+// the TFLM implementation ignores input tensor 0 and the only inputs we care
+// about are kFilterTensor, kInputTensor and kBiasTensor.
+
+constexpr int kWeightTensorIdx = 1;
+constexpr int kInputTensorIdx = 2;
+constexpr int kBiasTensorIdx = 3;
+constexpr int kOutputTensorIdx = 0;
+
+} // namespace
+
+// NOTE: doesn't currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleTransposeConv(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *weight;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *weight_data;
+  uint8_t *bias_data;
+  uint8_t *output_data;
+
+  const circle::TransposeConvOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input = runtime_kernel.inputs[kInputTensorIdx];
+    weight = runtime_kernel.inputs[kWeightTensorIdx];
+    output = runtime_kernel.outputs[kOutputTensorIdx];
+    assert(input != nullptr);
+    assert(weight != nullptr);
+    // Bias can be nullptr
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[kInputTensorIdx];
+    weight_data = runtime_kernel.inputs_data[kWeightTensorIdx];
+    bias_data = runtime_kernel.inputs_data[kBiasTensorIdx];
+    output_data = runtime_kernel.outputs_data[kOutputTensorIdx];
+    assert(input_data != nullptr);
+    assert(weight_data != nullptr);
+    // Bias can be nullptr
+    assert(output_data != nullptr);
+
+    options = runtime_kernel.first_operator->builtin_options_as_TransposeConvOptions();
+  }
+
+  OMStatus status;
+
+  int32_t padding_h = 0;
+  int32_t padding_w = 0;
+
+  OMRuntimeShape weight_shape(weight);
+  OMRuntimeShape input_shape(input);
+
+  const int input_width = input_shape.dims(2);
+  const int input_height = input_shape.dims(1);
+  const int weight_width = weight_shape.dims(2);
+  const int weight_height = weight_shape.dims(1);
+
+  // Note: Dilation height and width are always 1 for transpose_conv
+  execute::computePaddingHeightWidth(options->stride_h(), options->stride_w(), 1, 1, input_height,
+                                     input_width, weight_height, weight_width, options->padding(),
+                                     &padding_h, &padding_w);
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+    {
+
+      FloatConv2D params{};
+      status = calculateActivationRange(options->fused_activation_function(),
+                                        &params.activation_min, &params.activation_max);
+      params.stride_w = options->stride_w();
+      params.stride_h = options->stride_h();
+      params.dilation_width_factor = 1;
+      params.dilation_height_factor = 1;
+      params.pad_h = padding_h;
+      params.pad_w = padding_w;
+
+      if (status != Ok)
+        return status;
+
+      status = pal::TransposeConv<float>(
+        &params, input_shape, core::utils::castInputData<float>(input_data), weight_shape,
+        core::utils::castInputData<float>(weight_data),
+        core::utils::castInputData<float>(bias_data), OMRuntimeShape(output),
+        core::utils::castOutputData<float>(output_data));
+      assert(status == Ok);
+    }
+    break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedActivation;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/Unpack.cpp b/onert-micro/onert-micro/src/execute/kernels/Unpack.cpp
new file mode 100644 (file)
index 0000000..cfa61f4
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMKernelExecutionBuilder.h"
+#include "execute/OMUtils.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "PALUnpack.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::execute::execute_kernel_CircleUnpack(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+
+  // Read kernel
+  const circle::UnpackOptions *options;
+
+  core::SplitParams params{};
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(output != nullptr);
+
+    status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+    if (status != Ok)
+      return status;
+
+    input_data = runtime_kernel.inputs_data[inputTensorIdx];
+    assert(input_data != nullptr);
+    options = runtime_kernel.first_operator->builtin_options_as_UnpackOptions();
+
+    params.num_outputs = options->num();
+
+    for (uint32_t i = 0; i < params.num_outputs; ++i)
+    {
+      params.output_data[i] = runtime_kernel.outputs_data[i];
+    }
+  }
+  OMStatus status;
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  int32_t axis_value = options->axis();
+
+  switch (input->type())
+  {
+#ifndef DIS_FLOAT
+    case circle::TensorType_FLOAT32:
+      status =
+        pal::Unpack<float>(params, input_shape, core::utils::castInputData<float>(input_data),
+                           output_shape, axis_value);
+      break;
+#endif // DIS_FLOAT
+    default:
+    {
+      status = UnsupportedActivation;
+      assert(false && "Unsupported type.");
+    }
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/While.cpp b/onert-micro/onert-micro/src/execute/kernels/While.cpp
new file mode 100644 (file)
index 0000000..d59fa82
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMKernelExecutionBuilder.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/OMUtils.h"
+#include "core/OMDataType.h"
+#include "execute/OMKernelExecute.h"
+
+using namespace onert_micro;
+using namespace onert_micro::execute;
+
+// NOTE: doesnt currently support dynamic shapes
+OMStatus onert_micro::execute::execute_kernel_CircleWhile(const OMExecuteArgs &execute_args)
+{
+  core::OMRuntimeModule &runtime_module = execute_args.runtime_module;
+  core::OMRuntimeContext &runtime_context = execute_args.runtime_context;
+  core::OMRuntimeStorage &runtime_storage = execute_args.runtime_storage;
+  uint16_t op_index = execute_args.kernel_index;
+
+  OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+  auto options = runtime_kernel.first_operator->builtin_options_as_WhileOptions();
+
+  // Obtain conditional and body runtime subgraphs
+  const auto body_subgraph_index = options->body_subgraph_index();
+  const auto cond_subgraph_index = options->cond_subgraph_index();
+  core::OMRuntimeGraph *cond_runtime_graph = nullptr;
+  core::OMRuntimeGraph *body_runtime_graph = nullptr;
+  runtime_module.getRuntimeGraphAt(cond_subgraph_index, &cond_runtime_graph);
+  runtime_module.getRuntimeGraphAt(body_subgraph_index, &body_runtime_graph);
+
+  core::OMRuntimeContext &cond_runtime_context = cond_runtime_graph->getRuntimeContext();
+  core::OMRuntimeStorage &cond_runtime_storage = cond_runtime_graph->getRuntimeStorage();
+  core::memory::OMRuntimeAllocator &cond_runtime_allocator =
+    cond_runtime_graph->getRuntimeAllocator();
+
+  core::OMRuntimeContext &body_runtime_context = body_runtime_graph->getRuntimeContext();
+  core::OMRuntimeStorage &body_runtime_storage = body_runtime_graph->getRuntimeStorage();
+  core::memory::OMRuntimeAllocator &body_runtime_allocator =
+    body_runtime_graph->getRuntimeAllocator();
+
+  OMStatus status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  // Copy input data to the output
+  assert(runtime_kernel.inputs_num == runtime_kernel.outputs_num);
+  for (uint32_t i = 0; i < runtime_kernel.inputs_num; ++i)
+  {
+    const auto cur_input_tensor = runtime_kernel.inputs[i];
+    const auto input_data_size = sizeof(core::OMDataType(cur_input_tensor->type())) *
+                                 core::OMRuntimeShape(cur_input_tensor).flatSize();
+    std::memcpy(runtime_kernel.outputs_data[i], runtime_kernel.inputs_data[i], input_data_size);
+  }
+
+  do
+  {
+    // Handle conditional graph
+    {
+      // Allocate cond graph inputs
+      cond_runtime_graph->allocateGraphInputs();
+      auto cond_graphs_inputs = cond_runtime_graph->getNumberOfInputs();
+      for (uint32_t i = 0; i < cond_graphs_inputs; ++i)
+      {
+        auto *cur_cond_input_data =
+          reinterpret_cast<uint8_t *>(cond_runtime_graph->getInputDataAt(i));
+        uint8_t *cur_main_input_data = runtime_kernel.outputs_data[i];
+        assert(cur_main_input_data != nullptr);
+        assert(cur_cond_input_data != nullptr);
+        const auto cur_input_tensor = runtime_kernel.inputs[i];
+        const auto input_data_size = sizeof(core::OMDataType(cur_input_tensor->type())) *
+                                     core::OMRuntimeShape(cur_input_tensor).flatSize();
+        std::memcpy(cur_cond_input_data, cur_main_input_data, input_data_size);
+      }
+      // Run cond graph
+      execute::OMExecuteArgs cond_execute_args = {cond_runtime_storage, cond_runtime_context, 0,
+                                                  runtime_module};
+      status = execute::OMKernelExecute::runForward(cond_execute_args, cond_runtime_allocator);
+      if (status != Ok)
+        return status;
+
+      // Check cond graph result
+      bool cond_result_value = reinterpret_cast<bool *>(cond_runtime_graph->getOutputDataAt(0))[0];
+      // Reset cond graph values
+      cond_runtime_graph->reset();
+      // If false - then finish while loop
+      if (cond_result_value == false)
+        break;
+    }
+
+    // Handle body graph
+    {
+      // Allocate body graph inputs
+      body_runtime_graph->allocateGraphInputs();
+      // Copy data
+      auto body_graphs_inputs = body_runtime_graph->getNumberOfInputs();
+      for (uint32_t i = 0; i < body_graphs_inputs; ++i)
+      {
+        auto *cur_body_input_data =
+          reinterpret_cast<uint8_t *>(body_runtime_graph->getInputDataAt(i));
+        uint8_t *cur_main_input_data = runtime_kernel.outputs_data[i];
+        assert(cur_main_input_data != nullptr);
+        assert(cur_body_input_data != nullptr);
+        const auto cur_input_tensor = runtime_kernel.inputs[i];
+        const auto input_data_size = sizeof(core::OMDataType(cur_input_tensor->type())) *
+                                     core::OMRuntimeShape(cur_input_tensor).flatSize();
+        std::memcpy(cur_body_input_data, cur_main_input_data, input_data_size);
+      }
+      // Run body graph
+      execute::OMExecuteArgs body_execute_args = {body_runtime_storage, body_runtime_context, 0,
+                                                  runtime_module};
+      status = execute::OMKernelExecute::runForward(body_execute_args, body_runtime_allocator);
+      if (status != Ok)
+        return status;
+
+      // Copy body calculated data to the main output
+      for (uint32_t i = 0; i < runtime_kernel.inputs_num; ++i)
+      {
+        auto cur_calculated_data = body_runtime_graph->getOutputDataAt(i);
+        const auto cur_tensor = runtime_kernel.outputs[i];
+        const auto data_size = sizeof(core::OMDataType(cur_tensor->type())) *
+                               core::OMRuntimeShape(cur_tensor).flatSize();
+        std::memcpy(runtime_kernel.outputs_data[i], cur_calculated_data, data_size);
+      }
+
+      body_runtime_graph->reset();
+    }
+  } while (true);
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Abs.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Abs.test.cpp
new file mode 100644 (file)
index 0000000..b8176a6
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/abs/FloatAbsKernel.h"
+#include "test_models/abs/NegAbsKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class AbsTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(AbsTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatAbs test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &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)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchAbsKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(AbsTest, Input_output_shape_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputShapeMismatchAbsKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Add.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Add.test.cpp
new file mode 100644 (file)
index 0000000..c152c9e
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/add/FloatAddKernel.h"
+#include "test_models/add/NegAddKernel.h"
+#include "test_models/add/IntAddKernel.h"
+#include "test_models/add/QuantAddKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class AddTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(AddTest, INT32_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestData32IntAdd test_data_add_no_broadcasting(is_with_broadcast);
+    std::vector<int32_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int32_t>(2, &test_data_add_no_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_no_broadcasting.get_output_data_by_index(0));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestData32IntAdd test_data_add_with_broadcasting(is_with_broadcast);
+    std::vector<int32_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int32_t>(2, &test_data_add_with_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_with_broadcasting.get_output_data_by_index(0));
+  }
+}
+
+TEST_F(AddTest, INT64_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestData64IntAdd test_data_add_no_broadcasting(is_with_broadcast);
+    std::vector<int64_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int64_t>(2, &test_data_add_no_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_no_broadcasting.get_output_data_by_index(0));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestData64IntAdd test_data_add_with_broadcasting(is_with_broadcast);
+    std::vector<int64_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int64_t>(2, &test_data_add_with_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_with_broadcasting.get_output_data_by_index(0));
+  }
+}
+
+TEST_F(AddTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestDataFloatAdd test_data_float_add_no_broadcasting(is_with_broadcast);
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_float_add_no_broadcasting);
+    EXPECT_THAT(
+      output_data_vector,
+      FloatArrayNear(test_data_float_add_no_broadcasting.get_output_data_by_index(0), 0.0001f));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestDataFloatAdd test_data_float_add_with_broadcasting(is_with_broadcast);
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_float_add_with_broadcasting);
+    EXPECT_THAT(
+      output_data_vector,
+      FloatArrayNear(test_data_float_add_with_broadcasting.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(AddTest, INT8_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestDataInt8Add test_data_add_no_broadcasting(is_with_broadcast);
+    std::vector<int8_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int8_t>(2, &test_data_add_no_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_no_broadcasting.get_output_data_by_index(0));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestDataInt8Add test_data_add_with_broadcasting(is_with_broadcast);
+    std::vector<int8_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int8_t>(2, &test_data_add_with_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_with_broadcasting.get_output_data_by_index(0));
+  }
+}
+
+TEST_F(AddTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputMismatchAddKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(AddTest, No_quant_params_NEG)
+{
+  onert_micro::test_model::NegTestDataNoQuantParamsS16AddKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(AddTest, No_output_scale_param_NEG)
+{
+  onert_micro::test_model::NegTestQuantAddNoScaleKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/AddN.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/AddN.test.cpp
new file mode 100644 (file)
index 0000000..c4659ff
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/add_n/FloatAddNKernel.h"
+#include "test_models/add_n/NegAddNKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+class AddNTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(AddNTest, Float_P)
+{
+  test_model::TestDataFloatAddN test_data_float_add_n;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(3, &test_data_float_add_n);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_float_add_n.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(AddNTest, InputTypeMismatch_NEG)
+{
+  onert_micro::test_model::TestDataInputTypeMismatchAddN test_data_kernel;
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/ArgMax.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/ArgMax.test.cpp
new file mode 100644 (file)
index 0000000..f04ba37
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/arg_max/FloatArgMaxKernel.h"
+#include "test_models/arg_max/NegArgMaxKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+class ArgMaxTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(ArgMaxTest, Float_P)
+{
+  test_model::TestDataFloatArgMax test_data_float_arg_max;
+  std::vector<int> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_float_arg_max);
+  EXPECT_TRUE(output_data_vector == test_data_float_arg_max.get_output_data_by_index(0));
+}
+
+TEST_F(ArgMaxTest, InputTypeMismatch_NEG)
+{
+  onert_micro::test_model::TestDataAxisOutputTypeMismatchArgMax test_data_kernel;
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/ArgMin.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/ArgMin.test.cpp
new file mode 100644 (file)
index 0000000..74ebd02
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/arg_min/FloatArgMinKernel.h"
+#include "test_models/arg_min/NegArgMinKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+class ArgMinTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(ArgMinTest, Float_P)
+{
+  test_model::TestDataFloatArgMin test_data_float_arg_min;
+  std::vector<int> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_float_arg_min);
+  EXPECT_TRUE(output_data_vector == test_data_float_arg_min.get_output_data_by_index(0));
+}
+
+TEST_F(ArgMinTest, InputTypeMismatch_NEG)
+{
+  onert_micro::test_model::TestDataAxisOutputTypeMismatchArgMin test_data_kernel;
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/AveragePool2D.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/AveragePool2D.test.cpp
new file mode 100644 (file)
index 0000000..78c2fdb
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/averagepool2d/FloatAveragePool2DKernel.h"
+#include "test_models/averagepool2d/NegAveragePool2DKernel.h"
+#include "test_models/averagepool2d/QuantAveragePool2DKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class AveragePool2DTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(AveragePool2DTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatAveragePool2D test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(AveragePool2DTest, S8_P)
+{
+  onert_micro::test_model::TestDataS8AveragePool2D test_data_kernel;
+  std::vector<int8_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int8_t>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(AveragePool2DTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchAveragePool2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(AveragePool2DTest, No_quant_params_NEG)
+{
+  onert_micro::test_model::NegTestDataNoQuantParamsAveragePool2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/BatchToSpaceND.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/BatchToSpaceND.test.cpp
new file mode 100644 (file)
index 0000000..2c89ea3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/batch_to_space_nd/FloatBatchToSpaceNDKernel.h"
+#include "test_models/batch_to_space_nd/NegBatchToSpaceNDKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class BatchToSpaceNDTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(BatchToSpaceNDTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatBatchToSpaceND test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(BatchToSpaceNDTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchBatchToSpaceNDKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Concatenation.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Concatenation.test.cpp
new file mode 100644 (file)
index 0000000..0d14256
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/concatenation/FloatConcatenationKernel.h"
+#include "test_models/concatenation/NegConcatenationKernel.h"
+#include "test_models/concatenation/IntConcatenationKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class ConcatenationTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(ConcatenationTest, INT64_P)
+{
+  test_model::TestDataS64Concatenation test_data_kernel;
+  std::vector<int64_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int64_t>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(ConcatenationTest, INT32_P)
+{
+  test_model::TestDataS32Concatenation test_data_kernel;
+  std::vector<int32_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int32_t>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(ConcatenationTest, Float_P)
+{
+  test_model::TestDataFloatConcatenation test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(ConcatenationTest, Input_type_mismatch_NEG)
+{
+  test_model::TestDataInputTypeMismatchConcatenation test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(ConcatenationTest, With_activation_NEG)
+{
+  test_model::TestDataReluConcatenation test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(ConcatenationTest, Wrong_axis_NEG)
+{
+  test_model::TestDataWrongAxisConcatenation test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Conv2D.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Conv2D.test.cpp
new file mode 100644 (file)
index 0000000..b68b643
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/conv2d/FloatConv2DKernel.h"
+#include "test_models/conv2d/QuantConv2DKernel.h"
+#include "test_models/conv2d/NegConv2DKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class Conv2DTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(Conv2DTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatConv2D test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(Conv2DTest, S8_P)
+{
+  onert_micro::test_model::TestDataS8Conv2D test_data_kernel;
+  std::vector<int8_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int8_t>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(Conv2DTest, No_quant_params_NEG)
+{
+  onert_micro::test_model::NegTestDataNoQuantParamsConv2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(Conv2DTest, Input_weigth_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputMismatchConv2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(Conv2DTest, Invalid_input_shape_NEG)
+{
+  onert_micro::test_model::NegTestDataInvalidInputShapeConv2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Cos.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Cos.test.cpp
new file mode 100644 (file)
index 0000000..ca09013
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/cos/FloatCosKernel.h"
+#include "test_models/cos/NegCosKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class CosTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(CosTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatCos test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(CosTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchCosKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/DepthwiseConv2D.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/DepthwiseConv2D.test.cpp
new file mode 100644 (file)
index 0000000..42d35ac
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/depthwise_conv_2d/FloatDepthwiseConv2DKernel.h"
+#include "test_models/depthwise_conv_2d/NegDepthwiseConv2DKernel.h"
+#include "test_models/depthwise_conv_2d/QuantDepthwiseConv2DKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class DepthwiseConv2DTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(DepthwiseConv2DTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatDepthwiseConv2D test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(DepthwiseConv2DTest, INT8_P)
+{
+  onert_micro::test_model::TestDataInt8DepthwiseConv2D test_data_kernel;
+  std::vector<int8_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int8_t>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(DepthwiseConv2DTest, No_quant_params_NEG)
+{
+  onert_micro::test_model::NegTestDataNoQuantParamsDepthwiseConv2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(DepthwiseConv2DTest, Input_weigth_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputMismatchDepthwiseConv2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(DepthwiseConv2DTest, Invalid_input_shape_NEG)
+{
+  onert_micro::test_model::NegTestDataInvalidInputShapeDepthwiseConv2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(DepthwiseConv2DTest, Wrong_bias_type_NEG)
+{
+  onert_micro::test_model::NegTestDataWrongBiasTypeDepthwiseConv2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Dequantize.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Dequantize.test.cpp
new file mode 100644 (file)
index 0000000..64b619f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/dequantize/FloatDequantizeKernel.h"
+#include "test_models/dequantize/NegDequantizeKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class DequantizeTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(DequantizeTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatDequantize test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int8_t, float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(DequantizeTest, Invalid_output_shape_NEG)
+{
+  onert_micro::test_model::NegTestDataWithInvalidOutputShapeDequantizeKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Div.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Div.test.cpp
new file mode 100644 (file)
index 0000000..3f3465e
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/div/FloatDivKernel.h"
+#include "test_models/div/NegDivKernel.h"
+#include "test_models/div/IntDivKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class DivTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(DivTest, INT64_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestDataInt64Div test_data_add_no_broadcasting(is_with_broadcast);
+    std::vector<int64_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int64_t>(2, &test_data_add_no_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_no_broadcasting.get_output_data_by_index(0));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestDataInt64Div test_data_add_with_broadcasting(is_with_broadcast);
+    std::vector<int64_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int64_t>(2, &test_data_add_with_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_with_broadcasting.get_output_data_by_index(0));
+  }
+}
+
+TEST_F(DivTest, INT_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestDataIntDiv test_data_add_no_broadcasting(is_with_broadcast);
+    std::vector<int32_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int32_t>(2, &test_data_add_no_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_no_broadcasting.get_output_data_by_index(0));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestDataIntDiv test_data_add_with_broadcasting(is_with_broadcast);
+    std::vector<int32_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int32_t>(2, &test_data_add_with_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_with_broadcasting.get_output_data_by_index(0));
+  }
+}
+
+TEST_F(DivTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestDataFloatDiv test_data_float_add_no_broadcasting(is_with_broadcast);
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_float_add_no_broadcasting);
+    EXPECT_THAT(
+      output_data_vector,
+      FloatArrayNear(test_data_float_add_no_broadcasting.get_output_data_by_index(0), 0.0001f));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestDataFloatDiv test_data_float_add_with_broadcasting(is_with_broadcast);
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_float_add_with_broadcasting);
+    EXPECT_THAT(
+      output_data_vector,
+      FloatArrayNear(test_data_float_add_with_broadcasting.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(DivTest, Wrong_Input1_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput1WrongTypeDiv test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(DivTest, Wrong_Input2_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput2WrongTypeDiv test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Equal.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Equal.test.cpp
new file mode 100644 (file)
index 0000000..a7c5cf0
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/equal/FloatEqualKernel.h"
+#include "test_models/equal/IntEqualKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+using namespace testing;
+
+class EqualTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(EqualTest, FloatNoBroadcast_P)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataFloatEqual test_data_kernel(is_with_broadcast, false);
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(EqualTest, FloatWithBroadcast_P)
+{
+  const bool is_with_broadcast = true;
+  onert_micro::test_model::TestDataFloatEqual test_data_kernel(is_with_broadcast, false);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(EqualTest, FloatNoBroadcast_NEG)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataFloatEqual test_data_kernel(is_with_broadcast, true);
+
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel)), "");
+}
+
+TEST_F(EqualTest, FloatWithBroadcast_NEG)
+{
+  const bool is_with_broadcast = true;
+  onert_micro::test_model::TestDataFloatEqual test_data_kernel(is_with_broadcast, true);
+
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel)), "");
+}
+
+TEST_F(EqualTest, IntWithBroadcast_P)
+{
+  const bool is_with_broadcast = true;
+  onert_micro::test_model::TestDataIntEqual test_data_kernel(is_with_broadcast, false);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int32_t, bool>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(EqualTest, IntNoBroadcast_P)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataIntEqual test_data_kernel(is_with_broadcast, false);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int32_t, bool>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(EqualTest, IntWithBroadcast_NEG)
+{
+  const bool is_with_broadcast = true;
+  onert_micro::test_model::TestDataIntEqual test_data_kernel(is_with_broadcast, true);
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<int32_t, bool>(2, &test_data_kernel)),
+               "");
+}
+
+TEST_F(EqualTest, IntNoBroadcast_NEG)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataIntEqual test_data_kernel(is_with_broadcast, true);
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<int32_t, bool>(2, &test_data_kernel)),
+               "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Exp.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Exp.test.cpp
new file mode 100644 (file)
index 0000000..dba4983
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/exp/FloatExpKernel.h"
+#include "test_models/exp/NegExpKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class ExpTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(ExpTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatExp test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(ExpTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchExpKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/ExpandDims.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/ExpandDims.test.cpp
new file mode 100644 (file)
index 0000000..918eb2d
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/expand_dims/ExpandDimsKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class ExpandDimsTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(ExpandDimsTest, MainTest_P)
+{
+  onert_micro::test_model::TestDataExpandDimsKernel<float> test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(ExpandDimsTest, MainTest_NEG)
+{
+  onert_micro::test_model::NegTestDataInvalidInputTypeExpandDimsKernel test_data_kernel;
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Floor.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Floor.test.cpp
new file mode 100644 (file)
index 0000000..fca95bc
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/floor/FloatFloorKernel.h"
+#include "test_models/floor/NegFloorKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class FloorTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(FloorTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatFloor test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(FloorTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchFloorKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(FloorTest, Input_output_shape_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInvalidInputOutputShapeFloorKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/FloorDiv.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/FloorDiv.test.cpp
new file mode 100644 (file)
index 0000000..3ef33e2
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/floordiv/FloatFloorDivKernel.h"
+#include "test_models/floordiv/NegFloorDivKernel.h"
+
+#include "PALFloorDiv.h"
+#include <array>
+#include <numeric>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class FloorDivTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(FloorDivTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    onert_micro::test_model::TestDataFloatFloorDiv test_data_kernel(is_with_broadcast);
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_kernel);
+
+    EXPECT_THAT(output_data_vector,
+                FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    onert_micro::test_model::TestDataFloatFloorDiv test_data_kernel(is_with_broadcast);
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_kernel);
+
+    EXPECT_THAT(output_data_vector,
+                FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(FloorDivTest, Wrong_Input1_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput1WrongTypeFloorDiv test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(FloorDivTest, Wrong_Input2_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput2WrongTypeFloorDiv test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(FloorDivTest, PALFloat_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    onert_micro::test_model::TestDataFloatFloorDiv test_data_kernel(is_with_broadcast);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const auto num_elements = input1.size();
+    EXPECT_EQ(num_elements, input2.size());
+
+    std::vector<float> output = std::vector<float>(num_elements);
+    pal::FloorDiv(num_elements, input1.data(), input2.data(), const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    onert_micro::test_model::TestDataFloatFloorDiv test_data_kernel(is_with_broadcast);
+
+    const auto &input1 = test_data_kernel.get_input_data_by_index(0);
+    const auto &input2 = test_data_kernel.get_input_data_by_index(1);
+
+    const int32_t shape[2] = {2, 5};
+    const int32_t shape_broadcast[2] = {2, 1};
+
+    assert(input1.size() ==
+           std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    assert(input2.size() == std::accumulate(std::begin(shape_broadcast), std::end(shape_broadcast),
+                                            1, std::multiplies<float>()));
+
+    std::vector<float> output = std::vector<float>(
+      std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<float>()));
+    pal::BroadcastFloorDiv4DSlow(
+      core::OMRuntimeShape{2, shape}, input1.data(), core::OMRuntimeShape{2, shape_broadcast},
+      input2.data(), core::OMRuntimeShape{2, shape}, const_cast<float *>(output.data()));
+
+    EXPECT_THAT(output, FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/FloorMod.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/FloorMod.test.cpp
new file mode 100644 (file)
index 0000000..39f7a4a
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/floormod/FloatFloorModKernel.h"
+#include "test_models/floormod/NegFloorModKernel.h"
+
+#include "PALFloorMod.h"
+#include <array>
+#include <numeric>
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class FloorModTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(FloorModTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    onert_micro::test_model::TestDataFloatFloorMod test_data_kernel(is_with_broadcast);
+
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_kernel);
+
+    EXPECT_THAT(output_data_vector,
+                FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    onert_micro::test_model::TestDataFloatFloorMod test_data_kernel(is_with_broadcast);
+
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_kernel);
+
+    EXPECT_THAT(output_data_vector,
+                FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(FloorModTest, Wrong_Input1_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput1WrongTypeFloorMod test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(FloorModTest, Wrong_Input2_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput2WrongTypeFloorMod test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/FullyConnected.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/FullyConnected.test.cpp
new file mode 100644 (file)
index 0000000..5085341
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/fully_connected/FloatFullyConnectedKernel.h"
+#include "test_models/fully_connected/NegFullyConnectedKernel.h"
+#include "test_models/fully_connected/QuantFullyConnectedKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class FullyConnectedTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(FullyConnectedTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatFullyConnected test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(FullyConnectedTest, S8_P)
+{
+  onert_micro::test_model::TestDataS8FullyConnected test_data_kernel;
+  std::vector<int8_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int8_t>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(FullyConnectedTest, S16_P)
+{
+  onert_micro::test_model::TestDataS16FullyConnected test_data_kernel;
+  std::vector<int16_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int16_t>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(FullyConnectedTest, Wrong_weight_shape_NEG)
+{
+  onert_micro::test_model::NegTestDataWrongWeightShapeFullyConnectedKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(FullyConnectedTest, Wrong_bias_shape_NEG)
+{
+  onert_micro::test_model::NegTestDataWrongBiasShapeFullyConnectedKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(FullyConnectedTest, No_zero_points_NEG)
+{
+  onert_micro::test_model::NegTestDataNoZeroPointsFullyConnectedKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Gather.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Gather.test.cpp
new file mode 100644 (file)
index 0000000..b3a47d4
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/gather/FloatGatherKernel.h"
+#include "test_models/gather/IntGatherKernel.h"
+#include "test_models/gather/NegGatherKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class GatherTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(GatherTest, Gather_Float_P)
+{
+  onert_micro::test_model::TestDataFloatGather test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(GatherTest, Gather_Int_P)
+{
+  onert_micro::test_model::TestDataIntGather test_data_kernel;
+  std::vector<int32_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int32_t>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(GatherTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchGatherKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(GatherTest, Wrong_position_type_NEG)
+{
+  onert_micro::test_model::NegTestDataWrongPositionTypeGatherKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(GatherTest, Wrong_axis_NEG)
+{
+  onert_micro::test_model::NegTestDataWrongAxisGatherKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+// TODO: add S8 test
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/GatherND.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/GatherND.test.cpp
new file mode 100644 (file)
index 0000000..b3c24f7
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/gather_nd/FloatGatherNDKernel.h"
+#include "test_models/gather_nd/NegGatherNDKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class GatherNDTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(GatherNDTest, Gather_Float_P)
+{
+  onert_micro::test_model::TestDataFloatGatherND test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(GatherNDTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchGatherNDKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Greater.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Greater.test.cpp
new file mode 100644 (file)
index 0000000..a202da5
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/greater/FloatGreaterKernel.h"
+#include "test_models/greater/NegGreaterKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class GreaterTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(GreaterTest, FloatNoBroadcast_P)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataFloatGreater test_data_kernel(is_with_broadcast);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel);
+
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(GreaterTest, FloatNoBroadcast_NEG)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::NegTestDataFloatGreaterTypeMishmach test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/GreaterEqual.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/GreaterEqual.test.cpp
new file mode 100644 (file)
index 0000000..ae087bc
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/greater_equal/FloatGreaterEqualKernel.h"
+#include "test_models/greater_equal/NegGreaterEqualKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class GreaterEqualTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(GreaterEqualTest, FloatNoBroadcast_P)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataFloatGreaterEqual test_data_kernel(is_with_broadcast);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel);
+
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(GreaterEqualTest, FloatNoBroadcast_NEG)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::NegTestDataFloatGreaterEqualTypeMishmach test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/L2Normalize.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/L2Normalize.test.cpp
new file mode 100644 (file)
index 0000000..074a112
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/l2_normalization/FloatL2NormalizeKernel.h"
+#include "test_models/l2_normalization/NegL2NormalizeKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class L2NormalizeTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(L2NormalizeTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatL2Normalization test_data_kernel;
+
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(L2NormalizeTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchNegKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/L2Pool2D.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/L2Pool2D.test.cpp
new file mode 100644 (file)
index 0000000..91861f6
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/l2pool2d/FloatL2Pool2DKernel.h"
+#include "test_models/l2pool2d/NegL2Pool2DKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class L2Pool2DTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(L2Pool2DTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatL2Pool2D test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(L2Pool2DTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchL2Pool2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/LeakyRelu.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/LeakyRelu.test.cpp
new file mode 100644 (file)
index 0000000..1fa2ad9
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/leaky_relu/FloatLeakyReLUKernel.h"
+#include "test_models/leaky_relu/NegLeakyReLUKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class LeakyReLUTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(LeakyReLUTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatLeakyReLU test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(LeakyReLUTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchLeakyReLUKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Less.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Less.test.cpp
new file mode 100644 (file)
index 0000000..f7b8b8f
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/less/FloatLessKernel.h"
+#include "test_models/less/IntLessKernel.h"
+#include "test_models/less/QuantLessKernel.h"
+#include "test_models/less/NegTestDataLessKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+using namespace testing;
+
+class LessTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(LessTest, FloatNoBroadcast_P)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataFloatLess test_data_kernel(is_with_broadcast, false);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel);
+
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(LessTest, FloatWithBroadcast_P)
+{
+  const bool is_with_broadcast = true;
+  onert_micro::test_model::TestDataFloatLess test_data_kernel(is_with_broadcast, false);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel);
+
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(LessTest, FloatNoBroadcast_NEG)
+{
+
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataFloatLess test_data_kernel(is_with_broadcast, true);
+
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel)), "");
+}
+
+TEST_F(LessTest, FloatWithBroadcast_NEG)
+{
+  const bool is_with_broadcast = true;
+  onert_micro::test_model::TestDataFloatLess test_data_kernel(is_with_broadcast, true);
+
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel)), "");
+}
+
+TEST_F(LessTest, IntWithBroadcast_P)
+{
+  const bool is_with_broadcast = true;
+  onert_micro::test_model::TestDataIntLess test_data_kernel(is_with_broadcast, false);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int32_t, bool>(2, &test_data_kernel);
+
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(LessTest, IntNoBroadcast_P)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataIntLess test_data_kernel(is_with_broadcast, false);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int32_t, bool>(2, &test_data_kernel);
+
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(LessTest, IntWithBroadcast_NEG)
+{
+  const bool is_with_broadcast = true;
+  onert_micro::test_model::TestDataIntLess test_data_kernel(is_with_broadcast, true);
+
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<int32_t, bool>(2, &test_data_kernel)),
+               "");
+}
+
+TEST_F(LessTest, IntNoBroadcast_NEG)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataIntLess test_data_kernel(is_with_broadcast, true);
+
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<int32_t, bool>(2, &test_data_kernel)),
+               "");
+}
+
+TEST_F(LessTest, Quant_P)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataQuantLess test_data_kernel(is_with_broadcast, false);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<uint8_t, bool>(2, &test_data_kernel);
+
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(LessTest, Quant_NEG)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataQuantLess test_data_kernel(is_with_broadcast, true);
+
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<uint8_t, bool>(2, &test_data_kernel)),
+               "");
+}
+
+TEST_F(LessTest, Wrong_Output_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataLessKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/LessEqual.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/LessEqual.test.cpp
new file mode 100644 (file)
index 0000000..5e41b90
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/less_equal/FloatLessEqualKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+using namespace testing;
+
+class LessEqualTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(LessEqualTest, FloatNoBroadcast_P)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataFloatLessEqual test_data_kernel(is_with_broadcast, false);
+
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel);
+
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(LessEqualTest, FloatNoBroadcast_NEG)
+{
+
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataFloatLessEqual test_data_kernel(is_with_broadcast, true);
+
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel)), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Log.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Log.test.cpp
new file mode 100644 (file)
index 0000000..9275f14
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/log/FloatLogKernel.h"
+#include "test_models/log/NegLogKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class LogTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(LogTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatLog test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(LogTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchLogKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/LogSoftmax.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/LogSoftmax.test.cpp
new file mode 100644 (file)
index 0000000..fab8aa7
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/log_softmax/FloatLogSoftmaxKernel.h"
+#include "test_models/log_softmax/NegLogSoftmaxKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class LogSoftmaxTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(LogSoftmaxTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatLogSoftmax test_data_kernel;
+
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(LogSoftmaxTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchLogSoftmaxKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Logistic.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Logistic.test.cpp
new file mode 100644 (file)
index 0000000..9b82cad
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/logistic/FloatLogisticKernel.h"
+#include "test_models/logistic/NegLogisticKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class LogisticTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(LogisticTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatLogistic test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(LogisticTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchLogisticKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(LogisticTest, No_quant_params_NEG)
+{
+  onert_micro::test_model::NegTestDataNoQuantParamsLogisticKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+// TODO: Add S8 test
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/MaxPool2D.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/MaxPool2D.test.cpp
new file mode 100644 (file)
index 0000000..8062e56
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/maxpool2d/FloatMaxPool2DKernel.h"
+#include "test_models/maxpool2d/NegMaxPool2DKernel.h"
+#include "test_models/maxpool2d/QuantMaxPool2DKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class MaxPool2DTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(MaxPool2DTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatMaxPool2D test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(MaxPool2DTest, S8_P)
+{
+  onert_micro::test_model::TestDataS8MaxPool2D test_data_kernel;
+  std::vector<int8_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int8_t>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(MaxPool2DTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchMaxPool2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(MaxPool2DTest, Input_invalid_input_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInvalidInputShapeMaxPool2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(MaxPool2DTest, No_quant_params_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataNoQuantParamsMaxPool2DKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Maximum.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Maximum.test.cpp
new file mode 100644 (file)
index 0000000..42148e3
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/maximum/FloatMaximumKernel.h"
+#include "test_models/maximum/NegMaximumKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+using namespace testing;
+
+class MaximumTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(MaximumTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    onert_micro::test_model::TestDataFloatMaximum test_data_kernel(is_with_broadcast);
+
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float, float>(2, &test_data_kernel);
+
+    EXPECT_THAT(output_data_vector,
+                FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    onert_micro::test_model::TestDataFloatMaximum test_data_kernel(is_with_broadcast);
+
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float, float>(2, &test_data_kernel);
+
+    EXPECT_THAT(output_data_vector,
+                FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(MaximumTest, Wrong_Input1_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput1WrongTypeMaximum test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(MaximumTest, Wrong_Input2_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput2WrongTypeMaximum test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Minimum.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Minimum.test.cpp
new file mode 100644 (file)
index 0000000..9a29603
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/minimum/FloatMinimumKernel.h"
+#include "test_models/minimum/NegMinimumKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+using namespace testing;
+
+class MinimumTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(MinimumTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    onert_micro::test_model::TestDataFloatMinimum test_data_kernel(is_with_broadcast);
+
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float, float>(2, &test_data_kernel);
+
+    EXPECT_THAT(output_data_vector,
+                FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    onert_micro::test_model::TestDataFloatMinimum test_data_kernel(is_with_broadcast);
+
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float, float>(2, &test_data_kernel);
+
+    EXPECT_THAT(output_data_vector,
+                FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(MinimumTest, Wrong_Input1_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput1WrongTypeMinimum test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(MinimumTest, Wrong_Input2_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput2WrongTypeMinimum test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Mul.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Mul.test.cpp
new file mode 100644 (file)
index 0000000..a5dcf6b
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/mul/FloatMulKernel.h"
+#include "test_models/mul/NegMulKernel.h"
+#include "test_models/mul/IntMulKernel.h"
+#include "test_models/mul/QuantMulKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class MulTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(MulTest, INT_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestDataIntMul test_data_add_no_broadcasting(is_with_broadcast);
+    std::vector<int32_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int32_t>(2, &test_data_add_no_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_no_broadcasting.get_output_data_by_index(0));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestDataIntMul test_data_add_with_broadcasting(is_with_broadcast);
+    std::vector<int32_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int32_t>(2, &test_data_add_with_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_with_broadcasting.get_output_data_by_index(0));
+  }
+}
+
+TEST_F(MulTest, INT8_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestDataInt8Mul test_data_add_no_broadcasting(is_with_broadcast);
+    std::vector<int8_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int8_t>(2, &test_data_add_no_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_no_broadcasting.get_output_data_by_index(0));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestDataInt8Mul test_data_add_with_broadcasting(is_with_broadcast);
+    std::vector<int8_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int8_t>(2, &test_data_add_with_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_with_broadcasting.get_output_data_by_index(0));
+  }
+}
+
+TEST_F(MulTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestDataFloatMul test_data_float_add_no_broadcasting(is_with_broadcast);
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_float_add_no_broadcasting);
+    EXPECT_THAT(
+      output_data_vector,
+      FloatArrayNear(test_data_float_add_no_broadcasting.get_output_data_by_index(0), 0.0001f));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestDataFloatMul test_data_float_add_with_broadcasting(is_with_broadcast);
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_float_add_with_broadcasting);
+    EXPECT_THAT(
+      output_data_vector,
+      FloatArrayNear(test_data_float_add_with_broadcasting.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(MulTest, Wrong_Input1_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput1WrongTypeMul test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(MulTest, Wrong_Input2_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInput2WrongTypeMul test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(MulTest, Wrong_Ouput_Type_NEG)
+{
+  onert_micro::test_model::NegTestDataInt16TypeMul test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(MulTest, No_output_scale_param_NEG)
+{
+  onert_micro::test_model::NegTestQuantMulNoScaleKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Neg.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Neg.test.cpp
new file mode 100644 (file)
index 0000000..5cfad76
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/neg/FloatNegKernel.h"
+#include "test_models/neg/NegNegKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class NegTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(NegTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatNeg test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(NegTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchNegKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(NegTest, Invalid_input_shape_NEG)
+{
+  onert_micro::test_model::NegTestDataInvalidInputShapeNegKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/NotEqual.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/NotEqual.test.cpp
new file mode 100644 (file)
index 0000000..6a3e010
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 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 "execute/OMTestUtils.h"
+#include "test_models/notequal/FloatNotEqualKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+using namespace testing;
+
+class NotEqualTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(NotEqualTest, FloatNoBroadcast_P)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataFloatNotEqual test_data_kernel(is_with_broadcast, false);
+  std::vector<bool> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(NotEqualTest, FloatNoBroadcast_NEG)
+{
+  const bool is_with_broadcast = false;
+  onert_micro::test_model::TestDataFloatNotEqual test_data_kernel(is_with_broadcast, true);
+  EXPECT_DEATH((onert_micro::execute::testing::checkKernel<float, bool>(2, &test_data_kernel)), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Pack.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Pack.test.cpp
new file mode 100644 (file)
index 0000000..1f63ea3
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/pack/PackKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class PackTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(PackTest, Float_P)
+{
+  test_model::TestDataFloatPack test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(PackTest, Int_P)
+{
+  test_model::TestDataIntPack test_data_kernel;
+  std::vector<int32_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int32_t>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+// TODO: add negative tests and quant version
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Pad.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Pad.test.cpp
new file mode 100644 (file)
index 0000000..519d7a4
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/pad/FloatPadKernel.h"
+#include "test_models/pad/NegPadKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class PadTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(PadTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatPad test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(PadTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchPadKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Relu.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Relu.test.cpp
new file mode 100644 (file)
index 0000000..280e512
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/relu/FloatReLUKernel.h"
+#include "test_models/relu/NegReLUKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class ReLUTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(ReLUTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatReLU test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(ReLUTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchReLUKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Relu6.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Relu6.test.cpp
new file mode 100644 (file)
index 0000000..0279c0d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/relu6/FloatReLU6Kernel.h"
+#include "test_models/relu6/NegReLU6Kernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class ReLU6Test : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(ReLU6Test, Float_P)
+{
+  onert_micro::test_model::TestDataFloatReLU6 test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(ReLU6Test, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchReLU6Kernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Reshape.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Reshape.test.cpp
new file mode 100644 (file)
index 0000000..dda748e
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/reshape/ReshapeKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class ReshapeTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(ReshapeTest, MainTest_P)
+{
+  onert_micro::test_model::TestDataReshapeKernel<float> test_data_kernel(false);
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(ReshapeTest, MainTest_NEG)
+{
+  onert_micro::test_model::TestDataReshapeKernel<float> test_data_kernel(true);
+  EXPECT_DEATH(checkKernel(1, &test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Round.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Round.test.cpp
new file mode 100644 (file)
index 0000000..324c99d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/round/FloatRoundKernel.h"
+#include "test_models/round/NegRoundKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class RoundTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(RoundTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatRound test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(RoundTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchRoundKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Rsqrt.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Rsqrt.test.cpp
new file mode 100644 (file)
index 0000000..c1f71ba
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/rsqrt/FloatRsqrtKernel.h"
+#include "test_models/rsqrt/NegRsqrtKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class RsqrtTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(RsqrtTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatRsqrt test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(RsqrtTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchRsqrtKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Shape.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Shape.test.cpp
new file mode 100644 (file)
index 0000000..eb17152
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/shape/ShapeKernel.h"
+#include "test_models/shape/NegShapeKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class ShapeTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(ShapeTest, MainTest_P)
+{
+  onert_micro::test_model::TestDataShapeKernel<float, int32_t> test_data_kernel;
+  std::vector<int32_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float, int32_t>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(ShapeTest, Wrong_output_type_NEG)
+{
+  onert_micro::test_model::NegTestDataWrongOutputTypeShapeKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Sin.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Sin.test.cpp
new file mode 100644 (file)
index 0000000..ca7bfc7
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/sin/FloatSinKernel.h"
+#include "test_models/sin/NegSinKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class SinTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(SinTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatSin test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SinTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchSinKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Slice.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Slice.test.cpp
new file mode 100644 (file)
index 0000000..c72b4ec
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/slice/FloatSliceKernel.h"
+#include "test_models/slice/IntSliceKernel.h"
+#include "test_models/slice/NegSliceKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class SliceTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(SliceTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatSlice test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SliceTest, INT_P)
+{
+  // Check int32
+  {
+    onert_micro::test_model::TestDataInt32Slice test_data_kernel;
+    std::vector<int32_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int32_t>(1, &test_data_kernel);
+    EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+  }
+
+  // Check int64
+  {
+    onert_micro::test_model::TestDataInt64Slice test_data_kernel;
+    std::vector<int64_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int64_t>(1, &test_data_kernel);
+    EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+  }
+}
+
+TEST_F(SliceTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::TestDataTypeMismatchSlice test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(SliceTest, Wrong_Begin_type_NEG)
+{
+  onert_micro::test_model::TestDataWrongBeginTypeSlice test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(SliceTest, Wrong_size_type_NEG)
+{
+  onert_micro::test_model::TestDataWrongSizeTypeSlice test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(SliceTest, Wrong_input_shape_NEG)
+{
+  onert_micro::test_model::TestDataWrongInputShapeSlice test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Softmax.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Softmax.test.cpp
new file mode 100644 (file)
index 0000000..9e67712
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/softmax/FloatSoftmaxKernel.h"
+#include "test_models/softmax/NegSoftmaxKernel.h"
+#include "test_models/softmax/QuantSoftmaxKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class SoftmaxTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(SoftmaxTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatSoftmax test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(SoftmaxTest, Int8_P)
+{
+  onert_micro::test_model::TestDataInt8Softmax test_data_kernel;
+  std::vector<int8_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int8_t>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(SoftmaxTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchSoftmaxKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(SoftmaxTest, No_quant_params_NEG)
+{
+  onert_micro::test_model::NegTestDataNoQuantParamsSoftmaxKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/SpaceToBatchND.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/SpaceToBatchND.test.cpp
new file mode 100644 (file)
index 0000000..f4caaa2
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/space_to_batch_nd/FloatSpaceToBatchNDKernel.h"
+#include "test_models/space_to_batch_nd/NegSpaceToBatchNDKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class SpaceToBatchNDTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(SpaceToBatchNDTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatSpaceToBatchND test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(SpaceToBatchNDTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchSpaceToBatchNDKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/SpaceToDepth.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/SpaceToDepth.test.cpp
new file mode 100644 (file)
index 0000000..e427e20
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/space_to_depth/FloatSpaceToDepthKernel.h"
+#include "test_models/space_to_depth/NegSpaceToDepthKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class SpaceToDepthTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(SpaceToDepthTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatSpaceToDepth test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(SpaceToDepthTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchSpaceToDepthKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Split.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Split.test.cpp
new file mode 100644 (file)
index 0000000..94dd2e9
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/split/FloatSplitKernel.h"
+#include "test_models/split/NegSplitKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class SplitTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(SplitTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatSplit test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(SplitTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchSplitKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Sqrt.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Sqrt.test.cpp
new file mode 100644 (file)
index 0000000..d1a27b8
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/sqrt/FloatSqrtKernel.h"
+#include "test_models/sqrt/NegSqrtKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class SqrtTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(SqrtTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatSqrt test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SqrtTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchSqrtKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Square.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Square.test.cpp
new file mode 100644 (file)
index 0000000..0dabcca
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/square/FloatSquareKernel.h"
+#include "test_models/square/NegSquareKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class SquareTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(SquareTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatSquare test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SquareTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchSquareKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/SquaredDifference.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/SquaredDifference.test.cpp
new file mode 100644 (file)
index 0000000..caac28e
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/squared_difference/FloatSquaredDifferenceKernel.h"
+#include "test_models/squared_difference/NegSquaredDifferenceKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class SquaredDifferenceTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(SquaredDifferenceTest, Float_P)
+{
+
+  test_model::TestDataFloatSquaredDifference test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(2, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(SquaredDifferenceTest, Inputs_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputsTypeMismatchSquaredDifference test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/StridedSlice.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/StridedSlice.test.cpp
new file mode 100644 (file)
index 0000000..31c9ecb
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/strided_slice/StridedSliceKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class StridedSliceTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(StridedSliceTest, MainTest_P)
+{
+  onert_micro::test_model::TestDataStridedSliceKernel<float> test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+// TODO: add INT32 and INT8 tests
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Sub.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Sub.test.cpp
new file mode 100644 (file)
index 0000000..91d9da4
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/sub/FloatSubKernel.h"
+#include "test_models/sub/NegSubKernel.h"
+#include "test_models/sub/IntSubKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class SubTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(SubTest, INT_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestDataIntSub test_data_add_no_broadcasting(is_with_broadcast);
+    std::vector<int32_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int32_t>(2, &test_data_add_no_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_no_broadcasting.get_output_data_by_index(0));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestDataIntSub test_data_add_with_broadcasting(is_with_broadcast);
+    std::vector<int32_t> output_data_vector =
+      onert_micro::execute::testing::checkKernel<int32_t>(2, &test_data_add_with_broadcasting);
+    EXPECT_THAT(output_data_vector, test_data_add_with_broadcasting.get_output_data_by_index(0));
+  }
+}
+
+TEST_F(SubTest, Float_P)
+{
+  // No broadcast
+  {
+    const bool is_with_broadcast = false;
+    test_model::TestDataFloatSub test_data_float_add_no_broadcasting(is_with_broadcast);
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_float_add_no_broadcasting);
+    EXPECT_THAT(
+      output_data_vector,
+      FloatArrayNear(test_data_float_add_no_broadcasting.get_output_data_by_index(0), 0.0001f));
+  }
+  // With broadcast
+  {
+    const bool is_with_broadcast = true;
+    test_model::TestDataFloatSub test_data_float_add_with_broadcasting(is_with_broadcast);
+    std::vector<float> output_data_vector =
+      onert_micro::execute::testing::checkKernel<float>(2, &test_data_float_add_with_broadcasting);
+    EXPECT_THAT(
+      output_data_vector,
+      FloatArrayNear(test_data_float_add_with_broadcasting.get_output_data_by_index(0), 0.0001f));
+  }
+}
+
+TEST_F(SubTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchSubKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(SubTest, Inputs_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputsTypeMismatchSubKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(SubTest, No_quant_params_NEG)
+{
+  onert_micro::test_model::NegTestDataNoQuantParamsSubKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Tanh.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Tanh.test.cpp
new file mode 100644 (file)
index 0000000..9a3f4be
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/tanh/FloatTanhKernel.h"
+#include "test_models/tanh/NegTanhKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class TanhTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(TanhTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatTanh test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(TanhTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchTanhKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Transpose.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Transpose.test.cpp
new file mode 100644 (file)
index 0000000..eff37e8
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/transpose/TransposeKernel.h"
+#include "test_models/transpose/NegTransposeKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class TransposeTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(TransposeTest, Float_P)
+{
+  onert_micro::test_model::TestDataTransposeKernel<float> test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(TransposeTest, Perm_wrong_type_NEG)
+{
+  onert_micro::test_model::NegTestDataWrongPermTypeTransposeKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/TransposeConv.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/TransposeConv.test.cpp
new file mode 100644 (file)
index 0000000..33f8360
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/transpose_conv/FloatTransposeConvKernel.h"
+#include "test_models/transpose_conv/NegTransposeConvKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class TransposeConvTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(TransposeConvTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatTransposeConv test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector,
+              FloatArrayNear(test_data_kernel.get_output_data_by_index(0), 0.0001f));
+}
+
+TEST_F(TransposeConvTest, Input_weigth_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputMismatchTransposeConvKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+TEST_F(TransposeConvTest, Invalid_input_shape_NEG)
+{
+  onert_micro::test_model::NegTestDataInvalidInputShapeTransposeConvKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/Unpack.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/Unpack.test.cpp
new file mode 100644 (file)
index 0000000..9c57388
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/unpack/FloatUnpackKernel.h"
+#include "test_models/unpack/NegUnpackKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class UnpackTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(UnpackTest, Float_P)
+{
+  onert_micro::test_model::TestDataFloatUnpack test_data_kernel;
+  std::vector<float> output_data_vector =
+    onert_micro::execute::testing::checkKernel<float>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(UnpackTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataInputOutputTypeMismatchUnpackKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/execute/kernels/tests/While.test.cpp b/onert-micro/onert-micro/src/execute/kernels/tests/While.test.cpp
new file mode 100644 (file)
index 0000000..97f91bb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "execute/OMTestUtils.h"
+#include "test_models/while/WhileKernel.h"
+#include "test_models/while/NegWhileKernel.h"
+
+namespace onert_micro
+{
+namespace execute
+{
+namespace testing
+{
+
+using namespace testing;
+
+class WhileTest : public ::testing::Test
+{
+  // Do nothing
+};
+
+TEST_F(WhileTest, Main_P)
+{
+  onert_micro::test_model::TestDataWhileKernel<int32_t> test_data_kernel;
+  std::vector<int32_t> output_data_vector =
+    onert_micro::execute::testing::checkKernel<int32_t>(1, &test_data_kernel);
+  EXPECT_THAT(output_data_vector, test_data_kernel.get_output_data_by_index(0));
+}
+
+TEST_F(WhileTest, Input_output_type_mismatch_NEG)
+{
+  onert_micro::test_model::NegTestDataWhileKernel test_data_kernel;
+
+  EXPECT_DEATH(checkNEGSISOKernel(&test_data_kernel), "");
+}
+
+} // namespace testing
+} // namespace execute
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/import/CMakeLists.txt b/onert-micro/onert-micro/src/import/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ee8ea4d
--- /dev/null
@@ -0,0 +1,35 @@
+message(STATUS "ONERT MICRO IMPORT BUILD BEGIN")
+
+set(SOURCES
+        OMExecutionPlanCreator.cpp
+        OMKernelConfiguration.cpp
+        OMKernelConfigureBuilder.cpp
+        helpers/OMConfigureSISOKernel.cpp
+        helpers/OMPadCommon.cpp
+        helpers/OMConfigureTISOKernel.cpp
+        helpers/OMSpacesBatchesNDCommon.cpp
+        helpers/OMPoolingCommon.cpp
+        helpers/OMArgCommon.cpp
+        )
+
+# Add configure kernels
+macro(REGISTER_KERNEL OPERATOR, NODE)
+    list(APPEND SOURCES "kernels/${NODE}.cpp")
+endmacro(REGISTER_KERNEL)
+
+# To add REGISTER_KERNEL list
+include(${KERNEL_REGISTER_FILE})
+
+macro(REGISTER_CUSTOM_KERNEL NODE)
+    list(APPEND SOURCES "kernels/${NODE}.cpp")
+endmacro(REGISTER_CUSTOM_KERNEL)
+
+# To add CUSTOM_REGISTER_KERNEL list
+include(${CUSTOM_KERNEL_REGISTER_FILE})
+
+add_library(${OM_IMPORT_LIB} STATIC ${SOURCES})
+
+target_include_directories(${OM_IMPORT_LIB} PUBLIC "${OM_INCLUDE_DIR}")
+target_link_libraries(${OM_IMPORT_LIB} PUBLIC ${OM_CORE_LIB})
+
+message(STATUS "ONERT MICRO IMPORT BUILD FINISHED")
diff --git a/onert-micro/onert-micro/src/import/OMExecutionPlanCreator.cpp b/onert-micro/onert-micro/src/import/OMExecutionPlanCreator.cpp
new file mode 100644 (file)
index 0000000..fb85184
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMExecutionPlanCreator.h"
+
+#include <map>
+
+using namespace onert_micro::core;
+using namespace onert_micro::import;
+using namespace onert_micro;
+
+namespace
+{
+
+// Layers with trainable weights
+// Note: needed not to store some layers with const intputs but it is not trainable (for example
+// Reshape)
+bool isTrainableWeights(const circle::OperatorCode *opcode)
+{
+  switch (opcode->builtin_code())
+  {
+    case circle::BuiltinOperator_FULLY_CONNECTED:
+    case circle::BuiltinOperator_CONV_2D:
+      return true;
+    default:
+      return false;
+  }
+}
+
+} // namespace
+
+/*
+ * Create execution plan for forward graph
+ * TODO: describe creation execution plan logic
+ */
+OMStatus OMExecutionPlanCreator::createExecutionPlan(core::OMRuntimeStorage &runtime_storage,
+                                                     core::OMRuntimeContext &runtime_context,
+                                                     core::memory::OMRuntimeAllocator &allocator,
+                                                     const OMConfig &configs)
+{
+  bool keep_input = configs.keep_input;
+  bool train_mode = configs.train_mode;
+
+  std::vector<std::vector<uint16_t>> &alloc_plan = allocator.getAllocPlan();
+  std::vector<std::vector<uint16_t>> &dealloc_plan = allocator.getDeallocPlan();
+
+  using Lifetime = std::pair<int32_t, int32_t>;
+
+  std::map<uint16_t, Lifetime> lifetimes;
+
+  const reader::CircleOperators *operators = runtime_context.getCircleOperators();
+
+  const size_t num_kernels = operators->size();
+
+  uint32_t num_train_layers = configs.training_context.num_of_train_layers;
+  if (train_mode and num_train_layers == 0)
+    num_train_layers = num_kernels;
+
+  if (not keep_input)
+  {
+    auto graph_inputs = runtime_context.getCircleInputs();
+    for (const auto input_ind : *graph_inputs)
+    {
+      assert(lifetimes.count(input_ind) == 0);
+      lifetimes[input_ind] = Lifetime(-1, 0);
+    }
+  }
+
+  for (int32_t index = 0; index < num_kernels; ++index)
+  {
+    auto *cur_op = operators->operator[](index);
+
+    const auto *op_inputs = cur_op->inputs();
+    const auto *op_outputs = cur_op->outputs();
+    auto kernel_type = runtime_storage.getKernelType(index);
+    for (int32_t j = 0; j < op_inputs->size(); ++j)
+    {
+      const auto input_index = op_inputs->operator[](j);
+
+      if (input_index == -1)
+        continue;
+
+      // Pass constant tensors
+      if (runtime_context.isConstTensor(input_index))
+        continue;
+
+      if (lifetimes.count(input_index) > 0)
+      {
+        if (kernel_type == Inplace or train_mode and index >= (num_kernels - num_train_layers))
+          lifetimes.at(input_index).second = -1;
+        else
+          lifetimes.at(input_index).second = index;
+      }
+    }
+
+    for (int32_t j = 0; j < op_outputs->size(); ++j)
+    {
+      const auto output_index = op_outputs->operator[](j);
+
+      if (kernel_type == Inplace)
+        lifetimes[output_index] = Lifetime(-1, index);
+      else if (train_mode and index >= (num_kernels - num_train_layers))
+        lifetimes[output_index] = Lifetime(index, -1);
+      else
+        lifetimes[output_index] = Lifetime(index, index);
+    }
+  }
+  auto graph_outputs = runtime_context.getCircleOutputs();
+  for (const auto output_ind : *graph_outputs)
+  {
+    if (lifetimes.count(output_ind) > 0)
+      lifetimes.at(output_ind).second = static_cast<int32_t>(num_kernels);
+  }
+
+  alloc_plan.assign(num_kernels, std::vector<uint16_t>());
+  dealloc_plan.assign(num_kernels + 1, std::vector<uint16_t>());
+
+  for (const auto &item : lifetimes)
+  {
+    if (item.second.first != -1)
+      alloc_plan[item.second.first].push_back(item.first);
+    if (item.second.second != -1)
+      dealloc_plan[item.second.second].push_back(item.first);
+  }
+
+  return Ok;
+}
+
+/*
+ * Create execution plan for backward graph:
+ * - Allocate memory for inputs for current op using the following rules:
+ *   1) Don't allocate data for non const input tensor if it is last op for training (don't need to
+ * backpropagate result) 2) Don't allocate data for const input tensor if is non trainable const 3)
+ * Allocate data otherwise
+ * - Deallocate memory for outputs for current op using the following rules:
+ *   1) Deallocate all outputs tensors.
+ */
+OMStatus OMExecutionPlanCreator::createBackwardExecutionPlan(
+  core::OMRuntimeStorage &runtime_storage, core::OMRuntimeContext &runtime_context,
+  core::memory::OMRuntimeAllocator &allocator, const OMConfig &configs)
+{
+  bool keep_input = configs.keep_input;
+  bool train_mode = configs.train_mode;
+  assert(train_mode);
+  if (train_mode == false)
+    return UnknownError;
+
+  std::vector<std::vector<uint16_t>> &alloc_plan = allocator.getAllocPlan();
+  std::vector<std::vector<uint16_t>> &dealloc_plan = allocator.getDeallocPlan();
+
+  using Lifetime = std::pair<int32_t, int32_t>;
+  std::map<uint16_t, Lifetime> lifetimes;
+
+  const reader::CircleOperators *operators = runtime_context.getCircleOperators();
+  const uint32_t num_kernels = operators->size();
+
+  uint32_t num_train_layers = configs.training_context.num_of_train_layers == 0
+                                ? num_kernels
+                                : configs.training_context.num_of_train_layers;
+  auto graph_outputs = runtime_context.getCircleOutputs();
+
+  for (const auto output_ind : *graph_outputs)
+  {
+    assert(lifetimes.count(output_ind) == 0);
+    lifetimes[output_ind] = Lifetime(-1, 0);
+  }
+
+  uint32_t last_node_pos = std::min(num_kernels, num_train_layers);
+  const auto *op_codes = runtime_context.getCircleOpcodes();
+  for (int32_t index = 0; index < last_node_pos; ++index)
+  {
+    uint32_t cur_op_index = num_kernels - index - 1;
+    auto *cur_op = operators->operator[](cur_op_index);
+
+    uint32_t cur_opcode_index = cur_op->opcode_index();
+
+    assert(cur_opcode_index < op_codes->size());
+
+    const auto opcode = op_codes->operator[](cur_opcode_index);
+
+    const auto *op_inputs = cur_op->inputs();
+    const auto *op_outputs = cur_op->outputs();
+    for (int32_t j = 0; j < op_inputs->size(); ++j)
+    {
+      const auto input_index = op_inputs->operator[](j);
+      const auto is_const = runtime_context.isConstTensor(input_index);
+      // Note: we dont need to allocate for last node and for empty tensor
+      if (input_index == -1 or (is_const and not isTrainableWeights(opcode)) or
+          ((index == last_node_pos - 1) and !is_const))
+      {
+        continue;
+      }
+      lifetimes[input_index] = {index, -1};
+    }
+
+    for (int32_t j = 0; j < op_outputs->size(); ++j)
+    {
+      const auto output_index = op_outputs->operator[](j);
+
+      lifetimes.at(output_index).second = index;
+    }
+  }
+
+  alloc_plan.assign(last_node_pos, std::vector<uint16_t>());
+  dealloc_plan.assign(last_node_pos, std::vector<uint16_t>());
+
+  for (const auto &item : lifetimes)
+  {
+    if (item.second.first != -1)
+      alloc_plan[item.second.first].push_back(item.first);
+    if (item.second.second != -1)
+      dealloc_plan[item.second.second].push_back(item.first);
+  }
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/import/OMKernelConfiguration.cpp b/onert-micro/onert-micro/src/import/OMKernelConfiguration.cpp
new file mode 100644 (file)
index 0000000..cbc626b
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfiguration.h"
+#include "core/OMKernelType.h"
+#include "import/OMKernelConfigureBuilder.h"
+
+using namespace onert_micro::core;
+using namespace onert_micro::import;
+using namespace onert_micro;
+
+OMStatus OMKernelConfiguration::configureKernels(OMConfigureArgs &configure_args)
+{
+  OMRuntimeContext &runtime_context = configure_args.runtime_context;
+  const reader::CircleOperators *operators = runtime_context.getCircleOperators();
+
+  const auto num_operators = static_cast<uint16_t>(operators->size());
+  const auto op_codes = runtime_context.getCircleOpcodes();
+
+  OMStatus status = Ok;
+  for (uint16_t i = 0; i < num_operators; ++i)
+  {
+    OMBuilderID builder_id = core::OMBuilderID::Size;
+    const circle::Operator *op = operators->operator[](i);
+    uint32_t index = op->opcode_index();
+
+    assert(index < op_codes->size());
+
+    const auto opcode = op_codes->operator[](index);
+
+    status = core::getBuilderId(opcode, builder_id);
+
+    assert(status == Ok);
+    if (status != Ok)
+      return status;
+
+    KernelConfigureFunc *configure_func = nullptr;
+    if (size_t(builder_id) < size_t(core::OMBuilderID::BuiltinOperatorsSize))
+    {
+      // Builtin operator
+      status = kernel_builtin_configure.getKernelConfigureFunc(builder_id, &configure_func);
+    }
+    else
+    {
+      // Custom
+      status = kernel_custom_configure.getKernelConfigureFunc(builder_id, &configure_func);
+    }
+
+    assert(configure_func != nullptr);
+
+    if (status != Ok)
+      return status;
+
+    configure_args.kernel_index = i;
+    status = configure_func(configure_args);
+    assert(status == Ok && "");
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/OMKernelConfigureBuilder.cpp b/onert-micro/onert-micro/src/import/OMKernelConfigureBuilder.cpp
new file mode 100644 (file)
index 0000000..e2dab78
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
diff --git a/onert-micro/onert-micro/src/import/helpers/OMArgCommon.cpp b/onert-micro/onert-micro/src/import/helpers/OMArgCommon.cpp
new file mode 100644 (file)
index 0000000..d0c0453
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMArgCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus
+onert_micro::import::helpers::configure_arg_kernel_common(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+  assert(output != nullptr);
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  assert(input1 != nullptr);
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  assert(input2 != nullptr);
+
+  const OMRuntimeShape input2_shape(input2);
+
+  // dim tensor must be a scalar or has one element
+  status =
+    utils::checkCondition(input2_shape.dimensionsCount() == 0 or input2_shape.flatSize() == 1);
+  if (status != Ok)
+    return status;
+
+  // value and output type must match
+  status = utils::checkCondition(output->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+  status = utils::checkCondition(input2->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input1->type() != circle::TensorType_INT8 and
+                                 input1->type() != circle::TensorType_INT16);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/helpers/OMConfigureSISOKernel.cpp b/onert-micro/onert-micro/src/import/helpers/OMConfigureSISOKernel.cpp
new file mode 100644 (file)
index 0000000..abc6e3e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::helpers::configure_SISO_kernel(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  status = utils::checkCondition(input_shape == output_shape);
+
+  if (input->type() != circle::TensorType_INT8 and input->type() != circle::TensorType_INT16)
+    return status;
+
+  // Check quantized version
+  if (input->quantization() == nullptr or output->quantization() == nullptr)
+    return NoQuantization;
+
+  if (output->quantization()->scale() == nullptr or output->quantization()->scale()->size() != 1)
+    return UnsupportedQuantizationType;
+
+  if (input->quantization()->zero_point() == nullptr or
+      input->quantization()->zero_point()->size() != 1)
+    return UnsupportedQuantizationType;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/helpers/OMConfigureTISOKernel.cpp b/onert-micro/onert-micro/src/import/helpers/OMConfigureTISOKernel.cpp
new file mode 100644 (file)
index 0000000..93e7210
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureTISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+// TISO - Two Inputs Single Output
+OMStatus onert_micro::import::helpers::configure_TISO_kernel(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input2->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  if (input1->type() != circle::TensorType_INT8 and input1->type() != circle::TensorType_INT16)
+    return status;
+
+#ifndef DIS_QUANT
+
+  // Check quantization params
+  if (input1->quantization() == nullptr or input2->quantization() == nullptr or
+      output->quantization() == nullptr)
+  {
+    return NoQuantization;
+  }
+
+  if (input1->quantization()->scale() == nullptr or
+      input1->quantization()->zero_point() == nullptr or
+      input1->quantization()->scale()->size() != 1 or
+      input1->quantization()->zero_point()->size() != 1)
+  {
+    return NoQuantization;
+  }
+
+  if (input2->quantization()->scale() == nullptr or
+      input2->quantization()->zero_point() == nullptr or
+      input2->quantization()->scale()->size() != 1 or
+      input2->quantization()->zero_point()->size() != 1)
+  {
+    return NoQuantization;
+  }
+
+  if (output->quantization()->scale() == nullptr or
+      output->quantization()->zero_point() == nullptr or
+      output->quantization()->scale()->size() != 1 or
+      output->quantization()->zero_point()->size() != 1)
+  {
+    return NoQuantization;
+  }
+
+#endif // DIS_QUANT
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/helpers/OMPadCommon.cpp b/onert-micro/onert-micro/src/import/helpers/OMPadCommon.cpp
new file mode 100644 (file)
index 0000000..3f08054
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMPadCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t input3TensorIdx = 2;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus
+onert_micro::import::helpers::configure_pad_kernel_common(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  OMRuntimeStorage &runtime_storage = config_args.runtime_storage;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *input3 = runtime_kernel.inputs[input3TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input2->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+
+  if (input3 != nullptr)
+  {
+    status = utils::checkCondition(input3->type() == input1->type());
+    if (status != Ok)
+      return status;
+
+    // Value is scalar
+    status = utils::checkCondition(OMRuntimeShape(input3).flatSize() == 1);
+    if (status != Ok)
+      return status;
+  }
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/import/helpers/OMPoolingCommon.cpp b/onert-micro/onert-micro/src/import/helpers/OMPoolingCommon.cpp
new file mode 100644 (file)
index 0000000..f44e53d
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMPooingCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus
+onert_micro::import::helpers::configure_pooling_kernel_common(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == output_shape.dimensionsCount());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == 4);
+
+  auto option = runtime_kernel.first_operator->builtin_options_as_Pool2DOptions();
+
+  if (option == nullptr)
+    return UnknownError;
+
+  assert(option != nullptr);
+
+  if (input->type() != circle::TensorType_INT8 and input->type() != circle::TensorType_INT16)
+    return status;
+
+  // Check quantization params
+  if (input->quantization() == nullptr)
+  {
+    return NoQuantization;
+  }
+
+  if (input->quantization()->scale()->size() != 1)
+  {
+    return UnsupportedType;
+  }
+
+  // Check quantization params
+  if (output->quantization() == nullptr)
+  {
+    return NoQuantization;
+  }
+
+  if (output->quantization()->scale()->size() != 1)
+  {
+    return UnsupportedType;
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/helpers/OMSpacesBatchesNDCommon.cpp b/onert-micro/onert-micro/src/import/helpers/OMSpacesBatchesNDCommon.cpp
new file mode 100644 (file)
index 0000000..b8592a1
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMSpacesBatchesNDCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t input3TensorIdx = 2;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::helpers::configure_spaces_batches_nd_kernel_common(
+  const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *input3 = runtime_kernel.inputs[input3TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  core::OMRuntimeShape input1_shape(input1);
+  core::OMRuntimeShape output_shape(output);
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(input3 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input2->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input3->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(output_shape.dimensionsCount() >= 3);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input1_shape.dimensionsCount() >= 3);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(output_shape.dimensionsCount() <= 4);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input1_shape.dimensionsCount() <= 4);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Abs.cpp b/onert-micro/onert-micro/src/import/kernels/Abs.cpp
new file mode 100644 (file)
index 0000000..f614e69
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleAbs(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Add.cpp b/onert-micro/onert-micro/src/import/kernels/Add.cpp
new file mode 100644 (file)
index 0000000..90bd876
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureTISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleAdd(const OMConfigureArgs &config_args)
+{
+  return import::helpers::configure_TISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/AddN.cpp b/onert-micro/onert-micro/src/import/kernels/AddN.cpp
new file mode 100644 (file)
index 0000000..c009576
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleAddN(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const auto kInputsNum = runtime_kernel.inputs_num;
+
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+  assert(output != nullptr);
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  assert(input1 != nullptr);
+  const OMRuntimeShape input1_shape(input1);
+
+  for (int idx = 1; idx < kInputsNum; ++idx)
+  {
+    const circle::Tensor *input = runtime_kernel.inputs[idx];
+    assert(input != nullptr);
+    status = utils::checkCondition(input1->type() == input->type());
+    if (status != Ok)
+      return status;
+  }
+
+  status = utils::checkCondition(input1->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  for (int idx = 1; idx < kInputsNum; ++idx)
+  {
+    const circle::Tensor *input = runtime_kernel.inputs[idx];
+    assert(input != nullptr);
+    const OMRuntimeShape input_shape(input);
+    status = utils::checkCondition(input_shape == input1_shape);
+    if (status != Ok)
+      return status;
+  }
+
+  status = utils::checkCondition(input1->type() != circle::TensorType_INT8 and
+                                 input1->type() != circle::TensorType_INT16);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/ArgMax.cpp b/onert-micro/onert-micro/src/import/kernels/ArgMax.cpp
new file mode 100644 (file)
index 0000000..b38beaf
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMArgCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleArgMax(const OMConfigureArgs &config_args)
+{
+  return helpers::configure_arg_kernel_common(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/ArgMin.cpp b/onert-micro/onert-micro/src/import/kernels/ArgMin.cpp
new file mode 100644 (file)
index 0000000..1f9b9c5
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMArgCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleArgMin(const OMConfigureArgs &config_args)
+{
+  return helpers::configure_arg_kernel_common(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/AveragePool2D.cpp b/onert-micro/onert-micro/src/import/kernels/AveragePool2D.cpp
new file mode 100644 (file)
index 0000000..ea55814
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMPooingCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus
+onert_micro::import::configure_kernel_CircleAveragePool2D(const OMConfigureArgs &config_args)
+{
+  return import::helpers::configure_pooling_kernel_common(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/BatchToSpaceND.cpp b/onert-micro/onert-micro/src/import/kernels/BatchToSpaceND.cpp
new file mode 100644 (file)
index 0000000..6479171
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMSpacesBatchesNDCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleBatchToSpaceND(
+  const onert_micro::import::OMConfigureArgs &config_args)
+{
+  return helpers::configure_spaces_batches_nd_kernel_common(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Concatenation.cpp b/onert-micro/onert-micro/src/import/kernels/Concatenation.cpp
new file mode 100644 (file)
index 0000000..fb632ad
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+#include "core/OMDataType.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus
+onert_micro::import::configure_kernel_CircleConcatenation(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const int num_inputs = runtime_kernel.inputs_num;
+
+  const auto *t0 = runtime_kernel.inputs[0];
+  const auto *output = runtime_kernel.outputs[0];
+
+  const auto *params = runtime_kernel.first_operator->builtin_options_as_ConcatenationOptions();
+
+  // TODO: Support concat with fused activation function
+  if (params->fused_activation_function() != circle::ActivationFunctionType_NONE)
+    return UnknownError;
+
+  OMRuntimeShape input_shape(t0);
+  int axis = params->axis();
+  if (axis < 0)
+    axis += input_shape.dimensionsCount();
+
+  if (axis < 0 or axis > input_shape.dimensionsCount())
+    return FailedCheckCondition;
+
+  for (int i = 1; i < num_inputs; ++i)
+  {
+    const auto *tensor = runtime_kernel.inputs[i];
+    if (tensor->type() != t0->type())
+      return FailedCheckCondition;
+  }
+
+  if (t0->type() != circle::TensorType_INT8 and t0->type() != circle::TensorType_INT16)
+    return Ok;
+
+#ifndef DIS_QUANT
+  // If input tensors are INT8 or INT16 type then quantization parameters of all input tensors and
+  // the output should be the same
+  for (int i = 0; i < num_inputs; ++i)
+  {
+    const auto *tensor = runtime_kernel.inputs[i];
+
+    if (tensor->quantization() == nullptr)
+      return FailedCheckCondition;
+
+    if (tensor->quantization()->scale()->size() != 1)
+      return FailedCheckCondition;
+
+    if (tensor->quantization()->zero_point()->size() != 1)
+      return FailedCheckCondition;
+
+    if (*tensor->quantization()->scale()->begin() != *output->quantization()->scale()->begin())
+      return FailedCheckCondition;
+
+    if (*tensor->quantization()->zero_point()->begin() !=
+        *output->quantization()->zero_point()->begin())
+      return FailedCheckCondition;
+  }
+#endif // DIS_QUANT
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Conv2D.cpp b/onert-micro/onert-micro/src/import/kernels/Conv2D.cpp
new file mode 100644 (file)
index 0000000..a74713b
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "import/OMKernelConfigureBuilder.h"
+
+#include "execute/OMRuntimeKernel.h"
+#include "execute/OMUtils.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t weightTensorIdx = 1;
+constexpr uint32_t biasTensorIdx = 2;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleConv2D(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  execute::OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *weight = runtime_kernel.inputs[weightTensorIdx];
+  const circle::Tensor *bias = runtime_kernel.inputs[biasTensorIdx];
+
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(weight != nullptr);
+  // Bias can be nullptr
+  assert(output != nullptr);
+
+  OMStatus status = Ok;
+
+  if ((input->type() == circle::TensorType_FLOAT32 &&
+       weight->type() != circle::TensorType_FLOAT32) or
+      (input->type() == circle::TensorType_INT8 && weight->type() != circle::TensorType_INT8) or
+      (input->type() == circle::TensorType_INT16 && weight->type() != circle::TensorType_INT16))
+  {
+    return UnsupportedType;
+  }
+
+  core::OMRuntimeShape input_shape(input);
+  core::OMRuntimeShape weight_shape(weight);
+  core::OMRuntimeShape bias_shape(bias);
+  core::OMRuntimeShape output_shape(output);
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == 4);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == output_shape.dimensionsCount());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == weight_shape.dimensionsCount());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(bias == nullptr or weight_shape.dims(0) == bias_shape.flatSize());
+
+  if (input->type() == circle::TensorType_FLOAT32)
+    return status;
+
+  auto input_quant = input->quantization();
+  auto filter_quant = weight->quantization();
+  auto output_quant = output->quantization();
+
+  status = utils::checkCondition(input_quant != nullptr and filter_quant != nullptr and
+                                 output_quant != nullptr);
+  if (status != Ok)
+    return status;
+
+  auto input_scales = input_quant->scale();
+  auto filter_scales = filter_quant->scale();
+  auto output_scales = output_quant->scale();
+
+  status = utils::checkCondition(input_scales != nullptr and filter_scales != nullptr and
+                                 output_scales != nullptr);
+  if (status != Ok)
+    return status;
+
+  // Support only per channel
+  status = utils::checkCondition(filter_scales->size() > 1);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Cos.cpp b/onert-micro/onert-micro/src/import/kernels/Cos.cpp
new file mode 100644 (file)
index 0000000..5dcaf78
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleCos(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/DepthwiseConv2D.cpp b/onert-micro/onert-micro/src/import/kernels/DepthwiseConv2D.cpp
new file mode 100644 (file)
index 0000000..b39896d
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "import/OMKernelConfigureBuilder.h"
+
+#include "execute/OMRuntimeKernel.h"
+#include "execute/OMUtils.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t weightTensorIdx = 1;
+constexpr uint32_t biasTensorIdx = 2;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus
+onert_micro::import::configure_kernel_CircleDepthwiseConv2D(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  execute::OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *weight = runtime_kernel.inputs[weightTensorIdx];
+  const circle::Tensor *bias = runtime_kernel.inputs[biasTensorIdx];
+
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(weight != nullptr);
+  // Bias can be nullptr
+  assert(output != nullptr);
+
+  OMStatus status = Ok;
+  const auto *options = runtime_kernel.first_operator->builtin_options_as_DepthwiseConv2DOptions();
+
+  core::OMRuntimeShape input_shape(input);
+  core::OMRuntimeShape weight_shape(weight);
+  core::OMRuntimeShape bias_shape(bias);
+  core::OMRuntimeShape output_shape(output);
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input->type() == weight->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == 4);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == output_shape.dimensionsCount());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == weight_shape.dimensionsCount());
+  if (status != Ok)
+    return status;
+
+  const auto output_depth = output_shape.dims(3);
+
+  status = utils::checkCondition(
+    bias == nullptr or (bias_shape.dimensionsCount() == 1 && bias_shape.dims(0) == output_depth));
+  if (status != Ok)
+    return status;
+
+  switch (options->fused_activation_function())
+  {
+    case circle::ActivationFunctionType_NONE:
+    case circle::ActivationFunctionType_RELU:
+    case circle::ActivationFunctionType_RELU6:
+    case circle::ActivationFunctionType_RELU_N1_TO_1:
+      break;
+    default:
+      return UnsupportedActivation;
+  }
+
+  if (input->type() == circle::TensorType_FLOAT32)
+  {
+    status = utils::checkCondition(bias == nullptr or input->type() == bias->type());
+    return status;
+  }
+
+  auto input_quant = input->quantization();
+  auto filter_quant = weight->quantization();
+  auto output_quant = output->quantization();
+
+  status = utils::checkCondition(input_quant != nullptr and filter_quant != nullptr and
+                                 output_quant != nullptr);
+  if (status != Ok)
+    return status;
+
+  auto input_scales = input_quant->scale();
+  auto filter_scales = filter_quant->scale();
+  auto output_scales = output_quant->scale();
+
+  status = utils::checkCondition(input_scales != nullptr and filter_scales != nullptr and
+                                 output_scales != nullptr);
+  if (status != Ok)
+    return status;
+
+  // Support only per channel
+  status = utils::checkCondition(filter_scales->size() > 1);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Dequantize.cpp b/onert-micro/onert-micro/src/import/kernels/Dequantize.cpp
new file mode 100644 (file)
index 0000000..78bfc41
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleDequantize(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  // Check shapes
+  status = utils::checkCondition(input_shape == output_shape);
+  if (status != Ok)
+    return status;
+
+  // Check output type is float
+  status = utils::checkCondition(output->type() == circle::TensorType_FLOAT32);
+  if (status != Ok)
+    return status;
+
+  // Check input quantization params
+  const auto *input_quantization = input->quantization();
+  status = utils::checkCondition(input->type() != circle::TensorType_FLOAT32 or
+                                 input_quantization != nullptr and
+                                   input_quantization->scale() != nullptr and
+                                   input_quantization->scale()->size() == 1);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Div.cpp b/onert-micro/onert-micro/src/import/kernels/Div.cpp
new file mode 100644 (file)
index 0000000..0ce0166
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureTISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleDiv(const OMConfigureArgs &config_args)
+{
+  return import::helpers::configure_TISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Equal.cpp b/onert-micro/onert-micro/src/import/kernels/Equal.cpp
new file mode 100644 (file)
index 0000000..46fa2d7
--- /dev/null
@@ -0,0 +1,64 @@
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleEqual(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == input2->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(output->type() == circle::TensorType_BOOL);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Exp.cpp b/onert-micro/onert-micro/src/import/kernels/Exp.cpp
new file mode 100644 (file)
index 0000000..fa819b1
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleExp(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/ExpandDims.cpp b/onert-micro/onert-micro/src/import/kernels/ExpandDims.cpp
new file mode 100644 (file)
index 0000000..b90ef48
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "import/OMKernelConfigureBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t axisTensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleExpandDims(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+  OMRuntimeStorage &runtime_storage = config_args.runtime_storage;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *axis = runtime_kernel.inputs[axisTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(axis != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  OMRuntimeShape input_shape(input);
+
+  status = utils::checkCondition(axis->type() == circle::TensorType_INT32 or
+                                 axis->type() == circle::TensorType_INT64);
+  if (status != Ok)
+    return status;
+
+  // Check axis value
+  runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  uint8_t *axis_data = runtime_kernel.inputs_data[axisTensorIdx];
+  status = utils::checkCondition(axis_data != nullptr);
+  if (status != Ok)
+    return status;
+
+  if (axis->type() == circle::TensorType_INT32)
+  {
+    int32_t axis_value = *reinterpret_cast<int32_t *>(axis_data);
+    if (axis_value < 0)
+    {
+      axis_value += input_shape.dimensionsCount() + 1;
+    }
+
+    status = utils::checkCondition(axis_value <= input_shape.dimensionsCount() and axis_value >= 0);
+    if (status != Ok)
+      return status;
+  }
+  else
+  {
+    int64_t axis_value = *reinterpret_cast<int64_t *>(axis_data);
+    if (axis_value < 0)
+    {
+      axis_value += input_shape.dimensionsCount() + 1;
+    }
+
+    status = utils::checkCondition(axis_value <= input_shape.dimensionsCount() and axis_value >= 0);
+    if (status != Ok)
+      return status;
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Floor.cpp b/onert-micro/onert-micro/src/import/kernels/Floor.cpp
new file mode 100644 (file)
index 0000000..12a896f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleFloor(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/FloorDiv.cpp b/onert-micro/onert-micro/src/import/kernels/FloorDiv.cpp
new file mode 100644 (file)
index 0000000..a952932
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleFloorDiv(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == input2->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input1->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  if (input1->type() != circle::TensorType_INT8 and input1->type() != circle::TensorType_INT16)
+    return status;
+
+  // Check quantization params
+  if (input1->quantization() == nullptr or input2->quantization() == nullptr or
+      output->quantization() == nullptr)
+  {
+    return NoQuantization;
+  }
+
+  if (input1->quantization()->scale()->size() != 1 or
+      input2->quantization()->scale()->size() != 1 or output->quantization()->scale()->size() != 1)
+  {
+    return UnsupportedType;
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/FloorMod.cpp b/onert-micro/onert-micro/src/import/kernels/FloorMod.cpp
new file mode 100644 (file)
index 0000000..eb5a768
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleFloorMod(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == input2->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input1->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  if (input1->type() != circle::TensorType_INT8 and input1->type() != circle::TensorType_INT16)
+    return status;
+
+  // Check quantization params
+  if (input1->quantization() == nullptr or input2->quantization() == nullptr or
+      output->quantization() == nullptr)
+  {
+    return NoQuantization;
+  }
+
+  if (input1->quantization()->scale()->size() != 1 or
+      input2->quantization()->scale()->size() != 1 or output->quantization()->scale()->size() != 1)
+  {
+    return UnsupportedType;
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/FullyConnected.cpp b/onert-micro/onert-micro/src/import/kernels/FullyConnected.cpp
new file mode 100644 (file)
index 0000000..3d6f03b
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "import/OMKernelConfigureBuilder.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t weightTensorIdx = 1;
+constexpr uint32_t biasTensorIdx = 2;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus
+onert_micro::import::configure_kernel_CircleFullyConnected(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+  OMRuntimeStorage &runtime_storage = config_args.runtime_storage;
+
+  execute::OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *weight = runtime_kernel.inputs[weightTensorIdx];
+  const circle::Tensor *bias = runtime_kernel.inputs[biasTensorIdx];
+
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(weight != nullptr);
+  // Bias can be nullptr
+  assert(output != nullptr);
+
+  OMStatus status = Ok;
+
+  if ((input->type() == circle::TensorType_FLOAT32 &&
+       weight->type() != circle::TensorType_FLOAT32) or
+      (input->type() == circle::TensorType_INT8 && weight->type() != circle::TensorType_INT8) or
+      (input->type() == circle::TensorType_INT16 && weight->type() != circle::TensorType_INT16))
+  {
+    return UnsupportedType;
+  }
+
+  core::OMRuntimeShape weight_shape(weight);
+  core::OMRuntimeShape bias_shape(bias);
+  core::OMRuntimeShape input_shape(input);
+  core::OMRuntimeShape output_shape(output);
+
+  status = utils::checkCondition(weight_shape.dimensionsCount() == 2);
+  if (status != Ok)
+    return status;
+
+  if (input_shape.flatSize() == 1 and output_shape.flatSize() != 1)
+  {
+#ifndef DIS_DYN_SHAPES
+    int32_t dynamic_tensor_size =
+      runtime_storage.getDynamicTensorSize(runtime_kernel.inputs_index[inputTensorIdx]);
+    if (dynamic_tensor_size == -1)
+      return UnsupportedDynamicShapeCase;
+#else
+    return UnsupportedDynamicShapeCase;
+#endif // DIS_DYN_SHAPES
+  }
+
+  status = utils::checkCondition(bias == nullptr or weight_shape.dims(0) == bias_shape.flatSize());
+
+  if (input->type() == circle::TensorType_FLOAT32)
+    return status;
+
+#ifndef DIS_QUANT
+
+  // Check quantized version
+  if (input->quantization() == nullptr or output->quantization() == nullptr or
+      weight->quantization() == nullptr)
+    return NoQuantization;
+
+  if (output->quantization()->scale() == nullptr or output->quantization()->scale()->size() != 1)
+    return UnsupportedQuantizationType;
+
+  if (output->quantization()->zero_point() == nullptr or
+      output->quantization()->zero_point()->size() != 1)
+    return UnsupportedQuantizationType;
+
+  if (weight->quantization()->scale() == nullptr or weight->quantization()->scale()->size() != 1)
+    return UnsupportedQuantizationType;
+
+  if (weight->quantization()->zero_point() == nullptr or
+      weight->quantization()->zero_point()->size() != 1)
+    return UnsupportedQuantizationType;
+
+#endif // DIS_QUANT
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Gather.cpp b/onert-micro/onert-micro/src/import/kernels/Gather.cpp
new file mode 100644 (file)
index 0000000..622c700
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "import/OMKernelConfigureBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t positionsTensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleGather(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *positions = runtime_kernel.inputs[positionsTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(positions != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  const auto *options = runtime_kernel.first_operator->builtin_options_as_GatherOptions();
+
+  if (options == nullptr)
+    return UnknownError;
+
+  status = utils::checkCondition(positions->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+
+  auto input_type = input->type();
+  status = utils::checkCondition(input_type == circle::TensorType_INT32 or
+                                 input_type == circle::TensorType_FLOAT32 or
+                                 input_type == circle::TensorType_INT8);
+  if (status != Ok)
+    return status;
+
+  int32_t axis = options->axis();
+
+  core::OMRuntimeShape input_shape(input);
+  core::OMRuntimeShape positions_shape(positions);
+
+  int32_t num_dims = input_shape.dimensionsCount();
+  if (axis < 0)
+  {
+    axis += num_dims;
+  }
+
+  status = utils::checkCondition(axis >= 0 and axis < num_dims);
+  if (status != Ok)
+    return status;
+
+  int32_t batch_dims = options->batch_dims();
+  int32_t coords_num_dims = positions_shape.dimensionsCount();
+  // 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;
+  }
+
+  status = utils::checkCondition(batch_dims <= axis and batch_dims >= 0 and
+                                 batch_dims < num_dims and batch_dims <= coords_num_dims);
+
+  if (status != Ok)
+    return status;
+
+  for (int i = 0; i < batch_dims; ++i)
+  {
+    status = utils::checkCondition(input_shape.dims(i) == positions_shape.dims(i));
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/GatherND.cpp b/onert-micro/onert-micro/src/import/kernels/GatherND.cpp
new file mode 100644 (file)
index 0000000..0d90389
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ * Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "import/OMKernelConfigureBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+#include "PALGatherND.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::execute;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t positionsTensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleGatherND(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *positions = runtime_kernel.inputs[positionsTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(positions != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(positions->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+
+  auto input_type = input->type();
+  status = utils::checkCondition(input_type == circle::TensorType_FLOAT32);
+  if (status != Ok)
+    return status;
+
+  core::OMRuntimeShape input_shape(input);
+  core::OMRuntimeShape positions_shape(positions);
+
+  int32_t shape_num_dims = input_shape.dimensionsCount();
+
+  status = utils::checkCondition(shape_num_dims >= 1);
+  if (status != Ok)
+    return status;
+
+  int32_t positions_num_dims = positions_shape.dimensionsCount();
+  int32_t positions_num_dims_nd = positions_shape.dims(positions_num_dims - 1);
+
+  status = utils::checkCondition(positions_num_dims >= 1);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(positions_num_dims_nd <= shape_num_dims);
+  if (status != Ok)
+    return status;
+
+  status =
+    utils::checkCondition(positions_num_dims_nd <= onert_micro::execute::pal::MAX_INDICES_ND);
+  if (status != Ok)
+    return status;
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Greater.cpp b/onert-micro/onert-micro/src/import/kernels/Greater.cpp
new file mode 100644 (file)
index 0000000..e15360e
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleGreater(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == input2->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(output->type() == circle::TensorType_BOOL);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/GreaterEqual.cpp b/onert-micro/onert-micro/src/import/kernels/GreaterEqual.cpp
new file mode 100644 (file)
index 0000000..21c3e22
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus
+onert_micro::import::configure_kernel_CircleGreaterEqual(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == input2->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(output->type() == circle::TensorType_BOOL);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/L2Normalize.cpp b/onert-micro/onert-micro/src/import/kernels/L2Normalize.cpp
new file mode 100644 (file)
index 0000000..fb56bee
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+#include "core/OMUtils.h"
+#include "import/OMKernelConfigureBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+#include "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleL2Normalize(const OMConfigureArgs &config_args)
+{
+  OMStatus status = onert_micro::import::helpers::configure_SISO_kernel(config_args);
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/L2Pool2D.cpp b/onert-micro/onert-micro/src/import/kernels/L2Pool2D.cpp
new file mode 100644 (file)
index 0000000..40b9dc4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMPooingCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleL2Pool2D(const OMConfigureArgs &config_args)
+{
+  return helpers::configure_pooling_kernel_common(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/LeakyRelu.cpp b/onert-micro/onert-micro/src/import/kernels/LeakyRelu.cpp
new file mode 100644 (file)
index 0000000..7472fa9
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleLeakyRelu(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Less.cpp b/onert-micro/onert-micro/src/import/kernels/Less.cpp
new file mode 100644 (file)
index 0000000..6912eab
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleLess(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == input2->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(output->type() == circle::TensorType_BOOL);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/LessEqual.cpp b/onert-micro/onert-micro/src/import/kernels/LessEqual.cpp
new file mode 100644 (file)
index 0000000..cb0fc8a
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleLessEqual(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == input2->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(output->type() == circle::TensorType_BOOL);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Log.cpp b/onert-micro/onert-micro/src/import/kernels/Log.cpp
new file mode 100644 (file)
index 0000000..79532b3
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleLog(const OMConfigureArgs &config_args)
+{
+  return import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/LogSoftmax.cpp b/onert-micro/onert-micro/src/import/kernels/LogSoftmax.cpp
new file mode 100644 (file)
index 0000000..dbd55f8
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleLogSoftmax(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Logistic.cpp b/onert-micro/onert-micro/src/import/kernels/Logistic.cpp
new file mode 100644 (file)
index 0000000..256a26a
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleLogistic(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/MaxPool2D.cpp b/onert-micro/onert-micro/src/import/kernels/MaxPool2D.cpp
new file mode 100644 (file)
index 0000000..68d4ee7
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMPooingCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleMaxPool2D(const OMConfigureArgs &config_args)
+{
+  return helpers::configure_pooling_kernel_common(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Maximum.cpp b/onert-micro/onert-micro/src/import/kernels/Maximum.cpp
new file mode 100644 (file)
index 0000000..6548b9c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleMaximum(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == input2->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input1->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Minimum.cpp b/onert-micro/onert-micro/src/import/kernels/Minimum.cpp
new file mode 100644 (file)
index 0000000..3aa3d07
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleMinimum(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == input2->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input1->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Mul.cpp b/onert-micro/onert-micro/src/import/kernels/Mul.cpp
new file mode 100644 (file)
index 0000000..8eb35d0
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureTISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleMul(const OMConfigureArgs &config_args)
+{
+  return import::helpers::configure_TISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Neg.cpp b/onert-micro/onert-micro/src/import/kernels/Neg.cpp
new file mode 100644 (file)
index 0000000..9a47661
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleNeg(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/NotEqual.cpp b/onert-micro/onert-micro/src/import/kernels/NotEqual.cpp
new file mode 100644 (file)
index 0000000..66d7072
--- /dev/null
@@ -0,0 +1,64 @@
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleNotEqual(const OMConfigureArgs &config_args)
+{
+
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == input2->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(output->type() == circle::TensorType_BOOL);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Pack.cpp b/onert-micro/onert-micro/src/import/kernels/Pack.cpp
new file mode 100644 (file)
index 0000000..97ec90e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMDataType.h"
+#include "core/OMUtils.h"
+
+#include "import/OMKernelConfigureBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CirclePack(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const int num_inputs = runtime_kernel.inputs_num;
+
+  const auto *t0 = runtime_kernel.inputs[0];
+  const auto *output = runtime_kernel.outputs[0];
+
+  if (output->type() != t0->type())
+    return FailedCheckCondition;
+
+  const auto *params = runtime_kernel.first_operator->builtin_options_as_PackOptions();
+
+  OMRuntimeShape input_shape(t0);
+  int axis = params->axis();
+  if (axis < 0)
+    axis += input_shape.dimensionsCount();
+
+  if (axis < 0 or axis > input_shape.dimensionsCount())
+    return FailedCheckCondition;
+
+  for (int i = 1; i < num_inputs; ++i)
+  {
+    const auto *tensor = runtime_kernel.inputs[i];
+    if (tensor->type() != t0->type())
+      return FailedCheckCondition;
+  }
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Pad.cpp b/onert-micro/onert-micro/src/import/kernels/Pad.cpp
new file mode 100644 (file)
index 0000000..2e3e1cb
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMPadCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CirclePad(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_pad_kernel_common(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Relu.cpp b/onert-micro/onert-micro/src/import/kernels/Relu.cpp
new file mode 100644 (file)
index 0000000..c027fcf
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleRelu(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Relu6.cpp b/onert-micro/onert-micro/src/import/kernels/Relu6.cpp
new file mode 100644 (file)
index 0000000..aff10a3
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleRelu6(const OMConfigureArgs &config_args)
+{
+
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Reshape.cpp b/onert-micro/onert-micro/src/import/kernels/Reshape.cpp
new file mode 100644 (file)
index 0000000..d85f6e4
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "import/OMKernelConfigureBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t shapeTensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleReshape(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+  OMRuntimeStorage &runtime_storage = config_args.runtime_storage;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *shape = runtime_kernel.inputs[shapeTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(shape != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+#ifndef DIS_DYN_SHAPES
+  auto is_dynamic =
+    runtime_context.isConstTensor(runtime_kernel.inputs_index[shapeTensorIdx]) == false;
+
+  if (is_dynamic)
+  {
+    auto input_shape_size = input_shape.flatSize();
+
+    status = utils::checkCondition(output_shape.flatSize() == 1);
+    if (status != Ok)
+      return status;
+
+    status = utils::checkCondition(input_shape_size != 1);
+    if (status != Ok)
+      return status;
+
+    runtime_storage.setDynamicTensorSize(runtime_kernel.outputs_index[outputTensorIdx],
+                                         input_shape_size);
+  }
+  else
+  {
+    status = utils::checkCondition(input_shape.flatSize() == output_shape.flatSize());
+    assert(status == Ok);
+    if (status != Ok)
+      return status;
+  }
+#else
+  status = utils::checkCondition(
+    runtime_context.getCircleReader().isConstTensor(runtime_kernel.inputs_index[shapeTensorIdx]));
+  assert(status == Ok);
+  if (status != Ok)
+    return status;
+#endif // DIS_DYN_SHAPES
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Round.cpp b/onert-micro/onert-micro/src/import/kernels/Round.cpp
new file mode 100644 (file)
index 0000000..1c661e9
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleRound(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Rsqrt.cpp b/onert-micro/onert-micro/src/import/kernels/Rsqrt.cpp
new file mode 100644 (file)
index 0000000..41e608b
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleRsqrt(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Shape.cpp b/onert-micro/onert-micro/src/import/kernels/Shape.cpp
new file mode 100644 (file)
index 0000000..4ff50ea
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "import/OMKernelConfigureBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleShape(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(output != nullptr);
+
+  status = utils::checkCondition(output->type() == circle::TensorType_INT32);
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Sin.cpp b/onert-micro/onert-micro/src/import/kernels/Sin.cpp
new file mode 100644 (file)
index 0000000..c09261b
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleSin(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Slice.cpp b/onert-micro/onert-micro/src/import/kernels/Slice.cpp
new file mode 100644 (file)
index 0000000..c90168b
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "import/OMKernelConfigureBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+const int MAX_DIM = 5;
+
+constexpr uint32_t input1TensorIdx = 0;
+constexpr uint32_t input2TensorIdx = 1;
+constexpr uint32_t input3TensorIdx = 2;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleSlice(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  execute::OMRuntimeKernel runtime_kernel;
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input1 = runtime_kernel.inputs[input1TensorIdx];
+  const circle::Tensor *input2 = runtime_kernel.inputs[input2TensorIdx];
+  const circle::Tensor *input3 = runtime_kernel.inputs[input3TensorIdx];
+
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input1 != nullptr);
+  assert(input2 != nullptr);
+  assert(input3 != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input1->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input2->type() == circle::TensorType_INT32 and
+                                 input3->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(OMRuntimeShape(input2).dimensionsCount() == 1 and
+                                 OMRuntimeShape(input3).dimensionsCount() == 1);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(OMRuntimeShape(input1).dimensionsCount() <= MAX_DIM);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Softmax.cpp b/onert-micro/onert-micro/src/import/kernels/Softmax.cpp
new file mode 100644 (file)
index 0000000..4592d54
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+
+#include "import/OMKernelConfigureBuilder.h"
+
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleSoftmax(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == output_shape.dimensionsCount());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input_shape.dimensionsCount() >= 1);
+  if (status != Ok)
+    return status;
+
+  if (input->type() != circle::TensorType_INT8 and input->type() != circle::TensorType_INT16 and
+      input->type() != circle::TensorType_UINT8)
+    return status;
+
+  // Check quantized version
+  if (input->quantization() == nullptr or output->quantization() == nullptr)
+    return NoQuantization;
+
+  if (output->quantization()->scale() == nullptr or output->quantization()->scale()->size() != 1)
+    return NoQuantization;
+
+  if (input->quantization()->scale() == nullptr or input->quantization()->scale()->size() != 1)
+    return NoQuantization;
+
+  if (output->quantization()->zero_point() == nullptr or
+      output->quantization()->zero_point()->size() != 1)
+    return NoQuantization;
+
+  if (input->quantization()->zero_point() == nullptr or
+      input->quantization()->zero_point()->size() != 1)
+    return NoQuantization;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/SpaceToBatchND.cpp b/onert-micro/onert-micro/src/import/kernels/SpaceToBatchND.cpp
new file mode 100644 (file)
index 0000000..f3db592
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMSpacesBatchesNDCommon.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleSpaceToBatchND(
+  const onert_micro::import::OMConfigureArgs &config_args)
+{
+  return helpers::configure_spaces_batches_nd_kernel_common(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/SpaceToDepth.cpp b/onert-micro/onert-micro/src/import/kernels/SpaceToDepth.cpp
new file mode 100644 (file)
index 0000000..8520ccf
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleSpaceToDepth(
+  const onert_micro::import::OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  OMRuntimeShape input_shape(input);
+
+  const auto *options = runtime_kernel.first_operator->builtin_options_as_SpaceToDepthOptions();
+  const int32_t block_size = options->block_size();
+
+  status = utils::checkCondition(block_size > 0);
+  if (status != Ok)
+    return status;
+
+  constexpr int kHeightRank = 1;
+  constexpr int kWidthRank = 2;
+
+  const int input_height = input_shape.dims(kHeightRank);
+  const int input_width = input_shape.dims(kWidthRank);
+  int output_height = input_height / block_size;
+  int output_width = input_width / block_size;
+
+  status = utils::checkCondition(input_height == output_height * block_size);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input_width == output_width * block_size);
+  if (status != Ok)
+    return status;
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Split.cpp b/onert-micro/onert-micro/src/import/kernels/Split.cpp
new file mode 100644 (file)
index 0000000..5ef38f2
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "import/OMKernelConfigureBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t axisTensorIdx = 0;
+constexpr uint32_t inputTensorIdx = 1;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleSplit(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  OMRuntimeStorage &runtime_storage = config_args.runtime_storage;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *axis = runtime_kernel.inputs[axisTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(axis != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(output->type() == input->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(axis->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+
+  // Check it is scalar
+  status = utils::checkCondition(OMRuntimeShape(axis).flatSize() == 1);
+  if (status != Ok)
+    return status;
+
+  // Check axis value
+  runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  auto *axis_data = reinterpret_cast<int32_t *>(runtime_kernel.inputs_data[axisTensorIdx]);
+  status = utils::checkCondition(axis_data != nullptr);
+  if (status != Ok)
+    return status;
+
+  int32_t axis_value = axis_data[0];
+
+  OMRuntimeShape input_shape(input);
+  if (axis_value < 0)
+  {
+    axis_value += input_shape.dimensionsCount() + 1;
+  }
+
+  status = utils::checkCondition(axis_value <= input_shape.dimensionsCount() and axis_value >= 0);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Sqrt.cpp b/onert-micro/onert-micro/src/import/kernels/Sqrt.cpp
new file mode 100644 (file)
index 0000000..2dd4fb9
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleSqrt(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Square.cpp b/onert-micro/onert-micro/src/import/kernels/Square.cpp
new file mode 100644 (file)
index 0000000..eb9ef7e
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleSquare(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/SquaredDifference.cpp b/onert-micro/onert-micro/src/import/kernels/SquaredDifference.cpp
new file mode 100644 (file)
index 0000000..dd04fb9
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureTISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus
+onert_micro::import::configure_kernel_CircleSquaredDifference(const OMConfigureArgs &config_args)
+{
+  return import::helpers::configure_TISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/StridedSlice.cpp b/onert-micro/onert-micro/src/import/kernels/StridedSlice.cpp
new file mode 100644 (file)
index 0000000..2879234
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "import/OMKernelConfigureBuilder.h"
+
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t beginTensorIdx = 1;
+constexpr uint32_t endTensorIdx = 2;
+constexpr uint32_t stridesTensorIdx = 3;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus
+onert_micro::import::configure_kernel_CircleStridedSlice(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  execute::OMRuntimeKernel runtime_kernel;
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *begin = runtime_kernel.inputs[beginTensorIdx];
+  const circle::Tensor *end = runtime_kernel.inputs[endTensorIdx];
+  const circle::Tensor *strides = runtime_kernel.inputs[stridesTensorIdx];
+
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(begin != nullptr);
+  assert(end != nullptr);
+  assert(strides != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(begin->type() == circle::TensorType_INT32 and
+                                 end->type() == circle::TensorType_INT32 and
+                                 strides->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Sub.cpp b/onert-micro/onert-micro/src/import/kernels/Sub.cpp
new file mode 100644 (file)
index 0000000..a21201f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureTISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleSub(const OMConfigureArgs &config_args)
+{
+  return import::helpers::configure_TISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Tanh.cpp b/onert-micro/onert-micro/src/import/kernels/Tanh.cpp
new file mode 100644 (file)
index 0000000..c486111
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/helpers/OMConfigureSISOKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleTanh(const OMConfigureArgs &config_args)
+{
+  return onert_micro::import::helpers::configure_SISO_kernel(config_args);
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Transpose.cpp b/onert-micro/onert-micro/src/import/kernels/Transpose.cpp
new file mode 100644 (file)
index 0000000..462ac64
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "import/OMKernelConfigureBuilder.h"
+
+#include "execute/OMRuntimeKernel.h"
+#include "execute/OMUtils.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+constexpr int kInputTensorIdx = 0;
+constexpr int kPermTensorIdx = 1;
+constexpr int kOutputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleTranspose(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  execute::OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  const circle::Tensor *input = runtime_kernel.inputs[kInputTensorIdx];
+  const circle::Tensor *perm = runtime_kernel.inputs[kPermTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[kOutputTensorIdx];
+
+  assert(input != nullptr);
+  assert(perm != nullptr);
+  assert(output != nullptr);
+
+  OMStatus status = Ok;
+
+  status = utils::checkCondition(perm->type() == circle::TensorType_INT32);
+  if (status != Ok)
+    return status;
+
+  core::OMRuntimeShape input_shape(input);
+  core::OMRuntimeShape perm_shape(perm);
+
+  status = utils::checkCondition(perm_shape.dimensionsCount() == 1);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(perm_shape.dims(0) == input_shape.dimensionsCount());
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/TransposeConv.cpp b/onert-micro/onert-micro/src/import/kernels/TransposeConv.cpp
new file mode 100644 (file)
index 0000000..100019f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+
+#include "import/OMKernelConfigureBuilder.h"
+
+#include "execute/OMRuntimeKernel.h"
+#include "execute/OMUtils.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+// For the TfLite transpose_conv implementation, input tensor 0 corresponds to
+// the OutputShapeTensor. However, since TFLM does not support dynamic tensors,
+// the TFLM implementation ignores input tensor 0 and the only inputs we care
+// about are kFilterTensor, kInputTensor and kBiasTensor.
+
+constexpr int kWeightTensorIdx = 1;
+constexpr int kInputTensorIdx = 2;
+constexpr int kBiasTensorIdx = 3;
+constexpr int kOutputTensorIdx = 0;
+
+} // namespace
+
+OMStatus
+onert_micro::import::configure_kernel_CircleTransposeConv(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  execute::OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  const circle::Tensor *input = runtime_kernel.inputs[kInputTensorIdx];
+  const circle::Tensor *weight = runtime_kernel.inputs[kWeightTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[kOutputTensorIdx];
+
+  assert(input != nullptr);
+  assert(weight != nullptr);
+  // Bias can be nullptr
+  assert(output != nullptr);
+
+  OMStatus status = Ok;
+
+  status = utils::checkCondition(input->type() == output->type());
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input->type() == weight->type());
+  if (status != Ok)
+    return status;
+
+  core::OMRuntimeShape input_shape(input);
+  core::OMRuntimeShape weight_shape(weight);
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == 4);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(input_shape.dimensionsCount() == weight_shape.dimensionsCount());
+  if (status != Ok)
+    return status;
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/Unpack.cpp b/onert-micro/onert-micro/src/import/kernels/Unpack.cpp
new file mode 100644 (file)
index 0000000..c7536cb
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "import/OMKernelConfigureBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+OMStatus onert_micro::import::configure_kernel_CircleUnpack(const OMConfigureArgs &config_args)
+{
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  OMRuntimeStorage &runtime_storage = config_args.runtime_storage;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  status = utils::checkCondition(output->type() == input->type());
+  if (status != Ok)
+    return status;
+
+  auto options = runtime_kernel.first_operator->builtin_options_as_UnpackOptions();
+  status = utils::checkCondition(options != nullptr);
+  if (status != Ok)
+    return status;
+
+  status = utils::checkCondition(runtime_kernel.outputs_num == options->num());
+  if (status != Ok)
+    return status;
+
+  // Check all outputs have the same type and shapes
+  OMRuntimeShape output_shape(output);
+  for (uint32_t i = 1; i < options->num(); ++i)
+  {
+    const circle::Tensor *cur_output = runtime_kernel.outputs[i];
+    status = utils::checkCondition(output->type() == cur_output->type());
+    if (status != Ok)
+      return status;
+
+    OMRuntimeShape cur_output_shape(cur_output);
+    status = utils::checkCondition(output_shape == cur_output_shape);
+    if (status != Ok)
+      return status;
+  }
+
+  // Check shapes input and output
+  OMRuntimeShape input_shape(input);
+  for (int i = 0; i < input_shape.dimensionsCount(); ++i)
+  {
+    if (i == options->axis())
+      continue;
+
+    if (i < options->axis())
+    {
+      status = utils::checkCondition(input_shape.dims(i) == output_shape.dims(i));
+    }
+    else
+    {
+      status = utils::checkCondition(input_shape.dims(i) == output_shape.dims(i - 1));
+    }
+    if (status != Ok)
+      return status;
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/import/kernels/While.cpp b/onert-micro/onert-micro/src/import/kernels/While.cpp
new file mode 100644 (file)
index 0000000..6575281
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "core/OMUtils.h"
+#include "OMStatus.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+
+OMStatus onert_micro::import::configure_kernel_CircleWhile(
+  const onert_micro::import::OMConfigureArgs &config_args)
+{
+  OMRuntimeModule &runtime_module = config_args.runtime_module;
+  OMRuntimeContext &runtime_context = config_args.runtime_context;
+  uint16_t op_index = config_args.kernel_index;
+
+  onert_micro::execute::OMRuntimeKernel runtime_kernel;
+
+  OMStatus status = runtime_kernel.readKernel(op_index, runtime_context);
+  if (status != Ok)
+    return status;
+
+  auto options = runtime_kernel.first_operator->builtin_options_as_WhileOptions();
+  status = utils::checkCondition(options != nullptr);
+  if (status != Ok)
+    return status;
+
+  // Num of inputs equals to num of outputs
+  status = utils::checkCondition(runtime_kernel.inputs_num == runtime_kernel.outputs_num);
+  if (status != Ok)
+    return status;
+
+  // Obtain conditional and body runtime subgraphs
+  const auto body_subgraph_index = options->body_subgraph_index();
+  const auto cond_subgraph_index = options->cond_subgraph_index();
+  OMRuntimeGraph *cond_runtime_graph = nullptr;
+  OMRuntimeGraph *body_runtime_graph = nullptr;
+  status = runtime_module.getRuntimeGraphAt(cond_subgraph_index, &cond_runtime_graph);
+  if (status != Ok)
+    return status;
+  status = runtime_module.getRuntimeGraphAt(body_subgraph_index, &body_runtime_graph);
+  if (status != Ok)
+    return status;
+
+  OMRuntimeContext &cond_runtime_context = cond_runtime_graph->getRuntimeContext();
+  OMRuntimeContext &body_runtime_context = body_runtime_graph->getRuntimeContext();
+
+  // Check cond runtime graph
+  status =
+    utils::checkCondition(cond_runtime_graph->getNumberOfInputs() == runtime_kernel.inputs_num and
+                          cond_runtime_graph->getNumberOfOutputs() == 1);
+  if (status != Ok)
+    return status;
+
+  const auto cond_output_index = cond_runtime_context.getGraphOutputTensorIndex(0);
+  const auto cond_output_tensor =
+    cond_runtime_context.getTensorByIndex(static_cast<int32_t>(cond_output_index));
+  status = utils::checkCondition(cond_output_tensor->type() == circle::TensorType_BOOL);
+
+  // Check body runtime graph
+  status =
+    utils::checkCondition(body_runtime_graph->getNumberOfInputs() == runtime_kernel.inputs_num and
+                          body_runtime_graph->getNumberOfOutputs() == runtime_kernel.outputs_num);
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/optimize/CMakeLists.txt b/onert-micro/onert-micro/src/optimize/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a6137c8
--- /dev/null
@@ -0,0 +1,20 @@
+message(STATUS "ONERT MICRO OPTIMIZER BUILD BEGIN")
+
+set(SOURCES
+        OMOptimizer.cpp
+        )
+
+# Add configure kernels
+macro(REGISTER_PASS PASS_NAME)
+    list(APPEND SOURCES "pass/${PASS_NAME}.cpp")
+endmacro(REGISTER_PASS)
+
+# To add REGISTER_KERNEL list
+include(${PASS_REGISTER_FILE})
+
+add_library(${OM_OPTIMIZE_LIB} STATIC ${SOURCES})
+
+target_include_directories(${OM_OPTIMIZE_LIB} PUBLIC "${OM_INCLUDE_DIR}")
+target_link_libraries(${OM_OPTIMIZE_LIB} PUBLIC ${OM_CORE_LIB})
+
+message(STATUS "ONERT MICRO OPTIMIZER BUILD FINISHED")
diff --git a/onert-micro/onert-micro/src/optimize/OMOptimizer.cpp b/onert-micro/onert-micro/src/optimize/OMOptimizer.cpp
new file mode 100644 (file)
index 0000000..1dc9275
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "import/OMKernelConfigureBuilder.h"
+#include "optimize/OMGraphStatus.h"
+#include "OMStatus.h"
+#include "optimize/OMOptimizePassesBuilder.h"
+#include "optimize/OMOptimizer.h"
+
+using namespace onert_micro;
+using namespace onert_micro::optimize;
+
+OMStatus OMOptimizer::optimize(core::OMRuntimeStorage &storage, core::OMRuntimeContext &context,
+                               const OMConfig &configs)
+{
+  OMGraphStatus graph_status = {Unchanged, Ok};
+
+  const uint32_t number_of_passes = optimize_passes.getPassNumber();
+
+  do
+  {
+    for (uint32_t i = 0; i < number_of_passes; ++i)
+    {
+      OptimizePassFunc *cur_pass_func;
+      OMStatus status = optimize_passes.getOptimizeFunc(i, &cur_pass_func);
+      assert(status == Ok && "Unsupported pass");
+      if (status != Ok)
+        return status;
+
+      graph_status = cur_pass_func(storage, context, configs);
+      assert(graph_status.main_status == Ok);
+      if (graph_status.main_status != Ok)
+        return graph_status.main_status;
+    }
+  } while (graph_status.graph_status == Changed);
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/optimize/pass/FindInplaceOpPass.cpp b/onert-micro/onert-micro/src/optimize/pass/FindInplaceOpPass.cpp
new file mode 100644 (file)
index 0000000..06233d0
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "optimize/OMOptimizePassesBuilder.h"
+#include "OMStatus.h"
+#include "OMConfig.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMRuntimeStorage.h"
+#include "core/OMKernelType.h"
+#include "core/reader/OMCircleReader.h"
+
+using namespace onert_micro;
+
+namespace
+{
+OMStatus isInplaceOperation(const circle::Operator *op, core::OMRuntimeContext &runtime_context,
+                            bool &is_inplace)
+{
+  OMStatus status = Ok;
+
+  const auto op_codes = runtime_context.getCircleOpcodes();
+  uint32_t index = op->opcode_index();
+
+  assert(index < op_codes->size());
+
+  const auto opcode = op_codes->operator[](index);
+
+  switch (opcode->builtin_code())
+  {
+    case circle::BuiltinOperator_ABS:
+    case circle::BuiltinOperator_CEIL:
+    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_LOG:
+    case circle::BuiltinOperator_RELU:
+    case circle::BuiltinOperator_RELU6:
+    case circle::BuiltinOperator_ROUND:
+    case circle::BuiltinOperator_ADD:
+    case circle::BuiltinOperator_MUL:
+    case circle::BuiltinOperator_SUB:
+    case circle::BuiltinOperator_ZEROS_LIKE:
+    {
+      is_inplace = true;
+      break;
+    }
+#if 0 // FIXME: Enable after custom operation is introduced
+    case circle::BuiltinOperator_CUSTOM:
+    {
+      core::OMBuilderCustomID custom_id;
+
+      core::OMBuilderID builderID = core::OMBuilderID::Size;
+      status = core::getCustomOperatorBuilderId(opcode->custom_code(), builderID);
+
+      if (status != Ok)
+        return status;
+
+      status = core::getCustomOperatorByBuilderId(builderID, custom_id);
+
+      if (status != Ok)
+        return status;
+
+      switch (custom_id)
+      {
+        case onert_micro::core::CUSTOM_custom_gru:
+          is_inplace = true;
+          break;
+        default:
+          is_inplace = false;
+          break;
+      }
+    }
+#endif
+    default:
+      is_inplace = false;
+      break;
+  }
+  return status;
+}
+
+bool isSingleUsageOfTensor(core::OMRuntimeContext &context, const int32_t tensor_index)
+{
+  uint32_t usage_count = 0;
+
+  const auto operators = context.getCircleOperators();
+  for (uint32_t i = 0; i < operators->size(); ++i)
+  {
+    const auto *op = operators->operator[](i);
+    assert(op != nullptr);
+
+    const auto *op_inputs = op->inputs();
+    for (int32_t j = 0; j < op_inputs->size(); ++j)
+    {
+      const auto input_index = op_inputs->operator[](j);
+      if (input_index == tensor_index)
+      {
+        if (++usage_count > 1)
+          return false;
+      }
+    }
+  }
+
+  // Let's check that it is not graph output
+  if (usage_count == 1)
+  {
+    const auto &outputs_indexes = context.getCircleOutputs();
+    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;
+}
+
+OMStatus checkInplaceOp(core::OMRuntimeContext &context, const circle::Operator *cur_op,
+                        bool &is_inplace)
+{
+  const auto graph_outputs = context.getCircleOutputs();
+  const auto *op_inputs = cur_op->inputs();
+  const auto *op_outputs = cur_op->outputs();
+
+  auto non_const_input_it = op_inputs->begin();
+  while (non_const_input_it != op_inputs->end())
+  {
+    auto dist = std::distance(op_inputs->begin(), non_const_input_it);
+
+    const auto non_const_input_idx = *non_const_input_it;
+
+    if (context.isConstTensor(non_const_input_idx))
+    {
+      non_const_input_it++;
+      continue;
+    }
+
+    // Check single usage of input tensor
+    if (not isSingleUsageOfTensor(context, 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());
+    if (dist >= op_outputs->size())
+      return UnknownError;
+
+    const auto output_index = op_outputs->operator[](dist);
+    if (not isSingleUsageOfTensor(context, output_index))
+    {
+      is_inplace = false;
+      break;
+    }
+
+    // Check that num elements are equal
+    {
+      const auto *input_non_const_tensor = context.getTensorByIndex(non_const_input_idx);
+      const auto *output_tensor = context.getTensorByIndex(output_index);
+      if (input_non_const_tensor->shape()->size() != output_tensor->shape()->size())
+      {
+        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++;
+  }
+
+  return Ok;
+}
+
+OMStatus findInplaceOp(core::OMRuntimeStorage &storage, core::OMRuntimeContext &context,
+                       const OMConfig &configs, bool &is_changed)
+{
+  OMStatus status = Ok;
+
+  const core::reader::CircleOperators *operators = context.getCircleOperators();
+
+  for (uint32_t i = 0; i < operators->size(); ++i)
+  {
+    auto kernel_type = storage.getKernelType(i);
+    if (kernel_type == onert_micro::core::Inplace)
+      continue;
+
+    auto cur_op = operators->operator[](i);
+
+    bool is_inplace = false;
+    isInplaceOperation(cur_op, context, is_inplace);
+
+    if (is_inplace == false)
+      continue;
+
+    is_inplace = true;
+
+    status = checkInplaceOp(context, cur_op, is_inplace);
+
+    if (status != Ok)
+      return status;
+
+    if (not is_inplace)
+      continue;
+
+    is_changed = true;
+    storage.setKernelType(i, onert_micro::core::Inplace);
+  }
+
+  return status;
+}
+
+} // namespace
+
+optimize::OMGraphStatus optimize::onert_micro_FindInplaceOpPass(core::OMRuntimeStorage &storage,
+                                                                core::OMRuntimeContext &context,
+                                                                const OMConfig &configs)
+{
+  bool changed = false;
+
+  OMGraphStatus graph_status = {Unchanged, Ok};
+
+  // If it is train mode, skip inplace optimization
+  // We need all tensors
+  if (configs.train_mode)
+    return graph_status;
+
+  do
+  {
+    changed = false;
+    graph_status.main_status = findInplaceOp(storage, context, configs, changed);
+
+    if (graph_status.main_status != Ok)
+      return graph_status;
+
+    if (changed)
+      graph_status.graph_status = Changed;
+
+  } while (changed);
+
+  return graph_status;
+}
diff --git a/onert-micro/onert-micro/src/train/CMakeLists.txt b/onert-micro/onert-micro/src/train/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6374a9d
--- /dev/null
@@ -0,0 +1,57 @@
+message(STATUS "ONERT MICRO TRAIN BUILD BEGIN")
+
+include("${OM_PAL_DIR}/pal.cmake")
+
+initialize_pal()
+
+if (NOT PAL_INITIALIZED)
+    message(STATUS "ERROR: PAL Failed to initialize, skip BUILD EXECUTE")
+    return()
+endif()
+
+set(SOURCES
+        OMBackpropExecute.cpp
+        OMBackpropExecutionBuilder.cpp
+        losses_functions/MSE.cpp
+        losses_functions/CrossEntropy.cpp
+        metrics/CrossEntropy.cpp
+        metrics/MAE.cpp
+        metrics/MSE.cpp
+        metrics/Accuracy.cpp
+        train_optimizers/SGD.cpp
+        train_optimizers/Adam.cpp
+        )
+
+# Add configure kernels
+macro(REGISTER_TRAIN_KERNEL OPERATOR, NODE)
+    list(APPEND SOURCES "kernels/${NODE}.cpp")
+endmacro(REGISTER_TRAIN_KERNEL)
+
+# To add REGISTER_KERNEL list
+include(${KERNEL_TRAIN_REGISTER_FILE})
+
+add_library(${OM_TRAIN_LIB} STATIC ${SOURCES})
+
+target_include_directories(${OM_TRAIN_LIB} PUBLIC "${OM_INCLUDE_DIR}")
+target_link_libraries(${OM_TRAIN_LIB} PUBLIC ${OM_CORE_LIB})
+
+message(STATUS "ONERT MICRO TRAIN BUILD FINISHED")
+
+if(NOT ENABLE_TEST)
+    return()
+endif(NOT ENABLE_TEST)
+
+message(STATUS "ONERT MICRO TEST TRAIN BUILD STARTED")
+
+nnas_find_package(GTest REQUIRED)
+
+set (TEST_SOURCES
+        tests/BostonHousingTask.test.cpp
+        tests/CheckpointsHandler.test.cpp
+        tests/NumbersClassificationTask.test.cpp)
+
+GTest_AddTest(${OM_TRAIN_LIB}_test ${TEST_SOURCES})
+target_include_directories(${OM_TRAIN_LIB}_test PUBLIC "${OM_INCLUDE_DIR}")
+target_link_libraries(${OM_TRAIN_LIB}_test ${OM_TRAINING_INTERPRETER_LIB})
+target_link_libraries(${OM_TRAIN_LIB}_test onert_micro_coverage)
+target_link_libraries(${OM_TRAIN_LIB} PUBLIC onert_micro_coverage)
diff --git a/onert-micro/onert-micro/src/train/OMBackpropExecute.cpp b/onert-micro/onert-micro/src/train/OMBackpropExecute.cpp
new file mode 100644 (file)
index 0000000..4e224ad
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/OMBackpropExecute.h"
+#include "train/OMBackpropExecutionBuilder.h"
+
+using namespace onert_micro::train;
+using namespace onert_micro;
+
+/*
+ * Run backward graph to calculate gradients
+ */
+OMStatus OMBackpropExecute::runBackward(const OMConfig &config, OMBackpropExecuteArgs &args,
+                                        core::memory::OMRuntimeAllocator &allocator)
+{
+  OMStatus status = Ok;
+
+  core::OMRuntimeContext &context = args.backward_context;
+  core::OMRuntimeStorage &forward_storage = args.forward_storage;
+  core::OMRuntimeStorage &backward_storage = args.backward_storage;
+
+  const core::reader::CircleOperators *operators = context.getCircleOperators();
+
+  const auto num_operators = operators->size();
+  const auto *op_codes = context.getCircleOpcodes();
+
+  uint32_t num_train_layers = config.training_context.num_of_train_layers == 0
+                                ? num_operators
+                                : config.training_context.num_of_train_layers;
+  uint32_t last_node_pos = std::min(num_operators, num_train_layers);
+
+  for (uint32_t i = 0; i < last_node_pos; ++i)
+  {
+    uint32_t cur_op_index = num_operators - i - 1;
+    auto *cur_op = operators->operator[](cur_op_index);
+
+    status = allocator.allocate(i, &context, &backward_storage);
+
+    if (status != Ok)
+      return status;
+
+    core::OMBuilderID builder_id = core::OMBuilderID::Size;
+    const circle::Operator *op = operators->operator[](cur_op_index);
+    uint32_t index = op->opcode_index();
+
+    assert(index < op_codes->size());
+
+    const auto opcode = op_codes->operator[](index);
+
+    status = core::getBuilderId(opcode, builder_id);
+
+    assert(status == Ok);
+    if (status != Ok)
+      return status;
+
+    args.kernel_index = cur_op_index;
+
+    if (i == last_node_pos - 1)
+      args.is_last_layer = true;
+
+    // Calculate gradients
+    KernelTrainFunc *train_func = nullptr;
+    if (size_t(builder_id) < size_t(core::OMBuilderID::BuiltinOperatorsSize))
+    {
+      // Builtin operator
+      status = kernel_builtin_train.getKernelTrainFunc(builder_id, &train_func);
+    }
+    else
+    {
+      assert(false && "Unsupported kernel type for training");
+      return UnsupportedOp;
+    }
+
+    assert(train_func != nullptr);
+
+    if (status != Ok)
+      return status;
+
+    status = train_func(args);
+
+    assert(status == Ok);
+
+    if (status != Ok)
+      return status;
+
+    // Deallocate tensors data in backward storage
+    status = allocator.deallocate(i, &backward_storage);
+    if (status != Ok)
+      return status;
+
+    // Deallocate tensors data in forward storage
+    status = allocator.deallocate(i, &forward_storage);
+  }
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/train/OMBackpropExecutionBuilder.cpp b/onert-micro/onert-micro/src/train/OMBackpropExecutionBuilder.cpp
new file mode 100644 (file)
index 0000000..f274863
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/OMBackpropExecutionBuilder.h"
+// Do nothing
diff --git a/onert-micro/onert-micro/src/train/kernels/Conv2D.cpp b/onert-micro/onert-micro/src/train/kernels/Conv2D.cpp
new file mode 100644 (file)
index 0000000..af3f2a9
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+#include "core/OMUtils.h"
+#include "train/OMBackpropExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+#include "PALConv2DWeightGrad.h"
+#include "PALReluInputGrad.h"
+#include "PALConv2DInputGrad.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::train;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t weightTensorIdx = 1;
+constexpr uint32_t biasTensorIdx = 2;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+/*
+ * - Calculate weight gradient (with bias)
+ * - Calculate input gradient - Optional (not required if it is last op)
+ */
+OMStatus onert_micro::train::train_kernel_CircleConv2D(const OMBackpropExecuteArgs &args)
+{
+  core::OMRuntimeStorage &forward_storage = args.forward_storage;
+  core::OMRuntimeStorage &backward_storage = args.backward_storage;
+  core::OMRuntimeContext &context = args.backward_context;
+  uint16_t op_index = args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *weight;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *dloss_dinput_data;
+
+  uint8_t *weight_data;
+  uint8_t *dloss_dweight_data;
+
+  uint8_t *bias_data;
+  uint8_t *dloss_dbias_data;
+
+  uint8_t *output_data;
+  uint8_t *dloss_doutput_data;
+
+  const circle::Conv2DOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    weight = runtime_kernel.inputs[weightTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(weight != nullptr);
+    // Bias can be nullptr
+    assert(output != nullptr);
+
+    // Read forward storage
+    {
+      runtime_kernel.getDataFromStorage(op_index, forward_storage, context);
+
+      input_data = runtime_kernel.inputs_data[inputTensorIdx];
+      weight_data = runtime_kernel.inputs_data[weightTensorIdx];
+      bias_data = runtime_kernel.inputs_data[biasTensorIdx];
+      output_data = runtime_kernel.outputs_data[outputTensorIdx];
+      // Bias_data can be nullptr
+      // Output_data can be nullptr
+      assert(input_data != nullptr);
+      assert(weight_data != nullptr);
+    }
+
+    // Read backward storage
+    {
+      runtime_kernel.getDataFromStorage(op_index, backward_storage, context);
+
+      dloss_dinput_data = runtime_kernel.inputs_data[inputTensorIdx];
+      dloss_dweight_data = runtime_kernel.inputs_data[weightTensorIdx];
+      dloss_dbias_data = runtime_kernel.inputs_data[biasTensorIdx];
+      dloss_doutput_data = runtime_kernel.outputs_data[outputTensorIdx];
+      // Bias_data and dloss_dinput_data can be nullptr
+      // Note: dloss_dinput_data can be nullptr due to it can be last trainable node
+      assert(dloss_dweight_data != nullptr);
+      assert(dloss_doutput_data != nullptr);
+    }
+
+    options = runtime_kernel.first_operator->builtin_options_as_Conv2DOptions();
+  }
+
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+  OMRuntimeShape weight_shape(weight);
+
+  // 1. Handle activation functions
+  switch (options->fused_activation_function())
+  {
+    case circle::ActivationFunctionType_NONE:
+      // Do nothing
+      break;
+    case circle::ActivationFunctionType_RELU:
+    {
+      assert(output_data != nullptr);
+      pal::ReluInputGrad(utils::castInputData<float>(output_data),
+                         utils::castOutputData<float>(dloss_doutput_data), output_shape);
+      break;
+    }
+    default:
+    {
+      assert(false && "Unsupported activation type");
+      return UnsupportedType;
+    }
+  }
+
+  const int input_width = input_shape.dims(3);
+  const int input_height = input_shape.dims(2);
+  const int weight_width = output_shape.dims(3);
+  const int weight_height = output_shape.dims(2);
+
+  FloatConv2D params{};
+
+  params.stride_w = options->stride_w();
+  params.stride_h = options->stride_h();
+  params.dilation_width_factor = options->dilation_w_factor();
+  params.dilation_height_factor = options->dilation_h_factor();
+  params.pad_h = 0;
+  params.pad_w = 0;
+
+  // 2. Calculate weight gradient
+  pal::Conv2DWeightGrad(params, input_shape, utils::castInputData<float>(input_data), output_shape,
+                        utils::castInputData<float>(dloss_doutput_data), weight_shape,
+                        utils::castOutputData<float>(dloss_dweight_data));
+
+  // 3. Calculate bias gradient
+  if (dloss_dbias_data)
+  {
+    assert(bias_data != nullptr);
+    if (bias_data == nullptr)
+      return UnknownError;
+
+    pal::Conv2DBiasGrad(output_shape, utils::castInputData<float>(dloss_doutput_data),
+                        utils::castOutputData<float>(dloss_dbias_data));
+  }
+
+  // 4. Calculate (if needed) input grad
+  if (args.is_last_layer == false)
+  {
+    assert(dloss_dinput_data != nullptr);
+    pal::Conv2DInputGrad(params, weight_shape, utils::castInputData<float>(weight_data),
+                         output_shape, utils::castInputData<float>(dloss_doutput_data), input_shape,
+                         utils::castOutputData<float>(dloss_dinput_data));
+  }
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/train/kernels/FullyConnected.cpp b/onert-micro/onert-micro/src/train/kernels/FullyConnected.cpp
new file mode 100644 (file)
index 0000000..7aee884
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+#include "core/OMUtils.h"
+#include "core/OMDataType.h"
+#include "train/OMBackpropExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+#include "PALFullyConnectedWeightGrad.h"
+#include "PALFullyConnectedInputGrad.h"
+#include "PALReluInputGrad.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::train;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t weightTensorIdx = 1;
+constexpr uint32_t biasTensorIdx = 2;
+
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+/*
+ * - Calculate weight gradient (with bias)
+ * - Calculate input gradient - Optional (not required if it is last op)
+ */
+OMStatus onert_micro::train::train_kernel_CircleFullyConnected(const OMBackpropExecuteArgs &args)
+{
+  core::OMRuntimeStorage &forward_storage = args.forward_storage;
+  core::OMRuntimeStorage &backward_storage = args.backward_storage;
+  core::OMRuntimeContext &context = args.backward_context;
+  uint16_t op_index = args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *weight;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *dloss_dinput_data;
+
+  uint8_t *weight_data;
+  uint8_t *dloss_dweight_data;
+
+  uint8_t *bias_data;
+  uint8_t *dloss_dbias_data;
+
+  uint8_t *output_data;
+  uint8_t *dloss_doutput_data;
+
+  const circle::FullyConnectedOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    weight = runtime_kernel.inputs[weightTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(weight != nullptr);
+    // Bias can be nullptr
+    assert(output != nullptr);
+
+    // Read forward storage
+    {
+      runtime_kernel.getDataFromStorage(op_index, forward_storage, context);
+
+      input_data = runtime_kernel.inputs_data[inputTensorIdx];
+      weight_data = runtime_kernel.inputs_data[weightTensorIdx];
+      bias_data = runtime_kernel.inputs_data[biasTensorIdx];
+      output_data = runtime_kernel.outputs_data[outputTensorIdx];
+      // Bias_data can be nullptr
+      // Output_data can be nullptr
+      assert(input_data != nullptr);
+      assert(weight_data != nullptr);
+    }
+
+    // Read backward storage
+    {
+      runtime_kernel.getDataFromStorage(op_index, backward_storage, context);
+
+      dloss_dinput_data = runtime_kernel.inputs_data[inputTensorIdx];
+      dloss_dweight_data = runtime_kernel.inputs_data[weightTensorIdx];
+      dloss_dbias_data = runtime_kernel.inputs_data[biasTensorIdx];
+      dloss_doutput_data = runtime_kernel.outputs_data[outputTensorIdx];
+      // Bias_data and dloss_dinput_data can be nullptr
+      // Note: dloss_dinput_data can be nullptr due to it can be last trainable node
+      assert(dloss_dweight_data != nullptr);
+      assert(dloss_doutput_data != nullptr);
+    }
+
+    options = runtime_kernel.first_operator->builtin_options_as_FullyConnectedOptions();
+  }
+
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  // 1. Handle activation functions
+  switch (options->fused_activation_function())
+  {
+    case circle::ActivationFunctionType_NONE:
+      // Do nothing
+      break;
+    case circle::ActivationFunctionType_RELU:
+    {
+      assert(output_data != nullptr);
+      pal::ReluInputGrad(utils::castInputData<float>(output_data),
+                         utils::castOutputData<float>(dloss_doutput_data), output_shape);
+      break;
+    }
+    default:
+    {
+      assert(false && "Unsupported activation type");
+      return UnsupportedType;
+    }
+  }
+
+  // 2. Calculate weight gradient
+  pal::FullyConnectedWeightGrad(core::utils::castInputData<float>(dloss_doutput_data), output_shape,
+                                core::utils::castInputData<float>(input_data), input_shape,
+                                core::utils::castOutputData<float>(dloss_dweight_data));
+
+  // 3. Calculate bias gradient
+  // Just copy dloss_doutput_data to dloss_dbias_data
+  // TODO: introduce training inplace
+  if (dloss_dbias_data)
+  {
+    assert(bias_data != nullptr);
+    if (bias_data == nullptr)
+      return UnknownError;
+
+    std::memcpy(dloss_dbias_data, dloss_doutput_data,
+                sizeof(OMDataType(output->type())) *
+                  output_shape.dims(output_shape.dimensionsCount() - 1));
+  }
+
+  // 4. Calculate (if needed) input grad
+  if (args.is_last_layer == false)
+  {
+    assert(dloss_dinput_data != nullptr);
+
+    pal::FullyConnectedInputGrad(core::utils::castInputData<float>(dloss_doutput_data),
+                                 output_shape, core::utils::castInputData<float>(weight_data),
+                                 OMRuntimeShape(weight),
+                                 core::utils::castOutputData<float>(dloss_dinput_data));
+  }
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/train/kernels/MaxPool2D.cpp b/onert-micro/onert-micro/src/train/kernels/MaxPool2D.cpp
new file mode 100644 (file)
index 0000000..bb0b809
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+#include "core/OMUtils.h"
+#include "core/OMKernelData.h"
+#include "core/OMDataType.h"
+#include "train/OMBackpropExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+#include "execute/OMUtils.h"
+#include "core/memory/OMMemoryManager.h"
+#include "PALMaxPool2DInputGrad.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::train;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+/*
+ * - Calculate input gradient - Optional (not required if it is last op)
+ */
+OMStatus onert_micro::train::train_kernel_CircleMaxPool2D(const OMBackpropExecuteArgs &args)
+{
+  // Check is it last layer for training
+  if (args.is_last_layer)
+  {
+    return Ok;
+  }
+
+  core::OMRuntimeStorage &forward_storage = args.forward_storage;
+  core::OMRuntimeStorage &backward_storage = args.backward_storage;
+  core::OMRuntimeContext &context = args.backward_context;
+  uint16_t op_index = args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *output;
+
+  uint8_t *input_data;
+  uint8_t *dloss_dinput_data;
+
+  uint8_t *dloss_doutput_data;
+
+  const circle::Pool2DOptions *options;
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(output != nullptr);
+
+    // Read forward storage
+    {
+      runtime_kernel.getDataFromStorage(op_index, forward_storage, context);
+
+      input_data = runtime_kernel.inputs_data[inputTensorIdx];
+      assert(input_data != nullptr);
+    }
+
+    // Read backward storage
+    {
+      runtime_kernel.getDataFromStorage(op_index, backward_storage, context);
+
+      dloss_dinput_data = runtime_kernel.inputs_data[inputTensorIdx];
+      dloss_doutput_data = runtime_kernel.outputs_data[outputTensorIdx];
+
+      assert(dloss_dinput_data != nullptr);
+      assert(dloss_doutput_data != nullptr);
+    }
+
+    options = runtime_kernel.first_operator->builtin_options_as_Pool2DOptions();
+  }
+
+  assert(options->fused_activation_function() == circle::ActivationFunctionType_NONE);
+  if (options->fused_activation_function() != circle::ActivationFunctionType_NONE)
+    return UnsupportedType;
+
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  int32_t padding_h = 0;
+  int32_t padding_w = 0;
+
+  const int input_width = input_shape.dims(2);
+  const int input_height = input_shape.dims(1);
+  execute::computePaddingHeightWidth(
+    options->stride_h(), options->stride_w(), 1 /* dilation_rate_height */,
+    1 /* dilation_rate_width */, input_height, input_width, options->filter_height(),
+    options->filter_width(), options->padding(), &padding_h, &padding_w);
+
+  core::Pool2DParams params{};
+  params.pad_h = padding_h;
+  params.pad_w = padding_w;
+  params.stride_h = options->stride_h();
+  params.stride_w = options->stride_w();
+  params.filter_h = options->filter_height();
+  params.filter_w = options->filter_width();
+
+  // Set input grad to zero
+  std::memset(dloss_dinput_data, 0, sizeof(OMDataType(output->type())) * input_shape.flatSize());
+
+  // Calculate input grad
+  pal::MaxPool2D(params, input_shape, core::utils::castInputData<float>(input_data), output_shape,
+                 core::utils::castInputData<float>(dloss_doutput_data),
+                 core::utils::castOutputData<float>(dloss_dinput_data));
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/train/kernels/Reshape.cpp b/onert-micro/onert-micro/src/train/kernels/Reshape.cpp
new file mode 100644 (file)
index 0000000..a9dce01
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+
+#include "core/OMUtils.h"
+#include "core/OMDataType.h"
+
+#include "train/OMBackpropExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+
+using namespace onert_micro;
+using namespace onert_micro::train;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+/*
+ * - Calculate input gradient - Optional (not required if it is last op)
+ */
+OMStatus onert_micro::train::train_kernel_CircleReshape(const OMBackpropExecuteArgs &args)
+{
+  // Check is it last layer for training
+  if (args.is_last_layer)
+    return Ok;
+
+  core::OMRuntimeContext &runtime_context = args.backward_context;
+  core::OMRuntimeStorage &runtime_storage = args.backward_storage;
+  uint16_t op_index = args.kernel_index;
+
+  execute::OMRuntimeKernel runtime_kernel;
+  runtime_kernel.readKernel(op_index, runtime_context);
+
+  const circle::Tensor *input = runtime_kernel.inputs[inputTensorIdx];
+  const circle::Tensor *output = runtime_kernel.outputs[outputTensorIdx];
+
+  assert(input != nullptr);
+  assert(output != nullptr);
+
+  OMStatus status = Ok;
+
+  status = runtime_kernel.getDataFromStorage(op_index, runtime_storage, runtime_context);
+  if (status != Ok)
+    return status;
+
+  uint8_t *input_data = runtime_kernel.inputs_data[inputTensorIdx];
+  uint8_t *output_data = runtime_kernel.outputs_data[outputTensorIdx];
+
+  assert(input_data != nullptr);
+  assert(output_data != nullptr);
+
+  // Check is it inplace kernel
+  if (input_data == output_data)
+    return Ok;
+
+  const core::OMRuntimeShape shape(input);
+
+  const size_t element_size =
+    static_cast<uint32_t>(getOMDataTypeSize(core::onertMicroDatatype(input->type())));
+  const int32_t num_elements = shape.flatSize();
+  std::memcpy(input_data, output_data, num_elements * element_size);
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/train/kernels/Softmax.cpp b/onert-micro/onert-micro/src/train/kernels/Softmax.cpp
new file mode 100644 (file)
index 0000000..b2ab791
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMStatus.h"
+#include "core/OMUtils.h"
+#include "core/OMDataType.h"
+#include "train/OMBackpropExecutionBuilder.h"
+#include "execute/OMRuntimeKernel.h"
+#include "core/memory/OMMemoryManager.h"
+#include "PALSoftmaxInputGrad.h"
+
+using namespace onert_micro;
+using namespace onert_micro::core;
+using namespace onert_micro::train;
+
+namespace
+{
+
+constexpr uint32_t inputTensorIdx = 0;
+constexpr uint32_t outputTensorIdx = 0;
+
+} // namespace
+
+/*
+ * - Calculate input gradient - Optional (not required if it is last op)
+ */
+OMStatus onert_micro::train::train_kernel_CircleSoftmax(const OMBackpropExecuteArgs &args)
+{
+  // Check is it last layer for training
+  if (args.is_last_layer)
+  {
+    return Ok;
+  }
+
+  core::OMRuntimeStorage &forward_storage = args.forward_storage;
+  core::OMRuntimeStorage &backward_storage = args.backward_storage;
+  core::OMRuntimeContext &context = args.backward_context;
+  uint16_t op_index = args.kernel_index;
+
+  const circle::Tensor *input;
+  const circle::Tensor *output;
+
+  uint8_t *dloss_dinput_data;
+
+  uint8_t *output_data;
+  uint8_t *dloss_doutput_data;
+
+  // Read kernel
+  {
+    execute::OMRuntimeKernel runtime_kernel;
+    runtime_kernel.readKernel(op_index, context);
+
+    input = runtime_kernel.inputs[inputTensorIdx];
+    output = runtime_kernel.outputs[outputTensorIdx];
+    assert(input != nullptr);
+    assert(output != nullptr);
+
+    // Read forward storage
+    {
+      runtime_kernel.getDataFromStorage(op_index, forward_storage, context);
+
+      output_data = runtime_kernel.outputs_data[outputTensorIdx];
+      assert(output_data != nullptr);
+    }
+
+    // Read backward storage
+    {
+      runtime_kernel.getDataFromStorage(op_index, backward_storage, context);
+
+      dloss_dinput_data = runtime_kernel.inputs_data[inputTensorIdx];
+      dloss_doutput_data = runtime_kernel.outputs_data[outputTensorIdx];
+
+      assert(dloss_dinput_data != nullptr);
+      assert(dloss_doutput_data != nullptr);
+    }
+  }
+
+  OMRuntimeShape input_shape(input);
+  OMRuntimeShape output_shape(output);
+
+  // Check Softmax output and input shape
+  assert(output_shape.dimensionsCount() == 2);
+  assert(output_shape.dims(0) == 1);
+  if (output_shape.dimensionsCount() != 2 or output_shape.dims(0) != 1)
+    return UnsupportedType;
+
+  // Allocate temporary buffer to save Jacobian row
+  uint8_t *jacobian_row_data = nullptr;
+  OMStatus status = core::memory::OMMemoryManager::allocateMemory(
+    output_shape.flatSize() * sizeof(OMDataType(output->type())), &jacobian_row_data);
+  assert(status == Ok);
+  if (status != Ok)
+    return status;
+
+  // Calculate input grad
+  pal::SoftmaxInputGrad(core::utils::castInputData<float>(dloss_doutput_data), output_shape,
+                        core::utils::castInputData<float>(output_data),
+                        core::utils::castOutputData<float>(jacobian_row_data),
+                        core::utils::castOutputData<float>(dloss_dinput_data));
+
+  // Deallocate temporary buffer with Jacobian row
+  status = core::memory::OMMemoryManager::deallocateMemory(jacobian_row_data);
+
+  return status;
+}
diff --git a/onert-micro/onert-micro/src/train/losses_functions/CrossEntropy.cpp b/onert-micro/onert-micro/src/train/losses_functions/CrossEntropy.cpp
new file mode 100644 (file)
index 0000000..7aeb5da
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/losses_functions/CrossEntropy.h"
+
+using namespace onert_micro;
+using namespace onert_micro::train;
+using namespace onert_micro::train::losses_functions;
+
+/*
+ * dE/dY = Y_t / Y
+ * where Y - vector of calculated outputs,
+ *       Y_t - vector of target outputs
+ * Note: size of Y and Y_t should be the same and equal to flat_size
+ */
+void CrossEntropy::calculateErrorBackpropagation(const uint32_t flat_size,
+                                                 const float *calculated_data,
+                                                 const float *target_data, float *output_grad)
+{
+  for (uint32_t i = 0; i < flat_size; ++i)
+  {
+    output_grad[i] = -1.f * target_data[i] / (calculated_data[i] + float(10.0e-32));
+  }
+}
diff --git a/onert-micro/onert-micro/src/train/losses_functions/MSE.cpp b/onert-micro/onert-micro/src/train/losses_functions/MSE.cpp
new file mode 100644 (file)
index 0000000..17d2ded
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/losses_functions/MSE.h"
+
+using namespace onert_micro;
+using namespace onert_micro::train;
+using namespace onert_micro::train::losses_functions;
+
+/*
+ * dE/dY = (2 * (Y - Y_t)) / N
+ * where Y - vector of calculated outputs,
+ *       Y_t - vector of target outputs
+ * Note: size of Y and Y_t should be the same and equal to flat_size
+ */
+void MSE::calculateErrorBackpropagation(const uint32_t flat_size, const float *calculated_data,
+                                        const float *target_data, float *output_grad)
+{
+  for (uint32_t i = 0; i < flat_size; ++i)
+  {
+    output_grad[i] = (2 * (calculated_data[i] - target_data[i])) / static_cast<float>(flat_size);
+  }
+}
diff --git a/onert-micro/onert-micro/src/train/metrics/Accuracy.cpp b/onert-micro/onert-micro/src/train/metrics/Accuracy.cpp
new file mode 100644 (file)
index 0000000..36bebde
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/metrics/Accuracy.h"
+
+using namespace onert_micro;
+using namespace onert_micro::train;
+using namespace onert_micro::train::metrics;
+
+/*
+ * return 1.0 if predicted class equals to target
+ * return 0.0 otherwise
+ */
+float Accuracy::calculateValue(const uint32_t flat_size, const float *calculated_data,
+                               const float *target_data)
+{
+  // Find target class
+  float target_class = 0.f;
+  float target_max_val = target_data[0];
+  for (uint32_t i = 0; i < flat_size; ++i)
+  {
+    if (target_max_val < target_data[i])
+    {
+      target_max_val = target_data[i];
+      target_class = static_cast<float>(i);
+    }
+  }
+  // Find predicted class
+  float pred_class = 0.f;
+  float pred_max_val = calculated_data[0];
+  for (uint32_t i = 0; i < flat_size; ++i)
+  {
+    if (pred_max_val < calculated_data[i])
+    {
+      pred_max_val = calculated_data[i];
+      pred_class = static_cast<float>(i);
+    }
+  }
+
+  return pred_class == target_class ? 1.0f : 0.0f;
+}
diff --git a/onert-micro/onert-micro/src/train/metrics/CrossEntropy.cpp b/onert-micro/onert-micro/src/train/metrics/CrossEntropy.cpp
new file mode 100644 (file)
index 0000000..0aaf919
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/metrics/CrossEntropy.h"
+
+#include <cmath>
+
+using namespace onert_micro;
+using namespace onert_micro::train;
+using namespace onert_micro::train::metrics;
+
+/*
+ * Y - calculated value
+ * Y_t - target value
+ * E(Y, Y_t) = -SUM(Y_t_i * log(Y_i))
+ * SUM - sum among i = (0 ... N - 1), N - flat_size
+ */
+float CrossEntropy::calculateValue(const uint32_t flat_size, const float *calculated_data,
+                                   const float *target_data)
+{
+  float result_value = 0.f;
+
+  for (uint32_t i = 0; i < flat_size; ++i)
+  {
+    result_value += target_data[i] * std::log(calculated_data[i] + float(10.0e-32));
+  }
+
+  return -result_value;
+}
diff --git a/onert-micro/onert-micro/src/train/metrics/MAE.cpp b/onert-micro/onert-micro/src/train/metrics/MAE.cpp
new file mode 100644 (file)
index 0000000..4967564
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/metrics/MAE.h"
+
+#include <cmath>
+#include <cassert>
+
+using namespace onert_micro;
+using namespace onert_micro::train;
+using namespace onert_micro::train::metrics;
+
+/*
+ * E(Y, Y_t) = SUM(|Y_i - Y_t_i|) / N
+ * SUM - sum among i = (0 ... N - 1)
+ */
+float MAE::calculateValue(const uint32_t flat_size, const float *calculated_data,
+                          const float *target_data)
+{
+  float result_value = 0.f;
+
+  for (uint32_t i = 0; i < flat_size; ++i)
+  {
+    result_value += std::fabs(calculated_data[i] - target_data[i]);
+  }
+
+  assert(flat_size != 0);
+
+  return result_value / static_cast<float>(flat_size);
+}
diff --git a/onert-micro/onert-micro/src/train/metrics/MSE.cpp b/onert-micro/onert-micro/src/train/metrics/MSE.cpp
new file mode 100644 (file)
index 0000000..4582f21
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/metrics/MSE.h"
+
+#include <cmath>
+#include <cassert>
+
+using namespace onert_micro;
+using namespace onert_micro::train;
+using namespace onert_micro::train::metrics;
+
+/*
+ * E(Y, Y_t) = (SUM(Y_i - Y_t_i)^2) / N
+ * SUM - sum among i = (0 ... N - 1)
+ */
+float MSE::calculateValue(const uint32_t flat_size, const float *calculated_data,
+                          const float *target_data)
+{
+  float result_value = 0.f;
+
+  for (uint32_t i = 0; i < flat_size; ++i)
+  {
+    const auto cur_val = calculated_data[i] - target_data[i];
+    result_value += cur_val * cur_val;
+  }
+
+  assert(flat_size != 0);
+
+  return result_value / static_cast<float>(flat_size);
+}
diff --git a/onert-micro/onert-micro/src/train/tests/BostonHousingTask.test.cpp b/onert-micro/onert-micro/src/train/tests/BostonHousingTask.test.cpp
new file mode 100644 (file)
index 0000000..69d7550
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/tests/boston_housing_task/BostonHousingTask.h"
+#include "train/tests/OMTestUtils.h"
+
+#include <gtest/gtest.h>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+
+using namespace testing;
+
+class BostonHousingTaskTest : public ::testing::Test
+{
+public:
+  BostonHousingTaskTest()
+  {
+    // Set user defined training settings
+    const uint32_t training_epochs = 30;
+    const float lambda = 0.1f;
+    const uint32_t batch_size = 32;
+    // Train all layers
+    const uint32_t num_train_layers = 0;
+    const onert_micro::OMLoss loss = onert_micro::MSE;
+    const onert_micro::OMTrainOptimizer train_optim = onert_micro::ADAM;
+    const float beta = 0.9;
+    const float beta_squares = 0.999;
+    const float epsilon = 1e-07;
+
+    config.train_mode = true;
+    {
+      onert_micro::OMTrainingContext train_context;
+      train_context.batch_size = batch_size;
+      train_context.num_of_train_layers = num_train_layers;
+      train_context.learning_rate = lambda;
+      train_context.loss = loss;
+      train_context.optimizer = train_optim;
+      train_context.beta = beta;
+      train_context.beta_squares = beta_squares;
+      train_context.epsilon = epsilon;
+      train_context.epochs = training_epochs;
+
+      config.training_context = train_context;
+    }
+  }
+
+  OMConfig config = {};
+
+  // Some value for checking that the learning process has not become worse
+  const float golden_mae_metric = 10.f;
+};
+
+TEST_F(BostonHousingTaskTest, ADAM_MSE_P)
+{
+  // Create BostonHousing data handler
+  BostonHousingTask<float> bostonTask;
+
+  config.model_ptr = bostonTask.getModelPtr();
+  config.model_size = bostonTask.getModelSize();
+  config.train_mode = true;
+
+  // Create and import train interpreter
+  OMTrainingInterpreter train_interpreter;
+  OMStatus status = train_interpreter.importTrainModel(bostonTask.getModelPtr(), config);
+  EXPECT_EQ(status, Ok);
+
+  // Evaluate result before training
+  float mae_metric_before_training = 0.f;
+  status =
+    evaluate(train_interpreter, config, bostonTask, MAE_METRICS, &mae_metric_before_training);
+  EXPECT_EQ(status, Ok);
+
+  // Train model with current config
+  status = train(train_interpreter, config, bostonTask);
+  EXPECT_EQ(status, Ok);
+
+  // Evaluate result after training
+  float mae_metric_after_training = 0.f;
+  status = evaluate(train_interpreter, config, bostonTask, MAE_METRICS, &mae_metric_after_training);
+  EXPECT_EQ(status, Ok);
+
+  // MAE metric after training should be better then before (before training mae value greater then
+  // after)
+  EXPECT_GT(mae_metric_before_training, mae_metric_after_training);
+
+  // Compare with gold value
+  EXPECT_LE(mae_metric_after_training, golden_mae_metric);
+}
+
+TEST_F(BostonHousingTaskTest, Wrong_Loss_NEG)
+{
+  // Create BostonHousing data handler
+  BostonHousingTask<float> bostonTask;
+
+  config.model_ptr = bostonTask.getModelPtr();
+  config.model_size = bostonTask.getModelSize();
+  config.train_mode = true;
+  // Use CrossEntropy loss for regression task - it is wrong way
+  config.training_context.loss = CROSS_ENTROPY;
+
+  // Create and import train interpreter
+  OMTrainingInterpreter train_interpreter;
+  OMStatus status = train_interpreter.importTrainModel(bostonTask.getModelPtr(), config);
+  EXPECT_EQ(status, Ok);
+
+  // Evaluate result before training
+  float mae_metric_before_training = 0.f;
+  status =
+    evaluate(train_interpreter, config, bostonTask, MAE_METRICS, &mae_metric_before_training);
+  EXPECT_EQ(status, Ok);
+
+  // Train model with current config
+  status = train(train_interpreter, config, bostonTask);
+  EXPECT_EQ(status, Ok);
+
+  // Evaluate result after training
+  float mae_metric_after_training = 0.f;
+  status = evaluate(train_interpreter, config, bostonTask, MAE_METRICS, &mae_metric_after_training);
+  EXPECT_EQ(status, Ok);
+
+  // MAE metric will degraded due to wrong type
+  EXPECT_LT(mae_metric_before_training, mae_metric_after_training);
+}
+
+} // namespace test
+} // namespace train
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/train/tests/CheckpointsHandler.test.cpp b/onert-micro/onert-micro/src/train/tests/CheckpointsHandler.test.cpp
new file mode 100644 (file)
index 0000000..87e9b39
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/tests/models/checkoint_simple_example_model.h"
+#include "train/tests/models/saved_checkpoint_example.h"
+#include "core/train/OMCheckpointSaver.h"
+#include "train/tests/OMTestUtils.h"
+
+#include <gtest/gtest.h>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+
+using namespace testing;
+
+class CheckpointsHandlerTest : public ::testing::Test
+{
+public:
+  CheckpointsHandlerTest()
+  {
+    // Do nothing
+  }
+
+  OMConfig config = {};
+};
+
+// Check save functionality
+TEST_F(CheckpointsHandlerTest, Save_check_P)
+{
+  // Create BostonHousing data handler
+  config.model_ptr = reinterpret_cast<char *>(models::checkpoint_simple_example_model_data);
+  config.model_size = models::checkpoint_simple_example_model_size;
+  config.train_mode = true;
+
+  // Import model
+  core::OMTrainingRuntimeModule training_runtime_module;
+  OMStatus status = training_runtime_module.importTrainModel(config.model_ptr, config);
+  EXPECT_EQ(status, Ok);
+
+  // Get DataBuffer (vector of chars) of checkpoints
+  std::vector<char> checkpoint_data;
+  status = training_runtime_module.createCheckpointFile(config, checkpoint_data);
+  EXPECT_EQ(status, Ok);
+  EXPECT_TRUE(!checkpoint_data.empty());
+}
+
+// Check load functionality
+TEST_F(CheckpointsHandlerTest, Load_check_P)
+{
+  // Create BostonHousing data handler
+  config.model_ptr = reinterpret_cast<char *>(models::checkpoint_simple_example_model_data);
+  config.model_size = models::checkpoint_simple_example_model_size;
+  config.train_mode = true;
+
+  // Import model
+  core::OMTrainingRuntimeModule training_runtime_module;
+  OMStatus status = training_runtime_module.importTrainModel(config.model_ptr, config);
+  EXPECT_EQ(status, Ok);
+
+  // Get DataBuffer (vector of chars) of checkpoints
+  std::vector<char> checkpoint_data(models::saved_checkpoint_example_size);
+  std::memcpy(checkpoint_data.data(), models::saved_checkpoint_example,
+              models::saved_checkpoint_example_size);
+  // Load and check (validation inside)
+  status = training_runtime_module.loadCheckpointData(config, checkpoint_data.data());
+  EXPECT_EQ(status, Ok);
+}
+
+// Check load functionality
+TEST_F(CheckpointsHandlerTest, Wrong_magic_num_NEG)
+{
+  // Create BostonHousing data handler
+  config.model_ptr = reinterpret_cast<char *>(models::checkpoint_simple_example_model_data);
+  config.model_size = models::checkpoint_simple_example_model_size;
+  config.train_mode = true;
+
+  // Import model
+  core::OMTrainingRuntimeModule training_runtime_module;
+  OMStatus status = training_runtime_module.importTrainModel(config.model_ptr, config);
+  EXPECT_EQ(status, Ok);
+
+  // Get DataBuffer (vector of chars) of checkpoints
+  std::vector<char> checkpoint_data(models::saved_checkpoint_example_size);
+  std::memcpy(checkpoint_data.data(), models::saved_checkpoint_example_with_wrong_magic_num,
+              models::saved_checkpoint_example_size);
+  // Load and check (validation inside)
+  EXPECT_DEATH(training_runtime_module.loadCheckpointData(config, checkpoint_data.data()), "");
+}
+
+} // namespace test
+} // namespace train
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/train/tests/NumbersClassificationTask.test.cpp b/onert-micro/onert-micro/src/train/tests/NumbersClassificationTask.test.cpp
new file mode 100644 (file)
index 0000000..4e8db26
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "train/tests/numbers_classification_task/NumbersClassificationTask.h"
+#include "train/tests/OMTestUtils.h"
+
+#include <gtest/gtest.h>
+
+namespace onert_micro
+{
+namespace train
+{
+namespace test
+{
+
+using namespace testing;
+
+class NumbersClassificationTaskTest : public ::testing::Test
+{
+public:
+  NumbersClassificationTaskTest()
+  {
+    // Set user defined training settings
+    const uint32_t training_epochs = 10;
+    const float lambda = 0.1f;
+    const uint32_t batch_size = 1;
+    // Train all layers
+    const uint32_t num_train_layers = 0;
+    const onert_micro::OMLoss loss = onert_micro::CROSS_ENTROPY;
+    const onert_micro::OMTrainOptimizer train_optim = onert_micro::SGD;
+    const float beta = 0.9;
+    const float beta_squares = 0.999;
+    const float epsilon = 1e-07;
+
+    config.train_mode = true;
+    {
+      onert_micro::OMTrainingContext train_context;
+      train_context.batch_size = batch_size;
+      train_context.num_of_train_layers = num_train_layers;
+      train_context.learning_rate = lambda;
+      train_context.loss = loss;
+      train_context.optimizer = train_optim;
+      train_context.beta = beta;
+      train_context.beta_squares = beta_squares;
+      train_context.epsilon = epsilon;
+      train_context.epochs = training_epochs;
+
+      config.training_context = train_context;
+    }
+  }
+
+  OMConfig config = {};
+
+  // Some value for checking that the learning process has not become worse
+  const float golden_accuracy_metric = 1.f;
+};
+
+TEST_F(NumbersClassificationTaskTest, SGD_CROSS_ENTROPY_P)
+{
+  // Create BostonHousing data handler
+  NumbersClassificationTask<float> numbersClassificationTask;
+
+  config.model_ptr = numbersClassificationTask.getModelPtr();
+  config.model_size = numbersClassificationTask.getModelSize();
+  config.train_mode = true;
+
+  // Create and import train interpreter
+  OMTrainingInterpreter train_interpreter;
+  OMStatus status =
+    train_interpreter.importTrainModel(numbersClassificationTask.getModelPtr(), config);
+  EXPECT_EQ(status, Ok);
+
+  // Evaluate result before training
+  float acc_metric_before_training = 0.f;
+  status = evaluate(train_interpreter, config, numbersClassificationTask, ACCURACY,
+                    &acc_metric_before_training);
+  EXPECT_EQ(status, Ok);
+
+  // Train model with current config
+  status = train(train_interpreter, config, numbersClassificationTask);
+  EXPECT_EQ(status, Ok);
+
+  // Evaluate result after training
+  float acc_metric_after_training = 0.f;
+  status = evaluate(train_interpreter, config, numbersClassificationTask, ACCURACY,
+                    &acc_metric_after_training);
+  EXPECT_EQ(status, Ok);
+
+  // ACCURACY metric after training should be better then before (before training accuracy value
+  // smaller then after)
+  EXPECT_GT(acc_metric_after_training, acc_metric_before_training);
+
+  // Compare with gold value (should be greater or equal)
+  EXPECT_GE(acc_metric_after_training, golden_accuracy_metric);
+}
+
+} // namespace test
+} // namespace train
+} // namespace onert_micro
diff --git a/onert-micro/onert-micro/src/train/train_optimizers/Adam.cpp b/onert-micro/onert-micro/src/train/train_optimizers/Adam.cpp
new file mode 100644 (file)
index 0000000..0c32d42
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMConfig.h"
+#include "train/train_optimizers/Adam.h"
+#include "core/memory/OMMemoryManager.h"
+#include "core/OMRuntimeShape.h"
+#include "core/OMDataType.h"
+
+#include <cmath>
+
+using namespace onert_micro;
+using namespace onert_micro::train;
+using namespace onert_micro::train::optimizers;
+
+void Adam::fullReset()
+{
+  for (auto &cur_tensor_index_data : _tensor_to_exponent_avg)
+  {
+    uint8_t *allocated_data = cur_tensor_index_data.second;
+
+    core::memory::OMMemoryManager::deallocateMemory(allocated_data);
+  }
+  _tensor_to_exponent_avg.clear();
+
+  for (auto &cur_tensor_index_data : _tensor_to_exponent_avg_squares)
+  {
+    uint8_t *allocated_data = cur_tensor_index_data.second;
+
+    core::memory::OMMemoryManager::deallocateMemory(allocated_data);
+  }
+  _tensor_to_exponent_avg_squares.clear();
+
+  for (auto &cur_tensor_index_data : _tensor_index_to_gradient)
+  {
+    uint8_t *allocated_data = cur_tensor_index_data.second;
+
+    core::memory::OMMemoryManager::deallocateMemory(allocated_data);
+  }
+  _tensor_index_to_gradient.clear();
+}
+
+void Adam::reset()
+{
+  for (auto &cur_tensor_index_data : _tensor_index_to_gradient)
+  {
+    uint8_t *allocated_data = cur_tensor_index_data.second;
+
+    core::memory::OMMemoryManager::deallocateMemory(allocated_data);
+  }
+  _tensor_index_to_gradient.clear();
+}
+
+uint8_t *Adam::getExponentAvgDataByTensorIndex(uint16_t tensor_index)
+{
+  auto it = _tensor_to_exponent_avg.find(tensor_index);
+  if (it == _tensor_to_exponent_avg.end())
+    return nullptr;
+
+  return it->second;
+}
+
+uint8_t *Adam::getExponentAvgSquaresDataByTensorIndex(uint16_t tensor_index)
+{
+  auto it = _tensor_to_exponent_avg_squares.find(tensor_index);
+  if (it == _tensor_to_exponent_avg_squares.end())
+    return nullptr;
+
+  return it->second;
+}
+
+void Adam::setExponentAvgDataByTensorIndex(uint16_t tensor_index, uint8_t *data)
+{
+  assert(_tensor_to_exponent_avg.find(tensor_index) == _tensor_to_exponent_avg.end());
+  assert(data != nullptr);
+
+  _tensor_to_exponent_avg[tensor_index] = data;
+}
+
+void Adam::setExponentAvgSquaresDataByTensorIndex(uint16_t tensor_index, uint8_t *data)
+{
+  assert(_tensor_to_exponent_avg_squares.find(tensor_index) ==
+         _tensor_to_exponent_avg_squares.end());
+  assert(data != nullptr);
+
+  _tensor_to_exponent_avg_squares[tensor_index] = data;
+}
+
+/*
+ * Update internal states according to calculated gradients using Adam theory
+ * grad(t) = grad(t - 1) + calculated_grad(t)
+ */
+OMStatus Adam::handle(core::OMRuntimeStorage &backward_storage, core::OMRuntimeContext &context)
+{
+  auto &backward_tensor_to_data = backward_storage.getTensorIndexToData();
+
+  // Check is allocated or not helper buffers
+  if (_tensor_to_exponent_avg_squares.empty())
+  {
+    // If not - let's allocate it
+    assert(_tensor_to_exponent_avg.empty() == true);
+    // Goes over all calculated gradients
+    // Warning: assume that backward storage at this moment contains only weighs gradients -
+    // This should be done due to execution plan work
+    for (auto &tensor_to_data : backward_tensor_to_data)
+    {
+      auto tensor = context.getTensorByIndex(tensor_to_data.first);
+      core::OMRuntimeShape shape(tensor);
+
+      const auto flat_size = shape.flatSize();
+      const auto type_size = sizeof(core::OMDataType(tensor->type()));
+
+      // Allocate data for exponent calculation
+      uint8_t *exponent_data = nullptr;
+      OMStatus status =
+        core::memory::OMMemoryManager::allocateMemory(flat_size * type_size, &exponent_data);
+      assert(status == Ok);
+      if (status != Ok)
+        return UnknownError;
+      // Set to zeros
+      std::memset(exponent_data, 0, flat_size * type_size);
+      _tensor_to_exponent_avg[tensor_to_data.first] = exponent_data;
+
+      // Allocate data for exponent square calculation
+      uint8_t *exponent_square_data = nullptr;
+      status =
+        core::memory::OMMemoryManager::allocateMemory(flat_size * type_size, &exponent_square_data);
+      assert(status == Ok);
+      if (status != Ok)
+        return UnknownError;
+      // Set to zeros
+      std::memset(exponent_square_data, 0, flat_size * type_size);
+      _tensor_to_exponent_avg_squares[tensor_to_data.first] = exponent_square_data;
+    }
+  }
+
+  // Check is allocated or not helper buffer
+  if (_tensor_index_to_gradient.empty())
+  {
+    // If not - let's just move it with calculations
+    // Goes over all calculated gradients
+    // Warning: assume that backward storage at this moment contains only weights gradients -
+    // This should be done due to execution plan work
+    for (auto &tensor_to_data : backward_tensor_to_data)
+    {
+      // Move data
+      _tensor_index_to_gradient[tensor_to_data.first] = tensor_to_data.second;
+      tensor_to_data.second = nullptr;
+    }
+    backward_tensor_to_data.clear();
+  }
+  else
+  {
+    // Goes over all calculated gradients
+    // Warning: assume that backward storage at this moment contains only weighs gradients -
+    // This should be done due to execution plan work
+    for (auto &tensor_to_data : backward_tensor_to_data)
+    {
+      auto tensor = context.getTensorByIndex(tensor_to_data.first);
+      core::OMRuntimeShape shape(tensor);
+
+      const auto flat_size = shape.flatSize();
+
+      auto *grad_data = reinterpret_cast<float *>(_tensor_index_to_gradient[tensor_to_data.first]);
+      auto *calculated_data = reinterpret_cast<float *>(tensor_to_data.second);
+
+      for (uint32_t i = 0; i < flat_size; ++i)
+      {
+        grad_data[i] += calculated_data[i];
+      }
+    }
+  }
+
+  return Ok;
+}
+
+/*
+ * Update internal states according to calculated gradients using Adam theory
+ * m(t) = beta_1 * m(t-1) + (1 - beta_1) * calculated_gradients(t)
+ * v(t) = beta_2 * v(t-1) + (1 - beta_2) * (calculated_gradients(t)) ^ 2
+
+ * Update weights according to Adam theory:
+ * m`(t) = m(t) / (1 - (beta_1) ^ t)
+ * v`(t) = v(t) / (1 - (beta_2) ^ t)
+ *
+ * w(t + 1) = w(t) - lambda * m`(t) / (sqrt(v` + epsilon))
+ */
+OMStatus Adam::updateWeights(const onert_micro::OMTrainingContext &training_config,
+                             core::OMRuntimeContext &context)
+{
+  assert(!_tensor_index_to_gradient.empty());
+
+  for (auto &tensor_to_data : _tensor_index_to_gradient)
+  {
+    auto exponent_squares_it = _tensor_to_exponent_avg_squares.find(tensor_to_data.first);
+    if (exponent_squares_it == _tensor_to_exponent_avg_squares.end())
+      return UnknownError;
+
+    auto exponent_it = _tensor_to_exponent_avg.find(tensor_to_data.first);
+    if (exponent_it == _tensor_to_exponent_avg.end())
+      return UnknownError;
+
+    auto tensor = context.getTensorByIndex(tensor_to_data.first);
+    core::OMRuntimeShape shape(tensor);
+
+    const auto flat_size = shape.flatSize();
+
+    auto *exponent_data = reinterpret_cast<float *>(exponent_it->second);
+    auto *exponent_square_data = reinterpret_cast<float *>(exponent_squares_it->second);
+    auto *calculated_data = reinterpret_cast<float *>(tensor_to_data.second);
+    float beta = training_config.beta;
+    float beta_squares = training_config.beta_squares;
+    auto batches = static_cast<float>(training_config.batch_size);
+    for (uint32_t i = 0; i < flat_size; ++i)
+    {
+      const auto cur_val = calculated_data[i];
+      exponent_data[i] = beta * exponent_data[i] + (1 - beta) * cur_val;
+      exponent_square_data[i] =
+        beta_squares * exponent_square_data[i] + (1 - beta_squares) * cur_val * cur_val;
+    }
+
+    uint8_t *weight_data = nullptr;
+    if (context.getConstDataByTensorIndex(&weight_data, tensor_to_data.first) != Ok)
+      return UnknownError;
+
+    assert(weight_data != nullptr);
+    if (weight_data == nullptr)
+      return UnknownError;
+
+    auto *f_weight_data = reinterpret_cast<float *>(weight_data);
+    float lambda = training_config.learning_rate;
+    auto num_step = static_cast<float>(training_config.num_step);
+    float beta_in_pow_batch = std::pow(beta, num_step);
+    float beta_square_in_pow_batch = std::pow(beta_squares, num_step);
+    float epsilon = training_config.epsilon;
+
+    assert((1.f - beta_in_pow_batch) != 0);
+    assert((1.f - beta_square_in_pow_batch) != 0);
+
+    for (uint32_t i = 0; i < flat_size; ++i)
+    {
+      float exponent_corrected = exponent_data[i] / (1.f - beta_in_pow_batch);
+      float exponent_square_corrected = exponent_square_data[i] / (1.f - beta_square_in_pow_batch);
+      f_weight_data[i] -=
+        lambda * (exponent_corrected / (std::sqrt(exponent_square_corrected + epsilon)));
+    }
+  }
+
+  return Ok;
+}
diff --git a/onert-micro/onert-micro/src/train/train_optimizers/SGD.cpp b/onert-micro/onert-micro/src/train/train_optimizers/SGD.cpp
new file mode 100644 (file)
index 0000000..a33b0ee
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OMConfig.h"
+#include "train/train_optimizers/SGD.h"
+#include "core/memory/OMMemoryManager.h"
+#include "core/OMRuntimeShape.h"
+
+using namespace onert_micro;
+using namespace onert_micro::train;
+using namespace onert_micro::train::optimizers;
+
+void SGD::reset()
+{
+  for (auto &cur_tensor_index_data : _tensor_index_to_gradient)
+  {
+    uint8_t *allocated_data = cur_tensor_index_data.second;
+
+    core::memory::OMMemoryManager::deallocateMemory(allocated_data);
+  }
+  _tensor_index_to_gradient.clear();
+}
+
+/*
+ * Update internal states according to calculated gradients using Adam theory
+ * grad(t) = grad(t - 1) + calculated_grad(t)
+ */
+OMStatus SGD::handle(core::OMRuntimeStorage &backward_storage, core::OMRuntimeContext &context)
+{
+  auto &backward_tensor_to_data = backward_storage.getTensorIndexToData();
+  // Check is allocated or not helper buffers
+  if (_tensor_index_to_gradient.empty())
+  {
+    // If not - let's just move it with calculations
+    // Goes over all calculated gradients
+    // Warning: assume that backward storage at this moment contains only weigths gradients -
+    // This should be done due to execution plan work
+    for (auto &tensor_to_data : backward_tensor_to_data)
+    {
+      // Move data
+      _tensor_index_to_gradient[tensor_to_data.first] = tensor_to_data.second;
+      tensor_to_data.second = nullptr;
+    }
+    backward_tensor_to_data.clear();
+  }
+  else
+  {
+    // Goes over all calculated gradients
+    // Warning: assume that backward storage at this moment contains only weigths gradients -
+    // This should be done due to execution plan work
+    for (auto &tensor_to_data : backward_tensor_to_data)
+    {
+      auto tensor = context.getTensorByIndex(tensor_to_data.first);
+      core::OMRuntimeShape shape(tensor);
+
+      const auto flat_size = shape.flatSize();
+
+      auto *grad_data = reinterpret_cast<float *>(_tensor_index_to_gradient[tensor_to_data.first]);
+      auto *calculated_data = reinterpret_cast<float *>(tensor_to_data.second);
+
+      for (uint32_t i = 0; i < flat_size; ++i)
+      {
+        grad_data[i] += calculated_data[i];
+      }
+    }
+  }
+
+  return Ok;
+}
+
+/*
+ * Update weights according to Adam theory:
+ *
+ * w(t + 1) = w(t) - lambda * grad(t) / batch_size
+ */
+OMStatus SGD::updateWeights(const onert_micro::OMTrainingContext &training_config,
+                            core::OMRuntimeContext &context)
+{
+  assert(!_tensor_index_to_gradient.empty());
+  if (_tensor_index_to_gradient.empty())
+    return UnknownError;
+
+  for (auto &tensor_to_data : _tensor_index_to_gradient)
+  {
+    auto tensor = context.getTensorByIndex(tensor_to_data.first);
+    core::OMRuntimeShape shape(tensor);
+
+    const auto flat_size = shape.flatSize();
+
+    auto *grad_data = reinterpret_cast<float *>(tensor_to_data.second);
+    uint8_t *weight_data = nullptr;
+    if (context.getConstDataByTensorIndex(&weight_data, tensor_to_data.first) != Ok)
+      return UnknownError;
+
+    assert(weight_data != nullptr);
+    if (weight_data == nullptr)
+      return UnknownError;
+
+    auto *f_weight_data = reinterpret_cast<float *>(weight_data);
+    float lambda = training_config.learning_rate;
+    const uint32_t batch_size = training_config.batch_size;
+
+    assert(batch_size != 0);
+
+    for (uint32_t i = 0; i < flat_size; ++i)
+    {
+      f_weight_data[i] -= (lambda * grad_data[i]) / (static_cast<float>(batch_size));
+    }
+  }
+  return Ok;
+}
index e849597..68a0334 100644 (file)
@@ -1,6 +1,5 @@
 cmake_minimum_required(VERSION 3.15)
-project(luci_interpreter_micro_standalone)
-
+project(onert_micro_standalone)
 include(${NNAS_ROOT}/infra/onert-micro/utils.cmake)
 
 if (NOT ${NOT_BUILD_EXTERNALS})
@@ -11,4 +10,4 @@ else()
 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)
+add_subdirectory(${NNAS_PROJECT_SOURCE_DIR}/onert-micro/onert-micro ${CMAKE_CURRENT_BINARY_DIR}/onert-micro)
index 1d92825..862488b 100644 (file)
Binary files a/packaging/ABSEIL.tar.gz and b/packaging/ABSEIL.tar.gz differ
index a74fe35..637c20b 100644 (file)
Binary files a/packaging/CPUINFO.tar.gz and b/packaging/CPUINFO.tar.gz differ
diff --git a/packaging/EGL_HEADERS.tar.gz b/packaging/EGL_HEADERS.tar.gz
deleted file mode 100644 (file)
index 8022205..0000000
Binary files a/packaging/EGL_HEADERS.tar.gz and /dev/null differ
index 4bf98d8..9a72157 100644 (file)
Binary files a/packaging/FARMHASH.tar.gz and b/packaging/FARMHASH.tar.gz differ
diff --git a/packaging/FLATBUFFERS-2.0.tar.gz b/packaging/FLATBUFFERS-2.0.tar.gz
deleted file mode 100644 (file)
index 809aca0..0000000
Binary files a/packaging/FLATBUFFERS-2.0.tar.gz and /dev/null differ
diff --git a/packaging/FLATBUFFERS-23.5.26.tar.gz b/packaging/FLATBUFFERS-23.5.26.tar.gz
new file mode 100644 (file)
index 0000000..2068195
Binary files /dev/null and b/packaging/FLATBUFFERS-23.5.26.tar.gz differ
index 78c7876..490d4c1 100644 (file)
Binary files a/packaging/FP16.tar.gz and b/packaging/FP16.tar.gz differ
index 7c1b825..016bc73 100644 (file)
Binary files a/packaging/FXDIV.tar.gz and b/packaging/FXDIV.tar.gz differ
diff --git a/packaging/MLDTYPES.tar.gz b/packaging/MLDTYPES.tar.gz
new file mode 100644 (file)
index 0000000..fca0667
Binary files /dev/null and b/packaging/MLDTYPES.tar.gz differ
diff --git a/packaging/NEON2SSE.tar.gz b/packaging/NEON2SSE.tar.gz
new file mode 100644 (file)
index 0000000..2370bbc
Binary files /dev/null and b/packaging/NEON2SSE.tar.gz differ
diff --git a/packaging/OPENCL_HEADERS.tar.gz b/packaging/OPENCL_HEADERS.tar.gz
deleted file mode 100644 (file)
index 7bc3656..0000000
Binary files a/packaging/OPENCL_HEADERS.tar.gz and /dev/null differ
diff --git a/packaging/OPENGL_HEADERS.tar.gz b/packaging/OPENGL_HEADERS.tar.gz
deleted file mode 100644 (file)
index 53a395a..0000000
Binary files a/packaging/OPENGL_HEADERS.tar.gz and /dev/null differ
index 6cf42c0..254660f 100644 (file)
Binary files a/packaging/PTHREADPOOL.tar.gz and b/packaging/PTHREADPOOL.tar.gz differ
diff --git a/packaging/TENSORFLOW-2.16.1-EIGEN.tar.gz b/packaging/TENSORFLOW-2.16.1-EIGEN.tar.gz
new file mode 100644 (file)
index 0000000..fd810cd
Binary files /dev/null and b/packaging/TENSORFLOW-2.16.1-EIGEN.tar.gz differ
diff --git a/packaging/TENSORFLOW-2.16.1-GEMMLOWP.tar.gz b/packaging/TENSORFLOW-2.16.1-GEMMLOWP.tar.gz
new file mode 100644 (file)
index 0000000..9ea656a
Binary files /dev/null and b/packaging/TENSORFLOW-2.16.1-GEMMLOWP.tar.gz differ
diff --git a/packaging/TENSORFLOW-2.16.1-RUY.tar.gz b/packaging/TENSORFLOW-2.16.1-RUY.tar.gz
new file mode 100644 (file)
index 0000000..f1a448c
Binary files /dev/null and b/packaging/TENSORFLOW-2.16.1-RUY.tar.gz differ
diff --git a/packaging/TENSORFLOW-2.16.1.tar.gz b/packaging/TENSORFLOW-2.16.1.tar.gz
new file mode 100644 (file)
index 0000000..d68fce2
Binary files /dev/null and b/packaging/TENSORFLOW-2.16.1.tar.gz differ
diff --git a/packaging/TENSORFLOW-2.8.0-EIGEN.tar.gz b/packaging/TENSORFLOW-2.8.0-EIGEN.tar.gz
deleted file mode 100644 (file)
index 94a307f..0000000
Binary files a/packaging/TENSORFLOW-2.8.0-EIGEN.tar.gz and /dev/null differ
diff --git a/packaging/TENSORFLOW-2.8.0-GEMMLOWP.tar.gz b/packaging/TENSORFLOW-2.8.0-GEMMLOWP.tar.gz
deleted file mode 100644 (file)
index c76e088..0000000
Binary files a/packaging/TENSORFLOW-2.8.0-GEMMLOWP.tar.gz and /dev/null differ
diff --git a/packaging/TENSORFLOW-2.8.0-RUY.tar.gz b/packaging/TENSORFLOW-2.8.0-RUY.tar.gz
deleted file mode 100644 (file)
index 8e67347..0000000
Binary files a/packaging/TENSORFLOW-2.8.0-RUY.tar.gz and /dev/null differ
diff --git a/packaging/TENSORFLOW-2.8.0.tar.gz b/packaging/TENSORFLOW-2.8.0.tar.gz
deleted file mode 100644 (file)
index f0f7425..0000000
Binary files a/packaging/TENSORFLOW-2.8.0.tar.gz and /dev/null differ
diff --git a/packaging/VULKAN.tar.gz b/packaging/VULKAN.tar.gz
deleted file mode 100644 (file)
index 64ae0bd..0000000
Binary files a/packaging/VULKAN.tar.gz and /dev/null differ
index 2a1ce8e..b62a3ff 100644 (file)
Binary files a/packaging/XNNPACK.tar.gz and b/packaging/XNNPACK.tar.gz differ
index a972af3..c25bdbe 100644 (file)
@@ -1,6 +1,6 @@
 Name:    nnfw
 Summary: nnfw
-Version: 1.25.0
+Version: 1.28.0
 Release: 1
 Group:   Development
 License: Apache-2.0 and MIT and BSD-2-Clause and MPL-2.0
@@ -12,26 +12,23 @@ Source2001: nnfw.pc.in
 Source2002: nnfw-plugin.pc.in
 Source3001: ABSEIL.tar.gz
 Source3002: CPUINFO.tar.gz
-Source3003: EGL_HEADERS.tar.gz
-Source3004: FARMHASH.tar.gz
+Source3003: FARMHASH.tar.gz
+Source3004: FLATBUFFERS-23.5.26.tar.gz
 Source3005: FP16.tar.gz
 Source3006: FXDIV.tar.gz
-Source3007: GEMMLOWP.tar.gz
-Source3008: OOURAFFT.tar.gz
-Source3009: OPENCL_HEADERS.tar.gz
-Source3010: OPENGL_HEADERS.tar.gz
-Source3011: PSIMD.tar.gz
-Source3012: PTHREADPOOL.tar.gz
-Source3013: TENSORFLOW-2.8.0-EIGEN.tar.gz
-Source3014: TENSORFLOW-2.8.0-GEMMLOWP.tar.gz
-Source3015: TENSORFLOW-2.8.0-RUY.tar.gz
-Source3016: TENSORFLOW-2.8.0.tar.gz
-Source3017: VULKAN.tar.gz
-Source3018: XNNPACK.tar.gz
-Source3019: FLATBUFFERS-2.0.tar.gz
+Source3007: MLDTYPES.tar.gz
+Source3008: NEON2SSE.tar.gz
+Source3009: OOURAFFT.tar.gz
+Source3010: PSIMD.tar.gz
+Source3011: PTHREADPOOL.tar.gz
+Source3012: TENSORFLOW-2.16.1-EIGEN.tar.gz
+Source3013: TENSORFLOW-2.16.1-GEMMLOWP.tar.gz
+Source3014: TENSORFLOW-2.16.1-RUY.tar.gz
+Source3015: TENSORFLOW-2.16.1.tar.gz
+Source3016: XNNPACK.tar.gz
 
 %{!?build_type:     %define build_type      Release}
-%{!?npud_build:     %define npud_build      1}
+%{!?npud_build:     %define npud_build      0}
 %{!?trix_support:   %define trix_support    1}
 %{!?odc_build:      %define odc_build       1}
 %{!?coverage_build: %define coverage_build  0}
@@ -48,6 +45,12 @@ Source3019: FLATBUFFERS-2.0.tar.gz
 %define test_build 1
 %endif
 
+%ifarch riscv64
+# Disable npud on risc-v
+# TODO Enable on risc-v
+%define npud_build 0
+%endif
+
 BuildRequires:  cmake
 
 Requires(post): /sbin/ldconfig
@@ -56,7 +59,7 @@ Requires(postun): /sbin/ldconfig
 %if %{test_build} == 1
 BuildRequires:  pkgconfig(boost)
 BuildRequires:  pkgconfig(tensorflow2-lite)
-BuildRequires:  hdf5-devel
+BuildRequires:  hdf5-devel-static
 BuildRequires:  libaec-devel
 BuildRequires:  pkgconfig(zlib)
 BuildRequires:  pkgconfig(libjpeg)
@@ -136,6 +139,9 @@ NPU daemon for optimal management of NPU hardware
 %ifarch %ix86
 %define target_arch i686
 %endif
+%ifarch riscv64
+%define target_arch riscv64
+%endif
 
 %define install_dir %{_prefix}
 %define install_path %{buildroot}%{install_dir}
@@ -178,6 +184,11 @@ NPU daemon for optimal management of NPU hardware
         -DEXTERNALS_BUILD_THREAD=%{nproc} -DBUILD_MINIMAL_SAMPLE=ON -DNNFW_OVERLAY_DIR=$(pwd)/%{overlay_path} \\\
         %{option_test} %{option_coverage} %{option_config} %{extra_option}
 
+%define strip_options %{nil}
+%if %{build_type} == "Release"
+%define strip_options --strip
+%endif
+
 %prep
 %setup -q
 cp %{SOURCE1} .
@@ -199,33 +210,32 @@ tar -xf %{SOURCE3013} -C ./externals
 tar -xf %{SOURCE3014} -C ./externals
 tar -xf %{SOURCE3015} -C ./externals
 tar -xf %{SOURCE3016} -C ./externals
-tar -xf %{SOURCE3017} -C ./externals
-tar -xf %{SOURCE3018} -C ./externals
-tar -xf %{SOURCE3019} -C ./externals
 
 %build
-%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86
+%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86 riscv64
 # 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 \
+%{nncc_env} ./nncc configure -DBUILD_GTEST=OFF -DENABLE_TEST=OFF -DEXTERNALS_BUILD_THREADS=%{nproc} -DCMAKE_BUILD_TYPE=%{build_type} -DTARGET_ARCH=%{target_arch} -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"
+       -DBUILD_WHITELIST="luci;foder;pepper-csv2vec;loco;locop;logo;logo-core;mio-circle08;luci-compute;oops;hermes;hermes-std;angkor;pp;pepper-strcast;pepper-str"
 %{nncc_env} ./nncc build %{build_jobs}
-cmake --install %{nncc_workspace}
+cmake --install %{nncc_workspace} %{strip_options}
 %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
+mkdir -p %{overlay_path}/include/luci/IR
 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
+cp compiler/luci/lang/include/luci/IR/CircleNodes.lst %{overlay_path}/include/luci/IR
 
 # runtime build
 %{build_env} ./nnfw configure %{build_options}
 %{build_env} ./nnfw build %{build_jobs}
 # install in workspace
 # TODO Set install path
-%{build_env} ./nnfw install
+%{build_env} ./nnfw install --prefix %{nnfw_workspace}/out %{strip_options}
 
 %if %{test_build} == 1
 %if %{coverage_build} == 1
@@ -236,12 +246,15 @@ tar -zcf test-suite.tar.gz infra/scripts
 %endif # arm armv7l armv7hl aarch64
 
 %install
-%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86
+%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86 riscv64
 
-mkdir -p %{buildroot}%{_libdir}
+mkdir -p %{buildroot}%{_libdir}/nnfw/backend
+mkdir -p %{buildroot}%{_libdir}/nnfw/loader
 mkdir -p %{buildroot}%{_bindir}
 mkdir -p %{buildroot}%{_includedir}
 install -m 644 build/out/lib/*.so %{buildroot}%{_libdir}
+install -m 644 build/out/lib/nnfw/backend/*.so %{buildroot}%{_libdir}/nnfw/backend
+install -m 644 build/out/lib/nnfw/loader/*.so %{buildroot}%{_libdir}/nnfw/loader
 install -m 755 build/out/bin/onert-minimal-app %{buildroot}%{_bindir}
 cp -r build/out/include/* %{buildroot}%{_includedir}/
 
@@ -310,15 +323,17 @@ install -m 755 build/out/npud-gtest/* %{test_install_path}/npud-gtest
 %files
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
-%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86
+%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86 riscv64
 %{_libdir}/*.so
+%{_libdir}/nnfw/backend/*.so
+%{_libdir}/nnfw/loader/*.so
 %exclude %{_includedir}/CL/*
 %endif
 
 %files devel
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
-%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86
+%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86 riscv64
 %dir %{_includedir}/nnfw
 %{_includedir}/nnfw/*
 %{_libdir}/pkgconfig/nnfw.pc
@@ -327,13 +342,13 @@ install -m 755 build/out/npud-gtest/* %{test_install_path}/npud-gtest
 %files plugin-devel
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
-%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86
+%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86 riscv64
 %dir %{_includedir}/onert
 %{_includedir}/onert/*
 %{_libdir}/pkgconfig/nnfw-plugin.pc
 %endif
 
-%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86
+%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86 riscv64
 %files minimal-app
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
@@ -354,7 +369,7 @@ install -m 755 build/out/npud-gtest/* %{test_install_path}/npud-gtest
 %files npud
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
-%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86
+%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86 riscv64
 %{_bindir}/npud
 %endif # arm armv7l armv7hl aarch64 x86_64 %ix86
 %endif # npud_build
@@ -363,7 +378,7 @@ install -m 755 build/out/npud-gtest/* %{test_install_path}/npud-gtest
 %files odc
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
-%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86
+%ifarch arm armv7l armv7hl aarch64 x86_64 %ix86 riscv64
 %dir %{_libdir}/nnfw/odc
 %{_libdir}/nnfw/odc/*
 %endif # arm armv7l armv7hl aarch64 x86_64 %ix86
diff --git a/res/CircleRecipes/CircleBatchMatMul_I4_000/test.recipe b/res/CircleRecipes/CircleBatchMatMul_I4_000/test.recipe
new file mode 100644 (file)
index 0000000..295d7cf
--- /dev/null
@@ -0,0 +1,39 @@
+# This recipe is just to check processing of INT4 models.
+# do not run this model in any interpreter or runtime as it may throw an error.
+operand {
+  name: "ifm1"
+  type: INT4
+  shape { dim: 1 dim: 1 dim: 4 dim: 4 }
+  quant { min: -8 max: 7 scale: 1.0 zero_point: 0 }
+}
+operand {
+  name: "ifm2"
+  type: INT4
+  shape { dim: 1 dim: 1 dim: 4 dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "-8" arg: "-7" arg: "-6" arg: "-5"
+    arg: "-4" arg: "-3" arg: "-2" arg: "-1"
+    arg: "0" arg: "1" arg: "2" arg: "3"
+    arg: "4" arg: "5" arg: "6" arg: "7"
+  }
+  quant { min: -8 max: 7 scale: 1.0 zero_point: 0 }
+}
+operand {
+  name: "ofm"
+  type: INT4
+  shape { dim: 1 dim: 1 dim: 4 dim: 4 }
+  quant { min: -8 max: 7 scale: 1.0 zero_point: 0 }
+}
+operation {
+  type: "BatchMatMul"
+  input: "ifm1"
+  input: "ifm2"
+  output: "ofm"
+  batch_matmul_options {
+    adjoint_lhs: false
+    adjoint_rhs: false
+  }
+}
+input: "ifm1"
+output: "ofm"
diff --git a/res/CircleRecipes/CircleBatchMatMul_U4_000/test.recipe b/res/CircleRecipes/CircleBatchMatMul_U4_000/test.recipe
new file mode 100644 (file)
index 0000000..4bdf5a7
--- /dev/null
@@ -0,0 +1,39 @@
+# This recipe is just to check processing of UINT4 models.
+# do not run this model in any interpreter or runtime as it may throw an error.
+operand {
+  name: "ifm1"
+  type: UINT4
+  shape { dim: 1 dim: 1 dim: 4 dim: 4 }
+  quant { min: 0 max: 15 scale: 1.0 zero_point: 8 }
+}
+operand {
+  name: "ifm2"
+  type: UINT4
+  shape { dim: 1 dim: 1 dim: 4 dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "0" arg: "1" arg: "2" arg: "3"
+    arg: "4" arg: "5" arg: "6" arg: "7"
+    arg: "8" arg: "9" arg: "10" arg: "11"
+    arg: "12" arg: "13" arg: "14" arg: "15"
+  }
+  quant { min: 0 max: 15 scale: 1.0 zero_point: 8 }
+}
+operand {
+  name: "ofm"
+  type: UINT4
+  shape { dim: 1 dim: 1 dim: 4 dim: 4 }
+  quant { min: 0 max: 15 scale: 1.0 zero_point: 8 }
+}
+operation {
+  type: "BatchMatMul"
+  input: "ifm1"
+  input: "ifm2"
+  output: "ofm"
+  batch_matmul_options {
+    adjoint_lhs: false
+    adjoint_rhs: false
+  }
+}
+input: "ifm1"
+output: "ofm"
diff --git a/res/CircleRecipes/CircleFullyConnected_U4_000/test.recipe b/res/CircleRecipes/CircleFullyConnected_U4_000/test.recipe
new file mode 100644 (file)
index 0000000..b5b9e3c
--- /dev/null
@@ -0,0 +1,45 @@
+# This recipe is just to check processing of UINT4 models.
+# do not run this model in any interpreter or runtime as it may throw an error.
+operand {
+  name: "in"
+  type: UINT4
+  shape { dim: 1 dim: 4 }
+}
+operand {
+  name: "weight"
+  type: UINT4
+  shape { dim: 4 dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "0" arg: "1" arg: "2" arg: "3"
+    arg: "4" arg: "5" arg: "6" arg: "7"
+    arg: "8" arg: "9" arg: "10" arg: "11"
+    arg: "12" arg: "13" arg: "14" arg: "15"
+  }
+}
+operand {
+  name: "bias"
+  type: UINT4
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "0" arg: "1" arg: "1" arg: "3"
+  }
+}
+operand {
+  name: "out"
+  type: UINT4
+  shape { dim: 1 dim: 4 }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+  }
+  input: "in"
+  input: "weight"
+  input: "bias"
+  output: "out"
+}
+input: "in"
+output: "out"
diff --git a/res/CircleRecipes/CircleFullyConnected_U4_001/test.recipe b/res/CircleRecipes/CircleFullyConnected_U4_001/test.recipe
new file mode 100644 (file)
index 0000000..2501c85
--- /dev/null
@@ -0,0 +1,49 @@
+# This recipe is just to check processing of UINT4 models.
+# do not run this model in any interpreter or runtime as it may throw an error.
+operand {
+  name: "in"
+  type: UINT4
+  shape { dim: 1 dim: 4 }
+  quant { min: 0 max: 15 scale: 1.0 zero_point: 8 }
+}
+operand {
+  name: "weight"
+  type: UINT4
+  shape { dim: 4 dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "0" arg: "1" arg: "2" arg: "3"
+    arg: "4" arg: "5" arg: "6" arg: "7"
+    arg: "8" arg: "9" arg: "10" arg: "11"
+    arg: "12" arg: "13" arg: "14" arg: "15"
+  }
+  quant { min: 0 max: 15 scale: 1.0 zero_point: 8 }
+}
+operand {
+  name: "bias"
+  type: UINT4
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "0" arg: "1" arg: "1" arg: "3"
+  }
+  quant { min: 0 max: 15 scale: 1.0 zero_point: 8 }
+}
+operand {
+  name: "out"
+  type: UINT4
+  shape { dim: 1 dim: 4 }
+  quant { min: 0 max: 15 scale: 1.0 zero_point: 8 }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+  }
+  input: "in"
+  input: "weight"
+  input: "bias"
+  output: "out"
+}
+input: "in"
+output: "out"
diff --git a/res/CircleRecipes/CircleFullyConnected_U4_002/ref.input0 b/res/CircleRecipes/CircleFullyConnected_U4_002/ref.input0
new file mode 100644 (file)
index 0000000..3be2f57
--- /dev/null
@@ -0,0 +1,3 @@
+2,4
+float32
+0.45845914,0.59502566,0.012643684,0.9902574,0.083512,0.06890562,0.49019852,0.56146705
diff --git a/res/CircleRecipes/CircleFullyConnected_U4_002/ref.output0 b/res/CircleRecipes/CircleFullyConnected_U4_002/ref.output0
new file mode 100644 (file)
index 0000000..e5a4ade
--- /dev/null
@@ -0,0 +1,3 @@
+2,4
+float32
+-11.873346,-3.6393948,4.5945563,12.828507,-5.9188657,-1.0911331,3.7365992,8.564331
diff --git a/res/CircleRecipes/CircleFullyConnected_U4_002/test.recipe b/res/CircleRecipes/CircleFullyConnected_U4_002/test.recipe
new file mode 100644 (file)
index 0000000..44f4418
--- /dev/null
@@ -0,0 +1,44 @@
+operand {
+  name: "in"
+  type: FLOAT32
+  shape { dim: 2 dim: 4 }
+}
+operand {
+  name: "weight"
+  type: UINT4
+  shape { dim: 4 dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "0" arg: "1" arg: "2" arg: "3"
+    arg: "4" arg: "5" arg: "6" arg: "7"
+    arg: "8" arg: "9" arg: "10" arg: "11"
+    arg: "12" arg: "13" arg: "14" arg: "15"
+  }
+  quant { min: 0 max: 15 scale: 1.0 zero_point: 8 }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "1.0" arg: "1.0" arg: "1.0" arg: "1.0"
+  }
+}
+operand {
+  name: "out"
+  type: FLOAT32
+  shape { dim: 2 dim: 4 }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+  }
+  input: "in"
+  input: "weight"
+  input: "bias"
+  output: "out"
+}
+input: "in"
+output: "out"
diff --git a/res/CircleRecipes/GRU_000/test.recipe b/res/CircleRecipes/GRU_000/test.recipe
new file mode 100644 (file)
index 0000000..3ef639b
--- /dev/null
@@ -0,0 +1,77 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 2 }
+}
+operand {
+  name: "hidden_hidden"
+  type: FLOAT32
+  shape { dim: 12 dim: 4 }
+  filler {
+      tag: "gaussian"
+      arg: "0.0"
+      arg: "1.0"
+  }
+}
+operand {
+  name: "hidden_hidden_bias"
+  type: FLOAT32
+  shape { dim: 12 }
+  filler {
+      tag: "gaussian"
+      arg: "0.0"
+      arg: "1.0"
+  }
+}
+operand {
+  name: "hidden_input"
+  type: FLOAT32
+  shape { dim: 12 dim: 2 }
+  filler {
+      tag: "gaussian"
+      arg: "0.0"
+      arg: "1.0"
+  }
+}
+operand {
+  name: "hidden_input_bias"
+  type: FLOAT32
+  shape { dim: 12 }
+  filler {
+      tag: "gaussian"
+      arg: "0.0"
+      arg: "1.0"
+  }
+}
+operand {
+  name: "state"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 }
+  filler {
+      tag: "gaussian"
+      arg: "0.0"
+      arg: "1.0"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 4 }
+}
+operation {
+  type: "GRU"
+  gru_options {
+    activation: NONE
+    return_sequences: false
+    time_major: false
+  }
+  input: "ifm"
+  input: "hidden_hidden"
+  input: "hidden_hidden_bias"
+  input: "hidden_input"
+  input: "hidden_input_bias"
+  input: "state"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/CircleRecipes/GRU_000/test.reverse b/res/CircleRecipes/GRU_000/test.reverse
new file mode 100644 (file)
index 0000000..e69de29
index cdc1036..1630bac 100644 (file)
@@ -84,8 +84,12 @@ table QuantizationParameters {
   // 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.
+  // NOTE min/max values are valid if
+  // 1. length of min/max == 0 or
+  // 2. length of min/max == length of scale/zero_point
+  // Otherwise, min/max are not valid (undefined behavior).
+  min:[float];
+  max:[float];
   scale:[float];  // For dequantizing the tensor's values.
   zero_point:[long];
 
diff --git a/res/CircleSchema/0.7/circle_schema.fbs b/res/CircleSchema/0.7/circle_schema.fbs
new file mode 100644 (file)
index 0000000..c132c89
--- /dev/null
@@ -0,0 +1,1685 @@
+// 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.
+// Version 0.7: Base up to TensorFlow Lite v2.15.0 schema, deprecate data_format in Subgraph table
+
+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.
+  // NOTE min/max values are valid if
+  // 1. length of min/max == 0 or
+  // 2. length of min/max == length of scale/zero_point
+  // Otherwise, min/max are not valid (undefined behavior).
+  min:[float];
+  max:[float];
+  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.
+
+  // This field is added to distinguish between scalars and tensors of unknown
+  // ranks (both of which shape is []).
+  // For scalars (rank = 0), shape = [] and has_rank = true.
+  // For tensors with known rank (rank > 0) and shape, shape = [...] and
+  // has_rank = true.
+  // For tensors with unknown rank and shape, shape = [] and has_rank = false.
+  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,
+  // All Operators start with STABLEHLO_ prefixes are subject to change
+  // Many of the ops below can not be executed by runtime
+  STABLEHLO_LOGISTIC = 162, // WARNING: Do not have runtime support
+  STABLEHLO_ADD = 163, // WARNING: No runtime support yet
+  STABLEHLO_DIVIDE = 164, // WARNING: No runtime support yet
+  STABLEHLO_MULTIPLY = 165, // WARNING: No runtime support yet
+  STABLEHLO_MAXIMUM = 166, // WARNING: No runtime support yet
+  STABLEHLO_RESHAPE = 167, // WARNING: No runtime support yet
+  STABLEHLO_CLAMP = 168, // WARNING: No runtime support
+  STABLEHLO_CONCATENATE = 169, // WARNING: No runtime support
+  STABLEHLO_BROADCAST_IN_DIM = 170, // WARNING: No runtime support
+  STABLEHLO_CONVOLUTION = 171, // WARNING: No runtime support
+  STABLEHLO_SLICE = 172, // WARNING: No runtime support
+  STABLEHLO_CUSTOM_CALL = 173, // WARNING: No runtime support
+  STABLEHLO_REDUCE = 174, // WARNING: No runtime support
+  STABLEHLO_ABS = 175, // WARNING: No runtime support
+  STABLEHLO_AND = 176, // WARNING: No runtime support
+  STABLEHLO_COSINE = 177, // WARNING: No runtime support
+  STABLEHLO_EXPONENTIAL = 178, // WARNING: No runtime support
+  STABLEHLO_FLOOR = 179, // WARNING: No runtime support
+  STABLEHLO_LOG = 180, // WARNING: No runtime support
+  STABLEHLO_MINIMUM = 181, // WARNING: No runtime support
+  STABLEHLO_NEGATE = 182, // WARNING: No runtime support
+  STABLEHLO_OR = 183, // WARNING: No runtime support
+  STABLEHLO_POWER = 184, // WARNING: No runtime support
+  STABLEHLO_REMAINDER = 185, // WARNING: No runtime support
+  STABLEHLO_RSQRT = 186, // WARNING: No runtime support
+  STABLEHLO_SELECT = 187, // WARNING: No runtime support
+  STABLEHLO_SUBTRACT = 188, // WARNING: No runtime support
+  STABLEHLO_TANH = 189, // WARNING: No runtime support
+  STABLEHLO_SCATTER = 190,
+  STABLEHLO_COMPARE = 191, // WARNING: No runtime support
+  STABLEHLO_CONVERT = 192, // WARNING: No runtime support
+  STABLEHLO_DYNAMIC_SLICE = 193, // WARNING: No runtime support
+  STABLEHLO_DYNAMIC_UPDATE_SLICE = 194, // WARNING: No runtime support
+  STABLEHLO_PAD = 195, // WARNING: No runtime support
+  STABLEHLO_IOTA = 196, // WARNING: No runtime support
+  STABLEHLO_DOT_GENERAL = 197, // WARNING: No runtime support
+  STABLEHLO_REDUCE_WINDOW = 198, // WARNING: No runtime support
+  STABLEHLO_SORT = 199, // WARNING: No runtime support
+  STABLEHLO_WHILE = 200, // WARNING: No runtime support
+  STABLEHLO_GATHER = 201, // WARNING: No runtime support
+  STABLEHLO_TRANSPOSE = 202, // WARNING: No runtime support
+  DILATE = 203,
+  STABLEHLO_RNG_BIT_GENERATOR = 204,
+  REDUCE_WINDOW = 205,
+}
+// 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,
+}
+
+union BuiltinOptions2{
+  StablehloConcatenateOptions,
+  StablehloBroadcastInDimOptions,
+  StablehloSliceOptions,
+  StablehloConvolutionOptions,
+  StablehloCustomCallOptions,
+  StablehloReduceOptions,
+  StablehloScatterOptions,
+  StablehloCompareOptions,
+  StablehloDynamicSliceOptions,
+  StablehloPadOptions,
+  StablehloIotaOptions,
+  StablehloDotGeneralOptions,
+  StablehloReduceWindowOptions,
+  StablehloSortOptions,
+  StablehloWhileOptions,
+  StablehloGatherOptions,
+  StablehloTransposeOptions,
+  DilateOptions,
+  StablehloRngBitGeneratorOptions,
+  ReduceWindowOptions,
+}
+
+table StablehloGatherOptions{
+  offset_dims : [long];
+  collapsed_slice_dims : [long];
+  start_index_map : [long];
+  index_vector_dim : long;
+  slice_sizes : [long];
+  indices_are_sorted : bool;
+}
+
+table StablehloTransposeOptions{
+  permutation : [long];
+}
+
+enum StablehloPrecisionConfig : uint {
+  DEFAULT,
+  HIGH,
+  HIGHEST,
+}
+
+table StablehloDotGeneralOptions{
+  lhs_batching_dimensions : [long];
+  rhs_batching_dimensions : [long];
+  lhs_contracting_dimensions : [long];
+  rhs_contracting_dimensions : [long];
+  precision_config : [StablehloPrecisionConfig];
+}
+
+table StablehloReduceWindowOptions{
+  window_dimensions : [long];
+  window_strides : [long];
+  base_dilations : [long];
+  window_dilations : [long];
+  padding : [long];
+  body_subgraph_index : int;
+}
+
+table StablehloWhileOptions{
+  cond_subgraph_index : int;
+  body_subgraph_index : int;
+}
+
+table StablehloSortOptions{
+  dimension : long;
+  is_stable : bool;
+  comparator_subgraph_index : int;
+}
+
+table StablehloConcatenateOptions {
+  dimension : long;
+}
+
+table StablehloBroadcastInDimOptions{
+  broadcast_dimensions : [long];
+}
+
+enum StablehloComparisonDirection : uint {
+  STABLEHLO_COMPARISON_DIRECTION_EQ,
+  STABLEHLO_COMPARISON_DIRECTION_NE,
+  STABLEHLO_COMPARISON_DIRECTION_GE,
+  STABLEHLO_COMPARISON_DIRECTION_GT,
+  STABLEHLO_COMPARISON_DIRECTION_LE,
+  STABLEHLO_COMPARISON_DIRECTION_LT,
+
+}
+
+enum StablehloComparisonType : uint {
+  STABLEHLO_COMPARISON_TYPE_NOTYPE,
+  STABLEHLO_COMPARISON_TYPE_FLOAT,
+  STABLEHLO_COMPARISON_TYPE_FLOAT_TOTAL_ORDER,
+  STABLEHLO_COMPARISON_TYPE_SIGNED,
+  STABLEHLO_COMPARISON_TYPE_UNSIGNED,
+}
+
+table StablehloCompareOptions{
+  comparison_direction : StablehloComparisonDirection;
+  compare_type : StablehloComparisonType;
+}
+
+table StablehloDynamicSliceOptions{
+  slice_sizes : [long];
+}
+
+table StablehloPadOptions{
+  edge_padding_low : [long];
+  edge_padding_high : [long];
+  interior_padding : [long];
+}
+
+table StablehloIotaOptions{
+  iota_dimension : long;
+}
+
+table StablehloCustomCallOptions {
+  call_target_name : string;
+  has_side_effect : bool;
+  backend_config: string;
+  api_version : int; // will be decprecated
+  called_computations: [int]; // should point to subgraphs of the computations
+  custom_attributes : [ubyte];
+}
+
+table StablehloReduceOptions {
+  dimensions : [long];
+  body_subgraph_index : int;
+}
+
+table StablehloSliceOptions{
+  start_indices : [long];
+  limit_indices : [long];
+  strides : [long];
+}
+
+table StablehloConvolutionOptions{
+  window_strides : [long];
+  padding : [long];
+  lhs_dilation : [long];
+  rhs_dilation : [long];
+  window_reversal : [bool];
+  input_batch_dimension : long;
+  input_feature_dimension : long;
+  input_spatial_dimensions : [long];
+  kernel_input_feature_dimension : long;
+  kernel_output_feature_dimension : long;
+  kernel_spatial_dimensions : [long];
+  output_batch_dimension : long;
+  output_feature_dimension : long;
+  output_spatial_dimensions    : [long];
+  feature_group_count : long;
+  batch_group_count : long;
+  precision_config : [StablehloPrecisionConfig];
+}
+
+table StablehloScatterOptions {
+  indices_are_sorted: bool;
+  update_window_dims: [long];
+  inserted_window_dims: [long];
+  scatter_dims_to_operand_dims: [long];
+  index_vector_dim: long;
+  unique_indices: bool;
+  update_computation_subgraph_index: int;
+}
+
+enum RngAlgorithm : byte {
+  // An algorithm auto-selected by the system according to device type.
+  DEFAULT = 0,
+  // The Philox algorithm, as described in paper
+  // ['Parallel Random Numbers: As Easy as 1, 2, 3']
+  // (https://www.thesalmons.org/john/random123/papers/random123sc11.pdf)
+  PHILOX = 1,
+  // The ThreeFry algorithm, as described in paper
+  // ['Parallel Random Numbers: As Easy as 1, 2, 3']
+  // (https://www.thesalmons.org/john/random123/papers/random123sc11.pdf)
+  THREEFRY = 2,
+}
+
+table StablehloRngBitGeneratorOptions {
+  algorithm:RngAlgorithm;
+}
+
+// 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;
+  // Parameters for Conv2D version 8 or above.
+  // When set, quantized_bias_type defines the dtype for both bias and accumulator.
+  quantized_bias_type: TensorType;
+}
+
+// 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,
+  SHUFFLED16x1FLOAT32 = 127
+}
+// 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;
+
+  // Parameters for FullyConnected version 11 or above.
+  // When set, quantized_bias_type defines the dtype for both bias and accumulator.
+  quantized_bias_type: TensorType;
+}
+
+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;
+  // If true, then the end tensor is an offset of the begin tensor.
+  offset: bool;
+}
+
+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;
+
+  // Parameters for TransposeConv version 5 or above.
+  // If set, use this for bias and accumulator.
+  // When set, quantized_bias_type defines the dtype for both bias and accumulator.
+  quantized_bias_type: TensorType;
+}
+
+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 {
+  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 DilateOptions {
+}
+
+enum ReduceWindowFunction : int {
+  UNSUPPORTED,
+  ADD,
+  MUL,
+  MINIMUM,
+  MAXIMUM,
+  ALL,
+  ANY,
+}
+
+table ReduceWindowOptions{
+  reduce_function: ReduceWindowFunction;
+}
+
+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];
+
+  // When an op is using custom_options in a model that is larger than 2GB, then
+  // we instead use the following attributes to find the buffer location which
+  // is stored outside of flatbuffers, the offset is calculated relative to the
+  // beginning of the file and is only valid if > 1
+  large_custom_options_offset: ulong;
+  large_custom_options_size: ulong;
+
+  // Flatbuffers union struct has a 128 elements limit in JAVA, so a second
+  // union is added, in the case of where BuitlinOptions2 runs out, a third
+  // one can be added
+  builtin_options_2 : BuiltinOptions2;
+}
+
+// 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, deprecated
+  deprecated_data_format: DataFormat (deprecated);
+}
+
+// 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);
+
+  // In a model that is larger than 2GB, then buffers instead uses the following
+  // attributes to find stored data, which is outside of flatbuffers
+  // the offset is calculated relative to the beginning of the file and is only
+  // valid if > 1.
+  offset: ulong;
+  size: ulong;
+}
+
+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.8/circle_schema.fbs b/res/CircleSchema/0.8/circle_schema.fbs
new file mode 100644 (file)
index 0000000..460fa43
--- /dev/null
@@ -0,0 +1,1695 @@
+// 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.
+// Version 0.7: Base up to TensorFlow Lite v2.15.0 schema, deprecate data_format in Subgraph table
+// Version 0.8: GRU op is added. UINT4 is added.
+
+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 {
+  UINT4 = -1,
+  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.
+  // NOTE min/max values are valid if
+  // 1. length of min/max == 0 or
+  // 2. length of min/max == length of scale/zero_point
+  // Otherwise, min/max are not valid (undefined behavior).
+  min:[float];
+  max:[float];
+  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.
+
+  // This field is added to distinguish between scalars and tensors of unknown
+  // ranks (both of which shape is []).
+  // For scalars (rank = 0), shape = [] and has_rank = true.
+  // For tensors with known rank (rank > 0) and shape, shape = [...] and
+  // has_rank = true.
+  // For tensors with unknown rank and shape, shape = [] and has_rank = false.
+  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 {
+  GRU = -5,
+  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,
+  // All Operators start with STABLEHLO_ prefixes are subject to change
+  // Many of the ops below can not be executed by runtime
+  STABLEHLO_LOGISTIC = 162, // WARNING: Do not have runtime support
+  STABLEHLO_ADD = 163, // WARNING: No runtime support yet
+  STABLEHLO_DIVIDE = 164, // WARNING: No runtime support yet
+  STABLEHLO_MULTIPLY = 165, // WARNING: No runtime support yet
+  STABLEHLO_MAXIMUM = 166, // WARNING: No runtime support yet
+  STABLEHLO_RESHAPE = 167, // WARNING: No runtime support yet
+  STABLEHLO_CLAMP = 168, // WARNING: No runtime support
+  STABLEHLO_CONCATENATE = 169, // WARNING: No runtime support
+  STABLEHLO_BROADCAST_IN_DIM = 170, // WARNING: No runtime support
+  STABLEHLO_CONVOLUTION = 171, // WARNING: No runtime support
+  STABLEHLO_SLICE = 172, // WARNING: No runtime support
+  STABLEHLO_CUSTOM_CALL = 173, // WARNING: No runtime support
+  STABLEHLO_REDUCE = 174, // WARNING: No runtime support
+  STABLEHLO_ABS = 175, // WARNING: No runtime support
+  STABLEHLO_AND = 176, // WARNING: No runtime support
+  STABLEHLO_COSINE = 177, // WARNING: No runtime support
+  STABLEHLO_EXPONENTIAL = 178, // WARNING: No runtime support
+  STABLEHLO_FLOOR = 179, // WARNING: No runtime support
+  STABLEHLO_LOG = 180, // WARNING: No runtime support
+  STABLEHLO_MINIMUM = 181, // WARNING: No runtime support
+  STABLEHLO_NEGATE = 182, // WARNING: No runtime support
+  STABLEHLO_OR = 183, // WARNING: No runtime support
+  STABLEHLO_POWER = 184, // WARNING: No runtime support
+  STABLEHLO_REMAINDER = 185, // WARNING: No runtime support
+  STABLEHLO_RSQRT = 186, // WARNING: No runtime support
+  STABLEHLO_SELECT = 187, // WARNING: No runtime support
+  STABLEHLO_SUBTRACT = 188, // WARNING: No runtime support
+  STABLEHLO_TANH = 189, // WARNING: No runtime support
+  STABLEHLO_SCATTER = 190,
+  STABLEHLO_COMPARE = 191, // WARNING: No runtime support
+  STABLEHLO_CONVERT = 192, // WARNING: No runtime support
+  STABLEHLO_DYNAMIC_SLICE = 193, // WARNING: No runtime support
+  STABLEHLO_DYNAMIC_UPDATE_SLICE = 194, // WARNING: No runtime support
+  STABLEHLO_PAD = 195, // WARNING: No runtime support
+  STABLEHLO_IOTA = 196, // WARNING: No runtime support
+  STABLEHLO_DOT_GENERAL = 197, // WARNING: No runtime support
+  STABLEHLO_REDUCE_WINDOW = 198, // WARNING: No runtime support
+  STABLEHLO_SORT = 199, // WARNING: No runtime support
+  STABLEHLO_WHILE = 200, // WARNING: No runtime support
+  STABLEHLO_GATHER = 201, // WARNING: No runtime support
+  STABLEHLO_TRANSPOSE = 202, // WARNING: No runtime support
+  DILATE = 203,
+  STABLEHLO_RNG_BIT_GENERATOR = 204,
+  REDUCE_WINDOW = 205,
+}
+// 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,
+  GRUOptions = 251,
+  BCQGatherOptions = 252,
+  BCQFullyConnectedOptions = 253,
+  InstanceNormOptions = 254,
+}
+
+union BuiltinOptions2{
+  StablehloConcatenateOptions,
+  StablehloBroadcastInDimOptions,
+  StablehloSliceOptions,
+  StablehloConvolutionOptions,
+  StablehloCustomCallOptions,
+  StablehloReduceOptions,
+  StablehloScatterOptions,
+  StablehloCompareOptions,
+  StablehloDynamicSliceOptions,
+  StablehloPadOptions,
+  StablehloIotaOptions,
+  StablehloDotGeneralOptions,
+  StablehloReduceWindowOptions,
+  StablehloSortOptions,
+  StablehloWhileOptions,
+  StablehloGatherOptions,
+  StablehloTransposeOptions,
+  DilateOptions,
+  StablehloRngBitGeneratorOptions,
+  ReduceWindowOptions,
+}
+
+table StablehloGatherOptions{
+  offset_dims : [long];
+  collapsed_slice_dims : [long];
+  start_index_map : [long];
+  index_vector_dim : long;
+  slice_sizes : [long];
+  indices_are_sorted : bool;
+}
+
+table StablehloTransposeOptions{
+  permutation : [long];
+}
+
+enum StablehloPrecisionConfig : uint {
+  DEFAULT,
+  HIGH,
+  HIGHEST,
+}
+
+table StablehloDotGeneralOptions{
+  lhs_batching_dimensions : [long];
+  rhs_batching_dimensions : [long];
+  lhs_contracting_dimensions : [long];
+  rhs_contracting_dimensions : [long];
+  precision_config : [StablehloPrecisionConfig];
+}
+
+table StablehloReduceWindowOptions{
+  window_dimensions : [long];
+  window_strides : [long];
+  base_dilations : [long];
+  window_dilations : [long];
+  padding : [long];
+  body_subgraph_index : int;
+}
+
+table StablehloWhileOptions{
+  cond_subgraph_index : int;
+  body_subgraph_index : int;
+}
+
+table StablehloSortOptions{
+  dimension : long;
+  is_stable : bool;
+  comparator_subgraph_index : int;
+}
+
+table StablehloConcatenateOptions {
+  dimension : long;
+}
+
+table StablehloBroadcastInDimOptions{
+  broadcast_dimensions : [long];
+}
+
+enum StablehloComparisonDirection : uint {
+  STABLEHLO_COMPARISON_DIRECTION_EQ,
+  STABLEHLO_COMPARISON_DIRECTION_NE,
+  STABLEHLO_COMPARISON_DIRECTION_GE,
+  STABLEHLO_COMPARISON_DIRECTION_GT,
+  STABLEHLO_COMPARISON_DIRECTION_LE,
+  STABLEHLO_COMPARISON_DIRECTION_LT,
+
+}
+
+enum StablehloComparisonType : uint {
+  STABLEHLO_COMPARISON_TYPE_NOTYPE,
+  STABLEHLO_COMPARISON_TYPE_FLOAT,
+  STABLEHLO_COMPARISON_TYPE_FLOAT_TOTAL_ORDER,
+  STABLEHLO_COMPARISON_TYPE_SIGNED,
+  STABLEHLO_COMPARISON_TYPE_UNSIGNED,
+}
+
+table StablehloCompareOptions{
+  comparison_direction : StablehloComparisonDirection;
+  compare_type : StablehloComparisonType;
+}
+
+table StablehloDynamicSliceOptions{
+  slice_sizes : [long];
+}
+
+table StablehloPadOptions{
+  edge_padding_low : [long];
+  edge_padding_high : [long];
+  interior_padding : [long];
+}
+
+table StablehloIotaOptions{
+  iota_dimension : long;
+}
+
+table StablehloCustomCallOptions {
+  call_target_name : string;
+  has_side_effect : bool;
+  backend_config: string;
+  api_version : int; // will be decprecated
+  called_computations: [int]; // should point to subgraphs of the computations
+  custom_attributes : [ubyte];
+}
+
+table StablehloReduceOptions {
+  dimensions : [long];
+  body_subgraph_index : int;
+}
+
+table StablehloSliceOptions{
+  start_indices : [long];
+  limit_indices : [long];
+  strides : [long];
+}
+
+table StablehloConvolutionOptions{
+  window_strides : [long];
+  padding : [long];
+  lhs_dilation : [long];
+  rhs_dilation : [long];
+  window_reversal : [bool];
+  input_batch_dimension : long;
+  input_feature_dimension : long;
+  input_spatial_dimensions : [long];
+  kernel_input_feature_dimension : long;
+  kernel_output_feature_dimension : long;
+  kernel_spatial_dimensions : [long];
+  output_batch_dimension : long;
+  output_feature_dimension : long;
+  output_spatial_dimensions    : [long];
+  feature_group_count : long;
+  batch_group_count : long;
+  precision_config : [StablehloPrecisionConfig];
+}
+
+table StablehloScatterOptions {
+  indices_are_sorted: bool;
+  update_window_dims: [long];
+  inserted_window_dims: [long];
+  scatter_dims_to_operand_dims: [long];
+  index_vector_dim: long;
+  unique_indices: bool;
+  update_computation_subgraph_index: int;
+}
+
+enum RngAlgorithm : byte {
+  // An algorithm auto-selected by the system according to device type.
+  DEFAULT = 0,
+  // The Philox algorithm, as described in paper
+  // ['Parallel Random Numbers: As Easy as 1, 2, 3']
+  // (https://www.thesalmons.org/john/random123/papers/random123sc11.pdf)
+  PHILOX = 1,
+  // The ThreeFry algorithm, as described in paper
+  // ['Parallel Random Numbers: As Easy as 1, 2, 3']
+  // (https://www.thesalmons.org/john/random123/papers/random123sc11.pdf)
+  THREEFRY = 2,
+}
+
+table StablehloRngBitGeneratorOptions {
+  algorithm:RngAlgorithm;
+}
+
+// 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;
+  // Parameters for Conv2D version 8 or above.
+  // When set, quantized_bias_type defines the dtype for both bias and accumulator.
+  quantized_bias_type: TensorType;
+}
+
+// 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,
+  SHUFFLED16x1FLOAT32 = 127
+}
+// 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;
+
+  // Parameters for FullyConnected version 11 or above.
+  // When set, quantized_bias_type defines the dtype for both bias and accumulator.
+  quantized_bias_type: TensorType;
+}
+
+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;
+  // If true, then the end tensor is an offset of the begin tensor.
+  offset: bool;
+}
+
+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;
+
+  // Parameters for TransposeConv version 5 or above.
+  // If set, use this for bias and accumulator.
+  // When set, quantized_bias_type defines the dtype for both bias and accumulator.
+  quantized_bias_type: TensorType;
+}
+
+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 {
+  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 DilateOptions {
+}
+
+enum ReduceWindowFunction : int {
+  UNSUPPORTED,
+  ADD,
+  MUL,
+  MINIMUM,
+  MAXIMUM,
+  ALL,
+  ANY,
+}
+
+table ReduceWindowOptions{
+  reduce_function: ReduceWindowFunction;
+}
+
+table GRUOptions {
+  fused_activation_function:ActivationFunctionType;
+  return_sequences : bool;
+  time_major : bool;
+}
+
+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];
+
+  // When an op is using custom_options in a model that is larger than 2GB, then
+  // we instead use the following attributes to find the buffer location which
+  // is stored outside of flatbuffers, the offset is calculated relative to the
+  // beginning of the file and is only valid if > 1
+  large_custom_options_offset: ulong;
+  large_custom_options_size: ulong;
+
+  // Flatbuffers union struct has a 128 elements limit in JAVA, so a second
+  // union is added, in the case of where BuitlinOptions2 runs out, a third
+  // one can be added
+  builtin_options_2 : BuiltinOptions2;
+}
+
+// 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, deprecated
+  deprecated_data_format: DataFormat (deprecated);
+}
+
+// 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);
+
+  // In a model that is larger than 2GB, then buffers instead uses the following
+  // attributes to find stored data, which is outside of flatbuffers
+  // the offset is calculated relative to the beginning of the file and is only
+  // valid if > 1.
+  offset: ulong;
+  size: ulong;
+}
+
+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;
index 6e0da1a..3818722 100644 (file)
@@ -18,13 +18,14 @@ operand {
   }
 }
 operation {
-  type: "All"
+  type: "Custom"
   all_options {
     keep_dims: false
   }
   input: "ifm"
   input: "All/reduction_indices"
   output: "ofm"
+  custom_code: "All"
 }
 input: "ifm"
 output: "ofm"
index c6163af..9af38a6 100644 (file)
@@ -14,10 +14,11 @@ operand {
   shape { dim: 1 dim: 2 dim: 4 dim: 4 }
 }
 operation {
-  type: "BatchMatMulV2"
+  type: "Custom"
   input: "ifm1"
   input: "ifm2"
   output: "ofm"
+  custom_code: "BatchMatMulV2"
 }
 input: "ifm1"
 input: "ifm2"
index 9350ca8..9c5ca9f 100644 (file)
@@ -14,13 +14,14 @@ operand {
   shape { dim: 2 dim: 2 dim: 2 dim: 4 }
 }
 operation {
-  type: "BatchMatMulV2"
+  type: "Custom"
   batch_matmul_options {
       adj_x : true
   }
   input: "ifm1"
   input: "ifm2"
   output: "ofm"
+  custom_code: "BatchMatMulV2"
 }
 input: "ifm1"
 input: "ifm2"
index 015e40b..4365e08 100644 (file)
@@ -15,10 +15,11 @@ operand {
   shape { dim: 1 dim: 2 dim: 3 }
 }
 operation {
-  type: "BroadcastTo"
+  type: "Custom"
   input: "bc_input"
   input: "bc_shape"
   output: "bc_ofm"
+  custom_code: "BroadcastTo"
 }
 input: "bc_input"
 output: "bc_ofm"
diff --git a/res/TensorFlowLiteRecipes/BroadcastTo_000/test.rule b/res/TensorFlowLiteRecipes/BroadcastTo_000/test.rule
new file mode 100644 (file)
index 0000000..3a43193
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if BroadcastTo is Custom op
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "BROADCAST_TO_EXIST"       $(op_count BROADCAST_TO) '=' 1
+RULE    "NO_CUSTOM_BROADCAST_TO"   $(op_count 'CUSTOM(BROADCAST_TO)') '=' 0
diff --git a/res/TensorFlowLiteRecipes/BroadcastTo_001/test.recipe b/res/TensorFlowLiteRecipes/BroadcastTo_001/test.recipe
new file mode 100644 (file)
index 0000000..38dd14b
--- /dev/null
@@ -0,0 +1,29 @@
+# BroadcastTo Op supports op version 2 and 3.
+# BroadcastTo of Float type is version 2 and Quantized BroadcastTo is version 3.
+# We are using tflite kernels for float values. so, the version should be 2.
+# refer https://github.com/tensorflow/tensorflow/pull/46224/files
+operand {
+  name: "bc_input"
+  type: FLOAT32
+  shape { dim: 2 dim: 3 }
+}
+operand {
+  name: "bc_shape"
+  type: INT32
+  shape { dim: 3 }
+  filler { tag: "explicit" arg: "1" arg: "2" arg: "3" }
+}
+operand {
+  name: "bc_ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 3 }
+}
+operation {
+  type: "BroadcastTo"
+  input: "bc_input"
+  input: "bc_shape"
+  output: "bc_ofm"
+  version: 2
+}
+input: "bc_input"
+output: "bc_ofm"
diff --git a/res/TensorFlowLiteRecipes/BroadcastTo_001/test.reverse b/res/TensorFlowLiteRecipes/BroadcastTo_001/test.reverse
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/res/TensorFlowLiteRecipes/CSE_Quantize_000/test.recipe b/res/TensorFlowLiteRecipes/CSE_Quantize_000/test.recipe
new file mode 100644 (file)
index 0000000..0601163
--- /dev/null
@@ -0,0 +1,31 @@
+operand {
+  name: "ifm"
+  type: UINT8
+  shape { dim: 1 dim: 3 dim: 3 dim: 4 }
+  quant { min: 0 max: 255 scale: 1.0 zero_point: 0 }
+}
+operand {
+  name: "ofm1"
+  type: UINT8
+  shape { dim: 1 dim: 3 dim: 3 dim: 4 }
+  quant { min: 0 max: 510 scale: 2.0 zero_point: 0 }
+}
+operand {
+  name: "ofm2"
+  type: UINT8
+  shape { dim: 1 dim: 3 dim: 3 dim: 4 }
+  quant { min: 0 max: 510 scale: 2.0 zero_point: 0 }
+}
+operation {
+  type: "Quantize"
+  input: "ifm"
+  output: "ofm1"
+}
+operation {
+  type: "Quantize"
+  input: "ifm"
+  output: "ofm2"
+}
+input: "ifm"
+output: "ofm1"
+output: "ofm2"
diff --git a/res/TensorFlowLiteRecipes/CSE_Quantize_000/test.rule b/res/TensorFlowLiteRecipes/CSE_Quantize_000/test.rule
new file mode 100644 (file)
index 0000000..717cf9e
--- /dev/null
@@ -0,0 +1,5 @@
+# To check if common Quantize Op is eliminated
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "DUP_QUANTIZE_REMOVED"    $(op_count QUANTIZE) '=' 1
diff --git a/res/TensorFlowLiteRecipes/CSE_Quantize_001/test.recipe b/res/TensorFlowLiteRecipes/CSE_Quantize_001/test.recipe
new file mode 100644 (file)
index 0000000..afeadfb
--- /dev/null
@@ -0,0 +1,31 @@
+operand {
+  name: "ifm"
+  type: UINT8
+  shape { dim: 1 dim: 3 dim: 3 dim: 4 }
+  quant { min: 0 max: 255 scale: 1.0 zero_point: 0 }
+}
+operand {
+  name: "ofm1"
+  type: UINT8
+  shape { dim: 1 dim: 3 dim: 3 dim: 4 }
+  quant { min: 0 max: 510 scale: 2.0 zero_point: 0 }
+}
+operand {
+  name: "ofm2"
+  type: UINT8
+  shape { dim: 1 dim: 3 dim: 3 dim: 4 }
+  quant { min: 0 max: 765 scale: 3.0 zero_point: 0 }
+}
+operation {
+  type: "Quantize"
+  input: "ifm"
+  output: "ofm1"
+}
+operation {
+  type: "Quantize"
+  input: "ifm"
+  output: "ofm2"
+}
+input: "ifm"
+output: "ofm1"
+output: "ofm2"
diff --git a/res/TensorFlowLiteRecipes/CSE_Quantize_001/test.rule b/res/TensorFlowLiteRecipes/CSE_Quantize_001/test.rule
new file mode 100644 (file)
index 0000000..c5eb553
--- /dev/null
@@ -0,0 +1,5 @@
+# To check if different Quantize Ops remain
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "QUANTIZE_NOT_REMOVED"    $(op_count QUANTIZE) '=' 2
diff --git a/res/TensorFlowLiteRecipes/CSE_Transpose_000/test.recipe b/res/TensorFlowLiteRecipes/CSE_Transpose_000/test.recipe
new file mode 100644 (file)
index 0000000..aa34358
--- /dev/null
@@ -0,0 +1,42 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 3 dim: 3 dim: 4 }
+}
+operand {
+  name: "perm1"
+  type: INT32
+  shape { dim: 4 }
+  filler { tag: "explicit" arg: "0" arg: "3" arg: "1" arg: "2" }
+}
+operand {
+  name: "ofm1"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 3 dim: 3 }
+}
+operand {
+  name: "perm2"
+  type: INT32
+  shape { dim: 4 }
+  filler { tag: "explicit" arg: "0" arg: "3" arg: "1" arg: "2" }
+}
+operand {
+  name: "ofm2"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 3 dim: 3 }
+}
+operation {
+  type: "Transpose"
+  input: "ifm"
+  input: "perm1"
+  output: "ofm1"
+}
+operation {
+  type: "Transpose"
+  input: "ifm"
+  input: "perm2"
+  output: "ofm2"
+}
+input: "ifm"
+output: "ofm1"
+output: "ofm2"
diff --git a/res/TensorFlowLiteRecipes/CSE_Transpose_000/test.rule b/res/TensorFlowLiteRecipes/CSE_Transpose_000/test.rule
new file mode 100644 (file)
index 0000000..c70b6f0
--- /dev/null
@@ -0,0 +1,5 @@
+# To check if common Transpose Op is eliminated
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "DUP_TRANSPOSE_REMOVED"    $(op_count TRANSPOSE) '=' 1
diff --git a/res/TensorFlowLiteRecipes/CSE_Transpose_001/test.recipe b/res/TensorFlowLiteRecipes/CSE_Transpose_001/test.recipe
new file mode 100644 (file)
index 0000000..76577c8
--- /dev/null
@@ -0,0 +1,42 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 3 dim: 3 dim: 4 }
+}
+operand {
+  name: "perm1"
+  type: INT32
+  shape { dim: 4 }
+  filler { tag: "explicit" arg: "0" arg: "3" arg: "1" arg: "2" }
+}
+operand {
+  name: "ofm1"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 3 dim: 3 }
+}
+operand {
+  name: "perm2"
+  type: INT32
+  shape { dim: 4 }
+  filler { tag: "explicit" arg: "0" arg: "1" arg: "3" arg: "2" }
+}
+operand {
+  name: "ofm2"
+  type: FLOAT32
+  shape { dim: 1 dim: 3 dim: 4 dim: 3 }
+}
+operation {
+  type: "Transpose"
+  input: "ifm"
+  input: "perm1"
+  output: "ofm1"
+}
+operation {
+  type: "Transpose"
+  input: "ifm"
+  input: "perm2"
+  output: "ofm2"
+}
+input: "ifm"
+output: "ofm1"
+output: "ofm2"
diff --git a/res/TensorFlowLiteRecipes/CSE_Transpose_001/test.rule b/res/TensorFlowLiteRecipes/CSE_Transpose_001/test.rule
new file mode 100644 (file)
index 0000000..1cd4f12
--- /dev/null
@@ -0,0 +1,5 @@
+# To check if different Transpose Ops remain
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "TRANSPOSE_NOT_REMOVED"    $(op_count TRANSPOSE) '=' 2
diff --git a/res/TensorFlowLiteRecipes/CumSum_000/test.recipe b/res/TensorFlowLiteRecipes/CumSum_000/test.recipe
new file mode 100644 (file)
index 0000000..a050288
--- /dev/null
@@ -0,0 +1,45 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape {
+    dim: 1
+    dim: 1
+    dim: 10
+    dim: 10
+  }
+}
+
+operand {
+  name: "axis"
+  type: INT32
+  shape {}
+  filler {
+    tag: "explicit"
+    arg: "2"
+  }
+}
+
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape {
+    dim: 1
+    dim: 1
+    dim: 10
+    dim: 10
+  }
+}
+
+operation {
+  type: "CumSum"
+  input: "ifm"
+  input: "axis"
+  output: "ofm"
+  cumsum_options {
+    exclusive: false
+    reverse: false
+  }
+}
+
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/CumSum_000/test.reverse b/res/TensorFlowLiteRecipes/CumSum_000/test.reverse
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/res/TensorFlowLiteRecipes/FullyConnected_I4_000/test.recipe b/res/TensorFlowLiteRecipes/FullyConnected_I4_000/test.recipe
new file mode 100644 (file)
index 0000000..de7a605
--- /dev/null
@@ -0,0 +1,45 @@
+# This recipe is just to check processing of INT4 models.
+# do not run this model in any interpreter or runtime as it may throw an error.
+operand {
+  name: "in"
+  type: INT4
+  shape { dim: 1 dim: 4 }
+}
+operand {
+  name: "weight"
+  type: INT4
+  shape { dim: 4 dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "-8" arg: "-7" arg: "-6" arg: "-5"
+    arg: "-4" arg: "-3" arg: "-2" arg: "-1"
+    arg: "0" arg: "1" arg: "2" arg: "3"
+    arg: "4" arg: "5" arg: "6" arg: "7"
+  }
+}
+operand {
+  name: "bias"
+  type: INT4
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "1" arg: "0" arg: "-1" arg: "-2"
+  }
+}
+operand {
+  name: "out"
+  type: INT4
+  shape { dim: 1 dim: 4 }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+  }
+  input: "in"
+  input: "weight"
+  input: "bias"
+  output: "out"
+}
+input: "in"
+output: "out"
diff --git a/res/TensorFlowLiteRecipes/FullyConnected_I4_001/test.recipe b/res/TensorFlowLiteRecipes/FullyConnected_I4_001/test.recipe
new file mode 100644 (file)
index 0000000..d50a67f
--- /dev/null
@@ -0,0 +1,49 @@
+# This recipe is just to check processing of INT4 models.
+# do not run this model in any interpreter or runtime as it may throw an error.
+operand {
+  name: "in"
+  type: INT4
+  shape { dim: 1 dim: 4 }
+  quant { min: -8 max: 7 scale: 1.0 zero_point: 0 }
+}
+operand {
+  name: "weight"
+  type: INT4
+  shape { dim: 4 dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "-8" arg: "-7" arg: "-6" arg: "-5"
+    arg: "-4" arg: "-3" arg: "-2" arg: "-1"
+    arg: "0" arg: "1" arg: "2" arg: "3"
+    arg: "4" arg: "5" arg: "6" arg: "7"
+  }
+  quant { min: -8 max: 7 scale: 1.0 zero_point: 0 }
+}
+operand {
+  name: "bias"
+  type: INT4
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "1" arg: "0" arg: "-1" arg: "-2"
+  }
+  quant { min: -8 max: 7 scale: 1.0 zero_point: 0 }
+}
+operand {
+  name: "out"
+  type: INT4
+  shape { dim: 1 dim: 4 }
+  quant { min: -8 max: 7 scale: 1.0 zero_point: 0 }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+  }
+  input: "in"
+  input: "weight"
+  input: "bias"
+  output: "out"
+}
+input: "in"
+output: "out"
diff --git a/res/TensorFlowLiteRecipes/FullyConnected_I4_002/ref.input0 b/res/TensorFlowLiteRecipes/FullyConnected_I4_002/ref.input0
new file mode 100644 (file)
index 0000000..3be2f57
--- /dev/null
@@ -0,0 +1,3 @@
+2,4
+float32
+0.45845914,0.59502566,0.012643684,0.9902574,0.083512,0.06890562,0.49019852,0.56146705
diff --git a/res/TensorFlowLiteRecipes/FullyConnected_I4_002/ref.output0 b/res/TensorFlowLiteRecipes/FullyConnected_I4_002/ref.output0
new file mode 100644 (file)
index 0000000..e5a4ade
--- /dev/null
@@ -0,0 +1,3 @@
+2,4
+float32
+-11.873346,-3.6393948,4.5945563,12.828507,-5.9188657,-1.0911331,3.7365992,8.564331
diff --git a/res/TensorFlowLiteRecipes/FullyConnected_I4_002/test.recipe b/res/TensorFlowLiteRecipes/FullyConnected_I4_002/test.recipe
new file mode 100644 (file)
index 0000000..6838414
--- /dev/null
@@ -0,0 +1,44 @@
+operand {
+  name: "in"
+  type: FLOAT32
+  shape { dim: 2 dim: 4 }
+}
+operand {
+  name: "weight"
+  type: INT4
+  shape { dim: 4 dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "-8" arg: "-7" arg: "-6" arg: "-5"
+    arg: "-4" arg: "-3" arg: "-2" arg: "-1"
+    arg: "0" arg: "1" arg: "2" arg: "3"
+    arg: "4" arg: "5" arg: "6" arg: "7"
+  }
+  quant { min: -8 max: 7 scale: 1.0 zero_point: 0 }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "1.0" arg: "1.0" arg: "1.0" arg: "1.0"
+  }
+}
+operand {
+  name: "out"
+  type: FLOAT32
+  shape { dim: 2 dim: 4 }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+  }
+  input: "in"
+  input: "weight"
+  input: "bias"
+  output: "out"
+}
+input: "in"
+output: "out"
index 6e7853a..69564f1 100644 (file)
@@ -14,7 +14,7 @@ operand {
   shape { dim: 3 dim: 3 }
 }
 operation {
-  type: "MatMul"
+  type: "Custom"
   input: "ifm1"
   input: "ifm2"
   output: "ofm"
@@ -22,6 +22,7 @@ operation {
     transpose_a: true
     transpose_b: false
   }
+  custom_code: "MatMul"
 }
 input: "ifm1"
 input: "ifm2"
index 702aaf8..0d17289 100644 (file)
@@ -27,11 +27,12 @@ operand {
   shape { dim: 4 dim: 4 }
 }
 operation {
-  type: "MatrixBandPart"
+  type: "Custom"
   input: "ifm"
   input: "MatrixBandPart/num_lower"
   input: "MatrixBandPart/num_upper"
   output: "ofm"
+  custom_code: "MatrixBandPart"
 }
 input: "ifm"
 output: "ofm"
index 9218c20..d618a6f 100644 (file)
@@ -14,7 +14,7 @@ operand {
   shape { dim: 1 dim: 9 dim: 9 dim: 1 }
 }
 operation {
-  type: "MaxPoolWithArgmax"
+  type: "Custom"
   input: "ifm"
   output: "ofm"
   output: "argmax"
@@ -27,6 +27,7 @@ operation {
     output_type: INT64
     include_batch_in_index: false
   }
+  custom_code: "MaxPoolWithArgmax"
 }
 input: "ifm"
 output: "ofm"
index 9c15a7c..4b85f55 100644 (file)
@@ -14,7 +14,7 @@ operand {
   shape { dim: 1 dim: 9 dim: 9 dim: 1 }
 }
 operation {
-  type: "MaxPoolWithArgmax"
+  type: "Custom"
   input: "ifm"
   output: "ofm"
   output: "argmax"
@@ -27,6 +27,7 @@ operation {
     output_type: INT32
     include_batch_in_index: false
   }
+  custom_code: "MaxPoolWithArgmax"
 }
 input: "ifm"
 output: "ofm"
index 702e016..ad0ca7c 100644 (file)
@@ -14,7 +14,7 @@ operand {
   shape { dim: 1 dim: 8 dim: 8 dim: 2 }
 }
 operation {
-  type: "MaxPoolWithArgmax"
+  type: "Custom"
   input: "ifm"
   output: "ofm"
   output: "argmax"
@@ -27,6 +27,7 @@ operation {
     output_type: INT64
     include_batch_in_index: false
   }
+  custom_code: "MaxPoolWithArgmax"
 }
 input: "ifm"
 output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Add_FloorMod_Gather_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Add_FloorMod_Gather_000/test.recipe
new file mode 100644 (file)
index 0000000..9c1569b
--- /dev/null
@@ -0,0 +1,67 @@
+operand {
+  name: "input"
+  type: FLOAT32
+  # value test generates random value of [0,100) for INT32, INT64 inputs.
+  # we have to give at least that size for the input shape (100,?)(for axis=0)
+  # as indices will have value of [0,100)
+  shape { dim: 100 dim: 5 }
+}
+operand {
+  name: "indices"
+  type: INT32
+  shape { dim: 3 dim: 4 }
+}
+operand {
+  name: "add_const"
+  type: INT32
+  shape { }
+  filler { tag: "explicit" arg: "100" }
+}
+operand {
+  name: "add_out"
+  type: INT32
+  shape { dim: 3 dim: 4 }
+}
+operand {
+  name: "floormod_const"
+  type: INT32
+  shape { }
+  filler { tag: "explicit" arg: "100" }
+}
+operand {
+  name: "floormod_out"
+  type: INT32
+  shape { dim: 3 dim: 4 }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 3 dim: 4 dim: 5 }
+}
+operation {
+  type: "Add"
+  input: "indices"
+  input: "add_const"
+  output: "add_out"
+  add_options {
+    activation: NONE
+  }
+}
+operation {
+  type: "FloorMod"
+  input: "add_out"
+  input: "floormod_const"
+  output: "floormod_out"
+}
+operation {
+  type: "Gather"
+  gather_options {
+    axis: 0
+  }
+  input: "input"
+  input: "floormod_out"
+  output: "ofm"
+}
+input: "input"
+input: "indices"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Add_FloorMod_Gather_000/test.rule b/res/TensorFlowLiteRecipes/Net_Add_FloorMod_Gather_000/test.rule
new file mode 100644 (file)
index 0000000..fe61195
--- /dev/null
@@ -0,0 +1,7 @@
+# To check if Add and FloorMod are removed
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "NO_Add"                  $(op_count ADD) '=' 0
+RULE    "NO_FloorMod"             $(op_count FLOOR_MOD) '=' 0
+RULE    "Gather_Exist"            $(op_count GATHER) '=' 1
diff --git a/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_000/test.recipe
new file mode 100644 (file)
index 0000000..42d3882
--- /dev/null
@@ -0,0 +1,67 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "add"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "addc"
+  type: FLOAT32
+  shape { dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 6 }
+}
+operand {
+  name: "fc_wgt"
+  type: FLOAT32
+  shape { dim: 6 dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc_bias"
+  type: FLOAT32
+  shape { dim: 6 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operation {
+  type: "Add"
+  input: "ifm"
+  input: "addc"
+  output: "add"
+  add_options {
+    activation: NONE
+  }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+    keep_num_dims: true
+  }
+  input: "add"
+  input: "fc_wgt"
+  input: "fc_bias"
+  output: "fc"
+}
+input: "ifm"
+output: "fc"
diff --git a/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_000/test.rule b/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_000/test.rule
new file mode 100644 (file)
index 0000000..6c76a70
--- /dev/null
@@ -0,0 +1,7 @@
+# To check FC(Add(lhs, rhs), filter, bias) is converted to
+# FC(lhs, filter, FC(rhs, filter, bias))
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "NO_ADD"                  $(op_count ADD) '=' 0
+RULE    "FC_EXIST"                $(op_count FULLY_CONNECTED) '=' 2
diff --git a/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_001/test.recipe b/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_001/test.recipe
new file mode 100644 (file)
index 0000000..6610e9c
--- /dev/null
@@ -0,0 +1,67 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "add"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "addc"
+  type: FLOAT32
+  shape { dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 6 }
+}
+operand {
+  name: "fc_wgt"
+  type: FLOAT32
+  shape { dim: 6 dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc_bias"
+  type: FLOAT32
+  shape { dim: 6 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operation {
+  type: "Add"
+  input: "ifm"
+  input: "addc"
+  output: "add"
+  add_options {
+    activation: NONE
+  }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: RELU
+    keep_num_dims: true
+  }
+  input: "add"
+  input: "fc_wgt"
+  input: "fc_bias"
+  output: "fc"
+}
+input: "ifm"
+output: "fc"
diff --git a/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_001/test.rule b/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_001/test.rule
new file mode 100644 (file)
index 0000000..6c76a70
--- /dev/null
@@ -0,0 +1,7 @@
+# To check FC(Add(lhs, rhs), filter, bias) is converted to
+# FC(lhs, filter, FC(rhs, filter, bias))
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "NO_ADD"                  $(op_count ADD) '=' 0
+RULE    "FC_EXIST"                $(op_count FULLY_CONNECTED) '=' 2
diff --git a/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_002/test.recipe b/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_002/test.recipe
new file mode 100644 (file)
index 0000000..7420981
--- /dev/null
@@ -0,0 +1,57 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "add"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "addc"
+  type: FLOAT32
+  shape { dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 6 }
+}
+operand {
+  name: "fc_wgt"
+  type: FLOAT32
+  shape { dim: 6 dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operation {
+  type: "Add"
+  input: "ifm"
+  input: "addc"
+  output: "add"
+  add_options {
+    activation: NONE
+  }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+    keep_num_dims: true
+  }
+  input: "add"
+  input: "fc_wgt"
+  input: ""
+  output: "fc"
+}
+input: "ifm"
+output: "fc"
diff --git a/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_002/test.rule b/res/TensorFlowLiteRecipes/Net_Add_FullyConnected_002/test.rule
new file mode 100644 (file)
index 0000000..6c76a70
--- /dev/null
@@ -0,0 +1,7 @@
+# To check FC(Add(lhs, rhs), filter, bias) is converted to
+# FC(lhs, filter, FC(rhs, filter, bias))
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "NO_ADD"                  $(op_count ADD) '=' 0
+RULE    "FC_EXIST"                $(op_count FULLY_CONNECTED) '=' 2
index 5069aac..a3a1105 100644 (file)
@@ -15,10 +15,11 @@ operand {
   shape { dim: 1 dim: 2 dim: 3 }
 }
 operation {
-  type: "BroadcastTo"
+  type: "Custom"
   input: "bc_input"
   input: "bc_shape"
   output: "bc_ofm"
+  custom_code: "BroadcastTo"
 }
 operand {
   name: "reshape_data"
@@ -53,10 +54,11 @@ operand {
   shape { dim: 1 dim: 2 dim: 3 }
 }
 operation {
-  type: "AddV2"
+  type: "Custom"
   input: "bc_ofm"
   input: "reshape_ofm"
   output: "ofm"
+  custom_code: "AddV2"
 }
 input: "bc_input"
 input: "reshape_data"
index ca0ad8e..2a63758 100644 (file)
@@ -15,10 +15,11 @@ operand {
   shape { dim: 1 dim: 2 dim: 3 }
 }
 operation {
-  type: "BroadcastTo"
+  type: "Custom"
   input: "bc_input"
   input: "bc_shape"
   output: "bc_ofm"
+  custom_code: "BroadcastTo"
 }
 operand {
   name: "reshape_data"
@@ -53,10 +54,11 @@ operand {
   shape { dim: 1 dim: 2 dim: 3 }
 }
 operation {
-  type: "AddV2"
+  type: "Custom"
   input: "bc_ofm"
   input: "reshape_ofm"
   output: "ofm"
+  custom_code: "AddV2"
 }
 input: "bc_input"
 input: "reshape_data"
diff --git a/res/TensorFlowLiteRecipes/Net_BroadcastTo_AddV2_002/test.recipe b/res/TensorFlowLiteRecipes/Net_BroadcastTo_AddV2_002/test.recipe
new file mode 100644 (file)
index 0000000..ebc60d4
--- /dev/null
@@ -0,0 +1,69 @@
+# BroadcastTo Op supports op version 2 and 3.
+# BroadcastTo of Float type is version 2 and Quantized BroadcastTo is version 3.
+# We are using tflite kernels for float values. so, the version should be 2.
+# refer https://github.com/tensorflow/tensorflow/pull/46224/files
+operand {
+  name: "bc_input"
+  type: FLOAT32
+  shape { dim: 2 dim: 3 }
+}
+operand {
+  name: "bc_shape"
+  type: INT32
+  shape { dim: 3 }
+  filler { tag: "explicit" arg: "1" arg: "2" arg: "3" }
+}
+operand {
+  name: "bc_ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 3 }
+}
+operation {
+  type: "BroadcastTo"
+  input: "bc_input"
+  input: "bc_shape"
+  output: "bc_ofm"
+  version: 2
+}
+operand {
+  name: "reshape_data"
+  type: FLOAT32
+  shape { dim: 2 dim: 3 }
+}
+operand {
+  name: "reshape_shape"
+  type: INT32
+  shape { dim: 3 }
+  filler { tag: "explicit" arg: "1" arg: "2" arg: "3" }
+}
+operand {
+  name: "reshape_ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 3 }
+}
+operation {
+  type: "Reshape"
+  reshape_options {
+    new_shape: 1
+    new_shape: 2
+    new_shape: 3
+  }
+  input: "reshape_data"
+  input: "reshape_shape"
+  output: "reshape_ofm"
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 3 }
+}
+operation {
+  type: "Custom"
+  input: "bc_ofm"
+  input: "reshape_ofm"
+  output: "ofm"
+  custom_code: "AddV2"
+}
+input: "bc_input"
+input: "reshape_data"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_BroadcastTo_AddV2_002/test.rule b/res/TensorFlowLiteRecipes/Net_BroadcastTo_AddV2_002/test.rule
new file mode 100644 (file)
index 0000000..e397b5c
--- /dev/null
@@ -0,0 +1,7 @@
+# To check if BroadcastTo and AddV2 are fused to Add op
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "ADD_EXIST"               $(op_count ADD) '=' 1
+RULE    "NO_BroadcastTo"          $(op_count 'BroadcastTo') '=' 0
+RULE    "NO_AddV2"                $(op_count 'CUSTOM(AddV2)') '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Add_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Conv_Add_000/test.recipe
new file mode 100644 (file)
index 0000000..d413faf
--- /dev/null
@@ -0,0 +1,69 @@
+# Conv2D + Add(NONE)
+operand {
+  name: "ifm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 3 }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 6 dim: 1 dim: 1 dim: 3 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 6 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 6 }
+}
+operand {
+  name: "add_const"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 6 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_add"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 6 }
+}
+operation {
+  type: "Conv2D"
+  conv2d_options {
+    padding: VALID
+    stride_w: 1
+    stride_h: 1
+  }
+  input: "ifm_conv"
+  input: "filter"
+  input: "bias"
+  output: "ofm_conv"
+}
+operation {
+  type: "Add"
+  input: "ofm_conv"
+  input: "add_const"
+  output: "ofm_add"
+  add_options {
+    activation: NONE
+  }
+}
+input: "ifm_conv"
+output: "ofm_add"
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Add_000/test.rule b/res/TensorFlowLiteRecipes/Net_Conv_Add_000/test.rule
new file mode 100644 (file)
index 0000000..b75e573
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if Add is fused to Convolution op
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "CONV_EXIST"              $(op_count CONV_2D) '=' 1
+RULE    "NO_ADD"                  $(op_count ADD) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Add_001/test.recipe b/res/TensorFlowLiteRecipes/Net_Conv_Add_001/test.recipe
new file mode 100644 (file)
index 0000000..06de5f8
--- /dev/null
@@ -0,0 +1,69 @@
+# Conv2D + Add(RELU)
+operand {
+  name: "ifm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 3 }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 6 dim: 1 dim: 1 dim: 3 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 6 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 6 }
+}
+operand {
+  name: "add_const"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 6 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_add"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 6 }
+}
+operation {
+  type: "Conv2D"
+  conv2d_options {
+    padding: VALID
+    stride_w: 1
+    stride_h: 1
+  }
+  input: "ifm_conv"
+  input: "filter"
+  input: "bias"
+  output: "ofm_conv"
+}
+operation {
+  type: "Add"
+  input: "ofm_conv"
+  input: "add_const"
+  output: "ofm_add"
+  add_options {
+    activation: RELU
+  }
+}
+input: "ifm_conv"
+output: "ofm_add"
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Add_001/test.rule b/res/TensorFlowLiteRecipes/Net_Conv_Add_001/test.rule
new file mode 100644 (file)
index 0000000..b75e573
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if Add is fused to Convolution op
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "CONV_EXIST"              $(op_count CONV_2D) '=' 1
+RULE    "NO_ADD"                  $(op_count ADD) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Add_002/test.recipe b/res/TensorFlowLiteRecipes/Net_Conv_Add_002/test.recipe
new file mode 100644 (file)
index 0000000..0419d36
--- /dev/null
@@ -0,0 +1,59 @@
+# Conv2D(no bias) + Add(RELU)
+operand {
+  name: "ifm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 3 }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 6 dim: 1 dim: 1 dim: 3 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 6 }
+}
+operand {
+  name: "add_const"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 6 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_add"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 6 }
+}
+operation {
+  type: "Conv2D"
+  conv2d_options {
+    padding: VALID
+    stride_w: 1
+    stride_h: 1
+  }
+  input: "ifm_conv"
+  input: "filter"
+  input: ""
+  output: "ofm_conv"
+}
+operation {
+  type: "Add"
+  input: "ofm_conv"
+  input: "add_const"
+  output: "ofm_add"
+  add_options {
+    activation: RELU
+  }
+}
+input: "ifm_conv"
+output: "ofm_add"
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Add_002/test.rule b/res/TensorFlowLiteRecipes/Net_Conv_Add_002/test.rule
new file mode 100644 (file)
index 0000000..b75e573
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if Add is fused to Convolution op
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "CONV_EXIST"              $(op_count CONV_2D) '=' 1
+RULE    "NO_ADD"                  $(op_count ADD) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Mul_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Conv_Mul_000/test.recipe
new file mode 100644 (file)
index 0000000..d3f1785
--- /dev/null
@@ -0,0 +1,71 @@
+# test for Conv(pad=valid, krnl(2, 3, 2, 3), stride=(2, 1))->Mul_with_rank-4_channelwise_constant
+
+operand {
+  name: "ifm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 2 dim: 3 }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 2 dim: 3 dim: 2 dim: 3 }
+  filler {
+    tag: "gaussian"
+    arg: "-1.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 2 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 2 }
+}
+operand {
+  name: "mul_const"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 2 }
+  filler {
+    tag: "gaussian"
+    arg: "-1.0"
+    arg: "1.0"
+  }
+}
+operand { 
+  name: "ofm_mul"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 2 }
+}
+operation {
+  type: "Conv2D"
+  conv2d_options {
+    padding: VALID
+    stride_h: 2
+    stride_w: 1
+    activation: NONE
+  }
+  input: "ifm_conv"
+  input: "filter"
+  input: "bias"
+  output: "ofm_conv"
+}
+operation {
+  type: "Mul"
+  input: "ofm_conv"
+  input: "mul_const"
+  output: "ofm_mul"
+  mul_options {
+    activation: RELU
+  }
+}
+input: "ifm_conv"
+output: "ofm_mul"
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Mul_000/test.rule b/res/TensorFlowLiteRecipes/Net_Conv_Mul_000/test.rule
new file mode 100644 (file)
index 0000000..086cb9a
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if Mul is fused to Conv
+
+RULE    "VERIFY_FILE_FORMAT"    $(verify_file_format) '=' 1
+
+RULE    "CONV_EXIST"            $(op_count CONV_2D) '=' 1
+RULE    "MUL_NOT_EXIST"         $(op_count MUL) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Mul_001/test.recipe b/res/TensorFlowLiteRecipes/Net_Conv_Mul_001/test.recipe
new file mode 100644 (file)
index 0000000..8cf0536
--- /dev/null
@@ -0,0 +1,71 @@
+# test for Conv(pad=valid, krnl(2, 3, 2, 3), stride=(2, 1))->Mul_with_rank-1_channelwise_constant
+
+operand {
+  name: "ifm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 2 dim: 3 }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 2 dim: 3 dim: 2 dim: 3 }
+  filler {
+    tag: "gaussian"
+    arg: "-1.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 2 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 2 }
+}
+operand {
+  name: "mul_const"
+  type: FLOAT32
+  shape { dim: 2 }
+  filler {
+    tag: "gaussian"
+    arg: "-1.0"
+    arg: "1.0"
+  }
+}
+operand { 
+  name: "ofm_mul"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 2 }
+}
+operation {
+  type: "Conv2D"
+  conv2d_options {
+    padding: VALID
+    stride_h: 2
+    stride_w: 1
+    activation: NONE
+  }
+  input: "ifm_conv"
+  input: "filter"
+  input: "bias"
+  output: "ofm_conv"
+}
+operation {
+  type: "Mul"
+  input: "ofm_conv"
+  input: "mul_const"
+  output: "ofm_mul"
+  mul_options {
+    activation: RELU
+  }
+}
+input: "ifm_conv"
+output: "ofm_mul"
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Mul_001/test.rule b/res/TensorFlowLiteRecipes/Net_Conv_Mul_001/test.rule
new file mode 100644 (file)
index 0000000..086cb9a
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if Mul is fused to Conv
+
+RULE    "VERIFY_FILE_FORMAT"    $(verify_file_format) '=' 1
+
+RULE    "CONV_EXIST"            $(op_count CONV_2D) '=' 1
+RULE    "MUL_NOT_EXIST"         $(op_count MUL) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Mul_002/test.recipe b/res/TensorFlowLiteRecipes/Net_Conv_Mul_002/test.recipe
new file mode 100644 (file)
index 0000000..cd6a65f
--- /dev/null
@@ -0,0 +1,71 @@
+# test for Conv(pad=valid, krnl(2, 3, 2, 3), stride=(2, 1))->Mul_with_rank-1_constant
+
+operand {
+  name: "ifm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 2 dim: 3 }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 2 dim: 3 dim: 2 dim: 3 }
+  filler {
+    tag: "gaussian"
+    arg: "-1.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 2 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 2 }
+}
+operand {
+  name: "mul_const"
+  type: FLOAT32
+  shape { dim: 1 }
+  filler {
+    tag: "gaussian"
+    arg: "-1.0"
+    arg: "1.0"
+  }
+}
+operand { 
+  name: "ofm_mul"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 2 }
+}
+operation {
+  type: "Conv2D"
+  conv2d_options {
+    padding: VALID
+    stride_h: 2
+    stride_w: 1
+    activation: NONE
+  }
+  input: "ifm_conv"
+  input: "filter"
+  input: "bias"
+  output: "ofm_conv"
+}
+operation {
+  type: "Mul"
+  input: "ofm_conv"
+  input: "mul_const"
+  output: "ofm_mul"
+  mul_options {
+    activation: RELU
+  }
+}
+input: "ifm_conv"
+output: "ofm_mul"
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Mul_002/test.rule b/res/TensorFlowLiteRecipes/Net_Conv_Mul_002/test.rule
new file mode 100644 (file)
index 0000000..086cb9a
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if Mul is fused to Conv
+
+RULE    "VERIFY_FILE_FORMAT"    $(verify_file_format) '=' 1
+
+RULE    "CONV_EXIST"            $(op_count CONV_2D) '=' 1
+RULE    "MUL_NOT_EXIST"         $(op_count MUL) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Mul_003/test.recipe b/res/TensorFlowLiteRecipes/Net_Conv_Mul_003/test.recipe
new file mode 100644 (file)
index 0000000..163af98
--- /dev/null
@@ -0,0 +1,70 @@
+# test for Conv(pad=valid, krnl(2, 3, 2, 3), stride=(2, 1))->Mul_with_rank_0_constant
+
+operand {
+  name: "ifm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 2 dim: 3 }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 2 dim: 3 dim: 2 dim: 3 }
+  filler {
+    tag: "gaussian"
+    arg: "-1.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 2 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_conv"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 2 }
+}
+operand {
+  name: "mul_const"
+  type: FLOAT32
+  filler {
+    tag: "gaussian"
+    arg: "-1.0"
+    arg: "1.0"
+  }
+}
+operand { 
+  name: "ofm_mul"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 1 dim: 2 }
+}
+operation {
+  type: "Conv2D"
+  conv2d_options {
+    padding: VALID
+    stride_h: 2
+    stride_w: 1
+    activation: NONE
+  }
+  input: "ifm_conv"
+  input: "filter"
+  input: "bias"
+  output: "ofm_conv"
+}
+operation {
+  type: "Mul"
+  input: "ofm_conv"
+  input: "mul_const"
+  output: "ofm_mul"
+  mul_options {
+    activation: RELU
+  }
+}
+input: "ifm_conv"
+output: "ofm_mul"
diff --git a/res/TensorFlowLiteRecipes/Net_Conv_Mul_003/test.rule b/res/TensorFlowLiteRecipes/Net_Conv_Mul_003/test.rule
new file mode 100644 (file)
index 0000000..086cb9a
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if Mul is fused to Conv
+
+RULE    "VERIFY_FILE_FORMAT"    $(verify_file_format) '=' 1
+
+RULE    "CONV_EXIST"            $(op_count CONV_2D) '=' 1
+RULE    "MUL_NOT_EXIST"         $(op_count MUL) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_FC_Gelu_FC_000/test.recipe b/res/TensorFlowLiteRecipes/Net_FC_Gelu_FC_000/test.recipe
new file mode 100644 (file)
index 0000000..db3c106
--- /dev/null
@@ -0,0 +1,139 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 2 }
+}
+operand {
+  name: "fc1"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 2 }
+}
+operand {
+  name: "fc2"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 2 }
+}
+operand {
+  name: "fc1_w"
+  type: FLOAT32
+  shape { dim: 2 dim: 2 }
+  filler {
+    tag: "explicit"
+    arg: "1"
+    arg: "1"
+    arg: "1"
+    arg: "1"
+  }
+}
+operand {
+  name: "fc2_w"
+  type: FLOAT32
+  shape { dim: 2 dim: 2 }
+  filler {
+    tag: "explicit"
+    arg: "0.7071067690849304"
+    arg: "0.7071067690849304"
+    arg: "0.7071067690849304"
+    arg: "0.7071067690849304"
+  }
+}
+operand {
+  name: "erf"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 2 }
+}
+operand {
+  name: "add_one"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 2 }
+}
+operand {
+  name: "one"
+  type: FLOAT32
+  shape { dim: 1 }
+  filler {
+    tag: "explicit"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "mul"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 2 }
+}
+operand {
+  name: "fc3"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 2 }
+}
+operand {
+  name: "fc3_w"
+  type: FLOAT32
+  shape { dim: 2 dim: 2 }
+  filler {
+    tag: "explicit"
+    arg: "1.0"
+    arg: "1.0"
+    arg: "1.0"
+    arg: "1.0"
+  }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+    keep_num_dims: true
+  }
+  input: "ifm"
+  input: "fc1_w"
+  input: ""
+  output: "fc1"
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+    keep_num_dims: true
+  }
+  input: "ifm"
+  input: "fc2_w"
+  input: ""
+  output: "fc2"
+}
+operation {
+  type: "Custom"
+  input: "fc2"
+  output: "erf"
+  custom_code: "Erf"
+}
+operation {
+  type: "Add"
+  add_options {
+    activation: NONE
+  }
+  input: "erf"
+  input: "one"
+  output: "add_one"
+}
+operation {
+  type: "Mul"
+  mul_options {
+    activation: NONE
+  }
+  input: "fc1"
+  input: "add_one"
+  output: "mul"
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+    keep_num_dims: true
+  }
+  input: "mul"
+  input: "fc3_w"
+  input: ""
+  output: "fc3"
+}
+input: "ifm"
+output: "fc3"
diff --git a/res/TensorFlowLiteRecipes/Net_FC_Gelu_FC_000/test.rule b/res/TensorFlowLiteRecipes/Net_FC_Gelu_FC_000/test.rule
new file mode 100644 (file)
index 0000000..347c004
--- /dev/null
@@ -0,0 +1,9 @@
+# To check if extract_gelu_from_opt_fc works
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "GELU_EXIST"              $(op_count GELU) '=' 1
+RULE    "FC_EXIST"                $(op_count FULLY_CONNECTED) '=' 2
+RULE    "NO_MUL"                  $(op_count MUL) '=' 0
+RULE    "NO_ADD"                  $(op_count ADD) '=' 0
+RULE    "NO_CUSTOM"               $(op_count 'CUSTOM(Erf)') '=' 0
index 804d293..31a7251 100644 (file)
@@ -99,10 +99,11 @@ operation {
   output: "ofm_sparse"
 }
 operation {
-  type: "AddV2"
+  type: "Custom"
   input: "ofm_sparse"
   input: "add_v2_2"
   output: "ofm_add_v2"
+  custom_code: "AddV2"
 }
 operation {
   type: "Cast"
index ae7f823..73816c3 100644 (file)
@@ -65,9 +65,10 @@ operation {
   }
 }
 operation {
-  type: "Erf"
+  type: "Custom"
   input: "mul_sqrt"
   output: "erf"
+  custom_code: "Erf"
 }
 operation {
   type: "Add"
index 7633729..957ccc1 100644 (file)
@@ -65,9 +65,10 @@ operation {
   }
 }
 operation {
-  type: "Erf"
+  type: "Custom"
   input: "mul_sqrt"
   output: "erf"
+  custom_code: "Erf"
 }
 operation {
   type: "Add"
diff --git a/res/TensorFlowLiteRecipes/Net_Horizontal_FullyConnected_Add_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Horizontal_FullyConnected_Add_000/test.recipe
new file mode 100644 (file)
index 0000000..e7b634f
--- /dev/null
@@ -0,0 +1,91 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 120 }
+}
+operand {
+  name: "fc_wgt_1"
+  type: FLOAT32
+  shape { dim: 29 dim: 120 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc_bias_1"
+  type: FLOAT32
+  shape { dim: 29 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc_1"
+  type: FLOAT32
+  shape { dim: 1 dim: 29 }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+  }
+  input: "ifm"
+  input: "fc_wgt_1"
+  input: "fc_bias_1"
+  output: "fc_1"
+}
+operand {
+  name: "fc_wgt_2"
+  type: FLOAT32
+  shape { dim: 29 dim: 120 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc_bias_2"
+  type: FLOAT32
+  shape { dim: 29 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc_2"
+  type: FLOAT32
+  shape { dim: 1 dim: 29 }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+  }
+  input: "ifm"
+  input: "fc_wgt_2"
+  input: "fc_bias_2"
+  output: "fc_2"
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 29 }
+}
+operation {
+  type: "Add"
+  input: "fc_1"
+  input: "fc_2"
+  output: "ofm"
+  add_options {
+    activation: NONE
+  }
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Horizontal_FullyConnected_Add_000/test.rule b/res/TensorFlowLiteRecipes/Net_Horizontal_FullyConnected_Add_000/test.rule
new file mode 100644 (file)
index 0000000..db12be7
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if horizontal FullyConnected and Add kernels are fused
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "ADD_REMOVED"             $(op_count ADD) '=' 0
+RULE    "FC_FUSED"                $(op_count FULLY_CONNECTED) '=' 1
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Add_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Mul_Add_000/test.recipe
new file mode 100644 (file)
index 0000000..3f00a20
--- /dev/null
@@ -0,0 +1,52 @@
+# test for Add(Mul, zero) is converted to Mul
+
+operand {
+    name: "ifm1"
+    type: FLOAT32
+    shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operand {
+  name: "ifm2"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operand {
+  name: "mul_ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operation {
+    type: "Mul"
+    input: "ifm1"
+    input: "ifm2"
+    output: "mul_ofm"
+    mul_options {
+      activation: RELU
+    }
+}
+operand {
+  name: "zero"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+  filler {
+    tag: "explicit"
+    arg: "0"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operation {
+    type: "Add"
+    input: "mul_ofm"
+    input: "zero"
+    output: "ofm"
+    add_options {
+      activation: NONE
+    }
+}
+input: "ifm1"
+input: "ifm2"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Add_000/test.rule b/res/TensorFlowLiteRecipes/Net_Mul_Add_000/test.rule
new file mode 100644 (file)
index 0000000..e67289b
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if unnecessary Add is removed from sample graph
+
+RULE    "VERIFY_FILE_FORMAT"    $(verify_file_format) '=' 1
+
+RULE    "MUL_EXIST"             $(op_count MUL) '=' 1
+RULE    "ADD_NOT_EXIST"         $(op_count ADD) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Add_001/test.recipe b/res/TensorFlowLiteRecipes/Net_Mul_Add_001/test.recipe
new file mode 100644 (file)
index 0000000..4aef9bf
--- /dev/null
@@ -0,0 +1,52 @@
+# test for Add(Mul, zero_broadcasted) is converted to Mul
+
+operand {
+    name: "ifm1"
+    type: FLOAT32
+    shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operand {
+  name: "ifm2"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operand {
+  name: "mul_ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operation {
+    type: "Mul"
+    input: "ifm1"
+    input: "ifm2"
+    output: "mul_ofm"
+    mul_options {
+      activation: RELU
+    }
+}
+operand {
+  name: "zero_broadcasted"
+  type: FLOAT32
+  shape { dim: 1 }
+  filler {
+    tag: "explicit"
+    arg: "0"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operation {
+    type: "Add"
+    input: "mul_ofm"
+    input: "zero_broadcasted"
+    output: "ofm"
+    add_options {
+      activation: NONE
+    }
+}
+input: "ifm1"
+input: "ifm2"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Add_001/test.rule b/res/TensorFlowLiteRecipes/Net_Mul_Add_001/test.rule
new file mode 100644 (file)
index 0000000..e67289b
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if unnecessary Add is removed from sample graph
+
+RULE    "VERIFY_FILE_FORMAT"    $(verify_file_format) '=' 1
+
+RULE    "MUL_EXIST"             $(op_count MUL) '=' 1
+RULE    "ADD_NOT_EXIST"         $(op_count ADD) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Add_002/test.recipe b/res/TensorFlowLiteRecipes/Net_Mul_Add_002/test.recipe
new file mode 100644 (file)
index 0000000..94ad4ac
--- /dev/null
@@ -0,0 +1,52 @@
+# test for Add(Mul, zero_broadcasted) is converted to Mul
+
+operand {
+    name: "ifm1"
+    type: FLOAT32
+    shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operand {
+  name: "ifm2"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operand {
+  name: "mul_ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operation {
+    type: "Mul"
+    input: "ifm1"
+    input: "ifm2"
+    output: "mul_ofm"
+    mul_options {
+      activation: RELU
+    }
+}
+operand {
+  name: "zero_broadcasted"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 16 dim: 17 }
+  filler {
+    tag: "explicit"
+    arg: "0"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operation {
+    type: "Add"
+    input: "mul_ofm"
+    input: "zero_broadcasted"
+    output: "ofm"
+    add_options {
+      activation: NONE
+    }
+}
+input: "ifm1"
+input: "ifm2"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Add_002/test.rule b/res/TensorFlowLiteRecipes/Net_Mul_Add_002/test.rule
new file mode 100644 (file)
index 0000000..e67289b
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if unnecessary Add is removed from sample graph
+
+RULE    "VERIFY_FILE_FORMAT"    $(verify_file_format) '=' 1
+
+RULE    "MUL_EXIST"             $(op_count MUL) '=' 1
+RULE    "ADD_NOT_EXIST"         $(op_count ADD) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Add_003/test.recipe b/res/TensorFlowLiteRecipes/Net_Mul_Add_003/test.recipe
new file mode 100644 (file)
index 0000000..38e8047
--- /dev/null
@@ -0,0 +1,52 @@
+# test for Add(zero_broadcasted, Mul) is converted to Mul
+
+operand {
+    name: "ifm1"
+    type: FLOAT32
+    shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operand {
+  name: "ifm2"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operand {
+  name: "mul_ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operation {
+    type: "Mul"
+    input: "ifm1"
+    input: "ifm2"
+    output: "mul_ofm"
+    mul_options {
+      activation: NONE
+    }
+}
+operand {
+  name: "zero_broadcasted"
+  type: FLOAT32
+  shape { dim: 1 dim: 1 dim: 16 dim: 17 }
+  filler {
+    tag: "explicit"
+    arg: "0"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 16 dim: 17 }
+}
+operation {
+    type: "Add"
+    input: "zero_broadcasted"
+    input: "mul_ofm"
+    output: "ofm"
+    add_options {
+      activation: NONE
+    }
+}
+input: "ifm1"
+input: "ifm2"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Add_003/test.rule b/res/TensorFlowLiteRecipes/Net_Mul_Add_003/test.rule
new file mode 100644 (file)
index 0000000..e67289b
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if unnecessary Add is removed from sample graph
+
+RULE    "VERIFY_FILE_FORMAT"    $(verify_file_format) '=' 1
+
+RULE    "MUL_EXIST"             $(op_count MUL) '=' 1
+RULE    "ADD_NOT_EXIST"         $(op_count ADD) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Div_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Mul_Div_000/test.recipe
new file mode 100644 (file)
index 0000000..2af2b66
--- /dev/null
@@ -0,0 +1,47 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 3 dim: 5 dim: 1 }
+}
+operand {
+  name: "mul_const"
+  type: FLOAT32
+  shape { dim: 1 }
+  filler { tag: "explicit" arg: "1.1" }
+}
+operand {
+  name: "mul_out"
+  type: FLOAT32
+  shape { dim: 3 dim: 5 dim: 1}
+}
+operation {
+  type: "Mul"
+  input: "ifm"
+  input: "mul_const"
+  output: "mul_out"
+  mul_options {
+    activation: NONE
+  }
+}
+operand {
+  name: "div_const"
+  type: FLOAT32
+  shape { dim: 1 }
+  filler { tag: "explicit" arg: "2.2" }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 3 dim: 5 dim: 1 }
+}
+operation {
+  type: "Div"
+  input: "div_const"
+  input: "mul_out"
+  output: "ofm"
+  div_options {
+    activation: NONE
+  }
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Div_000/test.rule b/res/TensorFlowLiteRecipes/Net_Mul_Div_000/test.rule
new file mode 100644 (file)
index 0000000..db3b160
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if Mul_Div pattern are fused
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "MUL_FUSED"               $(op_count MUL) '=' 0
+RULE    "DIV_SAVED"               $(op_count DIV) '=' 1
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Div_001/test.recipe b/res/TensorFlowLiteRecipes/Net_Mul_Div_001/test.recipe
new file mode 100644 (file)
index 0000000..5af5c6a
--- /dev/null
@@ -0,0 +1,47 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 2 dim: 4 }
+}
+operand {
+  name: "mul_const"
+  type: FLOAT32
+  shape { }
+  filler { tag: "explicit" arg: "1.1" }
+}
+operand {
+  name: "mul_out"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 2 dim: 4 }
+}
+operation {
+  type: "Mul"
+  input: "ifm"
+  input: "mul_const"
+  output: "mul_out"
+  mul_options {
+    activation: NONE
+  }
+}
+operand {
+  name: "div_const"
+  type: FLOAT32
+  shape { }
+  filler { tag: "explicit" arg: "2.2" }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 2 dim: 4 }
+}
+operation {
+  type: "Div"
+  input: "mul_out"
+  input: "div_const"
+  output: "ofm"
+  div_options {
+    activation: NONE
+  }
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_Div_001/test.rule b/res/TensorFlowLiteRecipes/Net_Mul_Div_001/test.rule
new file mode 100644 (file)
index 0000000..33de982
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if Mul_Div pattern are fused
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "DIV_FUSED"               $(op_count DIV) '=' 0
+RULE    "MUL_SAVED"               $(op_count MUL) '=' 1
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_000/test.recipe
new file mode 100644 (file)
index 0000000..bbb7761
--- /dev/null
@@ -0,0 +1,67 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "mul"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "mulc"
+  type: FLOAT32
+  shape { dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 6 }
+}
+operand {
+  name: "fc_wgt"
+  type: FLOAT32
+  shape { dim: 6 dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc_bias"
+  type: FLOAT32
+  shape { dim: 6 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operation {
+  type: "Mul"
+  input: "ifm"
+  input: "mulc"
+  output: "mul"
+  mul_options {
+    activation: NONE
+  }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: NONE
+    keep_num_dims: true
+  }
+  input: "mul"
+  input: "fc_wgt"
+  input: "fc_bias"
+  output: "fc"
+}
+input: "ifm"
+output: "fc"
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_000/test.rule b/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_000/test.rule
new file mode 100644 (file)
index 0000000..01fe6f6
--- /dev/null
@@ -0,0 +1,8 @@
+# To check FC(Mul(lhs, rhs), filter, bias) is converted to
+# FC(lhs, Mul(filter, rhs), bias) and then Mul is folded to
+# FC(lhs, filter', bias)
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "NO_MUL"                  $(op_count MUL) '=' 0
+RULE    "FC_EXIST"                $(op_count FULLY_CONNECTED) '=' 1
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_001/test.recipe b/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_001/test.recipe
new file mode 100644 (file)
index 0000000..f0f7efd
--- /dev/null
@@ -0,0 +1,67 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "mul"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "mulc"
+  type: FLOAT32
+  shape { dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 6 }
+}
+operand {
+  name: "fc_wgt"
+  type: FLOAT32
+  shape { dim: 6 dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc_bias"
+  type: FLOAT32
+  shape { dim: 6 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operation {
+  type: "Mul"
+  input: "ifm"
+  input: "mulc"
+  output: "mul"
+  mul_options {
+    activation: NONE
+  }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: RELU
+    keep_num_dims: true
+  }
+  input: "mul"
+  input: "fc_wgt"
+  input: "fc_bias"
+  output: "fc"
+}
+input: "ifm"
+output: "fc"
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_001/test.rule b/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_001/test.rule
new file mode 100644 (file)
index 0000000..9045cdf
--- /dev/null
@@ -0,0 +1,9 @@
+# To check FC(Mul(lhs, rhs), filter, bias) is converted to
+# FC(lhs, Mul(filter, rhs), bias) and then Mul is folded to
+# FC(lhs, filter', bias)
+
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "NO_MUL"                  $(op_count MUL) '=' 0
+RULE    "FC_EXIST"                $(op_count FULLY_CONNECTED) '=' 1
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_002/test.recipe b/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_002/test.recipe
new file mode 100644 (file)
index 0000000..ad022cc
--- /dev/null
@@ -0,0 +1,57 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "mul"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 4 }
+}
+operand {
+  name: "mulc"
+  type: FLOAT32
+  shape { dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "fc"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 6 }
+}
+operand {
+  name: "fc_wgt"
+  type: FLOAT32
+  shape { dim: 6 dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operation {
+  type: "Mul"
+  input: "ifm"
+  input: "mulc"
+  output: "mul"
+  mul_options {
+    activation: NONE
+  }
+}
+operation {
+  type: "FullyConnected"
+  fullyconnected_options {
+    activation: RELU
+    keep_num_dims: true
+  }
+  input: "mul"
+  input: "fc_wgt"
+  input: ""
+  output: "fc"
+}
+input: "ifm"
+output: "fc"
diff --git a/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_002/test.rule b/res/TensorFlowLiteRecipes/Net_Mul_FullyConnected_002/test.rule
new file mode 100644 (file)
index 0000000..01fe6f6
--- /dev/null
@@ -0,0 +1,8 @@
+# To check FC(Mul(lhs, rhs), filter, bias) is converted to
+# FC(lhs, Mul(filter, rhs), bias) and then Mul is folded to
+# FC(lhs, filter', bias)
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "NO_MUL"                  $(op_count MUL) '=' 0
+RULE    "FC_EXIST"                $(op_count FULLY_CONNECTED) '=' 1
diff --git a/res/TensorFlowLiteRecipes/Net_Reshape_Mean_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Reshape_Mean_000/test.recipe
new file mode 100644 (file)
index 0000000..f01732d
--- /dev/null
@@ -0,0 +1,45 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 3 dim: 197 dim: 197 }
+}
+operand {
+  name: "shape1"
+  type: INT32
+  shape { dim: 3 }
+  filler { tag: "explicit" arg: "1" arg: "-1" arg: "197" }
+}
+operand {
+  name: "reshape_out"
+  type: FLOAT32
+  shape { dim: 1 dim: 591 dim: 197 }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 591 dim: 1 }
+}
+operand {
+  name: "reduction_indices"
+  type: INT32
+  shape { dim: 1 }
+  filler { tag: "explicit" arg: "-1" }
+}
+operation {
+  type: "Reshape"
+  input: "ifm"
+  input: "shape1"
+  output: "reshape_out"
+}
+operation {
+  type: "Mean"
+  mean_options {
+    keep_dims: true
+  }
+  input: "reshape_out"
+  input: "reduction_indices"
+  output: "ofm"
+}
+
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Shape_Add_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Shape_Add_000/test.recipe
new file mode 100644 (file)
index 0000000..c2f0a24
--- /dev/null
@@ -0,0 +1,46 @@
+# test for constant folding of Shape operation
+
+operand {
+  name: "ifm"
+  type: INT32
+  shape { dim: 4 }
+}
+operand {
+  name: "constant"
+  type: FLOAT32
+  shape { dim: 1 dim: 2 dim: 3 dim: 4 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "shape"
+  type: INT32
+  shape { dim: 4 }
+}
+operand {
+  name: "ofm"
+  type: INT32
+  shape { dim: 4 }
+}
+operation {
+  type: "Shape"
+  shape_options {
+    out_type: INT32
+  }
+  input: "constant"
+  output: "shape"
+}
+operation {
+  type: "Add"
+  input: "ifm"
+  input: "shape"
+  output: "ofm"
+  add_options {
+    activation: NONE
+  }
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Shape_Add_000/test.rule b/res/TensorFlowLiteRecipes/Net_Shape_Add_000/test.rule
new file mode 100644 (file)
index 0000000..12b5d84
--- /dev/null
@@ -0,0 +1,5 @@
+# To check if Shape op is folded
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "NO_SHAPE"                $(op_count Shape) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Sqrt_Div_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Sqrt_Div_000/test.recipe
new file mode 100644 (file)
index 0000000..f08c96f
--- /dev/null
@@ -0,0 +1,54 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+}
+# Add 100.0 is not to make divide by zero error in testing
+operand {
+  name: "one"
+  type: FLOAT32
+  shape { dim: 1 }
+  filler {
+    tag: "constant" arg: "100.0"
+  }
+}
+operand {
+  name: "add"
+  type: FLOAT32
+  shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+}
+operand {
+  name: "sqrt"
+  type: FLOAT32
+  shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+}
+operand {
+  name: "div"
+  type: FLOAT32
+  shape { dim: 1 dim: 3 dim: 3 dim: 2 }
+}
+operation {
+  type: "Add"
+  input: "ifm"
+  input: "one"
+  output: "add"
+  add_options {
+    activation: NONE
+  }
+}
+operation {
+  type: "Sqrt"
+  input: "add"
+  output: "sqrt"
+}
+operation {
+  type: "Div"
+  input: "ifm"
+  input: "sqrt"
+  output: "div"
+  div_options {
+    activation: NONE
+  }
+}
+input: "ifm"
+output: "div"
diff --git a/res/TensorFlowLiteRecipes/Net_Sqrt_Div_000/test.rule b/res/TensorFlowLiteRecipes/Net_Sqrt_Div_000/test.rule
new file mode 100644 (file)
index 0000000..4a1de8b
--- /dev/null
@@ -0,0 +1,8 @@
+# To check if Sqrt-Div is transformed to Rsqrt-Mul ops
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "RSQRT_EXIST"             $(op_count RSQRT) '=' 1
+RULE    "MUL_EXIST"               $(op_count MUL) '=' 1
+RULE    "SQRT_NOT_EXIST"          $(op_count SQRT) '=' 0
+RULE    "DIV_NOT_EXIST"           $(op_count DIV) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Slice_000/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_Slice_000/test.recipe
new file mode 100644 (file)
index 0000000..fceb5f5
--- /dev/null
@@ -0,0 +1,99 @@
+# test for zero spatial offset but spatial reduction in size
+# TConv(pad=valid, krnl=(32, 4, 4, 32))->Slice(offset = (0, 0, 0, 0), size = (0, 15, 15, 32))=TConv
+
+operand {
+  name: "tconv_shape"
+  type: INT32
+  shape {
+    dim: 4
+  }
+  filler {
+    tag: "explicit"
+    arg: "1"
+    arg: "18"
+    arg: "18"
+    arg: "32"
+  }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 32 dim: 4 dim: 4 dim: 32 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 8 dim: 8 dim: 32 }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 32 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_tconv"
+  type: FLOAT32
+  shape { dim: 1 dim: 18 dim: 18 dim: 32 }
+}
+operation {
+  type: "TransposeConv"
+  input: "tconv_shape"
+  input: "filter"
+  input: "ifm"
+  input: "bias"
+  output: "ofm_tconv"
+  transpose_conv_options {
+    padding: VALID
+    stride_w: 2
+    stride_h: 2
+    activation: RELU
+  }
+}
+operand {
+  name: "offset"
+  type: INT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "0"
+    arg: "0"
+    arg: "0"
+    arg: "0"
+  }
+}
+operand {
+  name: "size"
+  type: INT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "1" 
+    arg: "15" 
+    arg: "15"
+    arg: "32"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 15 dim: 32 }
+}
+operation {
+  type: "Slice"
+  input: "ofm_tconv"
+  input: "offset"
+  input: "size"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Slice_000/test.rule b/res/TensorFlowLiteRecipes/Net_TConv_Slice_000/test.rule
new file mode 100644 (file)
index 0000000..bb264e1
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if TConv->Slice is converted to TConv operation
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "TCONV_EXIST"             $(op_count TRANSPOSE_CONV) '=' 1
+RULE    "SLICE_NOT_EXIST"         $(op_count SLICE) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Slice_001/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_Slice_001/test.recipe
new file mode 100644 (file)
index 0000000..06ebcd0
--- /dev/null
@@ -0,0 +1,99 @@
+# test for non-zero spatial offset
+# TConv(pad=valid, krnl=(32, 4, 4, 32))->Slice(offset = (0, 1, 1, 0), size = (0, 14, 14, 32))=TConv
+
+operand {
+  name: "tconv_shape"
+  type: INT32
+  shape {
+    dim: 4
+  }
+  filler {
+    tag: "explicit"
+    arg: "1"
+    arg: "18"
+    arg: "18"
+    arg: "32"
+  }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 32 dim: 4 dim: 4 dim: 32 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 8 dim: 8 dim: 32 }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 32 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_tconv"
+  type: FLOAT32
+  shape { dim: 1 dim: 18 dim: 18 dim: 32 }
+}
+operation {
+  type: "TransposeConv"
+  input: "tconv_shape"
+  input: "filter"
+  input: "ifm"
+  input: "bias"
+  output: "ofm_tconv"
+  transpose_conv_options {
+    padding: VALID
+    stride_w: 2
+    stride_h: 2
+    activation: RELU
+  }
+}
+operand {
+  name: "offset"
+  type: INT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "0"
+    arg: "1"
+    arg: "1"
+    arg: "0"
+  }
+}
+operand {
+  name: "size"
+  type: INT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "1" 
+    arg: "14" 
+    arg: "14"
+    arg: "32"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 14 dim: 14 dim: 32 }
+}
+operation {
+  type: "Slice"
+  input: "ofm_tconv"
+  input: "offset"
+  input: "size"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Slice_001/test.rule b/res/TensorFlowLiteRecipes/Net_TConv_Slice_001/test.rule
new file mode 100644 (file)
index 0000000..bb264e1
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if TConv->Slice is converted to TConv operation
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "TCONV_EXIST"             $(op_count TRANSPOSE_CONV) '=' 1
+RULE    "SLICE_NOT_EXIST"         $(op_count SLICE) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Slice_002/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_Slice_002/test.recipe
new file mode 100644 (file)
index 0000000..22b4b58
--- /dev/null
@@ -0,0 +1,99 @@
+# test for channel-direction slice
+# TConv(pad=valid, krnl=(32, 4, 4, 32))->Slice(begin = (0, 0, 0, 10), size = (0, 15, 15, 10))=TConv
+
+operand {
+  name: "tconv_shape"
+  type: INT32
+  shape {
+    dim: 4
+  }
+  filler {
+    tag: "explicit"
+    arg: "1"
+    arg: "18"
+    arg: "18"
+    arg: "32"
+  }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 32 dim: 4 dim: 4 dim: 32 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 8 dim: 8 dim: 32 }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 32 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_tconv"
+  type: FLOAT32
+  shape { dim: 1 dim: 18 dim: 18 dim: 32 }
+}
+operation {
+  type: "TransposeConv"
+  input: "tconv_shape"
+  input: "filter"
+  input: "ifm"
+  input: "bias"
+  output: "ofm_tconv"
+  transpose_conv_options {
+    padding: VALID
+    stride_w: 2
+    stride_h: 2
+    activation: RELU
+  }
+}
+operand {
+  name: "offset"
+  type: INT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "0"
+    arg: "0"
+    arg: "0"
+    arg: "10"
+  }
+}
+operand {
+  name: "size"
+  type: INT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "1" 
+    arg: "18" 
+    arg: "18"
+    arg: "10"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 18 dim: 18 dim: 10 }
+}
+operation {
+  type: "Slice"
+  input: "ofm_tconv"
+  input: "offset"
+  input: "size"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Slice_002/test.rule b/res/TensorFlowLiteRecipes/Net_TConv_Slice_002/test.rule
new file mode 100644 (file)
index 0000000..bb264e1
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if TConv->Slice is converted to TConv operation
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "TCONV_EXIST"             $(op_count TRANSPOSE_CONV) '=' 1
+RULE    "SLICE_NOT_EXIST"         $(op_count SLICE) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Slice_003/test.recipe b/res/TensorFlowLiteRecipes/Net_TConv_Slice_003/test.recipe
new file mode 100644 (file)
index 0000000..a3bffec
--- /dev/null
@@ -0,0 +1,99 @@
+# test for original `same` padding and non-zero offset
+# TConv(pad=same, krnl=(32, 3, 3, 32))->Slice(begin = (0, 1, 1, 0), size = (0, 15, 15, 32))=TConv
+
+operand {
+  name: "tconv_shape"
+  type: INT32
+  shape {
+    dim: 4
+  }
+  filler {
+    tag: "explicit"
+    arg: "1"
+    arg: "16"
+    arg: "16"
+    arg: "32"
+  }
+}
+operand {
+  name: "filter"
+  type: FLOAT32
+  shape { dim: 32 dim: 3 dim: 3 dim: 32 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 8 dim: 8 dim: 32 }
+}
+operand {
+  name: "bias"
+  type: FLOAT32
+  shape { dim: 32 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm_tconv"
+  type: FLOAT32
+  shape { dim: 1 dim: 16 dim: 16 dim: 32 }
+}
+operation {
+  type: "TransposeConv"
+  input: "tconv_shape"
+  input: "filter"
+  input: "ifm"
+  input: "bias"
+  output: "ofm_tconv"
+  transpose_conv_options {
+    padding: SAME
+    stride_w: 2
+    stride_h: 2
+    activation: RELU
+  }
+}
+operand {
+  name: "offset"
+  type: INT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "0"
+    arg: "1"
+    arg: "1"
+    arg: "0"
+  }
+}
+operand {
+  name: "size"
+  type: INT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "1" 
+    arg: "15" 
+    arg: "15"
+    arg: "32"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 15 dim: 15 dim: 32 }
+}
+operation {
+  type: "Slice"
+  input: "ofm_tconv"
+  input: "offset"
+  input: "size"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_TConv_Slice_003/test.rule b/res/TensorFlowLiteRecipes/Net_TConv_Slice_003/test.rule
new file mode 100644 (file)
index 0000000..bb264e1
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if TConv->Slice is converted to TConv operation
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "TCONV_EXIST"             $(op_count TRANSPOSE_CONV) '=' 1
+RULE    "SLICE_NOT_EXIST"         $(op_count SLICE) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Net_Trans_Reshape_Trans_000/test.recipe b/res/TensorFlowLiteRecipes/Net_Trans_Reshape_Trans_000/test.recipe
new file mode 100644 (file)
index 0000000..a65f4bb
--- /dev/null
@@ -0,0 +1,67 @@
+operand 
+{
+  name : "ifm"
+  type : FLOAT32
+  shape {dim: 1, dim: 7, dim: 7, dim : 20}
+}
+operand 
+{
+  name : "front_perm"
+  type : INT32
+  shape {dim : 4}
+  filler {tag: "explicit" arg: "0", arg: "3", arg:"1", arg: "2"}
+}
+operand
+{
+  name : "front_transpose_out"
+  type : FLOAT32
+  shape {dim: 1, dim: 20, dim:7, dim:7} 
+}
+operand
+{
+  name : "shape"
+  type : INT32
+  shape {dim: 3}
+  filler {tag: "explicit", arg: "1", arg: "20", arg: "49"}
+}
+operand
+{
+  name : "reshape_out"
+  type : FLOAT32
+  shape : {dim: 1, dim:20, dim:49}
+}
+operand 
+{
+  name : "back_perm"
+  type : INT32
+  shape {dim : 3}
+  filler {tag: "explicit" arg: "0", arg: "2", arg:"1"}
+}
+operand
+{
+  name : "ofm"
+  type : FLOAT32
+  shape {dim: 1, dim: 49, dim:20} 
+}
+operation {
+  type: "Transpose"
+  input: "ifm"
+  input: "front_perm"
+  output: "front_transpose_out"
+}
+operation {
+  type: "Reshape"
+  input: "front_transpose_out"
+  input: "shape"
+  output: "reshape_out"
+}
+operation
+{
+  type: "Transpose"
+  input: "reshape_out"
+  input: "back_perm"
+  output: "ofm"
+} 
+
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Net_Trans_Reshape_Trans_000/test.rule b/res/TensorFlowLiteRecipes/Net_Trans_Reshape_Trans_000/test.rule
new file mode 100644 (file)
index 0000000..2ecfcac
--- /dev/null
@@ -0,0 +1,6 @@
+# To check if unnecessary Transposes are removed in Transpose-Reshape-Transpose
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "TRANSPOSE_NOT_EXIST"     $(op_count TRANSPOSE) '=' 0
+RULE    "RESHAPE_EXIST"           $(op_count RESHAPE) '=' 1
diff --git a/res/TensorFlowLiteRecipes/Quant_Mul_002/test.qconf.json b/res/TensorFlowLiteRecipes/Quant_Mul_002/test.qconf.json
new file mode 100644 (file)
index 0000000..010fa65
--- /dev/null
@@ -0,0 +1,11 @@
+{
+    "default_quantization_dtype" : "int16",
+    "default_granularity" : "channel",
+    "layers" : [
+        {
+            "name" : "ofm",
+            "dtype" : "uint8",
+            "granularity" : "channel"
+        }
+    ]
+}
diff --git a/res/TensorFlowLiteRecipes/Quant_Mul_002/test.recipe b/res/TensorFlowLiteRecipes/Quant_Mul_002/test.recipe
new file mode 100644 (file)
index 0000000..14d7854
--- /dev/null
@@ -0,0 +1,21 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 3 }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 3 }
+}
+operation {
+  type: "Mul"
+  input: "ifm"
+  input: "ifm"
+  output: "ofm"
+  mul_options {
+    activation: NONE
+  }
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Quant_Mul_002/test.rule b/res/TensorFlowLiteRecipes/Quant_Mul_002/test.rule
new file mode 100644 (file)
index 0000000..b4ac13a
--- /dev/null
@@ -0,0 +1,11 @@
+# To check mixed quantization. Mul's inputs are the same node.
+# Default dtype: S16, Target Op dtype: U8
+# Quantize Ops are inserted at the beginning/end of the model.
+
+RULE    "VERIFY_FILE_FORMAT"     $(verify_file_format) '=' 1
+
+RULE    "IFM_S16"                $(tensor_dtype ifm) '=' INT16
+RULE    "IFM_QUANTIZE_U8"        $(tensor_dtype ifm_Quantize) '=' UINT8
+RULE    "TARGET_U8"              $(tensor_dtype ofm) '=' UINT8
+RULE    "OUTPUT_S16"             $(tensor_dtype ofm_Quantize) '=' INT16
+RULE    "QUANTIZE_OP"            $(op_count QUANTIZE) '=' 2
diff --git a/res/TensorFlowLiteRecipes/ReLU0To1_000/test.recipe b/res/TensorFlowLiteRecipes/ReLU0To1_000/test.recipe
new file mode 100644 (file)
index 0000000..75fd0fa
--- /dev/null
@@ -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: "ReLU0To1"
+  input: "ifm"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/ReLU0To1_000/test.reverse b/res/TensorFlowLiteRecipes/ReLU0To1_000/test.reverse
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/res/TensorFlowLiteRecipes/Softmax_001/test.recipe b/res/TensorFlowLiteRecipes/Softmax_001/test.recipe
new file mode 100644 (file)
index 0000000..08b9b7d
--- /dev/null
@@ -0,0 +1,20 @@
+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: "Softmax"
+  softmax_options {
+    beta: 1.0
+  }
+  input: "ifm"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Softmax_001/test.rule b/res/TensorFlowLiteRecipes/Softmax_001/test.rule
new file mode 100644 (file)
index 0000000..aec813b
--- /dev/null
@@ -0,0 +1,11 @@
+# To check if Softmax is converted to Max, Sub, Exp, Sum and Div operations
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "REDUCE_MAX_EXIST"        $(op_count REDUCE_MAX) '=' 1
+RULE    "SUB_EXIST"               $(op_count SUB) '=' 1
+RULE    "MUL_NOT_EXIST"           $(op_count MUL) '=' 0
+RULE    "EXP_EXIST"               $(op_count EXP) '=' 1
+RULE    "SUM_EXIST"               $(op_count SUM) '=' 1
+RULE    "DIV_EXIST"               $(op_count DIV) '=' 1
+RULE    "SOFTMAX_NOT_EXIST"       $(op_count SOFTMAX) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Softmax_002/test.recipe b/res/TensorFlowLiteRecipes/Softmax_002/test.recipe
new file mode 100644 (file)
index 0000000..0a82b8f
--- /dev/null
@@ -0,0 +1,20 @@
+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: "Softmax"
+  softmax_options {
+    beta: 0.5
+  }
+  input: "ifm"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Softmax_002/test.rule b/res/TensorFlowLiteRecipes/Softmax_002/test.rule
new file mode 100644 (file)
index 0000000..142ceb6
--- /dev/null
@@ -0,0 +1,11 @@
+# To check if Softmax is converted to Max, Sub, Exp, Sum and Div operations
+
+RULE    "VERIFY_FILE_FORMAT"      $(verify_file_format) '=' 1
+
+RULE    "REDUCE_MAX_EXIST"        $(op_count REDUCE_MAX) '=' 1
+RULE    "SUB_EXIST"               $(op_count SUB) '=' 1
+RULE    "MUL_EXIST"               $(op_count MUL) '=' 1
+RULE    "EXP_EXIST"               $(op_count EXP) '=' 1
+RULE    "SUM_EXIST"               $(op_count SUM) '=' 1
+RULE    "DIV_EXIST"               $(op_count DIV) '=' 1
+RULE    "SOFTMAX_NOT_EXIST"       $(op_count SOFTMAX) '=' 0
diff --git a/res/TensorFlowLiteRecipes/Tile_001/test.recipe b/res/TensorFlowLiteRecipes/Tile_001/test.recipe
new file mode 100644 (file)
index 0000000..cbca5b0
--- /dev/null
@@ -0,0 +1,29 @@
+# mulplies 2D, dim(0) and dim(1)
+
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 2 dim: 3 }
+}
+operand {
+  name: "multiples"
+  type: INT32
+  shape { dim: 2 }
+  filler {
+    tag: "explicit"
+    arg: "2" arg: "2"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 4 dim: 6 }
+}
+operation {
+  type: "Tile"
+  input: "ifm"
+  input: "multiples"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Tile_001/test.reverse b/res/TensorFlowLiteRecipes/Tile_001/test.reverse
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/res/TensorFlowLiteRecipes/Tile_002/test.recipe b/res/TensorFlowLiteRecipes/Tile_002/test.recipe
new file mode 100644 (file)
index 0000000..cc6fda9
--- /dev/null
@@ -0,0 +1,29 @@
+# mulplies 4D , dim(0) and dim(2)
+
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 2 dim: 3 dim: 4 dim: 5 }
+}
+operand {
+  name: "multiples"
+  type: INT32
+  shape { dim: 4 }
+  filler {
+    tag: "explicit"
+    arg: "2" arg: "1" arg: "2" arg: "1"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 4 dim: 3 dim: 8 dim: 5 }
+}
+operation {
+  type: "Tile"
+  input: "ifm"
+  input: "multiples"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/res/TensorFlowLiteRecipes/Tile_002/test.reverse b/res/TensorFlowLiteRecipes/Tile_002/test.reverse
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/res/TensorFlowLiteRecipes/TransposeConv_002/test.recipe b/res/TensorFlowLiteRecipes/TransposeConv_002/test.recipe
new file mode 100644 (file)
index 0000000..a194914
--- /dev/null
@@ -0,0 +1,48 @@
+operand {
+  name: "ifm"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 3 }
+}
+operand {
+  name: "out_shape"
+  type: INT32
+  shape { dim: 4 }
+}
+operand {
+  name: "ker"
+  type: FLOAT32
+  shape { dim: 3 dim: 1 dim: 1 dim: 3 }
+  filler {
+    tag: "gaussian"
+    arg: "0.0"
+    arg: "1.0"
+  }
+}
+operand {
+  name: "ofm"
+  type: FLOAT32
+  shape { dim: 1 dim: 4 dim: 4 dim: 3 }
+}
+operation {
+  type: "Shape"
+  shape_options {
+    out_type: INT32
+  }
+  input: "ifm"
+  output: "out_shape"
+}
+operation {
+  type: "TransposeConv"
+  transpose_conv_options {
+    padding: SAME
+    stride_w: 1
+    stride_h: 1
+    activation: NONE
+  }
+  input: "out_shape"
+  input: "ker"
+  input: "ifm"
+  output: "ofm"
+}
+input: "ifm"
+output: "ofm"
diff --git a/runtime/3rdparty/half/README.md b/runtime/3rdparty/half/README.md
new file mode 100644 (file)
index 0000000..b1000b7
--- /dev/null
@@ -0,0 +1,7 @@
+# Origin of source code
+
+This library is based on half sourceforge(https://sourceforge.net/projects/half/files/half/)
+
+# Version
+
+- 2.2.0 : https://sourceforge.net/projects/half/files/half/2.2.0/
index d9fc2bb..c7489b2 100644 (file)
@@ -1,6 +1,14 @@
-Release Notes
+Release Notes                                                                                  {#changelog}
 =============
 
+2.2.0 release (2021-06-12):
+---------------------------
+
+- Added `rsqrt` function for inverse square root.
+- Improved performance of `pow` function.
+- Fixed bug that forgot to include `<immintrin.h>` for F16C intrinsics.
+
+
 2.1.0 release (2019-08-05):
 ---------------------------
 
index 36c20d1..6023222 100644 (file)
@@ -1,6 +1,6 @@
 The MIT License
 
-Copyright (c) 2012-2019 Christian Rau
+Copyright (c) 2012-2021 Christian Rau
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
index b8ca7ea..c7bf315 100644 (file)
@@ -1,4 +1,4 @@
-HALF-PRECISION FLOATING-POINT LIBRARY (Version 2.1.0)
+HALF-PRECISION FLOATING-POINT LIBRARY (Version 2.2.0)
 -----------------------------------------------------
 
 This is a C++ header-only library to provide an IEEE 754 conformant 16-bit 
index 0f60403..d0a882d 100644 (file)
@@ -1,6 +1,6 @@
 // half - IEEE 754-based half-precision floating-point library.
 //
-// Copyright (c) 2012-2019 Christian Rau <rauy@users.sourceforge.net>
+// Copyright (c) 2012-2021 Christian Rau <rauy@users.sourceforge.net>
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
 // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 
@@ -14,7 +14,7 @@
 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-// Version 2.1.0
+// Version 2.2.0
 
 /// \file
 /// Main header file for half-precision functionality.
 #if HALF_ENABLE_CPP11_HASH
        #include <functional>
 #endif
-#if HALF_ENABLE_F16C_INTRINSICS
-       #include <immintrin.h>
-#endif
 
 
 #ifndef HALF_ENABLE_F16C_INTRINSICS
        /// Unless predefined it will be enabled automatically when the `__F16C__` symbol is defined, which some compilers do on supporting platforms.
        #define HALF_ENABLE_F16C_INTRINSICS __F16C__
 #endif
+#if HALF_ENABLE_F16C_INTRINSICS
+       #include <immintrin.h>
+#endif
 
 #ifdef HALF_DOXYGEN_ONLY
 /// Type for internal floating-point computations.
@@ -869,12 +869,12 @@ namespace half_float
 
                /// Convert fixed point to half-precision floating-point.
                /// \tparam R rounding mode to use
-               /// \tparam F number of fractional bits (at least 11)
+               /// \tparam F number of fractional bits in [11,31]
                /// \tparam S `true` for signed, `false` for unsigned
                /// \tparam N `true` for additional normalization step, `false` if already normalized to 1.F
                /// \tparam I `true` to always raise INEXACT exception, `false` to raise only for rounded results
                /// \param m mantissa in Q1.F fixed point format
-               /// \param exp exponent
+               /// \param exp biased exponent - 1
                /// \param sign half-precision value with sign bit only
                /// \param s sticky bit (or of all but the most significant already discarded bits)
                /// \return value converted to half-precision
@@ -1676,34 +1676,34 @@ namespace half_float
 
                /// Postprocessing for binary exponential.
                /// \tparam R rounding mode to use
-               /// \tparam I `true` to always raise INEXACT exception, `false` to raise only for rounded results
-               /// \param m mantissa as Q1.31
+               /// \param m fractional part of as Q0.31
                /// \param exp absolute value of unbiased exponent
                /// \param esign sign of actual exponent
                /// \param sign sign bit of result
+               /// \param n number of BKM iterations (at most 32)
                /// \return value converted to half-precision
                /// \exception FE_OVERFLOW on overflows
                /// \exception FE_UNDERFLOW on underflows
                /// \exception FE_INEXACT if value had to be rounded or \a I is `true`
-               template<std::float_round_style R,bool I> unsigned int exp2_post(uint32 m, int exp, bool esign, unsigned int sign = 0)
+               template<std::float_round_style R> unsigned int exp2_post(uint32 m, int exp, bool esign, unsigned int sign = 0, unsigned int n = 32)
                {
-                       int s = 0;
                        if(esign)
                        {
-                               if(m > 0x80000000)
-                               {
-                                       m = divide64(0x80000000, m, s);
-                                       ++exp;
-                               }
-                               if(exp > 25)
+                               exp = -exp - (m!=0);
+                               if(exp < -25)
                                        return underflow<R>(sign);
-                               else if(exp == 25)
-                                       return rounded<R,I>(sign, 1, (m&0x7FFFFFFF)!=0);
-                               exp = -exp;
+                               else if(exp == -25)
+                                       return rounded<R,false>(sign, 1, m!=0);
                        }
                        else if(exp > 15)
                                return overflow<R>(sign);
-                       return fixed2half<R,31,false,false,I>(m, exp+14, sign, s);
+                       if(!m)
+                               return sign | (((exp+=15)>0) ? (exp<<10) : check_underflow(0x200>>-exp));
+                       m = exp2(m, n);
+                       int s = 0;
+                       if(esign)
+                               m = divide64(0x80000000, m, s);
+                       return fixed2half<R,31,false,false,true>(m, exp+14, sign, s);
                }
 
                /// Postprocessing for binary logarithm.
@@ -1737,7 +1737,7 @@ namespace half_float
                /// Hypotenuse square root and postprocessing.
                /// \tparam R rounding mode to use
                /// \param r mantissa as Q2.30
-               /// \param exp unbiased exponent
+               /// \param exp biased exponent
                /// \return square root converted to half-precision
                /// \exception FE_OVERFLOW on overflows
                /// \exception FE_UNDERFLOW on underflows
@@ -2201,6 +2201,7 @@ namespace half_float
                friend half log2(half);
                friend half log1p(half);
                friend half sqrt(half);
+               friend half rsqrt(half);
                friend half cbrt(half);
                friend half hypot(half, half);
                friend half hypot(half, half, half);
@@ -2937,7 +2938,7 @@ namespace half_float
        #ifdef HALF_ARITHMETIC_TYPE
                return half(detail::binary, detail::float2half<half::round_style>(std::exp(detail::half2float<detail::internal_t>(arg.data_))));
        #else
-               int abs = arg.data_ & 0x7FFF;
+               int abs = arg.data_ & 0x7FFF, e = (abs>>10) + (abs<=0x3FF), exp;
                if(!abs)
                        return half(detail::binary, 0x3C00);
                if(abs >= 0x7C00)
@@ -2945,7 +2946,6 @@ namespace half_float
                if(abs >= 0x4C80)
                        return half(detail::binary, (arg.data_&0x8000) ? detail::underflow<half::round_style>() : detail::overflow<half::round_style>());
                detail::uint32 m = detail::multiply64(static_cast<detail::uint32>((abs&0x3FF)+((abs>0x3FF)<<10))<<21, 0xB8AA3B29);
-               int e = (abs>>10) + (abs<=0x3FF), exp;
                if(e < 14)
                {
                        exp = 0;
@@ -2956,7 +2956,7 @@ namespace half_float
                        exp = m >> (45-e);
                        m = (m<<(e-14)) & 0x7FFFFFFF;
                }
-               return half(detail::binary, detail::exp2_post<half::round_style,true>(detail::exp2(m, 26), exp, (arg.data_&0x8000)!=0));
+               return half(detail::binary, detail::exp2_post<half::round_style>(m, exp, (arg.data_&0x8000)!=0, 0, 26));
        #endif
        }
 
@@ -2973,25 +2973,15 @@ namespace half_float
        #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
                return half(detail::binary, detail::float2half<half::round_style>(std::exp2(detail::half2float<detail::internal_t>(arg.data_))));
        #else
-               int abs = arg.data_ & 0x7FFF;
+               int abs = arg.data_ & 0x7FFF, e = (abs>>10) + (abs<=0x3FF), exp = (abs&0x3FF) + ((abs>0x3FF)<<10);
                if(!abs)
                        return half(detail::binary, 0x3C00);
                if(abs >= 0x7C00)
                        return half(detail::binary, (abs==0x7C00) ? (0x7C00&((arg.data_>>15)-1U)) : detail::signal(arg.data_));
                if(abs >= 0x4E40)
                        return half(detail::binary, (arg.data_&0x8000) ? detail::underflow<half::round_style>() : detail::overflow<half::round_style>());
-               int e = (abs>>10) + (abs<=0x3FF), exp = (abs&0x3FF) + ((abs>0x3FF)<<10);
-               detail::uint32 m = detail::exp2((static_cast<detail::uint32>(exp)<<(6+e))&0x7FFFFFFF, 28);
-               exp >>= 25 - e;
-               if(m == 0x80000000)
-               {
-                       if(arg.data_&0x8000)
-                               exp = -exp;
-                       else if(exp > 15)
-                               return half(detail::binary, detail::overflow<half::round_style>());
-                       return half(detail::binary, detail::fixed2half<half::round_style,31,false,false,false>(m, exp+14));
-               }
-               return half(detail::binary, detail::exp2_post<half::round_style,true>(m, exp, (arg.data_&0x8000)!=0));
+               return half(detail::binary, detail::exp2_post<half::round_style>(
+                       (static_cast<detail::uint32>(exp)<<(6+e))&0x7FFFFFFF, exp>>(25-e), (arg.data_&0x8000)!=0, 0, 28));
        #endif
        }
 
@@ -3009,7 +2999,7 @@ namespace half_float
        #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
                return half(detail::binary, detail::float2half<half::round_style>(std::expm1(detail::half2float<detail::internal_t>(arg.data_))));
        #else
-               unsigned int abs = arg.data_ & 0x7FFF, sign = arg.data_ & 0x8000;
+               unsigned int abs = arg.data_ & 0x7FFF, sign = arg.data_ & 0x8000, e = (abs>>10) + (abs<=0x3FF), exp;
                if(!abs)
                        return arg;
                if(abs >= 0x7C00)
@@ -3017,7 +3007,6 @@ namespace half_float
                if(abs >= 0x4A00)
                        return half(detail::binary, (arg.data_&0x8000) ? detail::rounded<half::round_style,true>(0xBBFF, 1, 1) : detail::overflow<half::round_style>());
                detail::uint32 m = detail::multiply64(static_cast<detail::uint32>((abs&0x3FF)+((abs>0x3FF)<<10))<<21, 0xB8AA3B29);
-               int e = (abs>>10) + (abs<=0x3FF), exp;
                if(e < 14)
                {
                        exp = 0;
@@ -3213,7 +3202,7 @@ namespace half_float
        /// \param arg function argument
        /// \return square root of \a arg
        /// \exception FE_INVALID for signaling NaN and negative arguments
-       /// \exception FE_OVERFLOW, ...UNDERFLOW, ...INEXACT according to rounding
+       /// \exception FE_INEXACT according to rounding
        inline half sqrt(half arg)
        {
        #ifdef HALF_ARITHMETIC_TYPE
@@ -3228,6 +3217,42 @@ namespace half_float
        #endif
        }
 
+       /// Inverse square root.
+       /// This function is exact to rounding for all rounding modes and thus generally more accurate than directly computing 
+       /// 1 / sqrt(\a arg) in half-precision, in addition to also being faster.
+       /// \param arg function argument
+       /// \return reciprocal of square root of \a arg
+       /// \exception FE_INVALID for signaling NaN and negative arguments
+       /// \exception FE_INEXACT according to rounding
+       inline half rsqrt(half arg)
+       {
+       #ifdef HALF_ARITHMETIC_TYPE
+               return half(detail::binary, detail::float2half<half::round_style>(detail::internal_t(1)/std::sqrt(detail::half2float<detail::internal_t>(arg.data_))));
+       #else
+               unsigned int abs = arg.data_ & 0x7FFF, bias = 0x4000;
+               if(!abs || arg.data_ >= 0x7C00)
+                       return half(detail::binary,     (abs>0x7C00) ? detail::signal(arg.data_) : (arg.data_>0x8000) ?
+                                                                               detail::invalid() : !abs ? detail::pole(arg.data_&0x8000) : 0);
+               for(; abs<0x400; abs<<=1,bias-=0x400) ;
+               unsigned int frac = (abs+=bias) & 0x7FF;
+               if(frac == 0x400)
+                       return half(detail::binary, 0x7A00-(abs>>1));
+               if((half::round_style == std::round_to_nearest && (frac == 0x3FE || frac == 0x76C)) ||
+                  (half::round_style != std::round_to_nearest && (frac == 0x15A || frac == 0x3FC || frac == 0x401 || frac == 0x402 || frac == 0x67B)))
+                       return pow(arg, half(detail::binary, 0xB800));
+               detail::uint32 f = 0x17376 - abs, mx = (abs&0x3FF) | 0x400, my = ((f>>1)&0x3FF) | 0x400, mz = my * my;
+               int expy = (f>>11) - 31, expx = 32 - (abs>>10), i = mz >> 21;
+               for(mz=0x60000000-(((mz>>i)*mx)>>(expx-2*expy-i)); mz<0x40000000; mz<<=1,--expy) ;
+               i = (my*=mz>>10) >> 31;
+               expy += i;
+               my = (my>>(20+i)) + 1;
+               i = (mz=my*my) >> 21;
+               for(mz=0x60000000-(((mz>>i)*mx)>>(expx-2*expy-i)); mz<0x40000000; mz<<=1,--expy) ;
+               i = (my*=(mz>>10)+1) >> 31;
+               return half(detail::binary, detail::fixed2half<half::round_style,30,false,false,true>(my>>i, expy+i+14));
+       #endif
+       }
+
        /// Cubic root.
        /// This function is exact to rounding for all rounding modes.
        ///
@@ -3235,7 +3260,7 @@ namespace half_float
        /// \param arg function argument
        /// \return cubic root of \a arg
        /// \exception FE_INVALID for signaling NaN
-       /// \exception FE_OVERFLOW, ...UNDERFLOW, ...INEXACT according to rounding
+       /// \exception FE_INEXACT according to rounding
        inline half cbrt(half arg)
        {
        #if defined(HALF_ARITHMETIC_TYPE) && HALF_ENABLE_CPP11_CMATH
@@ -3419,12 +3444,13 @@ namespace half_float
                        return half(detail::binary, detail::invalid());
                if(x.data_ == 0xBC00)
                        return half(detail::binary, sign|0x3C00);
-               if(y.data_ == 0x3800)
-                       return sqrt(x);
-               if(y.data_ == 0x3C00)
-                       return half(detail::binary, detail::check_underflow(x.data_));
-               if(y.data_ == 0x4000)
-                       return x * x;
+               switch(y.data_)
+               {
+                       case 0x3800: return sqrt(x);
+                       case 0x3C00: return half(detail::binary, detail::check_underflow(x.data_));
+                       case 0x4000: return x * x;
+                       case 0xBC00: return half(detail::binary, 0x3C00) / x;
+               }
                for(; absx<0x400; absx<<=1,--exp) ;
                detail::uint32 ilog = exp + (absx>>10), msign = detail::sign_mask(ilog), f, m = 
                        (((ilog<<27)+((detail::log2(static_cast<detail::uint32>((absx&0x3FF)|0x400)<<20)+8)>>4))^msign) - msign;
@@ -3444,7 +3470,7 @@ namespace half_float
                        f = (m<<exp) & 0x7FFFFFFF;
                        exp = m >> (31-exp);
                }
-               return half(detail::binary, detail::exp2_post<half::round_style,false>(detail::exp2(f), exp, ((msign&1)^(y.data_>>15))!=0, sign));
+               return half(detail::binary, detail::exp2_post<half::round_style>(f, exp, ((msign&1)^(y.data_>>15))!=0, sign));
        #endif
        }
 
index da5a06d..8c75e92 100644 (file)
@@ -1,6 +1,6 @@
 # Origin of source code
 
-This library is based on Json-cpp amalgated header and cpp files(https://github.com/open-source-parsers/jsoncpp/wiki/Amalgamated)
+This library is based on Json-cpp amalgated header and cpp files(https://github.com/open-source-parsers/jsoncpp/wiki/Amalgamated-(Possibly-outdated))
 
 # Background
 
@@ -8,4 +8,4 @@ Since jsoncpp on tizen does not support static jsoncpp library, nnfw project wil
 
 # Version
 
-- 1.7.7 : https://github.com/open-source-parsers/jsoncpp/archive/1.7.7.tar.gz
+- 1.9.5 : https://github.com/open-source-parsers/jsoncpp/archive/1.9.5.tar.gz
index 9fe95c0..87038fd 100644 (file)
@@ -1,4 +1,4 @@
-/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).
+/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).
 /// It is intended to be used with #include "json/json-forwards.h"
 /// This header provides forward declaration for all JsonCpp types.
 
@@ -11,13 +11,13 @@ The JsonCpp library's source code, including accompanying documentation,
 tests and demonstration applications, are licensed under the following
 conditions...
 
-The author (Baptiste Lepilleur) explicitly disclaims copyright in all
+Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
 jurisdictions which recognize such a disclaimer. In such jurisdictions,
 this software is released into the Public Domain.
 
 In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
-2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
-released under the terms of the MIT License (see below).
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
+The JsonCpp Authors, and is released under the terms of the MIT License (see below).
 
 In jurisdictions which recognize Public Domain property, the user of this
 software may choose to accept it either as 1) Public Domain, 2) under the
@@ -32,7 +32,7 @@ described in clear, concise terms at:
 The full text of the MIT License follows:
 
 ========================================================================
-Copyright (c) 2007-2010 Baptiste Lepilleur
+Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
@@ -69,36 +69,175 @@ license you like.
 // End of content of file: LICENSE
 // //////////////////////////////////////////////////////////////////////
 
-#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
-#define JSON_FORWARD_AMALGATED_H_INCLUDED
-/// If defined, indicates that the source file is amalgated
+#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED
+#define JSON_FORWARD_AMALGAMATED_H_INCLUDED
+/// If defined, indicates that the source file is amalgamated
 /// to prevent private header inclusion.
 #define JSON_IS_AMALGAMATION
 
 // //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/version.h
+// //////////////////////////////////////////////////////////////////////
+
+#ifndef JSON_VERSION_H_INCLUDED
+#define JSON_VERSION_H_INCLUDED
+
+// Note: version must be updated in three places when doing a release. This
+// annoying process ensures that amalgamate, CMake, and meson all report the
+// correct version.
+// 1. /meson.build
+// 2. /include/json/version.h
+// 3. /CMakeLists.txt
+// IMPORTANT: also update the SOVERSION!!
+
+#define JSONCPP_VERSION_STRING "1.9.5"
+#define JSONCPP_VERSION_MAJOR 1
+#define JSONCPP_VERSION_MINOR 9
+#define JSONCPP_VERSION_PATCH 5
+#define JSONCPP_VERSION_QUALIFIER
+#define JSONCPP_VERSION_HEXA \
+  ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
+
+#ifdef JSONCPP_USING_SECURE_MEMORY
+#undef JSONCPP_USING_SECURE_MEMORY
+#endif
+#define JSONCPP_USING_SECURE_MEMORY 0
+// If non-zero, the library zeroes any memory that it has allocated before
+// it frees its memory.
+
+#endif // JSON_VERSION_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/version.h
+// //////////////////////////////////////////////////////////////////////
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/allocator.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_ALLOCATOR_H_INCLUDED
+#define JSON_ALLOCATOR_H_INCLUDED
+
+#include <cstring>
+#include <memory>
+
+#pragma pack(push, 8)
+
+namespace Json
+{
+template <typename T> class SecureAllocator
+{
+public:
+  // Type definitions
+  using value_type = T;
+  using pointer = T *;
+  using const_pointer = const T *;
+  using reference = T &;
+  using const_reference = const T &;
+  using size_type = std::size_t;
+  using difference_type = std::ptrdiff_t;
+
+  /**
+   * Allocate memory for N items using the standard allocator.
+   */
+  pointer allocate(size_type n)
+  {
+    // allocate using "global operator new"
+    return static_cast<pointer>(::operator new(n * sizeof(T)));
+  }
+
+  /**
+   * Release memory which was allocated for N items at pointer P.
+   *
+   * The memory block is filled with zeroes before being released.
+   */
+  void deallocate(pointer p, size_type n)
+  {
+    // memset_s is used because memset may be optimized away by the compiler
+    memset_s(p, n * sizeof(T), 0, n * sizeof(T));
+    // free using "global operator delete"
+    ::operator delete(p);
+  }
+
+  /**
+   * Construct an item in-place at pointer P.
+   */
+  template <typename... Args> void construct(pointer p, Args &&...args)
+  {
+    // construct using "placement new" and "perfect forwarding"
+    ::new (static_cast<void *>(p)) T(std::forward<Args>(args)...);
+  }
+
+  size_type max_size() const { return size_t(-1) / sizeof(T); }
+
+  pointer address(reference x) const { return std::addressof(x); }
+
+  const_pointer address(const_reference x) const { return std::addressof(x); }
+
+  /**
+   * Destroy an item in-place at pointer P.
+   */
+  void destroy(pointer p)
+  {
+    // destroy using "explicit destructor"
+    p->~T();
+  }
+
+  // Boilerplate
+  SecureAllocator() {}
+  template <typename U> SecureAllocator(const SecureAllocator<U> &) {}
+  template <typename U> struct rebind
+  {
+    using other = SecureAllocator<U>;
+  };
+};
+
+template <typename T, typename U>
+bool operator==(const SecureAllocator<T> &, const SecureAllocator<U> &)
+{
+  return true;
+}
+
+template <typename T, typename U>
+bool operator!=(const SecureAllocator<T> &, const SecureAllocator<U> &)
+{
+  return false;
+}
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#endif // JSON_ALLOCATOR_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/allocator.h
+// //////////////////////////////////////////////////////////////////////
+
+// //////////////////////////////////////////////////////////////////////
 // Beginning of content of file: include/json/config.h
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 
 #ifndef JSON_CONFIG_H_INCLUDED
 #define JSON_CONFIG_H_INCLUDED
-#include <stddef.h>
-#include <string>   //typedef String
-#include <stdint.h> //typedef int64_t, uint64_t
-
-/// If defined, indicates that json library is embedded in CppTL library.
-//# define JSON_IN_CPPTL 1
-
-/// If defined, indicates that json may leverage CppTL library
-//#  define JSON_USE_CPPTL 1
-/// If defined, indicates that cpptl vector based map should be used instead of
-/// std::map
-/// as Value container.
-//#  define JSON_USE_CPPTL_SMALLMAP 1
+#include <cstddef>
+#include <cstdint>
+#include <istream>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <type_traits>
 
 // If non-zero, the library uses exceptions to report bad input instead of C
 // assertion macros. The default is to use exceptions.
@@ -106,158 +245,129 @@ license you like.
 #define JSON_USE_EXCEPTION 1
 #endif
 
-/// If defined, indicates that the source file is amalgated
+// Temporary, tracked for removal with issue #982.
+#ifndef JSON_USE_NULLREF
+#define JSON_USE_NULLREF 1
+#endif
+
+/// If defined, indicates that the source file is amalgamated
 /// to prevent private header inclusion.
-/// Remarks: it is automatically defined in the generated amalgated header.
+/// Remarks: it is automatically defined in the generated amalgamated header.
 // #define JSON_IS_AMALGAMATION
 
-#ifdef JSON_IN_CPPTL
-#include <cpptl/config.h>
-#ifndef JSON_USE_CPPTL
-#define JSON_USE_CPPTL 1
-#endif
-#endif
-
-#ifdef JSON_IN_CPPTL
-#define JSON_API CPPTL_API
-#elif defined(JSON_DLL_BUILD)
+// Export macros for DLL visibility
+#if defined(JSON_DLL_BUILD)
 #if defined(_MSC_VER) || defined(__MINGW32__)
 #define JSON_API __declspec(dllexport)
 #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#elif defined(__GNUC__) || defined(__clang__)
+#define JSON_API __attribute__((visibility("default")))
 #endif // if defined(_MSC_VER)
+
 #elif defined(JSON_DLL)
 #if defined(_MSC_VER) || defined(__MINGW32__)
 #define JSON_API __declspec(dllimport)
 #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
 #endif // if defined(_MSC_VER)
-#endif // ifdef JSON_IN_CPPTL
+#endif // ifdef JSON_DLL_BUILD
+
 #if !defined(JSON_API)
 #define JSON_API
 #endif
 
-// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
-// integer
-// Storages, and 64 bits integer support is disabled.
-// #define JSON_NO_INT64 1
-
-#if defined(_MSC_VER) // MSVC
-#if _MSC_VER <= 1200  // MSVC 6
-                      // Microsoft Visual Studio 6 only support conversion from __int64 to double
-                      // (no conversion from unsigned __int64).
-#define JSON_USE_INT64_DOUBLE_CONVERSION 1
-// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
-// characters in the debug information)
-// All projects I've ever seen with VS6 were using this globally (not bothering
-// with pragma push/pop).
-#pragma warning(disable : 4786)
-#endif // MSVC 6
-
-#if _MSC_VER >= 1500 // MSVC 2008
-                     /// Indicates that the following function is deprecated.
-#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#if defined(_MSC_VER) && _MSC_VER < 1800
+#error \
+  "ERROR:  Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
 #endif
 
-#endif // defined(_MSC_VER)
-
-// In c++11 the override keyword allows you to explicity define that a function
-// is intended to override the base-class version.  This makes the code more
-// managable and fixes a set of common hard-to-find bugs.
-#if __cplusplus >= 201103L
-#define JSONCPP_OVERRIDE override
-#elif defined(_MSC_VER) && _MSC_VER > 1600
-#define JSONCPP_OVERRIDE override
+#if defined(_MSC_VER) && _MSC_VER < 1900
+// As recommended at
+// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+extern JSON_API int msvc_pre1900_c99_snprintf(char *outBuf, size_t size, const char *format, ...);
+#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
 #else
-#define JSONCPP_OVERRIDE
+#define jsoncpp_snprintf std::snprintf
 #endif
 
-#ifndef JSON_HAS_RVALUE_REFERENCES
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
 
-#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif // MSVC >= 2010
+// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
+// C++11 should be used directly in JSONCPP.
+#define JSONCPP_OVERRIDE override
 
 #ifdef __clang__
-#if __has_feature(cxx_rvalue_references)
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif // has_feature
-
-#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
-#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif // GXX_EXPERIMENTAL
-
-#endif // __clang__ || __GNUC__
-
-#endif // not defined JSON_HAS_RVALUE_REFERENCES
-
-#ifndef JSON_HAS_RVALUE_REFERENCES
-#define JSON_HAS_RVALUE_REFERENCES 0
+#if __has_extension(attribute_deprecated_with_message)
+#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
 #endif
-
-#ifdef __clang__
-#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
 #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
 #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
 #elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
 #define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
-#endif // GNUC version
-#endif // __clang__ || __GNUC__
+#endif                  // GNUC version
+#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
+                        // MSVC)
+#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#endif // __clang__ || __GNUC__ || _MSC_VER
 
 #if !defined(JSONCPP_DEPRECATED)
 #define JSONCPP_DEPRECATED(message)
 #endif // if !defined(JSONCPP_DEPRECATED)
 
-#if __GNUC__ >= 6
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
 #define JSON_USE_INT64_DOUBLE_CONVERSION 1
 #endif
 
 #if !defined(JSON_IS_AMALGAMATION)
 
+#include "allocator.h"
 #include "version.h"
 
-#if JSONCPP_USING_SECURE_MEMORY
-#include "allocator.h" //typedef Allocator
-#endif
-
 #endif // if !defined(JSON_IS_AMALGAMATION)
 
 namespace Json
 {
-typedef int Int;
-typedef unsigned int UInt;
+using Int = int;
+using UInt = unsigned int;
 #if defined(JSON_NO_INT64)
-typedef int LargestInt;
-typedef unsigned int LargestUInt;
+using LargestInt = int;
+using LargestUInt = unsigned int;
 #undef JSON_HAS_INT64
 #else                 // if defined(JSON_NO_INT64)
 // For Microsoft Visual use specific types as long long is not supported
 #if defined(_MSC_VER) // Microsoft Visual Studio
-typedef __int64 Int64;
-typedef unsigned __int64 UInt64;
+using Int64 = __int64;
+using UInt64 = unsigned __int64;
 #else                 // if defined(_MSC_VER) // Other platforms, use long long
-typedef int64_t Int64;
-typedef uint64_t UInt64;
+using Int64 = int64_t;
+using UInt64 = uint64_t;
 #endif                // if defined(_MSC_VER)
-typedef Int64 LargestInt;
-typedef UInt64 LargestUInt;
+using LargestInt = Int64;
+using LargestUInt = UInt64;
 #define JSON_HAS_INT64
 #endif // if defined(JSON_NO_INT64)
-#if JSONCPP_USING_SECURE_MEMORY
-#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char>>
-#define JSONCPP_OSTRINGSTREAM \
-  std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char>>
-#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>>
-#define JSONCPP_ISTRINGSTREAM \
-  std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char>>
-#define JSONCPP_ISTREAM std::istream
-#else
-#define JSONCPP_STRING std::string
-#define JSONCPP_OSTRINGSTREAM std::ostringstream
-#define JSONCPP_OSTREAM std::ostream
-#define JSONCPP_ISTRINGSTREAM std::istringstream
-#define JSONCPP_ISTREAM std::istream
-#endif // if JSONCPP_USING_SECURE_MEMORY
-} // end namespace Json
+
+template <typename T>
+using Allocator = typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
+                                            std::allocator<T>>::type;
+using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
+using IStringStream =
+  std::basic_istringstream<String::value_type, String::traits_type, String::allocator_type>;
+using OStringStream =
+  std::basic_ostringstream<String::value_type, String::traits_type, String::allocator_type>;
+using IStream = std::istream;
+using OStream = std::ostream;
+} // namespace Json
+
+// Legacy names (formerly macros).
+using JSONCPP_STRING = Json::String;
+using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
+using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
+using JSONCPP_ISTREAM = Json::IStream;
+using JSONCPP_OSTREAM = Json::OStream;
 
 #endif // JSON_CONFIG_H_INCLUDED
 
@@ -269,7 +379,7 @@ typedef UInt64 LargestUInt;
 // Beginning of content of file: include/json/forwards.h
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -285,17 +395,23 @@ namespace Json
 {
 
 // writer.h
+class StreamWriter;
+class StreamWriterBuilder;
+class Writer;
 class FastWriter;
 class StyledWriter;
+class StyledStreamWriter;
 
 // reader.h
 class Reader;
+class CharReader;
+class CharReaderBuilder;
 
-// features.h
+// json_features.h
 class Features;
 
 // value.h
-typedef unsigned int ArrayIndex;
+using ArrayIndex = unsigned int;
 class StaticString;
 class Path;
 class PathArgument;
@@ -312,4 +428,4 @@ class ValueConstIterator;
 // End of content of file: include/json/forwards.h
 // //////////////////////////////////////////////////////////////////////
 
-#endif // ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
+#endif // ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED
index 19c5912..4e2dac7 100644 (file)
@@ -1,4 +1,4 @@
-/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/).
+/// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/).
 /// It is intended to be used with #include "json/json.h"
 
 // //////////////////////////////////////////////////////////////////////
@@ -10,13 +10,13 @@ The JsonCpp library's source code, including accompanying documentation,
 tests and demonstration applications, are licensed under the following
 conditions...
 
-The author (Baptiste Lepilleur) explicitly disclaims copyright in all
+Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
 jurisdictions which recognize such a disclaimer. In such jurisdictions,
 this software is released into the Public Domain.
 
 In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
-2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
-released under the terms of the MIT License (see below).
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
+The JsonCpp Authors, and is released under the terms of the MIT License (see below).
 
 In jurisdictions which recognize Public Domain property, the user of this
 software may choose to accept it either as 1) Public Domain, 2) under the
@@ -31,7 +31,7 @@ described in clear, concise terms at:
 The full text of the MIT License follows:
 
 ========================================================================
-Copyright (c) 2007-2010 Baptiste Lepilleur
+Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
@@ -68,9 +68,9 @@ license you like.
 // End of content of file: LICENSE
 // //////////////////////////////////////////////////////////////////////
 
-#ifndef JSON_AMALGATED_H_INCLUDED
-#define JSON_AMALGATED_H_INCLUDED
-/// If defined, indicates that the source file is amalgated
+#ifndef JSON_AMALGAMATED_H_INCLUDED
+#define JSON_AMALGAMATED_H_INCLUDED
+/// If defined, indicates that the source file is amalgamated
 /// to prevent private header inclusion.
 #define JSON_IS_AMALGAMATION
 
@@ -78,15 +78,21 @@ license you like.
 // Beginning of content of file: include/json/version.h
 // //////////////////////////////////////////////////////////////////////
 
-// DO NOT EDIT. This file (and "version") is generated by CMake.
-// Run CMake configure step to update it.
 #ifndef JSON_VERSION_H_INCLUDED
 #define JSON_VERSION_H_INCLUDED
 
-#define JSONCPP_VERSION_STRING "1.7.7"
+// Note: version must be updated in three places when doing a release. This
+// annoying process ensures that amalgamate, CMake, and meson all report the
+// correct version.
+// 1. /meson.build
+// 2. /include/json/version.h
+// 3. /CMakeLists.txt
+// IMPORTANT: also update the SOVERSION!!
+
+#define JSONCPP_VERSION_STRING "1.9.5"
 #define JSONCPP_VERSION_MAJOR 1
-#define JSONCPP_VERSION_MINOR 7
-#define JSONCPP_VERSION_PATCH 7
+#define JSONCPP_VERSION_MINOR 9
+#define JSONCPP_VERSION_PATCH 5
 #define JSONCPP_VERSION_QUALIFIER
 #define JSONCPP_VERSION_HEXA \
   ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
@@ -105,29 +111,132 @@ license you like.
 // //////////////////////////////////////////////////////////////////////
 
 // //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/allocator.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_ALLOCATOR_H_INCLUDED
+#define JSON_ALLOCATOR_H_INCLUDED
+
+#include <cstring>
+#include <memory>
+
+#pragma pack(push, 8)
+
+namespace Json
+{
+template <typename T> class SecureAllocator
+{
+public:
+  // Type definitions
+  using value_type = T;
+  using pointer = T *;
+  using const_pointer = const T *;
+  using reference = T &;
+  using const_reference = const T &;
+  using size_type = std::size_t;
+  using difference_type = std::ptrdiff_t;
+
+  /**
+   * Allocate memory for N items using the standard allocator.
+   */
+  pointer allocate(size_type n)
+  {
+    // allocate using "global operator new"
+    return static_cast<pointer>(::operator new(n * sizeof(T)));
+  }
+
+  /**
+   * Release memory which was allocated for N items at pointer P.
+   *
+   * The memory block is filled with zeroes before being released.
+   */
+  void deallocate(pointer p, size_type n)
+  {
+    // memset_s is used because memset may be optimized away by the compiler
+    memset_s(p, n * sizeof(T), 0, n * sizeof(T));
+    // free using "global operator delete"
+    ::operator delete(p);
+  }
+
+  /**
+   * Construct an item in-place at pointer P.
+   */
+  template <typename... Args> void construct(pointer p, Args &&...args)
+  {
+    // construct using "placement new" and "perfect forwarding"
+    ::new (static_cast<void *>(p)) T(std::forward<Args>(args)...);
+  }
+
+  size_type max_size() const { return size_t(-1) / sizeof(T); }
+
+  pointer address(reference x) const { return std::addressof(x); }
+
+  const_pointer address(const_reference x) const { return std::addressof(x); }
+
+  /**
+   * Destroy an item in-place at pointer P.
+   */
+  void destroy(pointer p)
+  {
+    // destroy using "explicit destructor"
+    p->~T();
+  }
+
+  // Boilerplate
+  SecureAllocator() {}
+  template <typename U> SecureAllocator(const SecureAllocator<U> &) {}
+  template <typename U> struct rebind
+  {
+    using other = SecureAllocator<U>;
+  };
+};
+
+template <typename T, typename U>
+bool operator==(const SecureAllocator<T> &, const SecureAllocator<U> &)
+{
+  return true;
+}
+
+template <typename T, typename U>
+bool operator!=(const SecureAllocator<T> &, const SecureAllocator<U> &)
+{
+  return false;
+}
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#endif // JSON_ALLOCATOR_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/allocator.h
+// //////////////////////////////////////////////////////////////////////
+
+// //////////////////////////////////////////////////////////////////////
 // Beginning of content of file: include/json/config.h
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 
 #ifndef JSON_CONFIG_H_INCLUDED
 #define JSON_CONFIG_H_INCLUDED
-#include <stddef.h>
-#include <string>   //typedef String
-#include <stdint.h> //typedef int64_t, uint64_t
-
-/// If defined, indicates that json library is embedded in CppTL library.
-//# define JSON_IN_CPPTL 1
-
-/// If defined, indicates that json may leverage CppTL library
-//#  define JSON_USE_CPPTL 1
-/// If defined, indicates that cpptl vector based map should be used instead of
-/// std::map
-/// as Value container.
-//#  define JSON_USE_CPPTL_SMALLMAP 1
+#include <cstddef>
+#include <cstdint>
+#include <istream>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <type_traits>
 
 // If non-zero, the library uses exceptions to report bad input instead of C
 // assertion macros. The default is to use exceptions.
@@ -135,158 +244,129 @@ license you like.
 #define JSON_USE_EXCEPTION 1
 #endif
 
-/// If defined, indicates that the source file is amalgated
+// Temporary, tracked for removal with issue #982.
+#ifndef JSON_USE_NULLREF
+#define JSON_USE_NULLREF 1
+#endif
+
+/// If defined, indicates that the source file is amalgamated
 /// to prevent private header inclusion.
-/// Remarks: it is automatically defined in the generated amalgated header.
+/// Remarks: it is automatically defined in the generated amalgamated header.
 // #define JSON_IS_AMALGAMATION
 
-#ifdef JSON_IN_CPPTL
-#include <cpptl/config.h>
-#ifndef JSON_USE_CPPTL
-#define JSON_USE_CPPTL 1
-#endif
-#endif
-
-#ifdef JSON_IN_CPPTL
-#define JSON_API CPPTL_API
-#elif defined(JSON_DLL_BUILD)
+// Export macros for DLL visibility
+#if defined(JSON_DLL_BUILD)
 #if defined(_MSC_VER) || defined(__MINGW32__)
 #define JSON_API __declspec(dllexport)
 #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#elif defined(__GNUC__) || defined(__clang__)
+#define JSON_API __attribute__((visibility("default")))
 #endif // if defined(_MSC_VER)
+
 #elif defined(JSON_DLL)
 #if defined(_MSC_VER) || defined(__MINGW32__)
 #define JSON_API __declspec(dllimport)
 #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
 #endif // if defined(_MSC_VER)
-#endif // ifdef JSON_IN_CPPTL
+#endif // ifdef JSON_DLL_BUILD
+
 #if !defined(JSON_API)
 #define JSON_API
 #endif
 
-// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
-// integer
-// Storages, and 64 bits integer support is disabled.
-// #define JSON_NO_INT64 1
-
-#if defined(_MSC_VER) // MSVC
-#if _MSC_VER <= 1200  // MSVC 6
-                      // Microsoft Visual Studio 6 only support conversion from __int64 to double
-                      // (no conversion from unsigned __int64).
-#define JSON_USE_INT64_DOUBLE_CONVERSION 1
-// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
-// characters in the debug information)
-// All projects I've ever seen with VS6 were using this globally (not bothering
-// with pragma push/pop).
-#pragma warning(disable : 4786)
-#endif // MSVC 6
-
-#if _MSC_VER >= 1500 // MSVC 2008
-                     /// Indicates that the following function is deprecated.
-#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#if defined(_MSC_VER) && _MSC_VER < 1800
+#error \
+  "ERROR:  Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
 #endif
 
-#endif // defined(_MSC_VER)
-
-// In c++11 the override keyword allows you to explicity define that a function
-// is intended to override the base-class version.  This makes the code more
-// managable and fixes a set of common hard-to-find bugs.
-#if __cplusplus >= 201103L
-#define JSONCPP_OVERRIDE override
-#elif defined(_MSC_VER) && _MSC_VER > 1600
-#define JSONCPP_OVERRIDE override
+#if defined(_MSC_VER) && _MSC_VER < 1900
+// As recommended at
+// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+extern JSON_API int msvc_pre1900_c99_snprintf(char *outBuf, size_t size, const char *format, ...);
+#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
 #else
-#define JSONCPP_OVERRIDE
+#define jsoncpp_snprintf std::snprintf
 #endif
 
-#ifndef JSON_HAS_RVALUE_REFERENCES
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
 
-#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif // MSVC >= 2010
+// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
+// C++11 should be used directly in JSONCPP.
+#define JSONCPP_OVERRIDE override
 
 #ifdef __clang__
-#if __has_feature(cxx_rvalue_references)
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif // has_feature
-
-#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
-#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif // GXX_EXPERIMENTAL
-
-#endif // __clang__ || __GNUC__
-
-#endif // not defined JSON_HAS_RVALUE_REFERENCES
-
-#ifndef JSON_HAS_RVALUE_REFERENCES
-#define JSON_HAS_RVALUE_REFERENCES 0
+#if __has_extension(attribute_deprecated_with_message)
+#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
 #endif
-
-#ifdef __clang__
-#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
 #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
 #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
 #elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
 #define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
-#endif // GNUC version
-#endif // __clang__ || __GNUC__
+#endif                  // GNUC version
+#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
+                        // MSVC)
+#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#endif // __clang__ || __GNUC__ || _MSC_VER
 
 #if !defined(JSONCPP_DEPRECATED)
 #define JSONCPP_DEPRECATED(message)
 #endif // if !defined(JSONCPP_DEPRECATED)
 
-#if __GNUC__ >= 6
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
 #define JSON_USE_INT64_DOUBLE_CONVERSION 1
 #endif
 
 #if !defined(JSON_IS_AMALGAMATION)
 
+#include "allocator.h"
 #include "version.h"
 
-#if JSONCPP_USING_SECURE_MEMORY
-#include "allocator.h" //typedef Allocator
-#endif
-
 #endif // if !defined(JSON_IS_AMALGAMATION)
 
 namespace Json
 {
-typedef int Int;
-typedef unsigned int UInt;
+using Int = int;
+using UInt = unsigned int;
 #if defined(JSON_NO_INT64)
-typedef int LargestInt;
-typedef unsigned int LargestUInt;
+using LargestInt = int;
+using LargestUInt = unsigned int;
 #undef JSON_HAS_INT64
 #else                 // if defined(JSON_NO_INT64)
 // For Microsoft Visual use specific types as long long is not supported
 #if defined(_MSC_VER) // Microsoft Visual Studio
-typedef __int64 Int64;
-typedef unsigned __int64 UInt64;
+using Int64 = __int64;
+using UInt64 = unsigned __int64;
 #else                 // if defined(_MSC_VER) // Other platforms, use long long
-typedef int64_t Int64;
-typedef uint64_t UInt64;
+using Int64 = int64_t;
+using UInt64 = uint64_t;
 #endif                // if defined(_MSC_VER)
-typedef Int64 LargestInt;
-typedef UInt64 LargestUInt;
+using LargestInt = Int64;
+using LargestUInt = UInt64;
 #define JSON_HAS_INT64
 #endif // if defined(JSON_NO_INT64)
-#if JSONCPP_USING_SECURE_MEMORY
-#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char>>
-#define JSONCPP_OSTRINGSTREAM \
-  std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char>>
-#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>>
-#define JSONCPP_ISTRINGSTREAM \
-  std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char>>
-#define JSONCPP_ISTREAM std::istream
-#else
-#define JSONCPP_STRING std::string
-#define JSONCPP_OSTRINGSTREAM std::ostringstream
-#define JSONCPP_OSTREAM std::ostream
-#define JSONCPP_ISTRINGSTREAM std::istringstream
-#define JSONCPP_ISTREAM std::istream
-#endif // if JSONCPP_USING_SECURE_MEMORY
-} // end namespace Json
+
+template <typename T>
+using Allocator = typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
+                                            std::allocator<T>>::type;
+using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
+using IStringStream =
+  std::basic_istringstream<String::value_type, String::traits_type, String::allocator_type>;
+using OStringStream =
+  std::basic_ostringstream<String::value_type, String::traits_type, String::allocator_type>;
+using IStream = std::istream;
+using OStream = std::ostream;
+} // namespace Json
+
+// Legacy names (formerly macros).
+using JSONCPP_STRING = Json::String;
+using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
+using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
+using JSONCPP_ISTREAM = Json::IStream;
+using JSONCPP_OSTREAM = Json::OStream;
 
 #endif // JSON_CONFIG_H_INCLUDED
 
@@ -298,7 +378,7 @@ typedef UInt64 LargestUInt;
 // Beginning of content of file: include/json/forwards.h
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -314,17 +394,23 @@ namespace Json
 {
 
 // writer.h
+class StreamWriter;
+class StreamWriterBuilder;
+class Writer;
 class FastWriter;
 class StyledWriter;
+class StyledStreamWriter;
 
 // reader.h
 class Reader;
+class CharReader;
+class CharReaderBuilder;
 
-// features.h
+// json_features.h
 class Features;
 
 // value.h
-typedef unsigned int ArrayIndex;
+using ArrayIndex = unsigned int;
 class StaticString;
 class Path;
 class PathArgument;
@@ -342,21 +428,23 @@ class ValueConstIterator;
 // //////////////////////////////////////////////////////////////////////
 
 // //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: include/json/features.h
+// Beginning of content of file: include/json/json_features.h
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 
-#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
-#define CPPTL_JSON_FEATURES_H_INCLUDED
+#ifndef JSON_FEATURES_H_INCLUDED
+#define JSON_FEATURES_H_INCLUDED
 
 #if !defined(JSON_IS_AMALGAMATION)
 #include "forwards.h"
 #endif // if !defined(JSON_IS_AMALGAMATION)
 
+#pragma pack(push, 8)
+
 namespace Json
 {
 
@@ -388,80 +476,96 @@ public:
   Features();
 
   /// \c true if comments are allowed. Default: \c true.
-  bool allowComments_;
+  bool allowComments_{true};
 
   /// \c true if root must be either an array or an object value. Default: \c
   /// false.
-  bool strictRoot_;
+  bool strictRoot_{false};
 
   /// \c true if dropped null placeholders are allowed. Default: \c false.
-  bool allowDroppedNullPlaceholders_;
+  bool allowDroppedNullPlaceholders_{false};
 
   /// \c true if numeric object key are allowed. Default: \c false.
-  bool allowNumericKeys_;
+  bool allowNumericKeys_{false};
 };
 
 } // namespace Json
 
-#endif // CPPTL_JSON_FEATURES_H_INCLUDED
+#pragma pack(pop)
+
+#endif // JSON_FEATURES_H_INCLUDED
 
 // //////////////////////////////////////////////////////////////////////
-// End of content of file: include/json/features.h
+// End of content of file: include/json/json_features.h
 // //////////////////////////////////////////////////////////////////////
 
 // //////////////////////////////////////////////////////////////////////
 // Beginning of content of file: include/json/value.h
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 
-#ifndef CPPTL_JSON_H_INCLUDED
-#define CPPTL_JSON_H_INCLUDED
+#ifndef JSON_H_INCLUDED
+#define JSON_H_INCLUDED
 
 #if !defined(JSON_IS_AMALGAMATION)
 #include "forwards.h"
 #endif // if !defined(JSON_IS_AMALGAMATION)
-#include <string>
-#include <vector>
-#include <exception>
-
-#ifndef JSON_USE_CPPTL_SMALLMAP
-#include <map>
-#else
-#include <cpptl/smallmap.h>
-#endif
-#ifdef JSON_USE_CPPTL
-#include <cpptl/forwards.h>
-#endif
 
 // Conditional NORETURN attribute on the throw functions would:
 // a) suppress false positives from static code analysis
 // b) possibly improve optimization opportunities.
 #if !defined(JSONCPP_NORETURN)
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && _MSC_VER == 1800
 #define JSONCPP_NORETURN __declspec(noreturn)
-#elif defined(__GNUC__)
-#define JSONCPP_NORETURN __attribute__((__noreturn__))
 #else
-#define JSONCPP_NORETURN
+#define JSONCPP_NORETURN [[noreturn]]
+#endif
+#endif
+
+// Support for '= delete' with template declarations was a late addition
+// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2
+// even though these declare themselves to be c++11 compilers.
+#if !defined(JSONCPP_TEMPLATE_DELETE)
+#if defined(__clang__) && defined(__apple_build_version__)
+#if __apple_build_version__ <= 8000042
+#define JSONCPP_TEMPLATE_DELETE
+#endif
+#elif defined(__clang__)
+#if __clang_major__ == 3 && __clang_minor__ <= 8
+#define JSONCPP_TEMPLATE_DELETE
+#endif
+#endif
+#if !defined(JSONCPP_TEMPLATE_DELETE)
+#define JSONCPP_TEMPLATE_DELETE = delete
 #endif
 #endif
 
+#include <array>
+#include <exception>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
 // Disable warning C4251: <data member>: <type> needs to have dll-interface to
 // be used by...
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 #pragma warning(push)
-#pragma warning(disable : 4251)
+#pragma warning(disable : 4251 4275)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
+#pragma pack(push, 8)
+
 /** \brief JSON (JavaScript Object Notation).
  */
 namespace Json
 {
 
+#if JSON_USE_EXCEPTION
 /** Base class for all exceptions we throw.
  *
  * We use nothing but these internally. Of course, STL can throw others.
@@ -469,12 +573,12 @@ namespace Json
 class JSON_API Exception : public std::exception
 {
 public:
-  Exception(JSONCPP_STRING const &msg);
-  ~Exception() throw() JSONCPP_OVERRIDE;
-  char const *what() const throw() JSONCPP_OVERRIDE;
+  Exception(String msg);
+  ~Exception() noexcept override;
+  char const *what() const noexcept override;
 
 protected:
-  JSONCPP_STRING msg_;
+  String msg_;
 };
 
 /** Exceptions which the user cannot easily avoid.
@@ -486,7 +590,7 @@ protected:
 class JSON_API RuntimeError : public Exception
 {
 public:
-  RuntimeError(JSONCPP_STRING const &msg);
+  RuntimeError(String const &msg);
 };
 
 /** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
@@ -498,13 +602,14 @@ public:
 class JSON_API LogicError : public Exception
 {
 public:
-  LogicError(JSONCPP_STRING const &msg);
+  LogicError(String const &msg);
 };
+#endif
 
 /// used internally
-JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const &msg);
+JSONCPP_NORETURN void throwRuntimeError(String const &msg);
 /// used internally
-JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const &msg);
+JSONCPP_NORETURN void throwLogicError(String const &msg);
 
 /** \brief Type of the value held by a Value object.
  */
@@ -529,14 +634,17 @@ enum CommentPlacement
   numberOfCommentPlacement
 };
 
-//# ifdef JSON_USE_CPPTL
-//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
-//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
-//# endif
+/** \brief Type of precision for formatting of real values.
+ */
+enum PrecisionType
+{
+  significantDigits = 0, ///< we set max number of significant digits in string
+  decimalPlaces          ///< we set max number of digits after "." in string
+};
 
 /** \brief Lightweight wrapper to tag static string.
  *
- * Value constructor and objectValue member assignement takes advantage of the
+ * Value constructor and objectValue member assignment takes advantage of the
  * StaticString and avoid the cost of string duplication when storing the
  * string or the member name.
  *
@@ -586,7 +694,7 @@ private:
  * The get() methods can be used to obtain default value in the case the
  * required element does not exist.
  *
- * It is possible to iterate over the list of a #objectValue values using
+ * It is possible to iterate over the list of member keys of an object using
  * the getMemberNames() method.
  *
  * \note #Value string-length fit in size_t, but keys must be < 2^30.
@@ -600,48 +708,67 @@ class JSON_API Value
   friend class ValueIteratorBase;
 
 public:
-  typedef std::vector<JSONCPP_STRING> Members;
-  typedef ValueIterator iterator;
-  typedef ValueConstIterator const_iterator;
-  typedef Json::UInt UInt;
-  typedef Json::Int Int;
+  using Members = std::vector<String>;
+  using iterator = ValueIterator;
+  using const_iterator = ValueConstIterator;
+  using UInt = Json::UInt;
+  using Int = Json::Int;
 #if defined(JSON_HAS_INT64)
-  typedef Json::UInt64 UInt64;
-  typedef Json::Int64 Int64;
+  using UInt64 = Json::UInt64;
+  using Int64 = Json::Int64;
 #endif // defined(JSON_HAS_INT64)
-  typedef Json::LargestInt LargestInt;
-  typedef Json::LargestUInt LargestUInt;
-  typedef Json::ArrayIndex ArrayIndex;
+  using LargestInt = Json::LargestInt;
+  using LargestUInt = Json::LargestUInt;
+  using ArrayIndex = Json::ArrayIndex;
+
+  // Required for boost integration, e. g. BOOST_TEST
+  using value_type = std::string;
+
+#if JSON_USE_NULLREF
+  // Binary compatibility kludges, do not use.
+  static const Value &null;
+  static const Value &nullRef;
+#endif
 
-  static const Value
-      &null; ///< We regret this reference to a global instance; prefer the simpler Value().
-  static const Value &nullRef;         ///< just a kludge for binary-compatibility; same as null
-  static Value const &nullSingleton(); ///< Prefer this to null or nullRef.
+  // null and nullRef are deprecated, use this instead.
+  static Value const &nullSingleton();
 
   /// Minimum signed integer value that can be stored in a Json::Value.
-  static const LargestInt minLargestInt;
+  static constexpr LargestInt minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
   /// Maximum signed integer value that can be stored in a Json::Value.
-  static const LargestInt maxLargestInt;
+  static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2);
   /// Maximum unsigned integer value that can be stored in a Json::Value.
-  static const LargestUInt maxLargestUInt;
+  static constexpr LargestUInt maxLargestUInt = LargestUInt(-1);
 
   /// Minimum signed int value that can be stored in a Json::Value.
-  static const Int minInt;
+  static constexpr Int minInt = Int(~(UInt(-1) / 2));
   /// Maximum signed int value that can be stored in a Json::Value.
-  static const Int maxInt;
+  static constexpr Int maxInt = Int(UInt(-1) / 2);
   /// Maximum unsigned int value that can be stored in a Json::Value.
-  static const UInt maxUInt;
+  static constexpr UInt maxUInt = UInt(-1);
 
 #if defined(JSON_HAS_INT64)
   /// Minimum signed 64 bits int value that can be stored in a Json::Value.
-  static const Int64 minInt64;
+  static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2));
   /// Maximum signed 64 bits int value that can be stored in a Json::Value.
-  static const Int64 maxInt64;
+  static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2);
   /// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
-  static const UInt64 maxUInt64;
+  static constexpr UInt64 maxUInt64 = UInt64(-1);
 #endif // defined(JSON_HAS_INT64)
-
+  /// Default precision for real value for string representation.
+  static constexpr UInt defaultRealPrecision = 17;
+  // The constant is hard-coded because some compiler have trouble
+  // converting Value::maxUInt64 to a double correctly (AIX/xlC).
+  // Assumes that UInt64 is a 64 bits integer.
+  static constexpr double maxUInt64AsDouble = 18446744073709551615.0;
+// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler
+// when using gcc and clang backend compilers.  CZString
+// cannot be defined as private.  See issue #486
+#ifdef __NVCC__
+public:
+#else
 private:
+#endif
 #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
   class CZString
   {
@@ -655,11 +782,11 @@ private:
     CZString(ArrayIndex index);
     CZString(char const *str, unsigned length, DuplicationPolicy allocate);
     CZString(CZString const &other);
-#if JSON_HAS_RVALUE_REFERENCES
-    CZString(CZString &&other);
-#endif
+    CZString(CZString &&other) noexcept;
     ~CZString();
-    CZString &operator=(CZString other);
+    CZString &operator=(const CZString &other);
+    CZString &operator=(CZString &&other) noexcept;
+
     bool operator<(CZString const &other) const;
     bool operator==(CZString const &other) const;
     ArrayIndex index() const;
@@ -685,29 +812,26 @@ private:
   };
 
 public:
-#ifndef JSON_USE_CPPTL_SMALLMAP
   typedef std::map<CZString, Value> ObjectValues;
-#else
-  typedef CppTL::SmallMap<CZString, Value> ObjectValues;
-#endif // ifndef JSON_USE_CPPTL_SMALLMAP
 #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
 
 public:
-  /** \brief Create a default Value of the given type.
-
-    This is a very useful constructor.
-    To create an empty array, pass arrayValue.
-    To create an empty object, pass objectValue.
-    Another Value can then be set to this one by assignment.
-This is useful since clear() and resize() will not alter types.
-
-    Examples:
-\code
-Json::Value null_value; // null
-Json::Value arr_value(Json::arrayValue); // []
-Json::Value obj_value(Json::objectValue); // {}
-\endcode
-  */
+  /**
+   * \brief Create a default Value of the given type.
+   *
+   * This is a very useful constructor.
+   * To create an empty array, pass arrayValue.
+   * To create an empty object, pass objectValue.
+   * Another Value can then be set to this one by assignment.
+   * This is useful since clear() and resize() will not alter types.
+   *
+   * Examples:
+   *   \code
+   *   Json::Value null_value; // null
+   *   Json::Value arr_value(Json::arrayValue); // []
+   *   Json::Value obj_value(Json::objectValue); // {}
+   *   \endcode
+   */
   Value(ValueType type = nullValue);
   Value(Int value);
   Value(UInt value);
@@ -718,43 +842,46 @@ Json::Value obj_value(Json::objectValue); // {}
   Value(double value);
   Value(const char *value);                  ///< Copy til first 0. (NULL causes to seg-fault.)
   Value(const char *begin, const char *end); ///< Copy all, incl zeroes.
-  /** \brief Constructs a value from a static string.
-
+  /**
+   * \brief Constructs a value from a static string.
+   *
    * Like other value string constructor but do not duplicate the string for
-   * internal storage. The given string must remain alive after the call to this
-   * constructor.
+   * internal storage. The given string must remain alive after the call to
+   * this constructor.
+   *
    * \note This works only for null-terminated strings. (We cannot change the
-   *   size of this class, so we have nowhere to store the length,
-   *   which might be computed later for various operations.)
+   * size of this class, so we have nowhere to store the length, which might be
+   * computed later for various operations.)
    *
    * Example of usage:
-   * \code
-   * static StaticString foo("some text");
-   * Json::Value aValue(foo);
-   * \endcode
+   *   \code
+   *   static StaticString foo("some text");
+   *   Json::Value aValue(foo);
+   *   \endcode
    */
   Value(const StaticString &value);
-  Value(const JSONCPP_STRING &value); ///< Copy data() til size(). Embedded zeroes too.
-#ifdef JSON_USE_CPPTL
-  Value(const CppTL::ConstString &value);
-#endif
+  Value(const String &value);
   Value(bool value);
-  /// Deep copy.
+  Value(std::nullptr_t ptr) = delete;
   Value(const Value &other);
-#if JSON_HAS_RVALUE_REFERENCES
-  /// Move constructor
-  Value(Value &&other);
-#endif
+  Value(Value &&other) noexcept;
   ~Value();
 
-  /// Deep copy, then swap(other).
-  /// \note Over-write existing comments. To preserve comments, use #swapPayload().
-  Value &operator=(Value other);
+  /// \note Overwrite existing comments. To preserve comments, use
+  /// #swapPayload().
+  Value &operator=(const Value &other);
+  Value &operator=(Value &&other) noexcept;
+
   /// Swap everything.
   void swap(Value &other);
   /// Swap values but leave comments and source offsets in place.
   void swapPayload(Value &other);
 
+  /// copy everything.
+  void copy(const Value &other);
+  /// copy values but leave comments and source offsets in place.
+  void copyPayload(const Value &other);
+
   ValueType type() const;
 
   /// Compare payload only, not comments etc.
@@ -768,16 +895,14 @@ Json::Value obj_value(Json::objectValue); // {}
 
   const char *asCString() const; ///< Embedded zeroes could cause you trouble!
 #if JSONCPP_USING_SECURE_MEMORY
-  unsigned getCStringLength() const; // Allows you to understand the length of the CString
+  unsigned getCStringLength() const; // Allows you to understand the length of
+                                     // the CString
 #endif
-  JSONCPP_STRING asString() const; ///< Embedded zeroes are possible.
+  String asString() const; ///< Embedded zeroes are possible.
   /** Get raw char* of string-value.
    *  \return false if !string. (Seg-fault if str or end are NULL.)
    */
   bool getString(char const **begin, char const **end) const;
-#ifdef JSON_USE_CPPTL
-  CppTL::ConstString asConstString() const;
-#endif
   Int asInt() const;
   UInt asUInt() const;
 #if defined(JSON_HAS_INT64)
@@ -803,6 +928,10 @@ Json::Value obj_value(Json::objectValue); // {}
   bool isArray() const;
   bool isObject() const;
 
+  /// The `as<T>` and `is<T>` member function templates and specializations.
+  template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
+  template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE;
+
   bool isConvertibleTo(ValueType other) const;
 
   /// Number of values in array or object
@@ -812,50 +941,41 @@ Json::Value obj_value(Json::objectValue); // {}
   /// otherwise, false.
   bool empty() const;
 
-  /// Return isNull()
-  bool operator!() const;
+  /// Return !isNull()
+  explicit operator bool() const;
 
   /// Remove all object members and array elements.
   /// \pre type() is arrayValue, objectValue, or nullValue
   /// \post type() is unchanged
   void clear();
 
-  /// Resize the array to size elements.
+  /// Resize the array to newSize elements.
   /// New elements are initialized to null.
   /// May only be called on nullValue or arrayValue.
   /// \pre type() is arrayValue or nullValue
   /// \post type() is arrayValue
-  void resize(ArrayIndex size);
+  void resize(ArrayIndex newSize);
 
-  /// Access an array element (zero based index ).
-  /// If the array contains less than index element, then null value are
-  /// inserted
-  /// in the array so that its size is index+1.
+  //@{
+  /// Access an array element (zero based index). If the array contains less
+  /// than index element, then null value are inserted in the array so that
+  /// its size is index+1.
   /// (You may need to say 'value[0u]' to get your compiler to distinguish
-  ///  this from the operator[] which takes a string.)
+  /// this from the operator[] which takes a string.)
   Value &operator[](ArrayIndex index);
-
-  /// Access an array element (zero based index ).
-  /// If the array contains less than index element, then null value are
-  /// inserted
-  /// in the array so that its size is index+1.
-  /// (You may need to say 'value[0u]' to get your compiler to distinguish
-  ///  this from the operator[] which takes a string.)
   Value &operator[](int index);
+  //@}
 
-  /// Access an array element (zero based index )
+  //@{
+  /// Access an array element (zero based index).
   /// (You may need to say 'value[0u]' to get your compiler to distinguish
-  ///  this from the operator[] which takes a string.)
+  /// this from the operator[] which takes a string.)
   const Value &operator[](ArrayIndex index) const;
-
-  /// Access an array element (zero based index )
-  /// (You may need to say 'value[0u]' to get your compiler to distinguish
-  ///  this from the operator[] which takes a string.)
   const Value &operator[](int index) const;
+  //@}
 
   /// If the array contains at least index+1 elements, returns the element
-  /// value,
-  /// otherwise returns defaultValue.
+  /// value, otherwise returns defaultValue.
   Value get(ArrayIndex index, const Value &defaultValue) const;
   /// Return true if index < size().
   bool isValidIndex(ArrayIndex index) const;
@@ -863,41 +983,39 @@ Json::Value obj_value(Json::objectValue); // {}
   ///
   /// Equivalent to jsonvalue[jsonvalue.size()] = value;
   Value &append(const Value &value);
+  Value &append(Value &&value);
+
+  /// \brief Insert value in array at specific index
+  bool insert(ArrayIndex index, const Value &newValue);
+  bool insert(ArrayIndex index, Value &&newValue);
 
   /// Access an object value by name, create a null member if it does not exist.
   /// \note Because of our implementation, keys are limited to 2^30 -1 chars.
-  ///  Exceeding that will cause an exception.
+  /// Exceeding that will cause an exception.
   Value &operator[](const char *key);
   /// Access an object value by name, returns null if there is no member with
   /// that name.
   const Value &operator[](const char *key) const;
   /// Access an object value by name, create a null member if it does not exist.
   /// \param key may contain embedded nulls.
-  Value &operator[](const JSONCPP_STRING &key);
+  Value &operator[](const String &key);
   /// Access an object value by name, returns null if there is no member with
   /// that name.
   /// \param key may contain embedded nulls.
-  const Value &operator[](const JSONCPP_STRING &key) const;
+  const Value &operator[](const String &key) const;
   /** \brief Access an object value by name, create a null member if it does not
-   exist.
-
-   * If the object has no entry for that name, then the member name used to store
-   * the new entry is not duplicated.
+   exist.
+   *
+   * If the object has no entry for that name, then the member name used to
+   * store the new entry is not duplicated.
    * Example of use:
-   * \code
-   * Json::Value object;
-   * static const StaticString code("code");
-   * object[code] = 1234;
-   * \endcode
+   *   \code
+   *   Json::Value object;
+   *   static const StaticString code("code");
+   *   object[code] = 1234;
+   *   \endcode
    */
   Value &operator[](const StaticString &key);
-#ifdef JSON_USE_CPPTL
-  /// Access an object value by name, create a null member if it does not exist.
-  Value &operator[](const CppTL::ConstString &key);
-  /// Access an object value by name, returns null if there is no member with
-  /// that name.
-  const Value &operator[](const CppTL::ConstString &key) const;
-#endif
   /// Return the member named key if it exist, defaultValue otherwise.
   /// \note deep copy
   Value get(const char *key, const Value &defaultValue) const;
@@ -908,12 +1026,7 @@ Json::Value obj_value(Json::objectValue); // {}
   /// Return the member named key if it exist, defaultValue otherwise.
   /// \note deep copy
   /// \param key may contain embedded nulls.
-  Value get(const JSONCPP_STRING &key, const Value &defaultValue) const;
-#ifdef JSON_USE_CPPTL
-  /// Return the member named key if it exist, defaultValue otherwise.
-  /// \note deep copy
-  Value get(const CppTL::ConstString &key, const Value &defaultValue) const;
-#endif
+  Value get(const String &key, const Value &defaultValue) const;
   /// Most general and efficient version of isMember()const, get()const,
   /// and operator[]const
   /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
@@ -921,51 +1034,44 @@ Json::Value obj_value(Json::objectValue); // {}
   /// Most general and efficient version of object-mutators.
   /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
   /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
-  Value const *demand(char const *begin, char const *end);
+  Value *demand(char const *begin, char const *end);
   /// \brief Remove and return the named member.
   ///
   /// Do nothing if it did not exist.
-  /// \return the removed Value, or null.
   /// \pre type() is objectValue or nullValue
   /// \post type() is unchanged
-  /// \deprecated
-  Value removeMember(const char *key);
+  void removeMember(const char *key);
   /// Same as removeMember(const char*)
   /// \param key may contain embedded nulls.
-  /// \deprecated
-  Value removeMember(const JSONCPP_STRING &key);
+  void removeMember(const String &key);
   /// Same as removeMember(const char* begin, const char* end, Value* removed),
   /// but 'key' is null-terminated.
   bool removeMember(const char *key, Value *removed);
   /** \brief Remove the named map member.
-
-      Update 'removed' iff removed.
-      \param key may contain embedded nulls.
-      \return true iff removed (no exceptions)
-  */
-  bool removeMember(JSONCPP_STRING const &key, Value *removed);
-  /// Same as removeMember(JSONCPP_STRING const& key, Value* removed)
+   *
+   *  Update 'removed' iff removed.
+   *  \param key may contain embedded nulls.
+   *  \return true iff removed (no exceptions)
+   */
+  bool removeMember(String const &key, Value *removed);
+  /// Same as removeMember(String const& key, Value* removed)
   bool removeMember(const char *begin, const char *end, Value *removed);
   /** \brief Remove the indexed array element.
-
-      O(n) expensive operations.
-      Update 'removed' iff removed.
-      \return true iff removed (no exceptions)
-  */
-  bool removeIndex(ArrayIndex i, Value *removed);
+   *
+   *  O(n) expensive operations.
+   *  Update 'removed' iff removed.
+   *  \return true if removed (no exceptions)
+   */
+  bool removeIndex(ArrayIndex index, Value *removed);
 
   /// Return true if the object has a member named key.
   /// \note 'key' must be null-terminated.
   bool isMember(const char *key) const;
   /// Return true if the object has a member named key.
   /// \param key may contain embedded nulls.
-  bool isMember(const JSONCPP_STRING &key) const;
-  /// Same as isMember(JSONCPP_STRING const& key)const
+  bool isMember(const String &key) const;
+  /// Same as isMember(String const& key)const
   bool isMember(const char *begin, const char *end) const;
-#ifdef JSON_USE_CPPTL
-  /// Return true if the object has a member named key.
-  bool isMember(const CppTL::ConstString &key) const;
-#endif
 
   /// \brief Return a list of the member names.
   ///
@@ -974,23 +1080,24 @@ Json::Value obj_value(Json::objectValue); // {}
   /// \post if type() was nullValue, it remains nullValue
   Members getMemberNames() const;
 
-  //# ifdef JSON_USE_CPPTL
-  //      EnumMemberNames enumMemberNames() const;
-  //      EnumValues enumValues() const;
-  //# endif
-
   /// \deprecated Always pass len.
-  JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.")
-  void setComment(const char *comment, CommentPlacement placement);
+  JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
+  void setComment(const char *comment, CommentPlacement placement)
+  {
+    setComment(String(comment, strlen(comment)), placement);
+  }
   /// Comments must be //... or /* ... */
-  void setComment(const char *comment, size_t len, CommentPlacement placement);
+  void setComment(const char *comment, size_t len, CommentPlacement placement)
+  {
+    setComment(String(comment, len), placement);
+  }
   /// Comments must be //... or /* ... */
-  void setComment(const JSONCPP_STRING &comment, CommentPlacement placement);
+  void setComment(String comment, CommentPlacement placement);
   bool hasComment(CommentPlacement placement) const;
   /// Include delimiters and embedded newlines.
-  JSONCPP_STRING getComment(CommentPlacement placement) const;
+  String getComment(CommentPlacement placement) const;
 
-  JSONCPP_STRING toStyledString() const;
+  String toStyledString() const;
 
   const_iterator begin() const;
   const_iterator end() const;
@@ -1006,21 +1113,18 @@ Json::Value obj_value(Json::objectValue); // {}
   ptrdiff_t getOffsetLimit() const;
 
 private:
+  void setType(ValueType v) { bits_.value_type_ = static_cast<unsigned char>(v); }
+  bool isAllocated() const { return bits_.allocated_; }
+  void setIsAllocated(bool v) { bits_.allocated_ = v; }
+
   void initBasic(ValueType type, bool allocated = false);
+  void dupPayload(const Value &other);
+  void releasePayload();
+  void dupMeta(const Value &other);
 
   Value &resolveReference(const char *key);
   Value &resolveReference(const char *key, const char *end);
 
-  struct CommentInfo
-  {
-    CommentInfo();
-    ~CommentInfo();
-
-    void setComment(const char *text, size_t len);
-
-    char *comment_;
-  };
-
   // struct MemberNamesTransform
   //{
   //   typedef const char *result_type;
@@ -1035,13 +1139,35 @@ private:
     LargestUInt uint_;
     double real_;
     bool bool_;
-    char *string_; // actually ptr to unsigned, followed by str, unless !allocated_
+    char *string_; // if allocated_, ptr to { unsigned, char[] }.
     ObjectValues *map_;
   } value_;
-  ValueType type_ : 8;
-  unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
-                               // If not allocated_, string_ must be null-terminated.
-  CommentInfo *comments_;
+
+  struct
+  {
+    // Really a ValueType, but types should agree for bitfield packing.
+    unsigned int value_type_ : 8;
+    // Unless allocated_, string_ must be null-terminated.
+    unsigned int allocated_ : 1;
+  } bits_;
+
+  class Comments
+  {
+  public:
+    Comments() = default;
+    Comments(const Comments &that);
+    Comments(Comments &&that) noexcept;
+    Comments &operator=(const Comments &that);
+    Comments &operator=(Comments &&that) noexcept;
+    bool has(CommentPlacement slot) const;
+    String get(CommentPlacement slot) const;
+    void set(CommentPlacement slot, String comment);
+
+  private:
+    using Array = std::array<String, numberOfCommentPlacement>;
+    std::unique_ptr<Array> ptr_;
+  };
+  Comments comments_;
 
   // [start, limit) byte offsets in the source JSON text from which this Value
   // was extracted.
@@ -1049,6 +1175,34 @@ private:
   ptrdiff_t limit_;
 };
 
+template <> inline bool Value::as<bool>() const { return asBool(); }
+template <> inline bool Value::is<bool>() const { return isBool(); }
+
+template <> inline Int Value::as<Int>() const { return asInt(); }
+template <> inline bool Value::is<Int>() const { return isInt(); }
+
+template <> inline UInt Value::as<UInt>() const { return asUInt(); }
+template <> inline bool Value::is<UInt>() const { return isUInt(); }
+
+#if defined(JSON_HAS_INT64)
+template <> inline Int64 Value::as<Int64>() const { return asInt64(); }
+template <> inline bool Value::is<Int64>() const { return isInt64(); }
+
+template <> inline UInt64 Value::as<UInt64>() const { return asUInt64(); }
+template <> inline bool Value::is<UInt64>() const { return isUInt64(); }
+#endif
+
+template <> inline double Value::as<double>() const { return asDouble(); }
+template <> inline bool Value::is<double>() const { return isDouble(); }
+
+template <> inline String Value::as<String>() const { return asString(); }
+template <> inline bool Value::is<String>() const { return isString(); }
+
+/// These `as` specializations are type conversions, and do not have a
+/// corresponding `is`.
+template <> inline float Value::as<float>() const { return asFloat(); }
+template <> inline const char *Value::as<const char *>() const { return asCString(); }
+
 /** \brief Experimental and untested: represents an element of the "path" to
  * access a node.
  */
@@ -1060,7 +1214,7 @@ public:
   PathArgument();
   PathArgument(ArrayIndex index);
   PathArgument(const char *key);
-  PathArgument(const JSONCPP_STRING &key);
+  PathArgument(String key);
 
 private:
   enum Kind
@@ -1069,9 +1223,9 @@ private:
     kindIndex,
     kindKey
   };
-  JSONCPP_STRING key_;
-  ArrayIndex index_;
-  Kind kind_;
+  String key_;
+  ArrayIndex index_{};
+  Kind kind_{kindNone};
 };
 
 /** \brief Experimental and untested: represents a "path" to access a node.
@@ -1083,12 +1237,12 @@ private:
  * - ".name1.name2.name3"
  * - ".[0][1][2].name1[3]"
  * - ".%" => member name is provided as parameter
- * - ".[%]" => index is provied as parameter
+ * - ".[%]" => index is provided as parameter
  */
 class JSON_API Path
 {
 public:
-  Path(const JSONCPP_STRING &path, const PathArgument &a1 = PathArgument(),
+  Path(const String &path, const PathArgument &a1 = PathArgument(),
        const PathArgument &a2 = PathArgument(), const PathArgument &a3 = PathArgument(),
        const PathArgument &a4 = PathArgument(), const PathArgument &a5 = PathArgument());
 
@@ -1099,13 +1253,13 @@ public:
   Value &make(Value &root) const;
 
 private:
-  typedef std::vector<const PathArgument *> InArgs;
-  typedef std::vector<PathArgument> Args;
+  using InArgs = std::vector<const PathArgument *>;
+  using Args = std::vector<PathArgument>;
 
-  void makePath(const JSONCPP_STRING &path, const InArgs &in);
-  void addPathInArg(const JSONCPP_STRING &path, const InArgs &in, InArgs::const_iterator &itInArg,
+  void makePath(const String &path, const InArgs &in);
+  void addPathInArg(const String &path, const InArgs &in, InArgs::const_iterator &itInArg,
                     PathArgument::Kind kind);
-  void invalidPath(const JSONCPP_STRING &path, int location);
+  static void invalidPath(const String &path, int location);
 
   Args args_;
 };
@@ -1116,10 +1270,10 @@ private:
 class JSON_API ValueIteratorBase
 {
 public:
-  typedef std::bidirectional_iterator_tag iterator_category;
-  typedef unsigned int size_t;
-  typedef int difference_type;
-  typedef ValueIteratorBase SelfType;
+  using iterator_category = std::bidirectional_iterator_tag;
+  using size_t = unsigned int;
+  using difference_type = int;
+  using SelfType = ValueIteratorBase;
 
   bool operator==(const SelfType &other) const { return isEqual(other); }
 
@@ -1131,17 +1285,19 @@ public:
   /// Value.
   Value key() const;
 
-  /// Return the index of the referenced Value, or -1 if it is not an arrayValue.
+  /// Return the index of the referenced Value, or -1 if it is not an
+  /// arrayValue.
   UInt index() const;
 
   /// Return the member name of the referenced Value, or "" if it is not an
   /// objectValue.
   /// \note Avoid `c_str()` on result, as embedded zeroes are possible.
-  JSONCPP_STRING name() const;
+  String name() const;
 
   /// Return the member name of the referenced Value. "" if it is not an
   /// objectValue.
-  /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
+  /// \deprecated This cannot be used for UTF-8 strings, since there can be
+  /// embedded nulls.
   JSONCPP_DEPRECATED("Use `key = name();` instead.")
   char const *memberName() const;
   /// Return the member name of the referenced Value, or NULL if it is not an
@@ -1150,7 +1306,14 @@ public:
   char const *memberName(char const **end) const;
 
 protected:
-  Value &deref() const;
+  /*! Internal utility functions to assist with implementing
+   *   other iterator functions. The const and non-const versions
+   *   of the "deref" protected methods expose the protected
+   *   current_ member variable in a way that can often be
+   *   optimized away by the compiler.
+   */
+  const Value &deref() const;
+  Value &deref();
 
   void increment();
 
@@ -1165,7 +1328,7 @@ protected:
 private:
   Value::ObjectValues::iterator current_;
   // Indicates that iterator is for a null value.
-  bool isNull_;
+  bool isNull_{true};
 
 public:
   // For some reason, BORLAND needs these at the end, rather
@@ -1182,12 +1345,12 @@ class JSON_API ValueConstIterator : public ValueIteratorBase
   friend class Value;
 
 public:
-  typedef const Value value_type;
+  using value_type = const Value;
   // typedef unsigned int size_t;
   // typedef int difference_type;
-  typedef const Value &reference;
-  typedef const Value *pointer;
-  typedef ValueConstIterator SelfType;
+  using reference = const Value &;
+  using pointer = const Value *;
+  using SelfType = ValueConstIterator;
 
   ValueConstIterator();
   ValueConstIterator(ValueIterator const &other);
@@ -1238,12 +1401,12 @@ class JSON_API ValueIterator : public ValueIteratorBase
   friend class Value;
 
 public:
-  typedef Value value_type;
-  typedef unsigned int size_t;
-  typedef int difference_type;
-  typedef Value &reference;
-  typedef Value *pointer;
-  typedef ValueIterator SelfType;
+  using value_type = Value;
+  using size_t = unsigned int;
+  using difference_type = int;
+  using reference = Value &;
+  using pointer = Value *;
+  using SelfType = ValueIterator;
 
   ValueIterator();
   explicit ValueIterator(const ValueConstIterator &other);
@@ -1283,24 +1446,26 @@ public:
     return *this;
   }
 
-  reference operator*() const { return deref(); }
-
-  pointer operator->() const { return &deref(); }
+  /*! The return value of non-const iterators can be
+   *  changed, so the these functions are not const
+   *  because the returned references/pointers can be used
+   *  to change state of the base class.
+   */
+  reference operator*() const { return const_cast<reference>(deref()); }
+  pointer operator->() const { return const_cast<pointer>(&deref()); }
 };
 
+inline void swap(Value &a, Value &b) { a.swap(b); }
+
 } // namespace Json
 
-namespace std
-{
-/// Specialize std::swap() for Json::Value.
-template <> inline void swap(Json::Value &a, Json::Value &b) { a.swap(b); }
-}
+#pragma pack(pop)
 
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 #pragma warning(pop)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
-#endif // CPPTL_JSON_H_INCLUDED
+#endif // JSON_H_INCLUDED
 
 // //////////////////////////////////////////////////////////////////////
 // End of content of file: include/json/value.h
@@ -1310,23 +1475,23 @@ template <> inline void swap(Json::Value &a, Json::Value &b) { a.swap(b); }
 // Beginning of content of file: include/json/reader.h
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 
-#ifndef CPPTL_JSON_READER_H_INCLUDED
-#define CPPTL_JSON_READER_H_INCLUDED
+#ifndef JSON_READER_H_INCLUDED
+#define JSON_READER_H_INCLUDED
 
 #if !defined(JSON_IS_AMALGAMATION)
-#include "features.h"
+#include "json_features.h"
 #include "value.h"
 #endif // if !defined(JSON_IS_AMALGAMATION)
 #include <deque>
 #include <iosfwd>
+#include <istream>
 #include <stack>
 #include <string>
-#include <istream>
 
 // Disable warning C4251: <data member>: <type> needs to have dll-interface to
 // be used by...
@@ -1335,134 +1500,135 @@ template <> inline void swap(Json::Value &a, Json::Value &b) { a.swap(b); }
 #pragma warning(disable : 4251)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
+#pragma pack(push, 8)
+
 namespace Json
 {
 
 /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
- *Value.
+ * Value.
  *
  * \deprecated Use CharReader and CharReaderBuilder.
  */
+
 class JSON_API Reader
 {
 public:
-  typedef char Char;
-  typedef const Char *Location;
+  using Char = char;
+  using Location = const Char *;
 
   /** \brief An error tagged with where in the JSON text it was encountered.
    *
    * The offsets give the [start, limit) range of bytes within the text. Note
    * that this is bytes, not codepoints.
-   *
    */
   struct StructuredError
   {
     ptrdiff_t offset_start;
     ptrdiff_t offset_limit;
-    JSONCPP_STRING message;
+    String message;
   };
 
-  /** \brief Constructs a Reader allowing all features
-   * for parsing.
+  /** \brief Constructs a Reader allowing all features for parsing.
+   * \deprecated Use CharReader and CharReaderBuilder.
    */
   Reader();
 
-  /** \brief Constructs a Reader allowing the specified feature set
-   * for parsing.
+  /** \brief Constructs a Reader allowing the specified feature set for parsing.
+   * \deprecated Use CharReader and CharReaderBuilder.
    */
   Reader(const Features &features);
 
   /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
    * document.
-   * \param document UTF-8 encoded string containing the document to read.
-   * \param root [out] Contains the root value of the document if it was
-   *             successfully parsed.
-   * \param collectComments \c true to collect comment and allow writing them
-   * back during
-   *                        serialization, \c false to discard comments.
-   *                        This parameter is ignored if
-   * Features::allowComments_
-   *                        is \c false.
+   *
+   * \param      document        UTF-8 encoded string containing the document
+   *                             to read.
+   * \param[out] root            Contains the root value of the document if it
+   *                             was successfully parsed.
+   * \param      collectComments \c true to collect comment and allow writing
+   *                             them back during serialization, \c false to
+   *                             discard comments.  This parameter is ignored
+   *                             if Features::allowComments_ is \c false.
    * \return \c true if the document was successfully parsed, \c false if an
    * error occurred.
    */
   bool parse(const std::string &document, Value &root, bool collectComments = true);
 
   /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
-   document.
-   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
-   document to read.
-   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
-   document to read.
-   *               Must be >= beginDoc.
-   * \param root [out] Contains the root value of the document if it was
-   *             successfully parsed.
-   * \param collectComments \c true to collect comment and allow writing them
-   back during
-   *                        serialization, \c false to discard comments.
-   *                        This parameter is ignored if
-   Features::allowComments_
-   *                        is \c false.
+   * document.
+   *
+   * \param      beginDoc        Pointer on the beginning of the UTF-8 encoded
+   *                             string of the document to read.
+   * \param      endDoc          Pointer on the end of the UTF-8 encoded string
+   *                             of the document to read.  Must be >= beginDoc.
+   * \param[out] root            Contains the root value of the document if it
+   *                             was successfully parsed.
+   * \param      collectComments \c true to collect comment and allow writing
+   *                             them back during serialization, \c false to
+   *                             discard comments.  This parameter is ignored
+   *                             if Features::allowComments_ is \c false.
    * \return \c true if the document was successfully parsed, \c false if an
-   error occurred.
+   error occurred.
    */
   bool parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments = true);
 
   /// \brief Parse from input stream.
   /// \see Json::operator>>(std::istream&, Json::Value&).
-  bool parse(JSONCPP_ISTREAM &is, Value &root, bool collectComments = true);
+  bool parse(IStream &is, Value &root, bool collectComments = true);
 
   /** \brief Returns a user friendly string that list errors in the parsed
    * document.
-   * \return Formatted error message with the list of errors with their location
-   * in
-   *         the parsed document. An empty string is returned if no error
-   * occurred
-   *         during parsing.
+   *
+   * \return Formatted error message with the list of errors with their
+   * location in the parsed document. An empty string is returned if no error
+   * occurred during parsing.
    * \deprecated Use getFormattedErrorMessages() instead (typo fix).
    */
   JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
-  JSONCPP_STRING getFormatedErrorMessages() const;
+  String getFormatedErrorMessages() const;
 
   /** \brief Returns a user friendly string that list errors in the parsed
    * document.
-   * \return Formatted error message with the list of errors with their location
-   * in
-   *         the parsed document. An empty string is returned if no error
-   * occurred
-   *         during parsing.
+   *
+   * \return Formatted error message with the list of errors with their
+   * location in the parsed document. An empty string is returned if no error
+   * occurred during parsing.
    */
-  JSONCPP_STRING getFormattedErrorMessages() const;
+  String getFormattedErrorMessages() const;
 
-  /** \brief Returns a vector of structured erros encounted while parsing.
+  /** \brief Returns a vector of structured errors encountered while parsing.
+   *
    * \return A (possibly empty) vector of StructuredError objects. Currently
-   *         only one error can be returned, but the caller should tolerate
-   * multiple
-   *         errors.  This can occur if the parser recovers from a non-fatal
-   *         parse error and then encounters additional errors.
+   * only one error can be returned, but the caller should tolerate multiple
+   * errors.  This can occur if the parser recovers from a non-fatal parse
+   * error and then encounters additional errors.
    */
   std::vector<StructuredError> getStructuredErrors() const;
 
   /** \brief Add a semantic error message.
-   * \param value JSON Value location associated with the error
+   *
+   * \param value   JSON Value location associated with the error
    * \param message The error message.
-   * \return \c true if the error was successfully added, \c false if the
-   * Value offset exceeds the document size.
+   * \return \c true if the error was successfully added, \c false if the Value
+   * offset exceeds the document size.
    */
-  bool pushError(const Value &value, const JSONCPP_STRING &message);
+  bool pushError(const Value &value, const String &message);
 
   /** \brief Add a semantic error message with extra context.
-   * \param value JSON Value location associated with the error
+   *
+   * \param value   JSON Value location associated with the error
    * \param message The error message.
-   * \param extra Additional JSON Value location to contextualize the error
+   * \param extra   Additional JSON Value location to contextualize the error
    * \return \c true if the error was successfully added, \c false if either
    * Value offset exceeds the document size.
    */
-  bool pushError(const Value &value, const JSONCPP_STRING &message, const Value &extra);
+  bool pushError(const Value &value, const String &message, const Value &extra);
 
   /** \brief Return whether there are any errors.
-   * \return \c true if there are no errors to report \c false if
-   * errors have occurred.
+   *
+   * \return \c true if there are no errors to report \c false if errors have
+   * occurred.
    */
   bool good() const;
 
@@ -1497,15 +1663,15 @@ private:
   {
   public:
     Token token_;
-    JSONCPP_STRING message_;
+    String message_;
     Location extra_;
   };
 
-  typedef std::deque<ErrorInfo> Errors;
+  using Errors = std::deque<ErrorInfo>;
 
   bool readToken(Token &token);
   void skipSpaces();
-  bool match(Location pattern, int patternLength);
+  bool match(const Char *pattern, int patternLength);
   bool readComment();
   bool readCStyleComment();
   bool readCppStyleComment();
@@ -1517,35 +1683,38 @@ private:
   bool decodeNumber(Token &token);
   bool decodeNumber(Token &token, Value &decoded);
   bool decodeString(Token &token);
-  bool decodeString(Token &token, JSONCPP_STRING &decoded);
+  bool decodeString(Token &token, String &decoded);
   bool decodeDouble(Token &token);
   bool decodeDouble(Token &token, Value &decoded);
   bool decodeUnicodeCodePoint(Token &token, Location &current, Location end, unsigned int &unicode);
   bool decodeUnicodeEscapeSequence(Token &token, Location &current, Location end,
                                    unsigned int &unicode);
-  bool addError(const JSONCPP_STRING &message, Token &token, Location extra = 0);
+  bool addError(const String &message, Token &token, Location extra = nullptr);
   bool recoverFromError(TokenType skipUntilToken);
-  bool addErrorAndRecover(const JSONCPP_STRING &message, Token &token, TokenType skipUntilToken);
+  bool addErrorAndRecover(const String &message, Token &token, TokenType skipUntilToken);
   void skipUntilSpace();
   Value &currentValue();
   Char getNextChar();
   void getLocationLineAndColumn(Location location, int &line, int &column) const;
-  JSONCPP_STRING getLocationLineAndColumn(Location location) const;
+  String getLocationLineAndColumn(Location location) const;
   void addComment(Location begin, Location end, CommentPlacement placement);
   void skipCommentTokens(Token &token);
 
-  typedef std::stack<Value *> Nodes;
+  static bool containsNewLine(Location begin, Location end);
+  static String normalizeEOL(Location begin, Location end);
+
+  using Nodes = std::stack<Value *>;
   Nodes nodes_;
   Errors errors_;
-  JSONCPP_STRING document_;
-  Location begin_;
-  Location end_;
-  Location current_;
-  Location lastValueEnd_;
-  Value *lastValue_;
-  JSONCPP_STRING commentsBefore_;
+  String document_;
+  Location begin_{};
+  Location end_{};
+  Location current_{};
+  Location lastValueEnd_{};
+  Value *lastValue_{};
+  String commentsBefore_;
   Features features_;
-  bool collectComments_;
+  bool collectComments_{};
 }; // Reader
 
 /** Interface for reading JSON from a char array.
@@ -1553,31 +1722,29 @@ private:
 class JSON_API CharReader
 {
 public:
-  virtual ~CharReader() {}
+  virtual ~CharReader() = default;
   /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
-   document.
-   * The document must be a UTF-8 encoded string containing the document to read.
+   * document. The document must be a UTF-8 encoded string containing the
+   * document to read.
    *
-   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
-   document to read.
-   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
-   document to read.
-   *        Must be >= beginDoc.
-   * \param root [out] Contains the root value of the document if it was
-   *             successfully parsed.
-   * \param errs [out] Formatted error messages (if not NULL)
-   *        a user friendly string that lists errors in the parsed
-   * document.
+   * \param      beginDoc Pointer on the beginning of the UTF-8 encoded string
+   *                      of the document to read.
+   * \param      endDoc   Pointer on the end of the UTF-8 encoded string of the
+   *                      document to read. Must be >= beginDoc.
+   * \param[out] root     Contains the root value of the document if it was
+   *                      successfully parsed.
+   * \param[out] errs     Formatted error messages (if not NULL) a user
+   *                      friendly string that lists errors in the parsed
+   *                      document.
    * \return \c true if the document was successfully parsed, \c false if an
-   error occurred.
+   error occurred.
    */
-  virtual bool parse(char const *beginDoc, char const *endDoc, Value *root,
-                     JSONCPP_STRING *errs) = 0;
+  virtual bool parse(char const *beginDoc, char const *endDoc, Value *root, String *errs) = 0;
 
   class JSON_API Factory
   {
   public:
-    virtual ~Factory() {}
+    virtual ~Factory() = default;
     /** \brief Allocate a CharReader via operator new().
      * \throw std::exception if something goes wrong (e.g. invalid settings)
      */
@@ -1586,64 +1753,70 @@ public:
 };   // CharReader
 
 /** \brief Build a CharReader implementation.
-
-Usage:
-\code
-  using namespace Json;
-  CharReaderBuilder builder;
-  builder["collectComments"] = false;
-  Value value;
 JSONCPP_STRING errs;
-  bool ok = parseFromStream(builder, std::cin, &value, &errs);
-\endcode
-*/
+ *
+ * Usage:
+ *   \code
*   using namespace Json;
*   CharReaderBuilder builder;
*   builder["collectComments"] = false;
*   Value value;
*   String errs;
*   bool ok = parseFromStream(builder, std::cin, &value, &errs);
+ *   \endcode
+ */
 class JSON_API CharReaderBuilder : public CharReader::Factory
 {
 public:
   // Note: We use a Json::Value so that we can add data-members to this class
   // without a major version bump.
   /** Configuration of this builder.
-    These are case-sensitive.
-    Available settings (case-sensitive):
-    - `"collectComments": false or true`
-      - true to collect comment and allow writing them
-        back during serialization, false to discard comments.
-        This parameter is ignored if allowComments is false.
-    - `"allowComments": false or true`
-      - true if comments are allowed.
-    - `"strictRoot": false or true`
-      - true if root must be either an array or an object value
-    - `"allowDroppedNullPlaceholders": false or true`
-      - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
-    - `"allowNumericKeys": false or true`
-      - true if numeric object keys are allowed.
-    - `"allowSingleQuotes": false or true`
-      - true if '' are allowed for strings (both keys and values)
-    - `"stackLimit": integer`
-      - Exceeding stackLimit (recursive depth of `readValue()`) will
-        cause an exception.
-      - This is a security issue (seg-faults caused by deeply nested JSON),
-        so the default is low.
-    - `"failIfExtra": false or true`
-      - If true, `parse()` returns false when extra non-whitespace trails
-        the JSON value in the input string.
-    - `"rejectDupKeys": false or true`
-      - If true, `parse()` returns false when a key is duplicated within an object.
-    - `"allowSpecialFloats": false or true`
-      - If true, special float values (NaNs and infinities) are allowed
-        and their values are lossfree restorable.
-
-    You can examine 'settings_` yourself
-    to see the defaults. You can also write and read them just like any
-    JSON Value.
-    \sa setDefaults()
-    */
+   * These are case-sensitive.
+   * Available settings (case-sensitive):
+   * - `"collectComments": false or true`
+   *   - true to collect comment and allow writing them back during
+   *     serialization, false to discard comments.  This parameter is ignored
+   *     if allowComments is false.
+   * - `"allowComments": false or true`
+   *   - true if comments are allowed.
+   * - `"allowTrailingCommas": false or true`
+   *   - true if trailing commas in objects and arrays are allowed.
+   * - `"strictRoot": false or true`
+   *   - true if root must be either an array or an object value
+   * - `"allowDroppedNullPlaceholders": false or true`
+   *   - true if dropped null placeholders are allowed. (See
+   *     StreamWriterBuilder.)
+   * - `"allowNumericKeys": false or true`
+   *   - true if numeric object keys are allowed.
+   * - `"allowSingleQuotes": false or true`
+   *   - true if '' are allowed for strings (both keys and values)
+   * - `"stackLimit": integer`
+   *   - Exceeding stackLimit (recursive depth of `readValue()`) will cause an
+   *     exception.
+   *   - This is a security issue (seg-faults caused by deeply nested JSON), so
+   *     the default is low.
+   * - `"failIfExtra": false or true`
+   *   - If true, `parse()` returns false when extra non-whitespace trails the
+   *     JSON value in the input string.
+   * - `"rejectDupKeys": false or true`
+   *   - If true, `parse()` returns false when a key is duplicated within an
+   *     object.
+   * - `"allowSpecialFloats": false or true`
+   *   - If true, special float values (NaNs and infinities) are allowed and
+   *     their values are lossfree restorable.
+   * - `"skipBom": false or true`
+   *   - If true, if the input starts with the Unicode byte order mark (BOM),
+   *     it is skipped.
+   *
+   * You can examine 'settings_` yourself to see the defaults. You can also
+   * write and read them just like any JSON Value.
+   * \sa setDefaults()
+   */
   Json::Value settings_;
 
   CharReaderBuilder();
-  ~CharReaderBuilder() JSONCPP_OVERRIDE;
+  ~CharReaderBuilder() override;
 
-  CharReader *newCharReader() const JSONCPP_OVERRIDE;
+  CharReader *newCharReader() const override;
 
   /** \return true if 'settings' are legal and consistent;
    *   otherwise, indicate bad settings via 'invalid'.
@@ -1652,7 +1825,7 @@ public:
 
   /** A simple way to update a specific setting.
    */
-  Value &operator[](JSONCPP_STRING key);
+  Value &operator[](const String &key);
 
   /** Called by ctor, but you can use this to reset settings_.
    * \pre 'settings' != NULL (but Json::null is fine)
@@ -1669,45 +1842,46 @@ public:
 };
 
 /** Consume entire stream and use its begin/end.
-  * Someday we might have a real StreamReader, but for now this
-  * is convenient.
-  */
-bool JSON_API parseFromStream(CharReader::Factory const &, JSONCPP_ISTREAM &, Value *root,
-                              std::string *errs);
+ * Someday we might have a real StreamReader, but for now this
+ * is convenient.
+ */
+bool JSON_API parseFromStream(CharReader::Factory const &, IStream &, Value *root, String *errs);
 
 /** \brief Read from 'sin' into 'root'.
-
- Always keep comments from the input JSON.
-
- This can be used to read a file into a particular sub-object.
- For example:
- \code
- Json::Value root;
- cin >> root["dir"]["file"];
- cout << root;
- \endcode
- Result:
- \verbatim
- {
- "dir": {
-     "file": {
-     // The input stream JSON would be nested here.
-     }
- }
- }
- \endverbatim
- \throw std::exception on parse error.
- \see Json::operator<<()
-*/
-JSON_API JSONCPP_ISTREAM &operator>>(JSONCPP_ISTREAM &, Value &);
+ *
Always keep comments from the input JSON.
+ *
This can be used to read a file into a particular sub-object.
For example:
*   \code
*   Json::Value root;
*   cin >> root["dir"]["file"];
*   cout << root;
*   \endcode
Result:
\verbatim
{
"dir": {
*    "file": {
*    // The input stream JSON would be nested here.
*    }
}
}
\endverbatim
\throw std::exception on parse error.
\see Json::operator<<()
+ */
+JSON_API IStream &operator>>(IStream &, Value &);
 
 } // namespace Json
 
+#pragma pack(pop)
+
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 #pragma warning(pop)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
-#endif // CPPTL_JSON_READER_H_INCLUDED
+#endif // JSON_READER_H_INCLUDED
 
 // //////////////////////////////////////////////////////////////////////
 // End of content of file: include/json/reader.h
@@ -1717,7 +1891,7 @@ JSON_API JSONCPP_ISTREAM &operator>>(JSONCPP_ISTREAM &, Value &);
 // Beginning of content of file: include/json/writer.h
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -1728,49 +1902,51 @@ JSON_API JSONCPP_ISTREAM &operator>>(JSONCPP_ISTREAM &, Value &);
 #if !defined(JSON_IS_AMALGAMATION)
 #include "value.h"
 #endif // if !defined(JSON_IS_AMALGAMATION)
-#include <vector>
-#include <string>
 #include <ostream>
+#include <string>
+#include <vector>
 
 // Disable warning C4251: <data member>: <type> needs to have dll-interface to
 // be used by...
-#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER)
 #pragma warning(push)
 #pragma warning(disable : 4251)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 
+#pragma pack(push, 8)
+
 namespace Json
 {
 
 class Value;
 
 /**
-
-Usage:
-\code
-  using namespace Json;
-  void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
-    std::unique_ptr<StreamWriter> const writer(
-      factory.newStreamWriter());
-    writer->write(value, &std::cout);
-    std::cout << std::endl;  // add lf and flush
-  }
-\endcode
-*/
+ *
+ * Usage:
+ *  \code
+ *  using namespace Json;
+ *  void writeToStdout(StreamWriter::Factory const& factory, Value const& value)
+ * { std::unique_ptr<StreamWriter> const writer( factory.newStreamWriter());
+ *    writer->write(value, &std::cout);
+ *    std::cout << std::endl;  // add lf and flush
+ *  }
+ *  \endcode
+ */
 class JSON_API StreamWriter
 {
 protected:
-  JSONCPP_OSTREAM *sout_; // not owned; will not delete
+  OStream *sout_; // not owned; will not delete
 public:
   StreamWriter();
   virtual ~StreamWriter();
   /** Write Value into document as configured in sub-class.
-      Do not take ownership of sout, but maintain a reference during function.
-      \pre sout != NULL
-      \return zero on success (For now, we always return zero, so check the stream instead.)
-      \throw std::exception possibly, depending on configuration
+   *   Do not take ownership of sout, but maintain a reference during function.
+   *   \pre sout != NULL
+   *   \return zero on success (For now, we always return zero, so check the
+   *   stream instead.) \throw std::exception possibly, depending on
+   * configuration
    */
-  virtual int write(Value const &root, JSONCPP_OSTREAM *sout) = 0;
+  virtual int write(Value const &root, OStream *sout) = 0;
 
   /** \brief A simple abstract factory.
    */
@@ -1788,22 +1964,22 @@ public:
 /** \brief Write into stringstream, then return string, for convenience.
  * A StreamWriter will be created from the factory, used, and then deleted.
  */
-JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const &factory, Value const &root);
+String JSON_API writeString(StreamWriter::Factory const &factory, Value const &root);
 
 /** \brief Build a StreamWriter implementation.
 
-Usage:
-\code
-  using namespace Json;
-  Value value = ...;
-  StreamWriterBuilder builder;
-  builder["commentStyle"] = "None";
-  builder["indentation"] = "   ";  // or whatever you like
-  std::unique_ptr<Json::StreamWriter> writer(
-      builder.newStreamWriter());
-  writer->write(value, &std::cout);
-  std::cout << std::endl;  // add lf and flush
-\endcode
+Usage:
+*   \code
+  using namespace Json;
+  Value value = ...;
+  StreamWriterBuilder builder;
+  builder["commentStyle"] = "None";
+  builder["indentation"] = "   ";  // or whatever you like
+  std::unique_ptr<Json::StreamWriter> writer(
+*      builder.newStreamWriter());
+  writer->write(value, &std::cout);
+  std::cout << std::endl;  // add lf and flush
+*   \endcode
 */
 class JSON_API StreamWriterBuilder : public StreamWriter::Factory
 {
@@ -1811,35 +1987,42 @@ public:
   // Note: We use a Json::Value so that we can add data-members to this class
   // without a major version bump.
   /** Configuration of this builder.
-    Available settings (case-sensitive):
-    - "commentStyle": "None" or "All"
-    - "indentation":  "<anything>"
-    - "enableYAMLCompatibility": false or true
-      - slightly change the whitespace around colons
-    - "dropNullPlaceholders": false or true
-      - Drop the "null" string from the writer's output for nullValues.
-        Strictly speaking, this is not valid JSON. But when the output is being
-        fed to a browser's Javascript, it makes for smaller output and the
-        browser can handle the output just fine.
-    - "useSpecialFloats": false or true
-      - If true, outputs non-finite floating point values in the following way:
-        NaN values as "NaN", positive infinity as "Infinity", and negative infinity
-        as "-Infinity".
-
-    You can examine 'settings_` yourself
-    to see the defaults. You can also write and read them just like any
-    JSON Value.
-    \sa setDefaults()
-    */
+   *  Available settings (case-sensitive):
+   *  - "commentStyle": "None" or "All"
+   *  - "indentation":  "<anything>".
+   *  - Setting this to an empty string also omits newline characters.
+   *  - "enableYAMLCompatibility": false or true
+   *  - slightly change the whitespace around colons
+   *  - "dropNullPlaceholders": false or true
+   *  - Drop the "null" string from the writer's output for nullValues.
+   *    Strictly speaking, this is not valid JSON. But when the output is being
+   *    fed to a browser's JavaScript, it makes for smaller output and the
+   *    browser can handle the output just fine.
+   *  - "useSpecialFloats": false or true
+   *  - If true, outputs non-finite floating point values in the following way:
+   *    NaN values as "NaN", positive infinity as "Infinity", and negative
+   *  infinity as "-Infinity".
+   *  - "precision": int
+   *  - Number of precision digits for formatting of real values.
+   *  - "precisionType": "significant"(default) or "decimal"
+   *  - Type of precision for formatting of real values.
+   *  - "emitUTF8": false or true
+   *  - If true, outputs raw UTF8 strings instead of escaping them.
+
+   *  You can examine 'settings_` yourself
+   *  to see the defaults. You can also write and read them just like any
+   *  JSON Value.
+   *  \sa setDefaults()
+   */
   Json::Value settings_;
 
   StreamWriterBuilder();
-  ~StreamWriterBuilder() JSONCPP_OVERRIDE;
+  ~StreamWriterBuilder() override;
 
   /**
    * \throw std::exception if something goes wrong (e.g. invalid settings)
    */
-  StreamWriter *newStreamWriter() const JSONCPP_OVERRIDE;
+  StreamWriter *newStreamWriter() const override;
 
   /** \return true if 'settings' are legal and consistent;
    *   otherwise, indicate bad settings via 'invalid'.
@@ -1847,7 +2030,7 @@ public:
   bool validate(Json::Value *invalid) const;
   /** A simple way to update a specific setting.
    */
-  Value &operator[](JSONCPP_STRING key);
+  Value &operator[](const String &key);
 
   /** Called by ctor, but you can use this to reset settings_.
    * \pre 'settings' != NULL (but Json::null is fine)
@@ -1865,7 +2048,7 @@ class JSON_API Writer
 public:
   virtual ~Writer();
 
-  virtual JSONCPP_STRING write(const Value &root) = 0;
+  virtual String write(const Value &root) = 0;
 };
 
 /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
@@ -1873,22 +2056,25 @@ public:
  *
  * The JSON document is written in a single line. It is not intended for 'human'
  *consumption,
- * but may be usefull to support feature such as RPC where bandwith is limited.
+ * but may be useful to support feature such as RPC where bandwidth is limited.
  * \sa Reader, Value
  * \deprecated Use StreamWriterBuilder.
  */
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996) // Deriving from deprecated class
+#endif
 class JSON_API FastWriter : public Writer
 {
-
 public:
   FastWriter();
-  ~FastWriter() JSONCPP_OVERRIDE {}
+  ~FastWriter() override = default;
 
   void enableYAMLCompatibility();
 
   /** \brief Drop the "null" string from the writer's output for nullValues.
    * Strictly speaking, this is not valid JSON. But when the output is being
-   * fed to a browser's Javascript, it makes for smaller output and the
+   * fed to a browser's JavaScript, it makes for smaller output and the
    * browser can handle the output just fine.
    */
   void dropNullPlaceholders();
@@ -1896,16 +2082,19 @@ public:
   void omitEndingLineFeed();
 
 public: // overridden from Writer
-  JSONCPP_STRING write(const Value &root) JSONCPP_OVERRIDE;
+  String write(const Value &root) override;
 
 private:
   void writeValue(const Value &value);
 
-  JSONCPP_STRING document_;
-  bool yamlCompatiblityEnabled_;
-  bool dropNullPlaceholders_;
-  bool omitEndingLineFeed_;
+  String document_;
+  bool yamlCompatibilityEnabled_{false};
+  bool dropNullPlaceholders_{false};
+  bool omitEndingLineFeed_{false};
 };
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
 
 /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
  *human friendly way.
@@ -1931,42 +2120,49 @@ private:
  * \sa Reader, Value, Value::setComment()
  * \deprecated Use StreamWriterBuilder.
  */
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996) // Deriving from deprecated class
+#endif
 class JSON_API StyledWriter : public Writer
 {
 public:
   StyledWriter();
-  ~StyledWriter() JSONCPP_OVERRIDE {}
+  ~StyledWriter() override = default;
 
 public: // overridden from Writer
   /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
    * \param root Value to serialize.
    * \return String containing the JSON document that represents the root value.
    */
-  JSONCPP_STRING write(const Value &root) JSONCPP_OVERRIDE;
+  String write(const Value &root) override;
 
 private:
   void writeValue(const Value &value);
   void writeArrayValue(const Value &value);
-  bool isMultineArray(const Value &value);
-  void pushValue(const JSONCPP_STRING &value);
+  bool isMultilineArray(const Value &value);
+  void pushValue(const String &value);
   void writeIndent();
-  void writeWithIndent(const JSONCPP_STRING &value);
+  void writeWithIndent(const String &value);
   void indent();
   void unindent();
   void writeCommentBeforeValue(const Value &root);
   void writeCommentAfterValueOnSameLine(const Value &root);
-  bool hasCommentForValue(const Value &value);
-  static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING &text);
+  static bool hasCommentForValue(const Value &value);
+  static String normalizeEOL(const String &text);
 
-  typedef std::vector<JSONCPP_STRING> ChildValues;
+  using ChildValues = std::vector<String>;
 
   ChildValues childValues_;
-  JSONCPP_STRING document_;
-  JSONCPP_STRING indentString_;
-  unsigned int rightMargin_;
-  unsigned int indentSize_;
-  bool addChildValues_;
+  String document_;
+  String indentString_;
+  unsigned int rightMargin_{74};
+  unsigned int indentSize_{3};
+  bool addChildValues_{false};
 };
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
 
 /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
  human friendly way,
@@ -1990,15 +2186,21 @@ private:
  * If the Value have comments then they are outputed according to their
  #CommentPlacement.
  *
- * \param indentation Each level will be indented by this amount extra.
  * \sa Reader, Value, Value::setComment()
  * \deprecated Use StreamWriterBuilder.
  */
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996) // Deriving from deprecated class
+#endif
 class JSON_API StyledStreamWriter
 {
 public:
-  StyledStreamWriter(JSONCPP_STRING indentation = "\t");
-  ~StyledStreamWriter() {}
+  /**
+   * \param indentation Each level will be indented by this amount extra.
+   */
+  StyledStreamWriter(String indentation = "\t");
+  ~StyledStreamWriter() = default;
 
 public:
   /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
@@ -2007,49 +2209,55 @@ public:
    * \note There is no point in deriving from Writer, since write() should not
    * return a value.
    */
-  void write(JSONCPP_OSTREAM &out, const Value &root);
+  void write(OStream &out, const Value &root);
 
 private:
   void writeValue(const Value &value);
   void writeArrayValue(const Value &value);
-  bool isMultineArray(const Value &value);
-  void pushValue(const JSONCPP_STRING &value);
+  bool isMultilineArray(const Value &value);
+  void pushValue(const String &value);
   void writeIndent();
-  void writeWithIndent(const JSONCPP_STRING &value);
+  void writeWithIndent(const String &value);
   void indent();
   void unindent();
   void writeCommentBeforeValue(const Value &root);
   void writeCommentAfterValueOnSameLine(const Value &root);
-  bool hasCommentForValue(const Value &value);
-  static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING &text);
+  static bool hasCommentForValue(const Value &value);
+  static String normalizeEOL(const String &text);
 
-  typedef std::vector<JSONCPP_STRING> ChildValues;
+  using ChildValues = std::vector<String>;
 
   ChildValues childValues_;
-  JSONCPP_OSTREAM *document_;
-  JSONCPP_STRING indentString_;
-  unsigned int rightMargin_;
-  JSONCPP_STRING indentation_;
+  OStream *document_;
+  String indentString_;
+  unsigned int rightMargin_{74};
+  String indentation_;
   bool addChildValues_ : 1;
   bool indented_ : 1;
 };
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
 
 #if defined(JSON_HAS_INT64)
-JSONCPP_STRING JSON_API valueToString(Int value);
-JSONCPP_STRING JSON_API valueToString(UInt value);
+String JSON_API valueToString(Int value);
+String JSON_API valueToString(UInt value);
 #endif // if defined(JSON_HAS_INT64)
-JSONCPP_STRING JSON_API valueToString(LargestInt value);
-JSONCPP_STRING JSON_API valueToString(LargestUInt value);
-JSONCPP_STRING JSON_API valueToString(double value);
-JSONCPP_STRING JSON_API valueToString(bool value);
-JSONCPP_STRING JSON_API valueToQuotedString(const char *value);
+String JSON_API valueToString(LargestInt value);
+String JSON_API valueToString(LargestUInt value);
+String JSON_API valueToString(double value, unsigned int precision = Value::defaultRealPrecision,
+                              PrecisionType precisionType = PrecisionType::significantDigits);
+String JSON_API valueToString(bool value);
+String JSON_API valueToQuotedString(const char *value);
 
 /// \brief Output using the StyledStreamWriter.
 /// \see Json::operator>>()
-JSON_API JSONCPP_OSTREAM &operator<<(JSONCPP_OSTREAM &, const Value &root);
+JSON_API OStream &operator<<(OStream &, const Value &root);
 
 } // namespace Json
 
+#pragma pack(pop)
+
 #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
 #pragma warning(pop)
 #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@@ -2064,15 +2272,15 @@ JSON_API JSONCPP_OSTREAM &operator<<(JSONCPP_OSTREAM &, const Value &root);
 // Beginning of content of file: include/json/assertions.h
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 
-#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
-#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
+#ifndef JSON_ASSERTIONS_H_INCLUDED
+#define JSON_ASSERTIONS_H_INCLUDED
 
-#include <stdlib.h>
+#include <cstdlib>
 #include <sstream>
 
 #if !defined(JSON_IS_AMALGAMATION)
@@ -2087,20 +2295,22 @@ JSON_API JSONCPP_OSTREAM &operator<<(JSONCPP_OSTREAM &, const Value &root);
 
 // @todo <= add detail about condition in exception
 #define JSON_ASSERT(condition)                     \
+  do                                               \
   {                                                \
     if (!(condition))                              \
     {                                              \
       Json::throwLogicError("assert json failed"); \
     }                                              \
-  }
+  } while (0)
 
 #define JSON_FAIL_MESSAGE(message)    \
+  do                                  \
   {                                   \
-    JSONCPP_OSTRINGSTREAM oss;        \
+    OStringStream oss;                \
     oss << message;                   \
     Json::throwLogicError(oss.str()); \
     abort();                          \
-  }
+  } while (0)
 
 #else // JSON_USE_EXCEPTION
 
@@ -2110,7 +2320,7 @@ JSON_API JSONCPP_OSTREAM &operator<<(JSONCPP_OSTREAM &, const Value &root);
 // release builds we abort, for a core-dump or debugger.
 #define JSON_FAIL_MESSAGE(message)      \
   {                                     \
-    JSONCPP_OSTRINGSTREAM oss;          \
+    OStringStream oss;                  \
     oss << message;                     \
     assert(false && oss.str().c_str()); \
     abort();                            \
@@ -2119,15 +2329,18 @@ JSON_API JSONCPP_OSTREAM &operator<<(JSONCPP_OSTREAM &, const Value &root);
 #endif
 
 #define JSON_ASSERT_MESSAGE(condition, message) \
-  if (!(condition))                             \
+  do                                            \
   {                                             \
-    JSON_FAIL_MESSAGE(message);                 \
-  }
+    if (!(condition))                           \
+    {                                           \
+      JSON_FAIL_MESSAGE(message);               \
+    }                                           \
+  } while (0)
 
-#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
+#endif // JSON_ASSERTIONS_H_INCLUDED
 
 // //////////////////////////////////////////////////////////////////////
 // End of content of file: include/json/assertions.h
 // //////////////////////////////////////////////////////////////////////
 
-#endif // ifndef JSON_AMALGATED_H_INCLUDED
+#endif // ifndef JSON_AMALGAMATED_H_INCLUDED
index 5b3cd69..8dc754f 100644 (file)
@@ -1,4 +1,4 @@
-/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
+/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/).
 /// It is intended to be used with #include "json/json.h"
 
 // //////////////////////////////////////////////////////////////////////
@@ -10,13 +10,13 @@ The JsonCpp library's source code, including accompanying documentation,
 tests and demonstration applications, are licensed under the following
 conditions...
 
-The author (Baptiste Lepilleur) explicitly disclaims copyright in all
+Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
 jurisdictions which recognize such a disclaimer. In such jurisdictions,
 this software is released into the Public Domain.
 
 In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
-2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
-released under the terms of the MIT License (see below).
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
+The JsonCpp Authors, and is released under the terms of the MIT License (see below).
 
 In jurisdictions which recognize Public Domain property, the user of this
 software may choose to accept it either as 1) Public Domain, 2) under the
@@ -31,7 +31,7 @@ described in clear, concise terms at:
 The full text of the MIT License follows:
 
 ========================================================================
-Copyright (c) 2007-2010 Baptiste Lepilleur
+Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
@@ -78,7 +78,7 @@ license you like.
 // Beginning of content of file: src/lib_json/json_tool.h
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -86,7 +86,16 @@ license you like.
 #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
 #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
 
-#ifndef NO_LOCALE_SUPPORT
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/config.h>
+#endif
+
+// Also support old flag NO_LOCALE_SUPPORT
+#ifdef NO_LOCALE_SUPPORT
+#define JSONCPP_NO_LOCALE_SUPPORT
+#endif
+
+#ifndef JSONCPP_NO_LOCALE_SUPPORT
 #include <clocale>
 #endif
 
@@ -98,9 +107,9 @@ license you like.
 
 namespace Json
 {
-static char getDecimalPoint()
+static inline char getDecimalPoint()
 {
-#ifdef NO_LOCALE_SUPPORT
+#ifdef JSONCPP_NO_LOCALE_SUPPORT
   return '\0';
 #else
   struct lconv *lc = localeconv();
@@ -109,9 +118,9 @@ static char getDecimalPoint()
 }
 
 /// Converts a unicode code-point to UTF-8.
-static inline JSONCPP_STRING codePointToUTF8(unsigned int cp)
+static inline String codePointToUTF8(unsigned int cp)
 {
-  JSONCPP_STRING result;
+  String result;
 
   // based on description from http://en.wikipedia.org/wiki/UTF-8
 
@@ -145,9 +154,6 @@ static inline JSONCPP_STRING codePointToUTF8(unsigned int cp)
   return result;
 }
 
-/// Returns true if ch is a control character (in range [1,31]).
-static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
-
 enum
 {
   /// Constant that specify the size of the buffer that must be passed to
@@ -156,10 +162,10 @@ enum
 };
 
 // Defines a char buffer for use with uintToString().
-typedef char UIntToStringBuffer[uintToStringBufferSize];
+using UIntToStringBuffer = char[uintToStringBufferSize];
 
 /** Converts an unsigned integer to string.
- * @param value Unsigned interger to convert to string
+ * @param value Unsigned integer to convert to string
  * @param current Input/Output string buffer.
  *        Must have at least uintToStringBufferSize chars free.
  */
@@ -178,35 +184,60 @@ static inline void uintToString(LargestUInt value, char *&current)
  * We had a sophisticated way, but it did not work in WinCE.
  * @see https://github.com/open-source-parsers/jsoncpp/pull/9
  */
-static inline void fixNumericLocale(char *begin, char *end)
+template <typename Iter> Iter fixNumericLocale(Iter begin, Iter end)
 {
-  while (begin < end)
+  for (; begin != end; ++begin)
   {
     if (*begin == ',')
     {
       *begin = '.';
     }
-    ++begin;
   }
+  return begin;
 }
 
-static inline void fixNumericLocaleInput(char *begin, char *end)
+template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end)
 {
   char decimalPoint = getDecimalPoint();
-  if (decimalPoint != '\0' && decimalPoint != '.')
+  if (decimalPoint == '\0' || decimalPoint == '.')
+  {
+    return;
+  }
+  for (; begin != end; ++begin)
+  {
+    if (*begin == '.')
+    {
+      *begin = decimalPoint;
+    }
+  }
+}
+
+/**
+ * Return iterator that would be the new end of the range [begin,end), if we
+ * were to delete zeros in the end of string, but not the last zero before '.'.
+ */
+template <typename Iter> Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision)
+{
+  for (; begin != end; --end)
   {
-    while (begin < end)
+    if (*(end - 1) != '0')
+    {
+      return end;
+    }
+    // Don't delete the last zero before the decimal point.
+    if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.')
     {
-      if (*begin == '.')
+      if (precision)
       {
-        *begin = decimalPoint;
+        return end;
       }
-      ++begin;
+      return end - 2;
     }
   }
+  return end;
 }
 
-} // namespace Json {
+} // namespace Json
 
 #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
 
@@ -218,74 +249,72 @@ static inline void fixNumericLocaleInput(char *begin, char *end)
 // Beginning of content of file: src/lib_json/json_reader.cpp
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2011 Baptiste Lepilleur
+// Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors
+// Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 
 #if !defined(JSON_IS_AMALGAMATION)
+#include "json_tool.h"
 #include <json/assertions.h>
 #include <json/reader.h>
 #include <json/value.h>
-#include "json_tool.h"
 #endif // if !defined(JSON_IS_AMALGAMATION)
-#include <utility>
-#include <cstdio>
+#include <algorithm>
 #include <cassert>
 #include <cstring>
+#include <iostream>
 #include <istream>
-#include <sstream>
+#include <limits>
 #include <memory>
 #include <set>
-#include <limits>
+#include <sstream>
+#include <utility>
 
-#if defined(_MSC_VER)
-#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
-#define snprintf sprintf_s
-#elif _MSC_VER >= 1900 // VC++ 14.0 and above
-#define snprintf std::snprintf
-#else
-#define snprintf _snprintf
-#endif
-#elif defined(__ANDROID__) || defined(__QNXNTO__)
-#define snprintf snprintf
-#elif __cplusplus >= 201103L
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-#define snprintf std::snprintf
-#endif
-#endif
+#include <cstdio>
+#if __cplusplus >= 201103L
 
-#if defined(__QNXNTO__)
+#if !defined(sscanf)
 #define sscanf std::sscanf
 #endif
 
-#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+#endif //__cplusplus
+
+#if defined(_MSC_VER)
+#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
+#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
+#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
+#endif //_MSC_VER
+
+#if defined(_MSC_VER)
 // Disable warning about strdup being deprecated.
 #pragma warning(disable : 4996)
 #endif
 
-static int const stackLimit_g = 1000;
-static int stackDepth_g = 0; // see readValue()
+// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile
+// time to change the stack limit
+#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
+#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
+#endif
+
+static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
 
 namespace Json
 {
 
 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
-typedef std::unique_ptr<CharReader> CharReaderPtr;
+using CharReaderPtr = std::unique_ptr<CharReader>;
 #else
-typedef std::auto_ptr<CharReader> CharReaderPtr;
+using CharReaderPtr = std::auto_ptr<CharReader>;
 #endif
 
 // Implementation of class Features
 // ////////////////////////////////
 
-Features::Features()
-    : allowComments_(true), strictRoot_(false), allowDroppedNullPlaceholders_(false),
-      allowNumericKeys_(false)
-{
-}
+Features::Features() = default;
 
-Features Features::all() { return Features(); }
+Features Features::all() { return {}; }
 
 Features Features::strictMode()
 {
@@ -300,49 +329,36 @@ Features Features::strictMode()
 // Implementation of class Reader
 // ////////////////////////////////
 
-static bool containsNewLine(Reader::Location begin, Reader::Location end)
+bool Reader::containsNewLine(Reader::Location begin, Reader::Location end)
 {
-  for (; begin < end; ++begin)
-    if (*begin == '\n' || *begin == '\r')
-      return true;
-  return false;
+  return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
 }
 
 // Class Reader
 // //////////////////////////////////////////////////////////////////
 
-Reader::Reader()
-    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), lastValue_(),
-      commentsBefore_(), features_(Features::all()), collectComments_()
-{
-}
+Reader::Reader() : features_(Features::all()) {}
 
-Reader::Reader(const Features &features)
-    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), lastValue_(),
-      commentsBefore_(), features_(features), collectComments_()
-{
-}
+Reader::Reader(const Features &features) : features_(features) {}
 
 bool Reader::parse(const std::string &document, Value &root, bool collectComments)
 {
-  JSONCPP_STRING documentCopy(document.data(), document.data() + document.capacity());
-  std::swap(documentCopy, document_);
+  document_.assign(document.begin(), document.end());
   const char *begin = document_.c_str();
   const char *end = begin + document_.length();
   return parse(begin, end, root, collectComments);
 }
 
-bool Reader::parse(std::istream &sin, Value &root, bool collectComments)
+bool Reader::parse(std::istream &is, Value &root, bool collectComments)
 {
-  // std::istream_iterator<char> begin(sin);
+  // std::istream_iterator<char> begin(is);
   // std::istream_iterator<char> end;
   // Those would allow streamed input from a file, if parse() were a
   // template function.
 
-  // Since JSONCPP_STRING is reference-counted, this at least does not
+  // Since String is reference-counted, this at least does not
   // create an extra copy.
-  JSONCPP_STRING doc;
-  std::getline(sin, doc, (char)EOF);
+  String doc(std::istreambuf_iterator<char>(is), {});
   return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
 }
 
@@ -357,15 +373,14 @@ bool Reader::parse(const char *beginDoc, const char *endDoc, Value &root, bool c
   end_ = endDoc;
   collectComments_ = collectComments;
   current_ = begin_;
-  lastValueEnd_ = 0;
-  lastValue_ = 0;
-  commentsBefore_ = "";
+  lastValueEnd_ = nullptr;
+  lastValue_ = nullptr;
+  commentsBefore_.clear();
   errors_.clear();
   while (!nodes_.empty())
     nodes_.pop();
   nodes_.push(&root);
 
-  stackDepth_g = 0; // Yes, this is bad coding, but options are limited.
   bool successful = readValue();
   Token token;
   skipCommentTokens(token);
@@ -389,13 +404,12 @@ bool Reader::parse(const char *beginDoc, const char *endDoc, Value &root, bool c
 
 bool Reader::readValue()
 {
-  // This is a non-reentrant way to support a stackLimit. Terrible!
-  // But this deprecated class has a security problem: Bad input can
-  // cause a seg-fault. This seems like a fair, binary-compatible way
-  // to prevent the problem.
-  if (stackDepth_g >= stackLimit_g)
+  // readValue() may call itself only if it calls readObject() or ReadArray().
+  // These methods execute nodes_.push() just before and nodes_.pop)() just
+  // after calling readValue(). parse() executes one nodes_.push(), so > instead
+  // of >=.
+  if (nodes_.size() > stackLimit_g)
     throwRuntimeError("Exceeded stackLimit in readValue().");
-  ++stackDepth_g;
 
   Token token;
   skipCommentTokens(token);
@@ -404,7 +418,7 @@ bool Reader::readValue()
   if (collectComments_ && !commentsBefore_.empty())
   {
     currentValue().setComment(commentsBefore_, commentBefore);
-    commentsBefore_ = "";
+    commentsBefore_.clear();
   }
 
   switch (token.type_)
@@ -473,7 +487,6 @@ bool Reader::readValue()
     lastValue_ = &currentValue();
   }
 
-  --stackDepth_g;
   return successful;
 }
 
@@ -562,7 +575,7 @@ bool Reader::readToken(Token &token)
   if (!ok)
     token.type_ = tokenError;
   token.end_ = current_;
-  return true;
+  return ok;
 }
 
 void Reader::skipSpaces()
@@ -577,7 +590,7 @@ void Reader::skipSpaces()
   }
 }
 
-bool Reader::match(Location pattern, int patternLength)
+bool Reader::match(const Char *pattern, int patternLength)
 {
   if (end_ - current_ < patternLength)
     return false;
@@ -615,9 +628,9 @@ bool Reader::readComment()
   return true;
 }
 
-static JSONCPP_STRING normalizeEOL(Reader::Location begin, Reader::Location end)
+String Reader::normalizeEOL(Reader::Location begin, Reader::Location end)
 {
-  JSONCPP_STRING normalized;
+  String normalized;
   normalized.reserve(static_cast<size_t>(end - begin));
   Reader::Location current = begin;
   while (current != end)
@@ -642,10 +655,10 @@ static JSONCPP_STRING normalizeEOL(Reader::Location begin, Reader::Location end)
 void Reader::addComment(Location begin, Location end, CommentPlacement placement)
 {
   assert(collectComments_);
-  const JSONCPP_STRING &normalized = normalizeEOL(begin, end);
+  const String &normalized = normalizeEOL(begin, end);
   if (placement == commentAfterOnSameLine)
   {
-    assert(lastValue_ != 0);
+    assert(lastValue_ != nullptr);
     lastValue_->setComment(normalized, placement);
   }
   else
@@ -686,7 +699,7 @@ bool Reader::readCppStyleComment()
 
 void Reader::readNumber()
 {
-  const char *p = current_;
+  Location p = current_;
   char c = '0'; // stopgap for already consumed character
   // integral part
   while (c >= '0' && c <= '9')
@@ -723,13 +736,13 @@ bool Reader::readString()
   return c == '"';
 }
 
-bool Reader::readObject(Token &tokenStart)
+bool Reader::readObject(Token &token)
 {
   Token tokenName;
-  JSONCPP_STRING name;
+  String name;
   Value init(objectValue);
   currentValue().swapPayload(init);
-  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  currentValue().setOffsetStart(token.start_ - begin_);
   while (readToken(tokenName))
   {
     bool initialTokenOk = true;
@@ -739,7 +752,7 @@ bool Reader::readObject(Token &tokenStart)
       break;
     if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
       return true;
-    name = "";
+    name.clear();
     if (tokenName.type_ == tokenString)
     {
       if (!decodeString(tokenName, name))
@@ -750,7 +763,7 @@ bool Reader::readObject(Token &tokenStart)
       Value numberName;
       if (!decodeNumber(tokenName, numberName))
         return recoverFromError(tokenObjectEnd);
-      name = JSONCPP_STRING(numberName.asCString());
+      name = numberName.asString();
     }
     else
     {
@@ -784,11 +797,11 @@ bool Reader::readObject(Token &tokenStart)
   return addErrorAndRecover("Missing '}' or object member name", tokenName, tokenObjectEnd);
 }
 
-bool Reader::readArray(Token &tokenStart)
+bool Reader::readArray(Token &token)
 {
   Value init(arrayValue);
   currentValue().swapPayload(init);
-  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  currentValue().setOffsetStart(token.start_ - begin_);
   skipSpaces();
   if (current_ != end_ && *current_ == ']') // empty array
   {
@@ -806,19 +819,21 @@ bool Reader::readArray(Token &tokenStart)
     if (!ok) // error already set
       return recoverFromError(tokenArrayEnd);
 
-    Token token;
+    Token currentToken;
     // Accept Comment after last item in the array.
-    ok = readToken(token);
-    while (token.type_ == tokenComment && ok)
+    ok = readToken(currentToken);
+    while (currentToken.type_ == tokenComment && ok)
     {
-      ok = readToken(token);
+      ok = readToken(currentToken);
     }
-    bool badTokenType = (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+    bool badTokenType =
+      (currentToken.type_ != tokenArraySeparator && currentToken.type_ != tokenArrayEnd);
     if (!ok || badTokenType)
     {
-      return addErrorAndRecover("Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+      return addErrorAndRecover("Missing ',' or ']' in array declaration", currentToken,
+                                tokenArrayEnd);
     }
-    if (token.type_ == tokenArrayEnd)
+    if (currentToken.type_ == tokenArrayEnd)
       break;
   }
   return true;
@@ -844,9 +859,10 @@ bool Reader::decodeNumber(Token &token, Value &decoded)
   bool isNegative = *current == '-';
   if (isNegative)
     ++current;
-  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+  // TODO: Help the compiler do the div and mod at compile time or get rid of
+  // them.
   Value::LargestUInt maxIntegerValue =
-      isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 : Value::maxLargestUInt;
+    isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 : Value::maxLargestUInt;
   Value::LargestUInt threshold = maxIntegerValue / 10;
   Value::LargestUInt value = 0;
   while (current < token.end_)
@@ -854,7 +870,7 @@ bool Reader::decodeNumber(Token &token, Value &decoded)
     Char c = *current++;
     if (c < '0' || c > '9')
       return decodeDouble(token, decoded);
-    Value::UInt digit(static_cast<Value::UInt>(c - '0'));
+    auto digit(static_cast<Value::UInt>(c - '0'));
     if (value >= threshold)
     {
       // We've hit or exceeded the max value divided by 10 (rounded down). If
@@ -893,17 +909,17 @@ bool Reader::decodeDouble(Token &token)
 bool Reader::decodeDouble(Token &token, Value &decoded)
 {
   double value = 0;
-  JSONCPP_STRING buffer(token.start_, token.end_);
-  JSONCPP_ISTRINGSTREAM is(buffer);
+  String buffer(token.start_, token.end_);
+  IStringStream is(buffer);
   if (!(is >> value))
-    return addError("'" + JSONCPP_STRING(token.start_, token.end_) + "' is not a number.", token);
+    return addError("'" + String(token.start_, token.end_) + "' is not a number.", token);
   decoded = value;
   return true;
 }
 
 bool Reader::decodeString(Token &token)
 {
-  JSONCPP_STRING decoded_string;
+  String decoded_string;
   if (!decodeString(token, decoded_string))
     return false;
   Value decoded(decoded_string);
@@ -913,7 +929,7 @@ bool Reader::decodeString(Token &token)
   return true;
 }
 
-bool Reader::decodeString(Token &token, JSONCPP_STRING &decoded)
+bool Reader::decodeString(Token &token, String &decoded)
 {
   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
   Location current = token.start_ + 1; // skip '"'
@@ -923,7 +939,7 @@ bool Reader::decodeString(Token &token, JSONCPP_STRING &decoded)
     Char c = *current++;
     if (c == '"')
       break;
-    else if (c == '\\')
+    if (c == '\\')
     {
       if (current == end)
         return addError("Empty escape sequence in string", token, current);
@@ -986,9 +1002,9 @@ bool Reader::decodeUnicodeCodePoint(Token &token, Location &current, Location en
     if (end - current < 6)
       return addError("additional six characters expected to parse unicode surrogate pair.", token,
                       current);
-    unsigned int surrogatePair;
     if (*(current++) == '\\' && *(current++) == 'u')
     {
+      unsigned int surrogatePair;
       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair))
       {
         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
@@ -1028,7 +1044,7 @@ bool Reader::decodeUnicodeEscapeSequence(Token &token, Location &current, Locati
   return true;
 }
 
-bool Reader::addError(const JSONCPP_STRING &message, Token &token, Location extra)
+bool Reader::addError(const String &message, Token &token, Location extra)
 {
   ErrorInfo info;
   info.token_ = token;
@@ -1053,8 +1069,7 @@ bool Reader::recoverFromError(TokenType skipUntilToken)
   return false;
 }
 
-bool Reader::addErrorAndRecover(const JSONCPP_STRING &message, Token &token,
-                                TokenType skipUntilToken)
+bool Reader::addErrorAndRecover(const String &message, Token &token, TokenType skipUntilToken)
 {
   addError(message, token);
   return recoverFromError(skipUntilToken);
@@ -1095,24 +1110,23 @@ void Reader::getLocationLineAndColumn(Location location, int &line, int &column)
   ++line;
 }
 
-JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const
+String Reader::getLocationLineAndColumn(Location location) const
 {
   int line, column;
   getLocationLineAndColumn(location, line, column);
   char buffer[18 + 16 + 16 + 1];
-  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+  jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
   return buffer;
 }
 
 // Deprecated. Preserved for backward compatibility
-JSONCPP_STRING Reader::getFormatedErrorMessages() const { return getFormattedErrorMessages(); }
+String Reader::getFormatedErrorMessages() const { return getFormattedErrorMessages(); }
 
-JSONCPP_STRING Reader::getFormattedErrorMessages() const
+String Reader::getFormattedErrorMessages() const
 {
-  JSONCPP_STRING formattedMessage;
-  for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError)
+  String formattedMessage;
+  for (const auto &error : errors_)
   {
-    const ErrorInfo &error = *itError;
     formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
     formattedMessage += "  " + error.message_ + "\n";
     if (error.extra_)
@@ -1124,9 +1138,8 @@ JSONCPP_STRING Reader::getFormattedErrorMessages() const
 std::vector<Reader::StructuredError> Reader::getStructuredErrors() const
 {
   std::vector<Reader::StructuredError> allErrors;
-  for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError)
+  for (const auto &error : errors_)
   {
-    const ErrorInfo &error = *itError;
     Reader::StructuredError structured;
     structured.offset_start = error.token_.start_ - begin_;
     structured.offset_limit = error.token_.end_ - begin_;
@@ -1136,7 +1149,7 @@ std::vector<Reader::StructuredError> Reader::getStructuredErrors() const
   return allErrors;
 }
 
-bool Reader::pushError(const Value &value, const JSONCPP_STRING &message)
+bool Reader::pushError(const Value &value, const String &message)
 {
   ptrdiff_t const length = end_ - begin_;
   if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
@@ -1144,16 +1157,16 @@ bool Reader::pushError(const Value &value, const JSONCPP_STRING &message)
   Token token;
   token.type_ = tokenError;
   token.start_ = begin_ + value.getOffsetStart();
-  token.end_ = end_ + value.getOffsetLimit();
+  token.end_ = begin_ + value.getOffsetLimit();
   ErrorInfo info;
   info.token_ = token;
   info.message_ = message;
-  info.extra_ = 0;
+  info.extra_ = nullptr;
   errors_.push_back(info);
   return true;
 }
 
-bool Reader::pushError(const Value &value, const JSONCPP_STRING &message, const Value &extra)
+bool Reader::pushError(const Value &value, const String &message, const Value &extra)
 {
   ptrdiff_t const length = end_ - begin_;
   if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
@@ -1171,14 +1184,16 @@ bool Reader::pushError(const Value &value, const JSONCPP_STRING &message, const
   return true;
 }
 
-bool Reader::good() const { return !errors_.size(); }
+bool Reader::good() const { return errors_.empty(); }
 
-// exact copy of Features
+// Originally copied from the Features class (now deprecated), used internally
+// for features implementation.
 class OurFeatures
 {
 public:
   static OurFeatures all();
   bool allowComments_;
+  bool allowTrailingCommas_;
   bool strictRoot_;
   bool allowDroppedNullPlaceholders_;
   bool allowNumericKeys_;
@@ -1186,37 +1201,33 @@ public:
   bool failIfExtra_;
   bool rejectDupKeys_;
   bool allowSpecialFloats_;
-  int stackLimit_;
+  bool skipBom_;
+  size_t stackLimit_;
 }; // OurFeatures
 
-// exact copy of Implementation of class Features
-// ////////////////////////////////
-
-OurFeatures OurFeatures::all() { return OurFeatures(); }
+OurFeatures OurFeatures::all() { return {}; }
 
 // Implementation of class Reader
 // ////////////////////////////////
 
-// exact copy of Reader, renamed to OurReader
+// Originally copied from the Reader class (now deprecated), used internally
+// for implementing JSON reading.
 class OurReader
 {
 public:
-  typedef char Char;
-  typedef const Char *Location;
+  using Char = char;
+  using Location = const Char *;
   struct StructuredError
   {
     ptrdiff_t offset_start;
     ptrdiff_t offset_limit;
-    JSONCPP_STRING message;
+    String message;
   };
 
-  OurReader(OurFeatures const &features);
+  explicit OurReader(OurFeatures const &features);
   bool parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments = true);
-  JSONCPP_STRING getFormattedErrorMessages() const;
+  String getFormattedErrorMessages() const;
   std::vector<StructuredError> getStructuredErrors() const;
-  bool pushError(const Value &value, const JSONCPP_STRING &message);
-  bool pushError(const Value &value, const JSONCPP_STRING &message, const Value &extra);
-  bool good() const;
 
 private:
   OurReader(OurReader const &);      // no impl
@@ -1255,17 +1266,18 @@ private:
   {
   public:
     Token token_;
-    JSONCPP_STRING message_;
+    String message_;
     Location extra_;
   };
 
-  typedef std::deque<ErrorInfo> Errors;
+  using Errors = std::deque<ErrorInfo>;
 
   bool readToken(Token &token);
   void skipSpaces();
-  bool match(Location pattern, int patternLength);
+  void skipBom(bool skipBom);
+  bool match(const Char *pattern, int patternLength);
   bool readComment();
-  bool readCStyleComment();
+  bool readCStyleComment(bool *containsNewLineResult);
   bool readCppStyleComment();
   bool readString();
   bool readStringSingleQuote();
@@ -1276,47 +1288,52 @@ private:
   bool decodeNumber(Token &token);
   bool decodeNumber(Token &token, Value &decoded);
   bool decodeString(Token &token);
-  bool decodeString(Token &token, JSONCPP_STRING &decoded);
+  bool decodeString(Token &token, String &decoded);
   bool decodeDouble(Token &token);
   bool decodeDouble(Token &token, Value &decoded);
   bool decodeUnicodeCodePoint(Token &token, Location &current, Location end, unsigned int &unicode);
   bool decodeUnicodeEscapeSequence(Token &token, Location &current, Location end,
                                    unsigned int &unicode);
-  bool addError(const JSONCPP_STRING &message, Token &token, Location extra = 0);
+  bool addError(const String &message, Token &token, Location extra = nullptr);
   bool recoverFromError(TokenType skipUntilToken);
-  bool addErrorAndRecover(const JSONCPP_STRING &message, Token &token, TokenType skipUntilToken);
+  bool addErrorAndRecover(const String &message, Token &token, TokenType skipUntilToken);
   void skipUntilSpace();
   Value &currentValue();
   Char getNextChar();
   void getLocationLineAndColumn(Location location, int &line, int &column) const;
-  JSONCPP_STRING getLocationLineAndColumn(Location location) const;
+  String getLocationLineAndColumn(Location location) const;
   void addComment(Location begin, Location end, CommentPlacement placement);
   void skipCommentTokens(Token &token);
 
-  typedef std::stack<Value *> Nodes;
-  Nodes nodes_;
-  Errors errors_;
-  JSONCPP_STRING document_;
-  Location begin_;
-  Location end_;
-  Location current_;
-  Location lastValueEnd_;
-  Value *lastValue_;
-  JSONCPP_STRING commentsBefore_;
-  int stackDepth_;
+  static String normalizeEOL(Location begin, Location end);
+  static bool containsNewLine(Location begin, Location end);
+
+  using Nodes = std::stack<Value *>;
+
+  Nodes nodes_{};
+  Errors errors_{};
+  String document_{};
+  Location begin_ = nullptr;
+  Location end_ = nullptr;
+  Location current_ = nullptr;
+  Location lastValueEnd_ = nullptr;
+  Value *lastValue_ = nullptr;
+  bool lastValueHasAComment_ = false;
+  String commentsBefore_{};
 
   OurFeatures const features_;
-  bool collectComments_;
+  bool collectComments_ = false;
 }; // OurReader
 
 // complete copy of Read impl, for OurReader
 
-OurReader::OurReader(OurFeatures const &features)
-    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), lastValue_(),
-      commentsBefore_(), stackDepth_(0), features_(features), collectComments_()
+bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end)
 {
+  return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
 }
 
+OurReader::OurReader(OurFeatures const &features) : features_(features) {}
+
 bool OurReader::parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments)
 {
   if (!features_.allowComments_)
@@ -1328,25 +1345,24 @@ bool OurReader::parse(const char *beginDoc, const char *endDoc, Value &root, boo
   end_ = endDoc;
   collectComments_ = collectComments;
   current_ = begin_;
-  lastValueEnd_ = 0;
-  lastValue_ = 0;
-  commentsBefore_ = "";
+  lastValueEnd_ = nullptr;
+  lastValue_ = nullptr;
+  commentsBefore_.clear();
   errors_.clear();
   while (!nodes_.empty())
     nodes_.pop();
   nodes_.push(&root);
 
-  stackDepth_ = 0;
+  // skip byte order mark if it exists at the beginning of the UTF-8 text.
+  skipBom(features_.skipBom_);
   bool successful = readValue();
+  nodes_.pop();
   Token token;
   skipCommentTokens(token);
-  if (features_.failIfExtra_)
+  if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream))
   {
-    if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream)
-    {
-      addError("Extra non-whitespace after JSON value.", token);
-      return false;
-    }
+    addError("Extra non-whitespace after JSON value.", token);
+    return false;
   }
   if (collectComments_ && !commentsBefore_.empty())
     root.setComment(commentsBefore_, commentAfter);
@@ -1368,9 +1384,9 @@ bool OurReader::parse(const char *beginDoc, const char *endDoc, Value &root, boo
 
 bool OurReader::readValue()
 {
-  if (stackDepth_ >= features_.stackLimit_)
+  //  To preserve the old behaviour we cast size_t to int.
+  if (nodes_.size() > features_.stackLimit_)
     throwRuntimeError("Exceeded stackLimit in readValue().");
-  ++stackDepth_;
   Token token;
   skipCommentTokens(token);
   bool successful = true;
@@ -1378,7 +1394,7 @@ bool OurReader::readValue()
   if (collectComments_ && !commentsBefore_.empty())
   {
     currentValue().setComment(commentsBefore_, commentBefore);
-    commentsBefore_ = "";
+    commentsBefore_.clear();
   }
 
   switch (token.type_)
@@ -1468,10 +1484,10 @@ bool OurReader::readValue()
   if (collectComments_)
   {
     lastValueEnd_ = current_;
+    lastValueHasAComment_ = false;
     lastValue_ = &currentValue();
   }
 
-  --stackDepth_;
   return successful;
 }
 
@@ -1519,8 +1535,13 @@ bool OurReader::readToken(Token &token)
       {
         token.type_ = tokenString;
         ok = readStringSingleQuote();
-        break;
-      } // else continue
+      }
+      else
+      {
+        // If we don't allow single quotes, this is a failure case.
+        ok = false;
+      }
+      break;
     case '/':
       token.type_ = tokenComment;
       ok = readComment();
@@ -1549,6 +1570,17 @@ bool OurReader::readToken(Token &token)
         ok = features_.allowSpecialFloats_ && match("nfinity", 7);
       }
       break;
+    case '+':
+      if (readNumber(true))
+      {
+        token.type_ = tokenNumber;
+      }
+      else
+      {
+        token.type_ = tokenPosInf;
+        ok = features_.allowSpecialFloats_ && match("nfinity", 7);
+      }
+      break;
     case 't':
       token.type_ = tokenTrue;
       ok = match("rue", 3);
@@ -1599,7 +1631,7 @@ bool OurReader::readToken(Token &token)
   if (!ok)
     token.type_ = tokenError;
   token.end_ = current_;
-  return true;
+  return ok;
 }
 
 void OurReader::skipSpaces()
@@ -1614,7 +1646,20 @@ void OurReader::skipSpaces()
   }
 }
 
-bool OurReader::match(Location pattern, int patternLength)
+void OurReader::skipBom(bool skipBom)
+{
+  // The default behavior is to skip BOM.
+  if (skipBom)
+  {
+    if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0)
+    {
+      begin_ += 3;
+      current_ = begin_;
+    }
+  }
+}
+
+bool OurReader::match(const Char *pattern, int patternLength)
 {
   if (end_ - current_ < patternLength)
     return false;
@@ -1628,23 +1673,39 @@ bool OurReader::match(Location pattern, int patternLength)
 
 bool OurReader::readComment()
 {
-  Location commentBegin = current_ - 1;
-  Char c = getNextChar();
+  const Location commentBegin = current_ - 1;
+  const Char c = getNextChar();
   bool successful = false;
-  if (c == '*')
-    successful = readCStyleComment();
-  else if (c == '/')
+  bool cStyleWithEmbeddedNewline = false;
+
+  const bool isCStyleComment = (c == '*');
+  const bool isCppStyleComment = (c == '/');
+  if (isCStyleComment)
+  {
+    successful = readCStyleComment(&cStyleWithEmbeddedNewline);
+  }
+  else if (isCppStyleComment)
+  {
     successful = readCppStyleComment();
+  }
+
   if (!successful)
     return false;
 
   if (collectComments_)
   {
     CommentPlacement placement = commentBefore;
-    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin))
+
+    if (!lastValueHasAComment_)
     {
-      if (c != '*' || !containsNewLine(commentBegin, current_))
-        placement = commentAfterOnSameLine;
+      if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin))
+      {
+        if (isCppStyleComment || !cStyleWithEmbeddedNewline)
+        {
+          placement = commentAfterOnSameLine;
+          lastValueHasAComment_ = true;
+        }
+      }
     }
 
     addComment(commentBegin, current_, placement);
@@ -1652,13 +1713,37 @@ bool OurReader::readComment()
   return true;
 }
 
+String OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end)
+{
+  String normalized;
+  normalized.reserve(static_cast<size_t>(end - begin));
+  OurReader::Location current = begin;
+  while (current != end)
+  {
+    char c = *current++;
+    if (c == '\r')
+    {
+      if (current != end && *current == '\n')
+        // convert dos EOL
+        ++current;
+      // convert Mac EOL
+      normalized += '\n';
+    }
+    else
+    {
+      normalized += c;
+    }
+  }
+  return normalized;
+}
+
 void OurReader::addComment(Location begin, Location end, CommentPlacement placement)
 {
   assert(collectComments_);
-  const JSONCPP_STRING &normalized = normalizeEOL(begin, end);
+  const String &normalized = normalizeEOL(begin, end);
   if (placement == commentAfterOnSameLine)
   {
-    assert(lastValue_ != 0);
+    assert(lastValue_ != nullptr);
     lastValue_->setComment(normalized, placement);
   }
   else
@@ -1667,14 +1752,19 @@ void OurReader::addComment(Location begin, Location end, CommentPlacement placem
   }
 }
 
-bool OurReader::readCStyleComment()
+bool OurReader::readCStyleComment(bool *containsNewLineResult)
 {
+  *containsNewLineResult = false;
+
   while ((current_ + 1) < end_)
   {
     Char c = getNextChar();
     if (c == '*' && *current_ == '/')
       break;
+    if (c == '\n')
+      *containsNewLineResult = true;
   }
+
   return getNextChar() == '/';
 }
 
@@ -1699,7 +1789,7 @@ bool OurReader::readCppStyleComment()
 
 bool OurReader::readNumber(bool checkInf)
 {
-  const char *p = current_;
+  Location p = current_;
   if (checkInf && p != end_ && *p == 'I')
   {
     current_ = ++p;
@@ -1755,13 +1845,13 @@ bool OurReader::readStringSingleQuote()
   return c == '\'';
 }
 
-bool OurReader::readObject(Token &tokenStart)
+bool OurReader::readObject(Token &token)
 {
   Token tokenName;
-  JSONCPP_STRING name;
+  String name;
   Value init(objectValue);
   currentValue().swapPayload(init);
-  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  currentValue().setOffsetStart(token.start_ - begin_);
   while (readToken(tokenName))
   {
     bool initialTokenOk = true;
@@ -1769,9 +1859,10 @@ bool OurReader::readObject(Token &tokenStart)
       initialTokenOk = readToken(tokenName);
     if (!initialTokenOk)
       break;
-    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+    if (tokenName.type_ == tokenObjectEnd &&
+        (name.empty() || features_.allowTrailingCommas_)) // empty object or trailing comma
       return true;
-    name = "";
+    name.clear();
     if (tokenName.type_ == tokenString)
     {
       if (!decodeString(tokenName, name))
@@ -1788,19 +1879,19 @@ bool OurReader::readObject(Token &tokenStart)
     {
       break;
     }
-
-    Token colon;
-    if (!readToken(colon) || colon.type_ != tokenMemberSeparator)
-    {
-      return addErrorAndRecover("Missing ':' after object member name", colon, tokenObjectEnd);
-    }
     if (name.length() >= (1U << 30))
       throwRuntimeError("keylength >= 2^30");
     if (features_.rejectDupKeys_ && currentValue().isMember(name))
     {
-      JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
+      String msg = "Duplicate key: '" + name + "'";
       return addErrorAndRecover(msg, tokenName, tokenObjectEnd);
     }
+
+    Token colon;
+    if (!readToken(colon) || colon.type_ != tokenMemberSeparator)
+    {
+      return addErrorAndRecover("Missing ':' after object member name", colon, tokenObjectEnd);
+    }
     Value &value = currentValue()[name];
     nodes_.push(&value);
     bool ok = readValue();
@@ -1823,21 +1914,24 @@ bool OurReader::readObject(Token &tokenStart)
   return addErrorAndRecover("Missing '}' or object member name", tokenName, tokenObjectEnd);
 }
 
-bool OurReader::readArray(Token &tokenStart)
+bool OurReader::readArray(Token &token)
 {
   Value init(arrayValue);
   currentValue().swapPayload(init);
-  currentValue().setOffsetStart(tokenStart.start_ - begin_);
-  skipSpaces();
-  if (current_ != end_ && *current_ == ']') // empty array
-  {
-    Token endArray;
-    readToken(endArray);
-    return true;
-  }
+  currentValue().setOffsetStart(token.start_ - begin_);
   int index = 0;
   for (;;)
   {
+    skipSpaces();
+    if (current_ != end_ && *current_ == ']' &&
+        (index == 0 || (features_.allowTrailingCommas_ &&
+                        !features_.allowDroppedNullPlaceholders_))) // empty array or trailing
+                                                                    // comma
+    {
+      Token endArray;
+      readToken(endArray);
+      return true;
+    }
     Value &value = currentValue()[index++];
     nodes_.push(&value);
     bool ok = readValue();
@@ -1845,19 +1939,21 @@ bool OurReader::readArray(Token &tokenStart)
     if (!ok) // error already set
       return recoverFromError(tokenArrayEnd);
 
-    Token token;
+    Token currentToken;
     // Accept Comment after last item in the array.
-    ok = readToken(token);
-    while (token.type_ == tokenComment && ok)
+    ok = readToken(currentToken);
+    while (currentToken.type_ == tokenComment && ok)
     {
-      ok = readToken(token);
+      ok = readToken(currentToken);
     }
-    bool badTokenType = (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+    bool badTokenType =
+      (currentToken.type_ != tokenArraySeparator && currentToken.type_ != tokenArrayEnd);
     if (!ok || badTokenType)
     {
-      return addErrorAndRecover("Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+      return addErrorAndRecover("Missing ',' or ']' in array declaration", currentToken,
+                                tokenArrayEnd);
     }
-    if (token.type_ == tokenArrayEnd)
+    if (currentToken.type_ == tokenArrayEnd)
       break;
   }
   return true;
@@ -1880,39 +1976,80 @@ bool OurReader::decodeNumber(Token &token, Value &decoded)
   // larger than the maximum supported value of an integer then
   // we decode the number as a double.
   Location current = token.start_;
-  bool isNegative = *current == '-';
+  const bool isNegative = *current == '-';
   if (isNegative)
+  {
     ++current;
-  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
-  Value::LargestUInt maxIntegerValue =
-      isNegative ? Value::LargestUInt(-Value::minLargestInt) : Value::maxLargestUInt;
-  Value::LargestUInt threshold = maxIntegerValue / 10;
+  }
+
+  // We assume we can represent the largest and smallest integer types as
+  // unsigned integers with separate sign. This is only true if they can fit
+  // into an unsigned integer.
+  static_assert(Value::maxLargestInt <= Value::maxLargestUInt, "Int must be smaller than UInt");
+
+  // We need to convert minLargestInt into a positive number. The easiest way
+  // to do this conversion is to assume our "threshold" value of minLargestInt
+  // divided by 10 can fit in maxLargestInt when absolute valued. This should
+  // be a safe assumption.
+  static_assert(Value::minLargestInt <= -Value::maxLargestInt,
+                "The absolute value of minLargestInt must be greater than or "
+                "equal to maxLargestInt");
+  static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt,
+                "The absolute value of minLargestInt must be only 1 magnitude "
+                "larger than maxLargest Int");
+
+  static constexpr Value::LargestUInt positive_threshold = Value::maxLargestUInt / 10;
+  static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10;
+
+  // For the negative values, we have to be more careful. Since typically
+  // -Value::minLargestInt will cause an overflow, we first divide by 10 and
+  // then take the inverse. This assumes that minLargestInt is only a single
+  // power of 10 different in magnitude, which we check above. For the last
+  // digit, we take the modulus before negating for the same reason.
+  static constexpr auto negative_threshold = Value::LargestUInt(-(Value::minLargestInt / 10));
+  static constexpr auto negative_last_digit = Value::UInt(-(Value::minLargestInt % 10));
+
+  const Value::LargestUInt threshold = isNegative ? negative_threshold : positive_threshold;
+  const Value::UInt max_last_digit = isNegative ? negative_last_digit : positive_last_digit;
+
   Value::LargestUInt value = 0;
   while (current < token.end_)
   {
     Char c = *current++;
     if (c < '0' || c > '9')
       return decodeDouble(token, decoded);
-    Value::UInt digit(static_cast<Value::UInt>(c - '0'));
+
+    const auto digit(static_cast<Value::UInt>(c - '0'));
     if (value >= threshold)
     {
       // We've hit or exceeded the max value divided by 10 (rounded down). If
-      // a) we've only just touched the limit, b) this is the last digit, and
+      // a) we've only just touched the limit, meaing value == threshold,
+      // b) this is the last digit, or
       // c) it's small enough to fit in that rounding delta, we're okay.
       // Otherwise treat this number as a double to avoid overflow.
-      if (value > threshold || current != token.end_ || digit > maxIntegerValue % 10)
+      if (value > threshold || current != token.end_ || digit > max_last_digit)
       {
         return decodeDouble(token, decoded);
       }
     }
     value = value * 10 + digit;
   }
+
   if (isNegative)
-    decoded = -Value::LargestInt(value);
-  else if (value <= Value::LargestUInt(Value::maxInt))
+  {
+    // We use the same magnitude assumption here, just in case.
+    const auto last_digit = static_cast<Value::UInt>(value % 10);
+    decoded = -Value::LargestInt(value / 10) * 10 - last_digit;
+  }
+  else if (value <= Value::LargestUInt(Value::maxLargestInt))
+  {
     decoded = Value::LargestInt(value);
+  }
   else
+  {
     decoded = value;
+  }
+
   return true;
 }
 
@@ -1930,47 +2067,19 @@ bool OurReader::decodeDouble(Token &token)
 bool OurReader::decodeDouble(Token &token, Value &decoded)
 {
   double value = 0;
-  const int bufferSize = 32;
-  int count;
-  ptrdiff_t const length = token.end_ - token.start_;
-
-  // Sanity check to avoid buffer overflow exploits.
-  if (length < 0)
-  {
-    return addError("Unable to parse token length", token);
-  }
-  size_t const ulength = static_cast<size_t>(length);
-
-  // Avoid using a string constant for the format control string given to
-  // sscanf, as this can cause hard to debug crashes on OS X. See here for more
-  // info:
-  //
-  //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
-  char format[] = "%lf";
-
-  if (length <= bufferSize)
-  {
-    Char buffer[bufferSize + 1];
-    memcpy(buffer, token.start_, ulength);
-    buffer[length] = 0;
-    fixNumericLocaleInput(buffer, buffer + length);
-    count = sscanf(buffer, format, &value);
-  }
-  else
+  const String buffer(token.start_, token.end_);
+  IStringStream is(buffer);
+  if (!(is >> value))
   {
-    JSONCPP_STRING buffer(token.start_, token.end_);
-    count = sscanf(buffer.c_str(), format, &value);
+    return addError("'" + String(token.start_, token.end_) + "' is not a number.", token);
   }
-
-  if (count != 1)
-    return addError("'" + JSONCPP_STRING(token.start_, token.end_) + "' is not a number.", token);
   decoded = value;
   return true;
 }
 
 bool OurReader::decodeString(Token &token)
 {
-  JSONCPP_STRING decoded_string;
+  String decoded_string;
   if (!decodeString(token, decoded_string))
     return false;
   Value decoded(decoded_string);
@@ -1980,7 +2089,7 @@ bool OurReader::decodeString(Token &token)
   return true;
 }
 
-bool OurReader::decodeString(Token &token, JSONCPP_STRING &decoded)
+bool OurReader::decodeString(Token &token, String &decoded)
 {
   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
   Location current = token.start_ + 1; // skip '"'
@@ -1990,7 +2099,7 @@ bool OurReader::decodeString(Token &token, JSONCPP_STRING &decoded)
     Char c = *current++;
     if (c == '"')
       break;
-    else if (c == '\\')
+    if (c == '\\')
     {
       if (current == end)
         return addError("Empty escape sequence in string", token, current);
@@ -2053,9 +2162,9 @@ bool OurReader::decodeUnicodeCodePoint(Token &token, Location &current, Location
     if (end - current < 6)
       return addError("additional six characters expected to parse unicode surrogate pair.", token,
                       current);
-    unsigned int surrogatePair;
     if (*(current++) == '\\' && *(current++) == 'u')
     {
+      unsigned int surrogatePair;
       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair))
       {
         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
@@ -2095,7 +2204,7 @@ bool OurReader::decodeUnicodeEscapeSequence(Token &token, Location &current, Loc
   return true;
 }
 
-bool OurReader::addError(const JSONCPP_STRING &message, Token &token, Location extra)
+bool OurReader::addError(const String &message, Token &token, Location extra)
 {
   ErrorInfo info;
   info.token_ = token;
@@ -2120,8 +2229,7 @@ bool OurReader::recoverFromError(TokenType skipUntilToken)
   return false;
 }
 
-bool OurReader::addErrorAndRecover(const JSONCPP_STRING &message, Token &token,
-                                   TokenType skipUntilToken)
+bool OurReader::addErrorAndRecover(const String &message, Token &token, TokenType skipUntilToken)
 {
   addError(message, token);
   return recoverFromError(skipUntilToken);
@@ -2162,21 +2270,20 @@ void OurReader::getLocationLineAndColumn(Location location, int &line, int &colu
   ++line;
 }
 
-JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const
+String OurReader::getLocationLineAndColumn(Location location) const
 {
   int line, column;
   getLocationLineAndColumn(location, line, column);
   char buffer[18 + 16 + 16 + 1];
-  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+  jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
   return buffer;
 }
 
-JSONCPP_STRING OurReader::getFormattedErrorMessages() const
+String OurReader::getFormattedErrorMessages() const
 {
-  JSONCPP_STRING formattedMessage;
-  for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError)
+  String formattedMessage;
+  for (const auto &error : errors_)
   {
-    const ErrorInfo &error = *itError;
     formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
     formattedMessage += "  " + error.message_ + "\n";
     if (error.extra_)
@@ -2188,9 +2295,8 @@ JSONCPP_STRING OurReader::getFormattedErrorMessages() const
 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const
 {
   std::vector<OurReader::StructuredError> allErrors;
-  for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError)
+  for (const auto &error : errors_)
   {
-    const ErrorInfo &error = *itError;
     OurReader::StructuredError structured;
     structured.offset_start = error.token_.start_ - begin_;
     structured.offset_limit = error.token_.end_ - begin_;
@@ -2200,43 +2306,6 @@ std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const
   return allErrors;
 }
 
-bool OurReader::pushError(const Value &value, const JSONCPP_STRING &message)
-{
-  ptrdiff_t length = end_ - begin_;
-  if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
-    return false;
-  Token token;
-  token.type_ = tokenError;
-  token.start_ = begin_ + value.getOffsetStart();
-  token.end_ = end_ + value.getOffsetLimit();
-  ErrorInfo info;
-  info.token_ = token;
-  info.message_ = message;
-  info.extra_ = 0;
-  errors_.push_back(info);
-  return true;
-}
-
-bool OurReader::pushError(const Value &value, const JSONCPP_STRING &message, const Value &extra)
-{
-  ptrdiff_t length = end_ - begin_;
-  if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
-      extra.getOffsetLimit() > length)
-    return false;
-  Token token;
-  token.type_ = tokenError;
-  token.start_ = begin_ + value.getOffsetStart();
-  token.end_ = begin_ + value.getOffsetLimit();
-  ErrorInfo info;
-  info.token_ = token;
-  info.message_ = message;
-  info.extra_ = begin_ + extra.getOffsetStart();
-  errors_.push_back(info);
-  return true;
-}
-
-bool OurReader::good() const { return !errors_.size(); }
-
 class OurCharReader : public CharReader
 {
   bool const collectComments_;
@@ -2244,11 +2313,10 @@ class OurCharReader : public CharReader
 
 public:
   OurCharReader(bool collectComments, OurFeatures const &features)
-      : collectComments_(collectComments), reader_(features)
+    : collectComments_(collectComments), reader_(features)
   {
   }
-  bool parse(char const *beginDoc, char const *endDoc, Value *root,
-             JSONCPP_STRING *errs) JSONCPP_OVERRIDE
+  bool parse(char const *beginDoc, char const *endDoc, Value *root, String *errs) override
   {
     bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
     if (errs)
@@ -2260,62 +2328,64 @@ public:
 };
 
 CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
-CharReaderBuilder::~CharReaderBuilder() {}
+CharReaderBuilder::~CharReaderBuilder() = default;
 CharReader *CharReaderBuilder::newCharReader() const
 {
   bool collectComments = settings_["collectComments"].asBool();
   OurFeatures features = OurFeatures::all();
   features.allowComments_ = settings_["allowComments"].asBool();
+  features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool();
   features.strictRoot_ = settings_["strictRoot"].asBool();
   features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
   features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
   features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
-  features.stackLimit_ = settings_["stackLimit"].asInt();
+
+  // Stack limit is always a size_t, so we get this as an unsigned int
+  // regardless of it we have 64-bit integer support enabled.
+  features.stackLimit_ = static_cast<size_t>(settings_["stackLimit"].asUInt());
   features.failIfExtra_ = settings_["failIfExtra"].asBool();
   features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
   features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
+  features.skipBom_ = settings_["skipBom"].asBool();
   return new OurCharReader(collectComments, features);
 }
-static void getValidReaderKeys(std::set<JSONCPP_STRING> *valid_keys)
-{
-  valid_keys->clear();
-  valid_keys->insert("collectComments");
-  valid_keys->insert("allowComments");
-  valid_keys->insert("strictRoot");
-  valid_keys->insert("allowDroppedNullPlaceholders");
-  valid_keys->insert("allowNumericKeys");
-  valid_keys->insert("allowSingleQuotes");
-  valid_keys->insert("stackLimit");
-  valid_keys->insert("failIfExtra");
-  valid_keys->insert("rejectDupKeys");
-  valid_keys->insert("allowSpecialFloats");
-}
+
 bool CharReaderBuilder::validate(Json::Value *invalid) const
 {
-  Json::Value my_invalid;
-  if (!invalid)
-    invalid = &my_invalid; // so we do not need to test for NULL
-  Json::Value &inv = *invalid;
-  std::set<JSONCPP_STRING> valid_keys;
-  getValidReaderKeys(&valid_keys);
-  Value::Members keys = settings_.getMemberNames();
-  size_t n = keys.size();
-  for (size_t i = 0; i < n; ++i)
-  {
-    JSONCPP_STRING const &key = keys[i];
-    if (valid_keys.find(key) == valid_keys.end())
-    {
-      inv[key] = settings_[key];
-    }
+  static const auto &valid_keys = *new std::set<String>{
+    "collectComments",
+    "allowComments",
+    "allowTrailingCommas",
+    "strictRoot",
+    "allowDroppedNullPlaceholders",
+    "allowNumericKeys",
+    "allowSingleQuotes",
+    "stackLimit",
+    "failIfExtra",
+    "rejectDupKeys",
+    "allowSpecialFloats",
+    "skipBom",
+  };
+  for (auto si = settings_.begin(); si != settings_.end(); ++si)
+  {
+    auto key = si.name();
+    if (valid_keys.count(key))
+      continue;
+    if (invalid)
+      (*invalid)[key] = *si;
+    else
+      return false;
   }
-  return 0u == inv.size();
+  return invalid ? invalid->empty() : true;
 }
-Value &CharReaderBuilder::operator[](JSONCPP_STRING key) { return settings_[key]; }
+
+Value &CharReaderBuilder::operator[](const String &key) { return settings_[key]; }
 // static
 void CharReaderBuilder::strictMode(Json::Value *settings)
 {
   //! [CharReaderBuilderStrictMode]
   (*settings)["allowComments"] = false;
+  (*settings)["allowTrailingCommas"] = false;
   (*settings)["strictRoot"] = true;
   (*settings)["allowDroppedNullPlaceholders"] = false;
   (*settings)["allowNumericKeys"] = false;
@@ -2324,6 +2394,7 @@ void CharReaderBuilder::strictMode(Json::Value *settings)
   (*settings)["failIfExtra"] = true;
   (*settings)["rejectDupKeys"] = true;
   (*settings)["allowSpecialFloats"] = false;
+  (*settings)["skipBom"] = true;
   //! [CharReaderBuilderStrictMode]
 }
 // static
@@ -2332,6 +2403,7 @@ void CharReaderBuilder::setDefaults(Json::Value *settings)
   //! [CharReaderBuilderDefaults]
   (*settings)["collectComments"] = true;
   (*settings)["allowComments"] = true;
+  (*settings)["allowTrailingCommas"] = true;
   (*settings)["strictRoot"] = false;
   (*settings)["allowDroppedNullPlaceholders"] = false;
   (*settings)["allowNumericKeys"] = false;
@@ -2340,18 +2412,18 @@ void CharReaderBuilder::setDefaults(Json::Value *settings)
   (*settings)["failIfExtra"] = false;
   (*settings)["rejectDupKeys"] = false;
   (*settings)["allowSpecialFloats"] = false;
+  (*settings)["skipBom"] = true;
   //! [CharReaderBuilderDefaults]
 }
 
 //////////////////////////////////
 // global functions
 
-bool parseFromStream(CharReader::Factory const &fact, JSONCPP_ISTREAM &sin, Value *root,
-                     JSONCPP_STRING *errs)
+bool parseFromStream(CharReader::Factory const &fact, IStream &sin, Value *root, String *errs)
 {
-  JSONCPP_OSTRINGSTREAM ssin;
+  OStringStream ssin;
   ssin << sin.rdbuf();
-  JSONCPP_STRING doc = ssin.str();
+  String doc = ssin.str();
   char const *begin = doc.data();
   char const *end = begin + doc.size();
   // Note that we do not actually need a null-terminator.
@@ -2359,15 +2431,13 @@ bool parseFromStream(CharReader::Factory const &fact, JSONCPP_ISTREAM &sin, Valu
   return reader->parse(begin, end, root, errs);
 }
 
-JSONCPP_ISTREAM &operator>>(JSONCPP_ISTREAM &sin, Value &root)
+IStream &operator>>(IStream &sin, Value &root)
 {
   CharReaderBuilder b;
-  JSONCPP_STRING errs;
+  String errs;
   bool ok = parseFromStream(b, sin, &root, &errs);
   if (!ok)
   {
-    fprintf(stderr, "Error from reader: %s", errs.c_str());
-
     throwRuntimeError(errs);
   }
   return sin;
@@ -2383,7 +2453,7 @@ JSONCPP_ISTREAM &operator>>(JSONCPP_ISTREAM &sin, Value &root)
 // Beginning of content of file: src/lib_json/json_valueiterator.inl
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2007-2010 Baptiste Lepilleur
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -2401,14 +2471,15 @@ namespace Json
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
 
-ValueIteratorBase::ValueIteratorBase() : current_(), isNull_(true) {}
+ValueIteratorBase::ValueIteratorBase() : current_() {}
 
 ValueIteratorBase::ValueIteratorBase(const Value::ObjectValues::iterator &current)
-    : current_(current), isNull_(false)
+  : current_(current), isNull_(false)
 {
 }
 
-Value &ValueIteratorBase::deref() const { return current_->second; }
+Value &ValueIteratorBase::deref() { return current_->second; }
+const Value &ValueIteratorBase::deref() const { return current_->second; }
 
 void ValueIteratorBase::increment() { ++current_; }
 
@@ -2416,9 +2487,6 @@ void ValueIteratorBase::decrement() { --current_; }
 
 ValueIteratorBase::difference_type ValueIteratorBase::computeDistance(const SelfType &other) const
 {
-#ifdef JSON_USE_CPPTL_SMALLMAP
-  return other.current_ - current_;
-#else
   // Iterator for null value are initialized using the default
   // constructor, which initialize current_ to the default
   // std::map::iterator. As begin() and end() are two instance
@@ -2440,7 +2508,6 @@ ValueIteratorBase::difference_type ValueIteratorBase::computeDistance(const Self
     ++myDistance;
   }
   return myDistance;
-#endif
 }
 
 bool ValueIteratorBase::isEqual(const SelfType &other) const
@@ -2478,14 +2545,14 @@ UInt ValueIteratorBase::index() const
   return Value::UInt(-1);
 }
 
-JSONCPP_STRING ValueIteratorBase::name() const
+String ValueIteratorBase::name() const
 {
   char const *keey;
   char const *end;
   keey = memberName(&end);
   if (!keey)
-    return JSONCPP_STRING();
-  return JSONCPP_STRING(keey, end);
+    return String();
+  return String(keey, end);
 }
 
 char const *ValueIteratorBase::memberName() const
@@ -2499,8 +2566,8 @@ char const *ValueIteratorBase::memberName(char const **end) const
   const char *cname = (*current_).first.data();
   if (!cname)
   {
-    *end = NULL;
-    return NULL;
+    *end = nullptr;
+    return nullptr;
   }
   *end = cname + (*current_).first.length();
   return cname;
@@ -2514,10 +2581,10 @@ char const *ValueIteratorBase::memberName(char const **end) const
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
 
-ValueConstIterator::ValueConstIterator() {}
+ValueConstIterator::ValueConstIterator() = default;
 
 ValueConstIterator::ValueConstIterator(const Value::ObjectValues::iterator &current)
-    : ValueIteratorBase(current)
+  : ValueIteratorBase(current)
 {
 }
 
@@ -2537,10 +2604,10 @@ ValueConstIterator &ValueConstIterator::operator=(const ValueIteratorBase &other
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
 
-ValueIterator::ValueIterator() {}
+ValueIterator::ValueIterator() = default;
 
 ValueIterator::ValueIterator(const Value::ObjectValues::iterator &current)
-    : ValueIteratorBase(current)
+  : ValueIteratorBase(current)
 {
 }
 
@@ -2549,7 +2616,7 @@ ValueIterator::ValueIterator(const ValueConstIterator &other) : ValueIteratorBas
   throwRuntimeError("ConstIterator to Iterator should never be allowed.");
 }
 
-ValueIterator::ValueIterator(const ValueIterator &other) : ValueIteratorBase(other) {}
+ValueIterator::ValueIterator(const ValueIterator &other) = default;
 
 ValueIterator &ValueIterator::operator=(const SelfType &other)
 {
@@ -2567,7 +2634,7 @@ ValueIterator &ValueIterator::operator=(const SelfType &other)
 // Beginning of content of file: src/lib_json/json_value.cpp
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2011 Baptiste Lepilleur
+// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
@@ -2577,21 +2644,56 @@ ValueIterator &ValueIterator::operator=(const SelfType &other)
 #include <json/value.h>
 #include <json/writer.h>
 #endif // if !defined(JSON_IS_AMALGAMATION)
-#include <math.h>
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <cstddef>
+#include <cstring>
+#include <iostream>
 #include <sstream>
 #include <utility>
-#include <cstring>
-#include <cassert>
-#ifdef JSON_USE_CPPTL
-#include <cpptl/conststring.h>
+
+// Provide implementation equivalent of std::snprintf for older _MSC compilers
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#include <stdarg.h>
+static int msvc_pre1900_c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
+{
+  int count = -1;
+  if (size != 0)
+    count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
+  if (count == -1)
+    count = _vscprintf(format, ap);
+  return count;
+}
+
+int JSON_API msvc_pre1900_c99_snprintf(char *outBuf, size_t size, const char *format, ...)
+{
+  va_list ap;
+  va_start(ap, format);
+  const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap);
+  va_end(ap);
+  return count;
+}
+#endif
+
+// Disable warning C4702 : unreachable code
+#if defined(_MSC_VER)
+#pragma warning(disable : 4702)
 #endif
-#include <cstddef>   // size_t
-#include <algorithm> // min()
 
 #define JSON_ASSERT_UNREACHABLE assert(false)
 
 namespace Json
 {
+template <typename T> static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T> &p)
+{
+  std::unique_ptr<T> r;
+  if (p)
+  {
+    r = std::unique_ptr<T>(new T(*p));
+  }
+  return r;
+}
 
 // This is a walkaround to avoid the static initialization of Value::null.
 // kNull must be word-aligned to avoid crashing on ARM.  We use an alignment of
@@ -2601,10 +2703,6 @@ namespace Json
 #else
 #define ALIGNAS(byte_alignment)
 #endif
-// static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
-// const unsigned char& kNullRef = kNull[0];
-// const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
-// const Value& Value::nullRef = null;
 
 // static
 Value const &Value::nullSingleton()
@@ -2613,34 +2711,22 @@ Value const &Value::nullSingleton()
   return nullStatic;
 }
 
-// for backwards compatibility, we'll leave these global references around, but DO NOT
-// use them in JSONCPP library code any more!
+#if JSON_USE_NULLREF
+// for backwards compatibility, we'll leave these global references around, but
+// DO NOT use them in JSONCPP library code any more!
+// static
 Value const &Value::null = Value::nullSingleton();
+
+// static
 Value const &Value::nullRef = Value::nullSingleton();
-
-const Int Value::minInt = Int(~(UInt(-1) / 2));
-const Int Value::maxInt = Int(UInt(-1) / 2);
-const UInt Value::maxUInt = UInt(-1);
-#if defined(JSON_HAS_INT64)
-const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
-const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
-const UInt64 Value::maxUInt64 = UInt64(-1);
-// The constant is hard-coded because some compiler have trouble
-// converting Value::maxUInt64 to a double correctly (AIX/xlC).
-// Assumes that UInt64 is a 64 bits integer.
-static const double maxUInt64AsDouble = 18446744073709551615.0;
-#endif // defined(JSON_HAS_INT64)
-const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
-const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
-const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
+#endif
 
 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 template <typename T, typename U> static inline bool InRange(double d, T min, U max)
 {
   // The casts can lose precision, but we are looking only for
   // an approximate range. Might fail on edge cases though. ~cdunn
-  // return d >= static_cast<double>(min) && d <= static_cast<double>(max);
-  return d >= min && d <= max;
+  return d >= static_cast<double>(min) && d <= static_cast<double>(max);
 }
 #else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
 static inline double integerToDouble(Json::UInt64 value)
@@ -2673,8 +2759,8 @@ static inline char *duplicateStringValue(const char *value, size_t length)
   if (length >= static_cast<size_t>(Value::maxInt))
     length = Value::maxInt - 1;
 
-  char *newString = static_cast<char *>(malloc(length + 1));
-  if (newString == NULL)
+  auto newString = static_cast<char *>(malloc(length + 1));
+  if (newString == nullptr)
   {
     throwRuntimeError("in Json::Value::duplicateStringValue(): "
                       "Failed to allocate string value buffer");
@@ -2693,9 +2779,9 @@ static inline char *duplicateAndPrefixStringValue(const char *value, unsigned in
   JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
                       "in Json::Value::duplicateAndPrefixStringValue(): "
                       "length too big for prefixing");
-  unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
-  char *newString = static_cast<char *>(malloc(actualLength));
-  if (newString == 0)
+  size_t actualLength = sizeof(length) + length + 1;
+  auto newString = static_cast<char *>(malloc(actualLength));
+  if (newString == nullptr)
   {
     throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
                       "Failed to allocate string value buffer");
@@ -2719,7 +2805,8 @@ inline static void decodePrefixedString(bool isPrefixed, char const *prefixed, u
     *value = prefixed + sizeof(unsigned);
   }
 }
-/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
+/** Free the string duplicated by
+ * duplicateStringValue()/duplicateAndPrefixStringValue().
  */
 #if JSONCPP_USING_SECURE_MEMORY
 static inline void releasePrefixedStringValue(char *value)
@@ -2760,43 +2847,26 @@ static inline void releaseStringValue(char *value, unsigned) { free(value); }
 namespace Json
 {
 
-Exception::Exception(JSONCPP_STRING const &msg) : msg_(msg) {}
-Exception::~Exception() throw() {}
-char const *Exception::what() const throw() { return msg_.c_str(); }
-RuntimeError::RuntimeError(JSONCPP_STRING const &msg) : Exception(msg) {}
-LogicError::LogicError(JSONCPP_STRING const &msg) : Exception(msg) {}
-JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const &msg) { throw RuntimeError(msg); }
-JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const &msg) { throw LogicError(msg); }
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class Value::CommentInfo
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-Value::CommentInfo::CommentInfo() : comment_(0) {}
-
-Value::CommentInfo::~CommentInfo()
+#if JSON_USE_EXCEPTION
+Exception::Exception(String msg) : msg_(std::move(msg)) {}
+Exception::~Exception() noexcept = default;
+char const *Exception::what() const noexcept { return msg_.c_str(); }
+RuntimeError::RuntimeError(String const &msg) : Exception(msg) {}
+LogicError::LogicError(String const &msg) : Exception(msg) {}
+JSONCPP_NORETURN void throwRuntimeError(String const &msg) { throw RuntimeError(msg); }
+JSONCPP_NORETURN void throwLogicError(String const &msg) { throw LogicError(msg); }
+#else // !JSON_USE_EXCEPTION
+JSONCPP_NORETURN void throwRuntimeError(String const &msg)
 {
-  if (comment_)
-    releaseStringValue(comment_, 0u);
+  std::cerr << msg << std::endl;
+  abort();
 }
-
-void Value::CommentInfo::setComment(const char *text, size_t len)
+JSONCPP_NORETURN void throwLogicError(String const &msg)
 {
-  if (comment_)
-  {
-    releaseStringValue(comment_, 0u);
-    comment_ = 0;
-  }
-  JSON_ASSERT(text != 0);
-  JSON_ASSERT_MESSAGE(text[0] == '\0' || text[0] == '/',
-                      "in Json::Value::setComment(): Comments must start with /");
-  // It seems that /**/ style comments are acceptable as well.
-  comment_ = duplicateStringValue(text, len);
+  std::cerr << msg << std::endl;
+  abort();
 }
+#endif
 
 // //////////////////////////////////////////////////////////////////
 // //////////////////////////////////////////////////////////////////
@@ -2809,46 +2879,44 @@ void Value::CommentInfo::setComment(const char *text, size_t len)
 // Notes: policy_ indicates if the string was allocated when
 // a string is stored.
 
-Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
+Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}
 
-Value::CZString::CZString(char const *str, unsigned ulength, DuplicationPolicy allocate)
-    : cstr_(str)
+Value::CZString::CZString(char const *str, unsigned length, DuplicationPolicy allocate) : cstr_(str)
 {
   // allocate != duplicate
   storage_.policy_ = allocate & 0x3;
-  storage_.length_ = ulength & 0x3FFFFFFF;
+  storage_.length_ = length & 0x3FFFFFFF;
 }
 
 Value::CZString::CZString(const CZString &other)
 {
-  cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
-               ? duplicateStringValue(other.cstr_, other.storage_.length_)
-               : other.cstr_);
+  cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
+             ? duplicateStringValue(other.cstr_, other.storage_.length_)
+             : other.cstr_);
   storage_.policy_ =
-      static_cast<unsigned>(
-          other.cstr_ ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
-                             ? noDuplication
-                             : duplicate)
-                      : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
-      3U;
+    static_cast<unsigned>(
+      other.cstr_
+        ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication ? noDuplication
+                                                                                   : duplicate)
+        : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
+    3U;
   storage_.length_ = other.storage_.length_;
 }
 
-#if JSON_HAS_RVALUE_REFERENCES
-Value::CZString::CZString(CZString &&other) : cstr_(other.cstr_), index_(other.index_)
+Value::CZString::CZString(CZString &&other) noexcept : cstr_(other.cstr_), index_(other.index_)
 {
   other.cstr_ = nullptr;
 }
-#endif
 
 Value::CZString::~CZString()
 {
   if (cstr_ && storage_.policy_ == duplicate)
   {
-    releaseStringValue(const_cast<char *>(cstr_), storage_.length_ + 1u); //+1 for null terminating
-                                                                          // character for sake of
-    // completeness but not
-    // actually necessary
+    releaseStringValue(const_cast<char *>(cstr_),
+                       storage_.length_ + 1U); // +1 for null terminating
+                                               // character for sake of
+                                               // completeness but not actually
+                                               // necessary
   }
 }
 
@@ -2858,9 +2926,18 @@ void Value::CZString::swap(CZString &other)
   std::swap(index_, other.index_);
 }
 
-Value::CZString &Value::CZString::operator=(CZString other)
+Value::CZString &Value::CZString::operator=(const CZString &other)
 {
-  swap(other);
+  cstr_ = other.cstr_;
+  index_ = other.index_;
+  return *this;
+}
+
+Value::CZString &Value::CZString::operator=(CZString &&other) noexcept
+{
+  cstr_ = other.cstr_;
+  index_ = other.index_;
+  other.cstr_ = nullptr;
   return *this;
 }
 
@@ -2872,7 +2949,7 @@ bool Value::CZString::operator<(const CZString &other) const
   // Assume both are strings.
   unsigned this_len = this->storage_.length_;
   unsigned other_len = other.storage_.length_;
-  unsigned min_len = std::min(this_len, other_len);
+  unsigned min_len = std::min<unsigned>(this_len, other_len);
   JSON_ASSERT(this->cstr_ && other.cstr_);
   int comp = memcmp(this->cstr_, other.cstr_, min_len);
   if (comp < 0)
@@ -2916,11 +2993,11 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
  * memset( this, 0, sizeof(Value) )
  * This optimization is used in ValueInternalMap fast allocator.
  */
-Value::Value(ValueType vtype)
+Value::Value(ValueType type)
 {
-  static char const empty[] = "";
-  initBasic(vtype);
-  switch (vtype)
+  static char const emptyString[] = "";
+  initBasic(type);
+  switch (type)
   {
     case nullValue:
       break;
@@ -2933,7 +3010,7 @@ Value::Value(ValueType vtype)
       break;
     case stringValue:
       // allocated_ == false, so this is safe.
-      value_.string_ = const_cast<char *>(static_cast<char const *>(empty));
+      value_.string_ = const_cast<char *>(static_cast<char const *>(emptyString));
       break;
     case arrayValue:
     case objectValue:
@@ -2980,21 +3057,21 @@ Value::Value(double value)
 Value::Value(const char *value)
 {
   initBasic(stringValue, true);
+  JSON_ASSERT_MESSAGE(value != nullptr, "Null Value Passed to Value Constructor");
   value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
 }
 
-Value::Value(const char *beginValue, const char *endValue)
+Value::Value(const char *begin, const char *end)
 {
   initBasic(stringValue, true);
-  value_.string_ =
-      duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
+  value_.string_ = duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin));
 }
 
-Value::Value(const JSONCPP_STRING &value)
+Value::Value(const String &value)
 {
   initBasic(stringValue, true);
   value_.string_ =
-      duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
+    duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
 }
 
 Value::Value(const StaticString &value)
@@ -3003,118 +3080,52 @@ Value::Value(const StaticString &value)
   value_.string_ = const_cast<char *>(value.c_str());
 }
 
-#ifdef JSON_USE_CPPTL
-Value::Value(const CppTL::ConstString &value)
-{
-  initBasic(stringValue, true);
-  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
-}
-#endif
-
 Value::Value(bool value)
 {
   initBasic(booleanValue);
   value_.bool_ = value;
 }
 
-Value::Value(Value const &other)
-    : type_(other.type_), allocated_(false), comments_(0), start_(other.start_),
-      limit_(other.limit_)
+Value::Value(const Value &other)
 {
-  switch (type_)
-  {
-    case nullValue:
-    case intValue:
-    case uintValue:
-    case realValue:
-    case booleanValue:
-      value_ = other.value_;
-      break;
-    case stringValue:
-      if (other.value_.string_ && other.allocated_)
-      {
-        unsigned len;
-        char const *str;
-        decodePrefixedString(other.allocated_, other.value_.string_, &len, &str);
-        value_.string_ = duplicateAndPrefixStringValue(str, len);
-        allocated_ = true;
-      }
-      else
-      {
-        value_.string_ = other.value_.string_;
-        allocated_ = false;
-      }
-      break;
-    case arrayValue:
-    case objectValue:
-      value_.map_ = new ObjectValues(*other.value_.map_);
-      break;
-    default:
-      JSON_ASSERT_UNREACHABLE;
-  }
-  if (other.comments_)
-  {
-    comments_ = new CommentInfo[numberOfCommentPlacement];
-    for (int comment = 0; comment < numberOfCommentPlacement; ++comment)
-    {
-      const CommentInfo &otherComment = other.comments_[comment];
-      if (otherComment.comment_)
-        comments_[comment].setComment(otherComment.comment_, strlen(otherComment.comment_));
-    }
-  }
+  dupPayload(other);
+  dupMeta(other);
 }
 
-#if JSON_HAS_RVALUE_REFERENCES
-// Move constructor
-Value::Value(Value &&other)
+Value::Value(Value &&other) noexcept
 {
   initBasic(nullValue);
   swap(other);
 }
-#endif
 
 Value::~Value()
 {
-  switch (type_)
-  {
-    case nullValue:
-    case intValue:
-    case uintValue:
-    case realValue:
-    case booleanValue:
-      break;
-    case stringValue:
-      if (allocated_)
-        releasePrefixedStringValue(value_.string_);
-      break;
-    case arrayValue:
-    case objectValue:
-      delete value_.map_;
-      break;
-    default:
-      JSON_ASSERT_UNREACHABLE;
-  }
-
-  delete[] comments_;
-
+  releasePayload();
   value_.uint_ = 0;
 }
 
-Value &Value::operator=(Value other)
+Value &Value::operator=(const Value &other)
 {
-  swap(other);
+  Value(other).swap(*this);
+  return *this;
+}
+
+Value &Value::operator=(Value &&other) noexcept
+{
+  other.swap(*this);
   return *this;
 }
 
 void Value::swapPayload(Value &other)
 {
-  ValueType temp = type_;
-  type_ = other.type_;
-  other.type_ = temp;
+  std::swap(bits_, other.bits_);
   std::swap(value_, other.value_);
-  int temp2 = allocated_;
-  allocated_ = other.allocated_;
-  other.allocated_ = temp2 & 0x1;
+}
+
+void Value::copyPayload(const Value &other)
+{
+  releasePayload();
+  dupPayload(other);
 }
 
 void Value::swap(Value &other)
@@ -3125,7 +3136,13 @@ void Value::swap(Value &other)
   std::swap(limit_, other.limit_);
 }
 
-ValueType Value::type() const { return type_; }
+void Value::copy(const Value &other)
+{
+  copyPayload(other);
+  dupMeta(other);
+}
+
+ValueType Value::type() const { return static_cast<ValueType>(bits_.value_type_); }
 
 int Value::compare(const Value &other) const
 {
@@ -3138,10 +3155,10 @@ int Value::compare(const Value &other) const
 
 bool Value::operator<(const Value &other) const
 {
-  int typeDelta = type_ - other.type_;
+  int typeDelta = type() - other.type();
   if (typeDelta)
-    return typeDelta < 0 ? true : false;
-  switch (type_)
+    return typeDelta < 0;
+  switch (type())
   {
     case nullValue:
       return false;
@@ -3155,20 +3172,17 @@ bool Value::operator<(const Value &other) const
       return value_.bool_ < other.value_.bool_;
     case stringValue:
     {
-      if ((value_.string_ == 0) || (other.value_.string_ == 0))
+      if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr))
       {
-        if (other.value_.string_)
-          return true;
-        else
-          return false;
+        return other.value_.string_ != nullptr;
       }
       unsigned this_len;
       unsigned other_len;
       char const *this_str;
       char const *other_str;
-      decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
-      decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
-      unsigned min_len = std::min(this_len, other_len);
+      decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, &this_str);
+      decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, &other_str);
+      unsigned min_len = std::min<unsigned>(this_len, other_len);
       JSON_ASSERT(this_str && other_str);
       int comp = memcmp(this_str, other_str, min_len);
       if (comp < 0)
@@ -3180,9 +3194,10 @@ bool Value::operator<(const Value &other) const
     case arrayValue:
     case objectValue:
     {
-      int delta = int(value_.map_->size() - other.value_.map_->size());
-      if (delta)
-        return delta < 0;
+      auto thisSize = value_.map_->size();
+      auto otherSize = other.value_.map_->size();
+      if (thisSize != otherSize)
+        return thisSize < otherSize;
       return (*value_.map_) < (*other.value_.map_);
     }
     default:
@@ -3199,14 +3214,9 @@ bool Value::operator>(const Value &other) const { return other < *this; }
 
 bool Value::operator==(const Value &other) const
 {
-  // if ( type_ != other.type_ )
-  // GCC 2.95.3 says:
-  // attempt to take address of bit-field structure member `Json::Value::type_'
-  // Beats me, but a temp solves the problem.
-  int temp = other.type_;
-  if (type_ != temp)
+  if (type() != other.type())
     return false;
-  switch (type_)
+  switch (type())
   {
     case nullValue:
       return true;
@@ -3220,7 +3230,7 @@ bool Value::operator==(const Value &other) const
       return value_.bool_ == other.value_.bool_;
     case stringValue:
     {
-      if ((value_.string_ == 0) || (other.value_.string_ == 0))
+      if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr))
       {
         return (value_.string_ == other.value_.string_);
       }
@@ -3228,8 +3238,8 @@ bool Value::operator==(const Value &other) const
       unsigned other_len;
       char const *this_str;
       char const *other_str;
-      decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
-      decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+      decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, &this_str);
+      decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, &other_str);
       if (this_len != other_len)
         return false;
       JSON_ASSERT(this_str && other_str);
@@ -3250,54 +3260,54 @@ bool Value::operator!=(const Value &other) const { return !(*this == other); }
 
 const char *Value::asCString() const
 {
-  JSON_ASSERT_MESSAGE(type_ == stringValue, "in Json::Value::asCString(): requires stringValue");
-  if (value_.string_ == 0)
-    return 0;
+  JSON_ASSERT_MESSAGE(type() == stringValue, "in Json::Value::asCString(): requires stringValue");
+  if (value_.string_ == nullptr)
+    return nullptr;
   unsigned this_len;
   char const *this_str;
-  decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+  decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, &this_str);
   return this_str;
 }
 
 #if JSONCPP_USING_SECURE_MEMORY
 unsigned Value::getCStringLength() const
 {
-  JSON_ASSERT_MESSAGE(type_ == stringValue, "in Json::Value::asCString(): requires stringValue");
+  JSON_ASSERT_MESSAGE(type() == stringValue, "in Json::Value::asCString(): requires stringValue");
   if (value_.string_ == 0)
     return 0;
   unsigned this_len;
   char const *this_str;
-  decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+  decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, &this_str);
   return this_len;
 }
 #endif
 
-bool Value::getString(char const **str, char const **cend) const
+bool Value::getString(char const **begin, char const **end) const
 {
-  if (type_ != stringValue)
+  if (type() != stringValue)
     return false;
-  if (value_.string_ == 0)
+  if (value_.string_ == nullptr)
     return false;
   unsigned length;
-  decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
-  *cend = *str + length;
+  decodePrefixedString(this->isAllocated(), this->value_.string_, &length, begin);
+  *end = *begin + length;
   return true;
 }
 
-JSONCPP_STRING Value::asString() const
+String Value::asString() const
 {
-  switch (type_)
+  switch (type())
   {
     case nullValue:
       return "";
     case stringValue:
     {
-      if (value_.string_ == 0)
+      if (value_.string_ == nullptr)
         return "";
       unsigned this_len;
       char const *this_str;
-      decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
-      return JSONCPP_STRING(this_str, this_len);
+      decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, &this_str);
+      return String(this_str, this_len);
     }
     case booleanValue:
       return value_.bool_ ? "true" : "false";
@@ -3312,19 +3322,9 @@ JSONCPP_STRING Value::asString() const
   }
 }
 
-#ifdef JSON_USE_CPPTL
-CppTL::ConstString Value::asConstString() const
-{
-  unsigned len;
-  char const *str;
-  decodePrefixedString(allocated_, value_.string_, &len, &str);
-  return CppTL::ConstString(str, len);
-}
-#endif
-
 Value::Int Value::asInt() const
 {
-  switch (type_)
+  switch (type())
   {
     case intValue:
       JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
@@ -3347,7 +3347,7 @@ Value::Int Value::asInt() const
 
 Value::UInt Value::asUInt() const
 {
-  switch (type_)
+  switch (type())
   {
     case intValue:
       JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
@@ -3372,7 +3372,7 @@ Value::UInt Value::asUInt() const
 
 Value::Int64 Value::asInt64() const
 {
-  switch (type_)
+  switch (type())
   {
     case intValue:
       return Int64(value_.int_);
@@ -3394,7 +3394,7 @@ Value::Int64 Value::asInt64() const
 
 Value::UInt64 Value::asUInt64() const
 {
-  switch (type_)
+  switch (type())
   {
     case intValue:
       JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
@@ -3435,7 +3435,7 @@ LargestUInt Value::asLargestUInt() const
 
 double Value::asDouble() const
 {
-  switch (type_)
+  switch (type())
   {
     case intValue:
       return static_cast<double>(value_.int_);
@@ -3459,7 +3459,7 @@ double Value::asDouble() const
 
 float Value::asFloat() const
 {
-  switch (type_)
+  switch (type())
   {
     case intValue:
       return static_cast<float>(value_.int_);
@@ -3475,7 +3475,7 @@ float Value::asFloat() const
     case nullValue:
       return 0.0;
     case booleanValue:
-      return value_.bool_ ? 1.0f : 0.0f;
+      return value_.bool_ ? 1.0F : 0.0F;
     default:
       break;
   }
@@ -3484,19 +3484,22 @@ float Value::asFloat() const
 
 bool Value::asBool() const
 {
-  switch (type_)
+  switch (type())
   {
     case booleanValue:
       return value_.bool_;
     case nullValue:
       return false;
     case intValue:
-      return value_.int_ ? true : false;
+      return value_.int_ != 0;
     case uintValue:
-      return value_.uint_ ? true : false;
+      return value_.uint_ != 0;
     case realValue:
-      // This is kind of strange. Not recommended.
-      return (value_.real_ != 0.0) ? true : false;
+    {
+      // According to JavaScript language zero or NaN is regarded as false
+      const auto value_classification = std::fpclassify(value_.real_);
+      return value_classification != FP_ZERO && value_classification != FP_NAN;
+    }
     default:
       break;
   }
@@ -3508,27 +3511,26 @@ bool Value::isConvertibleTo(ValueType other) const
   switch (other)
   {
     case nullValue:
-      return (isNumeric() && asDouble() == 0.0) ||
-             (type_ == booleanValue && value_.bool_ == false) ||
-             (type_ == stringValue && asString() == "") ||
-             (type_ == arrayValue && value_.map_->size() == 0) ||
-             (type_ == objectValue && value_.map_->size() == 0) || type_ == nullValue;
+      return (isNumeric() && asDouble() == 0.0) || (type() == booleanValue && !value_.bool_) ||
+             (type() == stringValue && asString().empty()) ||
+             (type() == arrayValue && value_.map_->empty()) ||
+             (type() == objectValue && value_.map_->empty()) || type() == nullValue;
     case intValue:
-      return isInt() || (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
-             type_ == booleanValue || type_ == nullValue;
+      return isInt() || (type() == realValue && InRange(value_.real_, minInt, maxInt)) ||
+             type() == booleanValue || type() == nullValue;
     case uintValue:
-      return isUInt() || (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
-             type_ == booleanValue || type_ == nullValue;
+      return isUInt() || (type() == realValue && InRange(value_.real_, 0, maxUInt)) ||
+             type() == booleanValue || type() == nullValue;
     case realValue:
-      return isNumeric() || type_ == booleanValue || type_ == nullValue;
+      return isNumeric() || type() == booleanValue || type() == nullValue;
     case booleanValue:
-      return isNumeric() || type_ == booleanValue || type_ == nullValue;
+      return isNumeric() || type() == booleanValue || type() == nullValue;
     case stringValue:
-      return isNumeric() || type_ == booleanValue || type_ == stringValue || type_ == nullValue;
+      return isNumeric() || type() == booleanValue || type() == stringValue || type() == nullValue;
     case arrayValue:
-      return type_ == arrayValue || type_ == nullValue;
+      return type() == arrayValue || type() == nullValue;
     case objectValue:
-      return type_ == objectValue || type_ == nullValue;
+      return type() == objectValue || type() == nullValue;
   }
   JSON_ASSERT_UNREACHABLE;
   return false;
@@ -3537,7 +3539,7 @@ bool Value::isConvertibleTo(ValueType other) const
 /// Number of values in array or object
 ArrayIndex Value::size() const
 {
-  switch (type_)
+  switch (type())
   {
     case nullValue:
     case intValue:
@@ -3564,20 +3566,19 @@ ArrayIndex Value::size() const
 bool Value::empty() const
 {
   if (isNull() || isArray() || isObject())
-    return size() == 0u;
-  else
-    return false;
+    return size() == 0U;
+  return false;
 }
 
-bool Value::operator!() const { return isNull(); }
+Value::operator bool() const { return !isNull(); }
 
 void Value::clear()
 {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || type_ == objectValue,
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue || type() == objectValue,
                       "in Json::Value::clear(): requires complex value");
   start_ = 0;
   limit_ = 0;
-  switch (type_)
+  switch (type())
   {
     case arrayValue:
     case objectValue:
@@ -3590,15 +3591,16 @@ void Value::clear()
 
 void Value::resize(ArrayIndex newSize)
 {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
                       "in Json::Value::resize(): requires arrayValue");
-  if (type_ == nullValue)
+  if (type() == nullValue)
     *this = Value(arrayValue);
   ArrayIndex oldSize = size();
   if (newSize == 0)
     clear();
   else if (newSize > oldSize)
-    (*this)[newSize - 1];
+    for (ArrayIndex i = oldSize; i < newSize; ++i)
+      (*this)[i];
   else
   {
     for (ArrayIndex index = newSize; index < oldSize; ++index)
@@ -3611,12 +3613,12 @@ void Value::resize(ArrayIndex newSize)
 
 Value &Value::operator[](ArrayIndex index)
 {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
                       "in Json::Value::operator[](ArrayIndex): requires arrayValue");
-  if (type_ == nullValue)
+  if (type() == nullValue)
     *this = Value(arrayValue);
   CZString key(index);
-  ObjectValues::iterator it = value_.map_->lower_bound(key);
+  auto it = value_.map_->lower_bound(key);
   if (it != value_.map_->end() && (*it).first == key)
     return (*it).second;
 
@@ -3634,9 +3636,9 @@ Value &Value::operator[](int index)
 
 const Value &Value::operator[](ArrayIndex index) const
 {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
                       "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
-  if (type_ == nullValue)
+  if (type() == nullValue)
     return nullSingleton();
   CZString key(index);
   ObjectValues::const_iterator it = value_.map_->find(key);
@@ -3652,26 +3654,93 @@ const Value &Value::operator[](int index) const
   return (*this)[ArrayIndex(index)];
 }
 
-void Value::initBasic(ValueType vtype, bool allocated)
+void Value::initBasic(ValueType type, bool allocated)
 {
-  type_ = vtype;
-  allocated_ = allocated;
-  comments_ = 0;
+  setType(type);
+  setIsAllocated(allocated);
+  comments_ = Comments{};
   start_ = 0;
   limit_ = 0;
 }
 
+void Value::dupPayload(const Value &other)
+{
+  setType(other.type());
+  setIsAllocated(false);
+  switch (type())
+  {
+    case nullValue:
+    case intValue:
+    case uintValue:
+    case realValue:
+    case booleanValue:
+      value_ = other.value_;
+      break;
+    case stringValue:
+      if (other.value_.string_ && other.isAllocated())
+      {
+        unsigned len;
+        char const *str;
+        decodePrefixedString(other.isAllocated(), other.value_.string_, &len, &str);
+        value_.string_ = duplicateAndPrefixStringValue(str, len);
+        setIsAllocated(true);
+      }
+      else
+      {
+        value_.string_ = other.value_.string_;
+      }
+      break;
+    case arrayValue:
+    case objectValue:
+      value_.map_ = new ObjectValues(*other.value_.map_);
+      break;
+    default:
+      JSON_ASSERT_UNREACHABLE;
+  }
+}
+
+void Value::releasePayload()
+{
+  switch (type())
+  {
+    case nullValue:
+    case intValue:
+    case uintValue:
+    case realValue:
+    case booleanValue:
+      break;
+    case stringValue:
+      if (isAllocated())
+        releasePrefixedStringValue(value_.string_);
+      break;
+    case arrayValue:
+    case objectValue:
+      delete value_.map_;
+      break;
+    default:
+      JSON_ASSERT_UNREACHABLE;
+  }
+}
+
+void Value::dupMeta(const Value &other)
+{
+  comments_ = other.comments_;
+  start_ = other.start_;
+  limit_ = other.limit_;
+}
+
 // Access an object value by name, create a null member if it does not exist.
 // @pre Type of '*this' is object or null.
 // @param key is null-terminated.
 Value &Value::resolveReference(const char *key)
 {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
                       "in Json::Value::resolveReference(): requires objectValue");
-  if (type_ == nullValue)
+  if (type() == nullValue)
     *this = Value(objectValue);
-  CZString actualKey(key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
-  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+  CZString actualKey(key, static_cast<unsigned>(strlen(key)),
+                     CZString::noDuplication); // NOTE!
+  auto it = value_.map_->lower_bound(actualKey);
   if (it != value_.map_->end() && (*it).first == actualKey)
     return (*it).second;
 
@@ -3682,14 +3751,14 @@ Value &Value::resolveReference(const char *key)
 }
 
 // @param key is not null-terminated.
-Value &Value::resolveReference(char const *key, char const *cend)
+Value &Value::resolveReference(char const *key, char const *end)
 {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
                       "in Json::Value::resolveReference(key, end): requires objectValue");
-  if (type_ == nullValue)
+  if (type() == nullValue)
     *this = Value(objectValue);
-  CZString actualKey(key, static_cast<unsigned>(cend - key), CZString::duplicateOnCopy);
-  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+  CZString actualKey(key, static_cast<unsigned>(end - key), CZString::duplicateOnCopy);
+  auto it = value_.map_->lower_bound(actualKey);
   if (it != value_.map_->end() && (*it).first == actualKey)
     return (*it).second;
 
@@ -3707,18 +3776,26 @@ Value Value::get(ArrayIndex index, const Value &defaultValue) const
 
 bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
 
-Value const *Value::find(char const *key, char const *cend) const
+Value const *Value::find(char const *begin, char const *end) const
 {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
-                      "in Json::Value::find(key, end, found): requires objectValue or nullValue");
-  if (type_ == nullValue)
-    return NULL;
-  CZString actualKey(key, static_cast<unsigned>(cend - key), CZString::noDuplication);
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
+                      "in Json::Value::find(begin, end): requires "
+                      "objectValue or nullValue");
+  if (type() == nullValue)
+    return nullptr;
+  CZString actualKey(begin, static_cast<unsigned>(end - begin), CZString::noDuplication);
   ObjectValues::const_iterator it = value_.map_->find(actualKey);
   if (it == value_.map_->end())
-    return NULL;
+    return nullptr;
   return &(*it).second;
 }
+Value *Value::demand(char const *begin, char const *end)
+{
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
+                      "in Json::Value::demand(begin, end): requires "
+                      "objectValue or nullValue");
+  return &resolveReference(begin, end);
+}
 const Value &Value::operator[](const char *key) const
 {
   Value const *found = find(key, key + strlen(key));
@@ -3726,7 +3803,7 @@ const Value &Value::operator[](const char *key) const
     return nullSingleton();
   return *found;
 }
-Value const &Value::operator[](JSONCPP_STRING const &key) const
+Value const &Value::operator[](const String &key) const
 {
   Value const *found = find(key.data(), key.data() + key.length());
   if (!found)
@@ -3736,54 +3813,74 @@ Value const &Value::operator[](JSONCPP_STRING const &key) const
 
 Value &Value::operator[](const char *key) { return resolveReference(key, key + strlen(key)); }
 
-Value &Value::operator[](const JSONCPP_STRING &key)
+Value &Value::operator[](const String &key)
 {
   return resolveReference(key.data(), key.data() + key.length());
 }
 
 Value &Value::operator[](const StaticString &key) { return resolveReference(key.c_str()); }
 
-#ifdef JSON_USE_CPPTL
-Value &Value::operator[](const CppTL::ConstString &key)
+Value &Value::append(const Value &value) { return append(Value(value)); }
+
+Value &Value::append(Value &&value)
 {
-  return resolveReference(key.c_str(), key.end_c_str());
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
+                      "in Json::Value::append: requires arrayValue");
+  if (type() == nullValue)
+  {
+    *this = Value(arrayValue);
+  }
+  return this->value_.map_->emplace(size(), std::move(value)).first->second;
 }
-Value const &Value::operator[](CppTL::ConstString const &key) const
+
+bool Value::insert(ArrayIndex index, const Value &newValue)
 {
-  Value const *found = find(key.c_str(), key.end_c_str());
-  if (!found)
-    return nullSingleton();
-  return *found;
+  return insert(index, Value(newValue));
 }
-#endif
 
-Value &Value::append(const Value &value) { return (*this)[size()] = value; }
+bool Value::insert(ArrayIndex index, Value &&newValue)
+{
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
+                      "in Json::Value::insert: requires arrayValue");
+  ArrayIndex length = size();
+  if (index > length)
+  {
+    return false;
+  }
+  for (ArrayIndex i = length; i > index; i--)
+  {
+    (*this)[i] = std::move((*this)[i - 1]);
+  }
+  (*this)[index] = std::move(newValue);
+  return true;
+}
 
-Value Value::get(char const *key, char const *cend, Value const &defaultValue) const
+Value Value::get(char const *begin, char const *end, Value const &defaultValue) const
 {
-  Value const *found = find(key, cend);
+  Value const *found = find(begin, end);
   return !found ? defaultValue : *found;
 }
 Value Value::get(char const *key, Value const &defaultValue) const
 {
   return get(key, key + strlen(key), defaultValue);
 }
-Value Value::get(JSONCPP_STRING const &key, Value const &defaultValue) const
+Value Value::get(String const &key, Value const &defaultValue) const
 {
   return get(key.data(), key.data() + key.length(), defaultValue);
 }
 
-bool Value::removeMember(const char *key, const char *cend, Value *removed)
+bool Value::removeMember(const char *begin, const char *end, Value *removed)
 {
-  if (type_ != objectValue)
+  if (type() != objectValue)
   {
     return false;
   }
-  CZString actualKey(key, static_cast<unsigned>(cend - key), CZString::noDuplication);
-  ObjectValues::iterator it = value_.map_->find(actualKey);
+  CZString actualKey(begin, static_cast<unsigned>(end - begin), CZString::noDuplication);
+  auto it = value_.map_->find(actualKey);
   if (it == value_.map_->end())
     return false;
-  *removed = it->second;
+  if (removed)
+    *removed = std::move(it->second);
   value_.map_->erase(it);
   return true;
 }
@@ -3791,36 +3888,36 @@ bool Value::removeMember(const char *key, Value *removed)
 {
   return removeMember(key, key + strlen(key), removed);
 }
-bool Value::removeMember(JSONCPP_STRING const &key, Value *removed)
+bool Value::removeMember(String const &key, Value *removed)
 {
   return removeMember(key.data(), key.data() + key.length(), removed);
 }
-Value Value::removeMember(const char *key)
+void Value::removeMember(const char *key)
 {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
                       "in Json::Value::removeMember(): requires objectValue");
-  if (type_ == nullValue)
-    return nullSingleton();
+  if (type() == nullValue)
+    return;
 
-  Value removed; // null
-  removeMember(key, key + strlen(key), &removed);
-  return removed; // still null if removeMember() did nothing
+  CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
+  value_.map_->erase(actualKey);
 }
-Value Value::removeMember(const JSONCPP_STRING &key) { return removeMember(key.c_str()); }
+void Value::removeMember(const String &key) { removeMember(key.c_str()); }
 
 bool Value::removeIndex(ArrayIndex index, Value *removed)
 {
-  if (type_ != arrayValue)
+  if (type() != arrayValue)
   {
     return false;
   }
   CZString key(index);
-  ObjectValues::iterator it = value_.map_->find(key);
+  auto it = value_.map_->find(key);
   if (it == value_.map_->end())
   {
     return false;
   }
-  *removed = it->second;
+  if (removed)
+    *removed = it->second;
   ArrayIndex oldSize = size();
   // shift left all items left, into the place of the "removed"
   for (ArrayIndex i = index; i < (oldSize - 1); ++i)
@@ -3830,41 +3927,27 @@ bool Value::removeIndex(ArrayIndex index, Value *removed)
   }
   // erase the last one ("leftover")
   CZString keyLast(oldSize - 1);
-  ObjectValues::iterator itLast = value_.map_->find(keyLast);
+  auto itLast = value_.map_->find(keyLast);
   value_.map_->erase(itLast);
   return true;
 }
 
-#ifdef JSON_USE_CPPTL
-Value Value::get(const CppTL::ConstString &key, const Value &defaultValue) const
+bool Value::isMember(char const *begin, char const *end) const
 {
-  return get(key.c_str(), key.end_c_str(), defaultValue);
-}
-#endif
-
-bool Value::isMember(char const *key, char const *cend) const
-{
-  Value const *value = find(key, cend);
-  return NULL != value;
+  Value const *value = find(begin, end);
+  return nullptr != value;
 }
 bool Value::isMember(char const *key) const { return isMember(key, key + strlen(key)); }
-bool Value::isMember(JSONCPP_STRING const &key) const
+bool Value::isMember(String const &key) const
 {
   return isMember(key.data(), key.data() + key.length());
 }
 
-#ifdef JSON_USE_CPPTL
-bool Value::isMember(const CppTL::ConstString &key) const
-{
-  return isMember(key.c_str(), key.end_c_str());
-}
-#endif
-
 Value::Members Value::getMemberNames() const
 {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
+  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
                       "in Json::Value::getMemberNames(), value must be objectValue");
-  if (type_ == nullValue)
+  if (type() == nullValue)
     return Value::Members();
   Members members;
   members.reserve(value_.map_->size());
@@ -3872,35 +3955,10 @@ Value::Members Value::getMemberNames() const
   ObjectValues::const_iterator itEnd = value_.map_->end();
   for (; it != itEnd; ++it)
   {
-    members.push_back(JSONCPP_STRING((*it).first.data(), (*it).first.length()));
+    members.push_back(String((*it).first.data(), (*it).first.length()));
   }
   return members;
 }
-//
-//# ifdef JSON_USE_CPPTL
-// EnumMemberNames
-// Value::enumMemberNames() const
-//{
-//   if ( type_ == objectValue )
-//   {
-//      return CppTL::Enum::any(  CppTL::Enum::transform(
-//         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
-//         MemberNamesTransform() ) );
-//   }
-//   return EnumMemberNames();
-//}
-//
-//
-// EnumValues
-// Value::enumValues() const
-//{
-//   if ( type_ == objectValue  ||  type_ == arrayValue )
-//      return CppTL::Enum::anyValues( *(value_.map_),
-//                                     CppTL::Type<const Value &>() );
-//   return EnumValues();
-//}
-//
-//# endif
 
 static bool IsIntegral(double d)
 {
@@ -3908,16 +3966,20 @@ static bool IsIntegral(double d)
   return modf(d, &integral_part) == 0.0;
 }
 
-bool Value::isNull() const { return type_ == nullValue; }
+bool Value::isNull() const { return type() == nullValue; }
 
-bool Value::isBool() const { return type_ == booleanValue; }
+bool Value::isBool() const { return type() == booleanValue; }
 
 bool Value::isInt() const
 {
-  switch (type_)
+  switch (type())
   {
     case intValue:
+#if defined(JSON_HAS_INT64)
       return value_.int_ >= minInt && value_.int_ <= maxInt;
+#else
+      return true;
+#endif
     case uintValue:
       return value_.uint_ <= UInt(maxInt);
     case realValue:
@@ -3930,12 +3992,20 @@ bool Value::isInt() const
 
 bool Value::isUInt() const
 {
-  switch (type_)
+  switch (type())
   {
     case intValue:
+#if defined(JSON_HAS_INT64)
       return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
+#else
+      return value_.int_ >= 0;
+#endif
     case uintValue:
+#if defined(JSON_HAS_INT64)
       return value_.uint_ <= maxUInt;
+#else
+      return true;
+#endif
     case realValue:
       return value_.real_ >= 0 && value_.real_ <= maxUInt && IsIntegral(value_.real_);
     default:
@@ -3947,7 +4017,7 @@ bool Value::isUInt() const
 bool Value::isInt64() const
 {
 #if defined(JSON_HAS_INT64)
-  switch (type_)
+  switch (type())
   {
     case intValue:
       return true;
@@ -3969,7 +4039,7 @@ bool Value::isInt64() const
 bool Value::isUInt64() const
 {
 #if defined(JSON_HAS_INT64)
-  switch (type_)
+  switch (type())
   {
     case intValue:
       return value_.int_ >= 0;
@@ -3989,57 +4059,91 @@ bool Value::isUInt64() const
 
 bool Value::isIntegral() const
 {
+  switch (type())
+  {
+    case intValue:
+    case uintValue:
+      return true;
+    case realValue:
 #if defined(JSON_HAS_INT64)
-  return isInt64() || isUInt64();
+      // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+      // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+      // require the value to be strictly less than the limit.
+      return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble &&
+             IsIntegral(value_.real_);
 #else
-  return isInt() || isUInt();
-#endif
+      return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
+#endif // JSON_HAS_INT64
+    default:
+      break;
+  }
+  return false;
+}
+
+bool Value::isDouble() const
+{
+  return type() == intValue || type() == uintValue || type() == realValue;
 }
 
-bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
+bool Value::isNumeric() const { return isDouble(); }
+
+bool Value::isString() const { return type() == stringValue; }
 
-bool Value::isNumeric() const { return isIntegral() || isDouble(); }
+bool Value::isArray() const { return type() == arrayValue; }
 
-bool Value::isString() const { return type_ == stringValue; }
+bool Value::isObject() const { return type() == objectValue; }
 
-bool Value::isArray() const { return type_ == arrayValue; }
+Value::Comments::Comments(const Comments &that) : ptr_{cloneUnique(that.ptr_)} {}
 
-bool Value::isObject() const { return type_ == objectValue; }
+Value::Comments::Comments(Comments &&that) noexcept : ptr_{std::move(that.ptr_)} {}
 
-void Value::setComment(const char *comment, size_t len, CommentPlacement placement)
+Value::Comments &Value::Comments::operator=(const Comments &that)
 {
-  if (!comments_)
-    comments_ = new CommentInfo[numberOfCommentPlacement];
-  if ((len > 0) && (comment[len - 1] == '\n'))
-  {
-    // Always discard trailing newline, to aid indentation.
-    len -= 1;
-  }
-  comments_[placement].setComment(comment, len);
+  ptr_ = cloneUnique(that.ptr_);
+  return *this;
 }
 
-void Value::setComment(const char *comment, CommentPlacement placement)
+Value::Comments &Value::Comments::operator=(Comments &&that) noexcept
 {
-  setComment(comment, strlen(comment), placement);
+  ptr_ = std::move(that.ptr_);
+  return *this;
 }
 
-void Value::setComment(const JSONCPP_STRING &comment, CommentPlacement placement)
+bool Value::Comments::has(CommentPlacement slot) const { return ptr_ && !(*ptr_)[slot].empty(); }
+
+String Value::Comments::get(CommentPlacement slot) const
 {
-  setComment(comment.c_str(), comment.length(), placement);
+  if (!ptr_)
+    return {};
+  return (*ptr_)[slot];
 }
 
-bool Value::hasComment(CommentPlacement placement) const
+void Value::Comments::set(CommentPlacement slot, String comment)
 {
-  return comments_ != 0 && comments_[placement].comment_ != 0;
+  if (slot >= CommentPlacement::numberOfCommentPlacement)
+    return;
+  if (!ptr_)
+    ptr_ = std::unique_ptr<Array>(new Array());
+  (*ptr_)[slot] = std::move(comment);
 }
 
-JSONCPP_STRING Value::getComment(CommentPlacement placement) const
+void Value::setComment(String comment, CommentPlacement placement)
 {
-  if (hasComment(placement))
-    return comments_[placement].comment_;
-  return "";
+  if (!comment.empty() && (comment.back() == '\n'))
+  {
+    // Always discard trailing newline, to aid indentation.
+    comment.pop_back();
+  }
+  JSON_ASSERT(!comment.empty());
+  JSON_ASSERT_MESSAGE(comment[0] == '\0' || comment[0] == '/',
+                      "in Json::Value::setComment(): Comments must start with /");
+  comments_.set(placement, std::move(comment));
 }
 
+bool Value::hasComment(CommentPlacement placement) const { return comments_.has(placement); }
+
+String Value::getComment(CommentPlacement placement) const { return comments_.get(placement); }
+
 void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
 
 void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
@@ -4048,15 +4152,20 @@ ptrdiff_t Value::getOffsetStart() const { return start_; }
 
 ptrdiff_t Value::getOffsetLimit() const { return limit_; }
 
-JSONCPP_STRING Value::toStyledString() const
+String Value::toStyledString() const
 {
-  StyledWriter writer;
-  return writer.write(*this);
+  StreamWriterBuilder builder;
+
+  String out = this->hasComment(commentBefore) ? "\n" : "";
+  out += Json::writeString(builder, *this);
+  out += '\n';
+
+  return out;
 }
 
 Value::const_iterator Value::begin() const
 {
-  switch (type_)
+  switch (type())
   {
     case arrayValue:
     case objectValue:
@@ -4066,12 +4175,12 @@ Value::const_iterator Value::begin() const
     default:
       break;
   }
-  return const_iterator();
+  return {};
 }
 
 Value::const_iterator Value::end() const
 {
-  switch (type_)
+  switch (type())
   {
     case arrayValue:
     case objectValue:
@@ -4081,12 +4190,12 @@ Value::const_iterator Value::end() const
     default:
       break;
   }
-  return const_iterator();
+  return {};
 }
 
 Value::iterator Value::begin()
 {
-  switch (type_)
+  switch (type())
   {
     case arrayValue:
     case objectValue:
@@ -4101,7 +4210,7 @@ Value::iterator Value::begin()
 
 Value::iterator Value::end()
 {
-  switch (type_)
+  switch (type())
   {
     case arrayValue:
     case objectValue:
@@ -4117,23 +4226,22 @@ Value::iterator Value::end()
 // class PathArgument
 // //////////////////////////////////////////////////////////////////
 
-PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
+PathArgument::PathArgument() = default;
 
-PathArgument::PathArgument(ArrayIndex index) : key_(), index_(index), kind_(kindIndex) {}
+PathArgument::PathArgument(ArrayIndex index) : index_(index), kind_(kindIndex) {}
 
-PathArgument::PathArgument(const char *key) : key_(key), index_(), kind_(kindKey) {}
+PathArgument::PathArgument(const char *key) : key_(key), kind_(kindKey) {}
 
-PathArgument::PathArgument(const JSONCPP_STRING &key) : key_(key.c_str()), index_(), kind_(kindKey)
-{
-}
+PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
 
 // class Path
 // //////////////////////////////////////////////////////////////////
 
-Path::Path(const JSONCPP_STRING &path, const PathArgument &a1, const PathArgument &a2,
+Path::Path(const String &path, const PathArgument &a1, const PathArgument &a2,
            const PathArgument &a3, const PathArgument &a4, const PathArgument &a5)
 {
   InArgs in;
+  in.reserve(5);
   in.push_back(&a1);
   in.push_back(&a2);
   in.push_back(&a3);
@@ -4142,11 +4250,11 @@ Path::Path(const JSONCPP_STRING &path, const PathArgument &a1, const PathArgumen
   makePath(path, in);
 }
 
-void Path::makePath(const JSONCPP_STRING &path, const InArgs &in)
+void Path::makePath(const String &path, const InArgs &in)
 {
   const char *current = path.c_str();
   const char *end = current + path.length();
-  InArgs::const_iterator itInArg = in.begin();
+  auto itInArg = in.begin();
   while (current != end)
   {
     if (*current == '[')
@@ -4178,13 +4286,13 @@ void Path::makePath(const JSONCPP_STRING &path, const InArgs &in)
       const char *beginName = current;
       while (current != end && !strchr("[.", *current))
         ++current;
-      args_.push_back(JSONCPP_STRING(beginName, current));
+      args_.push_back(String(beginName, current));
     }
   }
 }
 
-void Path::addPathInArg(const JSONCPP_STRING & /*path*/, const InArgs &in,
-                        InArgs::const_iterator &itInArg, PathArgument::Kind kind)
+void Path::addPathInArg(const String & /*path*/, const InArgs &in, InArgs::const_iterator &itInArg,
+                        PathArgument::Kind kind)
 {
   if (itInArg == in.end())
   {
@@ -4200,7 +4308,7 @@ void Path::addPathInArg(const JSONCPP_STRING & /*path*/, const InArgs &in,
   }
 }
 
-void Path::invalidPath(const JSONCPP_STRING & /*path*/, int /*location*/)
+void Path::invalidPath(const String & /*path*/, int /*location*/)
 {
   // Error: invalid path.
 }
@@ -4208,15 +4316,14 @@ void Path::invalidPath(const JSONCPP_STRING & /*path*/, int /*location*/)
 const Value &Path::resolve(const Value &root) const
 {
   const Value *node = &root;
-  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it)
+  for (const auto &arg : args_)
   {
-    const PathArgument &arg = *it;
     if (arg.kind_ == PathArgument::kindIndex)
     {
       if (!node->isArray() || !node->isValidIndex(arg.index_))
       {
-        // Error: unable to resolve path (array value expected at position...
-        return Value::null;
+        // Error: unable to resolve path (array value expected at position... )
+        return Value::nullSingleton();
       }
       node = &((*node)[arg.index_]);
     }
@@ -4225,14 +4332,14 @@ const Value &Path::resolve(const Value &root) const
       if (!node->isObject())
       {
         // Error: unable to resolve path (object value expected at position...)
-        return Value::null;
+        return Value::nullSingleton();
       }
       node = &((*node)[arg.key_]);
       if (node == &Value::nullSingleton())
       {
         // Error: unable to resolve path (object has no member named '' at
         // position...)
-        return Value::null;
+        return Value::nullSingleton();
       }
     }
   }
@@ -4242,9 +4349,8 @@ const Value &Path::resolve(const Value &root) const
 Value Path::resolve(const Value &root, const Value &defaultValue) const
 {
   const Value *node = &root;
-  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it)
+  for (const auto &arg : args_)
   {
-    const PathArgument &arg = *it;
     if (arg.kind_ == PathArgument::kindIndex)
     {
       if (!node->isArray() || !node->isValidIndex(arg.index_))
@@ -4266,9 +4372,8 @@ Value Path::resolve(const Value &root, const Value &defaultValue) const
 Value &Path::make(Value &root) const
 {
   Value *node = &root;
-  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it)
+  for (const auto &arg : args_)
   {
-    const PathArgument &arg = *it;
     if (arg.kind_ == PathArgument::kindIndex)
     {
       if (!node->isArray())
@@ -4299,76 +4404,86 @@ Value &Path::make(Value &root) const
 // Beginning of content of file: src/lib_json/json_writer.cpp
 // //////////////////////////////////////////////////////////////////////
 
-// Copyright 2011 Baptiste Lepilleur
+// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
 // Distributed under MIT license, or public domain if desired and
 // recognized in your jurisdiction.
 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
 
 #if !defined(JSON_IS_AMALGAMATION)
-#include <json/writer.h>
 #include "json_tool.h"
+#include <json/writer.h>
 #endif // if !defined(JSON_IS_AMALGAMATION)
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <cstring>
 #include <iomanip>
 #include <memory>
+#include <set>
 #include <sstream>
 #include <utility>
-#include <set>
-#include <cassert>
-#include <cstring>
+
+#if __cplusplus >= 201103L
+#include <cmath>
+#include <cstdio>
+
+#if !defined(isnan)
+#define isnan std::isnan
+#endif
+
+#if !defined(isfinite)
+#define isfinite std::isfinite
+#endif
+
+#else
+#include <cmath>
 #include <cstdio>
 
-#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
+#if defined(_MSC_VER)
+#if !defined(isnan)
+#include <float.h>
+#define isnan _isnan
+#endif
+
+#if !defined(isfinite)
 #include <float.h>
 #define isfinite _finite
-#elif defined(__sun) && defined(__SVR4) // Solaris
+#endif
+
+#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
+#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
+#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
+
+#endif //_MSC_VER
+
+#if defined(__sun) && defined(__SVR4) // Solaris
 #if !defined(isfinite)
 #include <ieeefp.h>
 #define isfinite finite
 #endif
-#elif defined(_AIX)
-#if !defined(isfinite)
-#include <math.h>
-#define isfinite finite
 #endif
-#elif defined(__hpux)
+
+#if defined(__hpux)
 #if !defined(isfinite)
 #if defined(__ia64) && !defined(finite)
 #define isfinite(x) ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
-#else
-#include <math.h>
-#define isfinite finite
 #endif
 #endif
-#else
-#include <cmath>
-#if !(defined(__QNXNTO__)) // QNX already defines isfinite
-#define isfinite std::isfinite
-#endif
 #endif
 
-#if defined(_MSC_VER)
-#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
-#define snprintf sprintf_s
-#elif _MSC_VER >= 1900 // VC++ 14.0 and above
-#define snprintf std::snprintf
-#else
-#define snprintf _snprintf
+#if !defined(isnan)
+// IEEE standard states that NaN values will not compare to themselves
+#define isnan(x) ((x) != (x))
 #endif
-#elif defined(__ANDROID__) || defined(__QNXNTO__)
-#define snprintf snprintf
-#elif __cplusplus >= 201103L
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-#define snprintf std::snprintf
+
+#if !defined(__APPLE__)
+#if !defined(isfinite)
+#define isfinite finite
 #endif
 #endif
-
-#if defined(__BORLANDC__)
-#include <float.h>
-#define isfinite _finite
-#define snprintf _snprintf
 #endif
 
-#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+#if defined(_MSC_VER)
 // Disable warning about strdup being deprecated.
 #pragma warning(disable : 4996)
 #endif
@@ -4377,34 +4492,12 @@ namespace Json
 {
 
 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
-typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
+using StreamWriterPtr = std::unique_ptr<StreamWriter>;
 #else
-typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
+using StreamWriterPtr = std::auto_ptr<StreamWriter>;
 #endif
 
-static bool containsControlCharacter(const char *str)
-{
-  while (*str)
-  {
-    if (isControlCharacter(*(str++)))
-      return true;
-  }
-  return false;
-}
-
-static bool containsControlCharacter0(const char *str, unsigned len)
-{
-  char const *end = str + len;
-  while (end != str)
-  {
-    if (isControlCharacter(*str) || 0 == *str)
-      return true;
-    ++str;
-  }
-  return false;
-}
-
-JSONCPP_STRING valueToString(LargestInt value)
+String valueToString(LargestInt value)
 {
   UIntToStringBuffer buffer;
   char *current = buffer + sizeof(buffer);
@@ -4426,7 +4519,7 @@ JSONCPP_STRING valueToString(LargestInt value)
   return current;
 }
 
-JSONCPP_STRING valueToString(LargestUInt value)
+String valueToString(LargestUInt value)
 {
   UIntToStringBuffer buffer;
   char *current = buffer + sizeof(buffer);
@@ -4437,156 +4530,176 @@ JSONCPP_STRING valueToString(LargestUInt value)
 
 #if defined(JSON_HAS_INT64)
 
-JSONCPP_STRING valueToString(Int value) { return valueToString(LargestInt(value)); }
+String valueToString(Int value) { return valueToString(LargestInt(value)); }
 
-JSONCPP_STRING valueToString(UInt value) { return valueToString(LargestUInt(value)); }
+String valueToString(UInt value) { return valueToString(LargestUInt(value)); }
 
 #endif // # if defined(JSON_HAS_INT64)
 
 namespace
 {
-JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision)
+String valueToString(double value, bool useSpecialFloats, unsigned int precision,
+                     PrecisionType precisionType)
 {
-  // Allocate a buffer that is more than large enough to store the 16 digits of
-  // precision requested below.
-  char buffer[32];
-  int len = -1;
-
-  char formatString[6];
-  sprintf(formatString, "%%.%dg", precision);
-
   // Print into the buffer. We need not request the alternative representation
-  // that always has a decimal point because JSON doesn't distingish the
+  // that always has a decimal point because JSON doesn't distinguish the
   // concepts of reals and integers.
-  if (isfinite(value))
+  if (!isfinite(value))
   {
-    len = snprintf(buffer, sizeof(buffer), formatString, value);
+    static const char *const reps[2][3] = {{"NaN", "-Infinity", "Infinity"},
+                                           {"null", "-1e+9999", "1e+9999"}};
+    return reps[useSpecialFloats ? 0 : 1][isnan(value) ? 0 : (value < 0) ? 1 : 2];
   }
-  else
+
+  String buffer(size_t(36), '\0');
+  while (true)
   {
-    // IEEE standard states that NaN values will not compare to themselves
-    if (value != value)
+    int len = jsoncpp_snprintf(
+      &*buffer.begin(), buffer.size(),
+      (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f", precision, value);
+    assert(len >= 0);
+    auto wouldPrint = static_cast<size_t>(len);
+    if (wouldPrint >= buffer.size())
     {
-      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
+      buffer.resize(wouldPrint + 1);
+      continue;
     }
-    else if (value < 0)
-    {
-      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
-    }
-    else
-    {
-      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
-    }
-    // For those, we do not need to call fixNumLoc, but it is fast.
+    buffer.resize(wouldPrint);
+    break;
+  }
+
+  buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
+
+  // try to ensure we preserve the fact that this was given to us as a double on
+  // input
+  if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos)
+  {
+    buffer += ".0";
+  }
+
+  // strip the zero padding from the right
+  if (precisionType == PrecisionType::decimalPlaces)
+  {
+    buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end(), precision), buffer.end());
   }
-  assert(len >= 0);
-  fixNumericLocale(buffer, buffer + len);
+
   return buffer;
 }
+} // namespace
+
+String valueToString(double value, unsigned int precision, PrecisionType precisionType)
+{
+  return valueToString(value, false, precision, precisionType);
 }
 
-JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
+String valueToString(bool value) { return value ? "true" : "false"; }
 
-JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
+static bool doesAnyCharRequireEscaping(char const *s, size_t n)
+{
+  assert(s || !n);
+
+  return std::any_of(s, s + n,
+                     [](unsigned char c) { return c == '\\' || c == '"' || c < 0x20 || c > 0x7F; });
+}
 
-JSONCPP_STRING valueToQuotedString(const char *value)
+static unsigned int utf8ToCodepoint(const char *&s, const char *e)
 {
-  if (value == NULL)
-    return "";
-  // Not sure how to handle unicode...
-  if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter(value))
-    return JSONCPP_STRING("\"") + value + "\"";
-  // We have to walk value and escape any special characters.
-  // Appending to JSONCPP_STRING is not efficient, but this should be rare.
-  // (Note: forward slashes are *not* rare, but I am not escaping them.)
-  JSONCPP_STRING::size_type maxsize = strlen(value) * 2 + 3; // allescaped+quotes+NULL
-  JSONCPP_STRING result;
-  result.reserve(maxsize); // to avoid lots of mallocs
-  result += "\"";
-  for (const char *c = value; *c != 0; ++c)
+  const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
+
+  unsigned int firstByte = static_cast<unsigned char>(*s);
+
+  if (firstByte < 0x80)
+    return firstByte;
+
+  if (firstByte < 0xE0)
   {
-    switch (*c)
-    {
-      case '\"':
-        result += "\\\"";
-        break;
-      case '\\':
-        result += "\\\\";
-        break;
-      case '\b':
-        result += "\\b";
-        break;
-      case '\f':
-        result += "\\f";
-        break;
-      case '\n':
-        result += "\\n";
-        break;
-      case '\r':
-        result += "\\r";
-        break;
-      case '\t':
-        result += "\\t";
-        break;
-      // case '/':
-      // Even though \/ is considered a legal escape in JSON, a bare
-      // slash is also legal, so I see no reason to escape it.
-      // (I hope I am not misunderstanding something.
-      // blep notes: actually escaping \/ may be useful in javascript to avoid </
-      // sequence.
-      // Should add a flag to allow this compatibility mode and prevent this
-      // sequence from occurring.
-      default:
-        if (isControlCharacter(*c))
-        {
-          JSONCPP_OSTRINGSTREAM oss;
-          oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4)
-              << static_cast<int>(*c);
-          result += oss.str();
-        }
-        else
-        {
-          result += *c;
-        }
-        break;
-    }
+    if (e - s < 2)
+      return REPLACEMENT_CHARACTER;
+
+    unsigned int calculated = ((firstByte & 0x1F) << 6) | (static_cast<unsigned int>(s[1]) & 0x3F);
+    s += 1;
+    // oversized encoded characters are invalid
+    return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
   }
-  result += "\"";
-  return result;
-}
 
-// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
-static char const *strnpbrk(char const *s, char const *accept, size_t n)
-{
-  assert((s || !n) && accept);
+  if (firstByte < 0xF0)
+  {
+    if (e - s < 3)
+      return REPLACEMENT_CHARACTER;
+
+    unsigned int calculated = ((firstByte & 0x0F) << 12) |
+                              ((static_cast<unsigned int>(s[1]) & 0x3F) << 6) |
+                              (static_cast<unsigned int>(s[2]) & 0x3F);
+    s += 2;
+    // surrogates aren't valid codepoints itself
+    // shouldn't be UTF-8 encoded
+    if (calculated >= 0xD800 && calculated <= 0xDFFF)
+      return REPLACEMENT_CHARACTER;
+    // oversized encoded characters are invalid
+    return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
+  }
 
-  char const *const end = s + n;
-  for (char const *cur = s; cur < end; ++cur)
+  if (firstByte < 0xF8)
   {
-    int const c = *cur;
-    for (char const *a = accept; *a; ++a)
-    {
-      if (*a == c)
-      {
-        return cur;
-      }
-    }
+    if (e - s < 4)
+      return REPLACEMENT_CHARACTER;
+
+    unsigned int calculated =
+      ((firstByte & 0x07) << 18) | ((static_cast<unsigned int>(s[1]) & 0x3F) << 12) |
+      ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) | (static_cast<unsigned int>(s[3]) & 0x3F);
+    s += 3;
+    // oversized encoded characters are invalid
+    return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
   }
-  return NULL;
+
+  return REPLACEMENT_CHARACTER;
+}
+
+static const char hex2[] = "000102030405060708090a0b0c0d0e0f"
+                           "101112131415161718191a1b1c1d1e1f"
+                           "202122232425262728292a2b2c2d2e2f"
+                           "303132333435363738393a3b3c3d3e3f"
+                           "404142434445464748494a4b4c4d4e4f"
+                           "505152535455565758595a5b5c5d5e5f"
+                           "606162636465666768696a6b6c6d6e6f"
+                           "707172737475767778797a7b7c7d7e7f"
+                           "808182838485868788898a8b8c8d8e8f"
+                           "909192939495969798999a9b9c9d9e9f"
+                           "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+                           "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+                           "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+                           "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+                           "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+                           "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
+
+static String toHex16Bit(unsigned int x)
+{
+  const unsigned int hi = (x >> 8) & 0xff;
+  const unsigned int lo = x & 0xff;
+  String result(4, ' ');
+  result[0] = hex2[2 * hi];
+  result[1] = hex2[2 * hi + 1];
+  result[2] = hex2[2 * lo];
+  result[3] = hex2[2 * lo + 1];
+  return result;
 }
-static JSONCPP_STRING valueToQuotedStringN(const char *value, unsigned length)
+
+static void appendRaw(String &result, unsigned ch) { result += static_cast<char>(ch); }
+
+static void appendHex(String &result, unsigned ch) { result.append("\\u").append(toHex16Bit(ch)); }
+
+static String valueToQuotedStringN(const char *value, size_t length, bool emitUTF8 = false)
 {
-  if (value == NULL)
+  if (value == nullptr)
     return "";
-  // Not sure how to handle unicode...
-  if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
-      !containsControlCharacter0(value, length))
-    return JSONCPP_STRING("\"") + value + "\"";
+
+  if (!doesAnyCharRequireEscaping(value, length))
+    return String("\"") + value + "\"";
   // We have to walk value and escape any special characters.
-  // Appending to JSONCPP_STRING is not efficient, but this should be rare.
+  // Appending to String is not efficient, but this should be rare.
   // (Note: forward slashes are *not* rare, but I am not escaping them.)
-  JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL
-  JSONCPP_STRING result;
+  String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL
+  String result;
   result.reserve(maxsize); // to avoid lots of mallocs
   result += "\"";
   char const *end = value + length;
@@ -4624,48 +4737,76 @@ static JSONCPP_STRING valueToQuotedStringN(const char *value, unsigned length)
       // Should add a flag to allow this compatibility mode and prevent this
       // sequence from occurring.
       default:
-        if ((isControlCharacter(*c)) || (*c == 0))
+      {
+        if (emitUTF8)
         {
-          JSONCPP_OSTRINGSTREAM oss;
-          oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4)
-              << static_cast<int>(*c);
-          result += oss.str();
+          unsigned codepoint = static_cast<unsigned char>(*c);
+          if (codepoint < 0x20)
+          {
+            appendHex(result, codepoint);
+          }
+          else
+          {
+            appendRaw(result, codepoint);
+          }
         }
         else
         {
-          result += *c;
+          unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c`
+          if (codepoint < 0x20)
+          {
+            appendHex(result, codepoint);
+          }
+          else if (codepoint < 0x80)
+          {
+            appendRaw(result, codepoint);
+          }
+          else if (codepoint < 0x10000)
+          {
+            // Basic Multilingual Plane
+            appendHex(result, codepoint);
+          }
+          else
+          {
+            // Extended Unicode. Encode 20 bits as a surrogate pair.
+            codepoint -= 0x10000;
+            appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
+            appendHex(result, 0xdc00 + (codepoint & 0x3ff));
+          }
         }
-        break;
+      }
+      break;
     }
   }
   result += "\"";
   return result;
 }
 
+String valueToQuotedString(const char *value) { return valueToQuotedStringN(value, strlen(value)); }
+
 // Class Writer
 // //////////////////////////////////////////////////////////////////
-Writer::~Writer() {}
+Writer::~Writer() = default;
 
 // Class FastWriter
 // //////////////////////////////////////////////////////////////////
 
 FastWriter::FastWriter()
-    : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), omitEndingLineFeed_(false)
-{
-}
 
-void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
+  = default;
+
+void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
 
 void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
 
 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
 
-JSONCPP_STRING FastWriter::write(const Value &root)
+String FastWriter::write(const Value &root)
 {
-  document_ = "";
+  document_.clear();
   writeValue(root);
   if (!omitEndingLineFeed_)
-    document_ += "\n";
+    document_ += '\n';
   return document_;
 }
 
@@ -4693,7 +4834,7 @@ void FastWriter::writeValue(const Value &value)
       char const *end;
       bool ok = value.getString(&str, &end);
       if (ok)
-        document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str));
+        document_ += valueToQuotedStringN(str, static_cast<size_t>(end - str));
       break;
     }
     case booleanValue:
@@ -4716,13 +4857,13 @@ void FastWriter::writeValue(const Value &value)
     {
       Value::Members members(value.getMemberNames());
       document_ += '{';
-      for (Value::Members::iterator it = members.begin(); it != members.end(); ++it)
+      for (auto it = members.begin(); it != members.end(); ++it)
       {
-        const JSONCPP_STRING &name = *it;
+        const String &name = *it;
         if (it != members.begin())
           document_ += ',';
-        document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
-        document_ += yamlCompatiblityEnabled_ ? ": " : ":";
+        document_ += valueToQuotedStringN(name.data(), name.length());
+        document_ += yamlCompatibilityEnabled_ ? ": " : ":";
         writeValue(value[name]);
       }
       document_ += '}';
@@ -4734,17 +4875,17 @@ void FastWriter::writeValue(const Value &value)
 // Class StyledWriter
 // //////////////////////////////////////////////////////////////////
 
-StyledWriter::StyledWriter() : rightMargin_(74), indentSize_(3), addChildValues_() {}
+StyledWriter::StyledWriter() = default;
 
-JSONCPP_STRING StyledWriter::write(const Value &root)
+String StyledWriter::write(const Value &root)
 {
-  document_ = "";
+  document_.clear();
   addChildValues_ = false;
-  indentString_ = "";
+  indentString_.clear();
   writeCommentBeforeValue(root);
   writeValue(root);
   writeCommentAfterValueOnSameLine(root);
-  document_ += "\n";
+  document_ += '\n';
   return document_;
 }
 
@@ -4771,7 +4912,7 @@ void StyledWriter::writeValue(const Value &value)
       char const *end;
       bool ok = value.getString(&str, &end);
       if (ok)
-        pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
+        pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
       else
         pushValue("");
       break;
@@ -4791,10 +4932,10 @@ void StyledWriter::writeValue(const Value &value)
       {
         writeWithIndent("{");
         indent();
-        Value::Members::iterator it = members.begin();
+        auto it = members.begin();
         for (;;)
         {
-          const JSONCPP_STRING &name = *it;
+          const String &name = *it;
           const Value &childValue = value[name];
           writeCommentBeforeValue(childValue);
           writeWithIndent(valueToQuotedString(name.c_str()));
@@ -4818,18 +4959,18 @@ void StyledWriter::writeValue(const Value &value)
 
 void StyledWriter::writeArrayValue(const Value &value)
 {
-  unsigned size = value.size();
+  size_t size = value.size();
   if (size == 0)
     pushValue("[]");
   else
   {
-    bool isArrayMultiLine = isMultineArray(value);
+    bool isArrayMultiLine = isMultilineArray(value);
     if (isArrayMultiLine)
     {
       writeWithIndent("[");
       indent();
       bool hasChildValue = !childValues_.empty();
-      unsigned index = 0;
+      ArrayIndex index = 0;
       for (;;)
       {
         const Value &childValue = value[index];
@@ -4856,7 +4997,7 @@ void StyledWriter::writeArrayValue(const Value &value)
     {
       assert(childValues_.size() == size);
       document_ += "[ ";
-      for (unsigned index = 0; index < size; ++index)
+      for (size_t index = 0; index < size; ++index)
       {
         if (index > 0)
           document_ += ", ";
@@ -4867,7 +5008,7 @@ void StyledWriter::writeArrayValue(const Value &value)
   }
 }
 
-bool StyledWriter::isMultineArray(const Value &value)
+bool StyledWriter::isMultilineArray(const Value &value)
 {
   ArrayIndex const size = value.size();
   bool isMultiLine = size * 3 >= rightMargin_;
@@ -4875,7 +5016,7 @@ bool StyledWriter::isMultineArray(const Value &value)
   for (ArrayIndex index = 0; index < size && !isMultiLine; ++index)
   {
     const Value &childValue = value[index];
-    isMultiLine = ((childValue.isArray() || childValue.isObject()) && childValue.size() > 0);
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) && !childValue.empty());
   }
   if (!isMultiLine) // check if line length > max line length
   {
@@ -4897,7 +5038,7 @@ bool StyledWriter::isMultineArray(const Value &value)
   return isMultiLine;
 }
 
-void StyledWriter::pushValue(const JSONCPP_STRING &value)
+void StyledWriter::pushValue(const String &value)
 {
   if (addChildValues_)
     childValues_.push_back(value);
@@ -4918,13 +5059,13 @@ void StyledWriter::writeIndent()
   document_ += indentString_;
 }
 
-void StyledWriter::writeWithIndent(const JSONCPP_STRING &value)
+void StyledWriter::writeWithIndent(const String &value)
 {
   writeIndent();
   document_ += value;
 }
 
-void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
+void StyledWriter::indent() { indentString_ += String(indentSize_, ' '); }
 
 void StyledWriter::unindent()
 {
@@ -4937,20 +5078,20 @@ void StyledWriter::writeCommentBeforeValue(const Value &root)
   if (!root.hasComment(commentBefore))
     return;
 
-  document_ += "\n";
+  document_ += '\n';
   writeIndent();
-  const JSONCPP_STRING &comment = root.getComment(commentBefore);
-  JSONCPP_STRING::const_iterator iter = comment.begin();
+  const String &comment = root.getComment(commentBefore);
+  String::const_iterator iter = comment.begin();
   while (iter != comment.end())
   {
     document_ += *iter;
-    if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
+    if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
       writeIndent();
     ++iter;
   }
 
   // Comments are stripped of trailing newlines, so add one here
-  document_ += "\n";
+  document_ += '\n';
 }
 
 void StyledWriter::writeCommentAfterValueOnSameLine(const Value &root)
@@ -4960,9 +5101,9 @@ void StyledWriter::writeCommentAfterValueOnSameLine(const Value &root)
 
   if (root.hasComment(commentAfter))
   {
-    document_ += "\n";
+    document_ += '\n';
     document_ += root.getComment(commentAfter);
-    document_ += "\n";
+    document_ += '\n';
   }
 }
 
@@ -4975,16 +5116,16 @@ bool StyledWriter::hasCommentForValue(const Value &value)
 // Class StyledStreamWriter
 // //////////////////////////////////////////////////////////////////
 
-StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
-    : document_(NULL), rightMargin_(74), indentation_(indentation), addChildValues_()
+StyledStreamWriter::StyledStreamWriter(String indentation)
+  : document_(nullptr), indentation_(std::move(indentation)), addChildValues_(), indented_(false)
 {
 }
 
-void StyledStreamWriter::write(JSONCPP_OSTREAM &out, const Value &root)
+void StyledStreamWriter::write(OStream &out, const Value &root)
 {
   document_ = &out;
   addChildValues_ = false;
-  indentString_ = "";
+  indentString_.clear();
   indented_ = true;
   writeCommentBeforeValue(root);
   if (!indented_)
@@ -4993,7 +5134,7 @@ void StyledStreamWriter::write(JSONCPP_OSTREAM &out, const Value &root)
   writeValue(root);
   writeCommentAfterValueOnSameLine(root);
   *document_ << "\n";
-  document_ = NULL; // Forget the stream, for safety.
+  document_ = nullptr; // Forget the stream, for safety.
 }
 
 void StyledStreamWriter::writeValue(const Value &value)
@@ -5019,7 +5160,7 @@ void StyledStreamWriter::writeValue(const Value &value)
       char const *end;
       bool ok = value.getString(&str, &end);
       if (ok)
-        pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
+        pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
       else
         pushValue("");
       break;
@@ -5039,10 +5180,10 @@ void StyledStreamWriter::writeValue(const Value &value)
       {
         writeWithIndent("{");
         indent();
-        Value::Members::iterator it = members.begin();
+        auto it = members.begin();
         for (;;)
         {
-          const JSONCPP_STRING &name = *it;
+          const String &name = *it;
           const Value &childValue = value[name];
           writeCommentBeforeValue(childValue);
           writeWithIndent(valueToQuotedString(name.c_str()));
@@ -5071,7 +5212,7 @@ void StyledStreamWriter::writeArrayValue(const Value &value)
     pushValue("[]");
   else
   {
-    bool isArrayMultiLine = isMultineArray(value);
+    bool isArrayMultiLine = isMultilineArray(value);
     if (isArrayMultiLine)
     {
       writeWithIndent("[");
@@ -5118,7 +5259,7 @@ void StyledStreamWriter::writeArrayValue(const Value &value)
   }
 }
 
-bool StyledStreamWriter::isMultineArray(const Value &value)
+bool StyledStreamWriter::isMultilineArray(const Value &value)
 {
   ArrayIndex const size = value.size();
   bool isMultiLine = size * 3 >= rightMargin_;
@@ -5126,7 +5267,7 @@ bool StyledStreamWriter::isMultineArray(const Value &value)
   for (ArrayIndex index = 0; index < size && !isMultiLine; ++index)
   {
     const Value &childValue = value[index];
-    isMultiLine = ((childValue.isArray() || childValue.isObject()) && childValue.size() > 0);
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) && !childValue.empty());
   }
   if (!isMultiLine) // check if line length > max line length
   {
@@ -5148,7 +5289,7 @@ bool StyledStreamWriter::isMultineArray(const Value &value)
   return isMultiLine;
 }
 
-void StyledStreamWriter::pushValue(const JSONCPP_STRING &value)
+void StyledStreamWriter::pushValue(const String &value)
 {
   if (addChildValues_)
     childValues_.push_back(value);
@@ -5165,7 +5306,7 @@ void StyledStreamWriter::writeIndent()
   *document_ << '\n' << indentString_;
 }
 
-void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING &value)
+void StyledStreamWriter::writeWithIndent(const String &value)
 {
   if (!indented_)
     writeIndent();
@@ -5188,12 +5329,12 @@ void StyledStreamWriter::writeCommentBeforeValue(const Value &root)
 
   if (!indented_)
     writeIndent();
-  const JSONCPP_STRING &comment = root.getComment(commentBefore);
-  JSONCPP_STRING::const_iterator iter = comment.begin();
+  const String &comment = root.getComment(commentBefore);
+  String::const_iterator iter = comment.begin();
   while (iter != comment.end())
   {
     *document_ << *iter;
-    if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
+    if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
       // writeIndent();  // would include newline
       *document_ << indentString_;
     ++iter;
@@ -5237,57 +5378,59 @@ struct CommentStyle
 
 struct BuiltStyledStreamWriter : public StreamWriter
 {
-  BuiltStyledStreamWriter(JSONCPP_STRING const &indentation, CommentStyle::Enum cs,
-                          JSONCPP_STRING const &colonSymbol, JSONCPP_STRING const &nullSymbol,
-                          JSONCPP_STRING const &endingLineFeedSymbol, bool useSpecialFloats,
-                          unsigned int precision);
-  int write(Value const &root, JSONCPP_OSTREAM *sout) JSONCPP_OVERRIDE;
+  BuiltStyledStreamWriter(String indentation, CommentStyle::Enum cs, String colonSymbol,
+                          String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats,
+                          bool emitUTF8, unsigned int precision, PrecisionType precisionType);
+  int write(Value const &root, OStream *sout) override;
 
 private:
   void writeValue(Value const &value);
   void writeArrayValue(Value const &value);
-  bool isMultineArray(Value const &value);
-  void pushValue(JSONCPP_STRING const &value);
+  bool isMultilineArray(Value const &value);
+  void pushValue(String const &value);
   void writeIndent();
-  void writeWithIndent(JSONCPP_STRING const &value);
+  void writeWithIndent(String const &value);
   void indent();
   void unindent();
   void writeCommentBeforeValue(Value const &root);
   void writeCommentAfterValueOnSameLine(Value const &root);
   static bool hasCommentForValue(const Value &value);
 
-  typedef std::vector<JSONCPP_STRING> ChildValues;
+  using ChildValues = std::vector<String>;
 
   ChildValues childValues_;
-  JSONCPP_STRING indentString_;
+  String indentString_;
   unsigned int rightMargin_;
-  JSONCPP_STRING indentation_;
+  String indentation_;
   CommentStyle::Enum cs_;
-  JSONCPP_STRING colonSymbol_;
-  JSONCPP_STRING nullSymbol_;
-  JSONCPP_STRING endingLineFeedSymbol_;
+  String colonSymbol_;
+  String nullSymbol_;
+  String endingLineFeedSymbol_;
   bool addChildValues_ : 1;
   bool indented_ : 1;
   bool useSpecialFloats_ : 1;
+  bool emitUTF8_ : 1;
   unsigned int precision_;
+  PrecisionType precisionType_;
 };
-BuiltStyledStreamWriter::BuiltStyledStreamWriter(JSONCPP_STRING const &indentation,
-                                                 CommentStyle::Enum cs,
-                                                 JSONCPP_STRING const &colonSymbol,
-                                                 JSONCPP_STRING const &nullSymbol,
-                                                 JSONCPP_STRING const &endingLineFeedSymbol,
-                                                 bool useSpecialFloats, unsigned int precision)
-    : rightMargin_(74), indentation_(indentation), cs_(cs), colonSymbol_(colonSymbol),
-      nullSymbol_(nullSymbol), endingLineFeedSymbol_(endingLineFeedSymbol), addChildValues_(false),
-      indented_(false), useSpecialFloats_(useSpecialFloats), precision_(precision)
+BuiltStyledStreamWriter::BuiltStyledStreamWriter(String indentation, CommentStyle::Enum cs,
+                                                 String colonSymbol, String nullSymbol,
+                                                 String endingLineFeedSymbol, bool useSpecialFloats,
+                                                 bool emitUTF8, unsigned int precision,
+                                                 PrecisionType precisionType)
+  : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
+    colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
+    endingLineFeedSymbol_(std::move(endingLineFeedSymbol)), addChildValues_(false),
+    indented_(false), useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
+    precision_(precision), precisionType_(precisionType)
 {
 }
-int BuiltStyledStreamWriter::write(Value const &root, JSONCPP_OSTREAM *sout)
+int BuiltStyledStreamWriter::write(Value const &root, OStream *sout)
 {
   sout_ = sout;
   addChildValues_ = false;
   indented_ = true;
-  indentString_ = "";
+  indentString_.clear();
   writeCommentBeforeValue(root);
   if (!indented_)
     writeIndent();
@@ -5295,7 +5438,7 @@ int BuiltStyledStreamWriter::write(Value const &root, JSONCPP_OSTREAM *sout)
   writeValue(root);
   writeCommentAfterValueOnSameLine(root);
   *sout_ << endingLineFeedSymbol_;
-  sout_ = NULL;
+  sout_ = nullptr;
   return 0;
 }
 void BuiltStyledStreamWriter::writeValue(Value const &value)
@@ -5312,7 +5455,7 @@ void BuiltStyledStreamWriter::writeValue(Value const &value)
       pushValue(valueToString(value.asLargestUInt()));
       break;
     case realValue:
-      pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
+      pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, precisionType_));
       break;
     case stringValue:
     {
@@ -5321,7 +5464,7 @@ void BuiltStyledStreamWriter::writeValue(Value const &value)
       char const *end;
       bool ok = value.getString(&str, &end);
       if (ok)
-        pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
+        pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str), emitUTF8_));
       else
         pushValue("");
       break;
@@ -5341,13 +5484,13 @@ void BuiltStyledStreamWriter::writeValue(Value const &value)
       {
         writeWithIndent("{");
         indent();
-        Value::Members::iterator it = members.begin();
+        auto it = members.begin();
         for (;;)
         {
-          JSONCPP_STRING const &name = *it;
+          String const &name = *it;
           Value const &childValue = value[name];
           writeCommentBeforeValue(childValue);
-          writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
+          writeWithIndent(valueToQuotedStringN(name.data(), name.length(), emitUTF8_));
           *sout_ << colonSymbol_;
           writeValue(childValue);
           if (++it == members.end())
@@ -5373,7 +5516,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const &value)
     pushValue("[]");
   else
   {
-    bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
+    bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
     if (isMultiLine)
     {
       writeWithIndent("[");
@@ -5424,7 +5567,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const &value)
   }
 }
 
-bool BuiltStyledStreamWriter::isMultineArray(Value const &value)
+bool BuiltStyledStreamWriter::isMultilineArray(Value const &value)
 {
   ArrayIndex const size = value.size();
   bool isMultiLine = size * 3 >= rightMargin_;
@@ -5432,7 +5575,7 @@ bool BuiltStyledStreamWriter::isMultineArray(Value const &value)
   for (ArrayIndex index = 0; index < size && !isMultiLine; ++index)
   {
     Value const &childValue = value[index];
-    isMultiLine = ((childValue.isArray() || childValue.isObject()) && childValue.size() > 0);
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) && !childValue.empty());
   }
   if (!isMultiLine) // check if line length > max line length
   {
@@ -5454,7 +5597,7 @@ bool BuiltStyledStreamWriter::isMultineArray(Value const &value)
   return isMultiLine;
 }
 
-void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const &value)
+void BuiltStyledStreamWriter::pushValue(String const &value)
 {
   if (addChildValues_)
     childValues_.push_back(value);
@@ -5476,7 +5619,7 @@ void BuiltStyledStreamWriter::writeIndent()
   }
 }
 
-void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const &value)
+void BuiltStyledStreamWriter::writeWithIndent(String const &value)
 {
   if (!indented_)
     writeIndent();
@@ -5501,12 +5644,12 @@ void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const &root)
 
   if (!indented_)
     writeIndent();
-  const JSONCPP_STRING &comment = root.getComment(commentBefore);
-  JSONCPP_STRING::const_iterator iter = comment.begin();
+  const String &comment = root.getComment(commentBefore);
+  String::const_iterator iter = comment.begin();
   while (iter != comment.end())
   {
     *sout_ << *iter;
-    if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
+    if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
       // writeIndent();  // would write extra newline
       *sout_ << indentString_;
     ++iter;
@@ -5538,18 +5681,20 @@ bool BuiltStyledStreamWriter::hasCommentForValue(const Value &value)
 ///////////////
 // StreamWriter
 
-StreamWriter::StreamWriter() : sout_(NULL) {}
-StreamWriter::~StreamWriter() {}
-StreamWriter::Factory::~Factory() {}
+StreamWriter::StreamWriter() : sout_(nullptr) {}
+StreamWriter::~StreamWriter() = default;
+StreamWriter::Factory::~Factory() = default;
 StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
-StreamWriterBuilder::~StreamWriterBuilder() {}
+StreamWriterBuilder::~StreamWriterBuilder() = default;
 StreamWriter *StreamWriterBuilder::newStreamWriter() const
 {
-  JSONCPP_STRING indentation = settings_["indentation"].asString();
-  JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
-  bool eyc = settings_["enableYAMLCompatibility"].asBool();
-  bool dnp = settings_["dropNullPlaceholders"].asBool();
-  bool usf = settings_["useSpecialFloats"].asBool();
+  const String indentation = settings_["indentation"].asString();
+  const String cs_str = settings_["commentStyle"].asString();
+  const String pt_str = settings_["precisionType"].asString();
+  const bool eyc = settings_["enableYAMLCompatibility"].asBool();
+  const bool dnp = settings_["dropNullPlaceholders"].asBool();
+  const bool usf = settings_["useSpecialFloats"].asBool();
+  const bool emitUTF8 = settings_["emitUTF8"].asBool();
   unsigned int pre = settings_["precision"].asUInt();
   CommentStyle::Enum cs = CommentStyle::All;
   if (cs_str == "All")
@@ -5564,7 +5709,20 @@ StreamWriter *StreamWriterBuilder::newStreamWriter() const
   {
     throwRuntimeError("commentStyle must be 'All' or 'None'");
   }
-  JSONCPP_STRING colonSymbol = " : ";
+  PrecisionType precisionType(significantDigits);
+  if (pt_str == "significant")
+  {
+    precisionType = PrecisionType::significantDigits;
+  }
+  else if (pt_str == "decimal")
+  {
+    precisionType = PrecisionType::decimalPlaces;
+  }
+  else
+  {
+    throwRuntimeError("precisionType must be 'significant' or 'decimal'");
+  }
+  String colonSymbol = " : ";
   if (eyc)
   {
     colonSymbol = ": ";
@@ -5573,48 +5731,44 @@ StreamWriter *StreamWriterBuilder::newStreamWriter() const
   {
     colonSymbol = ":";
   }
-  JSONCPP_STRING nullSymbol = "null";
+  String nullSymbol = "null";
   if (dnp)
   {
-    nullSymbol = "";
+    nullSymbol.clear();
   }
   if (pre > 17)
     pre = 17;
-  JSONCPP_STRING endingLineFeedSymbol = "";
+  String endingLineFeedSymbol;
   return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol, endingLineFeedSymbol,
-                                     usf, pre);
-}
-static void getValidWriterKeys(std::set<JSONCPP_STRING> *valid_keys)
-{
-  valid_keys->clear();
-  valid_keys->insert("indentation");
-  valid_keys->insert("commentStyle");
-  valid_keys->insert("enableYAMLCompatibility");
-  valid_keys->insert("dropNullPlaceholders");
-  valid_keys->insert("useSpecialFloats");
-  valid_keys->insert("precision");
+                                     usf, emitUTF8, pre, precisionType);
 }
+
 bool StreamWriterBuilder::validate(Json::Value *invalid) const
 {
-  Json::Value my_invalid;
-  if (!invalid)
-    invalid = &my_invalid; // so we do not need to test for NULL
-  Json::Value &inv = *invalid;
-  std::set<JSONCPP_STRING> valid_keys;
-  getValidWriterKeys(&valid_keys);
-  Value::Members keys = settings_.getMemberNames();
-  size_t n = keys.size();
-  for (size_t i = 0; i < n; ++i)
-  {
-    JSONCPP_STRING const &key = keys[i];
-    if (valid_keys.find(key) == valid_keys.end())
-    {
-      inv[key] = settings_[key];
-    }
+  static const auto &valid_keys = *new std::set<String>{
+    "indentation",
+    "commentStyle",
+    "enableYAMLCompatibility",
+    "dropNullPlaceholders",
+    "useSpecialFloats",
+    "emitUTF8",
+    "precision",
+    "precisionType",
+  };
+  for (auto si = settings_.begin(); si != settings_.end(); ++si)
+  {
+    auto key = si.name();
+    if (valid_keys.count(key))
+      continue;
+    if (invalid)
+      (*invalid)[key] = *si;
+    else
+      return false;
   }
-  return 0u == inv.size();
+  return invalid ? invalid->empty() : true;
 }
-Value &StreamWriterBuilder::operator[](JSONCPP_STRING key) { return settings_[key]; }
+
+Value &StreamWriterBuilder::operator[](const String &key) { return settings_[key]; }
 // static
 void StreamWriterBuilder::setDefaults(Json::Value *settings)
 {
@@ -5624,19 +5778,21 @@ void StreamWriterBuilder::setDefaults(Json::Value *settings)
   (*settings)["enableYAMLCompatibility"] = false;
   (*settings)["dropNullPlaceholders"] = false;
   (*settings)["useSpecialFloats"] = false;
+  (*settings)["emitUTF8"] = false;
   (*settings)["precision"] = 17;
+  (*settings)["precisionType"] = "significant";
   //! [StreamWriterBuilderDefaults]
 }
 
-JSONCPP_STRING writeString(StreamWriter::Factory const &builder, Value const &root)
+String writeString(StreamWriter::Factory const &factory, Value const &root)
 {
-  JSONCPP_OSTRINGSTREAM sout;
-  StreamWriterPtr const writer(builder.newStreamWriter());
+  OStringStream sout;
+  StreamWriterPtr const writer(factory.newStreamWriter());
   writer->write(root, &sout);
   return sout.str();
 }
 
-JSONCPP_OSTREAM &operator<<(JSONCPP_OSTREAM &sout, Value const &root)
+OStream &operator<<(OStream &sout, Value const &root)
 {
   StreamWriterBuilder builder;
   StreamWriterPtr const writer(builder.newStreamWriter());
index 3d71f89..6273806 100644 (file)
@@ -47,11 +47,12 @@ extern "C" {
     }                                                 \
   } while (0)
 #else // __TIZEN__
-#define LEVEL_TO_STR(level)                  \
-  (((level) == ERROR) ? "ERROR"              \
-                      : ((level) == WARNING) \
-                          ? "WARNING"        \
-                          : ((level) == INFO) ? "INFO" : ((level) == DEBUG) ? "DEBUG" : "DEFAULT")
+#define LEVEL_TO_STR(level)           \
+  (((level) == ERROR)     ? "ERROR"   \
+   : ((level) == WARNING) ? "WARNING" \
+   : ((level) == INFO)    ? "INFO"    \
+   : ((level) == DEBUG)   ? "DEBUG"   \
+                          : "DEFAULT")
 #define TFLITE_NATIVE_LOG(log_level, format, args...)      \
   do                                                       \
   {                                                        \
index 63cf2bc..9f0c014 100644 (file)
@@ -26,7 +26,7 @@ include $(CLEAR_VARS)
 LOCAL_MODULE := backend_cpu
 PREBUILT_LIB += backend_cpu
 LOCAL_SRC_FILES := \
-               $(ONERT_PREBUILT_LIB_DIR)/libbackend_cpu.so
+               $(ONERT_PREBUILT_LIB_DIR)/nnfw/backend/libbackend_cpu.so
 include $(PREBUILT_SHARED_LIBRARY)
 
 # TODO Support backend acl
index eed8f27..0419814 100644 (file)
@@ -8,7 +8,7 @@ android {
         minSdkVersion 26
         targetSdkVersion 29
         versionCode 1
-        versionName "1.25.0"
+        versionName "1.28.0"
 
         externalNativeBuild {
             ndkBuild {
index 663eb78..d0076fa 100644 (file)
@@ -1,15 +1,15 @@
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
 
 buildscript {
-    
+
     repositories {
         google()
-        jcenter()
-        
+        mavenCentral()
+
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.6.2'
-        
+        classpath 'com.android.tools.build:gradle:7.0.2'
+
 
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
@@ -19,8 +19,8 @@ buildscript {
 allprojects {
     repositories {
         google()
-        jcenter()
-        
+        mavenCentral()
+
     }
 }
 
index 490fda8..afba109 100644 (file)
Binary files a/runtime/contrib/android/gradle/wrapper/gradle-wrapper.jar and b/runtime/contrib/android/gradle/wrapper/gradle-wrapper.jar differ
index a4b4429..c7d437b 100644 (file)
@@ -1,5 +1,6 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip
+networkTimeout=10000
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
index 2fe81a7..79a61d4 100755 (executable)
@@ -1,7 +1,7 @@
-#!/usr/bin/env sh
+#!/bin/sh
 
 #
-# Copyright 2015 the original author or authors.
+# Copyright Â© 2015-2021 the original authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 #
 
 ##############################################################################
-##
-##  Gradle start up script for UN*X
-##
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions Â«$var», Â«${var}», Â«${var:-default}», Â«${var+SET}»,
+#           Â«${var#prefix}», Â«${var%suffix}», and Â«$( cmd )»;
+#         * compound commands having a testable exit status, especially Â«case»;
+#         * various built-in commands including Â«command», Â«set», and Â«ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
 ##############################################################################
 
 # Attempt to set APP_HOME
+
 # Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
 done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
 
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
 
 # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
 DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
 
 # Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
 
 warn () {
     echo "$*"
-}
+} >&2
 
 die () {
     echo
     echo "$*"
     echo
     exit 1
-}
+} >&2
 
 # OS specific support (must be 'true' or 'false').
 cygwin=false
 msys=false
 darwin=false
 nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
 esac
 
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
+
 # Determine the Java command to use to start the JVM.
 if [ -n "$JAVA_HOME" ] ; then
     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
         # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
+        JAVACMD=$JAVA_HOME/jre/sh/java
     else
-        JAVACMD="$JAVA_HOME/bin/java"
+        JAVACMD=$JAVA_HOME/bin/java
     fi
     if [ ! -x "$JAVACMD" ] ; then
         die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
 location of your Java installation."
     fi
 else
-    JAVACMD="java"
+    JAVACMD=java
     which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
 
 Please set the JAVA_HOME variable in your environment to match the
@@ -105,79 +140,105 @@ location of your Java installation."
 fi
 
 # Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC3045
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC3045
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
 fi
 
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
 
 # For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
     # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
         fi
-        i=`expr $i + 1`
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
     done
-    case $i in
-        0) set -- ;;
-        1) set -- "$args0" ;;
-        2) set -- "$args0" "$args1" ;;
-        3) set -- "$args0" "$args1" "$args2" ;;
-        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
 fi
 
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=`save "$@"`
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
 
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
 
 exec "$JAVACMD" "$@"
index 62bd9b9..93e3f59 100644 (file)
@@ -14,7 +14,7 @@
 @rem limitations under the License.
 @rem
 
-@if "%DEBUG%" == "" @echo off
+@if "%DEBUG%"=="" @echo off
 @rem ##########################################################################
 @rem
 @rem  Gradle startup script for Windows
@@ -25,7 +25,8 @@
 if "%OS%"=="Windows_NT" setlocal
 
 set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
 set APP_BASE_NAME=%~n0
 set APP_HOME=%DIRNAME%
 
@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
 
 set JAVA_EXE=java.exe
 %JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if %ERRORLEVEL% equ 0 goto execute
 
 echo.
 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -54,7 +55,7 @@ goto fail
 set JAVA_HOME=%JAVA_HOME:"=%
 set JAVA_EXE=%JAVA_HOME%/bin/java.exe
 
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
 
 echo.
 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -64,38 +65,26 @@ echo location of your Java installation.
 
 goto fail
 
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
 :execute
 @rem Setup the command line
 
 set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
 
+
 @rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
 
 :end
 @rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
+if %ERRORLEVEL% equ 0 goto mainEnd
 
 :fail
 rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
 rem the _cmd.exe /c_ return code!
-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
 
 :mainEnd
 if "%OS%"=="Windows_NT" endlocal
index 37d91b5..59c4a82 100644 (file)
@@ -7,5 +7,5 @@ nnfw_find_package(Tensorflow REQUIRED)
 list(APPEND SOURCES detection.cpp)
 
 add_executable(detection ${SOURCES})
-target_link_libraries(detection nnfw_lib_misc)
+target_link_libraries(detection nnfw_lib_benchmark)
 target_link_libraries(detection tensorflow-core)
index 8fe78ca..5c3649d 100644 (file)
@@ -22,7 +22,7 @@
 #include <cassert>
 #include <cstring>
 
-#include "misc/benchmark.h"
+#include <benchmark/Accumulator.h>
 
 #define CHECK_TF(e)                                \
   {                                                \
@@ -63,7 +63,7 @@ int main(int argc, char **argv)
   {
     std::chrono::milliseconds elapsed(0);
 
-    nnfw::misc::benchmark::measure(elapsed) << [&](void) {
+    benchmark::measure(elapsed) << [&](void) {
       CHECK_TF(sess->Run({{"input_node", input}}, output_nodes, {}, &outputs));
     };
 
diff --git a/runtime/contrib/gpu_cl/BackendContext.cc b/runtime/contrib/gpu_cl/BackendContext.cc
new file mode 100644 (file)
index 0000000..55c5ed6
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * 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 "BackendContext.h"
+
+#include "ConstantInitializer.h"
+#include "TensorBuilder.h"
+#include "KernelGenerator.h"
+
+#include "util/logging.h"
+#include "ir/Index.h"
+#include "ir/Operations.h"
+#include "ir/OperandIndexMap.h"
+#include "ir/OperandIndexSequence.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace gpu_cl
+{
+
+void BackendContext::registerTensorInfo(const ir::OperandIndex &ind, const ir::OperandInfo &info,
+                                        ir::Layout backend_layout)
+{
+  TensorType type = TensorType::TENSOR_TYPE_VALID;
+  tensor_builder->registerTensorInfo(ind, info, backend_layout, type);
+}
+
+ITensorRegistry *BackendContext::genTensors()
+{
+  ir::OperandIndexMap<TensorType> type_map;
+
+  for (const auto &ind : graph()->getInputs())
+  {
+    type_map[ind] = TensorType::TENSOR_TYPE_INPUT;
+  }
+
+  for (const auto &ind : graph()->getOutputs())
+  {
+    type_map[ind] = TensorType::TENSOR_TYPE_OUTPUT;
+  }
+  graph()->operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &obj) {
+    if (external_operands().contains(ind))
+      return;
+
+    const auto frontend_layout = graph()->layout();
+    const auto backend_layout = operand_layouts().at(ind);
+    ir::OperandInfo backend_info{permuteShape(obj.shape(), frontend_layout, backend_layout),
+                                 obj.typeInfo(), obj.info().memAllocType(), obj.isConstant()};
+    if (obj.isConstant())
+    {
+      type_map[ind] = TensorType::TENSOR_TYPE_INPUT;
+    }
+    tensor_builder->registerTensorInfo(ind, backend_info, backend_layout, type_map[ind]);
+  });
+
+  // TODO Get compiler options from compiler, and use it rather than getting it from Env
+  if (util::getConfigString(util::config::EXECUTOR) == "Linear")
+  {
+    planTensors();
+  }
+  else
+  {
+    // 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
+    graph()->operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &) {
+      if (tensor_builder->isRegistered(ind))
+        tensor_builder->notifyFirstUse(ind);
+    });
+  }
+  tensor_builder->prepare();
+  return tensor_registry.get();
+}
+
+FunctionMap BackendContext::genKernels()
+{
+  FunctionMap fn_map;
+
+  for (auto &&op_ind : _data.op_order)
+  {
+    auto fn_seq = kernel_gen->generate(op_ind);
+    fn_map.emplace(op_ind, std::move(fn_seq));
+  }
+
+  kernel_gen->get_operation(fn_map);
+  tensor_builder->allocate();
+  // NOTE For memory optimization, we want to free some operand data
+  const_cast<ir::Graph &>(*_data.graph)
+    .operands()
+    .iterate([&](const ir::OperandIndex &, ir::Operand &obj) { obj.releaseData(); });
+
+  for (auto &&it : fn_map)
+  {
+    auto &fn_seq = it.second;
+    fn_seq->iterate([&](exec::IFunction &ifunc) { ifunc.prepare(); });
+  }
+
+  return fn_map;
+}
+
+} // namespace gpu_cl
+} // namespace backend
+} // namespace onert
diff --git a/runtime/contrib/gpu_cl/CMakeLists.txt b/runtime/contrib/gpu_cl/CMakeLists.txt
new file mode 100644 (file)
index 0000000..bf65fce
--- /dev/null
@@ -0,0 +1,41 @@
+set(LIB_ONERT_BACKEND_GPU_CL onert_backend_gpu_cl)
+
+if(NOT BUILD_GPU_CL)
+  return()
+endif(NOT BUILD_GPU_CL)
+
+nnfw_find_package(TensorFlowGpu QUIET)
+if(NOT TensorFlowGpu_FOUND)
+  message(FATAL_ERROR 'TensorFlowGpu lib not found')
+  return()
+endif(NOT TensorFlowGpu_FOUND)
+
+file(GLOB_RECURSE SOURCES "*.cc")
+
+add_library(${LIB_ONERT_BACKEND_GPU_CL} SHARED ${SOURCES})
+
+target_include_directories(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+
+if (${TARGET_OS} MATCHES "tizen")
+    target_compile_options(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE "-Wno-error=deprecated-copy")
+endif ()
+
+target_compile_definitions(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE CL_TARGET_OPENCL_VERSION=220 EGL_NO_X11)
+
+target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE dl)
+target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE tflite-gpu-delegate)
+target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE onert_core)
+target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE ${LIB_ONERT_BACKEND_CL_COMMON})
+target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE nnfw_common)
+target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE nnfw_coverage)
+
+set_target_properties(${LIB_ONERT_BACKEND_GPU_CL} PROPERTIES OUTPUT_NAME backend_gpu_cl)
+
+add_library(tflite_ignore_warnings INTERFACE)
+target_compile_options(tflite_ignore_warnings INTERFACE -Wno-unused-parameter -Wno-sign-compare)
+if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10)
+  target_compile_options(tflite_ignore_warnings INTERFACE -Wno-deprecated-copy)
+endif()
+target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE tflite_ignore_warnings)
+
+install(TARGETS ${LIB_ONERT_BACKEND_GPU_CL} DESTINATION lib)
diff --git a/runtime/contrib/gpu_cl/ClConstantInitializer.h b/runtime/contrib/gpu_cl/ClConstantInitializer.h
new file mode 100644 (file)
index 0000000..ad5b47d
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * 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 __ONERT_COMPILER_GPU_CL_CLCONSTANT_INITIALIZER_H__
+#define __ONERT_COMPILER_GPU_CL_CLCONSTANT_INITIALIZER_H__
+
+#include <unordered_map>
+#include <functional>
+
+#include <ir/Coordinates.h>
+#include <ir/Layout.h>
+#include <ir/Operand.h>
+#include <ir/Operands.h>
+#include <ir/OperationVisitor.h>
+#include <backend/ITensorRegistry.h>
+#include <util/logging.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace gpu_cl
+{
+
+template <typename T>
+static void Init(const onert::ir::Operand &model_obj, onert::backend::ITensor &obj, const bool copy,
+                 const onert::ir::Layout frontend_layout = onert::ir::Layout::UNKNOWN)
+{
+  const auto &shape = model_obj.shape();
+  assert(model_obj.data());
+  obj.access([&](::onert::backend::ITensor &tensor) {
+    switch (shape.rank())
+    {
+      case 0:
+      case 1:
+      case 2:
+      case 3:
+      case 4:
+        if (copy)
+        {
+          tensor.enqueueWriteBuffer(model_obj.data()->base(), true);
+        }
+        else
+        {
+          // NYI
+          (void)frontend_layout;
+          throw std::runtime_error{"Not yet supported"};
+        }
+        break;
+      default:
+        throw std::runtime_error{"Not yet supported"};
+    }
+  });
+}
+
+template <typename T>
+void copyInit(const onert::ir::Operand &model_obj, onert::backend::ITensor &obj)
+{
+  Init<T>(model_obj, obj, true);
+}
+
+template <typename T>
+void permuteInit(const onert::ir::Operand &model_obj, onert::backend::ITensor &obj,
+                 const onert::ir::Layout frontend_layout)
+{
+  const bool copy = frontend_layout == obj.layout();
+  Init<T>(model_obj, obj, copy, frontend_layout);
+}
+
+class ClConstantInitializer : public ir::OperationVisitor
+{
+public:
+  void run()
+  {
+    assert(_tensor_reg);
+    for (const auto &it : _init_map)
+    {
+      const auto &ind = it.first;
+      const auto &fn = it.second;
+
+      const auto &model_obj = _operands.at(ind);
+      auto tensor_obj = _tensor_reg->getNativeITensor(ind);
+      assert(tensor_obj != nullptr);
+      fn(model_obj, *tensor_obj);
+      VERBOSE(FillOperandData) << "Fill data for operand " << ind << std::endl;
+    }
+    _init_map.clear();
+  }
+
+public:
+  ClConstantInitializer(const ir::Operands &operands,
+                        const std::shared_ptr<ITensorRegistry> &tensor_reg);
+
+public:
+  using Initializer = std::function<void(const ir::Operand &, backend::ITensor &)>;
+
+public:
+  void registerDefaultInitializer(const ir::OperandIndex &index, const ir::Operand &obj)
+  {
+    registerPermuteInitializer(index, obj);
+  }
+  void registerCopyInitializer(const ir::OperandIndex &index, const ir::Operand &obj);
+  void registerPermuteInitializer(const ir::OperandIndex &index, const ir::Operand &obj);
+
+public:
+  void setLayout(ir::Layout layout) { _current_layout = layout; }
+  bool exist(const ir::OperandIndex &ind) { return _init_map.find(ind) != _init_map.end(); }
+
+public:
+protected:
+  void copyInputInitialize(const ir::Operation &node, uint32_t index);
+  void permuteInputInitialize(const ir::Operation &node, uint32_t index);
+
+protected:
+  const ir::Operands &_operands;
+  std::shared_ptr<ITensorRegistry> _tensor_reg;
+  std::unordered_map<ir::OperandIndex, Initializer> _init_map;
+  ir::Layout _current_layout;
+};
+
+} // namespace gpu_cl
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_COMPILER_GPU_CL_CLCONSTANT_INITIALIZER_H__
diff --git a/runtime/contrib/gpu_cl/KernelGenerator.cc b/runtime/contrib/gpu_cl/KernelGenerator.cc
new file mode 100644 (file)
index 0000000..5db0025
--- /dev/null
@@ -0,0 +1,709 @@
+/*
+ * 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 <stdexcept>
+
+#include <backend/basic/KernelGeneratorBase.h>
+
+#include "KernelGenerator.h"
+
+#include "ClFunction.h"
+#include "TensorManager.h"
+
+#include "tensorflow/lite/delegates/gpu/common/shape.h"
+#include "tensorflow/lite/delegates/gpu/common/tensor.h"
+#include "tensorflow/lite/delegates/gpu/common/tasks/elementwise.h"
+#include "tensorflow/lite/delegates/gpu/common/selectors/convolution_selector.h"
+#include "tensorflow/lite/delegates/gpu/common/selectors/dw_convolution_selector.h"
+#include "tensorflow/lite/delegates/gpu/common/selectors/simple_selectors.h"
+
+#include "ir/Operations.h"
+#include "ir/Operations.Include.h"
+#include "ir/Index.h"
+#include "ir/DataType.h"
+#include "ir/InternalType.h"
+#include "exec/NopFunction.h"
+#include "exec/FunctionSequence.h"
+#include "util/logging.h"
+#include "util/Utils.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace gpu_cl
+{
+
+void KernelGenerator::addClNode(const std::vector<ir::OperandIndex> &inputs,
+                                const std::vector<ir::OperandIndex> &outputs,
+                                std::unique_ptr<tflite::gpu::GPUOperation> gpu_op)
+{
+  tflite::gpu::cl::CLNode cl_node;
+  cl_node.cl_operation.Init(std::move(gpu_op));
+  cl_node.inputs.resize(inputs.size());
+  for (size_t i = 0; i < inputs.size(); ++i)
+  {
+    cl_node.inputs[i] = inputs[i].value();
+  }
+  cl_node.outputs.resize(outputs.size());
+  for (size_t i = 0; i < outputs.size(); ++i)
+  {
+    cl_node.outputs[i] = outputs[i].value();
+  }
+  _nodes.push_back(std::move(cl_node));
+  _operation_indexes.push_back(_operation_index);
+  return;
+}
+
+void KernelGenerator::get_operation(FunctionMap &Functions)
+{
+  size_t size = _nodes.size();
+  size_t i = 0;
+  for (auto &&it : Functions)
+  {
+    auto index = it.first;
+    auto node_index = _operation_indexes[i];
+    while (index == node_index)
+    {
+      auto &fn_seq = it.second;
+      auto &node = _nodes[i++];
+      for (size_t j = 0; j < node.inputs.size(); ++j)
+      {
+        uint32_t idx = node.inputs[j];
+        node.cl_operation.GetGpuOperation().SetSrc(
+          _tensor_reg->getClTensor(ir::OperandIndex{idx})->handle(), j);
+      }
+      for (size_t j = 0; j < node.outputs.size(); ++j)
+      {
+        uint32_t idx = node.outputs[j];
+        node.cl_operation.GetGpuOperation().SetDst(
+          _tensor_reg->getClTensor(ir::OperandIndex{idx})->handle(), j);
+      }
+      fn_seq->iterate([&](exec::IFunction &ifunc) {
+        static_cast<ClFunction &>(ifunc).add_operation(&node.cl_operation);
+      });
+      if (i == size)
+      {
+        break;
+      }
+      node_index = _operation_indexes[i];
+    }
+    if (i == size)
+    {
+      break;
+    }
+  }
+}
+
+absl::Status KernelGenerator::readConstTensor(const ir::OperandIndex &index,
+                                              tflite::gpu::TensorOrScalar *param)
+{
+  const auto &shape = _ctx.at(index).shape();
+  if (shape.rank() == 0 && shape.num_elements() == 1)
+  {
+    tflite::gpu::Tensor<tflite::gpu::Scalar, tflite::gpu::DataType::FLOAT32> tensor;
+    tensor.shape.v = 1;
+    tensor.data.resize(1);
+    std::memcpy(&tensor.data[0], _ctx.at(index).data()->base(), _ctx.at(index).operandSize());
+    *param = tensor.data[0];
+  }
+  else
+  {
+    if (CheckIfLinearConvertible(&shape))
+    {
+      tflite::gpu::Tensor<tflite::gpu::Linear, tflite::gpu::DataType::FLOAT32> tensor;
+      tensor.shape.v = shape.dim(shape.rank() - 1);
+      tensor.data.resize(shape.num_elements());
+      std::memcpy(&tensor.data[0], _ctx.at(index).data()->base(), _ctx.at(index).operandSize());
+      *param = std::move(tensor);
+    }
+    else
+    {
+      tflite::gpu::Tensor<tflite::gpu::HWC, tflite::gpu::DataType::FLOAT32> tensor;
+      if (shape.rank() == 3)
+      {
+        tensor.shape.h = shape.dim(0);
+        tensor.shape.w = shape.dim(1);
+        tensor.shape.c = shape.dim(2);
+      }
+      else if (shape.rank() == 4)
+      {
+        if (shape.dim(0) != 1)
+        {
+          return absl::UnimplementedError("Batch size is not equal to 1.");
+        }
+        tensor.shape.h = shape.dim(1);
+        tensor.shape.w = shape.dim(2);
+        tensor.shape.c = shape.dim(3);
+      }
+      else
+      {
+        return absl::InvalidArgumentError(
+          "Expected a 3D tensor of shape HxWxC or a 4D tensor of shape 1xHxWxC.");
+      }
+      tensor.data.resize(shape.num_elements());
+      std::memcpy(&tensor.data[0], _ctx.at(index).data()->base(), _ctx.at(index).operandSize());
+      *param = std::move(tensor);
+    }
+  }
+  return absl::OkStatus();
+}
+
+absl::Status KernelGenerator::readConstTensor(
+  const ir::OperandIndex &index,
+  absl::variant<tflite::gpu::Tensor<tflite::gpu::Linear, tflite::gpu::DataType::FLOAT32>,
+                tflite::gpu::Tensor<tflite::gpu::HWC, tflite::gpu::DataType::FLOAT32>> *alpha)
+{
+  const auto &shape = _ctx.at(index).shape();
+  if (CheckIfLinearConvertible(&shape))
+  {
+    tflite::gpu::Tensor<tflite::gpu::Linear, tflite::gpu::DataType::FLOAT32> tensor;
+    tensor.shape.v = shape.dim(shape.rank() - 1);
+    tensor.data.resize(shape.num_elements());
+    std::memcpy(&tensor.data[0], _ctx.at(index).data()->base(), _ctx.at(index).operandSize());
+    *alpha = std::move(tensor);
+  }
+  else
+  {
+    tflite::gpu::Tensor<tflite::gpu::HWC, tflite::gpu::DataType::FLOAT32> tensor;
+    if (shape.rank() == 3)
+    {
+      tensor.shape.h = shape.dim(0);
+      tensor.shape.w = shape.dim(1);
+      tensor.shape.c = shape.dim(2);
+    }
+    else if (shape.rank() == 4)
+    {
+      if (shape.dim(0) != 1)
+      {
+        return absl::UnimplementedError("Batch size is not equal to 1.");
+      }
+      tensor.shape.h = shape.dim(1);
+      tensor.shape.w = shape.dim(2);
+      tensor.shape.c = shape.dim(3);
+    }
+    else
+    {
+      return absl::InvalidArgumentError(
+        "Expected a 3D tensor of shape HxWxC or a 4D tensor of shape 1xHxWxC.");
+    }
+    tensor.data.resize(shape.num_elements());
+    std::memcpy(&tensor.data[0], _ctx.at(index).data()->base(), _ctx.at(index).operandSize());
+    *alpha = std::move(tensor);
+  }
+  return absl::OkStatus();
+}
+
+KernelGenerator::KernelGenerator(
+  const ir::Graph &graph, const std::shared_ptr<TensorBuilder> &tensor_builder,
+  const std::shared_ptr<TensorRegistry> &tensor_reg,
+  const std::shared_ptr<tflite::gpu::cl::CreationContext> &creation_context)
+  : basic::KernelGeneratorBase{graph}, _ctx(graph.operands()), _operations_ctx(graph.operations()),
+    _current_layout{graph.layout()}, _tensor_builder(tensor_builder), _tensor_reg(tensor_reg),
+    _creation_context(creation_context)
+{
+}
+
+std::unique_ptr<exec::FunctionSequence> KernelGenerator::generate(ir::OperationIndex ind)
+{
+  auto fn_seq = std::make_unique<exec::FunctionSequence>();
+  fn_seq->enableDynamicShapeInferer(false);
+  _operation_index = ind;
+  const auto &op = _graph.operations().at(ind);
+  op.accept(*this);
+  fn_seq->append(releaseFunction());
+  return fn_seq;
+}
+
+void KernelGenerator::visit(const ir::operation::BinaryArithmetic &node)
+{
+  const auto ofm_index{node.getOutputs().at(0)};
+  const auto lhs_index{node.getInputs().at(ir::operation::BinaryArithmetic::Input::LHS)};
+  const auto rhs_index{node.getInputs().at(ir::operation::BinaryArithmetic::Input::RHS)};
+
+  tflite::gpu::OperationDef op_def;
+  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
+
+  const bool lhs_const = _ctx.at(lhs_index).isConstant();
+  const bool rhs_const = _ctx.at(rhs_index).isConstant();
+
+  if (lhs_const && rhs_const)
+  {
+    throw std::runtime_error("No runtime input tensors for " + node.name());
+  }
+
+  auto fn = std::make_unique<ClFunction>(_creation_context);
+  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
+
+  tflite::gpu::OperationType op_type = convertArithmeticType(node.param().arithmetic_type);
+
+  if (!lhs_const && !rhs_const)
+  {
+    auto lhs_shape = _tensor_reg->getClTensor(lhs_index)->get_info()._shape;
+    auto rhs_shape = _tensor_reg->getClTensor(rhs_index)->get_info()._shape;
+
+    bool swap =
+      (op_type == tflite::gpu::OperationType::MUL) &&
+      (lhs_shape.h <= rhs_shape.h && lhs_shape.w <= rhs_shape.w && lhs_shape.c <= rhs_shape.c);
+
+    auto first_index = swap ? rhs_index : lhs_index;
+    auto second_index = swap ? lhs_index : rhs_index;
+
+    op_def.src_tensors.push_back(_tensor_reg->getClTensor(first_index)->get_info()._desc);
+    op_def.src_tensors.push_back(_tensor_reg->getClTensor(second_index)->get_info()._desc);
+    op_def.dst_tensors.push_back(_tensor_reg->getClTensor(ofm_index)->get_info()._desc);
+
+    auto second_shape = _tensor_reg->getClTensor(second_index)->get_info()._shape;
+
+    tflite::gpu::GPUOperation operation = CreateElementwiseTwoInput(op_def, op_type, second_shape);
+    gpu_op = std::make_unique<tflite::gpu::GPUOperation>(std::move(operation));
+
+    addClNode({first_index, second_index}, {ofm_index}, std::move(gpu_op));
+  }
+  else
+  {
+    auto non_const_index = rhs_const ? lhs_index : rhs_index;
+    auto const_index = rhs_const ? rhs_index : lhs_index;
+
+    op_def.dst_tensors.push_back(_tensor_reg->getClTensor(ofm_index)->get_info()._desc);
+    op_def.src_tensors.push_back(_tensor_reg->getClTensor(non_const_index)->get_info()._desc);
+
+    tflite::gpu::ElementwiseAttributes attr;
+
+    if (!readConstTensor(const_index, &attr.param).ok())
+    {
+      throw std::runtime_error("BinaryArithmetic unsupported constant tensor");
+    }
+
+    tflite::gpu::GPUOperation operation =
+      CreateElementwise(_creation_context->GetGpuInfo(), op_def, op_type, attr);
+    gpu_op = absl::make_unique<tflite::gpu::GPUOperation>(std::move(operation));
+
+    addClNode({non_const_index}, {ofm_index}, std::move(gpu_op));
+  }
+  _return_fn = std::move(fn);
+}
+
+void KernelGenerator::visit(const ir::operation::Conv2D &node)
+{
+  auto output{node.getOutputs().at(0)};
+
+  auto input{node.getInputs().at(ir::operation::Conv2D::INPUT)};
+  auto kernel{node.getInputs().at(ir::operation::Conv2D::KERNEL)};
+  auto bias{node.getInputs().at(ir::operation::Conv2D::BIAS)};
+
+  const auto &param = node.param();
+
+  tflite::gpu::OperationDef op_def;
+  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
+
+  op_def.src_tensors.push_back(_tensor_reg->getClTensor(input)->get_info()._desc);
+
+  auto input_shape = _tensor_reg->getClTensor(input)->get_info()._shape;
+  auto kernel_shape = _tensor_reg->getClTensor(kernel)->get_info()._shape;
+  auto output_shape = _tensor_reg->getClTensor(output)->get_info()._shape;
+  auto bias_shape = _tensor_reg->getClTensor(bias)->get_info()._shape;
+
+  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(output)->get_info()._desc);
+
+  tflite::gpu::ModelHints hints;
+  std::unique_ptr<tflite::gpu::GPUOperation>
+    gpu_op; // = InitSingleOpSubgraph(inputs, outputs, gpu_subgraph);
+
+  auto kernel_tensor = _tensor_reg->getClTensor(kernel);
+  auto bias_tensor = _tensor_reg->getClTensor(bias);
+
+  tflite::gpu::Convolution2DAttributes attr;
+  attr.strides = ToHW(param.stride.vertical, param.stride.horizontal);
+  attr.dilations =
+    tflite::gpu::HW(std::max(static_cast<u_int32_t>(1), param.dilation.height_factor),
+                    std::max(static_cast<u_int32_t>(1), param.dilation.width_factor));
+
+  bool is_weight = (_ctx.at(kernel).isConstant() ? true : false);
+
+  if (is_weight)
+  {
+    attr.weights.id = kernel.value();
+    attr.weights.shape.o = kernel_shape.b;
+    attr.weights.shape.h = kernel_shape.h;
+    attr.weights.shape.w = kernel_shape.w;
+    attr.weights.shape.i = kernel_shape.c;
+    attr.weights.data.resize(kernel_shape.DimensionsProduct());
+    memcpy(attr.weights.data.data(), _ctx.at(kernel).data()->base(), kernel_tensor->total_size());
+  }
+
+  attr.bias.id = bias.value();
+  // TODO Modify
+  attr.bias.shape.v = bias_shape.b != 1 ? bias_shape.b : bias_shape.c;
+  attr.bias.data.resize(bias_shape.DimensionsProduct());
+  memcpy(attr.bias.data.data(), _ctx.at(bias).data()->base(), bias_tensor->total_size());
+
+  UpdatePadding(param.padding.type, input_shape, &attr);
+
+  gpu_op = SelectConvolution(attr, output_shape, _creation_context->GetGpuInfo(), op_def, hints);
+
+  tflite::gpu::cl::CLNode cl_node;
+  cl_node.inputs.resize(1);
+  cl_node.inputs[0] = input.value();
+  cl_node.outputs.resize(1);
+
+  auto fn = std::make_unique<ClFunction>(_creation_context);
+
+  const auto activation = node.param().activation;
+
+  switch (activation)
+  {
+    case ir::Activation::NONE:
+    {
+      addClNode({input}, {output}, std::move(gpu_op));
+      break;
+    }
+    case ir::Activation::RELU:
+    case ir::Activation::RELU6:
+    {
+      std::unique_ptr<tflite::gpu::GPUOperation> gpu_op_1;
+      tflite::gpu::OperationDef op_def_1;
+      const auto &shape = _ctx.at(output).shape();
+      auto new_ind = _tensor_reg->addNewClTensor(shape);
+
+      addClNode({input}, {new_ind}, std::move(gpu_op));
+
+      op_def_1.precision = tflite::gpu::CalculationsPrecision::F32;
+      op_def_1.src_tensors.push_back(_tensor_reg->getClTensor(output)->get_info()._desc);
+      op_def_1.dst_tensors.push_back(_tensor_reg->getClTensor(output)->get_info()._desc);
+
+      tflite::gpu::ReLUAttributes attr_1;
+      if (activation == ir::Activation::RELU6)
+      {
+        attr_1.clip = 6;
+      }
+      else
+      {
+        attr_1.clip = 0;
+      }
+      attr_1.alpha = 0;
+      gpu_op_1 = SelectReLU(attr_1, op_def_1);
+
+      addClNode({new_ind}, {output}, std::move(gpu_op_1));
+      break;
+    }
+    default:
+    {
+      throw std::runtime_error("gpu_cl KernelGenerator : Not supported Conv2D activiation");
+    }
+  }
+  _return_fn = std::move(fn);
+}
+
+void KernelGenerator::visit(const ir::operation::DepthwiseConv2D &node)
+{
+  using ir::operation::DepthwiseConv2D;
+
+  const auto ofm_index{node.getOutputs().at(0)};
+  const auto ifm_index{node.getInputs().at(DepthwiseConv2D::Input::INPUT)};
+  const auto ker_index{node.getInputs().at(DepthwiseConv2D::Input::KERNEL)};
+  const auto bias_index{node.getInputs().at(DepthwiseConv2D::Input::BIAS)};
+
+  const auto stride = node.param().stride;
+  const auto dilation = node.param().dilation;
+  const auto &padding = node.param().padding;
+
+  const auto multiplier = node.param().multiplier;
+
+  bool is_weight = (_ctx.at(ker_index).isConstant() ? true : false);
+  tflite::gpu::OperationDef op_def;
+  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
+
+  op_def.src_tensors.push_back(_tensor_reg->getClTensor(ifm_index)->get_info()._desc);
+  auto input_shape = _tensor_reg->getClTensor(ifm_index)->get_info()._shape;
+
+  auto ker_shape = _tensor_reg->getClTensor(ker_index)->get_info()._shape;
+
+  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(ofm_index)->get_info()._desc);
+  auto out_shape = _tensor_reg->getClTensor(ofm_index)->get_info()._shape;
+  auto bias_shape = _tensor_reg->getClTensor(bias_index)->get_info()._shape;
+
+  tflite::gpu::DepthwiseConvolution2DAttributes attr;
+  attr.strides = ToHW(stride.vertical, stride.horizontal);
+  attr.dilations = tflite::gpu::HW(std::max(static_cast<u_int32_t>(1), dilation.height_factor),
+                                   std::max(static_cast<u_int32_t>(1), dilation.width_factor));
+
+  if (is_weight)
+  {
+    attr.weights.id = ker_index.value();
+    attr.weights.shape.o = ker_shape.b;
+    attr.weights.shape.h = ker_shape.h;
+    attr.weights.shape.w = ker_shape.w;
+    attr.weights.shape.i = ker_shape.c;
+    attr.weights.data.resize(ker_shape.DimensionsProduct());
+    memcpy(attr.weights.data.data(), _ctx.at(ker_index).data()->base(),
+           _ctx.at(ker_index).operandSize());
+  }
+  attr.bias.id = bias_index.value();
+  attr.bias.shape.v = bias_shape.b != 1 ? bias_shape.b : bias_shape.c;
+  attr.bias.data.resize(bias_shape.DimensionsProduct());
+  memcpy(attr.bias.data.data(), _ctx.at(bias_index).data()->base(),
+         _ctx.at(bias_index).operandSize());
+  UpdatePadding(padding.type, input_shape, &attr);
+
+  if (multiplier != 1)
+  {
+    const int input_depth = input_shape.c;
+    const int filter_height = ker_shape.h;
+    const int filter_width = ker_shape.w;
+    const int output_depth = out_shape.c;
+
+    tflite::gpu::Tensor<tflite::gpu::OHWI, tflite::gpu::DataType::FLOAT32> weights;
+    weights.id = attr.weights.id;
+    weights.shape = tflite::gpu::OHWI(output_depth, filter_height, filter_width, input_depth);
+    weights.data.resize(weights.shape.DimensionsProduct());
+    float *dst = &weights.data[0];
+    for (int j = 0; j < output_depth; ++j)
+    {
+      const float *src = attr.weights.data.data() + j;
+      for (int i = 0; i < filter_height * filter_width; ++i)
+      {
+        *dst = *src;
+        dst++;
+        src += output_depth;
+      }
+    }
+    attr.weights = std::move(weights);
+  }
+
+  auto fn = std::make_unique<ClFunction>(_creation_context);
+  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
+
+  if (is_weight)
+  {
+    gpu_op = SelectDWConvolution(attr, _creation_context->GetGpuInfo(), op_def);
+  }
+  else
+  {
+    if (ker_shape.b != 1)
+    {
+      throw std::runtime_error(
+        "No support of depthwise runtime weights with channel multiplier != 1");
+    }
+    gpu_op = SelectDWConvolutionDynamicWeights(attr, _creation_context->GetGpuInfo(), op_def);
+  }
+
+  const auto activation = node.param().activation;
+
+  switch (activation)
+  {
+    case ir::Activation::NONE:
+    {
+      addClNode({ifm_index}, {ofm_index}, std::move(gpu_op));
+      break;
+    }
+    case ir::Activation::RELU:
+    case ir::Activation::RELU6:
+    {
+      std::unique_ptr<tflite::gpu::GPUOperation> gpu_op_1;
+      tflite::gpu::OperationDef op_def_1;
+      const auto &shape = _ctx.at(ofm_index).shape();
+      auto new_ind = _tensor_reg->addNewClTensor(shape);
+
+      addClNode({ifm_index}, {new_ind}, std::move(gpu_op));
+
+      op_def_1.precision = tflite::gpu::CalculationsPrecision::F32;
+
+      op_def_1.src_tensors.push_back(_tensor_reg->getClTensor(ofm_index)->get_info()._desc);
+      op_def_1.dst_tensors.push_back(_tensor_reg->getClTensor(ofm_index)->get_info()._desc);
+
+      tflite::gpu::ReLUAttributes attr_1;
+      if (activation == ir::Activation::RELU6)
+      {
+        attr_1.clip = 6;
+      }
+      else
+      {
+        attr_1.clip = 0;
+      }
+      attr_1.alpha = 0;
+      gpu_op_1 = SelectReLU(attr_1, op_def_1);
+
+      addClNode({new_ind}, {ofm_index}, std::move(gpu_op_1));
+      break;
+    }
+    default:
+    {
+      throw std::runtime_error("gpu_cl KernelGenerator : Not supported DepthwiseConv2D acvivation");
+    }
+  }
+
+  _return_fn = std::move(fn);
+}
+
+void KernelGenerator::visit(const ir::operation::ElementwiseActivation &node)
+{
+  const auto output_index{node.getOutputs().at(0)};
+  const auto input_index{node.getInputs().at(ir::operation::ElementwiseActivation::Input::INPUT)};
+
+  tflite::gpu::OperationDef op_def;
+  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
+
+  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(output_index)->get_info()._desc);
+  op_def.src_tensors.push_back(_tensor_reg->getClTensor(input_index)->get_info()._desc);
+
+  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
+  auto fn = std::make_unique<ClFunction>(_creation_context);
+  switch (node.param().op_type)
+  {
+    case ir::operation::ElementwiseActivation::Type::LEAKY_RELU:
+    case ir::operation::ElementwiseActivation::Type::RELU:
+    {
+      tflite::gpu::ReLUAttributes attr;
+      if (ir::operation::ElementwiseActivation::Type::LEAKY_RELU == node.param().op_type)
+      {
+        attr.alpha = node.param().alpha;
+        attr.clip = 0;
+      }
+      else
+      {
+        attr.alpha = node.param().beta;
+        attr.clip = node.param().alpha;
+      }
+      gpu_op = SelectReLU(attr, op_def);
+      break;
+    }
+    case ir::operation::ElementwiseActivation::Type::LOGISTIC:
+    {
+      if (_ctx.at(input_index).typeInfo().type() != ir::DataType::FLOAT32)
+      {
+        throw std::runtime_error{"Unsupported data type of LOGISTIC"};
+      }
+      tflite::gpu::GPUOperation operation =
+        CreateElementwiseOneInput(_creation_context->GetGpuInfo(), op_def,
+                                  convertElementwiseActivationType(node.param().op_type));
+      gpu_op = std::make_unique<tflite::gpu::GPUOperation>(std::move(operation));
+      break;
+    }
+    case ir::operation::ElementwiseActivation::Type::TANH:
+    {
+      tflite::gpu::GPUOperation operation = CreateElementwiseOneInput(
+        _creation_context->GetGpuInfo(), op_def, tflite::gpu::OperationType::TANH);
+      gpu_op = std::make_unique<tflite::gpu::GPUOperation>(std::move(operation));
+      break;
+    }
+    default:
+      throw std::runtime_error(
+        "gpu_cl KernelGenerator : Not supported operation on ElementwiseActivation");
+  }
+  addClNode({input_index}, {output_index}, std::move(gpu_op));
+  _return_fn = std::move(fn);
+}
+
+void KernelGenerator::visit(const ir::operation::Pool2D &node)
+{
+  const auto output_index{node.getOutputs().at(0)};
+  const auto input_index{node.getInputs().at(ir::operation::Pool2D::Input::INPUT)};
+
+  tflite::gpu::OperationDef op_def;
+  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
+
+  op_def.src_tensors.push_back(_tensor_reg->getClTensor(input_index)->get_info()._desc);
+  auto input_shape = _tensor_reg->getClTensor(input_index)->get_info()._shape;
+
+  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(output_index)->get_info()._desc);
+
+  const auto kh = node.param().kh;
+  const auto kw = node.param().kw;
+  const auto stride = node.param().stride;
+  const auto op_type = convertPoolType(node.param().op_type);
+
+  tflite::gpu::Pooling2DAttributes attributes;
+  attributes.type = op_type;
+  attributes.kernel = tflite::gpu::HW(kh > 0 ? kh : 1, kw > 0 ? kw : 1);
+  attributes.strides = tflite::gpu::HW(stride.vertical > 0 ? stride.vertical : 1,
+                                       stride.horizontal > 0 ? stride.horizontal : 1);
+
+  if (node.param().padding.type == ir::PaddingType::SAME)
+  {
+    attributes.padding = CalculateSamePadding(input_shape, attributes);
+  }
+  else
+  {
+    attributes.padding.prepended = tflite::gpu::HW(0, 0);
+    attributes.padding.appended = tflite::gpu::HW(0, 0);
+  }
+
+  auto fn = std::make_unique<ClFunction>(_creation_context);
+  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
+  gpu_op = SelectPooling(attributes, op_def);
+
+  addClNode({input_index}, {output_index}, std::move(gpu_op));
+  _return_fn = std::move(fn);
+}
+
+void KernelGenerator::visit(const ir::operation::Reshape &node)
+{
+  const auto output_index{node.getOutputs().at(0)};
+  const auto input_index{node.getInputs().at(ir::operation::Reshape::Input::INPUT)};
+
+  tflite::gpu::OperationDef op_def;
+  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
+
+  op_def.src_tensors.push_back(_tensor_reg->getClTensor(input_index)->get_info()._desc);
+  auto input_shape = _tensor_reg->getClTensor(input_index)->get_info()._shape;
+
+  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(output_index)->get_info()._desc);
+  auto output_shape = _tensor_reg->getClTensor(output_index)->get_info()._shape;
+
+  tflite::gpu::ReshapeAttributes attr;
+  attr.new_shape = output_shape;
+
+  auto fn = std::make_unique<ClFunction>(_creation_context);
+  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
+  const int src_channels = input_shape.c;
+  SelectReshape(src_channels, attr.new_shape.c, op_def, &gpu_op);
+
+  addClNode({input_index}, {output_index}, std::move(gpu_op));
+  _return_fn = std::move(fn);
+}
+
+void KernelGenerator::visit(const ir::operation::Softmax &node)
+{
+  const auto output_index{node.getOutputs().at(0)};
+  const auto input_index{node.getInputs().at(ir::operation::Softmax::Input::INPUT)};
+
+  const auto beta = node.param().beta;
+
+  if (beta != 1.0)
+  {
+    throw std::runtime_error("Softmax.beta != 1 is not supported in gpu_cl");
+  }
+
+  tflite::gpu::OperationDef op_def;
+  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
+
+  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(output_index)->get_info()._desc);
+
+  op_def.src_tensors.push_back(_tensor_reg->getClTensor(input_index)->get_info()._desc);
+  auto input_shape = _tensor_reg->getClTensor(input_index)->get_info()._shape;
+
+  auto fn = std::make_unique<ClFunction>(_creation_context);
+
+  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
+  SelectSoftmax(input_shape, op_def, &gpu_op);
+
+  addClNode({input_index}, {output_index}, std::move(gpu_op));
+  _return_fn = std::move(fn);
+}
+
+} // namespace gpu_cl
+} // namespace backend
+} // namespace onert
diff --git a/runtime/contrib/gpu_cl/operand/ICLTensor.cc b/runtime/contrib/gpu_cl/operand/ICLTensor.cc
new file mode 100644 (file)
index 0000000..1e61b99
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * 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 "ICLTensor.h"
+
+#include "tensorflow/lite/delegates/gpu/api.h"
+#include "tensorflow/lite/delegates/gpu/spi.h"
+#include "tensorflow/lite/delegates/gpu/cl/opencl_wrapper.h"
+#include "tensorflow/lite/delegates/gpu/cl/tensor_type_util.h"
+#include "tensorflow/lite/delegates/gpu/cl/kernels/converter.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace gpu_cl
+{
+namespace operand
+{
+
+using namespace tflite::gpu;
+using namespace tflite::gpu::cl;
+using namespace tflite::gpu::internal_tensor;
+
+void ICLTensor::access(const std::function<void(ITensor &tensor)> &fn)
+{
+  if (total_size() == 0)
+    return;
+
+  fn(*this);
+}
+
+void ICLTensor::writeConvertInit(tflite::gpu::TensorObjectConverterBuilder *converter_builder,
+                                 std::shared_ptr<tflite::gpu::cl::Environment> environment)
+{
+  _environment = environment;
+  TensorObjectDef input_def;
+  input_def.dimensions.b = handle()->Batch();
+  input_def.dimensions.h = handle()->Height();
+  input_def.dimensions.w = handle()->Width();
+  input_def.dimensions.c = handle()->Channels();
+  input_def.object_def.data_layout = DataLayout::BHWC;
+  input_def.object_def.data_type = DataType::FLOAT32;
+  input_def.object_def.object_type = ObjectType::CPU_MEMORY;
+  input_def.object_def.user_provided = true;
+
+  TensorObjectDef permute_def = input_def;
+  permute_def.object_def.object_type = ToObjectType(handle()->GetStorageType());
+
+  const auto &dims = permute_def.dimensions;
+  const BHWC shape(dims.b, dims.h, dims.w, dims.c);
+  const TensorDescriptor desc{
+    permute_def.object_def.data_type,
+    ToTensorStorageType(permute_def.object_def.object_type, permute_def.object_def.data_layout),
+    Layout::BHWC};
+  if (!AllocateTensorMemory(_environment->context(), shape, desc, &_cl_memory).ok())
+  {
+    throw std::runtime_error("Failed to AllocateTensorMemory");
+  }
+
+  TensorObjectDef output_def = permute_def;
+  output_def.object_def.data_layout = ToDataLayout(handle()->GetStorageType());
+  output_def.object_def.data_type = handle()->GetDataType();
+  input_def.object_def.user_provided = false;
+
+  if (!converter_builder->MakeConverter(input_def, permute_def, &_converter_to).ok())
+  {
+    throw std::runtime_error("Failed to make converter_to");
+  }
+  if (!converter_builder->MakeConverter(permute_def, output_def, &_converter_from).ok())
+  {
+    throw std::runtime_error("Failed to make converter_from");
+  }
+}
+
+void ICLTensor::readConvertInit(tflite::gpu::TensorObjectConverterBuilder *converter_builder,
+                                std::shared_ptr<tflite::gpu::cl::Environment> environment)
+{
+  _environment = environment;
+  TensorObjectDef input_def;
+  input_def.dimensions.b = handle()->Batch();
+  input_def.dimensions.h = handle()->Height();
+  input_def.dimensions.w = handle()->Width();
+  input_def.dimensions.c = handle()->Channels();
+  input_def.object_def.data_layout = ToDataLayout(handle()->GetStorageType());
+  input_def.object_def.data_type = handle()->GetDataType();
+  input_def.object_def.object_type = ToObjectType(handle()->GetStorageType());
+  input_def.object_def.user_provided = false;
+
+  TensorObjectDef permute_def = input_def;
+  permute_def.object_def.data_layout = DataLayout::BHWC;
+  permute_def.object_def.data_type = DataType::FLOAT32;
+  permute_def.object_def.user_provided = true;
+
+  const auto &dims = permute_def.dimensions;
+  const BHWC shape(dims.b, dims.h, dims.w, dims.c);
+  const TensorDescriptor desc{
+    permute_def.object_def.data_type,
+    ToTensorStorageType(permute_def.object_def.object_type, permute_def.object_def.data_layout),
+    Layout::BHWC};
+  if (!AllocateTensorMemory(_environment->context(), shape, desc, &_cl_memory).ok())
+  {
+    throw std::runtime_error("Failed to AllocateTensorMemory");
+  }
+
+  TensorObjectDef output_def = permute_def;
+  output_def.object_def.object_type = ObjectType::CPU_MEMORY;
+
+  if (!converter_builder->MakeConverter(input_def, permute_def, &_converter_from).ok())
+  {
+    throw std::runtime_error("Failed to make converter_from");
+  }
+  if (!converter_builder->MakeConverter(permute_def, output_def, &_converter_to).ok())
+  {
+    throw std::runtime_error("Failed to make converter_to");
+  }
+}
+
+void ICLTensor::enqueueWriteBuffer(const void *ptr, bool blocking)
+{
+  TensorObject input_obj = MakeReadableCpuMemory(
+    absl::MakeSpan(static_cast<const float *>(ptr), _info._shape.DimensionsProduct()));
+
+  TensorObject output_obj;
+
+  TensorObject permute_obj;
+  if (ToObjectType(handle()->GetStorageType()) == ObjectType::OPENCL_TEXTURE)
+  {
+    permute_obj = OpenClTexture{_cl_memory.memory()};
+  }
+  else
+  {
+    permute_obj = OpenClBuffer{_cl_memory.memory()};
+  }
+
+  if (handle()->GetStorageType() == TensorStorageType::BUFFER)
+  {
+    output_obj = OpenClBuffer{handle()->GetMemoryPtr()};
+  }
+  else if (handle()->GetStorageType() == TensorStorageType::IMAGE_BUFFER)
+  {
+    output_obj = OpenClBuffer{handle()->GetMemoryPtrForWriting()};
+  }
+  else
+  {
+    output_obj = OpenClTexture{handle()->GetMemoryPtr()};
+  }
+
+  if (!_converter_to->Convert(input_obj, permute_obj).ok())
+  {
+    throw std::runtime_error("Failed to write cl buffer from cpu memory");
+  }
+
+  if (blocking && !_environment->queue()->WaitForCompletion().ok())
+  {
+    throw std::runtime_error("Failed to WaitForCompletion");
+  }
+
+  if (!_converter_from->Convert(permute_obj, output_obj).ok())
+  {
+    throw std::runtime_error("Failed to change layout");
+  }
+}
+
+void ICLTensor::enqueueReadBuffer(void *ptr, bool blocking)
+{
+  TensorObject input_obj;
+
+  if (handle()->GetStorageType() == TensorStorageType::BUFFER)
+  {
+    input_obj = OpenClBuffer{handle()->GetMemoryPtr()};
+  }
+  else if (handle()->GetStorageType() == TensorStorageType::IMAGE_BUFFER)
+  {
+    input_obj = OpenClBuffer{handle()->GetMemoryPtrForWriting()};
+  }
+  else
+  {
+    input_obj = OpenClTexture{handle()->GetMemoryPtr()};
+  }
+
+  TensorObject permute_obj;
+  if (ToObjectType(handle()->GetStorageType()) == ObjectType::OPENCL_TEXTURE)
+  {
+    permute_obj = OpenClTexture{_cl_memory.memory()};
+  }
+  else
+  {
+    permute_obj = OpenClBuffer{_cl_memory.memory()};
+  }
+
+  TensorObject output_obj =
+    MakeCpuMemory(absl::MakeSpan(static_cast<float *>(ptr), _info._shape.DimensionsProduct()));
+
+  if (!_converter_from->Convert(input_obj, permute_obj).ok())
+  {
+    throw std::runtime_error("Failed to change layout");
+  }
+  if (!_converter_to->Convert(permute_obj, output_obj).ok())
+  {
+    throw std::runtime_error("Failed to read cl buffer");
+  }
+
+  if (blocking && !_environment->queue()->WaitForCompletion().ok())
+  {
+    throw std::runtime_error("Failed to WaitForCompletion");
+  }
+}
+
+} // namespace operand
+} // namespace gpu_cl
+} // namespace backend
+} // namespace onert
index e6738f0..97503cd 100644 (file)
@@ -4,9 +4,6 @@ endif(NOT BUILD_LOGGING)
 
 file(GLOB_RECURSE NNAPI_LOGGING_SRCS "src/*.cc")
 
-nnfw_find_package(Boost REQUIRED)
-
 add_library(neuralnetworks SHARED ${NNAPI_LOGGING_SRCS})
 target_include_directories(neuralnetworks PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
-target_include_directories(neuralnetworks PRIVATE ${Boost_INCLUDE_DIRS})
 target_link_libraries(neuralnetworks PUBLIC nnfw-nnapi-header)
index 370e72a..781a033 100644 (file)
@@ -25,8 +25,6 @@
 
 #include <cassert>
 
-#include <boost/format.hpp>
-
 namespace
 {
 
@@ -72,7 +70,7 @@ std::string OperationCodeResolver::resolve(int code) const
 
   if (it == _table.end())
   {
-    return boost::str(boost::format("unknown(%d)") % code);
+    return "unknown(" + std::to_string(code) + ")";
   }
 
   return it->second;
@@ -120,7 +118,7 @@ std::string OperandCodeResolver::resolve(int code) const
 
   if (it == _table.end())
   {
-    return boost::str(boost::format("unknown(%d)") % code);
+    return "unknown(" + std::to_string(code) + ")";
   }
 
   return it->second;
index 06e8df3..ac60dec 100644 (file)
@@ -5,7 +5,7 @@ file(GLOB_RECURSE SOURCES "*.cc")
 add_executable(mlapse-tfl ${SOURCES})
 target_include_directories(mlapse-tfl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
 target_link_libraries(mlapse-tfl nnfw_lib_tflite)
-target_link_libraries(mlapse-tfl nnfw_lib_misc)
+target_link_libraries(mlapse-tfl nnfw_lib_benchmark)
 target_link_libraries(mlapse-tfl tensorflow-lite)
 
 install(TARGETS mlapse-tfl DESTINATION bin)
index f5fc730..336f0a3 100644 (file)
 
 #include "mlapse/benchmark_runner.h"
 
-// From 'nnfw_lib_misc'
-#include <misc/benchmark.h>
+// From 'nnfw_lib_benchmark'
+#include <benchmark/Accumulator.h>
 
 // From C++ Standard Library
 #include <cassert>
+#include <stdexcept>
 
 namespace mlapse
 {
@@ -61,7 +62,7 @@ void BenchmarkRunner::run(nnfw::tflite::Session *sess) const
         notify(arg);
       };
 
-      nnfw::misc::benchmark::measure(elapsed) << [&](void) {
+      benchmark::measure(elapsed) << [&](void) {
         if (!sess->run())
         {
           throw std::runtime_error{"run failed"};
index 9ffbeae..850b9cb 100644 (file)
@@ -6,6 +6,10 @@ if(NOT BUILD_ONERT)
   return()
 endif(NOT BUILD_ONERT)
 
+# Use C++17 for style_transfer_app
+# TODO Remove this when we use C++17 for all runtime directories
+set(CMAKE_CXX_STANDARD 17)
+
 find_package(JPEG)
 if(JPEG_FOUND)
   add_definitions(-DNNFW_ST_APP_JPEG_SUPPORTED)
@@ -20,7 +24,7 @@ if(JPEG_FOUND)
   list(APPEND STYLE_TRANSFER_APP_SRCS "src/jpeg_helper.cc")
 endif(JPEG_FOUND)
 
-nnfw_find_package(Boost REQUIRED program_options system filesystem)
+nnfw_find_package(Boost REQUIRED program_options)
 
 add_executable(style_transfer_app ${STYLE_TRANSFER_APP_SRCS})
 target_include_directories(style_transfer_app PRIVATE src)
@@ -29,10 +33,9 @@ if(JPEG_FOUND)
   target_include_directories(style_transfer_app PRIVATE ${JPEG_INCLUDE_DIRS})
 endif(JPEG_FOUND)
 
-target_link_libraries(style_transfer_app onert_core onert tflite_loader)
-target_link_libraries(style_transfer_app tensorflow-lite ${LIB_PTHREAD} dl nnfw_lib_tflite)
+target_link_libraries(style_transfer_app ${LIB_PTHREAD} dl)
 target_link_libraries(style_transfer_app nnfw-dev)
-target_link_libraries(tflite_comparator ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY})
+target_link_libraries(style_transfer_app ${Boost_PROGRAM_OPTIONS_LIBRARY})
 if(JPEG_FOUND)
   target_link_libraries(style_transfer_app ${JPEG_LIBRARIES})
 endif(JPEG_FOUND)
index e194b82..f17373f 100644 (file)
@@ -17,7 +17,7 @@
 #include "args.h"
 
 #include <iostream>
-#include <boost/filesystem.hpp>
+#include <filesystem>
 
 namespace StyleTransferApp
 {
@@ -80,7 +80,7 @@ void Args::Parse(const int argc, char **argv)
     {
       _package_filename = vm["nnpackage"].as<std::string>();
 
-      if (!boost::filesystem::exists(_package_filename))
+      if (!std::filesystem::exists(_package_filename))
       {
         std::cerr << "nnpackage not found: " << _package_filename << "\n";
       }
index 1554524..3e21b7a 100644 (file)
@@ -43,7 +43,7 @@ int JpegHelper::readJpeg(const std::string filename, std::vector<float> &raw_ima
 
   if (!infile)
   {
-    printf("Error opening jpeg file %s\n!", filename);
+    printf("Error opening jpeg file %s\n!", filename.c_str());
     return -1;
   }
 
@@ -61,6 +61,13 @@ int JpegHelper::readJpeg(const std::string filename, std::vector<float> &raw_ima
   assert(cinfo.output_width == width);
   assert(cinfo.output_height == height);
 
+  // Size limitation: 16 x 1024 x 1024
+  if (cinfo.output_width * cinfo.output_height * cinfo.num_components > 16 * 1024 * 1024)
+  {
+    printf("Image size is too large\n");
+    return -1;
+  }
+
   raw_image.resize(cinfo.output_width * cinfo.output_height * cinfo.num_components);
 
   unsigned char *ptr = new unsigned char[cinfo.output_width * cinfo.num_components];
@@ -93,7 +100,7 @@ int JpegHelper::writeJpeg(const std::string filename, std::vector<float> &raw_im
 
   if (!outfile)
   {
-    printf("Error opening output jpeg file %s\n!", filename);
+    printf("Error opening output jpeg file %s\n!", filename.c_str());
     return -1;
   }
   cinfo.err = jpeg_std_error(&jerr);
index c0bf627..5f3dc10 100644 (file)
@@ -2,13 +2,16 @@ if(NOT BUILD_TFLITE_CLASSIFY_APP)
   return()
 endif(NOT BUILD_TFLITE_CLASSIFY_APP)
 
+# Use C++17 for tflite_classify
+# TODO Remove this when we use C++17 for all runtime directories
+set(CMAKE_CXX_STANDARD 17)
+
 list(APPEND SOURCES "src/tflite_classify.cc")
 list(APPEND SOURCES "src/ImageClassifier.cc")
 list(APPEND SOURCES "src/InferenceInterface.cc")
 
 ## Required package
 find_package(OpenCV REQUIRED)
-find_package(Boost REQUIRED COMPONENTS system filesystem)
 
 # Without this line, this appliation couldn't search the opencv library that were already installed in ${ROOTFS_DIR}/usr/lib/arm-linux-gnueabihf directory
 set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${ROOTFS_DIR}/usr/lib/arm-linux-gnueabihf -Wl,--rpath=${ROOTFS_DIR}/lib/arm-linux-gnueabihf")
@@ -16,7 +19,6 @@ set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${ROOTFS_DIR}/usr/lib/ar
 add_executable(tflite_classify ${SOURCES})
 target_include_directories(tflite_classify PRIVATE src)
 target_link_libraries(tflite_classify tensorflow-lite ${LIB_PTHREAD} dl nnfw_lib_tflite)
-target_link_libraries(tflite_classify ${Boost_LIBRARIES})
 target_link_libraries(tflite_classify ${OpenCV_LIBRARIES})
 
 install(TARGETS tflite_classify DESTINATION bin)
index 7bed778..1d9feb3 100644 (file)
 #include "ImageClassifier.h"
 
 #include <iostream>
+#include <filesystem>
 
-#include <boost/filesystem.hpp>
 #include <opencv2/opencv.hpp>
 
-namespace fs = boost::filesystem;
+namespace fs = std::filesystem;
 
 int main(const int argc, char **argv)
 {
diff --git a/runtime/libs/benchmark/CMakeLists.txt b/runtime/libs/benchmark/CMakeLists.txt
deleted file mode 100644 (file)
index 748b2d1..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-file(GLOB_RECURSE SOURCES "src/*.cpp")
-
-add_library(nnfw_lib_benchmark STATIC ${SOURCES})
-target_include_directories(nnfw_lib_benchmark PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
-target_link_libraries(nnfw_lib_benchmark PRIVATE ${LIB_PTHREAD})
diff --git a/runtime/libs/benchmark/src/Result.cpp b/runtime/libs/benchmark/src/Result.cpp
deleted file mode 100644 (file)
index 04925f4..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * 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 "benchmark/Result.h"
-#include "benchmark/Phases.h"
-#include "benchmark/CsvWriter.h"
-
-#include <string>
-#include <numeric>
-#include <algorithm>
-#include <cassert>
-#include <cmath>
-#include <iostream>
-#include <iomanip>
-
-namespace
-{
-
-template <class T, class R> R average(const std::vector<T> &v)
-{
-  T sum = std::accumulate(v.begin(), v.end(), 0);
-  R avg = sum / static_cast<R>(v.size());
-  return avg;
-}
-
-double averageTimeMs(const benchmark::Phase &phase)
-{
-  double avg_us = average<uint64_t, double>(phase.time);
-  return avg_us / 1e3;
-}
-
-double maxTimeMs(const benchmark::Phase &phase)
-{
-  auto it = max_element(std::begin(phase.time), std::end(phase.time));
-  return *it / 1e3;
-}
-
-double minTimeMs(const benchmark::Phase &phase)
-{
-  auto it = min_element(std::begin(phase.time), std::end(phase.time));
-  return *it / 1e3;
-}
-
-double geomeanTimeMs(const benchmark::Phase &phase)
-{
-  double log_sum = 0.0;
-  for (auto &&t_us : phase.time)
-  {
-    log_sum += std::log(t_us / 1e3);
-  }
-
-  // Calculating geometric mean with logs
-  //   "Geometric Mean of (V1, V2, ... Vn)"
-  // = (V1*V2*...*Vn)^(1/n)
-  // = exp(log((V1*V2*...*Vn)^(1/n)))
-  // = exp(log((V1*V2*...*Vn)/n)))
-  // = exp((log(V1) + log(V2) + ... + log(Vn))/n)
-  // = exp(_log_sum/num)
-  return std::exp(log_sum / static_cast<double>(phase.time.size()));
-}
-
-uint32_t averageMemoryKb(const benchmark::Phase &phase, int type)
-{
-  return average<uint32_t, uint32_t>(phase.memory[type]);
-}
-
-uint32_t peakMemory(
-  const uint32_t memory[benchmark::PhaseEnum::END_OF_PHASE][benchmark::MemoryType::END_OF_MEM_TYPE],
-  int type)
-{
-  using namespace benchmark;
-  // tricky. handle WARMUP as EXECUTE
-  return std::max({memory[PhaseEnum::MODEL_LOAD][type], memory[PhaseEnum::PREPARE][type],
-                   memory[PhaseEnum::WARMUP][type]});
-}
-
-void printResultTime(
-  const double time[benchmark::PhaseEnum::END_OF_PHASE][benchmark::FigureType::END_OF_FIG_TYPE])
-{
-  using namespace benchmark;
-
-  std::cout << "===================================" << std::endl;
-
-  std::streamsize ss_precision = std::cout.precision();
-  std::cout << std::setprecision(3);
-  std::cout << std::fixed;
-
-  for (int i = PhaseEnum::MODEL_LOAD; i <= PhaseEnum::EXECUTE; ++i)
-  {
-    // Note. Tricky. Ignore WARMUP
-    if (i == PhaseEnum::WARMUP)
-      continue;
-    std::cout << std::setw(12) << std::left << getPhaseString(i) << " takes "
-              << time[i][FigureType::MEAN] << " ms" << std::endl;
-  }
-
-  for (int j = FigureType::MEAN; j <= FigureType::GEOMEAN; ++j)
-  {
-    std::cout << "- " << std::setw(9) << std::left << getFigureTypeString(j) << ":  "
-              << time[PhaseEnum::EXECUTE][j] << " ms" << std::endl;
-  }
-
-  std::cout << std::setprecision(ss_precision);
-  std::cout << std::defaultfloat;
-
-  std::cout << "===================================" << std::endl;
-}
-
-void printResultMemory(
-  const uint32_t memory[benchmark::PhaseEnum::END_OF_PHASE][benchmark::MemoryType::END_OF_MEM_TYPE])
-{
-  using namespace benchmark;
-
-  for (int j = MemoryType::RSS; j <= MemoryType::PSS; ++j)
-  {
-    std::cout << getMemoryTypeString(j) << std::endl;
-    for (int i = PhaseEnum::MODEL_LOAD; i <= PhaseEnum::PREPARE; ++i)
-    {
-      std::cout << "- " << std::setw(12) << std::left << getPhaseString(i) << " takes "
-                << memory[i][j] << " kb" << std::endl;
-    }
-    // Tricky. Handle WARMUP as EXECUTE
-    std::cout << "- " << std::setw(12) << std::left << getPhaseString(PhaseEnum::EXECUTE)
-              << " takes " << memory[PhaseEnum::WARMUP][j] << " kb" << std::endl;
-    std::cout << "- " << std::setw(12) << std::left << "PEAK"
-              << " takes " << peakMemory(memory, j) << " kb" << std::endl;
-    std::cout << "===================================" << std::endl;
-  }
-}
-
-void printUsedPeakMemory(uint32_t init_memory, uint32_t peak_memory)
-{
-  uint32_t used_peak_memory = peak_memory - init_memory;
-  std::cout << "Used Peak Memory : " << used_peak_memory << " kb" << std::endl;
-  std::cout << "- HWM after run  : " << peak_memory << " kb" << std::endl;
-  std::cout << "- HWM before init: " << init_memory << " kb" << std::endl;
-  std::cout << "===================================" << std::endl;
-}
-
-} // namespace
-
-namespace benchmark
-{
-
-Result::Result(const Phases &phases)
-{
-  const auto option = phases.option();
-  {
-    for (int i = PhaseEnum::MODEL_LOAD; i <= PhaseEnum::PREPARE; ++i)
-    {
-      auto phase = phases.at(gPhaseStrings[i]);
-      time[i][FigureType::MEAN] = averageTimeMs(phase);
-    }
-
-    int i = PhaseEnum::EXECUTE;
-    auto exec_phase = phases.at(gPhaseStrings[i]);
-    time[i][FigureType::MEAN] = averageTimeMs(exec_phase);
-    time[i][FigureType::MAX] = maxTimeMs(exec_phase);
-    time[i][FigureType::MIN] = minTimeMs(exec_phase);
-    time[i][FigureType::GEOMEAN] = geomeanTimeMs(exec_phase);
-  }
-  if (option.memory)
-  {
-    print_memory = true;
-    for (int i = PhaseEnum::MODEL_LOAD; i < PhaseEnum::EXECUTE; ++i)
-    {
-      auto phase = phases.at(gPhaseStrings[i]);
-      for (int j = MemoryType::RSS; j <= MemoryType::PSS; ++j)
-      {
-        memory[i][j] = averageMemoryKb(phase, j);
-      }
-    }
-  }
-  init_memory = phases.mem_before_init();
-  peak_memory = phases.mem_after_run();
-}
-
-void printResult(const Result &result)
-{
-  printResultTime(result.time);
-
-  if (result.print_memory == false)
-    return;
-
-  printResultMemory(result.memory);
-  printUsedPeakMemory(result.init_memory, result.peak_memory);
-}
-
-// TODO There are necessary for a kind of output data file so that it doesn't have to be csv file
-// format.
-void writeResult(const Result &result, const std::string &exec, const std::string &model,
-                 const std::string &backend)
-{
-  std::string csv_filename = exec + "-" + model + "-" + backend + ".csv";
-
-  // write to csv
-  CsvWriter writer(csv_filename);
-  writer << model << backend;
-
-  // TODO Add GEOMEAN
-  // time
-  auto time = result.time;
-  writer << time[PhaseEnum::MODEL_LOAD][FigureType::MEAN]
-         << time[PhaseEnum::PREPARE][FigureType::MEAN] << time[PhaseEnum::EXECUTE][FigureType::MIN]
-         << time[PhaseEnum::EXECUTE][FigureType::MAX] << time[PhaseEnum::EXECUTE][FigureType::MEAN];
-
-  // memory
-  auto memory = result.memory;
-  for (int j = MemoryType::RSS; j <= MemoryType::PSS; ++j)
-  {
-    // Tricky. Handle WARMUP as EXECUTE
-    for (int i = PhaseEnum::MODEL_LOAD; i <= PhaseEnum::WARMUP; ++i)
-    {
-      writer << memory[i][j];
-    }
-    writer << peakMemory(memory, j);
-  }
-
-  bool done = writer.done();
-
-  if (!done)
-  {
-    std::cerr << "Writing to " << csv_filename << " is failed" << std::endl;
-  }
-}
-
-} // namespace benchmark
diff --git a/runtime/libs/circle-schema/CMakeLists.txt b/runtime/libs/circle-schema/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5a2f679
--- /dev/null
@@ -0,0 +1,7 @@
+add_library(circle_schema INTERFACE)
+
+nnfw_find_package(FlatBuffers EXACT 23.5.26 REQUIRED)
+
+target_link_libraries(circle_schema INTERFACE flatbuffers::flatbuffers-23.5.26)
+
+target_include_directories(circle_schema INTERFACE include)
diff --git a/runtime/libs/circle-schema/include/circle_schema_generated.h b/runtime/libs/circle-schema/include/circle_schema_generated.h
new file mode 100644 (file)
index 0000000..3da596b
--- /dev/null
@@ -0,0 +1,34339 @@
+/*
+ * Copyright (c) 2019-2024 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.
+ */
+// command: flatc -c --gen-onefile --gen-object-api ../../../../nnpackage/schema/circle_schema.fbs
+// automatically generated by the FlatBuffers compiler, do not modify
+
+#ifndef FLATBUFFERS_GENERATED_CIRCLESCHEMA_CIRCLE_H_
+#define FLATBUFFERS_GENERATED_CIRCLESCHEMA_CIRCLE_H_
+
+#include "flatbuffers/flatbuffers.h"
+
+// Ensure the included flatbuffers.h is the same version as when this file was
+// generated, otherwise it may not be compatible.
+static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && FLATBUFFERS_VERSION_MINOR == 5 &&
+                FLATBUFFERS_VERSION_REVISION == 26,
+              "Non-compatible flatbuffers version included");
+
+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 VariantSubType;
+struct VariantSubTypeBuilder;
+struct VariantSubTypeT;
+
+struct Tensor;
+struct TensorBuilder;
+struct TensorT;
+
+struct StablehloGatherOptions;
+struct StablehloGatherOptionsBuilder;
+struct StablehloGatherOptionsT;
+
+struct StablehloTransposeOptions;
+struct StablehloTransposeOptionsBuilder;
+struct StablehloTransposeOptionsT;
+
+struct StablehloDotGeneralOptions;
+struct StablehloDotGeneralOptionsBuilder;
+struct StablehloDotGeneralOptionsT;
+
+struct StablehloReduceWindowOptions;
+struct StablehloReduceWindowOptionsBuilder;
+struct StablehloReduceWindowOptionsT;
+
+struct StablehloWhileOptions;
+struct StablehloWhileOptionsBuilder;
+struct StablehloWhileOptionsT;
+
+struct StablehloSortOptions;
+struct StablehloSortOptionsBuilder;
+struct StablehloSortOptionsT;
+
+struct StablehloConcatenateOptions;
+struct StablehloConcatenateOptionsBuilder;
+struct StablehloConcatenateOptionsT;
+
+struct StablehloBroadcastInDimOptions;
+struct StablehloBroadcastInDimOptionsBuilder;
+struct StablehloBroadcastInDimOptionsT;
+
+struct StablehloCompareOptions;
+struct StablehloCompareOptionsBuilder;
+struct StablehloCompareOptionsT;
+
+struct StablehloDynamicSliceOptions;
+struct StablehloDynamicSliceOptionsBuilder;
+struct StablehloDynamicSliceOptionsT;
+
+struct StablehloPadOptions;
+struct StablehloPadOptionsBuilder;
+struct StablehloPadOptionsT;
+
+struct StablehloIotaOptions;
+struct StablehloIotaOptionsBuilder;
+struct StablehloIotaOptionsT;
+
+struct StablehloCustomCallOptions;
+struct StablehloCustomCallOptionsBuilder;
+struct StablehloCustomCallOptionsT;
+
+struct StablehloReduceOptions;
+struct StablehloReduceOptionsBuilder;
+struct StablehloReduceOptionsT;
+
+struct StablehloSliceOptions;
+struct StablehloSliceOptionsBuilder;
+struct StablehloSliceOptionsT;
+
+struct StablehloConvolutionOptions;
+struct StablehloConvolutionOptionsBuilder;
+struct StablehloConvolutionOptionsT;
+
+struct StablehloScatterOptions;
+struct StablehloScatterOptionsBuilder;
+struct StablehloScatterOptionsT;
+
+struct StablehloRngBitGeneratorOptions;
+struct StablehloRngBitGeneratorOptionsBuilder;
+struct StablehloRngBitGeneratorOptionsT;
+
+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 BucketizeOptions;
+struct BucketizeOptionsBuilder;
+struct BucketizeOptionsT;
+
+struct GeluOptions;
+struct GeluOptionsBuilder;
+struct GeluOptionsT;
+
+struct DynamicUpdateSliceOptions;
+struct DynamicUpdateSliceOptionsBuilder;
+struct DynamicUpdateSliceOptionsT;
+
+struct UnsortedSegmentProdOptions;
+struct UnsortedSegmentProdOptionsBuilder;
+struct UnsortedSegmentProdOptionsT;
+
+struct UnsortedSegmentMaxOptions;
+struct UnsortedSegmentMaxOptionsBuilder;
+struct UnsortedSegmentMaxOptionsT;
+
+struct UnsortedSegmentSumOptions;
+struct UnsortedSegmentSumOptionsBuilder;
+struct UnsortedSegmentSumOptionsT;
+
+struct ATan2Options;
+struct ATan2OptionsBuilder;
+struct ATan2OptionsT;
+
+struct UnsortedSegmentMinOptions;
+struct UnsortedSegmentMinOptionsBuilder;
+struct UnsortedSegmentMinOptionsT;
+
+struct SignOptions;
+struct SignOptionsBuilder;
+struct SignOptionsT;
+
+struct BitcastOptions;
+struct BitcastOptionsBuilder;
+struct BitcastOptionsT;
+
+struct BitwiseXorOptions;
+struct BitwiseXorOptionsBuilder;
+struct BitwiseXorOptionsT;
+
+struct RightShiftOptions;
+struct RightShiftOptionsBuilder;
+struct RightShiftOptionsT;
+
+struct DilateOptions;
+struct DilateOptionsBuilder;
+struct DilateOptionsT;
+
+struct ReduceWindowOptions;
+struct ReduceWindowOptionsBuilder;
+struct ReduceWindowOptionsT;
+
+struct GRUOptions;
+struct GRUOptionsBuilder;
+struct GRUOptionsT;
+
+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_UINT4 = -1,
+  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_UINT16 = 16,
+  TensorType_INT4 = 17,
+  TensorType_MIN = TensorType_UINT4,
+  TensorType_MAX = TensorType_INT4
+};
+
+inline const TensorType (&EnumValuesTensorType())[19]
+{
+  static const TensorType values[] = {
+    TensorType_UINT4,      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_UINT16,    TensorType_INT4};
+  return values;
+}
+
+inline const char *const *EnumNamesTensorType()
+{
+  static const char *const names[20] = {"UINT4",   "FLOAT32", "FLOAT16",    "INT32",  "UINT8",
+                                        "INT64",   "STRING",  "BOOL",       "INT16",  "COMPLEX64",
+                                        "INT8",    "FLOAT64", "COMPLEX128", "UINT64", "RESOURCE",
+                                        "VARIANT", "UINT32",  "UINT16",     "INT4",   nullptr};
+  return names;
+}
+
+inline const char *EnumNameTensorType(TensorType e)
+{
+  if (::flatbuffers::IsOutRange(e, TensorType_UINT4, TensorType_INT4))
+    return "";
+  const size_t index = static_cast<size_t>(e) - static_cast<size_t>(TensorType_UINT4);
+  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;
+};
+
+template <typename T> struct QuantizationDetailsUnionTraits
+{
+  static const QuantizationDetails enum_value = QuantizationDetails_NONE;
+};
+
+template <> struct QuantizationDetailsUnionTraits<circle::CustomQuantizationT>
+{
+  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();
+
+  template <typename T> void Set(T &&val)
+  {
+    typedef typename std::remove_reference<T>::type RT;
+    Reset();
+    type = QuantizationDetailsUnionTraits<RT>::enum_value;
+    if (type != QuantizationDetails_NONE)
+    {
+      value = new RT(std::forward<T>(val));
+    }
+  }
+
+  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;
+};
+
+template <typename T> struct SparseIndexVectorUnionTraits
+{
+  static const SparseIndexVector enum_value = SparseIndexVector_NONE;
+};
+
+template <> struct SparseIndexVectorUnionTraits<circle::Int32VectorT>
+{
+  static const SparseIndexVector enum_value = SparseIndexVector_Int32Vector;
+};
+
+template <> struct SparseIndexVectorUnionTraits<circle::Uint16VectorT>
+{
+  static const SparseIndexVector enum_value = SparseIndexVector_Uint16Vector;
+};
+
+template <> struct SparseIndexVectorUnionTraits<circle::Uint8VectorT>
+{
+  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();
+
+  template <typename T> void Set(T &&val)
+  {
+    typedef typename std::remove_reference<T>::type RT;
+    Reset();
+    type = SparseIndexVectorUnionTraits<RT>::enum_value;
+    if (type != SparseIndexVector_NONE)
+    {
+      value = new RT(std::forward<T>(val));
+    }
+  }
+
+  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_GRU = -5,
+  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_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_STABLEHLO_LOGISTIC = 162,
+  BuiltinOperator_STABLEHLO_ADD = 163,
+  BuiltinOperator_STABLEHLO_DIVIDE = 164,
+  BuiltinOperator_STABLEHLO_MULTIPLY = 165,
+  BuiltinOperator_STABLEHLO_MAXIMUM = 166,
+  BuiltinOperator_STABLEHLO_RESHAPE = 167,
+  BuiltinOperator_STABLEHLO_CLAMP = 168,
+  BuiltinOperator_STABLEHLO_CONCATENATE = 169,
+  BuiltinOperator_STABLEHLO_BROADCAST_IN_DIM = 170,
+  BuiltinOperator_STABLEHLO_CONVOLUTION = 171,
+  BuiltinOperator_STABLEHLO_SLICE = 172,
+  BuiltinOperator_STABLEHLO_CUSTOM_CALL = 173,
+  BuiltinOperator_STABLEHLO_REDUCE = 174,
+  BuiltinOperator_STABLEHLO_ABS = 175,
+  BuiltinOperator_STABLEHLO_AND = 176,
+  BuiltinOperator_STABLEHLO_COSINE = 177,
+  BuiltinOperator_STABLEHLO_EXPONENTIAL = 178,
+  BuiltinOperator_STABLEHLO_FLOOR = 179,
+  BuiltinOperator_STABLEHLO_LOG = 180,
+  BuiltinOperator_STABLEHLO_MINIMUM = 181,
+  BuiltinOperator_STABLEHLO_NEGATE = 182,
+  BuiltinOperator_STABLEHLO_OR = 183,
+  BuiltinOperator_STABLEHLO_POWER = 184,
+  BuiltinOperator_STABLEHLO_REMAINDER = 185,
+  BuiltinOperator_STABLEHLO_RSQRT = 186,
+  BuiltinOperator_STABLEHLO_SELECT = 187,
+  BuiltinOperator_STABLEHLO_SUBTRACT = 188,
+  BuiltinOperator_STABLEHLO_TANH = 189,
+  BuiltinOperator_STABLEHLO_SCATTER = 190,
+  BuiltinOperator_STABLEHLO_COMPARE = 191,
+  BuiltinOperator_STABLEHLO_CONVERT = 192,
+  BuiltinOperator_STABLEHLO_DYNAMIC_SLICE = 193,
+  BuiltinOperator_STABLEHLO_DYNAMIC_UPDATE_SLICE = 194,
+  BuiltinOperator_STABLEHLO_PAD = 195,
+  BuiltinOperator_STABLEHLO_IOTA = 196,
+  BuiltinOperator_STABLEHLO_DOT_GENERAL = 197,
+  BuiltinOperator_STABLEHLO_REDUCE_WINDOW = 198,
+  BuiltinOperator_STABLEHLO_SORT = 199,
+  BuiltinOperator_STABLEHLO_WHILE = 200,
+  BuiltinOperator_STABLEHLO_GATHER = 201,
+  BuiltinOperator_STABLEHLO_TRANSPOSE = 202,
+  BuiltinOperator_DILATE = 203,
+  BuiltinOperator_STABLEHLO_RNG_BIT_GENERATOR = 204,
+  BuiltinOperator_REDUCE_WINDOW = 205,
+  BuiltinOperator_MIN = BuiltinOperator_GRU,
+  BuiltinOperator_MAX = BuiltinOperator_REDUCE_WINDOW
+};
+
+inline const BuiltinOperator (&EnumValuesBuiltinOperator())[210]
+{
+  static const BuiltinOperator values[] = {BuiltinOperator_GRU,
+                                           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,
+                                           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,
+                                           BuiltinOperator_STABLEHLO_LOGISTIC,
+                                           BuiltinOperator_STABLEHLO_ADD,
+                                           BuiltinOperator_STABLEHLO_DIVIDE,
+                                           BuiltinOperator_STABLEHLO_MULTIPLY,
+                                           BuiltinOperator_STABLEHLO_MAXIMUM,
+                                           BuiltinOperator_STABLEHLO_RESHAPE,
+                                           BuiltinOperator_STABLEHLO_CLAMP,
+                                           BuiltinOperator_STABLEHLO_CONCATENATE,
+                                           BuiltinOperator_STABLEHLO_BROADCAST_IN_DIM,
+                                           BuiltinOperator_STABLEHLO_CONVOLUTION,
+                                           BuiltinOperator_STABLEHLO_SLICE,
+                                           BuiltinOperator_STABLEHLO_CUSTOM_CALL,
+                                           BuiltinOperator_STABLEHLO_REDUCE,
+                                           BuiltinOperator_STABLEHLO_ABS,
+                                           BuiltinOperator_STABLEHLO_AND,
+                                           BuiltinOperator_STABLEHLO_COSINE,
+                                           BuiltinOperator_STABLEHLO_EXPONENTIAL,
+                                           BuiltinOperator_STABLEHLO_FLOOR,
+                                           BuiltinOperator_STABLEHLO_LOG,
+                                           BuiltinOperator_STABLEHLO_MINIMUM,
+                                           BuiltinOperator_STABLEHLO_NEGATE,
+                                           BuiltinOperator_STABLEHLO_OR,
+                                           BuiltinOperator_STABLEHLO_POWER,
+                                           BuiltinOperator_STABLEHLO_REMAINDER,
+                                           BuiltinOperator_STABLEHLO_RSQRT,
+                                           BuiltinOperator_STABLEHLO_SELECT,
+                                           BuiltinOperator_STABLEHLO_SUBTRACT,
+                                           BuiltinOperator_STABLEHLO_TANH,
+                                           BuiltinOperator_STABLEHLO_SCATTER,
+                                           BuiltinOperator_STABLEHLO_COMPARE,
+                                           BuiltinOperator_STABLEHLO_CONVERT,
+                                           BuiltinOperator_STABLEHLO_DYNAMIC_SLICE,
+                                           BuiltinOperator_STABLEHLO_DYNAMIC_UPDATE_SLICE,
+                                           BuiltinOperator_STABLEHLO_PAD,
+                                           BuiltinOperator_STABLEHLO_IOTA,
+                                           BuiltinOperator_STABLEHLO_DOT_GENERAL,
+                                           BuiltinOperator_STABLEHLO_REDUCE_WINDOW,
+                                           BuiltinOperator_STABLEHLO_SORT,
+                                           BuiltinOperator_STABLEHLO_WHILE,
+                                           BuiltinOperator_STABLEHLO_GATHER,
+                                           BuiltinOperator_STABLEHLO_TRANSPOSE,
+                                           BuiltinOperator_DILATE,
+                                           BuiltinOperator_STABLEHLO_RNG_BIT_GENERATOR,
+                                           BuiltinOperator_REDUCE_WINDOW};
+  return values;
+}
+
+inline const char *const *EnumNamesBuiltinOperator()
+{
+  static const char *const names[212] = {"GRU",
+                                         "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",
+                                         "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",
+                                         "STABLEHLO_LOGISTIC",
+                                         "STABLEHLO_ADD",
+                                         "STABLEHLO_DIVIDE",
+                                         "STABLEHLO_MULTIPLY",
+                                         "STABLEHLO_MAXIMUM",
+                                         "STABLEHLO_RESHAPE",
+                                         "STABLEHLO_CLAMP",
+                                         "STABLEHLO_CONCATENATE",
+                                         "STABLEHLO_BROADCAST_IN_DIM",
+                                         "STABLEHLO_CONVOLUTION",
+                                         "STABLEHLO_SLICE",
+                                         "STABLEHLO_CUSTOM_CALL",
+                                         "STABLEHLO_REDUCE",
+                                         "STABLEHLO_ABS",
+                                         "STABLEHLO_AND",
+                                         "STABLEHLO_COSINE",
+                                         "STABLEHLO_EXPONENTIAL",
+                                         "STABLEHLO_FLOOR",
+                                         "STABLEHLO_LOG",
+                                         "STABLEHLO_MINIMUM",
+                                         "STABLEHLO_NEGATE",
+                                         "STABLEHLO_OR",
+                                         "STABLEHLO_POWER",
+                                         "STABLEHLO_REMAINDER",
+                                         "STABLEHLO_RSQRT",
+                                         "STABLEHLO_SELECT",
+                                         "STABLEHLO_SUBTRACT",
+                                         "STABLEHLO_TANH",
+                                         "STABLEHLO_SCATTER",
+                                         "STABLEHLO_COMPARE",
+                                         "STABLEHLO_CONVERT",
+                                         "STABLEHLO_DYNAMIC_SLICE",
+                                         "STABLEHLO_DYNAMIC_UPDATE_SLICE",
+                                         "STABLEHLO_PAD",
+                                         "STABLEHLO_IOTA",
+                                         "STABLEHLO_DOT_GENERAL",
+                                         "STABLEHLO_REDUCE_WINDOW",
+                                         "STABLEHLO_SORT",
+                                         "STABLEHLO_WHILE",
+                                         "STABLEHLO_GATHER",
+                                         "STABLEHLO_TRANSPOSE",
+                                         "DILATE",
+                                         "STABLEHLO_RNG_BIT_GENERATOR",
+                                         "REDUCE_WINDOW",
+                                         nullptr};
+  return names;
+}
+
+inline const char *EnumNameBuiltinOperator(BuiltinOperator e)
+{
+  if (::flatbuffers::IsOutRange(e, BuiltinOperator_GRU, BuiltinOperator_REDUCE_WINDOW))
+    return "";
+  const size_t index = static_cast<size_t>(e) - static_cast<size_t>(BuiltinOperator_GRU);
+  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_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_GRUOptions = 251,
+  BuiltinOptions_BCQGatherOptions = 252,
+  BuiltinOptions_BCQFullyConnectedOptions = 253,
+  BuiltinOptions_InstanceNormOptions = 254,
+  BuiltinOptions_MIN = BuiltinOptions_NONE,
+  BuiltinOptions_MAX = BuiltinOptions_InstanceNormOptions
+};
+
+inline const BuiltinOptions (&EnumValuesBuiltinOptions())[131]
+{
+  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_BucketizeOptions,
+                                          BuiltinOptions_GeluOptions,
+                                          BuiltinOptions_DynamicUpdateSliceOptions,
+                                          BuiltinOptions_UnsortedSegmentProdOptions,
+                                          BuiltinOptions_UnsortedSegmentMaxOptions,
+                                          BuiltinOptions_UnsortedSegmentMinOptions,
+                                          BuiltinOptions_UnsortedSegmentSumOptions,
+                                          BuiltinOptions_ATan2Options,
+                                          BuiltinOptions_SignOptions,
+                                          BuiltinOptions_BitcastOptions,
+                                          BuiltinOptions_BitwiseXorOptions,
+                                          BuiltinOptions_RightShiftOptions,
+                                          BuiltinOptions_GRUOptions,
+                                          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",
+                                         "BucketizeOptions",
+                                         "GeluOptions",
+                                         "DynamicUpdateSliceOptions",
+                                         "UnsortedSegmentProdOptions",
+                                         "UnsortedSegmentMaxOptions",
+                                         "UnsortedSegmentMinOptions",
+                                         "UnsortedSegmentSumOptions",
+                                         "ATan2Options",
+                                         "SignOptions",
+                                         "BitcastOptions",
+                                         "BitwiseXorOptions",
+                                         "RightShiftOptions",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "",
+                                         "GRUOptions",
+                                         "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::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::GRUOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GRUOptions;
+};
+
+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;
+};
+
+template <typename T> struct BuiltinOptionsUnionTraits
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_NONE;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::Conv2DOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_Conv2DOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::DepthwiseConv2DOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DepthwiseConv2DOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ConcatEmbeddingsOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ConcatEmbeddingsOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::LSHProjectionOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LSHProjectionOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::Pool2DOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_Pool2DOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SVDFOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SVDFOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::RNNOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_RNNOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::FullyConnectedOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_FullyConnectedOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SoftmaxOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SoftmaxOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ConcatenationOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ConcatenationOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::AddOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_AddOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::L2NormOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_L2NormOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::LocalResponseNormalizationOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LocalResponseNormalizationOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::LSTMOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LSTMOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ResizeBilinearOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ResizeBilinearOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::CallOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_CallOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ReshapeOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ReshapeOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SkipGramOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SkipGramOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SpaceToDepthOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SpaceToDepthOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::EmbeddingLookupSparseOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_EmbeddingLookupSparseOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::MulOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_MulOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::PadOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_PadOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::GatherOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GatherOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::BatchToSpaceNDOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BatchToSpaceNDOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SpaceToBatchNDOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SpaceToBatchNDOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::TransposeOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_TransposeOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ReducerOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ReducerOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SubOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SubOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::DivOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DivOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SqueezeOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SqueezeOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SequenceRNNOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SequenceRNNOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::StridedSliceOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_StridedSliceOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ExpOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ExpOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::TopKV2OptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_TopKV2Options;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SplitOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SplitOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::LogSoftmaxOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LogSoftmaxOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::CastOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_CastOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::DequantizeOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DequantizeOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::MaximumMinimumOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_MaximumMinimumOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ArgMaxOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ArgMaxOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::LessOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LessOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::NegOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_NegOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::PadV2OptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_PadV2Options;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::GreaterOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GreaterOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::GreaterEqualOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GreaterEqualOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::LessEqualOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LessEqualOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SelectOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SelectOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SliceOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SliceOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::TransposeConvOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_TransposeConvOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SparseToDenseOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SparseToDenseOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::TileOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_TileOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ExpandDimsOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ExpandDimsOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::EqualOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_EqualOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::NotEqualOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_NotEqualOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ShapeOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ShapeOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::PowOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_PowOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ArgMinOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ArgMinOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::FakeQuantOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_FakeQuantOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::PackOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_PackOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::LogicalOrOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LogicalOrOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::OneHotOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_OneHotOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::LogicalAndOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LogicalAndOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::LogicalNotOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LogicalNotOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::UnpackOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_UnpackOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::FloorDivOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_FloorDivOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SquareOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SquareOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ZerosLikeOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ZerosLikeOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::FillOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_FillOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::BidirectionalSequenceLSTMOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceLSTMOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::BidirectionalSequenceRNNOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceRNNOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::UnidirectionalSequenceLSTMOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_UnidirectionalSequenceLSTMOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::FloorModOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_FloorModOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::RangeOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_RangeOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ResizeNearestNeighborOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ResizeNearestNeighborOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::LeakyReluOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LeakyReluOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SquaredDifferenceOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SquaredDifferenceOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::MirrorPadOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_MirrorPadOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::AbsOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_AbsOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SplitVOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SplitVOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::UniqueOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_UniqueOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ReverseV2OptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ReverseV2Options;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::AddNOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_AddNOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::GatherNdOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GatherNdOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::CosOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_CosOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::WhereOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_WhereOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::RankOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_RankOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ReverseSequenceOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ReverseSequenceOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::MatrixDiagOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_MatrixDiagOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::QuantizeOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_QuantizeOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::MatrixSetDiagOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_MatrixSetDiagOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::HardSwishOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_HardSwishOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::IfOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_IfOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::WhileOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_WhileOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::DepthToSpaceOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DepthToSpaceOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::NonMaxSuppressionV4OptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV4Options;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::NonMaxSuppressionV5OptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV5Options;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ScatterNdOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ScatterNdOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SelectV2OptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SelectV2Options;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::DensifyOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DensifyOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SegmentSumOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SegmentSumOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::BatchMatMulOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BatchMatMulOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::CumsumOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_CumsumOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::CallOnceOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_CallOnceOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::BroadcastToOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BroadcastToOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::Rfft2dOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_Rfft2dOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::Conv3DOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_Conv3DOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::HashtableOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_HashtableOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::HashtableFindOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_HashtableFindOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::HashtableImportOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_HashtableImportOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::HashtableSizeOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_HashtableSizeOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::VarHandleOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_VarHandleOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ReadVariableOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ReadVariableOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::AssignVariableOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_AssignVariableOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::RandomOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_RandomOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::BucketizeOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BucketizeOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::GeluOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GeluOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::DynamicUpdateSliceOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DynamicUpdateSliceOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::UnsortedSegmentProdOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentProdOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::UnsortedSegmentMaxOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentMaxOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::UnsortedSegmentMinOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentMinOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::UnsortedSegmentSumOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_UnsortedSegmentSumOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::ATan2OptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ATan2Options;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::SignOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SignOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::BitcastOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BitcastOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::BitwiseXorOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BitwiseXorOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::RightShiftOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_RightShiftOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::GRUOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GRUOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::BCQGatherOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BCQGatherOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::BCQFullyConnectedOptionsT>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BCQFullyConnectedOptions;
+};
+
+template <> struct BuiltinOptionsUnionTraits<circle::InstanceNormOptionsT>
+{
+  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();
+
+  template <typename T> void Set(T &&val)
+  {
+    typedef typename std::remove_reference<T>::type RT;
+    Reset();
+    type = BuiltinOptionsUnionTraits<RT>::enum_value;
+    if (type != BuiltinOptions_NONE)
+    {
+      value = new RT(std::forward<T>(val));
+    }
+  }
+
+  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::BucketizeOptionsT *AsBucketizeOptions()
+  {
+    return type == BuiltinOptions_BucketizeOptions
+             ? reinterpret_cast<circle::BucketizeOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::BucketizeOptionsT *AsBucketizeOptions() const
+  {
+    return type == BuiltinOptions_BucketizeOptions
+             ? reinterpret_cast<const circle::BucketizeOptionsT *>(value)
+             : nullptr;
+  }
+  circle::GeluOptionsT *AsGeluOptions()
+  {
+    return type == BuiltinOptions_GeluOptions ? reinterpret_cast<circle::GeluOptionsT *>(value)
+                                              : nullptr;
+  }
+  const circle::GeluOptionsT *AsGeluOptions() const
+  {
+    return type == BuiltinOptions_GeluOptions
+             ? reinterpret_cast<const circle::GeluOptionsT *>(value)
+             : nullptr;
+  }
+  circle::DynamicUpdateSliceOptionsT *AsDynamicUpdateSliceOptions()
+  {
+    return type == BuiltinOptions_DynamicUpdateSliceOptions
+             ? reinterpret_cast<circle::DynamicUpdateSliceOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::DynamicUpdateSliceOptionsT *AsDynamicUpdateSliceOptions() const
+  {
+    return type == BuiltinOptions_DynamicUpdateSliceOptions
+             ? reinterpret_cast<const circle::DynamicUpdateSliceOptionsT *>(value)
+             : nullptr;
+  }
+  circle::UnsortedSegmentProdOptionsT *AsUnsortedSegmentProdOptions()
+  {
+    return type == BuiltinOptions_UnsortedSegmentProdOptions
+             ? reinterpret_cast<circle::UnsortedSegmentProdOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::UnsortedSegmentProdOptionsT *AsUnsortedSegmentProdOptions() const
+  {
+    return type == BuiltinOptions_UnsortedSegmentProdOptions
+             ? reinterpret_cast<const circle::UnsortedSegmentProdOptionsT *>(value)
+             : nullptr;
+  }
+  circle::UnsortedSegmentMaxOptionsT *AsUnsortedSegmentMaxOptions()
+  {
+    return type == BuiltinOptions_UnsortedSegmentMaxOptions
+             ? reinterpret_cast<circle::UnsortedSegmentMaxOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::UnsortedSegmentMaxOptionsT *AsUnsortedSegmentMaxOptions() const
+  {
+    return type == BuiltinOptions_UnsortedSegmentMaxOptions
+             ? reinterpret_cast<const circle::UnsortedSegmentMaxOptionsT *>(value)
+             : nullptr;
+  }
+  circle::UnsortedSegmentMinOptionsT *AsUnsortedSegmentMinOptions()
+  {
+    return type == BuiltinOptions_UnsortedSegmentMinOptions
+             ? reinterpret_cast<circle::UnsortedSegmentMinOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::UnsortedSegmentMinOptionsT *AsUnsortedSegmentMinOptions() const
+  {
+    return type == BuiltinOptions_UnsortedSegmentMinOptions
+             ? reinterpret_cast<const circle::UnsortedSegmentMinOptionsT *>(value)
+             : nullptr;
+  }
+  circle::UnsortedSegmentSumOptionsT *AsUnsortedSegmentSumOptions()
+  {
+    return type == BuiltinOptions_UnsortedSegmentSumOptions
+             ? reinterpret_cast<circle::UnsortedSegmentSumOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::UnsortedSegmentSumOptionsT *AsUnsortedSegmentSumOptions() const
+  {
+    return type == BuiltinOptions_UnsortedSegmentSumOptions
+             ? reinterpret_cast<const circle::UnsortedSegmentSumOptionsT *>(value)
+             : nullptr;
+  }
+  circle::ATan2OptionsT *AsATan2Options()
+  {
+    return type == BuiltinOptions_ATan2Options ? reinterpret_cast<circle::ATan2OptionsT *>(value)
+                                               : nullptr;
+  }
+  const circle::ATan2OptionsT *AsATan2Options() const
+  {
+    return type == BuiltinOptions_ATan2Options
+             ? reinterpret_cast<const circle::ATan2OptionsT *>(value)
+             : nullptr;
+  }
+  circle::SignOptionsT *AsSignOptions()
+  {
+    return type == BuiltinOptions_SignOptions ? reinterpret_cast<circle::SignOptionsT *>(value)
+                                              : nullptr;
+  }
+  const circle::SignOptionsT *AsSignOptions() const
+  {
+    return type == BuiltinOptions_SignOptions
+             ? reinterpret_cast<const circle::SignOptionsT *>(value)
+             : nullptr;
+  }
+  circle::BitcastOptionsT *AsBitcastOptions()
+  {
+    return type == BuiltinOptions_BitcastOptions
+             ? reinterpret_cast<circle::BitcastOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::BitcastOptionsT *AsBitcastOptions() const
+  {
+    return type == BuiltinOptions_BitcastOptions
+             ? reinterpret_cast<const circle::BitcastOptionsT *>(value)
+             : nullptr;
+  }
+  circle::BitwiseXorOptionsT *AsBitwiseXorOptions()
+  {
+    return type == BuiltinOptions_BitwiseXorOptions
+             ? reinterpret_cast<circle::BitwiseXorOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::BitwiseXorOptionsT *AsBitwiseXorOptions() const
+  {
+    return type == BuiltinOptions_BitwiseXorOptions
+             ? reinterpret_cast<const circle::BitwiseXorOptionsT *>(value)
+             : nullptr;
+  }
+  circle::RightShiftOptionsT *AsRightShiftOptions()
+  {
+    return type == BuiltinOptions_RightShiftOptions
+             ? reinterpret_cast<circle::RightShiftOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::RightShiftOptionsT *AsRightShiftOptions() const
+  {
+    return type == BuiltinOptions_RightShiftOptions
+             ? reinterpret_cast<const circle::RightShiftOptionsT *>(value)
+             : nullptr;
+  }
+  circle::GRUOptionsT *AsGRUOptions()
+  {
+    return type == BuiltinOptions_GRUOptions ? reinterpret_cast<circle::GRUOptionsT *>(value)
+                                             : nullptr;
+  }
+  const circle::GRUOptionsT *AsGRUOptions() const
+  {
+    return type == BuiltinOptions_GRUOptions ? reinterpret_cast<const circle::GRUOptionsT *>(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 BuiltinOptions2 : uint8_t
+{
+  BuiltinOptions2_NONE = 0,
+  BuiltinOptions2_StablehloConcatenateOptions = 1,
+  BuiltinOptions2_StablehloBroadcastInDimOptions = 2,
+  BuiltinOptions2_StablehloSliceOptions = 3,
+  BuiltinOptions2_StablehloConvolutionOptions = 4,
+  BuiltinOptions2_StablehloCustomCallOptions = 5,
+  BuiltinOptions2_StablehloReduceOptions = 6,
+  BuiltinOptions2_StablehloScatterOptions = 7,
+  BuiltinOptions2_StablehloCompareOptions = 8,
+  BuiltinOptions2_StablehloDynamicSliceOptions = 9,
+  BuiltinOptions2_StablehloPadOptions = 10,
+  BuiltinOptions2_StablehloIotaOptions = 11,
+  BuiltinOptions2_StablehloDotGeneralOptions = 12,
+  BuiltinOptions2_StablehloReduceWindowOptions = 13,
+  BuiltinOptions2_StablehloSortOptions = 14,
+  BuiltinOptions2_StablehloWhileOptions = 15,
+  BuiltinOptions2_StablehloGatherOptions = 16,
+  BuiltinOptions2_StablehloTransposeOptions = 17,
+  BuiltinOptions2_DilateOptions = 18,
+  BuiltinOptions2_StablehloRngBitGeneratorOptions = 19,
+  BuiltinOptions2_ReduceWindowOptions = 20,
+  BuiltinOptions2_MIN = BuiltinOptions2_NONE,
+  BuiltinOptions2_MAX = BuiltinOptions2_ReduceWindowOptions
+};
+
+inline const BuiltinOptions2 (&EnumValuesBuiltinOptions2())[21]
+{
+  static const BuiltinOptions2 values[] = {BuiltinOptions2_NONE,
+                                           BuiltinOptions2_StablehloConcatenateOptions,
+                                           BuiltinOptions2_StablehloBroadcastInDimOptions,
+                                           BuiltinOptions2_StablehloSliceOptions,
+                                           BuiltinOptions2_StablehloConvolutionOptions,
+                                           BuiltinOptions2_StablehloCustomCallOptions,
+                                           BuiltinOptions2_StablehloReduceOptions,
+                                           BuiltinOptions2_StablehloScatterOptions,
+                                           BuiltinOptions2_StablehloCompareOptions,
+                                           BuiltinOptions2_StablehloDynamicSliceOptions,
+                                           BuiltinOptions2_StablehloPadOptions,
+                                           BuiltinOptions2_StablehloIotaOptions,
+                                           BuiltinOptions2_StablehloDotGeneralOptions,
+                                           BuiltinOptions2_StablehloReduceWindowOptions,
+                                           BuiltinOptions2_StablehloSortOptions,
+                                           BuiltinOptions2_StablehloWhileOptions,
+                                           BuiltinOptions2_StablehloGatherOptions,
+                                           BuiltinOptions2_StablehloTransposeOptions,
+                                           BuiltinOptions2_DilateOptions,
+                                           BuiltinOptions2_StablehloRngBitGeneratorOptions,
+                                           BuiltinOptions2_ReduceWindowOptions};
+  return values;
+}
+
+inline const char *const *EnumNamesBuiltinOptions2()
+{
+  static const char *const names[22] = {"NONE",
+                                        "StablehloConcatenateOptions",
+                                        "StablehloBroadcastInDimOptions",
+                                        "StablehloSliceOptions",
+                                        "StablehloConvolutionOptions",
+                                        "StablehloCustomCallOptions",
+                                        "StablehloReduceOptions",
+                                        "StablehloScatterOptions",
+                                        "StablehloCompareOptions",
+                                        "StablehloDynamicSliceOptions",
+                                        "StablehloPadOptions",
+                                        "StablehloIotaOptions",
+                                        "StablehloDotGeneralOptions",
+                                        "StablehloReduceWindowOptions",
+                                        "StablehloSortOptions",
+                                        "StablehloWhileOptions",
+                                        "StablehloGatherOptions",
+                                        "StablehloTransposeOptions",
+                                        "DilateOptions",
+                                        "StablehloRngBitGeneratorOptions",
+                                        "ReduceWindowOptions",
+                                        nullptr};
+  return names;
+}
+
+inline const char *EnumNameBuiltinOptions2(BuiltinOptions2 e)
+{
+  if (::flatbuffers::IsOutRange(e, BuiltinOptions2_NONE, BuiltinOptions2_ReduceWindowOptions))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesBuiltinOptions2()[index];
+}
+
+template <typename T> struct BuiltinOptions2Traits
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_NONE;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloConcatenateOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloConcatenateOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloBroadcastInDimOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloBroadcastInDimOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloSliceOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloSliceOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloConvolutionOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloConvolutionOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloCustomCallOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloCustomCallOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloReduceOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloReduceOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloScatterOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloScatterOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloCompareOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloCompareOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloDynamicSliceOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloDynamicSliceOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloPadOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloPadOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloIotaOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloIotaOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloDotGeneralOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloDotGeneralOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloReduceWindowOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloReduceWindowOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloSortOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloSortOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloWhileOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloWhileOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloGatherOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloGatherOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloTransposeOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloTransposeOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::DilateOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_DilateOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::StablehloRngBitGeneratorOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloRngBitGeneratorOptions;
+};
+
+template <> struct BuiltinOptions2Traits<circle::ReduceWindowOptions>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_ReduceWindowOptions;
+};
+
+template <typename T> struct BuiltinOptions2UnionTraits
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_NONE;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloConcatenateOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloConcatenateOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloBroadcastInDimOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloBroadcastInDimOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloSliceOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloSliceOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloConvolutionOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloConvolutionOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloCustomCallOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloCustomCallOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloReduceOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloReduceOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloScatterOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloScatterOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloCompareOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloCompareOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloDynamicSliceOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloDynamicSliceOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloPadOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloPadOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloIotaOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloIotaOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloDotGeneralOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloDotGeneralOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloReduceWindowOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloReduceWindowOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloSortOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloSortOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloWhileOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloWhileOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloGatherOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloGatherOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloTransposeOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloTransposeOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::DilateOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_DilateOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::StablehloRngBitGeneratorOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_StablehloRngBitGeneratorOptions;
+};
+
+template <> struct BuiltinOptions2UnionTraits<circle::ReduceWindowOptionsT>
+{
+  static const BuiltinOptions2 enum_value = BuiltinOptions2_ReduceWindowOptions;
+};
+
+struct BuiltinOptions2Union
+{
+  BuiltinOptions2 type;
+  void *value;
+
+  BuiltinOptions2Union() : type(BuiltinOptions2_NONE), value(nullptr) {}
+  BuiltinOptions2Union(BuiltinOptions2Union &&u) FLATBUFFERS_NOEXCEPT : type(BuiltinOptions2_NONE),
+                                                                        value(nullptr)
+  {
+    std::swap(type, u.type);
+    std::swap(value, u.value);
+  }
+  BuiltinOptions2Union(const BuiltinOptions2Union &);
+  BuiltinOptions2Union &operator=(const BuiltinOptions2Union &u)
+  {
+    BuiltinOptions2Union t(u);
+    std::swap(type, t.type);
+    std::swap(value, t.value);
+    return *this;
+  }
+  BuiltinOptions2Union &operator=(BuiltinOptions2Union &&u) FLATBUFFERS_NOEXCEPT
+  {
+    std::swap(type, u.type);
+    std::swap(value, u.value);
+    return *this;
+  }
+  ~BuiltinOptions2Union() { Reset(); }
+
+  void Reset();
+
+  template <typename T> void Set(T &&val)
+  {
+    typedef typename std::remove_reference<T>::type RT;
+    Reset();
+    type = BuiltinOptions2UnionTraits<RT>::enum_value;
+    if (type != BuiltinOptions2_NONE)
+    {
+      value = new RT(std::forward<T>(val));
+    }
+  }
+
+  static void *UnPack(const void *obj, BuiltinOptions2 type,
+                      const ::flatbuffers::resolver_function_t *resolver);
+  ::flatbuffers::Offset<void>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
+
+  circle::StablehloConcatenateOptionsT *AsStablehloConcatenateOptions()
+  {
+    return type == BuiltinOptions2_StablehloConcatenateOptions
+             ? reinterpret_cast<circle::StablehloConcatenateOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloConcatenateOptionsT *AsStablehloConcatenateOptions() const
+  {
+    return type == BuiltinOptions2_StablehloConcatenateOptions
+             ? reinterpret_cast<const circle::StablehloConcatenateOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloBroadcastInDimOptionsT *AsStablehloBroadcastInDimOptions()
+  {
+    return type == BuiltinOptions2_StablehloBroadcastInDimOptions
+             ? reinterpret_cast<circle::StablehloBroadcastInDimOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloBroadcastInDimOptionsT *AsStablehloBroadcastInDimOptions() const
+  {
+    return type == BuiltinOptions2_StablehloBroadcastInDimOptions
+             ? reinterpret_cast<const circle::StablehloBroadcastInDimOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloSliceOptionsT *AsStablehloSliceOptions()
+  {
+    return type == BuiltinOptions2_StablehloSliceOptions
+             ? reinterpret_cast<circle::StablehloSliceOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloSliceOptionsT *AsStablehloSliceOptions() const
+  {
+    return type == BuiltinOptions2_StablehloSliceOptions
+             ? reinterpret_cast<const circle::StablehloSliceOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloConvolutionOptionsT *AsStablehloConvolutionOptions()
+  {
+    return type == BuiltinOptions2_StablehloConvolutionOptions
+             ? reinterpret_cast<circle::StablehloConvolutionOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloConvolutionOptionsT *AsStablehloConvolutionOptions() const
+  {
+    return type == BuiltinOptions2_StablehloConvolutionOptions
+             ? reinterpret_cast<const circle::StablehloConvolutionOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloCustomCallOptionsT *AsStablehloCustomCallOptions()
+  {
+    return type == BuiltinOptions2_StablehloCustomCallOptions
+             ? reinterpret_cast<circle::StablehloCustomCallOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloCustomCallOptionsT *AsStablehloCustomCallOptions() const
+  {
+    return type == BuiltinOptions2_StablehloCustomCallOptions
+             ? reinterpret_cast<const circle::StablehloCustomCallOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloReduceOptionsT *AsStablehloReduceOptions()
+  {
+    return type == BuiltinOptions2_StablehloReduceOptions
+             ? reinterpret_cast<circle::StablehloReduceOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloReduceOptionsT *AsStablehloReduceOptions() const
+  {
+    return type == BuiltinOptions2_StablehloReduceOptions
+             ? reinterpret_cast<const circle::StablehloReduceOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloScatterOptionsT *AsStablehloScatterOptions()
+  {
+    return type == BuiltinOptions2_StablehloScatterOptions
+             ? reinterpret_cast<circle::StablehloScatterOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloScatterOptionsT *AsStablehloScatterOptions() const
+  {
+    return type == BuiltinOptions2_StablehloScatterOptions
+             ? reinterpret_cast<const circle::StablehloScatterOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloCompareOptionsT *AsStablehloCompareOptions()
+  {
+    return type == BuiltinOptions2_StablehloCompareOptions
+             ? reinterpret_cast<circle::StablehloCompareOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloCompareOptionsT *AsStablehloCompareOptions() const
+  {
+    return type == BuiltinOptions2_StablehloCompareOptions
+             ? reinterpret_cast<const circle::StablehloCompareOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloDynamicSliceOptionsT *AsStablehloDynamicSliceOptions()
+  {
+    return type == BuiltinOptions2_StablehloDynamicSliceOptions
+             ? reinterpret_cast<circle::StablehloDynamicSliceOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloDynamicSliceOptionsT *AsStablehloDynamicSliceOptions() const
+  {
+    return type == BuiltinOptions2_StablehloDynamicSliceOptions
+             ? reinterpret_cast<const circle::StablehloDynamicSliceOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloPadOptionsT *AsStablehloPadOptions()
+  {
+    return type == BuiltinOptions2_StablehloPadOptions
+             ? reinterpret_cast<circle::StablehloPadOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloPadOptionsT *AsStablehloPadOptions() const
+  {
+    return type == BuiltinOptions2_StablehloPadOptions
+             ? reinterpret_cast<const circle::StablehloPadOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloIotaOptionsT *AsStablehloIotaOptions()
+  {
+    return type == BuiltinOptions2_StablehloIotaOptions
+             ? reinterpret_cast<circle::StablehloIotaOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloIotaOptionsT *AsStablehloIotaOptions() const
+  {
+    return type == BuiltinOptions2_StablehloIotaOptions
+             ? reinterpret_cast<const circle::StablehloIotaOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloDotGeneralOptionsT *AsStablehloDotGeneralOptions()
+  {
+    return type == BuiltinOptions2_StablehloDotGeneralOptions
+             ? reinterpret_cast<circle::StablehloDotGeneralOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloDotGeneralOptionsT *AsStablehloDotGeneralOptions() const
+  {
+    return type == BuiltinOptions2_StablehloDotGeneralOptions
+             ? reinterpret_cast<const circle::StablehloDotGeneralOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloReduceWindowOptionsT *AsStablehloReduceWindowOptions()
+  {
+    return type == BuiltinOptions2_StablehloReduceWindowOptions
+             ? reinterpret_cast<circle::StablehloReduceWindowOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloReduceWindowOptionsT *AsStablehloReduceWindowOptions() const
+  {
+    return type == BuiltinOptions2_StablehloReduceWindowOptions
+             ? reinterpret_cast<const circle::StablehloReduceWindowOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloSortOptionsT *AsStablehloSortOptions()
+  {
+    return type == BuiltinOptions2_StablehloSortOptions
+             ? reinterpret_cast<circle::StablehloSortOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloSortOptionsT *AsStablehloSortOptions() const
+  {
+    return type == BuiltinOptions2_StablehloSortOptions
+             ? reinterpret_cast<const circle::StablehloSortOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloWhileOptionsT *AsStablehloWhileOptions()
+  {
+    return type == BuiltinOptions2_StablehloWhileOptions
+             ? reinterpret_cast<circle::StablehloWhileOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloWhileOptionsT *AsStablehloWhileOptions() const
+  {
+    return type == BuiltinOptions2_StablehloWhileOptions
+             ? reinterpret_cast<const circle::StablehloWhileOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloGatherOptionsT *AsStablehloGatherOptions()
+  {
+    return type == BuiltinOptions2_StablehloGatherOptions
+             ? reinterpret_cast<circle::StablehloGatherOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloGatherOptionsT *AsStablehloGatherOptions() const
+  {
+    return type == BuiltinOptions2_StablehloGatherOptions
+             ? reinterpret_cast<const circle::StablehloGatherOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloTransposeOptionsT *AsStablehloTransposeOptions()
+  {
+    return type == BuiltinOptions2_StablehloTransposeOptions
+             ? reinterpret_cast<circle::StablehloTransposeOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloTransposeOptionsT *AsStablehloTransposeOptions() const
+  {
+    return type == BuiltinOptions2_StablehloTransposeOptions
+             ? reinterpret_cast<const circle::StablehloTransposeOptionsT *>(value)
+             : nullptr;
+  }
+  circle::DilateOptionsT *AsDilateOptions()
+  {
+    return type == BuiltinOptions2_DilateOptions ? reinterpret_cast<circle::DilateOptionsT *>(value)
+                                                 : nullptr;
+  }
+  const circle::DilateOptionsT *AsDilateOptions() const
+  {
+    return type == BuiltinOptions2_DilateOptions
+             ? reinterpret_cast<const circle::DilateOptionsT *>(value)
+             : nullptr;
+  }
+  circle::StablehloRngBitGeneratorOptionsT *AsStablehloRngBitGeneratorOptions()
+  {
+    return type == BuiltinOptions2_StablehloRngBitGeneratorOptions
+             ? reinterpret_cast<circle::StablehloRngBitGeneratorOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::StablehloRngBitGeneratorOptionsT *AsStablehloRngBitGeneratorOptions() const
+  {
+    return type == BuiltinOptions2_StablehloRngBitGeneratorOptions
+             ? reinterpret_cast<const circle::StablehloRngBitGeneratorOptionsT *>(value)
+             : nullptr;
+  }
+  circle::ReduceWindowOptionsT *AsReduceWindowOptions()
+  {
+    return type == BuiltinOptions2_ReduceWindowOptions
+             ? reinterpret_cast<circle::ReduceWindowOptionsT *>(value)
+             : nullptr;
+  }
+  const circle::ReduceWindowOptionsT *AsReduceWindowOptions() const
+  {
+    return type == BuiltinOptions2_ReduceWindowOptions
+             ? reinterpret_cast<const circle::ReduceWindowOptionsT *>(value)
+             : nullptr;
+  }
+};
+
+bool VerifyBuiltinOptions2(::flatbuffers::Verifier &verifier, const void *obj,
+                           BuiltinOptions2 type);
+bool VerifyBuiltinOptions2Vector(::flatbuffers::Verifier &verifier,
+                                 const ::flatbuffers::Vector<::flatbuffers::Offset<void>> *values,
+                                 const ::flatbuffers::Vector<uint8_t> *types);
+
+enum StablehloPrecisionConfig : uint32_t
+{
+  StablehloPrecisionConfig_DEFAULT = 0,
+  StablehloPrecisionConfig_HIGH = 1,
+  StablehloPrecisionConfig_HIGHEST = 2,
+  StablehloPrecisionConfig_MIN = StablehloPrecisionConfig_DEFAULT,
+  StablehloPrecisionConfig_MAX = StablehloPrecisionConfig_HIGHEST
+};
+
+inline const StablehloPrecisionConfig (&EnumValuesStablehloPrecisionConfig())[3]
+{
+  static const StablehloPrecisionConfig values[] = {StablehloPrecisionConfig_DEFAULT,
+                                                    StablehloPrecisionConfig_HIGH,
+                                                    StablehloPrecisionConfig_HIGHEST};
+  return values;
+}
+
+inline const char *const *EnumNamesStablehloPrecisionConfig()
+{
+  static const char *const names[4] = {"DEFAULT", "HIGH", "HIGHEST", nullptr};
+  return names;
+}
+
+inline const char *EnumNameStablehloPrecisionConfig(StablehloPrecisionConfig e)
+{
+  if (::flatbuffers::IsOutRange(e, StablehloPrecisionConfig_DEFAULT,
+                                StablehloPrecisionConfig_HIGHEST))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesStablehloPrecisionConfig()[index];
+}
+
+enum StablehloComparisonDirection : uint32_t
+{
+  StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_EQ = 0,
+  StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_NE = 1,
+  StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_GE = 2,
+  StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_GT = 3,
+  StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_LE = 4,
+  StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_LT = 5,
+  StablehloComparisonDirection_MIN = StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_EQ,
+  StablehloComparisonDirection_MAX = StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_LT
+};
+
+inline const StablehloComparisonDirection (&EnumValuesStablehloComparisonDirection())[6]
+{
+  static const StablehloComparisonDirection values[] = {
+    StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_EQ,
+    StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_NE,
+    StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_GE,
+    StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_GT,
+    StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_LE,
+    StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_LT};
+  return values;
+}
+
+inline const char *const *EnumNamesStablehloComparisonDirection()
+{
+  static const char *const names[7] = {"STABLEHLO_COMPARISON_DIRECTION_EQ",
+                                       "STABLEHLO_COMPARISON_DIRECTION_NE",
+                                       "STABLEHLO_COMPARISON_DIRECTION_GE",
+                                       "STABLEHLO_COMPARISON_DIRECTION_GT",
+                                       "STABLEHLO_COMPARISON_DIRECTION_LE",
+                                       "STABLEHLO_COMPARISON_DIRECTION_LT",
+                                       nullptr};
+  return names;
+}
+
+inline const char *EnumNameStablehloComparisonDirection(StablehloComparisonDirection e)
+{
+  if (::flatbuffers::IsOutRange(e, StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_EQ,
+                                StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_LT))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesStablehloComparisonDirection()[index];
+}
+
+enum StablehloComparisonType : uint32_t
+{
+  StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_NOTYPE = 0,
+  StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_FLOAT = 1,
+  StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_FLOAT_TOTAL_ORDER = 2,
+  StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_SIGNED = 3,
+  StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_UNSIGNED = 4,
+  StablehloComparisonType_MIN = StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_NOTYPE,
+  StablehloComparisonType_MAX = StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_UNSIGNED
+};
+
+inline const StablehloComparisonType (&EnumValuesStablehloComparisonType())[5]
+{
+  static const StablehloComparisonType values[] = {
+    StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_NOTYPE,
+    StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_FLOAT,
+    StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_FLOAT_TOTAL_ORDER,
+    StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_SIGNED,
+    StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_UNSIGNED};
+  return values;
+}
+
+inline const char *const *EnumNamesStablehloComparisonType()
+{
+  static const char *const names[6] = {"STABLEHLO_COMPARISON_TYPE_NOTYPE",
+                                       "STABLEHLO_COMPARISON_TYPE_FLOAT",
+                                       "STABLEHLO_COMPARISON_TYPE_FLOAT_TOTAL_ORDER",
+                                       "STABLEHLO_COMPARISON_TYPE_SIGNED",
+                                       "STABLEHLO_COMPARISON_TYPE_UNSIGNED",
+                                       nullptr};
+  return names;
+}
+
+inline const char *EnumNameStablehloComparisonType(StablehloComparisonType e)
+{
+  if (::flatbuffers::IsOutRange(e, StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_NOTYPE,
+                                StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_UNSIGNED))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesStablehloComparisonType()[index];
+}
+
+enum RngAlgorithm : int8_t
+{
+  RngAlgorithm_DEFAULT = 0,
+  RngAlgorithm_PHILOX = 1,
+  RngAlgorithm_THREEFRY = 2,
+  RngAlgorithm_MIN = RngAlgorithm_DEFAULT,
+  RngAlgorithm_MAX = RngAlgorithm_THREEFRY
+};
+
+inline const RngAlgorithm (&EnumValuesRngAlgorithm())[3]
+{
+  static const RngAlgorithm values[] = {RngAlgorithm_DEFAULT, RngAlgorithm_PHILOX,
+                                        RngAlgorithm_THREEFRY};
+  return values;
+}
+
+inline const char *const *EnumNamesRngAlgorithm()
+{
+  static const char *const names[4] = {"DEFAULT", "PHILOX", "THREEFRY", nullptr};
+  return names;
+}
+
+inline const char *EnumNameRngAlgorithm(RngAlgorithm e)
+{
+  if (::flatbuffers::IsOutRange(e, RngAlgorithm_DEFAULT, RngAlgorithm_THREEFRY))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesRngAlgorithm()[index];
+}
+
+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 ReduceWindowFunction : int32_t
+{
+  ReduceWindowFunction_UNSUPPORTED = 0,
+  ReduceWindowFunction_ADD = 1,
+  ReduceWindowFunction_MUL = 2,
+  ReduceWindowFunction_MINIMUM = 3,
+  ReduceWindowFunction_MAXIMUM = 4,
+  ReduceWindowFunction_ALL = 5,
+  ReduceWindowFunction_ANY = 6,
+  ReduceWindowFunction_MIN = ReduceWindowFunction_UNSUPPORTED,
+  ReduceWindowFunction_MAX = ReduceWindowFunction_ANY
+};
+
+inline const ReduceWindowFunction (&EnumValuesReduceWindowFunction())[7]
+{
+  static const ReduceWindowFunction values[] = {
+    ReduceWindowFunction_UNSUPPORTED, ReduceWindowFunction_ADD,     ReduceWindowFunction_MUL,
+    ReduceWindowFunction_MINIMUM,     ReduceWindowFunction_MAXIMUM, ReduceWindowFunction_ALL,
+    ReduceWindowFunction_ANY};
+  return values;
+}
+
+inline const char *const *EnumNamesReduceWindowFunction()
+{
+  static const char *const names[8] = {"UNSUPPORTED", "ADD", "MUL", "MINIMUM",
+                                       "MAXIMUM",     "ALL", "ANY", nullptr};
+  return names;
+}
+
+inline const char *EnumNameReduceWindowFunction(ReduceWindowFunction e)
+{
+  if (::flatbuffers::IsOutRange(e, ReduceWindowFunction_UNSUPPORTED, ReduceWindowFunction_ANY))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesReduceWindowFunction()[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, 1) &&
+           VerifyOffset(verifier, VT_DETAILS) &&
+           VerifyQuantizationDetails(verifier, details(), details_type()) &&
+           VerifyField<int32_t>(verifier, VT_QUANTIZED_DIMENSION, 4) && 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, 1) &&
+           VerifyField<int32_t>(verifier, VT_DENSE_SIZE, 4) &&
+           VerifyField<uint8_t>(verifier, VT_ARRAY_SEGMENTS_TYPE, 1) &&
+           VerifyOffset(verifier, VT_ARRAY_SEGMENTS) &&
+           VerifySparseIndexVector(verifier, array_segments(), array_segments_type()) &&
+           VerifyField<uint8_t>(verifier, VT_ARRAY_INDICES_TYPE, 1) &&
+           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{};
+  SparsityParametersT() = default;
+  SparsityParametersT(const SparsityParametersT &o);
+  SparsityParametersT(SparsityParametersT &&) FLATBUFFERS_NOEXCEPT = default;
+  SparsityParametersT &operator=(SparsityParametersT o) FLATBUFFERS_NOEXCEPT;
+};
+
+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 VariantSubTypeT : public ::flatbuffers::NativeTable
+{
+  typedef VariantSubType TableType;
+  std::vector<int32_t> shape{};
+  circle::TensorType type = circle::TensorType_FLOAT32;
+  bool has_rank = false;
+};
+
+struct VariantSubType FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef VariantSubTypeT NativeTableType;
+  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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_HAS_RANK, 1) && verifier.EndTable();
+  }
+  VariantSubTypeT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(VariantSubTypeT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<VariantSubType>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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);
+}
+
+::flatbuffers::Offset<VariantSubType>
+CreateVariantSubType(::flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT *_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{};
+  bool has_rank = false;
+  std::vector<std::unique_ptr<circle::VariantSubTypeT>> variant_tensors{};
+  TensorT() = default;
+  TensorT(const TensorT &o);
+  TensorT(TensorT &&) FLATBUFFERS_NOEXCEPT = default;
+  TensorT &operator=(TensorT o) FLATBUFFERS_NOEXCEPT;
+};
+
+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,
+    VT_HAS_RANK = 20,
+    VT_VARIANT_TENSORS = 22
+  };
+  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 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) &&
+           verifier.VerifyVector(shape()) && VerifyField<int8_t>(verifier, VT_TYPE, 1) &&
+           VerifyField<uint32_t>(verifier, VT_BUFFER, 4) && VerifyOffset(verifier, VT_NAME) &&
+           verifier.VerifyString(name()) && VerifyOffset(verifier, VT_QUANTIZATION) &&
+           verifier.VerifyTable(quantization()) &&
+           VerifyField<uint8_t>(verifier, VT_IS_VARIABLE, 1) &&
+           VerifyOffset(verifier, VT_SPARSITY) && verifier.VerifyTable(sparsity()) &&
+           VerifyOffset(verifier, VT_SHAPE_SIGNATURE) && verifier.VerifyVector(shape_signature()) &&
+           VerifyField<uint8_t>(verifier, VT_HAS_RANK, 1) &&
+           VerifyOffset(verifier, VT_VARIANT_TENSORS) && verifier.VerifyVector(variant_tensors()) &&
+           verifier.VerifyVectorOfTables(variant_tensors()) && 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);
+  }
+  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();
+  }
+  ::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, 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();
+}
+
+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, 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__, has_rank, variant_tensors__);
+}
+
+::flatbuffers::Offset<Tensor>
+CreateTensor(::flatbuffers::FlatBufferBuilder &_fbb, const TensorT *_o,
+             const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloGatherOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloGatherOptions TableType;
+  std::vector<int64_t> offset_dims{};
+  std::vector<int64_t> collapsed_slice_dims{};
+  std::vector<int64_t> start_index_map{};
+  int64_t index_vector_dim = 0;
+  std::vector<int64_t> slice_sizes{};
+  bool indices_are_sorted = false;
+};
+
+struct StablehloGatherOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloGatherOptionsT NativeTableType;
+  typedef StablehloGatherOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_OFFSET_DIMS = 4,
+    VT_COLLAPSED_SLICE_DIMS = 6,
+    VT_START_INDEX_MAP = 8,
+    VT_INDEX_VECTOR_DIM = 10,
+    VT_SLICE_SIZES = 12,
+    VT_INDICES_ARE_SORTED = 14
+  };
+  const ::flatbuffers::Vector<int64_t> *offset_dims() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_OFFSET_DIMS);
+  }
+  const ::flatbuffers::Vector<int64_t> *collapsed_slice_dims() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_COLLAPSED_SLICE_DIMS);
+  }
+  const ::flatbuffers::Vector<int64_t> *start_index_map() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_START_INDEX_MAP);
+  }
+  int64_t index_vector_dim() const { return GetField<int64_t>(VT_INDEX_VECTOR_DIM, 0); }
+  const ::flatbuffers::Vector<int64_t> *slice_sizes() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_SLICE_SIZES);
+  }
+  bool indices_are_sorted() const { return GetField<uint8_t>(VT_INDICES_ARE_SORTED, 0) != 0; }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_OFFSET_DIMS) &&
+           verifier.VerifyVector(offset_dims()) &&
+           VerifyOffset(verifier, VT_COLLAPSED_SLICE_DIMS) &&
+           verifier.VerifyVector(collapsed_slice_dims()) &&
+           VerifyOffset(verifier, VT_START_INDEX_MAP) && verifier.VerifyVector(start_index_map()) &&
+           VerifyField<int64_t>(verifier, VT_INDEX_VECTOR_DIM, 8) &&
+           VerifyOffset(verifier, VT_SLICE_SIZES) && verifier.VerifyVector(slice_sizes()) &&
+           VerifyField<uint8_t>(verifier, VT_INDICES_ARE_SORTED, 1) && verifier.EndTable();
+  }
+  StablehloGatherOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloGatherOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloGatherOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloGatherOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloGatherOptionsBuilder
+{
+  typedef StablehloGatherOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_offset_dims(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> offset_dims)
+  {
+    fbb_.AddOffset(StablehloGatherOptions::VT_OFFSET_DIMS, offset_dims);
+  }
+  void add_collapsed_slice_dims(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> collapsed_slice_dims)
+  {
+    fbb_.AddOffset(StablehloGatherOptions::VT_COLLAPSED_SLICE_DIMS, collapsed_slice_dims);
+  }
+  void add_start_index_map(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> start_index_map)
+  {
+    fbb_.AddOffset(StablehloGatherOptions::VT_START_INDEX_MAP, start_index_map);
+  }
+  void add_index_vector_dim(int64_t index_vector_dim)
+  {
+    fbb_.AddElement<int64_t>(StablehloGatherOptions::VT_INDEX_VECTOR_DIM, index_vector_dim, 0);
+  }
+  void add_slice_sizes(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> slice_sizes)
+  {
+    fbb_.AddOffset(StablehloGatherOptions::VT_SLICE_SIZES, slice_sizes);
+  }
+  void add_indices_are_sorted(bool indices_are_sorted)
+  {
+    fbb_.AddElement<uint8_t>(StablehloGatherOptions::VT_INDICES_ARE_SORTED,
+                             static_cast<uint8_t>(indices_are_sorted), 0);
+  }
+  explicit StablehloGatherOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloGatherOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloGatherOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloGatherOptions> CreateStablehloGatherOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> offset_dims = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> collapsed_slice_dims = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> start_index_map = 0,
+  int64_t index_vector_dim = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> slice_sizes = 0,
+  bool indices_are_sorted = false)
+{
+  StablehloGatherOptionsBuilder builder_(_fbb);
+  builder_.add_index_vector_dim(index_vector_dim);
+  builder_.add_slice_sizes(slice_sizes);
+  builder_.add_start_index_map(start_index_map);
+  builder_.add_collapsed_slice_dims(collapsed_slice_dims);
+  builder_.add_offset_dims(offset_dims);
+  builder_.add_indices_are_sorted(indices_are_sorted);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloGatherOptions> CreateStablehloGatherOptionsDirect(
+  ::flatbuffers::FlatBufferBuilder &_fbb, const std::vector<int64_t> *offset_dims = nullptr,
+  const std::vector<int64_t> *collapsed_slice_dims = nullptr,
+  const std::vector<int64_t> *start_index_map = nullptr, int64_t index_vector_dim = 0,
+  const std::vector<int64_t> *slice_sizes = nullptr, bool indices_are_sorted = false)
+{
+  auto offset_dims__ = offset_dims ? _fbb.CreateVector<int64_t>(*offset_dims) : 0;
+  auto collapsed_slice_dims__ =
+    collapsed_slice_dims ? _fbb.CreateVector<int64_t>(*collapsed_slice_dims) : 0;
+  auto start_index_map__ = start_index_map ? _fbb.CreateVector<int64_t>(*start_index_map) : 0;
+  auto slice_sizes__ = slice_sizes ? _fbb.CreateVector<int64_t>(*slice_sizes) : 0;
+  return circle::CreateStablehloGatherOptions(_fbb, offset_dims__, collapsed_slice_dims__,
+                                              start_index_map__, index_vector_dim, slice_sizes__,
+                                              indices_are_sorted);
+}
+
+::flatbuffers::Offset<StablehloGatherOptions>
+CreateStablehloGatherOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                             const StablehloGatherOptionsT *_o,
+                             const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloTransposeOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloTransposeOptions TableType;
+  std::vector<int64_t> permutation{};
+};
+
+struct StablehloTransposeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloTransposeOptionsT NativeTableType;
+  typedef StablehloTransposeOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_PERMUTATION = 4
+  };
+  const ::flatbuffers::Vector<int64_t> *permutation() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_PERMUTATION);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_PERMUTATION) &&
+           verifier.VerifyVector(permutation()) && verifier.EndTable();
+  }
+  StablehloTransposeOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloTransposeOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloTransposeOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloTransposeOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloTransposeOptionsBuilder
+{
+  typedef StablehloTransposeOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_permutation(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> permutation)
+  {
+    fbb_.AddOffset(StablehloTransposeOptions::VT_PERMUTATION, permutation);
+  }
+  explicit StablehloTransposeOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloTransposeOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloTransposeOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloTransposeOptions> CreateStablehloTransposeOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> permutation = 0)
+{
+  StablehloTransposeOptionsBuilder builder_(_fbb);
+  builder_.add_permutation(permutation);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloTransposeOptions>
+CreateStablehloTransposeOptionsDirect(::flatbuffers::FlatBufferBuilder &_fbb,
+                                      const std::vector<int64_t> *permutation = nullptr)
+{
+  auto permutation__ = permutation ? _fbb.CreateVector<int64_t>(*permutation) : 0;
+  return circle::CreateStablehloTransposeOptions(_fbb, permutation__);
+}
+
+::flatbuffers::Offset<StablehloTransposeOptions>
+CreateStablehloTransposeOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const StablehloTransposeOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloDotGeneralOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloDotGeneralOptions TableType;
+  std::vector<int64_t> lhs_batching_dimensions{};
+  std::vector<int64_t> rhs_batching_dimensions{};
+  std::vector<int64_t> lhs_contracting_dimensions{};
+  std::vector<int64_t> rhs_contracting_dimensions{};
+  std::vector<circle::StablehloPrecisionConfig> precision_config{};
+};
+
+struct StablehloDotGeneralOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloDotGeneralOptionsT NativeTableType;
+  typedef StablehloDotGeneralOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_LHS_BATCHING_DIMENSIONS = 4,
+    VT_RHS_BATCHING_DIMENSIONS = 6,
+    VT_LHS_CONTRACTING_DIMENSIONS = 8,
+    VT_RHS_CONTRACTING_DIMENSIONS = 10,
+    VT_PRECISION_CONFIG = 12
+  };
+  const ::flatbuffers::Vector<int64_t> *lhs_batching_dimensions() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_LHS_BATCHING_DIMENSIONS);
+  }
+  const ::flatbuffers::Vector<int64_t> *rhs_batching_dimensions() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_RHS_BATCHING_DIMENSIONS);
+  }
+  const ::flatbuffers::Vector<int64_t> *lhs_contracting_dimensions() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_LHS_CONTRACTING_DIMENSIONS);
+  }
+  const ::flatbuffers::Vector<int64_t> *rhs_contracting_dimensions() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_RHS_CONTRACTING_DIMENSIONS);
+  }
+  const ::flatbuffers::Vector<uint32_t> *precision_config() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<uint32_t> *>(VT_PRECISION_CONFIG);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_LHS_BATCHING_DIMENSIONS) &&
+           verifier.VerifyVector(lhs_batching_dimensions()) &&
+           VerifyOffset(verifier, VT_RHS_BATCHING_DIMENSIONS) &&
+           verifier.VerifyVector(rhs_batching_dimensions()) &&
+           VerifyOffset(verifier, VT_LHS_CONTRACTING_DIMENSIONS) &&
+           verifier.VerifyVector(lhs_contracting_dimensions()) &&
+           VerifyOffset(verifier, VT_RHS_CONTRACTING_DIMENSIONS) &&
+           verifier.VerifyVector(rhs_contracting_dimensions()) &&
+           VerifyOffset(verifier, VT_PRECISION_CONFIG) &&
+           verifier.VerifyVector(precision_config()) && verifier.EndTable();
+  }
+  StablehloDotGeneralOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloDotGeneralOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloDotGeneralOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloDotGeneralOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloDotGeneralOptionsBuilder
+{
+  typedef StablehloDotGeneralOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_lhs_batching_dimensions(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> lhs_batching_dimensions)
+  {
+    fbb_.AddOffset(StablehloDotGeneralOptions::VT_LHS_BATCHING_DIMENSIONS, lhs_batching_dimensions);
+  }
+  void add_rhs_batching_dimensions(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> rhs_batching_dimensions)
+  {
+    fbb_.AddOffset(StablehloDotGeneralOptions::VT_RHS_BATCHING_DIMENSIONS, rhs_batching_dimensions);
+  }
+  void add_lhs_contracting_dimensions(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> lhs_contracting_dimensions)
+  {
+    fbb_.AddOffset(StablehloDotGeneralOptions::VT_LHS_CONTRACTING_DIMENSIONS,
+                   lhs_contracting_dimensions);
+  }
+  void add_rhs_contracting_dimensions(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> rhs_contracting_dimensions)
+  {
+    fbb_.AddOffset(StablehloDotGeneralOptions::VT_RHS_CONTRACTING_DIMENSIONS,
+                   rhs_contracting_dimensions);
+  }
+  void add_precision_config(::flatbuffers::Offset<::flatbuffers::Vector<uint32_t>> precision_config)
+  {
+    fbb_.AddOffset(StablehloDotGeneralOptions::VT_PRECISION_CONFIG, precision_config);
+  }
+  explicit StablehloDotGeneralOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloDotGeneralOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloDotGeneralOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloDotGeneralOptions> CreateStablehloDotGeneralOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> lhs_batching_dimensions = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> rhs_batching_dimensions = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> lhs_contracting_dimensions = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> rhs_contracting_dimensions = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<uint32_t>> precision_config = 0)
+{
+  StablehloDotGeneralOptionsBuilder builder_(_fbb);
+  builder_.add_precision_config(precision_config);
+  builder_.add_rhs_contracting_dimensions(rhs_contracting_dimensions);
+  builder_.add_lhs_contracting_dimensions(lhs_contracting_dimensions);
+  builder_.add_rhs_batching_dimensions(rhs_batching_dimensions);
+  builder_.add_lhs_batching_dimensions(lhs_batching_dimensions);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloDotGeneralOptions> CreateStablehloDotGeneralOptionsDirect(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  const std::vector<int64_t> *lhs_batching_dimensions = nullptr,
+  const std::vector<int64_t> *rhs_batching_dimensions = nullptr,
+  const std::vector<int64_t> *lhs_contracting_dimensions = nullptr,
+  const std::vector<int64_t> *rhs_contracting_dimensions = nullptr,
+  const std::vector<uint32_t> *precision_config = nullptr)
+{
+  auto lhs_batching_dimensions__ =
+    lhs_batching_dimensions ? _fbb.CreateVector<int64_t>(*lhs_batching_dimensions) : 0;
+  auto rhs_batching_dimensions__ =
+    rhs_batching_dimensions ? _fbb.CreateVector<int64_t>(*rhs_batching_dimensions) : 0;
+  auto lhs_contracting_dimensions__ =
+    lhs_contracting_dimensions ? _fbb.CreateVector<int64_t>(*lhs_contracting_dimensions) : 0;
+  auto rhs_contracting_dimensions__ =
+    rhs_contracting_dimensions ? _fbb.CreateVector<int64_t>(*rhs_contracting_dimensions) : 0;
+  auto precision_config__ = precision_config ? _fbb.CreateVector<uint32_t>(*precision_config) : 0;
+  return circle::CreateStablehloDotGeneralOptions(
+    _fbb, lhs_batching_dimensions__, rhs_batching_dimensions__, lhs_contracting_dimensions__,
+    rhs_contracting_dimensions__, precision_config__);
+}
+
+::flatbuffers::Offset<StablehloDotGeneralOptions>
+CreateStablehloDotGeneralOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                 const StablehloDotGeneralOptionsT *_o,
+                                 const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloReduceWindowOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloReduceWindowOptions TableType;
+  std::vector<int64_t> window_dimensions{};
+  std::vector<int64_t> window_strides{};
+  std::vector<int64_t> base_dilations{};
+  std::vector<int64_t> window_dilations{};
+  std::vector<int64_t> padding{};
+  int32_t body_subgraph_index = 0;
+};
+
+struct StablehloReduceWindowOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloReduceWindowOptionsT NativeTableType;
+  typedef StablehloReduceWindowOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_WINDOW_DIMENSIONS = 4,
+    VT_WINDOW_STRIDES = 6,
+    VT_BASE_DILATIONS = 8,
+    VT_WINDOW_DILATIONS = 10,
+    VT_PADDING = 12,
+    VT_BODY_SUBGRAPH_INDEX = 14
+  };
+  const ::flatbuffers::Vector<int64_t> *window_dimensions() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_WINDOW_DIMENSIONS);
+  }
+  const ::flatbuffers::Vector<int64_t> *window_strides() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_WINDOW_STRIDES);
+  }
+  const ::flatbuffers::Vector<int64_t> *base_dilations() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_BASE_DILATIONS);
+  }
+  const ::flatbuffers::Vector<int64_t> *window_dilations() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_WINDOW_DILATIONS);
+  }
+  const ::flatbuffers::Vector<int64_t> *padding() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_PADDING);
+  }
+  int32_t body_subgraph_index() const { return GetField<int32_t>(VT_BODY_SUBGRAPH_INDEX, 0); }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_WINDOW_DIMENSIONS) &&
+           verifier.VerifyVector(window_dimensions()) &&
+           VerifyOffset(verifier, VT_WINDOW_STRIDES) && verifier.VerifyVector(window_strides()) &&
+           VerifyOffset(verifier, VT_BASE_DILATIONS) && verifier.VerifyVector(base_dilations()) &&
+           VerifyOffset(verifier, VT_WINDOW_DILATIONS) &&
+           verifier.VerifyVector(window_dilations()) && VerifyOffset(verifier, VT_PADDING) &&
+           verifier.VerifyVector(padding()) &&
+           VerifyField<int32_t>(verifier, VT_BODY_SUBGRAPH_INDEX, 4) && verifier.EndTable();
+  }
+  StablehloReduceWindowOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloReduceWindowOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloReduceWindowOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloReduceWindowOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloReduceWindowOptionsBuilder
+{
+  typedef StablehloReduceWindowOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void
+  add_window_dimensions(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> window_dimensions)
+  {
+    fbb_.AddOffset(StablehloReduceWindowOptions::VT_WINDOW_DIMENSIONS, window_dimensions);
+  }
+  void add_window_strides(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> window_strides)
+  {
+    fbb_.AddOffset(StablehloReduceWindowOptions::VT_WINDOW_STRIDES, window_strides);
+  }
+  void add_base_dilations(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> base_dilations)
+  {
+    fbb_.AddOffset(StablehloReduceWindowOptions::VT_BASE_DILATIONS, base_dilations);
+  }
+  void add_window_dilations(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> window_dilations)
+  {
+    fbb_.AddOffset(StablehloReduceWindowOptions::VT_WINDOW_DILATIONS, window_dilations);
+  }
+  void add_padding(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> padding)
+  {
+    fbb_.AddOffset(StablehloReduceWindowOptions::VT_PADDING, padding);
+  }
+  void add_body_subgraph_index(int32_t body_subgraph_index)
+  {
+    fbb_.AddElement<int32_t>(StablehloReduceWindowOptions::VT_BODY_SUBGRAPH_INDEX,
+                             body_subgraph_index, 0);
+  }
+  explicit StablehloReduceWindowOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloReduceWindowOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloReduceWindowOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloReduceWindowOptions> CreateStablehloReduceWindowOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> window_dimensions = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> window_strides = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> base_dilations = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> window_dilations = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> padding = 0,
+  int32_t body_subgraph_index = 0)
+{
+  StablehloReduceWindowOptionsBuilder builder_(_fbb);
+  builder_.add_body_subgraph_index(body_subgraph_index);
+  builder_.add_padding(padding);
+  builder_.add_window_dilations(window_dilations);
+  builder_.add_base_dilations(base_dilations);
+  builder_.add_window_strides(window_strides);
+  builder_.add_window_dimensions(window_dimensions);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloReduceWindowOptions> CreateStablehloReduceWindowOptionsDirect(
+  ::flatbuffers::FlatBufferBuilder &_fbb, const std::vector<int64_t> *window_dimensions = nullptr,
+  const std::vector<int64_t> *window_strides = nullptr,
+  const std::vector<int64_t> *base_dilations = nullptr,
+  const std::vector<int64_t> *window_dilations = nullptr,
+  const std::vector<int64_t> *padding = nullptr, int32_t body_subgraph_index = 0)
+{
+  auto window_dimensions__ = window_dimensions ? _fbb.CreateVector<int64_t>(*window_dimensions) : 0;
+  auto window_strides__ = window_strides ? _fbb.CreateVector<int64_t>(*window_strides) : 0;
+  auto base_dilations__ = base_dilations ? _fbb.CreateVector<int64_t>(*base_dilations) : 0;
+  auto window_dilations__ = window_dilations ? _fbb.CreateVector<int64_t>(*window_dilations) : 0;
+  auto padding__ = padding ? _fbb.CreateVector<int64_t>(*padding) : 0;
+  return circle::CreateStablehloReduceWindowOptions(_fbb, window_dimensions__, window_strides__,
+                                                    base_dilations__, window_dilations__, padding__,
+                                                    body_subgraph_index);
+}
+
+::flatbuffers::Offset<StablehloReduceWindowOptions>
+CreateStablehloReduceWindowOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                   const StablehloReduceWindowOptionsT *_o,
+                                   const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloWhileOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloWhileOptions TableType;
+  int32_t cond_subgraph_index = 0;
+  int32_t body_subgraph_index = 0;
+};
+
+struct StablehloWhileOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloWhileOptionsT NativeTableType;
+  typedef StablehloWhileOptionsBuilder 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, 4) &&
+           VerifyField<int32_t>(verifier, VT_BODY_SUBGRAPH_INDEX, 4) && verifier.EndTable();
+  }
+  StablehloWhileOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloWhileOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloWhileOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloWhileOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloWhileOptionsBuilder
+{
+  typedef StablehloWhileOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_cond_subgraph_index(int32_t cond_subgraph_index)
+  {
+    fbb_.AddElement<int32_t>(StablehloWhileOptions::VT_COND_SUBGRAPH_INDEX, cond_subgraph_index, 0);
+  }
+  void add_body_subgraph_index(int32_t body_subgraph_index)
+  {
+    fbb_.AddElement<int32_t>(StablehloWhileOptions::VT_BODY_SUBGRAPH_INDEX, body_subgraph_index, 0);
+  }
+  explicit StablehloWhileOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloWhileOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloWhileOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloWhileOptions>
+CreateStablehloWhileOptions(::flatbuffers::FlatBufferBuilder &_fbb, int32_t cond_subgraph_index = 0,
+                            int32_t body_subgraph_index = 0)
+{
+  StablehloWhileOptionsBuilder builder_(_fbb);
+  builder_.add_body_subgraph_index(body_subgraph_index);
+  builder_.add_cond_subgraph_index(cond_subgraph_index);
+  return builder_.Finish();
+}
+
+::flatbuffers::Offset<StablehloWhileOptions>
+CreateStablehloWhileOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                            const StablehloWhileOptionsT *_o,
+                            const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloSortOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloSortOptions TableType;
+  int64_t dimension = 0;
+  bool is_stable = false;
+  int32_t comparator_subgraph_index = 0;
+};
+
+struct StablehloSortOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloSortOptionsT NativeTableType;
+  typedef StablehloSortOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_DIMENSION = 4,
+    VT_IS_STABLE = 6,
+    VT_COMPARATOR_SUBGRAPH_INDEX = 8
+  };
+  int64_t dimension() const { return GetField<int64_t>(VT_DIMENSION, 0); }
+  bool is_stable() const { return GetField<uint8_t>(VT_IS_STABLE, 0) != 0; }
+  int32_t comparator_subgraph_index() const
+  {
+    return GetField<int32_t>(VT_COMPARATOR_SUBGRAPH_INDEX, 0);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int64_t>(verifier, VT_DIMENSION, 8) &&
+           VerifyField<uint8_t>(verifier, VT_IS_STABLE, 1) &&
+           VerifyField<int32_t>(verifier, VT_COMPARATOR_SUBGRAPH_INDEX, 4) && verifier.EndTable();
+  }
+  StablehloSortOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloSortOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloSortOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloSortOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloSortOptionsBuilder
+{
+  typedef StablehloSortOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_dimension(int64_t dimension)
+  {
+    fbb_.AddElement<int64_t>(StablehloSortOptions::VT_DIMENSION, dimension, 0);
+  }
+  void add_is_stable(bool is_stable)
+  {
+    fbb_.AddElement<uint8_t>(StablehloSortOptions::VT_IS_STABLE, static_cast<uint8_t>(is_stable),
+                             0);
+  }
+  void add_comparator_subgraph_index(int32_t comparator_subgraph_index)
+  {
+    fbb_.AddElement<int32_t>(StablehloSortOptions::VT_COMPARATOR_SUBGRAPH_INDEX,
+                             comparator_subgraph_index, 0);
+  }
+  explicit StablehloSortOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloSortOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloSortOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloSortOptions>
+CreateStablehloSortOptions(::flatbuffers::FlatBufferBuilder &_fbb, int64_t dimension = 0,
+                           bool is_stable = false, int32_t comparator_subgraph_index = 0)
+{
+  StablehloSortOptionsBuilder builder_(_fbb);
+  builder_.add_dimension(dimension);
+  builder_.add_comparator_subgraph_index(comparator_subgraph_index);
+  builder_.add_is_stable(is_stable);
+  return builder_.Finish();
+}
+
+::flatbuffers::Offset<StablehloSortOptions>
+CreateStablehloSortOptions(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloSortOptionsT *_o,
+                           const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloConcatenateOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloConcatenateOptions TableType;
+  int64_t dimension = 0;
+};
+
+struct StablehloConcatenateOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloConcatenateOptionsT NativeTableType;
+  typedef StablehloConcatenateOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_DIMENSION = 4
+  };
+  int64_t dimension() const { return GetField<int64_t>(VT_DIMENSION, 0); }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int64_t>(verifier, VT_DIMENSION, 8) &&
+           verifier.EndTable();
+  }
+  StablehloConcatenateOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloConcatenateOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloConcatenateOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloConcatenateOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloConcatenateOptionsBuilder
+{
+  typedef StablehloConcatenateOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_dimension(int64_t dimension)
+  {
+    fbb_.AddElement<int64_t>(StablehloConcatenateOptions::VT_DIMENSION, dimension, 0);
+  }
+  explicit StablehloConcatenateOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloConcatenateOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloConcatenateOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloConcatenateOptions>
+CreateStablehloConcatenateOptions(::flatbuffers::FlatBufferBuilder &_fbb, int64_t dimension = 0)
+{
+  StablehloConcatenateOptionsBuilder builder_(_fbb);
+  builder_.add_dimension(dimension);
+  return builder_.Finish();
+}
+
+::flatbuffers::Offset<StablehloConcatenateOptions>
+CreateStablehloConcatenateOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                  const StablehloConcatenateOptionsT *_o,
+                                  const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloBroadcastInDimOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloBroadcastInDimOptions TableType;
+  std::vector<int64_t> broadcast_dimensions{};
+};
+
+struct StablehloBroadcastInDimOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloBroadcastInDimOptionsT NativeTableType;
+  typedef StablehloBroadcastInDimOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_BROADCAST_DIMENSIONS = 4
+  };
+  const ::flatbuffers::Vector<int64_t> *broadcast_dimensions() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_BROADCAST_DIMENSIONS);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_BROADCAST_DIMENSIONS) &&
+           verifier.VerifyVector(broadcast_dimensions()) && verifier.EndTable();
+  }
+  StablehloBroadcastInDimOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloBroadcastInDimOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloBroadcastInDimOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloBroadcastInDimOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloBroadcastInDimOptionsBuilder
+{
+  typedef StablehloBroadcastInDimOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_broadcast_dimensions(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> broadcast_dimensions)
+  {
+    fbb_.AddOffset(StablehloBroadcastInDimOptions::VT_BROADCAST_DIMENSIONS, broadcast_dimensions);
+  }
+  explicit StablehloBroadcastInDimOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
+    : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloBroadcastInDimOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloBroadcastInDimOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloBroadcastInDimOptions> CreateStablehloBroadcastInDimOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> broadcast_dimensions = 0)
+{
+  StablehloBroadcastInDimOptionsBuilder builder_(_fbb);
+  builder_.add_broadcast_dimensions(broadcast_dimensions);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloBroadcastInDimOptions>
+CreateStablehloBroadcastInDimOptionsDirect(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  const std::vector<int64_t> *broadcast_dimensions = nullptr)
+{
+  auto broadcast_dimensions__ =
+    broadcast_dimensions ? _fbb.CreateVector<int64_t>(*broadcast_dimensions) : 0;
+  return circle::CreateStablehloBroadcastInDimOptions(_fbb, broadcast_dimensions__);
+}
+
+::flatbuffers::Offset<StablehloBroadcastInDimOptions>
+CreateStablehloBroadcastInDimOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                     const StablehloBroadcastInDimOptionsT *_o,
+                                     const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloCompareOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloCompareOptions TableType;
+  circle::StablehloComparisonDirection comparison_direction =
+    circle::StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_EQ;
+  circle::StablehloComparisonType compare_type =
+    circle::StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_NOTYPE;
+};
+
+struct StablehloCompareOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloCompareOptionsT NativeTableType;
+  typedef StablehloCompareOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_COMPARISON_DIRECTION = 4,
+    VT_COMPARE_TYPE = 6
+  };
+  circle::StablehloComparisonDirection comparison_direction() const
+  {
+    return static_cast<circle::StablehloComparisonDirection>(
+      GetField<uint32_t>(VT_COMPARISON_DIRECTION, 0));
+  }
+  circle::StablehloComparisonType compare_type() const
+  {
+    return static_cast<circle::StablehloComparisonType>(GetField<uint32_t>(VT_COMPARE_TYPE, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) &&
+           VerifyField<uint32_t>(verifier, VT_COMPARISON_DIRECTION, 4) &&
+           VerifyField<uint32_t>(verifier, VT_COMPARE_TYPE, 4) && verifier.EndTable();
+  }
+  StablehloCompareOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloCompareOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloCompareOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloCompareOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloCompareOptionsBuilder
+{
+  typedef StablehloCompareOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_comparison_direction(circle::StablehloComparisonDirection comparison_direction)
+  {
+    fbb_.AddElement<uint32_t>(StablehloCompareOptions::VT_COMPARISON_DIRECTION,
+                              static_cast<uint32_t>(comparison_direction), 0);
+  }
+  void add_compare_type(circle::StablehloComparisonType compare_type)
+  {
+    fbb_.AddElement<uint32_t>(StablehloCompareOptions::VT_COMPARE_TYPE,
+                              static_cast<uint32_t>(compare_type), 0);
+  }
+  explicit StablehloCompareOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloCompareOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloCompareOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloCompareOptions> CreateStablehloCompareOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  circle::StablehloComparisonDirection comparison_direction =
+    circle::StablehloComparisonDirection_STABLEHLO_COMPARISON_DIRECTION_EQ,
+  circle::StablehloComparisonType compare_type =
+    circle::StablehloComparisonType_STABLEHLO_COMPARISON_TYPE_NOTYPE)
+{
+  StablehloCompareOptionsBuilder builder_(_fbb);
+  builder_.add_compare_type(compare_type);
+  builder_.add_comparison_direction(comparison_direction);
+  return builder_.Finish();
+}
+
+::flatbuffers::Offset<StablehloCompareOptions>
+CreateStablehloCompareOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                              const StablehloCompareOptionsT *_o,
+                              const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloDynamicSliceOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloDynamicSliceOptions TableType;
+  std::vector<int64_t> slice_sizes{};
+};
+
+struct StablehloDynamicSliceOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloDynamicSliceOptionsT NativeTableType;
+  typedef StablehloDynamicSliceOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_SLICE_SIZES = 4
+  };
+  const ::flatbuffers::Vector<int64_t> *slice_sizes() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_SLICE_SIZES);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_SLICE_SIZES) &&
+           verifier.VerifyVector(slice_sizes()) && verifier.EndTable();
+  }
+  StablehloDynamicSliceOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloDynamicSliceOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloDynamicSliceOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloDynamicSliceOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloDynamicSliceOptionsBuilder
+{
+  typedef StablehloDynamicSliceOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_slice_sizes(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> slice_sizes)
+  {
+    fbb_.AddOffset(StablehloDynamicSliceOptions::VT_SLICE_SIZES, slice_sizes);
+  }
+  explicit StablehloDynamicSliceOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloDynamicSliceOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloDynamicSliceOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloDynamicSliceOptions> CreateStablehloDynamicSliceOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> slice_sizes = 0)
+{
+  StablehloDynamicSliceOptionsBuilder builder_(_fbb);
+  builder_.add_slice_sizes(slice_sizes);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloDynamicSliceOptions>
+CreateStablehloDynamicSliceOptionsDirect(::flatbuffers::FlatBufferBuilder &_fbb,
+                                         const std::vector<int64_t> *slice_sizes = nullptr)
+{
+  auto slice_sizes__ = slice_sizes ? _fbb.CreateVector<int64_t>(*slice_sizes) : 0;
+  return circle::CreateStablehloDynamicSliceOptions(_fbb, slice_sizes__);
+}
+
+::flatbuffers::Offset<StablehloDynamicSliceOptions>
+CreateStablehloDynamicSliceOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                   const StablehloDynamicSliceOptionsT *_o,
+                                   const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloPadOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloPadOptions TableType;
+  std::vector<int64_t> edge_padding_low{};
+  std::vector<int64_t> edge_padding_high{};
+  std::vector<int64_t> interior_padding{};
+};
+
+struct StablehloPadOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloPadOptionsT NativeTableType;
+  typedef StablehloPadOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_EDGE_PADDING_LOW = 4,
+    VT_EDGE_PADDING_HIGH = 6,
+    VT_INTERIOR_PADDING = 8
+  };
+  const ::flatbuffers::Vector<int64_t> *edge_padding_low() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_EDGE_PADDING_LOW);
+  }
+  const ::flatbuffers::Vector<int64_t> *edge_padding_high() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_EDGE_PADDING_HIGH);
+  }
+  const ::flatbuffers::Vector<int64_t> *interior_padding() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_INTERIOR_PADDING);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_EDGE_PADDING_LOW) &&
+           verifier.VerifyVector(edge_padding_low()) &&
+           VerifyOffset(verifier, VT_EDGE_PADDING_HIGH) &&
+           verifier.VerifyVector(edge_padding_high()) &&
+           VerifyOffset(verifier, VT_INTERIOR_PADDING) &&
+           verifier.VerifyVector(interior_padding()) && verifier.EndTable();
+  }
+  StablehloPadOptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloPadOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloPadOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloPadOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloPadOptionsBuilder
+{
+  typedef StablehloPadOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_edge_padding_low(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> edge_padding_low)
+  {
+    fbb_.AddOffset(StablehloPadOptions::VT_EDGE_PADDING_LOW, edge_padding_low);
+  }
+  void
+  add_edge_padding_high(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> edge_padding_high)
+  {
+    fbb_.AddOffset(StablehloPadOptions::VT_EDGE_PADDING_HIGH, edge_padding_high);
+  }
+  void add_interior_padding(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> interior_padding)
+  {
+    fbb_.AddOffset(StablehloPadOptions::VT_INTERIOR_PADDING, interior_padding);
+  }
+  explicit StablehloPadOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloPadOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloPadOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloPadOptions> CreateStablehloPadOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> edge_padding_low = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> edge_padding_high = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> interior_padding = 0)
+{
+  StablehloPadOptionsBuilder builder_(_fbb);
+  builder_.add_interior_padding(interior_padding);
+  builder_.add_edge_padding_high(edge_padding_high);
+  builder_.add_edge_padding_low(edge_padding_low);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloPadOptions>
+CreateStablehloPadOptionsDirect(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const std::vector<int64_t> *edge_padding_low = nullptr,
+                                const std::vector<int64_t> *edge_padding_high = nullptr,
+                                const std::vector<int64_t> *interior_padding = nullptr)
+{
+  auto edge_padding_low__ = edge_padding_low ? _fbb.CreateVector<int64_t>(*edge_padding_low) : 0;
+  auto edge_padding_high__ = edge_padding_high ? _fbb.CreateVector<int64_t>(*edge_padding_high) : 0;
+  auto interior_padding__ = interior_padding ? _fbb.CreateVector<int64_t>(*interior_padding) : 0;
+  return circle::CreateStablehloPadOptions(_fbb, edge_padding_low__, edge_padding_high__,
+                                           interior_padding__);
+}
+
+::flatbuffers::Offset<StablehloPadOptions>
+CreateStablehloPadOptions(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloPadOptionsT *_o,
+                          const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloIotaOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloIotaOptions TableType;
+  int64_t iota_dimension = 0;
+};
+
+struct StablehloIotaOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloIotaOptionsT NativeTableType;
+  typedef StablehloIotaOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_IOTA_DIMENSION = 4
+  };
+  int64_t iota_dimension() const { return GetField<int64_t>(VT_IOTA_DIMENSION, 0); }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int64_t>(verifier, VT_IOTA_DIMENSION, 8) &&
+           verifier.EndTable();
+  }
+  StablehloIotaOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloIotaOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloIotaOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloIotaOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloIotaOptionsBuilder
+{
+  typedef StablehloIotaOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_iota_dimension(int64_t iota_dimension)
+  {
+    fbb_.AddElement<int64_t>(StablehloIotaOptions::VT_IOTA_DIMENSION, iota_dimension, 0);
+  }
+  explicit StablehloIotaOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloIotaOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloIotaOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloIotaOptions>
+CreateStablehloIotaOptions(::flatbuffers::FlatBufferBuilder &_fbb, int64_t iota_dimension = 0)
+{
+  StablehloIotaOptionsBuilder builder_(_fbb);
+  builder_.add_iota_dimension(iota_dimension);
+  return builder_.Finish();
+}
+
+::flatbuffers::Offset<StablehloIotaOptions>
+CreateStablehloIotaOptions(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloIotaOptionsT *_o,
+                           const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloCustomCallOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloCustomCallOptions TableType;
+  std::string call_target_name{};
+  bool has_side_effect = false;
+  std::string backend_config{};
+  int32_t api_version = 0;
+  std::vector<int32_t> called_computations{};
+  std::vector<uint8_t> custom_attributes{};
+};
+
+struct StablehloCustomCallOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloCustomCallOptionsT NativeTableType;
+  typedef StablehloCustomCallOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_CALL_TARGET_NAME = 4,
+    VT_HAS_SIDE_EFFECT = 6,
+    VT_BACKEND_CONFIG = 8,
+    VT_API_VERSION = 10,
+    VT_CALLED_COMPUTATIONS = 12,
+    VT_CUSTOM_ATTRIBUTES = 14
+  };
+  const ::flatbuffers::String *call_target_name() const
+  {
+    return GetPointer<const ::flatbuffers::String *>(VT_CALL_TARGET_NAME);
+  }
+  bool has_side_effect() const { return GetField<uint8_t>(VT_HAS_SIDE_EFFECT, 0) != 0; }
+  const ::flatbuffers::String *backend_config() const
+  {
+    return GetPointer<const ::flatbuffers::String *>(VT_BACKEND_CONFIG);
+  }
+  int32_t api_version() const { return GetField<int32_t>(VT_API_VERSION, 0); }
+  const ::flatbuffers::Vector<int32_t> *called_computations() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int32_t> *>(VT_CALLED_COMPUTATIONS);
+  }
+  const ::flatbuffers::Vector<uint8_t> *custom_attributes() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_CUSTOM_ATTRIBUTES);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_CALL_TARGET_NAME) &&
+           verifier.VerifyString(call_target_name()) &&
+           VerifyField<uint8_t>(verifier, VT_HAS_SIDE_EFFECT, 1) &&
+           VerifyOffset(verifier, VT_BACKEND_CONFIG) && verifier.VerifyString(backend_config()) &&
+           VerifyField<int32_t>(verifier, VT_API_VERSION, 4) &&
+           VerifyOffset(verifier, VT_CALLED_COMPUTATIONS) &&
+           verifier.VerifyVector(called_computations()) &&
+           VerifyOffset(verifier, VT_CUSTOM_ATTRIBUTES) &&
+           verifier.VerifyVector(custom_attributes()) && verifier.EndTable();
+  }
+  StablehloCustomCallOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloCustomCallOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloCustomCallOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloCustomCallOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloCustomCallOptionsBuilder
+{
+  typedef StablehloCustomCallOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_call_target_name(::flatbuffers::Offset<::flatbuffers::String> call_target_name)
+  {
+    fbb_.AddOffset(StablehloCustomCallOptions::VT_CALL_TARGET_NAME, call_target_name);
+  }
+  void add_has_side_effect(bool has_side_effect)
+  {
+    fbb_.AddElement<uint8_t>(StablehloCustomCallOptions::VT_HAS_SIDE_EFFECT,
+                             static_cast<uint8_t>(has_side_effect), 0);
+  }
+  void add_backend_config(::flatbuffers::Offset<::flatbuffers::String> backend_config)
+  {
+    fbb_.AddOffset(StablehloCustomCallOptions::VT_BACKEND_CONFIG, backend_config);
+  }
+  void add_api_version(int32_t api_version)
+  {
+    fbb_.AddElement<int32_t>(StablehloCustomCallOptions::VT_API_VERSION, api_version, 0);
+  }
+  void
+  add_called_computations(::flatbuffers::Offset<::flatbuffers::Vector<int32_t>> called_computations)
+  {
+    fbb_.AddOffset(StablehloCustomCallOptions::VT_CALLED_COMPUTATIONS, called_computations);
+  }
+  void
+  add_custom_attributes(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> custom_attributes)
+  {
+    fbb_.AddOffset(StablehloCustomCallOptions::VT_CUSTOM_ATTRIBUTES, custom_attributes);
+  }
+  explicit StablehloCustomCallOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloCustomCallOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloCustomCallOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloCustomCallOptions> CreateStablehloCustomCallOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  ::flatbuffers::Offset<::flatbuffers::String> call_target_name = 0, bool has_side_effect = false,
+  ::flatbuffers::Offset<::flatbuffers::String> backend_config = 0, int32_t api_version = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int32_t>> called_computations = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> custom_attributes = 0)
+{
+  StablehloCustomCallOptionsBuilder builder_(_fbb);
+  builder_.add_custom_attributes(custom_attributes);
+  builder_.add_called_computations(called_computations);
+  builder_.add_api_version(api_version);
+  builder_.add_backend_config(backend_config);
+  builder_.add_call_target_name(call_target_name);
+  builder_.add_has_side_effect(has_side_effect);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloCustomCallOptions> CreateStablehloCustomCallOptionsDirect(
+  ::flatbuffers::FlatBufferBuilder &_fbb, const char *call_target_name = nullptr,
+  bool has_side_effect = false, const char *backend_config = nullptr, int32_t api_version = 0,
+  const std::vector<int32_t> *called_computations = nullptr,
+  const std::vector<uint8_t> *custom_attributes = nullptr)
+{
+  auto call_target_name__ = call_target_name ? _fbb.CreateString(call_target_name) : 0;
+  auto backend_config__ = backend_config ? _fbb.CreateString(backend_config) : 0;
+  auto called_computations__ =
+    called_computations ? _fbb.CreateVector<int32_t>(*called_computations) : 0;
+  auto custom_attributes__ = custom_attributes ? _fbb.CreateVector<uint8_t>(*custom_attributes) : 0;
+  return circle::CreateStablehloCustomCallOptions(_fbb, call_target_name__, has_side_effect,
+                                                  backend_config__, api_version,
+                                                  called_computations__, custom_attributes__);
+}
+
+::flatbuffers::Offset<StablehloCustomCallOptions>
+CreateStablehloCustomCallOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                 const StablehloCustomCallOptionsT *_o,
+                                 const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloReduceOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloReduceOptions TableType;
+  std::vector<int64_t> dimensions{};
+  int32_t body_subgraph_index = 0;
+};
+
+struct StablehloReduceOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloReduceOptionsT NativeTableType;
+  typedef StablehloReduceOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_DIMENSIONS = 4,
+    VT_BODY_SUBGRAPH_INDEX = 6
+  };
+  const ::flatbuffers::Vector<int64_t> *dimensions() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_DIMENSIONS);
+  }
+  int32_t body_subgraph_index() const { return GetField<int32_t>(VT_BODY_SUBGRAPH_INDEX, 0); }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_DIMENSIONS) &&
+           verifier.VerifyVector(dimensions()) &&
+           VerifyField<int32_t>(verifier, VT_BODY_SUBGRAPH_INDEX, 4) && verifier.EndTable();
+  }
+  StablehloReduceOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloReduceOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloReduceOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloReduceOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloReduceOptionsBuilder
+{
+  typedef StablehloReduceOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_dimensions(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> dimensions)
+  {
+    fbb_.AddOffset(StablehloReduceOptions::VT_DIMENSIONS, dimensions);
+  }
+  void add_body_subgraph_index(int32_t body_subgraph_index)
+  {
+    fbb_.AddElement<int32_t>(StablehloReduceOptions::VT_BODY_SUBGRAPH_INDEX, body_subgraph_index,
+                             0);
+  }
+  explicit StablehloReduceOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloReduceOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloReduceOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloReduceOptions>
+CreateStablehloReduceOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                             ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> dimensions = 0,
+                             int32_t body_subgraph_index = 0)
+{
+  StablehloReduceOptionsBuilder builder_(_fbb);
+  builder_.add_body_subgraph_index(body_subgraph_index);
+  builder_.add_dimensions(dimensions);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloReduceOptions>
+CreateStablehloReduceOptionsDirect(::flatbuffers::FlatBufferBuilder &_fbb,
+                                   const std::vector<int64_t> *dimensions = nullptr,
+                                   int32_t body_subgraph_index = 0)
+{
+  auto dimensions__ = dimensions ? _fbb.CreateVector<int64_t>(*dimensions) : 0;
+  return circle::CreateStablehloReduceOptions(_fbb, dimensions__, body_subgraph_index);
+}
+
+::flatbuffers::Offset<StablehloReduceOptions>
+CreateStablehloReduceOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                             const StablehloReduceOptionsT *_o,
+                             const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloSliceOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloSliceOptions TableType;
+  std::vector<int64_t> start_indices{};
+  std::vector<int64_t> limit_indices{};
+  std::vector<int64_t> strides{};
+};
+
+struct StablehloSliceOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloSliceOptionsT NativeTableType;
+  typedef StablehloSliceOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_START_INDICES = 4,
+    VT_LIMIT_INDICES = 6,
+    VT_STRIDES = 8
+  };
+  const ::flatbuffers::Vector<int64_t> *start_indices() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_START_INDICES);
+  }
+  const ::flatbuffers::Vector<int64_t> *limit_indices() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_LIMIT_INDICES);
+  }
+  const ::flatbuffers::Vector<int64_t> *strides() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_STRIDES);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_START_INDICES) &&
+           verifier.VerifyVector(start_indices()) && VerifyOffset(verifier, VT_LIMIT_INDICES) &&
+           verifier.VerifyVector(limit_indices()) && VerifyOffset(verifier, VT_STRIDES) &&
+           verifier.VerifyVector(strides()) && verifier.EndTable();
+  }
+  StablehloSliceOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloSliceOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloSliceOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloSliceOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloSliceOptionsBuilder
+{
+  typedef StablehloSliceOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_start_indices(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> start_indices)
+  {
+    fbb_.AddOffset(StablehloSliceOptions::VT_START_INDICES, start_indices);
+  }
+  void add_limit_indices(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> limit_indices)
+  {
+    fbb_.AddOffset(StablehloSliceOptions::VT_LIMIT_INDICES, limit_indices);
+  }
+  void add_strides(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> strides)
+  {
+    fbb_.AddOffset(StablehloSliceOptions::VT_STRIDES, strides);
+  }
+  explicit StablehloSliceOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloSliceOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloSliceOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloSliceOptions>
+CreateStablehloSliceOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                            ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> start_indices = 0,
+                            ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> limit_indices = 0,
+                            ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> strides = 0)
+{
+  StablehloSliceOptionsBuilder builder_(_fbb);
+  builder_.add_strides(strides);
+  builder_.add_limit_indices(limit_indices);
+  builder_.add_start_indices(start_indices);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloSliceOptions>
+CreateStablehloSliceOptionsDirect(::flatbuffers::FlatBufferBuilder &_fbb,
+                                  const std::vector<int64_t> *start_indices = nullptr,
+                                  const std::vector<int64_t> *limit_indices = nullptr,
+                                  const std::vector<int64_t> *strides = nullptr)
+{
+  auto start_indices__ = start_indices ? _fbb.CreateVector<int64_t>(*start_indices) : 0;
+  auto limit_indices__ = limit_indices ? _fbb.CreateVector<int64_t>(*limit_indices) : 0;
+  auto strides__ = strides ? _fbb.CreateVector<int64_t>(*strides) : 0;
+  return circle::CreateStablehloSliceOptions(_fbb, start_indices__, limit_indices__, strides__);
+}
+
+::flatbuffers::Offset<StablehloSliceOptions>
+CreateStablehloSliceOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                            const StablehloSliceOptionsT *_o,
+                            const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloConvolutionOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloConvolutionOptions TableType;
+  std::vector<int64_t> window_strides{};
+  std::vector<int64_t> padding{};
+  std::vector<int64_t> lhs_dilation{};
+  std::vector<int64_t> rhs_dilation{};
+  std::vector<bool> window_reversal{};
+  int64_t input_batch_dimension = 0;
+  int64_t input_feature_dimension = 0;
+  std::vector<int64_t> input_spatial_dimensions{};
+  int64_t kernel_input_feature_dimension = 0;
+  int64_t kernel_output_feature_dimension = 0;
+  std::vector<int64_t> kernel_spatial_dimensions{};
+  int64_t output_batch_dimension = 0;
+  int64_t output_feature_dimension = 0;
+  std::vector<int64_t> output_spatial_dimensions{};
+  int64_t feature_group_count = 0;
+  int64_t batch_group_count = 0;
+  std::vector<circle::StablehloPrecisionConfig> precision_config{};
+};
+
+struct StablehloConvolutionOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloConvolutionOptionsT NativeTableType;
+  typedef StablehloConvolutionOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_WINDOW_STRIDES = 4,
+    VT_PADDING = 6,
+    VT_LHS_DILATION = 8,
+    VT_RHS_DILATION = 10,
+    VT_WINDOW_REVERSAL = 12,
+    VT_INPUT_BATCH_DIMENSION = 14,
+    VT_INPUT_FEATURE_DIMENSION = 16,
+    VT_INPUT_SPATIAL_DIMENSIONS = 18,
+    VT_KERNEL_INPUT_FEATURE_DIMENSION = 20,
+    VT_KERNEL_OUTPUT_FEATURE_DIMENSION = 22,
+    VT_KERNEL_SPATIAL_DIMENSIONS = 24,
+    VT_OUTPUT_BATCH_DIMENSION = 26,
+    VT_OUTPUT_FEATURE_DIMENSION = 28,
+    VT_OUTPUT_SPATIAL_DIMENSIONS = 30,
+    VT_FEATURE_GROUP_COUNT = 32,
+    VT_BATCH_GROUP_COUNT = 34,
+    VT_PRECISION_CONFIG = 36
+  };
+  const ::flatbuffers::Vector<int64_t> *window_strides() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_WINDOW_STRIDES);
+  }
+  const ::flatbuffers::Vector<int64_t> *padding() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_PADDING);
+  }
+  const ::flatbuffers::Vector<int64_t> *lhs_dilation() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_LHS_DILATION);
+  }
+  const ::flatbuffers::Vector<int64_t> *rhs_dilation() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_RHS_DILATION);
+  }
+  const ::flatbuffers::Vector<uint8_t> *window_reversal() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_WINDOW_REVERSAL);
+  }
+  int64_t input_batch_dimension() const { return GetField<int64_t>(VT_INPUT_BATCH_DIMENSION, 0); }
+  int64_t input_feature_dimension() const
+  {
+    return GetField<int64_t>(VT_INPUT_FEATURE_DIMENSION, 0);
+  }
+  const ::flatbuffers::Vector<int64_t> *input_spatial_dimensions() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_INPUT_SPATIAL_DIMENSIONS);
+  }
+  int64_t kernel_input_feature_dimension() const
+  {
+    return GetField<int64_t>(VT_KERNEL_INPUT_FEATURE_DIMENSION, 0);
+  }
+  int64_t kernel_output_feature_dimension() const
+  {
+    return GetField<int64_t>(VT_KERNEL_OUTPUT_FEATURE_DIMENSION, 0);
+  }
+  const ::flatbuffers::Vector<int64_t> *kernel_spatial_dimensions() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_KERNEL_SPATIAL_DIMENSIONS);
+  }
+  int64_t output_batch_dimension() const { return GetField<int64_t>(VT_OUTPUT_BATCH_DIMENSION, 0); }
+  int64_t output_feature_dimension() const
+  {
+    return GetField<int64_t>(VT_OUTPUT_FEATURE_DIMENSION, 0);
+  }
+  const ::flatbuffers::Vector<int64_t> *output_spatial_dimensions() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_OUTPUT_SPATIAL_DIMENSIONS);
+  }
+  int64_t feature_group_count() const { return GetField<int64_t>(VT_FEATURE_GROUP_COUNT, 0); }
+  int64_t batch_group_count() const { return GetField<int64_t>(VT_BATCH_GROUP_COUNT, 0); }
+  const ::flatbuffers::Vector<uint32_t> *precision_config() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<uint32_t> *>(VT_PRECISION_CONFIG);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_WINDOW_STRIDES) &&
+           verifier.VerifyVector(window_strides()) && VerifyOffset(verifier, VT_PADDING) &&
+           verifier.VerifyVector(padding()) && VerifyOffset(verifier, VT_LHS_DILATION) &&
+           verifier.VerifyVector(lhs_dilation()) && VerifyOffset(verifier, VT_RHS_DILATION) &&
+           verifier.VerifyVector(rhs_dilation()) && VerifyOffset(verifier, VT_WINDOW_REVERSAL) &&
+           verifier.VerifyVector(window_reversal()) &&
+           VerifyField<int64_t>(verifier, VT_INPUT_BATCH_DIMENSION, 8) &&
+           VerifyField<int64_t>(verifier, VT_INPUT_FEATURE_DIMENSION, 8) &&
+           VerifyOffset(verifier, VT_INPUT_SPATIAL_DIMENSIONS) &&
+           verifier.VerifyVector(input_spatial_dimensions()) &&
+           VerifyField<int64_t>(verifier, VT_KERNEL_INPUT_FEATURE_DIMENSION, 8) &&
+           VerifyField<int64_t>(verifier, VT_KERNEL_OUTPUT_FEATURE_DIMENSION, 8) &&
+           VerifyOffset(verifier, VT_KERNEL_SPATIAL_DIMENSIONS) &&
+           verifier.VerifyVector(kernel_spatial_dimensions()) &&
+           VerifyField<int64_t>(verifier, VT_OUTPUT_BATCH_DIMENSION, 8) &&
+           VerifyField<int64_t>(verifier, VT_OUTPUT_FEATURE_DIMENSION, 8) &&
+           VerifyOffset(verifier, VT_OUTPUT_SPATIAL_DIMENSIONS) &&
+           verifier.VerifyVector(output_spatial_dimensions()) &&
+           VerifyField<int64_t>(verifier, VT_FEATURE_GROUP_COUNT, 8) &&
+           VerifyField<int64_t>(verifier, VT_BATCH_GROUP_COUNT, 8) &&
+           VerifyOffset(verifier, VT_PRECISION_CONFIG) &&
+           verifier.VerifyVector(precision_config()) && verifier.EndTable();
+  }
+  StablehloConvolutionOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloConvolutionOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloConvolutionOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloConvolutionOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloConvolutionOptionsBuilder
+{
+  typedef StablehloConvolutionOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_window_strides(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> window_strides)
+  {
+    fbb_.AddOffset(StablehloConvolutionOptions::VT_WINDOW_STRIDES, window_strides);
+  }
+  void add_padding(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> padding)
+  {
+    fbb_.AddOffset(StablehloConvolutionOptions::VT_PADDING, padding);
+  }
+  void add_lhs_dilation(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> lhs_dilation)
+  {
+    fbb_.AddOffset(StablehloConvolutionOptions::VT_LHS_DILATION, lhs_dilation);
+  }
+  void add_rhs_dilation(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> rhs_dilation)
+  {
+    fbb_.AddOffset(StablehloConvolutionOptions::VT_RHS_DILATION, rhs_dilation);
+  }
+  void add_window_reversal(::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> window_reversal)
+  {
+    fbb_.AddOffset(StablehloConvolutionOptions::VT_WINDOW_REVERSAL, window_reversal);
+  }
+  void add_input_batch_dimension(int64_t input_batch_dimension)
+  {
+    fbb_.AddElement<int64_t>(StablehloConvolutionOptions::VT_INPUT_BATCH_DIMENSION,
+                             input_batch_dimension, 0);
+  }
+  void add_input_feature_dimension(int64_t input_feature_dimension)
+  {
+    fbb_.AddElement<int64_t>(StablehloConvolutionOptions::VT_INPUT_FEATURE_DIMENSION,
+                             input_feature_dimension, 0);
+  }
+  void add_input_spatial_dimensions(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> input_spatial_dimensions)
+  {
+    fbb_.AddOffset(StablehloConvolutionOptions::VT_INPUT_SPATIAL_DIMENSIONS,
+                   input_spatial_dimensions);
+  }
+  void add_kernel_input_feature_dimension(int64_t kernel_input_feature_dimension)
+  {
+    fbb_.AddElement<int64_t>(StablehloConvolutionOptions::VT_KERNEL_INPUT_FEATURE_DIMENSION,
+                             kernel_input_feature_dimension, 0);
+  }
+  void add_kernel_output_feature_dimension(int64_t kernel_output_feature_dimension)
+  {
+    fbb_.AddElement<int64_t>(StablehloConvolutionOptions::VT_KERNEL_OUTPUT_FEATURE_DIMENSION,
+                             kernel_output_feature_dimension, 0);
+  }
+  void add_kernel_spatial_dimensions(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> kernel_spatial_dimensions)
+  {
+    fbb_.AddOffset(StablehloConvolutionOptions::VT_KERNEL_SPATIAL_DIMENSIONS,
+                   kernel_spatial_dimensions);
+  }
+  void add_output_batch_dimension(int64_t output_batch_dimension)
+  {
+    fbb_.AddElement<int64_t>(StablehloConvolutionOptions::VT_OUTPUT_BATCH_DIMENSION,
+                             output_batch_dimension, 0);
+  }
+  void add_output_feature_dimension(int64_t output_feature_dimension)
+  {
+    fbb_.AddElement<int64_t>(StablehloConvolutionOptions::VT_OUTPUT_FEATURE_DIMENSION,
+                             output_feature_dimension, 0);
+  }
+  void add_output_spatial_dimensions(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> output_spatial_dimensions)
+  {
+    fbb_.AddOffset(StablehloConvolutionOptions::VT_OUTPUT_SPATIAL_DIMENSIONS,
+                   output_spatial_dimensions);
+  }
+  void add_feature_group_count(int64_t feature_group_count)
+  {
+    fbb_.AddElement<int64_t>(StablehloConvolutionOptions::VT_FEATURE_GROUP_COUNT,
+                             feature_group_count, 0);
+  }
+  void add_batch_group_count(int64_t batch_group_count)
+  {
+    fbb_.AddElement<int64_t>(StablehloConvolutionOptions::VT_BATCH_GROUP_COUNT, batch_group_count,
+                             0);
+  }
+  void add_precision_config(::flatbuffers::Offset<::flatbuffers::Vector<uint32_t>> precision_config)
+  {
+    fbb_.AddOffset(StablehloConvolutionOptions::VT_PRECISION_CONFIG, precision_config);
+  }
+  explicit StablehloConvolutionOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloConvolutionOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloConvolutionOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloConvolutionOptions> CreateStablehloConvolutionOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> window_strides = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> padding = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> lhs_dilation = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> rhs_dilation = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> window_reversal = 0,
+  int64_t input_batch_dimension = 0, int64_t input_feature_dimension = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> input_spatial_dimensions = 0,
+  int64_t kernel_input_feature_dimension = 0, int64_t kernel_output_feature_dimension = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> kernel_spatial_dimensions = 0,
+  int64_t output_batch_dimension = 0, int64_t output_feature_dimension = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> output_spatial_dimensions = 0,
+  int64_t feature_group_count = 0, int64_t batch_group_count = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<uint32_t>> precision_config = 0)
+{
+  StablehloConvolutionOptionsBuilder builder_(_fbb);
+  builder_.add_batch_group_count(batch_group_count);
+  builder_.add_feature_group_count(feature_group_count);
+  builder_.add_output_feature_dimension(output_feature_dimension);
+  builder_.add_output_batch_dimension(output_batch_dimension);
+  builder_.add_kernel_output_feature_dimension(kernel_output_feature_dimension);
+  builder_.add_kernel_input_feature_dimension(kernel_input_feature_dimension);
+  builder_.add_input_feature_dimension(input_feature_dimension);
+  builder_.add_input_batch_dimension(input_batch_dimension);
+  builder_.add_precision_config(precision_config);
+  builder_.add_output_spatial_dimensions(output_spatial_dimensions);
+  builder_.add_kernel_spatial_dimensions(kernel_spatial_dimensions);
+  builder_.add_input_spatial_dimensions(input_spatial_dimensions);
+  builder_.add_window_reversal(window_reversal);
+  builder_.add_rhs_dilation(rhs_dilation);
+  builder_.add_lhs_dilation(lhs_dilation);
+  builder_.add_padding(padding);
+  builder_.add_window_strides(window_strides);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloConvolutionOptions> CreateStablehloConvolutionOptionsDirect(
+  ::flatbuffers::FlatBufferBuilder &_fbb, const std::vector<int64_t> *window_strides = nullptr,
+  const std::vector<int64_t> *padding = nullptr, const std::vector<int64_t> *lhs_dilation = nullptr,
+  const std::vector<int64_t> *rhs_dilation = nullptr,
+  const std::vector<uint8_t> *window_reversal = nullptr, int64_t input_batch_dimension = 0,
+  int64_t input_feature_dimension = 0,
+  const std::vector<int64_t> *input_spatial_dimensions = nullptr,
+  int64_t kernel_input_feature_dimension = 0, int64_t kernel_output_feature_dimension = 0,
+  const std::vector<int64_t> *kernel_spatial_dimensions = nullptr,
+  int64_t output_batch_dimension = 0, int64_t output_feature_dimension = 0,
+  const std::vector<int64_t> *output_spatial_dimensions = nullptr, int64_t feature_group_count = 0,
+  int64_t batch_group_count = 0, const std::vector<uint32_t> *precision_config = nullptr)
+{
+  auto window_strides__ = window_strides ? _fbb.CreateVector<int64_t>(*window_strides) : 0;
+  auto padding__ = padding ? _fbb.CreateVector<int64_t>(*padding) : 0;
+  auto lhs_dilation__ = lhs_dilation ? _fbb.CreateVector<int64_t>(*lhs_dilation) : 0;
+  auto rhs_dilation__ = rhs_dilation ? _fbb.CreateVector<int64_t>(*rhs_dilation) : 0;
+  auto window_reversal__ = window_reversal ? _fbb.CreateVector<uint8_t>(*window_reversal) : 0;
+  auto input_spatial_dimensions__ =
+    input_spatial_dimensions ? _fbb.CreateVector<int64_t>(*input_spatial_dimensions) : 0;
+  auto kernel_spatial_dimensions__ =
+    kernel_spatial_dimensions ? _fbb.CreateVector<int64_t>(*kernel_spatial_dimensions) : 0;
+  auto output_spatial_dimensions__ =
+    output_spatial_dimensions ? _fbb.CreateVector<int64_t>(*output_spatial_dimensions) : 0;
+  auto precision_config__ = precision_config ? _fbb.CreateVector<uint32_t>(*precision_config) : 0;
+  return circle::CreateStablehloConvolutionOptions(
+    _fbb, window_strides__, padding__, lhs_dilation__, rhs_dilation__, window_reversal__,
+    input_batch_dimension, input_feature_dimension, input_spatial_dimensions__,
+    kernel_input_feature_dimension, kernel_output_feature_dimension, kernel_spatial_dimensions__,
+    output_batch_dimension, output_feature_dimension, output_spatial_dimensions__,
+    feature_group_count, batch_group_count, precision_config__);
+}
+
+::flatbuffers::Offset<StablehloConvolutionOptions>
+CreateStablehloConvolutionOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                  const StablehloConvolutionOptionsT *_o,
+                                  const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloScatterOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloScatterOptions TableType;
+  bool indices_are_sorted = false;
+  std::vector<int64_t> update_window_dims{};
+  std::vector<int64_t> inserted_window_dims{};
+  std::vector<int64_t> scatter_dims_to_operand_dims{};
+  int64_t index_vector_dim = 0;
+  bool unique_indices = false;
+  int32_t update_computation_subgraph_index = 0;
+};
+
+struct StablehloScatterOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloScatterOptionsT NativeTableType;
+  typedef StablehloScatterOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_INDICES_ARE_SORTED = 4,
+    VT_UPDATE_WINDOW_DIMS = 6,
+    VT_INSERTED_WINDOW_DIMS = 8,
+    VT_SCATTER_DIMS_TO_OPERAND_DIMS = 10,
+    VT_INDEX_VECTOR_DIM = 12,
+    VT_UNIQUE_INDICES = 14,
+    VT_UPDATE_COMPUTATION_SUBGRAPH_INDEX = 16
+  };
+  bool indices_are_sorted() const { return GetField<uint8_t>(VT_INDICES_ARE_SORTED, 0) != 0; }
+  const ::flatbuffers::Vector<int64_t> *update_window_dims() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_UPDATE_WINDOW_DIMS);
+  }
+  const ::flatbuffers::Vector<int64_t> *inserted_window_dims() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_INSERTED_WINDOW_DIMS);
+  }
+  const ::flatbuffers::Vector<int64_t> *scatter_dims_to_operand_dims() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int64_t> *>(VT_SCATTER_DIMS_TO_OPERAND_DIMS);
+  }
+  int64_t index_vector_dim() const { return GetField<int64_t>(VT_INDEX_VECTOR_DIM, 0); }
+  bool unique_indices() const { return GetField<uint8_t>(VT_UNIQUE_INDICES, 0) != 0; }
+  int32_t update_computation_subgraph_index() const
+  {
+    return GetField<int32_t>(VT_UPDATE_COMPUTATION_SUBGRAPH_INDEX, 0);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_INDICES_ARE_SORTED, 1) &&
+           VerifyOffset(verifier, VT_UPDATE_WINDOW_DIMS) &&
+           verifier.VerifyVector(update_window_dims()) &&
+           VerifyOffset(verifier, VT_INSERTED_WINDOW_DIMS) &&
+           verifier.VerifyVector(inserted_window_dims()) &&
+           VerifyOffset(verifier, VT_SCATTER_DIMS_TO_OPERAND_DIMS) &&
+           verifier.VerifyVector(scatter_dims_to_operand_dims()) &&
+           VerifyField<int64_t>(verifier, VT_INDEX_VECTOR_DIM, 8) &&
+           VerifyField<uint8_t>(verifier, VT_UNIQUE_INDICES, 1) &&
+           VerifyField<int32_t>(verifier, VT_UPDATE_COMPUTATION_SUBGRAPH_INDEX, 4) &&
+           verifier.EndTable();
+  }
+  StablehloScatterOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloScatterOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloScatterOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloScatterOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloScatterOptionsBuilder
+{
+  typedef StablehloScatterOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_indices_are_sorted(bool indices_are_sorted)
+  {
+    fbb_.AddElement<uint8_t>(StablehloScatterOptions::VT_INDICES_ARE_SORTED,
+                             static_cast<uint8_t>(indices_are_sorted), 0);
+  }
+  void
+  add_update_window_dims(::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> update_window_dims)
+  {
+    fbb_.AddOffset(StablehloScatterOptions::VT_UPDATE_WINDOW_DIMS, update_window_dims);
+  }
+  void add_inserted_window_dims(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> inserted_window_dims)
+  {
+    fbb_.AddOffset(StablehloScatterOptions::VT_INSERTED_WINDOW_DIMS, inserted_window_dims);
+  }
+  void add_scatter_dims_to_operand_dims(
+    ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> scatter_dims_to_operand_dims)
+  {
+    fbb_.AddOffset(StablehloScatterOptions::VT_SCATTER_DIMS_TO_OPERAND_DIMS,
+                   scatter_dims_to_operand_dims);
+  }
+  void add_index_vector_dim(int64_t index_vector_dim)
+  {
+    fbb_.AddElement<int64_t>(StablehloScatterOptions::VT_INDEX_VECTOR_DIM, index_vector_dim, 0);
+  }
+  void add_unique_indices(bool unique_indices)
+  {
+    fbb_.AddElement<uint8_t>(StablehloScatterOptions::VT_UNIQUE_INDICES,
+                             static_cast<uint8_t>(unique_indices), 0);
+  }
+  void add_update_computation_subgraph_index(int32_t update_computation_subgraph_index)
+  {
+    fbb_.AddElement<int32_t>(StablehloScatterOptions::VT_UPDATE_COMPUTATION_SUBGRAPH_INDEX,
+                             update_computation_subgraph_index, 0);
+  }
+  explicit StablehloScatterOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloScatterOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloScatterOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloScatterOptions> CreateStablehloScatterOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb, bool indices_are_sorted = false,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> update_window_dims = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> inserted_window_dims = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int64_t>> scatter_dims_to_operand_dims = 0,
+  int64_t index_vector_dim = 0, bool unique_indices = false,
+  int32_t update_computation_subgraph_index = 0)
+{
+  StablehloScatterOptionsBuilder builder_(_fbb);
+  builder_.add_index_vector_dim(index_vector_dim);
+  builder_.add_update_computation_subgraph_index(update_computation_subgraph_index);
+  builder_.add_scatter_dims_to_operand_dims(scatter_dims_to_operand_dims);
+  builder_.add_inserted_window_dims(inserted_window_dims);
+  builder_.add_update_window_dims(update_window_dims);
+  builder_.add_unique_indices(unique_indices);
+  builder_.add_indices_are_sorted(indices_are_sorted);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<StablehloScatterOptions> CreateStablehloScatterOptionsDirect(
+  ::flatbuffers::FlatBufferBuilder &_fbb, bool indices_are_sorted = false,
+  const std::vector<int64_t> *update_window_dims = nullptr,
+  const std::vector<int64_t> *inserted_window_dims = nullptr,
+  const std::vector<int64_t> *scatter_dims_to_operand_dims = nullptr, int64_t index_vector_dim = 0,
+  bool unique_indices = false, int32_t update_computation_subgraph_index = 0)
+{
+  auto update_window_dims__ =
+    update_window_dims ? _fbb.CreateVector<int64_t>(*update_window_dims) : 0;
+  auto inserted_window_dims__ =
+    inserted_window_dims ? _fbb.CreateVector<int64_t>(*inserted_window_dims) : 0;
+  auto scatter_dims_to_operand_dims__ =
+    scatter_dims_to_operand_dims ? _fbb.CreateVector<int64_t>(*scatter_dims_to_operand_dims) : 0;
+  return circle::CreateStablehloScatterOptions(_fbb, indices_are_sorted, update_window_dims__,
+                                               inserted_window_dims__,
+                                               scatter_dims_to_operand_dims__, index_vector_dim,
+                                               unique_indices, update_computation_subgraph_index);
+}
+
+::flatbuffers::Offset<StablehloScatterOptions>
+CreateStablehloScatterOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                              const StablehloScatterOptionsT *_o,
+                              const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct StablehloRngBitGeneratorOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef StablehloRngBitGeneratorOptions TableType;
+  circle::RngAlgorithm algorithm = circle::RngAlgorithm_DEFAULT;
+};
+
+struct StablehloRngBitGeneratorOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef StablehloRngBitGeneratorOptionsT NativeTableType;
+  typedef StablehloRngBitGeneratorOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_ALGORITHM = 4
+  };
+  circle::RngAlgorithm algorithm() const
+  {
+    return static_cast<circle::RngAlgorithm>(GetField<int8_t>(VT_ALGORITHM, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_ALGORITHM, 1) &&
+           verifier.EndTable();
+  }
+  StablehloRngBitGeneratorOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(StablehloRngBitGeneratorOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<StablehloRngBitGeneratorOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloRngBitGeneratorOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct StablehloRngBitGeneratorOptionsBuilder
+{
+  typedef StablehloRngBitGeneratorOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_algorithm(circle::RngAlgorithm algorithm)
+  {
+    fbb_.AddElement<int8_t>(StablehloRngBitGeneratorOptions::VT_ALGORITHM,
+                            static_cast<int8_t>(algorithm), 0);
+  }
+  explicit StablehloRngBitGeneratorOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
+    : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<StablehloRngBitGeneratorOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<StablehloRngBitGeneratorOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<StablehloRngBitGeneratorOptions>
+CreateStablehloRngBitGeneratorOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                      circle::RngAlgorithm algorithm = circle::RngAlgorithm_DEFAULT)
+{
+  StablehloRngBitGeneratorOptionsBuilder builder_(_fbb);
+  builder_.add_algorithm(algorithm);
+  return builder_.Finish();
+}
+
+::flatbuffers::Offset<StablehloRngBitGeneratorOptions> CreateStablehloRngBitGeneratorOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb, const StablehloRngBitGeneratorOptionsT *_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;
+  circle::TensorType quantized_bias_type = circle::TensorType_FLOAT32;
+};
+
+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,
+    VT_QUANTIZED_BIAS_TYPE = 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); }
+  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); }
+  circle::TensorType quantized_bias_type() const
+  {
+    return static_cast<circle::TensorType>(GetField<int8_t>(VT_QUANTIZED_BIAS_TYPE, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_PADDING, 1) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_W, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_H, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_W_FACTOR, 4) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_H_FACTOR, 4) &&
+           VerifyField<int8_t>(verifier, VT_QUANTIZED_BIAS_TYPE, 1) && 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);
+  }
+  void add_quantized_bias_type(circle::TensorType quantized_bias_type)
+  {
+    fbb_.AddElement<int8_t>(Conv2DOptions::VT_QUANTIZED_BIAS_TYPE,
+                            static_cast<int8_t>(quantized_bias_type), 0);
+  }
+  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,
+  circle::TensorType quantized_bias_type = circle::TensorType_FLOAT32)
+{
+  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_quantized_bias_type(quantized_bias_type);
+  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, 1) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_D, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_W, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_H, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_D_FACTOR, 4) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_W_FACTOR, 4) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_H_FACTOR, 4) && 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, 1) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_W, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_H, 4) &&
+           VerifyField<int32_t>(verifier, VT_FILTER_WIDTH, 4) &&
+           VerifyField<int32_t>(verifier, VT_FILTER_HEIGHT, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && 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, 1) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_W, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_H, 4) &&
+           VerifyField<int32_t>(verifier, VT_DEPTH_MULTIPLIER, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_W_FACTOR, 4) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_H_FACTOR, 4) && 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, 4) &&
+           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, 1) &&
+           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, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && 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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && 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, 1) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && 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, 1) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<uint8_t>(verifier, VT_MERGE_OUTPUTS, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && 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;
+  circle::TensorType quantized_bias_type = circle::TensorType_FLOAT32;
+};
+
+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,
+    VT_QUANTIZED_BIAS_TYPE = 12
+  };
+  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;
+  }
+  circle::TensorType quantized_bias_type() const
+  {
+    return static_cast<circle::TensorType>(GetField<int8_t>(VT_QUANTIZED_BIAS_TYPE, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<int8_t>(verifier, VT_WEIGHTS_FORMAT, 1) &&
+           VerifyField<uint8_t>(verifier, VT_KEEP_NUM_DIMS, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) &&
+           VerifyField<int8_t>(verifier, VT_QUANTIZED_BIAS_TYPE, 1) && 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);
+  }
+  void add_quantized_bias_type(circle::TensorType quantized_bias_type)
+  {
+    fbb_.AddElement<int8_t>(FullyConnectedOptions::VT_QUANTIZED_BIAS_TYPE,
+                            static_cast<int8_t>(quantized_bias_type), 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,
+  circle::TensorType quantized_bias_type = circle::TensorType_FLOAT32)
+{
+  FullyConnectedOptionsBuilder builder_(_fbb);
+  builder_.add_quantized_bias_type(quantized_bias_type);
+  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, 4) &&
+           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, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && 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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_POT_SCALE_INT16, 1) && 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, 1) && 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, 1) && 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, 4) &&
+           VerifyField<float>(verifier, VT_BIAS, 4) && VerifyField<float>(verifier, VT_ALPHA, 4) &&
+           VerifyField<float>(verifier, VT_BETA, 4) && 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, 1) &&
+           VerifyField<float>(verifier, VT_CELL_CLIP, 4) &&
+           VerifyField<float>(verifier, VT_PROJ_CLIP, 4) &&
+           VerifyField<int8_t>(verifier, VT_KERNEL_TYPE, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && 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;
+  bool diagonal_recurrent_tensors = 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,
+    VT_DIAGONAL_RECURRENT_TENSORS = 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 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 diagonal_recurrent_tensors() const
+  {
+    return GetField<uint8_t>(VT_DIAGONAL_RECURRENT_TENSORS, 0) != 0;
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<float>(verifier, VT_CELL_CLIP, 4) &&
+           VerifyField<float>(verifier, VT_PROJ_CLIP, 4) &&
+           VerifyField<uint8_t>(verifier, VT_TIME_MAJOR, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) &&
+           VerifyField<uint8_t>(verifier, VT_DIAGONAL_RECURRENT_TENSORS, 1) && 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);
+  }
+  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)
+  {
+    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, 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);
+  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, 1) &&
+           VerifyField<float>(verifier, VT_CELL_CLIP, 4) &&
+           VerifyField<float>(verifier, VT_PROJ_CLIP, 4) &&
+           VerifyField<uint8_t>(verifier, VT_MERGE_OUTPUTS, 1) &&
+           VerifyField<uint8_t>(verifier, VT_TIME_MAJOR, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && 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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_HALF_PIXEL_CENTERS, 1) && 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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_HALF_PIXEL_CENTERS, 1) && 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, 4) &&
+           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, 4) &&
+           VerifyField<int32_t>(verifier, VT_MAX_SKIP_SIZE, 4) &&
+           VerifyField<uint8_t>(verifier, VT_INCLUDE_ALL_NGRAMS, 1) && 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, 4) &&
+           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, 4) &&
+           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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_POT_SCALE_INT16, 1) && 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, 1) && 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, 1) &&
+           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, 4) &&
+           VerifyField<int32_t>(verifier, VT_BATCH_DIMS, 4) && 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, 1) &&
+           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, 4) &&
+           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, 4) &&
+           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;
+  bool offset = false;
+};
+
+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,
+    VT_OFFSET = 14
+  };
+  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 offset() const { return GetField<uint8_t>(VT_OFFSET, 0) != 0; }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_BEGIN_MASK, 4) &&
+           VerifyField<int32_t>(verifier, VT_END_MASK, 4) &&
+           VerifyField<int32_t>(verifier, VT_ELLIPSIS_MASK, 4) &&
+           VerifyField<int32_t>(verifier, VT_NEW_AXIS_MASK, 4) &&
+           VerifyField<int32_t>(verifier, VT_SHRINK_AXIS_MASK, 4) &&
+           VerifyField<uint8_t>(verifier, VT_OFFSET, 1) && 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);
+  }
+  void add_offset(bool offset)
+  {
+    fbb_.AddElement<uint8_t>(StridedSliceOptions::VT_OFFSET, static_cast<uint8_t>(offset), 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,
+                          bool offset = false)
+{
+  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);
+  builder_.add_offset(offset);
+  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, 1) &&
+           VerifyField<int8_t>(verifier, VT_OUT_DATA_TYPE, 1) && 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, 1) &&
+           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, 1) &&
+           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;
+  circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+  circle::TensorType quantized_bias_type = circle::TensorType_FLOAT32;
+};
+
+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,
+    VT_FUSED_ACTIVATION_FUNCTION = 10,
+    VT_QUANTIZED_BIAS_TYPE = 12
+  };
+  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));
+  }
+  circle::TensorType quantized_bias_type() const
+  {
+    return static_cast<circle::TensorType>(GetField<int8_t>(VT_QUANTIZED_BIAS_TYPE, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_PADDING, 1) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_W, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_H, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<int8_t>(verifier, VT_QUANTIZED_BIAS_TYPE, 1) && 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);
+  }
+  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);
+  }
+  void add_quantized_bias_type(circle::TensorType quantized_bias_type)
+  {
+    fbb_.AddElement<int8_t>(TransposeConvOptions::VT_QUANTIZED_BIAS_TYPE,
+                            static_cast<int8_t>(quantized_bias_type), 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,
+  circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+  circle::TensorType quantized_bias_type = circle::TensorType_FLOAT32)
+{
+  TransposeConvOptionsBuilder builder_(_fbb);
+  builder_.add_stride_h(stride_h);
+  builder_.add_stride_w(stride_w);
+  builder_.add_quantized_bias_type(quantized_bias_type);
+  builder_.add_fused_activation_function(fused_activation_function);
+  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, 1) &&
+           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, 1) &&
+           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, 4) &&
+           VerifyField<float>(verifier, VT_MAX, 4) &&
+           VerifyField<int32_t>(verifier, VT_NUM_BITS, 4) &&
+           VerifyField<uint8_t>(verifier, VT_NARROW_RANGE, 1) && 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, 4) &&
+           VerifyField<int32_t>(verifier, VT_AXIS, 4) && 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, 4) &&
+           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, 4) &&
+           VerifyField<int32_t>(verifier, VT_AXIS, 4) && 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, 4) &&
+           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, 1) &&
+           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, 1) &&
+           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, 4) &&
+           VerifyField<int32_t>(verifier, VT_BATCH_DIM, 4) && 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, 4) &&
+           VerifyField<int32_t>(verifier, VT_ELSE_SUBGRAPH_INDEX, 4) && 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, 4) && 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, 4) &&
+           VerifyField<int32_t>(verifier, VT_BODY_SUBGRAPH_INDEX, 4) && 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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ADJOINT_RHS, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && 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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_REVERSE, 1) && 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, 4) &&
+           VerifyField<int8_t>(verifier, VT_KEY_DTYPE, 1) &&
+           VerifyField<int8_t>(verifier, VT_VALUE_DTYPE, 1) && 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;
+  int64_t seed = 0;
+  int64_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
+  };
+  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<int64_t>(verifier, VT_SEED, 8) &&
+           VerifyField<int64_t>(verifier, VT_SEED2, 8) && 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(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();
+  }
+  ::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, int64_t seed = 0, int64_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 BucketizeOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef BucketizeOptions TableType;
+  std::vector<float> boundaries{};
+};
+
+struct BucketizeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef BucketizeOptionsT NativeTableType;
+  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();
+  }
+  BucketizeOptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(BucketizeOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<BucketizeOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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__);
+}
+
+::flatbuffers::Offset<BucketizeOptions>
+CreateBucketizeOptions(::flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT *_o,
+                       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct GeluOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef GeluOptions TableType;
+  bool approximate = false;
+};
+
+struct GeluOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef GeluOptionsT NativeTableType;
+  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, 1) &&
+           verifier.EndTable();
+  }
+  GeluOptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(GeluOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<GeluOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<GeluOptions>
+CreateGeluOptions(::flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT *_o,
+                  const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct DynamicUpdateSliceOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef DynamicUpdateSliceOptions TableType;
+};
+
+struct DynamicUpdateSliceOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef DynamicUpdateSliceOptionsT NativeTableType;
+  typedef DynamicUpdateSliceOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  DynamicUpdateSliceOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(DynamicUpdateSliceOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<DynamicUpdateSliceOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const DynamicUpdateSliceOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<DynamicUpdateSliceOptions>
+CreateDynamicUpdateSliceOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const DynamicUpdateSliceOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct UnsortedSegmentProdOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef UnsortedSegmentProdOptions TableType;
+};
+
+struct UnsortedSegmentProdOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef UnsortedSegmentProdOptionsT NativeTableType;
+  typedef UnsortedSegmentProdOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  UnsortedSegmentProdOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(UnsortedSegmentProdOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<UnsortedSegmentProdOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentProdOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<UnsortedSegmentProdOptions>
+CreateUnsortedSegmentProdOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                 const UnsortedSegmentProdOptionsT *_o,
+                                 const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct UnsortedSegmentMaxOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef UnsortedSegmentMaxOptions TableType;
+};
+
+struct UnsortedSegmentMaxOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef UnsortedSegmentMaxOptionsT NativeTableType;
+  typedef UnsortedSegmentMaxOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  UnsortedSegmentMaxOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(UnsortedSegmentMaxOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<UnsortedSegmentMaxOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMaxOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<UnsortedSegmentMaxOptions>
+CreateUnsortedSegmentMaxOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMaxOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct UnsortedSegmentSumOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef UnsortedSegmentSumOptions TableType;
+};
+
+struct UnsortedSegmentSumOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef UnsortedSegmentSumOptionsT NativeTableType;
+  typedef UnsortedSegmentSumOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  UnsortedSegmentSumOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(UnsortedSegmentSumOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<UnsortedSegmentSumOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentSumOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<UnsortedSegmentSumOptions>
+CreateUnsortedSegmentSumOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentSumOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ATan2OptionsT : public ::flatbuffers::NativeTable
+{
+  typedef ATan2Options TableType;
+};
+
+struct ATan2Options FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ATan2OptionsT NativeTableType;
+  typedef ATan2OptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  ATan2OptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(ATan2OptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<ATan2Options>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<ATan2Options>
+CreateATan2Options(::flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT *_o,
+                   const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct UnsortedSegmentMinOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef UnsortedSegmentMinOptions TableType;
+};
+
+struct UnsortedSegmentMinOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef UnsortedSegmentMinOptionsT NativeTableType;
+  typedef UnsortedSegmentMinOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  UnsortedSegmentMinOptionsT *
+  UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(UnsortedSegmentMinOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<UnsortedSegmentMinOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const UnsortedSegmentMinOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<UnsortedSegmentMinOptions>
+CreateUnsortedSegmentMinOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMinOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct SignOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef SignOptions TableType;
+};
+
+struct SignOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SignOptionsT NativeTableType;
+  typedef SignOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  SignOptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(SignOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<SignOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<SignOptions>
+CreateSignOptions(::flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT *_o,
+                  const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BitcastOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef BitcastOptions TableType;
+};
+
+struct BitcastOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef BitcastOptionsT NativeTableType;
+  typedef BitcastOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  BitcastOptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(BitcastOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<BitcastOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const BitcastOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<BitcastOptions>
+CreateBitcastOptions(::flatbuffers::FlatBufferBuilder &_fbb, const BitcastOptionsT *_o,
+                     const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct BitwiseXorOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef BitwiseXorOptions TableType;
+};
+
+struct BitwiseXorOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef BitwiseXorOptionsT NativeTableType;
+  typedef BitwiseXorOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  BitwiseXorOptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(BitwiseXorOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<BitwiseXorOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const BitwiseXorOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<BitwiseXorOptions>
+CreateBitwiseXorOptions(::flatbuffers::FlatBufferBuilder &_fbb, const BitwiseXorOptionsT *_o,
+                        const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct RightShiftOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef RightShiftOptions TableType;
+};
+
+struct RightShiftOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef RightShiftOptionsT NativeTableType;
+  typedef RightShiftOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  RightShiftOptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(RightShiftOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<RightShiftOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RightShiftOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+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();
+}
+
+::flatbuffers::Offset<RightShiftOptions>
+CreateRightShiftOptions(::flatbuffers::FlatBufferBuilder &_fbb, const RightShiftOptionsT *_o,
+                        const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct DilateOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef DilateOptions TableType;
+};
+
+struct DilateOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef DilateOptionsT NativeTableType;
+  typedef DilateOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+  DilateOptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(DilateOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<DilateOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const DilateOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct DilateOptionsBuilder
+{
+  typedef DilateOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  explicit DilateOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<DilateOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<DilateOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<DilateOptions>
+CreateDilateOptions(::flatbuffers::FlatBufferBuilder &_fbb)
+{
+  DilateOptionsBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+::flatbuffers::Offset<DilateOptions>
+CreateDilateOptions(::flatbuffers::FlatBufferBuilder &_fbb, const DilateOptionsT *_o,
+                    const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct ReduceWindowOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef ReduceWindowOptions TableType;
+  circle::ReduceWindowFunction reduce_function = circle::ReduceWindowFunction_UNSUPPORTED;
+};
+
+struct ReduceWindowOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ReduceWindowOptionsT NativeTableType;
+  typedef ReduceWindowOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_REDUCE_FUNCTION = 4
+  };
+  circle::ReduceWindowFunction reduce_function() const
+  {
+    return static_cast<circle::ReduceWindowFunction>(GetField<int32_t>(VT_REDUCE_FUNCTION, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_REDUCE_FUNCTION, 4) &&
+           verifier.EndTable();
+  }
+  ReduceWindowOptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(ReduceWindowOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<ReduceWindowOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ReduceWindowOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct ReduceWindowOptionsBuilder
+{
+  typedef ReduceWindowOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_reduce_function(circle::ReduceWindowFunction reduce_function)
+  {
+    fbb_.AddElement<int32_t>(ReduceWindowOptions::VT_REDUCE_FUNCTION,
+                             static_cast<int32_t>(reduce_function), 0);
+  }
+  explicit ReduceWindowOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<ReduceWindowOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<ReduceWindowOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<ReduceWindowOptions> CreateReduceWindowOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  circle::ReduceWindowFunction reduce_function = circle::ReduceWindowFunction_UNSUPPORTED)
+{
+  ReduceWindowOptionsBuilder builder_(_fbb);
+  builder_.add_reduce_function(reduce_function);
+  return builder_.Finish();
+}
+
+::flatbuffers::Offset<ReduceWindowOptions>
+CreateReduceWindowOptions(::flatbuffers::FlatBufferBuilder &_fbb, const ReduceWindowOptionsT *_o,
+                          const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+
+struct GRUOptionsT : public ::flatbuffers::NativeTable
+{
+  typedef GRUOptions TableType;
+  circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE;
+  bool return_sequences = false;
+  bool time_major = false;
+};
+
+struct GRUOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef GRUOptionsT NativeTableType;
+  typedef GRUOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_FUSED_ACTIVATION_FUNCTION = 4,
+    VT_RETURN_SEQUENCES = 6,
+    VT_TIME_MAJOR = 8
+  };
+  circle::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<circle::ActivationFunctionType>(
+      GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+  }
+  bool return_sequences() const { return GetField<uint8_t>(VT_RETURN_SEQUENCES, 0) != 0; }
+  bool time_major() const { return GetField<uint8_t>(VT_TIME_MAJOR, 0) != 0; }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<uint8_t>(verifier, VT_RETURN_SEQUENCES, 1) &&
+           VerifyField<uint8_t>(verifier, VT_TIME_MAJOR, 1) && verifier.EndTable();
+  }
+  GRUOptionsT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  void UnPackTo(GRUOptionsT *_o,
+                const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
+  static ::flatbuffers::Offset<GRUOptions>
+  Pack(::flatbuffers::FlatBufferBuilder &_fbb, const GRUOptionsT *_o,
+       const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
+};
+
+struct GRUOptionsBuilder
+{
+  typedef GRUOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(circle::ActivationFunctionType fused_activation_function)
+  {
+    fbb_.AddElement<int8_t>(GRUOptions::VT_FUSED_ACTIVATION_FUNCTION,
+                            static_cast<int8_t>(fused_activation_function), 0);
+  }
+  void add_return_sequences(bool return_sequences)
+  {
+    fbb_.AddElement<uint8_t>(GRUOptions::VT_RETURN_SEQUENCES,
+                             static_cast<uint8_t>(return_sequences), 0);
+  }
+  void add_time_major(bool time_major)
+  {
+    fbb_.AddElement<uint8_t>(GRUOptions::VT_TIME_MAJOR, static_cast<uint8_t>(time_major), 0);
+  }
+  explicit GRUOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<GRUOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<GRUOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<GRUOptions> CreateGRUOptions(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  circle::ActivationFunctionType fused_activation_function = circle::ActivationFunctionType_NONE,
+  bool return_sequences = false, bool time_major = false)
+{
+  GRUOptionsBuilder builder_(_fbb);
+  builder_.add_time_major(time_major);
+  builder_.add_return_sequences(return_sequences);
+  builder_.add_fused_activation_function(fused_activation_function);
+  return builder_.Finish();
+}
+
+::flatbuffers::Offset<GRUOptions>
+CreateGRUOptions(::flatbuffers::FlatBufferBuilder &_fbb, const GRUOptionsT *_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, 4) &&
+           VerifyField<int32_t>(verifier, VT_AXIS, 4) && 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, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && 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, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && 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, 1) &&
+           VerifyOffset(verifier, VT_CUSTOM_CODE) && verifier.VerifyString(custom_code()) &&
+           VerifyField<int32_t>(verifier, VT_VERSION, 4) &&
+           VerifyField<int32_t>(verifier, VT_BUILTIN_CODE, 4) && 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{};
+  uint64_t large_custom_options_offset = 0;
+  uint64_t large_custom_options_size = 0;
+  circle::BuiltinOptions2Union builtin_options_2{};
+};
+
+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,
+    VT_LARGE_CUSTOM_OPTIONS_OFFSET = 22,
+    VT_LARGE_CUSTOM_OPTIONS_SIZE = 24,
+    VT_BUILTIN_OPTIONS_2_TYPE = 26,
+    VT_BUILTIN_OPTIONS_2 = 28
+  };
+  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::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::GRUOptions *builtin_options_as_GRUOptions() const
+  {
+    return builtin_options_type() == circle::BuiltinOptions_GRUOptions
+             ? static_cast<const circle::GRUOptions *>(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);
+  }
+  uint64_t large_custom_options_offset() const
+  {
+    return GetField<uint64_t>(VT_LARGE_CUSTOM_OPTIONS_OFFSET, 0);
+  }
+  uint64_t large_custom_options_size() const
+  {
+    return GetField<uint64_t>(VT_LARGE_CUSTOM_OPTIONS_SIZE, 0);
+  }
+  circle::BuiltinOptions2 builtin_options_2_type() const
+  {
+    return static_cast<circle::BuiltinOptions2>(GetField<uint8_t>(VT_BUILTIN_OPTIONS_2_TYPE, 0));
+  }
+  const void *builtin_options_2() const { return GetPointer<const void *>(VT_BUILTIN_OPTIONS_2); }
+  template <typename T> const T *builtin_options_2_as() const;
+  const circle::StablehloConcatenateOptions *
+  builtin_options_2_as_StablehloConcatenateOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloConcatenateOptions
+             ? static_cast<const circle::StablehloConcatenateOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloBroadcastInDimOptions *
+  builtin_options_2_as_StablehloBroadcastInDimOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloBroadcastInDimOptions
+             ? static_cast<const circle::StablehloBroadcastInDimOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloSliceOptions *builtin_options_2_as_StablehloSliceOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloSliceOptions
+             ? static_cast<const circle::StablehloSliceOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloConvolutionOptions *
+  builtin_options_2_as_StablehloConvolutionOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloConvolutionOptions
+             ? static_cast<const circle::StablehloConvolutionOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloCustomCallOptions *builtin_options_2_as_StablehloCustomCallOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloCustomCallOptions
+             ? static_cast<const circle::StablehloCustomCallOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloReduceOptions *builtin_options_2_as_StablehloReduceOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloReduceOptions
+             ? static_cast<const circle::StablehloReduceOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloScatterOptions *builtin_options_2_as_StablehloScatterOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloScatterOptions
+             ? static_cast<const circle::StablehloScatterOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloCompareOptions *builtin_options_2_as_StablehloCompareOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloCompareOptions
+             ? static_cast<const circle::StablehloCompareOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloDynamicSliceOptions *
+  builtin_options_2_as_StablehloDynamicSliceOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloDynamicSliceOptions
+             ? static_cast<const circle::StablehloDynamicSliceOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloPadOptions *builtin_options_2_as_StablehloPadOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloPadOptions
+             ? static_cast<const circle::StablehloPadOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloIotaOptions *builtin_options_2_as_StablehloIotaOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloIotaOptions
+             ? static_cast<const circle::StablehloIotaOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloDotGeneralOptions *builtin_options_2_as_StablehloDotGeneralOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloDotGeneralOptions
+             ? static_cast<const circle::StablehloDotGeneralOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloReduceWindowOptions *
+  builtin_options_2_as_StablehloReduceWindowOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloReduceWindowOptions
+             ? static_cast<const circle::StablehloReduceWindowOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloSortOptions *builtin_options_2_as_StablehloSortOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloSortOptions
+             ? static_cast<const circle::StablehloSortOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloWhileOptions *builtin_options_2_as_StablehloWhileOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloWhileOptions
+             ? static_cast<const circle::StablehloWhileOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloGatherOptions *builtin_options_2_as_StablehloGatherOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloGatherOptions
+             ? static_cast<const circle::StablehloGatherOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloTransposeOptions *builtin_options_2_as_StablehloTransposeOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloTransposeOptions
+             ? static_cast<const circle::StablehloTransposeOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::DilateOptions *builtin_options_2_as_DilateOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_DilateOptions
+             ? static_cast<const circle::DilateOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::StablehloRngBitGeneratorOptions *
+  builtin_options_2_as_StablehloRngBitGeneratorOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_StablehloRngBitGeneratorOptions
+             ? static_cast<const circle::StablehloRngBitGeneratorOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  const circle::ReduceWindowOptions *builtin_options_2_as_ReduceWindowOptions() const
+  {
+    return builtin_options_2_type() == circle::BuiltinOptions2_ReduceWindowOptions
+             ? static_cast<const circle::ReduceWindowOptions *>(builtin_options_2())
+             : nullptr;
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<uint32_t>(verifier, VT_OPCODE_INDEX, 4) &&
+           VerifyOffset(verifier, VT_INPUTS) && verifier.VerifyVector(inputs()) &&
+           VerifyOffset(verifier, VT_OUTPUTS) && verifier.VerifyVector(outputs()) &&
+           VerifyField<uint8_t>(verifier, VT_BUILTIN_OPTIONS_TYPE, 1) &&
+           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, 1) &&
+           VerifyOffset(verifier, VT_MUTATING_VARIABLE_INPUTS) &&
+           verifier.VerifyVector(mutating_variable_inputs()) &&
+           VerifyOffset(verifier, VT_INTERMEDIATES) && verifier.VerifyVector(intermediates()) &&
+           VerifyField<uint64_t>(verifier, VT_LARGE_CUSTOM_OPTIONS_OFFSET, 8) &&
+           VerifyField<uint64_t>(verifier, VT_LARGE_CUSTOM_OPTIONS_SIZE, 8) &&
+           VerifyField<uint8_t>(verifier, VT_BUILTIN_OPTIONS_2_TYPE, 1) &&
+           VerifyOffset(verifier, VT_BUILTIN_OPTIONS_2) &&
+           VerifyBuiltinOptions2(verifier, builtin_options_2(), builtin_options_2_type()) &&
+           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::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::GRUOptions *Operator::builtin_options_as<circle::GRUOptions>() const
+{
+  return builtin_options_as_GRUOptions();
+}
+
+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();
+}
+
+template <>
+inline const circle::StablehloConcatenateOptions *
+Operator::builtin_options_2_as<circle::StablehloConcatenateOptions>() const
+{
+  return builtin_options_2_as_StablehloConcatenateOptions();
+}
+
+template <>
+inline const circle::StablehloBroadcastInDimOptions *
+Operator::builtin_options_2_as<circle::StablehloBroadcastInDimOptions>() const
+{
+  return builtin_options_2_as_StablehloBroadcastInDimOptions();
+}
+
+template <>
+inline const circle::StablehloSliceOptions *
+Operator::builtin_options_2_as<circle::StablehloSliceOptions>() const
+{
+  return builtin_options_2_as_StablehloSliceOptions();
+}
+
+template <>
+inline const circle::StablehloConvolutionOptions *
+Operator::builtin_options_2_as<circle::StablehloConvolutionOptions>() const
+{
+  return builtin_options_2_as_StablehloConvolutionOptions();
+}
+
+template <>
+inline const circle::StablehloCustomCallOptions *
+Operator::builtin_options_2_as<circle::StablehloCustomCallOptions>() const
+{
+  return builtin_options_2_as_StablehloCustomCallOptions();
+}
+
+template <>
+inline const circle::StablehloReduceOptions *
+Operator::builtin_options_2_as<circle::StablehloReduceOptions>() const
+{
+  return builtin_options_2_as_StablehloReduceOptions();
+}
+
+template <>
+inline const circle::StablehloScatterOptions *
+Operator::builtin_options_2_as<circle::StablehloScatterOptions>() const
+{
+  return builtin_options_2_as_StablehloScatterOptions();
+}
+
+template <>
+inline const circle::StablehloCompareOptions *
+Operator::builtin_options_2_as<circle::StablehloCompareOptions>() const
+{
+  return builtin_options_2_as_StablehloCompareOptions();
+}
+
+template <>
+inline const circle::StablehloDynamicSliceOptions *
+Operator::builtin_options_2_as<circle::StablehloDynamicSliceOptions>() const
+{
+  return builtin_options_2_as_StablehloDynamicSliceOptions();
+}
+
+template <>
+inline const circle::StablehloPadOptions *
+Operator::builtin_options_2_as<circle::StablehloPadOptions>() const
+{
+  return builtin_options_2_as_StablehloPadOptions();
+}
+
+template <>
+inline const circle::StablehloIotaOptions *
+Operator::builtin_options_2_as<circle::StablehloIotaOptions>() const
+{
+  return builtin_options_2_as_StablehloIotaOptions();
+}
+
+template <>
+inline const circle::StablehloDotGeneralOptions *
+Operator::builtin_options_2_as<circle::StablehloDotGeneralOptions>() const
+{
+  return builtin_options_2_as_StablehloDotGeneralOptions();
+}
+
+template <>
+inline const circle::StablehloReduceWindowOptions *
+Operator::builtin_options_2_as<circle::StablehloReduceWindowOptions>() const
+{
+  return builtin_options_2_as_StablehloReduceWindowOptions();
+}
+
+template <>
+inline const circle::StablehloSortOptions *
+Operator::builtin_options_2_as<circle::StablehloSortOptions>() const
+{
+  return builtin_options_2_as_StablehloSortOptions();
+}
+
+template <>
+inline const circle::StablehloWhileOptions *
+Operator::builtin_options_2_as<circle::StablehloWhileOptions>() const
+{
+  return builtin_options_2_as_StablehloWhileOptions();
+}
+
+template <>
+inline const circle::StablehloGatherOptions *
+Operator::builtin_options_2_as<circle::StablehloGatherOptions>() const
+{
+  return builtin_options_2_as_StablehloGatherOptions();
+}
+
+template <>
+inline const circle::StablehloTransposeOptions *
+Operator::builtin_options_2_as<circle::StablehloTransposeOptions>() const
+{
+  return builtin_options_2_as_StablehloTransposeOptions();
+}
+
+template <>
+inline const circle::DilateOptions *Operator::builtin_options_2_as<circle::DilateOptions>() const
+{
+  return builtin_options_2_as_DilateOptions();
+}
+
+template <>
+inline const circle::StablehloRngBitGeneratorOptions *
+Operator::builtin_options_2_as<circle::StablehloRngBitGeneratorOptions>() const
+{
+  return builtin_options_2_as_StablehloRngBitGeneratorOptions();
+}
+
+template <>
+inline const circle::ReduceWindowOptions *
+Operator::builtin_options_2_as<circle::ReduceWindowOptions>() const
+{
+  return builtin_options_2_as_ReduceWindowOptions();
+}
+
+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);
+  }
+  void add_large_custom_options_offset(uint64_t large_custom_options_offset)
+  {
+    fbb_.AddElement<uint64_t>(Operator::VT_LARGE_CUSTOM_OPTIONS_OFFSET, large_custom_options_offset,
+                              0);
+  }
+  void add_large_custom_options_size(uint64_t large_custom_options_size)
+  {
+    fbb_.AddElement<uint64_t>(Operator::VT_LARGE_CUSTOM_OPTIONS_SIZE, large_custom_options_size, 0);
+  }
+  void add_builtin_options_2_type(circle::BuiltinOptions2 builtin_options_2_type)
+  {
+    fbb_.AddElement<uint8_t>(Operator::VT_BUILTIN_OPTIONS_2_TYPE,
+                             static_cast<uint8_t>(builtin_options_2_type), 0);
+  }
+  void add_builtin_options_2(::flatbuffers::Offset<void> builtin_options_2)
+  {
+    fbb_.AddOffset(Operator::VT_BUILTIN_OPTIONS_2, builtin_options_2);
+  }
+  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,
+  uint64_t large_custom_options_offset = 0, uint64_t large_custom_options_size = 0,
+  circle::BuiltinOptions2 builtin_options_2_type = circle::BuiltinOptions2_NONE,
+  ::flatbuffers::Offset<void> builtin_options_2 = 0)
+{
+  OperatorBuilder builder_(_fbb);
+  builder_.add_large_custom_options_size(large_custom_options_size);
+  builder_.add_large_custom_options_offset(large_custom_options_offset);
+  builder_.add_builtin_options_2(builtin_options_2);
+  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_builtin_options_2_type(builtin_options_2_type);
+  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, uint64_t large_custom_options_offset = 0,
+  uint64_t large_custom_options_size = 0,
+  circle::BuiltinOptions2 builtin_options_2_type = circle::BuiltinOptions2_NONE,
+  ::flatbuffers::Offset<void> builtin_options_2 = 0)
+{
+  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__,
+                                large_custom_options_offset, large_custom_options_size,
+                                builtin_options_2_type, builtin_options_2);
+}
+
+::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{};
+  SubGraphT() = default;
+  SubGraphT(const SubGraphT &o);
+  SubGraphT(SubGraphT &&) FLATBUFFERS_NOEXCEPT = default;
+  SubGraphT &operator=(SubGraphT o) FLATBUFFERS_NOEXCEPT;
+};
+
+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
+  };
+  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);
+  }
+  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()) && 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);
+  }
+  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)
+{
+  SubGraphBuilder builder_(_fbb);
+  builder_.add_name(name);
+  builder_.add_operators(operators);
+  builder_.add_outputs(outputs);
+  builder_.add_inputs(inputs);
+  builder_.add_tensors(tensors);
+  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)
+{
+  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__);
+}
+
+::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{};
+  uint64_t offset = 0;
+  uint64_t size = 0;
+};
+
+struct Buffer FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef BufferT NativeTableType;
+  typedef BufferBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_DATA = 4,
+    VT_OFFSET = 6,
+    VT_SIZE = 8
+  };
+  const ::flatbuffers::Vector<uint8_t> *data() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<uint8_t> *>(VT_DATA);
+  }
+  uint64_t offset() const { return GetField<uint64_t>(VT_OFFSET, 0); }
+  uint64_t size() const { return GetField<uint64_t>(VT_SIZE, 0); }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_DATA) &&
+           verifier.VerifyVector(data()) && VerifyField<uint64_t>(verifier, VT_OFFSET, 8) &&
+           VerifyField<uint64_t>(verifier, VT_SIZE, 8) && 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);
+  }
+  void add_offset(uint64_t offset) { fbb_.AddElement<uint64_t>(Buffer::VT_OFFSET, offset, 0); }
+  void add_size(uint64_t size) { fbb_.AddElement<uint64_t>(Buffer::VT_SIZE, size, 0); }
+  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, uint64_t offset = 0,
+             uint64_t size = 0)
+{
+  BufferBuilder builder_(_fbb);
+  builder_.add_size(size);
+  builder_.add_offset(offset);
+  builder_.add_data(data);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<Buffer> CreateBufferDirect(::flatbuffers::FlatBufferBuilder &_fbb,
+                                                        const std::vector<uint8_t> *data = nullptr,
+                                                        uint64_t offset = 0, uint64_t size = 0)
+{
+  if (data)
+  {
+    _fbb.ForceVectorAlignment(data->size(), sizeof(uint8_t), 16);
+  }
+  auto data__ = data ? _fbb.CreateVector<uint8_t>(*data) : 0;
+  return circle::CreateBuffer(_fbb, data__, offset, size);
+}
+
+::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, 4) &&
+           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, 4) &&
+           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;
+  SignatureDefT() = default;
+  SignatureDefT(const SignatureDefT &o);
+  SignatureDefT(SignatureDefT &&) FLATBUFFERS_NOEXCEPT = default;
+  SignatureDefT &operator=(SignatureDefT o) FLATBUFFERS_NOEXCEPT;
+};
+
+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, 4) && 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{};
+  ModelT() = default;
+  ModelT(const ModelT &o);
+  ModelT(ModelT &&) FLATBUFFERS_NOEXCEPT = default;
+  ModelT &operator=(ModelT o) FLATBUFFERS_NOEXCEPT;
+};
+
+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, 4) &&
+           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);
+      }
+    }
+    else
+    {
+      _o->min.resize(0);
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->max.resize(0);
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->scale.resize(0);
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->zero_point.resize(0);
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->values.resize(0);
+    }
+  }
+}
+
+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);
+      }
+    }
+    else
+    {
+      _o->values.resize(0);
+    }
+  }
+}
+
+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::SparsityParametersT(const SparsityParametersT &o)
+  : traversal_order(o.traversal_order), block_map(o.block_map)
+{
+  dim_metadata.reserve(o.dim_metadata.size());
+  for (const auto &dim_metadata_ : o.dim_metadata)
+  {
+    dim_metadata.emplace_back((dim_metadata_) ? new circle::DimensionMetadataT(*dim_metadata_)
+                                              : nullptr);
+  }
+}
+
+inline SparsityParametersT &
+SparsityParametersT::operator=(SparsityParametersT o) FLATBUFFERS_NOEXCEPT
+{
+  std::swap(traversal_order, o.traversal_order);
+  std::swap(block_map, o.block_map);
+  std::swap(dim_metadata, o.dim_metadata);
+  return *this;
+}
+
+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);
+      }
+    }
+    else
+    {
+      _o->traversal_order.resize(0);
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->block_map.resize(0);
+    }
+  }
+  {
+    auto _e = dim_metadata();
+    if (_e)
+    {
+      _o->dim_metadata.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        if (_o->dim_metadata[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->dim_metadata[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->dim_metadata[_i] =
+            std::unique_ptr<circle::DimensionMetadataT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->dim_metadata.resize(0);
+    }
+  }
+}
+
+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 VariantSubTypeT *
+VariantSubType::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<VariantSubTypeT>(new VariantSubTypeT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void VariantSubType::UnPackTo(VariantSubTypeT *_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);
+      }
+    }
+    else
+    {
+      _o->shape.resize(0);
+    }
+  }
+  {
+    auto _e = type();
+    _o->type = _e;
+  }
+  {
+    auto _e = has_rank();
+    _o->has_rank = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<VariantSubType>
+VariantSubType::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT *_o,
+                     const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateVariantSubType(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<VariantSubType>
+CreateVariantSubType(::flatbuffers::FlatBufferBuilder &_fbb, const VariantSubTypeT *_o,
+                     const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const VariantSubTypeT *__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 _has_rank = _o->has_rank;
+  return circle::CreateVariantSubType(_fbb, _shape, _type, _has_rank);
+}
+
+inline TensorT::TensorT(const TensorT &o)
+  : shape(o.shape), type(o.type), buffer(o.buffer), name(o.name),
+    quantization((o.quantization) ? new circle::QuantizationParametersT(*o.quantization) : nullptr),
+    is_variable(o.is_variable),
+    sparsity((o.sparsity) ? new circle::SparsityParametersT(*o.sparsity) : nullptr),
+    shape_signature(o.shape_signature), has_rank(o.has_rank)
+{
+  variant_tensors.reserve(o.variant_tensors.size());
+  for (const auto &variant_tensors_ : o.variant_tensors)
+  {
+    variant_tensors.emplace_back((variant_tensors_) ? new circle::VariantSubTypeT(*variant_tensors_)
+                                                    : nullptr);
+  }
+}
+
+inline TensorT &TensorT::operator=(TensorT o) FLATBUFFERS_NOEXCEPT
+{
+  std::swap(shape, o.shape);
+  std::swap(type, o.type);
+  std::swap(buffer, o.buffer);
+  std::swap(name, o.name);
+  std::swap(quantization, o.quantization);
+  std::swap(is_variable, o.is_variable);
+  std::swap(sparsity, o.sparsity);
+  std::swap(shape_signature, o.shape_signature);
+  std::swap(has_rank, o.has_rank);
+  std::swap(variant_tensors, o.variant_tensors);
+  return *this;
+}
+
+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);
+      }
+    }
+    else
+    {
+      _o->shape.resize(0);
+    }
+  }
+  {
+    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)
+    {
+      if (_o->quantization)
+      {
+        _e->UnPackTo(_o->quantization.get(), _resolver);
+      }
+      else
+      {
+        _o->quantization = std::unique_ptr<circle::QuantizationParametersT>(_e->UnPack(_resolver));
+      }
+    }
+    else if (_o->quantization)
+    {
+      _o->quantization.reset();
+    }
+  }
+  {
+    auto _e = is_variable();
+    _o->is_variable = _e;
+  }
+  {
+    auto _e = sparsity();
+    if (_e)
+    {
+      if (_o->sparsity)
+      {
+        _e->UnPackTo(_o->sparsity.get(), _resolver);
+      }
+      else
+      {
+        _o->sparsity = std::unique_ptr<circle::SparsityParametersT>(_e->UnPack(_resolver));
+      }
+    }
+    else if (_o->sparsity)
+    {
+      _o->sparsity.reset();
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->shape_signature.resize(0);
+    }
+  }
+  {
+    auto _e = has_rank();
+    _o->has_rank = _e;
+  }
+  {
+    auto _e = variant_tensors();
+    if (_e)
+    {
+      _o->variant_tensors.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        if (_o->variant_tensors[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->variant_tensors[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->variant_tensors[_i] =
+            std::unique_ptr<circle::VariantSubTypeT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->variant_tensors.resize(0);
+    }
+  }
+}
+
+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;
+  auto _has_rank = _o->has_rank;
+  auto _variant_tensors =
+    _o->variant_tensors.size()
+      ? _fbb.CreateVector<::flatbuffers::Offset<circle::VariantSubType>>(
+          _o->variant_tensors.size(),
+          [](size_t i, _VectorArgs *__va) {
+            return CreateVariantSubType(*__va->__fbb, __va->__o->variant_tensors[i].get(),
+                                        __va->__rehasher);
+          },
+          &_va)
+      : 0;
+  return circle::CreateTensor(_fbb, _shape, _type, _buffer, _name, _quantization, _is_variable,
+                              _sparsity, _shape_signature, _has_rank, _variant_tensors);
+}
+
+inline StablehloGatherOptionsT *
+StablehloGatherOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloGatherOptionsT>(new StablehloGatherOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloGatherOptions::UnPackTo(StablehloGatherOptionsT *_o,
+                                 const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = offset_dims();
+    if (_e)
+    {
+      _o->offset_dims.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->offset_dims[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->offset_dims.resize(0);
+    }
+  }
+  {
+    auto _e = collapsed_slice_dims();
+    if (_e)
+    {
+      _o->collapsed_slice_dims.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->collapsed_slice_dims[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->collapsed_slice_dims.resize(0);
+    }
+  }
+  {
+    auto _e = start_index_map();
+    if (_e)
+    {
+      _o->start_index_map.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->start_index_map[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->start_index_map.resize(0);
+    }
+  }
+  {
+    auto _e = index_vector_dim();
+    _o->index_vector_dim = _e;
+  }
+  {
+    auto _e = slice_sizes();
+    if (_e)
+    {
+      _o->slice_sizes.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->slice_sizes[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->slice_sizes.resize(0);
+    }
+  }
+  {
+    auto _e = indices_are_sorted();
+    _o->indices_are_sorted = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloGatherOptions>
+StablehloGatherOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                             const StablehloGatherOptionsT *_o,
+                             const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloGatherOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloGatherOptions>
+CreateStablehloGatherOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                             const StablehloGatherOptionsT *_o,
+                             const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloGatherOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _offset_dims = _o->offset_dims.size() ? _fbb.CreateVector(_o->offset_dims) : 0;
+  auto _collapsed_slice_dims =
+    _o->collapsed_slice_dims.size() ? _fbb.CreateVector(_o->collapsed_slice_dims) : 0;
+  auto _start_index_map = _o->start_index_map.size() ? _fbb.CreateVector(_o->start_index_map) : 0;
+  auto _index_vector_dim = _o->index_vector_dim;
+  auto _slice_sizes = _o->slice_sizes.size() ? _fbb.CreateVector(_o->slice_sizes) : 0;
+  auto _indices_are_sorted = _o->indices_are_sorted;
+  return circle::CreateStablehloGatherOptions(_fbb, _offset_dims, _collapsed_slice_dims,
+                                              _start_index_map, _index_vector_dim, _slice_sizes,
+                                              _indices_are_sorted);
+}
+
+inline StablehloTransposeOptionsT *
+StablehloTransposeOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloTransposeOptionsT>(new StablehloTransposeOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloTransposeOptions::UnPackTo(StablehloTransposeOptionsT *_o,
+                                    const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = permutation();
+    if (_e)
+    {
+      _o->permutation.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->permutation[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->permutation.resize(0);
+    }
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloTransposeOptions>
+StablehloTransposeOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const StablehloTransposeOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloTransposeOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloTransposeOptions>
+CreateStablehloTransposeOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const StablehloTransposeOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloTransposeOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _permutation = _o->permutation.size() ? _fbb.CreateVector(_o->permutation) : 0;
+  return circle::CreateStablehloTransposeOptions(_fbb, _permutation);
+}
+
+inline StablehloDotGeneralOptionsT *
+StablehloDotGeneralOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloDotGeneralOptionsT>(new StablehloDotGeneralOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloDotGeneralOptions::UnPackTo(StablehloDotGeneralOptionsT *_o,
+                                     const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = lhs_batching_dimensions();
+    if (_e)
+    {
+      _o->lhs_batching_dimensions.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->lhs_batching_dimensions[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->lhs_batching_dimensions.resize(0);
+    }
+  }
+  {
+    auto _e = rhs_batching_dimensions();
+    if (_e)
+    {
+      _o->rhs_batching_dimensions.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->rhs_batching_dimensions[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->rhs_batching_dimensions.resize(0);
+    }
+  }
+  {
+    auto _e = lhs_contracting_dimensions();
+    if (_e)
+    {
+      _o->lhs_contracting_dimensions.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->lhs_contracting_dimensions[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->lhs_contracting_dimensions.resize(0);
+    }
+  }
+  {
+    auto _e = rhs_contracting_dimensions();
+    if (_e)
+    {
+      _o->rhs_contracting_dimensions.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->rhs_contracting_dimensions[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->rhs_contracting_dimensions.resize(0);
+    }
+  }
+  {
+    auto _e = precision_config();
+    if (_e)
+    {
+      _o->precision_config.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->precision_config[_i] = static_cast<circle::StablehloPrecisionConfig>(_e->Get(_i));
+      }
+    }
+    else
+    {
+      _o->precision_config.resize(0);
+    }
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloDotGeneralOptions>
+StablehloDotGeneralOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                 const StablehloDotGeneralOptionsT *_o,
+                                 const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloDotGeneralOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloDotGeneralOptions>
+CreateStablehloDotGeneralOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                 const StablehloDotGeneralOptionsT *_o,
+                                 const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloDotGeneralOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _lhs_batching_dimensions =
+    _o->lhs_batching_dimensions.size() ? _fbb.CreateVector(_o->lhs_batching_dimensions) : 0;
+  auto _rhs_batching_dimensions =
+    _o->rhs_batching_dimensions.size() ? _fbb.CreateVector(_o->rhs_batching_dimensions) : 0;
+  auto _lhs_contracting_dimensions =
+    _o->lhs_contracting_dimensions.size() ? _fbb.CreateVector(_o->lhs_contracting_dimensions) : 0;
+  auto _rhs_contracting_dimensions =
+    _o->rhs_contracting_dimensions.size() ? _fbb.CreateVector(_o->rhs_contracting_dimensions) : 0;
+  auto _precision_config =
+    _o->precision_config.size()
+      ? _fbb.CreateVectorScalarCast<uint32_t>(::flatbuffers::data(_o->precision_config),
+                                              _o->precision_config.size())
+      : 0;
+  return circle::CreateStablehloDotGeneralOptions(
+    _fbb, _lhs_batching_dimensions, _rhs_batching_dimensions, _lhs_contracting_dimensions,
+    _rhs_contracting_dimensions, _precision_config);
+}
+
+inline StablehloReduceWindowOptionsT *
+StablehloReduceWindowOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloReduceWindowOptionsT>(new StablehloReduceWindowOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloReduceWindowOptions::UnPackTo(StablehloReduceWindowOptionsT *_o,
+                                       const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = window_dimensions();
+    if (_e)
+    {
+      _o->window_dimensions.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->window_dimensions[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->window_dimensions.resize(0);
+    }
+  }
+  {
+    auto _e = window_strides();
+    if (_e)
+    {
+      _o->window_strides.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->window_strides[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->window_strides.resize(0);
+    }
+  }
+  {
+    auto _e = base_dilations();
+    if (_e)
+    {
+      _o->base_dilations.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->base_dilations[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->base_dilations.resize(0);
+    }
+  }
+  {
+    auto _e = window_dilations();
+    if (_e)
+    {
+      _o->window_dilations.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->window_dilations[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->window_dilations.resize(0);
+    }
+  }
+  {
+    auto _e = padding();
+    if (_e)
+    {
+      _o->padding.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->padding[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->padding.resize(0);
+    }
+  }
+  {
+    auto _e = body_subgraph_index();
+    _o->body_subgraph_index = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloReduceWindowOptions>
+StablehloReduceWindowOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                   const StablehloReduceWindowOptionsT *_o,
+                                   const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloReduceWindowOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloReduceWindowOptions>
+CreateStablehloReduceWindowOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                   const StablehloReduceWindowOptionsT *_o,
+                                   const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloReduceWindowOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _window_dimensions =
+    _o->window_dimensions.size() ? _fbb.CreateVector(_o->window_dimensions) : 0;
+  auto _window_strides = _o->window_strides.size() ? _fbb.CreateVector(_o->window_strides) : 0;
+  auto _base_dilations = _o->base_dilations.size() ? _fbb.CreateVector(_o->base_dilations) : 0;
+  auto _window_dilations =
+    _o->window_dilations.size() ? _fbb.CreateVector(_o->window_dilations) : 0;
+  auto _padding = _o->padding.size() ? _fbb.CreateVector(_o->padding) : 0;
+  auto _body_subgraph_index = _o->body_subgraph_index;
+  return circle::CreateStablehloReduceWindowOptions(_fbb, _window_dimensions, _window_strides,
+                                                    _base_dilations, _window_dilations, _padding,
+                                                    _body_subgraph_index);
+}
+
+inline StablehloWhileOptionsT *
+StablehloWhileOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloWhileOptionsT>(new StablehloWhileOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloWhileOptions::UnPackTo(StablehloWhileOptionsT *_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<StablehloWhileOptions>
+StablehloWhileOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                            const StablehloWhileOptionsT *_o,
+                            const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloWhileOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloWhileOptions>
+CreateStablehloWhileOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                            const StablehloWhileOptionsT *_o,
+                            const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloWhileOptionsT *__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::CreateStablehloWhileOptions(_fbb, _cond_subgraph_index, _body_subgraph_index);
+}
+
+inline StablehloSortOptionsT *
+StablehloSortOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloSortOptionsT>(new StablehloSortOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloSortOptions::UnPackTo(StablehloSortOptionsT *_o,
+                               const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = dimension();
+    _o->dimension = _e;
+  }
+  {
+    auto _e = is_stable();
+    _o->is_stable = _e;
+  }
+  {
+    auto _e = comparator_subgraph_index();
+    _o->comparator_subgraph_index = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloSortOptions>
+StablehloSortOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloSortOptionsT *_o,
+                           const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloSortOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloSortOptions>
+CreateStablehloSortOptions(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloSortOptionsT *_o,
+                           const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloSortOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _dimension = _o->dimension;
+  auto _is_stable = _o->is_stable;
+  auto _comparator_subgraph_index = _o->comparator_subgraph_index;
+  return circle::CreateStablehloSortOptions(_fbb, _dimension, _is_stable,
+                                            _comparator_subgraph_index);
+}
+
+inline StablehloConcatenateOptionsT *
+StablehloConcatenateOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloConcatenateOptionsT>(new StablehloConcatenateOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloConcatenateOptions::UnPackTo(StablehloConcatenateOptionsT *_o,
+                                      const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = dimension();
+    _o->dimension = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloConcatenateOptions>
+StablehloConcatenateOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                  const StablehloConcatenateOptionsT *_o,
+                                  const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloConcatenateOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloConcatenateOptions>
+CreateStablehloConcatenateOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                  const StablehloConcatenateOptionsT *_o,
+                                  const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloConcatenateOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _dimension = _o->dimension;
+  return circle::CreateStablehloConcatenateOptions(_fbb, _dimension);
+}
+
+inline StablehloBroadcastInDimOptionsT *
+StablehloBroadcastInDimOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloBroadcastInDimOptionsT>(new StablehloBroadcastInDimOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloBroadcastInDimOptions::UnPackTo(StablehloBroadcastInDimOptionsT *_o,
+                                         const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = broadcast_dimensions();
+    if (_e)
+    {
+      _o->broadcast_dimensions.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->broadcast_dimensions[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->broadcast_dimensions.resize(0);
+    }
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloBroadcastInDimOptions>
+StablehloBroadcastInDimOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                     const StablehloBroadcastInDimOptionsT *_o,
+                                     const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloBroadcastInDimOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloBroadcastInDimOptions>
+CreateStablehloBroadcastInDimOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                     const StablehloBroadcastInDimOptionsT *_o,
+                                     const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloBroadcastInDimOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _broadcast_dimensions =
+    _o->broadcast_dimensions.size() ? _fbb.CreateVector(_o->broadcast_dimensions) : 0;
+  return circle::CreateStablehloBroadcastInDimOptions(_fbb, _broadcast_dimensions);
+}
+
+inline StablehloCompareOptionsT *
+StablehloCompareOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloCompareOptionsT>(new StablehloCompareOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloCompareOptions::UnPackTo(StablehloCompareOptionsT *_o,
+                                  const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = comparison_direction();
+    _o->comparison_direction = _e;
+  }
+  {
+    auto _e = compare_type();
+    _o->compare_type = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloCompareOptions>
+StablehloCompareOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                              const StablehloCompareOptionsT *_o,
+                              const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloCompareOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloCompareOptions>
+CreateStablehloCompareOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                              const StablehloCompareOptionsT *_o,
+                              const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloCompareOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _comparison_direction = _o->comparison_direction;
+  auto _compare_type = _o->compare_type;
+  return circle::CreateStablehloCompareOptions(_fbb, _comparison_direction, _compare_type);
+}
+
+inline StablehloDynamicSliceOptionsT *
+StablehloDynamicSliceOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloDynamicSliceOptionsT>(new StablehloDynamicSliceOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloDynamicSliceOptions::UnPackTo(StablehloDynamicSliceOptionsT *_o,
+                                       const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = slice_sizes();
+    if (_e)
+    {
+      _o->slice_sizes.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->slice_sizes[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->slice_sizes.resize(0);
+    }
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloDynamicSliceOptions>
+StablehloDynamicSliceOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                   const StablehloDynamicSliceOptionsT *_o,
+                                   const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloDynamicSliceOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloDynamicSliceOptions>
+CreateStablehloDynamicSliceOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                   const StablehloDynamicSliceOptionsT *_o,
+                                   const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloDynamicSliceOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _slice_sizes = _o->slice_sizes.size() ? _fbb.CreateVector(_o->slice_sizes) : 0;
+  return circle::CreateStablehloDynamicSliceOptions(_fbb, _slice_sizes);
+}
+
+inline StablehloPadOptionsT *
+StablehloPadOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloPadOptionsT>(new StablehloPadOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void StablehloPadOptions::UnPackTo(StablehloPadOptionsT *_o,
+                                          const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = edge_padding_low();
+    if (_e)
+    {
+      _o->edge_padding_low.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->edge_padding_low[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->edge_padding_low.resize(0);
+    }
+  }
+  {
+    auto _e = edge_padding_high();
+    if (_e)
+    {
+      _o->edge_padding_high.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->edge_padding_high[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->edge_padding_high.resize(0);
+    }
+  }
+  {
+    auto _e = interior_padding();
+    if (_e)
+    {
+      _o->interior_padding.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->interior_padding[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->interior_padding.resize(0);
+    }
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloPadOptions>
+StablehloPadOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloPadOptionsT *_o,
+                          const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloPadOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloPadOptions>
+CreateStablehloPadOptions(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloPadOptionsT *_o,
+                          const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloPadOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _edge_padding_low =
+    _o->edge_padding_low.size() ? _fbb.CreateVector(_o->edge_padding_low) : 0;
+  auto _edge_padding_high =
+    _o->edge_padding_high.size() ? _fbb.CreateVector(_o->edge_padding_high) : 0;
+  auto _interior_padding =
+    _o->interior_padding.size() ? _fbb.CreateVector(_o->interior_padding) : 0;
+  return circle::CreateStablehloPadOptions(_fbb, _edge_padding_low, _edge_padding_high,
+                                           _interior_padding);
+}
+
+inline StablehloIotaOptionsT *
+StablehloIotaOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloIotaOptionsT>(new StablehloIotaOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloIotaOptions::UnPackTo(StablehloIotaOptionsT *_o,
+                               const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = iota_dimension();
+    _o->iota_dimension = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloIotaOptions>
+StablehloIotaOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloIotaOptionsT *_o,
+                           const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloIotaOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloIotaOptions>
+CreateStablehloIotaOptions(::flatbuffers::FlatBufferBuilder &_fbb, const StablehloIotaOptionsT *_o,
+                           const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloIotaOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _iota_dimension = _o->iota_dimension;
+  return circle::CreateStablehloIotaOptions(_fbb, _iota_dimension);
+}
+
+inline StablehloCustomCallOptionsT *
+StablehloCustomCallOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloCustomCallOptionsT>(new StablehloCustomCallOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloCustomCallOptions::UnPackTo(StablehloCustomCallOptionsT *_o,
+                                     const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = call_target_name();
+    if (_e)
+      _o->call_target_name = _e->str();
+  }
+  {
+    auto _e = has_side_effect();
+    _o->has_side_effect = _e;
+  }
+  {
+    auto _e = backend_config();
+    if (_e)
+      _o->backend_config = _e->str();
+  }
+  {
+    auto _e = api_version();
+    _o->api_version = _e;
+  }
+  {
+    auto _e = called_computations();
+    if (_e)
+    {
+      _o->called_computations.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->called_computations[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->called_computations.resize(0);
+    }
+  }
+  {
+    auto _e = custom_attributes();
+    if (_e)
+    {
+      _o->custom_attributes.resize(_e->size());
+      std::copy(_e->begin(), _e->end(), _o->custom_attributes.begin());
+    }
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloCustomCallOptions>
+StablehloCustomCallOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                 const StablehloCustomCallOptionsT *_o,
+                                 const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloCustomCallOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloCustomCallOptions>
+CreateStablehloCustomCallOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                 const StablehloCustomCallOptionsT *_o,
+                                 const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloCustomCallOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _call_target_name =
+    _o->call_target_name.empty() ? 0 : _fbb.CreateString(_o->call_target_name);
+  auto _has_side_effect = _o->has_side_effect;
+  auto _backend_config = _o->backend_config.empty() ? 0 : _fbb.CreateString(_o->backend_config);
+  auto _api_version = _o->api_version;
+  auto _called_computations =
+    _o->called_computations.size() ? _fbb.CreateVector(_o->called_computations) : 0;
+  auto _custom_attributes =
+    _o->custom_attributes.size() ? _fbb.CreateVector(_o->custom_attributes) : 0;
+  return circle::CreateStablehloCustomCallOptions(_fbb, _call_target_name, _has_side_effect,
+                                                  _backend_config, _api_version,
+                                                  _called_computations, _custom_attributes);
+}
+
+inline StablehloReduceOptionsT *
+StablehloReduceOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloReduceOptionsT>(new StablehloReduceOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloReduceOptions::UnPackTo(StablehloReduceOptionsT *_o,
+                                 const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = dimensions();
+    if (_e)
+    {
+      _o->dimensions.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->dimensions[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->dimensions.resize(0);
+    }
+  }
+  {
+    auto _e = body_subgraph_index();
+    _o->body_subgraph_index = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloReduceOptions>
+StablehloReduceOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                             const StablehloReduceOptionsT *_o,
+                             const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloReduceOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloReduceOptions>
+CreateStablehloReduceOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                             const StablehloReduceOptionsT *_o,
+                             const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloReduceOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _dimensions = _o->dimensions.size() ? _fbb.CreateVector(_o->dimensions) : 0;
+  auto _body_subgraph_index = _o->body_subgraph_index;
+  return circle::CreateStablehloReduceOptions(_fbb, _dimensions, _body_subgraph_index);
+}
+
+inline StablehloSliceOptionsT *
+StablehloSliceOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloSliceOptionsT>(new StablehloSliceOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloSliceOptions::UnPackTo(StablehloSliceOptionsT *_o,
+                                const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = start_indices();
+    if (_e)
+    {
+      _o->start_indices.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->start_indices[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->start_indices.resize(0);
+    }
+  }
+  {
+    auto _e = limit_indices();
+    if (_e)
+    {
+      _o->limit_indices.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->limit_indices[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->limit_indices.resize(0);
+    }
+  }
+  {
+    auto _e = strides();
+    if (_e)
+    {
+      _o->strides.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->strides[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->strides.resize(0);
+    }
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloSliceOptions>
+StablehloSliceOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                            const StablehloSliceOptionsT *_o,
+                            const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloSliceOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloSliceOptions>
+CreateStablehloSliceOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                            const StablehloSliceOptionsT *_o,
+                            const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloSliceOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _start_indices = _o->start_indices.size() ? _fbb.CreateVector(_o->start_indices) : 0;
+  auto _limit_indices = _o->limit_indices.size() ? _fbb.CreateVector(_o->limit_indices) : 0;
+  auto _strides = _o->strides.size() ? _fbb.CreateVector(_o->strides) : 0;
+  return circle::CreateStablehloSliceOptions(_fbb, _start_indices, _limit_indices, _strides);
+}
+
+inline StablehloConvolutionOptionsT *
+StablehloConvolutionOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloConvolutionOptionsT>(new StablehloConvolutionOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloConvolutionOptions::UnPackTo(StablehloConvolutionOptionsT *_o,
+                                      const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = window_strides();
+    if (_e)
+    {
+      _o->window_strides.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->window_strides[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->window_strides.resize(0);
+    }
+  }
+  {
+    auto _e = padding();
+    if (_e)
+    {
+      _o->padding.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->padding[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->padding.resize(0);
+    }
+  }
+  {
+    auto _e = lhs_dilation();
+    if (_e)
+    {
+      _o->lhs_dilation.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->lhs_dilation[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->lhs_dilation.resize(0);
+    }
+  }
+  {
+    auto _e = rhs_dilation();
+    if (_e)
+    {
+      _o->rhs_dilation.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->rhs_dilation[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->rhs_dilation.resize(0);
+    }
+  }
+  {
+    auto _e = window_reversal();
+    if (_e)
+    {
+      _o->window_reversal.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->window_reversal[_i] = _e->Get(_i) != 0;
+      }
+    }
+    else
+    {
+      _o->window_reversal.resize(0);
+    }
+  }
+  {
+    auto _e = input_batch_dimension();
+    _o->input_batch_dimension = _e;
+  }
+  {
+    auto _e = input_feature_dimension();
+    _o->input_feature_dimension = _e;
+  }
+  {
+    auto _e = input_spatial_dimensions();
+    if (_e)
+    {
+      _o->input_spatial_dimensions.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->input_spatial_dimensions[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->input_spatial_dimensions.resize(0);
+    }
+  }
+  {
+    auto _e = kernel_input_feature_dimension();
+    _o->kernel_input_feature_dimension = _e;
+  }
+  {
+    auto _e = kernel_output_feature_dimension();
+    _o->kernel_output_feature_dimension = _e;
+  }
+  {
+    auto _e = kernel_spatial_dimensions();
+    if (_e)
+    {
+      _o->kernel_spatial_dimensions.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->kernel_spatial_dimensions[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->kernel_spatial_dimensions.resize(0);
+    }
+  }
+  {
+    auto _e = output_batch_dimension();
+    _o->output_batch_dimension = _e;
+  }
+  {
+    auto _e = output_feature_dimension();
+    _o->output_feature_dimension = _e;
+  }
+  {
+    auto _e = output_spatial_dimensions();
+    if (_e)
+    {
+      _o->output_spatial_dimensions.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->output_spatial_dimensions[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->output_spatial_dimensions.resize(0);
+    }
+  }
+  {
+    auto _e = feature_group_count();
+    _o->feature_group_count = _e;
+  }
+  {
+    auto _e = batch_group_count();
+    _o->batch_group_count = _e;
+  }
+  {
+    auto _e = precision_config();
+    if (_e)
+    {
+      _o->precision_config.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->precision_config[_i] = static_cast<circle::StablehloPrecisionConfig>(_e->Get(_i));
+      }
+    }
+    else
+    {
+      _o->precision_config.resize(0);
+    }
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloConvolutionOptions>
+StablehloConvolutionOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                  const StablehloConvolutionOptionsT *_o,
+                                  const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloConvolutionOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloConvolutionOptions>
+CreateStablehloConvolutionOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                  const StablehloConvolutionOptionsT *_o,
+                                  const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloConvolutionOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _window_strides = _o->window_strides.size() ? _fbb.CreateVector(_o->window_strides) : 0;
+  auto _padding = _o->padding.size() ? _fbb.CreateVector(_o->padding) : 0;
+  auto _lhs_dilation = _o->lhs_dilation.size() ? _fbb.CreateVector(_o->lhs_dilation) : 0;
+  auto _rhs_dilation = _o->rhs_dilation.size() ? _fbb.CreateVector(_o->rhs_dilation) : 0;
+  auto _window_reversal = _o->window_reversal.size() ? _fbb.CreateVector(_o->window_reversal) : 0;
+  auto _input_batch_dimension = _o->input_batch_dimension;
+  auto _input_feature_dimension = _o->input_feature_dimension;
+  auto _input_spatial_dimensions =
+    _o->input_spatial_dimensions.size() ? _fbb.CreateVector(_o->input_spatial_dimensions) : 0;
+  auto _kernel_input_feature_dimension = _o->kernel_input_feature_dimension;
+  auto _kernel_output_feature_dimension = _o->kernel_output_feature_dimension;
+  auto _kernel_spatial_dimensions =
+    _o->kernel_spatial_dimensions.size() ? _fbb.CreateVector(_o->kernel_spatial_dimensions) : 0;
+  auto _output_batch_dimension = _o->output_batch_dimension;
+  auto _output_feature_dimension = _o->output_feature_dimension;
+  auto _output_spatial_dimensions =
+    _o->output_spatial_dimensions.size() ? _fbb.CreateVector(_o->output_spatial_dimensions) : 0;
+  auto _feature_group_count = _o->feature_group_count;
+  auto _batch_group_count = _o->batch_group_count;
+  auto _precision_config =
+    _o->precision_config.size()
+      ? _fbb.CreateVectorScalarCast<uint32_t>(::flatbuffers::data(_o->precision_config),
+                                              _o->precision_config.size())
+      : 0;
+  return circle::CreateStablehloConvolutionOptions(
+    _fbb, _window_strides, _padding, _lhs_dilation, _rhs_dilation, _window_reversal,
+    _input_batch_dimension, _input_feature_dimension, _input_spatial_dimensions,
+    _kernel_input_feature_dimension, _kernel_output_feature_dimension, _kernel_spatial_dimensions,
+    _output_batch_dimension, _output_feature_dimension, _output_spatial_dimensions,
+    _feature_group_count, _batch_group_count, _precision_config);
+}
+
+inline StablehloScatterOptionsT *
+StablehloScatterOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<StablehloScatterOptionsT>(new StablehloScatterOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloScatterOptions::UnPackTo(StablehloScatterOptionsT *_o,
+                                  const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = indices_are_sorted();
+    _o->indices_are_sorted = _e;
+  }
+  {
+    auto _e = update_window_dims();
+    if (_e)
+    {
+      _o->update_window_dims.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->update_window_dims[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->update_window_dims.resize(0);
+    }
+  }
+  {
+    auto _e = inserted_window_dims();
+    if (_e)
+    {
+      _o->inserted_window_dims.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->inserted_window_dims[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->inserted_window_dims.resize(0);
+    }
+  }
+  {
+    auto _e = scatter_dims_to_operand_dims();
+    if (_e)
+    {
+      _o->scatter_dims_to_operand_dims.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->scatter_dims_to_operand_dims[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->scatter_dims_to_operand_dims.resize(0);
+    }
+  }
+  {
+    auto _e = index_vector_dim();
+    _o->index_vector_dim = _e;
+  }
+  {
+    auto _e = unique_indices();
+    _o->unique_indices = _e;
+  }
+  {
+    auto _e = update_computation_subgraph_index();
+    _o->update_computation_subgraph_index = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloScatterOptions>
+StablehloScatterOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                              const StablehloScatterOptionsT *_o,
+                              const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloScatterOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloScatterOptions>
+CreateStablehloScatterOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                              const StablehloScatterOptionsT *_o,
+                              const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloScatterOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _indices_are_sorted = _o->indices_are_sorted;
+  auto _update_window_dims =
+    _o->update_window_dims.size() ? _fbb.CreateVector(_o->update_window_dims) : 0;
+  auto _inserted_window_dims =
+    _o->inserted_window_dims.size() ? _fbb.CreateVector(_o->inserted_window_dims) : 0;
+  auto _scatter_dims_to_operand_dims = _o->scatter_dims_to_operand_dims.size()
+                                         ? _fbb.CreateVector(_o->scatter_dims_to_operand_dims)
+                                         : 0;
+  auto _index_vector_dim = _o->index_vector_dim;
+  auto _unique_indices = _o->unique_indices;
+  auto _update_computation_subgraph_index = _o->update_computation_subgraph_index;
+  return circle::CreateStablehloScatterOptions(_fbb, _indices_are_sorted, _update_window_dims,
+                                               _inserted_window_dims, _scatter_dims_to_operand_dims,
+                                               _index_vector_dim, _unique_indices,
+                                               _update_computation_subgraph_index);
+}
+
+inline StablehloRngBitGeneratorOptionsT *
+StablehloRngBitGeneratorOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o =
+    std::unique_ptr<StablehloRngBitGeneratorOptionsT>(new StablehloRngBitGeneratorOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+StablehloRngBitGeneratorOptions::UnPackTo(StablehloRngBitGeneratorOptionsT *_o,
+                                          const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = algorithm();
+    _o->algorithm = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<StablehloRngBitGeneratorOptions>
+StablehloRngBitGeneratorOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                      const StablehloRngBitGeneratorOptionsT *_o,
+                                      const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateStablehloRngBitGeneratorOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<StablehloRngBitGeneratorOptions>
+CreateStablehloRngBitGeneratorOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                      const StablehloRngBitGeneratorOptionsT *_o,
+                                      const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const StablehloRngBitGeneratorOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _algorithm = _o->algorithm;
+  return circle::CreateStablehloRngBitGeneratorOptions(_fbb, _algorithm);
+}
+
+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;
+  }
+  {
+    auto _e = quantized_bias_type();
+    _o->quantized_bias_type = _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;
+  auto _quantized_bias_type = _o->quantized_bias_type;
+  return circle::CreateConv2DOptions(_fbb, _padding, _stride_w, _stride_h,
+                                     _fused_activation_function, _dilation_w_factor,
+                                     _dilation_h_factor, _quantized_bias_type);
+}
+
+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);
+      }
+    }
+    else
+    {
+      _o->num_columns_per_channel.resize(0);
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->embedding_dim_per_channel.resize(0);
+    }
+  }
+}
+
+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;
+  }
+  {
+    auto _e = quantized_bias_type();
+    _o->quantized_bias_type = _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;
+  auto _quantized_bias_type = _o->quantized_bias_type;
+  return circle::CreateFullyConnectedOptions(_fbb, _fused_activation_function, _weights_format,
+                                             _keep_num_dims, _asymmetric_quantize_inputs,
+                                             _quantized_bias_type);
+}
+
+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;
+  }
+  {
+    auto _e = diagonal_recurrent_tensors();
+    _o->diagonal_recurrent_tensors = _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;
+  auto _diagonal_recurrent_tensors = _o->diagonal_recurrent_tensors;
+  return circle::CreateUnidirectionalSequenceLSTMOptions(
+    _fbb, _fused_activation_function, _cell_clip, _proj_clip, _time_major,
+    _asymmetric_quantize_inputs, _diagonal_recurrent_tensors);
+}
+
+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);
+      }
+    }
+    else
+    {
+      _o->new_shape.resize(0);
+    }
+  }
+}
+
+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);
+      }
+    }
+    else
+    {
+      _o->squeeze_dims.resize(0);
+    }
+  }
+}
+
+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;
+  }
+  {
+    auto _e = offset();
+    _o->offset = _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;
+  auto _offset = _o->offset;
+  return circle::CreateStridedSliceOptions(_fbb, _begin_mask, _end_mask, _ellipsis_mask,
+                                           _new_axis_mask, _shrink_axis_mask, _offset);
+}
+
+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;
+  }
+  {
+    auto _e = fused_activation_function();
+    _o->fused_activation_function = _e;
+  }
+  {
+    auto _e = quantized_bias_type();
+    _o->quantized_bias_type = _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;
+  auto _fused_activation_function = _o->fused_activation_function;
+  auto _quantized_bias_type = _o->quantized_bias_type;
+  return circle::CreateTransposeConvOptions(_fbb, _padding, _stride_w, _stride_h,
+                                            _fused_activation_function, _quantized_bias_type);
+}
+
+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 BucketizeOptionsT *
+BucketizeOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<BucketizeOptionsT>(new BucketizeOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void BucketizeOptions::UnPackTo(BucketizeOptionsT *_o,
+                                       const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = boundaries();
+    if (_e)
+    {
+      _o->boundaries.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        _o->boundaries[_i] = _e->Get(_i);
+      }
+    }
+    else
+    {
+      _o->boundaries.resize(0);
+    }
+  }
+}
+
+inline ::flatbuffers::Offset<BucketizeOptions>
+BucketizeOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT *_o,
+                       const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateBucketizeOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<BucketizeOptions>
+CreateBucketizeOptions(::flatbuffers::FlatBufferBuilder &_fbb, const BucketizeOptionsT *_o,
+                       const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const BucketizeOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _boundaries = _o->boundaries.size() ? _fbb.CreateVector(_o->boundaries) : 0;
+  return circle::CreateBucketizeOptions(_fbb, _boundaries);
+}
+
+inline GeluOptionsT *GeluOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<GeluOptionsT>(new GeluOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void GeluOptions::UnPackTo(GeluOptionsT *_o,
+                                  const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = approximate();
+    _o->approximate = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<GeluOptions>
+GeluOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT *_o,
+                  const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateGeluOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<GeluOptions>
+CreateGeluOptions(::flatbuffers::FlatBufferBuilder &_fbb, const GeluOptionsT *_o,
+                  const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const GeluOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _approximate = _o->approximate;
+  return circle::CreateGeluOptions(_fbb, _approximate);
+}
+
+inline DynamicUpdateSliceOptionsT *
+DynamicUpdateSliceOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<DynamicUpdateSliceOptionsT>(new DynamicUpdateSliceOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+DynamicUpdateSliceOptions::UnPackTo(DynamicUpdateSliceOptionsT *_o,
+                                    const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<DynamicUpdateSliceOptions>
+DynamicUpdateSliceOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const DynamicUpdateSliceOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateDynamicUpdateSliceOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<DynamicUpdateSliceOptions>
+CreateDynamicUpdateSliceOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const DynamicUpdateSliceOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const DynamicUpdateSliceOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateDynamicUpdateSliceOptions(_fbb);
+}
+
+inline UnsortedSegmentProdOptionsT *
+UnsortedSegmentProdOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<UnsortedSegmentProdOptionsT>(new UnsortedSegmentProdOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+UnsortedSegmentProdOptions::UnPackTo(UnsortedSegmentProdOptionsT *_o,
+                                     const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<UnsortedSegmentProdOptions>
+UnsortedSegmentProdOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                 const UnsortedSegmentProdOptionsT *_o,
+                                 const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateUnsortedSegmentProdOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<UnsortedSegmentProdOptions>
+CreateUnsortedSegmentProdOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                 const UnsortedSegmentProdOptionsT *_o,
+                                 const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const UnsortedSegmentProdOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateUnsortedSegmentProdOptions(_fbb);
+}
+
+inline UnsortedSegmentMaxOptionsT *
+UnsortedSegmentMaxOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<UnsortedSegmentMaxOptionsT>(new UnsortedSegmentMaxOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+UnsortedSegmentMaxOptions::UnPackTo(UnsortedSegmentMaxOptionsT *_o,
+                                    const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<UnsortedSegmentMaxOptions>
+UnsortedSegmentMaxOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMaxOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateUnsortedSegmentMaxOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<UnsortedSegmentMaxOptions>
+CreateUnsortedSegmentMaxOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMaxOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const UnsortedSegmentMaxOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateUnsortedSegmentMaxOptions(_fbb);
+}
+
+inline UnsortedSegmentSumOptionsT *
+UnsortedSegmentSumOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<UnsortedSegmentSumOptionsT>(new UnsortedSegmentSumOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+UnsortedSegmentSumOptions::UnPackTo(UnsortedSegmentSumOptionsT *_o,
+                                    const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<UnsortedSegmentSumOptions>
+UnsortedSegmentSumOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentSumOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateUnsortedSegmentSumOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<UnsortedSegmentSumOptions>
+CreateUnsortedSegmentSumOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentSumOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const UnsortedSegmentSumOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateUnsortedSegmentSumOptions(_fbb);
+}
+
+inline ATan2OptionsT *
+ATan2Options::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<ATan2OptionsT>(new ATan2OptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void ATan2Options::UnPackTo(ATan2OptionsT *_o,
+                                   const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<ATan2Options>
+ATan2Options::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT *_o,
+                   const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateATan2Options(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<ATan2Options>
+CreateATan2Options(::flatbuffers::FlatBufferBuilder &_fbb, const ATan2OptionsT *_o,
+                   const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const ATan2OptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateATan2Options(_fbb);
+}
+
+inline UnsortedSegmentMinOptionsT *
+UnsortedSegmentMinOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<UnsortedSegmentMinOptionsT>(new UnsortedSegmentMinOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void
+UnsortedSegmentMinOptions::UnPackTo(UnsortedSegmentMinOptionsT *_o,
+                                    const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<UnsortedSegmentMinOptions>
+UnsortedSegmentMinOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMinOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateUnsortedSegmentMinOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<UnsortedSegmentMinOptions>
+CreateUnsortedSegmentMinOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                const UnsortedSegmentMinOptionsT *_o,
+                                const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const UnsortedSegmentMinOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateUnsortedSegmentMinOptions(_fbb);
+}
+
+inline SignOptionsT *SignOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<SignOptionsT>(new SignOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void SignOptions::UnPackTo(SignOptionsT *_o,
+                                  const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<SignOptions>
+SignOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT *_o,
+                  const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateSignOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<SignOptions>
+CreateSignOptions(::flatbuffers::FlatBufferBuilder &_fbb, const SignOptionsT *_o,
+                  const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const SignOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateSignOptions(_fbb);
+}
+
+inline BitcastOptionsT *
+BitcastOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<BitcastOptionsT>(new BitcastOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void BitcastOptions::UnPackTo(BitcastOptionsT *_o,
+                                     const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<BitcastOptions>
+BitcastOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const BitcastOptionsT *_o,
+                     const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateBitcastOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<BitcastOptions>
+CreateBitcastOptions(::flatbuffers::FlatBufferBuilder &_fbb, const BitcastOptionsT *_o,
+                     const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const BitcastOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateBitcastOptions(_fbb);
+}
+
+inline BitwiseXorOptionsT *
+BitwiseXorOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<BitwiseXorOptionsT>(new BitwiseXorOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void BitwiseXorOptions::UnPackTo(BitwiseXorOptionsT *_o,
+                                        const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<BitwiseXorOptions>
+BitwiseXorOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const BitwiseXorOptionsT *_o,
+                        const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateBitwiseXorOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<BitwiseXorOptions>
+CreateBitwiseXorOptions(::flatbuffers::FlatBufferBuilder &_fbb, const BitwiseXorOptionsT *_o,
+                        const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const BitwiseXorOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateBitwiseXorOptions(_fbb);
+}
+
+inline RightShiftOptionsT *
+RightShiftOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<RightShiftOptionsT>(new RightShiftOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void RightShiftOptions::UnPackTo(RightShiftOptionsT *_o,
+                                        const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<RightShiftOptions>
+RightShiftOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const RightShiftOptionsT *_o,
+                        const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateRightShiftOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<RightShiftOptions>
+CreateRightShiftOptions(::flatbuffers::FlatBufferBuilder &_fbb, const RightShiftOptionsT *_o,
+                        const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const RightShiftOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateRightShiftOptions(_fbb);
+}
+
+inline DilateOptionsT *
+DilateOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<DilateOptionsT>(new DilateOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void DilateOptions::UnPackTo(DilateOptionsT *_o,
+                                    const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+}
+
+inline ::flatbuffers::Offset<DilateOptions>
+DilateOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const DilateOptionsT *_o,
+                    const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateDilateOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<DilateOptions>
+CreateDilateOptions(::flatbuffers::FlatBufferBuilder &_fbb, const DilateOptionsT *_o,
+                    const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const DilateOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  return circle::CreateDilateOptions(_fbb);
+}
+
+inline ReduceWindowOptionsT *
+ReduceWindowOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<ReduceWindowOptionsT>(new ReduceWindowOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void ReduceWindowOptions::UnPackTo(ReduceWindowOptionsT *_o,
+                                          const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = reduce_function();
+    _o->reduce_function = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<ReduceWindowOptions>
+ReduceWindowOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const ReduceWindowOptionsT *_o,
+                          const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateReduceWindowOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<ReduceWindowOptions>
+CreateReduceWindowOptions(::flatbuffers::FlatBufferBuilder &_fbb, const ReduceWindowOptionsT *_o,
+                          const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const ReduceWindowOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _reduce_function = _o->reduce_function;
+  return circle::CreateReduceWindowOptions(_fbb, _reduce_function);
+}
+
+inline GRUOptionsT *GRUOptions::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  auto _o = std::unique_ptr<GRUOptionsT>(new GRUOptionsT());
+  UnPackTo(_o.get(), _resolver);
+  return _o.release();
+}
+
+inline void GRUOptions::UnPackTo(GRUOptionsT *_o,
+                                 const ::flatbuffers::resolver_function_t *_resolver) const
+{
+  (void)_o;
+  (void)_resolver;
+  {
+    auto _e = fused_activation_function();
+    _o->fused_activation_function = _e;
+  }
+  {
+    auto _e = return_sequences();
+    _o->return_sequences = _e;
+  }
+  {
+    auto _e = time_major();
+    _o->time_major = _e;
+  }
+}
+
+inline ::flatbuffers::Offset<GRUOptions>
+GRUOptions::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const GRUOptionsT *_o,
+                 const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  return CreateGRUOptions(_fbb, _o, _rehasher);
+}
+
+inline ::flatbuffers::Offset<GRUOptions>
+CreateGRUOptions(::flatbuffers::FlatBufferBuilder &_fbb, const GRUOptionsT *_o,
+                 const ::flatbuffers::rehasher_function_t *_rehasher)
+{
+  (void)_rehasher;
+  (void)_o;
+  struct _VectorArgs
+  {
+    ::flatbuffers::FlatBufferBuilder *__fbb;
+    const GRUOptionsT *__o;
+    const ::flatbuffers::rehasher_function_t *__rehasher;
+  } _va = {&_fbb, _o, _rehasher};
+  (void)_va;
+  auto _fused_activation_function = _o->fused_activation_function;
+  auto _return_sequences = _o->return_sequences;
+  auto _time_major = _o->time_major;
+  return circle::CreateGRUOptions(_fbb, _fused_activation_function, _return_sequences, _time_major);
+}
+
+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);
+      }
+    }
+    else
+    {
+      _o->inputs.resize(0);
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->outputs.resize(0);
+    }
+  }
+  {
+    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;
+      }
+    }
+    else
+    {
+      _o->mutating_variable_inputs.resize(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);
+      }
+    }
+    else
+    {
+      _o->intermediates.resize(0);
+    }
+  }
+  {
+    auto _e = large_custom_options_offset();
+    _o->large_custom_options_offset = _e;
+  }
+  {
+    auto _e = large_custom_options_size();
+    _o->large_custom_options_size = _e;
+  }
+  {
+    auto _e = builtin_options_2_type();
+    _o->builtin_options_2.type = _e;
+  }
+  {
+    auto _e = builtin_options_2();
+    if (_e)
+      _o->builtin_options_2.value =
+        circle::BuiltinOptions2Union::UnPack(_e, builtin_options_2_type(), _resolver);
+  }
+}
+
+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;
+  auto _large_custom_options_offset = _o->large_custom_options_offset;
+  auto _large_custom_options_size = _o->large_custom_options_size;
+  auto _builtin_options_2_type = _o->builtin_options_2.type;
+  auto _builtin_options_2 = _o->builtin_options_2.Pack(_fbb);
+  return circle::CreateOperator(_fbb, _opcode_index, _inputs, _outputs, _builtin_options_type,
+                                _builtin_options, _custom_options, _custom_options_format,
+                                _mutating_variable_inputs, _intermediates,
+                                _large_custom_options_offset, _large_custom_options_size,
+                                _builtin_options_2_type, _builtin_options_2);
+}
+
+inline SubGraphT::SubGraphT(const SubGraphT &o) : inputs(o.inputs), outputs(o.outputs), name(o.name)
+{
+  tensors.reserve(o.tensors.size());
+  for (const auto &tensors_ : o.tensors)
+  {
+    tensors.emplace_back((tensors_) ? new circle::TensorT(*tensors_) : nullptr);
+  }
+  operators.reserve(o.operators.size());
+  for (const auto &operators_ : o.operators)
+  {
+    operators.emplace_back((operators_) ? new circle::OperatorT(*operators_) : nullptr);
+  }
+}
+
+inline SubGraphT &SubGraphT::operator=(SubGraphT o) FLATBUFFERS_NOEXCEPT
+{
+  std::swap(tensors, o.tensors);
+  std::swap(inputs, o.inputs);
+  std::swap(outputs, o.outputs);
+  std::swap(operators, o.operators);
+  std::swap(name, o.name);
+  return *this;
+}
+
+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++)
+      {
+        if (_o->tensors[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->tensors[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->tensors[_i] = std::unique_ptr<circle::TensorT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->tensors.resize(0);
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->inputs.resize(0);
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->outputs.resize(0);
+    }
+  }
+  {
+    auto _e = operators();
+    if (_e)
+    {
+      _o->operators.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        if (_o->operators[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->operators[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->operators[_i] = std::unique_ptr<circle::OperatorT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->operators.resize(0);
+    }
+  }
+  {
+    auto _e = name();
+    if (_e)
+      _o->name = _e->str();
+  }
+}
+
+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);
+  return circle::CreateSubGraph(_fbb, _tensors, _inputs, _outputs, _operators, _name);
+}
+
+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());
+    }
+  }
+  {
+    auto _e = offset();
+    _o->offset = _e;
+  }
+  {
+    auto _e = size();
+    _o->size = _e;
+  }
+}
+
+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;
+  auto _offset = _o->offset;
+  auto _size = _o->size;
+  return circle::CreateBuffer(_fbb, _data, _offset, _size);
+}
+
+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::SignatureDefT(const SignatureDefT &o)
+  : signature_key(o.signature_key), subgraph_index(o.subgraph_index)
+{
+  inputs.reserve(o.inputs.size());
+  for (const auto &inputs_ : o.inputs)
+  {
+    inputs.emplace_back((inputs_) ? new circle::TensorMapT(*inputs_) : nullptr);
+  }
+  outputs.reserve(o.outputs.size());
+  for (const auto &outputs_ : o.outputs)
+  {
+    outputs.emplace_back((outputs_) ? new circle::TensorMapT(*outputs_) : nullptr);
+  }
+}
+
+inline SignatureDefT &SignatureDefT::operator=(SignatureDefT o) FLATBUFFERS_NOEXCEPT
+{
+  std::swap(inputs, o.inputs);
+  std::swap(outputs, o.outputs);
+  std::swap(signature_key, o.signature_key);
+  std::swap(subgraph_index, o.subgraph_index);
+  return *this;
+}
+
+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++)
+      {
+        if (_o->inputs[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->inputs[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->inputs[_i] = std::unique_ptr<circle::TensorMapT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->inputs.resize(0);
+    }
+  }
+  {
+    auto _e = outputs();
+    if (_e)
+    {
+      _o->outputs.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        if (_o->outputs[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->outputs[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->outputs[_i] = std::unique_ptr<circle::TensorMapT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->outputs.resize(0);
+    }
+  }
+  {
+    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::ModelT(const ModelT &o)
+  : version(o.version), description(o.description), metadata_buffer(o.metadata_buffer)
+{
+  operator_codes.reserve(o.operator_codes.size());
+  for (const auto &operator_codes_ : o.operator_codes)
+  {
+    operator_codes.emplace_back((operator_codes_) ? new circle::OperatorCodeT(*operator_codes_)
+                                                  : nullptr);
+  }
+  subgraphs.reserve(o.subgraphs.size());
+  for (const auto &subgraphs_ : o.subgraphs)
+  {
+    subgraphs.emplace_back((subgraphs_) ? new circle::SubGraphT(*subgraphs_) : nullptr);
+  }
+  buffers.reserve(o.buffers.size());
+  for (const auto &buffers_ : o.buffers)
+  {
+    buffers.emplace_back((buffers_) ? new circle::BufferT(*buffers_) : nullptr);
+  }
+  metadata.reserve(o.metadata.size());
+  for (const auto &metadata_ : o.metadata)
+  {
+    metadata.emplace_back((metadata_) ? new circle::MetadataT(*metadata_) : nullptr);
+  }
+  signature_defs.reserve(o.signature_defs.size());
+  for (const auto &signature_defs_ : o.signature_defs)
+  {
+    signature_defs.emplace_back((signature_defs_) ? new circle::SignatureDefT(*signature_defs_)
+                                                  : nullptr);
+  }
+}
+
+inline ModelT &ModelT::operator=(ModelT o) FLATBUFFERS_NOEXCEPT
+{
+  std::swap(version, o.version);
+  std::swap(operator_codes, o.operator_codes);
+  std::swap(subgraphs, o.subgraphs);
+  std::swap(description, o.description);
+  std::swap(buffers, o.buffers);
+  std::swap(metadata_buffer, o.metadata_buffer);
+  std::swap(metadata, o.metadata);
+  std::swap(signature_defs, o.signature_defs);
+  return *this;
+}
+
+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++)
+      {
+        if (_o->operator_codes[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->operator_codes[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->operator_codes[_i] =
+            std::unique_ptr<circle::OperatorCodeT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->operator_codes.resize(0);
+    }
+  }
+  {
+    auto _e = subgraphs();
+    if (_e)
+    {
+      _o->subgraphs.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        if (_o->subgraphs[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->subgraphs[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->subgraphs[_i] = std::unique_ptr<circle::SubGraphT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->subgraphs.resize(0);
+    }
+  }
+  {
+    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++)
+      {
+        if (_o->buffers[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->buffers[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->buffers[_i] = std::unique_ptr<circle::BufferT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->buffers.resize(0);
+    }
+  }
+  {
+    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);
+      }
+    }
+    else
+    {
+      _o->metadata_buffer.resize(0);
+    }
+  }
+  {
+    auto _e = metadata();
+    if (_e)
+    {
+      _o->metadata.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        if (_o->metadata[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->metadata[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->metadata[_i] = std::unique_ptr<circle::MetadataT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->metadata.resize(0);
+    }
+  }
+  {
+    auto _e = signature_defs();
+    if (_e)
+    {
+      _o->signature_defs.resize(_e->size());
+      for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++)
+      {
+        if (_o->signature_defs[_i])
+        {
+          _e->Get(_i)->UnPackTo(_o->signature_defs[_i].get(), _resolver);
+        }
+        else
+        {
+          _o->signature_defs[_i] =
+            std::unique_ptr<circle::SignatureDefT>(_e->Get(_i)->UnPack(_resolver));
+        };
+      }
+    }
+    else
+    {
+      _o->signature_defs.resize(0);
+    }
+  }
+}
+
+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)
+{
+  (void)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
+{
+  (void)_rehasher;
+  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)
+{
+  (void)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
+{
+  (void)_rehasher;
+  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_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_GRUOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::GRUOptions *>(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)
+{
+  (void)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_BucketizeOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BucketizeOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_GeluOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::GeluOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_DynamicUpdateSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::DynamicUpdateSliceOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_UnsortedSegmentProdOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentProdOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_UnsortedSegmentMaxOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentMaxOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_UnsortedSegmentMinOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentMinOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_UnsortedSegmentSumOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentSumOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_ATan2Options:
+    {
+      auto ptr = reinterpret_cast<const circle::ATan2Options *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_SignOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::SignOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_BitcastOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BitcastOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_BitwiseXorOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BitwiseXorOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_RightShiftOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::RightShiftOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions_GRUOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::GRUOptions *>(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
+{
+  (void)_rehasher;
+  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_BucketizeOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BucketizeOptionsT *>(value);
+      return CreateBucketizeOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_GeluOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::GeluOptionsT *>(value);
+      return CreateGeluOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_DynamicUpdateSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::DynamicUpdateSliceOptionsT *>(value);
+      return CreateDynamicUpdateSliceOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_UnsortedSegmentProdOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentProdOptionsT *>(value);
+      return CreateUnsortedSegmentProdOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_UnsortedSegmentMaxOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentMaxOptionsT *>(value);
+      return CreateUnsortedSegmentMaxOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_UnsortedSegmentMinOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentMinOptionsT *>(value);
+      return CreateUnsortedSegmentMinOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_UnsortedSegmentSumOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::UnsortedSegmentSumOptionsT *>(value);
+      return CreateUnsortedSegmentSumOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_ATan2Options:
+    {
+      auto ptr = reinterpret_cast<const circle::ATan2OptionsT *>(value);
+      return CreateATan2Options(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_SignOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::SignOptionsT *>(value);
+      return CreateSignOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_BitcastOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BitcastOptionsT *>(value);
+      return CreateBitcastOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_BitwiseXorOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::BitwiseXorOptionsT *>(value);
+      return CreateBitwiseXorOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_RightShiftOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::RightShiftOptionsT *>(value);
+      return CreateRightShiftOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions_GRUOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::GRUOptionsT *>(value);
+      return CreateGRUOptions(_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_BucketizeOptions:
+    {
+      value =
+        new circle::BucketizeOptionsT(*reinterpret_cast<circle::BucketizeOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_GeluOptions:
+    {
+      value = new circle::GeluOptionsT(*reinterpret_cast<circle::GeluOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_DynamicUpdateSliceOptions:
+    {
+      value = new circle::DynamicUpdateSliceOptionsT(
+        *reinterpret_cast<circle::DynamicUpdateSliceOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentProdOptions:
+    {
+      value = new circle::UnsortedSegmentProdOptionsT(
+        *reinterpret_cast<circle::UnsortedSegmentProdOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentMaxOptions:
+    {
+      value = new circle::UnsortedSegmentMaxOptionsT(
+        *reinterpret_cast<circle::UnsortedSegmentMaxOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentMinOptions:
+    {
+      value = new circle::UnsortedSegmentMinOptionsT(
+        *reinterpret_cast<circle::UnsortedSegmentMinOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentSumOptions:
+    {
+      value = new circle::UnsortedSegmentSumOptionsT(
+        *reinterpret_cast<circle::UnsortedSegmentSumOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_ATan2Options:
+    {
+      value = new circle::ATan2OptionsT(*reinterpret_cast<circle::ATan2OptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_SignOptions:
+    {
+      value = new circle::SignOptionsT(*reinterpret_cast<circle::SignOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_BitcastOptions:
+    {
+      value = new circle::BitcastOptionsT(*reinterpret_cast<circle::BitcastOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_BitwiseXorOptions:
+    {
+      value =
+        new circle::BitwiseXorOptionsT(*reinterpret_cast<circle::BitwiseXorOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_RightShiftOptions:
+    {
+      value =
+        new circle::RightShiftOptionsT(*reinterpret_cast<circle::RightShiftOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions_GRUOptions:
+    {
+      value = new circle::GRUOptionsT(*reinterpret_cast<circle::GRUOptionsT *>(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_BucketizeOptions:
+    {
+      auto ptr = reinterpret_cast<circle::BucketizeOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_GeluOptions:
+    {
+      auto ptr = reinterpret_cast<circle::GeluOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_DynamicUpdateSliceOptions:
+    {
+      auto ptr = reinterpret_cast<circle::DynamicUpdateSliceOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentProdOptions:
+    {
+      auto ptr = reinterpret_cast<circle::UnsortedSegmentProdOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentMaxOptions:
+    {
+      auto ptr = reinterpret_cast<circle::UnsortedSegmentMaxOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentMinOptions:
+    {
+      auto ptr = reinterpret_cast<circle::UnsortedSegmentMinOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_UnsortedSegmentSumOptions:
+    {
+      auto ptr = reinterpret_cast<circle::UnsortedSegmentSumOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_ATan2Options:
+    {
+      auto ptr = reinterpret_cast<circle::ATan2OptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_SignOptions:
+    {
+      auto ptr = reinterpret_cast<circle::SignOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_BitcastOptions:
+    {
+      auto ptr = reinterpret_cast<circle::BitcastOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_BitwiseXorOptions:
+    {
+      auto ptr = reinterpret_cast<circle::BitwiseXorOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_RightShiftOptions:
+    {
+      auto ptr = reinterpret_cast<circle::RightShiftOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions_GRUOptions:
+    {
+      auto ptr = reinterpret_cast<circle::GRUOptionsT *>(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 bool VerifyBuiltinOptions2(::flatbuffers::Verifier &verifier, const void *obj,
+                                  BuiltinOptions2 type)
+{
+  switch (type)
+  {
+    case BuiltinOptions2_NONE:
+    {
+      return true;
+    }
+    case BuiltinOptions2_StablehloConcatenateOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloConcatenateOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloBroadcastInDimOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloBroadcastInDimOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloSliceOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloConvolutionOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloConvolutionOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloCustomCallOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloCustomCallOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloReduceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloReduceOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloScatterOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloScatterOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloCompareOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloCompareOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloDynamicSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloDynamicSliceOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloPadOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloPadOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloIotaOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloIotaOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloDotGeneralOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloDotGeneralOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloReduceWindowOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloReduceWindowOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloSortOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloSortOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloWhileOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloWhileOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloGatherOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloGatherOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloTransposeOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloTransposeOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_DilateOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::DilateOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_StablehloRngBitGeneratorOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloRngBitGeneratorOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions2_ReduceWindowOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::ReduceWindowOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    default:
+      return true;
+  }
+}
+
+inline bool
+VerifyBuiltinOptions2Vector(::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 (!VerifyBuiltinOptions2(verifier, values->Get(i), types->GetEnum<BuiltinOptions2>(i)))
+    {
+      return false;
+    }
+  }
+  return true;
+}
+
+inline void *BuiltinOptions2Union::UnPack(const void *obj, BuiltinOptions2 type,
+                                          const ::flatbuffers::resolver_function_t *resolver)
+{
+  (void)resolver;
+  switch (type)
+  {
+    case BuiltinOptions2_StablehloConcatenateOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloConcatenateOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloBroadcastInDimOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloBroadcastInDimOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloSliceOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloConvolutionOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloConvolutionOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloCustomCallOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloCustomCallOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloReduceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloReduceOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloScatterOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloScatterOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloCompareOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloCompareOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloDynamicSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloDynamicSliceOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloPadOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloPadOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloIotaOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloIotaOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloDotGeneralOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloDotGeneralOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloReduceWindowOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloReduceWindowOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloSortOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloSortOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloWhileOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloWhileOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloGatherOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloGatherOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloTransposeOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloTransposeOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_DilateOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::DilateOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_StablehloRngBitGeneratorOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloRngBitGeneratorOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    case BuiltinOptions2_ReduceWindowOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::ReduceWindowOptions *>(obj);
+      return ptr->UnPack(resolver);
+    }
+    default:
+      return nullptr;
+  }
+}
+
+inline ::flatbuffers::Offset<void>
+BuiltinOptions2Union::Pack(::flatbuffers::FlatBufferBuilder &_fbb,
+                           const ::flatbuffers::rehasher_function_t *_rehasher) const
+{
+  (void)_rehasher;
+  switch (type)
+  {
+    case BuiltinOptions2_StablehloConcatenateOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloConcatenateOptionsT *>(value);
+      return CreateStablehloConcatenateOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloBroadcastInDimOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloBroadcastInDimOptionsT *>(value);
+      return CreateStablehloBroadcastInDimOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloSliceOptionsT *>(value);
+      return CreateStablehloSliceOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloConvolutionOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloConvolutionOptionsT *>(value);
+      return CreateStablehloConvolutionOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloCustomCallOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloCustomCallOptionsT *>(value);
+      return CreateStablehloCustomCallOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloReduceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloReduceOptionsT *>(value);
+      return CreateStablehloReduceOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloScatterOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloScatterOptionsT *>(value);
+      return CreateStablehloScatterOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloCompareOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloCompareOptionsT *>(value);
+      return CreateStablehloCompareOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloDynamicSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloDynamicSliceOptionsT *>(value);
+      return CreateStablehloDynamicSliceOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloPadOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloPadOptionsT *>(value);
+      return CreateStablehloPadOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloIotaOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloIotaOptionsT *>(value);
+      return CreateStablehloIotaOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloDotGeneralOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloDotGeneralOptionsT *>(value);
+      return CreateStablehloDotGeneralOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloReduceWindowOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloReduceWindowOptionsT *>(value);
+      return CreateStablehloReduceWindowOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloSortOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloSortOptionsT *>(value);
+      return CreateStablehloSortOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloWhileOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloWhileOptionsT *>(value);
+      return CreateStablehloWhileOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloGatherOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloGatherOptionsT *>(value);
+      return CreateStablehloGatherOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloTransposeOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloTransposeOptionsT *>(value);
+      return CreateStablehloTransposeOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_DilateOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::DilateOptionsT *>(value);
+      return CreateDilateOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_StablehloRngBitGeneratorOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::StablehloRngBitGeneratorOptionsT *>(value);
+      return CreateStablehloRngBitGeneratorOptions(_fbb, ptr, _rehasher).Union();
+    }
+    case BuiltinOptions2_ReduceWindowOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::ReduceWindowOptionsT *>(value);
+      return CreateReduceWindowOptions(_fbb, ptr, _rehasher).Union();
+    }
+    default:
+      return 0;
+  }
+}
+
+inline BuiltinOptions2Union::BuiltinOptions2Union(const BuiltinOptions2Union &u)
+  : type(u.type), value(nullptr)
+{
+  switch (type)
+  {
+    case BuiltinOptions2_StablehloConcatenateOptions:
+    {
+      value = new circle::StablehloConcatenateOptionsT(
+        *reinterpret_cast<circle::StablehloConcatenateOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloBroadcastInDimOptions:
+    {
+      value = new circle::StablehloBroadcastInDimOptionsT(
+        *reinterpret_cast<circle::StablehloBroadcastInDimOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloSliceOptions:
+    {
+      value = new circle::StablehloSliceOptionsT(
+        *reinterpret_cast<circle::StablehloSliceOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloConvolutionOptions:
+    {
+      value = new circle::StablehloConvolutionOptionsT(
+        *reinterpret_cast<circle::StablehloConvolutionOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloCustomCallOptions:
+    {
+      value = new circle::StablehloCustomCallOptionsT(
+        *reinterpret_cast<circle::StablehloCustomCallOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloReduceOptions:
+    {
+      value = new circle::StablehloReduceOptionsT(
+        *reinterpret_cast<circle::StablehloReduceOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloScatterOptions:
+    {
+      value = new circle::StablehloScatterOptionsT(
+        *reinterpret_cast<circle::StablehloScatterOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloCompareOptions:
+    {
+      value = new circle::StablehloCompareOptionsT(
+        *reinterpret_cast<circle::StablehloCompareOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloDynamicSliceOptions:
+    {
+      value = new circle::StablehloDynamicSliceOptionsT(
+        *reinterpret_cast<circle::StablehloDynamicSliceOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloPadOptions:
+    {
+      value = new circle::StablehloPadOptionsT(
+        *reinterpret_cast<circle::StablehloPadOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloIotaOptions:
+    {
+      value = new circle::StablehloIotaOptionsT(
+        *reinterpret_cast<circle::StablehloIotaOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloDotGeneralOptions:
+    {
+      value = new circle::StablehloDotGeneralOptionsT(
+        *reinterpret_cast<circle::StablehloDotGeneralOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloReduceWindowOptions:
+    {
+      value = new circle::StablehloReduceWindowOptionsT(
+        *reinterpret_cast<circle::StablehloReduceWindowOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloSortOptions:
+    {
+      value = new circle::StablehloSortOptionsT(
+        *reinterpret_cast<circle::StablehloSortOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloWhileOptions:
+    {
+      value = new circle::StablehloWhileOptionsT(
+        *reinterpret_cast<circle::StablehloWhileOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloGatherOptions:
+    {
+      value = new circle::StablehloGatherOptionsT(
+        *reinterpret_cast<circle::StablehloGatherOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloTransposeOptions:
+    {
+      value = new circle::StablehloTransposeOptionsT(
+        *reinterpret_cast<circle::StablehloTransposeOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_DilateOptions:
+    {
+      value = new circle::DilateOptionsT(*reinterpret_cast<circle::DilateOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_StablehloRngBitGeneratorOptions:
+    {
+      value = new circle::StablehloRngBitGeneratorOptionsT(
+        *reinterpret_cast<circle::StablehloRngBitGeneratorOptionsT *>(u.value));
+      break;
+    }
+    case BuiltinOptions2_ReduceWindowOptions:
+    {
+      value = new circle::ReduceWindowOptionsT(
+        *reinterpret_cast<circle::ReduceWindowOptionsT *>(u.value));
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+inline void BuiltinOptions2Union::Reset()
+{
+  switch (type)
+  {
+    case BuiltinOptions2_StablehloConcatenateOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloConcatenateOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloBroadcastInDimOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloBroadcastInDimOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloSliceOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloSliceOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloConvolutionOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloConvolutionOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloCustomCallOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloCustomCallOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloReduceOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloReduceOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloScatterOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloScatterOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloCompareOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloCompareOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloDynamicSliceOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloDynamicSliceOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloPadOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloPadOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloIotaOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloIotaOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloDotGeneralOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloDotGeneralOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloReduceWindowOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloReduceWindowOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloSortOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloSortOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloWhileOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloWhileOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloGatherOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloGatherOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloTransposeOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloTransposeOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_DilateOptions:
+    {
+      auto ptr = reinterpret_cast<circle::DilateOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_StablehloRngBitGeneratorOptions:
+    {
+      auto ptr = reinterpret_cast<circle::StablehloRngBitGeneratorOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    case BuiltinOptions2_ReduceWindowOptions:
+    {
+      auto ptr = reinterpret_cast<circle::ReduceWindowOptionsT *>(value);
+      delete ptr;
+      break;
+    }
+    default:
+      break;
+  }
+  value = nullptr;
+  type = BuiltinOptions2_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 SizePrefixedModelBufferHasIdentifier(const void *buf)
+{
+  return ::flatbuffers::BufferHasIdentifier(buf, ModelIdentifier(), true);
+}
+
+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_CIRCLESCHEMA_CIRCLE_H_
diff --git a/runtime/libs/circle-schema/include/circle_traininfo.fbs b/runtime/libs/circle-schema/include/circle_traininfo.fbs
new file mode 100644 (file)
index 0000000..dd2362a
--- /dev/null
@@ -0,0 +1,124 @@
+// 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.
+
+namespace circle;
+
+// file_identifier for circle training.
+// The last character is a number which corresponds to the major version.
+// This identifier number should be same if it does not break compatibility.
+file_identifier "CTR0";
+
+// 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_training.
+//
+// Note: The scheme version is bumped up as it gets fields
+//       while identifier version is not changed unless compatibility is broken.
+//
+// Version 0.1: Initial version
+
+// File extension of any written files.
+file_extension "circletr";
+
+// --------
+// Optimizer: It defines fields about optimizer for training.
+//
+// It uses the well-known names for optimizer and its parameters.
+// If something is not clear, please refer to
+// https://www.tensorflow.org/api_docs/python/tf/keras/optimizers
+// --------
+
+enum Optimizer : byte {
+  SGD = 0,
+  ADAM = 1,
+}
+
+union OptimizerOptions {
+  SGDOptions,
+  AdamOptions,
+}
+
+table SGDOptions {
+  learning_rate:float;
+}
+
+table AdamOptions {
+  learning_rate:float;
+  beta_1:float;
+  beta_2:float;
+  epsilon:float;
+}
+
+// --------
+// Loss Function: It is about loss function used during training.
+//
+// It uses the well-known names for loss function and its parameters.
+// If something is not clear, please refer to
+// https://www.tensorflow.org/api_docs/python/tf/keras/losses
+// --------
+
+enum LossFn : byte {
+  SPARSE_CATEGORICAL_CROSSENTROPY = 0,
+  CATEGORICAL_CROSSENTROPY = 1,
+  MEAN_SQUARED_ERROR = 2,
+}
+
+union LossFnOptions {
+  SparseCategoricalCrossentropyOptions,
+  CategoricalCrossentropyOptions,
+  MeanSquaredErrorOptions,
+}
+
+table SparseCategoricalCrossentropyOptions {
+  from_logits: bool;
+}
+
+table CategoricalCrossentropyOptions {
+  from_logits: bool;
+}
+
+table MeanSquaredErrorOptions {
+}
+
+enum LossReductionType : byte {
+  SumOverBatchSize = 0,
+  Sum = 1,
+}
+
+// --------
+// Model Metadata
+//
+// --------
+
+table ModelTraining {
+  // Version of the schema.
+  version:uint;
+  // For training
+  optimizer: Optimizer;
+  optimizer_opt: OptimizerOptions;
+  lossfn: LossFn;
+  lossfn_opt: LossFnOptions;
+  epochs: int;
+  batch_size: int;
+  loss_reduction_type : LossReductionType;
+  trainable_ops : [int];
+}
+
+root_type ModelTraining;
diff --git a/runtime/libs/circle-schema/include/circle_traininfo_generated.h b/runtime/libs/circle-schema/include/circle_traininfo_generated.h
new file mode 100644 (file)
index 0000000..7a65c77
--- /dev/null
@@ -0,0 +1,857 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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: flatc -c --gen-onefile circle_traininfo.fbs
+// automatically generated by the FlatBuffers compiler, do not modify
+
+#ifndef FLATBUFFERS_GENERATED_CIRCLETRAININFO_CIRCLE_H_
+#define FLATBUFFERS_GENERATED_CIRCLETRAININFO_CIRCLE_H_
+
+#include "flatbuffers/flatbuffers.h"
+
+// Ensure the included flatbuffers.h is the same version as when this file was
+// generated, otherwise it may not be compatible.
+static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && FLATBUFFERS_VERSION_MINOR == 5 &&
+                FLATBUFFERS_VERSION_REVISION == 26,
+              "Non-compatible flatbuffers version included");
+
+namespace circle
+{
+
+struct SGDOptions;
+struct SGDOptionsBuilder;
+
+struct AdamOptions;
+struct AdamOptionsBuilder;
+
+struct SparseCategoricalCrossentropyOptions;
+struct SparseCategoricalCrossentropyOptionsBuilder;
+
+struct CategoricalCrossentropyOptions;
+struct CategoricalCrossentropyOptionsBuilder;
+
+struct MeanSquaredErrorOptions;
+struct MeanSquaredErrorOptionsBuilder;
+
+struct ModelTraining;
+struct ModelTrainingBuilder;
+
+enum Optimizer : int8_t
+{
+  Optimizer_SGD = 0,
+  Optimizer_ADAM = 1,
+  Optimizer_MIN = Optimizer_SGD,
+  Optimizer_MAX = Optimizer_ADAM
+};
+
+inline const Optimizer (&EnumValuesOptimizer())[2]
+{
+  static const Optimizer values[] = {Optimizer_SGD, Optimizer_ADAM};
+  return values;
+}
+
+inline const char *const *EnumNamesOptimizer()
+{
+  static const char *const names[3] = {"SGD", "ADAM", nullptr};
+  return names;
+}
+
+inline const char *EnumNameOptimizer(Optimizer e)
+{
+  if (::flatbuffers::IsOutRange(e, Optimizer_SGD, Optimizer_ADAM))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesOptimizer()[index];
+}
+
+enum OptimizerOptions : uint8_t
+{
+  OptimizerOptions_NONE = 0,
+  OptimizerOptions_SGDOptions = 1,
+  OptimizerOptions_AdamOptions = 2,
+  OptimizerOptions_MIN = OptimizerOptions_NONE,
+  OptimizerOptions_MAX = OptimizerOptions_AdamOptions
+};
+
+inline const OptimizerOptions (&EnumValuesOptimizerOptions())[3]
+{
+  static const OptimizerOptions values[] = {OptimizerOptions_NONE, OptimizerOptions_SGDOptions,
+                                            OptimizerOptions_AdamOptions};
+  return values;
+}
+
+inline const char *const *EnumNamesOptimizerOptions()
+{
+  static const char *const names[4] = {"NONE", "SGDOptions", "AdamOptions", nullptr};
+  return names;
+}
+
+inline const char *EnumNameOptimizerOptions(OptimizerOptions e)
+{
+  if (::flatbuffers::IsOutRange(e, OptimizerOptions_NONE, OptimizerOptions_AdamOptions))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesOptimizerOptions()[index];
+}
+
+template <typename T> struct OptimizerOptionsTraits
+{
+  static const OptimizerOptions enum_value = OptimizerOptions_NONE;
+};
+
+template <> struct OptimizerOptionsTraits<circle::SGDOptions>
+{
+  static const OptimizerOptions enum_value = OptimizerOptions_SGDOptions;
+};
+
+template <> struct OptimizerOptionsTraits<circle::AdamOptions>
+{
+  static const OptimizerOptions enum_value = OptimizerOptions_AdamOptions;
+};
+
+bool VerifyOptimizerOptions(::flatbuffers::Verifier &verifier, const void *obj,
+                            OptimizerOptions type);
+bool VerifyOptimizerOptionsVector(::flatbuffers::Verifier &verifier,
+                                  const ::flatbuffers::Vector<::flatbuffers::Offset<void>> *values,
+                                  const ::flatbuffers::Vector<uint8_t> *types);
+
+enum LossFn : int8_t
+{
+  LossFn_SPARSE_CATEGORICAL_CROSSENTROPY = 0,
+  LossFn_CATEGORICAL_CROSSENTROPY = 1,
+  LossFn_MEAN_SQUARED_ERROR = 2,
+  LossFn_MIN = LossFn_SPARSE_CATEGORICAL_CROSSENTROPY,
+  LossFn_MAX = LossFn_MEAN_SQUARED_ERROR
+};
+
+inline const LossFn (&EnumValuesLossFn())[3]
+{
+  static const LossFn values[] = {LossFn_SPARSE_CATEGORICAL_CROSSENTROPY,
+                                  LossFn_CATEGORICAL_CROSSENTROPY, LossFn_MEAN_SQUARED_ERROR};
+  return values;
+}
+
+inline const char *const *EnumNamesLossFn()
+{
+  static const char *const names[4] = {"SPARSE_CATEGORICAL_CROSSENTROPY",
+                                       "CATEGORICAL_CROSSENTROPY", "MEAN_SQUARED_ERROR", nullptr};
+  return names;
+}
+
+inline const char *EnumNameLossFn(LossFn e)
+{
+  if (::flatbuffers::IsOutRange(e, LossFn_SPARSE_CATEGORICAL_CROSSENTROPY,
+                                LossFn_MEAN_SQUARED_ERROR))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesLossFn()[index];
+}
+
+enum LossFnOptions : uint8_t
+{
+  LossFnOptions_NONE = 0,
+  LossFnOptions_SparseCategoricalCrossentropyOptions = 1,
+  LossFnOptions_CategoricalCrossentropyOptions = 2,
+  LossFnOptions_MeanSquaredErrorOptions = 3,
+  LossFnOptions_MIN = LossFnOptions_NONE,
+  LossFnOptions_MAX = LossFnOptions_MeanSquaredErrorOptions
+};
+
+inline const LossFnOptions (&EnumValuesLossFnOptions())[4]
+{
+  static const LossFnOptions values[] = {
+    LossFnOptions_NONE, LossFnOptions_SparseCategoricalCrossentropyOptions,
+    LossFnOptions_CategoricalCrossentropyOptions, LossFnOptions_MeanSquaredErrorOptions};
+  return values;
+}
+
+inline const char *const *EnumNamesLossFnOptions()
+{
+  static const char *const names[5] = {"NONE", "SparseCategoricalCrossentropyOptions",
+                                       "CategoricalCrossentropyOptions", "MeanSquaredErrorOptions",
+                                       nullptr};
+  return names;
+}
+
+inline const char *EnumNameLossFnOptions(LossFnOptions e)
+{
+  if (::flatbuffers::IsOutRange(e, LossFnOptions_NONE, LossFnOptions_MeanSquaredErrorOptions))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesLossFnOptions()[index];
+}
+
+template <typename T> struct LossFnOptionsTraits
+{
+  static const LossFnOptions enum_value = LossFnOptions_NONE;
+};
+
+template <> struct LossFnOptionsTraits<circle::SparseCategoricalCrossentropyOptions>
+{
+  static const LossFnOptions enum_value = LossFnOptions_SparseCategoricalCrossentropyOptions;
+};
+
+template <> struct LossFnOptionsTraits<circle::CategoricalCrossentropyOptions>
+{
+  static const LossFnOptions enum_value = LossFnOptions_CategoricalCrossentropyOptions;
+};
+
+template <> struct LossFnOptionsTraits<circle::MeanSquaredErrorOptions>
+{
+  static const LossFnOptions enum_value = LossFnOptions_MeanSquaredErrorOptions;
+};
+
+bool VerifyLossFnOptions(::flatbuffers::Verifier &verifier, const void *obj, LossFnOptions type);
+bool VerifyLossFnOptionsVector(::flatbuffers::Verifier &verifier,
+                               const ::flatbuffers::Vector<::flatbuffers::Offset<void>> *values,
+                               const ::flatbuffers::Vector<uint8_t> *types);
+
+enum LossReductionType : int8_t
+{
+  LossReductionType_SumOverBatchSize = 0,
+  LossReductionType_Sum = 1,
+  LossReductionType_MIN = LossReductionType_SumOverBatchSize,
+  LossReductionType_MAX = LossReductionType_Sum
+};
+
+inline const LossReductionType (&EnumValuesLossReductionType())[2]
+{
+  static const LossReductionType values[] = {LossReductionType_SumOverBatchSize,
+                                             LossReductionType_Sum};
+  return values;
+}
+
+inline const char *const *EnumNamesLossReductionType()
+{
+  static const char *const names[3] = {"SumOverBatchSize", "Sum", nullptr};
+  return names;
+}
+
+inline const char *EnumNameLossReductionType(LossReductionType e)
+{
+  if (::flatbuffers::IsOutRange(e, LossReductionType_SumOverBatchSize, LossReductionType_Sum))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesLossReductionType()[index];
+}
+
+struct SGDOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SGDOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_LEARNING_RATE = 4
+  };
+  float learning_rate() const { return GetField<float>(VT_LEARNING_RATE, 0.0f); }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<float>(verifier, VT_LEARNING_RATE, 4) &&
+           verifier.EndTable();
+  }
+};
+
+struct SGDOptionsBuilder
+{
+  typedef SGDOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_learning_rate(float learning_rate)
+  {
+    fbb_.AddElement<float>(SGDOptions::VT_LEARNING_RATE, learning_rate, 0.0f);
+  }
+  explicit SGDOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<SGDOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<SGDOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<SGDOptions> CreateSGDOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                                          float learning_rate = 0.0f)
+{
+  SGDOptionsBuilder builder_(_fbb);
+  builder_.add_learning_rate(learning_rate);
+  return builder_.Finish();
+}
+
+struct AdamOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef AdamOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_LEARNING_RATE = 4,
+    VT_BETA_1 = 6,
+    VT_BETA_2 = 8,
+    VT_EPSILON = 10
+  };
+  float learning_rate() const { return GetField<float>(VT_LEARNING_RATE, 0.0f); }
+  float beta_1() const { return GetField<float>(VT_BETA_1, 0.0f); }
+  float beta_2() const { return GetField<float>(VT_BETA_2, 0.0f); }
+  float epsilon() const { return GetField<float>(VT_EPSILON, 0.0f); }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<float>(verifier, VT_LEARNING_RATE, 4) &&
+           VerifyField<float>(verifier, VT_BETA_1, 4) &&
+           VerifyField<float>(verifier, VT_BETA_2, 4) &&
+           VerifyField<float>(verifier, VT_EPSILON, 4) && verifier.EndTable();
+  }
+};
+
+struct AdamOptionsBuilder
+{
+  typedef AdamOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_learning_rate(float learning_rate)
+  {
+    fbb_.AddElement<float>(AdamOptions::VT_LEARNING_RATE, learning_rate, 0.0f);
+  }
+  void add_beta_1(float beta_1) { fbb_.AddElement<float>(AdamOptions::VT_BETA_1, beta_1, 0.0f); }
+  void add_beta_2(float beta_2) { fbb_.AddElement<float>(AdamOptions::VT_BETA_2, beta_2, 0.0f); }
+  void add_epsilon(float epsilon)
+  {
+    fbb_.AddElement<float>(AdamOptions::VT_EPSILON, epsilon, 0.0f);
+  }
+  explicit AdamOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<AdamOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<AdamOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<AdamOptions>
+CreateAdamOptions(::flatbuffers::FlatBufferBuilder &_fbb, float learning_rate = 0.0f,
+                  float beta_1 = 0.0f, float beta_2 = 0.0f, float epsilon = 0.0f)
+{
+  AdamOptionsBuilder builder_(_fbb);
+  builder_.add_epsilon(epsilon);
+  builder_.add_beta_2(beta_2);
+  builder_.add_beta_1(beta_1);
+  builder_.add_learning_rate(learning_rate);
+  return builder_.Finish();
+}
+
+struct SparseCategoricalCrossentropyOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SparseCategoricalCrossentropyOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_FROM_LOGITS = 4
+  };
+  bool from_logits() const { return GetField<uint8_t>(VT_FROM_LOGITS, 0) != 0; }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_FROM_LOGITS, 1) &&
+           verifier.EndTable();
+  }
+};
+
+struct SparseCategoricalCrossentropyOptionsBuilder
+{
+  typedef SparseCategoricalCrossentropyOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_from_logits(bool from_logits)
+  {
+    fbb_.AddElement<uint8_t>(SparseCategoricalCrossentropyOptions::VT_FROM_LOGITS,
+                             static_cast<uint8_t>(from_logits), 0);
+  }
+  explicit SparseCategoricalCrossentropyOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
+    : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<SparseCategoricalCrossentropyOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<SparseCategoricalCrossentropyOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<SparseCategoricalCrossentropyOptions>
+CreateSparseCategoricalCrossentropyOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                           bool from_logits = false)
+{
+  SparseCategoricalCrossentropyOptionsBuilder builder_(_fbb);
+  builder_.add_from_logits(from_logits);
+  return builder_.Finish();
+}
+
+struct CategoricalCrossentropyOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef CategoricalCrossentropyOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_FROM_LOGITS = 4
+  };
+  bool from_logits() const { return GetField<uint8_t>(VT_FROM_LOGITS, 0) != 0; }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_FROM_LOGITS, 1) &&
+           verifier.EndTable();
+  }
+};
+
+struct CategoricalCrossentropyOptionsBuilder
+{
+  typedef CategoricalCrossentropyOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_from_logits(bool from_logits)
+  {
+    fbb_.AddElement<uint8_t>(CategoricalCrossentropyOptions::VT_FROM_LOGITS,
+                             static_cast<uint8_t>(from_logits), 0);
+  }
+  explicit CategoricalCrossentropyOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
+    : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<CategoricalCrossentropyOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<CategoricalCrossentropyOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<CategoricalCrossentropyOptions>
+CreateCategoricalCrossentropyOptions(::flatbuffers::FlatBufferBuilder &_fbb,
+                                     bool from_logits = false)
+{
+  CategoricalCrossentropyOptionsBuilder builder_(_fbb);
+  builder_.add_from_logits(from_logits);
+  return builder_.Finish();
+}
+
+struct MeanSquaredErrorOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef MeanSquaredErrorOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+struct MeanSquaredErrorOptionsBuilder
+{
+  typedef MeanSquaredErrorOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  explicit MeanSquaredErrorOptionsBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<MeanSquaredErrorOptions> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<MeanSquaredErrorOptions>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<MeanSquaredErrorOptions>
+CreateMeanSquaredErrorOptions(::flatbuffers::FlatBufferBuilder &_fbb)
+{
+  MeanSquaredErrorOptionsBuilder builder_(_fbb);
+  return builder_.Finish();
+}
+
+struct ModelTraining FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ModelTrainingBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_VERSION = 4,
+    VT_OPTIMIZER = 6,
+    VT_OPTIMIZER_OPT_TYPE = 8,
+    VT_OPTIMIZER_OPT = 10,
+    VT_LOSSFN = 12,
+    VT_LOSSFN_OPT_TYPE = 14,
+    VT_LOSSFN_OPT = 16,
+    VT_EPOCHS = 18,
+    VT_BATCH_SIZE = 20,
+    VT_LOSS_REDUCTION_TYPE = 22,
+    VT_TRAINABLE_OPS = 24
+  };
+  uint32_t version() const { return GetField<uint32_t>(VT_VERSION, 0); }
+  circle::Optimizer optimizer() const
+  {
+    return static_cast<circle::Optimizer>(GetField<int8_t>(VT_OPTIMIZER, 0));
+  }
+  circle::OptimizerOptions optimizer_opt_type() const
+  {
+    return static_cast<circle::OptimizerOptions>(GetField<uint8_t>(VT_OPTIMIZER_OPT_TYPE, 0));
+  }
+  const void *optimizer_opt() const { return GetPointer<const void *>(VT_OPTIMIZER_OPT); }
+  template <typename T> const T *optimizer_opt_as() const;
+  const circle::SGDOptions *optimizer_opt_as_SGDOptions() const
+  {
+    return optimizer_opt_type() == circle::OptimizerOptions_SGDOptions
+             ? static_cast<const circle::SGDOptions *>(optimizer_opt())
+             : nullptr;
+  }
+  const circle::AdamOptions *optimizer_opt_as_AdamOptions() const
+  {
+    return optimizer_opt_type() == circle::OptimizerOptions_AdamOptions
+             ? static_cast<const circle::AdamOptions *>(optimizer_opt())
+             : nullptr;
+  }
+  circle::LossFn lossfn() const
+  {
+    return static_cast<circle::LossFn>(GetField<int8_t>(VT_LOSSFN, 0));
+  }
+  circle::LossFnOptions lossfn_opt_type() const
+  {
+    return static_cast<circle::LossFnOptions>(GetField<uint8_t>(VT_LOSSFN_OPT_TYPE, 0));
+  }
+  const void *lossfn_opt() const { return GetPointer<const void *>(VT_LOSSFN_OPT); }
+  template <typename T> const T *lossfn_opt_as() const;
+  const circle::SparseCategoricalCrossentropyOptions *
+  lossfn_opt_as_SparseCategoricalCrossentropyOptions() const
+  {
+    return lossfn_opt_type() == circle::LossFnOptions_SparseCategoricalCrossentropyOptions
+             ? static_cast<const circle::SparseCategoricalCrossentropyOptions *>(lossfn_opt())
+             : nullptr;
+  }
+  const circle::CategoricalCrossentropyOptions *lossfn_opt_as_CategoricalCrossentropyOptions() const
+  {
+    return lossfn_opt_type() == circle::LossFnOptions_CategoricalCrossentropyOptions
+             ? static_cast<const circle::CategoricalCrossentropyOptions *>(lossfn_opt())
+             : nullptr;
+  }
+  const circle::MeanSquaredErrorOptions *lossfn_opt_as_MeanSquaredErrorOptions() const
+  {
+    return lossfn_opt_type() == circle::LossFnOptions_MeanSquaredErrorOptions
+             ? static_cast<const circle::MeanSquaredErrorOptions *>(lossfn_opt())
+             : nullptr;
+  }
+  int32_t epochs() const { return GetField<int32_t>(VT_EPOCHS, 0); }
+  int32_t batch_size() const { return GetField<int32_t>(VT_BATCH_SIZE, 0); }
+  circle::LossReductionType loss_reduction_type() const
+  {
+    return static_cast<circle::LossReductionType>(GetField<int8_t>(VT_LOSS_REDUCTION_TYPE, 0));
+  }
+  const ::flatbuffers::Vector<int32_t> *trainable_ops() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int32_t> *>(VT_TRAINABLE_OPS);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<uint32_t>(verifier, VT_VERSION, 4) &&
+           VerifyField<int8_t>(verifier, VT_OPTIMIZER, 1) &&
+           VerifyField<uint8_t>(verifier, VT_OPTIMIZER_OPT_TYPE, 1) &&
+           VerifyOffset(verifier, VT_OPTIMIZER_OPT) &&
+           VerifyOptimizerOptions(verifier, optimizer_opt(), optimizer_opt_type()) &&
+           VerifyField<int8_t>(verifier, VT_LOSSFN, 1) &&
+           VerifyField<uint8_t>(verifier, VT_LOSSFN_OPT_TYPE, 1) &&
+           VerifyOffset(verifier, VT_LOSSFN_OPT) &&
+           VerifyLossFnOptions(verifier, lossfn_opt(), lossfn_opt_type()) &&
+           VerifyField<int32_t>(verifier, VT_EPOCHS, 4) &&
+           VerifyField<int32_t>(verifier, VT_BATCH_SIZE, 4) &&
+           VerifyField<int8_t>(verifier, VT_LOSS_REDUCTION_TYPE, 1) &&
+           VerifyOffset(verifier, VT_TRAINABLE_OPS) && verifier.VerifyVector(trainable_ops()) &&
+           verifier.EndTable();
+  }
+};
+
+template <>
+inline const circle::SGDOptions *ModelTraining::optimizer_opt_as<circle::SGDOptions>() const
+{
+  return optimizer_opt_as_SGDOptions();
+}
+
+template <>
+inline const circle::AdamOptions *ModelTraining::optimizer_opt_as<circle::AdamOptions>() const
+{
+  return optimizer_opt_as_AdamOptions();
+}
+
+template <>
+inline const circle::SparseCategoricalCrossentropyOptions *
+ModelTraining::lossfn_opt_as<circle::SparseCategoricalCrossentropyOptions>() const
+{
+  return lossfn_opt_as_SparseCategoricalCrossentropyOptions();
+}
+
+template <>
+inline const circle::CategoricalCrossentropyOptions *
+ModelTraining::lossfn_opt_as<circle::CategoricalCrossentropyOptions>() const
+{
+  return lossfn_opt_as_CategoricalCrossentropyOptions();
+}
+
+template <>
+inline const circle::MeanSquaredErrorOptions *
+ModelTraining::lossfn_opt_as<circle::MeanSquaredErrorOptions>() const
+{
+  return lossfn_opt_as_MeanSquaredErrorOptions();
+}
+
+struct ModelTrainingBuilder
+{
+  typedef ModelTraining Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_version(uint32_t version)
+  {
+    fbb_.AddElement<uint32_t>(ModelTraining::VT_VERSION, version, 0);
+  }
+  void add_optimizer(circle::Optimizer optimizer)
+  {
+    fbb_.AddElement<int8_t>(ModelTraining::VT_OPTIMIZER, static_cast<int8_t>(optimizer), 0);
+  }
+  void add_optimizer_opt_type(circle::OptimizerOptions optimizer_opt_type)
+  {
+    fbb_.AddElement<uint8_t>(ModelTraining::VT_OPTIMIZER_OPT_TYPE,
+                             static_cast<uint8_t>(optimizer_opt_type), 0);
+  }
+  void add_optimizer_opt(::flatbuffers::Offset<void> optimizer_opt)
+  {
+    fbb_.AddOffset(ModelTraining::VT_OPTIMIZER_OPT, optimizer_opt);
+  }
+  void add_lossfn(circle::LossFn lossfn)
+  {
+    fbb_.AddElement<int8_t>(ModelTraining::VT_LOSSFN, static_cast<int8_t>(lossfn), 0);
+  }
+  void add_lossfn_opt_type(circle::LossFnOptions lossfn_opt_type)
+  {
+    fbb_.AddElement<uint8_t>(ModelTraining::VT_LOSSFN_OPT_TYPE,
+                             static_cast<uint8_t>(lossfn_opt_type), 0);
+  }
+  void add_lossfn_opt(::flatbuffers::Offset<void> lossfn_opt)
+  {
+    fbb_.AddOffset(ModelTraining::VT_LOSSFN_OPT, lossfn_opt);
+  }
+  void add_epochs(int32_t epochs) { fbb_.AddElement<int32_t>(ModelTraining::VT_EPOCHS, epochs, 0); }
+  void add_batch_size(int32_t batch_size)
+  {
+    fbb_.AddElement<int32_t>(ModelTraining::VT_BATCH_SIZE, batch_size, 0);
+  }
+  void add_loss_reduction_type(circle::LossReductionType loss_reduction_type)
+  {
+    fbb_.AddElement<int8_t>(ModelTraining::VT_LOSS_REDUCTION_TYPE,
+                            static_cast<int8_t>(loss_reduction_type), 0);
+  }
+  void add_trainable_ops(::flatbuffers::Offset<::flatbuffers::Vector<int32_t>> trainable_ops)
+  {
+    fbb_.AddOffset(ModelTraining::VT_TRAINABLE_OPS, trainable_ops);
+  }
+  explicit ModelTrainingBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb)
+  {
+    start_ = fbb_.StartTable();
+  }
+  ::flatbuffers::Offset<ModelTraining> Finish()
+  {
+    const auto end = fbb_.EndTable(start_);
+    auto o = ::flatbuffers::Offset<ModelTraining>(end);
+    return o;
+  }
+};
+
+inline ::flatbuffers::Offset<ModelTraining> CreateModelTraining(
+  ::flatbuffers::FlatBufferBuilder &_fbb, uint32_t version = 0,
+  circle::Optimizer optimizer = circle::Optimizer_SGD,
+  circle::OptimizerOptions optimizer_opt_type = circle::OptimizerOptions_NONE,
+  ::flatbuffers::Offset<void> optimizer_opt = 0,
+  circle::LossFn lossfn = circle::LossFn_SPARSE_CATEGORICAL_CROSSENTROPY,
+  circle::LossFnOptions lossfn_opt_type = circle::LossFnOptions_NONE,
+  ::flatbuffers::Offset<void> lossfn_opt = 0, int32_t epochs = 0, int32_t batch_size = 0,
+  circle::LossReductionType loss_reduction_type = circle::LossReductionType_SumOverBatchSize,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int32_t>> trainable_ops = 0)
+{
+  ModelTrainingBuilder builder_(_fbb);
+  builder_.add_trainable_ops(trainable_ops);
+  builder_.add_batch_size(batch_size);
+  builder_.add_epochs(epochs);
+  builder_.add_lossfn_opt(lossfn_opt);
+  builder_.add_optimizer_opt(optimizer_opt);
+  builder_.add_version(version);
+  builder_.add_loss_reduction_type(loss_reduction_type);
+  builder_.add_lossfn_opt_type(lossfn_opt_type);
+  builder_.add_lossfn(lossfn);
+  builder_.add_optimizer_opt_type(optimizer_opt_type);
+  builder_.add_optimizer(optimizer);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<ModelTraining> CreateModelTrainingDirect(
+  ::flatbuffers::FlatBufferBuilder &_fbb, uint32_t version = 0,
+  circle::Optimizer optimizer = circle::Optimizer_SGD,
+  circle::OptimizerOptions optimizer_opt_type = circle::OptimizerOptions_NONE,
+  ::flatbuffers::Offset<void> optimizer_opt = 0,
+  circle::LossFn lossfn = circle::LossFn_SPARSE_CATEGORICAL_CROSSENTROPY,
+  circle::LossFnOptions lossfn_opt_type = circle::LossFnOptions_NONE,
+  ::flatbuffers::Offset<void> lossfn_opt = 0, int32_t epochs = 0, int32_t batch_size = 0,
+  circle::LossReductionType loss_reduction_type = circle::LossReductionType_SumOverBatchSize,
+  const std::vector<int32_t> *trainable_ops = nullptr)
+{
+  auto trainable_ops__ = trainable_ops ? _fbb.CreateVector<int32_t>(*trainable_ops) : 0;
+  return circle::CreateModelTraining(_fbb, version, optimizer, optimizer_opt_type, optimizer_opt,
+                                     lossfn, lossfn_opt_type, lossfn_opt, epochs, batch_size,
+                                     loss_reduction_type, trainable_ops__);
+}
+
+inline bool VerifyOptimizerOptions(::flatbuffers::Verifier &verifier, const void *obj,
+                                   OptimizerOptions type)
+{
+  switch (type)
+  {
+    case OptimizerOptions_NONE:
+    {
+      return true;
+    }
+    case OptimizerOptions_SGDOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::SGDOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case OptimizerOptions_AdamOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::AdamOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    default:
+      return true;
+  }
+}
+
+inline bool
+VerifyOptimizerOptionsVector(::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 (!VerifyOptimizerOptions(verifier, values->Get(i), types->GetEnum<OptimizerOptions>(i)))
+    {
+      return false;
+    }
+  }
+  return true;
+}
+
+inline bool VerifyLossFnOptions(::flatbuffers::Verifier &verifier, const void *obj,
+                                LossFnOptions type)
+{
+  switch (type)
+  {
+    case LossFnOptions_NONE:
+    {
+      return true;
+    }
+    case LossFnOptions_SparseCategoricalCrossentropyOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::SparseCategoricalCrossentropyOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case LossFnOptions_CategoricalCrossentropyOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::CategoricalCrossentropyOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case LossFnOptions_MeanSquaredErrorOptions:
+    {
+      auto ptr = reinterpret_cast<const circle::MeanSquaredErrorOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    default:
+      return true;
+  }
+}
+
+inline bool
+VerifyLossFnOptionsVector(::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 (!VerifyLossFnOptions(verifier, values->Get(i), types->GetEnum<LossFnOptions>(i)))
+    {
+      return false;
+    }
+  }
+  return true;
+}
+
+inline const circle::ModelTraining *GetModelTraining(const void *buf)
+{
+  return ::flatbuffers::GetRoot<circle::ModelTraining>(buf);
+}
+
+inline const circle::ModelTraining *GetSizePrefixedModelTraining(const void *buf)
+{
+  return ::flatbuffers::GetSizePrefixedRoot<circle::ModelTraining>(buf);
+}
+
+inline const char *ModelTrainingIdentifier() { return "CTR0"; }
+
+inline bool ModelTrainingBufferHasIdentifier(const void *buf)
+{
+  return ::flatbuffers::BufferHasIdentifier(buf, ModelTrainingIdentifier());
+}
+
+inline bool SizePrefixedModelTrainingBufferHasIdentifier(const void *buf)
+{
+  return ::flatbuffers::BufferHasIdentifier(buf, ModelTrainingIdentifier(), true);
+}
+
+inline bool VerifyModelTrainingBuffer(::flatbuffers::Verifier &verifier)
+{
+  return verifier.VerifyBuffer<circle::ModelTraining>(ModelTrainingIdentifier());
+}
+
+inline bool VerifySizePrefixedModelTrainingBuffer(::flatbuffers::Verifier &verifier)
+{
+  return verifier.VerifySizePrefixedBuffer<circle::ModelTraining>(ModelTrainingIdentifier());
+}
+
+inline const char *ModelTrainingExtension() { return "circletr"; }
+
+inline void FinishModelTrainingBuffer(::flatbuffers::FlatBufferBuilder &fbb,
+                                      ::flatbuffers::Offset<circle::ModelTraining> root)
+{
+  fbb.Finish(root, ModelTrainingIdentifier());
+}
+
+inline void FinishSizePrefixedModelTrainingBuffer(::flatbuffers::FlatBufferBuilder &fbb,
+                                                  ::flatbuffers::Offset<circle::ModelTraining> root)
+{
+  fbb.FinishSizePrefixed(root, ModelTrainingIdentifier());
+}
+
+} // namespace circle
+
+#endif // FLATBUFFERS_GENERATED_CIRCLETRAININFO_CIRCLE_H_
diff --git a/runtime/libs/misc/include/misc/RandomGenerator.h b/runtime/libs/misc/include/misc/RandomGenerator.h
deleted file mode 100644 (file)
index 8da4f7f..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @file  RandomGenerator.h
- * @brief This file contains classes for random value generation
- */
-
-#ifndef __NNFW_MISC_RANDOM_GENERATOR_H__
-#define __NNFW_MISC_RANDOM_GENERATOR_H__
-
-#include "misc/tensor/Shape.h"
-#include "misc/tensor/Index.h"
-
-#include <random>
-
-namespace nnfw
-{
-namespace misc
-{
-
-/**
- * @brief Class to generate random values
- */
-class RandomGenerator
-{
-public:
-  /**
-   * @brief Construct a new RandomGenerator object
-   * @param[in] seed          Random seed value
-   * @param[in] mean          Mean value of normal random number generation
-   * @param[in] stddev        Standard deviation of random number generation
-   * @param[in] quantization  TfLiteQuantizationParams type to represent quantization value
-   *                          (not used yet)
-   */
-  RandomGenerator(uint32_t seed, float mean, float stddev) : _rand{seed}, _dist{mean, stddev}
-  {
-    // DO NOTHING
-  }
-
-public:
-  /**
-   * @brief  Generate random numbers for type T
-   * @param[in] s Shape value
-   * @param[in] i Index value
-   * @return Random generated value
-   * @note   This is same as T generate(void) as two input parameters are not used
-   */
-  template <typename T>
-  T generate(const ::nnfw::misc::tensor::Shape &, const ::nnfw::misc::tensor::Index &)
-  {
-    return generate<T>();
-  }
-
-  /**
-   * @brief  Generate random numbers for type T
-   * @return Random generated value
-   */
-  template <typename T> T generate(void) { return _dist(_rand); }
-
-private:
-  std::minstd_rand _rand;
-  std::normal_distribution<float> _dist;
-};
-
-template <> int8_t RandomGenerator::generate<int8_t>(void);
-template <> uint8_t RandomGenerator::generate<uint8_t>(void);
-template <> bool RandomGenerator::generate<bool>(void);
-template <> int32_t RandomGenerator::generate<int32_t>(void);
-template <> int64_t RandomGenerator::generate<int64_t>(void);
-
-} // namespace misc
-} // namespace nnfw
-
-#endif // __NNFW_MISC_RANDOM_GENERATOR_H__
diff --git a/runtime/libs/misc/include/misc/benchmark.h b/runtime/libs/misc/include/misc/benchmark.h
deleted file mode 100644 (file)
index aa487ac..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 benchmark.h
- * @ingroup COM_AI_RUNTIME
- * @brief This file contains nnfw::misc::benchmark::Accumulator class
- */
-#ifndef __NNFW_MISC_BENCHMARK_H__
-#define __NNFW_MISC_BENCHMARK_H__
-
-#include <chrono>
-
-namespace nnfw
-{
-namespace misc
-{
-// Benckmark support
-namespace benchmark
-{
-
-/**
- * @brief Class to accumulate time during benchmark
- */
-template <typename T> class Accumulator
-{
-public:
-  /**
-   * @brief Construct a new Accumulator object
-   * @param[in] ref   Object to keep time duration
-   */
-  Accumulator(T &ref) : _ref(ref)
-  {
-    // DO NOTHING
-  }
-
-public:
-  /**
-   * @brief Return the reference of @c ref passed to constructor
-   * @return Reference of @c ref
-   */
-  T &operator()(void) { return _ref; }
-
-private:
-  T &_ref;
-};
-
-/**
- * @brief Run passed function and returns accumulated time
- * @tparam T            Period used by @c std::chrono::duration_cast
- * @tparam Callable     Function type to benchmark
- * @param[in] acc       Accumulated time after running @cb
- * @param[in] cb        Function to run and benchmark
- * @return Accumulated time
- */
-template <typename T, typename Callable>
-Accumulator<T> &operator<<(Accumulator<T> &&acc, Callable cb)
-{
-  auto begin = std::chrono::high_resolution_clock::now();
-  cb();
-  auto end = std::chrono::high_resolution_clock::now();
-
-  acc() += std::chrono::duration_cast<T>(end - begin);
-
-  return acc;
-}
-
-template <typename T> Accumulator<T> measure(T &out) { return Accumulator<T>(out); }
-
-} // namespace benchmark
-} // namespace misc
-} // namespace nnfw
-
-#endif // __NNFW_MISC_BENCHMARK_H__
index c9d7203..307f649 100644 (file)
@@ -30,7 +30,7 @@ namespace
 
 template <typename Arg> void _str(std::ostream &os, Arg &&arg) { os << std::forward<Arg>(arg); }
 
-template <typename Arg, typename... Args> void _str(std::ostream &os, Arg &&arg, Args &&... args)
+template <typename Arg, typename... Args> void _str(std::ostream &os, Arg &&arg, Args &&...args)
 {
   _str(os, std::forward<Arg>(arg));
   _str(os, std::forward<Args>(args)...);
@@ -55,7 +55,7 @@ inline std::vector<std::string> split(const std::string &s, char delim)
   return elems;
 }
 
-template <typename... Args> std::string str(Args &&... args)
+template <typename... Args> std::string str(Args &&...args)
 {
   std::stringstream ss;
   _str(ss, std::forward<Args>(args)...);
diff --git a/runtime/libs/misc/include/misc/to_underlying.h b/runtime/libs/misc/include/misc/to_underlying.h
new file mode 100644 (file)
index 0000000..90aa6aa
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_MISC_TO_UNDERLYING_H__
+#define __NNFW_MISC_TO_UNDERLYING_H__
+
+#include <type_traits>
+
+namespace nnfw
+{
+namespace misc
+{
+
+template <typename E> constexpr auto to_underlying(E e) noexcept
+{
+  return static_cast<std::underlying_type_t<E>>(e);
+}
+
+} // namespace misc
+} // namespace nnfw
+
+#endif // __NNFW_MISC_TO_UNDERLYING_H__
diff --git a/runtime/libs/misc/src/RandomGenerator.cpp b/runtime/libs/misc/src/RandomGenerator.cpp
deleted file mode 100644 (file)
index af07232..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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 "misc/RandomGenerator.h"
-
-namespace nnfw
-{
-namespace misc
-{
-
-template <> int8_t RandomGenerator::generate<int8_t>(void)
-{
-  // The value of type_range is 255.
-  float type_range = static_cast<float>(std::numeric_limits<int8_t>::max()) -
-                     static_cast<float>(std::numeric_limits<int8_t>::min());
-  // Most _dist values range from -5.0 to 5.0.
-  float min_range = -5.0f;
-  float max_range = 5.0f;
-  // NOTE shifted_relative_val has Gaussian distribution that origin mean was 0 and standard
-  // deviation was 2. And then its values are distributed and shift to that mean is 127.5 and range
-  // is about [0, 255].
-  float shifted_relative_val = (_dist(_rand) - min_range) * type_range / (max_range - min_range);
-
-  // shifted_relative_val is adjusted to be mapped to end points of the range, if it is out of range
-  // values.
-  if (shifted_relative_val < -128.0f)
-  {
-    return -128;
-  }
-  else if (shifted_relative_val > type_range)
-  {
-    return 127;
-  }
-
-  // Convert shifted_relative_val from float to int8
-  return static_cast<int8_t>(shifted_relative_val);
-}
-
-template <> uint8_t RandomGenerator::generate<uint8_t>(void)
-{
-  // The value of type_range is 255.
-  float type_range = static_cast<float>(std::numeric_limits<uint8_t>::max()) -
-                     static_cast<float>(std::numeric_limits<uint8_t>::min());
-  // Most _dist values range from -5.0 to 5.0.
-  float min_range = -5.0f;
-  float max_range = 5.0f;
-  // NOTE shifted_relative_val has Gaussian distribution that origin mean was 0 and standard
-  // deviation was 2. And then its values are distributed and shift to that mean is 127.5 and range
-  // is about [0, 255].
-  float shifted_relative_val = (_dist(_rand) - min_range) * type_range / (max_range - min_range);
-
-  // shifted_relative_val is adjusted to be mapped to end points of the range, if it is out of range
-  // values.
-  if (shifted_relative_val < 0.0f)
-  {
-    return 0;
-  }
-  else if (shifted_relative_val > type_range)
-  {
-    return 255;
-  }
-
-  // Convert shifted_relative_val from float to uint8
-  return static_cast<uint8_t>(shifted_relative_val);
-}
-
-template <> bool RandomGenerator::generate<bool>(void)
-{
-  std::uniform_int_distribution<> dist(0, 1); // [0, 1]
-  return dist(_rand);
-}
-
-template <> int32_t RandomGenerator::generate<int32_t>(void)
-{
-  // Instead of INT_MAX, 99 is chosen because int32_t input does not mean
-  // that the model can have any value in int32_t can hold.
-  // For example, one_hot operation gets indices as int32_t tensor.
-  // However, we usually expect it would hold a value in [0..depth).
-  // In our given model, depth was 10137.
-  const int int32_random_max = 99;
-  std::uniform_int_distribution<> dist(0, int32_random_max);
-  return dist(_rand);
-}
-
-template <> int64_t RandomGenerator::generate<int64_t>(void)
-{
-  // Instead of INT_MAX, 99 is chosen because int64_t input does not mean
-  // that the model can have any value in int64_t can hold.
-  // For example, one_hot operation gets indices as int64_t tensor.
-  // However, we usually expect it would hold a value in [0..depth).
-  // In our given model, depth was 10137.
-  const int64_t int64_random_max = 99;
-  std::uniform_int_distribution<> dist(0, int64_random_max);
-  return dist(_rand);
-}
-
-} // namespace misc
-} // namespace nnfw
diff --git a/runtime/libs/tflite/CMakeLists.txt b/runtime/libs/tflite/CMakeLists.txt
deleted file mode 100644 (file)
index 3c57790..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-nnfw_find_package(TensorFlowLite EXACT 2.8.0 QUIET)
-if(NOT TensorFlowLite_FOUND)
-  message(STATUS "Check tensorflow lite library extension build: need tensorflow lite library")
-  return()
-endif(NOT TensorFlowLite_FOUND)
-
-file(GLOB_RECURSE SOURCES "src/*.cpp")
-file(GLOB_RECURSE TESTS "src/*.test.cpp")
-list(REMOVE_ITEM SOURCES ${TESTS})
-
-add_library(nnfw_lib_tflite STATIC ${SOURCES})
-set_target_properties(nnfw_lib_tflite PROPERTIES POSITION_INDEPENDENT_CODE ON)
-target_include_directories(nnfw_lib_tflite PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
-target_link_libraries(nnfw_lib_tflite PUBLIC tensorflow-lite-2.8.0)
-target_link_libraries(nnfw_lib_tflite PUBLIC nnfw_lib_misc)
-target_link_libraries(nnfw_lib_tflite PRIVATE ${LIB_PTHREAD} dl)
-target_link_libraries(nnfw_lib_tflite PRIVATE nnfw_common)
-
-if(NOT ENABLE_TEST)
-  return()
-endif(NOT ENABLE_TEST)
-
-add_executable(nnfw_lib_tflite_test_TensorView src/TensorView.test.cpp)
-target_link_libraries(nnfw_lib_tflite_test_TensorView nnfw_lib_tflite)
diff --git a/runtime/libs/tflite/include/tflite/Diff.h b/runtime/libs/tflite/include/tflite/Diff.h
deleted file mode 100644 (file)
index 2d30d41..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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     Diff.h
- * @brief    This file contains classes for testing correctess of implementation
- * @ingroup  COM_AI_RUNTIME
- */
-
-#ifndef __NNFW_TFLITE_DIFF_H__
-#define __NNFW_TFLITE_DIFF_H__
-
-#include "tflite/TensorView.h"
-
-#include "misc/RandomGenerator.h"
-#include "misc/tensor/Index.h"
-#include "misc/tensor/Diff.h"
-#include "misc/tensor/Shape.h"
-#include "misc/tensor/Comparator.h"
-
-#include <tensorflow/lite/c/c_api.h>
-
-#include <functional>
-#include <vector>
-
-/**
- * @brief Class to define TfLite interpreter match application
- */
-class TfLiteInterpMatchApp
-{
-public:
-  /**
-   * @brief Construct a new TfLiteInterpMatchApp object with Comparator
-   * @param[in] comparator   Comparator object for tensor comparation
-   */
-  TfLiteInterpMatchApp(const nnfw::misc::tensor::Comparator &comparator)
-    : _verbose{false}, _comparator(comparator)
-  {
-    // DO NOTHING
-  }
-
-public:
-  /**
-   * @brief Get reference verbose for debugging information
-   * @return Reference of verbose value
-   */
-  int &verbose(void) { return _verbose; }
-
-private:
-  int _verbose;
-
-public:
-  /**
-   * @brief Run two interpreter and return the output matching
-   * @param[in] expected    Interpreter object of expected
-   * @param[in] obtained  Interpreter object of obtained
-   * @return  @c true if two Interpreter results are same, otherwise @c false
-   */
-  bool run(TfLiteInterpreter &expected, TfLiteInterpreter &obtained) const;
-  /**
-   * @brief Compare two TensorView values and return the match result
-   * @param[in] expected  TensorView object to read expected values
-   * @param[in] obtained  TensorView object to read obtained values
-   * @param[in] id        Tensor ID value used for debug message
-   * @return  @c true if two TensorView values are same, otherwise @c false
-   */
-  template <typename T>
-  bool compareSingleTensorView(const nnfw::tflite::TensorView<T> &expected,
-                               const nnfw::tflite::TensorView<T> &obtained, int id) const;
-
-private:
-  const nnfw::misc::tensor::Comparator &_comparator;
-};
-
-#endif // __NNFW_TFLITE_DIFF_H__
diff --git a/runtime/libs/tflite/include/tflite/InterpreterSession.h b/runtime/libs/tflite/include/tflite/InterpreterSession.h
deleted file mode 100644 (file)
index 8fc1949..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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     InterpreterSession.h
- * @brief    This file contains InterpreterSession class
- * @ingroup  COM_AI_RUNTIME
- */
-
-#ifndef __NNFW_TFLITE_INTERPRETER_SESSION_H__
-#define __NNFW_TFLITE_INTERPRETER_SESSION_H__
-
-#include "Session.h"
-
-namespace nnfw
-{
-namespace tflite
-{
-
-/**
- * @brief Class to define TfLite interpreter session which is inherited from Session class
- */
-class InterpreterSession final : public Session
-{
-public:
-  /**
-   * @brief Construct a InterpreterSession object with interpreter of TfLite
-   * @param[in] interp The TfLite interpreter pointer
-   */
-  InterpreterSession(TfLiteInterpreter *interp) : _interp{interp}
-  {
-    // DO NOTHING
-  }
-
-public:
-  /**
-   * @brief Get TfLite interpreter pointer
-   * @return The TfLite interpreter
-   */
-  TfLiteInterpreter *interp(void) override { return _interp; }
-
-public:
-  /**
-   * @brief Prepare the TfLite interpreter session
-   * @return @c true if tensor preparation is successful, otherwise @c false
-   */
-  bool prepare(void) override
-  {
-    if (kTfLiteOk != TfLiteInterpreterAllocateTensors(_interp))
-    {
-      return false;
-    }
-
-    return true;
-  }
-
-  /**
-   * @brief Run the Invoke function of TfLite interpreter
-   * @return @c true if Invoke() is successful, otherwise @c false
-   */
-  bool run(void) override
-  {
-    // Return true if Invoke returns kTfLiteOk
-    return kTfLiteOk == TfLiteInterpreterInvoke(_interp);
-  }
-
-  /**
-   * @brief Tear down TfLite interpreter session
-   * @return @c true always
-   */
-  bool teardown(void) override
-  {
-    // Do NOTHING currently
-    return true;
-  }
-
-private:
-  TfLiteInterpreter *const _interp;
-};
-
-} // namespace tflite
-} // namespace nnfw
-
-#endif // __NNFW_TFLITE_INTERPRETER_SESSION_H__
diff --git a/runtime/libs/tflite/include/tflite/RandomInputInitializer.h b/runtime/libs/tflite/include/tflite/RandomInputInitializer.h
deleted file mode 100644 (file)
index 7dac3a8..0000000
+++ /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.
- */
-
-#ifndef __NNFW_TFLITE_RANDOM_INPUT_INITIALIZER_H__
-#define __NNFW_TFLITE_RANDOM_INPUT_INITIALIZER_H__
-
-#include <misc/RandomGenerator.h>
-
-#include <tensorflow/lite/c/c_api.h>
-
-namespace nnfw
-{
-namespace tflite
-{
-
-class RandomInputInitializer
-{
-public:
-  RandomInputInitializer(misc::RandomGenerator &randgen) : _randgen{randgen}
-  {
-    // DO NOTHING
-  }
-
-  void run(TfLiteInterpreter &interp);
-
-private:
-  nnfw::misc::RandomGenerator &_randgen;
-};
-
-} // namespace tflite
-} // namespace nnfw
-
-#endif // __NNFW_TFLITE_RANDOM_INPUT_INITIALIZER_H__
diff --git a/runtime/libs/tflite/src/Diff.cpp b/runtime/libs/tflite/src/Diff.cpp
deleted file mode 100644 (file)
index 8165798..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "tflite/Diff.h"
-
-#include "misc/fp32.h"
-
-#include "misc/tensor/IndexFormatter.h"
-#include "misc/tensor/Zipper.h"
-#include "misc/tensor/Comparator.h"
-
-#include <tensorflow/lite/c/c_api.h>
-
-#include <iostream>
-#include <cassert>
-
-class DiffSummary : public nnfw::misc::tensor::Comparator::Observer
-{
-public:
-  DiffSummary()
-    : max_abs_diff_index(0), max_abs_diff_expected{0.0f}, max_abs_diff_obtained{0.0f},
-      max_abs_diff_value{0.0f}, max_rel_diff_index(0), max_rel_diff_expected{0.0f},
-      max_rel_diff_obtained{0.0f}, max_rel_diff_value{0.0f}
-  {
-    // DO NOTHING
-  }
-
-public:
-  void notify(const nnfw::misc::tensor::Index &index, float expected, float obtained) override;
-
-public:
-  nnfw::misc::tensor::Index max_abs_diff_index;
-  float max_abs_diff_expected;
-  float max_abs_diff_obtained;
-  float max_abs_diff_value;
-
-  nnfw::misc::tensor::Index max_rel_diff_index;
-  float max_rel_diff_expected;
-  float max_rel_diff_obtained;
-  float max_rel_diff_value;
-};
-
-void DiffSummary::notify(const nnfw::misc::tensor::Index &index, float expected, float obtained)
-{
-  const auto abs_diff_value = std::fabs(expected - obtained);
-
-  if (max_abs_diff_value < abs_diff_value)
-  {
-    max_abs_diff_index = index;
-    max_abs_diff_value = abs_diff_value;
-    max_abs_diff_expected = expected;
-    max_abs_diff_obtained = obtained;
-  }
-
-  const auto rel_diff_value = nnfw::misc::fp32::relative_diff(expected, obtained);
-
-  if (max_rel_diff_value < rel_diff_value)
-  {
-    max_rel_diff_index = index;
-    max_rel_diff_value = rel_diff_value;
-    max_rel_diff_expected = expected;
-    max_rel_diff_obtained = obtained;
-  }
-}
-
-template <typename T>
-bool TfLiteInterpMatchApp::compareSingleTensorView(const nnfw::tflite::TensorView<T> &expected,
-                                                   const nnfw::tflite::TensorView<T> &obtained,
-                                                   int id) const
-{
-  std::vector<nnfw::misc::tensor::Diff<T>> diffs;
-  assert(expected.shape() == obtained.shape());
-
-  using nnfw::misc::tensor::Index;
-  using nnfw::misc::tensor::zip;
-
-  zip(expected.shape(), expected, obtained)
-    << [&](const Index &index, T expected_value, T obtained_value) {
-         if (expected_value != obtained_value)
-         {
-           diffs.emplace_back(index, expected_value, obtained_value);
-         }
-       };
-
-  // TODO Unify summary generation code
-  if (diffs.size() == 0)
-  {
-    std::cout << "  Tensor #" << id << ": MATCHED" << std::endl;
-  }
-  else
-  {
-    std::cout << "  Tensor #" << id << ": UNMATCHED" << std::endl;
-    std::cout << "    " << diffs.size() << " diffs are detected" << std::endl;
-  }
-
-  if (diffs.size() > 0 && _verbose != 0)
-  {
-    std::cout << "    ---- Details ---" << std::endl;
-    for (const auto &diff : diffs)
-    {
-      std::cout << "    Diff at [" << nnfw::misc::tensor::IndexFormatter(diff.index) << "]"
-                << std::endl;
-      std::cout << "      expected: " << diff.expected << std::endl;
-      std::cout << "      obtained: " << diff.obtained << std::endl;
-    }
-  }
-
-  return diffs.size() == 0;
-}
-
-template <>
-bool TfLiteInterpMatchApp::compareSingleTensorView<float>(
-  const nnfw::tflite::TensorView<float> &expected, const nnfw::tflite::TensorView<float> &obtained,
-  int id) const
-{
-  DiffSummary summary;
-
-  assert(expected.shape() == obtained.shape());
-  auto diffs = _comparator.compare(expected.shape(), expected, obtained, &summary);
-
-  // TODO Unify summary generation code
-  if (diffs.size() == 0)
-  {
-    std::cout << "  Tensor #" << id << ": MATCHED" << std::endl;
-  }
-  else
-  {
-    std::cout << "  Tensor #" << id << ": UNMATCHED" << std::endl;
-    std::cout << "    " << diffs.size() << " diffs are detected" << std::endl;
-  }
-
-  // Print out max_diff
-  if (summary.max_abs_diff_value > 0)
-  {
-    std::cout << "    Max absolute diff at ["
-              << nnfw::misc::tensor::IndexFormatter(summary.max_abs_diff_index) << "]" << std::endl;
-    std::cout << "       expected: " << summary.max_abs_diff_expected << std::endl;
-    std::cout << "       obtained: " << summary.max_abs_diff_obtained << std::endl;
-    std::cout << "       absolute diff: " << summary.max_abs_diff_value << std::endl;
-  }
-
-  if (summary.max_rel_diff_value > 0)
-  {
-    const auto tolerance_level = summary.max_rel_diff_value / FLT_EPSILON;
-
-    std::cout << "    Max relative diff at ["
-              << nnfw::misc::tensor::IndexFormatter(summary.max_rel_diff_index) << "]" << std::endl;
-    std::cout << "       expected: " << summary.max_rel_diff_expected << std::endl;
-    std::cout << "       obtained: " << summary.max_rel_diff_obtained << std::endl;
-    std::cout << "       relative diff: " << summary.max_rel_diff_value << std::endl;
-    std::cout << "         (tolerance level = " << tolerance_level << ")" << std::endl;
-  }
-
-  if (diffs.size() > 0)
-  {
-    if (_verbose != 0)
-    {
-      std::cout << "    ---- Details ---" << std::endl;
-      for (const auto &diff : diffs)
-      {
-        const auto absolute_diff = std::fabs(diff.expected - diff.obtained);
-        const auto relative_diff = nnfw::misc::fp32::relative_diff(diff.expected, diff.obtained);
-        const auto tolerance_level = relative_diff / FLT_EPSILON;
-
-        std::cout << "    Diff at [" << nnfw::misc::tensor::IndexFormatter(diff.index) << "]"
-                  << std::endl;
-        std::cout << "      expected: " << diff.expected << std::endl;
-        std::cout << "      obtained: " << diff.obtained << std::endl;
-        std::cout << "      absolute diff: " << absolute_diff << std::endl;
-        std::cout << "      relative diff: " << relative_diff << std::endl;
-        std::cout << "         (tolerance level = " << tolerance_level << ")" << std::endl;
-      }
-    }
-
-    return false;
-  }
-  return true;
-}
-
-#include <map>
-
-bool TfLiteInterpMatchApp::run(TfLiteInterpreter &expected, TfLiteInterpreter &obtained) const
-{
-  auto output_count = TfLiteInterpreterGetOutputTensorCount(&expected);
-  assert(output_count == TfLiteInterpreterGetOutputTensorCount(&obtained));
-
-  bool all_matched = true;
-
-  using Comparator = std::function<bool(int32_t, const TfLiteTensor *, const TfLiteTensor *)>;
-
-  std::map<TfLiteType, Comparator> comparators;
-
-  comparators[kTfLiteUInt8] = [this](int32_t id, const TfLiteTensor *expected_tensor,
-                                     const TfLiteTensor *obtained_tensor) {
-    const auto expected_view = nnfw::tflite::TensorView<uint8_t>::make(expected_tensor);
-    const auto obtained_view = nnfw::tflite::TensorView<uint8_t>::make(obtained_tensor);
-
-    return compareSingleTensorView(expected_view, obtained_view, id);
-  };
-
-  comparators[kTfLiteInt32] = [this](int32_t id, const TfLiteTensor *expected_tensor,
-                                     const TfLiteTensor *obtained_tensor) {
-    const auto expected_view = nnfw::tflite::TensorView<int32_t>::make(expected_tensor);
-    const auto obtained_view = nnfw::tflite::TensorView<int32_t>::make(obtained_tensor);
-
-    return compareSingleTensorView(expected_view, obtained_view, id);
-  };
-
-  comparators[kTfLiteFloat32] = [this](int32_t id, const TfLiteTensor *expected_tensor,
-                                       const TfLiteTensor *obtained_tensor) {
-    const auto expected_view = nnfw::tflite::TensorView<float>::make(expected_tensor);
-    const auto obtained_view = nnfw::tflite::TensorView<float>::make(obtained_tensor);
-
-    return compareSingleTensorView(expected_view, obtained_view, id);
-  };
-
-  comparators[kTfLiteBool] = [this](int32_t id, const TfLiteTensor *expected_tensor,
-                                    const TfLiteTensor *obtained_tensor) {
-    const auto expected_view = nnfw::tflite::TensorView<bool>::make(expected_tensor);
-    const auto obtained_view = nnfw::tflite::TensorView<bool>::make(obtained_tensor);
-
-    return compareSingleTensorView(expected_view, obtained_view, id);
-  };
-
-  for (int32_t idx = 0; idx < output_count; idx++)
-  {
-    auto const expected_tensor = TfLiteInterpreterGetOutputTensor(&expected, idx);
-    auto const obtained_tensor = TfLiteInterpreterGetOutputTensor(&obtained, idx);
-    auto const tensor_type = TfLiteTensorType(expected_tensor);
-    assert(tensor_type == TfLiteTensorType(obtained_tensor));
-
-    auto it = comparators.find(tensor_type);
-
-    if (it == comparators.end())
-    {
-      throw std::runtime_error{"Not supported output type"};
-    }
-
-    const auto &comparator = it->second;
-
-    if (!comparator(idx, expected_tensor, obtained_tensor))
-    {
-      all_matched = false;
-    }
-  }
-
-  return all_matched;
-}
diff --git a/runtime/libs/tflite/src/RandomInputInitializer.cpp b/runtime/libs/tflite/src/RandomInputInitializer.cpp
deleted file mode 100644 (file)
index 9ed90f3..0000000
+++ /dev/null
@@ -1,71 +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 "tflite/RandomInputInitializer.h"
-#include "tflite/TensorView.h"
-
-#include <misc/tensor/IndexIterator.h>
-
-namespace nnfw
-{
-namespace tflite
-{
-namespace
-{
-
-template <typename T>
-void setValue(nnfw::misc::RandomGenerator &randgen, const TfLiteTensor *tensor)
-{
-  auto tensor_view = nnfw::tflite::TensorView<T>::make(tensor);
-
-  nnfw::misc::tensor::iterate(tensor_view.shape())
-    << [&](const nnfw::misc::tensor::Index &ind) { tensor_view.at(ind) = randgen.generate<T>(); };
-}
-
-} // namespace
-
-void RandomInputInitializer::run(TfLiteInterpreter &interp)
-{
-  const auto input_count = TfLiteInterpreterGetInputTensorCount(&interp);
-  for (int32_t idx = 0; idx < input_count; idx++)
-  {
-    auto tensor = TfLiteInterpreterGetInputTensor(&interp, idx);
-    auto const tensor_type = TfLiteTensorType(tensor);
-    switch (tensor_type)
-    {
-      case kTfLiteFloat32:
-        setValue<float>(_randgen, tensor);
-        break;
-      case kTfLiteInt32:
-        setValue<int32_t>(_randgen, tensor);
-        break;
-      case kTfLiteUInt8:
-        setValue<uint8_t>(_randgen, tensor);
-        break;
-      case kTfLiteBool:
-        setValue<bool>(_randgen, tensor);
-        break;
-      case kTfLiteInt8:
-        setValue<int8_t>(_randgen, tensor);
-        break;
-      default:
-        throw std::runtime_error{"Not supported input type"};
-    }
-  }
-}
-
-} // namespace tflite
-} // namespace nnfw
index 74f7ae5..3ba2294 100644 (file)
@@ -2,9 +2,9 @@ if(NOT BUILD_ONERT)
   return()
 endif(NOT BUILD_ONERT)
 
+add_subdirectory(api)
 add_subdirectory(backend)
-add_subdirectory(frontend)
 add_subdirectory(core)
-add_subdirectory(api)
+add_subdirectory(loader)
 add_subdirectory(odc)
 add_subdirectory(sample)
index badd5d1..8a57010 100644 (file)
@@ -1,34 +1,3 @@
-file(GLOB_RECURSE API_SRC "*.cc")
-
-set(ONERT_DEV nnfw-dev)
-add_library(${ONERT_DEV} SHARED ${API_SRC})
-
-# Public headers to publish
-# nnfw_internal.h is header for runtime developer, so it will not be installed
-# But runtime developer can use nnfw_internal.h by linking nnfw-dev
-set(NNFW_API_HEADERS include/nnfw.h include/nnfw_experimental.h)
-
-target_link_libraries(${ONERT_DEV} PUBLIC nnfw-nnapi-header)
-target_link_libraries(${ONERT_DEV} PRIVATE onert_core)
-target_link_libraries(${ONERT_DEV} PRIVATE nnfw_lib_misc)
-target_link_libraries(${ONERT_DEV} PRIVATE jsoncpp tflite_loader circle_loader ${LIB_PTHREAD})
-target_link_libraries(${ONERT_DEV} PRIVATE trix_loader)
-target_link_libraries(${ONERT_DEV} PRIVATE nnfw_common)
-target_link_libraries(${ONERT_DEV} PRIVATE nnfw_coverage)
-# NOTE Below line is added to remove warning for android build
-#      It will be removed after android build uses gold linker
-if (ANDROID)
-  target_link_libraries(${ONERT_DEV} INTERFACE log)
-endif (ANDROID)
-
-target_include_directories(${ONERT_DEV} PUBLIC include)
-set_target_properties(${ONERT_DEV} PROPERTIES PUBLIC_HEADER "${NNFW_API_HEADERS}")
-
-if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
-  add_custom_command(TARGET ${ONERT_DEV} POST_BUILD
-                     COMMAND ${CMAKE_STRIP} "--strip-unneeded" $<TARGET_FILE_NAME:${ONERT_DEV}>)
-endif()
-
-install(TARGETS ${ONERT_DEV}
-        LIBRARY DESTINATION lib
-        PUBLIC_HEADER DESTINATION include/nnfw)
+add_subdirectory(nnapi)
+add_subdirectory(nnfw)
+add_subdirectory(python)
diff --git a/runtime/onert/api/include/nnfw.h b/runtime/onert/api/include/nnfw.h
deleted file mode 100644 (file)
index 1f1541a..0000000
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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  nnfw.h
- * @brief This file describes runtime API
- */
-#ifndef __NNFW_H__
-#define __NNFW_H__
-
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @brief Session to query with runtime
- *
- * <p>nnfw_session is started and passed by calling {@link nnfw_create_session}.
- * Each session has its own inference environment, such as model to inference, backend usage, etc.
- *
- * <p>Load model by calling {@link nnfw_load_model_from_file}
- *
- * <p>After loading, prepare inference by calling {@link nnfw_prepare}.
- * Application can set runtime environment before prepare by calling
- * {@link nnfw_set_available_backends} and {@link nnfw_set_op_backend}, and it is optional.
- *
- * <p>Application can inference by calling {@link nnfw_run}.
- * Before inference, application has responsibility to set input tensor to set input data by calling
- * {@link nnfw_set_output}, and output tensor to get output by calling {@link nnfw_set_input}
- *
- * <p>To support input and output setting, application can get
- * input and output tensor information by calling<ul>
- * <li>{@link nnfw_input_size}</li>
- * <li>{@link nnfw_output_size}</li>
- * <li>{@link nnfw_input_tensorinfo}</li>
- * <li>{@link nnfw_output_tensorinfo}</li>
- * </ul>
- *
- * <p>Application can inference many times using one session,
- * but next inference can do after prior inference end
- *
- * <p>Application cannot use muitiple model using one session
- */
-typedef struct nnfw_session nnfw_session;
-
-/**
- * @brief Tensor types
- *
- * The type of tensor represented in {@link nnfw_tensorinfo}
- */
-typedef enum
-{
-  /** A tensor of 32 bit floating point */
-  NNFW_TYPE_TENSOR_FLOAT32 = 0,
-  /** A tensor of 32 bit signed integer */
-  NNFW_TYPE_TENSOR_INT32 = 1,
-  /**
-   * A tensor of 8 bit unsigned integers that represent real numbers.
-   *
-   * real_value = (integer_value - zeroPoint) * scale.
-   */
-  NNFW_TYPE_TENSOR_QUANT8_ASYMM = 2,
-  /** A tensor of boolean */
-  NNFW_TYPE_TENSOR_BOOL = 3,
-
-  /** A tensor of 8 bit unsigned integer */
-  NNFW_TYPE_TENSOR_UINT8 = 4,
-
-  /** A tensor of 64 bit signed integer */
-  NNFW_TYPE_TENSOR_INT64 = 5,
-
-  /**
-   * A tensor of 8 bit signed integers that represent real numbers.
-   *
-   * real_value = (integer_value - zeroPoint) * scale.
-   */
-  NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED = 6,
-
-  /**
-   * A tensor of 16 bit signed integers that represent real numbers.
-   *
-   * real_value = (integer_value - zeroPoint) * scale.
-   *
-   * Forced to have zeroPoint equal to 0.
-   */
-  NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED = 7,
-
-} NNFW_TYPE;
-
-/**
- * @brief Result values returned from a call to an API function
- */
-typedef enum
-{
-  /** Successful */
-  NNFW_STATUS_NO_ERROR = 0,
-  /**
-   * An error code for general use.
-   * Mostly used when there is no specific value for that certain situation.
-   */
-  NNFW_STATUS_ERROR = 1,
-  /** Unexpected null argument is given. */
-  NNFW_STATUS_UNEXPECTED_NULL = 2,
-  /** When a function was called but it is not valid for the current session state. */
-  NNFW_STATUS_INVALID_STATE = 3,
-  /** When it is out of memory */
-  NNFW_STATUS_OUT_OF_MEMORY = 4,
-  /** When it was given an insufficient output buffer */
-  NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE = 5,
-} NNFW_STATUS;
-
-/**
- * @brief Data format of a tensor
- */
-typedef enum
-{
-  /** Don't care layout */
-  NNFW_LAYOUT_NONE = 0,
-  /**
-   * Channel last layout
-   * If rank is 4, layout is NHWC
-   */
-  NNFW_LAYOUT_CHANNELS_LAST = 1,
-  /**
-   * Channel first layout
-   * If rank is 4, layout is NCHW
-   */
-  NNFW_LAYOUT_CHANNELS_FIRST = 2,
-} NNFW_LAYOUT;
-
-/**
- * @brief Information ID for retrieving information on nnfw (e.g. version)
- */
-typedef enum
-{
-  /** nnfw runtime version
-   * Its value is uint32 in 0xMMmmmmPP, where MM = major, mmmm = minor, PP = patch.
-   */
-  NNFW_INFO_ID_VERSION = 0,
-} NNFW_INFO_ID;
-
-/**
- * @brief Maximum rank expressible with nnfw
- */
-#define NNFW_MAX_RANK (6)
-
-/**
- * @brief tensor info describes the type and shape of tensors
- *
- * <p>This structure is used to describe input and output tensors.
- * Application can get input and output tensor type and shape described in model by using
- * {@link nnfw_input_tensorinfo} and {@link nnfw_output_tensorinfo}
- *
- * <p>Maximum rank is 6 (NNFW_MAX_RANK). And tensor's dimension value is filled in 'dims' field from
- * index 0.
- * For example, if tensor's rank is 4,
- * application can get dimension value from dims[0], dims[1], dims[2], and dims[3]
- */
-typedef struct nnfw_tensorinfo
-{
-  /** The data type */
-  NNFW_TYPE dtype;
-  /** The number of dimensions (rank) */
-  int32_t rank;
-  /**
-   * The dimension of tensor.
-   * Maximum rank is 6 (NNFW_MAX_RANK).
-   */
-  int32_t dims[NNFW_MAX_RANK];
-} nnfw_tensorinfo;
-
-/**
- * @brief Create a new session instance.
- *
- * <p>This only creates a session.
- * Model is loaded after {@link nnfw_load_model_from_file} is invoked.
- * And inference is performed after {@link nnfw_run} is invoked.
- *
- * <p>{@link nnfw_close_session} should be called once
- * if session is no longer needed
- *
- * @param[out]  session The session to be created
- * @return      NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_create_session(nnfw_session **session);
-
-/**
- * @brief Close a session instance
- *
- * After called, access to closed session by application will be invalid
- *
- * @param[in] session The session to be closed
- * @return    @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_close_session(nnfw_session *session);
-
-/**
- * @brief     Load model from nnpackage file or directory
- *
- * The length of \p package_file_path must not exceed 1024 bytes including zero at the end.
- *
- * @param[in] session           nnfw_session loading the given nnpackage file/dir
- * @param[in] package_file_path Path to the nnpackage file or unzipped directory to be loaded
- *
- * @return    @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *package_file_path);
-
-/**
- * @brief     Apply i-th input's tensor info to resize input tensor
- *
- * This function should be called before {@link nnfw_prepare} is invoked, and
- * should be called after {@link nnfw_load_model_from_file} is invoked
- * See {@link nnfw_prepare} for information applying updated tensor info
- * If this function is called many times for same index, tensor info is overwritten
- *
- * @deprecated Deprecated since 1.7.0. Use {@link nnfw_set_input_tensorinfo} instead.
- *
- * @param[in] session     Session to the input tensor info is to be set
- * @param[in] index       Index of input to be applied (0-indexed)
- * @param[in] tensor_info Tensor info to be applied
- * @return    @c NNFW_STATUS_NO_ERROR if successful, otherwise return @c NNFW_STATUS_ERROR
- */
-NNFW_STATUS nnfw_apply_tensorinfo(nnfw_session *session, uint32_t index,
-                                  nnfw_tensorinfo tensor_info);
-
-/**
- * @brief    Set input model's tensor info for resizing
- *
- * 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_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
- * will be used when {@link nnfw_run}. And the shapes of the tensors are determined on the fly.
- * If this function is called many times for the same index, it is overwritten.
- *
- * @param[in] session     Session to the input tensor info is to be set
- * @param[in] index       Index of input to be set (0-indexed)
- * @param[in] tensor_info Tensor info to be set
- * @return    @c NNFW_STATUS_NO_ERROR if successful, otherwise return @c NNFW_STATUS_ERROR
- */
-NNFW_STATUS nnfw_set_input_tensorinfo(nnfw_session *session, uint32_t index,
-                                      const nnfw_tensorinfo *tensor_info);
-
-/**
- * @brief     Prepare session to be ready for inference
- *
- * This phase may finalize model compilation, scheduling, and additional settings.
- * 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
- * @return    @c NNFW_STATUS_NO_ERROR if successful, otherwise return @c NNFW_STATUS_ERROR
- */
-NNFW_STATUS nnfw_prepare(nnfw_session *session);
-
-/**
- * @brief     Run inference
- *
- * <p>This function should be called after model is loaded by {@link nnfw_load_model_from_file},
- * session is prepared for inference by {@link nnfw_prepare}, set input and output buffers
- * by {@link nnfw_set_input} and {@link nnfw_set_output}.</p>
- *
- * <p>This function return after inference is finished.</p>
- *
- * @param[in] session The session to run inference
- * @return    @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_run(nnfw_session *session);
-
-/**
- * @brief     Run inference asynchronously
- *
- * <p>This function must be called after model is loaded by {@link nnfw_load_model_from_file},
- * session is prepared for inference by {@link nnfw_prepare}, set input and output buffers
- * by {@link nnfw_set_input} and {@link nnfw_set_output}.</p>
- *
- * <p>This function returns immediately after starting a thread to run the inference.
- * To get the result of it or to do the next inference with {@link nnfw_run} or
- * {@link nnfw_run_async}, {@link nnfw_await} must be called to ensure the current asynchronous
- * inference has finished. Only one asynchronous inference is allowed at a time for a session.
- * If this function is called while the previous one is still running, it returns an error.</p>
- *
- * @param[in] session The session to run inference
- * @return    @c NNFW_STATUS_NO_ERROR if successful
- */
-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_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
- * the user can safely use the output data.</p>
- *
- * <p>This function returns after the asynchronous inference is finished.</p>
- *
- * @param[in] session The session to run inference
- * @return    @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_await(nnfw_session *session);
-
-/**
- * @brief     Set input buffer
- *
- * This function must be called after {@link nnfw_prepare}, \p buffer given to this function can be
- * reused for many inferences. \p length must be greater or equal than the operand requires. To
- * specify an optional input, you can either not call this for that input or call this with \p
- * buffer of NULL and \p length of 0.
- *
- * @param[in] session Session to the input is to be set
- * @param[in] index   Index of input to be set (0-indexed)
- * @param[in] type    Type of the input
- * @param[in] buffer  Raw buffer for input
- * @param[in] length  Size of bytes of input buffer
- *
- * @return    @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_set_input(nnfw_session *session, uint32_t index, NNFW_TYPE type,
-                           const void *buffer, size_t length);
-
-/**
- * @brief       Set output buffer
- *
- * This function must be called after {@link nnfw_prepare}, \p buffer given to this function can be
- * reused for many inferences. \p length must be greater or equal than the operand requires. An
- * output operand can have unspecified shape and deduced dynamically during the execution. You must
- * provide \p buffer large enough.
- *
- * @param[in]   session Session from inference output is to be extracted
- * @param[in]   index   Index of output to be set (0-indexed)
- * @param[in]   type    Type of the output
- * @param[out]  buffer  Raw buffer for output
- * @param[in]   length  Size of bytes of output buffer
- *
- * @return      @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_set_output(nnfw_session *session, uint32_t index, NNFW_TYPE type, void *buffer,
-                            size_t length);
-
-/**
- * @brief       Get the number of inputs
- *
- * Application can call this function to get number of inputs defined in loaded model.
- * This function should be called after {@link nnfw_load_model_from_file} is invoked to load model
- *
- * @param[in]   session Session from input information is to be extracted
- * @param[out]  number  Variable which the number of inputs is put into
- *
- * @return      @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_input_size(nnfw_session *session, uint32_t *number);
-
-/**
- * @brief       Get the number of outputs
- *
- * Application can call this function to get number of outputs defined in loaded model.
- * This function should be called after {@link nnfw_load_model_from_file} is invoked to load model
- *
- * @param[in]   session Session from output information is to be extracted
- * @param[out]  number  Variable which the number of outputs is put into
- *
- * @return      @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_output_size(nnfw_session *session, uint32_t *number);
-
-/**
- * @brief Set the layout of an input
- *
- * The input that does not call this has NNFW_LAYOUT_NHWC layout
- *
- * @param[in] session session from inference input is to be extracted
- * @param[in] index   index of input to be set (0-indexed)
- * @param[in] layout  layout to set to target input
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_set_input_layout(nnfw_session *session, uint32_t index, NNFW_LAYOUT layout);
-
-/**
- * @brief Set the layout of an output
- *
- * The output that does not call this has NNFW_LAYOUT_NHWC layout
- *
- * @param[in] session session from inference output is to be extracted
- * @param[in] index   index of output to be set (0-indexed)
- * @param[in] layout  layout to set to target output
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_set_output_layout(nnfw_session *session, uint32_t index, NNFW_LAYOUT layout);
-
-/**
- * @brief       Get i-th input tensor info
- *
- * <p>Before {@link nnfw_prepare} is invoked, this function return tensor info in model,
- * so updated tensor info by {@link nnfw_apply_tensorinfo} is not returned.</p>
- *
- * <p>After {@link nnfw_prepare} is invoked, this function return updated tensor info
- * if tensor info is updated by {@link nnfw_apply_tensorinfo}.</p>
- *
- * @param[in]   session     Session from input information is to be extracted
- * @param[in]   index       Index of input
- * @param[out]  tensor_info Tensor info (shape, type, etc)
- *
- * @return      @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_input_tensorinfo(nnfw_session *session, uint32_t index,
-                                  nnfw_tensorinfo *tensor_info);
-
-/**
- * @brief     Get i-th output tensor info
- *
- * <p>After {@link nnfw_load_model_from_file} and before {@link nnfw_prepare} is invoked, it returns
- * tensor info in the model.</p>
- *
- * <p>After {@link nnfw_prepare} and before {@link nnfw_run} is invoked, this function returns
- * updated tensor info if tensor info is updated by {@link nnfw_set_input_tensorinfo}.</p>
- *
- * <p>After {@link nnfw_run} is invoked(at least once), it returns the updated tensor info during
- * the latest execution.</p>
- *
- * @param[in]   session     Session from output information is to be extracted
- * @param[in]   index       Index of output
- * @param[out]  tensor_info Tensor info (shape, type, etc)
- *
- * @return      @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_output_tensorinfo(nnfw_session *session, uint32_t index,
-                                   nnfw_tensorinfo *tensor_info);
-
-/**
- * @brief     Set available backends
- *
- * This function should be called before {@link nnfw_prepare} is invoked.
- *
- * <p>Supported backends differs on each platforms.
- * For example, `x86_64` supports "cpu" only.
- * Multiple backends can be set and they must be separated by a semicolon (ex: "acl_cl;cpu").
- * For each backend string, `libbackend_{backend}.so` will be dynamically loaded during
- * {@link nnfw_prepare}.
- * Among the multiple backends, the 1st element is used as the default backend.</p>
- *
- * @param[in] session session to which avilable backends are set
- * @param[in] backends available backends on which nnfw uses
- *
- * @return @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_set_available_backends(nnfw_session *session, const char *backends);
-
-/**
- * @brief     Set the operation's backend
- *
- * This function should be called before {@link nnfw_prepare} is invoked.
- *
- * <p>The backend for op has higher priority than available backends specified by
- * {@link nnfw_set_available_backends}.</p>
- *
- * @deprecated Deprecated since 1.8.0.
- *
- * @param[in] session session to be modified
- * @param[in] op operation to be set
- * @param[in] backend bakcend on which operation run
- *
- * @return @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_set_op_backend(nnfw_session *session, const char *op, const char *backend);
-
-/**
- * @brief     Retrieve uint32 type of nnfw information for given information ID.
- *
- * <p>Retrieves the information of property given by information id </p>
- *
- * @note: The input session could be null for global information (e.g. runtime version).*
- *
- * @param[in] session session to be queried on.
- * @param[in] id ID to be queried
- * @param[out] val uint32 value to be returned.
- *
- * @return @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_query_info_u32(nnfw_session *session, NNFW_INFO_ID id, uint32_t *val);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/runtime/onert/api/include/nnfw_experimental.h b/runtime/onert/api/include/nnfw_experimental.h
deleted file mode 100644 (file)
index 3c8b08f..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_EXPERIMENTAL_H__
-#define __NNFW_EXPERIMENTAL_H__
-
-#include "nnfw.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Used for custom kernel development
-
-/*
- * operand type, used only for custom operations
- */
-typedef struct
-{
-  nnfw_tensorinfo type;
-  void *allocation;
-} nnfw_operand;
-
-/*
- * Used as input to custom operation eval function
- */
-typedef struct
-{
-  size_t ninputs;
-  nnfw_operand *inputs;
-
-  size_t noutputs;
-  nnfw_operand *outputs;
-} nnfw_custom_kernel_params;
-
-/*
- * Custom kernel evaluation function
- *
- * param[in] params custom operation parameters
- * param[in] userdata pointer to user-specified buffer( kernel instance specific )
- */
-typedef void (*nnfw_custom_eval)(nnfw_custom_kernel_params *params, char *userdata,
-                                 size_t userdata_size);
-
-/*
- * custom operation registration info
- */
-typedef struct
-{
-  nnfw_custom_eval eval_function;
-} custom_kernel_registration_info;
-
-NNFW_STATUS nnfw_register_custom_op_info(nnfw_session *session, const char *id,
-                                         custom_kernel_registration_info *info);
-
-/**
- * @brief Get the input tensor index by name
- *
- * This function finds an input tensor of the given name.
- * If found, the index value is set to the address that @c index points to, and returns
- * @c NNFW_STATUS_NO_ERROR. Otherwise, @c index is unchanged and returns @c NNFW_STATUS_ERROR .
- *
- * @note If two or more input tensors are of the same name, the one with the lowest index is always
- *       returned.
- *
- * @param[in]  session    the session object
- * @param[in]  tensorname the name of the tensor to find, a null terminated char pointer string
- * @param[out] index      the index to be ret
- * @return     @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_input_tensorindex(nnfw_session *session, const char *tensorname, uint32_t *index);
-
-/**
- * @brief Get the input tensor index by name
- *
- * This function finds an input tensor of the given name.
- * If found, the index value is set to the address that @c index points to, and returns
- * @c NNFW_STATUS_NO_ERROR. Otherwise, @c index is unchanged and returns @c NNFW_STATUS_ERROR .
- *
- * @note If two or more input tensors are of the same name, the one with the lowest index is always
- *       returned.
- *
- * @param[in]  session    the session object
- * @param[in]  tensorname the name of the tensor to find, a null terminated char pointer string
- * @param[out] index      the index to be ret
- * @return     @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_output_tensorindex(nnfw_session *session, const char *tensorname, uint32_t *index);
-
-/**
- * @brief Set the backend for each operation in the session
- *
- * This function assigns backends (acl_cl, acl_neon, cpu) to each operation in the session.
- * If successful,the function returns @c NNFW_STATUS_NO_ERROR. Otherwise, the function returns
- * @c NNFW_STATUS_ERROR.
- *
- * @note The argument specifying backends must be in the format
- *       "OP_BACKEND_MAP=\"0=acl_cl;1=cpu;2=acl_cl\"".
- *
- * @param[in]  session          the session object
- * @param[in]  backend_settings String containing backend assignments indexed by operation sequence
- * @return     @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_set_backends_per_operation(nnfw_session *session, const char *backend_settings);
-
-/*
- * Prepare session to be ready for inference
- * This phase may finalize model compilation, scheduling, and additional settings.
- *
- * @param session the session to be prepared
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_prepare_pipeline(nnfw_session *session, const char *map_file_path = nullptr);
-
-/**
- * @brief     Set input buffer
- *
- * This function must be called after {@link nnfw_prepare_pipeline}, \p inputs given to this
- * function can be reused for many inferences. \p lengths must be greater or equal than the operand
- * requires. if you give empty \p inputs to this function, then this function will join all threads.
- *
- * @param[in] session Session to the input is to be set
- * @param[in] inputs  Raw buffers for input, it must be \p std::vector<void *> type pointer for
- * multiple input model
- * @param[in] lengths Size of bytes of input buffers, it must be \p std::vector<uint32_t> type
- * pointer for multiple input model
- *
- * @return    @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_push_pipeline_input(nnfw_session *session, void *inputs, void *lengths);
-
-/**
- * @brief       Get last outputs of partitioned model in session
- *
- * This function must be called after {@link nnfw_prepare_pipeline}, \p outputs given to this
- * function must be cleared for memory management.
- *
- * @param[in]   session Session from last outputs is to be extracted
- * @param[out]  outputs Raw buffer for outputs, it must be \p std::vector<void *> type pointer for
- * multiple output model
- *
- * @return      @c NNFW_STATUS_NO_ERROR if successful
- */
-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_internal.h b/runtime/onert/api/include/nnfw_internal.h
deleted file mode 100644 (file)
index a88e324..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_INTERNAL_H__
-#define __NNFW_INTERNAL_H__
-
-#include "nnfw.h"
-
-NNFW_STATUS nnfw_set_config(nnfw_session *session, const char *key, const char *value);
-
-NNFW_STATUS nnfw_get_config(nnfw_session *session, const char *key, char *value, size_t value_size);
-
-/**
- * @brief Load a circle model from buffer.
- *
- * The buffer must outlive the session.
- *
- * @param[in] session session
- * @param[in] buffer  Pointer to the buffer
- * @param[in] size    Buffer size
- * @return NNFW_STATUS
- */
-NNFW_STATUS nnfw_load_circle_from_buffer(nnfw_session *session, uint8_t *buffer, size_t size);
-
-/**
- * @brief Load a tflite/circle model from file.
- *
- * @param[in] session   session
- * @param[in] file_path Path to model file. Model type(tflite/circle) is decided by file extension
- * @return    NFNFW_STATUS
- */
-NNFW_STATUS nnfw_load_model_from_modelfile(nnfw_session *session, const char *file_path);
-
-#endif // __NNFW_INTERNAL_H__
diff --git a/runtime/onert/api/include/nnfw_version.h b/runtime/onert/api/include/nnfw_version.h
deleted file mode 100644 (file)
index 7a280a6..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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 __NNFW_VERSION_H__
-#define __NNFW_VERSION_H__
-
-/**
- * NNFW_VERSION is a uint32 value representing nnfw runtime version
- * in 0xMMmmmmPP, where MM = major, mmmm = minor, PP = patch
- */
-#define NNFW_VERSION 0x01001900
-
-#endif // __NNFW_VERSION_H__
diff --git a/runtime/onert/api/nnapi/wrapper/ANeuralNetworksCompilation.cc b/runtime/onert/api/nnapi/wrapper/ANeuralNetworksCompilation.cc
new file mode 100644 (file)
index 0000000..a54fc53
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ANeuralNetworksCompilation.h"
+
+#include "util/logging.h"
+
+using namespace onert;
+
+// TODO Support multiple subgraphs
+ANeuralNetworksCompilation::ANeuralNetworksCompilation(const ANeuralNetworksModel *model)
+  : _model{model->getModel()}, _coptions{compiler::CompilerOptions::fromGlobalConfig()},
+    _compiler{std::make_shared<compiler::Compiler>(_model, _coptions.get())}
+{
+  if (model->allowedToFp16())
+    _coptions->fp16_enable = true;
+}
+
+bool ANeuralNetworksCompilation::finish() noexcept
+{
+  try
+  {
+    _artifact = _compiler->compile();
+    _compiler = nullptr;
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
diff --git a/runtime/onert/api/nnapi/wrapper/ANeuralNetworksCompilation.h b/runtime/onert/api/nnapi/wrapper/ANeuralNetworksCompilation.h
new file mode 100644 (file)
index 0000000..a643c55
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __COMPILATION_H__
+#define __COMPILATION_H__
+
+#include "ANeuralNetworksModel.h"
+
+#include "compiler/Compiler.h"
+#include "ir/Graph.h"
+#include "ir/Model.h"
+#include "exec/IExecutors.h"
+#include "util/TracingCtx.h"
+
+struct ANeuralNetworksCompilation
+{
+public:
+  ANeuralNetworksCompilation(const ANeuralNetworksModel *model);
+
+public:
+  bool finish() noexcept;
+  bool isFinished() noexcept { return _compiler == nullptr; }
+
+  void publish(std::shared_ptr<onert::exec::IExecutors> &executors) noexcept
+  {
+    executors = _artifact ? _artifact->_executors : nullptr;
+  }
+
+private:
+  std::shared_ptr<onert::ir::Model> _model;
+  std::unique_ptr<onert::compiler::CompilerOptions> _coptions;
+  std::shared_ptr<onert::compiler::Compiler> _compiler;
+  std::shared_ptr<onert::compiler::CompilerArtifact> _artifact;
+};
+
+#endif
diff --git a/runtime/onert/api/nnapi/wrapper/ANeuralNetworksExecution.cc b/runtime/onert/api/nnapi/wrapper/ANeuralNetworksExecution.cc
new file mode 100644 (file)
index 0000000..1a185f7
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ANeuralNetworksExecution.h"
+#include "NNAPIConvert.h"
+#include "util/logging.h"
+
+const onert::ir::OperandIndex ANeuralNetworksExecution::getInputOperandIndex(int32_t index) noexcept
+{
+  if (index < 0)
+  {
+    // Negative index: return invalid index
+    return onert::ir::OperandIndex{};
+  }
+
+  uint32_t cast_index = static_cast<uint32_t>(index);
+  if (cast_index >= _execution->primary_subgraph().getInputs().size())
+  {
+    // Return invalid index
+    return onert::ir::OperandIndex{};
+  }
+
+  onert::ir::IOIndex input_index{cast_index};
+  const auto operand_index = _execution->primary_subgraph().getInputs().at(input_index);
+  return operand_index;
+}
+
+const onert::ir::OperandIndex
+ANeuralNetworksExecution::getOutputOperandIndex(int32_t index) noexcept
+{
+  if (index < 0)
+  {
+    // Negative index: return invalid index
+    return onert::ir::OperandIndex{};
+  }
+
+  uint32_t cast_index = static_cast<uint32_t>(index);
+  if (cast_index >= _execution->primary_subgraph().getOutputs().size())
+  {
+    // Return invalid index
+    return onert::ir::OperandIndex{};
+  }
+
+  onert::ir::IOIndex output_index{cast_index};
+  const auto operand_index = _execution->primary_subgraph().getOutputs().at(output_index);
+  return operand_index;
+}
+
+bool ANeuralNetworksExecution::compareDataType(const ANeuralNetworksOperandType *type,
+                                               const onert::ir::OperandIndex index) noexcept
+{
+  try
+  {
+    const auto &operand_type = _execution->primary_subgraph().operands().at(index).typeInfo();
+    const auto typeInfo = NNAPIConvert::getTypeInfo(type);
+
+    if (operand_type != typeInfo)
+    {
+      // Data type mismatch
+      return false;
+    }
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+bool ANeuralNetworksExecution::compareShape(const ANeuralNetworksOperandType *type,
+                                            const onert::ir::OperandIndex index) noexcept
+{
+  // Passed shape should be specified
+  if (hasUnspecifiedDims(index))
+  {
+    return false;
+  }
+
+  const auto &operand_shape = _execution->primary_subgraph().operands().at(index).shape();
+  const auto &shape_from_type = NNAPIConvert::getShape(type);
+
+  return operand_shape == shape_from_type;
+}
+
+bool ANeuralNetworksExecution::IsOptionalInput(const onert::ir::OperandIndex index) noexcept
+{
+  const auto &operand_shape = _execution->primary_subgraph().operands().at(index).shape();
+  for (int32_t i = 0; i < operand_shape.rank(); ++i)
+  {
+    if (operand_shape.dim(i) != 0)
+      return false;
+  }
+  return true;
+}
+
+bool ANeuralNetworksExecution::hasUnspecifiedDims(const onert::ir::OperandIndex index) noexcept
+{
+  const auto &operand_shape = _execution->primary_subgraph().operands().at(index).shape();
+
+  return operand_shape.hasUnspecifiedDims();
+}
+
+size_t ANeuralNetworksExecution::getOperandSize(const onert::ir::OperandIndex index) noexcept
+{
+  try
+  {
+    return _execution->primary_subgraph().operands().at(index).operandSize();
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return 0;
+  }
+}
+
+bool ANeuralNetworksExecution::setInput(uint32_t index, const ANeuralNetworksOperandType *type,
+                                        const void *buffer, size_t length) noexcept
+{
+  try
+  {
+    onert::ir::IOIndex input_index{index};
+    const auto &shape =
+      (type != nullptr) ? NNAPIConvert::getShape(type) : _execution->getInputShape(input_index);
+
+    _execution->setInput(input_index, shape, buffer, length);
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+bool ANeuralNetworksExecution::setOptionalInput(uint32_t index,
+                                                const ANeuralNetworksOperandType *type,
+                                                const void *buffer, size_t length) noexcept
+{
+  assert(type == nullptr);
+  assert(buffer == nullptr);
+  assert(length == 0);
+  try
+  {
+    onert::ir::IOIndex input_index{index};
+    const auto &shape =
+      (type != nullptr) ? NNAPIConvert::getShape(type) : _execution->getInputShape(input_index);
+
+    // ANeuralNetworksExecution::setInput() uses only shape information
+    ANeuralNetworksOperandType optional_input_type;
+    optional_input_type.dimensionCount = shape.rank();
+    std::vector<uint32_t> dims(optional_input_type.dimensionCount);
+    for (uint32_t i = 0; i < optional_input_type.dimensionCount; ++i)
+    {
+      dims.at(i) = shape.dim(i);
+    }
+    optional_input_type.dimensions = dims.data();
+
+    return setInput(index, &optional_input_type, buffer, length);
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+bool ANeuralNetworksExecution::setOutput(uint32_t index, const ANeuralNetworksOperandType *type,
+                                         void *buffer, size_t length) noexcept
+{
+  try
+  {
+    onert::ir::IOIndex output_index{index};
+    const auto &shape =
+      (type != nullptr) ? NNAPIConvert::getShape(type) : _execution->getOutputShape(output_index);
+
+    _execution->setOutput(output_index, shape, buffer, length);
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+bool ANeuralNetworksExecution::startExecute(void) noexcept
+{
+  try
+  {
+    _execution->startExecute();
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+bool ANeuralNetworksExecution::execute(void) noexcept
+{
+  try
+  {
+    _execution->execute();
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+const std::shared_ptr<onert::exec::Execution> ANeuralNetworksExecution::instance(void) noexcept
+{
+  return _execution;
+}
+
+bool ANeuralNetworksExecution::getOutputOperandRank(uint32_t index, uint32_t *rank) noexcept
+{
+  try
+  {
+    onert::ir::IOIndex output_index{index};
+
+    // Check execution is finished
+    if (!_execution->isFinished())
+    {
+      return false;
+    }
+
+    const auto shape = _execution->getOutputShape(output_index);
+    if (shape.hasUnspecifiedDims())
+    {
+      throw std::runtime_error{"Internal error: Output tensor has unspecified dims"};
+    }
+
+    *rank = shape.rank();
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+bool ANeuralNetworksExecution::getOutputOperandDimensions(uint32_t index, uint32_t *dimensions)
+{
+  try
+  {
+    onert::ir::IOIndex output_index{index};
+
+    // Check execution is finished
+    if (!_execution->isFinished())
+    {
+      return false;
+    }
+
+    const auto shape = _execution->getOutputShape(output_index);
+    if (shape.hasUnspecifiedDims())
+    {
+      throw std::runtime_error{"Internal error: Output tensor has unspecified dims"};
+    }
+
+    for (int i = 0; i < shape.rank(); i++)
+    {
+      auto dim = shape.dim(i);
+
+      if (dim <= 0)
+      {
+        throw std::runtime_error{"Invalid dimension value"};
+      }
+
+      dimensions[i] = static_cast<uint32_t>(dim);
+    }
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
diff --git a/runtime/onert/api/nnapi/wrapper/ANeuralNetworksModel.cc b/runtime/onert/api/nnapi/wrapper/ANeuralNetworksModel.cc
new file mode 100644 (file)
index 0000000..ced3fa3
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ANeuralNetworksModel.h"
+#include "OperationFactory.h"
+#include "NNAPIConvert.h"
+
+#include "ir/Operations.Include.h"
+#include "util/logging.h"
+
+#include <memory>
+
+//
+// ANeuralNetworksModel
+//
+ANeuralNetworksModel::ANeuralNetworksModel() noexcept
+  : _finished_building{false}, _optional_operands{}, _operand_usages{},
+    _allowFloat32toFloat16{false}
+{
+  _graph = std::make_shared<onert::ir::Graph>();
+}
+
+bool ANeuralNetworksModel::addOperand(const ANeuralNetworksOperandType *type) noexcept
+{
+  try
+  {
+    const auto shape = NNAPIConvert::getShape(type);
+    const auto typeInfo = NNAPIConvert::getTypeInfo(type);
+    _graph->addOperand(shape, typeInfo);
+    _operand_usages.emplace_back(OperandUsage::NOT_DEFINED);
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+bool ANeuralNetworksModel::setOperandValue(uint32_t index, const void *buffer, size_t length,
+                                           bool optional, bool copy) noexcept
+{
+  const onert::ir::OperandIndex ind{index};
+
+  try
+  {
+    _operand_usages[index] = OperandUsage::CONSTANT;
+
+    // Remain operands.at(ind).data()->base() as nullptr for optional operand
+    // This will be filled when model finished
+    if (optional)
+    {
+      setOptionalOperand(ind);
+    }
+
+    using onert::ir::CachedData;
+    using onert::ir::ExternalData;
+    if (copy)
+    {
+      _graph->operands().at(ind).data(
+        std::make_unique<CachedData>(reinterpret_cast<const uint8_t *>(buffer), length));
+    }
+    else
+    {
+      _graph->operands().at(ind).data(
+        std::make_unique<ExternalData>(reinterpret_cast<const uint8_t *>(buffer), length));
+    }
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+bool ANeuralNetworksModel::addOperation(ANeuralNetworksOperationType type, uint32_t inputCount,
+                                        const uint32_t *inputs, uint32_t outputCount,
+                                        const uint32_t *outputs) noexcept
+{
+  try
+  {
+    for (uint32_t i = 0; i < outputCount; i++)
+    {
+      _operand_usages[outputs[i]] = OperandUsage::OPERATION_OUTPUT;
+    }
+
+    auto &factory = OperationFactory::get();
+    OperationFactory::Param param{inputCount, inputs, outputCount, outputs};
+
+    auto node = factory.create(type, param, _graph->operands());
+    _graph->addOperation(std::unique_ptr<onert::ir::Operation>{node});
+
+    // TODO Move these codes to delegate.cpp
+    if (type == ANEURALNETWORKS_FULLY_CONNECTED)
+    {
+      const auto &input_operand =
+        _graph->operands().at(node->getInputs().at(onert::ir::operation::FullyConnected::INPUT));
+      auto &weights_operand =
+        _graph->operands().at(node->getInputs().at(onert::ir::operation::FullyConnected::WEIGHT));
+      if (input_operand.typeInfo().type() == onert::ir::DataType::FLOAT32 &&
+          weights_operand.typeInfo().type() == onert::ir::DataType::QUANT_UINT8_ASYMM)
+      {
+        weights_operand.type(onert::ir::DataType::QUANT_INT8_SYMM);
+      }
+    }
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+bool ANeuralNetworksModel::addOperationEx(ANeuralNetworksOperationTypeEx type, uint32_t inputCount,
+                                          const uint32_t *inputs, uint32_t outputCount,
+                                          const uint32_t *outputs) noexcept
+{
+  try
+  {
+    for (uint32_t i = 0; i < outputCount; i++)
+    {
+      _operand_usages[outputs[i]] = OperandUsage::OPERATION_OUTPUT;
+    }
+
+    auto &factory = OperationFactory::get();
+    OperationFactory::Param param{inputCount, inputs, outputCount, outputs};
+
+    auto node = factory.create(type, param, _graph->operands());
+    _graph->addOperation(std::unique_ptr<onert::ir::Operation>{node});
+  }
+  catch (const std::exception &e)
+  {
+    return false;
+  }
+  return true;
+}
+
+bool ANeuralNetworksModel::addModelInput(uint32_t index) noexcept
+{
+  try
+  {
+    _operand_usages[index] = OperandUsage::MODEL_INPUT;
+
+    const onert::ir::OperandIndex ind{index};
+    _graph->addInput(ind);
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+bool ANeuralNetworksModel::addModelOutput(uint32_t index) noexcept
+{
+  try
+  {
+    const onert::ir::OperandIndex ind{index};
+
+    // Duplicated output is not allowed
+    if (_graph->getOutputs().contains(ind))
+    {
+      return false;
+    }
+
+    _graph->addOutput(ind);
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << std::endl;
+
+    return false;
+  }
+
+  return true;
+}
+
+void ANeuralNetworksModel::allowFloat32toFloat16(bool allow) noexcept
+{
+  _allowFloat32toFloat16 = allow;
+}
+
+bool ANeuralNetworksModel::finish() noexcept
+{
+  try
+  {
+    fillOptionalOperand();
+
+    _graph->verify();
+    _operand_usages.clear();
+    _finished_building = true;
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << '\n';
+
+    return false;
+  }
+
+  return true;
+}
+
+bool ANeuralNetworksModel::isFinished() noexcept { return _finished_building; }
+
+bool ANeuralNetworksModel::isExistOperand(uint32_t index) noexcept
+{
+  return _graph->operands().exist(onert::ir::OperandIndex{index});
+}
+
+size_t ANeuralNetworksModel::operandSize(uint32_t index) noexcept
+{
+  try
+  {
+    return _graph->operands().at(onert::ir::OperandIndex{index}).operandSize();
+  }
+  catch (const std::exception &e)
+  {
+    VERBOSE(EXCEPTION) << e.what() << '\n';
+
+    return 0;
+  }
+}
+
+bool ANeuralNetworksModel::isUsageSet(uint32_t index) noexcept
+{
+  return (_operand_usages[index] != OperandUsage::NOT_DEFINED);
+}
+
+bool ANeuralNetworksModel::isOperationOutput(uint32_t index) noexcept
+{
+  return (_operand_usages[index] == OperandUsage::OPERATION_OUTPUT);
+}
+
+void ANeuralNetworksModel::setOptionalOperand(const onert::ir::OperandIndex idx)
+{
+  _optional_operands.insert(idx);
+}
+
+void ANeuralNetworksModel::fillOptionalOperand(void)
+{
+  _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())
+      {
+        throw std::runtime_error{"Optional operand is not supported yet"};
+      }
+    }
+  });
+}
+
+std::shared_ptr<onert::ir::Model> ANeuralNetworksModel::getModel() const
+{
+  auto model = std::make_shared<onert::ir::Model>();
+
+  model->push(onert::ir::SubgraphIndex{0}, _graph);
+  // TODO Find all child subgraphs and copy them to all_subgs
+  // Must find the same subgraph by using to compare pointer of subgraphs and set subgraph's index
+  // to operands of control flow operations
+  // Must clean all child subgraphs's pointer to prevent memory leak in case of that graph has
+  // subgraph itself recursively
+
+  return model;
+}
diff --git a/runtime/onert/api/nnfw/CMakeLists.txt b/runtime/onert/api/nnfw/CMakeLists.txt
new file mode 100644 (file)
index 0000000..89e3e9d
--- /dev/null
@@ -0,0 +1,29 @@
+file(GLOB_RECURSE API_SRC "*.cc")
+
+set(ONERT_DEV nnfw-dev)
+add_library(${ONERT_DEV} SHARED ${API_SRC})
+
+# Public headers to publish
+# nnfw_internal.h is header for runtime developer, so it will not be installed
+# But runtime developer can use nnfw_internal.h by linking nnfw-dev
+set(NNFW_API_HEADERS include/nnfw.h include/nnfw_experimental.h)
+
+target_link_libraries(${ONERT_DEV} PUBLIC nnfw-nnapi-header)
+target_link_libraries(${ONERT_DEV} PRIVATE onert_core)
+target_link_libraries(${ONERT_DEV} PRIVATE nnfw_lib_misc)
+target_link_libraries(${ONERT_DEV} PRIVATE jsoncpp ${LIB_PTHREAD})
+target_link_libraries(${ONERT_DEV} PRIVATE nnfw_common)
+target_link_libraries(${ONERT_DEV} PRIVATE nnfw_coverage)
+target_link_libraries(${ONERT_DEV} PRIVATE circle_schema)
+# NOTE Below line is added to remove warning for android build
+#      It will be removed after android build uses gold linker
+if (ANDROID)
+  target_link_libraries(${ONERT_DEV} INTERFACE log)
+endif (ANDROID)
+
+target_include_directories(${ONERT_DEV} PUBLIC include)
+set_target_properties(${ONERT_DEV} PROPERTIES PUBLIC_HEADER "${NNFW_API_HEADERS}")
+
+install(TARGETS ${ONERT_DEV}
+        LIBRARY DESTINATION lib
+        PUBLIC_HEADER DESTINATION include/nnfw)
diff --git a/runtime/onert/api/nnfw/include/nnfw.h b/runtime/onert/api/nnfw/include/nnfw.h
new file mode 100644 (file)
index 0000000..f374525
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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  nnfw.h
+ * @brief This file describes runtime API
+ */
+#ifndef __NNFW_H__
+#define __NNFW_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Session to query with runtime
+ *
+ * <p>nnfw_session is started and passed by calling {@link nnfw_create_session}.
+ * Each session has its own inference environment, such as model to inference, backend usage, etc.
+ *
+ * <p>Load model by calling {@link nnfw_load_model_from_file}
+ *
+ * <p>After loading, prepare inference by calling {@link nnfw_prepare}.
+ * Application can set runtime environment before prepare by calling
+ * {@link nnfw_set_available_backends}, and it is optional.
+ *
+ * <p>Application can inference by calling {@link nnfw_run}.
+ * Before inference, application has responsibility to set input tensor to set input data by calling
+ * {@link nnfw_set_output}, and output tensor to get output by calling {@link nnfw_set_input}
+ *
+ * <p>To support input and output setting, application can get
+ * input and output tensor information by calling<ul>
+ * <li>{@link nnfw_input_size}</li>
+ * <li>{@link nnfw_output_size}</li>
+ * <li>{@link nnfw_input_tensorinfo}</li>
+ * <li>{@link nnfw_output_tensorinfo}</li>
+ * </ul>
+ *
+ * <p>Application can inference many times using one session,
+ * but next inference can do after prior inference end
+ *
+ * <p>Application cannot use muitiple model using one session
+ */
+typedef struct nnfw_session nnfw_session;
+
+/**
+ * @brief Tensor types
+ *
+ * The type of tensor represented in {@link nnfw_tensorinfo}
+ */
+typedef enum
+{
+  /** A tensor of 32 bit floating point */
+  NNFW_TYPE_TENSOR_FLOAT32 = 0,
+  /** A tensor of 32 bit signed integer */
+  NNFW_TYPE_TENSOR_INT32 = 1,
+  /**
+   * A tensor of 8 bit unsigned integers that represent real numbers.
+   *
+   * real_value = (integer_value - zeroPoint) * scale.
+   */
+  NNFW_TYPE_TENSOR_QUANT8_ASYMM = 2,
+  /** A tensor of boolean */
+  NNFW_TYPE_TENSOR_BOOL = 3,
+
+  /** A tensor of 8 bit unsigned integer */
+  NNFW_TYPE_TENSOR_UINT8 = 4,
+
+  /** A tensor of 64 bit signed integer */
+  NNFW_TYPE_TENSOR_INT64 = 5,
+
+  /**
+   * A tensor of 8 bit signed integers that represent real numbers.
+   *
+   * real_value = (integer_value - zeroPoint) * scale.
+   */
+  NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED = 6,
+
+  /**
+   * A tensor of 16 bit signed integers that represent real numbers.
+   *
+   * real_value = (integer_value - zeroPoint) * scale.
+   *
+   * Forced to have zeroPoint equal to 0.
+   */
+  NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED = 7,
+
+} NNFW_TYPE;
+
+/**
+ * @brief Result values returned from a call to an API function
+ */
+typedef enum
+{
+  /** Successful */
+  NNFW_STATUS_NO_ERROR = 0,
+  /**
+   * An error code for general use.
+   * Mostly used when there is no specific value for that certain situation.
+   */
+  NNFW_STATUS_ERROR = 1,
+  /** Unexpected null argument is given. */
+  NNFW_STATUS_UNEXPECTED_NULL = 2,
+  /** When a function was called but it is not valid for the current session state. */
+  NNFW_STATUS_INVALID_STATE = 3,
+  /** When it is out of memory */
+  NNFW_STATUS_OUT_OF_MEMORY = 4,
+  /** When it was given an insufficient output buffer */
+  NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE = 5,
+  /** When API is deprecated */
+  NNFW_STATUS_DEPRECATED_API = 6,
+} NNFW_STATUS;
+
+/**
+ * @brief Data format of a tensor
+ */
+typedef enum
+{
+  /** Don't care layout */
+  NNFW_LAYOUT_NONE = 0,
+  /**
+   * Channel last layout
+   * If rank is 4, layout is NHWC
+   */
+  NNFW_LAYOUT_CHANNELS_LAST = 1,
+  /**
+   * Channel first layout
+   * If rank is 4, layout is NCHW
+   */
+  NNFW_LAYOUT_CHANNELS_FIRST = 2,
+} NNFW_LAYOUT;
+
+/**
+ * @brief Information ID for retrieving information on nnfw (e.g. version)
+ */
+typedef enum
+{
+  /** nnfw runtime version
+   * Its value is uint32 in 0xMMmmmmPP, where MM = major, mmmm = minor, PP = patch.
+   */
+  NNFW_INFO_ID_VERSION = 0,
+} NNFW_INFO_ID;
+
+/**
+ * @brief Maximum rank expressible with nnfw
+ */
+#define NNFW_MAX_RANK (6)
+
+/**
+ * @brief tensor info describes the type and shape of tensors
+ *
+ * <p>This structure is used to describe input and output tensors.
+ * Application can get input and output tensor type and shape described in model by using
+ * {@link nnfw_input_tensorinfo} and {@link nnfw_output_tensorinfo}
+ *
+ * <p>Maximum rank is 6 (NNFW_MAX_RANK). And tensor's dimension value is filled in 'dims' field from
+ * index 0.
+ * For example, if tensor's rank is 4,
+ * application can get dimension value from dims[0], dims[1], dims[2], and dims[3]
+ */
+typedef struct nnfw_tensorinfo
+{
+  /** The data type */
+  NNFW_TYPE dtype;
+  /** The number of dimensions (rank) */
+  int32_t rank;
+  /**
+   * The dimension of tensor.
+   * Maximum rank is 6 (NNFW_MAX_RANK).
+   */
+  int32_t dims[NNFW_MAX_RANK];
+} nnfw_tensorinfo;
+
+/**
+ * @brief Create a new session instance.
+ *
+ * <p>This only creates a session.
+ * Model is loaded after {@link nnfw_load_model_from_file} is invoked.
+ * And inference is performed after {@link nnfw_run} is invoked.
+ *
+ * <p>{@link nnfw_close_session} should be called once
+ * if session is no longer needed
+ *
+ * @param[out]  session The session to be created
+ * @return      NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_create_session(nnfw_session **session);
+
+/**
+ * @brief Close a session instance
+ *
+ * After called, access to closed session by application will be invalid
+ *
+ * @param[in] session The session to be closed
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_close_session(nnfw_session *session);
+
+/**
+ * @brief     Load model from nnpackage file or directory
+ *
+ * The length of \p package_file_path must not exceed 1024 bytes including zero at the end.
+ *
+ * @param[in] session           nnfw_session loading the given nnpackage file/dir
+ * @param[in] package_file_path Path to the nnpackage file or unzipped directory to be loaded
+ *
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *package_file_path);
+
+/**
+ * @brief     Apply i-th input's tensor info to resize input tensor
+ *
+ * This function should be called before {@link nnfw_prepare} is invoked, and
+ * should be called after {@link nnfw_load_model_from_file} is invoked
+ * See {@link nnfw_prepare} for information applying updated tensor info
+ * If this function is called many times for same index, tensor info is overwritten
+ *
+ * @deprecated Deprecated since 1.7.0. Use {@link nnfw_set_input_tensorinfo} instead.
+ *
+ * @param[in] session     Session to the input tensor info is to be set
+ * @param[in] index       Index of input to be applied (0-indexed)
+ * @param[in] tensor_info Tensor info to be applied
+ * @return    @c NNFW_STATUS_NO_ERROR if successful, otherwise return @c NNFW_STATUS_ERROR
+ */
+NNFW_STATUS nnfw_apply_tensorinfo(nnfw_session *session, uint32_t index,
+                                  nnfw_tensorinfo tensor_info);
+
+/**
+ * @brief    Set input model's tensor info for resizing
+ *
+ * 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_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
+ * will be used when {@link nnfw_run}. And the shapes of the tensors are determined on the fly.
+ * If this function is called many times for the same index, it is overwritten.
+ * tensor_info's dtype field is ignored.
+ *
+ * @param[in] session     Session to the input tensor info is to be set
+ * @param[in] index       Index of input to be set (0-indexed)
+ * @param[in] tensor_info Tensor info to be set
+ * @return    @c NNFW_STATUS_NO_ERROR if successful, otherwise return @c NNFW_STATUS_ERROR
+ */
+NNFW_STATUS nnfw_set_input_tensorinfo(nnfw_session *session, uint32_t index,
+                                      const nnfw_tensorinfo *tensor_info);
+
+/**
+ * @brief     Prepare session to be ready for inference
+ *
+ * This phase may finalize model compilation, scheduling, and additional settings.
+ * 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
+ * @return    @c NNFW_STATUS_NO_ERROR if successful, otherwise return @c NNFW_STATUS_ERROR
+ */
+NNFW_STATUS nnfw_prepare(nnfw_session *session);
+
+/**
+ * @brief     Run inference
+ *
+ * <p>This function should be called after model is loaded by {@link nnfw_load_model_from_file},
+ * session is prepared for inference by {@link nnfw_prepare}, set input and output buffers
+ * by {@link nnfw_set_input} and {@link nnfw_set_output}.</p>
+ *
+ * <p>This function return after inference is finished.</p>
+ *
+ * @param[in] session The session to run inference
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_run(nnfw_session *session);
+
+/**
+ * @brief     Run inference asynchronously
+ *
+ * <p>This function must be called after model is loaded by {@link nnfw_load_model_from_file},
+ * session is prepared for inference by {@link nnfw_prepare}, set input and output buffers
+ * by {@link nnfw_set_input} and {@link nnfw_set_output}.</p>
+ *
+ * <p>This function returns immediately after starting a thread to run the inference.
+ * To get the result of it or to do the next inference with {@link nnfw_run} or
+ * {@link nnfw_run_async}, {@link nnfw_await} must be called to ensure the current asynchronous
+ * inference has finished. Only one asynchronous inference is allowed at a time for a session.
+ * If this function is called while the previous one is still running, it returns an error.</p>
+ *
+ * @param[in] session The session to run inference
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+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_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
+ * the user can safely use the output data.</p>
+ *
+ * <p>This function returns after the asynchronous inference is finished.</p>
+ *
+ * @param[in] session The session to run inference
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_await(nnfw_session *session);
+
+/**
+ * @brief     Set input buffer
+ *
+ * This function must be called after {@link nnfw_prepare}, \p buffer given to this function can be
+ * reused for many inferences. \p length must be greater or equal than the operand requires. To
+ * specify an optional input, you can either not call this for that input or call this with \p
+ * buffer of NULL and \p length of 0.
+ * If you set {@link NNFW_TYPE_TENSOR_FLOAT32} type and model has quantized input type on given
+ * index, runtime will set quantized data type model input by converting from float buffer data
+ * internally.
+ *
+ * @param[in] session Session to the input is to be set
+ * @param[in] index   Index of input to be set (0-indexed)
+ * @param[in] type    Type of the input
+ * @param[in] buffer  Raw buffer for input
+ * @param[in] length  Size of bytes of input buffer
+ *
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_input(nnfw_session *session, uint32_t index, NNFW_TYPE type,
+                           const void *buffer, size_t length);
+
+/**
+ * @brief       Set output buffer
+ *
+ * This function must be called after {@link nnfw_prepare}, \p buffer given to this function can be
+ * reused for many inferences. \p length must be greater or equal than the operand requires. An
+ * output operand can have unspecified shape and deduced dynamically during the execution. You must
+ * provide \p buffer large enough.
+ * If you set {@link NNFW_TYPE_TENSOR_FLOAT32} type and model has quantized output type on given
+ * index, runtime will set dequantized float buffer data from quantize data type model output
+ * internally.
+ *
+ * @param[in]   session Session from inference output is to be extracted
+ * @param[in]   index   Index of output to be set (0-indexed)
+ * @param[in]   type    Type of the output
+ * @param[out]  buffer  Raw buffer for output
+ * @param[in]   length  Size of bytes of output buffer
+ *
+ * @return      @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_output(nnfw_session *session, uint32_t index, NNFW_TYPE type, void *buffer,
+                            size_t length);
+
+/**
+ * @brief       Get the number of inputs
+ *
+ * Application can call this function to get number of inputs defined in loaded model.
+ * This function should be called after {@link nnfw_load_model_from_file} is invoked to load model
+ *
+ * @param[in]   session Session from input information is to be extracted
+ * @param[out]  number  Variable which the number of inputs is put into
+ *
+ * @return      @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_input_size(nnfw_session *session, uint32_t *number);
+
+/**
+ * @brief       Get the number of outputs
+ *
+ * Application can call this function to get number of outputs defined in loaded model.
+ * This function should be called after {@link nnfw_load_model_from_file} is invoked to load model
+ *
+ * @param[in]   session Session from output information is to be extracted
+ * @param[out]  number  Variable which the number of outputs is put into
+ *
+ * @return      @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_output_size(nnfw_session *session, uint32_t *number);
+
+/**
+ * @brief Set the layout of an input
+ *
+ * The input that does not call this has NNFW_LAYOUT_NHWC layout
+ *
+ * @param[in] session session from inference input is to be extracted
+ * @param[in] index   index of input to be set (0-indexed)
+ * @param[in] layout  layout to set to target input
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_input_layout(nnfw_session *session, uint32_t index, NNFW_LAYOUT layout);
+
+/**
+ * @brief Set the layout of an output
+ *
+ * The output that does not call this has NNFW_LAYOUT_NHWC layout
+ *
+ * @param[in] session session from inference output is to be extracted
+ * @param[in] index   index of output to be set (0-indexed)
+ * @param[in] layout  layout to set to target output
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_output_layout(nnfw_session *session, uint32_t index, NNFW_LAYOUT layout);
+
+/**
+ * @brief       Get i-th input tensor info
+ *
+ * <p>Before {@link nnfw_prepare} is invoked, this function return tensor info in model,
+ * so updated tensor info by {@link nnfw_apply_tensorinfo} is not returned.</p>
+ *
+ * <p>After {@link nnfw_prepare} is invoked, this function return updated tensor info
+ * if tensor info is updated by {@link nnfw_apply_tensorinfo}.</p>
+ *
+ * @param[in]   session     Session from input information is to be extracted
+ * @param[in]   index       Index of input
+ * @param[out]  tensor_info Tensor info (shape, type, etc)
+ *
+ * @return      @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_input_tensorinfo(nnfw_session *session, uint32_t index,
+                                  nnfw_tensorinfo *tensor_info);
+
+/**
+ * @brief     Get i-th output tensor info
+ *
+ * <p>After {@link nnfw_load_model_from_file} and before {@link nnfw_prepare} is invoked, it returns
+ * tensor info in the model.</p>
+ *
+ * <p>After {@link nnfw_prepare} and before {@link nnfw_run} is invoked, this function returns
+ * updated tensor info if tensor info is updated by {@link nnfw_set_input_tensorinfo}.</p>
+ *
+ * <p>After {@link nnfw_run} is invoked(at least once), it returns the updated tensor info during
+ * the latest execution.</p>
+ *
+ * @param[in]   session     Session from output information is to be extracted
+ * @param[in]   index       Index of output
+ * @param[out]  tensor_info Tensor info (shape, type, etc)
+ *
+ * @return      @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_output_tensorinfo(nnfw_session *session, uint32_t index,
+                                   nnfw_tensorinfo *tensor_info);
+
+/**
+ * @brief     Set available backends
+ *
+ * This function should be called before {@link nnfw_prepare} is invoked.
+ *
+ * <p>Supported backends differs on each platforms.
+ * For example, `x86_64` supports "cpu" only.
+ * Multiple backends can be set and they must be separated by a semicolon (ex: "acl_cl;cpu").
+ * For each backend string, `libbackend_{backend}.so` will be dynamically loaded during
+ * {@link nnfw_prepare}.
+ * Among the multiple backends, the 1st element is used as the default backend.</p>
+ *
+ * @param[in] session session to which avilable backends are set
+ * @param[in] backends available backends on which nnfw uses
+ *
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_available_backends(nnfw_session *session, const char *backends);
+
+/**
+ * @brief     Set the operation's backend
+ *
+ * This function should be called before {@link nnfw_prepare} is invoked.
+ *
+ * <p>The backend for op has higher priority than available backends specified by
+ * {@link nnfw_set_available_backends}.</p>
+ *
+ * @deprecated Deprecated since 1.8.0.
+ *
+ * @param[in] session session to be modified
+ * @param[in] op operation to be set
+ * @param[in] backend bakcend on which operation run
+ *
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_op_backend(nnfw_session *session, const char *op, const char *backend);
+
+/**
+ * @brief     Retrieve uint32 type of nnfw information for given information ID.
+ *
+ * <p>Retrieves the information of property given by information id </p>
+ *
+ * @note: The input session could be null for global information (e.g. runtime version).*
+ *
+ * @param[in] session session to be queried on.
+ * @param[in] id ID to be queried
+ * @param[out] val uint32 value to be returned.
+ *
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_query_info_u32(nnfw_session *session, NNFW_INFO_ID id, uint32_t *val);
+
+/**
+ * @brief     Set runtime's workspace directory
+ *
+ * <p>This function sets the directory to be used as a workspace.
+ * System should allow read and write access to the directory for the runtime.
+ * Default workspace is running directory of the application.
+ * This function should be called before {@link nnfw_load_model_from_file} is invoked.</p>
+ *
+ * @param[in] session session to be queried on.
+ * @param[in] dir     workspace directory path
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_workspace(nnfw_session *session, const char *dir);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/runtime/onert/api/nnfw/include/nnfw_experimental.h b/runtime/onert/api/nnfw/include/nnfw_experimental.h
new file mode 100644 (file)
index 0000000..9bcf978
--- /dev/null
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXPERIMENTAL_H__
+#define __NNFW_EXPERIMENTAL_H__
+
+#include "nnfw.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Used for custom kernel development
+
+/*
+ * operand type, used only for custom operations
+ */
+typedef struct
+{
+  nnfw_tensorinfo type;
+  void *allocation;
+} nnfw_operand;
+
+/*
+ * Used as input to custom operation eval function
+ */
+typedef struct
+{
+  size_t ninputs;
+  nnfw_operand *inputs;
+
+  size_t noutputs;
+  nnfw_operand *outputs;
+} nnfw_custom_kernel_params;
+
+/*
+ * Custom kernel evaluation function
+ *
+ * param[in] params custom operation parameters
+ * param[in] userdata pointer to user-specified buffer( kernel instance specific )
+ */
+typedef void (*nnfw_custom_eval)(nnfw_custom_kernel_params *params, char *userdata,
+                                 size_t userdata_size);
+
+/*
+ * custom operation registration info
+ */
+typedef struct
+{
+  nnfw_custom_eval eval_function;
+} custom_kernel_registration_info;
+
+NNFW_STATUS nnfw_register_custom_op_info(nnfw_session *session, const char *id,
+                                         custom_kernel_registration_info *info);
+
+/**
+ * @brief Get the input tensor index by name
+ *
+ * This function finds an input tensor of the given name.
+ * If found, the index value is set to the address that @c index points to, and returns
+ * @c NNFW_STATUS_NO_ERROR. Otherwise, @c index is unchanged and returns @c NNFW_STATUS_ERROR .
+ *
+ * @note If two or more input tensors are of the same name, the one with the lowest index is always
+ *       returned.
+ *
+ * @param[in]  session    the session object
+ * @param[in]  tensorname the name of the tensor to find, a null terminated char pointer string
+ * @param[out] index      the index to be ret
+ * @return     @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_input_tensorindex(nnfw_session *session, const char *tensorname, uint32_t *index);
+
+/**
+ * @brief Get the input tensor index by name
+ *
+ * This function finds an input tensor of the given name.
+ * If found, the index value is set to the address that @c index points to, and returns
+ * @c NNFW_STATUS_NO_ERROR. Otherwise, @c index is unchanged and returns @c NNFW_STATUS_ERROR .
+ *
+ * @note If two or more input tensors are of the same name, the one with the lowest index is always
+ *       returned.
+ *
+ * @param[in]  session    the session object
+ * @param[in]  tensorname the name of the tensor to find, a null terminated char pointer string
+ * @param[out] index      the index to be ret
+ * @return     @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_output_tensorindex(nnfw_session *session, const char *tensorname, uint32_t *index);
+
+/**
+ * @brief Set the backend for each operation in the session
+ *
+ * This function assigns backends (acl_cl, acl_neon, cpu) to each operation in the session.
+ * If successful,the function returns @c NNFW_STATUS_NO_ERROR. Otherwise, the function returns
+ * @c NNFW_STATUS_ERROR.
+ *
+ * @note The argument specifying backends must be in the format
+ *       "OP_BACKEND_MAP=\"0=acl_cl;1=cpu;2=acl_cl\"".
+ *
+ * @param[in]  session          the session object
+ * @param[in]  backend_settings String containing backend assignments indexed by operation sequence
+ * @return     @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_backends_per_operation(nnfw_session *session, const char *backend_settings);
+
+/**
+ * @brief Prepare session to be ready for inference
+ *
+ * This phase may finalize model compilation, scheduling, and additional settings.
+ *
+ * @deprecated Deprecated since 1.22.1
+ *
+ * @param session the session to be prepared
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_prepare_pipeline(nnfw_session *session, const char *map_file_path = nullptr);
+
+/**
+ * @brief     Set input buffer
+ *
+ * This function must be called after {@link nnfw_prepare_pipeline}, \p inputs given to this
+ * function can be reused for many inferences. \p lengths must be greater or equal than the operand
+ * requires. if you give empty \p inputs to this function, then this function will join all threads.
+ *
+ * @deprecated Deprecated since 1.22.1
+ *
+ * @param[in] session Session to the input is to be set
+ * @param[in] inputs  Raw buffers for input, it must be \p std::vector<void *> type pointer for
+ * multiple input model
+ * @param[in] lengths Size of bytes of input buffers, it must be \p std::vector<uint32_t> type
+ * pointer for multiple input model
+ *
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_push_pipeline_input(nnfw_session *session, void *inputs, void *lengths);
+
+/**
+ * @brief       Get last outputs of partitioned model in session
+ *
+ * This function must be called after {@link nnfw_prepare_pipeline}, \p outputs given to this
+ * function must be cleared for memory management.
+ *
+ * @deprecated Deprecated since 1.22.1
+ *
+ * @param[in]   session Session from last outputs is to be extracted
+ * @param[out]  outputs Raw buffer for outputs, it must be \p std::vector<void *> type pointer for
+ * multiple output model
+ *
+ * @return      @c NNFW_STATUS_NO_ERROR if successful
+ */
+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_UNDEFINED = 0,
+  NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR = 1,
+  NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY = 2,
+} NNFW_TRAIN_LOSS;
+
+typedef enum
+{
+  /** Undefined */
+  NNFW_TRAIN_LOSS_REDUCTION_UNDEFINED = 0,
+  /** Scalar sum divided by number of elements in losses */
+  NNFW_TRAIN_LOSS_REDUCTION_SUM_OVER_BATCH_SIZE = 1,
+  /** Scalar sum of weighted losses */
+  NNFW_TRAIN_LOSS_REDUCTION_SUM = 2,
+} NNFW_TRAIN_LOSS_REDUCTION;
+
+typedef enum
+{
+  NNFW_TRAIN_OPTIMIZER_UNDEFINED = 0,
+  NNFW_TRAIN_OPTIMIZER_SGD = 1,
+  NNFW_TRAIN_OPTIMIZER_ADAM = 2,
+} NNFW_TRAIN_OPTIMIZER;
+
+typedef struct nnfw_loss_info
+{
+  NNFW_TRAIN_LOSS loss;
+  NNFW_TRAIN_LOSS_REDUCTION reduction_type;
+} nnfw_loss_info;
+
+/**
+ * @brief Special values of num_of_trainable_ops.
+ *        Positive values are used to indicate layers to be trained from the back of the graph.
+ */
+typedef enum
+{
+  /** Error value of number of trainable ops */
+  NNFW_TRAIN_TRAINABLE_INCORRECT_STATE = -2,
+  /** All layers will be trained */
+  NNFW_TRAIN_TRAINABLE_ALL = -1,
+  /** No layer will be trained */
+  NNFW_TRAIN_TRAINABLE_NONE = 0,
+
+} NNFW_TRAIN_NUM_OF_TRAINABLE_OPS_SPECIAL_VALUES;
+
+/**
+ * @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 info */
+  nnfw_loss_info loss_info{.loss = NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR,
+                           .reduction_type = NNFW_TRAIN_LOSS_REDUCTION_SUM_OVER_BATCH_SIZE};
+  /** optimizer type */
+  NNFW_TRAIN_OPTIMIZER opt = NNFW_TRAIN_OPTIMIZER_SGD;
+
+  /** Number of layers to be trained from the back of the graph.
+   *  Note that some values have special meaning. "-1" means that all layers will be trained.
+   * "0" means that no layer will be trained. Negative value less than -1 means error.
+   *  The special values are collected in NNFW_TRAIN_NUM_OF_TRAINABLE_OPS_SPECIAL_VALUES enum.
+   */
+  int32_t num_of_trainable_ops = NNFW_TRAIN_TRAINABLE_NONE;
+} nnfw_train_info;
+
+/**
+ * @brief Get training information
+ * @note  This function should be called after calling {@link nnfw_load_model_from_file}
+ *
+ *        For the field which is not set in training information, it returns training information
+ *        filled with default value. The default value of each field is as follows :
+ *        learning_rate = 0.0f, batch_size = 0, *_UNDEF for other enums
+ *
+ * @param[in]   session   The session to get training information
+ * @param[out]  info      Training information
+ *
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_get_traininfo(nnfw_session *session, nnfw_train_info *info);
+
+/**
+ * @brief Set training information
+ * @note  This function should be called after calling {@link nnfw_load_model_from_file}
+ *        and before calling {@link nnfw_train_prepare}
+ *
+ * @param[in] session The session to be set training information
+ * @param[in] info    The training information
+ *
+ *  @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_set_traininfo(nnfw_session *session, const nnfw_train_info *info);
+
+/**
+ * @brief Prepare session to be ready for training
+ * @note  The session will be entered into training mode
+ *
+ *        If training info is NOT set in session, this function returns @c NNFW_STATUS_ERROR .
+ *        You should set training info using {@link nnfw_train_set_traininfo}.
+ *
+ * @param[in] session The session to be prepared for training
+ *
+ * @return  @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_prepare(nnfw_session *session);
+
+/**
+ * @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 Set training output buffer
+ *
+ * This function must be called after {@link nnfw_train_prepare}, \p buffer given to this function
+ * can be reused for training. \p length must be greater or equal than the operand requires.
+ * An output operand can have unspecified shape and deduced dynamically during the execution. You
+ * must provide \p buffer large enough.
+ *
+ * @param[in]   session Session from inference output is to be extracted
+ * @param[in]   index   Index of output to be set (0-indexed)
+ * @param[in]   type    Type of the output
+ * @param[out]  buffer  Raw buffer for output
+ * @param[in]   length  Size of bytes of output buffer
+ *
+ * @return      @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_set_output(nnfw_session *session, uint32_t index, NNFW_TYPE type,
+                                  void *buffer, size_t length);
+
+/**
+ * @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
+ *
+ *        In order to use \p update_weights as false, it should be called after
+ *        {@link nnfw_train_set_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);
+
+/**
+ *  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,
+  /** weight-only int8 symmetric quantization */
+  NNFW_QUANTIZE_TYPE_WO_I8_SYM,
+  /** weight-only int16 symmetric quantization */
+  NNFW_QUANTIZE_TYPE_WO_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);
+
+/**
+ * @brief Preference for target-dependent code generation
+ */
+typedef enum
+{
+  /** Use the default configuration */
+  NNFW_CODEGEN_PREF_DEFAULT,
+  // TODO Support Traffic and Cycle code generation preference
+  /** Do best efforts to generate target-dependent code for performance */
+  NNFW_CODEGEN_PREF_PERFORMANCE_FIRST,
+  /** Do best efforts to generate target-dependent code for reducing host memory usage */
+  NNFW_CODEGEN_PREF_MEMORY_FIRST,
+  /** Do best efforts to generate target-dependent code for reducing compilation time */
+  NNFW_CODEGEN_PREF_COMPILE_TIME_FIRST,
+} NNFW_CODEGEN_PREF;
+
+/**
+ * @brief Set exported codegen model path
+ *
+ * This function should be called before {@link nnfw_codegen} is invoked.
+ *
+ * @param[in] session nnfw_session to set codegen model path
+ * @param[in] path    Target-dependent model path
+ * @return    @c NNFW_STATUS_NO_ERROR if successful, otherwise return @c NNFW_STATUS_ERROR
+ */
+NNFW_STATUS nnfw_set_codegen_model_path(nnfw_session *session, const char *path);
+
+/**
+ * @brief Generate target-dependent code
+ *
+ * This function opens a dynamic shared object. It searches for the object as flollows
+ * ld.so(8) search rules. If the {@link nnfw_set_codegen_model_path} is not called before
+ * this function, the codegen model path is automatically defined and used using the same
+ * directory of the original model/package with the target backend extension.
+ *
+ * @param[in] session nnfw_session the session which contains information about compilation
+ * @param[in] target  Target backend to generate code
+ *                    This target string will be used to find a backend library.
+ *                    The name of target backend library should follow the following rules:
+ *                      'lib' +  {backend extension} + '-gen' + {lib extension}
+ *                    And the target string should be a name except 'lib' and {lib extension}.
+ *                    For example, if the backend extension is 'aaa', the backend library should
+ *                    be 'libaaa-gen.so', and the target string should be 'aaa-gen'.
+ * @param[in] pref @c NNFW_CODEGEN_PREF
+ * @return    @c NNFW_STATUS_NO_ERROR if successful, otherwise return @c NNFW_STATUS_ERROR
+ */
+NNFW_STATUS nnfw_codegen(nnfw_session *session, const char *target, NNFW_CODEGEN_PREF pref);
+
+//////////////////////////////////////////////
+// APIs for configuration
+//////////////////////////////////////////////
+
+/**
+ * @brief Configuration key for prepare (compile and schedule)
+ */
+typedef enum
+{
+  /**
+   * Prepare to dump execution time profile file (not require value setting)
+   * TODO: Use workspace
+   */
+  NNFW_PREPARE_CONFIG_PROFILE,
+} NNFW_PREPARE_CONFIG;
+
+/**
+ * @brief      Set prepare configuration
+ *
+ * This function set prepare configuration to decide additional compiling and scheduing feature.
+ * If you enable configuration to prepare dumping execution data into workspace,
+ * refer {@link nnfw_set_workspace} to use workspace directory.
+ *
+ * @param[in] session nnfw_session to set prepare configuration
+ * @param[in] key     prepare configuration key
+ * @param[in] value   prepare configuration value
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_prepare_config(nnfw_session *session, NNFW_PREPARE_CONFIG key,
+                                    const char *value);
+
+/**
+ * @brief     Reset prepare configurations
+ *
+ * This function reset all prepare configuration.
+ *
+ * @param[in] session nnfw_session to reset all prepare configurations
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_reset_prepare_config(nnfw_session *session);
+
+/**
+ * @brief Configuration key for execution
+ */
+typedef enum
+{
+  /** Dump minmax data for each layers to workspace (not require value setting) */
+  NNFW_RUN_CONFIG_DUMP_MINMAX,
+  /** Dump execution event file to workspace (not require value setting) */
+  NNFW_RUN_CONFIG_TRACE,
+  /**
+   * Dump execution time profile file (not require value setting)
+   *
+   * You should set prepare configuration {@link NNFW_PREPARE_CONFIG_PROFILE} before prepare.
+   * Otherwise, this configuration will be ignored.
+   *
+   * TODO: Use workspace
+   */
+  NNFW_RUN_CONFIG_PROFILE,
+} NNFW_RUN_CONFIG;
+
+/**
+ * @brief     Set execution (run or train) configuration
+ *
+ * This function set execution configuration to dump execution data to workspace.
+ * If you enable configuration to dump execution data into workspace and want to change workspace,
+ * refer {@link nnfw_set_workspace} to use workspace directory.
+ *
+ * @param[in] session nnfw_session to set execution configuration
+ * @param[in] key     execution configuration key
+ * @param[in] value   execution configuration value if needed, otherwise set NULL
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_execute_config(nnfw_session *session, const NNFW_RUN_CONFIG key,
+                                    const char *value);
+
+/**
+ * @brief     Reset execution (run or train) configurations
+ *
+ * This function reset all execution configuration.
+ *
+ * @param[in] session nnfw_session to reset all execution configurations
+ * @return    @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_reset_execute_config(nnfw_session *session);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __NNFW_EXPERIMENTAL_H__
diff --git a/runtime/onert/api/nnfw/include/nnfw_internal.h b/runtime/onert/api/nnfw/include/nnfw_internal.h
new file mode 100644 (file)
index 0000000..7559a81
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_INTERNAL_H__
+#define __NNFW_INTERNAL_H__
+
+#include "nnfw.h"
+
+NNFW_STATUS nnfw_set_config(nnfw_session *session, const char *key, const char *value);
+
+NNFW_STATUS nnfw_get_config(nnfw_session *session, const char *key, char *value, size_t value_size);
+
+/**
+ * @brief Load a circle model from buffer.
+ *
+ * The buffer must outlive the session.
+ *
+ * @param[in] session session
+ * @param[in] buffer  Pointer to the buffer
+ * @param[in] size    Buffer size
+ * @return NNFW_STATUS
+ */
+NNFW_STATUS nnfw_load_circle_from_buffer(nnfw_session *session, uint8_t *buffer, size_t size);
+
+/**
+ * @brief Load a tflite/circle model from file.
+ *
+ * @param[in] session   session
+ * @param[in] file_path Path to model file. Model type(tflite/circle) is decided by file extension
+ * @return    NFNFW_STATUS
+ */
+NNFW_STATUS nnfw_load_model_from_modelfile(nnfw_session *session, const char *file_path);
+
+/**
+ * @brief Export circle+ model
+ * @note  This function should be called on training mode
+ *        This function should be called before or after {@link nnfw_train}
+ *
+ * @param[in] session     The session to export training model
+ * @param[in] file_path   The path to export training model
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_train_export_circleplus(nnfw_session *session, const char *file_path);
+
+#endif // __NNFW_INTERNAL_H__
diff --git a/runtime/onert/api/nnfw/include/nnfw_version.h b/runtime/onert/api/nnfw/include/nnfw_version.h
new file mode 100644 (file)
index 0000000..2d076da
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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 __NNFW_VERSION_H__
+#define __NNFW_VERSION_H__
+
+/**
+ * NNFW_VERSION is a uint32 value representing nnfw runtime version
+ * in 0xMMmmmmPP, where MM = major, mmmm = minor, PP = patch
+ */
+#define NNFW_VERSION 0x01001C00
+
+#endif // __NNFW_VERSION_H__
diff --git a/runtime/onert/api/nnfw/src/OpMap.lst b/runtime/onert/api/nnfw/src/OpMap.lst
new file mode 100644 (file)
index 0000000..6d4d2fa
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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 MAP_MACRO
+#error  Define MAP_MACRO before including this file
+#endif
+
+// Table: circle operation ID order
+//        circle operation              | onert internal operation
+MAP_MACRO(ADD                           , Add)
+MAP_MACRO(AVERAGE_POOL_2D               , AvgPool2D)
+MAP_MACRO(CONCATENATION                 , Concat)
+MAP_MACRO(CONV_2D                       , Conv2D)
+MAP_MACRO(DEPTHWISE_CONV_2D             , DepthwiseConv2D)
+// DEPTH_TO_SPACE
+MAP_MACRO(DEQUANTIZE                    , Dequantize)
+MAP_MACRO(EMBEDDING_LOOKUP              , EmbeddingLookup)
+MAP_MACRO(FLOOR                         , Floor)
+MAP_MACRO(FULLY_CONNECTED               , FullyConnected)
+MAP_MACRO(HASHTABLE_LOOKUP              , HashtableLookup)
+MAP_MACRO(L2_NORMALIZATION              , L2Normalization)
+MAP_MACRO(L2_POOL_2D                    , L2Pool2D)
+MAP_MACRO(LOCAL_RESPONSE_NORMALIZATION  , LocalResponseNormalization)
+MAP_MACRO(LOGISTIC                      , Logistic)
+// LSH_PROJECTION
+MAP_MACRO(LSTM                          , LSTM)
+MAP_MACRO(MAX_POOL_2D                   , MaxPool2D)
+MAP_MACRO(MUL                           , Mul)
+MAP_MACRO(RELU                          , ReLU)
+MAP_MACRO(RELU_N1_TO_1                  , ReLU1)
+MAP_MACRO(RELU6                         , ReLU6)
+MAP_MACRO(RESHAPE                       , Reshape)
+MAP_MACRO(RESIZE_BILINEAR               , ResizeBilinear)
+MAP_MACRO(RNN                           , RNN)
+MAP_MACRO(SOFTMAX                       , Softmax)
+MAP_MACRO(SPACE_TO_DEPTH                , SpaceToDepth)
+// SVDF
+MAP_MACRO(TANH                          , Tanh)
+// CONCAT_EMBEDDINGS
+// SKIP_GRAM
+// CALL
+MAP_MACRO(CUSTOM                        , Custom)
+// EMBEDDING_LOOKUP_SPARSE
+MAP_MACRO(PAD                           , Pad)
+// UNIDIRECTIONAL_SEQUENCE_RNN
+MAP_MACRO(GATHER                        , Gather)
+MAP_MACRO(BATCH_TO_SPACE_ND             , BatchToSpaceND)
+MAP_MACRO(SPACE_TO_BATCH_ND             , SpaceToBatchND)
+MAP_MACRO(TRANSPOSE                     , Transpose)
+MAP_MACRO(MEAN                          , Mean)
+MAP_MACRO(SUB                           , Sub)
+MAP_MACRO(DIV                           , Div)
+MAP_MACRO(SQUEEZE                       , Squeeze)
+// UNIDIRECTIONAL_SEQUENCE_LSTM
+MAP_MACRO(STRIDED_SLICE                 , StridedSlice)
+// BIDIRECTIONAL_SEQUENCE_RNN
+MAP_MACRO(EXP                           , Exp)
+MAP_MACRO(TOPK_V2                       , TopKV2)
+MAP_MACRO(SPLIT                         , Split)
+// LOG_SOFTMAX
+// DELEGATE
+// BIDIRECTIONAL_SEQUENCE_LSTM
+MAP_MACRO(CAST                          , Cast)
+MAP_MACRO(PRELU                         , PReLU)
+MAP_MACRO(MAXIMUM                       , Max)
+MAP_MACRO(ARG_MAX                       , ArgMax)
+MAP_MACRO(MINIMUM                       , Min)
+// LESS (Comparison) ?
+MAP_MACRO(NEG                           , Neg)
+// PADV2
+// GREATER (Comparison) ?
+// GREATER_EQUAL (Comparison) ?
+// LESS_EQUAL (Comparison) ?
+MAP_MACRO(SELECT                        , Select)
+MAP_MACRO(SLICE                         , Slice)
+MAP_MACRO(SIN                           , Sin)
+MAP_MACRO(TRANSPOSE_CONV                , TransposeConv)
+// SPARSE_TO_DENSE
+MAP_MACRO(TILE                          , Tile)
+MAP_MACRO(EXPAND_DIMS                   , ExpandDims)
+// EQUAL (Comparison) ?
+// NOT_EQUAL (Comparison) ?
+MAP_MACRO(LOG                           , Log)
+MAP_MACRO(SUM                           , ReduceSum)
+MAP_MACRO(SQRT                          , SQRT)
+MAP_MACRO(RSQRT                         , RSQRT)
+MAP_MACRO(SHAPE                         , Shape)
+MAP_MACRO(POW                           , Pow)
+// ARG_MIN
+// FAKE_QUANT
+MAP_MACRO(REDUCE_PROD                   , ReduceProd)
+MAP_MACRO(REDUCE_MAX                    , ReduceMax)
+MAP_MACRO(PACK                          , Pack)
+MAP_MACRO(LOGICAL_OR                    , LogicalOr)
+MAP_MACRO(ONE_HOT                       , OneHot)
+MAP_MACRO(LOGICAL_AND                   , LogicalAnd)
+MAP_MACRO(LOGICAL_NOT                   , LogicalNot)
+MAP_MACRO(UNPACK                        , Unpack)
+MAP_MACRO(REDUCE_MIN                    , ReduceMin)
+// FLOOR_DIV
+MAP_MACRO(REDUCE_ANY                    , ReduceAny)
+// SQUARE
+MAP_MACRO(ZEROS_LIKE                    , ZerosLike)
+MAP_MACRO(FILL                          , Fill)
+MAP_MACRO(FLOOR_MOD                     , FloorMod)
+MAP_MACRO(RANGE                         , Range)
+// RESIZE_NEAREST_NEIGHBOR
+// LEAKY_RELU
+MAP_MACRO(SQUARED_DIFFERENCE            , SquaredDifference)
+// MIRROR_PAD
+MAP_MACRO(ABS                           , Abs)
+// SPLIT_V
+// UNIQUE
+// CEIL
+MAP_MACRO(REVERSE_V2                    , Reverse)
+// ADD_N
+// GATHER_ND
+MAP_MACRO(COS                           , Cos)
+// WHERE
+// RANK
+// ELU
+// REVERSE_SEQUENCE
+// MATRIX_DIAG
+// QUANTIZE
+// MATRIX_SET_DIAG
+MAP_MACRO(ROUND                         , Round)
+// HARD_SWISH
+MAP_MACRO(IF                            , If)
+MAP_MACRO(WHILE                         , While)
+// NON_MAX_SUPPRESSION_V4
+// NON_MAX_SUPPRESSION_V5
+// SCATTER_ND
+// SELECT_V2 (Select) ?
+// DENSIFY
+// SEGMENT_SUM
+MAP_MACRO(BATCH_MATMUL                  , BatchMatMul)
+MAP_MACRO(BCQ_GATHER                    , BCQGather)
+MAP_MACRO(BCQ_FULLY_CONNECTED           , BCQFullyConnected)
+MAP_MACRO(INSTANCE_NORM                 , InstanceNorm)
diff --git a/runtime/onert/api/nnfw/src/nnfw_api.cc b/runtime/onert/api/nnfw/src/nnfw_api.cc
new file mode 100644 (file)
index 0000000..483cad1
--- /dev/null
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_api_internal.h"
+#include "nnfw_version.h"
+
+// Double-check enum value changes
+
+#define STATIC_ASSERT_ENUM_CHECK(ENUM, VAL) static_assert((ENUM) == (VAL), #ENUM " has changed")
+
+STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_FLOAT32, 0);
+STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_INT32, 1);
+STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_QUANT8_ASYMM, 2);
+STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_BOOL, 3);
+STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_UINT8, 4);
+STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_INT64, 5);
+STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED, 6);
+STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED, 7);
+
+STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_NO_ERROR, 0);
+STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_ERROR, 1);
+STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_UNEXPECTED_NULL, 2);
+STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_INVALID_STATE, 3);
+STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_OUT_OF_MEMORY, 4);
+STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE, 5);
+
+STATIC_ASSERT_ENUM_CHECK(NNFW_LAYOUT_NONE, 0);
+STATIC_ASSERT_ENUM_CHECK(NNFW_LAYOUT_CHANNELS_LAST, 1);
+STATIC_ASSERT_ENUM_CHECK(NNFW_LAYOUT_CHANNELS_FIRST, 2);
+
+STATIC_ASSERT_ENUM_CHECK(NNFW_INFO_ID_VERSION, 0);
+
+#undef STATIC_ASSERT_ENUM_CHECK
+
+#define NNFW_RETURN_ERROR_IF_NULL(p)      \
+  do                                      \
+  {                                       \
+    if ((p) == NULL)                      \
+      return NNFW_STATUS_UNEXPECTED_NULL; \
+  } while (0)
+
+/*
+ * Create a new session instance
+ *
+ * @param session the session to be created
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_create_session(nnfw_session **session) { return nnfw_session::create(session); }
+
+/*
+ * Close a session instance
+ *
+ * @param session the session to be closed
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_close_session(nnfw_session *session)
+{
+  delete session;
+  return NNFW_STATUS_NO_ERROR;
+}
+
+/*
+ * Load model from nnpackage file or directory
+ *
+ * @param session nnfw_session loading the given nnpackage file/dir
+ * @param package_file_path path to the nnpackage file or unzipped directory to be loaded
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *pacakge_file_path)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->load_model_from_nnpackage(pacakge_file_path);
+}
+
+/*
+ * Prepare session to be ready for inference
+ * This phase may finalize model compilation, scheduling, and additional settings.
+ *
+ * @param session the session to be prepared
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_prepare(nnfw_session *session)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->prepare();
+}
+
+/*
+ * Run inference
+ *
+ * @param session the session to run inference
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_run(nnfw_session *session)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->run();
+}
+
+NNFW_STATUS nnfw_run_async(nnfw_session *session)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->run_async();
+}
+
+NNFW_STATUS nnfw_await(nnfw_session *session)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->await();
+}
+
+/*
+ * Set input
+ *
+ * @param session session to the input is to be set
+ * @param index index of input to be set (0-indexed)
+ * @param type type of the input
+ * @param buffer raw buffer for input
+ * @param length size of bytes of input
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+
+NNFW_STATUS nnfw_set_input(nnfw_session *session, uint32_t index, NNFW_TYPE type,
+                           const void *buffer, size_t length)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_input(index, type, buffer, length);
+}
+
+/*
+ * Set output
+ *
+ * @param session session from inference output is to be extracted
+ * @param index index of output to be set (0-indexed)
+ * @param type type of the output
+ * @param buffer raw buffer for output
+ * @param length size of bytes of output
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+
+NNFW_STATUS nnfw_set_output(nnfw_session *session, uint32_t index, NNFW_TYPE type, void *buffer,
+                            size_t length)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_output(index, type, buffer, length);
+}
+
+/*
+ * Get the number of inputs
+ *
+ * @param[in] session session from input information is to be extracted
+ * @param[out] number variable which the number of inputs is put into
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+
+NNFW_STATUS nnfw_input_size(nnfw_session *session, uint32_t *number)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->input_size(number);
+}
+
+/*
+ * Get the number of outputs
+ *
+ * @param[in] session session from output information is to be extracted
+ * @param[out] number variable which the number of outputs is put into
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_output_size(nnfw_session *session, uint32_t *number)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->output_size(number);
+}
+
+/*
+ * Set the layout of an input
+ * @note The input that does not call this has NNFW_LAYOUT_CHANNELS_LAST layout
+ *
+ * @param[in] session session from inference input is to be extracted
+ * @param[in] index   index of input to be set (0-indexed)
+ * @param[in] layout  layout to set to target input
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_input_layout(nnfw_session *session, uint32_t index, NNFW_LAYOUT layout)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_input_layout(index, layout);
+}
+
+/*
+ * Set the layout of an output
+ * @note The output that does not call this has NNFW_LAYOUT_CHANNELS_LAST layout
+ *
+ * @param[in] session session from inference output is to be extracted
+ * @param[in] index   index of output to be set (0-indexed)
+ * @param[in] layout  layout to set to target output
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_output_layout(nnfw_session *session, uint32_t index, NNFW_LAYOUT layout)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_output_layout(index, layout);
+}
+
+/*
+ * Get i-th input tensor info
+ *
+ * @param[in] session session from input information is to be extracted
+ * @param[in] index index of input
+ * @param[out] tensor_info nnfw_tensor_info
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_input_tensorinfo(nnfw_session *session, uint32_t index,
+                                  nnfw_tensorinfo *tensor_info)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->input_tensorinfo(index, tensor_info);
+}
+
+/*
+ * Get i-th output tensor info
+ *
+ * @param[in] session session from output information is to be extracted
+ * @param[in] index index of output
+ * @param[out] tensor_info nnfw_tensor_info
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_output_tensorinfo(nnfw_session *session, uint32_t index,
+                                   nnfw_tensorinfo *tensor_info)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->output_tensorinfo(index, tensor_info);
+}
+
+/*
+ * Register custom operation
+ * @param session session to register this operation
+ * @param id operation id
+ * @param info registration info ( eval function, etc. )
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_register_custom_op_info(nnfw_session *session, const char *id,
+                                         custom_kernel_registration_info *info)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->register_custom_operation(id, info->eval_function);
+}
+
+NNFW_STATUS nnfw_apply_tensorinfo(nnfw_session *, uint32_t, nnfw_tensorinfo)
+{
+  return nnfw_session::deprecated("nnfw_apply_tensorinfo: Deprecated");
+}
+
+NNFW_STATUS nnfw_set_input_tensorinfo(nnfw_session *session, uint32_t index,
+                                      const nnfw_tensorinfo *tensor_info)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_input_tensorinfo(index, tensor_info);
+}
+
+/*
+ * Set available backends
+ *
+ * @param[in] session session to which a avilable backends are set
+ * @param[in] backends available backends on which nnfw uses
+ */
+NNFW_STATUS nnfw_set_available_backends(nnfw_session *session, const char *backends)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_available_backends(backends);
+}
+
+/**
+ * Set the operation's backend
+ *
+ * @param[in] session session to be modified
+ * @param[in] op operation to be set
+ * @param[in] backend bakcend on which operation run
+ *
+ * @return NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_set_op_backend(nnfw_session *, const char *, const char *)
+{
+  return nnfw_session::deprecated("nnfw_set_op_backend: Deprecated");
+}
+
+/*
+ * Retrieve uint32 type of nnfw information for given information ID.
+ *
+ * @param[in] session session to be queried on
+ * @param[in] information ID to be queried
+ * @param[out] val uint32 value to be returned
+ *
+ * @return @c NNFW_STATUS_NO_ERROR if successful
+ */
+NNFW_STATUS nnfw_query_info_u32(nnfw_session *session, NNFW_INFO_ID id, uint32_t *val)
+{
+  (void)session;
+  switch (id)
+  {
+    case NNFW_INFO_ID_VERSION:
+      if (val)
+      {
+        *val = NNFW_VERSION;
+        return NNFW_STATUS_NO_ERROR;
+      }
+      break;
+    default:
+      return NNFW_STATUS_ERROR;
+  }
+  // It should not be reached.
+  return NNFW_STATUS_ERROR;
+}
+
+NNFW_STATUS nnfw_load_circle_from_buffer(nnfw_session *session, uint8_t *buffer, size_t size)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->load_circle_from_buffer(buffer, size);
+}
+
+NNFW_STATUS nnfw_load_model_from_modelfile(nnfw_session *session, const char *file_path)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->load_model_from_modelfile(file_path);
+}
+
+NNFW_STATUS nnfw_input_tensorindex(nnfw_session *session, const char *tensorname, uint32_t *index)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->input_tensorindex(tensorname, index);
+}
+
+NNFW_STATUS nnfw_output_tensorindex(nnfw_session *session, const char *tensorname, uint32_t *index)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->output_tensorindex(tensorname, index);
+}
+
+NNFW_STATUS nnfw_set_backends_per_operation(nnfw_session *session, const char *backend_settings)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_backends_per_operation(backend_settings);
+}
+
+NNFW_STATUS nnfw_prepare_pipeline(nnfw_session *, const char *)
+{
+  return nnfw_session::deprecated("nnfw_prepare_pipeline: Deprecated");
+}
+
+NNFW_STATUS nnfw_push_pipeline_input(nnfw_session *, void *, void *)
+{
+  return nnfw_session::deprecated("nnfw_push_pipeline_input: Deprecated");
+}
+
+NNFW_STATUS nnfw_pop_pipeline_output(nnfw_session *, void *)
+{
+  return nnfw_session::deprecated("nnfw_pop_pipeline_output: Deprecated");
+}
+
+NNFW_STATUS nnfw_set_workspace(nnfw_session *session, const char *dir)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_workspace(dir);
+}
+
+// Training
+
+NNFW_STATUS nnfw_train_get_traininfo(nnfw_session *session, nnfw_train_info *info)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->train_get_traininfo(info);
+}
+
+NNFW_STATUS nnfw_train_set_traininfo(nnfw_session *session, const nnfw_train_info *info)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->train_set_traininfo(info);
+}
+
+NNFW_STATUS nnfw_train_prepare(nnfw_session *session)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->train_prepare();
+}
+
+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_set_output(nnfw_session *session, uint32_t index, NNFW_TYPE type,
+                                  void *buffer, size_t length)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->train_set_output(index, type, buffer, length);
+}
+
+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);
+}
+
+NNFW_STATUS nnfw_train_export_circleplus(nnfw_session *session, const char *path)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->train_export_circleplus(path);
+}
+
+// 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();
+}
+
+NNFW_STATUS nnfw_set_codegen_model_path(nnfw_session *session, const char *path)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_codegen_model_path(path);
+}
+
+NNFW_STATUS nnfw_codegen(nnfw_session *session, const char *target, NNFW_CODEGEN_PREF pref)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->codegen(target, pref);
+}
+
+// Configuration
+
+NNFW_STATUS nnfw_set_prepare_config(nnfw_session *session, const NNFW_PREPARE_CONFIG key,
+                                    const char *value)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_prepare_config(key, value);
+}
+
+NNFW_STATUS nnfw_reset_prepare_config(nnfw_session *session)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->reset_prepare_config();
+}
+
+NNFW_STATUS nnfw_set_execute_config(nnfw_session *session, const NNFW_RUN_CONFIG key,
+                                    const char *value)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->set_execute_config(key, value);
+}
+
+NNFW_STATUS nnfw_reset_execute_config(nnfw_session *session)
+{
+  NNFW_RETURN_ERROR_IF_NULL(session);
+  return session->reset_execute_config();
+}
diff --git a/runtime/onert/api/nnfw/src/nnfw_api_internal.cc b/runtime/onert/api/nnfw/src/nnfw_api_internal.cc
new file mode 100644 (file)
index 0000000..1051826
--- /dev/null
@@ -0,0 +1,1998 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_api_internal.h"
+#include "CustomKernelRegistry.h"
+#include "compiler/CompilerFactory.h"
+#include "util/ConfigSource.h"
+#include "util/Exceptions.h"
+#include "util/logging.h"
+#include "exec/Execution.h"
+#include "loader/CircleLoader.h"
+#include "loader/ModelLoader.h"
+#include "loader/TFLiteLoader.h"
+#include "loader/TrainInfoLoader.h"
+#include "exporter/CircleExporter.h"
+#include "json/json.h"
+#include "ir/NNPkg.h"
+#include "ir/OpCode.h"
+#include "ir/train/TrainingInfo.h"
+#include "util/TracingCtx.h"
+#include "odc/QuantizeManager.h"
+#include "odc/CodegenManager.h"
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <dirent.h>
+#include <misc/string_helpers.h>
+
+/*
+ * API does not accept string argument longer than max length below
+ */
+#define MAX_BACKEND_NAME_LENGTH 32
+#define MAX_OP_NAME_LENGTH 64
+#define MAX_PATH_LENGTH 1024
+#define MAX_TENSOR_NAME_LENGTH 64
+
+namespace
+{
+
+// Is null-terminating in length ?
+bool null_terminating(const char *str, uint32_t length)
+{
+  for (uint32_t i = 0; i < length; i++)
+  {
+    if (*(str + i) == '\0')
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+onert::ir::Layout convertLayout(NNFW_LAYOUT layout)
+{
+  if (layout == NNFW_LAYOUT_CHANNELS_LAST)
+  {
+    return onert::ir::Layout::NHWC;
+  }
+  else if (layout == NNFW_LAYOUT_CHANNELS_FIRST)
+  {
+    return onert::ir::Layout::NCHW;
+  }
+  return onert::ir::Layout::UNKNOWN;
+}
+
+NNFW_STATUS getTensorIndexImpl(const onert::ir::IGraph &graph, const char *tensorname,
+                               uint32_t *index, bool is_input)
+{
+  if (!tensorname || !index)
+    return NNFW_STATUS_UNEXPECTED_NULL;
+
+  if (!null_terminating(tensorname, MAX_TENSOR_NAME_LENGTH))
+  {
+    std::cerr << "nnpackage path is too long" << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  auto ind_found = is_input ? graph.getInputIndex(tensorname) : graph.getOutputIndex(tensorname);
+
+  if (ind_found.undefined())
+  {
+    // Not found
+    return NNFW_STATUS_ERROR;
+  }
+  else
+  {
+    *index = ind_found.value();
+    return NNFW_STATUS_NO_ERROR;
+  }
+}
+
+std::string trim(const std::string &value)
+{
+  std::string whitespace = " \t";
+  auto begin = value.find_first_not_of(whitespace);
+  if (begin == std::string::npos)
+    return ""; // no content
+
+  auto end = value.find_last_not_of(whitespace);
+  auto range = end - begin + 1;
+  return value.substr(begin, range);
+}
+
+bool loadConfigure(const std::string cfgfile, onert::util::CfgKeyValues &keyValues)
+{
+  std::ifstream ifs(cfgfile);
+  if (ifs.is_open())
+  {
+    std::string line;
+    while (std::getline(ifs, line))
+    {
+      auto cmtpos = line.find('#');
+      if (cmtpos != std::string::npos)
+      {
+        line = line.substr(0, cmtpos);
+      }
+      std::istringstream isline(line);
+      std::string key;
+      if (std::getline(isline, key, '='))
+      {
+        std::string value;
+        if (std::getline(isline, value))
+        {
+          key = trim(key);
+          keyValues[key] = trim(value);
+        }
+      }
+    }
+    ifs.close();
+    return true;
+  }
+  return false;
+}
+
+NNFW_TYPE datatype_to_nnfw_dtype(onert::ir::DataType dt)
+{
+  using onert::ir::DataType;
+  switch (dt)
+  {
+    case DataType::FLOAT32:
+      return NNFW_TYPE_TENSOR_FLOAT32;
+    case DataType::INT32:
+      return NNFW_TYPE_TENSOR_INT32;
+    case DataType::QUANT_UINT8_ASYMM:
+      return NNFW_TYPE_TENSOR_QUANT8_ASYMM;
+    case DataType::BOOL8:
+      return NNFW_TYPE_TENSOR_BOOL;
+    case DataType::UINT8:
+      return NNFW_TYPE_TENSOR_UINT8;
+    case DataType::INT64:
+      return NNFW_TYPE_TENSOR_INT64;
+    case DataType::QUANT_INT8_ASYMM:
+      return NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED;
+    case DataType::QUANT_INT16_SYMM:
+      return NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED;
+    case DataType::UINT32:
+    case DataType::QUANT_INT8_SYMM:
+    default:
+      throw std::runtime_error("Error: Model has type that runtime API does not support.");
+  }
+}
+
+void fillTensorInfo(nnfw_tensorinfo *ti, const onert::ir::Shape &shape,
+                    const onert::ir::DataType &dtype)
+{
+  ti->rank = shape.rank();
+  for (int j = 0; j < ti->rank; ++j)
+  {
+    ti->dims[j] = shape.dim(j);
+  }
+  ti->dtype = datatype_to_nnfw_dtype(dtype);
+}
+
+std::unique_ptr<onert::ir::Model> loadModel(const std::string filename,
+                                            const std::string model_type)
+{
+  try
+  {
+    if (model_type == "tflite")
+      return onert::loader::loadTFLiteModel(filename.c_str());
+    if (model_type == "circle")
+      return onert::loader::loadCircleModel(filename.c_str());
+
+    return onert::loader::loadModel(filename, model_type);
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Fail to load model: " << e.what() << '\n';
+  }
+
+  return std::unique_ptr<onert::ir::Model>(nullptr);
+}
+
+std::unique_ptr<onert::ir::train::TrainingInfo>
+loadTrainingInfo(const std::shared_ptr<onert::ir::Model> &model)
+{
+  const auto tinfo_name = onert::loader::TRAININFO_METADATA_NAME;
+  if (model->exists_metadata(tinfo_name))
+  {
+    const auto buffer = model->extract_metadata(tinfo_name);
+    return onert::loader::loadTrainingInfo(buffer->base(), buffer->size());
+  }
+  return std::make_unique<onert::ir::train::TrainingInfo>();
+}
+
+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;
+}
+} // namespace
+
+nnfw_session::nnfw_session()
+  : _nnpkg{nullptr}, _coptions{onert::compiler::CompilerOptions::fromGlobalConfig()},
+    _compiler_artifact{nullptr}, _execution{nullptr}, _kernel_registry{nullptr},
+    _train_info{nullptr}, _quant_manager{std::make_unique<onert::odc::QuantizeManager>()},
+    _codegen_manager{std::make_unique<onert::odc::CodegenManager>()}, _model_path{""}
+{
+  // DO NOTHING
+}
+
+NNFW_STATUS nnfw_session::create(nnfw_session **session)
+{
+  if (session == nullptr)
+    return NNFW_STATUS_UNEXPECTED_NULL;
+  try
+  {
+    auto new_session = std::unique_ptr<nnfw_session>(new nnfw_session());
+    new_session->_kernel_registry = std::make_shared<onert::api::CustomKernelRegistry>();
+    *session = new_session.release();
+  }
+  catch (const std::bad_alloc &e)
+  {
+    std::cerr << "Error during session creation" << std::endl;
+    *session = nullptr; // Set nullptr on error to keep the old behavior
+    return NNFW_STATUS_OUT_OF_MEMORY;
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during session initialization : " << e.what() << std::endl;
+    *session = nullptr; // Set nullptr on error to keep the old behavior
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+nnfw_session::~nnfw_session() = default;
+
+NNFW_STATUS nnfw_session::load_circle_from_buffer(uint8_t *buffer, size_t size)
+{
+  if (!isStateInitialized())
+    return NNFW_STATUS_INVALID_STATE;
+
+  if (!buffer)
+    return NNFW_STATUS_UNEXPECTED_NULL;
+
+  if (size == 0)
+    return NNFW_STATUS_ERROR;
+
+  try
+  {
+    auto model = onert::loader::loadCircleModel(buffer, size);
+    // TODO: Update _model_path if necessary
+    _nnpkg = std::make_shared<onert::ir::NNPkg>(std::move(model));
+    _train_info = loadTrainingInfo(_nnpkg->primary_model());
+    _state = State::MODEL_LOADED;
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during model loading : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::load_model_from_modelfile(const char *model_file_path)
+{
+  if (!isStateInitialized())
+    return NNFW_STATUS_INVALID_STATE;
+
+  if (!model_file_path)
+  {
+    std::cerr << "Model file path is null." << std::endl;
+    return NNFW_STATUS_UNEXPECTED_NULL;
+  }
+
+  std::string filename{model_file_path};
+  // TODO: Use std::filesystem::path when we can use c++17.
+  auto dotidx = filename.find_last_of('.');
+  if (dotidx == std::string::npos)
+  {
+    std::cerr << "Invalid model file path. Please use file with extension." << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  std::string model_type = filename.substr(dotidx + 1); // + 1 to exclude dot
+  try
+  {
+    return loadModelFile(filename, model_type);
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during model loading : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+}
+
+NNFW_STATUS nnfw_session::load_model_from_nnpackage(const char *package_dir)
+{
+  if (!isStateInitialized())
+    return NNFW_STATUS_INVALID_STATE;
+
+  if (!package_dir)
+  {
+    std::cerr << "package_dir is null." << std::endl;
+    return NNFW_STATUS_UNEXPECTED_NULL;
+  }
+
+  if (!null_terminating(package_dir, MAX_PATH_LENGTH))
+  {
+    std::cerr << "nnpackage path is too long" << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  // TODO : add support for zipped package file load
+  DIR *dir;
+  if (!(dir = opendir(package_dir)))
+  {
+    std::cerr << "invalid nnpackge directory: " << package_dir << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  closedir(dir);
+
+  try
+  {
+    std::string package_path(package_dir);
+    std::string manifest_file_name = package_path + "/metadata/MANIFEST";
+    std::ifstream mfs(manifest_file_name);
+
+    // extract the filename of the first(index 0) model
+    // e.g. In MANIFEST file, { "models" : [ "firstmodel.tflite", "2nd.tflite" ] }
+    Json::Value root;
+    mfs >> root;
+    const Json::Value &models = root["models"];
+    const Json::Value &model_types = root["model-types"];
+    const Json::Value &configs = root["configs"];
+
+    if (!configs.empty() && !configs[0].empty())
+    {
+      auto filepath = package_path + std::string("/metadata/") + configs[0].asString();
+
+      onert::util::CfgKeyValues keyValues;
+      if (loadConfigure(filepath, keyValues))
+      {
+        onert::util::setConfigKeyValues(keyValues);
+      }
+    }
+    _nnpkg = std::make_shared<onert::ir::NNPkg>();
+    auto num_models = models.size();
+    if (num_models == 0 || (num_models - 1) > onert::ir::ModelIndex::max())
+    {
+      std::cerr << "Invalid model size - " << std::to_string(num_models) << std::endl;
+      return NNFW_STATUS_ERROR;
+    }
+
+    // Not support backend mapping to operator index for multiple models yet
+    // TODO Support this
+    if (num_models > 1 && _coptions->manual_scheduler_options.index_to_backend.size() != 0)
+    {
+      std::cerr << "Cannot set backend to operator index for multiple models" << std::endl;
+      return NNFW_STATUS_ERROR;
+    }
+
+    for (uint16_t i = 0; i < num_models; ++i)
+    {
+      auto model_file_path = package_path + std::string("/") + models[i].asString();
+      auto model_type = model_types[i].asString();
+      auto model = loadModel(model_file_path, model_type);
+      if (model == nullptr)
+        return NNFW_STATUS_ERROR;
+      _model_path = std::string(model_file_path); // TODO Support multiple models
+      model->bindKernelBuilder(_kernel_registry->getBuilder());
+      _nnpkg->push(onert::ir::ModelIndex{i}, std::move(model));
+    }
+
+    _train_info = loadTrainingInfo(_nnpkg->primary_model());
+
+    auto toIODesc = [](std::string str) {
+      auto indices = nnfw::misc::split(str, ':');
+      if (indices.size() != 3)
+      {
+        std::cerr << "IODesc should be 3-tuple." << std::endl;
+        return onert::ir::IODesc{};
+      }
+      auto model_idx = static_cast<uint32_t>(std::stoi(indices.at(0)));
+      auto subgraph_idx = static_cast<uint32_t>(std::stoi(indices.at(1)));
+      auto operand_idx = static_cast<uint32_t>(std::stoi(indices.at(2)));
+      return onert::ir::IODesc{model_idx, subgraph_idx, operand_idx};
+    };
+    // read pkg-inputs and pkg-outputs
+    const Json::Value &pkg_inputs = root["pkg-inputs"];
+    for (uint32_t i = 0; i < pkg_inputs.size(); ++i)
+      _nnpkg->addInput(toIODesc(pkg_inputs[i].asString()));
+    const Json::Value &pkg_outputs = root["pkg-outputs"];
+    for (uint32_t i = 0; i < pkg_outputs.size(); ++i)
+      _nnpkg->addOutput(toIODesc(pkg_outputs[i].asString()));
+    // read model-connect
+    const Json::Value &fromtos = root["model-connect"];
+    for (uint32_t i = 0; i < fromtos.size(); ++i)
+    {
+      const Json::Value &tos = fromtos[i]["to"];
+      for (uint32_t j = 0; j < tos.size(); ++j)
+        _nnpkg->addEdge(toIODesc(fromtos[i]["from"].asString()), toIODesc(tos[j].asString()));
+    }
+
+    _nnpkg->verify();
+    _state = State::MODEL_LOADED;
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during model loading : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::prepare()
+{
+  // NOTE. If users want to run prepare() more than one time, this could be removed.
+  if (!isStateModelLoaded())
+  {
+    std::cerr << "Error during model prepare : ";
+    if (isStateInitialized())
+    {
+      std::cerr << "prepare should be run once";
+    }
+    else
+    {
+      std::cerr << "invalid state";
+    }
+    std::cerr << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  try
+  {
+    auto compiler = onert::compiler::CompilerFactory::get().create(_nnpkg, _coptions.get());
+    _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 model prepare : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  _state = State::PREPARED;
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::run()
+{
+  if (!isStatePreparedOrFinishedRun())
+  {
+    std::cerr << "Error during nnfw_session::run : "
+              << "run should be run after prepare" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  try
+  {
+    _execution->execute();
+  }
+  catch (const onert::InsufficientBufferSizeException &e)
+  {
+    // Currently insufficient buffer always means output buffer.
+    std::cerr << "Error during nnfw_session::run : " << e.what() << std::endl;
+    return NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE;
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::run : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  _state = State::FINISHED_RUN;
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::run_async()
+{
+  if (!isStatePreparedOrFinishedRun())
+  {
+    std::cerr << "Error during nnfw_session::run_async : "
+              << "run_async should be run after prepare" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  _execution->startExecute();
+
+  _state = State::RUNNING;
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::await()
+{
+  if (!isStateRunning())
+  {
+    std::cerr << "Error during nnfw_session::run_await : "
+              << "run_await should be run after run_async" << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  _execution->waitFinish();
+
+  _state = State::FINISHED_RUN;
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_input(uint32_t index, NNFW_TYPE type, const void *buffer,
+                                    size_t length)
+{
+  if (!isStatePreparedOrFinishedRun())
+  {
+    std::cerr << "Error during nnfw_session::set_input : invalid state" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  if (!buffer && length != 0)
+  {
+    std::cerr
+      << "Error during nnfw_session::set_input : given buffer is NULL but the length is not 0"
+      << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  try
+  {
+    // Allow float input internal quantization only
+    if (type == NNFW_TYPE_TENSOR_FLOAT32)
+      _execution->setInputType(onert::ir::IOIndex(index),
+                               onert::ir::TypeInfo(onert::ir::DataType::FLOAT32));
+    _execution->setInput(onert::ir::IOIndex(index), buffer, length);
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::set_input : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_output(uint32_t index, NNFW_TYPE type, void *buffer, size_t length)
+{
+  if (!isStatePreparedOrFinishedRun())
+  {
+    std::cerr << "Error during nnfw_session::set_output : invalid state" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  if (!buffer && length != 0)
+  {
+    std::cerr
+      << "Error during nnfw_session::set_output : given buffer is NULL but the length is not 0"
+      << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  try
+  {
+    // Allow float output internal dequantization only
+    if (type == NNFW_TYPE_TENSOR_FLOAT32)
+      _execution->setOutputType(onert::ir::IOIndex(index),
+                                onert::ir::TypeInfo(onert::ir::DataType::FLOAT32));
+    _execution->setOutput(onert::ir::IOIndex(index), buffer, length);
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::set_output : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::input_size(uint32_t *number)
+{
+  if (isStateInitialized()) // Model is not loaded
+    return NNFW_STATUS_INVALID_STATE;
+
+  try
+  {
+    if (number == nullptr)
+    {
+      std::cerr << "Error during nnfw_session::input_size, number is null pointer." << std::endl;
+      return NNFW_STATUS_UNEXPECTED_NULL;
+    }
+    *number = getInputSize();
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::input_size : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::output_size(uint32_t *number)
+{
+  if (isStateInitialized()) // Model is not loaded
+    return NNFW_STATUS_INVALID_STATE;
+
+  try
+  {
+    if (number == nullptr)
+    {
+      std::cerr << "Error during nnfw_session::output_size, number is null pointer." << std::endl;
+      return NNFW_STATUS_UNEXPECTED_NULL;
+    }
+    *number = getOutputSize();
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::output_size" << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_input_layout(uint32_t index, NNFW_LAYOUT layout)
+{
+  if (!isStatePreparedOrFinishedRun())
+  {
+    std::cerr << "Error during nnfw_session::set_input_layout : "
+              << "run should be run after prepare" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  try
+  {
+    if (layout != NNFW_LAYOUT_NONE && layout != NNFW_LAYOUT_CHANNELS_FIRST &&
+        layout != NNFW_LAYOUT_CHANNELS_LAST)
+    {
+      std::cerr << "Error during nnfw_session::set_input_layout, not supported layout" << std::endl;
+      return NNFW_STATUS_ERROR;
+    }
+
+    _execution->setInputLayout(onert::ir::IOIndex(index), convertLayout(layout));
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::set_input_layout : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_output_layout(uint32_t index, NNFW_LAYOUT layout)
+{
+  if (!isStatePreparedOrFinishedRun())
+  {
+    std::cerr << "Error during nnfw_session::set_output_layout : "
+              << "run should be run after prepare" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  try
+  {
+    if (layout != NNFW_LAYOUT_NONE && layout != NNFW_LAYOUT_CHANNELS_FIRST &&
+        layout != NNFW_LAYOUT_CHANNELS_LAST)
+    {
+      std::cerr << "Error during nnfw_session::set_output_layout, not supported layout"
+                << std::endl;
+      return NNFW_STATUS_ERROR;
+    }
+
+    _execution->setOutputLayout(onert::ir::IOIndex(index), convertLayout(layout));
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::set_output_layout : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_input_tensorinfo(uint32_t index, const nnfw_tensorinfo *ti)
+{
+  // sanity check
+  {
+    if (isStateInitialized())
+    {
+      std::cerr << "Error during set_input_tensorinfo : should be run after load_model"
+                << std::endl;
+      return NNFW_STATUS_INVALID_STATE;
+    }
+
+    if (ti == nullptr)
+    {
+      std::cerr << "Error during nnfw_session::set_input_tensorinfo : tensorinfo is null"
+                << std::endl;
+      return NNFW_STATUS_UNEXPECTED_NULL;
+    }
+
+    if (ti->rank <= 0 || ti->rank > NNFW_MAX_RANK)
+    {
+      std::cerr << "unsupported rank: " << ti->rank << std::endl;
+      return NNFW_STATUS_ERROR;
+    }
+
+    for (int32_t i = 0; i < ti->rank; ++i)
+    {
+      if (ti->dims[i] <= 0)
+      {
+        std::cerr << "dim must be positive integer but was " << ti->dims[i] << std::endl;
+        return NNFW_STATUS_ERROR;
+      }
+    }
+  }
+
+  onert::ir::Shape new_shape(ti->rank);
+  for (int32_t i = 0; i < ti->rank; i++)
+    new_shape.dim(i) = ti->dims[i];
+
+  if (!isStatePreparedOrFinishedRun())
+  {
+
+    // In this case, if we apply input shape, it will propagate after compilation and excution
+    _nnpkg->changeInputShape(index, new_shape);
+  }
+  else // when called after nnfw_session::prepare()
+    _execution->changeInputShape(onert::ir::IOIndex(index), new_shape);
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::input_tensorinfo(uint32_t index, nnfw_tensorinfo *ti)
+{
+  if (isStateInitialized())
+    return NNFW_STATUS_INVALID_STATE;
+
+  try
+  {
+    if (ti == nullptr)
+    {
+      std::cerr << "Error during nnfw_session::input_tensorinfo, tensorinfo is null pointer."
+                << std::endl;
+      return NNFW_STATUS_UNEXPECTED_NULL;
+    }
+
+    if (index >= getInputSize())
+    {
+      std::cerr << "Error during nnfw_session::input_tensorinfo, index is out of range."
+                << std::endl;
+      return NNFW_STATUS_ERROR;
+    }
+
+    if (isStateModelLoaded())
+    {
+      auto info = _nnpkg->inputInfo(index);
+      fillTensorInfo(ti, info.shape(), info.typeInfo().type());
+    }
+    else
+    {
+      auto io_index = onert::ir::IOIndex{index};
+      auto shape = _execution->getInputShape(io_index);
+      auto dtype = _compiler_artifact->_executors->inputInfo(io_index).typeInfo().type();
+      fillTensorInfo(ti, shape, dtype);
+    }
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::input_tensorinfo : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::output_tensorinfo(uint32_t index, nnfw_tensorinfo *ti)
+{
+  if (isStateInitialized())
+    return NNFW_STATUS_INVALID_STATE;
+
+  if (ti == nullptr)
+  {
+    std::cerr << "Error during nnfw_session::output_tensorinfo, tensorinfo is null pointer."
+              << std::endl;
+    return NNFW_STATUS_UNEXPECTED_NULL;
+  }
+
+  try
+  {
+    if (index >= getOutputSize())
+    {
+      std::cerr << "Error during nnfw_session::output_tensorinfo, index is out of range."
+                << std::endl;
+      return NNFW_STATUS_ERROR;
+    }
+
+    if (isStateModelLoaded())
+    {
+      auto info = _nnpkg->outputInfo(index);
+      fillTensorInfo(ti, info.shape(), info.typeInfo().type());
+    }
+    else
+    {
+      auto io_index = onert::ir::IOIndex{index};
+      auto shape = _execution->getOutputShape(io_index);
+      auto dtype = _compiler_artifact->_executors->outputInfo(io_index).typeInfo().type();
+      fillTensorInfo(ti, shape, dtype);
+    }
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::output_tensorinfo : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::register_custom_operation(const std::string &id,
+                                                    nnfw_custom_eval eval_func)
+{
+  _kernel_registry->registerKernel(id, eval_func);
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_available_backends(const char *backends)
+{
+  if (!isStateModelLoaded())
+    return NNFW_STATUS_INVALID_STATE;
+
+  try
+  {
+    if (!backends)
+      return NNFW_STATUS_UNEXPECTED_NULL;
+    if (null_terminating(backends, MAX_BACKEND_NAME_LENGTH) == false)
+      return NNFW_STATUS_ERROR;
+
+    using namespace onert::util;
+
+    _coptions->backend_list = nnfw::misc::split(std::string{backends}, ';');
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::set_available_backends : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_workspace(const char *dir)
+{
+  // TODO Check dir read & write permission
+
+  if (!dir)
+    return NNFW_STATUS_UNEXPECTED_NULL;
+
+  if (!isStateInitialized())
+    return NNFW_STATUS_INVALID_STATE;
+
+  _coptions->workspace_dir = std::string(dir);
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::deprecated(const char *msg)
+{
+  std::cerr << msg << std::endl;
+  return NNFW_STATUS_DEPRECATED_API;
+}
+
+NNFW_STATUS nnfw_session::set_config(const char *key, const char *value)
+{
+  if (!isStateModelLoaded())
+    return NNFW_STATUS_INVALID_STATE;
+
+  if (!key || !value)
+    return NNFW_STATUS_UNEXPECTED_NULL;
+
+  using namespace onert::util;
+
+  const std::string skey = key;
+
+  if (skey == config::GRAPH_DOT_DUMP)
+  {
+    _coptions->graph_dump_level = toInt(value);
+  }
+  else if (skey == config::EXECUTOR)
+  {
+    _coptions->executor = value;
+  }
+  else if (skey == config::OP_BACKEND_ALLOPS)
+  {
+    _coptions->manual_scheduler_options.backend_for_all = value;
+  }
+  else if (skey == config::USE_SCHEDULER)
+  {
+    _coptions->he_scheduler = toBool(value);
+  }
+  else if (skey == config::PROFILING_MODE)
+  {
+    _coptions->he_profiling_mode = toBool(value);
+  }
+  else
+  {
+    return NNFW_STATUS_ERROR;
+  }
+  return NNFW_STATUS_NO_ERROR;
+}
+
+const onert::ir::IGraph *nnfw_session::primary_subgraph()
+{
+  if (_nnpkg != nullptr)
+  {
+    assert(_execution == nullptr);
+    return _nnpkg->primary_model()->primary_subgraph().get();
+  }
+  else
+  {
+    assert(_execution != nullptr);
+    // We assumed the graph will not change after compilation, but shape could change
+    return &_execution->primary_subgraph();
+  }
+}
+
+uint32_t nnfw_session::getInputSize()
+{
+  if (isStateInitialized())
+    throw std::runtime_error{"Model is not loaded yet"};
+
+  if (isStateModelLoaded())
+    return _nnpkg->inputSize();
+
+  // Session is prepared (general inference)
+  return _compiler_artifact->_executors->inputSize();
+}
+
+uint32_t nnfw_session::getOutputSize()
+{
+  if (isStateInitialized())
+    throw std::runtime_error{"Model is not loaded yet"};
+
+  if (isStateModelLoaded())
+    return _nnpkg->outputSize();
+
+  // Session is prepared (general inference)
+  return _compiler_artifact->_executors->outputSize();
+}
+
+NNFW_STATUS nnfw_session::loadModelFile(const std::string &model_file_path,
+                                        const std::string &model_type)
+{
+  auto model = loadModel(model_file_path, model_type);
+  if (model == nullptr)
+    return NNFW_STATUS_ERROR;
+
+  _nnpkg = std::make_shared<onert::ir::NNPkg>(std::move(model));
+  _model_path = model_file_path;
+  _compiler_artifact.reset();
+  _execution.reset();
+  _train_info = loadTrainingInfo(_nnpkg->primary_model());
+  _state = State::MODEL_LOADED;
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::get_config(const char *key, char *value, size_t value_size)
+{
+  if (!isStateModelLoaded())
+    return NNFW_STATUS_INVALID_STATE;
+
+  if (!key || !value)
+    return NNFW_STATUS_UNEXPECTED_NULL;
+
+  auto check_boundary = [](size_t dest_size, std::string &src) {
+    if (dest_size < src.length() + 1 /* for '\0' */)
+    {
+      std::cerr << "buffer is small to copy config value." << std::endl;
+      return false;
+    }
+    return true;
+  };
+
+  const std::string skey = key;
+
+  if (skey == onert::util::config::BACKENDS)
+  {
+    if (_coptions->backend_list.size() == 0)
+      return NNFW_STATUS_NO_ERROR; // no setting backend is not an error of get_config_str()
+
+    auto str =
+      nnfw::misc::join(_coptions->backend_list.begin(), _coptions->backend_list.end(), ";");
+
+    if (!check_boundary(value_size, str))
+      return NNFW_STATUS_ERROR;
+
+    strncpy(value, str.c_str(), value_size);
+  }
+  else if (skey == onert::util::config::EXECUTOR)
+  {
+    if (!check_boundary(value_size, _coptions->executor))
+      return NNFW_STATUS_ERROR;
+
+    strncpy(value, _coptions->executor.c_str(), _coptions->executor.length());
+  }
+  else
+  {
+    return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+bool nnfw_session::isStateInitialized()
+{
+  if (_state == State::INITIALIZED)
+  {
+    assert(_nnpkg == nullptr);
+    assert(_execution == nullptr);
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool nnfw_session::isStateModelLoaded()
+{
+  if (_state == State::MODEL_LOADED)
+  {
+    assert(_nnpkg != nullptr);
+    assert(_execution == nullptr);
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool nnfw_session::isStatePrepared()
+{
+  if (_state == State::PREPARED)
+  {
+    assert(_nnpkg == nullptr);
+    assert(_execution != nullptr);
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool nnfw_session::isStateRunning()
+{
+  if (_state == State::RUNNING)
+  {
+    assert(_nnpkg == nullptr);
+    assert(_execution != nullptr);
+    return true;
+  }
+  return false;
+}
+
+bool nnfw_session::isStateFinishedRun()
+{
+  if (_state == State::FINISHED_RUN)
+  {
+    assert(_nnpkg == nullptr);
+    assert(_execution != nullptr);
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool nnfw_session::isStatePreparedOrFinishedRun()
+{
+  return isStatePrepared() || isStateFinishedRun();
+}
+
+NNFW_STATUS nnfw_session::input_tensorindex(const char *tensorname, uint32_t *index)
+{
+  return getTensorIndexImpl(*primary_subgraph(), tensorname, index, true);
+}
+
+NNFW_STATUS nnfw_session::output_tensorindex(const char *tensorname, uint32_t *index)
+{
+  return getTensorIndexImpl(*primary_subgraph(), tensorname, index, false);
+}
+
+NNFW_STATUS nnfw_session::set_backends_per_operation(const char *backend_settings)
+{
+  if (backend_settings == NULL)
+    return NNFW_STATUS_ERROR;
+
+  if (!isStateModelLoaded())
+    return NNFW_STATUS_INVALID_STATE;
+
+  // Not supported multiple model
+  // TODO Support this
+  if (_nnpkg->model_count() > 1)
+  {
+    std::cerr << "Not supported multiple model" << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  try
+  {
+    // Backend for all
+    auto &ms_options = _coptions->manual_scheduler_options;
+    ms_options.setBackendMap(std::string{backend_settings});
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::set_backends_per_operation" << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_get_traininfo(nnfw_train_info *info)
+{
+  if (isStateInitialized())
+  {
+    // There is no _train_info in INITIALIZED, since _train_info is set when a model loaded
+    std::cerr << "Error during nnfw_session::train_get_traininfo : invalid state";
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  if (info == nullptr)
+  {
+    std::cerr << "Error during nnfw_session::train_get_traininfo : info is nullptr" << std::endl;
+    return NNFW_STATUS_UNEXPECTED_NULL;
+  }
+
+  // after model loaded, it ensures that _train_info is not nullptr
+  assert(_train_info != nullptr);
+
+  auto convertLossCode = [](const onert::ir::train::LossCode &code) -> NNFW_TRAIN_LOSS {
+    switch (code)
+    {
+      case onert::ir::train::LossCode::Undefined:
+        return NNFW_TRAIN_LOSS_UNDEFINED;
+      case onert::ir::train::LossCode::MeanSquaredError:
+        return NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR;
+      case onert::ir::train::LossCode::CategoricalCrossentropy:
+        return NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY;
+      default:
+        throw std::runtime_error{"fail to convert ir::train::LossCode"};
+    }
+  };
+
+  auto convertLossReduction =
+    [](const onert::ir::train::LossReductionType &type) -> NNFW_TRAIN_LOSS_REDUCTION {
+    switch (type)
+    {
+      case onert::ir::train::LossReductionType::Undefined:
+        return NNFW_TRAIN_LOSS_REDUCTION_UNDEFINED;
+      case onert::ir::train::LossReductionType::SumOverBatchSize:
+        return NNFW_TRAIN_LOSS_REDUCTION_SUM_OVER_BATCH_SIZE;
+      case onert::ir::train::LossReductionType::Sum:
+        return NNFW_TRAIN_LOSS_REDUCTION_SUM;
+      default:
+        throw std::runtime_error{"fail to convert from ir::train::LossReductionType"};
+        break;
+    }
+  };
+
+  auto convertOptimizerCode =
+    [](const onert::ir::train::OptimizerCode &code) -> NNFW_TRAIN_OPTIMIZER {
+    switch (code)
+    {
+      case onert::ir::train::OptimizerCode::Undefined:
+        return NNFW_TRAIN_OPTIMIZER_UNDEFINED;
+      case onert::ir::train::OptimizerCode::SGD:
+        return NNFW_TRAIN_OPTIMIZER_SGD;
+      case onert::ir::train::OptimizerCode::Adam:
+        return NNFW_TRAIN_OPTIMIZER_ADAM;
+      default:
+        throw std::runtime_error{"fail to convert from ir::train::OptimizerCode"};
+    }
+  };
+
+  const auto &loss = _train_info->lossInfo();
+  const auto &optim = _train_info->optimizerInfo();
+
+  try
+  {
+    info->learning_rate = optim.learning_rate;
+    info->batch_size = _train_info->batchSize();
+    info->loss_info.loss = convertLossCode(loss.loss_code);
+    info->loss_info.reduction_type = convertLossReduction(loss.reduction_type);
+    info->opt = convertOptimizerCode(optim.optim_code);
+
+    if (_train_info->getTrainableOps().size() > 0)
+    {
+      const uint32_t first_trainable_idx = _train_info->getTrainableOps().cbegin()->value();
+      const uint32_t last_trainable_idx = _train_info->getTrainableOps().crbegin()->value();
+      const uint32_t ops_size = primary_subgraph()->operations().size();
+      const uint32_t trainable_indexes_range = last_trainable_idx - first_trainable_idx + 1;
+
+      // check if trainable ops set contains continuous indexes on the back of the set
+      if (last_trainable_idx == ops_size - 1 &&
+          trainable_indexes_range == _train_info->getTrainableOps().size())
+      {
+        // check if all ops are trainable
+        if (0 == first_trainable_idx)
+        {
+          info->num_of_trainable_ops = NNFW_TRAIN_TRAINABLE_ALL;
+        }
+        else
+        {
+          info->num_of_trainable_ops = trainable_indexes_range;
+        }
+      }
+      else
+      {
+        info->num_of_trainable_ops = NNFW_TRAIN_TRAINABLE_INCORRECT_STATE;
+        std::cerr << "conversion from set of trainable ops to num_of_trainable_ops is impossible"
+                  << std::endl;
+        return NNFW_STATUS_INVALID_STATE;
+      }
+    }
+    else
+    {
+      // no layer will be trained
+      info->num_of_trainable_ops = NNFW_TRAIN_TRAINABLE_NONE;
+    }
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::train_get_traininfo" << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_set_traininfo(const nnfw_train_info *info)
+{
+  if (not isStateModelLoaded())
+  {
+    std::cerr << "Error during nnfw_session::train_set_traininfo : invalid state" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  if (info == nullptr)
+  {
+    std::cerr << "nnfw_session::train_set_traininfo : info is nullptr" << std::endl;
+    return NNFW_STATUS_UNEXPECTED_NULL;
+  }
+
+  // after model loaded, it ensures that _train_info is not nullptr
+  assert(_train_info != nullptr);
+
+  auto convertLossType = [](const int &type) {
+    if (type == NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR)
+      return onert::ir::train::LossCode::MeanSquaredError;
+    else if (type == NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY)
+      return onert::ir::train::LossCode::CategoricalCrossentropy;
+    else
+      throw std::runtime_error("not supported loss type");
+  };
+
+  auto convertLossReductionType = [](const int &type) {
+    if (type == NNFW_TRAIN_LOSS_REDUCTION_SUM_OVER_BATCH_SIZE)
+      return onert::ir::train::LossReductionType::SumOverBatchSize;
+    else if (type == NNFW_TRAIN_LOSS_REDUCTION_SUM)
+      return onert::ir::train::LossReductionType::Sum;
+    else
+      throw std::runtime_error("not supported loss reduction type");
+  };
+
+  auto convertOptType = [](const int &type) {
+    if (type == NNFW_TRAIN_OPTIMIZER_SGD)
+      return onert::ir::train::OptimizerCode::SGD;
+    else if (type == NNFW_TRAIN_OPTIMIZER_ADAM)
+      return onert::ir::train::OptimizerCode::Adam;
+    else
+      throw std::runtime_error("not supported optimizer type");
+  };
+
+  try
+  {
+    onert::ir::train::LossInfo loss_info;
+    loss_info.loss_code = convertLossType(info->loss_info.loss);
+    loss_info.reduction_type = convertLossReductionType(info->loss_info.reduction_type);
+
+    onert::ir::train::OptimizerInfo opt_info;
+    opt_info.learning_rate = info->learning_rate;
+    opt_info.optim_code = convertOptType(info->opt);
+
+    _train_info->setBatchSize(info->batch_size);
+    _train_info->setLossInfo(loss_info);
+    _train_info->setOptimizerInfo(opt_info);
+
+    if (info->num_of_trainable_ops < -1)
+    {
+      std::cerr << "Error during nnfw_session::train_set_traininfo: provided num_of_trainable_ops "
+                   "has incorrect value: "
+                << info->num_of_trainable_ops << std::endl;
+      return NNFW_STATUS_ERROR;
+    }
+
+    const uint32_t ops_size = primary_subgraph()->operations().size();
+    std::set<onert::ir::OperationIndex> trainable_ops;
+
+    if (NNFW_TRAIN_TRAINABLE_ALL == info->num_of_trainable_ops)
+    {
+      for (uint32_t idx = 0; idx < ops_size; ++idx)
+      {
+        trainable_ops.emplace(idx);
+      }
+    }
+    else
+    {
+      if (static_cast<uint32_t>(info->num_of_trainable_ops) > ops_size)
+      {
+        std::cerr
+          << "Error during nnfw_session::train_set_traininfo: provided num_of_trainable_ops="
+          << info->num_of_trainable_ops << " is out of operators range equals: " << ops_size
+          << std::endl;
+        return NNFW_STATUS_ERROR;
+      }
+      for (uint32_t i = 1; i <= static_cast<uint32_t>(info->num_of_trainable_ops); ++i)
+      {
+        trainable_ops.emplace(ops_size - i);
+      }
+    }
+    // Note that possible setting an empty trainable_ops set (for NNFW_TRAIN_TRAINABLE_NONE value)
+    _train_info->setTrainableOps(trainable_ops);
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::train_set_traininfo : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_prepare()
+{
+  // 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;
+  }
+
+  // after model loaded, it ensures that _train_info is not nullptr
+  assert(_train_info != nullptr);
+
+  try
+  {
+    if (not _train_info->isValid())
+      throw std::runtime_error{"training info is not valid"};
+
+    // initialize trainingStep count
+    _train_info->trainingStep() = 0;
+
+    auto compiler =
+      onert::compiler::CompilerFactory::get().create(_nnpkg, _coptions.get(), _train_info.get());
+    _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_set_output(uint32_t index, NNFW_TYPE /*type*/, void *buffer,
+                                           size_t length)
+{
+  if (!isStatePreparedOrFinishedTraining())
+  {
+    std::cerr << "Error during nnfw_session::train_set_output : invalid state" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  if (!buffer && length != 0)
+  {
+    std::cerr << "Error during nnfw_session::train_set_output : given buffer is NULL but the "
+                 "length is not 0"
+              << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  try
+  {
+    _execution->setOutput(onert::ir::IOIndex(index), buffer, length);
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::train_set_output : " << 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)
+    {
+      auto &training_step = _train_info->trainingStep();
+      _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;
+  }
+
+  try
+  {
+    onert::exporter::CircleExporter exporter(_model_path, std::string{path});
+    exporter.updateWeight(_execution);
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::train_export_circle : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::train_export_circleplus(const char *path)
+{
+  if (path == nullptr)
+  {
+    std::cerr << "Error during nnfw_session::train_export_circleplus : path is null" << std::endl;
+    return NNFW_STATUS_UNEXPECTED_NULL;
+  }
+
+  if (!isStatePreparedOrFinishedTraining())
+  {
+    std::cerr << "Error during nnfw_session::train_export_circleplus : invalid state" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  try
+  {
+    onert::exporter::CircleExporter exporter(_model_path, std::string{path});
+    exporter.updateWeight(_execution);
+    exporter.updateMetadata(_train_info);
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::train_export_circleplus : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+bool nnfw_session::isStatePreparedTraining()
+{
+  if (_state == State::PREPARED_TRAINING)
+  {
+    assert(_nnpkg == nullptr);
+    assert(_execution != nullptr);
+    return true;
+  }
+  else
+    return false;
+}
+
+bool nnfw_session::isStateFinishedTraining()
+{
+  if (_state == State::FINISHED_TRAINING)
+  {
+    assert(_nnpkg == nullptr);
+    assert(_execution != nullptr);
+    return true;
+  }
+  else
+    return false;
+}
+
+bool nnfw_session::isStatePreparedOrFinishedTraining()
+{
+  return isStatePreparedTraining() || isStateFinishedTraining();
+}
+
+NNFW_STATUS nnfw_session::set_quantization_type(NNFW_QUANTIZE_TYPE qtype)
+{
+  using onert::odc::QuantizeType;
+  try
+  {
+    if (isStateInitialized() || isStateRunning())
+    {
+      std::cerr << "invalid state" << std::endl;
+      return NNFW_STATUS_INVALID_STATE;
+    }
+
+    QuantizeType odc_qtype = onert::odc::ODC_QTYPE_NOT_SET;
+    switch (qtype)
+    {
+      case NNFW_QUANTIZE_TYPE_U8_ASYM:
+        odc_qtype = onert::odc::ODC_QTYPE_U8_ASYM;
+        break;
+      case NNFW_QUANTIZE_TYPE_I16_SYM:
+        odc_qtype = onert::odc::ODC_QTYPE_I16_SYM;
+        break;
+      case NNFW_QUANTIZE_TYPE_WO_I8_SYM:
+        odc_qtype = onert::odc::ODC_QTYPE_WO_I8_SYM;
+        break;
+      case NNFW_QUANTIZE_TYPE_WO_I16_SYM:
+        odc_qtype = onert::odc::ODC_QTYPE_WO_I16_SYM;
+        break;
+      default:
+        return NNFW_STATUS_INVALID_STATE;
+    }
+    _quant_manager->quantizeType(odc_qtype);
+  }
+  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 (isStateInitialized() || isStateRunning())
+    {
+      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 (isStateInitialized() || isStateRunning())
+    {
+      std::cerr << "invalid state" << std::endl;
+      return NNFW_STATUS_INVALID_STATE;
+    }
+
+    auto result = _quant_manager->quantize(_model_path);
+    if (!result)
+      return NNFW_STATUS_INVALID_STATE;
+
+    // Replace model
+    // TODO Support buffer replace, not file reload
+    return loadModelFile(_quant_manager->exportModelPath(), "circle");
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::quantize : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+}
+
+NNFW_STATUS nnfw_session::set_codegen_model_path(const char *path)
+{
+  try
+  {
+    if (isStateInitialized() || isStateRunning())
+    {
+      std::cerr << "invalid state" << std::endl;
+      return NNFW_STATUS_INVALID_STATE;
+    }
+
+    assert(_codegen_manager != nullptr);
+    _codegen_manager->exportModelPath(std::string(path));
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::set_codegen_model_path : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::codegen(const char *target, NNFW_CODEGEN_PREF pref)
+{
+  try
+  {
+    if (isStateInitialized() || isStateRunning())
+    {
+      std::cerr << "Error during nnfw_session::codegen : Invalid state" << std::endl;
+      return NNFW_STATUS_INVALID_STATE;
+    }
+
+    std::string target_str{target};
+    if (target_str.empty() || target_str.substr(target_str.size() - 4) != "-gen")
+    {
+      std::cerr << "Error during nnfw_session::codegen : Invalid target" << std::endl;
+      return NNFW_STATUS_ERROR;
+    }
+
+    onert::odc::CodegenPreference codegen_pref;
+    switch (pref)
+    {
+      case NNFW_CODEGEN_PREF_DEFAULT:
+        codegen_pref = onert::odc::CodegenPreference::CODEGEN_PREF_DEFAULT;
+        break;
+      case NNFW_CODEGEN_PREF_PERFORMANCE_FIRST:
+        codegen_pref = onert::odc::CodegenPreference::CODEGEN_PREF_PERFORMANCE_FIRST;
+        break;
+      case NNFW_CODEGEN_PREF_MEMORY_FIRST:
+        codegen_pref = onert::odc::CodegenPreference::CODEGEN_PREF_MEMORY_FIRST;
+        break;
+      case NNFW_CODEGEN_PREF_COMPILE_TIME_FIRST:
+        codegen_pref = onert::odc::CodegenPreference::CODEGEN_PREF_COMPILE_TIME_FIRST;
+        break;
+      default:
+        std::cerr << "Error during nnfw_session::codegen : Invalid preference" << std::endl;
+        return NNFW_STATUS_ERROR;
+    }
+
+    assert(_codegen_manager != nullptr);
+    auto export_model_path = _codegen_manager->exportModelPath();
+    // If the export_model_path is not set, it generates a compiled model path
+    // automatically.
+    if (export_model_path.empty())
+    {
+      // model path always has a dot. (valid extension)
+      auto dotidx = _model_path.rfind('.');
+      assert(dotidx != std::string::npos);
+      auto genidx = target_str.rfind("-gen");
+      assert(genidx != std::string::npos);
+      // The compiled model path is the same directory of the original model/package with
+      // target backend extension.
+      export_model_path = _model_path.substr(0, dotidx + 1) + target_str.substr(0, genidx);
+      _codegen_manager->exportModelPath(export_model_path);
+    }
+
+    _codegen_manager->codegen(_model_path, target, codegen_pref);
+
+    // Replace model
+    // TODO Support buffer replace, not file reload
+    // TODO: Use std::filesystem::path when we can use c++17.
+    auto dotidx = export_model_path.rfind('.');
+    if (dotidx == std::string::npos)
+    {
+      std::cerr << "Error during nnfw_session::codegen : Invalid compiled model path. Please use a "
+                   "path that includes the extension."
+                << std::endl;
+      return NNFW_STATUS_ERROR;
+    }
+
+    std::string model_type = export_model_path.substr(dotidx + 1); // + 1 to exclude dot
+
+    // Replace model
+    // TODO Support buffer replace, not file reload
+    return loadModelFile(export_model_path, model_type);
+  }
+  catch (const std::exception &e)
+  {
+    std::cerr << "Error during nnfw_session::compile : " << e.what() << std::endl;
+    return NNFW_STATUS_ERROR;
+  }
+}
+
+NNFW_STATUS nnfw_session::set_prepare_config(const NNFW_PREPARE_CONFIG key, const char *)
+{
+  if (!isStateModelLoaded())
+  {
+    std::cerr << "Error during nnfw_session::set_prepare_config : Invalid state" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  switch (key)
+  {
+    case NNFW_PREPARE_CONFIG_PROFILE:
+      _coptions->he_profiling_mode = true;
+      break;
+    default:
+      return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::reset_prepare_config()
+{
+  if (!isStateModelLoaded())
+  {
+    std::cerr << "Error during nnfw_session::reset_prepare_config : Invalid state" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  _coptions->he_profiling_mode = false;
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::set_execute_config(const NNFW_RUN_CONFIG key, const char *)
+{
+  if (!isStatePreparedOrFinishedRun())
+  {
+    std::cerr << "Error during nnfw_session::set_execution_config : Invalid state" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  switch (key)
+  {
+    case NNFW_RUN_CONFIG_DUMP_MINMAX:
+      if (_coptions->workspace_dir.empty())
+        return NNFW_STATUS_ERROR;
+      _execution->executionOptions().dump_minmax = true;
+      break;
+    case NNFW_RUN_CONFIG_TRACE:
+      if (_coptions->workspace_dir.empty())
+        return NNFW_STATUS_ERROR;
+      _execution->executionOptions().trace = true;
+      break;
+    case NNFW_RUN_CONFIG_PROFILE:
+      _execution->executionOptions().profile = true;
+      break;
+    default:
+      return NNFW_STATUS_ERROR;
+  }
+
+  return NNFW_STATUS_NO_ERROR;
+}
+
+NNFW_STATUS nnfw_session::reset_execute_config()
+{
+  if (!isStatePreparedOrFinishedRun())
+  {
+    std::cerr << "Error during nnfw_session::set_execution_config : Invalid state" << std::endl;
+    return NNFW_STATUS_INVALID_STATE;
+  }
+
+  _execution->executionOptions().dump_minmax = false;
+  _execution->executionOptions().trace = false;
+  _execution->executionOptions().profile = false;
+
+  return NNFW_STATUS_NO_ERROR;
+}
diff --git a/runtime/onert/api/nnfw/src/nnfw_api_internal.h b/runtime/onert/api/nnfw/src/nnfw_api_internal.h
new file mode 100644 (file)
index 0000000..14c2435
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __API_NNFW_API_INTERNAL_H__
+#define __API_NNFW_API_INTERNAL_H__
+
+#include "nnfw.h"
+#include "nnfw_experimental.h"
+
+#include <util/TracingCtx.h>
+
+#include <string>
+#include <memory>
+#include <thread>
+#include <vector>
+
+namespace onert
+{
+namespace api
+{
+class CustomKernelRegistry;
+} // namespace api
+namespace exec
+{
+class Execution;
+struct ExecutionOptions;
+} // namespace exec
+namespace ir
+{
+struct IGraph;
+class Model;
+class NNPkg;
+namespace train
+{
+class TrainingInfo;
+}
+} // namespace ir
+namespace compiler
+{
+struct CompilerArtifact;
+struct CompilerOptions;
+} // namespace compiler
+namespace odc
+{
+class QuantizeManager;
+class CodegenManager;
+} // namespace odc
+} // namespace onert
+
+struct nnfw_session
+{
+private:
+  /**
+   * @brief Enum class to express the session's state
+   *
+   * State transition diagram:
+   *
+   *           +--------------+
+   *           | INITIALIZED  |
+   *           +--------------+
+   *             |
+   *             | load_model
+   *             v
+   *           +--------------+
+   *           | MODEL_LOADED |
+   *           +--------------+
+   *             |
+   *             | prepare
+   *             v
+   *           +--------------+
+   *           |   PREPARED   | --------+
+   *           +--------------+         |
+   *             |                      |
+   *             | run                  |
+   *             v                      |
+   *           +--------------+  run    |
+   *           |              | -----+  |
+   *   +-----> | FINISHED_RUN |      |  | run_async
+   *   |       |              | <----+  |
+   *   |       +--------------+         |
+   *   |         |                      |
+   *   | await   | run_async            |
+   *   |         v                      |
+   *   |       +--------------+         |
+   *   +------ |   RUNNING    | <-------+
+   *           +--------------+
+   */
+  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
+    PREPARED_TRAINING, //< Prepared for training
+    FINISHED_TRAINING  //< Trained at least once
+  };
+
+public:
+  /**
+   * @brief Factory method. It creates and initialize nnfw_session
+   *
+   * @note  Use factory instead of constructor to get status
+   */
+  static NNFW_STATUS create(nnfw_session **session);
+
+private:
+  nnfw_session();
+
+public:
+  ~nnfw_session();
+  NNFW_STATUS load_model_from_nnpackage(const char *package_file_path);
+  NNFW_STATUS prepare();
+  NNFW_STATUS run();
+
+  NNFW_STATUS run_async();
+  NNFW_STATUS await();
+
+  NNFW_STATUS set_input(uint32_t index, NNFW_TYPE type, const void *buffer, size_t length);
+  NNFW_STATUS set_output(uint32_t index, NNFW_TYPE type, void *buffer, size_t length);
+
+  NNFW_STATUS input_size(uint32_t *number);
+  NNFW_STATUS output_size(uint32_t *number);
+
+  NNFW_STATUS set_input_layout(uint32_t index, NNFW_LAYOUT layout);
+  NNFW_STATUS set_output_layout(uint32_t index, NNFW_LAYOUT layout);
+
+  NNFW_STATUS set_input_tensorinfo(uint32_t index, const nnfw_tensorinfo *ti);
+
+  NNFW_STATUS input_tensorinfo(uint32_t index, nnfw_tensorinfo *ti);
+  NNFW_STATUS output_tensorinfo(uint32_t index, nnfw_tensorinfo *ti);
+
+  NNFW_STATUS set_available_backends(const char *backends);
+
+  NNFW_STATUS set_workspace(const char *dir);
+
+  static NNFW_STATUS deprecated(const char *msg);
+
+  //
+  // Internal-only API
+  //
+
+  NNFW_STATUS set_config(const char *key, const char *value);
+  NNFW_STATUS get_config(const char *key, char *value, size_t value_size);
+  NNFW_STATUS load_circle_from_buffer(uint8_t *buffer, size_t size);
+  NNFW_STATUS load_model_from_modelfile(const char *file_path);
+
+  //
+  // Experimental API
+  //
+  NNFW_STATUS register_custom_operation(const std::string &id, nnfw_custom_eval eval_func);
+  NNFW_STATUS input_tensorindex(const char *tensorname, uint32_t *index);
+  NNFW_STATUS output_tensorindex(const char *tensorname, uint32_t *index);
+  /**
+   * @brief   Set backends with string-encoded mapping from operation index to backend type
+   *          (cpu, acl_cl)
+   */
+  NNFW_STATUS set_backends_per_operation(const char *backend_settings);
+
+  NNFW_STATUS train_get_traininfo(nnfw_train_info *info);
+  NNFW_STATUS train_set_traininfo(const nnfw_train_info *info);
+  NNFW_STATUS train_prepare();
+  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_set_output(uint32_t index, NNFW_TYPE type, void *buffer, size_t length);
+  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);
+  NNFW_STATUS train_export_circleplus(const char *path);
+
+  NNFW_STATUS set_quantization_type(NNFW_QUANTIZE_TYPE qtype);
+  NNFW_STATUS set_quantized_model_path(const char *path);
+  NNFW_STATUS quantize();
+
+  NNFW_STATUS set_codegen_model_path(const char *path);
+  NNFW_STATUS codegen(const char *target, NNFW_CODEGEN_PREF pref);
+
+  NNFW_STATUS set_prepare_config(const NNFW_PREPARE_CONFIG key, const char *value);
+  NNFW_STATUS reset_prepare_config();
+  NNFW_STATUS set_execute_config(const NNFW_RUN_CONFIG key, const char *value);
+  NNFW_STATUS reset_execute_config();
+
+private:
+  const onert::ir::IGraph *primary_subgraph();
+  uint32_t getInputSize();
+  uint32_t getOutputSize();
+  NNFW_STATUS loadModelFile(const std::string &model_file_path, const std::string &model_type);
+
+  bool isStateInitialized();
+  bool isStateModelLoaded();
+  bool isStatePrepared();
+  bool isStateRunning();
+  bool isStateFinishedRun();
+  bool isStatePreparedOrFinishedRun();
+  bool isStatePreparedTraining();
+  bool isStateFinishedTraining();
+  bool isStatePreparedOrFinishedTraining();
+
+private:
+  State _state{State::INITIALIZED};
+  std::shared_ptr<onert::ir::NNPkg> _nnpkg;
+  std::unique_ptr<onert::compiler::CompilerOptions> _coptions;
+  std::shared_ptr<onert::compiler::CompilerArtifact> _compiler_artifact;
+  std::unique_ptr<onert::exec::Execution> _execution;
+  std::shared_ptr<onert::api::CustomKernelRegistry> _kernel_registry;
+  std::vector<std::thread> _threads;
+  std::unique_ptr<onert::ir::train::TrainingInfo> _train_info;
+  std::unique_ptr<onert::odc::QuantizeManager> _quant_manager;
+  std::unique_ptr<onert::odc::CodegenManager> _codegen_manager;
+  // Remember path to loaded original model
+  // It may be used for on-device compiler / on-device training.
+  //
+  // If necessary, we may replace _model_path to _model_origin like:
+  //
+  //   union _model_origin {
+  //     const char *path;
+  //     const uint8 *buf;
+  //   }
+  std::string _model_path;
+};
+
+#endif // __API_NNFW_API_INTERNAL_H__
diff --git a/runtime/onert/api/python/CMakeLists.txt b/runtime/onert/api/python/CMakeLists.txt
new file mode 100644 (file)
index 0000000..50e2a3a
--- /dev/null
@@ -0,0 +1,35 @@
+if(NOT BUILD_PYTHON_BINDING)
+  return()
+endif(NOT BUILD_PYTHON_BINDING)
+
+# CMakeLists.txt
+
+# refer to https://github.com/Samsung/ONE/issues/11368
+
+# Tell pybind11 where the target python installation is
+#
+# FindPythonLibs is deprecated since 3.12, and recommand to use FindPython.
+# But on cross compile, FindPython is not working for target environment
+# For workaround, use PythonLibs
+find_package(PythonLibs REQUIRED)
+set(PYTHON_MODULE_PREFIX "lib" CACHE INTERNAL "Cross python lib prefix")
+set(PYTHON_MODULE_EXTENSION ".so" CACHE INTERNAL "Cross python lib extension")
+
+# Disable pybind11 python search mechanism
+set(PYTHONLIBS_FOUND TRUE CACHE INTERNAL "")
+
+# Install pybind11
+nnfw_find_package(Pybind11 REQUIRED)
+if(NOT Pybind11_FOUND)
+  message(STATUS "Build onert/python: FAILED (Pybind11 is missing)")
+  return()
+endif()
+
+# Add the Python module
+file(GLOB_RECURSE NNFW_API_PYBIND_SOURCES "src/*.cc")
+pybind11_add_module(nnfw_api_pybind ${NNFW_API_PYBIND_SOURCES})
+target_include_directories(nnfw_api_pybind PRIVATE include)
+target_link_libraries(nnfw_api_pybind PRIVATE nnfw-dev)
+
+# Install the Python module
+install(TARGETS nnfw_api_pybind DESTINATION lib)
diff --git a/runtime/onert/api/python/include/nnfw_api_wrapper.h b/runtime/onert/api/python/include/nnfw_api_wrapper.h
new file mode 100644 (file)
index 0000000..bca242e
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <pybind11/stl.h>
+#include <pybind11/numpy.h>
+
+namespace py = pybind11;
+
+/**
+ *  @brief  tensor info describes the type and shape of tensors
+ *
+ * This structure is used to describe input and output tensors.
+ * Application can get input and output tensor type and shape described in model by using
+ * {@link input_tensorinfo} and {@link output_tensorinfo}
+ *
+ * Maximum rank is 6 (NNFW_MAX_RANK).
+ * And tensor's dimension value is filled in 'dims' field from index 0.
+ * For example, if tensor's rank is 4,
+ * application can get dimension value from dims[0], dims[1], dims[2], and dims[3]
+ */
+struct tensorinfo
+{
+  /** The data type */
+  const char *dtype;
+  /** The number of dimensions (rank) */
+  int32_t rank;
+  /**
+   * The dimension of tensor.
+   * Maximum rank is 6 (NNFW_MAX_RANK).
+   */
+  int32_t dims[NNFW_MAX_RANK];
+};
+
+/**
+ * @brief     Handle errors with NNFW_STATUS in API functions.
+ *
+ * This only handles NNFW_STATUS errors.
+ *
+ * @param[in] status The status returned by API functions
+ */
+void ensure_status(NNFW_STATUS status);
+
+/**
+ * Convert the layout with string to NNFW_LAYOUT
+ *
+ * @param[in] layout layout to be converted
+ * @return proper layout if exists
+ */
+NNFW_LAYOUT getLayout(const char *layout = "");
+
+/**
+ * Convert the type with string to NNFW_TYPE
+ *
+ * @param[in] type type to be converted
+ * @return proper type if exists
+ */
+NNFW_TYPE getType(const char *type = "");
+
+/**
+ * Convert the type with NNFW_TYPE to string
+ *
+ * @param[in] type type to be converted
+ * @return proper type
+ */
+const char *getStringType(NNFW_TYPE type);
+
+/**
+ * @brief     Get the total number of elements in nnfw_tensorinfo->dims.
+ *
+ * This function is called to set the size of the input, output array.
+ *
+ * @param[in] tensor_info Tensor info (shape, type, etc)
+ * @return total number of elements
+ */
+uint64_t num_elems(const nnfw_tensorinfo *tensor_info);
+
+/**
+ * @brief     Get nnfw_tensorinfo->dims.
+ *
+ * This function is called to get dimension array of tensorinfo.
+ *
+ * @param[in] tensor_info Tensor info (shape, type, etc)
+ * @return python list of dims
+ */
+py::list get_dims(const tensorinfo &tensor_info);
+
+/**
+ * @brief     Set nnfw_tensorinfo->dims.
+ *
+ * This function is called to set dimension array of tensorinfo.
+ *
+ * @param[in] tensor_info Tensor info (shape, type, etc)
+ * @param[in] array       array to set dimension
+ */
+void set_dims(tensorinfo &tensor_info, const py::list &array);
+
+class NNFW_SESSION
+{
+private:
+  nnfw_session *session;
+
+public:
+  NNFW_SESSION(const char *package_file_path, const char *backends);
+  NNFW_SESSION(const char *package_file_path, const char *op, const char *backend);
+  ~NNFW_SESSION();
+
+  void close_session();
+  void set_input_tensorinfo(uint32_t index, const tensorinfo *tensor_info);
+  void run();
+  void run_async();
+  void await();
+  /**
+   * @brief   process input array according to data type of numpy array sent by Python
+   *          (int, float, uint8_t, bool, int64_t, int8_t, int16_t)
+   */
+  template <typename T> void set_input(uint32_t index, py::array_t<T> &buffer)
+  {
+    nnfw_tensorinfo tensor_info;
+    nnfw_input_tensorinfo(this->session, index, &tensor_info);
+    NNFW_TYPE type = tensor_info.dtype;
+    uint32_t input_elements = num_elems(&tensor_info);
+    size_t length = sizeof(T) * input_elements;
+
+    ensure_status(nnfw_set_input(session, index, type, buffer.request().ptr, length));
+  }
+  /**
+   * @brief   process output array according to data type of numpy array sent by Python
+   *          (int, float, uint8_t, bool, int64_t, int8_t, int16_t)
+   */
+  template <typename T> void set_output(uint32_t index, py::array_t<T> &buffer)
+  {
+    nnfw_tensorinfo tensor_info;
+    nnfw_output_tensorinfo(this->session, index, &tensor_info);
+    NNFW_TYPE type = tensor_info.dtype;
+    uint32_t output_elements = num_elems(&tensor_info);
+    size_t length = sizeof(T) * output_elements;
+
+    ensure_status(nnfw_set_output(session, index, type, buffer.request().ptr, length));
+  }
+  uint32_t input_size();
+  uint32_t output_size();
+  // process the input layout by receiving a string from Python instead of NNFW_LAYOUT
+  void set_input_layout(uint32_t index, const char *layout);
+  // process the output layout by receiving a string from Python instead of NNFW_LAYOUT
+  void set_output_layout(uint32_t index, const char *layout);
+  tensorinfo input_tensorinfo(uint32_t index);
+  tensorinfo output_tensorinfo(uint32_t index);
+};
diff --git a/runtime/onert/api/python/package/__init__.py b/runtime/onert/api/python/package/__init__.py
new file mode 100644 (file)
index 0000000..cd1eacc
--- /dev/null
@@ -0,0 +1,2 @@
+__all__ = ['libnnfw_api_pybind']
+from . import libnnfw_api_pybind
diff --git a/runtime/onert/api/python/package/libnnfw_api_pybind.py b/runtime/onert/api/python/package/libnnfw_api_pybind.py
new file mode 100644 (file)
index 0000000..ea5fa90
--- /dev/null
@@ -0,0 +1,78 @@
+import numpy as np
+import os
+import shutil
+
+from .onert import libnnfw_api_pybind
+
+
+def num_elems(tensor_info):
+    """Get the total number of elements in nnfw_tensorinfo.dims."""
+    n = 1
+    for x in range(tensor_info.rank):
+        n *= tensor_info.dims[x]
+    return n
+
+
+class nnfw_session_wrapper(libnnfw_api_pybind.nnfw_session):
+    """Class inherited nnfw_session for easily processing input/output"""
+
+    def __init__(self, nnpackage_path, backends="cpu", operations=""):
+        if operations:
+            super().__init__(nnpackage_path, operations, backends)
+        else:
+            super().__init__(nnpackage_path, backends)
+
+        self.inputs = []
+        self.outputs = []
+        self.set_outputs(self.output_size())
+
+    def set_inputs(self, size, inputs_array=[]):
+        """Set inputs for each index"""
+        for i in range(size):
+            input_tensorinfo = self.input_tensorinfo(i)
+            ti_dtype = input_tensorinfo.dtype
+
+            if len(inputs_array) > i:
+                input_array = inputs_array[i]
+            else:
+                print(
+                    f"model's input size is {size} but given inputs_array size is {len(inputs_array)}.\n{i}-th index input is replaced by an array filled with 0."
+                )
+                input_array = [0.] * num_elems(input_tensorinfo)
+
+            input_array = np.array(input_array, dtype=ti_dtype)
+            self.set_input(i, input_array)
+
+            self.inputs.append(input_array)
+
+    def set_outputs(self, size):
+        """Set outputs for each index"""
+        for i in range(size):
+            output_tensorinfo = self.output_tensorinfo(i)
+            ti_dtype = output_tensorinfo.dtype
+
+            output_array = [0.] * num_elems(output_tensorinfo)
+            output_array = np.array(output_array, dtype=ti_dtype)
+            self.set_output(i, output_array)
+
+            self.outputs.append(output_array)
+
+    def inference(self):
+        """Inference model and get outputs"""
+        self.run()
+
+        return self.outputs
+
+
+def nnfw_session(nnpackage_path, backends="cpu", operations=""):
+    if operations == "":
+        return nnfw_session_wrapper(nnpackage_path, backends)
+    elif operations:
+        return nnfw_session_wrapper(nnpackage_path, backends, operations)
+    else:
+        print("Syntax Error")
+        return
+
+
+def tensorinfo():
+    return libnnfw_api_pybind.nnfw_tensorinfo()
diff --git a/runtime/onert/api/python/src/nnfw_api_wrapper.cc b/runtime/onert/api/python/src/nnfw_api_wrapper.cc
new file mode 100644 (file)
index 0000000..d9f94a4
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_api_wrapper.h"
+
+#include <iostream>
+
+void ensure_status(NNFW_STATUS status)
+{
+  switch (status)
+  {
+    case NNFW_STATUS::NNFW_STATUS_NO_ERROR:
+      break;
+    case NNFW_STATUS::NNFW_STATUS_ERROR:
+      std::cout << "[ERROR]\tNNFW_STATUS_ERROR\n";
+      exit(1);
+    case NNFW_STATUS::NNFW_STATUS_UNEXPECTED_NULL:
+      std::cout << "[ERROR]\tNNFW_STATUS_UNEXPECTED_NULL\n";
+      exit(1);
+    case NNFW_STATUS::NNFW_STATUS_INVALID_STATE:
+      std::cout << "[ERROR]\tNNFW_STATUS_INVALID_STATE\n";
+      exit(1);
+    case NNFW_STATUS::NNFW_STATUS_OUT_OF_MEMORY:
+      std::cout << "[ERROR]\tNNFW_STATUS_OUT_OF_MEMORY\n";
+      exit(1);
+    case NNFW_STATUS::NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE:
+      std::cout << "[ERROR]\tNNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE\n";
+      exit(1);
+  }
+}
+
+NNFW_LAYOUT getLayout(const char *layout)
+{
+  if (!strcmp(layout, "NCHW"))
+  {
+    return NNFW_LAYOUT::NNFW_LAYOUT_CHANNELS_FIRST;
+  }
+  else if (!strcmp(layout, "NHWC"))
+  {
+    return NNFW_LAYOUT::NNFW_LAYOUT_CHANNELS_LAST;
+  }
+  else if (!strcmp(layout, "NONE"))
+  {
+    return NNFW_LAYOUT::NNFW_LAYOUT_NONE;
+  }
+  else
+  {
+    std::cout << "[ERROR]\tLAYOUT_TYPE\n";
+    exit(1);
+  }
+}
+
+NNFW_TYPE getType(const char *type)
+{
+  if (!strcmp(type, "float32"))
+  {
+    return NNFW_TYPE::NNFW_TYPE_TENSOR_FLOAT32;
+  }
+  else if (!strcmp(type, "int32"))
+  {
+    return NNFW_TYPE::NNFW_TYPE_TENSOR_INT32;
+  }
+  else if (!strcmp(type, "uint8"))
+  {
+    return NNFW_TYPE::NNFW_TYPE_TENSOR_UINT8;
+    // return NNFW_TYPE::NNFW_TYPE_TENSOR_QUANT8_ASYMM;
+  }
+  else if (!strcmp(type, "bool"))
+  {
+    return NNFW_TYPE::NNFW_TYPE_TENSOR_BOOL;
+  }
+  else if (!strcmp(type, "int64"))
+  {
+    return NNFW_TYPE::NNFW_TYPE_TENSOR_INT64;
+  }
+  else if (!strcmp(type, "int8"))
+  {
+    return NNFW_TYPE::NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED;
+  }
+  else if (!strcmp(type, "int16"))
+  {
+    return NNFW_TYPE::NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED;
+  }
+  else
+  {
+    std::cout << "[ERROR] String to NNFW_TYPE Failure\n";
+    exit(1);
+  }
+}
+
+const char *getStringType(NNFW_TYPE type)
+{
+  switch (type)
+  {
+    case NNFW_TYPE::NNFW_TYPE_TENSOR_FLOAT32:
+      return "float32";
+    case NNFW_TYPE::NNFW_TYPE_TENSOR_INT32:
+      return "int32";
+    case NNFW_TYPE::NNFW_TYPE_TENSOR_QUANT8_ASYMM:
+    case NNFW_TYPE::NNFW_TYPE_TENSOR_UINT8:
+      return "uint8";
+    case NNFW_TYPE::NNFW_TYPE_TENSOR_BOOL:
+      return "bool";
+    case NNFW_TYPE::NNFW_TYPE_TENSOR_INT64:
+      return "int64";
+    case NNFW_TYPE::NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED:
+      return "int8";
+    case NNFW_TYPE::NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED:
+      return "int16";
+    default:
+      std::cout << "[ERROR] NNFW_TYPE to String Failure\n";
+      exit(1);
+  }
+}
+
+uint64_t num_elems(const nnfw_tensorinfo *tensor_info)
+{
+  uint64_t n = 1;
+  for (uint32_t i = 0; i < tensor_info->rank; ++i)
+  {
+    n *= tensor_info->dims[i];
+  }
+  return n;
+}
+
+py::list get_dims(const tensorinfo &tensor_info)
+{
+  py::list dims_list;
+  for (int32_t i = 0; i < tensor_info.rank; ++i)
+  {
+    dims_list.append(tensor_info.dims[i]);
+  }
+  return dims_list;
+}
+
+void set_dims(tensorinfo &tensor_info, const py::list &array)
+{
+  tensor_info.rank = py::len(array);
+  for (int32_t i = 0; i < tensor_info.rank; ++i)
+  {
+    tensor_info.dims[i] = py::cast<int32_t>(array[i]);
+  }
+}
+
+NNFW_SESSION::NNFW_SESSION(const char *package_file_path, const char *backends)
+{
+  this->session = nullptr;
+  ensure_status(nnfw_create_session(&(this->session)));
+  ensure_status(nnfw_load_model_from_file(this->session, package_file_path));
+  ensure_status(nnfw_set_available_backends(this->session, backends));
+  ensure_status(nnfw_prepare(this->session));
+}
+NNFW_SESSION::~NNFW_SESSION()
+{
+  if (session)
+  {
+    close_session();
+  }
+}
+
+void NNFW_SESSION::close_session()
+{
+  ensure_status(nnfw_close_session(this->session));
+  this->session = nullptr;
+}
+void NNFW_SESSION::set_input_tensorinfo(uint32_t index, const tensorinfo *tensor_info)
+{
+  nnfw_tensorinfo ti;
+  ti.dtype = getType(tensor_info->dtype);
+  ti.rank = tensor_info->rank;
+  for (int i = 0; i < NNFW_MAX_RANK; i++)
+  {
+    ti.dims[i] = tensor_info->dims[i];
+  }
+  ensure_status(nnfw_set_input_tensorinfo(session, index, &ti));
+}
+void NNFW_SESSION::run() { ensure_status(nnfw_run(session)); }
+void NNFW_SESSION::run_async() { ensure_status(nnfw_run_async(session)); }
+void NNFW_SESSION::await() { ensure_status(nnfw_await(session)); }
+uint32_t NNFW_SESSION::input_size()
+{
+  uint32_t number;
+  NNFW_STATUS status = nnfw_input_size(session, &number);
+  ensure_status(status);
+  return number;
+}
+uint32_t NNFW_SESSION::output_size()
+{
+  uint32_t number;
+  NNFW_STATUS status = nnfw_output_size(session, &number);
+  ensure_status(status);
+  return number;
+}
+void NNFW_SESSION::set_input_layout(uint32_t index, const char *layout)
+{
+  NNFW_LAYOUT nnfw_layout = getLayout(layout);
+  ensure_status(nnfw_set_input_layout(session, index, nnfw_layout));
+}
+void NNFW_SESSION::set_output_layout(uint32_t index, const char *layout)
+{
+  NNFW_LAYOUT nnfw_layout = getLayout(layout);
+  ensure_status(nnfw_set_output_layout(session, index, nnfw_layout));
+}
+tensorinfo NNFW_SESSION::input_tensorinfo(uint32_t index)
+{
+  nnfw_tensorinfo tensor_info = nnfw_tensorinfo();
+  ensure_status(nnfw_input_tensorinfo(session, index, &tensor_info));
+  tensorinfo ti;
+  ti.dtype = getStringType(tensor_info.dtype);
+  ti.rank = tensor_info.rank;
+  for (int i = 0; i < NNFW_MAX_RANK; i++)
+  {
+    ti.dims[i] = tensor_info.dims[i];
+  }
+  return ti;
+}
+tensorinfo NNFW_SESSION::output_tensorinfo(uint32_t index)
+{
+  nnfw_tensorinfo tensor_info = nnfw_tensorinfo();
+  ensure_status(nnfw_output_tensorinfo(session, index, &tensor_info));
+  tensorinfo ti;
+  ti.dtype = getStringType(tensor_info.dtype);
+  ti.rank = tensor_info.rank;
+  for (int i = 0; i < NNFW_MAX_RANK; i++)
+  {
+    ti.dims[i] = tensor_info.dims[i];
+  }
+  return ti;
+}
diff --git a/runtime/onert/api/python/src/nnfw_api_wrapper_pybind.cc b/runtime/onert/api/python/src/nnfw_api_wrapper_pybind.cc
new file mode 100644 (file)
index 0000000..9c63405
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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_api_wrapper.h"
+
+namespace py = pybind11;
+
+PYBIND11_MODULE(libnnfw_api_pybind, m)
+{
+  m.doc() = "nnfw python plugin";
+
+  py::class_<tensorinfo>(m, "tensorinfo", "tensorinfo describes the type and shape of tensors")
+    .def(py::init<>(), "The constructor of tensorinfo")
+    .def_readwrite("dtype", &tensorinfo::dtype, "The data type")
+    .def_readwrite("rank", &tensorinfo::rank, "The number of dimensions (rank)")
+    .def_property(
+      "dims", [](const tensorinfo &ti) { return get_dims(ti); },
+      [](tensorinfo &ti, const py::list &dims_list) { set_dims(ti, dims_list); },
+      "The dimension of tensor. Maximum rank is 6 (NNFW_MAX_RANK).");
+
+  py::class_<NNFW_SESSION>(m, "nnfw_session")
+    .def(
+      py::init<const char *, const char *>(), py::arg("package_file_path"), py::arg("backends"),
+      "Create a new session instance, load model from nnpackage file or directory, "
+      "set available backends and prepare session to be ready for inference\n"
+      "Parameters:\n"
+      "\tpackage_file_path (str): Path to the nnpackage file or unzipped directory to be loaded\n"
+      "\tbackends (str): Available backends on which nnfw uses\n"
+      "\t\tMultiple backends can be set and they must be separated by a semicolon "
+      "(ex: \"acl_cl;cpu\")\n"
+      "\t\tAmong the multiple backends, the 1st element is used as the default backend.")
+    .def(
+      py::init<const char *, const char *, const char *>(), py::arg("package_file_path"),
+      py::arg("op"), py::arg("backends"),
+      "Create a new session instance, load model from nnpackage file or directory, "
+      "set the operation's backend and prepare session to be ready for inference\n"
+      "Parameters:\n"
+      "\tpackage_file_path (str): Path to the nnpackage file or unzipped directory to be loaded\n"
+      "\top (str): operation to be set\n"
+      "\tbackends (str): Bakcend on which operation run")
+    .def("set_input_tensorinfo", &NNFW_SESSION::set_input_tensorinfo, py::arg("index"),
+         py::arg("tensor_info"),
+         "Set input model's tensor info for resizing.\n"
+         "Parameters:\n"
+         "\tindex (int): Index of input to be set (0-indexed)\n"
+         "\ttensor_info (tensorinfo): Tensor info to be set")
+    .def("run", &NNFW_SESSION::run, "Run inference")
+    .def("run_async", &NNFW_SESSION::run_async, "Run inference asynchronously")
+    .def("await", &NNFW_SESSION::await, "Wait for asynchronous run to finish")
+    .def(
+      "set_input",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<float> &buffer) {
+        session.set_input<float>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set input buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of input to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for input")
+    .def(
+      "set_input",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<int> &buffer) {
+        session.set_input<int>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set input buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of input to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for input")
+    .def(
+      "set_input",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<uint8_t> &buffer) {
+        session.set_input<uint8_t>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set input buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of input to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for input")
+    .def(
+      "set_input",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<bool> &buffer) {
+        session.set_input<bool>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set input buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of input to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for input")
+    .def(
+      "set_input",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<int64_t> &buffer) {
+        session.set_input<int64_t>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set input buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of input to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for input")
+    .def(
+      "set_input",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<int8_t> &buffer) {
+        session.set_input<int8_t>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set input buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of input to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for input")
+    .def(
+      "set_input",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<int16_t> &buffer) {
+        session.set_input<int16_t>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set input buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of input to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for input")
+    .def(
+      "set_output",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<float> &buffer) {
+        session.set_output<float>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set output buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of output to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for output")
+    .def(
+      "set_output",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<int> &buffer) {
+        session.set_output<int>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set output buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of output to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for output")
+    .def(
+      "set_output",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<uint8_t> &buffer) {
+        session.set_output<uint8_t>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set output buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of output to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for output")
+    .def(
+      "set_output",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<bool> &buffer) {
+        session.set_output<bool>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set output buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of output to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for output")
+    .def(
+      "set_output",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<int64_t> &buffer) {
+        session.set_output<int64_t>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set output buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of output to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for output")
+    .def(
+      "set_output",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<int8_t> &buffer) {
+        session.set_output<int8_t>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set output buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of output to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for output")
+    .def(
+      "set_output",
+      [](NNFW_SESSION &session, uint32_t index, py::array_t<int16_t> &buffer) {
+        session.set_output<int16_t>(index, buffer);
+      },
+      py::arg("index"), py::arg("buffer"),
+      "Set output buffer\n"
+      "Parameters:\n"
+      "\tindex (int): Index of output to be set (0-indexed)\n"
+      "\tbuffer (numpy): Raw buffer for output")
+    .def("input_size", &NNFW_SESSION::input_size,
+         "Get the number of inputs defined in loaded model\n"
+         "Returns:\n"
+         "\tint: The number of inputs")
+    .def("output_size", &NNFW_SESSION::output_size,
+         "Get the number of outputs defined in loaded model\n"
+         "Returns:\n"
+         "\tint: The number of outputs")
+    .def("set_input_layout", &NNFW_SESSION::set_input_layout, py::arg("index"),
+         py::arg("layout") = "NONE",
+         "Set the layout of an input\n"
+         "Parameters:\n"
+         "\tindex (int): Index of input to be set (0-indexed)\n"
+         "\tlayout (str): Layout to set to target input")
+    .def("set_output_layout", &NNFW_SESSION::set_output_layout, py::arg("index"),
+         py::arg("layout") = "NONE",
+         "Set the layout of an output\n"
+         "Parameters:\n"
+         "\tindex (int): Index of output to be set (0-indexed)\n"
+         "\tlayout (str): Layout to set to target output")
+    .def("input_tensorinfo", &NNFW_SESSION::input_tensorinfo, py::arg("index"),
+         "Get i-th input tensor info\n"
+         "Parameters:\n"
+         "\tindex (int): Index of input\n"
+         "Returns:\n"
+         "\ttensorinfo: Tensor info (shape, type, etc)")
+    .def("output_tensorinfo", &NNFW_SESSION::output_tensorinfo, py::arg("index"),
+         "Get i-th output tensor info\n"
+         "Parameters:\n"
+         "\tindex (int): Index of output\n"
+         "Returns:\n"
+         "\ttensorinfo: Tensor info (shape, type, etc)");
+}
diff --git a/runtime/onert/api/src/OpMap.lst b/runtime/onert/api/src/OpMap.lst
deleted file mode 100644 (file)
index fa8afae..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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 MAP_MACRO
-#error  Define MAP_MACRO before including this file
-#endif
-
-// Table: circle operation ID order
-//        circle operation              | onert internal operation
-MAP_MACRO(ADD                           , Add)
-MAP_MACRO(AVERAGE_POOL_2D               , AvgPool2D)
-MAP_MACRO(CONCATENATION                 , Concat)
-MAP_MACRO(CONV_2D                       , Conv2D)
-MAP_MACRO(DEPTHWISE_CONV_2D             , DepthwiseConv2D)
-// DEPTH_TO_SPACE
-MAP_MACRO(DEQUANTIZE                    , Dequantize)
-MAP_MACRO(EMBEDDING_LOOKUP              , EmbeddingLookup)
-MAP_MACRO(FLOOR                         , Floor)
-MAP_MACRO(FULLY_CONNECTED               , FullyConnected)
-MAP_MACRO(HASHTABLE_LOOKUP              , HashtableLookup)
-MAP_MACRO(L2_NORMALIZATION              , L2Normalization)
-MAP_MACRO(L2_POOL_2D                    , L2Pool2D)
-MAP_MACRO(LOCAL_RESPONSE_NORMALIZATION  , LocalResponseNormalization)
-MAP_MACRO(LOGISTIC                      , Logistic)
-// LSH_PROJECTION
-MAP_MACRO(LSTM                          , LSTM)
-MAP_MACRO(MAX_POOL_2D                   , MaxPool2D)
-MAP_MACRO(MUL                           , Mul)
-MAP_MACRO(RELU                          , ReLU)
-MAP_MACRO(RELU_N1_TO_1                  , ReLU1)
-MAP_MACRO(RELU6                         , ReLU6)
-MAP_MACRO(RESHAPE                       , Reshape)
-MAP_MACRO(RESIZE_BILINEAR               , ResizeBilinear)
-MAP_MACRO(RNN                           , RNN)
-MAP_MACRO(SOFTMAX                       , Softmax)
-MAP_MACRO(SPACE_TO_DEPTH                , SpaceToDepth)
-// SVDF
-MAP_MACRO(TANH                          , Tanh)
-// CONCAT_EMBEDDINGS
-// SKIP_GRAM
-// CALL
-MAP_MACRO(CUSTOM                        , Custom)
-// EMBEDDING_LOOKUP_SPARSE
-MAP_MACRO(PAD                           , Pad)
-// UNIDIRECTIONAL_SEQUENCE_RNN
-MAP_MACRO(GATHER                        , Gather)
-MAP_MACRO(BATCH_TO_SPACE_ND             , BatchToSpaceND)
-MAP_MACRO(SPACE_TO_BATCH_ND             , SpaceToBatchND)
-MAP_MACRO(TRANSPOSE                     , Transpose)
-MAP_MACRO(MEAN                          , Mean)
-MAP_MACRO(SUB                           , Sub)
-MAP_MACRO(DIV                           , Div)
-MAP_MACRO(SQUEEZE                       , Squeeze)
-// UNIDIRECTIONAL_SEQUENCE_LSTM
-MAP_MACRO(STRIDED_SLICE                 , StridedSlice)
-// BIDIRECTIONAL_SEQUENCE_RNN
-MAP_MACRO(EXP                           , Exp)
-MAP_MACRO(TOPK_V2                       , TopKV2)
-MAP_MACRO(SPLIT                         , Split)
-// LOG_SOFTMAX
-// DELEGATE
-// BIDIRECTIONAL_SEQUENCE_LSTM
-MAP_MACRO(CAST                          , Cast)
-MAP_MACRO(PRELU                         , PReLU)
-MAP_MACRO(MAXIMUM                       , Max)
-MAP_MACRO(ARG_MAX                       , ArgMax)
-MAP_MACRO(MINIMUM                       , Min)
-// LESS (Comparison) ?
-MAP_MACRO(NEG                           , Neg)
-// PADV2
-// GREATER (Comparison) ?
-// GREATER_EQUAL (Comparison) ?
-// LESS_EQUAL (Comparison) ?
-MAP_MACRO(SELECT                        , Select)
-MAP_MACRO(SLICE                         , Slice)
-MAP_MACRO(SIN                           , Sin)
-MAP_MACRO(TRANSPOSE_CONV                , TransposeConv)
-// SPARSE_TO_DENSE
-MAP_MACRO(TILE                          , Tile)
-MAP_MACRO(EXPAND_DIMS                   , ExpandDims)
-// EQUAL (Comparison) ?
-// NOT_EQUAL (Comparison) ?
-MAP_MACRO(LOG                           , Log)
-MAP_MACRO(SUM                           , ReduceSum)
-MAP_MACRO(SQRT                          , SQRT)
-MAP_MACRO(RSQRT                         , RSQRT)
-MAP_MACRO(SHAPE                         , Shape)
-MAP_MACRO(POW                           , Pow)
-// ARG_MIN
-// FAKE_QUANT
-MAP_MACRO(REDUCE_PROD                   , ReduceProd)
-MAP_MACRO(REDUCE_MAX                    , ReduceMax)
-MAP_MACRO(PACK                          , Pack)
-MAP_MACRO(LOGICAL_OR                    , LogicalOr)
-MAP_MACRO(ONE_HOT                       , OneHot)
-MAP_MACRO(LOGICAL_AND                   , LogicalAnd)
-MAP_MACRO(LOGICAL_NOT                   , LogicalNot)
-MAP_MACRO(UNPACK                        , Unpack)
-MAP_MACRO(REDUCE_MIN                    , ReduceMin)
-// FLOOR_DIV
-MAP_MACRO(REDUCE_ANY                    , ReduceAny)
-// SQUARE
-MAP_MACRO(ZEROS_LIKE                    , ZerosLike)
-MAP_MACRO(FILL                          , Fill)
-// FLOOR_MOD
-MAP_MACRO(RANGE                         , Range)
-// RESIZE_NEAREST_NEIGHBOR
-// LEAKY_RELU
-MAP_MACRO(SQUARED_DIFFERENCE            , SquaredDifference)
-// MIRROR_PAD
-MAP_MACRO(ABS                           , Abs)
-// SPLIT_V
-// UNIQUE
-// CEIL
-MAP_MACRO(REVERSE_V2                    , Reverse)
-// ADD_N
-// GATHER_ND
-MAP_MACRO(COS                           , Cos)
-// WHERE
-// RANK
-// ELU
-// REVERSE_SEQUENCE
-// MATRIX_DIAG
-// QUANTIZE
-// MATRIX_SET_DIAG
-MAP_MACRO(ROUND                         , Round)
-// HARD_SWISH
-MAP_MACRO(IF                            , If)
-MAP_MACRO(WHILE                         , While)
-// NON_MAX_SUPPRESSION_V4
-// NON_MAX_SUPPRESSION_V5
-// SCATTER_ND
-// SELECT_V2 (Select) ?
-// DENSIFY
-// SEGMENT_SUM
-MAP_MACRO(BATCH_MATMUL                  , BatchMatMul)
-MAP_MACRO(BCQ_GATHER                    , BCQGather)
-MAP_MACRO(BCQ_FULLY_CONNECTED           , BCQFullyConnected)
-MAP_MACRO(INSTANCE_NORM                 , InstanceNorm)
diff --git a/runtime/onert/api/src/nnfw_api.cc b/runtime/onert/api/src/nnfw_api.cc
deleted file mode 100644 (file)
index 185738a..0000000
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_api_internal.h"
-#include "nnfw_version.h"
-
-// Double-check enum value changes
-
-#define STATIC_ASSERT_ENUM_CHECK(ENUM, VAL) static_assert((ENUM) == (VAL), #ENUM " has changed")
-
-STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_FLOAT32, 0);
-STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_INT32, 1);
-STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_QUANT8_ASYMM, 2);
-STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_BOOL, 3);
-STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_UINT8, 4);
-STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_INT64, 5);
-STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED, 6);
-STATIC_ASSERT_ENUM_CHECK(NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED, 7);
-
-STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_NO_ERROR, 0);
-STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_ERROR, 1);
-STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_UNEXPECTED_NULL, 2);
-STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_INVALID_STATE, 3);
-STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_OUT_OF_MEMORY, 4);
-STATIC_ASSERT_ENUM_CHECK(NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE, 5);
-
-STATIC_ASSERT_ENUM_CHECK(NNFW_LAYOUT_NONE, 0);
-STATIC_ASSERT_ENUM_CHECK(NNFW_LAYOUT_CHANNELS_LAST, 1);
-STATIC_ASSERT_ENUM_CHECK(NNFW_LAYOUT_CHANNELS_FIRST, 2);
-
-STATIC_ASSERT_ENUM_CHECK(NNFW_INFO_ID_VERSION, 0);
-
-#undef STATIC_ASSERT_ENUM_CHECK
-
-#define NNFW_RETURN_ERROR_IF_NULL(p)      \
-  do                                      \
-  {                                       \
-    if ((p) == NULL)                      \
-      return NNFW_STATUS_UNEXPECTED_NULL; \
-  } while (0)
-
-/*
- * Create a new session instance
- *
- * @param session the session to be created
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_create_session(nnfw_session **session) { return nnfw_session::create(session); }
-
-/*
- * Close a session instance
- *
- * @param session the session to be closed
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_close_session(nnfw_session *session)
-{
-  delete session;
-  return NNFW_STATUS_NO_ERROR;
-}
-
-/*
- * Load model from nnpackage file or directory
- *
- * @param session nnfw_session loading the given nnpackage file/dir
- * @param package_file_path path to the nnpackage file or unzipped directory to be loaded
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_load_model_from_file(nnfw_session *session, const char *pacakge_file_path)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->load_model_from_nnpackage(pacakge_file_path);
-}
-
-/*
- * Prepare session to be ready for inference
- * This phase may finalize model compilation, scheduling, and additional settings.
- *
- * @param session the session to be prepared
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_prepare(nnfw_session *session)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->prepare();
-}
-
-/*
- * Run inference
- *
- * @param session the session to run inference
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_run(nnfw_session *session)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->run();
-}
-
-NNFW_STATUS nnfw_run_async(nnfw_session *session)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->run_async();
-}
-
-NNFW_STATUS nnfw_await(nnfw_session *session)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->await();
-}
-
-/*
- * Set input
- *
- * @param session session to the input is to be set
- * @param index index of input to be set (0-indexed)
- * @param type type of the input
- * @param buffer raw buffer for input
- * @param length size of bytes of input
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-
-NNFW_STATUS nnfw_set_input(nnfw_session *session, uint32_t index, NNFW_TYPE type,
-                           const void *buffer, size_t length)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->set_input(index, type, buffer, length);
-}
-
-/*
- * Set output
- *
- * @param session session from inference output is to be extracted
- * @param index index of output to be set (0-indexed)
- * @param type type of the output
- * @param buffer raw buffer for output
- * @param length size of bytes of output
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-
-NNFW_STATUS nnfw_set_output(nnfw_session *session, uint32_t index, NNFW_TYPE type, void *buffer,
-                            size_t length)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->set_output(index, type, buffer, length);
-}
-
-/*
- * Get the number of inputs
- *
- * @param[in] session session from input information is to be extracted
- * @param[out] number variable which the number of inputs is put into
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-
-NNFW_STATUS nnfw_input_size(nnfw_session *session, uint32_t *number)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->input_size(number);
-}
-
-/*
- * Get the number of outputs
- *
- * @param[in] session session from output information is to be extracted
- * @param[out] number variable which the number of outputs is put into
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_output_size(nnfw_session *session, uint32_t *number)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->output_size(number);
-}
-
-/*
- * Set the layout of an input
- * @note The input that does not call this has NNFW_LAYOUT_CHANNELS_LAST layout
- *
- * @param[in] session session from inference input is to be extracted
- * @param[in] index   index of input to be set (0-indexed)
- * @param[in] layout  layout to set to target input
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_set_input_layout(nnfw_session *session, uint32_t index, NNFW_LAYOUT layout)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->set_input_layout(index, layout);
-}
-
-/*
- * Set the layout of an output
- * @note The output that does not call this has NNFW_LAYOUT_CHANNELS_LAST layout
- *
- * @param[in] session session from inference output is to be extracted
- * @param[in] index   index of output to be set (0-indexed)
- * @param[in] layout  layout to set to target output
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_set_output_layout(nnfw_session *session, uint32_t index, NNFW_LAYOUT layout)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->set_output_layout(index, layout);
-}
-
-/*
- * Get i-th input tensor info
- *
- * @param[in] session session from input information is to be extracted
- * @param[in] index index of input
- * @param[out] tensor_info nnfw_tensor_info
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_input_tensorinfo(nnfw_session *session, uint32_t index,
-                                  nnfw_tensorinfo *tensor_info)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->input_tensorinfo(index, tensor_info);
-}
-
-/*
- * Get i-th output tensor info
- *
- * @param[in] session session from output information is to be extracted
- * @param[in] index index of output
- * @param[out] tensor_info nnfw_tensor_info
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_output_tensorinfo(nnfw_session *session, uint32_t index,
-                                   nnfw_tensorinfo *tensor_info)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->output_tensorinfo(index, tensor_info);
-}
-
-/*
- * Register custom operation
- * @param session session to register this operation
- * @param id operation id
- * @param info registration info ( eval function, etc. )
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_register_custom_op_info(nnfw_session *session, const char *id,
-                                         custom_kernel_registration_info *info)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->register_custom_operation(id, info->eval_function);
-}
-
-NNFW_STATUS nnfw_apply_tensorinfo(nnfw_session *session, uint32_t index,
-                                  nnfw_tensorinfo tensor_info)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->apply_tensorinfo(index, tensor_info);
-}
-
-NNFW_STATUS nnfw_set_input_tensorinfo(nnfw_session *session, uint32_t index,
-                                      const nnfw_tensorinfo *tensor_info)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->set_input_tensorinfo(index, tensor_info);
-}
-
-/*
- * Set available backends
- *
- * @param[in] session session to which a avilable backends are set
- * @param[in] backends available backends on which nnfw uses
- */
-NNFW_STATUS nnfw_set_available_backends(nnfw_session *session, const char *backends)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->set_available_backends(backends);
-}
-
-/*
- * Set the operation's backend
- *
- * @param[in] session session to be modified
- * @param[in] op operation to be set
- * @param[in] backend bakcend on which operation run
- *
- * @return NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_set_op_backend(nnfw_session *session, const char *op, const char *backend)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->set_op_backend(op, backend);
-}
-
-/*
- * Retrieve uint32 type of nnfw information for given information ID.
- *
- * @param[in] session session to be queried on
- * @param[in] information ID to be queried
- * @param[out] val uint32 value to be returned
- *
- * @return @c NNFW_STATUS_NO_ERROR if successful
- */
-NNFW_STATUS nnfw_query_info_u32(nnfw_session *session, NNFW_INFO_ID id, uint32_t *val)
-{
-  (void)session;
-  switch (id)
-  {
-    case NNFW_INFO_ID_VERSION:
-      if (val)
-      {
-        *val = NNFW_VERSION;
-        return NNFW_STATUS_NO_ERROR;
-      }
-      break;
-    default:
-      return NNFW_STATUS_ERROR;
-  }
-  // It should not be reached.
-  return NNFW_STATUS_ERROR;
-}
-
-NNFW_STATUS nnfw_load_circle_from_buffer(nnfw_session *session, uint8_t *buffer, size_t size)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->load_circle_from_buffer(buffer, size);
-}
-
-NNFW_STATUS nnfw_load_model_from_modelfile(nnfw_session *session, const char *file_path)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->load_model_from_modelfile(file_path);
-}
-
-NNFW_STATUS nnfw_input_tensorindex(nnfw_session *session, const char *tensorname, uint32_t *index)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->input_tensorindex(tensorname, index);
-}
-
-NNFW_STATUS nnfw_output_tensorindex(nnfw_session *session, const char *tensorname, uint32_t *index)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->output_tensorindex(tensorname, index);
-}
-
-NNFW_STATUS nnfw_set_backends_per_operation(nnfw_session *session, const char *backend_settings)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->set_backends_per_operation(backend_settings);
-}
-
-NNFW_STATUS nnfw_prepare_pipeline(nnfw_session *session, const char *map_file_path)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->prepare_pipeline(map_file_path);
-}
-
-NNFW_STATUS nnfw_push_pipeline_input(nnfw_session *session, void *inputs, void *lengths)
-{
-  NNFW_RETURN_ERROR_IF_NULL(session);
-  return session->push_pipeline_input((std::vector<void *> *)inputs,
-                                      (std::vector<uint32_t> *)lengths);
-}
-
-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
deleted file mode 100644 (file)
index fc02a92..0000000
+++ /dev/null
@@ -1,1559 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_api_internal.h"
-#include "CustomKernelRegistry.h"
-#include "compiler/CompilerFactory.h"
-#include "util/ConfigSource.h"
-#include "util/Exceptions.h"
-#include "util/logging.h"
-#include "exec/Execution.h"
-#include "circle_loader.h"
-#include "tflite_loader.h"
-#include "trix_loader.h"
-#include "json/json.h"
-#include "ir/NNPkg.h"
-#include "ir/OpCode.h"
-#include "util/TracingCtx.h"
-#include "odc/QuantizeManager.h"
-
-#include <fstream>
-#include <iostream>
-#include <string>
-#include <vector>
-#include <dirent.h>
-#include <misc/string_helpers.h>
-
-/*
- * API does not accept string argument longer than max length below
- */
-#define MAX_BACKEND_NAME_LENGTH 32
-#define MAX_OP_NAME_LENGTH 64
-#define MAX_PATH_LENGTH 1024
-#define MAX_TENSOR_NAME_LENGTH 64
-
-namespace
-{
-
-// Is null-terminating in length ?
-bool null_terminating(const char *str, uint32_t length)
-{
-  for (uint32_t i = 0; i < length; i++)
-  {
-    if (*(str + i) == '\0')
-    {
-      return true;
-    }
-  }
-  return false;
-}
-
-onert::ir::Layout convertLayout(NNFW_LAYOUT layout)
-{
-  if (layout == NNFW_LAYOUT_CHANNELS_LAST)
-  {
-    return onert::ir::Layout::NHWC;
-  }
-  else if (layout == NNFW_LAYOUT_CHANNELS_FIRST)
-  {
-    return onert::ir::Layout::NCHW;
-  }
-  return onert::ir::Layout::UNKNOWN;
-}
-
-NNFW_STATUS getTensorIndexImpl(const onert::ir::IGraph &graph, const char *tensorname,
-                               uint32_t *index, bool is_input)
-{
-  if (!tensorname || !index)
-    return NNFW_STATUS_UNEXPECTED_NULL;
-
-  if (!null_terminating(tensorname, MAX_TENSOR_NAME_LENGTH))
-  {
-    std::cerr << "nnpackage path is too long" << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-
-  auto ind_found = is_input ? graph.getInputIndex(tensorname) : graph.getOutputIndex(tensorname);
-
-  if (ind_found.undefined())
-  {
-    // Not found
-    return NNFW_STATUS_ERROR;
-  }
-  else
-  {
-    *index = ind_found.value();
-    return NNFW_STATUS_NO_ERROR;
-  }
-}
-
-std::string trim(const std::string &value)
-{
-  std::string whitespace = " \t";
-  auto begin = value.find_first_not_of(whitespace);
-  if (begin == std::string::npos)
-    return ""; // no content
-
-  auto end = value.find_last_not_of(whitespace);
-  auto range = end - begin + 1;
-  return value.substr(begin, range);
-}
-
-bool loadConfigure(const std::string cfgfile, onert::util::CfgKeyValues &keyValues)
-{
-  std::ifstream ifs(cfgfile);
-  if (ifs.is_open())
-  {
-    std::string line;
-    while (std::getline(ifs, line))
-    {
-      auto cmtpos = line.find('#');
-      if (cmtpos != std::string::npos)
-      {
-        line = line.substr(0, cmtpos);
-      }
-      std::istringstream isline(line);
-      std::string key;
-      if (std::getline(isline, key, '='))
-      {
-        std::string value;
-        if (std::getline(isline, value))
-        {
-          key = trim(key);
-          keyValues[key] = trim(value);
-        }
-      }
-    }
-    ifs.close();
-    return true;
-  }
-  return false;
-}
-
-NNFW_TYPE datatype_to_nnfw_dtype(onert::ir::DataType dt)
-{
-  using onert::ir::DataType;
-  switch (dt)
-  {
-    case DataType::FLOAT32:
-      return NNFW_TYPE_TENSOR_FLOAT32;
-    case DataType::INT32:
-      return NNFW_TYPE_TENSOR_INT32;
-    case DataType::QUANT_UINT8_ASYMM:
-      return NNFW_TYPE_TENSOR_QUANT8_ASYMM;
-    case DataType::BOOL8:
-      return NNFW_TYPE_TENSOR_BOOL;
-    case DataType::UINT8:
-      return NNFW_TYPE_TENSOR_UINT8;
-    case DataType::INT64:
-      return NNFW_TYPE_TENSOR_INT64;
-    case DataType::QUANT_INT8_ASYMM:
-      return NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED;
-    case DataType::QUANT_INT16_SYMM:
-      return NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED;
-    case DataType::UINT32:
-    case DataType::QUANT_INT8_SYMM:
-    default:
-      throw std::runtime_error("Error: Model has type that runtime API does not support.");
-  }
-}
-
-void fillTensorInfo(nnfw_tensorinfo *ti, const onert::ir::Shape &shape,
-                    const onert::ir::DataType &dtype)
-{
-  ti->rank = shape.rank();
-  for (int j = 0; j < ti->rank; ++j)
-  {
-    ti->dims[j] = shape.dim(j);
-  }
-  ti->dtype = datatype_to_nnfw_dtype(dtype);
-}
-
-std::unique_ptr<onert::ir::Model> loadModel(const std::string filename,
-                                            const std::string model_type)
-{
-  if (model_type == "tflite")
-    return onert::tflite_loader::loadModel(filename.c_str());
-  if (model_type == "circle")
-    return onert::circle_loader::loadModel(filename.c_str());
-  if (model_type == "tvn")
-    return onert::trix_loader::loadModel(filename.c_str());
-
-  std::cerr << "Unsupported model type" << std::endl;
-  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}, _quant_manager{nullptr}
-{
-  // DO NOTHING
-}
-
-NNFW_STATUS nnfw_session::create(nnfw_session **session)
-{
-  if (session == nullptr)
-    return NNFW_STATUS_UNEXPECTED_NULL;
-  try
-  {
-    auto new_session = std::unique_ptr<nnfw_session>(new nnfw_session());
-    new_session->_kernel_registry = std::make_shared<onert::api::CustomKernelRegistry>();
-    *session = new_session.release();
-  }
-  catch (const std::bad_alloc &e)
-  {
-    std::cerr << "Error during session creation" << std::endl;
-    *session = nullptr; // Set nullptr on error to keep the old behavior
-    return NNFW_STATUS_OUT_OF_MEMORY;
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during session initialization : " << e.what() << std::endl;
-    *session = nullptr; // Set nullptr on error to keep the old behavior
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-nnfw_session::~nnfw_session() = default;
-
-NNFW_STATUS nnfw_session::load_circle_from_buffer(uint8_t *buffer, size_t size)
-{
-  if (!isStateInitialized())
-    return NNFW_STATUS_INVALID_STATE;
-
-  if (!buffer)
-    return NNFW_STATUS_UNEXPECTED_NULL;
-
-  if (size == 0)
-    return NNFW_STATUS_ERROR;
-
-  try
-  {
-    auto model = onert::circle_loader::loadModel(buffer, size);
-    _nnpkg = std::make_shared<onert::ir::NNPkg>(std::move(model));
-    _coptions.push_back(onert::compiler::CompilerOptions::fromGlobalConfig());
-    _state = State::MODEL_LOADED;
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during model loading : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::load_model_from_modelfile(const char *model_file_path)
-{
-  if (!isStateInitialized())
-    return NNFW_STATUS_INVALID_STATE;
-
-  if (!model_file_path)
-  {
-    std::cerr << "Model file path is null." << std::endl;
-    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('.');
-  if (dotidx == std::string::npos)
-  {
-    std::cerr << "Invalid model file path. Please use file with extension." << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  std::string model_type = filename.substr(dotidx + 1); // + 1 to exclude dot
-  try
-  {
-    auto model = loadModel(filename, model_type);
-    if (model == nullptr)
-      return NNFW_STATUS_ERROR;
-    _nnpkg = std::make_shared<onert::ir::NNPkg>(std::move(model));
-    _coptions.push_back(onert::compiler::CompilerOptions::fromGlobalConfig());
-    _state = State::MODEL_LOADED;
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during model loading : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::load_model_from_nnpackage(const char *package_dir)
-{
-  if (!isStateInitialized())
-    return NNFW_STATUS_INVALID_STATE;
-
-  if (!package_dir)
-  {
-    std::cerr << "package_dir is null." << std::endl;
-    return NNFW_STATUS_UNEXPECTED_NULL;
-  }
-
-  if (!null_terminating(package_dir, MAX_PATH_LENGTH))
-  {
-    std::cerr << "nnpackage path is too long" << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-
-  // TODO : add support for zipped package file load
-  DIR *dir;
-  if (!(dir = opendir(package_dir)))
-  {
-    std::cerr << "invalid nnpackge directory: " << package_dir << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  closedir(dir);
-
-  try
-  {
-    std::string package_path(package_dir);
-    std::string manifest_file_name = package_path + "/metadata/MANIFEST";
-    std::ifstream mfs(manifest_file_name);
-
-    // extract the filename of the first(index 0) model
-    // e.g. In MANIFEST file, { "models" : [ "firstmodel.tflite", "2nd.tflite" ] }
-    Json::Value root;
-    mfs >> root;
-    const Json::Value &models = root["models"];
-    const Json::Value &model_types = root["model-types"];
-    const Json::Value &configs = root["configs"];
-
-    if (!configs.empty() && !configs[0].empty())
-    {
-      auto filepath = package_path + std::string("/metadata/") + configs[0].asString();
-
-      onert::util::CfgKeyValues keyValues;
-      if (loadConfigure(filepath, keyValues))
-      {
-        onert::util::setConfigKeyValues(keyValues);
-      }
-    }
-    _nnpkg = std::make_shared<onert::ir::NNPkg>();
-    auto num_models = models.size();
-    if (num_models == 0 || (num_models - 1) > onert::ir::ModelIndex::max())
-    {
-      std::cerr << "Invalid model size - " << std::to_string(num_models) << std::endl;
-      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();
-      auto model_type = model_types[i].asString();
-      auto model = loadModel(model_file_path, model_type);
-      if (model == nullptr)
-        return NNFW_STATUS_ERROR;
-      model->bindKernelBuilder(_kernel_registry->getBuilder());
-      _nnpkg->push(onert::ir::ModelIndex{i}, std::move(model));
-      _coptions.push_back(onert::compiler::CompilerOptions::fromGlobalConfig());
-    }
-
-    auto toIODesc = [](std::string str) {
-      auto indices = nnfw::misc::split(str, ':');
-      if (indices.size() != 3)
-      {
-        std::cerr << "IODesc should be 3-tuple." << std::endl;
-        return onert::ir::IODesc{};
-      }
-      auto model_idx = static_cast<uint32_t>(std::stoi(indices.at(0)));
-      auto subgraph_idx = static_cast<uint32_t>(std::stoi(indices.at(1)));
-      auto operand_idx = static_cast<uint32_t>(std::stoi(indices.at(2)));
-      return onert::ir::IODesc{model_idx, subgraph_idx, operand_idx};
-    };
-    // read pkg-inputs and pkg-outputs
-    const Json::Value &pkg_inputs = root["pkg-inputs"];
-    for (uint32_t i = 0; i < pkg_inputs.size(); ++i)
-      _nnpkg->addInput(toIODesc(pkg_inputs[i].asString()));
-    const Json::Value &pkg_outputs = root["pkg-outputs"];
-    for (uint32_t i = 0; i < pkg_outputs.size(); ++i)
-      _nnpkg->addOutput(toIODesc(pkg_outputs[i].asString()));
-    // read model-connect
-    const Json::Value &fromtos = root["model-connect"];
-    for (uint32_t i = 0; i < fromtos.size(); ++i)
-    {
-      const Json::Value &tos = fromtos[i]["to"];
-      for (uint32_t j = 0; j < tos.size(); ++j)
-        _nnpkg->addEdge(toIODesc(fromtos[i]["from"].asString()), toIODesc(tos[j].asString()));
-    }
-
-    _nnpkg->verify();
-    _state = State::MODEL_LOADED;
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during model loading : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::prepare()
-{
-  // NOTE. If users want to run prepare() more than one time, this could be removed.
-  if (!isStateModelLoaded())
-  {
-    std::cerr << "Error during model prepare : ";
-    if (isStateInitialized())
-    {
-      std::cerr << "prepare should be run once";
-    }
-    else
-    {
-      std::cerr << "invalid state";
-    }
-    std::cerr << std::endl;
-    return NNFW_STATUS_INVALID_STATE;
-  }
-
-  try
-  {
-    auto compiler = onert::compiler::CompilerFactory::get().create(_nnpkg, _coptions);
-    _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 model prepare : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-
-  _state = State::PREPARED;
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::prepare_pipeline(const char *)
-{
-  std::cerr << "Pipeline prepare_pipeline: deprecated feature " << std::endl;
-  return NNFW_STATUS_ERROR;
-}
-
-NNFW_STATUS nnfw_session::run()
-{
-  if (!isStatePreparedOrFinishedRun())
-  {
-    std::cerr << "Error during nnfw_session::run : "
-              << "run should be run after prepare" << std::endl;
-    return NNFW_STATUS_INVALID_STATE;
-  }
-
-  try
-  {
-    _execution->execute();
-  }
-  catch (const onert::InsufficientBufferSizeException &e)
-  {
-    // Currently insufficient buffer always means output buffer.
-    std::cerr << "Error during nnfw_session::run : " << e.what() << std::endl;
-    return NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE;
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::run : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-
-  _state = State::FINISHED_RUN;
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::run_async()
-{
-  if (!isStatePreparedOrFinishedRun())
-  {
-    std::cerr << "Error during nnfw_session::run_async : "
-              << "run_async should be run after prepare" << std::endl;
-    return NNFW_STATUS_INVALID_STATE;
-  }
-
-  _execution->startExecute();
-
-  _state = State::RUNNING;
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::await()
-{
-  if (!isStateRunning())
-  {
-    std::cerr << "Error during nnfw_session::run_await : "
-              << "run_await should be run after run_async" << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-
-  _execution->waitFinish();
-
-  _state = State::FINISHED_RUN;
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::set_input(uint32_t index, NNFW_TYPE /*type*/, const void *buffer,
-                                    size_t length)
-{
-  if (!isStatePreparedOrFinishedRun())
-  {
-    std::cerr << "Error during nnfw_session::set_input : invalid state" << std::endl;
-    return NNFW_STATUS_INVALID_STATE;
-  }
-
-  if (!buffer && length != 0)
-  {
-    std::cerr
-      << "Error during nnfw_session::set_input : given buffer is NULL but the length is not 0"
-      << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-
-  try
-  {
-    _execution->setInput(onert::ir::IOIndex(index), buffer, length);
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::set_input : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::set_output(uint32_t index, NNFW_TYPE /*type*/, void *buffer,
-                                     size_t length)
-{
-  if (!isStatePreparedOrFinishedRun())
-  {
-    std::cerr << "Error during nnfw_session::set_output : invalid state" << std::endl;
-    return NNFW_STATUS_INVALID_STATE;
-  }
-
-  if (!buffer && length != 0)
-  {
-    std::cerr
-      << "Error during nnfw_session::set_output : given buffer is NULL but the length is not 0"
-      << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-
-  try
-  {
-    _execution->setOutput(onert::ir::IOIndex(index), buffer, length);
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::set_output : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::input_size(uint32_t *number)
-{
-  if (isStateInitialized()) // Model is not loaded
-    return NNFW_STATUS_INVALID_STATE;
-
-  try
-  {
-    if (number == nullptr)
-    {
-      std::cerr << "Error during nnfw_session::input_size, number is null pointer." << std::endl;
-      return NNFW_STATUS_UNEXPECTED_NULL;
-    }
-    *number = getInputSize();
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::input_size : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::output_size(uint32_t *number)
-{
-  if (isStateInitialized()) // Model is not loaded
-    return NNFW_STATUS_INVALID_STATE;
-
-  try
-  {
-    if (number == nullptr)
-    {
-      std::cerr << "Error during nnfw_session::output_size, number is null pointer." << std::endl;
-      return NNFW_STATUS_UNEXPECTED_NULL;
-    }
-    *number = getOutputSize();
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::output_size" << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::set_input_layout(uint32_t index, NNFW_LAYOUT layout)
-{
-  if (!isStatePreparedOrFinishedRun())
-  {
-    std::cerr << "Error during nnfw_session::set_input_layout : "
-              << "run should be run after prepare" << std::endl;
-    return NNFW_STATUS_INVALID_STATE;
-  }
-
-  try
-  {
-    if (layout != NNFW_LAYOUT_NONE && layout != NNFW_LAYOUT_CHANNELS_FIRST &&
-        layout != NNFW_LAYOUT_CHANNELS_LAST)
-    {
-      std::cerr << "Error during nnfw_session::set_input_layout, not supported layout" << std::endl;
-      return NNFW_STATUS_ERROR;
-    }
-
-    _execution->setInputLayout(onert::ir::IOIndex(index), convertLayout(layout));
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::set_input_layout : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::set_output_layout(uint32_t index, NNFW_LAYOUT layout)
-{
-  if (!isStatePreparedOrFinishedRun())
-  {
-    std::cerr << "Error during nnfw_session::set_output_layout : "
-              << "run should be run after prepare" << std::endl;
-    return NNFW_STATUS_INVALID_STATE;
-  }
-
-  try
-  {
-    if (layout != NNFW_LAYOUT_NONE && layout != NNFW_LAYOUT_CHANNELS_FIRST &&
-        layout != NNFW_LAYOUT_CHANNELS_LAST)
-    {
-      std::cerr << "Error during nnfw_session::set_output_layout, not supported layout"
-                << std::endl;
-      return NNFW_STATUS_ERROR;
-    }
-
-    _execution->setOutputLayout(onert::ir::IOIndex(index), convertLayout(layout));
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::set_output_layout : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::apply_tensorinfo(uint32_t index, nnfw_tensorinfo ti)
-{
-  // sanity check
-  {
-    if (isStateInitialized())
-    {
-      std::cerr << "Error during set_input_tensorinfo : should be run after load_model"
-                << std::endl;
-      return NNFW_STATUS_INVALID_STATE;
-    }
-
-    if (ti.rank <= 0 || ti.rank > NNFW_MAX_RANK)
-    {
-      std::cerr << "unsupported rank: " << ti.rank << std::endl;
-      return NNFW_STATUS_ERROR;
-    }
-
-    for (int32_t i = 0; i < ti.rank; ++i)
-    {
-      if (ti.dims[i] <= 0)
-      {
-        std::cerr << "dim must be positive integer but was " << ti.dims[i] << std::endl;
-        return NNFW_STATUS_ERROR;
-      }
-    }
-  }
-
-  onert::ir::Shape new_shape(ti.rank);
-  for (int32_t i = 0; i < ti.rank; i++)
-    new_shape.dim(i) = ti.dims[i];
-
-  if (!isStatePreparedOrFinishedRun())
-  {
-
-    // In this case, if we apply input shape, it will propagate after compilation and excution
-    _nnpkg->changeInputShape(index, new_shape);
-  }
-  else // when called after nnfw_session::prepare()
-    _execution->changeInputShape(onert::ir::IOIndex(index), new_shape);
-
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::set_input_tensorinfo(uint32_t index, const nnfw_tensorinfo *ti)
-{
-  nnfw_tensorinfo ti_copy = *ti;
-  return apply_tensorinfo(index, ti_copy);
-}
-
-NNFW_STATUS nnfw_session::input_tensorinfo(uint32_t index, nnfw_tensorinfo *ti)
-{
-  if (isStateInitialized())
-    return NNFW_STATUS_INVALID_STATE;
-
-  try
-  {
-    if (ti == nullptr)
-    {
-      std::cerr << "Error during nnfw_session::input_tensorinfo, tensorinfo is null pointer."
-                << std::endl;
-      return NNFW_STATUS_UNEXPECTED_NULL;
-    }
-
-    if (index >= getInputSize())
-    {
-      std::cerr << "Error during nnfw_session::input_tensorinfo, index is out of range."
-                << std::endl;
-      return NNFW_STATUS_ERROR;
-    }
-
-    if (isStateModelLoaded())
-    {
-      auto info = _nnpkg->inputInfo(index);
-      fillTensorInfo(ti, info.shape(), info.typeInfo().type());
-    }
-    else
-    {
-      auto io_index = onert::ir::IOIndex{index};
-      auto shape = _execution->getInputShape(io_index);
-      auto dtype = _compiler_artifact->_executors->inputInfo(io_index).typeInfo().type();
-      fillTensorInfo(ti, shape, dtype);
-    }
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::input_tensorinfo : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::output_tensorinfo(uint32_t index, nnfw_tensorinfo *ti)
-{
-  if (isStateInitialized())
-    return NNFW_STATUS_INVALID_STATE;
-
-  if (ti == nullptr)
-  {
-    std::cerr << "Error during nnfw_session::output_tensorinfo, tensorinfo is null pointer."
-              << std::endl;
-    return NNFW_STATUS_UNEXPECTED_NULL;
-  }
-
-  try
-  {
-    if (index >= getOutputSize())
-    {
-      std::cerr << "Error during nnfw_session::output_tensorinfo, index is out of range."
-                << std::endl;
-      return NNFW_STATUS_ERROR;
-    }
-
-    if (isStateModelLoaded())
-    {
-      auto info = _nnpkg->outputInfo(index);
-      fillTensorInfo(ti, info.shape(), info.typeInfo().type());
-    }
-    else
-    {
-      auto io_index = onert::ir::IOIndex{index};
-      auto shape = _execution->getOutputShape(io_index);
-      auto dtype = _compiler_artifact->_executors->outputInfo(io_index).typeInfo().type();
-      fillTensorInfo(ti, shape, dtype);
-    }
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::output_tensorinfo : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::push_pipeline_input(std::vector<void *> *, std::vector<uint32_t> *)
-{
-  std::cerr << "Pipeline push_pipeline_input: deprecated feature " << std::endl;
-  return NNFW_STATUS_ERROR;
-}
-
-NNFW_STATUS nnfw_session::pop_pipeline_output(std::vector<void *> *)
-{
-  std::cerr << "Pipeline pop_pipeline_output: deprecated feature " << std::endl;
-  return NNFW_STATUS_ERROR;
-}
-
-NNFW_STATUS nnfw_session::register_custom_operation(const std::string &id,
-                                                    nnfw_custom_eval eval_func)
-{
-  _kernel_registry->registerKernel(id, eval_func);
-  return NNFW_STATUS_NO_ERROR;
-}
-
-static std::string get_op_backend_string(std::string op)
-{
-#define MAP_MACRO(CircleName, OneRTName) {#CircleName, #OneRTName},
-
-  static std::unordered_map<std::string, std::string> operation_map = {
-#include "OpMap.lst"
-  };
-
-#undef MAP_MACRO
-
-  auto n = operation_map.find(op);
-
-  if (n == operation_map.end())
-  {
-    // this return value is handled by a caller to return error code
-    return std::string("");
-  }
-  else
-  {
-    return n->second;
-  }
-}
-
-NNFW_STATUS nnfw_session::set_available_backends(const char *backends)
-{
-  if (!isStateModelLoaded())
-    return NNFW_STATUS_INVALID_STATE;
-
-  try
-  {
-    if (!backends)
-      return NNFW_STATUS_UNEXPECTED_NULL;
-    if (null_terminating(backends, MAX_BACKEND_NAME_LENGTH) == false)
-      return NNFW_STATUS_ERROR;
-
-    auto &options = *_coptions[0];
-
-    using namespace onert::util;
-
-    options.backend_list = nnfw::misc::split(std::string{backends}, ';');
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::set_available_backends : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::set_op_backend(const char *op, const char *backend)
-{
-  if (!isStateModelLoaded())
-    return NNFW_STATUS_INVALID_STATE;
-
-  try
-  {
-    if (!op || !backend)
-      return NNFW_STATUS_UNEXPECTED_NULL;
-    if (!null_terminating(op, MAX_OP_NAME_LENGTH) ||
-        !null_terminating(backend, MAX_BACKEND_NAME_LENGTH))
-      return NNFW_STATUS_ERROR;
-
-    auto key = get_op_backend_string(op);
-
-    if (key.empty())
-    {
-      return NNFW_STATUS_ERROR;
-    }
-
-    auto &opcode_to_backend = _coptions[0]->manual_scheduler_options.opcode_to_backend;
-    opcode_to_backend.emplace(onert::ir::toOpCode(key), backend);
-  }
-  catch (const std::exception &e)
-  {
-    std::cerr << "Error during nnfw_session::set_op_backend : " << e.what() << std::endl;
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-NNFW_STATUS nnfw_session::set_config(const char *key, const char *value)
-{
-  if (!isStateModelLoaded())
-    return NNFW_STATUS_INVALID_STATE;
-
-  if (!key || !value)
-    return NNFW_STATUS_UNEXPECTED_NULL;
-
-  auto &options = *_coptions[0];
-
-  using namespace onert::util;
-
-  const std::string skey = key;
-
-  if (skey == config::TRACE_FILEPATH)
-  {
-    options.trace_filepath = value;
-  }
-  else if (skey == config::GRAPH_DOT_DUMP)
-  {
-    options.graph_dump_level = toInt(value);
-  }
-  else if (skey == config::EXECUTOR)
-  {
-    options.executor = value;
-  }
-  else if (skey == config::OP_BACKEND_ALLOPS)
-  {
-    options.manual_scheduler_options.backend_for_all = value;
-  }
-  else if (skey == config::USE_SCHEDULER)
-  {
-    options.he_scheduler = toBool(value);
-  }
-  else if (skey == config::PROFILING_MODE)
-  {
-    options.he_profiling_mode = toBool(value);
-  }
-  else
-  {
-    return NNFW_STATUS_ERROR;
-  }
-  return NNFW_STATUS_NO_ERROR;
-}
-
-const onert::ir::IGraph *nnfw_session::primary_subgraph()
-{
-  if (_nnpkg != nullptr)
-  {
-    assert(_execution == nullptr);
-    return _nnpkg->primary_model()->primary_subgraph().get();
-  }
-  else
-  {
-    assert(_execution != nullptr);
-    // We assumed the graph will not change after compilation, but shape could change
-    return &_execution->primary_subgraph();
-  }
-}
-
-uint32_t nnfw_session::getInputSize()
-{
-  if (isStateInitialized())
-    throw std::runtime_error{"Model is not loaded yet"};
-
-  if (isStateModelLoaded())
-    return _nnpkg->inputSize();
-
-  // Session is prepared (general inference)
-  return _compiler_artifact->_executors->inputSize();
-}
-
-uint32_t nnfw_session::getOutputSize()
-{
-  if (isStateInitialized())
-    throw std::runtime_error{"Model is not loaded yet"};
-
-  if (isStateModelLoaded())
-    return _nnpkg->outputSize();
-
-  // Session is prepared (general inference)
-  return _compiler_artifact->_executors->outputSize();
-}
-
-NNFW_STATUS nnfw_session::get_config(const char *key, char *value, size_t value_size)
-{
-  if (!isStateModelLoaded())
-    return NNFW_STATUS_INVALID_STATE;
-
-  if (!key || !value)
-    return NNFW_STATUS_UNEXPECTED_NULL;
-
-  auto &options = *_coptions[0];
-
-  auto check_boundary = [](size_t dest_size, std::string &src) {
-    if (dest_size < src.length() + 1 /* for '\0' */)
-    {
-      std::cerr << "buffer is small to copy config value." << std::endl;
-      return false;
-    }
-    return true;
-  };
-
-  const std::string skey = key;
-
-  if (skey == onert::util::config::BACKENDS)
-  {
-    if (options.backend_list.size() == 0)
-      return NNFW_STATUS_NO_ERROR; // no setting backend is not an error of get_config_str()
-
-    auto str = nnfw::misc::join(options.backend_list.begin(), options.backend_list.end(), ";");
-
-    if (!check_boundary(value_size, str))
-      return NNFW_STATUS_ERROR;
-
-    strncpy(value, str.c_str(), value_size);
-  }
-  else if (skey == onert::util::config::EXECUTOR)
-  {
-    if (!check_boundary(value_size, options.executor))
-      return NNFW_STATUS_ERROR;
-
-    strncpy(value, options.executor.c_str(), options.executor.length());
-  }
-  else
-  {
-    return NNFW_STATUS_ERROR;
-  }
-
-  return NNFW_STATUS_NO_ERROR;
-}
-
-bool nnfw_session::isStateInitialized()
-{
-  if (_state == State::INITIALIZED)
-  {
-    assert(_nnpkg == nullptr);
-    assert(_coptions.empty());
-    assert(_execution == nullptr);
-    return true;
-  }
-  else
-  {
-    return false;
-  }
-}
-
-bool nnfw_session::isStateModelLoaded()
-{
-  if (_state == State::MODEL_LOADED)
-  {
-    assert(_nnpkg != nullptr);
-    assert(!_coptions.empty());
-    assert(_execution == nullptr);
-    return true;
-  }
-  else
-  {
-    return false;
-  }
-}
-
-bool nnfw_session::isStatePrepared()
-{
-  if (_state == State::PREPARED)
-  {
-    assert(_nnpkg == nullptr);
-    assert(!_coptions.empty());
-    assert(_execution != nullptr);
-    return true;
-  }
-  else
-  {
-    return false;
-  }
-}
-
-bool nnfw_session::isStateRunning()
-{
-  if (_state == State::RUNNING)
-  {
-    assert(_nnpkg == nullptr);
-    assert(!_coptions.empty());
-    assert(_execution != nullptr);
-    return true;
-  }
-  return false;
-}
-
-bool nnfw_session::isStateFinishedRun()
-{
-  if (_state == State::FINISHED_RUN)
-  {
-    assert(_nnpkg == nullptr);
-    assert(!_coptions.empty());
-    assert(_execution != nullptr);
-    return true;
-  }
-  else
-  {
-    return false;
-  }
-}
-
-bool nnfw_session::isStatePreparedOrFinishedRun()
-{
-  return isStatePrepared() || isStateFinishedRun();
-}
-
-NNFW_STATUS nnfw_session::input_tensorindex(const char *tensorname, uint32_t *index)
-{
-  return getTensorIndexImpl(*primary_subgraph(), tensorname, index, true);
-}
-
-NNFW_STATUS nnfw_session::output_tensorindex(const char *tensorname, uint32_t *index)
-{
-  return getTensorIndexImpl(*primary_subgraph(), tensorname, index, false);
-}
-
-NNFW_STATUS nnfw_session::set_backends_per_operation(const char *backend_settings)
-{
-  if (backend_settings == NULL)
-    return NNFW_STATUS_ERROR;
-
-  if (!isStateModelLoaded())
-    return NNFW_STATUS_INVALID_STATE;
-
-  // Backend for all
-  auto &ms_options = _coptions[0]->manual_scheduler_options;
-  ms_options.setBackendMap(std::string{backend_settings});
-
-  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
deleted file mode 100644 (file)
index 6279176..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __API_NNFW_API_INTERNAL_H__
-#define __API_NNFW_API_INTERNAL_H__
-
-#include "nnfw.h"
-#include "nnfw_experimental.h"
-
-#include <util/TracingCtx.h>
-
-#include <string>
-#include <memory>
-#include <thread>
-#include <vector>
-
-namespace onert
-{
-namespace api
-{
-class CustomKernelRegistry;
-} // namespace api
-namespace exec
-{
-class Execution;
-} // namespace exec
-namespace ir
-{
-struct IGraph;
-class Model;
-class NNPkg;
-} // namespace ir
-namespace compiler
-{
-struct CompilerArtifact;
-class CompilerOptions;
-} // namespace compiler
-namespace odc
-{
-class QuantizeManager;
-} // namespace odc
-} // namespace onert
-
-struct nnfw_session
-{
-private:
-  /**
-   * @brief Enum class to express the session's state
-   *
-   * State transition diagram:
-   *
-   *           +--------------+
-   *           | INITIALIZED  |
-   *           +--------------+
-   *             |
-   *             | load_model
-   *             v
-   *           +--------------+
-   *           | MODEL_LOADED |
-   *           +--------------+
-   *             |
-   *             | prepare
-   *             v
-   *           +--------------+
-   *           |   PREPARED   | --------+
-   *           +--------------+         |
-   *             |                      |
-   *             | run                  |
-   *             v                      |
-   *           +--------------+  run    |
-   *           |              | -----+  |
-   *   +-----> | FINISHED_RUN |      |  | run_async
-   *   |       |              | <----+  |
-   *   |       +--------------+         |
-   *   |         |                      |
-   *   | await   | run_async            |
-   *   |         v                      |
-   *   |       +--------------+         |
-   *   +------ |   RUNNING    | <-------+
-   *           +--------------+
-   */
-  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
-    PREPARED_TRAINING, //< Prepared for training
-    FINISHED_TRAINING  //< Trained at least once
-  };
-
-public:
-  /**
-   * @brief Factory method. It creates and initialize nnfw_session
-   *
-   * @note  Use factory instead of constructor to get status
-   */
-  static NNFW_STATUS create(nnfw_session **session);
-
-private:
-  nnfw_session();
-
-public:
-  ~nnfw_session();
-  NNFW_STATUS load_model_from_nnpackage(const char *package_file_path);
-  NNFW_STATUS prepare();
-  NNFW_STATUS prepare_pipeline(const char *map_file_path);
-  NNFW_STATUS run();
-
-  NNFW_STATUS run_async();
-  NNFW_STATUS await();
-
-  NNFW_STATUS set_input(uint32_t index, NNFW_TYPE type, const void *buffer, size_t length);
-  NNFW_STATUS set_output(uint32_t index, NNFW_TYPE type, void *buffer, size_t length);
-
-  NNFW_STATUS input_size(uint32_t *number);
-  NNFW_STATUS output_size(uint32_t *number);
-
-  NNFW_STATUS set_input_layout(uint32_t index, NNFW_LAYOUT layout);
-  NNFW_STATUS set_output_layout(uint32_t index, NNFW_LAYOUT layout);
-
-  NNFW_STATUS apply_tensorinfo(uint32_t index, nnfw_tensorinfo ti); // Will be deprecated
-  NNFW_STATUS set_input_tensorinfo(uint32_t index, const nnfw_tensorinfo *ti);
-
-  NNFW_STATUS input_tensorinfo(uint32_t index, nnfw_tensorinfo *ti);
-  NNFW_STATUS output_tensorinfo(uint32_t index, nnfw_tensorinfo *ti);
-
-  NNFW_STATUS set_available_backends(const char *backends);
-  NNFW_STATUS set_op_backend(const char *op, const char *backend);
-
-  //
-  // Internal-only API
-  //
-
-  NNFW_STATUS set_config(const char *key, const char *value);
-  NNFW_STATUS get_config(const char *key, char *value, size_t value_size);
-  NNFW_STATUS load_circle_from_buffer(uint8_t *buffer, size_t size);
-  NNFW_STATUS load_model_from_modelfile(const char *file_path);
-
-  //
-  // Experimental API
-  //
-  NNFW_STATUS push_pipeline_input(std::vector<void *> *inputs, std::vector<uint32_t> *lengths);
-  NNFW_STATUS pop_pipeline_output(std::vector<void *> *outputs);
-
-  NNFW_STATUS register_custom_operation(const std::string &id, nnfw_custom_eval eval_func);
-  NNFW_STATUS input_tensorindex(const char *tensorname, uint32_t *index);
-  NNFW_STATUS output_tensorindex(const char *tensorname, uint32_t *index);
-  /**
-   * @brief   Set backends with string-encoded mapping from operation index to backend type
-   *          (cpu, acl_cl)
-   */
-  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::IGraph *primary_subgraph();
-  uint32_t getInputSize();
-  uint32_t getOutputSize();
-
-  bool isStateInitialized();
-  bool isStateModelLoaded();
-  bool isStatePrepared();
-  bool isStateRunning();
-  bool isStateFinishedRun();
-  bool isStatePreparedOrFinishedRun();
-#ifdef ONERT_TRAIN
-  bool isStatePreparedTraining();
-  bool isStateFinishedTraining();
-  bool isStatePreparedOrFinishedTraining();
-#endif // ONERT_TRAIN
-
-private:
-  State _state{State::INITIALIZED};
-  std::shared_ptr<onert::ir::NNPkg> _nnpkg;
-  std::vector<std::unique_ptr<onert::compiler::CompilerOptions>> _coptions;
-  std::shared_ptr<onert::compiler::CompilerArtifact> _compiler_artifact;
-  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__
index e6af06a..0721881 100644 (file)
@@ -10,12 +10,8 @@ add_subdirectory(cpu)
 add_subdirectory(acl_cl)
 add_subdirectory(acl_neon)
 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)
-
+add_subdirectory(train)
index 2c94ea6..33bd3a2 100644 (file)
@@ -14,11 +14,8 @@ target_link_libraries(${LIB_ONERT_BACKEND_ACL_CL} PRIVATE ${LIB_ONERT_BACKEND_AC
 target_link_libraries(${LIB_ONERT_BACKEND_ACL_CL} PRIVATE nnfw_common)
 target_link_libraries(${LIB_ONERT_BACKEND_ACL_CL} PRIVATE nnfw_coverage)
 
-set_target_properties(${LIB_ONERT_BACKEND_ACL_CL} PROPERTIES OUTPUT_NAME backend_acl_cl)
+set_target_properties(${LIB_ONERT_BACKEND_ACL_CL} PROPERTIES
+  OUTPUT_NAME backend_acl_cl
+  INSTALL_RPATH "$ORIGIN:$ORIGIN/../..")
 
-if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
-  add_custom_command(TARGET onert_backend_acl_cl POST_BUILD
-                     COMMAND ${CMAKE_STRIP} "--strip-unneeded" $<TARGET_FILE_NAME:onert_backend_acl_cl>)
-endif()
-
-install(TARGETS ${LIB_ONERT_BACKEND_ACL_CL} DESTINATION lib)
+install(TARGETS ${LIB_ONERT_BACKEND_ACL_CL} DESTINATION lib/nnfw/backend)
index dcf3185..3bc8900 100644 (file)
@@ -47,9 +47,8 @@ using ActivationBuilder = ::onert::backend::acl_common::AclActivationBuilder<
 KernelGenerator::KernelGenerator(
   const ir::Graph &graph, const std::shared_ptr<TensorBuilder> &tensor_builder,
   const std::shared_ptr<acl_common::AclTensorRegistry<TensorManager>> &tensor_reg)
-  : basic::KernelGeneratorBase{graph}, _ctx(graph.operands()),
-    _operations_ctx(graph.operations()), _current_layout{graph.layout()},
-    _tensor_builder(tensor_builder), _tensor_reg(tensor_reg)
+  : basic::KernelGeneratorBase{graph}, _ctx(graph.operands()), _operations_ctx(graph.operations()),
+    _current_layout{graph.layout()}, _tensor_builder(tensor_builder), _tensor_reg(tensor_reg)
 {
   // DO NOTHING
 }
index 0f779f4..d1f92fe 100644 (file)
@@ -31,8 +31,8 @@ namespace acl_cl
 {
 
 Optimizer::Optimizer(BackendContext *context)
-  : _context{context}, _tensor_builder{
-                         std::dynamic_pointer_cast<TensorBuilder>(context->tensor_builder)}
+  : _context{context},
+    _tensor_builder{std::dynamic_pointer_cast<TensorBuilder>(context->tensor_builder)}
 {
   assert(context);
 }
index e05d36a..c068fb7 100644 (file)
@@ -45,7 +45,7 @@ void disableDimCorrection(IACLTensor *tensor)
 }
 
 template <typename Layer, typename... Args>
-std::unique_ptr<arm_compute::IFunction> generateLayer(Args &&... args)
+std::unique_ptr<arm_compute::IFunction> generateLayer(Args &&...args)
 {
   auto l = std::make_unique<Layer>();
 
@@ -56,7 +56,7 @@ std::unique_ptr<arm_compute::IFunction> generateLayer(Args &&... args)
 
 template <typename Layer, typename... Args>
 std::unique_ptr<arm_compute::IFunction>
-generateLayer(std::shared_ptr<arm_compute::IMemoryManager> memory_manager, Args &&... args)
+generateLayer(std::shared_ptr<arm_compute::IMemoryManager> memory_manager, Args &&...args)
 {
   auto l = std::make_unique<Layer>(memory_manager);
 
index a37256c..687bfb6 100644 (file)
@@ -14,11 +14,8 @@ target_link_libraries(${LIB_ONERT_BACKEND_ACL_NEON} PRIVATE ${LIB_ONERT_BACKEND_
 target_link_libraries(${LIB_ONERT_BACKEND_ACL_NEON} PRIVATE nnfw_common)
 target_link_libraries(${LIB_ONERT_BACKEND_ACL_NEON} PRIVATE nnfw_coverage)
 
-set_target_properties(${LIB_ONERT_BACKEND_ACL_NEON} PROPERTIES OUTPUT_NAME backend_acl_neon)
+set_target_properties(${LIB_ONERT_BACKEND_ACL_NEON} PROPERTIES
+  OUTPUT_NAME backend_acl_neon
+  INSTALL_RPATH "$ORIGIN:$ORIGIN/../..")
 
-if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
-  add_custom_command(TARGET onert_backend_acl_neon POST_BUILD
-                     COMMAND ${CMAKE_STRIP} "--strip-unneeded" $<TARGET_FILE_NAME:onert_backend_acl_neon>)
-endif()
-
-install(TARGETS ${LIB_ONERT_BACKEND_ACL_NEON} DESTINATION lib)
+install(TARGETS ${LIB_ONERT_BACKEND_ACL_NEON} DESTINATION lib/nnfw/backend)
index e71aa36..4eeeab8 100644 (file)
@@ -46,9 +46,8 @@ using ActivationBuilder = ::onert::backend::acl_common::AclActivationBuilder<
 KernelGenerator::KernelGenerator(
   const ir::Graph &graph, const std::shared_ptr<TensorBuilder> &tensor_builder,
   const std::shared_ptr<acl_common::AclTensorRegistry<TensorManager>> &tensor_reg)
-  : basic::KernelGeneratorBase{graph}, _ctx(graph.operands()),
-    _operations_ctx(graph.operations()), _current_layout{graph.layout()},
-    _tensor_builder(tensor_builder), _tensor_reg(tensor_reg)
+  : basic::KernelGeneratorBase{graph}, _ctx(graph.operands()), _operations_ctx(graph.operations()),
+    _current_layout{graph.layout()}, _tensor_builder(tensor_builder), _tensor_reg(tensor_reg)
 {
   // DO NOTHING
 }
index f207ca8..7c7d5e0 100644 (file)
@@ -31,8 +31,8 @@ namespace acl_neon
 {
 
 Optimizer::Optimizer(BackendContext *context)
-  : _context{context}, _tensor_builder{
-                         std::dynamic_pointer_cast<TensorBuilder>(context->tensor_builder)}
+  : _context{context},
+    _tensor_builder{std::dynamic_pointer_cast<TensorBuilder>(context->tensor_builder)}
 {
   assert(context);
 }
index 76d4039..148189f 100644 (file)
@@ -41,8 +41,8 @@ public:
                  std::shared_ptr<T_ConstantInitializer> constant_initializer = nullptr,
                  std::shared_ptr<T_KernelGenerator> kernel_gen = nullptr)
     : onert::backend::BackendContext(backend, std::move(data), tensor_registry),
-      tensor_builder{tensor_builder}, constant_initializer{constant_initializer}, kernel_gen{
-                                                                                    kernel_gen}
+      tensor_builder{tensor_builder}, constant_initializer{constant_initializer},
+      kernel_gen{kernel_gen}
   {
   }
 
@@ -54,7 +54,7 @@ public:
     for (auto &&op_ind : _data.op_order)
     {
       auto fn_seq = kernel_gen->generate(op_ind);
-      ret.emplace_back(op_ind, std::move(fn_seq));
+      ret.emplace(op_ind, std::move(fn_seq));
     }
 
     tensor_builder->allocate();
@@ -121,7 +121,7 @@ protected:
       if (!tensor_builder->isRegistered(ind))
       {
         // These tensors do not exist in any operation (No use and def)
-        const auto info = obj.info();
+        const auto &info = obj.info();
         const auto layout = _data.operand_layouts.at(ind);
         // TODO Change tensor info to have permuted shape
         registerTensorInfo(ind, info, layout);
index 45de6b9..17a121a 100644 (file)
@@ -40,7 +40,7 @@ FunctionMap BackendContext::genKernels()
   for (auto &&op_ind : _data.op_order)
   {
     auto fn_seq = kernel_gen->generate(op_ind);
-    ret.emplace_back(op_ind, std::move(fn_seq));
+    ret.emplace(op_ind, std::move(fn_seq));
   }
 
   basic::initConsts(*this);
index 1383263..5ca7e60 100644 (file)
@@ -13,12 +13,9 @@ target_link_libraries(${LIB_ONERT_BACKEND_CPU} PRIVATE ruy)
 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)
+set_target_properties(${LIB_ONERT_BACKEND_CPU} PROPERTIES
+  OUTPUT_NAME backend_cpu
+  POSITION_INDEPENDENT_CODE ON
+  INSTALL_RPATH "$ORIGIN:$ORIGIN/../..")
 
-if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
-  add_custom_command(TARGET ${LIB_ONERT_BACKEND_CPU} POST_BUILD
-                     COMMAND ${CMAKE_STRIP} "--strip-unneeded" $<TARGET_FILE_NAME:${LIB_ONERT_BACKEND_CPU}>)
-endif()
-
-install(TARGETS ${LIB_ONERT_BACKEND_CPU} DESTINATION lib)
+install(TARGETS ${LIB_ONERT_BACKEND_CPU} DESTINATION lib/nnfw/backend)
index c927bf5..6c363f8 100644 (file)
@@ -133,6 +133,8 @@ convertElementwiseBinaryType(ir::operation::ElementwiseBinary::ElementwiseBinary
   {
     case ir::operation::ElementwiseBinary::ElementwiseBinaryType::FLOOR_DIV:
       return ops::ElementwiseBinaryType::kFloorDiv;
+    case ir::operation::ElementwiseBinary::ElementwiseBinaryType::FLOOR_MOD:
+      return ops::ElementwiseBinaryType::kFloorMod;
     case ir::operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_AND:
       return ops::ElementwiseBinaryType::kLogicalAnd;
     case ir::operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_OR:
@@ -229,10 +231,9 @@ KernelGenerator::KernelGenerator(
   const std::shared_ptr<basic::TensorRegistry> &tensor_reg,
   const std::shared_ptr<backend::custom::IKernelBuilder> &kernel_builder,
   const std::shared_ptr<ExternalContext> &external_context)
-  : basic::KernelGeneratorBase{graph},
-    _ctx(graph.operands()), _operations_ctx{graph.operations()}, _current_layout{graph.layout()},
-    _tensor_builder(tensor_builder), _tensor_reg{tensor_reg}, _kernel_builder(kernel_builder),
-    _external_context(external_context)
+  : basic::KernelGeneratorBase{graph}, _ctx(graph.operands()), _operations_ctx{graph.operations()},
+    _current_layout{graph.layout()}, _tensor_builder(tensor_builder), _tensor_reg{tensor_reg},
+    _kernel_builder(kernel_builder), _external_context(external_context)
 {
   // DO NOTHING
 }
@@ -307,8 +308,11 @@ void KernelGenerator::visit(const ir::operation::Conv2D &node)
 
   const auto stride = node.param().stride;
   const auto activation = node.param().activation;
-  const auto param_padding = node.param().padding;
+  const auto &param_padding = node.param().padding;
   const auto dilation = node.param().dilation;
+
+  const bool is_cacheable_weights = ker_tensor->is_constant();
+
   auto fn = std::make_unique<ops::ConvolutionLayer>();
 
   if (_ctx.at(ifm_index).info().isDynamic() || _ctx.at(ker_index).info().isDynamic())
@@ -316,7 +320,7 @@ void KernelGenerator::visit(const ir::operation::Conv2D &node)
     fn->configure(ifm_tensor, ker_tensor, bias_tensor, param_padding.type, param_padding.param.left,
                   param_padding.param.right, param_padding.param.top, param_padding.param.bottom,
                   stride.horizontal, stride.vertical, dilation.width_factor, dilation.height_factor,
-                  activation, ofm_tensor);
+                  activation, ofm_tensor, is_cacheable_weights);
 
     _return_fn = std::move(fn);
     return;
@@ -334,7 +338,8 @@ void KernelGenerator::visit(const ir::operation::Conv2D &node)
 
   fn->configure(ifm_tensor, ker_tensor, bias_tensor, param_padding.type, padding.left,
                 padding.right, padding.top, padding.bottom, stride.horizontal, stride.vertical,
-                dilation.width_factor, dilation.height_factor, activation, ofm_tensor);
+                dilation.width_factor, dilation.height_factor, activation, ofm_tensor,
+                is_cacheable_weights);
 
   _return_fn = std::move(fn);
 }
@@ -629,7 +634,7 @@ void KernelGenerator::visit(const ir::operation::Einsum &node)
   for (const auto &ifm_idx : node.getInputs())
     input_tensors.emplace_back(_tensor_reg->getPortableTensor(ifm_idx));
 
-  const auto equation = node.param().equation;
+  const auto &equation = node.param().equation;
 
   auto fn = std::make_unique<ops::EinsumLayer>();
 
@@ -789,25 +794,21 @@ void KernelGenerator::visit(const ir::operation::Pad &node)
   const auto input_index{node.getInputs().at(ir::operation::Pad::Input::INPUT)};
   const auto pad_index{node.getInputs().at(ir::operation::Pad::Input::PAD)};
   const auto output_index{node.getOutputs().at(0)};
-  assert(_ctx.at(pad_index).data());
 
   auto input = _tensor_reg->getPortableTensor(input_index);
+  auto pad = _tensor_reg->getPortableTensor(pad_index);
   auto output = _tensor_reg->getPortableTensor(output_index);
-  auto pad_rank = _ctx.at(pad_index).shape().dim(0);
-  auto pad_base = reinterpret_cast<const int32_t *>(_ctx.at(pad_index).data()->base());
 
   auto fn = std::make_unique<ops::PadLayer>();
 
-  bool isPadV2 = node.getInputs().size() == 3 ? true : false;
-  const void *value = nullptr;
-
-  if (isPadV2)
+  IPortableTensor *value = nullptr;
+  if (node.getInputs().size() == 3) // isPadV2
   {
     const auto value_index{node.getInputs().at(ir::operation::Pad::Input::VALUE)};
-    value = reinterpret_cast<const void *>(_ctx.at(value_index).data()->base());
+    value = _tensor_reg->getPortableTensor(value_index);
   }
 
-  fn->configure(input, output, pad_base, pad_rank, value);
+  fn->configure(input, pad, value, output);
   _return_fn = std::move(fn);
 }
 
@@ -1266,7 +1267,7 @@ void KernelGenerator::visit(const ir::operation::FusedBatchNorm &node)
 
   const auto epsilon = node.param().epsilon;
   const auto is_training = node.param().is_training;
-  const auto data_format = node.param().data_format;
+  const auto &data_format = node.param().data_format;
 
   auto fn = std::make_unique<ops::FusedBatchNormLayer>();
 
index e0d5a3c..c64cef4 100644 (file)
@@ -105,6 +105,17 @@ generateKernelGeneric(const IPortableTensor *lhs, const IPortableTensor *rhs,
       return Eval<arithmetic_type, int32_t>(lhs, rhs, output, op_params);
       break;
     }
+    case OperandType::BOOL8:
+    {
+      if (activation != ir::Activation::NONE)
+        throw std::runtime_error(
+          "BinaryArithmetic(generic): Fused activation is not supported with bool8 type");
+      int32_t output_activation_min = 0, output_activation_max = 0;
+      CalculateActivationRange(activation, &output_activation_min, &output_activation_max);
+      static_assert(sizeof(bool) == 1, "cpu backend supports bool type which is 1 byte");
+      return Eval<arithmetic_type, bool>(lhs, rhs, output, op_params);
+      break;
+    }
     default:
       throw std::runtime_error{"BinaryArithmetic(generic): Unsupported data type"};
   }
index d6b33ad..c7ed891 100644 (file)
@@ -53,7 +53,7 @@ public:
 
   void run() override;
 
-private:
+protected:
   const IPortableTensor *_lhs;
   const IPortableTensor *_rhs;
   IPortableTensor *_output;
index b621952..07b7402 100644 (file)
@@ -62,7 +62,7 @@ void compareQuant8(const IPortableTensor *lhs, const IPortableTensor *rhs, IPort
   params.is_broadcast = !HaveSameShapes(lhs, rhs);
 
   using CompareFunction = void (*)(
-    ComparisonParams & params, const Shape &input1_shape, const T *input1_data,
+    ComparisonParams &params, const Shape &input1_shape, const T *input1_data,
     const Shape &input2_shape, const T *input2_data, const Shape &output_shape, bool *output_data);
 
   static const CompareFunction broadcast_fns[] = {
index 62e8ae4..95e6f06 100644 (file)
@@ -35,7 +35,8 @@ 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), _is_hybrid(false)
+    _conv_kernel(new nnfw::cker::Conv()), _prepare(false), _is_cachable_weights(false),
+    _is_hybrid(false)
 {
   // DO NOTHING
 }
@@ -200,7 +201,8 @@ void ConvolutionLayer::configure(const IPortableTensor *input, const IPortableTe
                                  const uint32_t strideWidth, const uint32_t strideHeight,
                                  const uint32_t dilationWidthFactor,
                                  const uint32_t dilationHeightFactor,
-                                 const ir::Activation activation, IPortableTensor *output)
+                                 const ir::Activation activation, IPortableTensor *output,
+                                 bool is_cachable_weights)
 {
   _input = input;
   _kernel = kernel;
@@ -216,6 +218,7 @@ void ConvolutionLayer::configure(const IPortableTensor *input, const IPortableTe
   _dilationHeightFactor = dilationHeightFactor;
   _activation = activation;
   _output = output;
+  _is_cachable_weights = is_cachable_weights;
   _is_hybrid = _input->data_type() == OperandType::FLOAT32 &&
                _kernel->data_type() == OperandType::QUANT_INT8_SYMM;
 }
@@ -305,7 +308,7 @@ void ConvolutionLayer::prepare()
   }
 
   nnfw::cker::Conv &kernel = *_conv_kernel;
-  if (_input->data_type() == OperandType::FLOAT32 && _kernel->is_constant())
+  if (_input->data_type() == OperandType::FLOAT32 && _is_cachable_weights)
   {
     bool is_transposed = false;
     kernel.prepareF32(getShape(_kernel), getBuffer<float>(_kernel), getPaddingType(_paddingType),
@@ -320,7 +323,7 @@ void ConvolutionLayer::prepare()
         const_cast<Tensor *>(kernel_tensor)->decrease_ref();
     }
   }
-  else if (_input->data_type() == OperandType::QUANT_UINT8_ASYMM && _kernel->is_constant() &&
+  else if (_input->data_type() == OperandType::QUANT_UINT8_ASYMM && _is_cachable_weights &&
            !_input->is_dynamic() && !_output->is_dynamic())
   {
     const bool per_channel_quantized = _kernel->data_scales().size() > 1;
@@ -340,7 +343,7 @@ void ConvolutionLayer::prepare()
   }
   else if (_input->data_type() == OperandType::QUANT_INT8_ASYMM)
   {
-    if (_kernel->is_constant() && !_input->is_dynamic() && !_output->is_dynamic())
+    if (_is_cachable_weights && !_input->is_dynamic() && !_output->is_dynamic())
     {
       GetQuantizedConvolutionMultipliersAndShifts(
         _input->data_scale(), _output->data_scale(), _kernel->data_scales().data(),
index 5e1bd0b..c5bab1a 100644 (file)
@@ -56,7 +56,7 @@ public:
                  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);
+                 IPortableTensor *output, bool is_cachable_weights);
   void prepare() override;
   void run() override;
 
@@ -67,7 +67,7 @@ private:
   void convQ8i();
   void convQ8iHybridPerChannel();
 
-private:
+protected:
   const IPortableTensor *_input;
   const IPortableTensor *_kernel;
   const IPortableTensor *_bias;
@@ -90,6 +90,7 @@ private:
   std::unique_ptr<nnfw::cker::ConvHybridTempArena> _hybrid_arena;
 
   bool _prepare;
+  bool _is_cachable_weights;
   bool _is_hybrid;
 };
 
index 5721f87..dca36a6 100644 (file)
@@ -62,7 +62,7 @@ private:
   void prepareQ8iHybridPerChannel();
   void ensureQ8iHybridPerChannel();
 
-private:
+protected:
   const IPortableTensor *_input{nullptr};
   const IPortableTensor *_kernel{nullptr};
   const IPortableTensor *_bias{nullptr};
@@ -83,6 +83,7 @@ private:
 
   ir::Activation _activation{ir::Activation::NONE};
 
+private:
   std::shared_ptr<ExternalContext> _external_context;
 
   bool _prepared{false};
index d89741c..dc9e20e 100644 (file)
@@ -106,7 +106,7 @@ Array<const CornerBox> decodeBoxes(const Array<float> &raw_boxes, const Array<fl
 
     for (size_t i = 0; i < num_boxes; ++i)
     {
-      auto anchor = anchors.at(i);
+      const auto &anchor = anchors.at(i);
       auto &box = decoded_boxes_a.at(i);
       float yc = in_boxes.at(i).y / scales.y * anchor.h + anchor.y;
       float xc = in_boxes.at(i).x / scales.x * anchor.w + anchor.x;
@@ -121,7 +121,7 @@ Array<const CornerBox> decodeBoxes(const Array<float> &raw_boxes, const Array<fl
       assert(box.y2 > box.y1);
     }
 
-    auto decoded_boxes_a_shape = decoded_boxes_a.shape();
+    const auto &decoded_boxes_a_shape = decoded_boxes_a.shape();
 
     return array_cast<const CornerBox>(std::move(decoded_boxes_a), decoded_boxes_a_shape);
   }
index 27b2cdf..184d74e 100644 (file)
@@ -168,7 +168,7 @@ void ElementwiseActivationLayer::configure(const IPortableTensor *input, IPortab
       }
       else
       {
-        throw std::runtime_error{"ElementwiseActivationLayer(Logistic): unsupported data type"};
+        throw std::runtime_error{"ElementwiseActivationLayer(Tanh): unsupported data type"};
       }
       break;
     case ElementwiseActivationType::kLeakyReLU:
index 391bf51..4dc0394 100644 (file)
@@ -19,6 +19,7 @@
 #include "OperationUtils.h"
 
 #include <cker/operation/FloorDiv.h>
+#include <cker/operation/FloorMod.h>
 #include <cker/operation/LogicalAnd.h>
 #include <cker/operation/LogicalOr.h>
 #include <cker/operation/MaxMin.h>
@@ -51,6 +52,22 @@ void FloorDivGeneric(const IPortableTensor *lhs, const IPortableTensor *rhs,
 }
 
 template <typename T>
+void FloorModGeneric(const IPortableTensor *lhs, const IPortableTensor *rhs,
+                     IPortableTensor *output)
+{
+  if (!HaveSameShapes(lhs, rhs))
+  {
+    nnfw::cker::FloorModBroadcast<T>(getShape(lhs), getBuffer<T>(lhs), getShape(rhs),
+                                     getBuffer<T>(rhs), getShape(output), getBuffer<T>(output));
+  }
+  else
+  {
+    nnfw::cker::FloorModElementwise<T>(getShape(lhs), getBuffer<T>(lhs), getBuffer<T>(rhs),
+                                       getBuffer<T>(output));
+  }
+}
+
+template <typename T>
 void logicalAndGeneric(const IPortableTensor *lhs, const IPortableTensor *rhs,
                        IPortableTensor *output)
 {
@@ -132,9 +149,24 @@ void ElementwiseBinaryLayer::configure(const IPortableTensor *lhs, const IPortab
         throw std::runtime_error{"Max: unsupported data type"};
       }
       break;
+    case ElementwiseBinaryType::kFloorMod:
+      if (_lhs->data_type() == OperandType::FLOAT32)
+      {
+        _kernel = FloorModGeneric<float>;
+      }
+      else if (_lhs->data_type() == OperandType::INT64)
+      {
+        _kernel = FloorModGeneric<int64_t>;
+      }
+      else
+      {
+        throw std::runtime_error{"FloorMod: unsupported data type"};
+      }
+      break;
     case ElementwiseBinaryType::kLogicalAnd:
       if ((_lhs->data_type() == OperandType::BOOL8) && (_rhs->data_type() == OperandType::BOOL8))
       {
+        static_assert(sizeof(bool) == 1, "cpu backend supports bool type which is 1 byte");
         _kernel = logicalAndGeneric<bool>;
       }
       else
@@ -145,6 +177,7 @@ void ElementwiseBinaryLayer::configure(const IPortableTensor *lhs, const IPortab
     case ElementwiseBinaryType::kLogicalOr:
       if ((_lhs->data_type() == OperandType::BOOL8) && (_rhs->data_type() == OperandType::BOOL8))
       {
+        static_assert(sizeof(bool) == 1, "cpu backend supports bool type which is 1 byte");
         _kernel = logicalOrGeneric<bool>;
       }
       else
index af3bb63..a6007ec 100644 (file)
@@ -33,6 +33,7 @@ namespace ops
 enum class ElementwiseBinaryType
 {
   kFloorDiv,
+  kFloorMod,
   kLogicalAnd,
   kLogicalOr,
   kMax,
index d58937b..f8e26e1 100644 (file)
@@ -63,6 +63,7 @@ void castPtr(const FromT *in, DataPtr out, int num_elements, ir::DataType data_t
                      [](FromT a) { return static_cast<uint8_t>(a); });
       return;
     case ir::DataType::BOOL8:
+      static_assert(sizeof(bool) == 1, "cpu backend supports bool type which is 1 byte");
       std::transform(in, in + num_elements, out.b, [](FromT a) { return static_cast<bool>(a); });
       return;
     case ir::DataType::INT64:
@@ -298,6 +299,7 @@ void ElementwiseUnaryLayer::configure(const IPortableTensor *input, IPortableTen
     case ElementwiseUnaryType::kLogicalNot:
       if ((input->data_type() == OperandType::BOOL8))
       {
+        static_assert(sizeof(bool) == 1, "cpu backend supports bool type which is 1 byte");
         _kernel = logicalNot;
       }
       else
index 3e95c12..7ad81e1 100644 (file)
@@ -45,7 +45,7 @@ public:
 
   void run() override;
 
-private:
+protected:
   const IPortableTensor *_input;
   const IPortableTensor *_axes;
   IPortableTensor *_output;
index 1fefc32..29452c4 100644 (file)
@@ -189,6 +189,18 @@ template <typename T> T *getBuffer(IPortableTensor *tensor)
   return reinterpret_cast<T *>(tensor->buffer());
 }
 
+template <> inline const bool *getBuffer(const IPortableTensor *tensor)
+{
+  static_assert(sizeof(bool) == 1, "cpu backend supports bool type which is 1 byte");
+  return reinterpret_cast<const bool *>(tensor->buffer());
+}
+
+template <> inline bool *getBuffer(IPortableTensor *tensor)
+{
+  static_assert(sizeof(bool) == 1, "cpu backend supports bool type which is 1 byte");
+  return reinterpret_cast<bool *>(tensor->buffer());
+}
+
 } // namespace ops
 } // namespace cpu
 } // namespace backend
index d9da564..aceb42d 100644 (file)
@@ -28,29 +28,38 @@ namespace ops
 {
 
 PadLayer::PadLayer()
-  : _input(nullptr), _output(nullptr), _padData(), _padRank(), _constantValueData()
+  : _input(nullptr), _pad(nullptr), _value(nullptr), _output(nullptr), _constantValueData()
 {
   // DO NOTHING
 }
 
 template <typename T> void PadLayer::padImpl(const T *constant_value_data)
 {
-  nnfw::cker::Pad<T>(_padData, _padRank, getShape(_input), getBuffer<T>(_input), getShape(_output),
+  assert(_pad->data_type() == onert::ir::DataType::INT32);
+  assert(_pad->buffer());
+  const auto pad_data = reinterpret_cast<const int32_t *>(_pad->buffer());
+  auto pad_rank = _pad->getShape().dim(0);
+  nnfw::cker::Pad<T>(pad_data, pad_rank, getShape(_input), getBuffer<T>(_input), getShape(_output),
                      getBuffer<T>(_output), constant_value_data);
 }
 
-void PadLayer::configure(const IPortableTensor *input, IPortableTensor *output,
-                         const int32_t *padData, int32_t padRank, const void *constantValueData)
+void PadLayer::configure(const IPortableTensor *input, const IPortableTensor *pad,
+                         const IPortableTensor *value, IPortableTensor *output)
 {
   _input = input;
+  _pad = pad;
+  _value = value;
   _output = output;
-  memcpy(_padData, padData, sizeof(_padData));
-  _padRank = padRank;
-  _constantValueData.v = constantValueData;
 }
 
 void PadLayer::run()
 {
+  if (_value != nullptr) // isPadV2
+  {
+    assert(_value->buffer());
+    _constantValueData.v = reinterpret_cast<const void *>(_value->buffer());
+  }
+
   switch (_input->data_type())
   {
     case OperandType::FLOAT32:
index efd73d5..b6cadda 100644 (file)
@@ -41,17 +41,16 @@ public:
 public:
   template <typename T> void padImpl(const T *constant_value_data);
 
-  void configure(const IPortableTensor *input, IPortableTensor *output, const int32_t *padData,
-                 int32_t padRank, const void *constantValueData = nullptr);
+  void configure(const IPortableTensor *input, const IPortableTensor *pad,
+                 const IPortableTensor *value, IPortableTensor *output);
 
   void run() override;
 
-private:
+protected:
   const IPortableTensor *_input;
+  const IPortableTensor *_pad;
+  const IPortableTensor *_value;
   IPortableTensor *_output;
-
-  int32_t _padData[8];
-  int32_t _padRank;
   ConstDataPtr _constantValueData;
 };
 
index b378359..adc8955 100644 (file)
@@ -53,10 +53,11 @@ public:
 
   void run() override;
 
-private:
+protected:
   const IPortableTensor *_input;
   IPortableTensor *_output;
 
+private:
   std::function<void(const IPortableTensor *, IPortableTensor *)> _kernel;
 };
 
index 66b5abb..8c2bc1b 100644 (file)
@@ -87,6 +87,7 @@ template <>
 std::function<void(const IPortableTensor *, IPortableTensor *, const std::vector<int> &)>
 evalType<bool>(bool keep_dims, nnfw::cker::Reduce &reduce_kernel, ReduceType reduce_type)
 {
+  static_assert(sizeof(bool) == 1, "cpu backend supports bool type which is 1 byte");
   switch (reduce_type)
   {
     case ReduceType::kAny:
index e63be0c..fd20136 100644 (file)
@@ -44,10 +44,11 @@ public:
 
   void run() override;
 
-private:
+protected:
   const IPortableTensor *_input;
   IPortableTensor *_output;
 
+private:
   float _beta;
 
   float _table[256];
diff --git a/runtime/onert/backend/gpu_cl/BackendContext.cc b/runtime/onert/backend/gpu_cl/BackendContext.cc
deleted file mode 100644 (file)
index 9d45770..0000000
+++ /dev/null
@@ -1,117 +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 "BackendContext.h"
-
-#include "ConstantInitializer.h"
-#include "TensorBuilder.h"
-#include "KernelGenerator.h"
-
-#include "util/logging.h"
-#include "ir/Index.h"
-#include "ir/Operations.h"
-#include "ir/OperandIndexMap.h"
-#include "ir/OperandIndexSequence.h"
-
-namespace onert
-{
-namespace backend
-{
-namespace gpu_cl
-{
-
-void BackendContext::registerTensorInfo(const ir::OperandIndex &ind, const ir::OperandInfo &info,
-                                        ir::Layout backend_layout)
-{
-  TensorType type = TensorType::TENSOR_TYPE_VALID;
-  tensor_builder->registerTensorInfo(ind, info, backend_layout, type);
-}
-
-ITensorRegistry *BackendContext::genTensors()
-{
-  ir::OperandIndexMap<TensorType> type_map;
-
-  for (const auto &ind : graph()->getInputs())
-  {
-    type_map[ind] = TensorType::TENSOR_TYPE_INPUT;
-  }
-
-  for (const auto &ind : graph()->getOutputs())
-  {
-    type_map[ind] = TensorType::TENSOR_TYPE_OUTPUT;
-  }
-  graph()->operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &obj) {
-    if (external_operands().contains(ind))
-      return;
-
-    const auto frontend_layout = graph()->layout();
-    const auto backend_layout = operand_layouts().at(ind);
-    ir::OperandInfo backend_info{permuteShape(obj.shape(), frontend_layout, backend_layout),
-                                 obj.typeInfo(), obj.info().memAllocType(), obj.isConstant()};
-    if (obj.isConstant())
-    {
-      type_map[ind] = TensorType::TENSOR_TYPE_INPUT;
-    }
-    tensor_builder->registerTensorInfo(ind, backend_info, backend_layout, type_map[ind]);
-  });
-
-  // TODO Get compiler options from compiler, and use it rather than getting it from Env
-  if (util::getConfigString(util::config::EXECUTOR) == "Linear")
-  {
-    planTensors();
-  }
-  else
-  {
-    // 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
-    graph()->operands().iterate([&](const ir::OperandIndex &ind, const ir::Operand &) {
-      if (tensor_builder->isRegistered(ind))
-        tensor_builder->notifyFirstUse(ind);
-    });
-  }
-  tensor_builder->prepare();
-  return tensor_registry.get();
-}
-
-FunctionMap BackendContext::genKernels()
-{
-  FunctionMap fn_map;
-
-  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));
-  }
-
-  kernel_gen->get_operation(fn_map);
-  tensor_builder->allocate();
-  // NOTE For memory optimization, we want to free some operand data
-  const_cast<ir::Graph &>(*_data.graph)
-    .operands()
-    .iterate([&](const ir::OperandIndex &, ir::Operand &obj) { obj.releaseData(); });
-
-  for (auto &&it : fn_map)
-  {
-    auto &fn_seq = it.second;
-    fn_seq->iterate([&](exec::IFunction &ifunc) { ifunc.prepare(); });
-  }
-
-  return fn_map;
-}
-
-} // namespace gpu_cl
-} // namespace backend
-} // namespace onert
diff --git a/runtime/onert/backend/gpu_cl/CMakeLists.txt b/runtime/onert/backend/gpu_cl/CMakeLists.txt
deleted file mode 100644 (file)
index d62dbd8..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-set(LIB_ONERT_BACKEND_GPU_CL onert_backend_gpu_cl)
-
-if(NOT BUILD_GPU_CL)
-  return()
-endif(NOT BUILD_GPU_CL)
-
-nnas_find_package(Opencl_Headers QUIET)
-if(NOT Opencl_Headers_FOUND)
-  return()
-endif(NOT Opencl_Headers_FOUND)
-
-nnas_find_package(Farmhash QUIET)
-if(NOT Farmhash_FOUND)
-  return()
-endif(NOT Farmhash_FOUND)
-
-nnas_find_package(Abseil QUIET)
-if(NOT Abseil_FOUND)
-  return()
-endif(NOT Abseil_FOUND)
-
-nnfw_find_package(Fp16 QUIET)
-if(NOT Fp16_FOUND)
-  return()
-endif(NOT Fp16_FOUND)
-
-nnas_find_package(VulkanSource QUIET)
-if(NOT VulkanSource_FOUND)
-  return()
-endif(NOT VulkanSource_FOUND)
-
-nnas_find_package(Opengl_HeadersSource QUIET)
-if(NOT Opengl_HeadersSource_FOUND)
-  return()
-endif(NOT Opengl_HeadersSource_FOUND)
-
-nnas_find_package(Egl_HeadersSource QUIET)
-if(NOT Egl_HeadersSource_FOUND)
-  return()
-endif(NOT Egl_HeadersSource_FOUND)
-
-if (NOT ${TARGET_OS} MATCHES "tizen")
-  nnas_find_package(FlatBuffers REQUIRED)
-endif ()
-
-nnfw_find_package(TensorFlowGpu QUIET)
-if(NOT TensorFlowGpu_FOUND)
-  message(FATAL_ERROR 'TensorFlowGpu lib not found')
-  return()
-endif(NOT TensorFlowGpu_FOUND)
-
-file(GLOB_RECURSE SOURCES "*.cc")
-
-add_library(${LIB_ONERT_BACKEND_GPU_CL} SHARED ${SOURCES})
-
-target_include_directories(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
-target_include_directories(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE ${TensorFlowSource_DIR})
-target_include_directories(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE ${VulkanSource_DIR}/include)
-target_include_directories(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE ${Opengl_HeadersSource_DIR}/api)
-target_include_directories(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE ${Egl_HeadersSource_DIR}/api)
-
-if (${TARGET_OS} MATCHES "tizen")
-    target_compile_options(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE "-Wno-error=deprecated-copy")
-endif ()
-
-target_compile_options(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE "-DCL_TARGET_OPENCL_VERSION=220" "-DEGL_NO_X11")
-
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE abseil)
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE dl)
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE farmhash)
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE OpenCL_Headers)
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE fp16)
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE TensorFlowGpu)
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE onert_core)
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE ${LIB_ONERT_BACKEND_CL_COMMON})
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE nnfw_common)
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE nnfw_coverage)
-if (${TARGET_OS} MATCHES "tizen")
-  target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE flatbuffers)
-else()
-  target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE flatbuffers::flatbuffers)
-endif ()
-
-set_target_properties(${LIB_ONERT_BACKEND_GPU_CL} PROPERTIES OUTPUT_NAME backend_gpu_cl)
-
-if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
-  add_custom_command(TARGET ${LIB_ONERT_BACKEND_GPU_CL} POST_BUILD
-                     COMMAND ${CMAKE_STRIP} "--strip-unneeded" $<TARGET_FILE_NAME:${LIB_ONERT_BACKEND_GPU_CL}>)
-endif()
-
-add_library(tflite_ignore_warnings INTERFACE)
-target_compile_options(tflite_ignore_warnings INTERFACE -Wno-unused-parameter -Wno-sign-compare)
-target_link_libraries(${LIB_ONERT_BACKEND_GPU_CL} PRIVATE tflite_ignore_warnings)
-
-install(TARGETS ${LIB_ONERT_BACKEND_GPU_CL} DESTINATION lib)
diff --git a/runtime/onert/backend/gpu_cl/ClConstantInitializer.h b/runtime/onert/backend/gpu_cl/ClConstantInitializer.h
deleted file mode 100644 (file)
index 95e228a..0000000
+++ /dev/null
@@ -1,138 +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.
- */
-
-#ifndef __ONERT_COMPILER_GPU_CL_CLCONSTANT_INITIALIZER_H__
-#define __ONERT_COMPILER_GPU_CL_CLCONSTANT_INITIALIZER_H__
-
-#include <unordered_map>
-#include <functional>
-
-#include <ir/Coordinates.h>
-#include <ir/Layout.h>
-#include <ir/Operand.h>
-#include <ir/Operands.h>
-#include <ir/OperationVisitor.h>
-#include <backend/ITensorRegistry.h>
-#include <util/logging.h>
-
-namespace onert
-{
-namespace backend
-{
-namespace gpu_cl
-{
-
-template <typename T>
-static void Init(const onert::ir::Operand &model_obj, onert::backend::ITensor &obj, const bool copy,
-                 const onert::ir::Layout frontend_layout = onert::ir::Layout::UNKNOWN)
-{
-  const auto shape = model_obj.shape();
-  assert(model_obj.data());
-  obj.access([&](::onert::backend::ITensor &tensor) {
-    switch (shape.rank())
-    {
-      case 0:
-      case 1:
-      case 2:
-      case 3:
-      case 4:
-        if (copy)
-        {
-          tensor.enqueueWriteBuffer(model_obj.data()->base(), true);
-        }
-        else
-        {
-          // NYI
-          (void)frontend_layout;
-          throw std::runtime_error{"Not yet supported"};
-        }
-        break;
-      default:
-        throw std::runtime_error{"Not yet supported"};
-    }
-  });
-}
-
-template <typename T>
-void copyInit(const onert::ir::Operand &model_obj, onert::backend::ITensor &obj)
-{
-  Init<T>(model_obj, obj, true);
-}
-
-template <typename T>
-void permuteInit(const onert::ir::Operand &model_obj, onert::backend::ITensor &obj,
-                 const onert::ir::Layout frontend_layout)
-{
-  const bool copy = frontend_layout == obj.layout();
-  Init<T>(model_obj, obj, copy, frontend_layout);
-}
-
-class ClConstantInitializer : public ir::OperationVisitor
-{
-public:
-  void run()
-  {
-    assert(_tensor_reg);
-    for (const auto &it : _init_map)
-    {
-      const auto &ind = it.first;
-      const auto &fn = it.second;
-
-      const auto &model_obj = _operands.at(ind);
-      auto tensor_obj = _tensor_reg->getNativeITensor(ind);
-      assert(tensor_obj != nullptr);
-      fn(model_obj, *tensor_obj);
-      VERBOSE(FillOperandData) << "Fill data for operand " << ind << std::endl;
-    }
-    _init_map.clear();
-  }
-
-public:
-  ClConstantInitializer(const ir::Operands &operands,
-                        const std::shared_ptr<ITensorRegistry> &tensor_reg);
-
-public:
-  using Initializer = std::function<void(const ir::Operand &, backend::ITensor &)>;
-
-public:
-  void registerDefaultInitializer(const ir::OperandIndex &index, const ir::Operand &obj)
-  {
-    registerPermuteInitializer(index, obj);
-  }
-  void registerCopyInitializer(const ir::OperandIndex &index, const ir::Operand &obj);
-  void registerPermuteInitializer(const ir::OperandIndex &index, const ir::Operand &obj);
-
-public:
-  void setLayout(ir::Layout layout) { _current_layout = layout; }
-  bool exist(const ir::OperandIndex &ind) { return _init_map.find(ind) != _init_map.end(); }
-
-public:
-protected:
-  void copyInputInitialize(const ir::Operation &node, uint32_t index);
-  void permuteInputInitialize(const ir::Operation &node, uint32_t index);
-
-protected:
-  const ir::Operands &_operands;
-  std::shared_ptr<ITensorRegistry> _tensor_reg;
-  std::unordered_map<ir::OperandIndex, Initializer> _init_map;
-  ir::Layout _current_layout;
-};
-
-} // namespace gpu_cl
-} // namespace backend
-} // namespace onert
-
-#endif // __ONERT_COMPILER_GPU_CL_CLCONSTANT_INITIALIZER_H__
diff --git a/runtime/onert/backend/gpu_cl/KernelGenerator.cc b/runtime/onert/backend/gpu_cl/KernelGenerator.cc
deleted file mode 100644 (file)
index a24c4f5..0000000
+++ /dev/null
@@ -1,709 +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 <stdexcept>
-
-#include <backend/basic/KernelGeneratorBase.h>
-
-#include "KernelGenerator.h"
-
-#include "ClFunction.h"
-#include "TensorManager.h"
-
-#include "tensorflow/lite/delegates/gpu/common/shape.h"
-#include "tensorflow/lite/delegates/gpu/common/tensor.h"
-#include "tensorflow/lite/delegates/gpu/common/tasks/elementwise.h"
-#include "tensorflow/lite/delegates/gpu/common/selectors/convolution_selector.h"
-#include "tensorflow/lite/delegates/gpu/common/selectors/dw_convolution_selector.h"
-#include "tensorflow/lite/delegates/gpu/common/selectors/simple_selectors.h"
-
-#include "ir/Operations.h"
-#include "ir/Operations.Include.h"
-#include "ir/Index.h"
-#include "ir/DataType.h"
-#include "ir/InternalType.h"
-#include "exec/NopFunction.h"
-#include "exec/FunctionSequence.h"
-#include "util/logging.h"
-#include "util/Utils.h"
-
-namespace onert
-{
-namespace backend
-{
-namespace gpu_cl
-{
-
-void KernelGenerator::addClNode(const std::vector<ir::OperandIndex> &inputs,
-                                const std::vector<ir::OperandIndex> &outputs,
-                                std::unique_ptr<tflite::gpu::GPUOperation> gpu_op)
-{
-  tflite::gpu::cl::CLNode cl_node;
-  cl_node.cl_operation.Init(std::move(gpu_op));
-  cl_node.inputs.resize(inputs.size());
-  for (size_t i = 0; i < inputs.size(); ++i)
-  {
-    cl_node.inputs[i] = inputs[i].value();
-  }
-  cl_node.outputs.resize(outputs.size());
-  for (size_t i = 0; i < outputs.size(); ++i)
-  {
-    cl_node.outputs[i] = outputs[i].value();
-  }
-  _nodes.push_back(std::move(cl_node));
-  _operation_indexes.push_back(_operation_index);
-  return;
-}
-
-void KernelGenerator::get_operation(FunctionMap &Functions)
-{
-  size_t size = _nodes.size();
-  size_t i = 0;
-  for (auto &&it : Functions)
-  {
-    auto index = it.first;
-    auto node_index = _operation_indexes[i];
-    while (index == node_index)
-    {
-      auto &fn_seq = it.second;
-      auto &node = _nodes[i++];
-      for (size_t j = 0; j < node.inputs.size(); ++j)
-      {
-        uint32_t idx = node.inputs[j];
-        node.cl_operation.GetGpuOperation().SetSrc(
-          _tensor_reg->getClTensor(ir::OperandIndex{idx})->handle(), j);
-      }
-      for (size_t j = 0; j < node.outputs.size(); ++j)
-      {
-        uint32_t idx = node.outputs[j];
-        node.cl_operation.GetGpuOperation().SetDst(
-          _tensor_reg->getClTensor(ir::OperandIndex{idx})->handle(), j);
-      }
-      fn_seq->iterate([&](exec::IFunction &ifunc) {
-        static_cast<ClFunction &>(ifunc).add_operation(&node.cl_operation);
-      });
-      if (i == size)
-      {
-        break;
-      }
-      node_index = _operation_indexes[i];
-    }
-    if (i == size)
-    {
-      break;
-    }
-  }
-}
-
-absl::Status KernelGenerator::readConstTensor(const ir::OperandIndex &index,
-                                              tflite::gpu::TensorOrScalar *param)
-{
-  const auto shape = _ctx.at(index).shape();
-  if (shape.rank() == 0 && shape.num_elements() == 1)
-  {
-    tflite::gpu::Tensor<tflite::gpu::Scalar, tflite::gpu::DataType::FLOAT32> tensor;
-    tensor.shape.v = 1;
-    tensor.data.resize(1);
-    std::memcpy(&tensor.data[0], _ctx.at(index).data()->base(), _ctx.at(index).operandSize());
-    *param = tensor.data[0];
-  }
-  else
-  {
-    if (CheckIfLinearConvertible(&shape))
-    {
-      tflite::gpu::Tensor<tflite::gpu::Linear, tflite::gpu::DataType::FLOAT32> tensor;
-      tensor.shape.v = shape.dim(shape.rank() - 1);
-      tensor.data.resize(shape.num_elements());
-      std::memcpy(&tensor.data[0], _ctx.at(index).data()->base(), _ctx.at(index).operandSize());
-      *param = std::move(tensor);
-    }
-    else
-    {
-      tflite::gpu::Tensor<tflite::gpu::HWC, tflite::gpu::DataType::FLOAT32> tensor;
-      if (shape.rank() == 3)
-      {
-        tensor.shape.h = shape.dim(0);
-        tensor.shape.w = shape.dim(1);
-        tensor.shape.c = shape.dim(2);
-      }
-      else if (shape.rank() == 4)
-      {
-        if (shape.dim(0) != 1)
-        {
-          return absl::UnimplementedError("Batch size is not equal to 1.");
-        }
-        tensor.shape.h = shape.dim(1);
-        tensor.shape.w = shape.dim(2);
-        tensor.shape.c = shape.dim(3);
-      }
-      else
-      {
-        return absl::InvalidArgumentError(
-          "Expected a 3D tensor of shape HxWxC or a 4D tensor of shape 1xHxWxC.");
-      }
-      tensor.data.resize(shape.num_elements());
-      std::memcpy(&tensor.data[0], _ctx.at(index).data()->base(), _ctx.at(index).operandSize());
-      *param = std::move(tensor);
-    }
-  }
-  return absl::OkStatus();
-}
-
-absl::Status KernelGenerator::readConstTensor(
-  const ir::OperandIndex &index,
-  absl::variant<tflite::gpu::Tensor<tflite::gpu::Linear, tflite::gpu::DataType::FLOAT32>,
-                tflite::gpu::Tensor<tflite::gpu::HWC, tflite::gpu::DataType::FLOAT32>> *alpha)
-{
-  const auto shape = _ctx.at(index).shape();
-  if (CheckIfLinearConvertible(&shape))
-  {
-    tflite::gpu::Tensor<tflite::gpu::Linear, tflite::gpu::DataType::FLOAT32> tensor;
-    tensor.shape.v = shape.dim(shape.rank() - 1);
-    tensor.data.resize(shape.num_elements());
-    std::memcpy(&tensor.data[0], _ctx.at(index).data()->base(), _ctx.at(index).operandSize());
-    *alpha = std::move(tensor);
-  }
-  else
-  {
-    tflite::gpu::Tensor<tflite::gpu::HWC, tflite::gpu::DataType::FLOAT32> tensor;
-    if (shape.rank() == 3)
-    {
-      tensor.shape.h = shape.dim(0);
-      tensor.shape.w = shape.dim(1);
-      tensor.shape.c = shape.dim(2);
-    }
-    else if (shape.rank() == 4)
-    {
-      if (shape.dim(0) != 1)
-      {
-        return absl::UnimplementedError("Batch size is not equal to 1.");
-      }
-      tensor.shape.h = shape.dim(1);
-      tensor.shape.w = shape.dim(2);
-      tensor.shape.c = shape.dim(3);
-    }
-    else
-    {
-      return absl::InvalidArgumentError(
-        "Expected a 3D tensor of shape HxWxC or a 4D tensor of shape 1xHxWxC.");
-    }
-    tensor.data.resize(shape.num_elements());
-    std::memcpy(&tensor.data[0], _ctx.at(index).data()->base(), _ctx.at(index).operandSize());
-    *alpha = std::move(tensor);
-  }
-  return absl::OkStatus();
-}
-
-KernelGenerator::KernelGenerator(
-  const ir::Graph &graph, const std::shared_ptr<TensorBuilder> &tensor_builder,
-  const std::shared_ptr<TensorRegistry> &tensor_reg,
-  const std::shared_ptr<tflite::gpu::cl::CreationContext> &creation_context)
-  : basic::KernelGeneratorBase{graph}, _ctx(graph.operands()),
-    _operations_ctx(graph.operations()), _current_layout{graph.layout()},
-    _tensor_builder(tensor_builder), _tensor_reg(tensor_reg), _creation_context(creation_context)
-{
-}
-
-std::unique_ptr<exec::FunctionSequence> KernelGenerator::generate(ir::OperationIndex ind)
-{
-  auto fn_seq = std::make_unique<exec::FunctionSequence>();
-  fn_seq->enableDynamicShapeInferer(false);
-  _operation_index = ind;
-  const auto &op = _graph.operations().at(ind);
-  op.accept(*this);
-  fn_seq->append(releaseFunction());
-  return fn_seq;
-}
-
-void KernelGenerator::visit(const ir::operation::BinaryArithmetic &node)
-{
-  const auto ofm_index{node.getOutputs().at(0)};
-  const auto lhs_index{node.getInputs().at(ir::operation::BinaryArithmetic::Input::LHS)};
-  const auto rhs_index{node.getInputs().at(ir::operation::BinaryArithmetic::Input::RHS)};
-
-  tflite::gpu::OperationDef op_def;
-  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
-
-  const bool lhs_const = _ctx.at(lhs_index).isConstant();
-  const bool rhs_const = _ctx.at(rhs_index).isConstant();
-
-  if (lhs_const && rhs_const)
-  {
-    throw std::runtime_error("No runtime input tensors for " + node.name());
-  }
-
-  auto fn = std::make_unique<ClFunction>(_creation_context);
-  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
-
-  tflite::gpu::OperationType op_type = convertArithmeticType(node.param().arithmetic_type);
-
-  if (!lhs_const && !rhs_const)
-  {
-    auto lhs_shape = _tensor_reg->getClTensor(lhs_index)->get_info()._shape;
-    auto rhs_shape = _tensor_reg->getClTensor(rhs_index)->get_info()._shape;
-
-    bool swap =
-      (op_type == tflite::gpu::OperationType::MUL) &&
-      (lhs_shape.h <= rhs_shape.h && lhs_shape.w <= rhs_shape.w && lhs_shape.c <= rhs_shape.c);
-
-    auto first_index = swap ? rhs_index : lhs_index;
-    auto second_index = swap ? lhs_index : rhs_index;
-
-    op_def.src_tensors.push_back(_tensor_reg->getClTensor(first_index)->get_info()._desc);
-    op_def.src_tensors.push_back(_tensor_reg->getClTensor(second_index)->get_info()._desc);
-    op_def.dst_tensors.push_back(_tensor_reg->getClTensor(ofm_index)->get_info()._desc);
-
-    auto second_shape = _tensor_reg->getClTensor(second_index)->get_info()._shape;
-
-    tflite::gpu::GPUOperation operation = CreateElementwiseTwoInput(op_def, op_type, second_shape);
-    gpu_op = std::make_unique<tflite::gpu::GPUOperation>(std::move(operation));
-
-    addClNode({first_index, second_index}, {ofm_index}, std::move(gpu_op));
-  }
-  else
-  {
-    auto non_const_index = rhs_const ? lhs_index : rhs_index;
-    auto const_index = rhs_const ? rhs_index : lhs_index;
-
-    op_def.dst_tensors.push_back(_tensor_reg->getClTensor(ofm_index)->get_info()._desc);
-    op_def.src_tensors.push_back(_tensor_reg->getClTensor(non_const_index)->get_info()._desc);
-
-    tflite::gpu::ElementwiseAttributes attr;
-
-    if (!readConstTensor(const_index, &attr.param).ok())
-    {
-      throw std::runtime_error("BinaryArithmetic unsupported constant tensor");
-    }
-
-    tflite::gpu::GPUOperation operation =
-      CreateElementwise(_creation_context->GetGpuInfo(), op_def, op_type, attr);
-    gpu_op = absl::make_unique<tflite::gpu::GPUOperation>(std::move(operation));
-
-    addClNode({non_const_index}, {ofm_index}, std::move(gpu_op));
-  }
-  _return_fn = std::move(fn);
-}
-
-void KernelGenerator::visit(const ir::operation::Conv2D &node)
-{
-  auto output{node.getOutputs().at(0)};
-
-  auto input{node.getInputs().at(ir::operation::Conv2D::INPUT)};
-  auto kernel{node.getInputs().at(ir::operation::Conv2D::KERNEL)};
-  auto bias{node.getInputs().at(ir::operation::Conv2D::BIAS)};
-
-  const auto param = node.param();
-
-  tflite::gpu::OperationDef op_def;
-  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
-
-  op_def.src_tensors.push_back(_tensor_reg->getClTensor(input)->get_info()._desc);
-
-  auto input_shape = _tensor_reg->getClTensor(input)->get_info()._shape;
-  auto kernel_shape = _tensor_reg->getClTensor(kernel)->get_info()._shape;
-  auto output_shape = _tensor_reg->getClTensor(output)->get_info()._shape;
-  auto bias_shape = _tensor_reg->getClTensor(bias)->get_info()._shape;
-
-  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(output)->get_info()._desc);
-
-  tflite::gpu::ModelHints hints;
-  std::unique_ptr<tflite::gpu::GPUOperation>
-    gpu_op; // = InitSingleOpSubgraph(inputs, outputs, gpu_subgraph);
-
-  auto kernel_tensor = _tensor_reg->getClTensor(kernel);
-  auto bias_tensor = _tensor_reg->getClTensor(bias);
-
-  tflite::gpu::Convolution2DAttributes attr;
-  attr.strides = ToHW(param.stride.vertical, param.stride.horizontal);
-  attr.dilations =
-    tflite::gpu::HW(std::max(static_cast<u_int32_t>(1), param.dilation.height_factor),
-                    std::max(static_cast<u_int32_t>(1), param.dilation.width_factor));
-
-  bool is_weight = (_ctx.at(kernel).isConstant() ? true : false);
-
-  if (is_weight)
-  {
-    attr.weights.id = kernel.value();
-    attr.weights.shape.o = kernel_shape.b;
-    attr.weights.shape.h = kernel_shape.h;
-    attr.weights.shape.w = kernel_shape.w;
-    attr.weights.shape.i = kernel_shape.c;
-    attr.weights.data.resize(kernel_shape.DimensionsProduct());
-    memcpy(attr.weights.data.data(), _ctx.at(kernel).data()->base(), kernel_tensor->total_size());
-  }
-
-  attr.bias.id = bias.value();
-  // TODO Modify
-  attr.bias.shape.v = bias_shape.b != 1 ? bias_shape.b : bias_shape.c;
-  attr.bias.data.resize(bias_shape.DimensionsProduct());
-  memcpy(attr.bias.data.data(), _ctx.at(bias).data()->base(), bias_tensor->total_size());
-
-  UpdatePadding(param.padding.type, input_shape, &attr);
-
-  gpu_op = SelectConvolution(attr, output_shape, _creation_context->GetGpuInfo(), op_def, hints);
-
-  tflite::gpu::cl::CLNode cl_node;
-  cl_node.inputs.resize(1);
-  cl_node.inputs[0] = input.value();
-  cl_node.outputs.resize(1);
-
-  auto fn = std::make_unique<ClFunction>(_creation_context);
-
-  const auto activation = node.param().activation;
-
-  switch (activation)
-  {
-    case ir::Activation::NONE:
-    {
-      addClNode({input}, {output}, std::move(gpu_op));
-      break;
-    }
-    case ir::Activation::RELU:
-    case ir::Activation::RELU6:
-    {
-      std::unique_ptr<tflite::gpu::GPUOperation> gpu_op_1;
-      tflite::gpu::OperationDef op_def_1;
-      const auto shape = _ctx.at(output).shape();
-      auto new_ind = _tensor_reg->addNewClTensor(shape);
-
-      addClNode({input}, {new_ind}, std::move(gpu_op));
-
-      op_def_1.precision = tflite::gpu::CalculationsPrecision::F32;
-      op_def_1.src_tensors.push_back(_tensor_reg->getClTensor(output)->get_info()._desc);
-      op_def_1.dst_tensors.push_back(_tensor_reg->getClTensor(output)->get_info()._desc);
-
-      tflite::gpu::ReLUAttributes attr_1;
-      if (activation == ir::Activation::RELU6)
-      {
-        attr_1.clip = 6;
-      }
-      else
-      {
-        attr_1.clip = 0;
-      }
-      attr_1.alpha = 0;
-      gpu_op_1 = SelectReLU(attr_1, op_def_1);
-
-      addClNode({new_ind}, {output}, std::move(gpu_op_1));
-      break;
-    }
-    default:
-    {
-      throw std::runtime_error("gpu_cl KernelGenerator : Not supported Conv2D activiation");
-    }
-  }
-  _return_fn = std::move(fn);
-}
-
-void KernelGenerator::visit(const ir::operation::DepthwiseConv2D &node)
-{
-  using ir::operation::DepthwiseConv2D;
-
-  const auto ofm_index{node.getOutputs().at(0)};
-  const auto ifm_index{node.getInputs().at(DepthwiseConv2D::Input::INPUT)};
-  const auto ker_index{node.getInputs().at(DepthwiseConv2D::Input::KERNEL)};
-  const auto bias_index{node.getInputs().at(DepthwiseConv2D::Input::BIAS)};
-
-  const auto stride = node.param().stride;
-  const auto dilation = node.param().dilation;
-  const auto padding = node.param().padding;
-
-  const auto multiplier = node.param().multiplier;
-
-  bool is_weight = (_ctx.at(ker_index).isConstant() ? true : false);
-  tflite::gpu::OperationDef op_def;
-  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
-
-  op_def.src_tensors.push_back(_tensor_reg->getClTensor(ifm_index)->get_info()._desc);
-  auto input_shape = _tensor_reg->getClTensor(ifm_index)->get_info()._shape;
-
-  auto ker_shape = _tensor_reg->getClTensor(ker_index)->get_info()._shape;
-
-  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(ofm_index)->get_info()._desc);
-  auto out_shape = _tensor_reg->getClTensor(ofm_index)->get_info()._shape;
-  auto bias_shape = _tensor_reg->getClTensor(bias_index)->get_info()._shape;
-
-  tflite::gpu::DepthwiseConvolution2DAttributes attr;
-  attr.strides = ToHW(stride.vertical, stride.horizontal);
-  attr.dilations = tflite::gpu::HW(std::max(static_cast<u_int32_t>(1), dilation.height_factor),
-                                   std::max(static_cast<u_int32_t>(1), dilation.width_factor));
-
-  if (is_weight)
-  {
-    attr.weights.id = ker_index.value();
-    attr.weights.shape.o = ker_shape.b;
-    attr.weights.shape.h = ker_shape.h;
-    attr.weights.shape.w = ker_shape.w;
-    attr.weights.shape.i = ker_shape.c;
-    attr.weights.data.resize(ker_shape.DimensionsProduct());
-    memcpy(attr.weights.data.data(), _ctx.at(ker_index).data()->base(),
-           _ctx.at(ker_index).operandSize());
-  }
-  attr.bias.id = bias_index.value();
-  attr.bias.shape.v = bias_shape.b != 1 ? bias_shape.b : bias_shape.c;
-  attr.bias.data.resize(bias_shape.DimensionsProduct());
-  memcpy(attr.bias.data.data(), _ctx.at(bias_index).data()->base(),
-         _ctx.at(bias_index).operandSize());
-  UpdatePadding(padding.type, input_shape, &attr);
-
-  if (multiplier != 1)
-  {
-    const int input_depth = input_shape.c;
-    const int filter_height = ker_shape.h;
-    const int filter_width = ker_shape.w;
-    const int output_depth = out_shape.c;
-
-    tflite::gpu::Tensor<tflite::gpu::OHWI, tflite::gpu::DataType::FLOAT32> weights;
-    weights.id = attr.weights.id;
-    weights.shape = tflite::gpu::OHWI(output_depth, filter_height, filter_width, input_depth);
-    weights.data.resize(weights.shape.DimensionsProduct());
-    float *dst = &weights.data[0];
-    for (int j = 0; j < output_depth; ++j)
-    {
-      const float *src = attr.weights.data.data() + j;
-      for (int i = 0; i < filter_height * filter_width; ++i)
-      {
-        *dst = *src;
-        dst++;
-        src += output_depth;
-      }
-    }
-    attr.weights = std::move(weights);
-  }
-
-  auto fn = std::make_unique<ClFunction>(_creation_context);
-  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
-
-  if (is_weight)
-  {
-    gpu_op = SelectDWConvolution(attr, _creation_context->GetGpuInfo(), op_def);
-  }
-  else
-  {
-    if (ker_shape.b != 1)
-    {
-      throw std::runtime_error(
-        "No support of depthwise runtime weights with channel multiplier != 1");
-    }
-    gpu_op = SelectDWConvolutionDynamicWeights(attr, _creation_context->GetGpuInfo(), op_def);
-  }
-
-  const auto activation = node.param().activation;
-
-  switch (activation)
-  {
-    case ir::Activation::NONE:
-    {
-      addClNode({ifm_index}, {ofm_index}, std::move(gpu_op));
-      break;
-    }
-    case ir::Activation::RELU:
-    case ir::Activation::RELU6:
-    {
-      std::unique_ptr<tflite::gpu::GPUOperation> gpu_op_1;
-      tflite::gpu::OperationDef op_def_1;
-      const auto shape = _ctx.at(ofm_index).shape();
-      auto new_ind = _tensor_reg->addNewClTensor(shape);
-
-      addClNode({ifm_index}, {new_ind}, std::move(gpu_op));
-
-      op_def_1.precision = tflite::gpu::CalculationsPrecision::F32;
-
-      op_def_1.src_tensors.push_back(_tensor_reg->getClTensor(ofm_index)->get_info()._desc);
-      op_def_1.dst_tensors.push_back(_tensor_reg->getClTensor(ofm_index)->get_info()._desc);
-
-      tflite::gpu::ReLUAttributes attr_1;
-      if (activation == ir::Activation::RELU6)
-      {
-        attr_1.clip = 6;
-      }
-      else
-      {
-        attr_1.clip = 0;
-      }
-      attr_1.alpha = 0;
-      gpu_op_1 = SelectReLU(attr_1, op_def_1);
-
-      addClNode({new_ind}, {ofm_index}, std::move(gpu_op_1));
-      break;
-    }
-    default:
-    {
-      throw std::runtime_error("gpu_cl KernelGenerator : Not supported DepthwiseConv2D acvivation");
-    }
-  }
-
-  _return_fn = std::move(fn);
-}
-
-void KernelGenerator::visit(const ir::operation::ElementwiseActivation &node)
-{
-  const auto output_index{node.getOutputs().at(0)};
-  const auto input_index{node.getInputs().at(ir::operation::ElementwiseActivation::Input::INPUT)};
-
-  tflite::gpu::OperationDef op_def;
-  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
-
-  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(output_index)->get_info()._desc);
-  op_def.src_tensors.push_back(_tensor_reg->getClTensor(input_index)->get_info()._desc);
-
-  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
-  auto fn = std::make_unique<ClFunction>(_creation_context);
-  switch (node.param().op_type)
-  {
-    case ir::operation::ElementwiseActivation::Type::LEAKY_RELU:
-    case ir::operation::ElementwiseActivation::Type::RELU:
-    {
-      tflite::gpu::ReLUAttributes attr;
-      if (ir::operation::ElementwiseActivation::Type::LEAKY_RELU == node.param().op_type)
-      {
-        attr.alpha = node.param().alpha;
-        attr.clip = 0;
-      }
-      else
-      {
-        attr.alpha = node.param().beta;
-        attr.clip = node.param().alpha;
-      }
-      gpu_op = SelectReLU(attr, op_def);
-      break;
-    }
-    case ir::operation::ElementwiseActivation::Type::LOGISTIC:
-    {
-      if (_ctx.at(input_index).typeInfo().type() != ir::DataType::FLOAT32)
-      {
-        throw std::runtime_error{"Unsupported data type of LOGISTIC"};
-      }
-      tflite::gpu::GPUOperation operation =
-        CreateElementwiseOneInput(_creation_context->GetGpuInfo(), op_def,
-                                  convertElementwiseActivationType(node.param().op_type));
-      gpu_op = std::make_unique<tflite::gpu::GPUOperation>(std::move(operation));
-      break;
-    }
-    case ir::operation::ElementwiseActivation::Type::TANH:
-    {
-      tflite::gpu::GPUOperation operation = CreateElementwiseOneInput(
-        _creation_context->GetGpuInfo(), op_def, tflite::gpu::OperationType::TANH);
-      gpu_op = std::make_unique<tflite::gpu::GPUOperation>(std::move(operation));
-      break;
-    }
-    default:
-      throw std::runtime_error(
-        "gpu_cl KernelGenerator : Not supported operation on ElementwiseActivation");
-  }
-  addClNode({input_index}, {output_index}, std::move(gpu_op));
-  _return_fn = std::move(fn);
-}
-
-void KernelGenerator::visit(const ir::operation::Pool2D &node)
-{
-  const auto output_index{node.getOutputs().at(0)};
-  const auto input_index{node.getInputs().at(ir::operation::Pool2D::Input::INPUT)};
-
-  tflite::gpu::OperationDef op_def;
-  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
-
-  op_def.src_tensors.push_back(_tensor_reg->getClTensor(input_index)->get_info()._desc);
-  auto input_shape = _tensor_reg->getClTensor(input_index)->get_info()._shape;
-
-  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(output_index)->get_info()._desc);
-
-  const auto kh = node.param().kh;
-  const auto kw = node.param().kw;
-  const auto stride = node.param().stride;
-  const auto op_type = convertPoolType(node.param().op_type);
-
-  tflite::gpu::Pooling2DAttributes attributes;
-  attributes.type = op_type;
-  attributes.kernel = tflite::gpu::HW(kh > 0 ? kh : 1, kw > 0 ? kw : 1);
-  attributes.strides = tflite::gpu::HW(stride.vertical > 0 ? stride.vertical : 1,
-                                       stride.horizontal > 0 ? stride.horizontal : 1);
-
-  if (node.param().padding.type == ir::PaddingType::SAME)
-  {
-    attributes.padding = CalculateSamePadding(input_shape, attributes);
-  }
-  else
-  {
-    attributes.padding.prepended = tflite::gpu::HW(0, 0);
-    attributes.padding.appended = tflite::gpu::HW(0, 0);
-  }
-
-  auto fn = std::make_unique<ClFunction>(_creation_context);
-  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
-  gpu_op = SelectPooling(attributes, op_def);
-
-  addClNode({input_index}, {output_index}, std::move(gpu_op));
-  _return_fn = std::move(fn);
-}
-
-void KernelGenerator::visit(const ir::operation::Reshape &node)
-{
-  const auto output_index{node.getOutputs().at(0)};
-  const auto input_index{node.getInputs().at(ir::operation::Reshape::Input::INPUT)};
-
-  tflite::gpu::OperationDef op_def;
-  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
-
-  op_def.src_tensors.push_back(_tensor_reg->getClTensor(input_index)->get_info()._desc);
-  auto input_shape = _tensor_reg->getClTensor(input_index)->get_info()._shape;
-
-  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(output_index)->get_info()._desc);
-  auto output_shape = _tensor_reg->getClTensor(output_index)->get_info()._shape;
-
-  tflite::gpu::ReshapeAttributes attr;
-  attr.new_shape = output_shape;
-
-  auto fn = std::make_unique<ClFunction>(_creation_context);
-  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
-  const int src_channels = input_shape.c;
-  SelectReshape(src_channels, attr.new_shape.c, op_def, &gpu_op);
-
-  addClNode({input_index}, {output_index}, std::move(gpu_op));
-  _return_fn = std::move(fn);
-}
-
-void KernelGenerator::visit(const ir::operation::Softmax &node)
-{
-  const auto output_index{node.getOutputs().at(0)};
-  const auto input_index{node.getInputs().at(ir::operation::Softmax::Input::INPUT)};
-
-  const auto beta = node.param().beta;
-
-  if (beta != 1.0)
-  {
-    throw std::runtime_error("Softmax.beta != 1 is not supported in gpu_cl");
-  }
-
-  tflite::gpu::OperationDef op_def;
-  op_def.precision = tflite::gpu::CalculationsPrecision::F32;
-
-  op_def.dst_tensors.push_back(_tensor_reg->getClTensor(output_index)->get_info()._desc);
-
-  op_def.src_tensors.push_back(_tensor_reg->getClTensor(input_index)->get_info()._desc);
-  auto input_shape = _tensor_reg->getClTensor(input_index)->get_info()._shape;
-
-  auto fn = std::make_unique<ClFunction>(_creation_context);
-
-  std::unique_ptr<tflite::gpu::GPUOperation> gpu_op;
-  SelectSoftmax(input_shape, op_def, &gpu_op);
-
-  addClNode({input_index}, {output_index}, std::move(gpu_op));
-  _return_fn = std::move(fn);
-}
-
-} // namespace gpu_cl
-} // namespace backend
-} // namespace onert
diff --git a/runtime/onert/backend/gpu_cl/operand/ICLTensor.cc b/runtime/onert/backend/gpu_cl/operand/ICLTensor.cc
deleted file mode 100644 (file)
index ef71bbc..0000000
+++ /dev/null
@@ -1,226 +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 "ICLTensor.h"
-
-#include "tensorflow/lite/delegates/gpu/api.h"
-#include "tensorflow/lite/delegates/gpu/spi.h"
-#include "tensorflow/lite/delegates/gpu/cl/opencl_wrapper.h"
-#include "tensorflow/lite/delegates/gpu/cl/tensor_type_util.h"
-#include "tensorflow/lite/delegates/gpu/cl/kernels/converter.h"
-
-namespace onert
-{
-namespace backend
-{
-namespace gpu_cl
-{
-namespace operand
-{
-
-using namespace tflite::gpu;
-using namespace tflite::gpu::cl;
-using namespace tflite::gpu::internal_tensor;
-
-void ICLTensor::access(const std::function<void(ITensor &tensor)> &fn)
-{
-  if (total_size() == 0)
-    return;
-
-  fn(*this);
-}
-
-void ICLTensor::writeConvertInit(tflite::gpu::TensorObjectConverterBuilder *converter_builder,
-                                 std::shared_ptr<tflite::gpu::cl::Environment> environment)
-{
-  _environment = environment;
-  TensorObjectDef input_def;
-  input_def.dimensions.b = handle()->Batch();
-  input_def.dimensions.h = handle()->Height();
-  input_def.dimensions.w = handle()->Width();
-  input_def.dimensions.c = handle()->Channels();
-  input_def.object_def.data_layout = DataLayout::BHWC;
-  input_def.object_def.data_type = DataType::FLOAT32;
-  input_def.object_def.object_type = ObjectType::CPU_MEMORY;
-  input_def.object_def.user_provided = true;
-
-  TensorObjectDef permute_def = input_def;
-  permute_def.object_def.object_type = ToObjectType(handle()->GetStorageType());
-
-  auto dims = permute_def.dimensions;
-  const BHWC shape(dims.b, dims.h, dims.w, dims.c);
-  const TensorDescriptor desc{
-    permute_def.object_def.data_type,
-    ToTensorStorageType(permute_def.object_def.object_type, permute_def.object_def.data_layout),
-    Layout::BHWC};
-  if (!AllocateTensorMemory(_environment->context(), shape, desc, &_cl_memory).ok())
-  {
-    throw std::runtime_error("Failed to AllocateTensorMemory");
-  }
-
-  TensorObjectDef output_def = permute_def;
-  output_def.object_def.data_layout = ToDataLayout(handle()->GetStorageType());
-  output_def.object_def.data_type = handle()->GetDataType();
-  input_def.object_def.user_provided = false;
-
-  if (!converter_builder->MakeConverter(input_def, permute_def, &_converter_to).ok())
-  {
-    throw std::runtime_error("Failed to make converter_to");
-  }
-  if (!converter_builder->MakeConverter(permute_def, output_def, &_converter_from).ok())
-  {
-    throw std::runtime_error("Failed to make converter_from");
-  }
-}
-
-void ICLTensor::readConvertInit(tflite::gpu::TensorObjectConverterBuilder *converter_builder,
-                                std::shared_ptr<tflite::gpu::cl::Environment> environment)
-{
-  _environment = environment;
-  TensorObjectDef input_def;
-  input_def.dimensions.b = handle()->Batch();
-  input_def.dimensions.h = handle()->Height();
-  input_def.dimensions.w = handle()->Width();
-  input_def.dimensions.c = handle()->Channels();
-  input_def.object_def.data_layout = ToDataLayout(handle()->GetStorageType());
-  input_def.object_def.data_type = handle()->GetDataType();
-  input_def.object_def.object_type = ToObjectType(handle()->GetStorageType());
-  input_def.object_def.user_provided = false;
-
-  TensorObjectDef permute_def = input_def;
-  permute_def.object_def.data_layout = DataLayout::BHWC;
-  permute_def.object_def.data_type = DataType::FLOAT32;
-  permute_def.object_def.user_provided = true;
-
-  auto dims = permute_def.dimensions;
-  const BHWC shape(dims.b, dims.h, dims.w, dims.c);
-  const TensorDescriptor desc{
-    permute_def.object_def.data_type,
-    ToTensorStorageType(permute_def.object_def.object_type, permute_def.object_def.data_layout),
-    Layout::BHWC};
-  if (!AllocateTensorMemory(_environment->context(), shape, desc, &_cl_memory).ok())
-  {
-    throw std::runtime_error("Failed to AllocateTensorMemory");
-  }
-
-  TensorObjectDef output_def = permute_def;
-  output_def.object_def.object_type = ObjectType::CPU_MEMORY;
-
-  if (!converter_builder->MakeConverter(input_def, permute_def, &_converter_from).ok())
-  {
-    throw std::runtime_error("Failed to make converter_from");
-  }
-  if (!converter_builder->MakeConverter(permute_def, output_def, &_converter_to).ok())
-  {
-    throw std::runtime_error("Failed to make converter_to");
-  }
-}
-
-void ICLTensor::enqueueWriteBuffer(const void *ptr, bool blocking)
-{
-  TensorObject input_obj = MakeReadableCpuMemory(
-    absl::MakeSpan(static_cast<const float *>(ptr), _info._shape.DimensionsProduct()));
-
-  TensorObject output_obj;
-
-  TensorObject permute_obj;
-  if (ToObjectType(handle()->GetStorageType()) == ObjectType::OPENCL_TEXTURE)
-  {
-    permute_obj = OpenClTexture{_cl_memory.memory()};
-  }
-  else
-  {
-    permute_obj = OpenClBuffer{_cl_memory.memory()};
-  }
-
-  if (handle()->GetStorageType() == TensorStorageType::BUFFER)
-  {
-    output_obj = OpenClBuffer{handle()->GetMemoryPtr()};
-  }
-  else if (handle()->GetStorageType() == TensorStorageType::IMAGE_BUFFER)
-  {
-    output_obj = OpenClBuffer{handle()->GetMemoryPtrForWriting()};
-  }
-  else
-  {
-    output_obj = OpenClTexture{handle()->GetMemoryPtr()};
-  }
-
-  if (!_converter_to->Convert(input_obj, permute_obj).ok())
-  {
-    throw std::runtime_error("Failed to write cl buffer from cpu memory");
-  }
-
-  if (blocking && !_environment->queue()->WaitForCompletion().ok())
-  {
-    throw std::runtime_error("Failed to WaitForCompletion");
-  }
-
-  if (!_converter_from->Convert(permute_obj, output_obj).ok())
-  {
-    throw std::runtime_error("Failed to change layout");
-  }
-}
-
-void ICLTensor::enqueueReadBuffer(void *ptr, bool blocking)
-{
-  TensorObject input_obj;
-
-  if (handle()->GetStorageType() == TensorStorageType::BUFFER)
-  {
-    input_obj = OpenClBuffer{handle()->GetMemoryPtr()};
-  }
-  else if (handle()->GetStorageType() == TensorStorageType::IMAGE_BUFFER)
-  {
-    input_obj = OpenClBuffer{handle()->GetMemoryPtrForWriting()};
-  }
-  else
-  {
-    input_obj = OpenClTexture{handle()->GetMemoryPtr()};
-  }
-
-  TensorObject permute_obj;
-  if (ToObjectType(handle()->GetStorageType()) == ObjectType::OPENCL_TEXTURE)
-  {
-    permute_obj = OpenClTexture{_cl_memory.memory()};
-  }
-  else
-  {
-    permute_obj = OpenClBuffer{_cl_memory.memory()};
-  }
-
-  TensorObject output_obj =
-    MakeCpuMemory(absl::MakeSpan(static_cast<float *>(ptr), _info._shape.DimensionsProduct()));
-
-  if (!_converter_from->Convert(input_obj, permute_obj).ok())
-  {
-    throw std::runtime_error("Failed to change layout");
-  }
-  if (!_converter_to->Convert(permute_obj, output_obj).ok())
-  {
-    throw std::runtime_error("Failed to read cl buffer");
-  }
-
-  if (blocking && !_environment->queue()->WaitForCompletion().ok())
-  {
-    throw std::runtime_error("Failed to WaitForCompletion");
-  }
-}
-
-} // namespace operand
-} // namespace gpu_cl
-} // namespace backend
-} // namespace onert
index 1943f70..43e3703 100644 (file)
@@ -40,7 +40,7 @@ FunctionMap BackendContext::genKernels()
   for (auto &&op_ind : _data.op_order)
   {
     auto fn_seq = kernel_gen->generate(op_ind);
-    ret.emplace_back(op_ind, std::move(fn_seq));
+    ret.emplace(op_ind, std::move(fn_seq));
   }
 
   basic::initConsts(*this);
index 206acbf..ab7f2f9 100644 (file)
@@ -12,11 +12,8 @@ target_link_libraries(${LIB_ONERT_BACKEND_RUY} PRIVATE nnfw_common)
 target_link_libraries(${LIB_ONERT_BACKEND_RUY} PRIVATE nnfw_coverage)
 target_link_libraries(${LIB_ONERT_BACKEND_RUY} PRIVATE ruy)
 
-set_target_properties(${LIB_ONERT_BACKEND_RUY} PROPERTIES OUTPUT_NAME backend_ruy)
+set_target_properties(${LIB_ONERT_BACKEND_RUY} PROPERTIES
+  OUTPUT_NAME backend_ruy
+  INSTALL_RPATH "$ORIGIN:$ORIGIN/../..")
 
-if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
-  add_custom_command(TARGET ${LIB_ONERT_BACKEND_RUY} POST_BUILD
-                     COMMAND ${CMAKE_STRIP} "--strip-unneeded" $<TARGET_FILE_NAME:${LIB_ONERT_BACKEND_RUY}>)
-endif()
-
-install(TARGETS ${LIB_ONERT_BACKEND_RUY} DESTINATION lib)
+install(TARGETS ${LIB_ONERT_BACKEND_RUY} DESTINATION lib/nnfw/backend)
index ae7ec28..90fbc84 100644 (file)
@@ -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 (const auto &ind : (op.getInputs() | ir::Remove::UNDEFINED) + op.getOutputs())
   {
     auto portable_tensor = _tensor_reg->getPortableTensor(ind);
     if (portable_tensor)
@@ -77,10 +77,9 @@ KernelGenerator::KernelGenerator(
   const std::shared_ptr<basic::TensorRegistry> &tensor_reg,
   const std::shared_ptr<backend::custom::IKernelBuilder> &kernel_builder,
   const std::shared_ptr<ExternalContext> &external_context)
-  : basic::KernelGeneratorBase{graph},
-    _ctx(graph.operands()), _operations_ctx{graph.operations()}, _current_layout{graph.layout()},
-    _tensor_builder(tensor_builder), _tensor_reg{tensor_reg}, _kernel_builder(kernel_builder),
-    _external_context(external_context)
+  : basic::KernelGeneratorBase{graph}, _ctx(graph.operands()), _operations_ctx{graph.operations()},
+    _current_layout{graph.layout()}, _tensor_builder(tensor_builder), _tensor_reg{tensor_reg},
+    _kernel_builder(kernel_builder), _external_context(external_context)
 {
   // DO NOTHING
 }
@@ -101,7 +100,7 @@ void KernelGenerator::visit(const ir::operation::Conv2D &node)
 
   const auto stride = node.param().stride;
   const auto activation = node.param().activation;
-  const auto param_padding = node.param().padding;
+  const auto &param_padding = node.param().padding;
   const auto dilation = node.param().dilation;
   auto fn = std::make_unique<ops::ConvolutionLayer>();
 
index 9b8d50a..9ba689d 100644 (file)
@@ -20,6 +20,7 @@
 #include "BackendContext.h"
 #include "Config.h"
 #include "KernelGenerator.h"
+#include "optimizer/Optimizers.h"
 
 #include <backend/Backend.h>
 #include <backend/train/ITrainableBackend.h>
@@ -51,13 +52,15 @@ public:
   newContext(backend::train::TrainableContextData &&tdata) const override
   {
     const auto &tgraph = *tdata.tgraph;
+    auto optimizer = createOptimizer(tdata.optim_info);
     auto tr = std::make_shared<TensorRegistry>();
-    auto tb = std::make_shared<TensorBuilder>(tr, "Bump");
+    auto tb = std::make_shared<TensorBuilder>(tr, optimizer.get(), "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);
+    auto context = std::make_unique<train::BackendContext>(this, std::move(tdata_ptr), tr, tb,
+                                                           std::move(optimizer));
 
     context->kernel_gen = std::make_shared<train::KernelGenerator>(
-      tgraph, tr, context->external_context(), context->data()->optimizer);
+      tgraph, tr, context->external_context(), context->optimizer());
     return context;
   }
 
index 3ee9a72..349f2bf 100644 (file)
 
 #include "TensorBuilder.h"
 #include "KernelGenerator.h"
+#include "ops/BackPropInitializer.h"
 
 #include <backend/basic/train/TrainableBackendContextHelpers.h>
+#include <misc/polymorphic_downcast.h>
+
+#include <cassert>
 
 namespace onert
 {
@@ -28,6 +32,73 @@ namespace backend
 namespace train
 {
 
+namespace
+{
+ir::OperandInfo createBackwardTensorInfo(const ir::Operand &operand)
+{
+  // TODO Use different shape of back-propagated tensor if it exists
+  return ir::OperandInfo{operand.shape(), operand.typeInfo(), operand.info().memAllocType(),
+                         operand.isConstant()};
+}
+
+// NOTE Even if there are duplicate indices, the duplicate back-propagated tensors may need
+//      to be updated respectively. So we use a sequence instead of a set.
+ir::OperandIndexSequence getBackPropSeq(const ir::train::TrainableGraph &tgraph,
+                                        const ir::OperationIndex &op_index)
+{
+  ir::OperandIndexSequence ret;
+
+  const auto &op = tgraph.operations().at(op_index);
+  for (const auto &input : (op.getInputs() | ir::Remove::UNDEFINED))
+  {
+    const auto &operand = tgraph.operands().at(input);
+    // TODO Remove other inputs that are not back-propagated
+    if (!operand.isConstant() && !tgraph.getInputs().contains(input))
+      ret.append(input);
+  }
+
+  return ret;
+}
+
+void AddBackPropInitializers(const ir::train::TrainableGraph &tgraph, TensorRegistry &tensor_reg,
+                             FunctionMap &fn_map)
+{
+  util::Set<ir::OperandIndex> unvisited;
+  tgraph.operands().iterate([&](const ir::OperandIndex &index, const ir::Operand &operand) {
+    if (!tgraph.getInputs().contains(index) && !operand.isConstant())
+      unvisited.add(index);
+  });
+
+  for (const auto &op_index : tgraph.essentialBackwardOrder())
+  {
+    assert(fn_map.find(op_index) != fn_map.end());
+
+    auto &tn_seq = fn_map.at(op_index);
+
+    // The function added latest is executed first in a sequence during backwarding.
+    std::vector<BackPropTensor *> back_props;
+    const auto &op = tgraph.operation(op_index);
+    for (const auto &back_prop_index :
+         op.getInputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED)
+    {
+      assert(op.isRequiredForBackward());
+      if (unvisited.contains(back_prop_index))
+      {
+        auto back_prop_tensor = tensor_reg.getBackPropTensor(back_prop_index);
+        assert(back_prop_tensor != nullptr);
+        back_props.emplace_back(back_prop_tensor);
+        unvisited.remove(back_prop_index);
+      }
+    }
+    if (back_props.size() != 0)
+    {
+      auto initializer = std::make_unique<ops::BackPropInitializer>(back_props);
+      tn_seq->append(std::move(initializer));
+    }
+  }
+}
+} // namespace
+
 backend::ITensorRegistry *BackendContext::genTensors()
 {
   return basic::train::genTensors(*this, _tensor_builder);
@@ -37,39 +108,96 @@ 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))
+  tgraph.operations().iterate([&](const ir::OperationIndex &, const ir::IOperation &op) {
+    const auto trainable_op = dynamic_cast<const ir::train::TrainableOperation *>(&op);
+    assert(trainable_op);
+    if (!trainable_op->isRequiredForBackward())
+    {
       return;
-    // NOTE Assuming there is no layout changes (Always assume NHWC or UNKNOWN)
-    assert(tgraph.layout() != ir::Layout::NCHW);
+    }
+    for (const auto &ind : op.getInputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
+    {
+      if (tensor_builder->isRegisteredBackward(ind))
+        continue;
+      if (external_operands().contains(ind))
+        continue;
+      // 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);
+      const auto &operand = tgraph.operands().at(ind);
+      tensor_builder->registerBackwardTensorInfo(ind, createBackwardTensorInfo(operand),
+                                                 ir::Layout::NHWC);
+    }
   });
 
+  for (const auto &op_index : tgraph.essentialBackwardOrder())
+  {
+    const auto back_prop_seq = getBackPropSeq(tgraph, op_index);
+    for (const auto &back_prop_index : back_prop_seq)
+    {
+      DisposableTensorIndex disposable_index{op_index, back_prop_index};
+      const auto &operand = tgraph.operands().at(back_prop_index);
+      tensor_builder->registerDisposableBackwardTensorInfo(
+        disposable_index, createBackwardTensorInfo(operand), ir::Layout::NHWC);
+    }
+  }
+
+  planBackwardTensors();
+
+  tensor_builder->allocateBackward();
+
+  return _tensor_registry.get();
+}
+
+void BackendContext::planForwardTensors()
+{
+  // TODO Plan forwarding tensors
+}
+
+void BackendContext::planBackwardTensors()
+{
+  const ir::train::TrainableGraph &tgraph = *trainable_graph();
+  auto tensor_builder = _tensor_builder;
+
   // 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();
+  planDisposableBackPropTensors();
 }
 
-FunctionMap BackendContext::genKernels()
+void BackendContext::planDisposableBackPropTensors()
 {
-  train::FunctionMap ret;
+  const ir::train::TrainableGraph &tgraph = *trainable_graph();
+  auto tensor_builder = _tensor_builder;
 
-  for (const auto &op_ind : _tdata->op_order)
+  std::vector<DisposableTensorIndex> prev_seq;
+  for (const auto &op_index : tgraph.essentialBackwardOrder())
   {
-    auto fn_seq = kernel_gen->generate(op_ind);
-    ret.emplace_back(op_ind, std::move(fn_seq));
+    for (const auto &index : prev_seq)
+    {
+      tensor_builder->notifyDisposableBackPropLastUse(index);
+    }
+
+    std::vector<DisposableTensorIndex> cur_seq;
+    const auto back_prop_indices = getBackPropSeq(tgraph, op_index);
+    for (const auto &back_prop_index : back_prop_indices)
+    {
+      DisposableTensorIndex cur_index{op_index, back_prop_index};
+      tensor_builder->notifyDisposableBackPropFirstUse(cur_index);
+
+      cur_seq.emplace_back(cur_index);
+    }
+
+    prev_seq = cur_seq;
   }
+}
+
+FunctionMap BackendContext::genKernels()
+{
+  auto ret = generateFunctionMap();
 
   // Initialize TrainableTensors
   trainable_graph()->operands().iterate(
@@ -107,6 +235,24 @@ FunctionMap BackendContext::genKernels()
   return ret;
 }
 
+FunctionMap BackendContext::generateFunctionMap()
+{
+  train::FunctionMap ret;
+
+  for (const auto &op_ind : _tdata->op_order)
+  {
+    auto fn_seq = kernel_gen->generate(op_ind);
+    ret.emplace(op_ind, std::move(fn_seq));
+  }
+
+  // NOTE Each BackPropInitializer should be called first in each op node during backwarding
+  const auto &tgraph = *_tdata->tgraph;
+  auto tensor_reg = nnfw::misc::polymorphic_downcast<TensorRegistry *>(_tensor_registry.get());
+  AddBackPropInitializers(tgraph, *tensor_reg, ret);
+
+  return ret;
+}
+
 } // namespace train
 } // namespace backend
 } // namespace onert
index b5b572b..6c36a1e 100644 (file)
@@ -54,21 +54,40 @@ 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::unique_ptr<exec::train::optimizer::Optimizer> optimizer = 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}
+      kernel_gen{kernel_gen}, _external_context(new ExternalContext),
+      _tensor_builder{tensor_builder}, _optimizer{std::move(optimizer)}
   {
   }
+  BackendContext(const BackendContext &) = delete;
+  ~BackendContext() = default;
 
+public:
+  BackendContext &operator=(const BackendContext &) = delete;
+
+public:
   backend::ITensorRegistry *genTensors() override;
   backend::train::ITensorRegistry *genTrainingTensors() override;
 
+private:
+  void planForwardTensors();
+  void planBackwardTensors();
+
 public:
   FunctionMap genKernels() override;
 
   std::shared_ptr<ExternalContext> external_context() { return _external_context; }
 
+  const exec::train::optimizer::Optimizer *optimizer() const { return _optimizer.get(); }
+
+private:
+  FunctionMap generateFunctionMap();
+
+private:
+  void planDisposableBackPropTensors();
+
 public:
   // TODO Make it private
   std::shared_ptr<KernelGenerator> kernel_gen;
@@ -81,6 +100,9 @@ private:
 
 private:
   std::shared_ptr<TensorBuilder> _tensor_builder;
+
+private:
+  std::unique_ptr<exec::train::optimizer::Optimizer> _optimizer;
 };
 
 } // namespace train
index fd50685..a9fd6a1 100644 (file)
@@ -1,6 +1,8 @@
 set(LIB_ONERT_BACKEND_TRAIN onert_backend_train)
 
 file(GLOB_RECURSE SOURCES "*.cc")
+file(GLOB_RECURSE TESTS "*.test.cc")
+list(REMOVE_ITEM SOURCES ${TESTS})
 
 add_library(${LIB_ONERT_BACKEND_TRAIN} SHARED ${SOURCES})
 
@@ -10,11 +12,30 @@ target_link_libraries(${LIB_ONERT_BACKEND_TRAIN} PRIVATE nnfw_lib_cker nnfw_lib_
 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)
+set_target_properties(${LIB_ONERT_BACKEND_TRAIN} PROPERTIES
+  OUTPUT_NAME backend_train
+  INSTALL_RPATH "$ORIGIN:$ORIGIN/../..")
 
-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/nnfw/backend)
 
-install(TARGETS ${LIB_ONERT_BACKEND_TRAIN} DESTINATION lib)
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+# Unit Tests
+set(TEST_ONERT_TRAIN_BACKEND test_onert_train_backend)
+
+add_executable(${TEST_ONERT_TRAIN_BACKEND} ${TESTS})
+
+target_link_libraries(${TEST_ONERT_TRAIN_BACKEND} ${LIB_ONERT_BACKEND_TRAIN})
+# Requires linking nnfw_coverage: check header coverage
+target_link_libraries(${TEST_ONERT_TRAIN_BACKEND} nnfw_coverage)
+target_link_libraries(${TEST_ONERT_TRAIN_BACKEND} onert_core)
+target_link_libraries(${TEST_ONERT_TRAIN_BACKEND} gtest gtest_main dl ${LIB_PTHREAD})
+
+# Set install rpath to find onert_core, onert_backend_train, etc
+set_target_properties(${TEST_ONERT_TRAIN_BACKEND} PROPERTIES
+  INSTALL_RPATH "$ORIGIN:$ORIGIN/../lib:$ORIGIN/../lib/nnfw/backend")
+
+add_test(${TEST_ONERT_TRAIN_BACKEND} ${TEST_ONERT_TRAIN_BACKEND})
+install(TARGETS ${TEST_ONERT_TRAIN_BACKEND} DESTINATION unittest)
diff --git a/runtime/onert/backend/train/DisposableTensorIndex.h b/runtime/onert/backend/train/DisposableTensorIndex.h
new file mode 100644 (file)
index 0000000..793121e
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_DISPOSABLE_TENSOR_INDEX_H__
+#define __ONERT_BACKEND_TRAIN_DISPOSABLE_TENSOR_INDEX_H__
+
+#include <cassert>
+#include <functional>
+#include <unordered_map>
+
+#include "ir/Index.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+/**
+ * @brief Class that is index of DisposableTensor
+ */
+class DisposableTensorIndex
+{
+public:
+  /**
+   * @brief Construct DisposableTensorIndex object.
+   * @param op_index      The operation index
+   * @param operand_index The operand index
+   */
+  DisposableTensorIndex(const ir::OperationIndex &op_index, const ir::OperandIndex &operand_index)
+    : _op_index{op_index}, _operand_index{operand_index}
+  {
+    assert(op_index.valid());
+    assert(operand_index.valid());
+    // NOTE This constraint is necessary to check overflow of hash value
+    assert((op_index.value() < (1 << 16) && operand_index.value() < (1 << 16)) &&
+           "DisposableTensorIndex does not support index value of operation or "
+           "operand greater than 65535");
+  }
+
+public:
+  /**
+   * @brief Get Operation index
+   *
+   * @return Operation index
+   */
+  const ir::OperationIndex &op_index() const { return _op_index; }
+  /**
+   * @brief Get operand index
+   *
+   * @return Operand index
+   */
+  const ir::OperandIndex &operand_index() const { return _operand_index; }
+
+public:
+  /**
+   * @brief operator overloading function for `==`
+   *
+   * @return Whether two DisposableTensorIndex are the same
+   */
+  bool operator==(const DisposableTensorIndex &other) const
+  {
+    return _op_index == other.op_index() && _operand_index == other.operand_index();
+  }
+  /**
+   * @brief operator overloading function for `!=`
+   *
+   * @return Whether two DisposableTensorIndex are differenct
+   */
+  bool operator!=(const DisposableTensorIndex &other) const { return !(*this == other); }
+
+private:
+  ir::OperationIndex _op_index;
+  ir::OperandIndex _operand_index;
+};
+
+template <typename T> using DisposableTensorIndexMap = std::unordered_map<DisposableTensorIndex, T>;
+
+inline std::ostream &operator<<(std::ostream &o, const DisposableTensorIndex &i)
+{
+  return operator<<(o, i.operand_index());
+}
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+namespace std
+{
+
+/**
+ * @brief Structure that provides hash value of DisposableTensorIndex
+ */
+template <> struct hash<onert::backend::train::DisposableTensorIndex>
+{
+  size_t operator()(const onert::backend::train::DisposableTensorIndex &index) const noexcept
+  {
+    const auto op_index = index.op_index();
+    const auto operand_index = index.operand_index();
+
+    assert(sizeof(op_index) <= 4);
+    assert(sizeof(operand_index) <= 4);
+    static_assert(sizeof(size_t) >= sizeof(uint32_t),
+                  "DisposableTensorIndex's hash creation error, size_t size is less than uint32_t");
+
+    return (static_cast<size_t>(op_index.value())) << 16 |
+           static_cast<size_t>(operand_index.value());
+  }
+};
+
+} // namespace std
+
+#endif // __ONERT_BACKEND_TRAIN_DISPOSABLE_TENSOR_INDEX_H__
index d3114e8..4eee7bb 100644 (file)
 
 #include "KernelGenerator.h"
 
+#include "ops/BackPropAccumulator.h"
+#include "ops/BinaryArithmeticLayer.h"
 #include "ops/ConvolutionLayer.h"
+#include "ops/DepthwiseConvolutionLayer.h"
 #include "ops/ElementwiseActivationLayer.h"
 #include "ops/FullyConnectedLayer.h"
-#include "ops/LossLayer.h"
+#include "ops/LossMeanSquaredErrorLayer.h"
+#include "ops/LossCategoricalCrossentropyLayer.h"
+#include "ops/MeanLayer.h"
 #include "ops/GradientApplier.h"
+#include "ops/PadLayer.h"
 #include "ops/PoolLayer.h"
 #include "ops/ReshapeLayer.h"
+#include "ops/SoftMaxLayer.h"
 
 #include <backend/Backend.h>
 #include <backend/IConfig.h>
@@ -54,31 +61,46 @@ convertElementwiseActivationType(ir::operation::ElementwiseActivation::Type type
   }
 }
 
-ops::LossType convertLossType(ir::operation::Loss::Type type_ir)
+ops::PoolType convertPoolType(ir::operation::Pool2D::PoolType type_ir)
 {
   switch (type_ir)
   {
-    case ir::operation::Loss::Type::MEAN_SQUARED_ERROR:
-      return ops::LossType::kMSE;
+    // 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");
   }
 }
 
-ops::PoolType convertPoolType(ir::operation::Pool2D::PoolType type_ir)
+std::unique_ptr<ops::BackPropAccumulator>
+generateBackPropAccumulator(const IPortableTensor *disposable, BackPropTensor *gradient)
 {
-  switch (type_ir)
+  auto update_fn = std::make_unique<ops::BackPropAccumulator>(disposable, gradient);
+  return update_fn;
+}
+
+void appendBackPropAccumulator(const ir::train::ITrainableOperation &op,
+                               const ir::OperationIndex &op_index, TensorRegistry *tensor_reg,
+                               exec::train::TrainableFnSequence *seq)
+{
+  for (const auto &input_index : (op.getInputs() | ir::Remove::UNDEFINED))
   {
-    // 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");
+    if (op.isRequiredForBackward())
+    {
+      const auto disposable =
+        tensor_reg->getDisposableBackPropTensor(DisposableTensorIndex{op_index, input_index});
+      if (disposable != nullptr)
+      {
+        auto back_prop = tensor_reg->getBackPropTensor(input_index);
+        seq->append(generateBackPropAccumulator(disposable, back_prop));
+      }
+    }
   }
 }
 
 std::unique_ptr<ops::GradientApplier>
-generateGradientApplier(const std::shared_ptr<exec::train::optimizer::Optimizer> optimizer,
+generateGradientApplier(const exec::train::optimizer::Optimizer *optimizer,
                         const IPortableTensor *gradient, ITrainableTensor *trainable)
 {
   auto update_fn = std::make_unique<ops::GradientApplier>();
@@ -92,6 +114,11 @@ std::unique_ptr<exec::train::TrainableFnSequence> KernelGenerator::generate(ir::
   auto ret = std::make_unique<exec::train::TrainableFnSequence>();
 
   const auto &op = _tgraph.operation(idx);
+
+  // NOTE appendBackPropAccumulator() must be called before appending _return_fn to
+  //      TrainableFnSequence as long as both are appended to the same TrainableFnSequence.
+  appendBackPropAccumulator(op, idx, _tensor_reg.get(), ret.get());
+
   op.accept(*this);
   assert(_return_fn);
   ret->append(std::move(_return_fn));
@@ -119,29 +146,164 @@ std::unique_ptr<exec::train::TrainableFnSequence> KernelGenerator::generate(ir::
 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)
+                                 const 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{}
+    _tensor_reg{tensor_reg}, _external_context(external_context), _optimizer{optimizer},
+    _update_funcs{}, _node_to_idx{}
+{
+  tgraph.operations().iterate(
+    [&](const onert::ir::OperationIndex &idx, const onert::ir::IOperation &op) {
+      assert(_node_to_idx.find(&op) == _node_to_idx.end());
+      _node_to_idx[&op] = idx;
+    });
+}
+
+void KernelGenerator::visit(const ir::train::operation::BinaryArithmetic &node)
 {
-  // DO NOTHING
+  using ir::train::operation::BinaryArithmetic;
+
+  const auto output_index{node.getOutputs().at(0)};
+  const auto lhs_index{node.getInputs().at(BinaryArithmetic::Input::LHS)};
+  const auto rhs_index{node.getInputs().at(BinaryArithmetic::Input::RHS)};
+
+  const auto arithmetic_type = node.param().arithmetic_type;
+  const auto activation = node.param().activation;
+
+  auto output_tensor = _tensor_reg->getPortableTensor(output_index);
+  auto lhs_tensor = _tensor_reg->getPortableTensor(lhs_index);
+  auto rhs_tensor = _tensor_reg->getPortableTensor(rhs_index);
+
+  auto fn = std::make_unique<ops::BinaryArithmeticLayer>();
+  fn->configure(lhs_tensor, rhs_tensor, output_tensor, activation,
+                static_cast<cpu::ops::ArithmeticType>(arithmetic_type));
+
+  if (node.isRequiredForBackward())
+  {
+    auto back_prop_output_tensor = getBackPropOut(output_index);
+    auto back_prop_lhs_tensor = getBackPropIn(node, lhs_index);
+    auto back_prop_rhs_tensor = getBackPropIn(node, rhs_index);
+
+    fn->configureBackward(back_prop_lhs_tensor, back_prop_rhs_tensor, back_prop_output_tensor,
+                          activation, static_cast<train::ops::ArithmeticType>(arithmetic_type));
+  }
+  _return_fn = std::move(fn);
 }
 
 void KernelGenerator::visit(const ir::train::operation::Conv2D &node)
 {
-  // TODO Generate kernel
+  using ir::train::operation::Conv2D;
 
-  // Generate GradientApplier
-  const auto ker_index{node.getInputs().at(ir::train::operation::Conv2D::Input::KERNEL)};
+  const auto out_index{node.getOutputs().at(0)};
+  const auto in_index{node.getInputs().at(Conv2D::Input::INPUT)};
+  const auto ker_index{node.getInputs().at(Conv2D::Input::KERNEL)};
+  const auto bias_index{node.getInputs().at(Conv2D::Input::BIAS)};
 
-  auto grad_tensor = _tensor_reg->getGradientTensor(ker_index);
+  auto out_tensor = _tensor_reg->getPortableTensor(out_index);
+  auto in_tensor = _tensor_reg->getPortableTensor(in_index);
   auto ker_tensor = _tensor_reg->getTrainableTensor(ker_index);
+  auto bias_tensor = _tensor_reg->getTrainableTensor(bias_index);
 
-  auto update_fn = std::make_unique<ops::GradientApplier>();
+  // Generate kernel
+  const auto stride = node.param().stride;
+  const auto activation = node.param().activation;
+  const auto &param_padding = node.param().padding;
+  const auto dilation = node.param().dilation;
+  auto fn = std::make_unique<ops::ConvolutionLayer>();
+
+  auto &operands = _tgraph.operands();
+  const auto ifm_shape = operands.at(in_index).shape().asFeature(_current_layout);
+  const auto ofm_shape = operands.at(out_index).shape().asFeature(_current_layout);
+  // Kernel format is [depth_out, kernel_height, kernel_width, depth_in].
+  const auto &ker_shape = operands.at(ker_index).shape();
+  const auto ker_height = ker_shape.dim(1);
+  const auto ker_width = ker_shape.dim(2);
+
+  const auto padding =
+    ir::calculatePadding(param_padding, ifm_shape, ofm_shape, stride, ker_width, ker_height,
+                         dilation.width_factor, dilation.height_factor);
+
+  const bool is_cacheable_weights = false;
+  fn->configure(in_tensor, ker_tensor, bias_tensor, param_padding.type, padding.left, padding.right,
+                padding.top, padding.bottom, stride.horizontal, stride.vertical,
+                dilation.width_factor, dilation.height_factor, activation, out_tensor,
+                is_cacheable_weights);
+
+  auto ker_grad_tensor = _tensor_reg->getGradientTensor(ker_index);
+  auto bias_grad_tensor = _tensor_reg->getGradientTensor(bias_index);
 
-  update_fn->configure(_optimizer, grad_tensor, ker_tensor);
+  if (node.isRequiredForBackward())
+  {
+
+    auto out_back_prop_tensor = getBackPropOut(out_index);
+    auto in_back_prop_tensor = getBackPropIn(node, in_index);
+
+    fn->configureBackward(ker_tensor, in_back_prop_tensor, ker_grad_tensor, bias_grad_tensor,
+                          out_back_prop_tensor, activation);
 
-  _update_funcs.emplace_back(generateGradientApplier(_optimizer, grad_tensor, ker_tensor));
+    // Generate GradientApplier
+    if (bias_tensor)
+      _update_funcs.emplace_back(
+        generateGradientApplier(_optimizer, bias_grad_tensor, bias_tensor));
+    _update_funcs.emplace_back(generateGradientApplier(_optimizer, ker_grad_tensor, ker_tensor));
+  }
+
+  _return_fn = std::move(fn);
+}
+
+void KernelGenerator::visit(const ir::train::operation::DepthwiseConv2D &node)
+{
+  using ir::train::operation::DepthwiseConv2D;
+
+  const auto ofm_index{node.getOutputs().at(0)};
+  const auto ifm_index{node.getInputs().at(DepthwiseConv2D::Input::INPUT)};
+  const auto ker_index{node.getInputs().at(DepthwiseConv2D::Input::KERNEL)};
+  const auto bias_index{node.getInputs().at(DepthwiseConv2D::Input::BIAS)};
+
+  auto ofm_tensor = _tensor_reg->getPortableTensor(ofm_index);
+  auto ifm_tensor = _tensor_reg->getPortableTensor(ifm_index);
+  auto ker_tensor = _tensor_reg->getTrainableTensor(ker_index);
+  auto bias_tensor = _tensor_reg->getTrainableTensor(bias_index);
+
+  const auto stride = node.param().stride;
+  const auto &operands = _tgraph.operands();
+  const auto ofm_shape = operands.at(ofm_index).shape().asFeature(_current_layout);
+  const auto ifm_shape = operands.at(ifm_index).shape().asFeature(_current_layout);
+  // Kernel format is [1, kernel_height, kernel_width, depth_out].
+  const auto &ker_shape = operands.at(ker_index).shape();
+  const auto ker_height = ker_shape.dim(1);
+  const auto ker_width = ker_shape.dim(2);
+  const auto dilation_width = node.param().dilation.width_factor;
+  const auto dilation_height = node.param().dilation.height_factor;
+  const auto padding = ir::calculatePadding(node.param().padding, ifm_shape, ofm_shape, stride,
+                                            ker_width, ker_height, dilation_width, dilation_height);
+  const auto multiplier = node.param().multiplier;
+  const auto activation = node.param().activation;
+
+  auto fn = std::make_unique<ops::DepthwiseConvolutionLayer>();
+
+  fn->configure(ifm_tensor, ker_tensor, bias_tensor, padding.left, padding.right, padding.top,
+                padding.bottom, stride.horizontal, stride.vertical, multiplier, dilation_width,
+                dilation_height, activation, ofm_tensor, _external_context);
+
+  if (node.isRequiredForBackward())
+  {
+    auto ker_grad_tensor = _tensor_reg->getGradientTensor(ker_index);
+    auto bias_grad_tensor = _tensor_reg->getGradientTensor(bias_index);
+
+    auto ofm_back_prop_tensor = getBackPropOut(ofm_index);
+    auto ifm_back_prop_tensor = getBackPropIn(node, ifm_index);
+
+    fn->configureBackward(ifm_back_prop_tensor, ker_grad_tensor, bias_grad_tensor,
+                          ofm_back_prop_tensor, activation);
+
+    // Generate GradientApplier
+    if (bias_tensor)
+      _update_funcs.emplace_back(
+        generateGradientApplier(_optimizer, bias_grad_tensor, bias_tensor));
+    _update_funcs.emplace_back(generateGradientApplier(_optimizer, ker_grad_tensor, ker_tensor));
+  }
+
+  _return_fn = std::move(fn);
 }
 
 void KernelGenerator::visit(const ir::train::operation::ElementwiseActivation &node)
@@ -154,14 +316,30 @@ void KernelGenerator::visit(const ir::train::operation::ElementwiseActivation &n
   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));
+  auto convertToInferActivationType = [](const ir::operation::ElementwiseActivation::Type &type) {
+    switch (type)
+    {
+      case ir::operation::ElementwiseActivation::Type::RELU:
+        return cpu::ops::ElementwiseActivationType::kReLU;
+      default:
+        throw std::invalid_argument("Unsupported ElementwiseActivation::Type");
+    }
+  };
+
+  fn->configure(input_tensor, output_tensor, node.param().alpha, node.param().beta,
+                convertToInferActivationType(node.param().op_type));
+
+  if (node.isRequiredForBackward())
+  {
+    auto back_prop_input_tensor = getBackPropIn(node, input_index);
+    auto back_prop_output_tensor = getBackPropOut(output_index);
+
+    fn->configureBackward(input_tensor, back_prop_input_tensor, back_prop_output_tensor,
+                          node.param().alpha, node.param().beta,
+                          convertElementwiseActivationType(node.param().op_type));
+  }
 
   _return_fn = std::move(fn);
 }
@@ -180,28 +358,35 @@ void KernelGenerator::visit(const ir::train::operation::FullyConnected &node)
   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,
+  fn->configure(in_tensor, weights_tensor, bias_tensor, activation, weights_format, out_tensor,
                 _external_context);
 
-  _return_fn = std::move(fn);
+  if (node.isRequiredForBackward())
+  {
+    auto out_back_prop_tensor = getBackPropOut(out_index);
+    auto in_back_prop_tensor = getBackPropIn(node, in_index);
+    auto weights_grad_tensor = _tensor_reg->getGradientTensor(weights_index);
+    auto bias_grad_tensor = _tensor_reg->getGradientTensor(bias_index);
+
+    fn->configureBackward(in_tensor, weights_tensor, out_tensor, in_back_prop_tensor,
+                          weights_grad_tensor, bias_grad_tensor, out_back_prop_tensor, activation,
+                          weights_format);
+
+    // 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));
+  }
 
-  // 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));
+  _return_fn = std::move(fn);
 }
 
 void KernelGenerator::visit(const ir::train::operation::Loss &node)
@@ -216,15 +401,153 @@ void KernelGenerator::visit(const ir::train::operation::Loss &node)
   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>();
+  // TODO Use BackPropTensor directly instead of DisposableTensor if y_pred is always used by only
+  //      loss
+  auto back_prop_y_pred_tensor = getBackPropIn(node, y_pred_index);
+
+  auto loss_code = node.param().loss_code;
+  auto loss_param = node.param().loss_param;
+
+  switch (loss_code)
+  {
+    case ir::train::LossCode::MeanSquaredError:
+    {
+      auto fn = std::make_unique<ops::LossMeanSquaredErrorLayer>();
+      fn->configure(y_pred_tensor, y_true_tensor, output_tensor, back_prop_y_pred_tensor);
+      _return_fn = std::move(fn);
+      break;
+    }
+    case ir::train::LossCode::CategoricalCrossentropy:
+    {
+      auto fn = std::make_unique<ops::LossCategoricalCrossentropyLayer>();
+      fn->configure(y_pred_tensor, y_true_tensor, output_tensor, back_prop_y_pred_tensor,
+                    loss_param.cce.axis, loss_param.cce.label_smoothing);
+      _return_fn = std::move(fn);
+      break;
+    }
+    default:
+      throw std::runtime_error("LossLayer: unsupported loss type");
+      break;
+  }
+}
+
+void KernelGenerator::visit(const ir::train::operation::Pad &node)
+{
+  const auto input_index{node.getInputs().at(ir::operation::Pad::Input::INPUT)};
+  const auto pad_index{node.getInputs().at(ir::operation::Pad::Input::PAD)};
+  const auto output_index{node.getOutputs().at(0)};
 
-  fn->configure(y_pred_tensor, y_true_tensor, output_tensor, deriv_y_pred_tensor,
-                convertLossType(node.param().op_type));
+  auto input = _tensor_reg->getPortableTensor(input_index);
+  auto pad = _tensor_reg->getPortableTensor(pad_index);
+  auto output = _tensor_reg->getPortableTensor(output_index);
 
+  auto fn = std::make_unique<ops::PadLayer>();
+
+  IPortableTensor *value = nullptr;
+  if (node.getInputs().size() == 3) // isPadV2
+  {
+    const auto value_index{node.getInputs().at(ir::operation::Pad::Input::VALUE)};
+    value = _tensor_reg->getPortableTensor(value_index);
+  }
+
+  fn->configure(input, pad, value, output);
+  if (node.isRequiredForBackward())
+  {
+    auto out_back_prop_tensor = getBackPropOut(output_index);
+    auto in_back_prop_tensor = getBackPropIn(node, input_index);
+    fn->configureBackward(in_back_prop_tensor, out_back_prop_tensor);
+  }
   _return_fn = std::move(fn);
+}
+
+void KernelGenerator::visit(const ir::train::operation::Pool2D &node)
+{
+  using ir::train::operation::Pool2D;
+
+  const auto output_index{node.getOutputs().at(0)};
+  const auto input_index{node.getInputs().at(0)};
+
+  const auto &operands = _tgraph.operands();
+  const auto &ofm_shape = operands.at(output_index).shape();
+  const auto &ifm_shape = operands.at(input_index).shape();
+
+  if (ifm_shape.rank() != 4)
+  {
+    std::runtime_error(node.name() + " only supports 4D tensor as input");
+  }
+
+  // calcualate padding
+  const auto stride = node.param().stride;
+  const auto kh = node.param().kh;
+  const auto kw = node.param().kw;
+  const auto padding =
+    ir::calculatePadding(node.param().padding, ifm_shape.asFeature(_current_layout),
+                         ofm_shape.asFeature(_current_layout), stride, kw, kh);
 
-  UNUSED_RELEASE(convertPoolType);
+  auto out_tensor = _tensor_reg->getPortableTensor(output_index);
+  auto in_tensor = _tensor_reg->getPortableTensor(input_index);
+
+  const auto activation = node.param().activation;
+  const auto pool_type = convertPoolType(node.param().op_type);
+
+  auto fn = std::make_unique<ops::PoolLayer>();
+
+  auto convertToInferPoolType = [](const train::ops::PoolType &pool_type) {
+    switch (pool_type)
+    {
+      case train::ops::PoolType::kMax:
+        return cpu::ops::PoolType::kMax;
+      default:
+        throw std::runtime_error("PoolLayer: Unsupported pool type yet");
+    }
+  };
+
+  fn->configure(in_tensor, padding.left, padding.right, padding.top, padding.bottom,
+                stride.horizontal, stride.vertical, kw, kh, activation, out_tensor,
+                convertToInferPoolType(pool_type));
+
+  if (node.isRequiredForBackward())
+  {
+    auto out_back_prop_tensor = getBackPropOut(output_index);
+    auto in_back_prop_tensor = getBackPropIn(node, input_index);
+    fn->configureBackward(padding.left, padding.right, padding.top, padding.bottom,
+                          stride.horizontal, stride.vertical, kw, kh, activation, pool_type,
+                          out_tensor, in_back_prop_tensor, out_back_prop_tensor);
+  }
+
+  _return_fn = std::move(fn);
+}
+
+void KernelGenerator::visit(const ir::train::operation::Reduce &node)
+{
+  using ir::train::operation::Reduce;
+
+  const auto output_index{node.getOutputs().at(0)};
+  const auto input_index{node.getInputs().at(Reduce::Input::INPUT)};
+  const auto axes_index{node.getInputs().at(Reduce::Input::AXES)};
+
+  const auto keep_dims = node.param().keep_dims;
+
+  auto output_tensor = _tensor_reg->getPortableTensor(output_index);
+  auto input_tensor = _tensor_reg->getPortableTensor(input_index);
+  auto axes_tensor = _tensor_reg->getPortableTensor(axes_index);
+
+  if (node.param().reduce_type == ir::operation::Reduce::ReduceType::MEAN)
+  {
+    auto fn = std::make_unique<ops::MeanLayer>();
+    fn->configure(input_tensor, axes_tensor, output_tensor, keep_dims);
+    if (node.isRequiredForBackward())
+    {
+      auto back_prop_output_tensor = getBackPropOut(output_index);
+      auto back_prop_input_tensor = getBackPropIn(node, input_index);
+      fn->configureBackward(back_prop_input_tensor, back_prop_output_tensor);
+    }
+    _return_fn = std::move(fn);
+  }
+  else
+  {
+    throw std::runtime_error("ReduceLayer: unsupported reduce type");
+  }
 }
 
 void KernelGenerator::visit(const ir::train::operation::Reshape &node)
@@ -237,9 +560,6 @@ void KernelGenerator::visit(const ir::train::operation::Reshape &node)
   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;
 
@@ -251,10 +571,61 @@ void KernelGenerator::visit(const ir::train::operation::Reshape &node)
 
   auto fn = std::make_unique<ops::ReshapeLayer>();
 
-  fn->configure(input_tensor, shape_tensor, output_tensor, input_deriv_tensor, output_deriv_tensor);
+  fn->configure(input_tensor, shape_tensor, output_tensor);
+  if (node.isRequiredForBackward())
+  {
+    auto output_back_prop_tensor = getBackPropOut(output_index);
+    auto input_back_prop_tensor = getBackPropIn(node, input_index);
+    fn->configureBackward(input_back_prop_tensor, output_back_prop_tensor);
+  }
   _return_fn = std::move(fn);
 }
 
+void KernelGenerator::visit(const ir::train::operation::Softmax &node)
+{
+  using ir::train::operation::Softmax;
+
+  const auto output_index{node.getOutputs().at(0)};
+  const auto input_index{node.getInputs().at(ir::operation::Softmax::Input::INPUT)};
+
+  const auto beta = node.param().beta;
+
+  auto output_tensor = _tensor_reg->getPortableTensor(output_index);
+  auto input_tensor = _tensor_reg->getPortableTensor(input_index);
+
+  auto fn = std::make_unique<ops::SoftMaxLayer>();
+
+  fn->configure(input_tensor, beta, output_tensor);
+
+  if (node.isRequiredForBackward())
+  {
+    auto output_back_prop_tensor = getBackPropOut(output_index);
+    auto input_back_prop_tensor = getBackPropIn(node, input_index);
+    fn->configureBackward(input_back_prop_tensor, output_back_prop_tensor);
+  }
+  _return_fn = std::move(fn);
+}
+
+IPortableTensor *KernelGenerator::getBackPropIn(const ir::Operation &node,
+                                                const ir::OperandIndex &operand_index)
+{
+  const auto &op_index = _node_to_idx[&node];
+
+  auto temp_tensor =
+    _tensor_reg->getDisposableBackPropTensor(DisposableTensorIndex{op_index, operand_index});
+  if (temp_tensor == nullptr)
+  {
+    temp_tensor = _tensor_reg->getBackPropTensor(operand_index);
+  }
+
+  return temp_tensor;
+}
+
+IPortableTensor *KernelGenerator::getBackPropOut(const ir::OperandIndex &output_index)
+{
+  return _tensor_reg->getBackPropTensor(output_index);
+}
+
 } // namespace train
 } // namespace backend
 } // namespace onert
index 660dc5d..5832bd5 100644 (file)
@@ -42,22 +42,34 @@ 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);
+                  const exec::train::optimizer::Optimizer *optimizer);
 
   std::unique_ptr<exec::train::TrainableFnSequence> generate(ir::OperationIndex op_ind) override;
 
+  void visit(const ir::train::operation::BinaryArithmetic &) override;
   void visit(const ir::train::operation::Conv2D &) override;
+  void visit(const ir::train::operation::DepthwiseConv2D &) 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::Pad &) override;
+  void visit(const ir::train::operation::Pool2D &) override;
+  void visit(const ir::train::operation::Reduce &node) override;
   void visit(const ir::train::operation::Reshape &node) override;
+  void visit(const ir::train::operation::Softmax &node) override;
+
+private:
+  IPortableTensor *getBackPropIn(const ir::Operation &op_index,
+                                 const ir::OperandIndex &operand_index);
+  IPortableTensor *getBackPropOut(const ir::OperandIndex &index);
 
 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;
+  const exec::train::optimizer::Optimizer *_optimizer;
   std::vector<std::unique_ptr<exec::train::IGradientApplier>> _update_funcs;
+  std::unordered_map<const ir::IOperation *, ir::OperationIndex> _node_to_idx;
 };
 
 } // namespace train
diff --git a/runtime/onert/backend/train/MemoryManager.cc b/runtime/onert/backend/train/MemoryManager.cc
new file mode 100644 (file)
index 0000000..87cd15d
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "MemoryManager.h"
+
+#include "MemoryPlannerFactory.h"
+
+#include <util/ConfigSource.h>
+
+#include <cassert>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+GradientMemoryManager::GradientMemoryManager(const std::string planner_id,
+                                             uint32_t optim_vars_count)
+  : MemoryManager{planner_id}, _optim_vars_count{optim_vars_count}
+{
+  // DO NOTHING
+}
+
+void GradientMemoryManager::allocate(void)
+{
+  _mem_alloc = std::make_shared<basic::Allocator>(_mem_planner->capacity());
+  assert(_mem_alloc->base());
+
+  const auto vars_capacity = _mem_planner->capacity() * _optim_vars_count;
+  _var_mem_alloc = std::make_shared<basic::Allocator>(vars_capacity);
+}
+
+uint8_t *GradientMemoryManager::getOptVarBuffer(const ir::OperandIndex &ind, uint32_t pos_var) const
+{
+  assert(_mem_planner->memory_plans().find(ind) != _mem_planner->memory_plans().end());
+  const auto var_offset = pos_var * _mem_planner->capacity();
+  const auto &mem_blk = _mem_planner->memory_plans().at(ind);
+  return _var_mem_alloc->base() + var_offset + mem_blk.offset;
+}
+
+DisposableMemoryManager::DisposableMemoryManager() : _mem_planner{createMemoryPlanner()}
+{
+  // DO NOTHING
+}
+
+DisposableMemoryManager::DisposableMemoryManager(const std::string planner_id)
+  : _mem_planner{createMemoryPlanner(planner_id)}
+{
+  // DO NOTHING
+}
+
+basic::IMemoryPlanner<DisposableTensorIndex> *DisposableMemoryManager::createMemoryPlanner()
+{
+  auto planner_id = util::getConfigString(util::config::CPU_MEMORY_PLANNER);
+  return MemoryPlannerFactory::get().create(planner_id);
+}
+
+basic::IMemoryPlanner<DisposableTensorIndex> *
+DisposableMemoryManager::createMemoryPlanner(const std::string planner_id)
+{
+  return MemoryPlannerFactory::get().create(planner_id);
+}
+
+void DisposableMemoryManager::claimPlan(const DisposableTensorIndex &ind, uint32_t size)
+{
+  _mem_planner->claim(ind, size);
+}
+
+void DisposableMemoryManager::releasePlan(const DisposableTensorIndex &ind)
+{
+  _mem_planner->release(ind);
+}
+
+void DisposableMemoryManager::allocate(void)
+{
+  _mem_alloc = std::make_shared<basic::Allocator>(_mem_planner->capacity());
+  assert(_mem_alloc->base());
+}
+
+uint8_t *DisposableMemoryManager::getBuffer(const DisposableTensorIndex &ind) const
+{
+  assert(_mem_planner->memory_plans().find(ind) != _mem_planner->memory_plans().end());
+  const auto &mem_blk = _mem_planner->memory_plans().at(ind);
+  return _mem_alloc->base() + mem_blk.offset;
+}
+
+} // namespace train
+} // namespace backend
+} // namespace onert
index 6ac5799..987cf90 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <backend/basic/MemoryManager.h>
 
+#include "DisposableTensorIndex.h"
+
 namespace onert
 {
 namespace backend
@@ -28,6 +30,44 @@ namespace train
 
 using MemoryManager = backend::basic::MemoryManager;
 
+class GradientMemoryManager : public MemoryManager
+{
+public:
+  GradientMemoryManager(const std::string planner_id, uint32_t optimizer_vars_count);
+  virtual ~GradientMemoryManager() = default;
+
+  void allocate(void);
+  uint8_t *getOptVarBuffer(const ir::OperandIndex &ind, uint32_t pos_var) const;
+
+private:
+  std::shared_ptr<basic::Allocator> _var_mem_alloc;
+  uint32_t _optim_vars_count;
+};
+
+class DisposableMemoryManager
+{
+public:
+  DisposableMemoryManager();
+  DisposableMemoryManager(const std::string planner_id);
+
+  void allocate(void);
+  uint8_t *getBuffer(const DisposableTensorIndex &ind) const;
+  void deallocate(void) { _mem_alloc->release(); }
+
+  void claimPlan(const DisposableTensorIndex &ind, uint32_t size);
+  void releasePlan(const DisposableTensorIndex &ind);
+
+  std::shared_ptr<basic::Allocator> getMemAlloc() { return _mem_alloc; }
+
+private:
+  basic::IMemoryPlanner<DisposableTensorIndex> *createMemoryPlanner();
+  basic::IMemoryPlanner<DisposableTensorIndex> *createMemoryPlanner(const std::string planner_id);
+
+private:
+  std::shared_ptr<basic::IMemoryPlanner<DisposableTensorIndex>> _mem_planner;
+  std::shared_ptr<basic::Allocator> _mem_alloc;
+};
+
 } // namespace train
 } // namespace backend
 } // namespace onert
diff --git a/runtime/onert/backend/train/MemoryPlanner.cc b/runtime/onert/backend/train/MemoryPlanner.cc
new file mode 100644 (file)
index 0000000..4576c2b
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "MemoryPlanner.h"
+
+#include <util/logging.h>
+
+#include <cassert>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+void BumpPlanner::claim(const DisposableTensorIndex &ind, size_t size)
+{
+  basic::Block blk{_capacity, size};
+  _mem_plans[ind] = blk;
+  _capacity += size;
+
+  VERBOSE(BP_PLANNER) << "CLAIM(" << ind << "): " << blk.offset << ", " << blk.size << std::endl;
+}
+
+void BumpPlanner::release(const DisposableTensorIndex &ind)
+{
+  VERBOSE(BP_PLANNER) << "RELEASE(" << ind << "): "
+                      << "NOTHING does" << std::endl;
+}
+
+// There are some assumptions for claiming memory(== making a reservation for memory).
+// 1. About _claim_table(std::map).
+//   - The table's data structure is std::map so that it always sorts
+//     value(Index) by key(base_offset).
+//   - This claim() inserts key/value into _claim_table and the release() removes the key/value from
+//     _claim_table.
+//   - _claim_table shows the memory status at a certain point in time. Therefore,
+//     - If _claim_table has an offset and a certain size at a certain point in time,
+//       it means the place at the offset has been already claimed(== can't claim now. need to find
+//       someplace new).
+//     - If _claim_table doesn't have any element for an offset and a certain size at a certain
+//       point in time, it means the place at the offset can be claimed.
+// 2. In the loop for _claim_table, we can assume the current claim_base_offset value is bigger than
+//    the previous claim_base_offset.
+void FirstFitPlanner::claim(const DisposableTensorIndex &ind, size_t size)
+{
+  // Find the right position for claiming
+  uint32_t next_offset = 0;
+  for (const auto &mem_claim : _claim_table)
+  {
+    auto claimed_base_offset = mem_claim.first;
+    auto claimed_size = _mem_plans[mem_claim.second].size;
+    if (next_offset + size <= claimed_base_offset)
+    {
+      break;
+    }
+    else
+    {
+      next_offset = claimed_base_offset + claimed_size;
+    }
+  }
+
+  // Now next_offset is set to the proper offset
+  // std::map's operator[] requires default constructor of value
+  // _claim_table[next_offset] = ind;
+  _claim_table.emplace(std::make_pair(next_offset, ind));
+  _mem_plans[ind] = {next_offset, size};
+
+  VERBOSE(FF_PLANNER) << "claim(" << ind << "): [+" << next_offset << ", " << size << "sz]"
+                      << std::endl;
+
+  if (_capacity < next_offset + size)
+  {
+    _capacity = next_offset + size;
+  }
+}
+
+void FirstFitPlanner::release(const DisposableTensorIndex &ind)
+{
+  for (auto it = _claim_table.cbegin(); it != _claim_table.cend(); ++it)
+  {
+    if (it->second == ind)
+    {
+      uint32_t offset = it->first;
+      uint32_t size = _mem_plans[ind].size;
+
+      _claim_table.erase(it);
+
+      VERBOSE(FF_PLANNER) << "release(" << ind << "): [+" << offset << ", " << size << "sz]"
+                          << std::endl;
+      return;
+    }
+  }
+  assert(!"Cannot release for given index. It has been not claimed or released already.");
+}
+
+WICPlanner::WICPlanner()
+  : _initialized(false), _capacity(0), _mem_plans(), _live_indices(), _interference_graph(),
+    _indices()
+{
+  // DO NOTHING
+}
+
+void WICPlanner::claim(const DisposableTensorIndex &ind, size_t size)
+{
+  _indices.emplace(size, ind);
+  _interference_graph[ind].insert(_interference_graph[ind].end(), _live_indices.cbegin(),
+                                  _live_indices.cend());
+  for (const auto &live_operand : _live_indices)
+  {
+    _interference_graph[live_operand].emplace_back(ind);
+  }
+  _live_indices.emplace(ind);
+
+  VERBOSE(WIC_PLANNER) << "claim(" << ind << "): [" << size << "sz]" << std::endl;
+}
+
+void WICPlanner::release(const DisposableTensorIndex &ind)
+{
+  _live_indices.erase(ind);
+  VERBOSE(WIC_PLANNER) << "release(" << ind << ")" << std::endl;
+}
+
+/*
+ * Build memory plans using liveness and size of operands
+ * 1. Build inference graph at claim
+ *   - Two operands interfere if they have overlapped live range
+ * 2. Sort operands in descending order of size
+ *   - Use std::multimap to sort operands
+ * 3. Allocate memory block for sorted operands
+ *   - Find free memory block which does not overlap with interfered operands
+ */
+void WICPlanner::buildMemoryPlans()
+{
+  for (const auto &operand : _indices)
+  {
+    uint32_t size = operand.first;
+    const DisposableTensorIndex &ind = operand.second;
+    VERBOSE(WIC_PLANNER) << "build_plan(" << ind << "): [" << size << "sz]" << std::endl;
+
+    uint32_t next_offset = 0;
+    if (_interference_graph.count(ind))
+    {
+      // Find interfered memory plans and sort them by offset
+      std::multimap<uint32_t, uint32_t> interfered_plans;
+      for (const auto &interference : _interference_graph[ind])
+      {
+        if (_mem_plans.count(interference))
+          interfered_plans.emplace(_mem_plans[interference].offset, _mem_plans[interference].size);
+      }
+
+      // Find free memory block in first-fit manner
+      for (const auto &interfered_plan : interfered_plans)
+      {
+        auto claimed_base_offset = interfered_plan.first;
+        auto claimed_size = interfered_plan.second;
+        VERBOSE(WIC_PLANNER) << "interfere : [+" << claimed_base_offset << ", " << claimed_size
+                             << "sz]" << std::endl;
+        if (next_offset + size <= claimed_base_offset)
+        {
+          break;
+        }
+        else if (next_offset < claimed_base_offset + claimed_size)
+        {
+          next_offset = claimed_base_offset + claimed_size;
+        }
+      }
+    }
+    else
+    {
+      VERBOSE(WIC_PLANNER) << "No interference" << std::endl;
+    }
+
+    _mem_plans[ind] = {next_offset, size};
+    VERBOSE(WIC_PLANNER) << "alloc(" << ind << "): [+" << next_offset << ", " << size << "sz]"
+                         << std::endl;
+
+    if (_capacity < next_offset + size)
+    {
+      _capacity = next_offset + size;
+    }
+  }
+  _initialized = true;
+  _interference_graph.clear();
+  _indices.clear();
+}
+
+std::unordered_map<DisposableTensorIndex, basic::Block> &WICPlanner::memory_plans()
+{
+  if (!_initialized)
+    buildMemoryPlans();
+  return _mem_plans;
+}
+
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/MemoryPlanner.h b/runtime/onert/backend/train/MemoryPlanner.h
new file mode 100644 (file)
index 0000000..181dd5e
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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        MemoryPlanner.h
+ * @brief       This file contains Memory Planning related classes
+ */
+
+#ifndef __ONERT_BACKEND_TRAIN_MEMORY_PLANNER_H__
+#define __ONERT_BACKEND_TRAIN_MEMORY_PLANNER_H__
+
+#include <backend/basic/IMemoryPlanner.h>
+
+#include "DisposableTensorIndex.h"
+
+#include <map>
+#include <vector>
+#include <unordered_set>
+#include <memory>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+/**
+ * @brief Class to plan memory by bump way
+ */
+class BumpPlanner : public basic::IMemoryPlanner<DisposableTensorIndex>
+{
+public:
+  /**
+   * @brief Claim memory for tensor by bump way
+   * @param[in] index The tensor index
+   * @param[in] size The size of the memory
+   */
+  void claim(const DisposableTensorIndex &, size_t) override;
+  /**
+   * @brief Release memory for tensor by bump way
+   * @param[in] index The tensor index
+   */
+  void release(const DisposableTensorIndex &) override;
+  /**
+   * @brief Get capacity for memory planning
+   * @return The value of capacity
+   */
+  uint32_t capacity() override { return _capacity; }
+  /**
+   * @brief Get MemoryPlans
+   * @return MemoryPlans
+   */
+  MemoryPlans &memory_plans() override { return _mem_plans; }
+
+private:
+  uint32_t _capacity = 0;
+  MemoryPlans _mem_plans;
+};
+
+/**
+ * @brief Class to plan memory by firstfit way
+ */
+class FirstFitPlanner : public basic::IMemoryPlanner<DisposableTensorIndex>
+{
+public:
+  /**
+   * @brief Claim memory for tensor by firstfit way
+   * @param[in] index The tensor index
+   * @param[in] size The size of the memory
+   */
+  void claim(const DisposableTensorIndex &, size_t) override;
+  /**
+   * @brief Release memory for tensor by firstfit way
+   * @param[in] index The tensor index
+   */
+  void release(const DisposableTensorIndex &) override;
+  /**
+   * @brief Get capacity for memory planning
+   * @return The value of capacity
+   */
+  uint32_t capacity() override { return _capacity; }
+  /**
+   * @brief Get MemoryPlans
+   * @return MemoryPlans
+   */
+  MemoryPlans &memory_plans() override { return _mem_plans; }
+
+private:
+  uint32_t _capacity = 0;
+  MemoryPlans _mem_plans;
+  // Use std::map because claim() assumes that _claim_table is sorted by uint32_t(base_offset)
+  std::map<uint32_t, DisposableTensorIndex> _claim_table;
+};
+
+/**
+ * @brief Class to plan memory by Weighted Interval Color algorithm
+ */
+class WICPlanner : public basic::IMemoryPlanner<DisposableTensorIndex>
+{
+public:
+  WICPlanner();
+
+  /**
+   * @brief Claim memory for tensor by WIC algorithm
+   * @param[in] index The tensor index
+   * @param[in] size The size of the memory
+   */
+  void claim(const DisposableTensorIndex &, size_t) override;
+  /**
+   * @brief Release memory for tensor by WIC algorithm
+   * @param[in] index The tensor index
+   */
+  void release(const DisposableTensorIndex &) override;
+  /**
+   * @brief Get capacity for memory planning
+   * @return The value of capacity
+   */
+  uint32_t capacity() override
+  {
+    if (!_initialized)
+      buildMemoryPlans();
+    return _capacity;
+  }
+  /**
+   * @brief Get MemoryPlans
+   * @return MemoryPlans
+   */
+  MemoryPlans &memory_plans() override;
+
+private:
+  void buildMemoryPlans();
+
+  bool _initialized;
+  uint32_t _capacity;
+  MemoryPlans _mem_plans;
+  std::unordered_set<DisposableTensorIndex> _live_indices;
+  DisposableTensorIndexMap<std::vector<DisposableTensorIndex>> _interference_graph;
+  // Sort tensors by descending order of size
+  std::multimap<uint32_t, DisposableTensorIndex, std::greater<uint32_t>> _indices;
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_MEMORY_PLANNER_H__
diff --git a/runtime/onert/backend/train/MemoryPlanner.test.cc b/runtime/onert/backend/train/MemoryPlanner.test.cc
new file mode 100644 (file)
index 0000000..8978607
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "MemoryPlanner.h"
+#include "ir/Index.h"
+
+using namespace onert::backend::train;
+using onert::ir::OperandIndex;
+using onert::ir::OperationIndex;
+
+TEST(BumpPlanner, claim_test)
+{
+  BumpPlanner planner;
+
+  auto claim = [&planner](uint32_t op_index, uint32_t operand_index, size_t size,
+                          uint32_t expected_offset) {
+    DisposableTensorIndex mem_idx{OperationIndex{op_index}, OperandIndex{operand_index}};
+    planner.claim(mem_idx, size);
+    auto mem_blk = planner.memory_plans()[mem_idx];
+    ASSERT_EQ(mem_blk.offset, expected_offset);
+    ASSERT_EQ(mem_blk.size, size);
+  };
+
+  auto release = [&planner](uint32_t op_index, uint32_t operand_index) {
+    DisposableTensorIndex mem_idx{OperationIndex{op_index}, OperandIndex{operand_index}};
+    planner.release(mem_idx);
+  };
+
+  auto capacity = [&planner](uint32_t expected_capacity) {
+    auto actual_capacity = planner.capacity();
+    ASSERT_EQ(actual_capacity, expected_capacity);
+  };
+
+  claim(0, 0, 10, 0);
+  claim(1, 0, 20, 10);
+  claim(2, 2, 30, 30);
+  release(0, 0);
+  capacity(60);
+}
+
+TEST(FirstFitPlanner, claim_release_test)
+{
+  FirstFitPlanner planner;
+
+  auto claim = [&planner](uint32_t op_index, uint32_t operand_index, size_t size,
+                          uint32_t expected_offset) {
+    DisposableTensorIndex mem_idx{OperationIndex{op_index}, OperandIndex{operand_index}};
+    planner.claim(mem_idx, size);
+    auto mem_blk = planner.memory_plans()[mem_idx];
+    ASSERT_EQ(mem_blk.offset, expected_offset);
+    ASSERT_EQ(mem_blk.size, size);
+  };
+
+  auto release = [&planner](uint32_t op_index, uint32_t operand_index) {
+    DisposableTensorIndex mem_idx{OperationIndex{op_index}, OperandIndex{operand_index}};
+    planner.release(mem_idx);
+  };
+
+  auto capacity = [&planner](uint32_t expected_capacity) {
+    auto actual_capacity = planner.capacity();
+    ASSERT_EQ(actual_capacity, expected_capacity);
+  };
+
+  // 0 CLAIM - 10
+  claim(0, 0, 10, 0);
+
+  // 1 CLAIM - 20
+  claim(1, 0, 20, 10);
+
+  // 2 CLAIM - 30
+  claim(2, 2, 30, 30);
+
+  // 0 RELEASE - 10
+  release(0, 0);
+
+  // 3 CLAIM - 20
+  claim(3, 1, 20, 60);
+
+  // 4 CLAIM - 5
+  claim(4, 1, 5, 0);
+
+  // 5 CLAIM - 10
+  claim(5, 1, 10, 80);
+
+  // 6 CLAIM - 5
+  claim(6, 1, 5, 5);
+
+  // 2 RELEASE - 30
+  release(2, 2);
+
+  // 7 CLAIM - 35
+  claim(7, 1, 35, 90);
+
+  // 8 CLAIM - 10
+  claim(8, 1, 10, 30);
+
+  // 4 RELEASE - 5
+  release(4, 1);
+
+  // 9 CLAIM - 10
+  claim(9, 0, 10, 40);
+
+  // 10 CLAIM - 10
+  claim(10, 0, 10, 50);
+
+  // 6 RELEASE
+  release(6, 1);
+
+  // 1 RELEASE
+  release(1, 0);
+
+  // 8 RELEASE
+  release(8, 1);
+
+  // 9 RELEASE
+  release(9, 0);
+
+  // 10 RELEASE
+  release(10, 0);
+
+  // 3 RELEASE
+  release(3, 1);
+
+  // 5 RELEASE
+  release(5, 1);
+
+  // 7 RELEASE
+  release(7, 1);
+
+  // CAPACITY - 125
+  capacity(125);
+}
+
+TEST(FirstFitPlanner, neg_release_non_existing_index)
+{
+  FirstFitPlanner planner;
+
+  auto claim = [&planner](uint32_t op_index, uint32_t operand_index, size_t size,
+                          uint32_t expected_offset) {
+    DisposableTensorIndex mem_idx{OperationIndex{op_index}, OperandIndex{operand_index}};
+    planner.claim(mem_idx, size);
+    auto mem_blk = planner.memory_plans()[mem_idx];
+    ASSERT_EQ(mem_blk.offset, expected_offset);
+    ASSERT_EQ(mem_blk.size, size);
+  };
+
+  auto release = [&planner](uint32_t op_index, uint32_t operand_index) {
+    DisposableTensorIndex mem_idx{OperationIndex{op_index}, OperandIndex{operand_index}};
+    planner.release(mem_idx);
+  };
+
+  // 0 CLAIM - 10
+  claim(0, 0, 10, 0);
+
+  // 1 CLAIM - 20
+  claim(1, 0, 20, 10);
+
+  // 2 CLAIM - 30
+  claim(2, 2, 30, 30);
+
+  // RELEASE non-existing index
+  auto on_only_debug_mode = [&release]() {
+    EXPECT_DEATH({ release(0, 1); },
+                 "Cannot release for given index. It has been not claimed or released already.");
+    return true;
+  };
+  assert(on_only_debug_mode());
+}
+
+TEST(FirstFitPlanner, neg_release_twice)
+{
+  FirstFitPlanner planner;
+
+  auto claim = [&planner](uint32_t op_index, uint32_t operand_index, size_t size,
+                          uint32_t expected_offset) {
+    DisposableTensorIndex mem_idx{OperationIndex{op_index}, OperandIndex{operand_index}};
+    planner.claim(mem_idx, size);
+    auto mem_blk = planner.memory_plans()[mem_idx];
+    ASSERT_EQ(mem_blk.offset, expected_offset);
+    ASSERT_EQ(mem_blk.size, size);
+  };
+
+  auto release = [&planner](uint32_t op_index, uint32_t operand_index) {
+    DisposableTensorIndex mem_idx{OperationIndex{op_index}, OperandIndex{operand_index}};
+    planner.release(mem_idx);
+  };
+
+  // 0 CLAIM - 10
+  claim(0, 0, 10, 0);
+
+  // 1 CLAIM - 20
+  claim(1, 0, 20, 10);
+
+  // 2 CLAIM - 30
+  claim(2, 2, 30, 30);
+
+  // 0 RELEASE - 10
+  release(0, 0);
+
+  // 0 RELEASE again
+  auto on_only_debug_mode = [&release]() {
+    EXPECT_EXIT({ release(0, 0); }, ::testing::KilledBySignal(SIGABRT),
+                "Cannot release for given index. It has been not claimed or released already.");
+    return true;
+  };
+  assert(on_only_debug_mode());
+}
+
+TEST(WICPlanner, claim_release_test)
+{
+  WICPlanner planner;
+
+  auto claim = [&planner](uint32_t op_index, uint32_t operand_index, size_t size) {
+    DisposableTensorIndex mem_idx{OperationIndex{op_index}, OperandIndex{operand_index}};
+    planner.claim(mem_idx, size);
+  };
+
+  auto release = [&planner](uint32_t op_index, uint32_t operand_index) {
+    DisposableTensorIndex mem_idx{OperationIndex{op_index}, OperandIndex{operand_index}};
+    planner.release(mem_idx);
+  };
+
+  auto verify = [&planner](uint32_t op_index, uint32_t operand_index, uint32_t size,
+                           uint32_t expected_offset) {
+    DisposableTensorIndex mem_idx(OperationIndex{op_index}, OperandIndex{operand_index});
+    auto mem_blk = planner.memory_plans()[mem_idx];
+    ASSERT_EQ(mem_blk.offset, expected_offset);
+    ASSERT_EQ(mem_blk.size, size);
+  };
+
+  auto capacity = [&planner](uint32_t expected_capacity) {
+    auto actual_capacity = planner.capacity();
+    ASSERT_EQ(actual_capacity, expected_capacity);
+  };
+
+  claim(0, 0, 20);
+  claim(1, 0, 5);
+  release(0, 0);
+  claim(2, 2, 10);
+  release(1, 0);
+  claim(3, 1, 10);
+  release(2, 2);
+  claim(4, 1, 10);
+  release(3, 1);
+  claim(5, 1, 20);
+  release(4, 1);
+  claim(6, 1, 20);
+  release(5, 1);
+
+  // VERIFY 0 - 0
+  verify(0, 0, 20, 0);
+
+  // VERIFY 1 - 20
+  verify(1, 0, 5, 20);
+
+  // VERIFY 2 - 0
+  verify(2, 2, 10, 0);
+
+  // VERIFY 3 - 10
+  verify(3, 1, 10, 10);
+
+  // VERIFY 4 - 20
+  verify(4, 1, 10, 20);
+
+  // VERIFY 5 - 0
+  verify(5, 1, 20, 0);
+
+  // VERIFY 6 - 20
+  verify(6, 1, 20, 20);
+
+  // CAPACITY - 40
+  capacity(40);
+}
diff --git a/runtime/onert/backend/train/MemoryPlannerFactory.cc b/runtime/onert/backend/train/MemoryPlannerFactory.cc
new file mode 100644 (file)
index 0000000..acfa44e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "MemoryPlannerFactory.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+MemoryPlannerFactory &MemoryPlannerFactory::get()
+{
+  static MemoryPlannerFactory instance;
+  return instance;
+}
+
+basic::IMemoryPlanner<DisposableTensorIndex> *MemoryPlannerFactory::create(const std::string &key)
+{
+  if (key == "FirstFit")
+  {
+    return new FirstFitPlanner;
+  }
+  else if (key == "Bump")
+  {
+    return new BumpPlanner;
+  }
+  else if (key == "WIC")
+  {
+    return new WICPlanner;
+  }
+  return new FirstFitPlanner; // Default Planner
+}
+
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/MemoryPlannerFactory.h b/runtime/onert/backend/train/MemoryPlannerFactory.h
new file mode 100644 (file)
index 0000000..d1609e1
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_PLANNER_FACTORY_H__
+#define __ONERT_BACKEND_TRAIN_MEMORY_PLANNER_FACTORY_H__
+
+#include "MemoryPlanner.h"
+
+#include <string>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+class MemoryPlannerFactory
+{
+public:
+  static MemoryPlannerFactory &get();
+
+private:
+  MemoryPlannerFactory() = default;
+
+public:
+  // Currently, only the memory planner for DisposableTensor is supported
+  basic::IMemoryPlanner<DisposableTensorIndex> *create(const std::string &key);
+};
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_MEMORY_PLANNER_FACTORY_H__
index 34a3cc1..64e184a 100644 (file)
@@ -45,7 +45,7 @@ public:
 };
 
 using TrainableTensor = basic::train::TrainableTensor;
-using DerivativeTensor = Tensor;
+using BackPropTensor = Tensor;
 using GradientTensor = Tensor;
 
 } // namespace train
index 99e06d3..640a018 100644 (file)
@@ -26,8 +26,11 @@ namespace train
 {
 
 TensorBuilder::TensorBuilder(const std::shared_ptr<TensorRegistry> &tensor_reg,
+                             const exec::train::optimizer::Optimizer *optimizer,
                              const std::string planner_id)
-  : _tensor_reg{tensor_reg}, _tensor_mgr{new TensorManager(tensor_reg, planner_id)}
+  : _tensor_reg{tensor_reg},
+    _tensor_mgr{new TensorManager(tensor_reg, planner_id, optimizer->getVarCount())},
+    _optimizer{optimizer}
 {
   /* empty */
 }
@@ -72,14 +75,36 @@ void TensorBuilder::registerBackwardTensorInfo(const ir::OperandIndex &index,
   {
     auto tensor = std::make_unique<GradientTensor>(info, layout);
     _tensor_reg->setGradientTensor(index, std::move(tensor));
+
+    // Initialize tensors for gradient variables
+    for (uint32_t i = 0; i < _optimizer->getVarCount(); ++i)
+    {
+      auto tensor = std::make_unique<Tensor>(info, layout);
+      _tensor_reg->getTrainableTensor(index)->appendOptVar(std::move(tensor));
+    }
   }
   else
   {
-    auto tensor = std::make_unique<DerivativeTensor>(info, layout);
-    _tensor_reg->setDerivativeTensor(index, std::move(tensor));
+    auto tensor = std::make_unique<BackPropTensor>(info, layout);
+    _tensor_reg->setBackPropTensor(index, std::move(tensor));
   }
 }
 
+void TensorBuilder::registerDisposableBackwardTensorInfo(const DisposableTensorIndex &index,
+                                                         const ir::OperandInfo &info,
+                                                         ir::Layout layout)
+{
+  // Train backend supports only one layout as NHWC
+  assert(layout == ir::Layout::NHWC);
+  assert(!info.isDynamic());
+  assert(!_as_constants[index.operand_index()]);
+
+  auto disposable_tensor = std::make_unique<BackPropTensor>(info, layout);
+  _tensor_reg->setDisposableBackPropTensor(index, std::move(disposable_tensor));
+
+  _disposable_backprops.add(index);
+}
+
 void TensorBuilder::notifyFirstUse(const ir::OperandIndex &index)
 {
   // TODO Support momory plan
@@ -107,10 +132,20 @@ void TensorBuilder::notifyBackwardFirstUse(const ir::OperandIndex &index)
   }
   else
   {
-    _tensor_mgr->claimDerivativePlan(index);
+    _tensor_mgr->claimBackPropPlan(index);
   }
 }
 
+void TensorBuilder::notifyDisposableBackPropFirstUse(const DisposableTensorIndex &index)
+{
+  _tensor_mgr->claimDisposableBackPropPlan(index);
+}
+
+void TensorBuilder::notifyDisposableBackPropLastUse(const DisposableTensorIndex &index)
+{
+  _tensor_mgr->releaseDisposableBackPropPlan(index);
+}
+
 bool TensorBuilder::isRegistered(const ir::OperandIndex &index) const
 {
   return _tensor_info_map.find(index) != _tensor_info_map.end();
@@ -121,6 +156,11 @@ bool TensorBuilder::isRegisteredBackward(const ir::OperandIndex &index) const
   return _backward_tensor_info_map.find(index) != _backward_tensor_info_map.end();
 }
 
+bool TensorBuilder::isRegisteredDisposableBackwardTensor(const DisposableTensorIndex &index) const
+{
+  return _disposable_backprops.contains(index);
+}
+
 void TensorBuilder::allocate(void)
 {
   _tensor_mgr->allocateNonConstTensors();
@@ -129,8 +169,9 @@ void TensorBuilder::allocate(void)
 
 void TensorBuilder::allocateBackward(void)
 {
-  _tensor_mgr->allocateDerivativeTensors();
+  _tensor_mgr->allocateBackPropTensors();
   _tensor_mgr->allocateGradientTensors();
+  _tensor_mgr->allocateDisposableBackPropTensors();
 }
 
 } // namespace train
index d0738fe..8aef64c 100644 (file)
 #ifndef __ONERT_BACKEND_TRAIN_TENSOR_BUILDER_H__
 #define __ONERT_BACKEND_TRAIN_TENSOR_BUILDER_H__
 
+#include "DisposableTensorIndex.h"
 #include "TensorManager.h"
 #include "TensorRegistry.h"
+#include "util/Set.h"
+
+#include <exec/train/optimizer/Optimizer.h>
 
 namespace onert
 {
@@ -31,7 +35,8 @@ namespace train
 class TensorBuilder
 {
 public:
-  TensorBuilder(const std::shared_ptr<TensorRegistry> &tensor_reg, const std::string planner_id);
+  TensorBuilder(const std::shared_ptr<TensorRegistry> &tensor_reg,
+                const exec::train::optimizer::Optimizer *optimizer, const std::string planner_id);
 
   /**
    * @brief     Register tensor information to allocate on train backend
@@ -51,13 +56,19 @@ public:
   void registerBackwardTensorInfo(const ir::OperandIndex &ind, const ir::OperandInfo &info,
                                   ir::Layout backend_layout);
 
+  void registerDisposableBackwardTensorInfo(const DisposableTensorIndex &index,
+                                            const ir::OperandInfo &info, ir::Layout layout);
+
   // TODO Support memory plan of all tensors
   void notifyFirstUse(const ir::OperandIndex &);
   void notifyLastUse(const ir::OperandIndex &);
   void notifyBackwardFirstUse(const ir::OperandIndex &);
+  void notifyDisposableBackPropFirstUse(const DisposableTensorIndex &);
+  void notifyDisposableBackPropLastUse(const DisposableTensorIndex &);
 
   bool isRegistered(const ir::OperandIndex &) const;
   bool isRegisteredBackward(const ir::OperandIndex &) const;
+  bool isRegisteredDisposableBackwardTensor(const DisposableTensorIndex &index) const;
 
   void allocate(void);
   void allocateBackward(void);
@@ -68,6 +79,8 @@ private:
   ir::OperandIndexMap<ir::OperandInfo> _tensor_info_map;
   ir::OperandIndexMap<ir::OperandInfo> _backward_tensor_info_map;
   ir::OperandIndexMap<bool> _as_constants;
+  util::Set<DisposableTensorIndex> _disposable_backprops;
+  const exec::train::optimizer::Optimizer *_optimizer;
 };
 
 } // namespace train
index 50144a7..804e6f3 100644 (file)
@@ -23,10 +23,8 @@ 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)
+template <typename MemoryManager, typename TensorMap>
+void allocateMemory(MemoryManager *mgr, const TensorMap &tensors, const std::string tensor_type)
 {
   mgr->allocate();
 
@@ -43,6 +41,11 @@ void allocateMemory(backend::train::MemoryManager *mgr,
   }
 }
 
+inline size_t alignedSize(const size_t size, const uint64_t align)
+{
+  return (((size) + ((align)-1)) & ~((align)-1));
+}
+
 } // namespace
 
 namespace onert
@@ -53,10 +56,12 @@ namespace train
 {
 
 TensorManager::TensorManager(const std::shared_ptr<TensorRegistry> &reg,
-                             const std::string planner_id)
+                             const std::string planner_id, uint32_t optim_vars_count)
   : _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}
+    _back_prop_mgr{new MemoryManager(planner_id)},
+    _gradient_mgr{new GradientMemoryManager(planner_id, optim_vars_count)},
+    // TODO Find a suitable planner of disposable tensors to reduce peak memory usage
+    _disposable_back_prop_mgr{new DisposableMemoryManager(std::string("WIC"))}, _tensors{reg}
 {
   // DO NOTHING
 }
@@ -64,25 +69,46 @@ TensorManager::TensorManager(const std::shared_ptr<TensorRegistry> &reg,
 void TensorManager::allocateNonConstTensors()
 {
   allocateMemory(_nonconst_mgr.get(), _tensors->nonconst_tensors(),
-                 std::string{"          TENSOR "});
+                 std::string{"               TENSOR "});
 }
 
 void TensorManager::allocateTrainableTensors()
 {
   allocateMemory(_trainable_mgr.get(), _tensors->trainable_tensors(),
-                 std::string{"TRAINABLE TENSOR "});
+                 std::string{"     TRAINABLE TENSOR "});
 }
 
-void TensorManager::allocateDerivativeTensors()
+void TensorManager::allocateBackPropTensors()
 {
-  allocateMemory(_derivative_mgr.get(), _tensors->derivative_tensors(),
-                 std::string{"DERIVATIVE TENSOR "});
+  allocateMemory(_back_prop_mgr.get(), _tensors->back_prop_tensors(),
+                 std::string{"     BACK_PROP TENSOR "});
 }
 
 void TensorManager::allocateGradientTensors()
 {
   allocateMemory(_gradient_mgr.get(), _tensors->gradient_tensors(),
-                 std::string{"GRADIENT TENSOR "});
+                 std::string{"     GRADIENT TENSOR "});
+
+  // Set buffers of optimizer variables
+  // Allocating optimizer variables has been done when calling allocate() of GradientMemoryManager
+  for (const auto &pair : _tensors->gradient_tensors())
+  {
+    const auto &index = pair.first;
+    const auto trainable_tensor = _tensors->trainable_tensors().at(index).get();
+    for (uint32_t var_pos = 0; var_pos < trainable_tensor->optVars().size(); ++var_pos)
+    {
+      auto *buffer = _gradient_mgr.get()->getOptVarBuffer(index, var_pos);
+      trainable_tensor->setOptVarBuffer(buffer, var_pos);
+      VERBOSE(TensorManager) << std::string{"     OPTIM_VAR TENSOR "} << index << " : "
+                             << static_cast<void *>(buffer) << std::endl;
+    }
+  }
+}
+
+void TensorManager::allocateDisposableBackPropTensors()
+{
+  allocateMemory(_disposable_back_prop_mgr.get(), _tensors->disposable_back_prop_tensors(),
+                 std::string{"DISPOSABLE BACK_PROP TENSOR "});
 }
 
 void TensorManager::claimNonConstPlan(const ir::OperandIndex &index)
@@ -90,7 +116,7 @@ void TensorManager::claimNonConstPlan(const ir::OperandIndex &index)
   auto tensor = _tensors->getNonConstTensor(index);
   assert(tensor && !tensor->is_dynamic());
 
-  auto size = tensor->total_size();
+  auto size = alignedSize(tensor->total_size(), _align);
   _nonconst_mgr->claimPlan(index, size);
 }
 
@@ -106,7 +132,7 @@ void TensorManager::claimTrainablePlan(const ir::OperandIndex &index)
   auto tensor = _tensors->getTrainableTensor(index);
   assert(tensor && !tensor->is_dynamic());
 
-  auto size = tensor->total_size();
+  auto size = alignedSize(tensor->total_size(), _align);
   _trainable_mgr->claimPlan(index, size);
 }
 
@@ -117,21 +143,20 @@ void TensorManager::releaseTrainablePlan(const ir::OperandIndex &index)
   _trainable_mgr->releasePlan(index);
 }
 
-void TensorManager::claimDerivativePlan(const ir::OperandIndex &index)
+void TensorManager::claimBackPropPlan(const ir::OperandIndex &index)
 {
-  auto tensor = _tensors->getDerivativeTensor(index);
+  auto tensor = _tensors->getBackPropTensor(index);
   assert(tensor && !tensor->is_dynamic());
 
-  auto size = tensor->total_size();
-  _derivative_mgr->claimPlan(index, size);
+  auto size = alignedSize(tensor->total_size(), _align);
+  _back_prop_mgr->claimPlan(index, size);
 }
 
-void TensorManager::releaseDerivativePlan(const ir::OperandIndex &index)
+void TensorManager::releaseBackPropPlan(const ir::OperandIndex &index)
 {
-  assert(_tensors->getDerivativeTensor(index) &&
-         !_tensors->getDerivativeTensor(index)->is_dynamic());
+  assert(_tensors->getBackPropTensor(index) && !_tensors->getBackPropTensor(index)->is_dynamic());
 
-  _derivative_mgr->releasePlan(index);
+  _back_prop_mgr->releasePlan(index);
 }
 
 void TensorManager::claimGradientPlan(const ir::OperandIndex &index)
@@ -139,7 +164,7 @@ void TensorManager::claimGradientPlan(const ir::OperandIndex &index)
   auto tensor = _tensors->getGradientTensor(index);
   assert(tensor && !tensor->is_dynamic());
 
-  auto size = tensor->total_size();
+  auto size = alignedSize(tensor->total_size(), _align);
   _gradient_mgr->claimPlan(index, size);
 }
 
@@ -150,6 +175,23 @@ void TensorManager::releaseGradientPlan(const ir::OperandIndex &index)
   _gradient_mgr->releasePlan(index);
 }
 
+void TensorManager::claimDisposableBackPropPlan(const DisposableTensorIndex &index)
+{
+  const auto tensor = _tensors->getDisposableBackPropTensor(index);
+  assert(tensor && !tensor->is_dynamic());
+
+  auto size = alignedSize(tensor->total_size(), _align);
+  _disposable_back_prop_mgr->claimPlan(index, size);
+}
+
+void TensorManager::releaseDisposableBackPropPlan(const DisposableTensorIndex &index)
+{
+  assert(_tensors->getDisposableBackPropTensor(index) &&
+         !_tensors->getDisposableBackPropTensor(index)->is_dynamic());
+
+  _disposable_back_prop_mgr->releasePlan(index);
+}
+
 } // namespace train
 } // namespace backend
 } // namespace onert
index 06da3ed..f8d29b1 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef __ONERT_BACKEND_TRAIN_TENSOR_MANAGER_H__
 #define __ONERT_BACKEND_TRAIN_TENSOR_MANAGER_H__
 
+#include "DisposableTensorIndex.h"
 #include "MemoryManager.h"
 #include "TensorRegistry.h"
 
@@ -33,29 +34,41 @@ namespace train
 class TensorManager
 {
 public:
-  TensorManager(const std::shared_ptr<TensorRegistry> &reg, const std::string planner_id);
+  // Minimum alignment for buffers
+  //
+  // _align is equal to EIGEN_MAX_ALIGN_BYTES, though including Eigen headers
+  // here to get that symbol may not be a good idea.
+  static constexpr uint64_t _align = 16;
+
+public:
+  TensorManager(const std::shared_ptr<TensorRegistry> &reg, const std::string planner_id,
+                uint32_t optim_vars_count);
   virtual ~TensorManager() = default;
 
   void allocateNonConstTensors();
   void allocateTrainableTensors();
-  void allocateDerivativeTensors();
+  void allocateBackPropTensors();
   void allocateGradientTensors();
+  void allocateDisposableBackPropTensors();
   // 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 claimBackPropPlan(const ir::OperandIndex &ind);
+  void releaseBackPropPlan(const ir::OperandIndex &ind);
   void claimGradientPlan(const ir::OperandIndex &ind);
   void releaseGradientPlan(const ir::OperandIndex &ind);
+  void claimDisposableBackPropPlan(const DisposableTensorIndex &ind);
+  void releaseDisposableBackPropPlan(const DisposableTensorIndex &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;
+  std::unique_ptr<MemoryManager> _back_prop_mgr;
+  std::unique_ptr<GradientMemoryManager> _gradient_mgr;
+  std::unique_ptr<DisposableMemoryManager> _disposable_back_prop_mgr;
   const std::shared_ptr<TensorRegistry> _tensors;
 };
 
index 34aeb0f..1393219 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <backend/train/ITensorRegistry.h>
 
+#include "DisposableTensorIndex.h"
 #include "Tensor.h"
 
 namespace onert
@@ -28,8 +29,41 @@ namespace backend
 namespace train
 {
 
-using TensorRegistry =
-  PortableTensorRegistryTemplate<Tensor, TrainableTensor, DerivativeTensor, GradientTensor>;
+class TensorRegistry
+  : public PortableTensorRegistryTemplate<Tensor, TrainableTensor, BackPropTensor, GradientTensor>
+{
+public:
+  BackPropTensor *getDisposableBackPropTensor(const DisposableTensorIndex &index)
+  {
+    auto itr = _disposable_back_prop.find(index);
+    if (itr != _disposable_back_prop.end())
+      return itr->second.get();
+
+    return nullptr;
+  }
+
+  void setDisposableBackPropTensor(const DisposableTensorIndex &index,
+                                   std::unique_ptr<BackPropTensor> tensor)
+  {
+    assert(tensor != nullptr);
+    auto itr = _disposable_back_prop.find(index);
+    if (itr != _disposable_back_prop.end())
+      throw std::runtime_error{
+        "Tried to set a disposable tensor but another disposable tensor already exists."};
+
+    _disposable_back_prop[index] = std::move(tensor);
+  }
+
+  const std::unordered_map<DisposableTensorIndex, std::unique_ptr<BackPropTensor>> &
+  disposable_back_prop_tensors()
+  {
+    return _disposable_back_prop;
+  }
+
+private:
+  // Disposable Tensors to be accumulated to BackPropTensor
+  std::unordered_map<DisposableTensorIndex, std::unique_ptr<BackPropTensor>> _disposable_back_prop;
+};
 
 } // namespace train
 } // namespace backend
diff --git a/runtime/onert/backend/train/ops/BackPropAccumulator.cc b/runtime/onert/backend/train/ops/BackPropAccumulator.cc
new file mode 100644 (file)
index 0000000..ecf6302
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BackPropAccumulator.h"
+
+#include "OperationUtils.h"
+
+#include <cker/operation/BinaryArithmeticOps.h>
+#include <util/CalculateActivationRange.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+BackPropAccumulator::BackPropAccumulator(const IPortableTensor *disposable_tensor,
+                                         IPortableTensor *back_prop_tensor)
+  : _disposable_tensor{disposable_tensor}, _back_prop_tensor{back_prop_tensor}
+{
+  if (disposable_tensor->getShape() != back_prop_tensor->getShape())
+    throw std::runtime_error("train BackPropAccumulator: Unsupported shapes");
+
+  float output_activation_min = 0, output_activation_max = 0;
+  util::CalculateActivationRange(ir::Activation::NONE, &output_activation_min,
+                                 &output_activation_max);
+  _op_params.float_activation_max = output_activation_max;
+  _op_params.float_activation_min = output_activation_min;
+}
+
+void BackPropAccumulator::forward(bool)
+{
+  // DO NOTHING
+}
+
+void BackPropAccumulator::backward()
+{
+  nnfw::cker::BinaryArithmeticOp<nnfw::cker::BinaryArithmeticOpType::ADD>(
+    _op_params, getShape(_disposable_tensor), getBuffer<float>(_disposable_tensor),
+    getShape(_back_prop_tensor), getBuffer<float>(_back_prop_tensor), getShape(_back_prop_tensor),
+    getBuffer<float>(_back_prop_tensor));
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/BackPropAccumulator.h b/runtime/onert/backend/train/ops/BackPropAccumulator.h
new file mode 100644 (file)
index 0000000..f7c1c66
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_BACKPROP_ACCUMULATOR_H__
+#define __ONERT_BACKEND_TRAIN_OPS_BACKPROP_ACCUMULATOR_H__
+
+#include <backend/IPortableTensor.h>
+#include <cker/Types.h>
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+// TODO Introduce IFunction for only backwarding
+class BackPropAccumulator : public exec::train::ITrainableFunction
+{
+public:
+  BackPropAccumulator(const IPortableTensor *disposable_tensor, IPortableTensor *back_prop_tensor);
+
+public:
+  void forward(bool training) override;
+  void backward() override;
+
+private:
+  const IPortableTensor *_disposable_tensor;
+  IPortableTensor *_back_prop_tensor;
+
+  nnfw::cker::BinaryArithmeticOpParam _op_params;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_BACKPROP_ACCUMULATOR_H__
diff --git a/runtime/onert/backend/train/ops/BackPropInitializer.cc b/runtime/onert/backend/train/ops/BackPropInitializer.cc
new file mode 100644 (file)
index 0000000..e8a4d9f
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BackPropInitializer.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+BackPropInitializer::BackPropInitializer(const std::vector<BackPropTensor *> back_props)
+  : _back_props{back_props}
+{
+  assert(std::all_of(back_props.cbegin(), back_props.cend(),
+                     [](const BackPropTensor *back_prop) { return back_prop != nullptr; }));
+}
+
+void BackPropInitializer::forward(bool)
+{
+  // DO NOTHING
+}
+
+void BackPropInitializer::backward()
+{
+  for (auto &&back_prop_tensor : _back_props)
+  {
+    assert(back_prop_tensor->buffer() != nullptr);
+    memset(back_prop_tensor->buffer(), 0, back_prop_tensor->total_size());
+  }
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/BackPropInitializer.h b/runtime/onert/backend/train/ops/BackPropInitializer.h
new file mode 100644 (file)
index 0000000..90e17fa
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_BACKPROP_INITIALIZER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_BACKPROP_INITIALIZER_H__
+
+#include <backend/IPortableTensor.h>
+#include <exec/train/ITrainableFunction.h>
+
+#include "../Tensor.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+// TODO Introduce IFunction for only backwarding
+class BackPropInitializer : public exec::train::ITrainableFunction
+{
+public:
+  BackPropInitializer(const std::vector<BackPropTensor *> back_props);
+
+public:
+  void forward(bool training) override;
+  void backward() override;
+
+private:
+  const std::vector<BackPropTensor *> _back_props;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_BACKPROP_INITIALIZER_H__
diff --git a/runtime/onert/backend/train/ops/BinaryArithmeticLayer.cc b/runtime/onert/backend/train/ops/BinaryArithmeticLayer.cc
new file mode 100644 (file)
index 0000000..a97ce46
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "BinaryArithmeticLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/Shape.h>
+#include <cker/train/operation/BinaryArithmetic.h>
+#include <cker/operation/BinaryArithmeticOps.h>
+#include <cker/train/operation/BinaryArithmetic.h>
+#include <cker/train/operation/ReLU.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+BinaryArithmeticLayer::BinaryArithmeticLayer()
+  : cpu::ops::BinaryArithmeticLayer(), _back_prop_lhs{nullptr}, _back_prop_rhs{nullptr},
+    _back_prop_output{nullptr}, _arithmetic_type{ArithmeticType::kAdd},
+    _activation{ir::Activation::NONE}, _act_back_prop_output{nullptr}
+{
+  // DO NOTHING
+}
+
+void BinaryArithmeticLayer::configureBackward(IPortableTensor *back_prop_lhs,
+                                              IPortableTensor *back_prop_rhs,
+                                              const IPortableTensor *back_prop_output,
+                                              const ir::Activation activation,
+                                              const ArithmeticType arithmetic_type)
+{
+  _back_prop_lhs = back_prop_lhs;
+  _back_prop_rhs = back_prop_rhs;
+  _back_prop_output = back_prop_output;
+  _arithmetic_type = arithmetic_type;
+  _activation = activation;
+
+  if (activation != ir::Activation::NONE)
+  {
+    _act_back_prop_output = std::make_unique<Tensor>(_output->get_info(), _output->layout());
+    _act_back_prop_output->setBuffer(std::make_shared<basic::Allocator>(_output->total_size()));
+  }
+}
+
+void BinaryArithmeticLayer::forward(bool) { cpu::ops::BinaryArithmeticLayer::run(); }
+
+void BinaryArithmeticLayer::backward()
+{
+  // Calculate gradient for activation
+  if (_back_prop_output->data_type() != OperandType::FLOAT32)
+    throw std::runtime_error{"Unsupported Data Type"};
+
+  const IPortableTensor *backprop_act;
+  try
+  {
+    backprop_act =
+      backpropActivation(_activation, _output, _back_prop_output, _act_back_prop_output.get());
+  }
+  catch (const std::exception &e)
+  {
+    throw std::runtime_error{"train BinaryArithmeticLayer: " + std::string(e.what())};
+  }
+  assert(backprop_act != nullptr);
+
+  nnfw::cker::train::BinaryArithmeticGrad(
+    getShape(_lhs), getBuffer<float>(_lhs), getShape(_rhs), getBuffer<float>(_rhs),
+    getShape(backprop_act), getBuffer<float>(backprop_act), getShape(_back_prop_lhs),
+    getBuffer<float>(_back_prop_lhs), getShape(_back_prop_rhs), getBuffer<float>(_back_prop_rhs),
+    static_cast<nnfw::cker::train::ArithmeticType>(_arithmetic_type));
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/BinaryArithmeticLayer.h b/runtime/onert/backend/train/ops/BinaryArithmeticLayer.h
new file mode 100644 (file)
index 0000000..60d6e8b
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_BINARYARITHMETICLAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_BINARYARITHMETICLAYER_H__
+
+#include <ops/BinaryArithmeticLayer.h>
+#include <backend/IPortableTensor.h>
+
+#include "../Tensor.h"
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+enum class ArithmeticType
+{
+  kAdd,
+  kSub,
+  kMul,
+  kDiv,
+};
+
+class BinaryArithmeticLayer : public ::onert::exec::train::ITrainableFunction,
+                              public cpu::ops::BinaryArithmeticLayer
+{
+public:
+  BinaryArithmeticLayer();
+
+public:
+  void configureBackward(IPortableTensor *back_prop_lhs, IPortableTensor *back_prop_rhs,
+                         const IPortableTensor *back_prop_output, const ir::Activation activation,
+                         const ArithmeticType arithmetic_type);
+  void forward(bool training) override;
+  void backward() override;
+
+private:
+  IPortableTensor *_back_prop_lhs;
+  IPortableTensor *_back_prop_rhs;
+  const IPortableTensor *_back_prop_output;
+
+  ArithmeticType _arithmetic_type;
+  ir::Activation _activation;
+  std::unique_ptr<BackPropTensor> _act_back_prop_output;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_BINARYARITHMETICLAYER_H__
index ac736c3..ea2ea1d 100644 (file)
 
 #include "ConvolutionLayer.h"
 
+#include "OperationUtils.h"
+
+#include <cker/operation/Conv.h>
+#include <cker/operation/Transpose.h>
+#include <cker/train/operation/Conv.h>
+#include <cker/train/operation/ReLU.h>
+
+#include <cker/operation/TransposeConv.h>
+
+namespace
+{
+
+using namespace onert;
+
+template <typename Tensor>
+std::unique_ptr<Tensor> createTransposedWeights(const backend::IPortableTensor *origin_weights)
+{
+  const auto &origin_shape = origin_weights->getShape();
+  assert(origin_shape.rank() == 4);
+
+  auto transposed_info = origin_weights->get_info();
+  // OHWI to HWIO
+  auto transposed_shape =
+    ir::Shape{origin_shape.dim(1), origin_shape.dim(2), origin_shape.dim(3), origin_shape.dim(0)};
+  transposed_info.shape(transposed_shape);
+
+  return std::make_unique<Tensor>(transposed_info, origin_weights->layout());
+}
+
+} // namespace
+
 namespace onert
 {
 namespace backend
@@ -24,31 +55,140 @@ namespace train
 {
 namespace ops
 {
-ConvolutionLayer::ConvolutionLayer() : cpu::ops::ConvolutionLayer()
+
+ConvolutionLayer::ConvolutionLayer()
+  : cpu::ops::ConvolutionLayer(), _grad_weights{nullptr}, _grad_bias{nullptr},
+    _back_prop_input{nullptr}, _back_prop_output{nullptr}, _transposed_weights{nullptr}
 {
   // 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::configureBackward(const IPortableTensor *weights,
+                                         IPortableTensor *back_prop_input,
+                                         IPortableTensor *grad_weights, IPortableTensor *grad_bias,
+                                         const IPortableTensor *back_prop_output,
+                                         const ir::Activation activation)
+{
+  _back_prop_input = back_prop_input;
+  _grad_weights = grad_weights;
+  _grad_bias = grad_bias;
+  _back_prop_output = back_prop_output;
+
+  if (_dilationHeightFactor != 1 || _dilationWidthFactor != 1)
+    throw std::runtime_error("train ConvolutionLayer: Unsupported dilation yet");
+
+  // TODO Optimize transposed tensors
+  _transposed_weights = createTransposedWeights<Tensor>(weights);
+  _transposed_weights->setBuffer(
+    std::make_shared<basic::Allocator>(_transposed_weights->total_size()));
+
+  _conv_back_prop_output =
+    std::make_unique<BackPropTensor>(back_prop_output->get_info(), back_prop_output->layout());
+  _conv_back_prop_output->setBuffer(
+    std::make_shared<basic::Allocator>(_conv_back_prop_output->total_size()));
+
+  _transposed_grad_weights = createTransposedWeights<GradientTensor>(weights);
+  _transposed_grad_weights->setBuffer(
+    std::make_shared<basic::Allocator>(_transposed_grad_weights->total_size()));
+
+  if (activation != ir::Activation::NONE)
+  {
+    _act_back_prop_output =
+      std::make_unique<BackPropTensor>(_back_prop_output->get_info(), _back_prop_output->layout());
+    _act_back_prop_output->setBuffer(
+      std::make_shared<basic::Allocator>(_act_back_prop_output->total_size()));
+  }
 }
 
 void ConvolutionLayer::forward(bool) { cpu::ops::ConvolutionLayer::run(); }
 void ConvolutionLayer::backward()
 {
-  // TODO Implement detail
+  const auto data_type = _back_prop_output->data_type();
+  assert(data_type == _input->data_type());
+  switch (data_type)
+  {
+    case OperandType::FLOAT32:
+    {
+      assert(data_type == _grad_bias->data_type());
+      backwardFloat32();
+      break;
+    }
+    default:
+      throw std::runtime_error{"train ConvolutionLayer: unsupported data type"};
+  }
+}
+
+void ConvolutionLayer::backwardFloat32()
+{
+  // Calculate gradient for activation
+  const IPortableTensor *backprop_act;
+  try
+  {
+    backprop_act =
+      backpropActivation(_activation, _output, _back_prop_output, _act_back_prop_output.get());
+  }
+  catch (const std::exception &e)
+  {
+    throw std::runtime_error{"train ConvolutionLayer: " + std::string(e.what())};
+  }
+  assert(backprop_act != nullptr);
+
+  // Initialize conv params for training kernels
+  nnfw::cker::ConvParams conv_train_params;
+  conv_train_params.padding_type = getPaddingType(_paddingType);
+  conv_train_params.padding_values.width = _paddingLeft;
+  conv_train_params.padding_values.height = _paddingTop;
+  conv_train_params.stride_width = _strideWidth;
+  conv_train_params.stride_height = _strideHeight;
+  conv_train_params.dilation_width_factor = _dilationWidthFactor;
+  conv_train_params.dilation_height_factor = _dilationHeightFactor;
+
+  // Transpose weights from OHWI to HWIO
+  auto transposed_weights = _transposed_weights.get();
+  assert(transposed_weights->getShape().rank() == 4);
+  nnfw::cker::TransposeParams transpose_param;
+  transpose_param.perm_count = transposed_weights->getShape().rank();
+  transpose_param.perm[0] = 1;
+  transpose_param.perm[1] = 2;
+  transpose_param.perm[2] = 3;
+  transpose_param.perm[3] = 0;
+  nnfw::cker::Transpose(transpose_param, getShape(_kernel), getBuffer<float>(_kernel),
+                        getShape(transposed_weights), getBuffer<float>(transposed_weights));
+
+  // Calculate gradient for input
+  nnfw::cker::train::ConvInputGrad(
+    conv_train_params, getShape(backprop_act), getBuffer<float>(backprop_act),
+    getShape(transposed_weights), getBuffer<float>(transposed_weights), _paddingBottom,
+    _paddingRight, getShape(_back_prop_input), getBuffer<float>(_back_prop_input));
+
+  // Calculate gradient for weights
+  auto transposed_grad_weights = _transposed_grad_weights.get();
+  assert(_grad_weights->getShape().rank() == 4);
+  assert(transposed_grad_weights->getShape().rank() == 4);
+  nnfw::cker::train::ConvFilterGrad(
+    conv_train_params, getShape(backprop_act), getBuffer<float>(backprop_act), getShape(_input),
+    getBuffer<float>(_input), _paddingBottom, _paddingRight, getShape(transposed_grad_weights),
+    getBuffer<float>(transposed_grad_weights));
+
+  // Transpose weights'gradient from HWIO to OHWI
+  nnfw::cker::TransposeParams transpose_grad_param;
+  transpose_grad_param.perm_count = transposed_grad_weights->getShape().rank();
+  transpose_grad_param.perm[0] = 3;
+  transpose_grad_param.perm[1] = 0;
+  transpose_grad_param.perm[2] = 1;
+  transpose_grad_param.perm[3] = 2;
+  nnfw::cker::Transpose(transpose_grad_param, getShape(transposed_grad_weights),
+                        getBuffer<float>(transposed_grad_weights), getShape(_grad_weights),
+                        getBuffer<float>(_grad_weights));
+
+  // Calculate gradient for bias
+  if (_bias)
+  {
+    assert(_grad_bias);
+    biasGrad(backprop_act, _grad_bias);
+  }
 }
 
 } // namespace ops
index ed42a20..ef11f68 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <ops/ConvolutionLayer.h>
 
+#include "../Tensor.h"
 #include <exec/train/ITrainableFunction.h>
 
 namespace onert
@@ -37,15 +38,26 @@ 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 configureBackward(const IPortableTensor *weights, IPortableTensor *back_prop_input,
+                         IPortableTensor *grad_weights, IPortableTensor *grad_bias,
+                         const IPortableTensor *back_prop_output, const ir::Activation activation);
   void forward(bool training) override;
   void backward() override;
+
+private:
+  void backwardFloat32();
+
+private:
+  IPortableTensor *_grad_weights;
+  IPortableTensor *_grad_bias;
+  IPortableTensor *_back_prop_input;
+  const IPortableTensor *_back_prop_output;
+
+  // TODO Consider if these tensors should be built in TensorBuilder
+  std::unique_ptr<Tensor> _transposed_weights;
+  std::unique_ptr<BackPropTensor> _conv_back_prop_output;
+  std::unique_ptr<BackPropTensor> _act_back_prop_output;
+  std::unique_ptr<GradientTensor> _transposed_grad_weights;
 };
 
 } // namespace ops
diff --git a/runtime/onert/backend/train/ops/DepthwiseConvolutionLayer.cc b/runtime/onert/backend/train/ops/DepthwiseConvolutionLayer.cc
new file mode 100644 (file)
index 0000000..2433a0f
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "DepthwiseConvolutionLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/train/operation/ReLU.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+DepthwiseConvolutionLayer::DepthwiseConvolutionLayer()
+  : cpu::ops::DepthwiseConvolutionLayer(), _grad_weights{nullptr}, _grad_bias{nullptr},
+    _back_prop_input{nullptr}, _back_prop_output{nullptr}, _act_back_prop_output{nullptr},
+    _use_padded_filter{false}, _padded_filter{nullptr}, _filter_buffers{nullptr},
+    _filter_dim_buffers{nullptr},
+    _dconv_kernel{std::make_unique<nnfw::cker::train::DepthwiseConv>()}
+{
+  // DO NOTHING
+}
+
+void DepthwiseConvolutionLayer::configureBackward(IPortableTensor *back_prop_input,
+                                                  IPortableTensor *grad_weights,
+                                                  IPortableTensor *grad_bias,
+                                                  const IPortableTensor *back_prop_output,
+                                                  const ir::Activation activation)
+{
+  _back_prop_input = back_prop_input;
+  _back_prop_output = back_prop_output;
+  _grad_weights = grad_weights;
+  _grad_bias = grad_bias;
+
+  if (_dilationWidth != 1 || _dilationHeight != 1)
+    throw std::runtime_error("train DepthwiseConvolutionLayer: Unsupported dilation yet");
+
+  if (activation != ir::Activation::NONE)
+  {
+    _act_back_prop_output =
+      std::make_unique<BackPropTensor>(_back_prop_output->get_info(), _back_prop_output->layout());
+    _act_back_prop_output->setBuffer(
+      std::make_shared<basic::Allocator>(_act_back_prop_output->total_size()));
+  }
+
+  const int64_t k_packet_size = [&]() {
+    const auto data_type = _back_prop_output->data_type();
+    switch (data_type)
+    {
+      case OperandType::FLOAT32:
+      {
+        return _dconv_kernel->kPacketSize<float>();
+      }
+      default:
+        throw std::runtime_error("train DepthwiseConvolutionLayer: unsupported data type");
+    }
+  }();
+
+  const auto incoming_shape = getShape(_back_prop_output);
+  const auto filter_shape = getShape(_kernel);
+  const int batch = incoming_shape.Dims(0);
+  const int out_depth = incoming_shape.Dims(3);
+  const int filter_rows = filter_shape.Dims(1);
+  const int filter_cols = filter_shape.Dims(2);
+
+  const int filter_spatial_size = filter_rows * filter_cols;
+  const int padded_filter_inner_dim_size =
+    ((out_depth + k_packet_size - 1) / k_packet_size) * k_packet_size;
+
+  _use_padded_filter = (out_depth % k_packet_size) == 0 ? false : true;
+
+  // prepare padded_filter buffer for cker
+  auto padded_filter_info = ir::OperandInfo(_kernel->get_info());
+  padded_filter_info.shape({batch, filter_spatial_size, padded_filter_inner_dim_size});
+  _padded_filter = std::make_unique<Tensor>(padded_filter_info, _kernel->layout());
+  _padded_filter->setBuffer(std::make_shared<basic::Allocator>(_padded_filter->total_size()));
+
+  // prepare out_bprop and in_bprop buffer for cker
+  const int thread_count = _dconv_kernel->getThreadCount();
+
+  auto filter_buffers_info = ir::OperandInfo(_kernel->get_info());
+  filter_buffers_info.shape({thread_count, filter_spatial_size, padded_filter_inner_dim_size});
+  _filter_buffers = std::make_unique<Tensor>(filter_buffers_info, _kernel->layout());
+  _filter_buffers->setBuffer(std::make_shared<basic::Allocator>(_filter_buffers->total_size()));
+
+  auto filter_dim_buffers_info = ir::OperandInfo(_back_prop_input->get_info());
+  filter_dim_buffers_info.shape({thread_count, padded_filter_inner_dim_size});
+  _filter_dim_buffers =
+    std::make_unique<Tensor>(filter_dim_buffers_info, _back_prop_input->layout());
+  _filter_dim_buffers->setBuffer(
+    std::make_shared<basic::Allocator>(_filter_dim_buffers->total_size()));
+}
+
+void DepthwiseConvolutionLayer::forward(bool) { cpu::ops::DepthwiseConvolutionLayer::run(); }
+
+void DepthwiseConvolutionLayer::backward()
+{
+  const auto data_type = _back_prop_output->data_type();
+  assert(data_type == _input->data_type());
+  switch (data_type)
+  {
+    case OperandType::FLOAT32:
+    {
+      assert(data_type == _grad_bias->data_type());
+      backwardFloat32();
+      break;
+    }
+    default:
+      throw std::runtime_error{"train DepthwiseConvolutionLayer: unsupported data type"};
+  }
+}
+
+void DepthwiseConvolutionLayer::backwardFloat32()
+{
+  // Calculate gradient for activation
+  const IPortableTensor *backprop_act;
+  try
+  {
+    backprop_act =
+      backpropActivation(_activation, _output, _back_prop_output, _act_back_prop_output.get());
+  }
+  catch (const std::exception &e)
+  {
+    throw std::runtime_error{"train DepthwiseConvolutionLayer: " + std::string(e.what())};
+  }
+  assert(backprop_act != nullptr);
+
+  nnfw::cker::DepthwiseConvParams dconv_params;
+  dconv_params.stride_width = _strideWidth;
+  dconv_params.stride_height = _strideHeight;
+  dconv_params.padding_values.width = _paddingLeft;
+  dconv_params.padding_values.height = _paddingTop;
+  dconv_params.depth_multiplier = _multiplier;
+
+  // Calculate gradient for input
+  _dconv_kernel->backpropInput(
+    dconv_params, getShape(backprop_act), getBuffer<float>(backprop_act), getShape(_kernel),
+    getBuffer<float>(_kernel), getBuffer<float>(_padded_filter.get()), getShape(_back_prop_input),
+    getBuffer<float>(_back_prop_input), _use_padded_filter, getBuffer<float>(_filter_buffers.get()),
+    getBuffer<float>(_filter_dim_buffers.get()));
+
+  // Calculate gradient for weights
+  _dconv_kernel->backpropFilter(
+    dconv_params, getShape(backprop_act), getBuffer<float>(backprop_act), getShape(_input),
+    getBuffer<float>(_input), getShape(_grad_weights), getBuffer<float>(_grad_weights),
+    getBuffer<float>(_padded_filter.get()), getBuffer<float>(_filter_buffers.get()));
+
+  // Calculate gradient for bias
+  if (_bias)
+  {
+    assert(_grad_bias);
+    biasGrad(backprop_act, _grad_bias);
+  }
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/DepthwiseConvolutionLayer.h b/runtime/onert/backend/train/ops/DepthwiseConvolutionLayer.h
new file mode 100644 (file)
index 0000000..7cf887e
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_DEPTHWISECONVOLUTIONLAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_DEPTHWISECONVOLUTIONLAYER_H__
+
+#include <cker/train/operation/DepthwiseConv.h>
+#include <ops/DepthwiseConvolutionLayer.h>
+#include <backend/basic/Allocator.h>
+
+#include "../Tensor.h"
+#include "../ExternalContext.h"
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+class DepthwiseConvolutionLayer : public ::onert::exec::train::ITrainableFunction,
+                                  public cpu::ops::DepthwiseConvolutionLayer
+{
+public:
+  DepthwiseConvolutionLayer();
+
+  void configureBackward(IPortableTensor *back_prop_input, IPortableTensor *grad_weights,
+                         IPortableTensor *grad_bias, const IPortableTensor *back_prop_output,
+                         const ir::Activation activation);
+  void forward(bool training) override;
+  void backward() override;
+
+private:
+  void backwardFloat32();
+
+private:
+  IPortableTensor *_grad_weights;
+  IPortableTensor *_grad_bias;
+  IPortableTensor *_back_prop_input;
+  const IPortableTensor *_back_prop_output;
+
+  // TODO Consider if these tensors should be built in TensorBuilder
+  std::unique_ptr<BackPropTensor> _act_back_prop_output;
+  bool _use_padded_filter;
+  std::unique_ptr<Tensor> _padded_filter;
+  std::unique_ptr<Tensor> _filter_buffers;
+  std::unique_ptr<Tensor> _filter_dim_buffers;
+
+  std::unique_ptr<nnfw::cker::train::DepthwiseConv> _dconv_kernel;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_DEPTHWISECONVOLUTIONLAYER_H__
index 860eca4..ba82361 100644 (file)
@@ -19,6 +19,7 @@
 #include "OperationUtils.h"
 
 #include <cker/train/operation/ReLU.h>
+#include <cker/train/operation/ReLU6.h>
 
 namespace onert
 {
@@ -34,18 +35,18 @@ ElementwiseActivationLayer::ElementwiseActivationLayer() : cpu::ops::Elementwise
   // DO NOTHING
 }
 
-void ElementwiseActivationLayer::configure(const IPortableTensor *input, IPortableTensor *output,
-                                           IPortableTensor *deriv_input,
-                                           const IPortableTensor *deriv_output, float alpha,
-                                           float beta, ElementwiseActivationType op_type)
+void ElementwiseActivationLayer::configureBackward(const IPortableTensor *input,
+                                                   IPortableTensor *back_prop_input,
+                                                   const IPortableTensor *back_prop_output,
+                                                   float alpha, float beta,
+                                                   ElementwiseActivationType op_type)
 {
   assert(input != nullptr);
-  assert(output != nullptr);
-  assert(deriv_input != nullptr);
-  assert(deriv_output != nullptr);
+  assert(back_prop_input != nullptr);
+  assert(back_prop_output != nullptr);
 
-  _deriv_input = deriv_input;
-  _deriv_output = deriv_output;
+  _back_prop_input = back_prop_input;
+  _back_prop_output = back_prop_output;
 
   _op_type = op_type;
 
@@ -54,22 +55,28 @@ void ElementwiseActivationLayer::configure(const IPortableTensor *input, IPortab
     case ElementwiseActivationType::kReLU:
       if (input->data_type() == OperandType::FLOAT32)
       {
-        if (alpha == std::numeric_limits<float>::infinity() && beta == 0.f)
+        if ((alpha == std::numeric_limits<float>::infinity() || alpha == 6.0f) && beta == 0.f)
         {
-          cpu::ops::ElementwiseActivationLayer::configure(
-            input, output, alpha, beta, cpu::ops::ElementwiseActivationType::kReLU);
+          auto relu_cker = [&alpha]() {
+            if (alpha == std::numeric_limits<float>::infinity())
+              return nnfw::cker::train::ReLUGrad;
+            else if (alpha == 6.0f)
+              return nnfw::cker::train::ReLU6Grad;
+            else
+              throw std::runtime_error{"no supported relu kernel"};
+          }();
 
-          _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));
+          _backward_kernel = [relu_cker](const IPortableTensor *output,
+                                         const IPortableTensor *incoming,
+                                         IPortableTensor *outgoing) {
+            relu_cker(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)");
+          throw std::runtime_error(
+            "train ElementwiseActivationLayer : Unsupported ReLU activation type");
         }
       }
       else
@@ -86,7 +93,7 @@ void ElementwiseActivationLayer::forward(bool) { cpu::ops::ElementwiseActivation
 
 void ElementwiseActivationLayer::backward()
 {
-  _backward_kernel(_output, _deriv_output, _deriv_input);
+  _backward_kernel(_output, _back_prop_output, _back_prop_input);
 }
 
 } // namespace ops
index dac1efe..a6b1955 100644 (file)
@@ -42,17 +42,17 @@ class ElementwiseActivationLayer : public ::onert::exec::train::ITrainableFuncti
 public:
   ElementwiseActivationLayer();
 
-  void configure(const IPortableTensor *input, IPortableTensor *output,
-                 IPortableTensor *deriv_input, const IPortableTensor *deriv_output, float alpha,
-                 float beta, ElementwiseActivationType op_type);
+  void configureBackward(const IPortableTensor *input, IPortableTensor *back_prop_input,
+                         const IPortableTensor *back_prop_output, float alpha, float beta,
+                         ElementwiseActivationType op_type);
   void forward(bool training) override;
   void backward() override;
 
 private:
-  IPortableTensor *_deriv_input;
-  const IPortableTensor *_deriv_output;
+  IPortableTensor *_back_prop_input = nullptr;
+  const IPortableTensor *_back_prop_output = nullptr;
 
-  ElementwiseActivationType _op_type;
+  ElementwiseActivationType _op_type = ElementwiseActivationType::kReLU;
   std::function<void(const IPortableTensor *output, const IPortableTensor *incoming,
                      IPortableTensor *outgoing)>
     _backward_kernel;
index 8fdc822..311621b 100644 (file)
@@ -54,37 +54,34 @@ 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}
+    _back_prop_input{nullptr}, _back_prop_output{nullptr}, _transposed_weights{nullptr},
+    _transposed_input{nullptr}, _transposed_back_prop_output{nullptr},
+    _act_back_prop_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)
+void FullyConnectedLayer::configureBackward(
+  const IPortableTensor *input, const IPortableTensor *weights, IPortableTensor *output,
+  IPortableTensor *back_prop_input, IPortableTensor *grad_weights, IPortableTensor *grad_bias,
+  const IPortableTensor *back_prop_output, ir::Activation activation,
+  ir::FullyConnectedWeightsFormat weights_format)
 {
-  cpu::ops::FullyConnectedLayer::configure(input, weights, bias, activation, weights_format, output,
-                                           external_context);
-
-  _deriv_input = deriv_input;
+  _back_prop_input = back_prop_input;
   _grad_weights = grad_weights;
   _grad_bias = grad_bias;
-  _deriv_output = deriv_output;
+  _back_prop_output = back_prop_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)
+      output->get_info().shape().rank() != 2 || back_prop_input->get_info().shape().rank() != 2 ||
+      grad_weights->get_info().shape().rank() != 2 ||
+      back_prop_output->get_info().shape().rank() != 2)
     throw std::runtime_error{
       "train FullyConnectedLayer: Input other ranks than 2 are not supported."};
 
@@ -94,15 +91,16 @@ void FullyConnectedLayer::configure(const IPortableTensor *input, const IPortabl
   _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()));
+  _transposed_back_prop_output = createTransposedTensor(back_prop_output);
+  _transposed_back_prop_output->setBuffer(
+    std::make_shared<basic::Allocator>(back_prop_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()));
+    _act_back_prop_output =
+      std::make_unique<Tensor>(_back_prop_output->get_info(), _back_prop_output->layout());
+    _act_back_prop_output->setBuffer(
+      std::make_shared<basic::Allocator>(_back_prop_output->total_size()));
   }
 }
 
@@ -110,14 +108,14 @@ void FullyConnectedLayer::forward(bool) { cpu::ops::FullyConnectedLayer::run();
 
 void FullyConnectedLayer::backward()
 {
-  const auto data_type = _deriv_output->data_type();
+  const auto data_type = _back_prop_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());
+      assert(_grad_bias == nullptr || data_type == _grad_bias->data_type());
       backwardFloat32();
       break;
     }
@@ -130,21 +128,16 @@ void FullyConnectedLayer::backwardFloat32()
 {
   // Calculate gradient for activation
   const IPortableTensor *backprop_act;
-  switch (_activation)
+  try
   {
-    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");
+    backprop_act =
+      backpropActivation(_activation, _output, _back_prop_output, _act_back_prop_output.get());
+  }
+  catch (const std::exception &e)
+  {
+    throw std::runtime_error{"train FullyConnectedLayer: " + std::string(e.what())};
   }
+  assert(backprop_act != nullptr);
 
   // Initialize TransposeParams
   nnfw::cker::TransposeParams transpose_param;
@@ -172,8 +165,8 @@ void FullyConnectedLayer::backwardFloat32()
 
   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));
+                             getShape(nullptr), nullptr, getShape(_back_prop_input),
+                             getBuffer<float>(_back_prop_input));
 
   // Transpose and compute gradient for weights
   // âˆ‚L/∂W = fc(transposed incomming gradient, transposed X)
@@ -182,16 +175,16 @@ void FullyConnectedLayer::backwardFloat32()
   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);
+  auto transposed_back_prop_output = _transposed_back_prop_output.get();
+  assert(transposed_back_prop_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));
+                        getShape(transposed_back_prop_output),
+                        getBuffer<float>(transposed_back_prop_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));
+  nnfw::cker::FullyConnected(
+    op_params, getShape(transposed_back_prop_output), getBuffer<float>(transposed_back_prop_output),
+    getShape(transposed_input), getBuffer<float>(transposed_input), getShape(nullptr), nullptr,
+    getShape(_grad_weights), getBuffer<float>(_grad_weights));
 
   // Compute gradient for bias
   if (_bias)
index 1d9b30a..190bfbf 100644 (file)
@@ -40,12 +40,11 @@ public:
   ~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 configureBackward(const IPortableTensor *input, const IPortableTensor *weights,
+                         IPortableTensor *output, IPortableTensor *back_prop_input,
+                         IPortableTensor *grad_weights, IPortableTensor *grad_bias,
+                         const IPortableTensor *back_prop_output, ir::Activation activation,
+                         ir::FullyConnectedWeightsFormat weights_format);
 
   void forward(bool training) override;
   void backward() override;
@@ -56,14 +55,14 @@ private:
 private:
   IPortableTensor *_grad_weights;
   IPortableTensor *_grad_bias;
-  IPortableTensor *_deriv_input;
-  const IPortableTensor *_deriv_output;
+  IPortableTensor *_back_prop_input;
+  const IPortableTensor *_back_prop_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;
+  std::unique_ptr<Tensor> _transposed_back_prop_output;
+  std::unique_ptr<Tensor> _act_back_prop_output;
 };
 
 } // namespace ops
index 90d1bb9..534a43e 100644 (file)
@@ -32,7 +32,7 @@ GradientApplier::GradientApplier() : _optimizer{nullptr}, _gradient_tensor{}, _t
   // DO NOTHING
 }
 
-void GradientApplier::configure(std::shared_ptr<exec::train::optimizer::Optimizer> optimizer,
+void GradientApplier::configure(const exec::train::optimizer::Optimizer *optimizer,
                                 const IPortableTensor *gradient, ITrainableTensor *trainable)
 {
   _optimizer = optimizer;
index 94234e1..b572523 100644 (file)
@@ -36,12 +36,12 @@ public:
   GradientApplier();
   ~GradientApplier() = default;
 
-  void configure(std::shared_ptr<exec::train::optimizer::Optimizer> optimizer,
+  void configure(const 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 exec::train::optimizer::Optimizer *_optimizer;
   const IPortableTensor *_gradient_tensor;
   ITrainableTensor *_trainable_tensor;
 };
diff --git a/runtime/onert/backend/train/ops/LossCategoricalCrossentropyLayer.cc b/runtime/onert/backend/train/ops/LossCategoricalCrossentropyLayer.cc
new file mode 100644 (file)
index 0000000..e6a778a
--- /dev/null
@@ -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 "LossCategoricalCrossentropyLayer.h"
+#include "OperationUtils.h"
+
+#include <cker/train/operation/Loss.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+void LossCategoricalCrossentropyLayer::configure(const IPortableTensor *y_pred,
+                                                 const IPortableTensor *y_true,
+                                                 IPortableTensor *output,
+                                                 IPortableTensor *back_prop_y_pred, int32_t axis,
+                                                 float label_smoothing)
+{
+  LossLayer::configure(y_pred, y_true, output, back_prop_y_pred);
+
+  _axis = axis;
+  _label_smoothing = label_smoothing;
+}
+
+void LossCategoricalCrossentropyLayer::forward(bool)
+{
+  if (_y_pred->data_type() == OperandType::FLOAT32)
+  {
+    nnfw::cker::train::CategoricalCrossEntropy(getShape(_y_pred), getBuffer<float>(_y_pred),
+                                               getShape(_y_true), getBuffer<float>(_y_true),
+                                               getShape(_output), getBuffer<float>(_output));
+  }
+  else
+  {
+    throw std::runtime_error("LossCategoricalCrossentropyLayer: unsupported data type");
+  }
+}
+
+void LossCategoricalCrossentropyLayer::backward()
+{
+  assert(_back_prop_y_pred != nullptr);
+
+  if (_y_pred->data_type() == OperandType::FLOAT32)
+  {
+    nnfw::cker::train::CategoricalCrossEntropyGrad(
+      getShape(_y_pred), getBuffer<float>(_y_pred), getShape(_y_true), getBuffer<float>(_y_true),
+      getShape(_back_prop_y_pred), getBuffer<float>(_back_prop_y_pred));
+  }
+  else
+  {
+    throw std::runtime_error("LossCategoricalCrossentropyLayer: unsupported data type");
+  }
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/LossCategoricalCrossentropyLayer.h b/runtime/onert/backend/train/ops/LossCategoricalCrossentropyLayer.h
new file mode 100644 (file)
index 0000000..35001e0
--- /dev/null
@@ -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_OPS_LOSS_CATEGORICALCROSSENTROPY_LAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_LOSS_CATEGORICALCROSSENTROPY_LAYER_H__
+
+#include "LossLayer.h"
+#include "../Tensor.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+class LossCategoricalCrossentropyLayer : public LossLayer
+{
+public:
+  LossCategoricalCrossentropyLayer() = default;
+
+  void configure(const IPortableTensor *y_pred, const IPortableTensor *y_true,
+                 IPortableTensor *output, IPortableTensor *back_prop_y_pred, int32_t axis,
+                 float label_smoothing);
+  void forward(bool training) override;
+  void backward() override;
+
+private:
+  int32_t _axis{-1};
+  float _label_smoothing{0.0f};
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_LOSS_CATEGORICALCROSSENTROPY_LAYER_H__
index d004722..b175f14 100644 (file)
@@ -15,9 +15,6 @@
  */
 
 #include "LossLayer.h"
-#include "OperationUtils.h"
-
-#include <cker/train/operation/Loss.h>
 
 namespace onert
 {
@@ -29,68 +26,23 @@ namespace ops
 {
 
 LossLayer::LossLayer()
-  : _y_pred(nullptr), _y_true(nullptr), _output(nullptr), _deriv_y_pred(nullptr),
-    _loss_type(LossType::kMSE)
+  : _y_pred(nullptr), _y_true(nullptr), _output(nullptr), _back_prop_y_pred(nullptr)
 {
   // DO NOTHING
 }
 
 void LossLayer::configure(const IPortableTensor *y_pred, const IPortableTensor *y_true,
-                          IPortableTensor *output, IPortableTensor *deriv_y_pred,
-                          LossType loss_type)
+                          IPortableTensor *output, IPortableTensor *back_prop_y_pred)
 {
   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");
-  }
+  // back_prop_y_pred can be nullptr if backwarding is not required
 
   _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");
-  }
+  _back_prop_y_pred = back_prop_y_pred;
 }
 
 } // namespace ops
index 18c6b31..17b3276 100644 (file)
@@ -42,16 +42,13 @@ 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;
+                 IPortableTensor *output, IPortableTensor *back_prop_y_pred);
 
-private:
+protected:
   const IPortableTensor *_y_pred;
   const IPortableTensor *_y_true;
   IPortableTensor *_output;
-  IPortableTensor *_deriv_y_pred;
-  LossType _loss_type;
+  IPortableTensor *_back_prop_y_pred;
 };
 
 } // namespace ops
diff --git a/runtime/onert/backend/train/ops/LossMeanSquaredErrorLayer.cc b/runtime/onert/backend/train/ops/LossMeanSquaredErrorLayer.cc
new file mode 100644 (file)
index 0000000..65c81ff
--- /dev/null
@@ -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.
+ */
+
+#include "LossMeanSquaredErrorLayer.h"
+#include "OperationUtils.h"
+
+#include <cker/train/operation/Loss.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+void LossMeanSquaredErrorLayer::configure(const IPortableTensor *y_pred,
+                                          const IPortableTensor *y_true, IPortableTensor *output,
+                                          IPortableTensor *back_prop_y_pred)
+{
+  LossLayer::configure(y_pred, y_true, output, back_prop_y_pred);
+}
+
+void LossMeanSquaredErrorLayer::forward(bool)
+{
+  // TODO Implement this
+  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));
+  }
+  else
+  {
+    throw std::runtime_error("LossMeanSquaredErrorLayer: unsupported data type");
+  }
+}
+
+void LossMeanSquaredErrorLayer::backward()
+{
+  assert(_back_prop_y_pred != nullptr);
+
+  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(_back_prop_y_pred),
+                               getBuffer<float>(_back_prop_y_pred));
+  }
+  else
+  {
+    throw std::runtime_error("LossMeanSquaredErrorLayer: unsupported data type");
+  }
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/LossMeanSquaredErrorLayer.h b/runtime/onert/backend/train/ops/LossMeanSquaredErrorLayer.h
new file mode 100644 (file)
index 0000000..a0d2a1b
--- /dev/null
@@ -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_OPS_LOSS_MEANSQUAREDERROR_LAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_LOSS_MEANSQUAREDERROR_LAYER_H__
+
+#include "LossLayer.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+class LossMeanSquaredErrorLayer : public LossLayer
+{
+public:
+  LossMeanSquaredErrorLayer() = default;
+
+  void configure(const IPortableTensor *y_pred, const IPortableTensor *y_true,
+                 IPortableTensor *output, IPortableTensor *back_prop_y_pred);
+  void forward(bool training) override;
+  void backward() override;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_LOSS_MEANSQUAREDERROR_LAYER_H__
diff --git a/runtime/onert/backend/train/ops/MeanLayer.cc b/runtime/onert/backend/train/ops/MeanLayer.cc
new file mode 100644 (file)
index 0000000..c6744e6
--- /dev/null
@@ -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 "MeanLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/Shape.h>
+#include <cker/train/operation/ReduceMean.h>
+#include <cker/operation/BinaryArithmeticOps.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+MeanLayer::MeanLayer()
+  : cpu::ops::MeanLayer(), _back_prop_input{nullptr}, _back_prop_output{nullptr}
+{
+  // DO NOTHING
+}
+
+void MeanLayer::configureBackward(IPortableTensor *back_prop_input,
+                                  const IPortableTensor *back_prop_output)
+{
+  _back_prop_input = back_prop_input;
+  _back_prop_output = back_prop_output;
+}
+
+void MeanLayer::forward(bool) { cpu::ops::MeanLayer::run(); }
+
+void MeanLayer::backward()
+{
+  nnfw::cker::Shape keep_dim_shape;
+  // If _keep_dims is false, the input rank and the output rank can be different.
+  // MeanGrad does not support other ranking cases. This code corrects the shape
+  // by creating a temporary shape having the same rank as the input.
+  if (_keep_dims == false)
+  {
+    keep_dim_shape.ReplaceWith(getShape(_input));
+    auto axes_vec = cpu::ops::getReducerAxes(_axes);
+    for (const auto &axis : axes_vec)
+    {
+      keep_dim_shape.SetDim(axis, 1);
+    }
+  }
+  else
+  {
+    keep_dim_shape.ReplaceWith(getShape(_back_prop_output));
+  }
+
+  switch (_back_prop_output->data_type())
+  {
+    case OperandType::FLOAT32:
+    {
+      nnfw::cker::train::MeanGrad(keep_dim_shape, getBuffer<float>(_back_prop_output),
+                                  getShape(_back_prop_input), getBuffer<float>(_back_prop_input));
+      break;
+    }
+    default:
+      throw std::runtime_error("train MeanLayer: unsupported data type");
+  }
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/MeanLayer.h b/runtime/onert/backend/train/ops/MeanLayer.h
new file mode 100644 (file)
index 0000000..71be42f
--- /dev/null
@@ -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_MEANLAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_MEANLAYER_H__
+
+#include <ops/MeanLayer.h>
+#include <backend/IPortableTensor.h>
+
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+class MeanLayer : public ::onert::exec::train::ITrainableFunction, public cpu::ops::MeanLayer
+{
+public:
+  MeanLayer();
+
+public:
+  void configureBackward(IPortableTensor *back_prop_input, const IPortableTensor *back_prop_output);
+  void forward(bool training) override;
+  void backward() override;
+
+private:
+  IPortableTensor *_back_prop_input;
+  const IPortableTensor *_back_prop_output;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_MEANLAYER_H__
diff --git a/runtime/onert/backend/train/ops/OperationUtils.cc b/runtime/onert/backend/train/ops/OperationUtils.cc
new file mode 100644 (file)
index 0000000..9736d5b
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "OperationUtils.h"
+
+#include <cker/eigen/redux_functor.h>
+#include <cker/train/operation/ReLU.h>
+#include <cker/train/operation/ReLU6.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+nnfw::cker::Shape getShape(const IPortableTensor *tensor)
+{
+  if (tensor == nullptr)
+    return nnfw::cker::Shape();
+
+  assert(!tensor->is_dynamic() && "Dynamic tensor is not supported yet");
+
+  const ir::Shape &shape = tensor->get_info().shape();
+
+  assert(tensor->layout() == ir::Layout::NHWC);
+
+  auto rank = shape.rank();
+  nnfw::cker::Shape ret(rank);
+  auto data = ret.DimsData();
+  for (int i = 0; i < rank; ++i)
+  {
+    data[i] = shape.dim(i);
+  }
+  return ret;
+}
+
+const IPortableTensor *backpropActivation(const ir::Activation &activation,
+                                          const IPortableTensor *output,
+                                          const IPortableTensor *input_backprop,
+                                          IPortableTensor *output_backprop)
+{
+  assert(output != nullptr);
+  assert(input_backprop != nullptr);
+
+  // handle NONE - just propagate incoming gradient
+  if (activation == ir::Activation::NONE)
+  {
+    return input_backprop;
+  }
+
+  assert(output_backprop != nullptr);
+
+  // handle other activation
+  switch (activation)
+  {
+    case ir::Activation::RELU:
+      nnfw::cker::train::ReLUGrad(getShape(output), getBuffer<float>(output),
+                                  getShape(input_backprop), getBuffer<float>(input_backprop),
+                                  getShape(output_backprop), getBuffer<float>(output_backprop));
+      break;
+    case ir::Activation::RELU6:
+      nnfw::cker::train::ReLU6Grad(getShape(output), getBuffer<float>(output),
+                                   getShape(input_backprop), getBuffer<float>(input_backprop),
+                                   getShape(output_backprop), getBuffer<float>(output_backprop));
+      break;
+    // TODO: Add other activation backpropagation here
+    default:
+      throw std::runtime_error("Unsupported activation type yet");
+  }
+  return output_backprop;
+}
+
+void biasGrad(const IPortableTensor *input_backprop, IPortableTensor *bias_grad)
+{
+  assert(bias_grad);
+
+  nnfw::cker::Shape input_backprop_shape = getShape(input_backprop);
+  float *input_backprop_buffer = reinterpret_cast<float *>(input_backprop->buffer());
+
+  nnfw::cker::Shape bias_grad_shape = getShape(bias_grad);
+  float *bias_grad_buffer = getBuffer<float>(bias_grad);
+
+  nnfw::cker::functor::biasReductionHelper(input_backprop_buffer, input_backprop_shape,
+                                           bias_grad_buffer, bias_grad_shape);
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
index fe0a023..e432965 100644 (file)
@@ -30,7 +30,52 @@ namespace ops
 
 using OperandType = onert::ir::DataType;
 using cpu::ops::getBuffer;
-using cpu::ops::getShape;
+using cpu::ops::getPaddingType;
+using cpu::ops::getNumberOfDimensions;
+using cpu::ops::getNumberOfElements;
+using cpu::ops::getSizeOfDimension;
+
+/**
+ * @brief Get shape of tensor
+ *
+ * @param tensor tensor to get shape
+ * @return Shape to be used in cker
+ */
+nnfw::cker::Shape getShape(const IPortableTensor *tensor);
+
+/**
+ * @brief backpropagate acitvation
+ *
+ *             -- forward direction -->
+ *
+ *   [ current layer ]   ----   [ next layer ]
+ *   [ op    |  act  ]
+ *
+ *             <-- backward direction --
+ *
+ * @param activation      activation of current layer
+ * @param output          forward direction's output of current layer
+ * @param input_backprop  backward direction's output of next layer
+ *                        In other words, incoming gradient to current layer
+ * @param output_backprop backward direction's output of activation,
+ *                        In other words, outcoming gradient of current layer's acitvation
+ *                        If activation is NONE, this param can be nullptr
+ * @return tensor that holds backpropagate result of activation
+ *         If activation is NONE, just return input_backprop
+ */
+const IPortableTensor *backpropActivation(const ir::Activation &activation,
+                                          const IPortableTensor *output,
+                                          const IPortableTensor *input_backprop,
+                                          IPortableTensor *output_backprop);
+
+/**
+ * @brief backpropagate bias
+ *
+ * @param input_backprop backward direction's output of next layer
+ *                       In other words, incoming gradient to current layer
+ * @param bias_grad      gradient tensor of bias
+ */
+void biasGrad(const IPortableTensor *input_backprop, IPortableTensor *bias_grad);
 
 } // namespace ops
 } // namespace train
diff --git a/runtime/onert/backend/train/ops/PadLayer.cc b/runtime/onert/backend/train/ops/PadLayer.cc
new file mode 100644 (file)
index 0000000..0ac917b
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "PadLayer.h"
+
+#include <cker/train/operation/Pad.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+PadLayer::PadLayer() : cpu::ops::PadLayer(), _back_prop_input{nullptr}, _back_prop_output{nullptr}
+{
+  // DO NOTHING
+}
+
+template <typename T> void PadLayer::depad()
+{
+  assert(_pad->data_type() == onert::ir::DataType::INT32);
+  assert(_pad->buffer());
+  const auto pad_data = reinterpret_cast<const int32_t *>(_pad->buffer());
+  auto pad_rank = _pad->getShape().dim(0);
+  nnfw::cker::train::Depad<T>(pad_data, pad_rank, getShape(_back_prop_output),
+                              getBuffer<T>(_back_prop_output), getShape(_back_prop_input),
+                              getBuffer<T>(_back_prop_input));
+}
+
+void PadLayer::configureBackward(IPortableTensor *back_prop_input,
+                                 const IPortableTensor *back_prop_output)
+{
+  _back_prop_input = back_prop_input;
+  _back_prop_output = back_prop_output;
+}
+
+void PadLayer::forward(bool) { cpu::ops::PadLayer::run(); }
+
+void PadLayer::backward()
+{
+  switch (_back_prop_output->data_type())
+  {
+    case OperandType::FLOAT32:
+      depad<float>();
+      break;
+    case OperandType::QUANT_UINT8_ASYMM:
+      depad<uint8_t>();
+      break;
+    case OperandType::QUANT_INT8_ASYMM:
+      depad<int8_t>();
+      break;
+    default:
+      throw std::runtime_error{"Pad: unsupported data type"};
+  }
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/PadLayer.h b/runtime/onert/backend/train/ops/PadLayer.h
new file mode 100644 (file)
index 0000000..2e6f2c7
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_PADLAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_PADLAYER_H__
+
+#include <ops/PadLayer.h>
+#include <backend/IPortableTensor.h>
+#include "OperationUtils.h"
+
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+// Note, this is pad with mode=`CONSTANT`: it doesn't support `REFLECT` and
+// `SYMMETRIC`
+class PadLayer : public ::onert::exec::train::ITrainableFunction, public cpu::ops::PadLayer
+{
+public:
+  PadLayer();
+
+public:
+  template <typename T> void depad();
+
+  void configureBackward(IPortableTensor *back_prop_input, const IPortableTensor *back_prop_output);
+  void forward(bool training) override;
+  void backward() override;
+
+private:
+  IPortableTensor *_back_prop_input;
+  const IPortableTensor *_back_prop_output;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_PADLAYER_H__
index c8a8422..4ba1457 100644 (file)
  */
 
 #include "PoolLayer.h"
+#include "OperationUtils.h"
+#include "../Tensor.h"
+
+#include <cker/Utils.h>
+#include <cker/train/operation/MaxPool.h>
+#include <cker/train/operation/ReLU.h>
 
 namespace onert
 {
@@ -25,24 +31,118 @@ namespace train
 namespace ops
 {
 
-PoolLayer::PoolLayer() : cpu::ops::PoolLayer()
+namespace
+{
+
+class MaxPool2D final : public TrainingKernelRegistry
+{
+private:
+  const ir::Activation _activation;
+  const IPortableTensor *_output;
+  nnfw::cker::PoolParams _op_params;
+
+  std::unique_ptr<Tensor> _act_back_prop_output;
+  std::unique_ptr<Tensor> _arg_max_index;
+
+public:
+  MaxPool2D(const uint32_t paddingLeft, const uint32_t, const uint32_t paddingTop, const uint32_t,
+            const uint32_t strideWidth, const uint32_t strideHeight, const uint32_t kernelWidth,
+            const uint32_t kernelHeight, const ir::Activation activation,
+            const IPortableTensor *output)
+    : _activation(activation), _output(output)
+  {
+    {
+      _op_params.stride_height = strideHeight;
+      _op_params.stride_width = strideWidth;
+      _op_params.filter_height = kernelHeight;
+      _op_params.filter_width = kernelWidth;
+      _op_params.padding_values.height = (int8_t)paddingTop;
+      _op_params.padding_values.width = (int8_t)paddingLeft;
+      CalculateActivationRange<float>(activation, &_op_params.float_activation_min,
+                                      &_op_params.float_activation_max);
+    }
+
+    _arg_max_index = std::make_unique<Tensor>(_output->get_info(), _output->layout());
+    _arg_max_index->setBuffer(std::make_shared<basic::Allocator>(_output->total_size()));
+
+    if (activation != ir::Activation::NONE)
+    {
+      _act_back_prop_output = std::make_unique<Tensor>(_output->get_info(), _output->layout());
+      _act_back_prop_output->setBuffer(std::make_shared<basic::Allocator>(_output->total_size()));
+    }
+  };
+
+  ~MaxPool2D() {}
+
+public:
+  void forward(const IPortableTensor *in, IPortableTensor *out)
+  {
+    assert(in->layout() == ir::Layout::NHWC);
+
+    auto out_shape = getShape(out);
+    auto out_data = getBuffer<float>(out);
+    auto arg_max_index = _arg_max_index.get();
+
+    // maxpool forward
+    nnfw::cker::train::MaxPool2D(_op_params, getShape(in), getBuffer<float>(in), out_shape,
+                                 out_data, getBuffer<int>(arg_max_index));
+  }
+
+  void backward(const IPortableTensor *back_prop_out, IPortableTensor *back_prop_in)
+  {
+    assert(back_prop_out->layout() == ir::Layout::NHWC);
+
+    // activation backward
+    try
+    {
+      back_prop_out =
+        backpropActivation(_activation, _output, back_prop_out, _act_back_prop_output.get());
+    }
+    catch (const std::exception &e)
+    {
+      throw std::runtime_error{"train PoolLayer: " + std::string(e.what())};
+    }
+    assert(back_prop_out != nullptr);
+
+    // maxpool baackward
+    auto arg_max_index = _arg_max_index.get();
+    nnfw::cker::train::MaxPool2DGrad(getShape(back_prop_out), getBuffer<float>(back_prop_out),
+                                     getBuffer<int>(arg_max_index), getShape(back_prop_in),
+                                     getBuffer<float>(back_prop_in));
+  }
+};
+
+} // namespace
+
+PoolLayer::PoolLayer()
+  : cpu::ops::PoolLayer(), _back_prop_input(nullptr), _back_prop_output(nullptr), _kernel(nullptr)
 {
   // 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)
+void PoolLayer::configureBackward(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, const PoolType op_type,
+                                  IPortableTensor *output, IPortableTensor *back_prop_input,
+                                  const IPortableTensor *back_prop_output)
 {
+  _back_prop_output = back_prop_output;
+  _back_prop_input = back_prop_input;
+
+  if (output->data_type() != OperandType::FLOAT32)
+  {
+    throw std::runtime_error("PoolLayer : Unsupported data type for training");
+  }
+
+  // ready training kernel
   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);
+      _kernel = std::make_unique<MaxPool2D>(paddingLeft, paddingRight, paddingTop, paddingBottom,
+                                            strideWidth, strideHeight, kernelWidth, kernelHeight,
+                                            activation, output);
       break;
     default:
       throw std::runtime_error("PoolLayer: Unsupported pool type");
@@ -53,7 +153,7 @@ void PoolLayer::forward(bool training)
 {
   if (training)
   {
-    // TODO Implement training pool layer
+    _kernel->forward(_input, _output);
   }
   else
   {
@@ -61,10 +161,7 @@ void PoolLayer::forward(bool training)
   }
 }
 
-void PoolLayer::backward()
-{
-  // TODO Implement detail
-}
+void PoolLayer::backward() { _kernel->backward(_back_prop_output, _back_prop_input); }
 
 } // namespace ops
 } // namespace train
index 7f93b4a..5ced951 100644 (file)
@@ -30,6 +30,18 @@ namespace train
 namespace ops
 {
 
+/**
+ * This is to register the pair of (forward, backward) training kernel.
+ */
+class TrainingKernelRegistry
+{
+public:
+  virtual void forward(const IPortableTensor *in, IPortableTensor *out) = 0;
+  virtual void backward(const IPortableTensor *back_prop_out, IPortableTensor *back_prop_in) = 0;
+  TrainingKernelRegistry() = default;
+  virtual ~TrainingKernelRegistry() = default;
+};
+
 enum class PoolType
 {
   kMax,
@@ -41,14 +53,22 @@ 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 configureBackward(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, const PoolType op_type,
+                         IPortableTensor *output, IPortableTensor *back_prop_input,
+                         const IPortableTensor *back_prop_output);
+
   void forward(bool training) override;
   void backward() override;
+
+private:
+  IPortableTensor *_back_prop_input;
+  const IPortableTensor *_back_prop_output;
+
+  std::unique_ptr<TrainingKernelRegistry> _kernel;
 };
 
 } // namespace ops
index 1716174..1c8a019 100644 (file)
@@ -26,8 +26,8 @@ namespace ops
 {
 
 ReshapeLayer::ReshapeLayer()
-  : _input{nullptr}, _shape{nullptr}, _output{nullptr}, _deriv_input{nullptr}, _deriv_output{
-                                                                                 nullptr}
+  : _input{nullptr}, _shape{nullptr}, _output{nullptr}, _back_prop_input{nullptr},
+    _back_prop_output{nullptr}
 {
   // DO NOTHING
 }
@@ -39,21 +39,24 @@ void ReshapeLayer::reshapeGeneric(const IPortableTensor *input, IPortableTensor
 }
 
 void ReshapeLayer::configure(const IPortableTensor *input, const IPortableTensor *shape,
-                             IPortableTensor *output, IPortableTensor *deriv_input,
-                             const IPortableTensor *deriv_output)
+                             IPortableTensor *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::configureBackward(IPortableTensor *back_prop_input,
+                                     const IPortableTensor *back_prop_output)
+{
+  _back_prop_input = back_prop_input;
+  _back_prop_output = back_prop_output;
 }
 
 void ReshapeLayer::forward(bool) { reshapeGeneric(_input, _output); }
 
-void ReshapeLayer::backward() { reshapeGeneric(_deriv_output, _deriv_input); }
+void ReshapeLayer::backward() { reshapeGeneric(_back_prop_output, _back_prop_input); }
 
 } // namespace ops
 } // namespace train
index e4f0172..2cd098d 100644 (file)
@@ -37,8 +37,8 @@ public:
 
 public:
   void configure(const IPortableTensor *input, const IPortableTensor *shape,
-                 IPortableTensor *output, IPortableTensor *deriv_input,
-                 const IPortableTensor *deriv_output);
+                 IPortableTensor *output);
+  void configureBackward(IPortableTensor *back_prop_input, const IPortableTensor *back_prop_output);
   void forward(bool training) override;
   void backward() override;
 
@@ -50,8 +50,8 @@ private:
   const IPortableTensor *_shape;
   IPortableTensor *_output;
 
-  IPortableTensor *_deriv_input;
-  const IPortableTensor *_deriv_output;
+  IPortableTensor *_back_prop_input;
+  const IPortableTensor *_back_prop_output;
 };
 
 } // namespace ops
diff --git a/runtime/onert/backend/train/ops/SoftMaxLayer.cc b/runtime/onert/backend/train/ops/SoftMaxLayer.cc
new file mode 100644 (file)
index 0000000..0d98f29
--- /dev/null
@@ -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.
+ */
+
+#include "SoftMaxLayer.h"
+
+#include "OperationUtils.h"
+
+#include <cker/train/operation/SoftMax.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+SoftMaxLayer::SoftMaxLayer()
+  : cpu::ops::SoftMaxLayer(), _back_prop_input{nullptr}, _back_prop_output{nullptr}
+{
+  // DO NOTHING
+}
+
+void SoftMaxLayer::configureBackward(IPortableTensor *back_prop_input,
+                                     const IPortableTensor *back_prop_output)
+{
+  _back_prop_input = back_prop_input;
+  _back_prop_output = back_prop_output;
+}
+
+void SoftMaxLayer::forward(bool) { cpu::ops::SoftMaxLayer::run(); }
+
+void SoftMaxLayer::backward()
+{
+  assert(_back_prop_output->data_type() == _input->data_type());
+  switch (_back_prop_output->data_type())
+  {
+    case OperandType::FLOAT32:
+    {
+      nnfw::cker::train::SoftMaxGrad(
+        getShape(_output), getBuffer<float>(_output), getShape(_back_prop_output),
+        getBuffer<float>(_back_prop_output), getShape(_back_prop_input),
+        getBuffer<float>(_back_prop_input));
+      break;
+    }
+    default:
+      throw std::runtime_error("train SoftMaxLayer: unsupported data type");
+  }
+}
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/ops/SoftMaxLayer.h b/runtime/onert/backend/train/ops/SoftMaxLayer.h
new file mode 100644 (file)
index 0000000..1b7b402
--- /dev/null
@@ -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_SOFTMAXLAYER_H__
+#define __ONERT_BACKEND_TRAIN_OPS_SOFTMAXLAYER_H__
+
+#include <ops/SoftMaxLayer.h>
+#include <backend/IPortableTensor.h>
+
+#include <exec/train/ITrainableFunction.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace ops
+{
+
+class SoftMaxLayer : public ::onert::exec::train::ITrainableFunction, public cpu::ops::SoftMaxLayer
+{
+public:
+  SoftMaxLayer();
+
+public:
+  void configureBackward(IPortableTensor *back_prop_input, const IPortableTensor *back_prop_output);
+  void forward(bool training) override;
+  void backward() override;
+
+private:
+  IPortableTensor *_back_prop_input;
+  const IPortableTensor *_back_prop_output;
+};
+
+} // namespace ops
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPS_SOFTMAXLAYER_H__
diff --git a/runtime/onert/backend/train/optimizer/Adam.cc b/runtime/onert/backend/train/optimizer/Adam.cc
new file mode 100644 (file)
index 0000000..fd541fe
--- /dev/null
@@ -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.
+ */
+
+#include "Adam.h"
+
+#include "../ops/OperationUtils.h"
+#include <cker/train/optimizer/Adam.h>
+#include <cmath>
+#include <misc/polymorphic_downcast.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace optimizer
+{
+
+double Adam::getLearningRate(uint32_t training_step) const
+{
+  auto biasCorrection = [&](double f) { return 1.0f - std::pow(f, training_step + 1); };
+  return _learning_rate * (std::sqrt(biasCorrection(_props.beta2)) / biasCorrection(_props.beta1));
+}
+
+void Adam::applyGradient(const UpdateFactors &factors) const
+{
+  const auto training_step = 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 opt_vars = trainable_tensor.optVars();
+  assert(opt_vars.size() == 2);
+  // Get the variable for exponential moving average of the gradient
+  auto m_tensor = nnfw::misc::polymorphic_downcast<IPortableTensor *>(opt_vars.at(0));
+  // Get the variable for exponential moving average of the squared_gradient
+  auto v_tensor = nnfw::misc::polymorphic_downcast<IPortableTensor *>(opt_vars.at(1));
+
+  const auto beta1_power = std::pow(_props.beta1, training_step + 1);
+  const auto beta2_power = std::pow(_props.beta2, training_step + 1);
+  // TODO Support nesterov
+  const bool use_nesterov = false;
+
+  if (trainable_tensor.getShape() != grad_tensor.getShape())
+  {
+    throw std::runtime_error("Adam: Invalid gradient tensor");
+  }
+
+  switch (grad_tensor.data_type())
+  {
+    case ir::DataType::FLOAT32:
+      nnfw::cker::train::Adam(
+        ops::getShape(&trainable_tensor), ops::getBuffer<float>(&trainable_tensor),
+        ops::getShape(&grad_tensor), ops::getBuffer<float>(&grad_tensor), ops::getShape(m_tensor),
+        ops::getBuffer<float>(m_tensor), ops::getShape(v_tensor), ops::getBuffer<float>(v_tensor),
+        beta1_power, beta2_power, _learning_rate, _props.beta1, _props.beta2, _props.epsilon,
+        use_nesterov);
+      break;
+    default:
+      throw std::runtime_error("Adam: Not supported data type");
+  }
+}
+
+} // namespace optimizer
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/optimizer/Adam.h b/runtime/onert/backend/train/optimizer/Adam.h
new file mode 100644 (file)
index 0000000..1a43fe4
--- /dev/null
@@ -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 __ONERT_BACKEND_TRAIN_OPTIMIZER_ADAM_H__
+#define __ONERT_BACKEND_TRAIN_OPTIMIZER_ADAM_H__
+
+#include "exec/train/optimizer/Optimizer.h"
+
+#include "backend/basic/Tensor.h"
+#include "ir/OperandIndexMap.h"
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace optimizer
+{
+
+/**
+ * @class   Adam optimizer class
+ * @brief   Adam optimizer
+ */
+class Adam : public exec::train::optimizer::Optimizer
+{
+public:
+  using UpdateFactors = exec::train::optimizer::UpdateFactors;
+
+public:
+  struct Property
+  {
+    double beta1{0.9};
+    double beta2{0.999};
+    double epsilon{1e-07};
+  };
+
+public:
+  explicit Adam() : _props{}, _learning_rate{0.001} {}
+  explicit Adam(const Property &props) : _props{props}, _learning_rate{0.001} {}
+  explicit Adam(double lr) : _props{}, _learning_rate{lr} {}
+  explicit Adam(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{"Adam"}; }
+
+  /**
+   * @brief Get the Learning Rate
+   *
+   * @param training_step The number of training steps
+   * @return Learning rate
+   */
+  double getLearningRate(uint32_t training_step) const override;
+
+  /**
+   * @brief Get the number of optimizer variables
+   *s
+   * @return The number of optimizer variables
+   */
+  virtual uint32_t getVarCount() const override { return 2; };
+
+  /**
+   * @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 backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPTIMIZER_ADAM_H__
diff --git a/runtime/onert/backend/train/optimizer/Optimizers.h b/runtime/onert/backend/train/optimizer/Optimizers.h
new file mode 100644 (file)
index 0000000..dae8e93
--- /dev/null
@@ -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_OPTIMIZER_OPTIMIZERS_H__
+#define __ONERT_BACKEND_TRAIN_OPTIMIZER_OPTIMIZERS_H__
+
+#include "Adam.h"
+#include "SGD.h"
+
+#include <ir/train/OptimizerInfo.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+
+std::unique_ptr<exec::train::optimizer::Optimizer>
+createOptimizer(const ir::train::OptimizerInfo &optim_info)
+{
+  // TODO Set properties of optimizer
+  if (optim_info.optim_code == ir::train::OptimizerCode::SGD)
+  {
+    return std::make_unique<optimizer::SGD>(optim_info.learning_rate);
+  }
+  else if (optim_info.optim_code == ir::train::OptimizerCode::Adam)
+  {
+    return std::make_unique<optimizer::Adam>(optim_info.learning_rate);
+  }
+  else
+    throw std::runtime_error("Invalid optimizer type, " +
+                             ir::train::toString(optim_info.optim_code));
+}
+
+} // namespace train
+} // namespace backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPTIMIZER_OPTIMIZERS_H__
diff --git a/runtime/onert/backend/train/optimizer/Optimizers.test.cc b/runtime/onert/backend/train/optimizer/Optimizers.test.cc
new file mode 100644 (file)
index 0000000..f24138c
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Optimizers.h"
+
+#include <backend/train/ITrainableTensor.h>
+
+#include <cmath>
+#include <gtest/gtest.h>
+#include <vector>
+
+namespace
+{
+
+using namespace onert;
+using namespace onert::backend;
+using namespace onert::ir;
+
+class MockUpTensor : public IPortableTensor
+{
+public:
+  MockUpTensor(const Shape &shape, const TypeInfo &type_info)
+    : IPortableTensor{ir::OperandInfo{shape, type_info, MemAllocType::STATIC}}, _data{}
+  {
+  }
+  virtual ~MockUpTensor() = default;
+
+  template <typename T> void setData(const std::vector<T> &data)
+  {
+    _data.resize(data.size() * sizeof(T));
+    std::copy(data.begin(), data.end(), _data.begin());
+  }
+
+  uint8_t *buffer() const override
+  {
+    if (_data.size() != total_size())
+      return nullptr;
+
+    return const_cast<uint8_t *>(_data.data());
+  }
+
+  template <typename T> const std::vector<T> &data() const { return _data; }
+
+  ir::Layout layout() const override { return ir::Layout::NHWC; }
+
+private:
+  using ITensor::setShape;
+  using ITensor::set_dynamic;
+  using ITensor::applyShape;
+
+private:
+  std::vector<uint8_t> _data;
+};
+
+class MockUpTrainableTensor : public backend::train::ITrainableTensor
+{
+public:
+  MockUpTrainableTensor(const Shape &shape, const TypeInfo &type_info)
+    : ITrainableTensor{ir::OperandInfo{shape, type_info, MemAllocType::STATIC}}, _data{},
+      _opt_vars{}
+  {
+  }
+  virtual ~MockUpTrainableTensor() {}
+
+  template <typename T> void setData(const std::vector<T> &data)
+  {
+    _data.resize(data.size() * sizeof(T));
+    std::copy(data.begin(), data.end(), _data.begin());
+  }
+
+  uint8_t *buffer() const override
+  {
+    if (_data.size() != total_size())
+      return nullptr;
+
+    return const_cast<uint8_t *>(_data.data());
+  }
+
+  ir::Layout layout() const override { return ir::Layout::NHWC; }
+
+public:
+  std::vector<ITensor *> optVars() override
+  {
+    std::vector<ITensor *> ret;
+    for (auto &&e : _opt_vars)
+    {
+      ret.emplace_back(e);
+    }
+    return ret;
+  }
+  void appendOptVar(MockUpTensor *opt_var) { _opt_vars.emplace_back(opt_var); }
+
+private:
+  using ITensor::setShape;
+  using ITensor::set_dynamic;
+  using ITensor::applyShape;
+
+private:
+  std::vector<uint8_t> _data;
+  std::vector<MockUpTensor *> _opt_vars; //< Optimizer variables
+};
+
+template <typename T> class SGDOptimizerVerifier
+{
+public:
+  SGDOptimizerVerifier(MockUpTrainableTensor &trainable, const MockUpTensor &gradient,
+                       float learning_rate, uint32_t nums_step)
+    : _sgd{backend::train::optimizer::SGD::Property{}, learning_rate}, _trainable{trainable},
+      _gradient{gradient}, _learning_rate{learning_rate}, _nums_step{nums_step}
+  {
+    EXPECT_TRUE(trainable.total_size() == gradient.total_size());
+
+    _expected_trainable.resize(trainable.getShape().num_elements());
+    memcpy(_expected_trainable.data(), trainable.buffer(), trainable.total_size());
+
+    _expected_gradient.resize(gradient.getShape().num_elements());
+    memcpy(_expected_gradient.data(), gradient.buffer(), gradient.total_size());
+  }
+
+  SGDOptimizerVerifier(const SGDOptimizerVerifier &) = delete;
+  SGDOptimizerVerifier &operator=(const SGDOptimizerVerifier &) = delete;
+  SGDOptimizerVerifier(SGDOptimizerVerifier &&) = delete;
+  SGDOptimizerVerifier &operator=(SGDOptimizerVerifier &&) = delete;
+
+public:
+  void verify()
+  {
+    for (uint32_t step = 0; step < _nums_step; ++step)
+    {
+      auto actual_lr = _sgd.getLearningRate(step);
+      EXPECT_EQ(actual_lr, _learning_rate);
+
+      calculateExpected();
+
+      backend::train::optimizer::Adam::UpdateFactors factors{_gradient, _trainable, step};
+      _sgd.applyGradient(factors);
+
+      for (size_t i = 0; i < _expected_trainable.size(); ++i)
+      {
+        EXPECT_NEAR(reinterpret_cast<T *>(_gradient.buffer())[i], _expected_gradient[i], 1e-07f);
+        EXPECT_NEAR(reinterpret_cast<T *>(_trainable.buffer())[i], _expected_trainable[i], 1e-07f);
+      }
+    }
+  }
+
+private:
+  void calculateExpected()
+  {
+    EXPECT_TRUE(_expected_trainable.size() == _expected_gradient.size());
+
+    for (size_t i = 0; i < _expected_trainable.size(); ++i)
+    {
+      T &g = _expected_gradient[i];
+      T &t = _expected_trainable[i];
+
+      t -= g * _learning_rate;
+    }
+  }
+
+private:
+  backend::train::optimizer::SGD _sgd;
+  MockUpTrainableTensor &_trainable;
+  const MockUpTensor &_gradient;
+  float _learning_rate;
+  uint32_t _nums_step;
+
+  std::vector<T> _expected_trainable;
+  std::vector<T> _expected_gradient;
+};
+
+template <typename T> class AdamOptimizerVerifier
+{
+public:
+  AdamOptimizerVerifier(MockUpTrainableTensor &trainable, const MockUpTensor &gradient,
+                        float learning_rate, float beta1, float beta2, float epsilon,
+                        bool use_nesterov, uint32_t nums_step)
+    : _adam{backend::train::optimizer::Adam::Property{beta1, beta2, epsilon}, learning_rate},
+      _trainable{trainable}, _gradient{gradient}, _learning_rate{learning_rate}, _beta1{beta1},
+      _beta2{beta2}, _epsilon{epsilon}, _use_nesterov{use_nesterov}, _nums_step{nums_step}
+  {
+    auto vars = trainable.optVars();
+    EXPECT_TRUE(vars.size() == 2);
+    const auto &m = *vars[0];
+    const auto &v = *vars[1];
+    EXPECT_TRUE(trainable.total_size() == gradient.total_size());
+    EXPECT_TRUE(trainable.total_size() == m.total_size());
+    EXPECT_TRUE(trainable.total_size() == v.total_size());
+
+    _expected_trainable.resize(trainable.getShape().num_elements());
+    memcpy(_expected_trainable.data(), trainable.buffer(), trainable.total_size());
+
+    _expected_gradient.resize(gradient.getShape().num_elements());
+    memcpy(_expected_gradient.data(), gradient.buffer(), gradient.total_size());
+
+    _expected_m.resize(m.getShape().num_elements());
+    memcpy(_expected_m.data(), m.buffer(), m.total_size());
+
+    _expected_v.resize(v.getShape().num_elements());
+    memcpy(_expected_v.data(), v.buffer(), v.total_size());
+  }
+
+  AdamOptimizerVerifier(const AdamOptimizerVerifier &) = delete;
+  AdamOptimizerVerifier &operator=(const AdamOptimizerVerifier &) = delete;
+
+public:
+  void verify()
+  {
+    for (uint32_t step = 0; step < _nums_step; ++step)
+    {
+      const T beta1_power = std::pow(_beta1, step + 1);
+      const T beta2_power = std::pow(_beta2, step + 1);
+
+      calculateExpected(beta1_power, beta2_power);
+
+      backend::train::optimizer::Adam::UpdateFactors factors{_gradient, _trainable, step};
+      _adam.applyGradient(factors);
+
+      const auto vars = _trainable.optVars();
+      const auto &m = *vars[0];
+      const auto &v = *vars[1];
+
+      auto actual_lr = _adam.getLearningRate(step);
+      auto expected_lr = [&]() {
+        auto biasCorrection = [&](double f) { return 1.0f - std::pow(f, step + 1); };
+        return _learning_rate * (std::sqrt(biasCorrection(_beta2)) / biasCorrection(_beta1));
+      }();
+      EXPECT_EQ(actual_lr, expected_lr);
+
+      for (size_t i = 0; i < _expected_trainable.size(); ++i)
+      {
+        EXPECT_NEAR(reinterpret_cast<T *>(m.buffer())[i], _expected_m[i], 1e-07f);
+        EXPECT_NEAR(reinterpret_cast<T *>(v.buffer())[i], _expected_v[i], 1e-07f);
+        EXPECT_NEAR(reinterpret_cast<T *>(_gradient.buffer())[i], _expected_gradient[i], 1e-07f);
+        EXPECT_NEAR(reinterpret_cast<T *>(_trainable.buffer())[i], _expected_trainable[i], 1e-07f);
+      }
+    }
+  }
+
+private:
+  void calculateExpected(const float beta1_power, const float beta2_power)
+  {
+    EXPECT_TRUE(_expected_trainable.size() == _expected_gradient.size());
+    EXPECT_TRUE(_expected_trainable.size() == _expected_m.size());
+    EXPECT_TRUE(_expected_trainable.size() == _expected_v.size());
+
+    const T alpha = _learning_rate * std::sqrt(static_cast<T>(1) - beta2_power) /
+                    (static_cast<T>(1) - beta1_power);
+
+    for (size_t i = 0; i < _expected_trainable.size(); ++i)
+    {
+      T &m = _expected_m[i];
+      T &v = _expected_v[i];
+      T &g = _expected_gradient[i];
+      T &t = _expected_trainable[i];
+
+      if (_use_nesterov)
+      {
+        m += (g - m) * (static_cast<T>(1) - _beta1);
+        v += (std::pow(g, 2) - v) * (static_cast<T>(1) - _beta2);
+        t -= ((g * (static_cast<T>(1) - _beta1) + _beta1 * m) * alpha) / (std::sqrt(v) + _epsilon);
+      }
+      else
+      {
+        m += (g - m) * (static_cast<T>(1) - _beta1);
+        v += (std::pow(g, 2) - v) * (static_cast<T>(1) - _beta2);
+        t -= (m * alpha) / (std::sqrt(v) + _epsilon);
+      }
+    }
+  }
+
+private:
+  backend::train::optimizer::Adam _adam;
+  MockUpTrainableTensor &_trainable;
+  const MockUpTensor &_gradient;
+  float _learning_rate;
+  float _beta1;
+  float _beta2;
+  float _epsilon;
+  bool _use_nesterov;
+  uint32_t _nums_step;
+
+  std::vector<T> _expected_trainable;
+  std::vector<T> _expected_gradient;
+  std::vector<T> _expected_m;
+  std::vector<T> _expected_v;
+};
+
+} // namespace
+
+TEST(Optimizer, SGDValueValidation)
+{
+  // 10 steps
+  {
+    const auto shape = ir::Shape{1, 3, 3};
+    const auto type_info = ir::TypeInfo{ir::DataType::FLOAT32};
+    MockUpTrainableTensor trainable{shape, type_info};
+    MockUpTensor gradient{shape, type_info};
+
+    std::vector<float> trainable_data = {-1, 2, -3, -4, 5, -6, 7, -8, 9};
+    std::vector<float> gradient_data = {-1, -2, -3, 4, 5, -6, 7, 8, -9};
+
+    trainable.setData(trainable_data);
+    gradient.setData(gradient_data);
+
+    float lr = 0.001;
+    uint32_t training_steps = 10;
+
+    SGDOptimizerVerifier<float>{trainable, gradient, lr, training_steps}.verify();
+  }
+
+  // 10000 steps
+  {
+    const auto shape = ir::Shape{1, 3, 3};
+    const auto type_info = ir::TypeInfo{ir::DataType::FLOAT32};
+    MockUpTrainableTensor trainable{shape, type_info};
+    MockUpTensor gradient{shape, type_info};
+
+    std::vector<float> trainable_data = {-1, 2, -3, -4, 5, -6, 7, -8, 9};
+    std::vector<float> gradient_data = {-1, -2, -3, 4, 5, -6, 7, 8, -9};
+
+    trainable.setData(trainable_data);
+    gradient.setData(gradient_data);
+
+    float lr = 0.001;
+    uint32_t training_steps = 10000;
+
+    SGDOptimizerVerifier<float>{trainable, gradient, lr, training_steps}.verify();
+  }
+}
+
+TEST(Optimizer, SGDVarCount)
+{
+  backend::train::optimizer::SGD sgd{};
+
+  EXPECT_EQ(sgd.getVarCount(), 0);
+}
+
+TEST(Optimizer, neg_SGDUnmatchedGradientShape)
+{
+  // Unmatched shape
+  {
+    const auto type_info = ir::TypeInfo{ir::DataType::FLOAT32};
+    MockUpTrainableTensor trainable{{1, 3, 3}, type_info};
+    MockUpTensor gradient{ir::Shape{2, 2, 2}, type_info};
+
+    std::vector<float> trainable_data = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient_data = {-1, 2, -3, 4, 5, -6, 7, 8};
+
+    trainable.setData(trainable_data);
+    gradient.setData(gradient_data);
+
+    float lr = 0.001;
+
+    backend::train::optimizer::SGD sgd{lr};
+    backend::train::optimizer::SGD::UpdateFactors factors{gradient, trainable, 0};
+
+    EXPECT_ANY_THROW(sgd.applyGradient(factors));
+  }
+}
+
+TEST(Optimizer, neg_SGDUnsupportedType)
+{
+  // Unsupported type
+  {
+    const auto shape = ir::Shape{1, 3, 3};
+    const auto type_info = ir::TypeInfo{ir::DataType::INT32};
+    MockUpTrainableTensor trainable{shape, type_info};
+    MockUpTensor gradient{shape, type_info};
+
+    std::vector<float> trainable_data = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient_data = {-1, 2, -3, 4, 5, -6, 7, 8, -9};
+
+    trainable.setData(trainable_data);
+    gradient.setData(gradient_data);
+
+    float lr = 0.001;
+
+    backend::train::optimizer::SGD sgd{lr};
+    backend::train::optimizer::SGD::UpdateFactors factors{gradient, trainable, 0};
+
+    EXPECT_ANY_THROW(sgd.applyGradient(factors));
+  }
+}
+
+TEST(Optimizer, AdamValueValidation)
+{
+  // 10 steps
+  {
+    const auto shape = ir::Shape{1, 3, 3};
+    const auto type_info = ir::TypeInfo{ir::DataType::FLOAT32};
+    MockUpTrainableTensor trainable{shape, type_info};
+    MockUpTensor gradient{shape, type_info};
+    MockUpTensor m{shape, type_info};
+    MockUpTensor v{shape, type_info};
+
+    std::vector<float> trainable_data = {-1, 2, -3, -4, 5, -6, 7, -8, 9};
+    std::vector<float> gradient_data = {-1, -2, -3, 4, 5, -6, 7, 8, -9};
+    std::vector<float> m_data = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+    std::vector<float> v_data = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+    trainable.setData(trainable_data);
+    gradient.setData(gradient_data);
+    m.setData(m_data);
+    v.setData(v_data);
+
+    trainable.appendOptVar(&m);
+    trainable.appendOptVar(&v);
+
+    float lr = 0.1;
+    float beta1 = 0.9;
+    float beta2 = 0.999;
+    float epsilon = 1e-07;
+    bool use_nesterov = false;
+    uint32_t training_steps = 10;
+
+    AdamOptimizerVerifier<float>{trainable, gradient, lr,           beta1,
+                                 beta2,     epsilon,  use_nesterov, training_steps}
+      .verify();
+  }
+
+  // 10000 steps
+  {
+    const auto shape = ir::Shape{1, 3, 3};
+    const auto type_info = ir::TypeInfo{ir::DataType::FLOAT32};
+    MockUpTrainableTensor trainable{shape, type_info};
+    MockUpTensor gradient{shape, type_info};
+    MockUpTensor m{shape, type_info};
+    MockUpTensor v{shape, type_info};
+
+    std::vector<float> trainable_data = {-1, 2, -3, -4, 5, -6, 7, -8, 9};
+    std::vector<float> gradient_data = {-1, -2, -3, 4, 5, -6, 7, 8, -9};
+    std::vector<float> m_data = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+    std::vector<float> v_data = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+    trainable.setData(trainable_data);
+    gradient.setData(gradient_data);
+    m.setData(m_data);
+    v.setData(v_data);
+
+    trainable.appendOptVar(&m);
+    trainable.appendOptVar(&v);
+
+    float lr = 0.001;
+    float beta1 = 0.9;
+    float beta2 = 0.999;
+    float epsilon = 1e-07;
+    bool use_nesterov = false;
+    uint32_t training_steps = 10000;
+
+    AdamOptimizerVerifier<float>{trainable, gradient, lr,           beta1,
+                                 beta2,     epsilon,  use_nesterov, training_steps}
+      .verify();
+  }
+
+  // TODO Add tests with use_nesterov = true
+}
+
+TEST(Optimizer, AdamVarCount)
+{
+  float lr = 0.001;
+  backend::train::optimizer::Adam adam(lr);
+
+  EXPECT_EQ(adam.getVarCount(), 2);
+}
+
+TEST(Optimizer, neg_AdamUnmatchedGradientShape)
+{
+  // Unmatched shape
+  {
+    const auto shape = ir::Shape{1, 3, 3};
+    const auto type_info = ir::TypeInfo{ir::DataType::FLOAT32};
+    MockUpTrainableTensor trainable{shape, type_info};
+    MockUpTensor gradient{ir::Shape{2, 2, 2}, type_info};
+    MockUpTensor m{shape, type_info};
+    MockUpTensor v{shape, type_info};
+
+    std::vector<float> trainable_data = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient_data = {-1, 2, -3, 4, 5, -6, 7, 8};
+    std::vector<float> m_data = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> v_data = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+    trainable.setData(trainable_data);
+    gradient.setData(gradient_data);
+    m.setData(m_data);
+    v.setData(v_data);
+
+    trainable.appendOptVar(&m);
+    trainable.appendOptVar(&v);
+
+    backend::train::optimizer::Adam adam{};
+    backend::train::optimizer::Adam::UpdateFactors factors{gradient, trainable, 0};
+
+    EXPECT_ANY_THROW(adam.applyGradient(factors));
+  }
+}
+
+TEST(Optimizer, neg_AdamUnmatchedEMAShape)
+{
+  // Unmatched shape
+  {
+    const auto shape = ir::Shape{1, 3, 3};
+    const auto type_info = ir::TypeInfo{ir::DataType::FLOAT32};
+    MockUpTrainableTensor trainable{shape, type_info};
+    MockUpTensor gradient{shape, type_info};
+    MockUpTensor m{ir::Shape{2, 2, 2}, type_info};
+    MockUpTensor v{ir::Shape{2, 2, 2}, type_info};
+
+    std::vector<float> trainable_data = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient_data = {-1, 2, -3, 4, 5, -6, 7, 8};
+    std::vector<float> m_data = {0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> v_data = {0, 0, 0, 0, 0, 0, 0, 0};
+
+    trainable.setData(trainable_data);
+    gradient.setData(gradient_data);
+    m.setData(m_data);
+    v.setData(v_data);
+
+    trainable.appendOptVar(&m);
+    trainable.appendOptVar(&v);
+
+    backend::train::optimizer::Adam adam{};
+    backend::train::optimizer::Adam::UpdateFactors factors{gradient, trainable, 0};
+
+    EXPECT_ANY_THROW(adam.applyGradient(factors));
+  }
+}
+
+TEST(Optimizer, neg_AdamUnsupportedType)
+{
+  // Unsupported type
+  {
+    const auto shape = ir::Shape{1, 3, 3};
+    const auto type_info = ir::TypeInfo{ir::DataType::INT32};
+    MockUpTrainableTensor trainable{shape, type_info};
+    MockUpTensor gradient{shape, type_info};
+    MockUpTensor m{shape, type_info};
+    MockUpTensor v{shape, type_info};
+
+    std::vector<float> trainable_data = {-1, 2, -3, 4, 5, -6, -7, 8, 9};
+    std::vector<float> gradient_data = {-1, 2, -3, 4, 5, -6, 7, 8, -9};
+    std::vector<float> m_data = {0, 0, 0, 0, 0, 0, 0, 0};
+    std::vector<float> v_data = {0, 0, 0, 0, 0, 0, 0, 0};
+
+    trainable.setData(trainable_data);
+    gradient.setData(gradient_data);
+    m.setData(m_data);
+    v.setData(v_data);
+
+    trainable.appendOptVar(&m);
+    trainable.appendOptVar(&v);
+
+    float beta1 = 0.9;
+    float beta2 = 0.999;
+    float epsilon = 1e-07;
+
+    backend::train::optimizer::Adam adam{
+      backend::train::optimizer::Adam::Property{beta1, beta2, epsilon}};
+    backend::train::optimizer::Adam::UpdateFactors factors{gradient, trainable, 0};
+
+    EXPECT_ANY_THROW(adam.applyGradient(factors));
+  }
+}
+
+TEST(Optimizer, CreateOptimizer)
+{
+  // SGD
+  {
+    ir::train::OptimizerInfo optim_info;
+    optim_info.optim_code = ir::train::OptimizerCode::SGD;
+    optim_info.learning_rate = 0.001f;
+    auto sgd = backend::train::createOptimizer(optim_info);
+    EXPECT_EQ(sgd->getVarCount(), 0);
+    EXPECT_EQ(sgd->name(), std::string{"SGD"});
+  }
+
+  // Adam
+  {
+    ir::train::OptimizerInfo optim_info;
+    optim_info.optim_code = ir::train::OptimizerCode::Adam;
+    optim_info.learning_rate = 0.001f;
+    auto adam = backend::train::createOptimizer(optim_info);
+    EXPECT_EQ(adam->getVarCount(), 2);
+    EXPECT_EQ(adam->name(), std::string{"Adam"});
+  }
+}
+
+TEST(Optimizer, neg_UndefinedOptimizerCode)
+{
+  // Undefined optimizer code
+  {
+    ir::train::OptimizerInfo optim_info;
+    optim_info.optim_code = ir::train::OptimizerCode::Undefined;
+    EXPECT_ANY_THROW(backend::train::createOptimizer(optim_info));
+  }
+}
diff --git a/runtime/onert/backend/train/optimizer/SGD.cc b/runtime/onert/backend/train/optimizer/SGD.cc
new file mode 100644 (file)
index 0000000..99bd62e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "SGD.h"
+
+#include "../ops/OperationUtils.h"
+
+#include <cker/train/optimizer/SGD.h>
+
+namespace onert
+{
+namespace backend
+{
+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());
+
+  if (trainable_tensor.getShape() != grad_tensor.getShape())
+  {
+    throw std::runtime_error("SGD: Invalid gradient tensor");
+  }
+
+  switch (grad_tensor.data_type())
+  {
+    case ir::DataType::FLOAT32:
+      nnfw::cker::train::GradientDescent(
+        ops::getShape(&trainable_tensor), ops::getBuffer<float>(&trainable_tensor),
+        ops::getShape(&grad_tensor), ops::getBuffer<float>(&grad_tensor), lr);
+      break;
+    default:
+      throw std::runtime_error("SGD: Not supported data type");
+  }
+}
+
+} // namespace optimizer
+} // namespace train
+} // namespace backend
+} // namespace onert
diff --git a/runtime/onert/backend/train/optimizer/SGD.h b/runtime/onert/backend/train/optimizer/SGD.h
new file mode 100644 (file)
index 0000000..37968c2
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_OPTIMIZER_SGD_H__
+#define __ONERT_BACKEND_TRAIN_OPTIMIZER_SGD_H__
+
+#include <exec/train/optimizer/Optimizer.h>
+
+namespace onert
+{
+namespace backend
+{
+namespace train
+{
+namespace optimizer
+{
+
+/**
+ * @class   SGD optimizer class
+ * @brief   SGD optimizer
+ */
+class SGD : public exec::train::optimizer::Optimizer
+{
+public:
+  using UpdateFactors = exec::train::optimizer::UpdateFactors;
+
+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 Get the number of optimizer variables
+   *s
+   * @return The number of optimizer variables
+   */
+  virtual uint32_t getVarCount() const override { return 0; };
+
+  /**
+   * @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 backend
+} // namespace onert
+
+#endif // __ONERT_BACKEND_TRAIN_OPTIMIZER_SGD_H__
index 51571b4..f71853e 100644 (file)
@@ -40,7 +40,7 @@ FunctionMap BackendContext::genKernels()
   for (auto &&op_ind : _data.op_order)
   {
     auto fn_seq = kernel_gen->generate(op_ind);
-    ret.emplace_back(op_ind, std::move(fn_seq));
+    ret.emplace(op_ind, std::move(fn_seq));
   }
 
   basic::initConsts(*this);
index bc2936f..e1e2257 100644 (file)
@@ -53,8 +53,7 @@ public:
    * @return std::future<typename std::result_of<F(uint32_t, Args...)>::type>
    */
   template <class F, class... Args>
-  std::future<typename std::result_of<F(uint32_t, Args...)>::type> enqueueJob(F &&f,
-                                                                              Args &&... args)
+  std::future<typename std::result_of<F(uint32_t, Args...)>::type> enqueueJob(F &&f, Args &&...args)
   {
     if (_stop_all)
     {
index a94be24..25e6bd9 100644 (file)
@@ -2,8 +2,10 @@ set(LIB_ONERT_BACKEND_TRIX onert_backend_trix)
 
 nnfw_find_package(TRIXEngine QUIET 2.5.0)
 if(NOT TRIXEngine_FOUND)
+  message(STATUS "ONERT backend: Failed to find TRIXEngine")
   return()
 endif(NOT TRIXEngine_FOUND)
+message(STATUS "ONERT backend: Found TRIXEngine")
 
 file(GLOB_RECURSE SOURCES "*.cc")
 
@@ -14,11 +16,8 @@ target_link_libraries(${LIB_ONERT_BACKEND_TRIX} PRIVATE trix_engine)
 target_link_libraries(${LIB_ONERT_BACKEND_TRIX} PRIVATE nnfw_common)
 target_link_libraries(${LIB_ONERT_BACKEND_TRIX} PRIVATE nnfw_coverage)
 
-set_target_properties(${LIB_ONERT_BACKEND_TRIX} PROPERTIES OUTPUT_NAME backend_trix)
+set_target_properties(${LIB_ONERT_BACKEND_TRIX} PROPERTIES
+  OUTPUT_NAME backend_trix
+  INSTALL_RPATH "$ORIGIN:$ORIGIN/../..")
 
-if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
-  add_custom_command(TARGET ${LIB_ONERT_BACKEND_TRIX} POST_BUILD
-                     COMMAND ${CMAKE_STRIP} "--strip-unneeded" $<TARGET_FILE_NAME:${LIB_ONERT_BACKEND_TRIX}>)
-endif()
-
-install(TARGETS ${LIB_ONERT_BACKEND_TRIX} DESTINATION lib)
+install(TARGETS ${LIB_ONERT_BACKEND_TRIX} DESTINATION lib/nnfw/backend)
index 4d58a7d..f8f2484 100644 (file)
@@ -31,7 +31,7 @@ namespace trix
 // deamon, others except the context roles should be seperated.
 DevContext::DevContext() : _dev_handles{}, _model_ids{}, _meta_map{}
 {
-  auto dev_count = getnumNPUdeviceByType(NPUCOND_TRIV2_CONN_SOCIP);
+  auto dev_count = getnumNPUdeviceByType(NPUCOND_TRIV24_CONN_SOCIP);
   if (dev_count <= 0)
   {
     throw std::runtime_error("Unable to find TRIX NPU device");
@@ -41,7 +41,7 @@ DevContext::DevContext() : _dev_handles{}, _model_ids{}, _meta_map{}
   for (int i = 0; i < dev_count; ++i)
   {
     npudev_h handle;
-    if (getNPUdeviceByType(&handle, NPUCOND_TRIV2_CONN_SOCIP, i) < 0)
+    if (getNPUdeviceByType(&handle, NPUCOND_TRIV24_CONN_SOCIP, i) < 0)
     {
       throw std::runtime_error("Failed to get TRIX NPU device handle");
     }
index 2783bd7..74b6b6e 100644 (file)
@@ -38,9 +38,9 @@ KernelGenerator::KernelGenerator(const ir::Graph &graph,
                                  const std::shared_ptr<TensorBuilder> &tensor_builder,
                                  const std::shared_ptr<basic::TensorRegistry> &tensor_reg,
                                  const std::shared_ptr<DevContext> &dev_context)
-  : basic::KernelGeneratorBase{graph},
-    _ctx(graph.operands()), _operations_ctx{graph.operations()}, _current_layout{graph.layout()},
-    _tensor_builder(tensor_builder), _tensor_reg{tensor_reg}, _dev_context{dev_context}
+  : basic::KernelGeneratorBase{graph}, _ctx(graph.operands()), _operations_ctx{graph.operations()},
+    _current_layout{graph.layout()}, _tensor_builder(tensor_builder), _tensor_reg{tensor_reg},
+    _dev_context{dev_context}
 {
   // DO NOTHING
 }
@@ -69,7 +69,7 @@ void KernelGenerator::visit(const ir::operation::Bulk &node)
     input_tensors.emplace_back(_tensor_reg->getPortableTensor(ifm_idx));
 
   // parameters
-  const auto binary_path = node.param().binary_path;
+  const auto &binary_path = node.param().binary_path;
 
   auto fn = std::make_unique<ops::BulkLayer>();
 
index b555a4a..df6efdb 100644 (file)
@@ -40,7 +40,7 @@ FunctionMap BackendContext::genKernels()
   for (auto &&op_ind : _data.op_order)
   {
     auto fn_seq = kernel_gen->generate(op_ind);
-    ret.emplace_back(op_ind, std::move(fn_seq));
+    ret.emplace(op_ind, std::move(fn_seq));
   }
 
   basic::initConsts(*this);
index e3de31e..e29c812 100644 (file)
@@ -16,11 +16,8 @@ target_link_libraries(${LIB_ONERT_BACKEND_XNNPACK} PRIVATE nnfw_coverage)
 target_link_libraries(${LIB_ONERT_BACKEND_XNNPACK} PRIVATE pthreadpool)
 target_link_libraries(${LIB_ONERT_BACKEND_XNNPACK} PRIVATE XNNPACK)
 
-set_target_properties(${LIB_ONERT_BACKEND_XNNPACK} PROPERTIES OUTPUT_NAME backend_xnnpack)
+set_target_properties(${LIB_ONERT_BACKEND_XNNPACK} PROPERTIES
+  OUTPUT_NAME backend_xnnpack
+  INSTALL_RPATH "$ORIGIN:$ORIGIN/../..")
 
-if(CMAKE_BUILD_TYPE_LC STREQUAL "release")
-  add_custom_command(TARGET ${LIB_ONERT_BACKEND_XNNPACK} POST_BUILD
-                     COMMAND ${CMAKE_STRIP} "--strip-unneeded" $<TARGET_FILE_NAME:${LIB_ONERT_BACKEND_XNNPACK}>)
-endif()
-
-install(TARGETS ${LIB_ONERT_BACKEND_XNNPACK} DESTINATION lib)
+install(TARGETS ${LIB_ONERT_BACKEND_XNNPACK} DESTINATION lib/nnfw/backend)
index 25f3fd2..2a0cc8f 100644 (file)
@@ -41,10 +41,9 @@ KernelGenerator::KernelGenerator(
   const std::shared_ptr<basic::TensorRegistry> &tensor_reg,
   const std::shared_ptr<backend::custom::IKernelBuilder> &kernel_builder,
   const std::shared_ptr<ExternalContext> &external_context)
-  : basic::KernelGeneratorBase{graph},
-    _ctx(graph.operands()), _operations_ctx{graph.operations()}, _current_layout{graph.layout()},
-    _tensor_builder(tensor_builder), _tensor_reg{tensor_reg}, _kernel_builder(kernel_builder),
-    _external_context(external_context)
+  : basic::KernelGeneratorBase{graph}, _ctx(graph.operands()), _operations_ctx{graph.operations()},
+    _current_layout{graph.layout()}, _tensor_builder(tensor_builder), _tensor_reg{tensor_reg},
+    _kernel_builder(kernel_builder), _external_context(external_context)
 {
   // DO NOTHING
 }
@@ -102,7 +101,7 @@ void KernelGenerator::visit(const ir::operation::Conv2D &node)
 
   const auto stride = node.param().stride;
   const auto activation = node.param().activation;
-  const auto param_padding = node.param().padding;
+  const auto &param_padding = node.param().padding;
   const auto dilation = node.param().dilation;
   auto fn = std::make_unique<ops::ConvolutionLayer>(_external_context);
 
@@ -142,7 +141,7 @@ void KernelGenerator::visit(const ir::operation::DepthwiseConv2D &node)
   const auto ker_width = ker_shape.dim(2);
   const auto dilation_width = node.param().dilation.width_factor;
   const auto dilation_height = node.param().dilation.height_factor;
-  const auto param_padding = node.param().padding;
+  const auto &param_padding = node.param().padding;
   const auto padding = ir::calculatePadding(param_padding, ifm_shape, ofm_shape, stride, ker_width,
                                             ker_height, dilation_width, dilation_height);
   const auto multiplier = node.param().multiplier;
index 32ca994..d08f7ea 100644 (file)
@@ -111,7 +111,7 @@ bool ConvolutionLayer::create()
     input_channels /* input_channel_stride */, output_channels /* output_channel_stride */,
     reinterpret_cast<const float *>(_kernel->buffer()),
     reinterpret_cast<const float *>(_bias->buffer()), output_activation_min, output_activation_max,
-    0, &_kernel_op);
+    0, nullptr, nullptr, &_kernel_op);
   if (status != xnn_status_success)
   {
     throw std::runtime_error{"failed to create FP32 Convolution operator"};
@@ -131,10 +131,20 @@ bool ConvolutionLayer::setup()
   uint32_t input_width = _input->getShape().dim(2);
   uint32_t input_height = _input->getShape().dim(1);
   uint32_t batch_size = _input->getShape().dim(0);
-  enum xnn_status status = xnn_setup_convolution2d_nhwc_f32(
-    _kernel_op, batch_size, input_height, input_width,
-    reinterpret_cast<const float *>(_input->buffer()), reinterpret_cast<float *>(_output->buffer()),
-    _external_context->getThreadPool());
+  size_t workspace_size = 0;
+  size_t workspace_alignment = 0;
+  enum xnn_status status = xnn_reshape_convolution2d_nhwc_f32(
+    _kernel_op, batch_size, input_height, input_width, &workspace_size, &workspace_alignment,
+    nullptr, nullptr, _external_context->getThreadPool());
+  if (status != xnn_status_success)
+  {
+    throw std::runtime_error{"failed to create FP32 DepthwiseConvolution operator"};
+  }
+
+  std::vector<uint8_t> workspace(workspace_size);
+  status = xnn_setup_convolution2d_nhwc_f32(_kernel_op, workspace.data(),
+                                            reinterpret_cast<const float *>(_input->buffer()),
+                                            reinterpret_cast<float *>(_output->buffer()));
   if (status != xnn_status_success)
   {
     throw std::runtime_error{"failed to create FP32 Convolution operator"};
index 9a671d4..87617e1 100644 (file)
@@ -112,7 +112,7 @@ bool DepthwiseConvolutionLayer::create()
     _multiplier /* group_output_channels */, input_channels /* input_channel_stride */,
     output_channels /* output_channel_stride */, reinterpret_cast<const float *>(_kernel->buffer()),
     reinterpret_cast<const float *>(_bias->buffer()), output_activation_min, output_activation_max,
-    XNN_FLAG_DEPTHWISE_CONVOLUTION, &_kernel_op);
+    XNN_FLAG_DEPTHWISE_CONVOLUTION, nullptr, nullptr, &_kernel_op);
   if (status != xnn_status_success)
   {
     throw std::runtime_error{"failed to create FP32 DepthwiseConvolution operator"};
@@ -132,10 +132,20 @@ bool DepthwiseConvolutionLayer::setup()
   uint32_t input_width = _input->getShape().dim(2);
   uint32_t input_height = _input->getShape().dim(1);
   uint32_t batch_size = _input->getShape().dim(0);
-  enum xnn_status status = xnn_setup_convolution2d_nhwc_f32(
-    _kernel_op, batch_size, input_height, input_width,
-    reinterpret_cast<const float *>(_input->buffer()), reinterpret_cast<float *>(_output->buffer()),
-    _external_context->getThreadPool());
+  size_t workspace_size = 0;
+  size_t workspace_alignment = 0;
+  enum xnn_status status = xnn_reshape_convolution2d_nhwc_f32(
+    _kernel_op, batch_size, input_height, input_width, &workspace_size, &workspace_alignment,
+    nullptr, nullptr, _external_context->getThreadPool());
+  if (status != xnn_status_success)
+  {
+    throw std::runtime_error{"failed to create FP32 DepthwiseConvolution operator"};
+  }
+
+  std::vector<uint8_t> workspace(workspace_size);
+  status = xnn_setup_convolution2d_nhwc_f32(_kernel_op, workspace.data(),
+                                            reinterpret_cast<const float *>(_input->buffer()),
+                                            reinterpret_cast<float *>(_output->buffer()));
   if (status != xnn_status_success)
   {
     throw std::runtime_error{"failed to create FP32 DepthwiseConvolution operator"};
index 66171ad..93885c6 100644 (file)
@@ -104,7 +104,7 @@ bool FullyConnectedLayer::create()
   enum xnn_status status = xnn_create_fully_connected_nc_f32(
     input_channels, output_channels, input_channels /* input stride */,
     output_channels /* output stride */, kernel_buffer, bias_buffer, output_activation_min,
-    output_activation_max, flag, &_kernel_op);
+    output_activation_max, flag, nullptr, nullptr, &_kernel_op);
   if (status != xnn_status_success)
   {
     throw std::runtime_error{"failed to create FP32 FullyConnected operator"};
@@ -122,9 +122,16 @@ bool FullyConnectedLayer::setup()
   }
 
   uint32_t batch_size = _input->getShape().num_elements() / _kernel->getShape().dim(1);
-  enum xnn_status status = xnn_setup_fully_connected_nc_f32(
-    _kernel_op, batch_size, reinterpret_cast<const float *>(_input->buffer()),
-    reinterpret_cast<float *>(_output->buffer()), _external_context->getThreadPool());
+  enum xnn_status status =
+    xnn_reshape_fully_connected_nc_f32(_kernel_op, batch_size, _external_context->getThreadPool());
+  if (status != xnn_status_success)
+  {
+    throw std::runtime_error{"failed to create FP32 FullyConnected operator"};
+  }
+
+  status =
+    xnn_setup_fully_connected_nc_f32(_kernel_op, reinterpret_cast<const float *>(_input->buffer()),
+                                     reinterpret_cast<float *>(_output->buffer()));
   if (status != xnn_status_success)
   {
     throw std::runtime_error{"failed to create FP32 FullyConnected operator"};
index 8ff3fdf..7795ceb 100644 (file)
@@ -5,17 +5,8 @@ list(REMOVE_ITEM SOURCES ${TESTS})
 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)
 
@@ -25,6 +16,11 @@ set_target_properties(onert_core PROPERTIES POSITION_INDEPENDENT_CODE ON)
 # private target_include_directories scope for src/ directory.
 target_include_directories(onert_core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
 
+# Flatbuffer for loader
+nnfw_find_package(FlatBuffers EXACT 23.5.26 REQUIRED)
+target_link_libraries(onert_core PRIVATE flatbuffers::flatbuffers-23.5.26)
+target_link_libraries(onert_core PRIVATE circle_schema)
+
 target_link_libraries(onert_core PRIVATE jsoncpp half)
 target_link_libraries(onert_core PRIVATE nnfw_lib_misc nnfw_lib_cker)
 target_link_libraries(onert_core PRIVATE nnfw_common)
@@ -44,17 +40,6 @@ if(BUILD_MINMAX_H5DUMPER)
   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>)
-endif()
-
 # NOTE Below line is added to remove warning for android build
 #      It will be removed after android build uses gold linker
 if (ANDROID)
@@ -70,6 +55,9 @@ install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/"
         DESTINATION "include/onert"
         FILES_MATCHING PATTERN "*.h" PATTERN "*.lst"
         )
+# Set install rpath to find plugins - odc, codegen, etc
+set_target_properties(onert_core PROPERTIES
+  INSTALL_RPATH "$ORIGIN:$ORIGIN/nnfw/odc:$ORIGIN/nnfw/codegen:$ORIGIN/nnfw/backend:$ORIGIN/nnfw/loader")
 
 if(NOT ENABLE_TEST)
   return()
index ccecc2d..654aee9 100644 (file)
@@ -32,8 +32,7 @@ namespace backend
 class Backend;
 struct ITensorRegistry;
 
-using FunctionMap =
-  std::vector<std::pair<ir::OperationIndex, std::unique_ptr<exec::FunctionSequence>>>;
+using FunctionMap = std::unordered_map<ir::OperationIndex, std::unique_ptr<exec::FunctionSequence>>;
 
 struct ContextData
 {
index 608ca44..efb2f0d 100644 (file)
@@ -41,17 +41,31 @@ public:
   IPortableTensor(const ir::OperandInfo &info) : _info(info) {}
 
   virtual ~IPortableTensor();
-  virtual const ir::Sparsity *sparsity() const { return nullptr; }
+
+public:
+  // It is introduced to reduce virtual method call overhead on inference
+  // So derived class should maintain actual OperandInfo to "_info" field
+  // Ex. CPU backend getShape() in OperationUtils.h is called frequently on inference
+  //     and it calls get_info()
   const ir::OperandInfo &get_info() const { return _info; }
-  float data_scale() const override { return _info.typeInfo().scale(); }
-  int32_t data_zero_point() const override { return _info.typeInfo().zero_point(); }
-  const std::vector<float> &data_scales() const override { return _info.typeInfo().scales(); }
+  const ir::Sparsity *sparsity() const { return _info.typeInfo().sparsity(); }
+
+  // Finalized methods for IPortableTensor by "_info" field read
+  size_t total_size() const override final { return _info.total_size(); }
+  size_t calcOffset(const ir::Coordinates &coords) const override final;
+  ir::DataType data_type() const override final { return _info.typeInfo().type(); }
+  float data_scale() const override final { return _info.typeInfo().scale(); }
+  int32_t data_zero_point() const override final { return _info.typeInfo().zero_point(); }
+  const std::vector<float> &data_scales() const override final { return _info.typeInfo().scales(); }
   const std::vector<int32_t> &data_zero_points() const override
   {
     return _info.typeInfo().zero_points();
   }
+  bool is_constant() const override final { return _info.isConstant(); }
+  bool is_dynamic() const override final { return _info.isDynamic(); }
+  ir::Shape getShape() const override final { return _info.shape(); }
 
-public:
+  // Finalized methods for IPortableTensor by no padding
   bool has_padding() const final { return false; }
   void access(const std::function<void(ITensor &tensor)> &fn) final { fn(*this); }
 
index 9992ca1..ba73cda 100644 (file)
@@ -44,9 +44,6 @@ template <typename T_BackendContext> void planTensors(const T_BackendContext &ct
   ir::OperandIndexMap<uint32_t> def_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) {
     if (ctx.external_operands().contains(ind))
@@ -63,7 +60,7 @@ template <typename T_BackendContext> void planTensors(const T_BackendContext &ct
     if (!tensor_builder->isRegistered(ind))
     {
       // These tensors do not exist in any  (No use and def)
-      const auto info = obj.info();
+      const auto &info = obj.info();
       // NOTE Currently we only support NHWC tensors for cpu-common tensors.
       //      There is no way to get the layout info from the backend context for now.
       //      When we support NCHW tensors as well, we also need to change tensor info to be
@@ -194,16 +191,12 @@ template <typename T_BackendContext> ITensorRegistry *genTensors(T_BackendContex
   const ir::Graph &graph = *ctx.graph();
   auto tensor_builder = ctx.tensor_builder;
 
-  auto model_io =
-    (graph.getInputs() + graph.getOutputs()) | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED;
   graph.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(graph.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);
+    tensor_builder->registerTensorInfo(ind, obj.info(), ir::Layout::NHWC);
   });
 
   // TODO Get compiler options from compiler, and use it rather than getting it from Env
index 5ca2d95..4225b16 100644 (file)
@@ -17,7 +17,9 @@
 #ifndef __ONERT_BACKEND_IMEMORY_PLANNER_H__
 #define __ONERT_BACKEND_IMEMORY_PLANNER_H__
 
-#include "ir/OperandIndexMap.h"
+#include <cstddef>
+#include <cstdint>
+#include <unordered_map>
 
 namespace onert
 {
@@ -38,21 +40,21 @@ struct Block
 /**
  * @brief Interface to plan memory
  */
-struct IMemoryPlanner
+template <typename Index> struct IMemoryPlanner
 {
-  using MemoryPlans = ir::OperandIndexMap<Block>;
+  using MemoryPlans = std::unordered_map<Index, Block>;
 
   /**
-   * @brief Claim memory for operand
-   * @param[in] index The operand index
+   * @brief Claim memory for tensor
+   * @param[in] index The tensor index
    * @param[in] size The size of the memory
    */
-  virtual void claim(const ir::OperandIndex &, size_t) = 0;
+  virtual void claim(const Index &, size_t) = 0;
   /**
-   * @brief Release memory for operand
-   * @param[in] index The operand index
+   * @brief Release memory for tensor
+   * @param[in] index The tensor index
    */
-  virtual void release(const ir::OperandIndex &) = 0;
+  virtual void release(const Index &) = 0;
   /**
    * @brief Get capacity for memory planning
    * @return The value of capacity
index 6261835..e181a2e 100644 (file)
@@ -18,6 +18,7 @@
 #define __ONERT_BACKEND_CPU_MEMORY_MANAGER_H__
 
 #include "Allocator.h"
+#include "ir/Index.h"
 #include "IMemoryPlanner.h"
 
 namespace onert
@@ -45,12 +46,12 @@ public:
   void releasePlan(const ir::OperandIndex &ind);
 
 private:
-  IMemoryPlanner *createMemoryPlanner();
-  IMemoryPlanner *createMemoryPlanner(const std::string);
+  IMemoryPlanner<ir::OperandIndex> *createMemoryPlanner();
+  IMemoryPlanner<ir::OperandIndex> *createMemoryPlanner(const std::string);
 
-private:
-  ir::OperandIndexMap<Block> _tensor_mem_map;
-  std::shared_ptr<IMemoryPlanner> _mem_planner;
+protected:
+  std::unordered_map<ir::OperandIndex, Block> _tensor_mem_map;
+  std::shared_ptr<IMemoryPlanner<ir::OperandIndex>> _mem_planner;
   std::shared_ptr<Allocator> _mem_alloc;
 };
 
index da51038..0784990 100644 (file)
@@ -71,25 +71,9 @@ public:
 
 public:
   uint8_t *buffer() const override { return _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 _info.total_size(); }
-  size_t calcOffset(const ir::Coordinates &coords) const override;
   ir::Layout layout() const override { return _layout; }
-  ir::DataType data_type() const override { return _info.typeInfo().type(); }
-  bool is_constant() const override { return _info.isConstant(); }
-  bool is_dynamic() const override { return _info.isDynamic(); }
   void set_dynamic() override { _info.setDynamic(); }
   bool applyShape(const ir::Shape &new_shape) override;
-  const ir::Sparsity *sparsity() const override { return _info.typeInfo().sparsity(); }
 
   virtual void increase_ref()
   {
@@ -140,7 +124,6 @@ public:
   virtual int32_t num_references() { return _num_references; }
 
   void setShape(const ir::Shape &new_shape) override;
-  ir::Shape getShape() const override;
 
 protected:
   ir::Layout _layout;
@@ -199,8 +182,6 @@ public:
 public:
   uint8_t *buffer() const override { return _buffer; }
 
-  bool is_constant() const override { return true; }
-  bool is_dynamic() const override { return false; }
   void set_dynamic() override
   {
     throw std::runtime_error("This tensor does not support changing dynamic");
index e1d3b03..571c83a 100644 (file)
@@ -36,16 +36,12 @@ ITensorRegistry *genTensors(backend::train::TrainableBackendContext &ctx,
 {
   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);
+    tensor_builder->registerTensorInfo(ind, obj.info(), ir::Layout::NHWC);
   });
 
   // For the executors that does not have fixed linear execution order:
index e985f29..4b12cc5 100644 (file)
@@ -51,31 +51,12 @@ public:
 
 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)); }
+  void setOptVarBuffer(uint8_t *buffer, size_t pos) { _opt_vars.at(pos)->setBuffer(buffer); }
 
 public:
   void fillBuffer(const std::shared_ptr<ir::Data> &data);
index 72b8a35..3d21e53 100644 (file)
@@ -18,6 +18,7 @@
 #define __ONERT_BACKEND_TRAIN_ITENSOR_REGISTRY_H__
 
 #include "backend/ITensorRegistry.h"
+#include "backend/train/ITrainableTensor.h"
 
 namespace onert
 {
@@ -30,23 +31,24 @@ class ITensorRegistry : public backend::ITensorRegistry
 {
 public:
   /**
-   * @brief Returns pointer of ITensor among native and migrant tensors, not derivative and gradient
+   * @brief Returns pointer of ITensor among native and migrant tensors, not back propatation and
+   * gradient
    *
    */
   using backend::ITensorRegistry::getITensor;
 
   /**
-   * @brief Returns pointer of ITensor among native tensors, not derivative and gradient
+   * @brief Returns pointer of ITensor among native tensors, not back propatation and gradient
    *
    */
   using backend::ITensorRegistry::getNativeITensor;
 
   /**
-   * @brief Returns pointer of ITensor for derivative
+   * @brief Returns pointer of ITensor for back propatation
    *
    * @note  Return tensor cannot be used longer than dynamic tensor manager
    */
-  virtual ITensor *getDerivativeITensor(const ir::OperandIndex &) = 0;
+  virtual ITensor *getBackPropITensor(const ir::OperandIndex &) = 0;
 
   /**
    * @brief Returns pointer of ITensor for gradient
@@ -54,6 +56,14 @@ public:
    * @note  Returned tensor cannot be used longer than dynamic tensor manager
    */
   virtual ITensor *getGradientITensor(const ir::OperandIndex &) = 0;
+
+  /**
+   * @brief Iterate ITrainableTensors with fn
+   * @param fn function to be called with OperandIndex and a pointer to ITrainableTensor
+   */
+  virtual void iterateTrainableTensors(
+    const std::function<void(const ir::OperandIndex &, const train::ITrainableTensor *)> &)
+    const = 0;
 };
 
 } // namespace train
@@ -67,7 +77,7 @@ namespace backend
 namespace train
 {
 
-template <typename Tensor, typename TrainableTensor, typename DerivativeTensor,
+template <typename Tensor, typename TrainableTensor, typename BackPropTensor,
           typename GradientTensor>
 class PortableTensorRegistryTemplate : public backend::train::ITensorRegistry
 {
@@ -91,9 +101,9 @@ public:
     return tensor;
   }
 
-  ITensor *getDerivativeITensor(const ir::OperandIndex &index) override
+  ITensor *getBackPropITensor(const ir::OperandIndex &index) override
   {
-    return getDerivativeTensor(index);
+    return getBackPropTensor(index);
   }
 
   ITensor *getGradientITensor(const ir::OperandIndex &index) override
@@ -101,6 +111,14 @@ public:
     return getGradientTensor(index);
   }
 
+  void iterateTrainableTensors(
+    const std::function<void(const ir::OperandIndex &, const train::ITrainableTensor *)> &fn)
+    const override
+  {
+    for (const auto &e : _trainable)
+      fn(e.first, e.second.get());
+  }
+
   IPortableTensor *getPortableTensor(const ir::OperandIndex &index)
   {
     auto tensor = _trainable.find(index);
@@ -129,10 +147,10 @@ public:
     return nullptr;
   }
 
-  DerivativeTensor *getDerivativeTensor(const ir::OperandIndex &index)
+  BackPropTensor *getBackPropTensor(const ir::OperandIndex &index)
   {
-    auto tensor = _derivative.find(index);
-    if (tensor != _derivative.end())
+    auto tensor = _back_prop.find(index);
+    if (tensor != _back_prop.end())
       return tensor->second.get();
     return nullptr;
   }
@@ -191,15 +209,15 @@ public:
     _trainable[index] = std::move(tensor);
   }
 
-  void setDerivativeTensor(const ir::OperandIndex &index, std::unique_ptr<DerivativeTensor> tensor)
+  void setBackPropTensor(const ir::OperandIndex &index, std::unique_ptr<BackPropTensor> 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."};
+    auto itr = _back_prop.find(index);
+    if (itr != _back_prop.end())
+      throw std::runtime_error{"Tried to set a back propagation tensor but another back "
+                               "propagation tensor already exists."};
 
-    _derivative[index] = std::move(tensor);
+    _back_prop[index] = std::move(tensor);
   }
 
   void setGradientTensor(const ir::OperandIndex &index, std::unique_ptr<GradientTensor> tensor)
@@ -218,7 +236,7 @@ public:
     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<Tensor>> &back_prop_tensors() { return _back_prop; }
   const ir::OperandIndexMap<std::unique_ptr<GradientTensor>> &gradient_tensors()
   {
     return _gradient;
@@ -233,7 +251,7 @@ private:
   ir::OperandIndexMap<IPortableTensor *> _migrant;
 
   // Tensors for backpropagation
-  ir::OperandIndexMap<std::unique_ptr<DerivativeTensor>> _derivative;
+  ir::OperandIndexMap<std::unique_ptr<BackPropTensor>> _back_prop;
 
   // Tensors for updating trainable tensors
   ir::OperandIndexMap<std::unique_ptr<GradientTensor>> _gradient;
index 3f47af7..b3a9cdd 100644 (file)
@@ -20,9 +20,9 @@
 #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/OptimizerInfo.h"
 #include "ir/train/TrainableGraph.h"
 #include "util/Set.h"
 
@@ -34,7 +34,7 @@ namespace train
 {
 
 using FunctionMap =
-  std::vector<std::pair<ir::OperationIndex, std::unique_ptr<exec::train::TrainableFnSequence>>>;
+  std::unordered_map<ir::OperationIndex, std::unique_ptr<exec::train::TrainableFnSequence>>;
 
 struct TrainableContextData
 {
@@ -50,8 +50,8 @@ struct TrainableContextData
   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;
+  /* Optimizer information */
+  ir::train::OptimizerInfo optim_info;
 };
 
 class TrainableBackendContext
index 9a86f40..7ae0805 100644 (file)
@@ -39,18 +39,17 @@ class Compiler : public ICompiler
 public:
   /**
    * @brief     Construct a new Compiler object for single model
-   * @param[in] model     model to compile
-   * @param[in] coptions  Compiler Options
+   * @param[in] model model to compile
+   * @param[in] copts Compiler Options
    */
-  Compiler(const std::shared_ptr<ir::Model> &model, CompilerOptions &copt);
+  Compiler(const std::shared_ptr<ir::Model> &model, CompilerOptions *copts);
 
   /**
    * @brief     Construct a new Compiler object for NN package
-   * @param[in] nnpkg    NN package to compile
-   * @param[in] coptions Compiler option vector for each model in package
+   * @param[in] nnpkg NN package to compile
+   * @param[in] copts Compiler option for package
    */
-  Compiler(const std::shared_ptr<ir::NNPkg> &nnpkg,
-           std::vector<std::unique_ptr<CompilerOptions>> &copts);
+  Compiler(const std::shared_ptr<ir::NNPkg> &nnpkg, CompilerOptions *copts);
 
   /**
    * @brief Destroy the Compiler object
index 5a8886a..dde399a 100644 (file)
@@ -19,8 +19,8 @@
 
 #include "ICompiler.h"
 #include "CompilerOptions.h"
-#include "compiler/train/TrainingInfo.h"
 #include "ir/NNPkg.h"
+#include "ir/train/TrainingInfo.h"
 
 namespace onert
 {
@@ -34,9 +34,8 @@ public:
   static CompilerFactory &get();
 
 public:
-  std::unique_ptr<ICompiler> create(const std::shared_ptr<ir::NNPkg> &nnpkg,
-                                    std::vector<std::unique_ptr<CompilerOptions>> &copts,
-                                    const compiler::train::TrainingInfo *training_info = nullptr);
+  std::unique_ptr<ICompiler> create(const std::shared_ptr<ir::NNPkg> &nnpkg, CompilerOptions *copts,
+                                    const ir::train::TrainingInfo *training_info = nullptr);
 
 private:
   // It is not allowed to use CompilerFactory without get()
index bb0d0a4..27f236e 100644 (file)
@@ -32,18 +32,15 @@ namespace compiler
 
 struct ManualSchedulerOptions
 {
-public:
   void setBackendMap(const std::string &str);
 
-public:
   std::string backend_for_all;
   std::unordered_map<ir::OpCode, std::string> opcode_to_backend;
   std::unordered_map<ir::OperationIndex, std::string> index_to_backend;
 };
 
-class CompilerOptions
+struct CompilerOptions
 {
-public:
   /**
    * @brief   Set default values for CompilerOptions
    * @return  Generated CompileOption
@@ -54,11 +51,6 @@ public:
   static std::unique_ptr<CompilerOptions> fromGlobalConfig();
 
   /**
-   * @brief Allow to compute float32 using float16 data type
-   */
-  void enableToFp16() { fp16_enable = true; }
-
-  /**
    * @brief Force default values of CompilerOptions for correct compilations
    *
    * @note  This should be called after CompilerOptions setting is finished
@@ -71,19 +63,17 @@ public:
    */
   void verboseOptions();
 
-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
-  int graph_dump_level;       //< Graph dump level, values between 0 and 2 are valid
-  std::string executor;       //< Executor name to use
+  int graph_dump_level; //< Graph dump level, values between 0 and 2 are valid
+  std::string executor; //< Executor name to use
   ManualSchedulerOptions manual_scheduler_options; //< Options for ManualScheduler
-  bool he_scheduler;      //< HEScheduler if true, ManualScheduler otherwise
-  bool he_profiling_mode; //< Whether HEScheduler profiling mode ON/OFF
-  bool fp16_enable;       //< Whether fp16 mode ON/OFF
+  bool he_scheduler;         //< HEScheduler if true, ManualScheduler otherwise
+  bool he_profiling_mode;    //< Whether HEScheduler profiling mode ON/OFF
+  bool fp16_enable;          //< Whether fp16 mode ON/OFF
+  std::string workspace_dir; //< Workspace directory path
 };
 
 } // namespace compiler
index 83dede7..9102cca 100644 (file)
@@ -126,6 +126,7 @@ private:
   void visit(const ir::operation::Comparison &op) override;
   void visit(const ir::operation::Concat &op) override;
   void visit(const ir::operation::Conv2D &op) override;
+  void visit(const ir::operation::DepthwiseConv2D &op) override;
   void visit(const ir::operation::ElementwiseActivation &op) override;
   void visit(const ir::operation::ElementwiseBinary &op) override;
   void visit(const ir::operation::ElementwiseUnary &op) override;
@@ -143,6 +144,7 @@ private:
   void visit(const ir::operation::Pack &op) override;
   void visit(const ir::operation::Pad &op) override;
   void visit(const ir::operation::Permute &op) override;
+  void visit(const ir::operation::Pool2D &op) override;
   void visit(const ir::operation::Pow &op) override;
   void visit(const ir::operation::Range &op) override;
   void visit(const ir::operation::Reduce &op) override;
diff --git a/runtime/onert/core/include/compiler/train/TrainingInfo.h b/runtime/onert/core/include/compiler/train/TrainingInfo.h
deleted file mode 100644 (file)
index 3b77c83..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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__
index f814b78..d34dc05 100644 (file)
@@ -72,6 +72,7 @@ public:
   void visit(const ir::operation::Pack &op) override;
   void visit(const ir::operation::Pad &op) override;
   void visit(const ir::operation::Permute &op) override;
+  void visit(const ir::operation::Pool2D &op) override;
   void visit(const ir::operation::Pow &op) override;
   // TODO write op starting from Q
   void visit(const ir::operation::Range &op) override;
index da4d20d..6ff4820 100644 (file)
 #ifndef __ONERT_EXEC_EXECUTION_H__
 #define __ONERT_EXEC_EXECUTION_H__
 
+#include "backend/train/ITrainableTensor.h"
 #include "ir/Layout.h"
 #include "exec/IExecutors.h"
-#include "IODescription.h"
+#include "ExecutionContext.h"
 
 #include <thread>
 #include <deque>
@@ -67,44 +68,35 @@ public:
    * @param[in] index   Input index
    * @param[in] buffer  Input data's buffer pointer
    * @param[in] length  Input data's length
-   * @param[in] layout  Input data's data format
    */
-  void setInput(const ir::IOIndex &index, const void *buffer, size_t length,
-                ir::Layout layout = ir::Layout::NHWC);
+  void setInput(const ir::IOIndex &index, const void *buffer, size_t length);
 
   /**
    * @brief     Set input data's information, especially to specify unknown dimensions on model
    * build time.
    * @param[in] index   Input index
-   * @param[in] type    Input data's type info
    * @param[in] shape   Input data's shape
    * @param[in] buffer  Input data's buffer pointer
    * @param[in] length  Input data's length
-   * @param[in] layout  Input data's data format
    */
-  void setInput(const ir::IOIndex &index, const ir::TypeInfo &type, const ir::Shape &shape,
-                const void *buffer, size_t length, ir::Layout layout = ir::Layout::NHWC);
+  void setInput(const ir::IOIndex &index, const ir::Shape &shape, const void *buffer,
+                size_t length);
   /**
    * @brief     Set output data's information
    * @param[in] index   Output index
    * @param[in] buffer  Output data's buffer pointer
    * @param[in] length  Output data's length
-   * @param[in] layout  Output data's data format
    */
-  void setOutput(const ir::IOIndex &index, void *buffer, size_t length,
-                 ir::Layout layout = ir::Layout::NHWC);
+  void setOutput(const ir::IOIndex &index, void *buffer, size_t length);
   /**
    * @brief     Set output data's information, especially to specify unknown dimensions on model
    * build time.
    * @param[in] index   Output index
-   * @param[in] type    Output data's type info
    * @param[in] shape   Output data's shape
    * @param[in] buffer  Output data's buffer pointer
    * @param[in] length  Output data's length
-   * @param[in] layout  Output data's data format
    */
-  void setOutput(const ir::IOIndex &index, const ir::TypeInfo &type, const ir::Shape &shape,
-                 void *buffer, size_t length, ir::Layout layout = ir::Layout::NHWC);
+  void setOutput(const ir::IOIndex &index, const ir::Shape &shape, void *buffer, size_t length);
   /**
    * @brief     Set input data's data format
    * @param[in] index   Input index
@@ -118,6 +110,18 @@ public:
    */
   void setOutputLayout(const ir::IOIndex &index, ir::Layout layout);
   /**
+   * @brief     Set input type information
+   * @param[in] index     Input index
+   * @param[in] typeInfo  Input type information
+   */
+  void setInputType(const ir::IOIndex &index, const ir::TypeInfo &typeInfo);
+  /**
+   * @brief     Set output type information
+   * @param[in] index     Output index
+   * @param[in] typeInfo  Output type information
+   */
+  void setOutputType(const ir::IOIndex &index, const ir::TypeInfo &typeInfo);
+  /**
    * @brief  Execution
    * @note   It should be called after setting input and output buffer
    */
@@ -142,7 +146,6 @@ public:
    */
   bool isFinished(void) const;
 
-#ifdef ONERT_TRAIN
   /**
    * @brief  Train
    * @note   It should be called after setting input and output buffer
@@ -158,20 +161,30 @@ public:
    * @return @c float Loss value
    */
   float getLoss(const ir::IOIndex &ind);
-#endif // ONERT_TRAIN
+
+  /**
+   * @brief     Iterate trainable tensors
+   * @note      It should be called after training
+   * @param[in] fn  function to be called with OperandIndex and a pointer to ITrainableTensor
+   */
+  void iterateTrainableTensors(
+    const std::function<void(const ir::OperandIndex &, const backend::train::ITrainableTensor *)>
+      &fn) const;
 
   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;
 
+  ExecutionOptions &executionOptions() { return _ctx.options; }
+
 private:
   const IExecutor *entryExecutor() const { return _executors->entryExecutor(); };
   IExecutor *entryExecutor() { return _executors->entryExecutor(); };
 
 private:
   const std::shared_ptr<IExecutors> _executors;
-  IODescription _io_desc;
+  ExecutionContext _ctx;
   std::unique_ptr<std::thread> _exec_thread;
   bool finished{false};
 };
diff --git a/runtime/onert/core/include/exec/ExecutionContext.h b/runtime/onert/core/include/exec/ExecutionContext.h
new file mode 100644 (file)
index 0000000..4a1f3f5
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXECUTION_CONTEXT_H__
+#define __ONERT_EXEC_EXECUTION_CONTEXT_H__
+
+#include <vector>
+#include <unordered_map>
+#include <semaphore.h>
+
+#include "ir/OperandInfo.h"
+#include "ir/Index.h"
+
+namespace onert
+{
+namespace exec
+{
+
+struct InputDesc
+{
+  ir::OperandInfo info;
+  const void *buffer;
+  size_t size;
+  ir::Layout layout;
+
+  InputDesc(void) = delete;
+  InputDesc(const ir::OperandInfo &info)
+    : info(info), buffer(nullptr), size(0), layout(ir::Layout::NHWC)
+  {
+  }
+};
+
+struct OutputDesc
+{
+  ir::OperandInfo info;
+  void *buffer;
+  size_t size;
+  ir::Layout layout;
+
+  OutputDesc(void) = delete;
+  OutputDesc(const ir::OperandInfo &info)
+    : info(info), buffer(nullptr), size(0), layout(ir::Layout::NHWC)
+  {
+  }
+};
+
+struct IODescription
+{
+  std::vector<std::unique_ptr<InputDesc>> inputs;
+  std::vector<std::unique_ptr<OutputDesc>> outputs;
+};
+
+struct ExecutionOptions
+{
+  bool dump_minmax = false;
+  bool trace = false;
+  bool profile = false;
+
+  static void fromGlobalConfig(ExecutionOptions &options);
+};
+
+struct ExecutionContext
+{
+  IODescription desc;
+  bool shape_updated = false; // Require shape inference and buffer size calculation
+  ExecutionOptions options;
+};
+
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_EXECUTION_CONTEXT_H__
index f3384be..075aa1a 100644 (file)
@@ -35,7 +35,7 @@ namespace exec
 class FunctionSequence : public IFunction
 {
 public:
-  template <typename... Args> FunctionSequence(Args &&... args) { initialize(std::move(args)...); }
+  template <typename... Args> FunctionSequence(Args &&...args) { initialize(std::move(args)...); }
 
 private:
   void initialize()
@@ -43,7 +43,7 @@ private:
     // Template base case : do nothing
   }
 
-  template <typename T, typename... Args> void initialize(std::unique_ptr<T> &&fn, Args &&... args)
+  template <typename T, typename... Args> void initialize(std::unique_ptr<T> &&fn, Args &&...args)
   {
     _functions.emplace_back(std::move(fn));
     initialize(std::move(args)...);
@@ -64,7 +64,7 @@ public:
 
   void iterate(const std::function<void(IFunction &)> &fn);
 
-  template <typename T, typename... Args> void wrap(Args &&... args)
+  template <typename T, typename... Args> void wrap(Args &&...args)
   {
     for (auto &&function : _functions)
     {
index 46dbcd0..9b55627 100644 (file)
 #ifndef __ONERT_EXEC_I_EXECUTOR_H__
 #define __ONERT_EXEC_I_EXECUTOR_H__
 
+#include "ExecutionContext.h"
+#include "backend/IPortableTensor.h"
 #include "ir/Graph.h"
-#include "IFunction.h"
-#include "IODescription.h"
 #include "ir/Index.h"
+#include "ir/OperandInfo.h"
 #include "ir/OperationIndexMap.h"
 
 #include <cstdint>
 #include <memory>
-#include <unordered_map>
+#include <vector>
 
 namespace onert
 {
-namespace backend
-{
-class IPortableTensor;
-namespace builtin
-{
-class IOTensor;
-}
-} // namespace backend
-} // namespace onert
-namespace onert
-{
 namespace exec
 {
 /**
@@ -74,36 +64,63 @@ struct IExecutor
   virtual void setIndexedRanks(std::shared_ptr<ir::OperationIndexMap<int64_t>>) = 0;
 
   /**
-   * @brief     Execute with user-given input/output description (for primary subgraph)
-   * @param[in] desc Input and output description
-   * @note      This method should be thread-safe
-   */
-  virtual void execute(const IODescription &desc) = 0;
-
-  /**
    * @brief Execute with given input/output tensors
    *
-   * For non-primary subgraphs, input and output tensors must be given.
+   * Input and output tensors must be given.
    *
-   * @param[in] inputs tensors that are passed as inputs
-   * @param[in] outputs tensors that are passed as outputs
+   * @param[in] inputs  Tensors that are passed as inputs
+   * @param[in] outputs Tensors that are passed as outputs
+   * @param[in] options Execution options
    */
   virtual void execute(const std::vector<backend::IPortableTensor *> &inputs,
-                       const std::vector<backend::IPortableTensor *> &outputs) = 0;
+                       const std::vector<backend::IPortableTensor *> &outputs,
+                       const ExecutionOptions &options) = 0;
 
   /**
-   * @brief Get input tensor objects
-   *
-   * @return Vector of @c IOTensor
+   * @brief   Get input size
+   * @return  Input size
    */
-  virtual const std::vector<backend::builtin::IOTensor *> &getInputTensors() const = 0;
+  virtual uint32_t inputSize() const = 0;
 
   /**
-   * @brief Get output tensor objects
-   *
-   * @return Vector of @c IOTensor
+   * @brief   Get output size
+   * @return  Output size
+   */
+  virtual uint32_t outputSize() const = 0;
+
+  /**
+   * @brief     Get input info at index
+   * @param[in] index Index of input
+   * @return    Input operand info
+   */
+  virtual const ir::OperandInfo &inputInfo(uint32_t index) const = 0;
+
+  /**
+   * @brief     Get output info at index
+   * @param[in] index Index of output
+   * @return    Output operand info
+   */
+  virtual const ir::OperandInfo &outputInfo(uint32_t index) const = 0;
+
+  /**
+   * @brief     Get input layout at index
+   * @param[in] index Index of input
+   * @return    Input operand layout
+   */
+  virtual ir::Layout inputLayout(uint32_t index) const = 0;
+
+  /**
+   * @brief     Get output layout at index
+   * @param[in] index Index of output
+   * @return    Output operand layout
+   */
+  virtual ir::Layout outputLayout(uint32_t index) const = 0;
+
+  /**
+   * @brief   Return current execution configuration
+   * @return  Current execution configuration
    */
-  virtual const std::vector<backend::builtin::IOTensor *> &getOutputTensors() const = 0;
+  virtual const ExecutionOptions &currentOptions() const = 0;
 };
 
 } // namespace exec
index 013da71..37a14d2 100644 (file)
@@ -87,9 +87,9 @@ public:
 
   /**
    * @brief     Execute NN package executor set
-   * @param[in] desc  Input and output buffer description
+   * @param[in] ctx  Execution context
    */
-  virtual void execute(const IODescription &desc) = 0;
+  virtual void execute(const ExecutionContext &ctx) = 0;
 };
 
 } // namespace exec
diff --git a/runtime/onert/core/include/exec/IODescription.h b/runtime/onert/core/include/exec/IODescription.h
deleted file mode 100644 (file)
index 14c5ffc..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_IO_DESCRIPTION_H__
-#define __ONERT_EXEC_IO_DESCRIPTION_H__
-
-#include <vector>
-#include <unordered_map>
-#include <semaphore.h>
-
-#include "ir/OperandInfo.h"
-#include "ir/Index.h"
-
-namespace onert
-{
-namespace exec
-{
-
-struct InputDesc
-{
-  const ir::OperandInfo info;
-  const void *buffer;
-  const size_t size;
-  const ir::Layout layout;
-
-  InputDesc(void) = delete;
-  InputDesc(const ir::OperandInfo &info, const void *buffer, const size_t size, ir::Layout layout)
-    : info(info), buffer(buffer), size(size), layout(layout)
-  {
-  }
-};
-
-struct OutputDesc
-{
-  // not `const` because shape should be modified after execution in case when output is
-  // a dynamic tensor
-  ir::OperandInfo info;
-  void *buffer;
-  const size_t size;
-  const ir::Layout layout;
-
-  OutputDesc(void) = delete;
-  OutputDesc(const ir::OperandInfo &info, void *buffer, const size_t size, ir::Layout layout)
-    : info(info), buffer(buffer), size(size), layout(layout)
-  {
-  }
-};
-
-struct IODescription
-{
-  std::vector<std::unique_ptr<InputDesc>> inputs;
-  std::vector<std::unique_ptr<OutputDesc>> outputs;
-  // Contains shape of input set by nnfw_set_input_tensorinfo(..)
-  std::unordered_map<ir::IOIndex, ir::Shape> dynamic_input_shapes;
-};
-
-} // namespace exec
-} // namespace onert
-
-#endif // __ONERT_EXEC_IO_DESCRIPTION_H__
index fc6849e..a9dec24 100644 (file)
@@ -24,15 +24,36 @@ namespace onert
 {
 namespace exec
 {
-struct SMHash
+
+/*
+ * NOTE: To record MinMax, the key would be better to use Tensor ID in circle.
+ * But in general, onert does not keep track of circle tensor ID to onert tensor ID.
+ * The ordering in tensors in onert may be different from ordering in circle
+ * because onert could try optimization (reusing allocation, removing redundant tensors,
+ * code optimization, ...)
+ * For Linear Executor and CPU backcend, onert keep track of op index in generated Code.
+ * MinMaxMap uses operation index instead.
+ *
+ * TODO: Stop recording in case of onert internal optimization (e.g. code fusion) occcurs.
+ *       It rarely happens since most fusioning is done by compiler frontend, not by onert.
+ */
+struct OpMinMaxHash
 {
   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>;
+using OpMinMaxMap = util::MinMaxMap<std::pair<ir::SubgraphIndex, ir::OperationIndex>, OpMinMaxHash>;
+
+struct IOMinMaxHash
+{
+  size_t operator()(const std::pair<ir::SubgraphIndex, ir::IOIndex> &k) const noexcept
+  {
+    return std::hash<ir::SubgraphIndex>()(k.first) ^ std::hash<ir::IOIndex>()(k.second);
+  }
+};
+using IOMinMaxMap = util::MinMaxMap<std::pair<ir::SubgraphIndex, ir::IOIndex>, IOMinMaxHash>;
 } // namespace exec
 } // namespace onert
 
index 8be1b1e..2cdad1b 100644 (file)
@@ -34,7 +34,7 @@ class TrainableFnSequence
 {
 public:
   void forward(bool training);
-  void backward(uint32_t training_step);
+  void backward(uint32_t training_step, bool weight_update_enabled);
 
   void append(std::unique_ptr<ITrainableFunction> &&fn);
   void append(std::unique_ptr<IGradientApplier> &&applier);
index 05f2ee1..ea14bc4 100644 (file)
@@ -60,6 +60,13 @@ public:
   virtual double getLearningRate(uint32_t iteration) const = 0;
 
   /**
+   * @brief Get the number of optimizer variables
+   *s
+   * @return The number of optimizer variables
+   */
+  virtual uint32_t getVarCount() const = 0;
+
+  /**
    * @brief Apply gradient to a trainable tensor
    *
    * @param factors UpdateFactors to be used for applying gradient to a trainable tensor
diff --git a/runtime/onert/core/include/exec/train/optimizer/OptimizerCode.h b/runtime/onert/core/include/exec/train/optimizer/OptimizerCode.h
deleted file mode 100644 (file)
index 3e4a8f2..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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
deleted file mode 100644 (file)
index 6a1a5c9..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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/exporter/CircleExporter.h b/runtime/onert/core/include/exporter/CircleExporter.h
new file mode 100644 (file)
index 0000000..c9d0419
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <string>
+#include <memory>
+#include <mutex>
+
+namespace circle
+{
+struct ModelT;
+} // namespace circle
+namespace onert
+{
+namespace exec
+{
+class Execution;
+} // namespace exec
+namespace ir
+{
+namespace train
+{
+class TrainingInfo;
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+namespace onert
+{
+namespace exporter
+{
+class CircleExporter
+{
+public:
+  CircleExporter(const std::string &source, const std::string &path);
+  ~CircleExporter();
+
+  void updateWeight(const std::unique_ptr<onert::exec::Execution> &exec);
+  void updateMetadata(const std::unique_ptr<onert::ir::train::TrainingInfo> &training_info);
+
+private:
+  void finish();
+
+private:
+  std::string _path;
+  std::string _data;
+  std::unique_ptr<::circle::ModelT> _model;
+  std::mutex _mutex;
+};
+
+} // namespace exporter
+} // namespace onert
index 1864c3b..6b82bfa 100644 (file)
@@ -19,7 +19,9 @@
 
 #include "util/Index.h"
 
+#include <iomanip>
 #include <ostream>
+#include <sstream>
 
 namespace onert
 {
@@ -41,13 +43,18 @@ using SubgraphIndex = ::onert::util::Index<uint16_t, SubgraphIndexTag>;
 struct ModelIndexTag;
 using ModelIndex = ::onert::util::Index<uint16_t, ModelIndexTag>;
 
+struct OriginIndexTag;
+using OriginIndex = ::onert::util::Index<uint32_t, OriginIndexTag>;
+
 template <typename IndexType>
 std::ostream &_index_print_impl(std::ostream &o, const std::string &prefix, IndexType index)
 {
+  std::ostringstream oss;
   if (index.undefined())
-    return o << prefix << std::string("?");
+    oss << prefix << std::string("?");
   else
-    return o << prefix << index.value();
+    oss << prefix << index.value();
+  return o << std::right << std::setw(4) << oss.str();
 }
 
 inline std::ostream &operator<<(std::ostream &o, const OperationIndex &i)
@@ -75,6 +82,10 @@ inline std::ostream &operator<<(std::ostream &o, const ModelIndex &i)
   return _index_print_impl(o, "MODEL", i);
 }
 
+inline std::ostream &operator<<(std::ostream &o, const OriginIndex &i)
+{
+  return _index_print_impl(o, "", i);
+}
 } // namespace ir
 } // namespace onert
 
index 950d288..5f9a07c 100644 (file)
@@ -175,8 +175,34 @@ public:
 
 private:
   std::shared_ptr<backend::custom::IKernelBuilder> _kernel_builder;
-};
 
+public:
+  void add_metadata(const std::string &name, std::unique_ptr<const ir::Data> data)
+  {
+    _metadatas.emplace(name, std::move(data));
+  }
+
+  bool exists_metadata(const std::string &name) const
+  {
+    return _metadatas.find(name) != _metadatas.end();
+  }
+
+  // NOTE The corresponding metadata is deleted from the model and returned
+  std::unique_ptr<const ir::Data> extract_metadata(const std::string name)
+  {
+    auto m = _metadatas.find(name);
+
+    if (m == _metadatas.end())
+      throw std::out_of_range{"no meatdata named " + name};
+
+    auto data = std::move(m->second);
+    _metadatas.erase(m);
+    return data;
+  }
+
+private:
+  std::unordered_map<std::string, std::unique_ptr<const ir::Data>> _metadatas;
+};
 } // namespace ir
 } // namespace onert
 
index e4a9157..71da3e4 100644 (file)
@@ -79,7 +79,7 @@ public:
   bool isConstant(void) const { return _info.isConstant(); }
 
 public:
-  template <typename T, typename... Args> void data(Args &&... args)
+  template <typename T, typename... Args> void data(Args &&...args)
   {
     data(std::make_unique<T>(std::forward<Args>(args)...));
   }
@@ -104,6 +104,9 @@ public:
     return std::vector<T>(base, base + size);
   }
 
+  void setOriginIndex(OriginIndex origin) { _info.setOriginIndex(origin); }
+  OriginIndex originIndex() const { return _info.originIndex(); }
+
 private:
   OperandInfo _info;
   std::shared_ptr<Data> _data;
index 11aeb49..2957be2 100644 (file)
 #ifndef __ONERT_IR_OPERAND_INFO_H__
 #define __ONERT_IR_OPERAND_INFO_H__
 
+#include "ir/Index.h"
+#include "ir/Layout.h"
 #include "ir/Shape.h"
 #include "ir/TypeInfo.h"
-#include "ir/Layout.h"
 
 namespace onert
 {
@@ -66,9 +67,9 @@ public:
    * @param[in] alloc_type  When the thesor needs memory allocation
    */
   OperandInfo(const Shape &shape, const TypeInfo &typeInfo, MemAllocType alloc_type,
-              bool is_const = false, bool is_variable = false)
+              bool is_const = false, bool is_variable = false, OriginIndex origin = OriginIndex())
     : _shape(shape), _typeInfo(typeInfo), _alloc_type(alloc_type), _const(is_const),
-      _variable(is_variable)
+      _variable(is_variable), _origin(origin)
   {
     // DO NOTHING
   }
@@ -107,6 +108,11 @@ public:
    */
   const TypeInfo &typeInfo() const { return _typeInfo; }
   /**
+   * @brief     Set type information
+   * @param[in] typeInfo Type information
+   */
+  void typeInfo(const ir::TypeInfo &typeInfo) { _typeInfo = typeInfo; }
+  /**
    * @brief   Set tensor data type
    */
   void type(const DataType type) { _typeInfo.type(type); }
@@ -135,14 +141,16 @@ public:
   bool isVariable() const { return _variable; }
   bool isDynamic() const { return _alloc_type == MemAllocType::DYNAMIC; }
   void setDynamic() { _alloc_type = MemAllocType::DYNAMIC; }
+  OriginIndex originIndex() const { return _origin; }
+  void setOriginIndex(OriginIndex origin) { _origin = origin; }
 
 private:
   Shape _shape;
   TypeInfo _typeInfo;
-
   MemAllocType _alloc_type;
   bool _const;
   bool _variable;
+  OriginIndex _origin;
 };
 
 } // namespace ir
index e265e81..17e94ee 100644 (file)
@@ -38,6 +38,7 @@ public:
   enum class ElementwiseBinaryType
   {
     FLOOR_DIV,
+    FLOOR_MOD,
     LOGICAL_AND,
     LOGICAL_OR,
     MAX,
index 73f1aed..e0e8b38 100644 (file)
@@ -36,35 +36,12 @@ public:
     // 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);
+  Loss(const OperandIndexSequence &inputs, const OperandIndexSequence &outputs);
 
 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
index 590bed4..9a563d7 100644 (file)
@@ -39,7 +39,23 @@ 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
+  virtual bool hasTrainableParameter() const = 0;
+
+  // Update of the node will be disabled during traning
+  virtual void disableWeightsUpdate() = 0;
+  // Note that the update is disabled by default
+  // Update of the node will be enabled during traning
+  virtual void enableWeightsUpdate() = 0;
+  // Check if the node is trainable
+  virtual bool isWeightsUpdateEnabled() const = 0;
+
+  // Mark the node as needed for backward propagation part of the traning
+  virtual void enableBackward() = 0;
+  virtual void disableBackward() = 0;
+  // Check if the nodes is required for backward propagation part of the traning.
+  // If returned false, it means that there are no node before (in topological sense) which is
+  // trainable.
+  virtual bool isRequiredForBackward() const = 0;
 };
 
 } // namespace train
diff --git a/runtime/onert/core/include/ir/train/Index.h b/runtime/onert/core/include/ir/train/Index.h
new file mode 100644 (file)
index 0000000..6d081e5
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_INDEX_H__
+#define __ONERT_IR_TRAIN_INDEX_H__
+
+#include "ir/Index.h"
+
+#include <cassert>
+#include <cstdint>
+#include <utility>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+/**
+ * @brief Class that provides index of tensor for training
+ * @tparam T  Type of index
+ */
+template <typename T> class TrainingIndex
+{
+public:
+  /**
+   * @brief Construct TrainingOperationIndex object.
+   * @param index      The operation index
+   * @param is_forward Whether the tensor is forward tensor or not
+   */
+  TrainingIndex() : _index{T{}}, _is_forward{true}
+  {
+    // DO NOTHING
+  }
+
+  /**
+   * @brief Construct TrainingOperationIndex object.
+   * @tparam T     Type of index
+   * @param index      The operation index
+   * @param is_forward Whether the tensor is forward tensor or not
+   */
+  TrainingIndex(const T &index, bool is_forward) : _index{index}, _is_forward{is_forward}
+  {
+    // DO NOTHING
+  }
+
+public:
+  /**
+   * @brief Get index
+   *
+   * @return index
+   */
+  const T &index() const { return _index; }
+  /**
+   * @brief Get whether the tensor is forward tensor or not
+   *
+   * @return true if the tensor is forward tensor
+   */
+  bool is_forward() const { return _is_forward; }
+
+public:
+  /**
+   * @brief Check if the index is valid or not
+   *
+   * @return true if the index is valid, false otherwise
+   */
+  bool valid() const { return _index.valid(); }
+
+public:
+  /**
+   * @brief operator overloading function for `==`
+   *
+   * @return Whether two TrainingIndex are equal
+   */
+  bool operator==(const TrainingIndex &other) const
+  {
+    return (!_index.valid() && !other.index().valid()) ||
+           (_index == other.index() && _is_forward == other.is_forward());
+  }
+  /**
+   * @brief operator overloading function for `!=`
+   *
+   * @return Whether two TrainingIndex are differenct
+   */
+  bool operator!=(const TrainingIndex &other) const { return !(*this == other); }
+
+  /**
+   * @brief operator overloading function for `<`
+   *
+   * @return Whether this TrainingIndex is less than other TrainingIndex
+   */
+  bool operator<(const TrainingIndex &other) const
+  {
+    return std::hash<TrainingIndex<T>>{}(*this) < std::hash<TrainingIndex<T>>{}(other);
+  }
+
+private:
+  T _index;
+  bool _is_forward;
+};
+
+/**
+ * @brief Type that provides index of operation node for training
+ * @note TrainingOperationIndex can be index of a forwarding node if the member "_is_forward"
+ *       of TrainingIndex is true
+ *       TrainingOperationIndex can be index of a backwarding node if the membwr "_is_forward"
+ *       of TrainingIndex is false
+ */
+using TrainingOperationIndex = TrainingIndex<OperationIndex>;
+
+/**
+ * @brief Type that provides index of operand for training
+ * @note TrainingOperandIndex can be index of an operand used in forwarding if the member
+ *       "_is_forward" of TrainingIndex is true
+ *       TrainingOperandIndex can be index of an operand used in backwarding if the member
+ *       "_is_forward" of TrainingIndex is false
+ */
+using TrainingOperandIndex = TrainingIndex<OperandIndex>;
+
+inline std::ostream &operator<<(std::ostream &o, const TrainingOperationIndex &i)
+{
+  return operator<<(o, i.index());
+}
+
+inline std::ostream &operator<<(std::ostream &o, const TrainingOperandIndex &i)
+{
+  return operator<<(o, i.index());
+}
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+namespace std
+{
+
+/**
+ * @brief Structure that provides hash value of TrainingOperationIndex
+ */
+template <> struct hash<onert::ir::train::TrainingOperationIndex>
+{
+  size_t operator()(const onert::ir::train::TrainingOperationIndex &index) const noexcept
+  {
+    const auto &op_index = index.index();
+    const bool is_forward = index.is_forward();
+
+    assert(sizeof(op_index) <= 4);
+    assert((op_index.undefined() || op_index.value() < (1 << 16)) &&
+           "TrainingOperationIndex's hash creation error, operand_index is too big");
+    static_assert(
+      sizeof(size_t) >= sizeof(uint32_t),
+      "TrainingOperationIndex's hash creation error, size_t size is less than uint32_t");
+
+    return (static_cast<size_t>(op_index.value())) << 16 | static_cast<size_t>(is_forward);
+  }
+};
+
+} // namespace std
+
+namespace std
+{
+
+/**
+ * @brief Structure that provides hash value of TrainingOperandIndex
+ */
+template <> struct hash<onert::ir::train::TrainingOperandIndex>
+{
+  size_t operator()(const onert::ir::train::TrainingOperandIndex &index) const noexcept
+  {
+    const auto &operand_index = index.index();
+    const bool &is_forward = index.is_forward();
+
+    assert(sizeof(operand_index) <= 4);
+    assert((operand_index.undefined() || operand_index.value() < (1 << 16)) &&
+           "TrainingOperandIndex's hash creation error, operand_index is too big");
+    static_assert(sizeof(size_t) >= sizeof(uint32_t),
+                  "TrainingOperandIndex's hash creation error, size_t size is less than uint32_t");
+
+    return (static_cast<size_t>(operand_index.value())) << 16 | static_cast<size_t>(is_forward);
+  }
+};
+
+} // namespace std
+
+#endif // __ONERT_IR_TRAIN_INDEX_H__
diff --git a/runtime/onert/core/include/ir/train/LossCode.h b/runtime/onert/core/include/ir/train/LossCode.h
new file mode 100644 (file)
index 0000000..b500497
--- /dev/null
@@ -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.
+ */
+
+#ifndef __ONERT_IR_TRAIN_LOSS_CODE_H__
+#define __ONERT_IR_TRAIN_LOSS_CODE_H__
+
+#include <string>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+enum class LossCode
+{
+  Undefined,              //< Undefined
+  MeanSquaredError,       //< MeanSquaredError optimizer
+  CategoricalCrossentropy //< CategoricalCrossentropy optimizer
+};
+
+/**
+ * @brief Convert the optimizer code to the name
+ *
+ * @param opcode The optimizer code
+ * @return The name of the optimizer
+ */
+std::string toString(LossCode opcode);
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_LOSS_CODE_H__
diff --git a/runtime/onert/core/include/ir/train/LossInfo.h b/runtime/onert/core/include/ir/train/LossInfo.h
new file mode 100644 (file)
index 0000000..a5cc694
--- /dev/null
@@ -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 __ONERT_IR_TRAIN_LOSS_INFO_H__
+#define __ONERT_IR_TRAIN_LOSS_INFO_H__
+
+#include "LossCode.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+enum class LossReductionType
+{
+  Undefined,        //< Undefined
+  SumOverBatchSize, //< SumOverBatchSize loss reduction type
+  Sum,              //< Sum loss reduction type
+};
+
+struct CategoricalCrossentropyParam
+{
+  int32_t axis;
+  float label_smoothing;
+};
+
+struct LossInfo
+{
+  LossCode loss_code;
+  LossReductionType reduction_type;
+  union LossParam {
+    CategoricalCrossentropyParam cce;
+  } loss_param;
+
+  LossInfo()
+    : loss_code{LossCode::Undefined}, reduction_type{LossReductionType::Undefined},
+      loss_param{-1, 0.0f}
+  {
+  }
+};
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_LOSS_INFO_H__
index 56e752f..697c6b9 100644 (file)
 #ifndef __ONERT_IR_TRAIN_OPERATIONS_OPERATION_INCLUDE_H__
 #define __ONERT_IR_TRAIN_OPERATIONS_OPERATION_INCLUDE_H__
 
+#include "ir/train/operation/BinaryArithmetic.h"
 #include "ir/train/operation/Conv2D.h"
+#include "ir/train/operation/DepthwiseConv2D.h"
 #include "ir/train/operation/ElementwiseActivation.h"
 #include "ir/train/operation/FullyConnected.h"
 #include "ir/train/operation/Loss.h"
+#include "ir/train/operation/Pad.h"
 #include "ir/train/operation/Permute.h"
 #include "ir/train/operation/Pool2D.h"
+#include "ir/train/operation/Reduce.h"
 #include "ir/train/operation/Reshape.h"
 #include "ir/train/operation/Softmax.h"
 
index 14dc388..4b07980 100644 (file)
 #error Define OP before including this file
 #endif
 
+OP(BinaryArithmetic)
 OP(Conv2D)
+OP(DepthwiseConv2D)
 OP(ElementwiseActivation)
 OP(FullyConnected)
 OP(Loss)
+OP(Pad)
 OP(Permute)
 OP(Pool2D)
+OP(Reduce)
 OP(Reshape)
 OP(Softmax)
diff --git a/runtime/onert/core/include/ir/train/OptimizerCode.h b/runtime/onert/core/include/ir/train/OptimizerCode.h
new file mode 100644 (file)
index 0000000..d2a5b58
--- /dev/null
@@ -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_TRAIN_OPTIMIZER_CODE_H__
+#define __ONERT_IR_TRAIN_OPTIMIZER_CODE_H__
+
+#include <functional>
+#include <stdint.h>
+#include <string>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+enum class OptimizerCode
+{
+  Undefined, //< Undefined
+  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 train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPTIMIZER_CODE_H__
diff --git a/runtime/onert/core/include/ir/train/OptimizerInfo.h b/runtime/onert/core/include/ir/train/OptimizerInfo.h
new file mode 100644 (file)
index 0000000..a8b5adc
--- /dev/null
@@ -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_IR_TRAIN_OPTIMIZER_INFO_H__
+#define __ONERT_IR_TRAIN_OPTIMIZER_INFO_H__
+
+#include "OptimizerCode.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+struct OptimizerInfo
+{
+  OptimizerCode optim_code;
+  float learning_rate;
+  // TODO Add properties
+
+  OptimizerInfo() : optim_code{OptimizerCode::Undefined}, learning_rate{0.0f} {}
+};
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPTIMIZER_INFO_H__
index 90c49e2..1faf8c5 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "ir/Graph.h"
 #include "ir/train/ITrainableOperation.h"
+#include "ir/train/UseDefChains.h"
 
 namespace onert
 {
@@ -30,6 +31,7 @@ namespace ir
 namespace train
 {
 
+// TODO Add Phase enum
 class TrainableGraph : public IGraph
 {
 public:
@@ -84,21 +86,21 @@ public:
                                   std::unique_ptr<ITrainableOperation> &&operation);
 
   /**
-   * @brief Add a derivative to the graph with the given index and object
+   * @brief Add an operand for backwarding 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.
+   * If the given index is available, it succeeds. And @c bwd_operand is moved which invalidates
+   * the caller's pointer. If the given index is already taken, it fails. And @c bwd_operand 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
+   * @param[in] index       Index to be added
+   * @param[in] bwd_operand Backward operand to be added
    * @return OperandIndex @c index if successful, UNDEFINED otherwise
    */
-  OperandIndex addDerivative(OperandIndex index, std::unique_ptr<Operand> &&derivative);
+  OperandIndex addBackwardOperand(OperandIndex index, std::unique_ptr<Operand> &&bwd_operand);
 
 public:
   void changeShape(const OperandIndex &ind, const ir::Shape &new_shape) override;
-  void changeDerivativeShape(const OperandIndex &ind, const ir::Shape &new_shape);
+  void changeBackwardShape(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);
@@ -109,6 +111,9 @@ public:
                  std::unordered_map<std::string, IOIndex> name_to_input);
   void setOutputs(OperandIndexSequence outputs,
                   std::unordered_map<std::string, IOIndex> name_to_output);
+  void enableBackward(const OperationIndex &index);
+  void disableBackward(const OperationIndex &index);
+  void setTrainingUseDefs(const UseDefChains &training_defuses);
 
   // Accessors
 public:
@@ -119,21 +124,47 @@ public:
   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; }
+  const Operands &backward_operands() const { return _backward_operands; }
   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;
+  const UseDefChains &trainingUseDefs() const { return _training_defuses; }
+
+private:
+  void validateTopologicalOrder(std::vector<ir::OperationIndex> order, bool is_forward) const;
+  void validateForwardTopologicalOrder(const std::vector<ir::OperationIndex> &order) const;
+  void validateBackwardTopologicalOrder(const std::vector<ir::OperationIndex> &order) const;
+  void verifyTrainingUseDefs() const;
 
 public:
   std::vector<ir::OperationIndex> topolSortOperations() const;
-  // TODO Support topological sort for backwarding
+  std::vector<ir::OperationIndex> btopolSortOperations() const;
+  std::vector<ir::OperationIndex> essentialBackwardOrder() const;
+
+public:
+  /**
+   * @brief Truncate the backward order of operations in accordance with the alive condition
+   *        whether the corresponding operation has trainable parameters
+   * @param  backward_order  The order of operations in a backward graph
+   */
+  std::vector<ir::OperationIndex>
+  truncateBackwardOrder(const std::vector<ir::OperationIndex> &backward_order) const;
+  /**
+   * @brief Truncate the backward order of operations in accordance with the given alive condition.
+   * @param  backward_order  The order of operations in a backward graph
+   * @param  alive_cond The alive condition to stop the backward order
+   */
+  std::vector<ir::OperationIndex>
+  truncateBackwardOrder(std::vector<ir::OperationIndex> backward_order,
+                        std::function<bool(const ir::OperationIndex &)> truncating_cond) const;
 
 private:
   Graph _graph;
-  Operands _derivatives;
+  Operands _backward_operands;
+  UseDefChains _training_defuses;
 
   std::unordered_map<IOIndex, OperandIndex> _losses;
 };
diff --git a/runtime/onert/core/include/ir/train/TrainableOperation.h b/runtime/onert/core/include/ir/train/TrainableOperation.h
new file mode 100644 (file)
index 0000000..f5146c9
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_H__
+#define __ONERT_IR_TRAIN_TRAINABLE_OPERATION_H__
+
+#include "ITrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+class TrainableOperation : public ITrainableOperation
+{
+public:
+  virtual ~TrainableOperation() = default;
+
+public:
+  void disableWeightsUpdate() final { _trainable = false; }
+
+  void enableWeightsUpdate() final { _trainable = true; }
+
+  virtual bool isWeightsUpdateEnabled() const final { return _trainable; }
+
+  void enableBackward() final { _required_for_backward = true; }
+  void disableBackward() final { _required_for_backward = false; }
+  virtual bool isRequiredForBackward() const final { return _required_for_backward; }
+
+private:
+  bool _trainable = false;
+  bool _required_for_backward = false;
+};
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_TRAINABLE_OPERATION_H__
diff --git a/runtime/onert/core/include/ir/train/TrainingInfo.h b/runtime/onert/core/include/ir/train/TrainingInfo.h
new file mode 100644 (file)
index 0000000..9c8d770
--- /dev/null
@@ -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_IR_TRAIN_TRAINING_INFO_H__
+#define __ONERT_IR_TRAIN_TRAINING_INFO_H__
+
+#include "ir/Index.h"
+#include "ir/train/OptimizerCode.h"
+#include "ir/train/OptimizerInfo.h"
+#include "ir/train/LossInfo.h"
+
+#include <set>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+class TrainingInfo final
+{
+public:
+  TrainingInfo()
+    : _version{0}, _loss_info(), _optimizer_info(), _batch_size(0), _training_step{0},
+      _trainable_ops{}
+  {
+  }
+  TrainingInfo(const TrainingInfo &) = default;
+  TrainingInfo(TrainingInfo &&) = default;
+  TrainingInfo &operator=(const TrainingInfo &) = default;
+  TrainingInfo &operator=(TrainingInfo &&) = default;
+  ~TrainingInfo() = default;
+
+  // getter
+  uint32_t version() const { return _version; }
+  const LossInfo &lossInfo() const { return _loss_info; }
+  const OptimizerInfo &optimizerInfo() const { return _optimizer_info; }
+  uint32_t batchSize() const { return _batch_size; }
+  const uint32_t &trainingStep() const { return _training_step; }
+  const std::set<OperationIndex> &getTrainableOps() const { return _trainable_ops; }
+
+  // setter
+  void setVersion(const uint32_t version) { _version = version; }
+  void setBatchSize(const uint32_t batch_size) { _batch_size = batch_size; }
+  void setLossInfo(const LossInfo &loss_info) { _loss_info = loss_info; }
+  void setOptimizerInfo(const OptimizerInfo &optimizer_info) { _optimizer_info = optimizer_info; }
+  uint32_t &trainingStep() { return _training_step; }
+  void setTrainableOps(const std::set<OperationIndex> &trainable_ops)
+  {
+    _trainable_ops = trainable_ops;
+  }
+
+  bool isValid() const;
+
+private:
+  uint32_t _version;
+  LossInfo _loss_info;
+  OptimizerInfo _optimizer_info;
+  uint32_t _batch_size;
+  uint32_t _training_step;
+  std::set<OperationIndex> _trainable_ops;
+};
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_TRAINING_INFO_H__
diff --git a/runtime/onert/core/include/ir/train/UseDefChain.h b/runtime/onert/core/include/ir/train/UseDefChain.h
new file mode 100644 (file)
index 0000000..aee1bec
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_USEDEFCHAIN_H__
+#define __ONERT_IR_TRAIN_USEDEFCHAIN_H__
+
+#include "ir/Operand.h"
+#include "ir/train/Index.h"
+
+#include <set>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+class UseDefChain
+{
+public:
+  explicit UseDefChain(const Operand &operand) : _operand{operand}
+  {
+    // DO NOTHING
+  }
+  explicit UseDefChain(const UseDefChain &other)
+    : _operand{other._operand}, _uses{other._uses}, _defs{other._defs}
+  {
+    // DO NOTHING
+  }
+  UseDefChain(UseDefChain &&other)
+    : _operand{other._operand}, _uses{std::move(other._uses)}, _defs{std::move(other._defs)}
+  {
+    // DO NOTHING
+  }
+  ~UseDefChain() = default;
+
+public:
+  UseDefChain &operator=(const UseDefChain &other) = delete;
+  UseDefChain &operator=(UseDefChain &&other) = delete;
+
+public:
+  bool operator==(const UseDefChain &other) const;
+
+public:
+  const std::set<TrainingOperationIndex> &getTrainingUses() const { return _uses; }
+  const std::set<TrainingOperationIndex> &getTrainingDefs() const { return _defs; }
+  void insertTrainingUse(const TrainingOperationIndex &idx);
+  void removeTrainingUse(const TrainingOperationIndex &idx);
+  void insertTrainingDef(const TrainingOperationIndex &idx);
+  void removeTrainingDef(const TrainingOperationIndex &idx);
+  void clearTrainingUseDefs();
+
+public:
+  const Operand &operand() const { return _operand; };
+
+private:
+  const Operand &_operand;
+
+private:
+  std::set<TrainingOperationIndex> _uses;
+  // NOTE Allowing multiple defs is a workaround to support training of branching models.
+  //      Back-prop tensors corresponding to forwarding tensors that are used in multiple nodes
+  //      have multiple defs. Those back-prop tensors would be accumulated during backwarding,
+  //      but current TrainableGraph cannot represent accumulated back-prop tensors.
+  std::set<TrainingOperationIndex> _defs;
+};
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_USEDEFCHAIN_H__
diff --git a/runtime/onert/core/include/ir/train/UseDefChains.h b/runtime/onert/core/include/ir/train/UseDefChains.h
new file mode 100644 (file)
index 0000000..65a2d58
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_USEDEFCHAINS_H__
+#define __ONERT_IR_TRAIN_USEDEFCHAINS_H__
+
+#include "ir/train/UseDefChain.h"
+#include "ir/train/Index.h"
+
+#include <unordered_map>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+using UseDefChains = std::unordered_map<TrainingOperandIndex, UseDefChain>;
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_USEDEFCHAINS_H__
diff --git a/runtime/onert/core/include/ir/train/operation/BinaryArithmetic.h b/runtime/onert/core/include/ir/train/operation/BinaryArithmetic.h
new file mode 100644 (file)
index 0000000..4ace373
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_BINARY_ARITHMETIC_H__
+#define __ONERT_IR_TRAIN_OPERATION_BINARY_ARITHMETIC_H__
+
+#include "ir/operation/BinaryArithmetic.h"
+#include "ir/train/TrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class BinaryArithmetic : public ir::operation::BinaryArithmetic, public TrainableOperation
+{
+private:
+  using OperationType = ir::operation::BinaryArithmetic;
+
+public:
+  BinaryArithmetic(const OperationType &operation);
+
+public:
+  std::unique_ptr<ITrainableOperation> clone() const override;
+  void accept(OperationVisitor &v) const override;
+  void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return false; }
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_BINARY_ARITHMETIC_H__
index b896892..63e24ea 100644 (file)
@@ -18,7 +18,7 @@
 #define __ONERT_IR_TRAIN_OPERATION_CONV2D_H__
 
 #include "ir/operation/Conv2D.h"
-#include "ir/train/ITrainableOperation.h"
+#include "ir/train/TrainableOperation.h"
 
 namespace onert
 {
@@ -29,7 +29,7 @@ namespace train
 namespace operation
 {
 
-class Conv2D : public ir::operation::Conv2D, public ITrainableOperation
+class Conv2D : public ir::operation::Conv2D, public TrainableOperation
 {
 private:
   using OperationType = ir::operation::Conv2D;
@@ -41,6 +41,7 @@ public:
   std::unique_ptr<ITrainableOperation> clone() const override;
   void accept(OperationVisitor &v) const override;
   void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return true; }
 };
 
 } // namespace operation
diff --git a/runtime/onert/core/include/ir/train/operation/DepthwiseConv2D.h b/runtime/onert/core/include/ir/train/operation/DepthwiseConv2D.h
new file mode 100644 (file)
index 0000000..a74634a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_DEPTHWISE_CONV2D_H__
+#define __ONERT_IR_TRAIN_OPERATION_DEPTHWISE_CONV2D_H__
+
+#include "ir/operation/DepthwiseConv2D.h"
+#include "ir/train/TrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class DepthwiseConv2D : public ir::operation::DepthwiseConv2D, public TrainableOperation
+{
+private:
+  using OperationType = ir::operation::DepthwiseConv2D;
+
+public:
+  DepthwiseConv2D(const OperationType &operation);
+
+public:
+  std::unique_ptr<ITrainableOperation> clone() const override;
+  void accept(OperationVisitor &v) const override;
+  void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return true; }
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_DEPTHWISE_CONV2D_H__
index 97ab54d..4524cb1 100644 (file)
@@ -18,7 +18,7 @@
 #define __ONERT_IR_TRAIN_OPERATION_ELEMENTWISE_ACTIVATION_H__
 
 #include "ir/operation/ElementwiseActivation.h"
-#include "ir/train/ITrainableOperation.h"
+#include "ir/train/TrainableOperation.h"
 
 namespace onert
 {
@@ -29,8 +29,7 @@ namespace train
 namespace operation
 {
 
-class ElementwiseActivation : public ir::operation::ElementwiseActivation,
-                              public ITrainableOperation
+class ElementwiseActivation : public ir::operation::ElementwiseActivation, public TrainableOperation
 {
 private:
   using OperationType = ir::operation::ElementwiseActivation;
@@ -42,6 +41,7 @@ public:
   std::unique_ptr<ITrainableOperation> clone() const override;
   void accept(OperationVisitor &v) const override;
   void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return false; }
 };
 
 } // namespace operation
index bede58d..12d1b22 100644 (file)
@@ -18,7 +18,7 @@
 #define __ONERT_IR_TRAIN_OPERATION_FULLYCONNECTED_H__
 
 #include "ir/operation/FullyConnected.h"
-#include "ir/train/ITrainableOperation.h"
+#include "ir/train/TrainableOperation.h"
 
 namespace onert
 {
@@ -29,7 +29,7 @@ namespace train
 namespace operation
 {
 
-class FullyConnected : public ir::operation::FullyConnected, public ITrainableOperation
+class FullyConnected : public ir::operation::FullyConnected, public TrainableOperation
 {
 private:
   using OperationType = ir::operation::FullyConnected;
@@ -41,6 +41,7 @@ public:
   std::unique_ptr<ITrainableOperation> clone() const override;
   void accept(OperationVisitor &v) const override;
   void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return true; }
 };
 
 } // namespace operation
index c7cc421..35b0b55 100644 (file)
 #define __ONERT_IR_TRAIN_OPERATION_LOSS_H__
 
 #include "ir/operation/Loss.h"
-#include "ir/train/ITrainableOperation.h"
+#include "ir/train/TrainableOperation.h"
+
+#include "ir/train/LossCode.h"
+#include "ir/train/LossInfo.h"
 
 namespace onert
 {
@@ -29,18 +32,26 @@ namespace train
 namespace operation
 {
 
-class Loss : public ir::operation::Loss, public ITrainableOperation
+class Loss : public ir::operation::Loss, public TrainableOperation
 {
 private:
   using OperationType = ir::operation::Loss;
 
 public:
-  Loss(const OperationType &operation);
+  Loss(const OperationType &operation, const LossInfo &info);
 
 public:
   std::unique_ptr<ITrainableOperation> clone() const override;
   void accept(OperationVisitor &v) const override;
   void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return false; }
+  std::string name() const override { return toString(_param.loss_code) + toString(opcode()); };
+
+public:
+  const LossInfo &param() const { return _param; }
+
+private:
+  LossInfo _param;
 };
 
 } // namespace operation
diff --git a/runtime/onert/core/include/ir/train/operation/Pad.h b/runtime/onert/core/include/ir/train/operation/Pad.h
new file mode 100644 (file)
index 0000000..63b6a65
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_PAD_H__
+#define __ONERT_IR_TRAIN_OPERATION_PAD_H__
+
+#include "ir/operation/Pad.h"
+#include "ir/train/TrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class Pad : public ir::operation::Pad, public TrainableOperation
+{
+private:
+  using OperationType = ir::operation::Pad;
+
+public:
+  Pad(const OperationType &operation);
+
+public:
+  std::unique_ptr<ITrainableOperation> clone() const override;
+  void accept(OperationVisitor &v) const override;
+  void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return false; }
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_PAD_H__
index e652b13..9b64b7e 100644 (file)
@@ -18,7 +18,7 @@
 #define __ONERT_IR_TRAIN_OPERATION_PERMUTE_H__
 
 #include "ir/operation/Permute.h"
-#include "ir/train/ITrainableOperation.h"
+#include "ir/train/TrainableOperation.h"
 
 namespace onert
 {
@@ -29,7 +29,7 @@ namespace train
 namespace operation
 {
 
-class Permute : public ir::operation::Permute, public ITrainableOperation
+class Permute : public ir::operation::Permute, public TrainableOperation
 {
 private:
   using OperationType = ir::operation::Permute;
@@ -41,6 +41,7 @@ public:
   std::unique_ptr<ITrainableOperation> clone() const override;
   void accept(OperationVisitor &v) const override;
   void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return false; }
 };
 
 } // namespace operation
index 0249970..7e6bc38 100644 (file)
@@ -18,7 +18,7 @@
 #define __ONERT_IR_TRAIN_OPERATION_POOL2D_H__
 
 #include "ir/operation/Pool2D.h"
-#include "ir/train/ITrainableOperation.h"
+#include "ir/train/TrainableOperation.h"
 
 namespace onert
 {
@@ -29,7 +29,7 @@ namespace train
 namespace operation
 {
 
-class Pool2D : public ir::operation::Pool2D, public ITrainableOperation
+class Pool2D : public ir::operation::Pool2D, public TrainableOperation
 {
 private:
   using OperationType = ir::operation::Pool2D;
@@ -41,6 +41,7 @@ public:
   std::unique_ptr<ITrainableOperation> clone() const override;
   void accept(OperationVisitor &v) const override;
   void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return false; }
 };
 
 } // namespace operation
diff --git a/runtime/onert/core/include/ir/train/operation/Reduce.h b/runtime/onert/core/include/ir/train/operation/Reduce.h
new file mode 100644 (file)
index 0000000..bce8129
--- /dev/null
@@ -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_REDUCE_H__
+#define __ONERT_IR_TRAIN_OPERATION_REDUCE_H__
+
+#include "ir/operation/Reduce.h"
+#include "ir/train/TrainableOperation.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+class Reduce : public ir::operation::Reduce, public TrainableOperation
+{
+private:
+  using OperationType = ir::operation::Reduce;
+
+public:
+  Reduce(const OperationType &operation);
+
+public:
+  std::unique_ptr<ITrainableOperation> clone() const override;
+  void accept(OperationVisitor &v) const override;
+  void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return false; }
+};
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_OPERATION_REDUCE_H__
index 1efd62c..6068e00 100644 (file)
@@ -18,7 +18,7 @@
 #define __ONERT_IR_TRAIN_OPERATION_RESHAPE_H__
 
 #include "ir/operation/Reshape.h"
-#include "ir/train/ITrainableOperation.h"
+#include "ir/train/TrainableOperation.h"
 
 namespace onert
 {
@@ -29,7 +29,7 @@ namespace train
 namespace operation
 {
 
-class Reshape : public ir::operation::Reshape, public ITrainableOperation
+class Reshape : public ir::operation::Reshape, public TrainableOperation
 {
 private:
   using OperationType = ir::operation::Reshape;
@@ -41,6 +41,7 @@ public:
   std::unique_ptr<ITrainableOperation> clone() const override;
   void accept(OperationVisitor &v) const override;
   void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return false; }
 };
 
 } // namespace operation
index b12e6ab..6452e74 100644 (file)
@@ -18,7 +18,7 @@
 #define __ONERT_IR_TRAIN_OPERATION_SOFTMAX_H__
 
 #include "ir/operation/Softmax.h"
-#include "ir/train/ITrainableOperation.h"
+#include "ir/train/TrainableOperation.h"
 
 namespace onert
 {
@@ -29,7 +29,7 @@ namespace train
 namespace operation
 {
 
-class Softmax : public ir::operation::Softmax, public ITrainableOperation
+class Softmax : public ir::operation::Softmax, public TrainableOperation
 {
 private:
   using OperationType = ir::operation::Softmax;
@@ -41,6 +41,7 @@ public:
   std::unique_ptr<ITrainableOperation> clone() const override;
   void accept(OperationVisitor &v) const override;
   void accept(TrainableOperationVisitor &v) const override;
+  bool hasTrainableParameter() const override { return false; }
 };
 
 } // namespace operation
index 7cda0ec..a291dc0 100644 (file)
@@ -17,7 +17,7 @@
 #ifndef __ONERT_IR_TRAIN_OPERATION_UNTRAINABLE_OPERATION_H__
 #define __ONERT_IR_TRAIN_OPERATION_UNTRAINABLE_OPERATION_H__
 
-#include "ir/train/ITrainableOperation.h"
+#include "ir/train/TrainableOperation.h"
 
 #include "ir/OperationVisitor.h"
 #include "ir/train/TrainableOperationVisitor.h"
@@ -37,7 +37,7 @@ namespace operation
 // 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
+class UntrainableOperation : public OperationType, public TrainableOperation
 {
 public:
   UntrainableOperation(const OperationType &operation) : OperationType{operation} {}
@@ -53,6 +53,7 @@ public:
   {
     throw std::runtime_error(OperationType::name() + "operation is not trainable yet");
   }
+  bool hasTrainableParameter() const override { return false; }
 };
 
 } // namespace operation
diff --git a/runtime/onert/core/include/loader/CircleLoader.h b/runtime/onert/core/include/loader/CircleLoader.h
new file mode 100644 (file)
index 0000000..a65fa09
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_LOADER_CIRCLE_LOADER_H__
+#define __ONERT_LOADER_CIRCLE_LOADER_H__
+
+#include "ir/Graph.h"
+
+#include <memory>
+
+namespace onert
+{
+namespace loader
+{
+std::unique_ptr<ir::Model> loadCircleModel(const std::string &filename);
+std::unique_ptr<ir::Model> loadCircleModel(uint8_t *buffer, size_t size);
+} // namespace loader
+} // namespace onert
+
+#endif // __ONERT_LOADER_CIRCLE_LOADER_H__
diff --git a/runtime/onert/core/include/loader/ILoader.h b/runtime/onert/core/include/loader/ILoader.h
new file mode 100644 (file)
index 0000000..ec7ab32
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_LOADER_ILOADER_H__
+#define __ONERT_LOADER_ILOADER_H__
+
+#include "ir/Model.h"
+
+#include <memory>
+#include <string>
+
+namespace onert
+{
+namespace loader
+{
+
+class ILoader
+{
+public:
+  virtual ~ILoader() = default;
+
+public:
+  /**
+   * @brief     Load model from file
+   * @param[in] file_path File path to load model from
+   * @return    Loaded model
+   */
+  virtual std::unique_ptr<ir::Model> loadFromFile(const std::string &file_path) = 0;
+};
+
+} // namespace loader
+} // namespace onert
+
+#endif // __ONERT_LOADER_ILOADER_H__
diff --git a/runtime/onert/core/include/loader/ModelLoader.h b/runtime/onert/core/include/loader/ModelLoader.h
new file mode 100644 (file)
index 0000000..f00ec0a
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_LOADER_MODEL_LOADER_H__
+#define __ONERT_LOADER_MODEL_LOADER_H__
+
+#include "ir/Model.h"
+
+#include <memory>
+
+namespace onert
+{
+namespace loader
+{
+
+/**
+ * @brief     Create custom loader and load model from file
+ * @param[in] filename  File path to load model from
+ * @param[in] type      Type of model to load
+ * @return    Loaded model.
+ *
+ * @note  Throw exception if failed to load model
+ */
+std::unique_ptr<ir::Model> loadModel(const std::string &filename, const std::string &type);
+
+} // namespace loader
+} // namespace onert
+
+#endif // __ONERT_LOADER_MODEL_LOADER_H__
diff --git a/runtime/onert/core/include/loader/TFLiteLoader.h b/runtime/onert/core/include/loader/TFLiteLoader.h
new file mode 100644 (file)
index 0000000..7e5d8a8
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_LOADER_TFLITE_LOADER_H__
+#define __ONERT_LOADER_TFLITE_LOADER_H__
+
+#include "ir/Graph.h"
+
+#include <memory>
+
+namespace onert
+{
+namespace loader
+{
+
+std::unique_ptr<ir::Model> loadTFLiteModel(const std::string &filename);
+
+} // namespace loader
+} // namespace onert
+
+#endif // __ONERT_LOADER_TFLITE_LOADER_H__
diff --git a/runtime/onert/core/include/loader/TrainInfoLoader.h b/runtime/onert/core/include/loader/TrainInfoLoader.h
new file mode 100644 (file)
index 0000000..2687f0a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_LOADER_CIRCLE_TRAININFO_LOADER_H__
+#define __ONERT_LOADER_CIRCLE_TRAININFO_LOADER_H__
+
+#include "ir/train/TrainingInfo.h"
+
+#include <memory>
+
+namespace onert
+{
+namespace loader
+{
+
+// TODO change this line to use inline variable after C++17
+extern const char *const TRAININFO_METADATA_NAME;
+
+std::unique_ptr<ir::train::TrainingInfo> loadTrainingInfo(const uint8_t *buffer, const size_t size);
+
+} // namespace loader
+} // namespace onert
+
+#endif // __ONERT_LOADER_CIRCLE_TRAININFO_LOADER_H__
diff --git a/runtime/onert/core/include/odc/CodegenManager.h b/runtime/onert/core/include/odc/CodegenManager.h
new file mode 100644 (file)
index 0000000..947750b
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CODEGEN_MANAGER_H__
+#define __ONERT_ODC_CODEGEN_MANAGER_H__
+
+#include <string>
+
+namespace onert
+{
+namespace odc
+{
+
+enum class CodegenPreference
+{
+  CODEGEN_PREF_DEFAULT,
+  // TODO Support Traffic and Cycle codegen preference
+  CODEGEN_PREF_PERFORMANCE_FIRST,
+  CODEGEN_PREF_MEMORY_FIRST,
+  CODEGEN_PREF_COMPILE_TIME_FIRST,
+};
+
+class CodegenManager
+{
+public:
+  // Non-copyable
+  CodegenManager() = default;
+  CodegenManager(CodegenManager const &) = delete;
+  CodegenManager &operator=(CodegenManager const &) = delete;
+
+public:
+  /**
+   * @brief Set model path to export compiled model
+   *
+   * @param model_path  Model path to export compiled model
+   */
+  void exportModelPath(const std::string &model_path) { _export_model_path = model_path; }
+
+  /**
+   * @brief Get model path to export compiled model
+   *
+   * @return Model path to export compiled model
+   */
+  const std::string &exportModelPath() const { return _export_model_path; }
+
+  /**
+   * @brief Execute code generator
+   *
+   * @param model[in]   Model to be compiled
+   * @param target[in]  Target backend name
+   *                    This target string will be used to find a backend library.
+   *                    The name of target backend library should follow the following rules:
+   *                      'lib' + {backend extension} + '-gen' + {lib extension}
+   *                    And the target string should be a name except 'lib' and {lib extension}.
+   *                    For example, if the backend extension is 'aaa', the backend library name
+   *                    should be 'libaaa-gen.so', and the target string should be 'aaa-gen'.
+   * @param pref        @c CodegenPreference Codegen preference
+   */
+  bool codegen(const std::string &model_path, const char *target, CodegenPreference pref);
+
+private:
+  std::string _export_model_path = "";
+};
+
+} // namespace odc
+} // namespace onert
+
+#endif // __ONERT_ODC_CODEGEN_MANAGER_H__
diff --git a/runtime/onert/core/include/odc/ICodegen.h b/runtime/onert/core/include/odc/ICodegen.h
new file mode 100644 (file)
index 0000000..04cf836
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_ICODEGEN_H__
+#define __ONERT_ODC_ICODEGEN_H__
+
+// NOTE
+// Backend code generator must implement the following two functions.
+// #ifdef __cplusplus
+// extern "C"
+// {
+// #endif
+
+// ICodegen *create_codegen();
+// void destroy_codegen(ICodegen *codegen);
+
+// #ifdef __cplusplus
+// }
+// #endif
+
+namespace onert
+{
+namespace odc
+{
+
+class ICodegen
+{
+public:
+  virtual ~ICodegen() = default;
+
+  virtual int codegen(const char *in, const char *out) const = 0;
+};
+
+} // namespace odc
+} // namespace onert
+
+#endif // __ONERT_ODC_ICODEGEN_H__
index d698d9e..3491d21 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef __ONERT_ODC_IQUANTIZER_H__
 #define __ONERT_ODC_IQUANTIZER_H__
 
+#include "odc/QuantizeType.h"
+
 namespace onert
 {
 namespace odc
@@ -27,7 +29,7 @@ class IQuantizer
 public:
   virtual ~IQuantizer() = default;
 
-  virtual int quantize(const char *in, const char *out, bool is_q16) = 0;
+  virtual int quantize(const char *in, const char *out, QuantizeType qtype) = 0;
 };
 
 } // namespace odc
index a749c0e..257b86b 100644 (file)
@@ -18,6 +18,7 @@
 #define __ONERT_ODC_QUANTIZE_MANAGER_H__
 
 #include "IQuantizer.h"
+#include "QuantizeType.h"
 
 #include <functional>
 #include <string>
@@ -33,8 +34,7 @@ class QuantizeManager
 {
 public:
   // Non-copyable
-  QuantizeManager() = delete;
-  QuantizeManager(const std::string &model_path) : _model_path(model_path) {}
+  QuantizeManager() = default;
   QuantizeManager(QuantizeManager const &) = delete;
   QuantizeManager &operator=(QuantizeManager const &) = delete;
 
@@ -56,23 +56,22 @@ public:
   /**
    * @brief Set quantize type
    *
-   * @param is_q16  true if q16, false if q8
+   * @param qtype quantization type
    *
    * @todo  Support more general quantize type
    */
-  void quantizeType(bool is_q16) { _is_q16 = is_q16; }
+  void quantizeType(QuantizeType qtype) { _qtype = qtype; }
 
   /**
-   * @brief  Quantize model
-   *
-   * @return  true if success, otherwise false
+   * @brief     Quantize model
+   * @param[in] model_path  Model path to quantize
+   * @return    @c true if success, otherwise @c false
    */
-  bool quantize();
+  bool quantize(const std::string &model_path);
 
 private:
-  std::string _model_path = "";
   std::string _export_model_path = "";
-  bool _is_q16 = false;
+  QuantizeType _qtype = ODC_QTYPE_NOT_SET;
 };
 
 } // namespace odc
diff --git a/runtime/onert/core/include/odc/QuantizeType.h b/runtime/onert/core/include/odc/QuantizeType.h
new file mode 100644 (file)
index 0000000..10aa730
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_TYPE_H__
+#define __ONERT_ODC_QUANTIZE_TYPE_H__
+
+namespace onert
+{
+namespace odc
+{
+
+enum QuantizeType
+{
+  /** default value: type not set */
+  ODC_QTYPE_NOT_SET,
+  /** asymmetric quantization with a scale and zero point */
+  ODC_QTYPE_U8_ASYM,
+  /** symmetric quantization with a scale only */
+  ODC_QTYPE_I16_SYM,
+  /** weight-only int8 symmetric quantization */
+  ODC_QTYPE_WO_I8_SYM,
+  /** weight-only int16 symmetric quantization */
+  ODC_QTYPE_WO_I16_SYM,
+};
+
+} // namespace odc
+} // namespace onert
+
+#endif // __ONERT_ODC_QUANTIZE_TYPE_H__
index d3e37ce..aaa4c04 100644 (file)
@@ -30,12 +30,13 @@ CONFIG(ACL_LAYOUT              , std::string  , "none")
 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(TRACING_MODE            , bool         , "0")
+CONFIG(MINMAX_DUMP             , bool         , "0")
 CONFIG(FP16_ENABLE             , bool         , "0")
 CONFIG(RUY_THREADS             , int          , "-1")
 CONFIG(XNNPACK_THREADS         , int          , "-1")
 CONFIG(USE_MMAPED_DATA         , bool         , "0")
+CONFIG(WORKSPACE_DIR           , std::string  , ".")
 
 // Auto-generate all operations
 
index 49c5f4c..36c1834 100644 (file)
@@ -138,6 +138,8 @@ public:
    */
   T value() const { return _index; }
 
+  bool operator<(const Index &I) const { return value() < I.value(); }
+
   /**
    * @brief Return max index value
    *
index 2245f84..62fd77a 100644 (file)
@@ -36,6 +36,7 @@ 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(); }
+  auto size() const { return _minmax_map.size(); }
 
 private:
   std::unordered_map<N, MinMaxPair, Hash> _minmax_map;
index 077a4c2..ceac533 100644 (file)
@@ -46,7 +46,7 @@ public:
    * @param[in] args Arguments for creating Operand object
    * @return Created index that is associated to the object if successful, Undefined index otherwise
    */
-  template <class... Args> Index emplace(Args &&... args)
+  template <class... Args> Index emplace(Args &&...args)
   {
     auto index = generateIndex();
     if (!index.valid())
index d859378..8f1aa98 100644 (file)
@@ -87,8 +87,8 @@ ir::Shape inferPoolShape(const ir::Shape &in_shape, const ir::operation::Pool2D:
 
 template <typename T> ir::Shape inferRangeShape(T start_val, T limit_val, T delta_val);
 
-ir::Shape inferReshapeShape(const int32_t *shape_buf, const int32_t shape_num_elements,
-                            const size_t total_num_elements);
+ir::Shape inferReshapeShape(const ir::Shape &input_shape, const int32_t *shape_buf,
+                            const int32_t shape_num_elements);
 
 ir::Shape inferReduceShape(const ir::Shape &input_shape, const std::vector<int> &axes,
                            bool keep_dims);
index fe255f8..2e55828 100644 (file)
@@ -83,4 +83,19 @@ inline std::string decorated_name(const char *input)
       METHOD;                                \
   } while (0)
 
+#define MEASURE_TIME_START(name) \
+  do                             \
+  {                              \
+  auto beg_##name = std::chrono::steady_clock::now()
+
+#define MEASURE_TIME_END(name)                                                      \
+  auto end_##name = std::chrono::steady_clock::now();                               \
+  auto dur_##name =                                                                 \
+    std::chrono::duration_cast<std::chrono::microseconds>(end_##name - beg_##name); \
+  if (::onert::util::logging::ctx.enabled())                                        \
+    std::cout << ::onert::util::logging::decorated_name(__func__) << #name          \
+              << " time = " << dur_##name.count() << std::endl;                     \
+  }                                                                                 \
+  while (0)
+
 #endif // __ONERT_UTIL_LOGGING_H__
index cec34e7..066ba00 100644 (file)
@@ -25,5 +25,20 @@ namespace backend
 // With this as a key function, `dynamic_cast` works across dl
 IPortableTensor::~IPortableTensor() {}
 
+size_t IPortableTensor::calcOffset(const ir::Coordinates &coords) const
+{
+  auto shape = _info.shape();
+  size_t rank = shape.rank();
+  rank = rank == 0 ? 1 : rank;
+  size_t offset = 0;
+  for (size_t i = 0; i < rank; ++i)
+  {
+    auto dim = shape.rank() == 0 ? 1 : shape.dim(i);
+    offset = offset * dim + coords[i];
+  }
+  offset *= sizeOfDataType(data_type());
+  return offset;
+}
+
 } // namespace backend
 } // namespace onert
index 05fd9cc..4814456 100644 (file)
@@ -40,13 +40,14 @@ MemoryManager::MemoryManager(const std::string planner_id)
   // DO NOTHING
 }
 
-basic::IMemoryPlanner *MemoryManager::createMemoryPlanner()
+basic::IMemoryPlanner<ir::OperandIndex> *MemoryManager::createMemoryPlanner()
 {
   auto planner_id = util::getConfigString(util::config::CPU_MEMORY_PLANNER);
   return basic::MemoryPlannerFactory::get().create(planner_id);
 }
 
-basic::IMemoryPlanner *MemoryManager::createMemoryPlanner(const std::string planner_id)
+basic::IMemoryPlanner<ir::OperandIndex> *
+MemoryManager::createMemoryPlanner(const std::string planner_id)
 {
   return basic::MemoryPlannerFactory::get().create(planner_id);
 }
index 661d0b5..03e9775 100644 (file)
@@ -41,7 +41,7 @@ namespace basic
 /**
  * @brief Class to plan memory by bump way
  */
-class BumpPlanner : public IMemoryPlanner
+class BumpPlanner : public IMemoryPlanner<ir::OperandIndex>
 {
 public:
   /**
@@ -74,7 +74,7 @@ private:
 /**
  * @brief Class to plan memory by firstfit way
  */
-class FirstFitPlanner : public IMemoryPlanner
+class FirstFitPlanner : public IMemoryPlanner<ir::OperandIndex>
 {
 public:
   /**
@@ -109,7 +109,7 @@ private:
 /**
  * @brief Class to plan memory by Weighted Interval Color algorithm
  */
-class WICPlanner : public IMemoryPlanner
+class WICPlanner : public IMemoryPlanner<ir::OperandIndex>
 {
 public:
   WICPlanner();
index e126353..7338f87 100644 (file)
@@ -31,7 +31,7 @@ MemoryPlannerFactory &MemoryPlannerFactory::get()
   return instance;
 }
 
-IMemoryPlanner *MemoryPlannerFactory::create(const std::string &key)
+IMemoryPlanner<ir::OperandIndex> *MemoryPlannerFactory::create(const std::string &key)
 {
   if (key == "FirstFit")
   {
index fe32f4c..b4173f7 100644 (file)
@@ -18,6 +18,7 @@
 #define __ONERT_BACKEND_BASIC_MEMORY_PLANNER_FACTORY_H__
 
 #include "backend/basic/IMemoryPlanner.h"
+#include "MemoryPlanner.h"
 
 #include <string>
 
@@ -37,7 +38,7 @@ private:
   MemoryPlannerFactory() = default;
 
 public:
-  IMemoryPlanner *create(const std::string &key);
+  IMemoryPlanner<ir::OperandIndex> *create(const std::string &key);
 };
 
 } // namespace basic
index 71cde4c..04dbc4a 100644 (file)
@@ -29,8 +29,8 @@ namespace basic
 
 StaticTensorManager::StaticTensorManager(const std::shared_ptr<TensorRegistry> &reg,
                                          DynamicTensorManager *dynamic_tensor_manager)
-  : _nonconst_mgr{new MemoryManager()}, _tensors{reg}, _dynamic_tensor_manager{
-                                                         dynamic_tensor_manager}
+  : _nonconst_mgr{new MemoryManager()}, _tensors{reg},
+    _dynamic_tensor_manager{dynamic_tensor_manager}
 {
   // DO NOTHING
 }
@@ -38,8 +38,8 @@ StaticTensorManager::StaticTensorManager(const std::shared_ptr<TensorRegistry> &
 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}
+  : _nonconst_mgr{new MemoryManager(planner_id)}, _tensors{reg},
+    _dynamic_tensor_manager{dynamic_tensor_manager}
 {
   // DO NOTHING
 }
index de1cff4..7f33d4d 100644 (file)
@@ -28,21 +28,6 @@ namespace basic
 
 Tensor::~Tensor() {}
 
-size_t Tensor::calcOffset(const ir::Coordinates &coords) const
-{
-  auto shape = getShape();
-  size_t rank = shape.rank();
-  rank = rank == 0 ? 1 : rank;
-  size_t offset = 0;
-  for (size_t i = 0; i < rank; ++i)
-  {
-    auto dim = shape.rank() == 0 ? 1 : shape.dim(i);
-    offset = offset * dim + coords[i];
-  }
-  offset *= sizeOfDataType(data_type());
-  return offset;
-}
-
 void Tensor::setShape(const ir::Shape &new_shape) { _info.shape(new_shape); }
 
 bool Tensor::applyShape(const ir::Shape &new_shape)
@@ -84,8 +69,6 @@ bool Tensor::applyShape(const ir::Shape &new_shape)
   return true;
 }
 
-ir::Shape Tensor::getShape() const { return _info.shape(); }
-
 void Tensor::deallocBuffer()
 {
   if (_allocator)
index f9d8387..4912af1 100644 (file)
@@ -62,7 +62,7 @@ void TensorBuilder::registerTensorInfo(const ir::OperandIndex &ind, const ir::Op
 void TensorBuilder::notifyFirstUse(const ir::OperandIndex &ind)
 {
   assert(_tensor_info_map.find(ind) != _tensor_info_map.end());
-  const auto tensor_info = _tensor_info_map.at(ind);
+  const auto &tensor_info = _tensor_info_map.at(ind);
 
   if (!_tensor_reg->getNativeTensor(ind)->is_dynamic())
   {
index c05494a..85d3895 100644 (file)
 #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>
 
@@ -42,11 +38,7 @@ namespace backend
 namespace builtin
 {
 
-class Backend : public ::onert::backend::Backend
-#ifdef ONERT_TRAIN
-  ,
-                public backend::train::ITrainableBackend
-#endif // ONERT_TRAIN
+class Backend : public ::onert::backend::Backend, public backend::train::ITrainableBackend
 {
 public:
   Backend() : _config{std::make_shared<Config>()} {}
@@ -82,7 +74,6 @@ public:
     return context;
   }
 
-#ifdef ONERT_TRAIN
   std::unique_ptr<backend::train::TrainableBackendContext>
   newContext(backend::train::TrainableContextData &&tdata) const override
   {
@@ -96,7 +87,6 @@ public:
       std::make_shared<train::KernelGenerator>(tgraph, tr, context->external_context());
     return context;
   }
-#endif // ONERT_TRAIN
 
 private:
   std::shared_ptr<IConfig> _config;
index 573617e..a66e97b 100644 (file)
@@ -35,7 +35,7 @@ FunctionMap BackendContext::genKernels()
   for (auto &&op_ind : _data.op_order)
   {
     auto fn_seq = kernel_gen->generate(op_ind);
-    ret.emplace_back(op_ind, std::move(fn_seq));
+    ret.emplace(op_ind, std::move(fn_seq));
   }
 
   basic::initConsts(*this);
index f7f4a69..e157a12 100644 (file)
@@ -30,25 +30,29 @@ namespace builtin
 IOTensor::~IOTensor() {}
 
 IOTensor::IOTensor(const ir::OperandInfo &info, ir::Layout layout)
-  : IPortableTensor{info}, _orig_info{info}, _orig_layout{layout}
+  : IPortableTensor{info}, _tensor{nullptr},
+    _orig{std::make_unique<UserTensor>(info, layout, (uint8_t *)nullptr, 0)}
 {
-  setUserTensor(nullptr, 0);
+  _tensor = _orig.get();
 }
 
 void IOTensor::setTensor(IPortableTensor *tensor)
 {
   assert(tensor);
   assert(tensor != this);
-  // TODO Handle when layout was changed
-  assert(tensor->layout() == _orig_layout); // Changing layout is not considered yet
-  _user_tensor.reset();
+  assert(tensor->layout() == _orig->layout()); // Changing layout is not considered yet
   _tensor = tensor;
-}
-
-void IOTensor::setUserTensor(uint8_t *buffer, size_t size)
-{
-  _user_tensor = std::make_unique<UserTensor>(_orig_info, _orig_layout, buffer, size);
-  _tensor = _user_tensor.get();
+  if (_info.shape() != tensor->getShape())
+  {
+    _info.shape(tensor->getShape());
+
+    // If input tensor shape is updated, other effective buffers use dynamic memory manager.
+    // Dynamic memory manager deallocate allcoated memory after each execution.
+    // So we should remain input tensor as dynamic if we mark it dynamic at least once.
+    // If dynamic memory manager maintains allocated memory after execution is finished,
+    // we may need to reset it as static for each setTensor call.
+    _info.setDynamic();
+  }
 }
 
 } // namespace builtin
index d94ed0b..3d684e0 100644 (file)
@@ -30,13 +30,21 @@ namespace builtin
 /**
  * @brief Tensor object that indirects to the tensor it is pointing to.
  *
- * A model I/O tensor could be two types.
+ * A executor's I/O tensor could be two types.
  *
- * 1. @c UserTensor, if it is the primary graph
- * 2. Any other derivative of @c IPortableTensor from another backend, otherwise
+ * 1. @c UserTensor, if it is the primary graph (package's input/output)
+ * 2. Any other derivative of @c IPortableTensor from another executor, otherwise
  *
  * To support these, this object indirects everything to the actual tensor pointer.
- * Exceptionally if it is UserTensor, this class creates and manages it.
+ *
+ * IOTensor is derived from IPortableTensor, and it also have "_info" field.
+ * "_info" field is accessed by IPortableTensor's getter method.
+ *
+ * It assumes that IOTensor's info is always same with actual tensor's info except shape.
+ * setTensor() updates IOTensor's info's shape to actual tensor shape.
+ * Actual tensor's info should not be updated directly after setTensor() call until
+ * executor's execution is finished, instead it is allowed to update actual tensor's info
+ * indirectly by IOTensor's setter methods.
  */
 class IOTensor : public IPortableTensor
 {
@@ -46,48 +54,57 @@ public:
 
 public:
   void setTensor(IPortableTensor *tensor);
-  void setUserTensor(uint8_t *buffer, size_t size);
-  const ir::OperandInfo &orig_info() const { return _orig_info; }
-  ir::Layout orig_layout() const { return _orig_layout; }
 
 public:
   uint8_t *buffer() const override { return _tensor->buffer(); }
-  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_dynamic() const override
+  ir::Layout layout() const override { return _orig->layout(); }
+  void set_dynamic() override
   {
-    return _is_dynamic || _orig_info.isDynamic() || (_tensor && _tensor->is_dynamic());
+    _info.setDynamic();
+    _tensor->set_dynamic();
   }
-  void set_dynamic() override { _is_dynamic = true; }
-  ir::Shape getShape() const override { return _tensor->getShape(); }
   void setShape(const ir::Shape &shape) override
   {
-    // Workaround for IPortableTensor holds _info as its member
     _info.shape(shape);
     _tensor->setShape(shape);
   }
-  bool is_constant() const override { return _tensor->is_constant(); }
+
+  /*
+   * Changes tensor shape and allocate memory since its shape was changed
+   * perhaps by nnfw_set_input_tensorinfo()
+   *
+   * Cases are:
+   * 1) static operand -> nnfw_set_input_tensorinfo() -> execute() -> execute()
+   *                                                 (a)          (b)
+   *
+   * at (a), operand is static, tensor is static - memory dealloc is not needed
+   *   (DynamicTensorManager cannot dealloc memory allocated by StaticTensorManager)
+   * at (b), operand is static, tensor is dynamic - memory dealloc is needed
+   *
+   * 2) dynamic operand -> nnfw_set_input_tensorinfo() -> execute() -> execute()
+   *                                                  (a)          (b)
+   *
+   * at (a), operand is dynamic, tensor is dynamic - memory dealloc is not needed
+   *                                       since it has not been allocated yet
+   * at (b), operand is dynamic, tensor is dynamic - memory dealloc is needed
+   */
   bool applyShape(const ir::Shape &shape) override
   {
-    // Workaround for IPortableTensor holds _info as its member
-    _info.shape(shape);
-    return _tensor->applyShape(shape);
+    auto return_val = _tensor->applyShape(shape);
+    if (return_val)
+    {
+      _info.shape(shape);
+      _info.setDynamic();
+    }
+    return return_val;
   }
 
-public:
-  void setShapeOfIPortableTensor(const ir::Shape &shape) { _info.shape(shape); }
-
 private:
-  const ir::OperandInfo _orig_info;
-  const ir::Layout _orig_layout;
-  bool _is_dynamic{false};
-  IPortableTensor *_tensor{nullptr};        //< The actual tensor that is indirected
-  std::unique_ptr<UserTensor> _user_tensor; //< If it is a user tensor, it is managed by this object
+  IPortableTensor *_tensor{nullptr}; //< The actual tensor that is indirected
+  // "_orig" has UserTensor type original tensor's info with nullptr buffer and layout,
+  // and "_tensor" points to "_user_tensor".
+  // After 1st setTensor(tensor) call, "_tensor" is updated to actual tensor
+  std::unique_ptr<UserTensor> _orig; //< If it is a user tensor, it is managed by this object
 };
 
 } // namespace builtin
index fefae40..a2f7af3 100644 (file)
@@ -57,7 +57,7 @@ void TensorBuilder::notifyFirstUse(const ir::OperandIndex &ind)
   if (_tensor_info_map.find(ind) == _tensor_info_map.end()) // Do not proceed for user tensors
     return;
 
-  const auto tensor_info = _tensor_info_map.at(ind);
+  const auto &tensor_info = _tensor_info_map.at(ind);
 
   if (!nativeOwnTensorAt(ind)->is_dynamic())
   {
index f0b00b9..e260de2 100644 (file)
@@ -26,23 +26,11 @@ namespace backend
 namespace builtin
 {
 
-size_t UserTensor::calcOffset(const ir::Coordinates &coords) const
-{
-  size_t rank = getShape().rank();
-  size_t offset = 0;
-  for (size_t i = 0; i < rank; ++i)
-  {
-    offset = offset * getShape().dim(i) + coords[i];
-  }
-  offset *= sizeOfDataType(data_type());
-  return offset;
-}
-
 bool UserTensor::applyShape(const ir::Shape &new_shape)
 {
   // User tensors cannot be reallocated.
   auto new_size = new_shape.num_elements() * ir::sizeOfDataType(data_type());
-  if (total_size() < new_size)
+  if (_size < new_size)
     throw InsufficientBufferSizeException{"User given buffer size is too small."};
   setShape(new_shape);
   return true;
index 0d0ed73..b7f6ce0 100644 (file)
@@ -39,39 +39,21 @@ class UserTensor : public IPortableTensor
 {
 public:
   UserTensor(const ir::OperandInfo &info, ir::Layout layout, uint8_t *buffer, size_t size)
-    : IPortableTensor{info}, _layout{layout}, _buffer{buffer}, _size{size}, _dynamic{false}
+    : IPortableTensor{info}, _layout{layout}, _buffer{buffer}, _size{size}
   {
   }
 
-  UserTensor(const ir::OperandInfo &info, ir::Layout layout) : UserTensor{info, layout, nullptr, 0}
-  {
-  }
-
-public:
-  void setBuffer(uint8_t *buffer, size_t size)
-  {
-    _buffer = buffer;
-    _size = size;
-  }
-
 public:
   uint8_t *buffer() const override { return _buffer; }
-  size_t total_size() const override { return _size; }
-  size_t calcOffset(const ir::Coordinates &coords) const override;
   ir::Layout layout() const override { return _layout; }
-  ir::DataType data_type() const override { return _info.typeInfo().type(); }
-  bool is_dynamic() const override { return _dynamic; }
-  void set_dynamic() override { _dynamic = true; }
-  ir::Shape getShape() const override { return _info.shape(); }
+  void set_dynamic() override { _info.setDynamic(); }
   void setShape(const ir::Shape &new_shape) override { _info.shape(new_shape); }
-  bool is_constant() const override { return false; }
   bool applyShape(const ir::Shape &) override;
 
 private:
   ir::Layout _layout;
   uint8_t *_buffer;
   size_t _size;
-  bool _dynamic;
 };
 
 } // namespace builtin
index 51bc5a8..bf8c5fc 100644 (file)
@@ -69,7 +69,8 @@ void IfLayer::run()
     subg_exec = _executors->at(_model_index, _else_subg_index);
   }
 
-  subg_exec->execute(_input_tensors, _output_tensors);
+  subg_exec->execute(_input_tensors, _output_tensors,
+                     _executors->entryExecutor()->currentOptions());
   VERBOSE(If) << "Return from $" << (cond_result ? _then_subg_index : _else_subg_index)
               << std::endl;
 }
index 8f639ce..a9b8f27 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <backend/IPortableTensor.h>
 #include <exec/IExecutors.h>
+#include <exec/IFunction.h>
 #include "../ExternalContext.h"
 
 namespace onert
index 227e324..cf25f54 100644 (file)
@@ -72,8 +72,8 @@ private:
     PermuteWorkerTask(const uint8_t *src_buffer, uint8_t *dst_buffer, uint32_t src_start_offset,
                       uint32_t dst_start_offset, size_t size)
       : _src_buffer{src_buffer}, _dst_buffer{dst_buffer}, _src_start_offset{src_start_offset},
-        _dst_start_offset{dst_start_offset}, _src_strides{0}, _dst_strides{0},
-        _loop_shape{1}, _size{size}, _src_layout{}, _dst_layout{}, _is_permutation{false}
+        _dst_start_offset{dst_start_offset}, _src_strides{0}, _dst_strides{0}, _loop_shape{1},
+        _size{size}, _src_layout{}, _dst_layout{}, _is_permutation{false}
     {
       // DO NOTHING
     }
index 8b00db4..06e5722 100644 (file)
@@ -41,8 +41,8 @@ WhileLayer::WhileLayer(const std::vector<backend::IPortableTensor *> input_tenso
                        const std::shared_ptr<ExternalContext> &external_context)
   : _cond_subg_index{cond_subg_index}, _body_subg_index{body_subg_index},
     _input_tensors{input_tensors}, _output_tensors{output_tensors}, _executors{executors},
-    _model_index{model_index}, _dyn_memory_manager{dyn_memory_manager}, _external_context{
-                                                                          external_context}
+    _model_index{model_index}, _dyn_memory_manager{dyn_memory_manager},
+    _external_context{external_context}
 {
   // At this point, executors may not have executors of cond subg and body subg
 }
@@ -63,10 +63,9 @@ void WhileLayer::run()
   auto body_exec = _executors->at(_model_index, _body_subg_index);
 
   // Need a temp tensor to hold the cond subgraph output
-  assert(cond_exec->getOutputTensors().size() == 1);
+  assert(cond_exec->outputSize() == 1);
   auto cond_output_tensor = [&]() {
-    auto cond_output = cond_exec->getOutputTensors().at(0);
-    auto tensor = std::make_unique<Tensor>(cond_output->orig_info(), cond_output->orig_layout(),
+    auto tensor = std::make_unique<Tensor>(cond_exec->outputInfo(0), cond_exec->outputLayout(0),
                                            _dyn_memory_manager);
     tensor->set_dynamic();
     tensor->setBuffer(_dyn_memory_manager->allocate(tensor.get(), tensor->total_size()));
@@ -74,7 +73,8 @@ void WhileLayer::run()
   }();
 
   VERBOSE(While) << "Call to $" << _cond_subg_index << " (cond)" << std::endl;
-  cond_exec->execute(_input_tensors, {cond_output_tensor.get()});
+  const auto &options = _executors->entryExecutor()->currentOptions();
+  cond_exec->execute(_input_tensors, {cond_output_tensor.get()}, options);
   VERBOSE(While) << "Return from $" << _cond_subg_index << std::endl;
 
   auto getResultCond = [](backend::ITensor *tensor) -> bool {
@@ -96,9 +96,9 @@ 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 (uint32_t i = 0; i < body_exec->outputSize(); i++)
   {
-    auto tensor = std::make_unique<Tensor>(io_tensor->orig_info(), io_tensor->orig_layout(),
+    auto tensor = std::make_unique<Tensor>(body_exec->outputInfo(i), body_exec->outputLayout(i),
                                            _dyn_memory_manager);
     tensor->set_dynamic();
     tensor->setBuffer(_dyn_memory_manager->allocate(tensor.get(), tensor->total_size()));
@@ -111,20 +111,20 @@ void WhileLayer::run()
 
   const auto body_execute_with_op_inputs = [&]() {
     VERBOSE(While) << "Call to $" << _body_subg_index << " (body)" << std::endl;
-    body_exec->execute(_input_tensors, temp_outputs);
+    body_exec->execute(_input_tensors, temp_outputs, options);
     VERBOSE(While) << "Return from $" << _body_subg_index << std::endl;
   };
 
   const auto body_execute_with_body_outputs = [&]() {
     VERBOSE(While) << "Call to $" << _body_subg_index << " (body)" << std::endl;
-    body_exec->execute(_output_tensors, temp_outputs);
+    body_exec->execute(_output_tensors, temp_outputs, options);
     VERBOSE(While) << "Return from $" << _body_subg_index << std::endl;
   };
 
   std::function<void()> body_execute = body_execute_with_op_inputs;
   const auto cond_execute = [&]() {
     VERBOSE(While) << "Call to $" << _cond_subg_index << " (cond)" << std::endl;
-    cond_exec->execute(_output_tensors, {cond_output_tensor.get()});
+    cond_exec->execute(_output_tensors, {cond_output_tensor.get()}, options);
     VERBOSE(While) << "Return from $" << _cond_subg_index << std::endl;
   };
 
index fa9131f..69483ea 100644 (file)
@@ -50,7 +50,7 @@ backend::train::FunctionMap BackendContext::genKernels()
   for (auto &&op_ind : _tdata->op_order)
   {
     auto tn_seq = kernel_gen->generate(op_ind);
-    ret.emplace_back(op_ind, std::move(tn_seq));
+    ret.emplace(op_ind, std::move(tn_seq));
   }
 
   trainable_graph()->operands().iterate(
index 6f8ce4c..4782756 100644 (file)
@@ -41,8 +41,8 @@ public:
                  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}
+      kernel_gen{kernel_gen}, _external_context(new ExternalContext),
+      _tensor_builder{tensor_builder}
   {
   }
 
index 6f2c0a3..32032de 100644 (file)
@@ -59,20 +59,26 @@ void KernelGenerator::visit(const ir::train::operation::Permute &node)
   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);
+  std::vector<ITensor *> output_back_prop_tensors;
+  std::vector<ITensor *> input_back_prop_tensors;
+
+  auto input_back_prop_tensor = getBackPropTensor(input_index);
+  auto output_back_prop_tensor = getBackPropTensor(output_index);
+  output_back_prop_tensors.emplace_back(output_back_prop_tensor);
+  input_back_prop_tensors.emplace_back(input_back_prop_tensor);
+
+  // NOTE The output buffers of IOTensors are not essential for training. If there
+  //      is no output buffer provided by the user, permute is not performed.
+  bool ignore_forward_in_training = false;
+  for (const auto dst_tensor : output_tensors)
+  {
+    if (dst_tensor->buffer() == nullptr || dst_tensor->total_size() == 0)
+      ignore_forward_in_training = true;
+  }
 
-  // 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);
+  auto fn = std::make_unique<kernel::PermuteLayer>(
+    input_tensors, output_tensors, input_back_prop_tensors, output_back_prop_tensors,
+    ignore_forward_in_training, _external_context);
 
   _return_fn = std::move(fn);
 }
@@ -85,10 +91,10 @@ backend::ITensor *KernelGenerator::getTensor(const ir::OperandIndex &index)
   return ret;
 }
 
-backend::ITensor *KernelGenerator::getDerivativeTensor(const ir::OperandIndex &index)
+backend::ITensor *KernelGenerator::getBackPropTensor(const ir::OperandIndex &index)
 {
-  // Get derivative Tensor from all tensor registries (for Permute op)
-  auto ret = _tensor_registries.getDerivativeITensor(index);
+  // Get back propagation Tensor from all tensor registries (for Permute op)
+  auto ret = _tensor_registries.getBackPropITensor(index);
   return ret;
 }
 
index d8781c0..162955b 100644 (file)
@@ -58,7 +58,7 @@ private:
 
 private:
   backend::ITensor *getTensor(const ir::OperandIndex &index);
-  backend::ITensor *getDerivativeTensor(const ir::OperandIndex &index);
+  backend::ITensor *getBackPropTensor(const ir::OperandIndex &index);
 
 private:
   std::shared_ptr<TensorRegistry> _tensor_reg;
index 611407b..baf4279 100644 (file)
@@ -29,7 +29,7 @@ namespace train
 {
 
 using TrainableTensor = basic::train::TrainableTensor;
-using DerivativeTensor = basic::Tensor;
+using BackPropTensor = basic::Tensor;
 using GradientTensor = basic::Tensor;
 
 } // namespace train
index c48e5fe..7c8166b 100644 (file)
@@ -33,7 +33,7 @@ namespace train
 {
 
 using BaseTensorRegistry =
-  backend::train::PortableTensorRegistryTemplate<Tensor, TrainableTensor, DerivativeTensor,
+  backend::train::PortableTensorRegistryTemplate<Tensor, TrainableTensor, BackPropTensor,
                                                  GradientTensor>;
 
 class TensorRegistry : public backend::train::ITensorRegistry
@@ -73,9 +73,9 @@ public:
     return nullptr;
   }
 
-  ITensor *getDerivativeITensor(const ir::OperandIndex &index) override
+  ITensor *getBackPropITensor(const ir::OperandIndex &index) override
   {
-    return _base_reg->getDerivativeTensor(index);
+    return _base_reg->getBackPropTensor(index);
   }
 
   ITensor *getGradientITensor(const ir::OperandIndex &index) override
@@ -83,9 +83,9 @@ public:
     return _base_reg->getGradientTensor(index);
   }
 
-  DerivativeTensor *getDerivativeTensor(const ir::OperandIndex &index)
+  BackPropTensor *getBackPropTensor(const ir::OperandIndex &index)
   {
-    return _base_reg->getDerivativeTensor(index);
+    return _base_reg->getBackPropTensor(index);
   }
 
   bool setMigrantTensor(const ir::OperandIndex &index, IPortableTensor *tensor) override
@@ -96,9 +96,17 @@ public:
     return true;
   }
 
-  void setDerivativeTensor(const ir::OperandIndex &index, std::unique_ptr<DerivativeTensor> tensor)
+  void iterateTrainableTensors(
+    const std::function<void(const ir::OperandIndex &, const backend::train::ITrainableTensor *)> &)
+    const override
   {
-    _base_reg->setDerivativeTensor(index, std::move(tensor));
+    // DO NOTHING
+    // Builtin tensor registry does not have trainable tensor.
+  }
+
+  void setBackPropTensor(const ir::OperandIndex &index, std::unique_ptr<BackPropTensor> tensor)
+  {
+    _base_reg->setBackPropTensor(index, std::move(tensor));
   }
 
   void setGradientTensor(const ir::OperandIndex &index, std::unique_ptr<GradientTensor> tensor)
index 929092d..dce7482 100644 (file)
@@ -31,15 +31,16 @@ 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,
+                           const std::vector<ITensor *> &input_back_prop_tensors,
+                           const std::vector<ITensor *> &output_back_prop_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},
+    _input_back_prop_tensors{input_back_prop_tensors},
+    _output_back_prop_tensors{output_back_prop_tensors},
     _ignore_forward_in_training{ignore_forward_in_training}
 {
-  assert(input_deriv_tensors.size() == output_deriv_tensors.size());
+  assert(input_back_prop_tensors.size() == output_back_prop_tensors.size());
   assert(src_tensors.size() == dst_tensors.size());
 }
 
@@ -47,12 +48,12 @@ void PermuteLayer::optimize()
 {
   builtin::kernel::PermuteLayer::optimize();
 
-  // TODO Calculate offsets of derivative tensors if necessary
+  // TODO Calculate offsets of back propagation tensors if necessary
 }
 
-void PermuteLayer::forward(bool training)
+void PermuteLayer::forward(bool)
 {
-  if (training && _ignore_forward_in_training)
+  if (_ignore_forward_in_training)
     return;
 
   builtin::kernel::PermuteLayer::run();
@@ -60,20 +61,21 @@ void PermuteLayer::forward(bool training)
 
 void PermuteLayer::backward()
 {
-  for (uint32_t i = 0; i < _output_deriv_tensors.size(); ++i)
+  for (uint32_t i = 0; i < _output_back_prop_tensors.size(); ++i)
   {
-    auto src_deriv = _output_deriv_tensors.at(i);
-    auto dst_deriv = _input_deriv_tensors.at(i);
+    auto src_back_prop = _output_back_prop_tensors.at(i);
+    auto dst_back_prop = _input_back_prop_tensors.at(i);
 
-    // NOTE The derivative tensors corresponding to inputs/outputs of model are nullptr
+    // NOTE The back propagation tensors corresponding to inputs/outputs of model are nullptr
     //      because permuting those tensors is meaningless
-    if (src_deriv && dst_deriv)
+    if (src_back_prop && dst_back_prop)
     {
-      const auto rank = src_deriv->getShape().rank();
+      const auto rank = src_back_prop->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);
+      exec::IPermuteFunction::permute(src_back_prop, dst_back_prop, rank, output_offsets,
+                                      input_offsets);
     }
   }
 }
index de8063a..1dc221b 100644 (file)
@@ -36,8 +36,9 @@ class PermuteLayer : public builtin::kernel::PermuteLayer, public exec::train::I
 {
 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::vector<ITensor *> &input_back_prop_tensors,
+               const std::vector<ITensor *> &output_back_prop_tensors,
+               bool ignore_forward_in_training,
                const std::shared_ptr<ExternalContext> &external_context);
 
   void optimize() override;
@@ -46,8 +47,8 @@ public:
   void backward() override;
 
 private:
-  std::vector<ITensor *> _input_deriv_tensors;
-  std::vector<ITensor *> _output_deriv_tensors;
+  std::vector<ITensor *> _input_back_prop_tensors;
+  std::vector<ITensor *> _output_back_prop_tensors;
   bool _ignore_forward_in_training;
 };
 
index ba621bb..63667a0 100644 (file)
@@ -38,15 +38,14 @@ namespace onert
 namespace compiler
 {
 
-Compiler::Compiler(const std::shared_ptr<ir::Model> &model, CompilerOptions &copt)
-  : _model{model}, _options{&copt}
+Compiler::Compiler(const std::shared_ptr<ir::Model> &model, CompilerOptions *copts)
+  : _model{model}, _options{copts}
 {
   // DO NOTHING
 }
 
-Compiler::Compiler(const std::shared_ptr<ir::NNPkg> &nnpkg,
-                   std::vector<std::unique_ptr<CompilerOptions>> &copts)
-  : _model{nnpkg->primary_model()}, _options{copts[0].get()}
+Compiler::Compiler(const std::shared_ptr<ir::NNPkg> &nnpkg, CompilerOptions *copts)
+  : _model{nnpkg->primary_model()}, _options{copts}
 {
   // Use for single model only
   assert(nnpkg->model_count() == 1);
@@ -71,12 +70,6 @@ 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.");
@@ -119,8 +112,7 @@ std::shared_ptr<CompilerArtifact> Compiler::compile(void)
       // Lower: Assign backend
       lowered_subgs[subg_index] = std::make_unique<compiler::LoweredGraph>(subg, *_options);
       // Set tracing_ctx for copied graph
-      if (tracing_ctx != nullptr)
-        tracing_ctx->setSubgraphIndex(&(lowered_subgs[subg_index]->graph()), subg_index.value());
+      tracing_ctx->setSubgraphIndex(&(lowered_subgs[subg_index]->graph()), subg_index.value());
     });
   }
 
index aeb0876..3e1209a 100644 (file)
 #include "compiler/CompilerFactory.h"
 
 #include "MultiModelCompiler.h"
-#ifdef ONERT_TRAIN
 #include "train/TrainingCompiler.h"
-#endif // ONERT_TRAIN
-
 #include "compiler/Compiler.h"
 
 namespace onert
@@ -34,18 +31,13 @@ CompilerFactory &CompilerFactory::get()
   return singleton;
 }
 
-std::unique_ptr<ICompiler>
-CompilerFactory::create(const std::shared_ptr<ir::NNPkg> &nnpkg,
-                        std::vector<std::unique_ptr<CompilerOptions>> &copts,
-                        const compiler::train::TrainingInfo *training_info)
+std::unique_ptr<ICompiler> CompilerFactory::create(const std::shared_ptr<ir::NNPkg> &nnpkg,
+                                                   CompilerOptions *copts,
+                                                   const ir::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)
index 830d9dd..c5aee19 100644 (file)
@@ -64,6 +64,9 @@ void ManualSchedulerOptions::setBackendMap(const std::string &str)
     }
 
     auto key_val = nnfw::misc::split(key_val_str, '=');
+    if (key_val.size() != 2)
+      throw std::runtime_error{"Invalid key-value pair"};
+
     const auto &key_str = key_val.at(0);
     const auto &val = key_val.at(1);
     auto key = static_cast<uint32_t>(std::stoi(key_str));
@@ -75,13 +78,12 @@ 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);
   o->he_scheduler = util::getConfigBool(util::config::USE_SCHEDULER);
   o->he_profiling_mode = util::getConfigBool(util::config::PROFILING_MODE);
   o->fp16_enable = util::getConfigBool(util::config::FP16_ENABLE);
+  o->workspace_dir = util::getConfigString(util::config::WORKSPACE_DIR);
   {
     // Backend for all
     auto &ms_options = o->manual_scheduler_options;
@@ -129,7 +131,6 @@ void CompilerOptions::verboseOptions()
   VERBOSE(Compiler) << std::boolalpha << "==== Compiler Options ====" << std::endl;
   VERBOSE(Compiler) << "backend_list             : "
                     << nnfw::misc::join(backend_list.begin(), backend_list.end(), "/") << std::endl;
-  VERBOSE(Compiler) << "trace_filepath           : " << trace_filepath << std::endl;
   VERBOSE(Compiler) << "graph_dump_level         : " << graph_dump_level << std::endl;
   VERBOSE(Compiler) << "executor                 : " << executor << std::endl;
   VERBOSE(Compiler) << "manual backend_for_all   : " << manual_scheduler_options.backend_for_all
index 6a08524..eff3f5a 100644 (file)
 #include "../backend/builtin/BackendContext.h"
 #include "../backend/builtin/Config.h"
 #include "../backend/builtin/UserTensor.h"
+#include "../backend/builtin/train/BackendContext.h"
 #include "../dumper/text/GraphDumper.h"
 #include "../exec/DataflowExecutor.h"
 #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 "../exec/train/TrainableExecutor.h"
 #include "../ir/OperationCloner.h"
 
 #include <backend/IPortableTensor.h>
+#include <backend/train/TrainableBackendContext.h>
+#include <backend/train/ITrainableBackend.h>
 #include <compiler/BackendManager.h>
 #include <compiler/ExecutionBuilder.h>
 #include <util/TracingCtx.h>
 #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
@@ -129,7 +123,6 @@ void initializeSubgraphIOTensors(compiler::ILoweredGraph &lowered_graph,
   }
 }
 
-#ifdef ONERT_TRAIN
 void initializeSubgraphIOTensors(compiler::ILoweredGraph &lowered_graph,
                                  const backend::train::TrainableBackendContexts &backend_contexts,
                                  const ir::OperandIndexSequence &indices)
@@ -159,25 +152,21 @@ void initializeSubgraphIOTensors(compiler::ILoweredGraph &lowered_graph,
     builtin_tensor_reg->setNativeIOTensor(ind, std::move(tensor));
   }
 }
-#endif // ONERT_TRAIN
 
 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();
-
   std::unordered_map<const backend::Backend *, backend::ContextData> context_data_map;
 
   // Generate partial graphs for each backend
-  for (auto &&backend : backend_manager.getAll())
-  {
+  auto init_context_data = [&](const backend::Backend *backend) {
     auto &data = context_data_map[backend];
     auto graph = std::make_unique<ir::Graph>();
     graph->setLayout(lgraph.graph().layout());
     data.graph = std::move(graph);
-  }
+  };
 
   auto &whole_graph = lgraph.graph();
   // Separate operands into partial graphs
@@ -188,6 +177,9 @@ createBackendContexts(compiler::ILoweredGraph &lgraph, bool linear_executor,
       return;
     const auto &def_factor = def_factors.getOnlyElement();
     const auto backend = def_factor.backend();
+    if (context_data_map.find(backend) == context_data_map.end())
+      init_context_data(backend);
+
     auto &partial_graph = *context_data_map[backend].graph;
     auto &operand_layouts = context_data_map[backend].operand_layouts;
     assert(operand_layouts.find(operand_ind) == operand_layouts.end());
@@ -206,6 +198,9 @@ createBackendContexts(compiler::ILoweredGraph &lgraph, bool linear_executor,
     [&](const ir::OperationIndex &op_ind, const ir::IOperation &operation) {
       auto &op_li = lgraph.lower_info().operation;
       auto backend = op_li.at(op_ind).backend();
+      if (context_data_map.find(backend) == context_data_map.end())
+        init_context_data(backend);
+
       auto &partial_graph = *context_data_map[backend].graph;
       auto &external_operands = context_data_map[backend].external_operands;
       auto &operand_layouts = context_data_map[backend].operand_layouts;
@@ -258,6 +253,8 @@ createBackendContexts(compiler::ILoweredGraph &lgraph, bool linear_executor,
       if (whole_graph.getOutputs().contains(ind) || operand.getUses().size() == 0)
         data.graph->addOutput(ind);
     });
+    VERBOSE(ExecutorFactory) << "createBackendContexts: partial graph for backend="
+                             << backend->config()->id() << std::endl;
     dumper::text::dumpGraph(*data.graph);
 
     std::copy_if(whole_op_order.begin(), whole_op_order.end(), std::back_inserter(data.op_order),
@@ -504,17 +501,13 @@ ExecutorFactory::createLinearExecutor(std::unique_ptr<compiler::LoweredGraph> lo
                                        order,
                                        tracing_ctx};
 
-  if (!options->trace_filepath.empty())
+  if (!options->workspace_dir.empty())
   {
-    std::unique_ptr<exec::IExecutionObserver> ctp =
-      std::make_unique<exec::TracingObserver>(options->trace_filepath, exec->graph(), tracing_ctx);
-    exec->addObserver(std::move(ctp));
+    exec->addObserver(
+      std::make_unique<exec::TracingObserver>(options->workspace_dir, exec->graph(), tracing_ctx));
+    exec->addObserver(std::make_unique<exec::MinMaxRecorder>(options->workspace_dir, exec->graph(),
+                                                             exec->getBackendContexts()));
   }
-#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;
 }
@@ -598,29 +591,27 @@ ExecutorFactory::createDataflowExecutor(std::unique_ptr<compiler::LoweredGraph>
     exec = dataflow_exec;
   }
 
-  if (!options->trace_filepath.empty())
+  if (!options->workspace_dir.empty())
   {
-    std::unique_ptr<exec::IExecutionObserver> ctp =
-      std::make_unique<exec::TracingObserver>(options->trace_filepath, exec->graph(), tracing_ctx);
-    exec->addObserver(std::move(ctp));
+    exec->addObserver(
+      std::make_unique<exec::TracingObserver>(options->workspace_dir, exec->graph(), tracing_ctx));
   }
 
   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)
+                        const ir::train::TrainingInfo &training_info)
 {
   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);
+  return createTrainableExecutor(std::move(lowered_graph), executors, args, training_info);
 }
 
 void ExecutorFactory::prepareMigrantTensors(
@@ -654,7 +645,7 @@ void ExecutorFactory::prepareMigrantTensors(
 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 ir::train::TrainingInfo &training_info)
 {
   const auto options = args.options;
   const auto tracing_ctx = args.tracing_ctx;
@@ -697,11 +688,11 @@ exec::IExecutor *ExecutorFactory::createTrainableExecutor(
       });
     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))
+      if (orig_tgraph.backward_operands().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));
+        const auto &bwd_operand = orig_tgraph.backward_operands().at(index);
+        auto new_bwd_operand = std::make_unique<ir::Operand>(bwd_operand);
+        auto gen_index = tgraph->addBackwardOperand(index, std::move(new_bwd_operand));
         UNUSED_RELEASE(gen_index);
         assert(gen_index == index);
       }
@@ -723,20 +714,17 @@ exec::IExecutor *ExecutorFactory::createTrainableExecutor(
     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;
+    tdata.optim_info = training_info.optimizerInfo();
 
     // 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 &)
+    const auto backend = pair.first;
+    const auto tbackend = dynamic_cast<const backend::train::ITrainableBackend *>(backend);
+    if (!tbackend)
     {
       throw std::runtime_error("ExecutorFactory: Invalid backend - TrainableExecutor does not "
                                "support non-trainble backends");
     }
+    tbackend_contexts.emplace(backend, tbackend->newContext(std::move(tdata)));
   }
   base_backend_contexts.clear();
 
@@ -747,10 +735,16 @@ exec::IExecutor *ExecutorFactory::createTrainableExecutor(
     (lowered_graph->graph().getInputs() + lowered_graph->graph().getOutputs()) |
       ir::Remove::DUPLICATED | ir::Remove::UNDEFINED);
 
-  // linearize
+  // linearize for forwarding
   auto order = Linear::linearize(*lowered_graph);
+  VERBOSE(ExecutorFactory) << "Linearize for forwarding order" << std::endl;
   Linear::dump(*lowered_graph, order);
 
+  // linearize for backwarding
+  auto backward_order = lowered_graph->trainable_graph().essentialBackwardOrder();
+  VERBOSE(ExecutorFactory) << "Linearize for backwarding order" << std::endl;
+  Linear::dump(*lowered_graph, backward_order);
+
   for (auto &&pair : tbackend_contexts)
   {
     pair.second->genTensors();
@@ -805,7 +799,7 @@ exec::IExecutor *ExecutorFactory::createTrainableExecutor(
       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;
@@ -835,23 +829,23 @@ exec::IExecutor *ExecutorFactory::createTrainableExecutor(
                   [](std::pair<const ir::OperandIndex, uint32_t> it) { return it.second == 0; }));
   }
 
-  // Check derivative tensors
+  // Check back propagation 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
+    // Check if the back propagation tensors corresponding to inputs of model are nullptr
+    // NOTE The back propagation 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;
-                       }));
+    assert(std::all_of(
+      lowered_graph->trainable_graph().getInputs().begin(),
+      lowered_graph->trainable_graph().getInputs().end(),
+      [&](const auto &input_idx) { return tensor_regs.getBackPropITensor(input_idx) == nullptr; }));
 
-    // Check if the derivative tensors corresponding to outputs of model exist
+    // Check if the back propagation 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;
+                         return tensor_regs.getBackPropITensor(output_idx) == nullptr;
                        }));
   }
 
@@ -883,19 +877,19 @@ exec::IExecutor *ExecutorFactory::createTrainableExecutor(
                                                  tensor_regs,
                                                  std::move(code_map),
                                                  order,
-                                                 tracing_ctx};
+                                                 backward_order,
+                                                 tracing_ctx,
+                                                 training_info.lossInfo()};
 
-  if (!options->trace_filepath.empty())
+  if (!options->workspace_dir.empty())
   {
-    std::unique_ptr<exec::IExecutionObserver> ctp =
-      std::make_unique<exec::TracingObserver>(options->trace_filepath, exec->graph(), tracing_ctx);
-    exec->addObserver(std::move(ctp));
+    exec->addObserver(
+      std::make_unique<exec::TracingObserver>(options->workspace_dir, exec->graph(), tracing_ctx));
   }
   // TODO Support MINMAX_H5DUMPER
 
   return exec;
 }
-#endif // ONERT_TRAIN
 
 } // namespace compiler
 } // namespace onert
index cc621bc..1b9bd4a 100644 (file)
 #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 "ir/train/TrainingInfo.h"
 
 #include <deque>
 #include <unordered_map>
@@ -58,13 +53,11 @@ public:
                           const std::shared_ptr<exec::IExecutors> &executors,
                           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
+                          const ir::train::TrainingInfo &training_info);
 
 private:
   ExecutorFactory();
@@ -87,7 +80,6 @@ private:
   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,
@@ -96,8 +88,7 @@ private:
   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
+                          const ir::train::TrainingInfo &training_info);
 
 private:
   std::unordered_map<
index f662ef5..2d04d42 100644 (file)
@@ -52,12 +52,6 @@ bool isQuant(const ir::Graph &graph, const ir::IOperation &node)
   return false;
 }
 
-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::IOperation &node)
 {
@@ -114,11 +108,6 @@ void HEScheduler::scheduleShufflingBackends()
       {
         backend_ind = 0;
       }
-      if (isWorkaroundSkip(*_graph, _all_backends[backend_ind], node, quant))
-      {
-        ++backend_ind;
-        continue;
-      }
       const auto exec_time =
         _exec_time->getOperationExecTime(_all_backends[backend_ind], node.name(), quant, size);
       // Scheduling to measure data transfer must be done after measuring all backends separately
@@ -409,7 +398,7 @@ int64_t HEScheduler::DFSChildrenMaxRank(const ir::OperationIndex &index)
 int64_t HEScheduler::backendAvailableTime(const backend::Backend *backend,
                                           const int64_t &starting_time, const int64_t &time_amount)
 {
-  const auto backend_times = _backends_avail_time.at(backend);
+  const auto &backend_times = _backends_avail_time.at(backend);
   // finishing and starting times of an op, that will come after current op
   auto next_op_fst = backend_times.upper_bound(starting_time);
   // finishing time of an op, that will come before current op
@@ -493,10 +482,6 @@ HEScheduler::ESTAndExecTime(const backend::Backend *backend, const ir::Operation
   {
     permute_fine *= 2;
   }
-  if (isWorkaroundSkip(*_graph, backend, node, quant))
-  {
-    return {_exec_time->getMax(), _exec_time->getMax()};
-  }
   // get average exec time of the op on this backend
   auto exec_time = getOpTime(backend, node.name(), quant, size);
   if (backend->config()->id() == "cpu" && _is_parallel_exec)
index 1654bfc..505fbbb 100644 (file)
@@ -206,7 +206,7 @@ void setPermutationsExecutionTime(const std::vector<const Backend *> &backends,
 using OIS = OperandIndexSequence;
 
 template <typename NodeT, typename... Types>
-OperationIndex create(std::shared_ptr<Graph> graph, Types &&... args)
+OperationIndex create(std::shared_ptr<Graph> graph, Types &&...args)
 {
   auto op = std::make_unique<NodeT>(std::forward<Types>(args)...);
   auto op_idx = graph->addOperation(std::move(op));
index 4dbe229..663cf54 100644 (file)
@@ -43,7 +43,7 @@ void Linear::dump(const compiler::ILoweredGraph &lowered_graph,
     std::istringstream iss{dumper::text::formatOperation(lowered_graph.graph(), ind)};
     std::string line;
     while (std::getline(iss, line))
-      VERBOSE(GraphDumper) << line << std::endl;
+      VERBOSE(Linearize) << line << std::endl;
   }
 }
 
index 141fdfe..7fdf700 100644 (file)
@@ -24,7 +24,7 @@
 #include "pass/PassRunner.h"
 #include "pass/UnusedOperandEliminationPass.h"
 #include "../dumper/dot/DotDumper.h"
-#include "../exec/Executors.h"
+#include "../exec/MultiModelExecutors.h"
 #include "../ir/OperationDumper.h"
 #include "../ir/verifier/Verifier.h"
 
@@ -39,15 +39,10 @@ namespace compiler
 {
 
 MultiModelCompiler::MultiModelCompiler(const std::shared_ptr<ir::NNPkg> &nnpkg,
-                                       std::vector<std::unique_ptr<CompilerOptions>> &copts)
-  : _nnpkg{nnpkg}, _voptions{}
+                                       CompilerOptions *copts)
+  : _nnpkg{nnpkg}, _options{copts}
 {
-  assert(nnpkg->model_count() != 1);
-
-  for (uint32_t i = 0; i < copts.size(); i++)
-  {
-    _voptions.push_back(copts[i].get());
-  }
+  // DO NOTHING
 }
 
 std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
@@ -55,28 +50,21 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
   /***************************************************
    * Prepare compilation phase
    ***************************************************/
-  for (auto &&options : _voptions)
   {
-    if (!options)
+    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_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();
+    _options->forceInternalOptions();
+    _options->verboseOptions();
   }
 
   // NYI: allow one model compilation
   auto const model_count = _nnpkg->model_count();
-  if (model_count != _voptions.size())
-    throw std::runtime_error{"Model count and option vector size mismatch"};
-
   for (uint16_t i = 0; i < model_count; i++)
   {
     if (!_nnpkg->model(ir::ModelIndex{i})->hasOnly<ir::Graph>())
@@ -103,7 +91,7 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
    * Backend independent analysis & optimization phase
    ***************************************************/
   // TODO Handle dump level for each model
-  auto dump_level = static_cast<dumper::dot::DotDumper::Level>(_voptions[0]->graph_dump_level);
+  auto dump_level = static_cast<dumper::dot::DotDumper::Level>(_options->graph_dump_level);
   onert::dumper::dot::DotDumper dot_dumper(dump_level);
 
   // Tracing context
@@ -139,7 +127,7 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
                       nnfw::misc::str("before_lower_model-", i, "-subg-", subg_index.value()));
       // Lower: Assign backend
       lowered_subgs[model_index][subg_index] =
-        std::make_unique<compiler::LoweredGraph>(subg, *_voptions[i]);
+        std::make_unique<compiler::LoweredGraph>(subg, *_options);
       // Set tracing_ctx for copied graph
       if (tracing_ctx != nullptr)
         tracing_ctx->setSubgraphIndex(&(lowered_subgs[model_index][subg_index]->graph()),
@@ -203,7 +191,7 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
   /*************************************************************
    *  Backend independent analysis & optimization phase finished
    *************************************************************/
-  auto executors = std::make_shared<exec::Executors>(std::move(model_edges));
+  auto executors = std::make_shared<exec::MultiModelExecutors>(std::move(model_edges));
   for (auto &&pair : lowered_subgs)
   {
     auto const &model_index = pair.first;
@@ -222,7 +210,7 @@ std::shared_ptr<CompilerArtifact> MultiModelCompiler::compile(void)
 
       ExecutorFactoryArgs args;
       args.tracing_ctx = tracing_ctx.get();
-      args.options = _voptions[model_index.value()];
+      args.options = _options;
       args.model_index = model_index;
       args.custom_kernel_builder = custom_kernel_builders[model_index];
       auto executor = std::unique_ptr<exec::IExecutor>{
index b282a50..7e202a7 100644 (file)
@@ -39,11 +39,10 @@ class MultiModelCompiler final : public ICompiler
 public:
   /**
    * @brief     Construct a new Compiler object for NN package
-   * @param[in] nnpkg    NN package to compile
-   * @param[in] coptions Compiler option vector for each model in package
+   * @param[in] nnpkg NN package to compile
+   * @param[in] copts Compiler option for package
    */
-  MultiModelCompiler(const std::shared_ptr<ir::NNPkg> &nnpkg,
-                     std::vector<std::unique_ptr<CompilerOptions>> &copts);
+  MultiModelCompiler(const std::shared_ptr<ir::NNPkg> &nnpkg, CompilerOptions *copts);
 
   /**
    * @brief Destroy the MultiModelCompiler object
@@ -54,13 +53,13 @@ public:
   /**
    * @brief   Do compilation with the options
    *
-   * @return std::shared_ptr<CompilerArtifact> Executors as a result of compilation
+   * @return std::shared_ptr<CompilerArtifact> MultiModelExecutors as a result of compilation
    */
   std::shared_ptr<CompilerArtifact> compile(void);
 
 private:
   std::shared_ptr<ir::NNPkg> _nnpkg;
-  std::vector<CompilerOptions *> _voptions;
+  CompilerOptions *_options;
 };
 
 } // namespace compiler
index 3e940f0..0cd14c1 100644 (file)
@@ -119,7 +119,7 @@ void ShapeValidator::visit(const ir::operation::BCQFullyConnected &node)
     node.getInputs().at(ir::operation::BCQFullyConnected::Input::WEIGHTS_BINARY)};
   const auto weight_cluster_index{
     node.getInputs().at(ir::operation::BCQFullyConnected::Input::WEIGHTS_CLUSTERS)};
-  // const auto bias_index{node.getInputs().at(ir::operation::BCQFullyConnected::Input::BIAS)};
+  const auto bias_index{node.getInputs().at(ir::operation::BCQFullyConnected::Input::BIAS)};
 
   OP_REQUIRES(operands.at(ifm_index).shape().rank() == 2);
   OP_REQUIRES(operands.at(ofm_index).shape().rank() == 2);
@@ -134,7 +134,7 @@ void ShapeValidator::visit(const ir::operation::BCQFullyConnected &node)
 
   // more shape validation will be done inside kernel.
 
-  // TODO Check bias dimension (can be null tensor)
+  OP_REQUIRES(!operands.exist(bias_index) || operands.at(bias_index).shape().rank() == 1);
 }
 
 void ShapeValidator::visit(const ir::operation::BCQGather &node)
@@ -162,11 +162,61 @@ void ShapeValidator::visit(const ir::operation::BCQGather &node)
   // more shape validation will be done inside kernel.
 }
 
+void ShapeValidator::visit(const ir::operation::Conv2D &node)
+{
+  const auto &operands = _graph.operands();
+  const auto ofm_index{node.getOutputs().at(0)};
+  if (operands.at(ofm_index).info().isDynamic())
+    return;
+
+  const auto ifm_index{node.getInputs().at(ir::operation::Conv2D::Input::INPUT)};
+  const auto ker_index{node.getInputs().at(ir::operation::Conv2D::Input::KERNEL)};
+  const auto bias_index{node.getInputs().at(ir::operation::Conv2D::Input::BIAS)};
+
+  OP_REQUIRES(operands.at(ifm_index).shape().rank() == 4);
+  OP_REQUIRES(operands.at(ker_index).shape().rank() == 4);
+  OP_REQUIRES(!operands.exist(bias_index) || operands.at(bias_index).shape().rank() == 1);
+  OP_REQUIRES(operands.at(ofm_index).shape().rank() == 4);
+}
+
 void ShapeValidator::visit(const ir::operation::Comparison &)
 {
   // TODO Shape validation of comparison
 }
 
+void ShapeValidator::visit(const ir::operation::DepthwiseConv2D &node)
+{
+  const auto &operands = _graph.operands();
+  const auto ofm_index{node.getOutputs().at(0)};
+  if (operands.at(ofm_index).info().isDynamic())
+    return;
+
+  const auto ifm_index{node.getInputs().at(ir::operation::DepthwiseConv2D::Input::INPUT)};
+  const auto ker_index{node.getInputs().at(ir::operation::DepthwiseConv2D::Input::KERNEL)};
+  const auto bias_index{node.getInputs().at(ir::operation::DepthwiseConv2D::Input::BIAS)};
+
+  OP_REQUIRES(operands.at(ifm_index).shape().rank() == 4);
+  OP_REQUIRES(operands.at(ker_index).shape().rank() == 4);
+  OP_REQUIRES(!operands.exist(bias_index) || operands.at(bias_index).shape().rank() == 1);
+  OP_REQUIRES(operands.at(ofm_index).shape().rank() == 4);
+}
+
+void ShapeValidator::visit(const ir::operation::FullyConnected &node)
+{
+  const auto &operands = _graph.operands();
+  const auto ofm_index{node.getOutputs().at(0)};
+  if (operands.at(ofm_index).info().isDynamic())
+    return;
+
+  const auto ifm_index{node.getInputs().at(ir::operation::FullyConnected::Input::INPUT)};
+  const auto ker_index{node.getInputs().at(ir::operation::FullyConnected::Input::WEIGHT)};
+  const auto bias_index{node.getInputs().at(ir::operation::FullyConnected::Input::BIAS)};
+
+  OP_REQUIRES(operands.at(ifm_index).shape().rank() >= 2);
+  OP_REQUIRES(operands.at(ker_index).shape().rank() == 2);
+  OP_REQUIRES(!operands.exist(bias_index) || operands.at(bias_index).shape().rank() == 1);
+}
+
 void ShapeValidator::visit(const ir::operation::Softmax &node)
 {
   const auto &operands = _graph.operands();
@@ -227,9 +277,9 @@ void ShapeValidator::visit(const ir::operation::Reduce &node)
   if (operands.at(output_index).info().isDynamic())
     return;
 
-  const auto input_index{node.getInputs().at(ir::operation::Reduce::Input::INPUT)};
-  const auto input_shape = operands.at(input_index).shape();
-  const auto output_shape = operands.at(output_index).shape();
+  const auto &input_index{node.getInputs().at(ir::operation::Reduce::Input::INPUT)};
+  const auto &input_shape = operands.at(input_index).shape();
+  const auto &output_shape = operands.at(output_index).shape();
 
   OP_REQUIRES(input_shape.rank() <= 4);
   OP_REQUIRES(output_shape.rank() <= input_shape.rank());
@@ -516,9 +566,9 @@ void ShapeValidator::visit(const ir::operation::Gather &node)
   const auto ifm_index{node.getInputs().at(ir::operation::Gather::Input::INPUT)};
   const auto indices_index{node.getInputs().at(ir::operation::Gather::Input::INDICES)};
 
-  const auto ifm_shape = operands.at(ifm_index).shape();
-  const auto indices_shape = operands.at(indices_index).shape();
-  const auto ofm_shape = operands.at(ofm_index).shape();
+  const auto &ifm_shape = operands.at(ifm_index).shape();
+  const auto &indices_shape = operands.at(indices_index).shape();
+  const auto &ofm_shape = operands.at(ofm_index).shape();
 
   OP_REQUIRES(ifm_shape.rank() <= 4);
   OP_REQUIRES(indices_shape.rank() <= 3);
@@ -566,7 +616,7 @@ void ShapeValidator::visit(const ir::operation::Pack &node)
   const auto output_rank = static_cast<int32_t>(output_shape.rank());
 
   const auto input1_index{node.getInputs().at(0)};
-  const auto input_shape = operands.at(input1_index).shape();
+  const auto &input_shape = operands.at(input1_index).shape();
 
   OP_REQUIRES(axis >= -output_rank && axis < output_rank);
   for (const auto &index : node.getInputs())
index a51e8ad..da83a43 100644 (file)
@@ -53,7 +53,10 @@ public:
   void visit(const ir::operation::BatchToSpaceND &node) override;
   void visit(const ir::operation::BCQFullyConnected &node) override;
   void visit(const ir::operation::BCQGather &node) override;
+  void visit(const ir::operation::Conv2D &node) override;
   void visit(const ir::operation::Comparison &node) override;
+  void visit(const ir::operation::DepthwiseConv2D &node) override;
+  void visit(const ir::operation::FullyConnected &node) override;
   void visit(const ir::operation::Softmax &node) override;
   void visit(const ir::operation::InstanceNorm &node) override;
   void visit(const ir::operation::Permute &node) override;
index a25b326..622edba 100644 (file)
@@ -253,28 +253,42 @@ StaticShapeInferer::createStaticShapeInferers(
         {
           // 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);
+          try
+          {
+            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);
+            appendChildInferer(if_op.param().then_subg_index);
+            appendChildInferer(if_op.param().else_subg_index);
 
-          appendSubgraphInputObserver(if_op.param().then_subg_index);
-          appendSubgraphInputObserver(if_op.param().else_subg_index);
+            appendSubgraphInputObserver(if_op.param().then_subg_index);
+            appendSubgraphInputObserver(if_op.param().else_subg_index);
 
-          setControlFlowOutputObserver(if_op.param().then_subg_index);
+            setControlFlowOutputObserver(if_op.param().then_subg_index);
+          }
+          catch (const std::bad_cast &)
+          {
+            throw std::runtime_error("StaticShapeInferer: Invalid If operation");
+          }
         }
         else if (op.opcode() == ir::OpCode::While)
         {
           // TODO Remove dynamic_cast
-          const auto &while_op = dynamic_cast<const ir::operation::While &>(op);
+          try
+          {
+            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);
+            appendChildInferer(while_op.param().cond_subg_index);
+            appendChildInferer(while_op.param().body_subg_index);
 
-          appendSubgraphInputObserver(while_op.param().cond_subg_index);
-          appendSubgraphInputObserver(while_op.param().body_subg_index);
+            appendSubgraphInputObserver(while_op.param().cond_subg_index);
+            appendSubgraphInputObserver(while_op.param().body_subg_index);
 
-          setControlFlowOutputObserver(while_op.param().body_subg_index);
+            setControlFlowOutputObserver(while_op.param().body_subg_index);
+          }
+          catch (const std::bad_cast &)
+          {
+            throw std::runtime_error("StaticShapeInferer: Invalid While operation");
+          }
         }
       });
   }
@@ -453,6 +467,23 @@ void StaticShapeInferer::visit(const ir::operation::Conv2D &op)
   output.info().shape(new_shape);
 }
 
+void StaticShapeInferer::visit(const ir::operation::DepthwiseConv2D &op)
+{
+  auto &operands = _lowered_subg->graph().operands();
+
+  const auto input_idx{op.getInputs().at(ir::operation::DepthwiseConv2D::Input::INPUT)};
+  const auto &input = operands.at(input_idx);
+  const auto ker_idx{op.getInputs().at(ir::operation::DepthwiseConv2D::Input::KERNEL)};
+  const auto &ker = operands.at(ker_idx);
+  const auto output_idx = op.getOutputs().at(0);
+  ir::Operand &output = operands.at(output_idx);
+
+  // re-sizing output shape
+  ir::Shape new_shape = shape_inference::inferDepthwiseConv2DShape(input.info().shape(),
+                                                                   ker.info().shape(), op.param());
+  output.info().shape(new_shape);
+}
+
 void StaticShapeInferer::visit(const ir::operation::ElementwiseActivation &op)
 {
   handleSimpleUnaryOp(op, op.getInputs().at(ir::operation::ElementwiseActivation::Input::INPUT));
@@ -524,11 +555,11 @@ void StaticShapeInferer::visit(const ir::operation::Fill &op)
   assert(dims_buf);
 
   const auto &dims_shape = shape.info().shape();
-  auto new_shape = ((dims_type == ir::DataType::INT32)
-                      ? shape_inference::inferFillShape<int32_t>(
-                          dims_shape, reinterpret_cast<const int32_t *>(dims_buf))
-                      : shape_inference::inferFillShape<int64_t>(
-                          dims_shape, reinterpret_cast<const int64_t *>(dims_buf)));
+  const auto &new_shape = ((dims_type == ir::DataType::INT32)
+                             ? shape_inference::inferFillShape<int32_t>(
+                                 dims_shape, reinterpret_cast<const int32_t *>(dims_buf))
+                             : shape_inference::inferFillShape<int64_t>(
+                                 dims_shape, reinterpret_cast<const int64_t *>(dims_buf)));
 
   output.info().shape(new_shape);
 }
@@ -605,11 +636,22 @@ 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 &)
+void StaticShapeInferer::visit(const ir::operation::Loss &op)
 {
   // TODO Consider SparseCategoricalCrossentropy case
 
-  // TODO Consider output shape in case of reduction option
+  auto &operands = _lowered_subg->graph().operands();
+
+  const auto input_index{op.getInputs().at(ir::operation::Loss::Input::Y_PRED)};
+  auto &input = operands.at(input_index);
+
+  const auto output_index{op.getOutputs().at(0)};
+  auto &output = operands.at(output_index);
+
+  ir::Shape new_shape = output.info().shape();
+  new_shape.dim(0) = input.info().shape().dim(0);
+
+  output.info().shape(new_shape);
 }
 
 void StaticShapeInferer::visit(const ir::operation::LSTM &op)
@@ -783,7 +825,7 @@ void StaticShapeInferer::visit(const ir::operation::Pad &op)
   }
 
   // re-sizing output shape
-  const auto new_shape = shape_inference::inferPadShape(
+  const auto &new_shape = shape_inference::inferPadShape(
     input.shape(), reinterpret_cast<const int32_t *>(pad.data()->base()),
     pad.shape().num_elements());
   output.info().shape(new_shape);
@@ -803,7 +845,27 @@ void StaticShapeInferer::visit(const ir::operation::Permute &op)
   // However, it is not applied here, so input/output have the same layout of frontend. Because
   // "ExecutorFactory" would convert shape of input/output accoding to the layouts when registering
   // operand info to "TensorBuilder" after calling "StaticShapeInferer"
-  const auto new_shape = input.info().shape();
+  const auto &new_shape = input.info().shape();
+  output.info().shape(new_shape);
+}
+
+void StaticShapeInferer::visit(const ir::operation::Pool2D &op)
+{
+  auto &operands = _lowered_subg->graph().operands();
+
+  const auto layout = _lowered_subg->graph().layout();
+
+  const auto input_idx{op.getInputs().at(ir::operation::Pool2D::Input::INPUT)};
+  const auto &input = operands.at(input_idx);
+  if (input.info().shape().rank() != 4)
+  {
+    throw std::runtime_error(op.name() + ": supports only 4D tensor as input");
+  }
+
+  const auto output_idx = op.getOutputs().at(0);
+  ir::Operand &output = operands.at(output_idx);
+
+  ir::Shape new_shape = shape_inference::inferPoolShape(input.info().shape(), op.param(), layout);
   output.info().shape(new_shape);
 }
 
@@ -916,8 +978,8 @@ void StaticShapeInferer::visit(const ir::operation::Reshape &op)
       const auto *shape_buf = reinterpret_cast<const int32_t *>(shape.data()->base());
       assert(shape_buf);
 
-      ir::Shape new_shape = shape_inference::inferReshapeShape(
-        shape_buf, shape.shape().num_elements(), input.shape().num_elements());
+      ir::Shape new_shape =
+        shape_inference::inferReshapeShape(input.shape(), shape_buf, shape.shape().num_elements());
 
       // if shape is from Const, TFLC put the shape of output into tensor
       if (new_shape != output.shape())
@@ -938,7 +1000,7 @@ void StaticShapeInferer::visit(const ir::operation::Reshape &op)
     // Let's check the new_shape option
     auto shape = op.param().new_shape;
     ir::Shape new_shape =
-      shape_inference::inferReshapeShape(shape.data(), shape.size(), input.shape().num_elements());
+      shape_inference::inferReshapeShape(input.shape(), shape.data(), shape.size());
 
     if (new_shape != output.shape())
     {
@@ -1088,8 +1150,8 @@ void StaticShapeInferer::visit(const ir::operation::SpaceToBatchND &op)
 
   const auto output_index = op.getOutputs().at(0);
   const auto input_idx{op.getInputs().at(ir::operation::SpaceToBatchND::Input::INPUT)};
-  const auto block_shape_idx{op.getInputs().at(ir::operation::SpaceToBatchND::Input::BLOCK_SIZE)};
-  const auto padding_idx{op.getInputs().at(ir::operation::SpaceToBatchND::Input::PADDINGS)};
+  const auto &block_shape_idx{op.getInputs().at(ir::operation::SpaceToBatchND::Input::BLOCK_SIZE)};
+  const auto &padding_idx{op.getInputs().at(ir::operation::SpaceToBatchND::Input::PADDINGS)};
 
   ir::Operand &output = operands.at(output_index);
   const auto &input = operands.at(input_idx);
@@ -1103,9 +1165,9 @@ void StaticShapeInferer::visit(const ir::operation::SpaceToBatchND &op)
     return;
   }
 
-  auto input_shape = input.info().shape();
-  auto block_shape_shape = block_shape.info().shape();
-  auto padding_shape = padding.info().shape();
+  const auto &input_shape = input.info().shape();
+  const auto &block_shape_shape = block_shape.info().shape();
+  const auto &padding_shape = padding.info().shape();
 
   auto block_shape_data = reinterpret_cast<const int32_t *>(block_shape.data()->base());
   auto padding_data = reinterpret_cast<const int32_t *>(padding.data()->base());
@@ -1325,7 +1387,7 @@ void StaticShapeInferer::visit(const ir::operation::While &op)
   auto body_input_observer = _subg_input_observers.at(op.param().body_subg_index).get();
   auto cond_input_observer = _subg_input_observers.at(op.param().cond_subg_index).get();
   // re-sizing input shapes of body subgraph
-  const auto inputs = op.getInputs();
+  const auto &inputs = op.getInputs();
   std::vector<ir::OperandInfo> inputs_info;
   const auto &graph = _lowered_subg->graph();
   for (size_t i = 0; i < inputs.size(); ++i)
@@ -1401,9 +1463,7 @@ void StaticShapeInferer::visit(const ir::operation::Bulk &op)
   const auto output_idx = op.getOutputs().at(0);
   ir::Operand &output = operands.at(output_idx);
 
-  auto cur_input_shape = input.info().shape();
-  auto origin_input_shape = op.param().origin_input_shapes[0];
-  auto cur_output_shape = output.info().shape();
+  const auto &cur_input_shape = input.info().shape();
   auto origin_output_shape = op.param().origin_output_shapes[0];
 
   // TODO: more check for valid batch request
index c7e06e8..4c30785 100644 (file)
@@ -71,7 +71,7 @@ public:
 
   backend::ITensor *getITensor(ir::OperandIndex ind) const
   {
-    for (auto &&tensor_reg : _tensor_regs)
+    for (const auto &tensor_reg : _tensor_regs)
     {
       auto tensor = tensor_reg->getITensor(ind);
       if (tensor)
index a6590b1..ac13180 100644 (file)
@@ -39,9 +39,10 @@ void ConstantInsertionPass::callback(const ir::OperationIndex &node_index, ir::I
   {
     auto &object = _graph.operands().at(input);
 
-    if (object.isConstant())
+    const auto key = ReplaceKey{input, factor};
+    if (object.isConstant() && (object.getUses().size() >= 2 ||
+                                _replace_operands_map.find(key) != _replace_operands_map.end()))
     {
-      const auto key = ReplaceKey{input, factor};
       if (_replace_operands_map.count(key) == 0)
       {
         ir::Operand new_object(object);
index 39eb803..f5ad7e6 100644 (file)
@@ -87,8 +87,7 @@ void PermutationInsertionPass::callback(const ir::OperandIndex &index, ir::Opera
       const auto op_layout = op_li->layout();
       const backend::Backend *backend = op_li->backend();
       assert(backend);
-      auto use_node_inputs = operation.getInputs();
-      assert(use_node_inputs.contains(index));
+      assert(operation.getInputs().contains(index));
 
       auto new_index = factor_to_index.at({backend, op_layout});
       if (index != new_index)
index 490c648..8b368c4 100644 (file)
@@ -111,6 +111,7 @@ void LoweredTrainableGraph::lowerGraph(const CompilerOptions &options)
       if (op.opcode() == ir::OpCode::Permute)
       {
         auto trainable_op = op_converter(op);
+        trainable_op->enableBackward();
         auto gen_index = _trainable_graph.replaceOperation(index, std::move(trainable_op));
         UNUSED_RELEASE(gen_index);
         assert(gen_index == index);
diff --git a/runtime/onert/core/src/compiler/train/StaticBackwardShapeInferer.cc b/runtime/onert/core/src/compiler/train/StaticBackwardShapeInferer.cc
new file mode 100644 (file)
index 0000000..eae8cde
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "StaticBackwardShapeInferer.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 StaticBackwardShapeInferer::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 << "StaticBackwardShapeInferer 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 StaticBackwardShapeInferer::dump()
+{
+  // TODO dump
+}
+
+bool StaticBackwardShapeInferer::checkDynamicInput(const ir::IOperation &op)
+{
+  const auto &operands = _lowered_subg->graph().operands();
+  for (const auto &input_idx : op.getInputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED)
+  {
+    if (operands.at(input_idx).info().isDynamic())
+    {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void StaticBackwardShapeInferer::checkOutput(const ir::IOperation &op)
+{
+  const auto &bwd_operands = _lowered_subg->trainable_graph().backward_operands();
+  for (const auto &output_idx : op.getOutputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED)
+  {
+    if (!bwd_operands.exist(output_idx))
+    {
+      std::stringstream msg;
+      msg << "StaticBackwardShapeInferer : Invalid output, ";
+      msg << op.name() << "'s back propagation output(index: " << output_idx << ") does not exist.";
+      throw std::runtime_error(msg.str());
+    }
+  }
+}
+
+void StaticBackwardShapeInferer::setShape(const ir::OperandIndex &index, const ir::Shape &shape)
+{
+  auto &tgraph = _lowered_subg->trainable_graph();
+
+  if (tgraph.backward_operands().exist(index))
+    tgraph.changeBackwardShape(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.addBackwardOperand(index, std::make_unique<ir::Operand>(shape, type));
+    assert(new_index == index);
+    UNUSED_RELEASE(new_index);
+  }
+}
+
+void StaticBackwardShapeInferer::visit(const ir::train::operation::Conv2D &)
+{
+  // NYI
+}
+
+void StaticBackwardShapeInferer::visit(const ir::train::operation::ElementwiseActivation &)
+{
+  // NYI
+}
+
+void StaticBackwardShapeInferer::visit(const ir::train::operation::Loss &)
+{
+  // NYI
+}
+
+void StaticBackwardShapeInferer::visit(const ir::train::operation::Permute &op)
+{
+  const auto &bwd_operands = _lowered_subg->trainable_graph().backward_operands();
+
+  const auto &output_idx = op.getOutputs().at(0);
+  const auto &output = bwd_operands.at(output_idx);
+
+  // re-sizing shape of back propagatation input
+  const auto &input_idx = op.getInputs().at(0);
+  const auto &new_shape = output.info().shape();
+  setShape(input_idx, new_shape);
+}
+
+void StaticBackwardShapeInferer::visit(const ir::train::operation::Pool2D &)
+{
+  // NYI
+}
+
+void StaticBackwardShapeInferer::visit(const ir::train::operation::Reshape &)
+{
+  // NYI
+}
+
+void StaticBackwardShapeInferer::visit(const ir::train::operation::Softmax &)
+{
+  // NYI
+}
+
+} // namespace train
+} // namespace compiler
+} // namespace onert
diff --git a/runtime/onert/core/src/compiler/train/StaticBackwardShapeInferer.h b/runtime/onert/core/src/compiler/train/StaticBackwardShapeInferer.h
new file mode 100644 (file)
index 0000000..2ad9bca
--- /dev/null
@@ -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_STATIC_BACKWARD_SHAPE_INFERER_H__
+#define __ONERT_COMPILER_TRAIN_STATIC_BACKWARD_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 StaticBackwardShapeInferer : public ir::train::TrainableOperationVisitor
+{
+public:
+  StaticBackwardShapeInferer(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_TRAIN_STATIC_BACKWARD_SHAPE_INFERER_H__
diff --git a/runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.cc b/runtime/onert/core/src/compiler/train/StaticDerivativeShapeInferer.cc
deleted file mode 100644 (file)
index d215329..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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
deleted file mode 100644 (file)
index 48b3172..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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__
index 48eaf10..8886c9b 100644 (file)
@@ -20,6 +20,7 @@
 #include "../../backend/builtin/Config.h"
 #include "../../backend/builtin/train/TensorRegistry.h"
 
+#include <backend/train/ITensorRegistry.h>
 #include <backend/train/TrainableBackendContext.h>
 
 #include <memory>
@@ -73,7 +74,7 @@ public:
 
   backend::ITensor *getITensor(ir::OperandIndex index) const
   {
-    for (auto &&tensor_reg : _tensor_regs)
+    for (const auto &tensor_reg : _tensor_regs)
     {
       auto tensor = tensor_reg->getITensor(index);
       if (tensor)
@@ -82,17 +83,25 @@ public:
     return nullptr;
   }
 
-  backend::ITensor *getDerivativeITensor(ir::OperandIndex index) const
+  backend::ITensor *getBackPropITensor(ir::OperandIndex index) const
   {
-    for (auto &&tensor_reg : _tensor_regs)
+    for (const auto &tensor_reg : _tensor_regs)
     {
-      auto tensor = tensor_reg->getDerivativeITensor(index);
+      auto tensor = tensor_reg->getBackPropITensor(index);
       if (tensor)
         return tensor;
     }
     return nullptr;
   }
 
+  void iterateTrainableTensors(
+    const std::function<void(const ir::OperandIndex &, const backend::train::ITrainableTensor *)>
+      &fn) const
+  {
+    for (const auto &tensor_reg : _tensor_regs)
+      tensor_reg->iterateTrainableTensors(fn);
+  }
+
 private:
   std::unordered_set<std::shared_ptr<backend::train::ITensorRegistry>> _tensor_regs;
   std::shared_ptr<backend::builtin::train::TensorRegistry> _builtin_tensor_reg;
index d20ae9f..80ed05a 100644 (file)
@@ -27,18 +27,28 @@ namespace train
 {
 
 TrainableOperationConverter::TrainableOperationConverter(
-  ir::train::TrainableGraph &tgraph, const compiler::train::TrainingInfo *training_info)
+  ir::train::TrainableGraph &tgraph, const ir::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::BinaryArithmetic &node)
+{
+  _return_op = std::make_unique<ir::train::operation::BinaryArithmetic>(node);
+}
+
 void TrainableOperationConverter::visit(const ir::operation::Conv2D &node)
 {
   _return_op = std::make_unique<ir::train::operation::Conv2D>(node);
 }
 
+void TrainableOperationConverter::visit(const ir::operation::DepthwiseConv2D &node)
+{
+  _return_op = std::make_unique<ir::train::operation::DepthwiseConv2D>(node);
+}
+
 void TrainableOperationConverter::visit(const ir::operation::ElementwiseActivation &node)
 {
   if (node.param().op_type == ir::operation::ElementwiseActivation::Type::RELU)
@@ -58,7 +68,12 @@ void TrainableOperationConverter::visit(const ir::operation::FullyConnected &nod
 
 void TrainableOperationConverter::visit(const ir::operation::Loss &node)
 {
-  _return_op = std::make_unique<ir::train::operation::Loss>(node);
+  _return_op = std::make_unique<ir::train::operation::Loss>(node, _training_info->lossInfo());
+}
+
+void TrainableOperationConverter::visit(const ir::operation::Pad &node)
+{
+  _return_op = std::make_unique<ir::train::operation::Pad>(node);
 }
 
 void TrainableOperationConverter::visit(const ir::operation::Permute &node)
@@ -71,6 +86,11 @@ void TrainableOperationConverter::visit(const ir::operation::Pool2D &node)
   _return_op = std::make_unique<ir::train::operation::Pool2D>(node);
 }
 
+void TrainableOperationConverter::visit(const ir::operation::Reduce &node)
+{
+  _return_op = std::make_unique<ir::train::operation::Reduce>(node);
+}
+
 void TrainableOperationConverter::visit(const ir::operation::Reshape &node)
 {
   _return_op = std::make_unique<ir::train::operation::Reshape>(node);
index 5f6fc10..59f92f9 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "UntrainableOperationConverter.h"
 
-#include "compiler/train/TrainingInfo.h"
+#include "ir/train/TrainingInfo.h"
 
 namespace onert
 {
@@ -32,22 +32,26 @@ class TrainableOperationConverter : public UntrainableOperationConverter
 {
 public:
   TrainableOperationConverter(ir::train::TrainableGraph &trainable_graph,
-                              const compiler::train::TrainingInfo *training_info);
+                              const ir::train::TrainingInfo *training_info);
 
   using UntrainableOperationConverter::operator();
 
 private:
+  void visit(const ir::operation::BinaryArithmetic &) override;
   void visit(const ir::operation::Conv2D &) override;
+  void visit(const ir::operation::DepthwiseConv2D &) 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::Pad &node) override;
   void visit(const ir::operation::Permute &node) override;
   void visit(const ir::operation::Pool2D &node) override;
+  void visit(const ir::operation::Reduce &node) override;
   void visit(const ir::operation::Reshape &) override;
   void visit(const ir::operation::Softmax &) override;
 
 private:
-  const compiler::train::TrainingInfo *_training_info;
+  const ir::train::TrainingInfo *_training_info;
 };
 
 } // namespace train
index 711af16..ab0de8d 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "TrainingCompiler.h"
 
-#include "StaticDerivativeShapeInferer.h"
+#include "StaticBackwardShapeInferer.h"
 #include "TrainableOperationConverter.h"
 #include "pass/LossInsertionPass.h"
 #include "../CompilerHelpers.h"
@@ -34,7 +34,6 @@
 #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>
@@ -46,10 +45,9 @@ 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}
+TrainingCompiler::TrainingCompiler(const std::shared_ptr<ir::NNPkg> &nnpkg, CompilerOptions *copts,
+                                   const ir::train::TrainingInfo &training_info)
+  : _model{nnpkg->primary_model()}, _options{copts}, _training_info{training_info}
 {
   if (nnpkg->model_count() > 1)
     throw std::runtime_error("TrainingCompiler does not support multiple models yet");
@@ -77,12 +75,6 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::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");
-  }
-
   _options->forceInternalOptions();
   _options->verboseOptions();
 
@@ -115,14 +107,30 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
 
       // Convert operations to trainable operations
       auto converter = TrainableOperationConverter{*trainable_subg, &_training_info};
+      ir::OperationIndex min_trainable_op_idx;
       subg.operations().iterate(
         [&](const onert::ir::OperationIndex &op_index, const onert::ir::IOperation &op) {
           auto trainable_op = converter(op);
+          if (_training_info.getTrainableOps().find(op_index) !=
+              std::end(_training_info.getTrainableOps()))
+          {
+            trainable_op->enableWeightsUpdate();
+            if (op_index.value() < min_trainable_op_idx.value())
+            {
+              min_trainable_op_idx = op_index;
+            }
+          }
           auto gen_index = trainable_subg->replaceOperation(op_index, std::move(trainable_op));
           UNUSED_RELEASE(gen_index);
           assert(gen_index == op_index);
         });
 
+      for (ir::OperationIndex idx{min_trainable_op_idx};
+           idx.value() < trainable_subg->operations().size(); idx++)
+      {
+        trainable_subg->enableBackward(idx);
+      }
+
       trainable_subgraphs[subg_index] = std::move(trainable_subg);
     });
   }
@@ -135,6 +143,17 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
   // operation
   _model.reset();
 
+  // 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);
+
+  for (const auto &pair : trainable_subgraphs)
+  {
+    const auto &subg_index = pair.first;
+    const auto &subg = pair.second;
+    dot_dumper.dump(*subg, nnfw::misc::str("before_loss_insertion-", subg_index.value()));
+  }
+
   // Apply pass for trainable subgraphs
   for (auto &&pair : trainable_subgraphs)
   {
@@ -147,6 +166,13 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
       .run();
   }
 
+  for (const auto &pair : trainable_subgraphs)
+  {
+    const auto &subg_index = pair.first;
+    const auto &subg = pair.second;
+    dot_dumper.dump(*subg, nnfw::misc::str("after_loss_insertion-", subg_index.value()));
+  }
+
   // Change input shape according to batch_size
   for (auto &&pair : trainable_subgraphs)
   {
@@ -167,10 +193,6 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
   /***************************************************
    * 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>();
 
@@ -187,8 +209,7 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
       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());
+      tracing_ctx->setSubgraphIndex(&(lowered_subgs[subg_index]->graph()), subg_index.value());
     }
   }
 
@@ -199,7 +220,7 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
     dot_dumper.dump(*lowered_subg, nnfw::misc::str("after_lower_subg-", subg_index.value()));
   }
 
-  // Set derivatives as default tensor info
+  // Set operands' info for back propagation as default tensor info
   for (const auto &pair : lowered_subgs)
   {
     auto lowered_subg = pair.second.get();
@@ -207,8 +228,8 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
     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));
+        auto bwd_operand = std::make_unique<ir::Operand>(obj);
+        const auto gen_index = tgraph.addBackwardOperand(index, std::move(bwd_operand));
         assert(gen_index == index);
         UNUSED_RELEASE(gen_index);
       }
@@ -231,12 +252,12 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
       inferer->dump();
     }
 
-    // NOTE StaticDerivativeShapeInferer is allocated for each subgraph,
+    // NOTE StaticBackwardShapeInferer 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());
+      auto inferer = std::make_unique<StaticBackwardShapeInferer>(lowered_subg.get());
       inferer->infer();
       inferer->dump();
     }
@@ -249,17 +270,7 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
     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));
+  // TODO Validate shapes of the tensors for back propagation
 
   /*************************************************************
    *  Backend independent analysis & optimization phase finished
@@ -283,7 +294,7 @@ std::shared_ptr<CompilerArtifact> TrainingCompiler::compile(void)
     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)};
+      ExecutorFactory::get().create(std::move(lowered_subg), executors, args, _training_info)};
     executor->setIndexedRanks(indexed_ranks);
     executors->emplace(model_index, subg_index, std::move(executor));
   }
index b934372..ab62c0f 100644 (file)
@@ -24,8 +24,8 @@
 
 #include "compiler/CompilerOptions.h"
 #include "compiler/ICompiler.h"
-#include "compiler/train/TrainingInfo.h"
 #include "ir/NNPkg.h"
+#include "ir/train/TrainingInfo.h"
 
 namespace onert
 {
@@ -41,18 +41,16 @@ 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
+   * @brief     Construct a new TrainingCompiler object for an nnpkg
+   * @param[in] nnpkg         nnpkg to compile
+   * @param[in] copts         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);
+  explicit TrainingCompiler(const std::shared_ptr<ir::NNPkg> &nnpkg, CompilerOptions *copts,
+                            const ir::train::TrainingInfo &training_info);
 
   /**
-   * @brief Default Construct
+   * @brief Construct a TrainingCompiler object
    *
    */
   TrainingCompiler(void) = delete;
@@ -73,7 +71,7 @@ public:
 private:
   std::shared_ptr<ir::Model> _model;
   CompilerOptions *_options;
-  const TrainingInfo _training_info;
+  const ir::train::TrainingInfo _training_info;
 };
 
 } // namespace train
index 6a5a052..22f7604 100644 (file)
@@ -30,8 +30,8 @@ UntrainableOperationConverter::UntrainableOperationConverter(ir::train::Trainabl
 {
 }
 
-std::unique_ptr<ir::train::ITrainableOperation> UntrainableOperationConverter::
-operator()(const ir::IOperation &op)
+std::unique_ptr<ir::train::ITrainableOperation>
+UntrainableOperationConverter::operator()(const ir::IOperation &op)
 {
   op.accept(*this);
 
index 3e01a97..ea1f21e 100644 (file)
@@ -17,6 +17,7 @@
 #include "LossInsertionPass.h"
 
 #include "ir/train/TrainableGraph.h"
+#include "ir/train/TrainingInfo.h"
 #include "ir/train/operation/Loss.h"
 
 namespace onert
@@ -32,9 +33,6 @@ 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");
@@ -48,20 +46,27 @@ void LossInsertionPass::run()
   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);
+  auto y_true_index = _trainable_graph.addOperand(y_pred.shape(), y_pred.typeInfo());
   ir::OperandIndexSequence inputs{y_pred_index, y_true_index};
 
-  // TODO Consider Reduction
-  //      Some types of Reduction have the same shape y_true and output.
+  ir::Shape output_shape;
+  if (loss_info.reduction_type == ir::train::LossReductionType::Sum ||
+      loss_info.reduction_type == ir::train::LossReductionType::SumOverBatchSize)
+  {
+    output_shape = ir::Shape{1};
+  }
+  else
+  {
+    throw std::runtime_error("LossInsertionPass: Not supported reduction type");
+  }
 
   const ir::TypeInfo float_op(ir::DataType::FLOAT32);
-  auto output_index = _trainable_graph.addOperand(ir::Shape{1}, float_op);
+  auto output_index = _trainable_graph.addOperand(output_shape, 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);
+  auto loss_op = std::make_unique<ir::operation::Loss>(inputs, outputs);
+  auto trainable_loss_op = std::make_unique<ir::train::operation::Loss>(*loss_op, loss_info);
+  trainable_loss_op->enableBackward();
 
   _trainable_graph.addOperation(std::move(trainable_loss_op));
 
index ed4d60c..1a313fb 100644 (file)
@@ -19,7 +19,7 @@
 
 #include "Pass.h"
 
-#include "compiler/train/TrainingInfo.h"
+#include "ir/Index.h"
 
 namespace onert
 {
@@ -33,7 +33,8 @@ namespace pass
 class LossInsertionPass : public Pass
 {
 public:
-  LossInsertionPass(ir::train::TrainableGraph &trainable_graph, const TrainingInfo *training_info,
+  LossInsertionPass(ir::train::TrainableGraph &trainable_graph,
+                    const ir::train::TrainingInfo *training_info,
                     const ir::SubgraphIndex &subg_index)
     : Pass{trainable_graph, training_info}, _subg_index{subg_index}
   {
index d64c06c..0e835e1 100644 (file)
@@ -26,6 +26,7 @@ namespace ir
 namespace train
 {
 class TrainableGraph;
+class TrainingInfo;
 } // namespace train
 } // namespace ir
 } // namespace onert
@@ -36,16 +37,13 @@ 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)
+  Pass(ir::train::TrainableGraph &trainable_graph, const ir::train::TrainingInfo *training_info)
     : _trainable_graph{trainable_graph}, _training_info{training_info}
   {
   }
@@ -53,7 +51,7 @@ public:
 
 protected:
   ir::train::TrainableGraph &_trainable_graph;
-  const TrainingInfo *_training_info;
+  const ir::train::TrainingInfo *_training_info;
 };
 
 } // namespace pass
index ab77a6c..98524d8 100644 (file)
@@ -213,7 +213,7 @@ void DotDumper::dump(const ir::Graph &graph, const std::string &tag)
   dump_to_file(dot_operands, dot_operations, tag);
 }
 
-// TODO Support derivative tensors
+// TODO Support tensors for training
 void DotDumper::dump(const compiler::ILoweredGraph &lowered_graph, const std::string &tag)
 {
   if (_level == Level::OFF)
@@ -228,6 +228,11 @@ void DotDumper::dump(const compiler::ILoweredGraph &lowered_graph, const std::st
   dump_to_file(dot_operands, dot_operations, tag);
 }
 
+void DotDumper::dump(const ir::train::TrainableGraph &graph, const std::string &tag)
+{
+  dump(graph.graph(), tag);
+}
+
 } // namespace dot
 } // namespace dumper
 } // namespace onert
index fca5f35..59f4b3b 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include "ir/Graph.h"
+#include "ir/train/TrainableGraph.h"
 #include "compiler/ILoweredGraph.h"
 
 #ifndef __ONERT_DUMPER_DOT_DOT_DUMPER_H__
@@ -59,6 +60,15 @@ public:
    */
   void dump(const compiler::ILoweredGraph &lowered_graph, const std::string &tag);
 
+  /**
+   * @brief Dump graph information to dot file as tag name if "GRAPH_DOT_DUMP" is set
+   *
+   * @param[in] graph  TrainableGraph to be dumped
+   * @param[in] tag    The name of dot file to be dumped
+   * @return N/A
+   */
+  void dump(const ir::train::TrainableGraph &graph, const std::string &tag);
+
 private:
   Level _level;
 };
index 88f5254..cbc7387 100644 (file)
@@ -35,7 +35,7 @@ Operand::Operand(const ir::OperandIndex &index, Type type)
   : Node{"operand" + std::to_string(index.value())}
 {
   {
-    auto type_to_shape = [](Type type) {
+    auto type_to_shape = [](Type type) -> const std::string & {
       switch (type)
       {
         case Type::MODEL_INPUT:
index 8a9de9f..e353ed5 100644 (file)
@@ -32,16 +32,16 @@ static const char *h5_value_grpname = "value";
 /*
  * ensure grp_name exists in parent
  */
-H5::Group ensureGroup(H5::Group parent, const char *child)
+H5::Group ensureGroup(H5::Group parent, const std::string &child)
 {
   H5::Exception::dontPrint();
   try
   {
-    return parent.openGroup(child);
+    return parent.openGroup(child.c_str());
   }
   catch (H5::Exception &e)
   {
-    return parent.createGroup(child);
+    return parent.createGroup(child.c_str());
   }
 }
 
@@ -51,21 +51,33 @@ MinMaxDumper::MinMaxDumper(const std::string &filepath) : Dumper(filepath)
   ensureGroup(root_grp, h5_value_grpname);
 }
 
-void MinMaxDumper::dump(const exec::SMMinMaxMap &mmmap) const
+void MinMaxDumper::dump(const exec::IOMinMaxMap &input_minmax,
+                        const exec::OpMinMaxMap &op_minmax) 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");
+  auto run_grp = val_grp.createGroup(std::string("run_") + std::to_string(num_run));
+  auto model_grp = ensureGroup(run_grp, std::string("model_") + "0");
   hsize_t dims[] = {2};
   H5::DataSpace dspace(1, dims); // rank=1, dim(0)=2, {min, max}
-  for (auto &&e : mmmap)
+  for (auto &&e : input_minmax)
+  {
+    // key = {subg_idx, io_idx} = e.first
+    const auto subg_idx = e.first.first.value();
+    const auto io_idx = e.first.second.value();
+    auto subg_grp = ensureGroup(model_grp, std::string("subg_") + std::to_string(subg_idx));
+    auto input_dset = subg_grp.createDataSet(std::string("input_") + std::to_string(io_idx),
+                                             H5::PredType::IEEE_F32BE, dspace);
+    input_dset.write(e.second.data, H5::PredType::NATIVE_FLOAT);
+  }
+  for (auto &&e : op_minmax)
   {
     // 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);
+    auto subg_grp = ensureGroup(model_grp, std::string("subg_") + std::to_string(subg_idx));
+    auto op_dset = subg_grp.createDataSet(std::string("op_") + std::to_string(op_idx),
+                                          H5::PredType::IEEE_F32BE, dspace);
     op_dset.write(e.second.data, H5::PredType::NATIVE_FLOAT);
   }
 }
index 1f1b27c..d7e2c1c 100644 (file)
@@ -34,30 +34,38 @@ namespace h5
 //
 // GROUP /
 //   GROUP value
-//     â””── GROUP run_idx
-//           â””── GROUP model_idx
-//                 â””── GROUP subg_idx
-//                       â””── DATASET op_idx
+//     â””── GROUP run_{idx}
+//           â””── GROUP model_{idx}
+//                 â””── GROUP subg_{idx}
+//                       â”œâ”€â”€ DATASET op_{idx}
+//                       â”‚      DATATYPE Float32
+//                       â”‚      DATASPACE (2)
+//                       â”‚      DATA { min, max }
+//                       â””── DATASET input_{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"}
+//     â””── GROUP model_{idx}
+//           â””── GROUP subg_{idx}
+//                       â”œâ”€â”€ ATTRIBUTE op_{idx}
+//                       â”‚      DATATYPE String
+//                       â”‚      DATA { "op/name"}
+//                       â””── ATTRIBUTE input_{idx}
+//                              DATATYPE String
+//                              DATA { "input/name"}
 //
 class MinMaxDumper : private Dumper
 {
 public:
   MinMaxDumper(const std::string &filepath);
   /**
-   * @brief Dump minmax map
+   * @brief Dump input minmax map
    *
-   * @param[in] map  single model minmax map
+   * @param[in] in_minmax  input minmax map
+   * @param[in] op_minmax  op minmax map
    */
-  void dump(const exec::SMMinMaxMap &map) const;
+  void dump(const exec::IOMinMaxMap &in_minmax, const exec::OpMinMaxMap &op_minmax) const;
 
 private:
   H5::Group _val_grp;
index 6bd7904..c89253b 100644 (file)
@@ -18,9 +18,7 @@
 
 #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"
 
@@ -39,7 +37,7 @@ std::string formatOperandIndexSequence(const ir::OperandIndexSequence &seq)
   std::vector<std::string> strs;
   for (auto &&ind : seq)
     strs.push_back(dumper::text::formatOperandBrief(ind));
-  return nnfw::misc::join(strs.begin(), strs.end(), ", ");
+  return nnfw::misc::join(strs.begin(), strs.end(), ",");
 }
 
 } // namespace
@@ -87,8 +85,10 @@ void dumpGraph(const ir::Graph &graph)
     const auto &op = graph.operations().at(op_ind);
     VERBOSE(GraphDumper) << "  " << formatOperation(op, op_ind) << "\n";
   }
+  graph.operands().iterate([&](const ir::OperandIndex &idx, const ir::Operand &oprd) {
+    VERBOSE(GraphDumper) << "  Origin(" << idx << "): " << oprd.originIndex() << std::endl;
+  });
   VERBOSE(GraphDumper) << "}\n";
-  VERBOSE(GraphDumper) << std::endl;
 }
 
 void dumpLoweredGraph(const compiler::LoweredGraph &lgraph)
@@ -97,13 +97,11 @@ 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
index ab00614..3cc13c9 100644 (file)
@@ -34,12 +34,10 @@ namespace compiler
 {
 class LoweredGraph;
 
-#ifdef ONERT_TRAIN
 namespace train
 {
 class LoweredTrainableGraph;
 } // namespace train
-#endif // ONERT_TRAIN
 } // namespace compiler
 } // namespace onert
 
@@ -55,9 +53,7 @@ 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
index e0b0007..50984ce 100644 (file)
@@ -123,7 +123,7 @@ DataflowExecutor::DataflowExecutor(std::unique_ptr<compiler::LoweredGraph> lower
   _input_info = _initial_input_info;
 }
 
-void DataflowExecutor::executeImpl()
+void DataflowExecutor::executeImpl(const ExecutionObservee &subject)
 {
   assert(noWaitingJobs());
 
@@ -143,7 +143,7 @@ void DataflowExecutor::executeImpl()
 
   auto profiling_subg_index = _tracing_ctx->getSubgraphIndex(&_graph);
 
-  _subject.notifySubgraphBegin(profiling_subg_index);
+  subject.notifySubgraphBegin(profiling_subg_index);
 
   while (!_ready_jobs.empty())
   {
@@ -155,7 +155,7 @@ void DataflowExecutor::executeImpl()
     auto op_ind = _job_to_op[job_index];
     const backend::Backend *backend = _lowered_graph->lower_info().operation.at(op_ind).backend();
 
-    _subject.notifyJobBegin(this, profiling_subg_index, op_ind, backend);
+    subject.notifyJobBegin(this, profiling_subg_index, op_ind, backend);
 
     job->fn_seq()->initRunning();
 
@@ -166,13 +166,13 @@ void DataflowExecutor::executeImpl()
 
     job->run();
 
-    _subject.notifyJobEnd(this, profiling_subg_index, op_ind, backend);
+    subject.notifyJobEnd(this, profiling_subg_index, op_ind, backend);
     notify(job_index);
     _finished_jobs[job_index] = std::move(job);
   }
   assert(noWaitingJobs());
 
-  _subject.notifySubgraphEnd(profiling_subg_index);
+  subject.notifySubgraphEnd(profiling_subg_index);
 
   // Reset input info for the next execution
   _input_info = _initial_input_info;
index 1649be7..750dc24 100644 (file)
@@ -54,7 +54,7 @@ public:
                    const compiler::TensorRegistries &tensor_regs, compiler::CodeMap &&code_map,
                    const util::TracingCtx *tracing_ctx);
 
-  void executeImpl() override;
+  void executeImpl(const ExecutionObservee &subject) override;
 
 protected:
   int64_t calculateRank(const std::vector<ir::OperationIndex> &operations);
index 78b21cf..691a119 100644 (file)
@@ -423,11 +423,11 @@ void DynamicShapeInferer::visit(const ir::operation::Fill &op)
   assert(dims_buf);
 
   const auto &dims_shape = shape->getShape();
-  auto output_shape = ((dims_type == ir::DataType::INT32)
-                         ? shape_inference::inferFillShape<int32_t>(
-                             dims_shape, reinterpret_cast<const int32_t *>(dims_buf))
-                         : shape_inference::inferFillShape<int64_t>(
-                             dims_shape, reinterpret_cast<const int64_t *>(dims_buf)));
+  const auto &output_shape = ((dims_type == ir::DataType::INT32)
+                                ? shape_inference::inferFillShape<int32_t>(
+                                    dims_shape, reinterpret_cast<const int32_t *>(dims_buf))
+                                : shape_inference::inferFillShape<int64_t>(
+                                    dims_shape, reinterpret_cast<const int64_t *>(dims_buf)));
 
   output->applyShape(output_shape);
   assert(output->buffer() != nullptr);
@@ -705,6 +705,26 @@ void DynamicShapeInferer::visit(const ir::operation::Permute & /* op */)
   // on-the-fly, as it must support inter-backend inference/allocation.
 }
 
+void DynamicShapeInferer::visit(const ir::operation::Pool2D &op)
+{
+  // check if input is not dynamic
+  auto input_ind = op.getInputs().at(ir::operation::Pool2D::INPUT);
+  auto input = _tensor_registry->getITensor(input_ind);
+
+  if (!input->is_dynamic())
+    return;
+
+  ir::Shape input_shape = input->getShape();
+
+  auto output_ind = op.getOutputs().at(0);
+  auto output = _tensor_registry->getITensor(output_ind);
+
+  ir::Shape output_shape = shape_inference::inferPoolShape(input_shape, op.param());
+
+  output->applyShape(output_shape);
+  assert(output->buffer() != nullptr);
+}
+
 void DynamicShapeInferer::visit(const ir::operation::Pow &op)
 {
   handleBinaryArithmeticOp(op, op.getInputs().at(ir::operation::Pow::Input::LHS),
@@ -837,8 +857,8 @@ void DynamicShapeInferer::visit(const ir::operation::Reshape &op)
     int32_t *new_shape_buf = reinterpret_cast<int32_t *>(new_shape->buffer());
     assert(new_shape_buf);
 
-    auto output_shape = shape_inference::inferReshapeShape(
-      new_shape_buf, new_shape->getShape().num_elements(), input->getShape().num_elements());
+    auto output_shape = shape_inference::inferReshapeShape(input->getShape(), new_shape_buf,
+                                                           new_shape->getShape().num_elements());
 
     // if shape is changed, change output shape and reallocate output tensor memory
     if (output_shape != output->getShape() || output->buffer() == nullptr)
@@ -853,8 +873,8 @@ void DynamicShapeInferer::visit(const ir::operation::Reshape &op)
   {
     // Let's check the new_shape option
     auto shape = op.param().new_shape;
-    auto output_shape = shape_inference::inferReshapeShape(shape.data(), shape.size(),
-                                                           input->getShape().num_elements());
+    auto output_shape =
+      shape_inference::inferReshapeShape(input->getShape(), shape.data(), shape.size());
 
     // if shape is changed, change output shape and reallocate output tensor memory
     if (output_shape != output->getShape() || output->buffer() == nullptr)
diff --git a/runtime/onert/core/src/exec/EdgeTensor.cc b/runtime/onert/core/src/exec/EdgeTensor.cc
new file mode 100644 (file)
index 0000000..569a2f6
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "EdgeTensor.h"
+
+namespace onert
+{
+namespace exec
+{
+
+bool EdgeTensor::applyShape(const ir::Shape &new_shape)
+{
+  bool previously_dynamic = is_dynamic();
+  if (!previously_dynamic || _buffer == nullptr)
+  {
+    // Always set shape - when buffer with same size was already allocated, shape could differ
+    setShape(new_shape);
+    set_dynamic();
+    const auto total_size = get_info().total_size();
+    _buffer = std::make_unique<uint8_t[]>(total_size);
+  }
+  else
+  {
+    auto previous_size = total_size();
+    auto new_size = new_shape.num_elements() * ir::sizeOfDataType(data_type());
+    if (previous_size != new_size)
+    {
+      setShape(new_shape);
+      set_dynamic();
+      const auto total_size = get_info().total_size();
+      _buffer = std::make_unique<uint8_t[]>(total_size);
+    }
+    else
+    { // when buffer with same size was already allocated, shape could differ
+      setShape(new_shape);
+    }
+  }
+  return true;
+}
+
+} // namespace exec
+} // namespace onert
diff --git a/runtime/onert/core/src/exec/EdgeTensor.h b/runtime/onert/core/src/exec/EdgeTensor.h
new file mode 100644 (file)
index 0000000..8df79c3
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EDGE_TENSOR_H__
+#define __ONERT_EXEC_EDGE_TENSOR_H__
+
+#include "backend/IPortableTensor.h"
+
+#include <memory>
+
+namespace onert
+{
+namespace exec
+{
+
+class EdgeTensor : public backend::IPortableTensor
+{
+public:
+  EdgeTensor(const ir::OperandInfo &info, ir::Layout layout)
+    : IPortableTensor(info), _layout{layout}, _buffer{nullptr}, _ref_count{0}
+  {
+  }
+  ~EdgeTensor() = default;
+
+  uint8_t *buffer() const override { return _buffer.get(); }
+  ir::Layout layout() const override { return _layout; }
+  void set_dynamic() override { _info.setDynamic(); }
+  bool applyShape(const ir::Shape &new_shape) override;
+  void setShape(const ir::Shape &new_shape) override { _info.shape(new_shape); }
+
+  void allocate_buffer()
+  {
+    const auto total_size = _info.total_size();
+    _buffer = std::make_unique<uint8_t[]>(total_size);
+    _ref_count = 1;
+  }
+
+  void increase_ref() { _ref_count++; }
+
+  void decrease_ref()
+  {
+    assert(_ref_count > 0);
+    _ref_count--;
+    if (_ref_count == 0)
+    {
+      _buffer.reset();
+    }
+  }
+
+private:
+  ir::Layout _layout;
+  std::unique_ptr<uint8_t[]> _buffer;
+  int32_t _ref_count;
+};
+
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_EDGE_TENSOR_H__
index 1384c9f..895a82f 100644 (file)
@@ -16,8 +16,8 @@
 
 #include "exec/Execution.h"
 
+#include "ir/DataType.h"
 #include "train/TrainableExecutors.h"
-
 #include "util/logging.h"
 
 namespace onert
@@ -29,8 +29,19 @@ Execution::Execution(const std::shared_ptr<IExecutors> &executors) : _executors{
 {
   assert(executors != nullptr);
   assert(executors->entryExecutor() != nullptr);
-  _io_desc.inputs.resize(_executors->inputSize());
-  _io_desc.outputs.resize(_executors->outputSize());
+
+  // Initialize I/O description
+  _ctx.desc.inputs.resize(_executors->inputSize());
+  for (uint32_t i = 0; i < _executors->inputSize(); ++i)
+    _ctx.desc.inputs.at(i) = std::make_unique<InputDesc>(_executors->inputInfo(ir::IOIndex(i)));
+
+  _ctx.desc.outputs.resize(_executors->outputSize());
+  for (uint32_t i = 0; i < _executors->outputSize(); ++i)
+    _ctx.desc.outputs.at(i) = std::make_unique<OutputDesc>(_executors->outputInfo(ir::IOIndex(i)));
+  _ctx.shape_updated = false;
+
+  // Initialize options
+  ExecutionOptions::fromGlobalConfig(_ctx.options);
 }
 
 void Execution::changeInputShape(const ir::IOIndex &index, const ir::Shape &new_shape)
@@ -38,99 +49,96 @@ void Execution::changeInputShape(const ir::IOIndex &index, const ir::Shape &new_
   // This will be used later to set input tensor dynamic
   // Note that 'compiled' model will not be updated with new_shape
   // but new_shape will change model input shape while 'running' the model
-  _io_desc.dynamic_input_shapes[index] = new_shape;
-
-  VERBOSE(Execution) << "Model input shape will be changed at the start of execute()"
-                     << "(index: " << index << ")" << std::endl;
-}
-
-// TODO Remove default parameter
-void Execution::setInput(const ir::IOIndex &index, const void *buffer, size_t length,
-                         ir::Layout layout)
-{
-  const auto info = _executors->inputInfo(index);
-
-  // TODO handle when (!buffer && length != 0) : setting the input as an optional tensor
-
-  // check if size enough for input is passed
-  // if input_shape_sig is set, input_shape_sig overrides shape in info
-  // note: input_shape_sig contains shape passed by nnfw_set_input_tensorinfo()
+  auto &input_desc = _ctx.desc.inputs.at(index.value());
+  if (new_shape != input_desc->info.shape())
   {
-    auto input_shape_sig = _io_desc.dynamic_input_shapes.find(index);
-    auto size_required =
-      (input_shape_sig != _io_desc.dynamic_input_shapes.end())
-        ? input_shape_sig->second.num_elements() * onert::ir::sizeOfDataType(info.typeInfo().type())
-        : info.total_size();
+    input_desc->info.shape(new_shape);
+    _ctx.shape_updated = true;
 
-    if (length < size_required)
-    {
-      throw std::runtime_error{"Too small length"};
-    }
+    VERBOSE(Execution) << "Model input shape will be changed at the start of execute()"
+                       << "(index: " << index << ")" << std::endl;
   }
-
-  _io_desc.inputs.at(index.value()) = std::make_unique<InputDesc>(info, buffer, length, layout);
 }
 
 // TODO Remove default parameter
-void Execution::setInput(const ir::IOIndex &index, const ir::TypeInfo &type, const ir::Shape &shape,
-                         const void *buffer, size_t length, ir::Layout layout)
+void Execution::setInput(const ir::IOIndex &index, const void *buffer, size_t length)
 {
-  auto info = ir::OperandInfo::createStaticInfo(shape, type);
-
-  if (length < info.total_size())
-  {
-    throw std::runtime_error{"Too small length"};
-  }
-
-  _io_desc.inputs.at(index.value()) = std::make_unique<InputDesc>(info, buffer, length, layout);
+  // Length validation in execute(): datatype can be changed by API call
+  auto &input_desc = _ctx.desc.inputs.at(index.value());
+  input_desc->buffer = buffer;
+  input_desc->size = length;
 }
 
-// TODO Remove default parameter
-void Execution::setOutput(const ir::IOIndex &index, void *buffer, size_t length, ir::Layout layout)
+void Execution::setInput(const ir::IOIndex &index, const ir::Shape &shape, const void *buffer,
+                         size_t length)
 {
-  const auto info = _executors->outputInfo(index);
-
-  if (length < info.total_size())
-  {
-    throw std::runtime_error{"Too small length"};
-  }
-
-  _io_desc.outputs.at(index.value()) = std::make_unique<OutputDesc>(info, buffer, length, layout);
+  changeInputShape(index, shape);
+  setInput(index, buffer, length);
 }
 
-// TODO Remove default parameter
-void Execution::setOutput(const ir::IOIndex &index, const ir::TypeInfo &type,
-                          const ir::Shape &shape, void *buffer, size_t length, ir::Layout layout)
+void Execution::setOutput(const ir::IOIndex &index, void *buffer, size_t length)
 {
-  auto info = ir::OperandInfo::createStaticInfo(shape, type);
+  // Length validation in execute()
+  // - datatype can be changed by API call
+  // - shape can be changed by dynamic shape inference
+  auto &output_desc = _ctx.desc.outputs.at(index.value());
+  output_desc->buffer = buffer;
+  output_desc->size = length;
+}
 
-  if (length < info.total_size())
-  {
-    throw std::runtime_error{"Too small length"};
-  }
+void Execution::setOutput(const ir::IOIndex &index, const ir::Shape &shape, void *buffer,
+                          size_t length)
+{
+  auto &output_desc = _ctx.desc.outputs.at(index.value());
+  output_desc->info.shape(shape);
 
-  _io_desc.outputs.at(index.value()) = std::make_unique<OutputDesc>(info, buffer, length, layout);
+  setOutput(index, buffer, length);
 }
 
 void Execution::setInputLayout(const ir::IOIndex &index, ir::Layout layout)
 {
-  const auto &input_desc = _io_desc.inputs.at(index.value());
-  _io_desc.inputs.at(index.value()) =
-    std::make_unique<InputDesc>(input_desc->info, input_desc->buffer, input_desc->size, layout);
+  _ctx.desc.inputs.at(index.value())->layout = layout;
 }
 
 void Execution::setOutputLayout(const ir::IOIndex &index, ir::Layout layout)
 {
-  const auto &output_desc = _io_desc.outputs.at(index.value());
-  _io_desc.outputs.at(index.value()) =
-    std::make_unique<OutputDesc>(output_desc->info, output_desc->buffer, output_desc->size, layout);
+  _ctx.desc.outputs.at(index.value())->layout = layout;
+}
+
+void Execution::setInputType(const ir::IOIndex &index, const ir::TypeInfo &typeInfo)
+{
+  _ctx.desc.inputs.at(index.value())->info.typeInfo(typeInfo);
+  _ctx.shape_updated = true;
+}
+
+void Execution::setOutputType(const ir::IOIndex &index, const ir::TypeInfo &typeInfo)
+{
+  _ctx.desc.outputs.at(index.value())->info.typeInfo(typeInfo);
+  _ctx.shape_updated = true;
 }
 
 void Execution::execute()
 {
   VERBOSE(Execution) << "Start execution" << std::endl;
 
-  _executors->execute(_io_desc);
+  // Input length validation check
+  for (const auto &input : _ctx.desc.inputs)
+  {
+    if (input->info.total_size() > input->size)
+      throw std::runtime_error{"Too small input buffer length"};
+  }
+
+  // Output length validation check
+  if (!_ctx.shape_updated)
+  {
+    for (const auto &output : _ctx.desc.outputs)
+    {
+      if (output->info.total_size() > output->size)
+        throw std::runtime_error{"Too small output buffer length"};
+    }
+  }
+
+  _executors->execute(_ctx);
   finished = true;
 
   VERBOSE(Execution) << "Execution finished" << std::endl;
@@ -153,7 +161,6 @@ 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());
@@ -162,12 +169,8 @@ void Execution::train(uint32_t training_step)
     throw std::runtime_error{"Supported only TrainableExecutors"};
   }
 
-  VERBOSE(Execution) << "Start training" << std::endl;
-
-  execs->train(_io_desc, training_step);
+  execs->train(_ctx, training_step);
   finished = true;
-
-  VERBOSE(Execution) << "training finished" << std::endl;
 }
 
 float Execution::getLoss(const ir::IOIndex &ind)
@@ -180,19 +183,22 @@ float Execution::getLoss(const ir::IOIndex &ind)
 
   return execs->getLoss(ind);
 }
-#endif // ONERT_TRAIN
 
-ir::Shape Execution::getInputShape(ir::IOIndex ind) const
+void Execution::iterateTrainableTensors(
+  const std::function<void(const ir::OperandIndex &, const backend::train::ITrainableTensor *)> &fn)
+  const
 {
-  auto itr = _io_desc.dynamic_input_shapes.find(ind);
-  if (itr == _io_desc.dynamic_input_shapes.end())
-  {
-    return _executors->inputInfo(ind).shape();
-  }
-  else
+  auto execs = dynamic_cast<exec::train::TrainableExecutors *>(_executors.get());
+  if (!execs)
   {
-    return itr->second;
+    throw std::runtime_error{"Supported only TrainableExecutors"};
   }
+  execs->iterateTrainableTensors(fn);
+}
+
+ir::Shape Execution::getInputShape(ir::IOIndex ind) const
+{
+  return _ctx.desc.inputs.at(ind.value())->info.shape();
 }
 
 // NNAPI return fail if ANeuralNetworksExecution_getOutputOperandRank or
@@ -203,23 +209,18 @@ ir::Shape Execution::getInputShape(ir::IOIndex ind) const
 // NNAPI frontend.
 ir::Shape Execution::getOutputShape(ir::IOIndex ind) const
 {
-  if (!isFinished())
-    return _executors->outputInfo(ind).shape();
-
-  const auto &output_desc = _io_desc.outputs.at(ind.value());
-
-  return output_desc->info.shape();
+  return _ctx.desc.outputs.at(ind.value())->info.shape();
 }
 
 size_t Execution::getInputTotalSize(ir::IOIndex ind) const
 {
   // TODO Support dynamic shape
-  return _executors->inputInfo(ind).total_size();
+  return _ctx.desc.inputs.at(ind.value())->info.total_size();
 }
 
 size_t Execution::getOutputTotalSize(ir::IOIndex ind) const
 {
-  return _executors->outputInfo(ind).total_size();
+  return _ctx.desc.outputs.at(ind.value())->info.total_size();
 }
 
 } // namespace exec
index fefe8a3..15f9444 100644 (file)
@@ -81,7 +81,7 @@ public:
     auto model = std::make_shared<onert::ir::Model>();
     model->push(onert::ir::SubgraphIndex{0}, graph);
     coptions = onert::compiler::CompilerOptions::fromGlobalConfig();
-    onert::compiler::Compiler compiler{model, *coptions};
+    onert::compiler::Compiler compiler{model, coptions.get()};
     artifact = compiler.compile();
   }
 
@@ -212,11 +212,10 @@ public:
   void compile()
   {
     auto nnpkg = std::make_shared<onert::ir::NNPkg>();
-    coptions.clear();
+    coptions = onert::compiler::CompilerOptions::fromGlobalConfig();
+
     for (uint16_t i = 0; i < graphs.size(); ++i)
     {
-      coptions.emplace_back(onert::compiler::CompilerOptions::fromGlobalConfig());
-
       auto model = std::make_shared<onert::ir::Model>();
       model->push(SubgraphIndex{0}, graphs[i]);
 
@@ -234,18 +233,79 @@ public:
     {
       nnpkg->addEdge(edge.from, edge.to);
     }
-    auto compiler = onert::compiler::CompilerFactory::get().create(nnpkg, coptions);
+    auto compiler = onert::compiler::CompilerFactory::get().create(nnpkg, coptions.get());
     nnpkg.reset();
     artifact = compiler->compile();
   }
 
 public:
   std::vector<std::shared_ptr<Graph>> graphs;
-  std::vector<std::unique_ptr<onert::compiler::CompilerOptions>> coptions;
+  std::unique_ptr<onert::compiler::CompilerOptions> coptions;
   std::shared_ptr<onert::compiler::CompilerArtifact> artifact;
   ModelEdges edges;
 };
 
+class CompiledMockUpQuantModel
+{
+public:
+  CompiledMockUpQuantModel()
+  {
+    // Model: two elementwise add operation
+    // model input: lhs, rhs1
+    // model output: second add result (result2)
+    // constant: rhs2
+    // result1 <= (lhs + rhs)
+    // result2 <= (result1 + rhs2)
+    // lhs, rhs1, rh2, result1, result2 shape: {1, 2, 2, 1}
+    // activation: none (constant)
+    graph = std::make_shared<Graph>();
+    // 1st add operands (result1 <= lhs + rhs1)
+    Shape shape{1, 2, 2, 1};
+    TypeInfo type{DataType::QUANT_UINT8_ASYMM, 1.0f, 128};
+    static uint8_t rhs2_data[4] = {131, 129, 127, 133};
+    auto operand_lhs = graph->addOperand(shape, type);
+    auto operand_rhs1 = graph->addOperand(shape, type);
+    auto operand_result1 = graph->addOperand(shape, type);
+    auto operand_rhs2 = graph->addOperand(shape, type);
+    auto operand_result2 = graph->addOperand(shape, type);
+    graph->operands()
+      .at(operand_rhs2)
+      .data(std::make_unique<CachedData>(reinterpret_cast<const uint8_t *>(&rhs2_data), 4));
+    // 2nd add operations (result2 <= result1 + rhs2)
+    operation::BinaryArithmetic::Param param1;
+    param1.arithmetic_type = operation::BinaryArithmetic::ArithmeticType::ADD;
+    param1.activation = Activation::NONE;
+    auto input_set1 = OperandIndexSequence{operand_lhs, operand_rhs1};
+    auto output_set1 = OperandIndexSequence{operand_result1};
+    graph->addOperation(
+      std::make_unique<operation::BinaryArithmetic>(input_set1, output_set1, param1));
+    operation::BinaryArithmetic::Param param2;
+    param2.arithmetic_type = operation::BinaryArithmetic::ArithmeticType::ADD;
+    param2.activation = Activation::NONE;
+    auto input_set2 = OperandIndexSequence{operand_result1, operand_rhs2};
+    auto output_set2 = OperandIndexSequence{operand_result2};
+    graph->addOperation(
+      std::make_unique<operation::BinaryArithmetic>(input_set2, output_set2, param2));
+    // Identify model inputs and outputs
+    graph->addInput(operand_lhs);
+    graph->addInput(operand_rhs1);
+    graph->addOutput(operand_result2);
+    graph->verify();
+
+    // Compile
+    auto model = std::make_shared<onert::ir::Model>();
+    model->push(onert::ir::SubgraphIndex{0}, graph);
+    coptions = onert::compiler::CompilerOptions::fromGlobalConfig();
+    onert::compiler::Compiler compiler{model, coptions.get()};
+    artifact = compiler.compile();
+  }
+
+public:
+  std::shared_ptr<Graph> graph;
+  std::unique_ptr<onert::compiler::CompilerOptions> coptions;
+  std::shared_ptr<onert::compiler::CompilerArtifact> artifact;
+};
+
 TEST(ExecInstance, simple)
 {
   auto mockup = CompiledMockUpModel();
@@ -274,6 +334,60 @@ TEST(ExecInstance, simple)
   }
 }
 
+TEST(ExecInstance, neg_small_outputbuffer)
+{
+  auto mockup = CompiledMockUpModel();
+  auto graph = mockup.graph;
+  auto executors = mockup.artifact->_executors;
+
+  auto input1 = IOIndex{0};
+  auto input2 = IOIndex{1};
+  auto output = IOIndex{0};
+
+  const float input1_buffer[4] = {1, 0, -1, -2};
+  const float input2_buffer[4] = {1, -3, 2, -4};
+  float output_buffer[2] = {};
+
+  onert::exec::Execution execution{executors};
+
+  execution.setInput(input1, reinterpret_cast<const void *>(input1_buffer), 16);
+  execution.setInput(input2, reinterpret_cast<const void *>(input2_buffer), 16);
+  execution.setOutput(output, reinterpret_cast<void *>(output_buffer), 8);
+  EXPECT_ANY_THROW(execution.execute());
+}
+
+TEST(ExecInstance, neg_small_inoutsize)
+{
+  auto mockup = CompiledMockUpModel();
+  auto graph = mockup.graph;
+  auto executors = mockup.artifact->_executors;
+
+  auto input1 = IOIndex{0};
+  auto input2 = IOIndex{1};
+  auto output = IOIndex{0};
+
+  const float input1_buffer[2] = {1, 0};
+  const float input2_buffer[2] = {1, -3};
+  const auto new_shape = onert::ir::Shape({1, 1, 2, 1});
+  float output_buffer[2] = {};
+
+  onert::exec::Execution execution{executors};
+
+  execution.setInput(input1, new_shape, reinterpret_cast<const void *>(input1_buffer), 8);
+  execution.setInput(input2, new_shape, reinterpret_cast<const void *>(input2_buffer), 2);
+  EXPECT_THROW(execution.execute(), std::exception);
+
+  // Not throw exception because input shape is changed and output buffer is enough
+  execution.setInput(input2, new_shape, reinterpret_cast<const void *>(input2_buffer), 8);
+  execution.setOutput(output, reinterpret_cast<void *>(output_buffer), 16);
+  execution.execute();
+
+  execution.setOutput(output, reinterpret_cast<void *>(output_buffer), 8);
+  // Throw exception by shape inference because output buffer size is small:
+  // output shape is {1, 2, 2, 1}
+  EXPECT_THROW(execution.execute(), std::exception);
+}
+
 TEST(ExecInstance, twoCompile)
 {
   auto mockup = CompiledMockUpModel();
@@ -298,7 +412,7 @@ TEST(ExecInstance, twoCompile)
   auto model = std::make_shared<onert::ir::Model>();
   model->push(onert::ir::SubgraphIndex{0}, graph);
   auto coptions = onert::compiler::CompilerOptions::fromGlobalConfig();
-  onert::compiler::Compiler compiler{model, *coptions};
+  onert::compiler::Compiler compiler{model, coptions.get()};
   std::shared_ptr<onert::compiler::CompilerArtifact> artifact = compiler.compile();
   onert::exec::Execution execution2{artifact->_executors};
 
@@ -361,6 +475,37 @@ TEST(ExecInstance, twoExecution)
   }
 }
 
+TEST(ExecInstance, quantModel_floatIO)
+{
+  auto mockup = CompiledMockUpQuantModel();
+  auto graph = mockup.graph;
+  auto executors = mockup.artifact->_executors;
+
+  auto input1 = IOIndex{0};
+  auto input2 = IOIndex{1};
+  auto output = IOIndex{0};
+
+  const float input1_buffer[4] = {1, 0, -1, -2};
+  const float input2_buffer[4] = {1, -3, 2, -4};
+  float output_buffer[4] = {};
+  const float output_expected[4] = {5, -2, 0, -1};
+
+  onert::exec::Execution execution{executors};
+
+  execution.setInput(input1, reinterpret_cast<const void *>(input1_buffer), 16);
+  execution.setInput(input2, reinterpret_cast<const void *>(input2_buffer), 16);
+  execution.setOutput(output, reinterpret_cast<void *>(output_buffer), 16);
+  execution.setInputType(input1, onert::ir::TypeInfo{onert::ir::DataType::FLOAT32});
+  execution.setInputType(input2, onert::ir::TypeInfo{onert::ir::DataType::FLOAT32});
+  execution.setOutputType(output, onert::ir::TypeInfo{onert::ir::DataType::FLOAT32});
+  execution.execute();
+
+  EXPECT_EQ(output_buffer[0], output_expected[0]);
+  EXPECT_EQ(output_buffer[1], output_expected[1]);
+  EXPECT_EQ(output_buffer[2], output_expected[2]);
+  EXPECT_EQ(output_buffer[3], output_expected[3]);
+}
+
 class Inference
 {
 public:
@@ -616,12 +761,15 @@ TEST(ExecInstance, multi_model_dequant_input_quant_output)
   onert::exec::Execution execution{executors};
 
   onert::ir::TypeInfo type_info{onert::ir::DataType::QUANT_UINT8_ASYMM, scale, zero_point};
-  execution.setInput(input1, type_info, execution.getInputShape(input1),
-                     reinterpret_cast<const void *>(input1_buffer), 4, onert::ir::Layout::NHWC);
-  execution.setInput(input2, type_info, execution.getInputShape(input2),
-                     reinterpret_cast<const void *>(input2_buffer), 4, onert::ir::Layout::NHWC);
-  execution.setOutput(output, type_info, execution.getOutputShape(output),
-                      reinterpret_cast<void *>(output_buffer), 4, onert::ir::Layout::NHWC);
+  execution.setInputType(input1, type_info);
+  execution.setInput(input1, execution.getInputShape(input1),
+                     reinterpret_cast<const void *>(input1_buffer), 4);
+  execution.setInputType(input2, type_info);
+  execution.setInput(input2, execution.getInputShape(input2),
+                     reinterpret_cast<const void *>(input2_buffer), 4);
+  execution.setOutputType(output, type_info);
+  execution.setOutput(output, execution.getOutputShape(output),
+                      reinterpret_cast<void *>(output_buffer), 4);
   execution.execute();
 
   for (auto i = 0; i < 4; i++)
diff --git a/runtime/onert/core/src/exec/ExecutionContext.cc b/runtime/onert/core/src/exec/ExecutionContext.cc
new file mode 100644 (file)
index 0000000..aec10ee
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/ExecutionContext.h"
+
+#include "util/ConfigSource.h"
+
+namespace onert
+{
+namespace exec
+{
+
+void ExecutionOptions::fromGlobalConfig(ExecutionOptions &options)
+{
+  options.dump_minmax = util::getConfigBool(util::config::MINMAX_DUMP);
+  options.trace = util::getConfigBool(util::config::TRACING_MODE);
+  options.profile = util::getConfigBool(util::config::PROFILING_MODE);
+}
+
+} // namespace exec
+} // namespace onert
index 66610f0..22881b8 100644 (file)
@@ -21,12 +21,40 @@ namespace onert
 namespace exec
 {
 
-void ExecutionObservee::add(std::unique_ptr<IExecutionObserver> observer)
+ExecutionObservee::ExecutionObservee(const ExecObservers &observers,
+                                     const ExecutionOptions &options)
 {
-  _observers.emplace_back(std::move(observer));
+  // TODO Use execution option
+  if (options.dump_minmax)
+  {
+    auto observer = observers.get(ObserverType::MINMAX_DUMP);
+    if (!observer)
+      throw std::runtime_error{"MinMaxRecorder is only supported on LinearExecutor, single model"};
+
+    _observers.emplace_back(observer);
+  }
+
+  if (options.trace)
+  {
+    auto observer = observers.get(ObserverType::TRACING);
+    if (!observer)
+      throw std::runtime_error{"Cannot find TracingObserver"};
+
+    _observers.emplace_back(observer);
+  }
+
+  if (options.profile)
+  {
+    auto observer = observers.get(ObserverType::PROFILE);
+    if (!observer)
+      throw std::runtime_error{
+        "Profiling is only supported on DataflowExecutor with heterogenous scheduler"};
+
+    _observers.emplace_back(observer);
+  }
 }
 
-void ExecutionObservee::notifySubgraphBegin(ir::SubgraphIndex ind)
+void ExecutionObservee::notifySubgraphBegin(ir::SubgraphIndex ind) const
 {
   for (auto &&o : _observers)
   {
@@ -34,7 +62,7 @@ void ExecutionObservee::notifySubgraphBegin(ir::SubgraphIndex ind)
   }
 }
 
-void ExecutionObservee::notifySubgraphEnd(ir::SubgraphIndex ind)
+void ExecutionObservee::notifySubgraphEnd(ir::SubgraphIndex ind) const
 {
   for (auto &&o : _observers)
   {
@@ -43,7 +71,8 @@ void ExecutionObservee::notifySubgraphEnd(ir::SubgraphIndex ind)
 }
 
 void ExecutionObservee::notifyJobBegin(IExecutor *executor, ir::SubgraphIndex subg_ind,
-                                       ir::OperationIndex op_ind, const backend::Backend *backend)
+                                       ir::OperationIndex op_ind,
+                                       const backend::Backend *backend) const
 {
   for (auto &&o : _observers)
   {
@@ -52,7 +81,8 @@ void ExecutionObservee::notifyJobBegin(IExecutor *executor, ir::SubgraphIndex su
 }
 
 void ExecutionObservee::notifyJobEnd(IExecutor *executor, ir::SubgraphIndex subg_ind,
-                                     ir::OperationIndex op_ind, const backend::Backend *backend)
+                                     ir::OperationIndex op_ind,
+                                     const backend::Backend *backend) const
 {
   for (auto &&o : _observers)
   {
index 3ee1754..e6461c7 100644 (file)
@@ -36,20 +36,21 @@ class ExecutionObservee
 {
 public:
   /**
-   * @brief Register an observer
+   * @brief Register enabled observers
    *
-   * @param observer Observer to be added
+   * @param observer Observers generated by compiler
    */
-  void add(std::unique_ptr<IExecutionObserver> observer);
-  void notifySubgraphBegin(ir::SubgraphIndex ind);
-  void notifySubgraphEnd(ir::SubgraphIndex ind);
+  ExecutionObservee(const ExecObservers &observers, const ExecutionOptions &options);
+  void notifySubgraphBegin(ir::SubgraphIndex ind) const;
+  void notifySubgraphEnd(ir::SubgraphIndex ind) const;
   void notifyJobBegin(IExecutor *executor, ir::SubgraphIndex subg_ind, ir::OperationIndex op_ind,
-                      const backend::Backend *backend);
+                      const backend::Backend *backend) const;
   void notifyJobEnd(IExecutor *executor, ir::SubgraphIndex subg_ind, ir::OperationIndex op_ind,
-                    const backend::Backend *backend);
+                    const backend::Backend *backend) const;
+  bool isEmpty() const { return _observers.size() == 0; }
 
 private:
-  std::list<std::unique_ptr<IExecutionObserver>> _observers;
+  std::list<IExecutionObserver *> _observers;
 };
 
 } // namespace exec
index 5245518..a58daea 100644 (file)
@@ -113,20 +113,25 @@ void ProfileObserver::handleJobEnd(IExecutor *exec, ir::SubgraphIndex,
   }
 };
 
-TracingObserver::TracingObserver(const std::string &filepath, const ir::Graph &graph,
+TracingObserver::TracingObserver(const std::string &workspace_dir, const ir::Graph &graph,
                                  const util::TracingCtx *tracing_ctx)
   : _recorder{std::make_unique<EventRecorder>()}, _collector{_recorder.get()}, _graph{graph},
-    _tracing_ctx{tracing_ctx}
+    _workspace_dir{workspace_dir}, _tracing_ctx{tracing_ctx}, _triggered{false}
 {
-  _event_writer = EventWriter::get(filepath);
-  _event_writer->startToUse();
+  // DO NOTHING
 }
 
 TracingObserver::~TracingObserver()
 {
   try
   {
-    _event_writer->readyToFlush(std::move(_recorder));
+    // Write file if this observer is triggered at least once
+    if (_triggered)
+    {
+      auto event_writer = EventWriter::get(_workspace_dir);
+      event_writer->startToUse();
+      event_writer->readyToFlush(std::move(_recorder));
+    }
   }
   catch (const std::exception &e)
   {
@@ -136,6 +141,8 @@ TracingObserver::~TracingObserver()
 
 void TracingObserver::handleSubgraphBegin(ir::SubgraphIndex subg_ind)
 {
+  _triggered = true;
+
   _collector.onEvent(
     EventCollector::SubgEvent{_tracing_ctx, EventCollector::Edge::BEGIN, subg_ind.value()});
 }
index 7e93ecf..e59d587 100644 (file)
@@ -32,6 +32,14 @@ namespace onert
 {
 namespace exec
 {
+
+enum class ObserverType
+{
+  PROFILE,
+  TRACING,
+  MINMAX_DUMP,
+};
+
 class IExecutionObserver
 {
 public:
@@ -46,9 +54,31 @@ public:
   /// @brief Invoked just after model (not individual operation) execution ends
   virtual void handleSubgraphEnd(ir::SubgraphIndex) { return; }
 
+  virtual ObserverType type() const = 0;
+
   virtual ~IExecutionObserver() = default;
 };
 
+class ExecObservers
+{
+public:
+  void add(std::unique_ptr<IExecutionObserver> &&observer)
+  {
+    _observers.emplace(observer->type(), std::move(observer));
+  }
+
+  IExecutionObserver *get(ObserverType type) const
+  {
+    if (_observers.find(type) != _observers.end())
+      return _observers.at(type).get();
+
+    return nullptr;
+  }
+
+private:
+  std::unordered_map<ObserverType, std::unique_ptr<IExecutionObserver>> _observers;
+};
+
 class ProfileObserver : public IExecutionObserver
 {
 public:
@@ -62,6 +92,7 @@ public:
                     const backend::Backend *) override;
 
   void handleSubgraphEnd(ir::SubgraphIndex) override { _et->storeOperationsExecTime(); }
+  ObserverType type() const override { return ObserverType::PROFILE; }
 
 private:
   std::unique_ptr<util::ITimer> _timer;
@@ -72,7 +103,7 @@ private:
 class TracingObserver : public IExecutionObserver
 {
 public:
-  TracingObserver(const std::string &filepath, const ir::Graph &graph,
+  TracingObserver(const std::string &workspace_dir, const ir::Graph &graph,
                   const util::TracingCtx *tracing_ctx);
   ~TracingObserver();
   void handleSubgraphBegin(ir::SubgraphIndex) override;
@@ -81,13 +112,15 @@ public:
   void handleJobEnd(IExecutor *, ir::SubgraphIndex, ir::OperationIndex,
                     const backend::Backend *) override;
   void handleSubgraphEnd(ir::SubgraphIndex) override;
+  ObserverType type() const override { return ObserverType::TRACING; }
 
 private:
   std::unique_ptr<EventRecorder> _recorder;
   EventCollector _collector;
   const ir::Graph &_graph;
-  EventWriter *_event_writer;
+  std::string _workspace_dir;
   const util::TracingCtx *_tracing_ctx;
+  bool _triggered;
 };
 
 } // namespace exec
index ad00734..2526e4e 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "ShapeConverter.h"
 
+#include "util/ConfigSource.h"
 #include <misc/polymorphic_downcast.h>
 
 namespace onert
@@ -29,9 +30,8 @@ ExecutorBase::ExecutorBase(std::unique_ptr<compiler::LoweredGraph> &&lowered_gra
                            backend::BackendContexts &&backend_contexts,
                            const compiler::TensorRegistries &tensor_regs,
                            const util::TracingCtx *tracing_ctx)
-  : _lowered_graph{std::move(lowered_graph)},
-    _backend_contexts{std::move(backend_contexts)}, _graph{_lowered_graph->graph()}, _mutex(),
-    _tracing_ctx(tracing_ctx)
+  : _lowered_graph{std::move(lowered_graph)}, _backend_contexts{std::move(backend_contexts)},
+    _graph{_lowered_graph->graph()}, _mutex(), _tracing_ctx(tracing_ctx)
 {
   auto build_tensor_list = [&](const auto &ind_seq, auto &tensors) {
     assert(tensors.empty());
@@ -48,38 +48,24 @@ ExecutorBase::ExecutorBase(std::unique_ptr<compiler::LoweredGraph> &&lowered_gra
 }
 
 void ExecutorBase::execute(const std::vector<backend::IPortableTensor *> &inputs,
-                           const std::vector<backend::IPortableTensor *> &outputs)
+                           const std::vector<backend::IPortableTensor *> &outputs,
+                           const ExecutionOptions &options)
 {
   // 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)
   // Deadlock occurs when an Executor is called recursively.
   std::lock_guard<std::mutex> lock(_mutex);
+  _current_options = options;
 
   assert(inputs.size() == _graph.getInputs().size());
   assert(inputs.size() == _input_tensors.size());
   for (uint32_t n = 0; n < inputs.size(); ++n)
   {
     const auto input = inputs[n];
-    assert(input->buffer() != nullptr);
+    assert(input->buffer() != nullptr || input->get_info().total_size() == 0);
     auto input_tensor = _input_tensors[n];
     assert(input_tensor != nullptr);
-    if (input != nullptr)
-    {
-      const auto orig_input_shape = input_tensor->orig_info().shape();
-      const auto changed_input_shape =
-        convertShape(input->getShape(), input->layout(), input_tensor->orig_layout());
-      if (input_tensor->get_info().shape() != changed_input_shape)
-      {
-        // TODO Fix this workaround that is introduced since cpu based kernels directly use `_info`
-        // rather than interface methods to avoid virtual function calls.
-        input_tensor->setShapeOfIPortableTensor(changed_input_shape);
-      }
-      if (orig_input_shape != changed_input_shape)
-      {
-        input_tensor->set_dynamic();
-      }
-    }
     input_tensor->setTensor(input);
   }
 
@@ -88,90 +74,16 @@ void ExecutorBase::execute(const std::vector<backend::IPortableTensor *> &inputs
   for (uint32_t n = 0; n < outputs.size(); ++n)
   {
     const auto output = outputs[n];
-    // assert(dst_tensor->buffer() != nullptr);
+    assert(output->buffer() != nullptr || output->get_info().total_size() == 0);
     auto output_tensor = _output_tensors[n];
     assert(output_tensor != nullptr);
     output_tensor->setTensor(output);
   }
 
-  executeImpl();
-}
-
-void ExecutorBase::execute(const IODescription &desc)
-{
-  // 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);
-
-  // 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);
-
-    auto input_shape = desc.dynamic_input_shapes.find(ir::IOIndex{i});
-    if (input_shape != desc.dynamic_input_shapes.end())
-    {
-      tensor->set_dynamic();
-      tensor->setShape(input_shape->second);
-      /*
-       * Changes tensor shape and allocate memory since its shape was changed
-       * perhaps by nnfw_set_input_tensorinfo()
-       *
-       * Cases are:
-       * 1) static operand -> nnfw_set_input_tensorinfo() -> execute() -> execute()
-       *                                                 (a)          (b)
-       *
-       * at (a), operand is static, tensor is static - memory dealloc is not needed
-       *   (DynamicTensorManager cannot dealloc memory allocated by StaticTensorManager)
-       * at (b), operand is static, tensor is dynamic - memory dealloc is needed
-       *
-       * 2) dynamic operand -> nnfw_set_input_tensorinfo() -> execute() -> execute()
-       *                                                  (a)          (b)
-       *
-       * at (a), operand is dynamic, tensor is dynamic - memory dealloc is not needed
-       *                                       since it has not been allocated yet
-       * at (b), operand is dynamic, tensor is dynamic - memory dealloc is needed
-       */
-      tensor->applyShape(input_shape->second);
-    }
-  }
-
-  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);
-    tensor->set_dynamic(); // It can't be resized but shape could change
-  }
+  // Create observee
+  ExecutionObservee subject(_observers, options);
 
-  executeImpl();
-
-  // Update output(s) desc
-  for (uint32_t n = 0; n < _graph.getOutputs().size(); ++n)
-  {
-    ir::IOIndex output_index{n};
-    // Optional output
-    if (desc.outputs.at(n) == nullptr)
-    {
-      continue;
-    }
-    auto &output = *desc.outputs.at(n);
-
-    // set shape of outputDesc to tensor shape since tensor can be dynamic
-    const auto output_tensor_shape = _output_tensors[n]->getShape();
-    output.info.shape(
-      convertShape(output_tensor_shape, _output_tensors[n]->layout(), output.layout));
-  }
+  executeImpl(subject);
 }
 
 bool ExecutorBase::hasDynamicInput()
index 4f97de9..2ae63dd 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "compiler/LoweredGraph.h"
 #include "exec/IExecutor.h"
-#include "exec/IODescription.h"
+#include "exec/ExecutionContext.h"
 #include "ir/Graph.h"
 #include "ir/OperationIndexMap.h"
 #include "util/TracingCtx.h"
@@ -53,32 +53,45 @@ public:
 
   const ir::Graph &graph() const final { return _graph; }
 
-  void execute(const IODescription &desc) final;
-
   void execute(const std::vector<backend::IPortableTensor *> &inputs,
-               const std::vector<backend::IPortableTensor *> &outputs) override;
+               const std::vector<backend::IPortableTensor *> &outputs,
+               const ExecutionOptions &options) override;
 
-  // Used only in Dataflow and Parallel Executors
-  void setIndexedRanks(std::shared_ptr<ir::OperationIndexMap<int64_t>> ranks) final
-  {
-    _indexed_ranks = std::move(ranks);
-  };
+  uint32_t inputSize() const override { return _input_tensors.size(); }
 
-  virtual void executeImpl(void) = 0;
+  uint32_t outputSize() const override { return _output_tensors.size(); }
 
-  void addObserver(std::unique_ptr<IExecutionObserver> ref) { _subject.add(std::move(ref)); };
+  const ir::OperandInfo &inputInfo(uint32_t index) const override
+  {
+    return _input_tensors[index]->get_info();
+  }
 
-  const std::vector<backend::builtin::IOTensor *> &getInputTensors() const override
+  const ir::OperandInfo &outputInfo(uint32_t index) const override
   {
-    return _input_tensors;
+    return _output_tensors[index]->get_info();
   }
 
-  const std::vector<backend::builtin::IOTensor *> &getOutputTensors() const override
+  ir::Layout inputLayout(uint32_t index) const override { return _input_tensors[index]->layout(); }
+
+  ir::Layout outputLayout(uint32_t index) const override
   {
-    return _output_tensors;
+    return _output_tensors[index]->layout();
   }
+
+  // Used only in Dataflow and Parallel Executors
+  void setIndexedRanks(std::shared_ptr<ir::OperationIndexMap<int64_t>> ranks) final
+  {
+    _indexed_ranks = std::move(ranks);
+  };
+
+  virtual void executeImpl(const ExecutionObservee &subject) = 0;
+
+  void addObserver(std::unique_ptr<IExecutionObserver> ref) { _observers.add(std::move(ref)); };
+
   backend::BackendContexts &getBackendContexts() { return _backend_contexts; }
 
+  const ExecutionOptions &currentOptions() const override { return _current_options; }
+
 protected:
   /**
    * @brief Returns @c true if any input tensor is dynamic; @c false if all are static tensors
@@ -86,7 +99,7 @@ protected:
   bool hasDynamicInput();
 
 protected:
-  ExecutionObservee _subject;
+  ExecObservers _observers;
   std::shared_ptr<ir::OperationIndexMap<int64_t>> _indexed_ranks;
   std::unique_ptr<compiler::LoweredGraph> _lowered_graph;
   backend::BackendContexts _backend_contexts;
@@ -95,6 +108,14 @@ protected:
   std::vector<backend::builtin::IOTensor *> _output_tensors;
   std::mutex _mutex;
   const util::TracingCtx *_tracing_ctx;
+  /**
+   * It is set by execute() method only in thread-safe environment.
+   * It is used for non-primary executor call on builtin backend
+   * and accessed by entryExecutor's currentOptions() method.
+   *
+   * TODO: Find better way to pass config to non-primary executor
+   */
+  ExecutionOptions _current_options;
 };
 
 } // namespace exec
diff --git a/runtime/onert/core/src/exec/Executors.cc b/runtime/onert/core/src/exec/Executors.cc
deleted file mode 100644 (file)
index 8a1be3d..0000000
+++ /dev/null
@@ -1,649 +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 "Executors.h"
-
-#include "../backend/builtin/IOTensor.h"
-
-namespace
-{
-
-using namespace onert;
-
-int32_t find_input_index(const std::vector<ir::IODesc> &pkg_inputs,
-                         const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index,
-                         const ir::IOIndex &io_index)
-{
-  for (size_t i = 0; i < pkg_inputs.size(); i++)
-  {
-    auto &input_desc = pkg_inputs[i];
-    if ((std::get<ir::ModelIndex>(input_desc) == model_index) &&
-        (std::get<ir::SubgraphIndex>(input_desc) == subg_index) &&
-        (std::get<ir::IOIndex>(input_desc) == io_index))
-      return static_cast<int32_t>(i);
-  }
-  return -1;
-}
-
-int32_t find_output_index(const std::vector<ir::IODesc> &pkg_outputs,
-                          const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index,
-                          const ir::IOIndex &io_index)
-{
-  for (size_t i = 0; i < pkg_outputs.size(); i++)
-  {
-    auto &input_desc = pkg_outputs[i];
-    if ((std::get<ir::ModelIndex>(input_desc) == model_index) &&
-        (std::get<ir::SubgraphIndex>(input_desc) == subg_index) &&
-        (std::get<ir::IOIndex>(input_desc) == io_index))
-      return static_cast<int32_t>(i);
-  }
-  return -1;
-}
-
-} // namespace
-
-namespace onert
-{
-namespace exec
-{
-
-class Executors::EdgeTensor : public backend::builtin::IOTensor
-{
-public:
-  EdgeTensor(const ir::OperandInfo &info, ir::Layout layout)
-    : backend::builtin::IOTensor(info, layout), _buffer{nullptr}, _ref_count{0}
-  {
-  }
-  ~EdgeTensor() = default;
-
-  void allocate_buffer()
-  {
-    const auto total_size = orig_info().total_size();
-    _buffer = std::make_unique<uint8_t[]>(total_size);
-    _ref_count = 1;
-
-    // NOTE Executor's inputs/outputs are always IPortableTensor. If backend of inputs/outputs
-    //      is using tensor that does not inherit IPortableTensor, Permute operation is added
-    //      and all inputs/outputs become IPortableTensor at compile stage.
-    //      This allows user's buffers to be set to inputs/outputs of executors.
-    setUserTensor(_buffer.get(), total_size);
-  }
-
-  void increase_ref() { _ref_count++; }
-
-  void decrease_ref()
-  {
-    assert(_ref_count > 0);
-    _ref_count--;
-    if (_ref_count == 0)
-    {
-      _buffer.reset();
-      setUserTensor(nullptr, orig_info().total_size());
-    }
-  }
-
-private:
-  std::unique_ptr<uint8_t[]> _buffer;
-  int32_t _ref_count;
-};
-
-void Executors::emplace(const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index,
-                        std::unique_ptr<IExecutor> exec)
-{
-  _executors.emplace(std::make_pair(model_index, subg_index), std::move(exec));
-}
-
-IExecutor *Executors::at(const ir::ModelIndex &model_index,
-                         const ir::SubgraphIndex &subg_index) const
-{
-  return _executors.at(std::make_pair(model_index, subg_index)).get();
-}
-
-uint32_t Executors::inputSize() const { return _model_edges->pkg_inputs.size(); }
-
-uint32_t Executors::outputSize() const { return _model_edges->pkg_outputs.size(); }
-
-const ir::OperandInfo &Executors::inputInfo(const ir::IOIndex &index) const
-{
-  auto const desc = _model_edges->pkg_inputs[index.value()];
-  auto const model_index = std::get<0>(desc);
-  auto const subg_index = std::get<1>(desc);
-  auto const io_index = std::get<2>(desc);
-  auto const executor = at(model_index, subg_index);
-  return executor->getInputTensors().at(io_index.value())->orig_info();
-}
-
-const ir::OperandInfo &Executors::outputInfo(const ir::IOIndex &index) const
-{
-  auto const desc = _model_edges->pkg_outputs[index.value()];
-  auto const model_index = std::get<0>(desc);
-  auto const subg_index = std::get<1>(desc);
-  auto const io_index = std::get<2>(desc);
-  auto const executor = at(model_index, subg_index);
-  return executor->getOutputTensors().at(io_index.value())->orig_info();
-}
-
-// Allow below edges only
-//  m1 < m2, s1 == 0 and s2 == 0 if m1:s1:o1 -> m2:s2:o2'
-void Executors::checkSupportedMultimodel() const
-{
-  // If package includes no-connection model, model_count is less than real model count in package.
-  // Then this method will throw exception based on model index
-  //  1st model: input assumption
-  //  Otherwise: edges assumption
-
-  // Assumption: edges
-  // m1 < m2, s1 == 0 and s2 == 0 if edge 'm1:s1:o1 -> m2:s2:o2'
-  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);
-    auto const subg_from = std::get<ir::SubgraphIndex>(edge.from);
-    auto const subg_to = std::get<ir::SubgraphIndex>(edge.to);
-
-    if (model_from.value() == model_to.value())
-    {
-      throw std::runtime_error{"Multi model's edge set has invalid edge"};
-    }
-
-    if ((model_from.value() > model_to.value()) || (subg_from != ir::SubgraphIndex{0}) ||
-        (subg_to != ir::SubgraphIndex{0}))
-      throw std::runtime_error{"NYI: Multi model execution for this edge set is not supported yet"};
-  }
-
-  // Assumption: package inputs
-  //  All 1st model inputs come from package input if always m1 < m2
-  {
-    auto first_executor = at(ir::ModelIndex{0}, ir::SubgraphIndex{0});
-    auto search_first_model = [&](const ir::IOIndex &input_index) {
-      for (const auto &input : _model_edges->pkg_inputs)
-      {
-        if ((std::get<ir::ModelIndex>(input) == ir::ModelIndex{0}) ||
-            (std::get<ir::SubgraphIndex>(input) == ir::SubgraphIndex{0}) ||
-            (std::get<ir::IOIndex>(input) == input_index))
-          return true;
-      }
-
-      return false;
-    };
-
-    for (uint32_t i = 0; i < first_executor->getInputTensors().size(); i++)
-    {
-      if (!search_first_model(ir::IOIndex{i}))
-        throw std::runtime_error{"Cannot find 1st model's input buffer"};
-    }
-  }
-
-  // Check whether nnpkg outputs and Edge `from` are duplicated
-  for (const auto &edge : _model_edges->edges)
-  {
-    if (std::find(_model_edges->pkg_outputs.begin(), _model_edges->pkg_outputs.end(), edge.from) !=
-        _model_edges->pkg_outputs.end())
-    {
-      throw std::runtime_error{"Multi model execution does not support duplicating nnpkg outputs "
-                               "with `from` of edges yet"};
-    }
-  }
-}
-
-void Executors::createEdgeQuantLayers()
-{
-  if (_is_created_edge_quant_layers)
-  {
-    return;
-  }
-
-  // Create EdgeTensor for edges between executors
-  for (const auto &pair : _edge_map)
-  {
-    const auto &from_iodesc = pair.first;
-    const auto &from_model_index = std::get<ir::ModelIndex>(from_iodesc);
-    const auto &from_subg_index = std::get<ir::SubgraphIndex>(from_iodesc);
-    const auto &from_io_index = std::get<ir::IOIndex>(from_iodesc);
-
-    const auto from_executor = _executors.at({from_model_index, from_subg_index}).get();
-    const auto from_tensor = from_executor->getOutputTensors().at(from_io_index.value());
-
-    const auto &from_info = from_tensor->orig_info();
-    const auto from_layout = from_tensor->orig_layout();
-    _edge_tensors[from_iodesc] = std::make_unique<EdgeTensor>(from_info, from_layout);
-  }
-
-  // Append type-aware quantization layer for edges between executors
-  for (const auto &executor_pair : _executors)
-  {
-    const auto &executor_index = executor_pair.first;
-    const auto &model_index = executor_index.first;
-    const auto &subg_index = executor_index.second;
-
-    std::vector<backend::ITensor *> inputs;
-    std::vector<backend::ITensor *> outputs;
-    for (const auto &pair : _edge_map)
-    {
-      const auto &from_iodesc = pair.first;
-      if (std::get<ir::ModelIndex>(from_iodesc) == model_index &&
-          std::get<ir::SubgraphIndex>(from_iodesc) == subg_index)
-      {
-        const auto from_tensor = _edge_tensors[from_iodesc].get();
-        const auto &to_list = pair.second;
-
-        for (const auto &to_iodesc : to_list)
-        {
-          const auto &to_model_index = std::get<ir::ModelIndex>(to_iodesc);
-          const auto &to_subg_index = std::get<ir::SubgraphIndex>(to_iodesc);
-          const auto &to_io_index = std::get<ir::IOIndex>(to_iodesc);
-
-          const auto to_executor = _executors.at({to_model_index, to_subg_index}).get();
-          const auto to_tensor = to_executor->getInputTensors().at(to_io_index.value());
-
-          // TODO Unify tensors with the same `from` tensor and same type
-          if (from_tensor->data_type() != to_tensor->data_type())
-          {
-            assert(inputs.size() == outputs.size());
-            const auto &to_info =
-              to_executor->getInputTensors().at(to_io_index.value())->orig_info();
-            const auto to_layout = to_tensor->orig_layout();
-            inputs.emplace_back(from_tensor);
-
-            auto type_aware_quant_tensor = std::make_unique<EdgeTensor>(to_info, to_layout);
-            outputs.emplace_back(type_aware_quant_tensor.get());
-
-            _edge_quant_tensors[to_iodesc] = std::move(type_aware_quant_tensor);
-          }
-        }
-      }
-    }
-
-    auto layer = std::make_unique<PermuteLayer>(inputs, outputs);
-    layer->prepare();
-    _edge_quant_layers[{model_index, subg_index}] = std::move(layer);
-  }
-
-  _is_created_edge_quant_layers = true;
-}
-
-void Executors::CreatePkgIOTensors(const IODescription &desc)
-{
-  for (const auto &pkg_input : _model_edges->pkg_inputs)
-  {
-    // Create IOTensor for nnpkg inputs
-    const auto &model_index = std::get<ir::ModelIndex>(pkg_input);
-    const auto &subg_index = std::get<ir::SubgraphIndex>(pkg_input);
-    const auto &io_index = std::get<ir::IOIndex>(pkg_input);
-    const auto input_pkg_index =
-      find_input_index(_model_edges->pkg_inputs, model_index, subg_index, io_index);
-    if (input_pkg_index == -1)
-      throw std::runtime_error{"Cannot find multi model input index"};
-    auto input_desc = desc.inputs[input_pkg_index].get();
-    _pkg_input_tensors[pkg_input] =
-      std::make_unique<backend::builtin::IOTensor>(input_desc->info, input_desc->layout);
-  }
-
-  for (const auto &pkg_output : _model_edges->pkg_outputs)
-  {
-    // Create IOTensor for nnpkg outputs
-    const auto &model_index = std::get<ir::ModelIndex>(pkg_output);
-    const auto &subg_index = std::get<ir::SubgraphIndex>(pkg_output);
-    const auto &io_index = std::get<ir::IOIndex>(pkg_output);
-    const auto output_pkg_index =
-      find_output_index(_model_edges->pkg_outputs, model_index, subg_index, io_index);
-    if (output_pkg_index == -1)
-      throw std::runtime_error{"Cannot find multi model output index"};
-    auto output_desc = desc.outputs[output_pkg_index].get();
-    _pkg_output_tensors[pkg_output] =
-      std::make_unique<backend::builtin::IOTensor>(output_desc->info, output_desc->layout);
-  }
-}
-
-void Executors::createPkgIOQuantLayers(const IODescription &desc)
-{
-  // Append type-aware quantization layer for nnpkg inputs/outputs between executors
-  for (const auto &pair : _executors)
-  {
-    const auto &executor_index = pair.first;
-    const auto &model_index = executor_index.first;
-    const auto &subg_index = executor_index.second;
-    const auto executor = pair.second.get();
-
-    // Find pkg inputs of current executor
-    std::vector<ir::IODesc> pkg_inputs;
-    for (const auto &pkg_input : _model_edges->pkg_inputs)
-    {
-      if (std::get<ir::ModelIndex>(pkg_input) == model_index &&
-          std::get<ir::SubgraphIndex>(pkg_input) == subg_index)
-      {
-        pkg_inputs.emplace_back(pkg_input);
-      }
-    }
-    std::vector<backend::ITensor *> src_tensors;
-    std::vector<backend::ITensor *> dst_tensors;
-    for (const auto &pkg_input : pkg_inputs)
-    {
-      const auto &io_index = std::get<ir::IOIndex>(pkg_input);
-      const auto input_pkg_index =
-        find_input_index(_model_edges->pkg_inputs, model_index, subg_index, io_index);
-      if (input_pkg_index == -1)
-        throw std::runtime_error{"Cannot find multi model input index"};
-      auto input_desc = desc.inputs[input_pkg_index].get();
-
-      // Create EdgeTensor for nnpkg input if type is different
-      const auto input_tensor =
-        executor->getInputTensors().at(std::get<ir::IOIndex>(pkg_input).value());
-      const auto &orig_info = input_tensor->orig_info();
-      if (input_desc->info.typeInfo().type() != input_tensor->orig_info().typeInfo().type())
-      {
-        const auto orig_layout = input_tensor->orig_layout();
-        auto pkg_input_edge_tensor = std::make_unique<EdgeTensor>(orig_info, orig_layout);
-        _pkg_input_quant_tensors[pkg_input] = std::move(pkg_input_edge_tensor);
-
-        // Append type-aware quantization layer's inputs/outputs
-        src_tensors.emplace_back(_pkg_input_tensors[pkg_input].get());
-        dst_tensors.emplace_back(_pkg_input_quant_tensors[pkg_input].get());
-      }
-    }
-
-    // Create type-aware quantization layer for nnpkg inputs
-    auto pkg_input_layer = std::make_unique<PermuteLayer>(src_tensors, dst_tensors);
-    pkg_input_layer->prepare();
-    _pkg_input_quant_layers[{model_index, subg_index}] = std::move(pkg_input_layer);
-
-    // Find pkg outputs of current executor
-    std::vector<ir::IODesc> pkg_outputs;
-    for (const auto &pkg_output : _model_edges->pkg_outputs)
-    {
-      if (std::get<ir::ModelIndex>(pkg_output) == model_index &&
-          std::get<ir::SubgraphIndex>(pkg_output) == subg_index)
-      {
-        pkg_outputs.emplace_back(pkg_output);
-      }
-    }
-    src_tensors.clear();
-    dst_tensors.clear();
-    // Create Tensors of nnpkg outputs for type-aware quantization
-    for (const auto &pkg_output : pkg_outputs)
-    {
-      const auto &io_index = std::get<ir::IOIndex>(pkg_output);
-      const auto output_pkg_index =
-        find_output_index(_model_edges->pkg_outputs, model_index, subg_index, io_index);
-      if (output_pkg_index == -1)
-        throw std::runtime_error{"Cannot find multi model output index"};
-      auto output_desc = desc.outputs[output_pkg_index].get();
-
-      // Create EdgeTensor for nnpkg output if type is different
-      const auto output_tensor =
-        executor->getOutputTensors().at(std::get<ir::IOIndex>(pkg_output).value());
-      const auto &orig_info = output_tensor->orig_info();
-      if (output_desc->info.typeInfo().type() != output_tensor->orig_info().typeInfo().type())
-      {
-        const auto orig_layout = output_tensor->orig_layout();
-        auto pkg_output_edge_tensor = std::make_unique<EdgeTensor>(orig_info, orig_layout);
-        _pkg_output_quant_tensors[pkg_output] = std::move(pkg_output_edge_tensor);
-
-        // Append type-aware quantization layer's inputs/outputs
-        src_tensors.emplace_back(_pkg_output_quant_tensors[pkg_output].get());
-        dst_tensors.emplace_back(_pkg_output_tensors[pkg_output].get());
-      }
-    }
-
-    // Create type-aware quantization layer for nnpkg outputs
-    auto pkg_output_layer = std::make_unique<PermuteLayer>(src_tensors, dst_tensors);
-    pkg_output_layer->prepare();
-    _pkg_output_quant_layers[{model_index, subg_index}] = std::move(pkg_output_layer);
-  }
-}
-
-void Executors::execute(const IODescription &desc)
-{
-  // Check supported multi model package
-  checkSupportedMultimodel();
-
-  // TODO Move creating type-aware quantization layers for edges in compilation stage
-  createEdgeQuantLayers();
-
-  // TODO Create IOTensors only once and recreate them only if nnpkg info changes
-  CreatePkgIOTensors(desc);
-
-  // TODO Create type-aware quantization layers only once and recreate them only if type changes
-  createPkgIOQuantLayers(desc);
-
-  // TODO Find better way to schedule order of executors
-  auto const model_count = modelCount();
-
-  auto find_from = [&](const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index,
-                       const ir::IOIndex &io_index) {
-    for (const auto &edge : _model_edges->edges)
-    {
-      if ((std::get<ir::ModelIndex>(edge.to) == model_index) &&
-          (std::get<ir::SubgraphIndex>(edge.to) == subg_index) &&
-          (std::get<ir::IOIndex>(edge.to) == io_index))
-        return edge.from;
-    }
-
-    throw std::runtime_error{"Cannot find edge for model input"};
-  };
-
-  // Execute each model
-  // NOTE May be better to use vector instead of unordered_map for _executors
-  for (auto model_index = ir::ModelIndex{0}; model_index.value() < model_count; model_index++)
-  {
-    // Find executor
-    auto executor = at(model_index, ir::SubgraphIndex{0});
-
-    // Set IOTensors
-    // TODO Set internal IOTensors only once
-    std::vector<backend::IPortableTensor *> inputs_inter;
-    std::vector<backend::IPortableTensor *> outputs_inter;
-    const auto &input_tensors = executor->getInputTensors();
-    const auto &output_tensors = executor->getOutputTensors();
-    auto const input_size = input_tensors.size();
-    auto const output_size = output_tensors.size();
-    inputs_inter.resize(input_size);
-    outputs_inter.resize(output_size);
-
-    // Set inputs of executor
-    // TODO Create layer to allocate/deallocate buffers of EdgeTensor for each executor
-    for (uint32_t i = 0; i < input_size; i++)
-    {
-      const auto input_pkg_index = find_input_index(_model_edges->pkg_inputs, model_index,
-                                                    ir::SubgraphIndex{0}, ir::IOIndex{i});
-      const auto input_io_desc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
-      if (input_pkg_index != -1)
-      {
-        // Allocate type-aware quantization tensors for nnpkg inputs and set internal tensors
-        if (_pkg_input_quant_tensors.find(input_io_desc) != _pkg_input_quant_tensors.end())
-        {
-          _pkg_input_quant_tensors[input_io_desc]->allocate_buffer();
-
-          inputs_inter[i] = _pkg_input_quant_tensors[input_io_desc].get();
-        }
-        else
-        {
-          inputs_inter[i] = _pkg_input_tensors[input_io_desc].get();
-        }
-
-        // Set buffer of IOTensor
-        auto input_desc = desc.inputs[input_pkg_index].get();
-        // TODO Remove const_cast (we need const_cast as ITensor is writable)
-        _pkg_input_tensors[input_io_desc]->setUserTensor(
-          reinterpret_cast<uint8_t *>(const_cast<void *>(input_desc->buffer)), input_desc->size);
-      }
-      else
-      {
-        auto from_iodesc = find_from(model_index, ir::SubgraphIndex{0}, ir::IOIndex{i});
-        const auto &from_model_index = std::get<ir::ModelIndex>(from_iodesc);
-        const auto &from_subg_index = std::get<ir::SubgraphIndex>(from_iodesc);
-        const auto &from_ioindex = std::get<ir::IOIndex>(from_iodesc).value();
-
-        // Supported only sequantial execution of models
-        assert(from_model_index.value() < model_index.value());
-        assert(from_subg_index.value() == 0);
-        const auto from_executor = _executors.at({from_model_index, from_subg_index}).get();
-        const auto to_iodesc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
-        if (_edge_quant_tensors.find(to_iodesc) == _edge_quant_tensors.end())
-        {
-          inputs_inter[i] = from_executor->getOutputTensors().at(from_ioindex);
-        }
-        else
-        {
-          inputs_inter[i] = _edge_quant_tensors.at(to_iodesc).get();
-        }
-        assert(inputs_inter[i]->buffer() != nullptr);
-      }
-    }
-
-    // Set outputs of executor
-    for (uint32_t i = 0; i < output_size; i++)
-    {
-      const auto output_pkg_index = find_output_index(_model_edges->pkg_outputs, model_index,
-                                                      ir::SubgraphIndex{0}, ir::IOIndex{i});
-      const auto output_io_desc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
-      if (output_pkg_index != -1)
-      {
-        // Allocate type-aware quantization tensors for nnpkg outputs and set internal tensors
-        if (_pkg_output_quant_tensors.find(output_io_desc) != _pkg_output_quant_tensors.end())
-        {
-          _pkg_output_quant_tensors[output_io_desc]->allocate_buffer();
-
-          outputs_inter[i] = _pkg_output_quant_tensors[output_io_desc].get();
-        }
-        else
-        {
-          outputs_inter[i] = _pkg_output_tensors[output_io_desc].get();
-        }
-
-        // Set buffer of IOTensor
-        auto output_desc = desc.outputs[output_pkg_index].get();
-        _pkg_output_tensors[output_io_desc]->setUserTensor(
-          reinterpret_cast<uint8_t *>(output_desc->buffer), output_desc->size);
-      }
-      else
-      {
-        // Allocate buffer of `from` tensors
-        const auto from_iodesc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
-        _edge_tensors[from_iodesc]->allocate_buffer();
-        outputs_inter[i] = _edge_tensors[from_iodesc].get();
-
-        // Allocate buffer of tensors for type-aware quantization
-        for (const auto &to_iodesc : _edge_map[from_iodesc])
-        {
-          _edge_tensors[from_iodesc]->increase_ref();
-          if (_edge_quant_tensors.find(to_iodesc) != _edge_quant_tensors.end())
-          {
-            auto type_aware_quant_tensor = _edge_quant_tensors.at(to_iodesc).get();
-            type_aware_quant_tensor->allocate_buffer();
-
-            _edge_tensors[from_iodesc]->decrease_ref();
-          }
-        }
-      }
-    }
-
-    _pkg_input_quant_layers[{model_index, ir::SubgraphIndex{0}}]->run();
-
-    executor->execute(inputs_inter, outputs_inter);
-
-    _edge_quant_layers[{model_index, ir::SubgraphIndex{0}}]->run();
-    _pkg_output_quant_layers[{model_index, ir::SubgraphIndex{0}}]->run();
-
-    // Release input buffers that are no longer needed
-    for (uint32_t i = 0; i < input_size; i++)
-    {
-      const auto input_pkg_index = find_input_index(_model_edges->pkg_inputs, model_index,
-                                                    ir::SubgraphIndex{0}, ir::IOIndex{i});
-
-      const auto to_iodesc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
-      if (input_pkg_index == -1)
-      {
-        if (_edge_quant_tensors.find(to_iodesc) != _edge_quant_tensors.end())
-        {
-          // Decrease reference count of tensor for type-aware quantization if input tensor is the
-          // tensor
-          const auto to_iodesc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
-          if (_edge_quant_tensors.find(to_iodesc) != _edge_quant_tensors.end())
-          {
-            _edge_quant_tensors[to_iodesc]->decrease_ref();
-          }
-        }
-        else
-        {
-          // Decrease reference count of `from` tensor if input tensor is the `from` tensor
-          const auto from_iodesc = find_from(model_index, ir::SubgraphIndex{0}, ir::IOIndex{i});
-          _edge_tensors[from_iodesc]->decrease_ref();
-
-          // Decrease reference count of nnpkg inputs
-          if (_pkg_input_quant_tensors.find(to_iodesc) != _pkg_input_quant_tensors.end())
-          {
-            _pkg_input_quant_tensors[to_iodesc]->decrease_ref();
-          }
-        }
-      }
-    }
-
-    // Release output buffers if those buffers are no longer used other executors because of
-    // type-aware quantization
-    // FIXME if tensors for type-aware quantization unified for the same `from` tensor and same type
-    for (uint32_t i = 0; i < output_size; i++)
-    {
-      auto from_iodesc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
-
-      // Check if other executors will use the buffer of edge tensor
-      const auto &to_list = _edge_map[from_iodesc];
-      if (to_list.size() == 0)
-      {
-        // This condition means `from_iodesc` tensor is an output of nnpkg
-        continue;
-      }
-
-      bool to_be_release =
-        !std::any_of(to_list.begin(), to_list.end(), [&](const ir::IODesc &to_iodesc) {
-          // This condition means another executor uses the buffer of edge tensor
-          return _edge_quant_tensors.find(to_iodesc) == _edge_quant_tensors.end();
-        });
-
-      if (to_be_release)
-      {
-        // This edge tensor's buffer won't be used in other executors
-        // Tensors for type-aware quantization take over the role of this edge tensor instead
-        _edge_tensors[from_iodesc]->decrease_ref();
-      }
-
-      // Decrease reference count of nnpkg outputs
-      if (_pkg_output_quant_tensors.find(from_iodesc) != _pkg_output_quant_tensors.end())
-      {
-        _pkg_output_quant_tensors[from_iodesc]->decrease_ref();
-      }
-    }
-  }
-}
-
-// modelCount() iterates _executors.
-// It assumes that Compiler will generate Executor for all models and _executors includes all
-// generated Executor.
-// If nnpackage includes model(s) which has no connection and Compiler does not
-// generate Executor for them, modelCount() return less value than real model count.
-uint16_t Executors::modelCount() const
-{
-  uint16_t model_count = 0;
-  for (; _executors.find(std::make_pair(ir::ModelIndex{model_count}, ir::SubgraphIndex{0})) !=
-         _executors.end();
-       model_count++)
-    ;
-
-  return model_count;
-}
-
-} // namespace exec
-} // namespace onert
diff --git a/runtime/onert/core/src/exec/Executors.h b/runtime/onert/core/src/exec/Executors.h
deleted file mode 100644 (file)
index ac74891..0000000
+++ /dev/null
@@ -1,169 +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.
- */
-
-#ifndef __ONERT_EXEC_EXECUTORS_H__
-#define __ONERT_EXEC_EXECUTORS_H__
-
-#include "exec/IExecutors.h"
-#include "ir/NNPkg.h"
-#include "IPermuteFunction.h"
-
-namespace std
-{
-
-template <> struct hash<std::pair<::onert::ir::ModelIndex, ::onert::ir::SubgraphIndex>>
-{
-  size_t
-  operator()(const std::pair<::onert::ir::ModelIndex, ::onert::ir::SubgraphIndex> &pair) const
-    noexcept
-  {
-    return (hash<uint32_t>()(pair.first.value()) << 16) ^ hash<uint32_t>()(pair.second.value());
-  }
-};
-
-} // namespace std
-
-namespace onert
-{
-namespace exec
-{
-
-/**
- * @brief Class to gather executors
- */
-class Executors : public IExecutors
-{
-public:
-  Executors(void) = delete;
-  Executors(std::unique_ptr<ir::ModelEdges> model_edges)
-    : _executors{}, _model_edges{std::move(model_edges)}, _edge_quant_layers{},
-      _edge_quant_tensors{}, _edge_tensors{}, _is_created_edge_quant_layers{false},
-      _pkg_input_quant_layers{}, _pkg_output_quant_layers{}, _pkg_input_quant_tensors{},
-      _pkg_output_quant_tensors{}, _pkg_input_tensors{}, _pkg_output_tensors{}
-  {
-    for (const auto &edge : _model_edges->edges)
-    {
-      _edge_map[edge.from].emplace_back(edge.to);
-    }
-  }
-  Executors(const Executors &) = delete;
-  Executors(Executors &&) = default;
-  ~Executors() = default;
-
-  // TODO Use Executor index
-  void emplace(const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index,
-               std::unique_ptr<IExecutor> exec) override;
-
-  IExecutor *at(const ir::ModelIndex &model_index,
-                const ir::SubgraphIndex &subg_index) const override;
-
-  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;
-
-private:
-  void checkSupportedMultimodel() const;
-  void createEdgeQuantLayers();
-  void CreatePkgIOTensors(const IODescription &desc);
-  void createPkgIOQuantLayers(const IODescription &desc);
-  uint16_t modelCount() const;
-
-private:
-  // TODO Remove this class
-  class PermuteLayer : public exec::IPermuteFunction
-  {
-  public:
-    PermuteLayer(const std::vector<backend::ITensor *> &inputs,
-                 const std::vector<backend::ITensor *> &outputs)
-    {
-      assert(inputs.size() == outputs.size());
-      _src_tensors = inputs;
-      _dst_tensors = outputs;
-    }
-    virtual ~PermuteLayer() {}
-    void optimize() override {}
-  };
-
-  class EdgeTensor;
-
-private:
-  std::unordered_map<std::pair<ir::ModelIndex, ir::SubgraphIndex>, std::unique_ptr<IExecutor>>
-    _executors;
-
-  // NOTE _model_edges may use different struct type for executor implementation
-  std::unique_ptr<ir::ModelEdges> _model_edges;
-  std::unordered_map<ir::IODesc, std::vector<ir::IODesc>> _edge_map;
-
-  /**
-   * @brief Type-aware quantization layers for edges between executors
-   *
-   */
-  // TODO Move variables related to type-aware quantization for edges into compilation stage
-  // TODO Replace PermuteLayer with backend::builtin::kernel::PermuteLayer
-  std::unordered_map<std::pair<ir::ModelIndex, ir::SubgraphIndex>, std::unique_ptr<PermuteLayer>>
-    _edge_quant_layers;
-
-  /**
-   * @brief Tensors for type-aware quantization of edges
-   *        Key: `to` IODesc, Value: EdgeTensor
-   */
-  //
-  // Q: Why is Key `to` IODesc
-  // A: these tensors are currently created depending on the type of `to`
-  // TODO Unify tensors with the same `from` tensor and same type
-  // NOTE The incomplete type 'EdgeTensor' cannot be declared as unique_ptr.
-  std::unordered_map<ir::IODesc, std::shared_ptr<EdgeTensor>> _edge_quant_tensors;
-
-  /**
-   * @brief Tensors for edges between executors that are not related to type-aware quantization
-   *        Key: `from` IODesc, Value: EdgeTensor
-   */
-  // Q: Why is Key `from` IODesc
-  // A: `from` can be connected to multiple `to`
-  // NOTE The incomplete type 'EdgeTensor' cannot be declared as unique_ptr.
-  std::unordered_map<ir::IODesc, std::shared_ptr<EdgeTensor>> _edge_tensors;
-  /**
-   * @brief Whether type-aware quantization layers for edges between executors are created
-   *
-   */
-  // TODO Remove this member after the creation of type-aware quantization layers for edges
-  //      is moved into compilation stage
-  bool _is_created_edge_quant_layers;
-
-  // TODO Replace PermuteLayer with backend::builtin::kernel::PermuteLayer
-  std::unordered_map<std::pair<ir::ModelIndex, ir::SubgraphIndex>, std::unique_ptr<PermuteLayer>>
-    _pkg_input_quant_layers;
-  // TODO Replace PermuteLayer with backend::builtin::kernel::PermuteLayer
-  std::unordered_map<std::pair<ir::ModelIndex, ir::SubgraphIndex>, std::unique_ptr<PermuteLayer>>
-    _pkg_output_quant_layers;
-  // Edge tensors of nnpkg inputs/outputs for type-aware quantization
-  std::unordered_map<ir::IODesc, std::shared_ptr<EdgeTensor>> _pkg_input_quant_tensors;
-  std::unordered_map<ir::IODesc, std::shared_ptr<EdgeTensor>> _pkg_output_quant_tensors;
-  // IOTensors for user buffer
-  std::unordered_map<ir::IODesc, std::unique_ptr<backend::builtin::IOTensor>> _pkg_input_tensors;
-  std::unordered_map<ir::IODesc, std::unique_ptr<backend::builtin::IOTensor>> _pkg_output_tensors;
-};
-
-} // namespace exec
-} // namespace onert
-
-#endif // __ONERT_EXEC_EXECUTORS_H__
index e790f32..ccac66c 100644 (file)
@@ -263,6 +263,21 @@ protected:
   std::unordered_map<const backend::ITensor *, std::vector<uint8_t>> _buffers_map;
 };
 
+// Simple PermuteLayer
+class PermuteLayer : public onert::exec::IPermuteFunction
+{
+public:
+  PermuteLayer(const std::vector<onert::backend::ITensor *> &inputs,
+               const std::vector<onert::backend::ITensor *> &outputs)
+  {
+    assert(inputs.size() == outputs.size());
+    _src_tensors = inputs;
+    _dst_tensors = outputs;
+  }
+  virtual ~PermuteLayer() {}
+  void optimize() override {}
+};
+
 } // namespace exec
 } // namespace onert
 
index 1009f19..fb2dd3b 100644 (file)
@@ -107,80 +107,42 @@ public:
   void optimize() override {}
 };
 
-TEST(IPermuteFunction, float_rank1)
+TEST(IPermuteFunction, float_to_float)
 {
-  const size_t input_pads[4] = {0, 1, 0, 2};
-  const size_t output_pads[4] = {0, 0, 2, 1};
-  const std::vector<Shape> shapes{{1}, {4}, {5}, {2}};
-  float expected_buffer[] = {1, 0, -1, -2, 3};
-  const auto type_info = TypeInfo(DataType::FLOAT32);
-
-  std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
-  std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
-
-  std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
-  for (size_t i = 0; i < 4; ++i)
+  // rank 1
   {
-    inputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, input_pads[i]);
-    inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
+    const size_t input_pads[4] = {0, 1, 0, 2};
+    const size_t output_pads[4] = {0, 0, 2, 1};
+    const std::vector<Shape> shapes{{1}, {4}, {5}, {2}};
+    float expected_buffer[] = {1, 0, -1, -2, 3};
+    const auto type_info = TypeInfo(DataType::FLOAT32);
 
-    outputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, output_pads[i]);
-    output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
-    outputs[i]->setBuffer(output_buffers[i].get());
-  }
-
-  auto mockup_layer = std::make_unique<MockUpLayer>(
-    std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
-    std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(), outputs[3].get()});
-  mockup_layer->run();
+    std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
+    std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
 
-  for (size_t i = 0; i < 4; ++i)
-  {
-    for (int32_t j = 0; j < shapes[i].dim(0); ++j)
+    std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
+    for (size_t i = 0; i < 4; ++i)
     {
-      Coordinates coords{j};
-      float result =
-        *reinterpret_cast<float *>(outputs[i]->buffer() + outputs[i]->calcOffset(coords));
-      float expected =
-        *reinterpret_cast<float *>(inputs[i]->buffer() + inputs[i]->calcOffset(coords));
-      EXPECT_EQ(result, expected);
-    }
-  }
-}
-
-TEST(IPermuteFunction, float_rank2)
-{
-  const size_t input_pads[4] = {0, 1, 0, 2};
-  const size_t output_pads[4] = {0, 0, 2, 1};
-  const std::vector<Shape> shapes{{1, 4}, {2, 2}, {1, 5}, {2, 3}};
-  float expected_buffer[] = {1, 0, -1, -2, 3, -4, 5, -6, 7, -8};
-  const auto type_info = TypeInfo(DataType::FLOAT32);
+      inputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, input_pads[i]);
+      inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
 
-  std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
-  std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
-  std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
-  for (size_t i = 0; i < 4; ++i)
-  {
-    inputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, input_pads[i]);
-    inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
-
-    outputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, output_pads[i]);
-    output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
-    outputs[i]->setBuffer(output_buffers[i].get());
-  }
+      outputs[i] =
+        std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, output_pads[i]);
+      output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
+      outputs[i]->setBuffer(output_buffers[i].get());
+    }
 
-  auto mockup_layer = std::make_unique<MockUpLayer>(
-    std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
-    std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(), outputs[3].get()});
-  mockup_layer->run();
+    auto mockup_layer = std::make_unique<MockUpLayer>(
+      std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
+      std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(),
+                             outputs[3].get()});
+    mockup_layer->run();
 
-  for (size_t i = 0; i < 4; ++i)
-  {
-    for (int32_t j = 0; j < shapes[i].dim(0); ++j)
+    for (size_t i = 0; i < 4; ++i)
     {
-      for (int32_t k = 0; k < shapes[i].dim(1); ++k)
+      for (int32_t j = 0; j < shapes[i].dim(0); ++j)
       {
-        Coordinates coords{j, k};
+        Coordinates coords{j};
         float result =
           *reinterpret_cast<float *>(outputs[i]->buffer() + outputs[i]->calcOffset(coords));
         float expected =
@@ -189,43 +151,42 @@ TEST(IPermuteFunction, float_rank2)
       }
     }
   }
-}
 
-TEST(IPermuteFunction, float_rank3)
-{
-  const size_t input_pads[4] = {0, 5, 0, 2};
-  const size_t output_pads[4] = {0, 3, 2, 1};
-  const std::vector<Shape> shapes{{1, 4, 1}, {1, 2, 1}, {2, 1, 5}, {1, 2, 3}};
-  float expected_buffer[] = {1, 0, -1, -2, 3, -4, 5, -6, 7, -8, 9, -10};
-  const auto type_info = TypeInfo(DataType::FLOAT32);
-
-  std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
-  std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
-  std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
-  for (size_t i = 0; i < 4; ++i)
+  // rank 2
   {
-    inputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, input_pads[i]);
-    inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
+    const size_t input_pads[4] = {0, 1, 0, 2};
+    const size_t output_pads[4] = {0, 0, 2, 1};
+    const std::vector<Shape> shapes{{1, 4}, {2, 2}, {1, 5}, {2, 3}};
+    float expected_buffer[] = {1, 0, -1, -2, 3, -4, 5, -6, 7, -8};
+    const auto type_info = TypeInfo(DataType::FLOAT32);
 
-    outputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, output_pads[i]);
-    output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
-    outputs[i]->setBuffer(output_buffers[i].get());
-  }
+    std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
+    std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
+    std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
+    for (size_t i = 0; i < 4; ++i)
+    {
+      inputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, input_pads[i]);
+      inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
 
-  auto mockup_layer = std::make_unique<MockUpLayer>(
-    std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
-    std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(), outputs[3].get()});
-  mockup_layer->run();
+      outputs[i] =
+        std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, output_pads[i]);
+      output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
+      outputs[i]->setBuffer(output_buffers[i].get());
+    }
 
-  for (size_t i = 0; i < 4; ++i)
-  {
-    for (int32_t j = 0; j < shapes[i].dim(0); ++j)
+    auto mockup_layer = std::make_unique<MockUpLayer>(
+      std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
+      std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(),
+                             outputs[3].get()});
+    mockup_layer->run();
+
+    for (size_t i = 0; i < 4; ++i)
     {
-      for (int32_t k = 0; k < shapes[i].dim(1); ++k)
+      for (int32_t j = 0; j < shapes[i].dim(0); ++j)
       {
-        for (int32_t l = 0; l < shapes[i].dim(2); ++l)
+        for (int32_t k = 0; k < shapes[i].dim(1); ++k)
         {
-          Coordinates coords{j, k, l};
+          Coordinates coords{j, k};
           float result =
             *reinterpret_cast<float *>(outputs[i]->buffer() + outputs[i]->calcOffset(coords));
           float expected =
@@ -235,45 +196,44 @@ TEST(IPermuteFunction, float_rank3)
       }
     }
   }
-}
-
-TEST(IPermuteFunction, float_rank4)
-{
-  const size_t input_pads[4] = {0, 0, 1, 2};
-  const size_t output_pads[4] = {0, 3, 2, 1};
-  const std::vector<Shape> shapes{{1, 1, 4, 1}, {2, 1, 2, 3}, {1, 2, 1, 2}, {1, 1, 2, 3}};
-  float expected_buffer[] = {1, 0, -1, -2, 3, -4, 5, -6, 7, -8, 9, -10};
-  const auto type_info = TypeInfo(DataType::FLOAT32);
 
-  std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
-  std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
-  std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
-  for (size_t i = 0; i < 4; ++i)
+  // rank 3
   {
-    inputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, input_pads[i]);
-    inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
+    const size_t input_pads[4] = {0, 5, 0, 2};
+    const size_t output_pads[4] = {0, 3, 2, 1};
+    const std::vector<Shape> shapes{{1, 4, 1}, {1, 2, 1}, {2, 1, 5}, {1, 2, 3}};
+    float expected_buffer[] = {1, 0, -1, -2, 3, -4, 5, -6, 7, -8, 9, -10};
+    const auto type_info = TypeInfo(DataType::FLOAT32);
 
-    outputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, output_pads[i]);
-    output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
-    outputs[i]->setBuffer(output_buffers[i].get());
-  }
+    std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
+    std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
+    std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
+    for (size_t i = 0; i < 4; ++i)
+    {
+      inputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, input_pads[i]);
+      inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
 
-  auto mockup_layer = std::make_unique<MockUpLayer>(
-    std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
-    std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(), outputs[3].get()});
-  mockup_layer->run();
+      outputs[i] =
+        std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, output_pads[i]);
+      output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
+      outputs[i]->setBuffer(output_buffers[i].get());
+    }
 
-  for (size_t i = 0; i < 4; ++i)
-  {
-    for (int32_t j = 0; j < shapes[i].dim(0); ++j)
+    auto mockup_layer = std::make_unique<MockUpLayer>(
+      std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
+      std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(),
+                             outputs[3].get()});
+    mockup_layer->run();
+
+    for (size_t i = 0; i < 4; ++i)
     {
-      for (int32_t k = 0; k < shapes[i].dim(1); ++k)
+      for (int32_t j = 0; j < shapes[i].dim(0); ++j)
       {
-        for (int32_t l = 0; l < shapes[i].dim(2); ++l)
+        for (int32_t k = 0; k < shapes[i].dim(1); ++k)
         {
-          for (int32_t m = 0; m < shapes[i].dim(3); ++m)
+          for (int32_t l = 0; l < shapes[i].dim(2); ++l)
           {
-            Coordinates coords{j, k, l, m};
+            Coordinates coords{j, k, l};
             float result =
               *reinterpret_cast<float *>(outputs[i]->buffer() + outputs[i]->calcOffset(coords));
             float expected =
@@ -284,84 +244,137 @@ TEST(IPermuteFunction, float_rank4)
       }
     }
   }
-}
 
-TEST(IPermuteFunction, float_rank4_layout)
-{
-  const size_t input_pads[4] = {0, 0, 1, 2};
-  const size_t output_pads[4] = {0, 3, 2, 1};
-  const std::vector<Shape> shapes{{1, 1, 4, 1}, {2, 1, 2, 3}, {1, 2, 1, 2}, {1, 1, 2, 3}};
-  float expected_buffer[] = {1, 0, -1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13, -14, 15, -16};
-  const auto type_info = TypeInfo(DataType::FLOAT32);
-
-  std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
-  std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
-  std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
-  for (size_t i = 0; i < 4; ++i)
+  // rank 4
   {
-    Layout layout = Layout::NHWC;
-    Shape shape = shapes[i];
-    if (i % 2 == 1)
+    const size_t input_pads[4] = {0, 0, 1, 2};
+    const size_t output_pads[4] = {0, 3, 2, 1};
+    const std::vector<Shape> shapes{{1, 1, 4, 1}, {2, 1, 2, 3}, {1, 2, 1, 2}, {1, 1, 2, 3}};
+    float expected_buffer[] = {1, 0, -1, -2, 3, -4, 5, -6, 7, -8, 9, -10};
+    const auto type_info = TypeInfo(DataType::FLOAT32);
+
+    std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
+    std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
+    std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
+    for (size_t i = 0; i < 4; ++i)
     {
-      layout = Layout::NCHW;
-      shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
+      inputs[i] = std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, input_pads[i]);
+      inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
+
+      outputs[i] =
+        std::make_unique<MockUpTensor>(shapes[i], type_info, Layout::NHWC, output_pads[i]);
+      output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
+      outputs[i]->setBuffer(output_buffers[i].get());
     }
-    inputs[i] = std::make_unique<MockUpTensor>(shape, type_info, layout, input_pads[i]);
-    inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
 
-    if (layout == Layout::NHWC)
+    auto mockup_layer = std::make_unique<MockUpLayer>(
+      std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
+      std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(),
+                             outputs[3].get()});
+    mockup_layer->run();
+
+    for (size_t i = 0; i < 4; ++i)
     {
-      layout = Layout::NCHW;
-      shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
+      for (int32_t j = 0; j < shapes[i].dim(0); ++j)
+      {
+        for (int32_t k = 0; k < shapes[i].dim(1); ++k)
+        {
+          for (int32_t l = 0; l < shapes[i].dim(2); ++l)
+          {
+            for (int32_t m = 0; m < shapes[i].dim(3); ++m)
+            {
+              Coordinates coords{j, k, l, m};
+              float result =
+                *reinterpret_cast<float *>(outputs[i]->buffer() + outputs[i]->calcOffset(coords));
+              float expected =
+                *reinterpret_cast<float *>(inputs[i]->buffer() + inputs[i]->calcOffset(coords));
+              EXPECT_EQ(result, expected);
+            }
+          }
+        }
+      }
     }
-    else
+  }
+
+  // rank4 layout
+  {
+    const size_t input_pads[4] = {0, 0, 1, 2};
+    const size_t output_pads[4] = {0, 3, 2, 1};
+    const std::vector<Shape> shapes{{1, 1, 4, 1}, {2, 1, 2, 3}, {1, 2, 1, 2}, {1, 1, 2, 3}};
+    float expected_buffer[] = {1,  0, -1,  -2, 3,   -4, 5,   -6, 7,
+                               -8, 9, -10, 11, -12, 13, -14, 15, -16};
+    const auto type_info = TypeInfo(DataType::FLOAT32);
+
+    std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
+    std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
+    std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
+    for (size_t i = 0; i < 4; ++i)
     {
-      layout = Layout::NHWC;
-      shape = shapes[i];
+      Layout layout = Layout::NHWC;
+      Shape shape = shapes[i];
+      if (i % 2 == 1)
+      {
+        layout = Layout::NCHW;
+        shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
+      }
+      inputs[i] = std::make_unique<MockUpTensor>(shape, type_info, layout, input_pads[i]);
+      inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
+
+      if (layout == Layout::NHWC)
+      {
+        layout = Layout::NCHW;
+        shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
+      }
+      else
+      {
+        layout = Layout::NHWC;
+        shape = shapes[i];
+      }
+      outputs[i] = std::make_unique<MockUpTensor>(shape, type_info, layout, output_pads[i]);
+      output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
+      outputs[i]->setBuffer(output_buffers[i].get());
     }
-    outputs[i] = std::make_unique<MockUpTensor>(shape, type_info, layout, output_pads[i]);
-    output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
-    outputs[i]->setBuffer(output_buffers[i].get());
-  }
 
-  auto mockup_layer = std::make_unique<MockUpLayer>(
-    std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
-    std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(), outputs[3].get()});
-  mockup_layer->run();
+    auto mockup_layer = std::make_unique<MockUpLayer>(
+      std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
+      std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(),
+                             outputs[3].get()});
+    mockup_layer->run();
 
-  for (size_t i = 0; i < 4; ++i)
-  {
-    for (int32_t j = 0; j < shapes[i].dim(0); ++j)
+    for (size_t i = 0; i < 4; ++i)
     {
-      for (int32_t k = 0; k < shapes[i].dim(1); ++k)
+      for (int32_t j = 0; j < shapes[i].dim(0); ++j)
       {
-        for (int32_t l = 0; l < shapes[i].dim(2); ++l)
+        for (int32_t k = 0; k < shapes[i].dim(1); ++k)
         {
-          for (int32_t m = 0; m < shapes[i].dim(3); ++m)
+          for (int32_t l = 0; l < shapes[i].dim(2); ++l)
           {
-            Coordinates input_coords;
-            Coordinates output_coords;
-            if (inputs[i]->layout() == Layout::NHWC)
-            {
-              input_coords = Coordinates{j, k, l, m};
-            }
-            else
+            for (int32_t m = 0; m < shapes[i].dim(3); ++m)
             {
-              input_coords = Coordinates{j, m, k, l};
+              Coordinates input_coords;
+              Coordinates output_coords;
+              if (inputs[i]->layout() == Layout::NHWC)
+              {
+                input_coords = Coordinates{j, k, l, m};
+              }
+              else
+              {
+                input_coords = Coordinates{j, m, k, l};
+              }
+              if (outputs[i]->layout() == Layout::NHWC)
+              {
+                output_coords = Coordinates{j, k, l, m};
+              }
+              else
+              {
+                output_coords = Coordinates{j, m, k, l};
+              }
+              float result = *reinterpret_cast<float *>(outputs[i]->buffer() +
+                                                        outputs[i]->calcOffset(output_coords));
+              float expected = *reinterpret_cast<float *>(inputs[i]->buffer() +
+                                                          inputs[i]->calcOffset(input_coords));
+              EXPECT_EQ(result, expected);
             }
-            if (outputs[i]->layout() == Layout::NHWC)
-            {
-              output_coords = Coordinates{j, k, l, m};
-            }
-            else
-            {
-              output_coords = Coordinates{j, m, k, l};
-            }
-            float result = *reinterpret_cast<float *>(outputs[i]->buffer() +
-                                                      outputs[i]->calcOffset(output_coords));
-            float expected =
-              *reinterpret_cast<float *>(inputs[i]->buffer() + inputs[i]->calcOffset(input_coords));
-            EXPECT_EQ(result, expected);
           }
         }
       }
@@ -714,184 +727,189 @@ TEST(IPermuteFunction, qsymm16_to_float)
   }
 }
 
-TEST(IPermuteFunction, float_to_qasymm8_layout)
+TEST(IPermuteFunction, float_qasymm8_layout)
 {
-  const size_t input_pads[4] = {0, 0, 1, 2};
-  const size_t output_pads[4] = {0, 3, 2, 1};
-  const std::vector<Shape> shapes{{1, 1, 4, 1}, {2, 1, 2, 3}, {1, 2, 1, 2}, {1, 1, 2, 3}};
-  float expected_buffer[] = {10,  0,  -10,  -20, 30,   -40, 50,   -60, 70,
-                             -80, 90, -100, 110, -120, 130, -140, 150, -160};
-  float scale = 10;
-  int32_t zero_point = 128;
-
-  std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
-  std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
-  std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
-  for (size_t i = 0; i < 4; ++i)
-  {
-    Layout layout = Layout::NHWC;
-    Shape shape = shapes[i];
-    if (i % 2 == 1)
+  // float -> quasymm8
+  {
+    const size_t input_pads[4] = {0, 0, 1, 2};
+    const size_t output_pads[4] = {0, 3, 2, 1};
+    const std::vector<Shape> shapes{{1, 1, 4, 1}, {2, 1, 2, 3}, {1, 2, 1, 2}, {1, 1, 2, 3}};
+    float expected_buffer[] = {10,  0,  -10,  -20, 30,   -40, 50,   -60, 70,
+                               -80, 90, -100, 110, -120, 130, -140, 150, -160};
+    float scale = 10;
+    int32_t zero_point = 128;
+
+    std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
+    std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
+    std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
+    for (size_t i = 0; i < 4; ++i)
     {
-      layout = Layout::NCHW;
-      shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
-    }
-    inputs[i] =
-      std::make_unique<MockUpTensor>(shape, TypeInfo(DataType::FLOAT32), layout, input_pads[i]);
-    inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
+      Layout layout = Layout::NHWC;
+      Shape shape = shapes[i];
+      if (i % 2 == 1)
+      {
+        layout = Layout::NCHW;
+        shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
+      }
+      inputs[i] =
+        std::make_unique<MockUpTensor>(shape, TypeInfo(DataType::FLOAT32), layout, input_pads[i]);
+      inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
 
-    if (layout == Layout::NHWC)
-    {
-      layout = Layout::NCHW;
-      shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
-    }
-    else
-    {
-      layout = Layout::NHWC;
-      shape = shapes[i];
+      if (layout == Layout::NHWC)
+      {
+        layout = Layout::NCHW;
+        shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
+      }
+      else
+      {
+        layout = Layout::NHWC;
+        shape = shapes[i];
+      }
+      TypeInfo type_info{DataType::QUANT_UINT8_ASYMM, scale, zero_point};
+      outputs[i] = std::make_unique<MockUpTensor>(shape, type_info, layout, output_pads[i]);
+      output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
+      outputs[i]->setBuffer(output_buffers[i].get());
     }
-    TypeInfo type_info{DataType::QUANT_UINT8_ASYMM, scale, zero_point};
-    outputs[i] = std::make_unique<MockUpTensor>(shape, type_info, layout, output_pads[i]);
-    output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
-    outputs[i]->setBuffer(output_buffers[i].get());
-  }
 
-  auto mockup_layer = std::make_unique<MockUpLayer>(
-    std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
-    std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(), outputs[3].get()});
-  mockup_layer->run();
+    auto mockup_layer = std::make_unique<MockUpLayer>(
+      std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
+      std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(),
+                             outputs[3].get()});
+    mockup_layer->run();
 
-  for (size_t i = 0; i < 4; ++i)
-  {
-    for (int32_t j = 0; j < shapes[i].dim(0); ++j)
+    for (size_t i = 0; i < 4; ++i)
     {
-      for (int32_t k = 0; k < shapes[i].dim(1); ++k)
+      for (int32_t j = 0; j < shapes[i].dim(0); ++j)
       {
-        for (int32_t l = 0; l < shapes[i].dim(2); ++l)
+        for (int32_t k = 0; k < shapes[i].dim(1); ++k)
         {
-          for (int32_t m = 0; m < shapes[i].dim(3); ++m)
+          for (int32_t l = 0; l < shapes[i].dim(2); ++l)
           {
-            Coordinates input_coords;
-            Coordinates output_coords;
-            if (inputs[i]->layout() == Layout::NHWC)
-            {
-              input_coords = Coordinates{j, k, l, m};
-            }
-            else
-            {
-              input_coords = Coordinates{j, m, k, l};
-            }
-            if (outputs[i]->layout() == Layout::NHWC)
-            {
-              output_coords = Coordinates{j, k, l, m};
-            }
-            else
+            for (int32_t m = 0; m < shapes[i].dim(3); ++m)
             {
-              output_coords = Coordinates{j, m, k, l};
+              Coordinates input_coords;
+              Coordinates output_coords;
+              if (inputs[i]->layout() == Layout::NHWC)
+              {
+                input_coords = Coordinates{j, k, l, m};
+              }
+              else
+              {
+                input_coords = Coordinates{j, m, k, l};
+              }
+              if (outputs[i]->layout() == Layout::NHWC)
+              {
+                output_coords = Coordinates{j, k, l, m};
+              }
+              else
+              {
+                output_coords = Coordinates{j, m, k, l};
+              }
+              uint8_t qasymm8 = *reinterpret_cast<uint8_t *>(outputs[i]->buffer() +
+                                                             outputs[i]->calcOffset(output_coords));
+              float result = (qasymm8 - zero_point) * scale;
+              float expected = *reinterpret_cast<float *>(inputs[i]->buffer() +
+                                                          inputs[i]->calcOffset(input_coords));
+              EXPECT_EQ(result, expected);
             }
-            uint8_t qasymm8 = *reinterpret_cast<uint8_t *>(outputs[i]->buffer() +
-                                                           outputs[i]->calcOffset(output_coords));
-            float result = (qasymm8 - zero_point) * scale;
-            float expected =
-              *reinterpret_cast<float *>(inputs[i]->buffer() + inputs[i]->calcOffset(input_coords));
-            EXPECT_EQ(result, expected);
           }
         }
       }
     }
   }
-}
-
-TEST(IPermuteFunction, asymm8_to_float_layout)
-{
-  const size_t input_pads[4] = {0, 0, 1, 2};
-  const size_t output_pads[4] = {0, 3, 2, 1};
-  const std::vector<Shape> shapes{{1, 1, 4, 1}, {2, 1, 2, 3}, {1, 2, 1, 2}, {1, 1, 2, 3}};
-  float expected_buffer[] = {10,  0,  -10,  -20, 30,   -40, 50,   -60, 70,
-                             -80, 90, -100, 110, -120, 130, -140, 150, -160};
-  float scale = 10;
-  int32_t zero_point = 128;
-  uint8_t input_buffer[18];
 
-  int32_t min_val = std::numeric_limits<int16_t>::min();
-  int32_t max_val = std::numeric_limits<int16_t>::max();
-  for (int32_t i = 0; i < sizeof(expected_buffer) / sizeof(float); ++i)
+  // qasymm8 -> float
   {
-    int32_t unclamped = static_cast<int32_t>(std::round(expected_buffer[i] / scale)) + zero_point;
-    input_buffer[i] = std::min(std::max(unclamped, min_val), max_val);
-  }
+    const size_t input_pads[4] = {0, 0, 1, 2};
+    const size_t output_pads[4] = {0, 3, 2, 1};
+    const std::vector<Shape> shapes{{1, 1, 4, 1}, {2, 1, 2, 3}, {1, 2, 1, 2}, {1, 1, 2, 3}};
+    float expected_buffer[] = {10,  0,  -10,  -20, 30,   -40, 50,   -60, 70,
+                               -80, 90, -100, 110, -120, 130, -140, 150, -160};
+    float scale = 10;
+    int32_t zero_point = 128;
+    uint8_t input_buffer[18];
 
-  std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
-  std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
-  std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
-  for (size_t i = 0; i < 4; ++i)
-  {
-    Layout layout = Layout::NHWC;
-    Shape shape = shapes[i];
-    if (i % 2 == 1)
+    int32_t min_val = std::numeric_limits<int16_t>::min();
+    int32_t max_val = std::numeric_limits<int16_t>::max();
+    for (int32_t i = 0; i < sizeof(expected_buffer) / sizeof(float); ++i)
     {
-      layout = Layout::NCHW;
-      shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
+      int32_t unclamped = static_cast<int32_t>(std::round(expected_buffer[i] / scale)) + zero_point;
+      input_buffer[i] = std::min(std::max(unclamped, min_val), max_val);
     }
-    TypeInfo type_info{DataType::QUANT_UINT8_ASYMM, scale, zero_point};
-    inputs[i] = std::make_unique<MockUpTensor>(shape, type_info, layout, input_pads[i]);
-    inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
 
-    if (layout == Layout::NHWC)
-    {
-      layout = Layout::NCHW;
-      shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
-    }
-    else
+    std::vector<std::unique_ptr<MockUpTensor>> inputs(4);
+    std::vector<std::unique_ptr<MockUpTensor>> outputs(4);
+    std::vector<std::unique_ptr<uint8_t[]>> output_buffers(4);
+    for (size_t i = 0; i < 4; ++i)
     {
-      layout = Layout::NHWC;
-      shape = shapes[i];
+      Layout layout = Layout::NHWC;
+      Shape shape = shapes[i];
+      if (i % 2 == 1)
+      {
+        layout = Layout::NCHW;
+        shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
+      }
+      TypeInfo type_info{DataType::QUANT_UINT8_ASYMM, scale, zero_point};
+      inputs[i] = std::make_unique<MockUpTensor>(shape, type_info, layout, input_pads[i]);
+      inputs[i]->setBuffer(reinterpret_cast<uint8_t *>(expected_buffer));
+
+      if (layout == Layout::NHWC)
+      {
+        layout = Layout::NCHW;
+        shape = Shape{shapes[i].dim(0), shapes[i].dim(3), shapes[i].dim(1), shapes[i].dim(2)};
+      }
+      else
+      {
+        layout = Layout::NHWC;
+        shape = shapes[i];
+      }
+      outputs[i] =
+        std::make_unique<MockUpTensor>(shape, TypeInfo(DataType::FLOAT32), layout, output_pads[i]);
+      output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
+      outputs[i]->setBuffer(output_buffers[i].get());
     }
-    outputs[i] =
-      std::make_unique<MockUpTensor>(shape, TypeInfo(DataType::FLOAT32), layout, output_pads[i]);
-    output_buffers[i] = std::make_unique<uint8_t[]>(outputs[i]->total_size());
-    outputs[i]->setBuffer(output_buffers[i].get());
-  }
 
-  auto mockup_layer = std::make_unique<MockUpLayer>(
-    std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
-    std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(), outputs[3].get()});
-  mockup_layer->run();
+    auto mockup_layer = std::make_unique<MockUpLayer>(
+      std::vector<ITensor *>{inputs[0].get(), inputs[1].get(), inputs[2].get(), inputs[3].get()},
+      std::vector<ITensor *>{outputs[0].get(), outputs[1].get(), outputs[2].get(),
+                             outputs[3].get()});
+    mockup_layer->run();
 
-  for (size_t i = 0; i < 4; ++i)
-  {
-    for (int32_t j = 0; j < shapes[i].dim(0); ++j)
+    for (size_t i = 0; i < 4; ++i)
     {
-      for (int32_t k = 0; k < shapes[i].dim(1); ++k)
+      for (int32_t j = 0; j < shapes[i].dim(0); ++j)
       {
-        for (int32_t l = 0; l < shapes[i].dim(2); ++l)
+        for (int32_t k = 0; k < shapes[i].dim(1); ++k)
         {
-          for (int32_t m = 0; m < shapes[i].dim(3); ++m)
+          for (int32_t l = 0; l < shapes[i].dim(2); ++l)
           {
-            Coordinates input_coords;
-            Coordinates output_coords;
-            if (inputs[i]->layout() == Layout::NHWC)
+            for (int32_t m = 0; m < shapes[i].dim(3); ++m)
             {
-              input_coords = Coordinates{j, k, l, m};
+              Coordinates input_coords;
+              Coordinates output_coords;
+              if (inputs[i]->layout() == Layout::NHWC)
+              {
+                input_coords = Coordinates{j, k, l, m};
+              }
+              else
+              {
+                input_coords = Coordinates{j, m, k, l};
+              }
+              if (outputs[i]->layout() == Layout::NHWC)
+              {
+                output_coords = Coordinates{j, k, l, m};
+              }
+              else
+              {
+                output_coords = Coordinates{j, m, k, l};
+              }
+              float result = *reinterpret_cast<float *>(outputs[i]->buffer() +
+                                                        outputs[i]->calcOffset(output_coords));
+              uint8_t qasymm8 = *reinterpret_cast<uint8_t *>(inputs[i]->buffer() +
+                                                             inputs[i]->calcOffset(input_coords));
+              float expected = (qasymm8 - zero_point) * scale;
+              EXPECT_EQ(result, expected);
             }
-            else
-            {
-              input_coords = Coordinates{j, m, k, l};
-            }
-            if (outputs[i]->layout() == Layout::NHWC)
-            {
-              output_coords = Coordinates{j, k, l, m};
-            }
-            else
-            {
-              output_coords = Coordinates{j, m, k, l};
-            }
-            float result = *reinterpret_cast<float *>(outputs[i]->buffer() +
-                                                      outputs[i]->calcOffset(output_coords));
-            uint8_t qasymm8 = *reinterpret_cast<uint8_t *>(inputs[i]->buffer() +
-                                                           inputs[i]->calcOffset(input_coords));
-            float expected = (qasymm8 - zero_point) * scale;
-            EXPECT_EQ(result, expected);
           }
         }
       }
index a64dadc..228c4d3 100644 (file)
@@ -24,13 +24,13 @@ namespace onert
 namespace exec
 {
 
-void LinearExecutor::executeImpl()
+void LinearExecutor::executeImpl(const ExecutionObservee &subject)
 {
-  if (_tracing_ctx)
+  if (!subject.isEmpty() && _tracing_ctx)
   {
     auto profiling_subg_index = _tracing_ctx->getSubgraphIndex(&_graph);
 
-    _subject.notifySubgraphBegin(profiling_subg_index);
+    subject.notifySubgraphBegin(profiling_subg_index);
     for (auto &&code : _code)
     {
       const auto backend = code.lower_info->backend();
@@ -38,7 +38,7 @@ void LinearExecutor::executeImpl()
 #ifdef RUY_PROFILER
       ruy::profiler::ScopeLabel label(code.op->name());
 #endif
-      _subject.notifyJobBegin(this, profiling_subg_index, code.op_ind, backend);
+      subject.notifyJobBegin(this, profiling_subg_index, code.op_ind, backend);
 
       auto &fn_seq = code.fn_seq;
 
@@ -49,9 +49,9 @@ void LinearExecutor::executeImpl()
       fn_seq->enableDynamicShapeInferer(handle_dynamic_tensor);
       fn_seq->run();
 
-      _subject.notifyJobEnd(this, profiling_subg_index, code.op_ind, backend);
+      subject.notifyJobEnd(this, profiling_subg_index, code.op_ind, backend);
     }
-    _subject.notifySubgraphEnd(profiling_subg_index);
+    subject.notifySubgraphEnd(profiling_subg_index);
   }
   else
   {
index cc07341..853632a 100644 (file)
@@ -59,7 +59,7 @@ public:
   }
 
 public:
-  void executeImpl(void) override;
+  void executeImpl(const ExecutionObservee &subject) override;
 
 private:
   std::vector<compiler::CodeAndInfo> _code;
diff --git a/runtime/onert/core/src/exec/MinMaxData.cc b/runtime/onert/core/src/exec/MinMaxData.cc
new file mode 100644 (file)
index 0000000..1d18252
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "MinMaxData.h"
+
+#include <iostream>
+
+namespace onert
+{
+namespace exec
+{
+
+RawMinMaxDumper::RawMinMaxDumper(const std::string &filename) : _filename(filename) {}
+
+void RawMinMaxDumper::dump(const exec::IOMinMaxMap &input_minmax,
+                           const exec::OpMinMaxMap &op_minmax) const
+{
+  // Find file is already exist for modifying
+  auto file = std::fopen(_filename.c_str(), "rb+");
+  uint32_t runs = 1;
+
+  // Magic code and version
+  // Match with runtime/onert/odc/MinMaxReader.cc
+  // TODO Use util to share code and version
+  const uint32_t MAGIC_CODE = 0x4F4D4D44;
+  const uint32_t VERSION = 1;
+  if (!file)
+  {
+    // If file is not exist, create new file
+    file = std::fopen(_filename.c_str(), "wb+");
+    if (!file)
+      throw std::runtime_error{"RawMinMaxDumper: Failed to open minmax file " + _filename};
+
+    // Write magic code and version
+    std::fwrite(&MAGIC_CODE, sizeof(uint32_t), 1, file);
+    std::fwrite(&VERSION, sizeof(uint32_t), 1, file);
+  }
+  else
+  {
+    // Check magic code and version
+    std::fseek(file, 0, SEEK_SET);
+    uint32_t read_magic_code = 0;
+    uint32_t read_version = 0;
+    bool rewrite = true;
+    if (std::fread(&read_magic_code, sizeof(uint32_t), 1, file) == 1 &&
+        read_magic_code == MAGIC_CODE &&
+        std::fread(&read_version, sizeof(uint32_t), 1, file) == 1 && read_version == VERSION)
+      rewrite = false;
+
+    // Destroy and create if file is not valid
+    if (rewrite)
+    {
+      std::fclose(file);
+      file = std::fopen(_filename.c_str(), "wb+");
+      if (!file)
+        throw std::runtime_error{"RawMinMaxDumper: Failed to rewrite minmax file " + _filename};
+
+      // Write magic code and version
+      std::fwrite(&MAGIC_CODE, sizeof(uint32_t), 1, file);
+      std::fwrite(&VERSION, sizeof(uint32_t), 1, file);
+    }
+  }
+
+  // Read run count
+  if (std::fread(&runs, sizeof(uint32_t), 1, file) == 1)
+    runs++;
+  else
+    runs = 1;
+
+  // TODO Verify file size
+
+  // Overwrite run count
+  std::fseek(file, sizeof(MAGIC_CODE) + sizeof(VERSION), SEEK_SET);
+  std::fwrite(&runs, sizeof(uint32_t), 1, file);
+
+  // Go to end of file to append new data
+  std::fseek(file, 0, SEEK_END);
+
+  uint32_t input_count = input_minmax.size();
+  uint32_t op_count = op_minmax.size();
+
+  // Write op_count and input_count
+  std::fwrite(&op_count, sizeof(uint32_t), 1, file);
+  std::fwrite(&input_count, sizeof(uint32_t), 1, file);
+
+  // For each op
+  for (auto &&elem : op_minmax)
+  {
+    const uint32_t model_idx = 0;
+    const uint32_t subg_idx = elem.first.first.value();
+    const uint32_t op_idx = elem.first.second.value();
+
+    // Write model/subg/op index
+    std::fwrite(&model_idx, sizeof(uint32_t), 1, file);
+    std::fwrite(&subg_idx, sizeof(uint32_t), 1, file);
+    std::fwrite(&op_idx, sizeof(uint32_t), 1, file);
+
+    // Write min/max
+    std::fwrite(elem.second.data, sizeof(float), 2, file);
+  }
+
+  // For each input
+  for (auto &&elem : input_minmax)
+  {
+    const uint32_t model_idx = 0;
+    const uint32_t subg_idx = elem.first.first.value();
+    const uint32_t input_idx = elem.first.second.value();
+
+    // Write model/subg/input index
+    std::fwrite(&model_idx, sizeof(uint32_t), 1, file);
+    std::fwrite(&subg_idx, sizeof(uint32_t), 1, file);
+    std::fwrite(&input_idx, sizeof(uint32_t), 1, file);
+
+    // Write min/max
+    std::fwrite(elem.second.data, sizeof(float), 2, file);
+  }
+
+  std::fclose(file);
+}
+
+} // namespace exec
+} // namespace onert
diff --git a/runtime/onert/core/src/exec/MinMaxData.h b/runtime/onert/core/src/exec/MinMaxData.h
new file mode 100644 (file)
index 0000000..2538d44
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_DATA_H__
+#define __ONERT_EXEC_MINMAX_DATA_H__
+
+#include "exec/MinMaxMap.h"
+
+#include <string>
+
+namespace onert
+{
+namespace exec
+{
+
+// Because IOMinMaxMap and OpMinMaxMap does not have the ordering and size information,
+// we need to dump model, subgraph id for each minmax
+
+// File structure
+// uint32_t magic code
+// uint32_t version
+// uint32_t num of runs
+
+// For each run
+// uint32_t num of operations
+// uint32_t num of inputs
+
+// For each operation
+// uint32_t model id
+// uint32_t subgraph id
+// uint32_t operation id
+// float min
+// float max
+
+// For each input
+// uint32_t model id
+// uint32_t subgraph id
+// uint32_t input id
+// float min
+// float max
+
+class RawMinMaxDumper
+{
+public:
+  RawMinMaxDumper(const std::string &filename);
+  /**
+   * @brief Dump input minmax map
+   *
+   * @param[in] in_minmax  input minmax map
+   * @param[in] op_minmax  op minmax map
+   */
+
+  void dump(const exec::IOMinMaxMap &in_minmax, const exec::OpMinMaxMap &op_minmax) const;
+
+private:
+  std::string _filename;
+};
+
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_MINMAX_DATA_H__
index 88fc104..1798000 100644 (file)
  */
 
 #include "MinMaxRecorder.h"
-
+#if MINMAX_H5DUMPER
+#include "../dumper/h5/MinMaxDumper.h"
+#else
+#include "MinMaxData.h"
+#endif
 #include "backend/ITensor.h"
 
 #include <cassert>
@@ -26,10 +30,44 @@ namespace onert
 namespace exec
 {
 
-MinMaxRecorder::MinMaxRecorder(const std::string &minmax_filepath, const ir::Graph &graph,
+MinMaxRecorder::MinMaxRecorder(const std::string &workspace_dir, const ir::Graph &graph,
                                const backend::BackendContexts &backend_contexts)
-  : _graph{graph}, _backend_contexts{backend_contexts}, _h5dumper(minmax_filepath)
+  : _graph{graph}, _backend_contexts{backend_contexts}, _workspace_dir(workspace_dir)
+{
+  // DO NOTHING
+}
+
+std::pair<float, float> minmaxFrom(const backend::ITensor *tensor)
 {
+  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)");
+
+  return {min, max};
 }
 
 void MinMaxRecorder::handleJobEnd(IExecutor *, ir::SubgraphIndex subg_idx,
@@ -70,42 +108,53 @@ void MinMaxRecorder::handleJobEnd(IExecutor *, ir::SubgraphIndex subg_idx,
 
   // 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();
+  auto minmax = minmaxFrom(tensor);
+  _op_minmax.append({subg_idx, op_idx}, minmax.first, minmax.second);
+}
 
-  bool all_nan = true;
-  for (size_t i = 0; i < num_elements; ++i)
+void MinMaxRecorder::handleSubgraphBegin(ir::SubgraphIndex subg_idx)
+{
+  // Make sure there is only cpu backend except for builtin backend
+  std::set<std::string> backend_names;
+  backend::ITensorRegistry *tensor_reg = nullptr;
+  for (const auto &pair : _backend_contexts)
   {
-    const float number = data[i];
-    if (std::isnan(number))
-      continue;
-
-    if (number == std::numeric_limits<float>::lowest())
-      continue;
+    backend_names.insert(pair.first->config()->id());
+    if (pair.first->config()->id() == "cpu")
+    {
+      tensor_reg = pair.second->tensor_registry.get();
+    }
+  }
+  if (backend_names != std::set<std::string>{"builtin", "cpu"})
+    throw std::runtime_error("MinMaxRecorder must have cpu backend only.");
 
-    all_nan = false;
+  const auto &inputs = _graph.getInputs(); //.at(op_idx);
+  for (uint32_t i = 0; i < inputs.size(); ++i)
+  {
+    auto input_idx = inputs.at(i);
+    auto tensor = tensor_reg->getITensor(input_idx);
 
-    if (number > max)
-      max = number;
+    if (tensor->is_constant())
+      return;
+    if (tensor->data_type() != ir::DataType::FLOAT32)
+      return;
 
-    if (number < min)
-      min = number;
+    auto minmax = minmaxFrom(tensor);
+    _input_minmax.append({subg_idx, ir::IOIndex{i}}, minmax.first, minmax.second);
   }
-
-  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);
+#if MINMAX_H5DUMPER
+  auto h5dumper = dumper::h5::MinMaxDumper(_workspace_dir + "/minmax.h5");
+  h5dumper.dump(_input_minmax, _op_minmax);
+#else
+  auto raw_dumper = RawMinMaxDumper(_workspace_dir + "/minmax.bin");
+  raw_dumper.dump(_input_minmax, _op_minmax);
+#endif
 }
 
 } // namespace exec
index 7a0817f..ed51639 100644 (file)
@@ -20,9 +20,8 @@
 #include "ExecutionObservers.h"
 #include "ir/Index.h"
 #include "exec/MinMaxMap.h"
-#include "../dumper/h5/MinMaxDumper.h"
 
-#include <memory>
+#include <string>
 
 namespace onert
 {
@@ -32,7 +31,7 @@ namespace exec
 class MinMaxRecorder : public IExecutionObserver
 {
 public:
-  MinMaxRecorder(const std::string &minmax_filepath, const ir::Graph &graph,
+  MinMaxRecorder(const std::string &workspace_dir, const ir::Graph &graph,
                  const backend::BackendContexts &backend_contexts);
   void handleJobBegin(IExecutor *, ir::SubgraphIndex, ir::OperationIndex,
                       const backend::Backend *) override
@@ -41,13 +40,16 @@ public:
   }
   void handleJobEnd(IExecutor *, ir::SubgraphIndex, ir::OperationIndex,
                     const backend::Backend *) override;
+  void handleSubgraphBegin(ir::SubgraphIndex) override;
   void handleSubgraphEnd(ir::SubgraphIndex) override;
+  ObserverType type() const override { return ObserverType::MINMAX_DUMP; }
 
 private:
   const ir::Graph &_graph;
   const backend::BackendContexts &_backend_contexts;
-  dumper::h5::MinMaxDumper _h5dumper;
-  SMMinMaxMap _minmax_map;
+  std::string _workspace_dir;
+  OpMinMaxMap _op_minmax;
+  IOMinMaxMap _input_minmax;
 };
 
 } // namespace exec
diff --git a/runtime/onert/core/src/exec/MultiModelExecutors.cc b/runtime/onert/core/src/exec/MultiModelExecutors.cc
new file mode 100644 (file)
index 0000000..920b17d
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ * 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 "MultiModelExecutors.h"
+
+namespace
+{
+
+using namespace onert;
+
+int32_t find_input_index(const std::vector<ir::IODesc> &pkg_inputs,
+                         const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index,
+                         const ir::IOIndex &io_index)
+{
+  for (size_t i = 0; i < pkg_inputs.size(); i++)
+  {
+    auto &input_desc = pkg_inputs[i];
+    if ((std::get<ir::ModelIndex>(input_desc) == model_index) &&
+        (std::get<ir::SubgraphIndex>(input_desc) == subg_index) &&
+        (std::get<ir::IOIndex>(input_desc) == io_index))
+      return static_cast<int32_t>(i);
+  }
+  return -1;
+}
+
+int32_t find_output_index(const std::vector<ir::IODesc> &pkg_outputs,
+                          const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index,
+                          const ir::IOIndex &io_index)
+{
+  for (size_t i = 0; i < pkg_outputs.size(); i++)
+  {
+    auto &input_desc = pkg_outputs[i];
+    if ((std::get<ir::ModelIndex>(input_desc) == model_index) &&
+        (std::get<ir::SubgraphIndex>(input_desc) == subg_index) &&
+        (std::get<ir::IOIndex>(input_desc) == io_index))
+      return static_cast<int32_t>(i);
+  }
+  return -1;
+}
+
+} // namespace
+
+namespace onert
+{
+namespace exec
+{
+
+void MultiModelExecutors::emplace(const ir::ModelIndex &model_index,
+                                  const ir::SubgraphIndex &subg_index,
+                                  std::unique_ptr<IExecutor> exec)
+{
+  _executors.emplace(std::make_pair(model_index, subg_index), std::move(exec));
+}
+
+IExecutor *MultiModelExecutors::at(const ir::ModelIndex &model_index,
+                                   const ir::SubgraphIndex &subg_index) const
+{
+  return _executors.at(std::make_pair(model_index, subg_index)).get();
+}
+
+uint32_t MultiModelExecutors::inputSize() const { return _model_edges->pkg_inputs.size(); }
+
+uint32_t MultiModelExecutors::outputSize() const { return _model_edges->pkg_outputs.size(); }
+
+const ir::OperandInfo &MultiModelExecutors::inputInfo(const ir::IOIndex &index) const
+{
+  auto const desc = _model_edges->pkg_inputs[index.value()];
+  auto const model_index = std::get<0>(desc);
+  auto const subg_index = std::get<1>(desc);
+  auto const io_index = std::get<2>(desc);
+  auto const executor = at(model_index, subg_index);
+  return executor->inputInfo(io_index.value());
+}
+
+const ir::OperandInfo &MultiModelExecutors::outputInfo(const ir::IOIndex &index) const
+{
+  auto const desc = _model_edges->pkg_outputs[index.value()];
+  auto const model_index = std::get<0>(desc);
+  auto const subg_index = std::get<1>(desc);
+  auto const io_index = std::get<2>(desc);
+  auto const executor = at(model_index, subg_index);
+  return executor->outputInfo(io_index.value());
+}
+
+// Allow below edges only
+//  m1 < m2, s1 == 0 and s2 == 0 if m1:s1:o1 -> m2:s2:o2'
+void MultiModelExecutors::checkSupportedMultimodel() const
+{
+  // If package includes no-connection model, model_count is less than real model count in package.
+  // Then this method will throw exception based on model index
+  //  1st model: input assumption
+  //  Otherwise: edges assumption
+
+  // Assumption: edges
+  // m1 < m2, s1 == 0 and s2 == 0 if edge 'm1:s1:o1 -> m2:s2:o2'
+  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);
+    auto const subg_from = std::get<ir::SubgraphIndex>(edge.from);
+    auto const subg_to = std::get<ir::SubgraphIndex>(edge.to);
+
+    if (model_from.value() == model_to.value())
+    {
+      throw std::runtime_error{"Multi model's edge set has invalid edge"};
+    }
+
+    if ((model_from.value() > model_to.value()) || (subg_from != ir::SubgraphIndex{0}) ||
+        (subg_to != ir::SubgraphIndex{0}))
+      throw std::runtime_error{"NYI: Multi model execution for this edge set is not supported yet"};
+  }
+
+  // Assumption: package inputs
+  //  All 1st model inputs come from package input if always m1 < m2
+  {
+    auto first_executor = at(ir::ModelIndex{0}, ir::SubgraphIndex{0});
+    auto search_first_model = [&](const ir::IOIndex &input_index) {
+      for (const auto &input : _model_edges->pkg_inputs)
+      {
+        if ((std::get<ir::ModelIndex>(input) == ir::ModelIndex{0}) ||
+            (std::get<ir::SubgraphIndex>(input) == ir::SubgraphIndex{0}) ||
+            (std::get<ir::IOIndex>(input) == input_index))
+          return true;
+      }
+
+      return false;
+    };
+
+    for (uint32_t i = 0; i < first_executor->inputSize(); i++)
+    {
+      if (!search_first_model(ir::IOIndex{i}))
+        throw std::runtime_error{"Cannot find 1st model's input buffer"};
+    }
+  }
+
+  // Check whether nnpkg outputs and Edge `from` are duplicated
+  for (const auto &edge : _model_edges->edges)
+  {
+    if (std::find(_model_edges->pkg_outputs.begin(), _model_edges->pkg_outputs.end(), edge.from) !=
+        _model_edges->pkg_outputs.end())
+    {
+      throw std::runtime_error{"Multi model execution does not support duplicating nnpkg outputs "
+                               "with `from` of edges yet"};
+    }
+  }
+}
+
+void MultiModelExecutors::createEdgeQuantLayers()
+{
+  if (_is_created_edge_quant_layers)
+  {
+    return;
+  }
+
+  // Create EdgeTensor for edges between executors
+  for (const auto &pair : _edge_map)
+  {
+    const auto &from_iodesc = pair.first;
+    const auto &from_model_index = std::get<ir::ModelIndex>(from_iodesc);
+    const auto &from_subg_index = std::get<ir::SubgraphIndex>(from_iodesc);
+    const auto &from_io_index = std::get<ir::IOIndex>(from_iodesc);
+
+    const auto from_executor = _executors.at({from_model_index, from_subg_index}).get();
+    const auto &from_info = from_executor->inputInfo(from_io_index.value());
+    const auto from_layout = from_executor->inputLayout(from_io_index.value());
+    _edge_tensors[from_iodesc] = std::make_unique<EdgeTensor>(from_info, from_layout);
+  }
+
+  // Append type-aware quantization layer for edges between executors
+  for (const auto &executor_pair : _executors)
+  {
+    const auto &executor_index = executor_pair.first;
+    const auto &model_index = executor_index.first;
+    const auto &subg_index = executor_index.second;
+
+    std::vector<backend::ITensor *> inputs;
+    std::vector<backend::ITensor *> outputs;
+    for (const auto &pair : _edge_map)
+    {
+      const auto &from_iodesc = pair.first;
+      if (std::get<ir::ModelIndex>(from_iodesc) == model_index &&
+          std::get<ir::SubgraphIndex>(from_iodesc) == subg_index)
+      {
+        const auto from_tensor = _edge_tensors[from_iodesc].get();
+        const auto &to_list = pair.second;
+
+        for (const auto &to_iodesc : to_list)
+        {
+          const auto &to_model_index = std::get<ir::ModelIndex>(to_iodesc);
+          const auto &to_subg_index = std::get<ir::SubgraphIndex>(to_iodesc);
+          const auto &to_io_index = std::get<ir::IOIndex>(to_iodesc);
+
+          const auto to_executor = _executors.at({to_model_index, to_subg_index}).get();
+          const auto &to_info = to_executor->inputInfo(to_io_index.value());
+          const auto to_layout = to_executor->inputLayout(to_io_index.value());
+
+          // TODO Unify tensors with the same `from` tensor and same type
+          if (from_tensor->data_type() != to_info.typeInfo().type())
+          {
+            assert(inputs.size() == outputs.size());
+            inputs.emplace_back(from_tensor);
+
+            auto type_aware_quant_tensor = std::make_unique<EdgeTensor>(to_info, to_layout);
+            outputs.emplace_back(type_aware_quant_tensor.get());
+
+            _edge_quant_tensors[to_iodesc] = std::move(type_aware_quant_tensor);
+          }
+        }
+      }
+    }
+
+    auto layer = std::make_unique<PermuteLayer>(inputs, outputs);
+    layer->prepare();
+    _edge_quant_layers[{model_index, subg_index}] = std::move(layer);
+  }
+
+  _is_created_edge_quant_layers = true;
+}
+
+void MultiModelExecutors::CreatePkgIOTensors(const IODescription &desc)
+{
+  for (const auto &pkg_input : _model_edges->pkg_inputs)
+  {
+    // Create IOTensor for nnpkg inputs
+    const auto &model_index = std::get<ir::ModelIndex>(pkg_input);
+    const auto &subg_index = std::get<ir::SubgraphIndex>(pkg_input);
+    const auto &io_index = std::get<ir::IOIndex>(pkg_input);
+    const auto input_pkg_index =
+      find_input_index(_model_edges->pkg_inputs, model_index, subg_index, io_index);
+    if (input_pkg_index == -1)
+      throw std::runtime_error{"Cannot find multi model input index"};
+    auto input_desc = desc.inputs[input_pkg_index].get();
+    // TODO Remove const_cast (we need const_cast as ITensor is writable)
+    _pkg_input_tensors[pkg_input] = std::make_unique<backend::builtin::UserTensor>(
+      input_desc->info, input_desc->layout,
+      const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(input_desc->buffer)),
+      input_desc->size);
+  }
+
+  for (const auto &pkg_output : _model_edges->pkg_outputs)
+  {
+    // Create IOTensor for nnpkg outputs
+    const auto &model_index = std::get<ir::ModelIndex>(pkg_output);
+    const auto &subg_index = std::get<ir::SubgraphIndex>(pkg_output);
+    const auto &io_index = std::get<ir::IOIndex>(pkg_output);
+    const auto output_pkg_index =
+      find_output_index(_model_edges->pkg_outputs, model_index, subg_index, io_index);
+    if (output_pkg_index == -1)
+      throw std::runtime_error{"Cannot find multi model output index"};
+    auto output_desc = desc.outputs[output_pkg_index].get();
+    _pkg_output_tensors[pkg_output] = std::make_unique<backend::builtin::UserTensor>(
+      output_desc->info, output_desc->layout, reinterpret_cast<uint8_t *>(output_desc->buffer),
+      output_desc->size);
+  }
+}
+
+void MultiModelExecutors::createPkgIOQuantLayers(const IODescription &desc)
+{
+  // Append type-aware quantization layer for nnpkg inputs/outputs between executors
+  for (const auto &pair : _executors)
+  {
+    const auto &executor_index = pair.first;
+    const auto &model_index = executor_index.first;
+    const auto &subg_index = executor_index.second;
+    const auto executor = pair.second.get();
+
+    // Find pkg inputs of current executor
+    std::vector<ir::IODesc> pkg_inputs;
+    for (const auto &pkg_input : _model_edges->pkg_inputs)
+    {
+      if (std::get<ir::ModelIndex>(pkg_input) == model_index &&
+          std::get<ir::SubgraphIndex>(pkg_input) == subg_index)
+      {
+        pkg_inputs.emplace_back(pkg_input);
+      }
+    }
+    std::vector<backend::ITensor *> src_tensors;
+    std::vector<backend::ITensor *> dst_tensors;
+    for (const auto &pkg_input : pkg_inputs)
+    {
+      const auto &io_index = std::get<ir::IOIndex>(pkg_input);
+      const auto input_pkg_index =
+        find_input_index(_model_edges->pkg_inputs, model_index, subg_index, io_index);
+      if (input_pkg_index == -1)
+        throw std::runtime_error{"Cannot find multi model input index"};
+      auto input_desc = desc.inputs[input_pkg_index].get();
+
+      // Create EdgeTensor for nnpkg input if type is different
+      const auto &orig_info = executor->inputInfo(io_index.value());
+      const auto orig_layout = executor->inputLayout(io_index.value());
+      if (input_desc->info.typeInfo().type() != orig_info.typeInfo().type())
+      {
+        auto pkg_input_edge_tensor = std::make_unique<EdgeTensor>(orig_info, orig_layout);
+        _pkg_input_quant_tensors[pkg_input] = std::move(pkg_input_edge_tensor);
+
+        // Append type-aware quantization layer's inputs/outputs
+        src_tensors.emplace_back(_pkg_input_tensors[pkg_input].get());
+        dst_tensors.emplace_back(_pkg_input_quant_tensors[pkg_input].get());
+      }
+    }
+
+    // Create type-aware quantization layer for nnpkg inputs
+    auto pkg_input_layer = std::make_unique<PermuteLayer>(src_tensors, dst_tensors);
+    pkg_input_layer->prepare();
+    _pkg_input_quant_layers[{model_index, subg_index}] = std::move(pkg_input_layer);
+
+    // Find pkg outputs of current executor
+    std::vector<ir::IODesc> pkg_outputs;
+    for (const auto &pkg_output : _model_edges->pkg_outputs)
+    {
+      if (std::get<ir::ModelIndex>(pkg_output) == model_index &&
+          std::get<ir::SubgraphIndex>(pkg_output) == subg_index)
+      {
+        pkg_outputs.emplace_back(pkg_output);
+      }
+    }
+    src_tensors.clear();
+    dst_tensors.clear();
+    // Create Tensors of nnpkg outputs for type-aware quantization
+    for (const auto &pkg_output : pkg_outputs)
+    {
+      const auto &io_index = std::get<ir::IOIndex>(pkg_output);
+      const auto output_pkg_index =
+        find_output_index(_model_edges->pkg_outputs, model_index, subg_index, io_index);
+      if (output_pkg_index == -1)
+        throw std::runtime_error{"Cannot find multi model output index"};
+      auto output_desc = desc.outputs[output_pkg_index].get();
+
+      // Create EdgeTensor for nnpkg output if type is different
+      const auto &orig_info = executor->outputInfo(io_index.value());
+      const auto orig_layout = executor->outputLayout(io_index.value());
+      if (output_desc->info.typeInfo().type() != orig_info.typeInfo().type())
+      {
+        auto pkg_output_edge_tensor = std::make_unique<EdgeTensor>(orig_info, orig_layout);
+        _pkg_output_quant_tensors[pkg_output] = std::move(pkg_output_edge_tensor);
+
+        // Append type-aware quantization layer's inputs/outputs
+        src_tensors.emplace_back(_pkg_output_quant_tensors[pkg_output].get());
+        dst_tensors.emplace_back(_pkg_output_tensors[pkg_output].get());
+      }
+    }
+
+    // Create type-aware quantization layer for nnpkg outputs
+    auto pkg_output_layer = std::make_unique<PermuteLayer>(src_tensors, dst_tensors);
+    pkg_output_layer->prepare();
+    _pkg_output_quant_layers[{model_index, subg_index}] = std::move(pkg_output_layer);
+  }
+}
+
+void MultiModelExecutors::execute(const ExecutionContext &ctx)
+{
+  auto &desc = ctx.desc;
+
+  // Check supported multi model package
+  checkSupportedMultimodel();
+
+  // TODO Move creating type-aware quantization layers for edges in compilation stage
+  createEdgeQuantLayers();
+
+  // TODO Create IOTensors only once and recreate them only if nnpkg info changes
+  CreatePkgIOTensors(desc);
+
+  // TODO Create type-aware quantization layers only once and recreate them only if type changes
+  createPkgIOQuantLayers(desc);
+
+  // TODO Find better way to schedule order of executors
+  auto const model_count = modelCount();
+
+  auto find_from = [&](const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index,
+                       const ir::IOIndex &io_index) {
+    for (const auto &edge : _model_edges->edges)
+    {
+      if ((std::get<ir::ModelIndex>(edge.to) == model_index) &&
+          (std::get<ir::SubgraphIndex>(edge.to) == subg_index) &&
+          (std::get<ir::IOIndex>(edge.to) == io_index))
+        return edge.from;
+    }
+
+    throw std::runtime_error{"Cannot find edge for model input"};
+  };
+
+  // Execute each model
+  // NOTE May be better to use vector instead of unordered_map for _executors
+  for (auto model_index = ir::ModelIndex{0}; model_index.value() < model_count; model_index++)
+  {
+    // Find executor
+    auto executor = at(model_index, ir::SubgraphIndex{0});
+
+    // Set IOTensors
+    // TODO Set internal IOTensors only once
+    std::vector<backend::IPortableTensor *> inputs_inter;
+    std::vector<backend::IPortableTensor *> outputs_inter;
+    auto const input_size = executor->inputSize();
+    auto const output_size = executor->outputSize();
+    inputs_inter.resize(input_size);
+    outputs_inter.resize(output_size);
+
+    // Set inputs of executor
+    // TODO Create layer to allocate/deallocate buffers of EdgeTensor for each executor
+    for (uint32_t i = 0; i < input_size; i++)
+    {
+      const auto input_pkg_index = find_input_index(_model_edges->pkg_inputs, model_index,
+                                                    ir::SubgraphIndex{0}, ir::IOIndex{i});
+      const auto input_io_desc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
+      if (input_pkg_index != -1)
+      {
+        // Allocate type-aware quantization tensors for nnpkg inputs and set internal tensors
+        if (_pkg_input_quant_tensors.find(input_io_desc) != _pkg_input_quant_tensors.end())
+        {
+          _pkg_input_quant_tensors[input_io_desc]->allocate_buffer();
+
+          inputs_inter[i] = _pkg_input_quant_tensors[input_io_desc].get();
+        }
+        else
+        {
+          inputs_inter[i] = _pkg_input_tensors[input_io_desc].get();
+        }
+      }
+      else
+      {
+        auto from_iodesc = find_from(model_index, ir::SubgraphIndex{0}, ir::IOIndex{i});
+
+        // Supported only sequantial execution of models
+        assert(std::get<ir::ModelIndex>(from_iodesc).value() < model_index.value());
+        assert(std::get<ir::SubgraphIndex>(from_iodesc).value() == 0);
+        const auto to_iodesc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
+        if (_edge_quant_tensors.find(to_iodesc) == _edge_quant_tensors.end())
+        {
+          inputs_inter[i] = _edge_tensors.at(from_iodesc).get();
+        }
+        else
+        {
+          inputs_inter[i] = _edge_quant_tensors.at(to_iodesc).get();
+        }
+        assert(inputs_inter[i]->buffer() != nullptr);
+      }
+    }
+
+    // Set outputs of executor
+    for (uint32_t i = 0; i < output_size; i++)
+    {
+      const auto output_pkg_index = find_output_index(_model_edges->pkg_outputs, model_index,
+                                                      ir::SubgraphIndex{0}, ir::IOIndex{i});
+      const auto output_io_desc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
+      if (output_pkg_index != -1)
+      {
+        // Allocate type-aware quantization tensors for nnpkg outputs and set internal tensors
+        if (_pkg_output_quant_tensors.find(output_io_desc) != _pkg_output_quant_tensors.end())
+        {
+          _pkg_output_quant_tensors[output_io_desc]->allocate_buffer();
+
+          outputs_inter[i] = _pkg_output_quant_tensors[output_io_desc].get();
+        }
+        else
+        {
+          outputs_inter[i] = _pkg_output_tensors[output_io_desc].get();
+        }
+      }
+      else
+      {
+        // Allocate buffer of `from` tensors
+        const auto from_iodesc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
+        _edge_tensors[from_iodesc]->allocate_buffer();
+        outputs_inter[i] = _edge_tensors[from_iodesc].get();
+
+        // Allocate buffer of tensors for type-aware quantization
+        for (const auto &to_iodesc : _edge_map[from_iodesc])
+        {
+          _edge_tensors[from_iodesc]->increase_ref();
+          if (_edge_quant_tensors.find(to_iodesc) != _edge_quant_tensors.end())
+          {
+            auto type_aware_quant_tensor = _edge_quant_tensors.at(to_iodesc).get();
+            type_aware_quant_tensor->allocate_buffer();
+
+            _edge_tensors[from_iodesc]->decrease_ref();
+          }
+        }
+      }
+    }
+
+    _pkg_input_quant_layers[{model_index, ir::SubgraphIndex{0}}]->run();
+
+    executor->execute(inputs_inter, outputs_inter, ctx.options);
+
+    _edge_quant_layers[{model_index, ir::SubgraphIndex{0}}]->run();
+    _pkg_output_quant_layers[{model_index, ir::SubgraphIndex{0}}]->run();
+
+    // Release input buffers that are no longer needed
+    for (uint32_t i = 0; i < input_size; i++)
+    {
+      const auto input_pkg_index = find_input_index(_model_edges->pkg_inputs, model_index,
+                                                    ir::SubgraphIndex{0}, ir::IOIndex{i});
+
+      const auto to_iodesc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
+      if (input_pkg_index == -1)
+      {
+        if (_edge_quant_tensors.find(to_iodesc) != _edge_quant_tensors.end())
+        {
+          // Decrease reference count of tensor for type-aware quantization if input tensor is the
+          // tensor
+          const auto to_iodesc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
+          if (_edge_quant_tensors.find(to_iodesc) != _edge_quant_tensors.end())
+          {
+            _edge_quant_tensors[to_iodesc]->decrease_ref();
+          }
+        }
+        else
+        {
+          // Decrease reference count of `from` tensor if input tensor is the `from` tensor
+          const auto from_iodesc = find_from(model_index, ir::SubgraphIndex{0}, ir::IOIndex{i});
+          _edge_tensors[from_iodesc]->decrease_ref();
+
+          // Decrease reference count of nnpkg inputs
+          if (_pkg_input_quant_tensors.find(to_iodesc) != _pkg_input_quant_tensors.end())
+          {
+            _pkg_input_quant_tensors[to_iodesc]->decrease_ref();
+          }
+        }
+      }
+    }
+
+    // Release output buffers if those buffers are no longer used other executors because of
+    // type-aware quantization
+    // FIXME if tensors for type-aware quantization unified for the same `from` tensor and same type
+    for (uint32_t i = 0; i < output_size; i++)
+    {
+      auto from_iodesc = ir::IODesc{model_index, ir::SubgraphIndex{0}, ir::IOIndex{i}};
+
+      // Check if other executors will use the buffer of edge tensor
+      const auto &to_list = _edge_map[from_iodesc];
+      if (to_list.size() == 0)
+      {
+        // This condition means `from_iodesc` tensor is an output of nnpkg
+        continue;
+      }
+
+      bool to_be_release =
+        !std::any_of(to_list.begin(), to_list.end(), [&](const ir::IODesc &to_iodesc) {
+          // This condition means another executor uses the buffer of edge tensor
+          return _edge_quant_tensors.find(to_iodesc) == _edge_quant_tensors.end();
+        });
+
+      if (to_be_release)
+      {
+        // This edge tensor's buffer won't be used in other executors
+        // Tensors for type-aware quantization take over the role of this edge tensor instead
+        _edge_tensors[from_iodesc]->decrease_ref();
+      }
+
+      // Decrease reference count of nnpkg outputs
+      if (_pkg_output_quant_tensors.find(from_iodesc) != _pkg_output_quant_tensors.end())
+      {
+        _pkg_output_quant_tensors[from_iodesc]->decrease_ref();
+      }
+    }
+  }
+}
+
+// modelCount() iterates _executors.
+// It assumes that Compiler will generate Executor for all models and _executors includes all
+// generated Executor.
+// If nnpackage includes model(s) which has no connection and Compiler does not
+// generate Executor for them, modelCount() return less value than real model count.
+uint16_t MultiModelExecutors::modelCount() const
+{
+  uint16_t model_count = 0;
+  for (; _executors.find(std::make_pair(ir::ModelIndex{model_count}, ir::SubgraphIndex{0})) !=
+         _executors.end();
+       model_count++)
+    ;
+
+  return model_count;
+}
+
+} // namespace exec
+} // namespace onert
diff --git a/runtime/onert/core/src/exec/MultiModelExecutors.h b/runtime/onert/core/src/exec/MultiModelExecutors.h
new file mode 100644 (file)
index 0000000..0bd9f11
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+
+#ifndef __ONERT_EXEC_EXECUTORS_H__
+#define __ONERT_EXEC_EXECUTORS_H__
+
+#include "exec/IExecutors.h"
+#include "ir/NNPkg.h"
+#include "IPermuteFunction.h"
+#include "EdgeTensor.h"
+#include "../backend/builtin/UserTensor.h"
+
+namespace std
+{
+
+template <> struct hash<std::pair<::onert::ir::ModelIndex, ::onert::ir::SubgraphIndex>>
+{
+  size_t operator()(
+    const std::pair<::onert::ir::ModelIndex, ::onert::ir::SubgraphIndex> &pair) const noexcept
+  {
+    return (hash<uint32_t>()(pair.first.value()) << 16) ^ hash<uint32_t>()(pair.second.value());
+  }
+};
+
+} // namespace std
+
+namespace onert
+{
+namespace exec
+{
+
+/**
+ * @brief Class to gather executors
+ */
+class MultiModelExecutors : public IExecutors
+{
+public:
+  MultiModelExecutors(void) = delete;
+  MultiModelExecutors(std::unique_ptr<ir::ModelEdges> model_edges)
+    : _executors{}, _model_edges{std::move(model_edges)}, _edge_quant_layers{},
+      _edge_quant_tensors{}, _edge_tensors{}, _is_created_edge_quant_layers{false},
+      _pkg_input_quant_layers{}, _pkg_output_quant_layers{}, _pkg_input_quant_tensors{},
+      _pkg_output_quant_tensors{}, _pkg_input_tensors{}, _pkg_output_tensors{}
+  {
+    for (const auto &edge : _model_edges->edges)
+    {
+      _edge_map[edge.from].emplace_back(edge.to);
+    }
+  }
+  MultiModelExecutors(const MultiModelExecutors &) = delete;
+  MultiModelExecutors(MultiModelExecutors &&) = default;
+  ~MultiModelExecutors() = default;
+
+  // TODO Use Executor index
+  void emplace(const ir::ModelIndex &model_index, const ir::SubgraphIndex &subg_index,
+               std::unique_ptr<IExecutor> exec) override;
+
+  IExecutor *at(const ir::ModelIndex &model_index,
+                const ir::SubgraphIndex &subg_index) const override;
+
+  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 ExecutionContext &ctx) override;
+
+private:
+  void checkSupportedMultimodel() const;
+  void createEdgeQuantLayers();
+  void CreatePkgIOTensors(const IODescription &desc);
+  void createPkgIOQuantLayers(const IODescription &desc);
+  uint16_t modelCount() const;
+
+private:
+  std::unordered_map<std::pair<ir::ModelIndex, ir::SubgraphIndex>, std::unique_ptr<IExecutor>>
+    _executors;
+
+  // NOTE _model_edges may use different struct type for executor implementation
+  std::unique_ptr<ir::ModelEdges> _model_edges;
+  std::unordered_map<ir::IODesc, std::vector<ir::IODesc>> _edge_map;
+
+  /**
+   * @brief Type-aware quantization layers for edges between executors
+   *
+   */
+  // TODO Move variables related to type-aware quantization for edges into compilation stage
+  // TODO Replace PermuteLayer with backend::builtin::kernel::PermuteLayer
+  std::unordered_map<std::pair<ir::ModelIndex, ir::SubgraphIndex>, std::unique_ptr<PermuteLayer>>
+    _edge_quant_layers;
+
+  /**
+   * @brief Tensors for type-aware quantization of edges
+   *        Key: `to` IODesc, Value: EdgeTensor
+   */
+  //
+  // Q: Why is Key `to` IODesc
+  // A: these tensors are currently created depending on the type of `to`
+  // TODO Unify tensors with the same `from` tensor and same type
+  // NOTE The incomplete type 'EdgeTensor' cannot be declared as unique_ptr.
+  std::unordered_map<ir::IODesc, std::shared_ptr<EdgeTensor>> _edge_quant_tensors;
+
+  /**
+   * @brief Tensors for edges between executors that are not related to type-aware quantization
+   *        Key: `from` IODesc, Value: EdgeTensor
+   */
+  // Q: Why is Key `from` IODesc
+  // A: `from` can be connected to multiple `to`
+  // NOTE The incomplete type 'EdgeTensor' cannot be declared as unique_ptr.
+  std::unordered_map<ir::IODesc, std::shared_ptr<EdgeTensor>> _edge_tensors;
+  /**
+   * @brief Whether type-aware quantization layers for edges between executors are created
+   *
+   */
+  // TODO Remove this member after the creation of type-aware quantization layers for edges
+  //      is moved into compilation stage
+  bool _is_created_edge_quant_layers;
+
+  // TODO Replace PermuteLayer with backend::builtin::kernel::PermuteLayer
+  std::unordered_map<std::pair<ir::ModelIndex, ir::SubgraphIndex>, std::unique_ptr<PermuteLayer>>
+    _pkg_input_quant_layers;
+  // TODO Replace PermuteLayer with backend::builtin::kernel::PermuteLayer
+  std::unordered_map<std::pair<ir::ModelIndex, ir::SubgraphIndex>, std::unique_ptr<PermuteLayer>>
+    _pkg_output_quant_layers;
+  // Edge tensors of nnpkg inputs/outputs for type-aware quantization
+  std::unordered_map<ir::IODesc, std::shared_ptr<EdgeTensor>> _pkg_input_quant_tensors;
+  std::unordered_map<ir::IODesc, std::shared_ptr<EdgeTensor>> _pkg_output_quant_tensors;
+  // IOTensors for user buffer
+  std::unordered_map<ir::IODesc, std::unique_ptr<backend::builtin::UserTensor>> _pkg_input_tensors;
+  std::unordered_map<ir::IODesc, std::unique_ptr<backend::builtin::UserTensor>> _pkg_output_tensors;
+};
+
+} // namespace exec
+} // namespace onert
+
+#endif // __ONERT_EXEC_EXECUTORS_H__
index 9da7c82..152fa7c 100644 (file)
@@ -70,7 +70,7 @@ ParallelExecutor::ParallelExecutor(std::unique_ptr<compiler::LoweredGraph> lower
   VERBOSE(ParallelExecutor) << "Constructing Parallel Executor" << std::endl;
 }
 
-void ParallelExecutor::executeImpl()
+void ParallelExecutor::executeImpl(const ExecutionObservee &subject)
 {
   bool dynamic_input_exists = hasDynamicInput();
 
@@ -102,7 +102,7 @@ void ParallelExecutor::executeImpl()
 
   auto profiling_subg_index = _tracing_ctx->getSubgraphIndex(&_graph);
 
-  _subject.notifySubgraphBegin(profiling_subg_index);
+  subject.notifySubgraphBegin(profiling_subg_index);
 
   while (true)
   {
@@ -129,10 +129,10 @@ void ParallelExecutor::executeImpl()
     auto op_ind = _job_to_op[job_index];
     auto backend = _lowered_graph->lower_info().operation.at(op_ind).backend();
     auto setup = [&, op_ind, backend]() {
-      _subject.notifyJobBegin(this, profiling_subg_index, op_ind, backend);
+      subject.notifyJobBegin(this, profiling_subg_index, op_ind, backend);
     };
     auto teardown = [&, job_index, op_ind, backend]() {
-      _subject.notifyJobEnd(this, profiling_subg_index, op_ind, backend);
+      subject.notifyJobEnd(this, profiling_subg_index, op_ind, backend);
       notify(job_index);
     };
 
@@ -151,7 +151,7 @@ void ParallelExecutor::executeImpl()
 
   // Wait for all the jobs done
   _scheduler->finish();
-  _subject.notifySubgraphEnd(profiling_subg_index);
+  subject.notifySubgraphEnd(profiling_subg_index);
 
   // Reset input info for the next execution
   _input_info = _initial_input_info;
index 7d459b0..3162d86 100644 (file)
@@ -50,7 +50,7 @@ public:
                    const compiler::TensorRegistries &tensor_regs, compiler::CodeMap &&code_map,
                    const util::TracingCtx *tracing_ctx);
 
-  void executeImpl() override;
+  void executeImpl(const ExecutionObservee &subject) override;
 
 private:
   std::condition_variable _cv_jobs;
index 4b954ba..44c5e57 100644 (file)
@@ -16,7 +16,9 @@
 
 #include "SingleModelExecutors.h"
 
-#include "../backend/builtin/IOTensor.h"
+#include "EdgeTensor.h"
+#include "IPermuteFunction.h"
+#include "../backend/builtin/UserTensor.h"
 
 namespace onert
 {
@@ -35,27 +37,134 @@ IExecutor *SingleModelExecutors::at(const ir::ModelIndex &,
   return _executors.at(subg_index).get();
 }
 
-uint32_t SingleModelExecutors::inputSize() const
-{
-  return entryExecutor()->getInputTensors().size();
-}
+uint32_t SingleModelExecutors::inputSize() const { return entryExecutor()->inputSize(); }
 
-uint32_t SingleModelExecutors::outputSize() const
-{
-  return entryExecutor()->getOutputTensors().size();
-}
+uint32_t SingleModelExecutors::outputSize() const { return entryExecutor()->outputSize(); }
 
 const ir::OperandInfo &SingleModelExecutors::inputInfo(const ir::IOIndex &index) const
 {
-  return entryExecutor()->getInputTensors().at(index.value())->orig_info();
+  return entryExecutor()->inputInfo(index.value());
 }
 
 const ir::OperandInfo &SingleModelExecutors::outputInfo(const ir::IOIndex &index) const
 {
-  return entryExecutor()->getOutputTensors().at(index.value())->orig_info();
+  return entryExecutor()->outputInfo(index.value());
 }
 
-void SingleModelExecutors::execute(const IODescription &desc) { entryExecutor()->execute(desc); }
+void SingleModelExecutors::execute(const ExecutionContext &ctx)
+{
+  // UserTensor for Input/Output
+  std::vector<std::unique_ptr<backend::builtin::UserTensor>> tensorpool;
+
+  // EdgeTensor for Input Quantization / Output Dequantization
+  std::vector<std::unique_ptr<EdgeTensor>> qtensorpool;
+
+  // Input/Output Tensor vector for executor
+  std::vector<backend::IPortableTensor *> inputs(ctx.desc.inputs.size());
+  std::vector<backend::IPortableTensor *> outputs(ctx.desc.outputs.size());
+
+  // Vector for input quantization I/O
+  std::vector<backend::ITensor *> input_tensors;
+  std::vector<backend::ITensor *> input_qtensors;
+
+  // Vector for output dequantization I/O
+  std::vector<backend::ITensor *> output_qtensors;
+  std::vector<backend::ITensor *> output_tensors;
+
+  // Prepare UserTensor and EdgeTensor for input quantization
+  for (uint32_t i = 0; i < inputs.size(); i++)
+  {
+    auto &desc = ctx.desc.inputs[i];
+
+    // Input is optional if buffer is nullptr, and optional input's size is 0
+    if (desc->buffer == nullptr && (desc->size != 0 || desc->info.total_size() != 0))
+      throw std::runtime_error{"Input " + std::to_string(i) + "'s buffer is not set."};
+
+    tensorpool.emplace_back(std::make_unique<backend::builtin::UserTensor>(
+      desc->info, desc->layout, const_cast<uint8_t *>(static_cast<const uint8_t *>(desc->buffer)),
+      desc->size));
+
+    auto user_type = desc->info.typeInfo().type();
+    auto &model_info = entryExecutor()->inputInfo(i).typeInfo();
+    auto model_type = model_info.type();
+    if (user_type != model_type && user_type == ir::DataType::FLOAT32)
+    {
+      auto quantized_info = desc->info;
+      quantized_info.typeInfo(model_info);
+      qtensorpool.emplace_back(
+        std::make_unique<EdgeTensor>(quantized_info, entryExecutor()->inputLayout(i)));
+      qtensorpool.back()->allocate_buffer();
+
+      input_tensors.push_back(tensorpool.back().get());
+      input_qtensors.push_back(qtensorpool.back().get());
+      inputs[i] = qtensorpool.back().get();
+    }
+    else
+      inputs[i] = tensorpool.back().get();
+  }
+
+  // Prepare UserTensor and EdgeTensor for output dequantization
+  for (uint32_t i = 0; i < outputs.size(); i++)
+  {
+    auto &desc = ctx.desc.outputs[i];
+
+    // Output is optional if buffer is nullptr, and optional output's size is 0
+    if (desc->buffer == nullptr && (desc->size != 0 || desc->info.total_size() != 0))
+      throw std::runtime_error{"Output " + std::to_string(i) + "'s buffer is not set."};
+
+    tensorpool.emplace_back(std::make_unique<backend::builtin::UserTensor>(
+      desc->info, desc->layout, static_cast<uint8_t *>(desc->buffer), desc->size));
+
+    auto user_type = desc->info.typeInfo().type();
+    auto &model_info = entryExecutor()->outputInfo(i).typeInfo();
+    auto model_type = model_info.type();
+    if (user_type != model_type && user_type == ir::DataType::FLOAT32)
+    {
+      auto quantized_info = desc->info;
+      quantized_info.typeInfo(model_info);
+      qtensorpool.emplace_back(
+        std::make_unique<EdgeTensor>(quantized_info, entryExecutor()->outputLayout(i)));
+      qtensorpool.back()->allocate_buffer();
+
+      output_qtensors.push_back(qtensorpool.back().get());
+      output_tensors.push_back(tensorpool.back().get());
+      outputs[i] = qtensorpool.back().get();
+    }
+    else
+      outputs[i] = tensorpool.back().get();
+  }
+
+  // Run quantization
+  if (input_tensors.size() > 0)
+  {
+    auto input_quantize_layer = PermuteLayer(input_tensors, input_qtensors);
+    input_quantize_layer.prepare();
+    input_quantize_layer.run();
+  }
+
+  // Executor
+  entryExecutor()->execute(inputs, outputs, ctx.options);
+
+  // Run dequantization
+  if (output_tensors.size() != 0)
+  {
+    auto output_dequantize_layer = PermuteLayer(output_qtensors, output_tensors);
+    output_dequantize_layer.prepare();
+    output_dequantize_layer.run();
+  }
+
+  // Get dynamic shape inference result
+  for (uint32_t i = 0; i < outputs.size(); i++)
+  {
+    if (ctx.desc.outputs[i]->buffer == nullptr)
+    {
+      // Output is optional if buffer is nullptr
+      continue;
+    }
+
+    ctx.desc.outputs[i]->info.shape(outputs[i]->getShape());
+  }
+}
 
 } // namespace exec
 } // namespace onert
index 98d629e..66dce60 100644 (file)
@@ -58,7 +58,7 @@ public:
 
   const ir::OperandInfo &outputInfo(const ir::IOIndex &index) const override;
 
-  void execute(const IODescription &desc) override;
+  void execute(const ExecutionContext &ctx) override;
 
 private:
   std::unordered_map<ir::SubgraphIndex, std::unique_ptr<IExecutor>> _executors;
index d5e3cb9..e1a963c 100644 (file)
@@ -42,11 +42,10 @@ public:
     : _shape{shape}, _strides{strides}, _ptr{reinterpret_cast<const uint8_t *>(ptr)}, _len{len}
   {
     UNUSED_RELEASE(len); // Workaround for unused variable in release mode
-    assert(len == static_cast<size_t>(strides.N != 0
-                                        ? shape.N * strides.N
-                                        : strides.C != 0 ? shape.C * strides.C
-                                                         : strides.H != 0 ? shape.H * strides.H
-                                                                          : shape.W * strides.W));
+    assert(len == static_cast<size_t>(strides.N != 0   ? shape.N * strides.N
+                                      : strides.C != 0 ? shape.C * strides.C
+                                      : strides.H != 0 ? shape.H * strides.H
+                                                       : shape.W * strides.W));
   }
 
   // Construct for backend tensor
index f439caf..c405190 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "Reader.h"
 
-#include "../MockTensor.h"
+#include "../MockTensor.test.h"
 
 #include <gtest/gtest.h>
 
index c6dcda7..d21a8b7 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "View.h"
 
-#include "../MockTensor.h"
+#include "../MockTensor.test.h"
 
 #include <gtest/gtest.h>
 
index 0bc1ee9..3e3c431 100644 (file)
@@ -43,11 +43,10 @@ public:
     : _shape{shape}, _strides{strides}, _ptr{reinterpret_cast<const uint8_t *>(ptr)}, _len{len}
   {
     UNUSED_RELEASE(len); // Workaround for unused variable in release mode
-    assert(len == static_cast<size_t>(strides.N != 0
-                                        ? shape.N * strides.N
-                                        : strides.H != 0 ? shape.H * strides.H
-                                                         : strides.W != 0 ? shape.W * strides.W
-                                                                          : shape.C * strides.C));
+    assert(len == static_cast<size_t>(strides.N != 0   ? shape.N * strides.N
+                                      : strides.H != 0 ? shape.H * strides.H
+                                      : strides.W != 0 ? shape.W * strides.W
+                                                       : shape.C * strides.C));
   }
 
   // Construct for backend tensor
index 7731990..1f3a4dd 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "Reader.h"
 
-#include "../MockTensor.h"
+#include "../MockTensor.test.h"
 
 #include <gtest/gtest.h>
 
index bdd73d5..c901866 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "View.h"
 
-#include "../MockTensor.h"
+#include "../MockTensor.test.h"
 
 #include <gtest/gtest.h>
 
index 9c7e70c..5d7c4f3 100644 (file)
@@ -32,17 +32,21 @@ 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)},
+  compiler::train::TrainableCodeMap &&code_map,
+  const std::vector<ir::OperationIndex> &forward_order,
+  const std::vector<ir::OperationIndex> &backward_order, const util::TracingCtx *tracing_ctx,
+  const ir::train::LossInfo &loss_info)
+  : _code_map{std::move(code_map)}, _forward_order{std::move(forward_order)},
+    _backward_order{std::move(backward_order)}, _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)
+    _mutex(), _tracing_ctx(tracing_ctx), _loss_info(loss_info)
 {
   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);
+      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);
@@ -50,141 +54,143 @@ TrainableExecutor::TrainableExecutor(
   };
   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)
+void TrainableExecutor::forward(const std::vector<backend::IPortableTensor *> &inputs,
+                                const std::vector<backend::IPortableTensor *> &outputs,
+                                const ExecutionOptions &options, 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);
+  _current_options = options;
 
-  // TODO Update IO tensors if desc has dynamic input
-  // Set input(s)
-  assert(_input_tensors.size() == desc.inputs.size());
+  assert(_input_tensors.size() == 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);
+    const auto input = inputs[i];
+    assert(input->buffer() != nullptr || input->get_info().total_size() == 0);
+    assert(tensor != nullptr);
+    tensor->setTensor(input);
   }
 
-  if (!training)
+  // Set output(s)
+  assert(_output_tensors.size() == outputs.size());
+  for (uint32_t i = 0; i < _output_tensors.size(); ++i)
   {
-    // 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);
-    }
+    auto tensor = _output_tensors[i];
+    const auto output = outputs[i];
+    // Output may not be used on training, so don't check optional
+    assert(tensor != nullptr);
+    tensor->setTensor(output);
   }
 
-  forwardImpl(training);
+  // Create observee
+  ExecutionObservee subject(_observers, options);
+
+  forwardImpl(subject, training);
 
   // TODO Update output(s) desc if desc has dynamic input
 }
 
-void TrainableExecutor::forwardImpl(bool training)
+void TrainableExecutor::forwardImpl(const ExecutionObservee &subject, bool training)
 {
-  if (_tracing_ctx)
+  if (!subject.isEmpty() && _tracing_ctx)
   {
     auto profiling_subg_index = _tracing_ctx->getSubgraphIndex(&_trainable_graph.graph());
 
-    _subject.notifySubgraphBegin(profiling_subg_index);
-    for (auto &&code : _code)
+    subject.notifySubgraphBegin(profiling_subg_index);
+    for (auto &&index : _forward_order)
     {
+      const auto &code = _code_map.at(index);
       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);
+      subject.notifyJobBegin(this, profiling_subg_index, code.op_ind, backend);
 
       auto &tn_seq = code.tn_seq;
-      tn_seq->forward(training);
+      tn_seq->forward(training && code.op->isRequiredForBackward());
 
-      _subject.notifyJobEnd(this, profiling_subg_index, code.op_ind, backend);
+      subject.notifyJobEnd(this, profiling_subg_index, code.op_ind, backend);
     }
-    _subject.notifySubgraphEnd(profiling_subg_index);
+    subject.notifySubgraphEnd(profiling_subg_index);
   }
   else
   {
-    for (auto &&code : _code)
+    for (auto &&index : _forward_order)
     {
+      const auto &code = _code_map.at(index);
 // 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);
+      tn_seq->forward(training && code.op->isRequiredForBackward());
     }
   }
 }
 
-void TrainableExecutor::backward(const IODescription &, uint32_t training_step)
+void TrainableExecutor::backward(const ExecutionOptions &options, 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);
+  _current_options = options;
+
+  // Create observee
+  ExecutionObservee subject(_observers, options);
 
-  backwardImpl(training_step);
+  backwardImpl(subject, training_step);
 }
 
-void TrainableExecutor::backwardImpl(uint32_t training_step)
+void TrainableExecutor::backwardImpl(const ExecutionObservee &subject, uint32_t training_step)
 {
-  if (_tracing_ctx)
+  if (!subject.isEmpty() && _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)
+    subject.notifySubgraphBegin(profiling_subg_index);
+    for (auto &&index : _backward_order)
     {
-      const auto &code = *it;
+      const auto &code = _code_map.at(index);
+      if (!code.op->isRequiredForBackward())
+      {
+        continue;
+      }
       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);
+      subject.notifyJobBegin(this, profiling_subg_index, code.op_ind, backend);
 
       auto &tn_seq = code.tn_seq;
-      tn_seq->backward(training_step);
+      tn_seq->backward(training_step, code.op->isWeightsUpdateEnabled());
 
-      _subject.notifyJobEnd(this, profiling_subg_index, code.op_ind, backend);
+      subject.notifyJobEnd(this, profiling_subg_index, code.op_ind, backend);
     }
-    _subject.notifySubgraphEnd(profiling_subg_index);
+    subject.notifySubgraphEnd(profiling_subg_index);
   }
   else
   {
-    for (auto it = _code.rbegin(); it != _code.rend(); ++it)
+    for (auto &&index : _backward_order)
     {
-      const auto &code = *it;
+      const auto &code = _code_map.at(index);
+      if (!code.op->isRequiredForBackward())
+      {
+        continue;
+      }
 // 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);
+      tn_seq->backward(training_step, code.op->isWeightsUpdateEnabled());
     }
   }
 }
@@ -195,8 +201,23 @@ float TrainableExecutor::getLoss(const ir::IOIndex &pred_io_ind) const
   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;
+  long double sum = 0;
+  for (uint64_t i = 0; i < tensor->getShape().num_elements(); ++i)
+  {
+    sum += reinterpret_cast<float *>(tensor->buffer())[i];
+  }
+  if (_loss_info.reduction_type == ir::train::LossReductionType::SumOverBatchSize)
+  {
+    sum /= tensor->getShape().num_elements();
+  }
+  return static_cast<float>(sum);
+}
+
+void TrainableExecutor::iterateTrainableTensors(
+  const std::function<void(const ir::OperandIndex &, const backend::train::ITrainableTensor *)> &fn)
+  const
+{
+  _tensor_regs.iterateTrainableTensors(fn);
 }
 
 } // namespace train
index 6b64530..986c223 100644 (file)
@@ -25,6 +25,7 @@
 #include "backend/train/TrainableBackendContext.h"
 #include "compiler/train/TrainableCodeMap.h"
 #include "compiler/train/LoweredTrainableGraph.h"
+#include "ir/train/LossInfo.h"
 #include "ir/Index.h"
 #include "util/TracingCtx.h"
 
@@ -48,49 +49,73 @@ public:
                     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);
+                    const std::vector<ir::OperationIndex> &forward_order,
+                    const std::vector<ir::OperationIndex> &backward_order,
+                    const util::TracingCtx *tracing_ctx, const ir::train::LossInfo &training_info);
 
 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;
+               const std::vector<backend::IPortableTensor *> &outputs,
+               const ExecutionOptions &options) override
+  {
+    forward(inputs, outputs, options, false);
+  }
 
-  void forward(const IODescription &desc, bool training);
-  void backward(const IODescription &desc, uint32_t training_step);
+  uint32_t inputSize() const override { return _input_tensors.size(); }
 
-  // Used only in Dataflow and Parallel Executors
-  void setIndexedRanks(std::shared_ptr<ir::OperationIndexMap<int64_t>> ranks) final
-  {
-    _indexed_ranks = std::move(ranks);
-  };
+  uint32_t outputSize() const override { return _output_tensors.size(); }
 
-  void addObserver(std::unique_ptr<IExecutionObserver> ref) { _subject.add(std::move(ref)); };
+  const ir::OperandInfo &inputInfo(uint32_t index) const override
+  {
+    return _input_tensors[index]->get_info();
+  }
 
-  const std::vector<backend::builtin::IOTensor *> &getInputTensors() const override
+  const ir::OperandInfo &outputInfo(uint32_t index) const override
   {
-    return _input_tensors;
+    return _output_tensors[index]->get_info();
   }
 
-  const std::vector<backend::builtin::IOTensor *> &getOutputTensors() const override
+  ir::Layout inputLayout(uint32_t index) const override { return _input_tensors[index]->layout(); }
+
+  ir::Layout outputLayout(uint32_t index) const override
   {
-    return _output_tensors;
+    return _output_tensors[index]->layout();
   }
 
+  void forward(const std::vector<backend::IPortableTensor *> &inputs,
+               const std::vector<backend::IPortableTensor *> &outputs,
+               const ExecutionOptions &options, bool training);
+  void backward(const ExecutionOptions &options, 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) { _observers.add(std::move(ref)); };
+
   float getLoss(const ir::IOIndex &pred_io_ind) const;
 
+  void iterateTrainableTensors(
+    const std::function<void(const ir::OperandIndex &, const backend::train::ITrainableTensor *)>
+      &fn) const;
+
   backend::train::TrainableBackendContexts &getBackendContexts() { return _backend_contexts; }
 
+  const ExecutionOptions &currentOptions() const override { return _current_options; }
+
 private:
-  void forwardImpl(bool training);
-  void backwardImpl(uint32_t training_step);
+  void forwardImpl(const ExecutionObservee &subject, bool training);
+  void backwardImpl(const ExecutionObservee &subject, uint32_t training_step);
 
 private:
-  std::vector<compiler::train::TrainableCodeAndInfo> _code;
-  ExecutionObservee _subject;
+  compiler::train::TrainableCodeMap _code_map;
+  std::vector<ir::OperationIndex> _forward_order;
+  std::vector<ir::OperationIndex> _backward_order;
+  ExecObservers _observers;
   std::shared_ptr<ir::OperationIndexMap<int64_t>> _indexed_ranks;
   std::unique_ptr<compiler::train::LoweredTrainableGraph> _lowered_graph;
   backend::train::TrainableBackendContexts _backend_contexts;
@@ -100,6 +125,15 @@ private:
   std::vector<backend::builtin::IOTensor *> _output_tensors;
   std::mutex _mutex;
   const util::TracingCtx *_tracing_ctx;
+  const ir::train::LossInfo _loss_info;
+  /**
+   * It is set by execute() method only in thread-safe environment.
+   * It is used for non-primary executor call on builtin backend
+   * and accessed by entryExecutor's currentOptions() method.
+   *
+   * TODO: Find better way to pass config to non-primary executor
+   */
+  ExecutionOptions _current_options;
 };
 
 } // namespace train
index ba39bf0..73217c8 100644 (file)
@@ -41,42 +41,88 @@ TrainableExecutor *TrainableExecutors::at(const ir::ModelIndex &,
   return _executors.at(subg_index).get();
 }
 
-uint32_t TrainableExecutors::inputSize() const { return entryExecutor()->getInputTensors().size(); }
+uint32_t TrainableExecutors::inputSize() const { return entryExecutor()->inputSize(); }
 
-uint32_t TrainableExecutors::outputSize() const
-{
-  return entryExecutor()->getOutputTensors().size();
-}
+uint32_t TrainableExecutors::outputSize() const { return entryExecutor()->outputSize(); }
 
 const ir::OperandInfo &TrainableExecutors::inputInfo(const ir::IOIndex &index) const
 {
-  return entryExecutor()->getInputTensors().at(index.value())->orig_info();
+  return entryExecutor()->inputInfo(index.value());
 }
 
 const ir::OperandInfo &TrainableExecutors::outputInfo(const ir::IOIndex &index) const
 {
-  return entryExecutor()->getOutputTensors().at(index.value())->orig_info();
+  return entryExecutor()->outputInfo(index.value());
 }
 
-void TrainableExecutors::execute(const IODescription &desc)
+void TrainableExecutors::execute(const ExecutionContext &ctx)
 {
   if (_executors.size() > 1)
     throw std::runtime_error("TrainableExecutors does not support multiple executors yet");
-  entryExecutor()->forward(desc, false);
+
+  // UserTensor for Input/Output
+  std::vector<std::unique_ptr<backend::builtin::UserTensor>> tensorpool;
+
+  // Allocate UserTensor and call executor forward
+  forward(ctx, tensorpool, false);
 
   // TODO Support multple executors
 }
 
-void TrainableExecutors::train(const IODescription &desc, uint32_t training_step)
+void TrainableExecutors::train(const ExecutionContext &ctx, 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);
+
+  // UserTensor for Input/Output
+  std::vector<std::unique_ptr<backend::builtin::UserTensor>> tensorpool;
+
+  // Allocate UserTensor and call executor forward and backward
+  forward(ctx, tensorpool, true);
+  entryExecutor()->backward(ctx.options, training_step);
 
   // TODO Support multple executors
 }
 
+void TrainableExecutors::forward(
+  const ExecutionContext &ctx,
+  std::vector<std::unique_ptr<backend::builtin::UserTensor>> &tensorpool, bool training)
+{
+  // Input/Output Tensor vector for executor
+  std::vector<backend::IPortableTensor *> inputs(ctx.desc.inputs.size());
+  std::vector<backend::IPortableTensor *> outputs(ctx.desc.outputs.size());
+
+  // Prepare UserTensor for input
+  for (uint32_t i = 0; i < inputs.size(); i++)
+  {
+    auto &desc = ctx.desc.inputs[i];
+
+    // Input is optional if buffer is nullptr, and optional input's size is 0
+    if (desc->buffer == nullptr && (desc->size != 0 || desc->info.total_size() != 0))
+      throw std::runtime_error{"Input " + std::to_string(i) + "'s buffer is not set."};
+
+    tensorpool.emplace_back(std::make_unique<backend::builtin::UserTensor>(
+      desc->info, desc->layout, const_cast<uint8_t *>(static_cast<const uint8_t *>(desc->buffer)),
+      desc->size));
+    inputs[i] = tensorpool.back().get();
+  }
+
+  // Prepare UserTensor for output
+  for (uint32_t i = 0; i < outputs.size(); i++)
+  {
+    auto &desc = ctx.desc.outputs[i];
+
+    // If training, output buffer may not be used
+    // So don't check optional
+    tensorpool.emplace_back(std::make_unique<backend::builtin::UserTensor>(
+      desc->info, desc->layout, static_cast<uint8_t *>(desc->buffer), desc->size));
+    outputs[i] = tensorpool.back().get();
+  }
+
+  // Call forward
+  entryExecutor()->forward(inputs, outputs, ctx.options, training);
+}
+
 float TrainableExecutors::getLoss(const ir::IOIndex &index) const
 {
   if (_executors.size() > 1)
@@ -84,6 +130,13 @@ float TrainableExecutors::getLoss(const ir::IOIndex &index) const
   return entryExecutor()->getLoss(index);
 }
 
+void TrainableExecutors::iterateTrainableTensors(
+  const std::function<void(const ir::OperandIndex &, const backend::train::ITrainableTensor *)> &fn)
+  const
+{
+  return entryExecutor()->iterateTrainableTensors(fn);
+}
+
 } // namespace train
 } // namespace exec
 } // namespace onert
index db6d198..ae120f6 100644 (file)
@@ -67,19 +67,31 @@ public:
 
   const ir::OperandInfo &outputInfo(const ir::IOIndex &index) const override;
 
-  void execute(const IODescription &desc) override;
+  void execute(const ExecutionContext &ctx) override;
 
   /**
    * @brief Train
    *
-   * @param desc          IO information
+   * @param ctx           Execution context
    * @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);
+  void train(const ExecutionContext &ctx, uint32_t training_step);
 
   float getLoss(const ir::IOIndex &index) const;
 
+  void iterateTrainableTensors(
+    const std::function<void(const ir::OperandIndex &, const backend::train::ITrainableTensor *)>
+      &fn) const;
+
+private:
+  // If you want to use I/O buffer on step, tensorpool should be alive until one step is finished
+  // So this method get tensorpool from outside.
+  // tensorpool is not defined as a member variable to avoid memory access conflict between threads.
+  void forward(const ExecutionContext &ctx,
+               std::vector<std::unique_ptr<backend::builtin::UserTensor>> &tensorpool,
+               bool training);
+
 private:
   // TODO Append model index to ModelIndex
   std::unordered_map<ir::SubgraphIndex, std::unique_ptr<TrainableExecutor>> _executors;
index 084b3d7..36e4c31 100644 (file)
@@ -31,16 +31,18 @@ void TrainableFnSequence::forward(bool training)
   }
 }
 
-void TrainableFnSequence::backward(uint32_t training_step)
+void TrainableFnSequence::backward(uint32_t training_step, bool weight_update_enabled)
 {
   for (auto it = _functions.rbegin(); it != _functions.rend(); ++it)
   {
     (*it)->backward();
   }
-
-  for (const auto &applier : _appliers)
+  if (weight_update_enabled)
   {
-    applier->applyGradient(training_step);
+    for (const auto &applier : _appliers)
+    {
+      applier->applyGradient(training_step);
+    }
   }
 }
 
diff --git a/runtime/onert/core/src/exec/train/optimizer/OptimizerCode.cc b/runtime/onert/core/src/exec/train/optimizer/OptimizerCode.cc
deleted file mode 100644 (file)
index 72b581b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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
deleted file mode 100644 (file)
index 66a08b5..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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
deleted file mode 100644 (file)
index abfbc1b..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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/exporter/CircleExporter.cc b/runtime/onert/core/src/exporter/CircleExporter.cc
new file mode 100644 (file)
index 0000000..b9ac8d5
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "exporter/CircleExporter.h"
+
+#include "exec/Execution.h"
+#include "ir/train/TrainingInfo.h"
+#include "circle_schema_generated.h"
+#include "TrainInfoBuilder.h"
+
+#include <fstream>
+#include <iostream>
+
+namespace onert
+{
+namespace exporter
+{
+
+CircleExporter::CircleExporter(const std::string &source, const std::string &path)
+  : _path{path}, _data{}, _model{nullptr}
+{
+  // make sure the architecture is little endian before direct access to flatbuffers
+  assert(FLATBUFFERS_LITTLEENDIAN);
+
+  std::ifstream src(source.c_str(), std::ios::binary);
+  if (src.is_open())
+  {
+    src.seekg(0, std::ios::end);
+    _data.resize(src.tellg());
+    src.seekg(0, std::ios::beg);
+    src.read(&_data[0], static_cast<std::streamsize>(_data.size()));
+    src.close();
+  }
+
+  if (_data.size() == 0)
+    throw std::runtime_error("Invalid source file");
+
+  const auto model = ::circle::GetModel(_data.data());
+  if (!model)
+    throw std::runtime_error("Failed to load original circle file");
+  _model.reset(model->UnPack());
+}
+
+CircleExporter::~CircleExporter() { finish(); }
+
+void CircleExporter::updateWeight(const std::unique_ptr<exec::Execution> &exec)
+{
+  exec->iterateTrainableTensors(
+    [&](const ir::OperandIndex &idx, const backend::train::ITrainableTensor *tensor) {
+      std::lock_guard<std::mutex> guard(_mutex);
+      const auto &subgs = _model->subgraphs;
+      if (subgs.size() != 1)
+        throw std::runtime_error("Circle does not has valid subgraph or has multiple subgraphs");
+
+      if (!idx.valid())
+        throw std::runtime_error("Trainable tensor is invalid");
+
+      uint32_t buf_idx = -1;
+      const auto &subg = subgs.at(0); // Get 1st subgraph
+      if (idx.value() >= subg->tensors.size())
+      {
+        auto buffer = std::make_unique<::circle::BufferT>();
+        buffer->size = tensor->total_size();
+        buffer->data.resize(buffer->size);
+
+        buf_idx = _model->buffers.size();
+        _model->buffers.push_back(std::move(buffer));
+      }
+      else
+      {
+        buf_idx = subg->tensors.at(idx.value())->buffer;
+        if (buf_idx >= _model->buffers.size())
+          throw std::runtime_error("Buffer for trainable tensors is invalid");
+      }
+
+      const auto &buffer = _model->buffers.at(buf_idx);
+
+      auto org_buf_sz = buffer->data.size();
+      if (org_buf_sz != tensor->total_size())
+        throw std::runtime_error("Trained tensor buffer size does not match original tensor's one");
+
+      memcpy(buffer->data.data(), tensor->buffer(), org_buf_sz);
+    });
+}
+
+void CircleExporter::updateMetadata(const std::unique_ptr<ir::train::TrainingInfo> &training_info)
+{
+  const char *const TRAININFO_METADATA_NAME = "CIRCLE_TRAINING";
+
+  TrainInfoBuilder tbuilder(training_info);
+  bool found = false;
+  for (const auto &meta : _model->metadata)
+  {
+    if (meta->name == std::string{TRAININFO_METADATA_NAME})
+    {
+      std::lock_guard<std::mutex> guard(_mutex);
+      const uint32_t buf_idx = meta->buffer;
+      auto &buffer = _model->buffers.at(buf_idx);
+
+      if (tbuilder.size() != buffer->data.size())
+      {
+        buffer->data.resize(tbuilder.size());
+        buffer->size = tbuilder.size();
+      }
+
+      memcpy(buffer->data.data(), tbuilder.get(), tbuilder.size());
+      found = true;
+      break;
+    }
+  }
+
+  if (!found)
+  {
+    std::lock_guard<std::mutex> guard(_mutex);
+    auto buffer = std::make_unique<::circle::BufferT>();
+    buffer->size = tbuilder.size();
+    buffer->data.resize(buffer->size);
+    memcpy(buffer->data.data(), tbuilder.get(), buffer->size);
+
+    auto meta = std::make_unique<::circle::MetadataT>();
+    meta->name = std::string{TRAININFO_METADATA_NAME};
+    meta->buffer = _model->buffers.size();
+
+    _model->buffers.push_back(std::move(buffer));
+    _model->metadata.push_back(std::move(meta));
+  }
+}
+
+void CircleExporter::finish()
+{
+  flatbuffers::FlatBufferBuilder builder(1024);
+  builder.Finish(::circle::Model::Pack(builder, _model.get()), ::circle::ModelIdentifier());
+
+  std::ofstream dst(_path.c_str(), std::ios::binary);
+  dst.write(reinterpret_cast<const char *>(builder.GetBufferPointer()),
+            static_cast<std::streamsize>(builder.GetSize()));
+  dst.close();
+}
+} // namespace exporter
+} // namespace onert
diff --git a/runtime/onert/core/src/exporter/TrainInfoBuilder.h b/runtime/onert/core/src/exporter/TrainInfoBuilder.h
new file mode 100644 (file)
index 0000000..c3084b4
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EXPORTER_TRAININFO_BUILDER_H__
+#define __ONERT_EXPORTER_TRAININFO_BUILDER_H__
+
+#include "ir/train/TrainingInfo.h"
+#include "circle_schema_generated.h"
+#include "circle_traininfo_generated.h"
+
+namespace onert
+{
+namespace exporter
+{
+
+class TrainInfoBuilder
+{
+public:
+  TrainInfoBuilder(const std::unique_ptr<ir::train::TrainingInfo> &training_info) : _builder(1024)
+  {
+    const auto &optimizerInfo = training_info->optimizerInfo();
+    const auto &lossInfo = training_info->lossInfo();
+
+    ::circle::Optimizer optimizer;
+    ::circle::OptimizerOptions optimizer_opt_type;
+    ::flatbuffers::Offset<void> optimizer_opt;
+    switch (optimizerInfo.optim_code)
+    {
+      case ir::train::OptimizerCode::SGD:
+        optimizer = ::circle::Optimizer_SGD;
+        optimizer_opt_type = ::circle::OptimizerOptions_SGDOptions;
+        optimizer_opt = ::circle::CreateSGDOptions(_builder, optimizerInfo.learning_rate).Union();
+        break;
+      case ir::train::OptimizerCode::Adam:
+        optimizer = ::circle::Optimizer_ADAM;
+        optimizer_opt_type = ::circle::OptimizerOptions_AdamOptions;
+        optimizer_opt = ::circle::CreateAdamOptions(_builder, optimizerInfo.learning_rate).Union();
+        break;
+      default:
+        throw std::runtime_error("Not supported optimizer code");
+    }
+
+    ::circle::LossFn lossfn;
+    ::circle::LossFnOptions lossfn_opt_type;
+    ::flatbuffers::Offset<void> lossfn_opt;
+    switch (lossInfo.loss_code)
+    {
+      case ir::train::LossCode::MeanSquaredError:
+        lossfn = ::circle::LossFn_MEAN_SQUARED_ERROR;
+        lossfn_opt_type = ::circle::LossFnOptions_MeanSquaredErrorOptions;
+        lossfn_opt = ::circle::CreateMeanSquaredErrorOptions(_builder).Union();
+        break;
+      case ir::train::LossCode::CategoricalCrossentropy:
+        lossfn = ::circle::LossFn_CATEGORICAL_CROSSENTROPY;
+        lossfn_opt_type = ::circle::LossFnOptions_CategoricalCrossentropyOptions;
+        lossfn_opt = ::circle::CreateCategoricalCrossentropyOptions(_builder).Union();
+        break;
+      default:
+        throw std::runtime_error("Not supported loss code");
+    }
+
+    ::circle::LossReductionType loss_reduction_type;
+    switch (lossInfo.reduction_type)
+    {
+      case ir::train::LossReductionType::SumOverBatchSize:
+        loss_reduction_type = ::circle::LossReductionType_SumOverBatchSize;
+        break;
+      case ir::train::LossReductionType::Sum:
+        loss_reduction_type = ::circle::LossReductionType_Sum;
+        break;
+      default:
+        throw std::runtime_error("Not supported loss reduction type");
+    }
+
+    std::vector<int32_t> trainable_ops;
+    for (const auto &op : training_info->getTrainableOps())
+    {
+      trainable_ops.push_back(op.value());
+    }
+
+    const auto end = ::circle::CreateModelTrainingDirect(
+      _builder, training_info->version(), optimizer, optimizer_opt_type, optimizer_opt, lossfn,
+      lossfn_opt_type, lossfn_opt, 0, training_info->batchSize(), loss_reduction_type,
+      &trainable_ops);
+    _builder.Finish(end, ::circle::ModelTrainingIdentifier());
+
+    ::flatbuffers::Verifier v(_builder.GetBufferPointer(), _builder.GetSize());
+    bool verified = ::circle::VerifyModelTrainingBuffer(v);
+    if (not verified)
+      throw std::runtime_error{"TrainingInfo buffer is not accessible"};
+  }
+
+  uint8_t *get() const { return _builder.GetBufferPointer(); }
+  uint32_t size() const { return _builder.GetSize(); }
+
+private:
+  ::flatbuffers::FlatBufferBuilder _builder;
+};
+
+} // namespace exporter
+} // namespace onert
+
+#endif // __ONERT_EXPORTER_TRAININFO_BUILDER_H__
index ef0f988..306572c 100644 (file)
@@ -168,7 +168,7 @@ void Graph::verify(void) const
 void Graph::initializeUseDef()
 {
   operations().iterate([&](const OperationIndex &index, const IOperation &node) -> void {
-    auto outputs = node.getOutputs();
+    const auto &outputs = node.getOutputs();
     for (auto &&output : outputs | ir::Remove::UNDEFINED)
     {
       operands().at(output).setDef(index);
index 5e6d700..5aa4693 100644 (file)
@@ -166,10 +166,11 @@ void OperationDumper::visit(const Fill &node)
 
 void OperationDumper::visit(const FullyConnected &node)
 {
-  std::string inputs =
-    "Weight(" + std::to_string(node.getInputs().at(FullyConnected::Input::WEIGHT).value()) +
-    ") Bias(" + std::to_string(node.getInputs().at(FullyConnected::Input::BIAS).value()) + ")";
-  dumpUnaryInputOp(node, inputs);
+  VERBOSE(LIR) << "* " << node.name() << std::endl;
+  VERBOSE(LIR) << "  - Inputs : Input(" << node.getInputs().at(ArgMinMax::INPUT) << ") Weight("
+               << node.getInputs().at(FullyConnected::Input::WEIGHT) << ") Bias("
+               << node.getInputs().at(FullyConnected::Input::BIAS) << ")" << std::endl;
+  VERBOSE(LIR) << "  - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
 }
 
 void OperationDumper::visit(const Gather &node)
index cf7323d..5598c40 100644 (file)
@@ -123,7 +123,8 @@ void OperationValidator::visit(const operation::BatchMatMul &node)
   OP_REQUIRES(!isConstant(lhs_index) && !isConstant(rhs_index));
 
   // Allow hybrid quantization (lhs: float / rhs: qint8 / out: float)
-  OP_REQUIRES(isValidType(lhs_index, {DataType::FLOAT32, DataType::QUANT_INT8_ASYMM}));
+  OP_REQUIRES(isValidType(
+    lhs_index, {DataType::FLOAT32, DataType::QUANT_UINT8_ASYMM, DataType::QUANT_INT8_ASYMM}));
   OP_REQUIRES(isSameType(lhs_index, rhs_index) ||
               ((operandType(lhs_index) == DataType::FLOAT32) &&
                (operandType(rhs_index) == DataType::QUANT_INT8_ASYMM)));
@@ -213,7 +214,7 @@ void OperationValidator::visit(const operation::DepthToSpace &node)
 
 void OperationValidator::visit(const operation::DetectionPostProcess &node)
 {
-  auto param = node.param();
+  const auto &param = node.param();
 
   // FIXME: number of classes should be 1 for now.
   OP_REQUIRES(param.num_classes == 1);
index b22bed7..d445171 100644 (file)
@@ -39,6 +39,7 @@ std::string ElementwiseBinary::name() const
   using ElementwiseBinaryType = onert::ir::operation::ElementwiseBinary::ElementwiseBinaryType;
   static const std::unordered_map<ElementwiseBinaryType, std::string> name_map{
     {ElementwiseBinaryType::FLOOR_DIV, std::string{"FloorDiv"}},
+    {ElementwiseBinaryType::FLOOR_MOD, std::string{"FloorMod"}},
     {ElementwiseBinaryType::LOGICAL_AND, std::string{"LogicalAnd"}},
     {ElementwiseBinaryType::LOGICAL_OR, std::string{"LogicalOr"}},
     {ElementwiseBinaryType::MAX, std::string{"Max"}},
index fa3520b..2a0d6c4 100644 (file)
@@ -28,23 +28,10 @@ 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}
+Loss::Loss(const OperandIndexSequence &inputs, const OperandIndexSequence &outputs)
+  : Operation{OperandConstraint::createAtLeast(2u), inputs, outputs}
 {
-  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);
+  assert(inputs.size() == 2);
 }
 
 } // namespace operation
diff --git a/runtime/onert/core/src/ir/train/LossCode.cc b/runtime/onert/core/src/ir/train/LossCode.cc
new file mode 100644 (file)
index 0000000..eccae8c
--- /dev/null
@@ -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.
+ */
+
+#include "ir/train/LossCode.h"
+
+#include <unordered_map>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+std::string toString(LossCode code)
+{
+  static const std::unordered_map<LossCode, const char *> map{
+    {LossCode::Undefined, "Undefined"},
+    {LossCode::MeanSquaredError, "MeanSquaredError"},
+    {LossCode::CategoricalCrossentropy, "CategoricalCrossentropy"}};
+  return map.at(code);
+}
+
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/OptimizerCode.cc b/runtime/onert/core/src/ir/train/OptimizerCode.cc
new file mode 100644 (file)
index 0000000..4ab6890
--- /dev/null
@@ -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.
+ */
+
+#include "ir/train/OptimizerCode.h"
+
+#include <unordered_map>
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+std::string toString(OptimizerCode code)
+{
+  static const std::unordered_map<OptimizerCode, const char *> map{
+    {OptimizerCode::Undefined, "Undefined"},
+    {OptimizerCode::SGD, "SGD"},
+    {OptimizerCode::Adam, "Adam"}};
+  return map.at(code);
+}
+
+} // namespace train
+} // namespace ir
+} // namespace onert
index 781f049..5ecdcc2 100644 (file)
  */
 
 #include "ir/train/TrainableGraph.h"
+
+#include "ir/OperandIndexMap.h"
 #include "util/Utils.h"
+#include "util/Set.h"
+#include "../verifier/Verifier.h"
 
 #include <algorithm>
+#include <set>
+#include <map>
 #include <misc/polymorphic_downcast.h>
 
 namespace onert
@@ -30,7 +36,8 @@ namespace train
 TrainableGraph::TrainableGraph() : _graph{} {}
 
 TrainableGraph::TrainableGraph(const TrainableGraph &tgraph)
-  : _graph{tgraph._graph}, _derivatives{tgraph._derivatives}, _losses{tgraph._losses}
+  : _graph{tgraph._graph}, _backward_operands{tgraph._backward_operands},
+    _training_defuses{tgraph._training_defuses}, _losses{tgraph._losses}
 {
   tgraph.operations().iterate(
     [&](const onert::ir::OperationIndex &index, const onert::ir::IOperation &op) {
@@ -61,10 +68,10 @@ OperationIndex TrainableGraph::replaceOperation(OperationIndex index,
   return _graph.replaceOperation(index, std::move(operation));
 }
 
-OperandIndex TrainableGraph::addDerivative(OperandIndex index,
-                                           std::unique_ptr<Operand> &&derivative)
+OperandIndex TrainableGraph::addBackwardOperand(OperandIndex index,
+                                                std::unique_ptr<Operand> &&bwd_operand)
 {
-  return _derivatives.push(std::move(derivative), index);
+  return _backward_operands.push(std::move(bwd_operand), index);
 }
 
 IOIndex TrainableGraph::getInputIndex(const std::string &name) const
@@ -82,10 +89,10 @@ void TrainableGraph::changeShape(const OperandIndex &index, const ir::Shape &new
   _graph.changeShape(index, new_shape);
 }
 
-void TrainableGraph::changeDerivativeShape(const OperandIndex &index, const ir::Shape &new_shape)
+void TrainableGraph::changeBackwardShape(const OperandIndex &index, const ir::Shape &new_shape)
 {
-  assert(_derivatives.exist(index));
-  _derivatives.at(index).info().shape(new_shape);
+  assert(_backward_operands.exist(index));
+  _backward_operands.at(index).info().shape(new_shape);
 }
 
 void TrainableGraph::addInput(const OperandIndex &ind, const std::string &name)
@@ -109,9 +116,11 @@ void TrainableGraph::verify(void) const
     }
     catch (const std::bad_cast &)
     {
-      std::runtime_error("TrainableGraph: " + op.name() + " is not a trainable operation");
+      throw std::runtime_error("TrainableGraph: " + op.name() + " is not a trainable operation");
     }
   });
+
+  verifyTrainingUseDefs();
 }
 
 void TrainableGraph::removeOperand(const OperandIndex &ind) { _graph.removeOperand(ind); }
@@ -124,9 +133,192 @@ const ITrainableOperation &TrainableGraph::operation(OperationIndex index) const
   return dynamic_cast<const ITrainableOperation &>(_graph.operations().at(index));
 }
 
+void TrainableGraph::enableBackward(const OperationIndex &index)
+{
+  auto op = dynamic_cast<ir::train::ITrainableOperation *>(&_graph.operations().at(index));
+  assert(op);
+  op->enableBackward();
+}
+
+void TrainableGraph::disableBackward(const OperationIndex &index)
+{
+  auto &op = dynamic_cast<ir::train::ITrainableOperation &>(_graph.operations().at(index));
+  op.disableBackward();
+}
+
+void TrainableGraph::setTrainingUseDefs(const UseDefChains &training_defuses)
+{
+  _training_defuses.clear();
+  // TODO Replace this loop with `std::unordered_map::insert_range` since C++23
+  for (const auto &defuse_chain : training_defuses)
+  {
+    _training_defuses.emplace(defuse_chain.first, defuse_chain.second);
+  }
+}
+
+void TrainableGraph::validateTopologicalOrder(std::vector<ir::OperationIndex> order,
+                                              bool is_forward) const
+{
+  if (!is_forward)
+    std::reverse(order.begin(), order.end());
+
+  const std::string order_type = is_forward ? "forward" : "backward";
+
+  std::map<ir::OperationIndex, uint32_t> position;
+  for (uint32_t p = 0; p < order.size(); ++p)
+  {
+    auto index = order[p];
+    // TODO: replace this with `std::map::contains` after C++20
+    if (position.find(index) != position.end())
+      throw std::runtime_error{"Invalid " + order_type + " topological order: duplicate node @" +
+                               std::to_string(index.value())};
+
+    position[index] = p;
+  }
+
+  operations().iterate([&](const ir::OperationIndex &index, const ir::IOperation &op) {
+    if (position.count(index) == 0)
+      return;
+
+    uint32_t p = position[index];
+
+    for (const auto &output : op.getOutputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
+    {
+      const auto &operand = operands().at(output);
+      for (const auto &use : operand.getUses())
+      {
+        if (position.count(use) == 0)
+          continue;
+
+        uint32_t q = position[use];
+        if (p > q)
+          throw std::runtime_error{
+            "Invalid " + order_type + " topological order: inversion between @" +
+            std::to_string(index.value()) + " and @" + std::to_string(use.value())};
+      }
+    }
+  });
+}
+
+void TrainableGraph::validateForwardTopologicalOrder(
+  const std::vector<ir::OperationIndex> &order) const
+{
+  validateTopologicalOrder(order, true);
+}
+
+void TrainableGraph::validateBackwardTopologicalOrder(
+  const std::vector<ir::OperationIndex> &order) const
+{
+  validateTopologicalOrder(order, false);
+}
+
+void TrainableGraph::verifyTrainingUseDefs() const
+{
+  if (!verifier::DAGChecker().verify(_training_defuses))
+    throw std::runtime_error{"The training def-uses is cyclic."};
+  assert(verifier::EdgeChecker().verify(_training_defuses));
+}
+
 std::vector<ir::OperationIndex> TrainableGraph::topolSortOperations() const
 {
-  return _graph.topolSortOperations();
+  auto ret = _graph.topolSortOperations();
+  validateForwardTopologicalOrder(ret);
+
+  return ret;
+}
+
+std::vector<ir::OperationIndex> TrainableGraph::btopolSortOperations() const
+{
+  std::vector<ir::OperationIndex> ret;
+  util::Set<ir::OperationIndex> unvisited;
+  ir::OperationIndex loss_idx;
+  operations().iterate([&](const ir::OperationIndex &index, const ir::IOperation &op) {
+    unvisited.add(index);
+    if (op.opcode() == ir::OpCode::Loss)
+    {
+      assert(!loss_idx.valid()); // Should be only one loss
+      loss_idx = index;
+    }
+  });
+
+  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 &input : op.getInputs() | ir::Remove::DUPLICATED | ir::Remove::UNDEFINED)
+    {
+      const auto &operand = operands().at(input);
+      const auto &def = operand.getDef();
+      if (!def.valid())
+        continue;
+      dfs(def, operations().at(def));
+    }
+
+    ret.push_back(index);
+  };
+
+  dfs(loss_idx, operations().at(loss_idx));
+  std::reverse(ret.begin(), ret.end());
+  validateBackwardTopologicalOrder(ret);
+
+  return ret;
+}
+
+std::vector<ir::OperationIndex> TrainableGraph::essentialBackwardOrder() const
+{
+  auto backward_order = btopolSortOperations();
+  // get rid of all nodes not reachable from a node with trainable parameters
+  backward_order = truncateBackwardOrder(backward_order, [&](const OperationIndex &index) {
+    return operation(index).isRequiredForBackward();
+  });
+
+  return truncateBackwardOrder(backward_order);
+}
+
+std::vector<ir::OperationIndex> TrainableGraph::truncateBackwardOrder(
+  std::vector<ir::OperationIndex> backward_order,
+  std::function<bool(const ir::OperationIndex &)> alive_cond) const
+{
+  auto forward_order = backward_order;
+  std::reverse(forward_order.begin(), forward_order.end());
+  std::set<ir::OperationIndex> alive;
+
+  for (const auto &index : forward_order)
+  {
+    if (alive_cond(index))
+      alive.insert(index);
+
+    // TODO: replace this with `std::set::contains` after C++20
+    if (alive.find(index) != alive.end())
+    {
+      const auto &op = operations().at(index);
+      for (const auto &output : op.getOutputs())
+      {
+        const auto &operand = operands().at(output);
+        for (const auto &use : operand.getUses())
+          alive.insert(use);
+      }
+    }
+  }
+
+  // TODO: replace this with `std::erase_if(std::vector)` after C++20
+  backward_order.erase(
+    std::remove_if(backward_order.begin(), backward_order.end(),
+                   [&](const auto &index) { return alive.find(index) == alive.end(); }),
+    backward_order.end());
+  return backward_order;
+}
+
+std::vector<ir::OperationIndex>
+TrainableGraph::truncateBackwardOrder(const std::vector<ir::OperationIndex> &backward_order) const
+{
+  return truncateBackwardOrder(backward_order, [&](const ir::OperationIndex &index) {
+    const auto &trainable_op = operation(index);
+
+    return trainable_op.hasTrainableParameter();
+  });
 }
 
 void TrainableGraph::addLoss(const OperandIndex &loss_ind, const IOIndex &pred_ioind)
diff --git a/runtime/onert/core/src/ir/train/TrainableGraph.test.cc b/runtime/onert/core/src/ir/train/TrainableGraph.test.cc
new file mode 100644 (file)
index 0000000..84df228
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "ir/train/operation/BinaryArithmetic.h"
+#include "ir/train/operation/ElementwiseActivation.h"
+#include "ir/train/operation/FullyConnected.h"
+#include "ir/train/operation/Loss.h"
+#include "ir/train/LossInfo.h"
+
+#include <gtest/gtest.h>
+
+using namespace onert::ir;
+
+OperationIndex addAddOperation(train::TrainableGraph &tgraph, const OperandIndexSequence inputs,
+                               const OperandIndexSequence outputs)
+{
+  // Add "ADD" operation
+  operation::BinaryArithmetic::Param param;
+  param.arithmetic_type = operation::BinaryArithmetic::ArithmeticType::ADD;
+  param.activation = Activation::NONE;
+  auto add_op = operation::BinaryArithmetic(inputs, outputs, param);
+  return tgraph.addOperation(std::make_unique<train::operation::BinaryArithmetic>(add_op));
+}
+
+OperationIndex addElementwiseActivationOperation(train::TrainableGraph &tgraph,
+                                                 const OperandIndexSequence inputs,
+                                                 const OperandIndexSequence outputs)
+{
+  // Add "ElementwiseActivation" operation
+  operation::ElementwiseActivation::Param param;
+  auto ea_op = operation::ElementwiseActivation(inputs, outputs, param);
+  return tgraph.addOperation(std::make_unique<train::operation::ElementwiseActivation>(ea_op));
+}
+
+OperationIndex addFullyConnectedOperation(train::TrainableGraph &tgraph,
+                                          const OperandIndexSequence inputs,
+                                          const OperandIndexSequence outputs)
+{
+  // Add "FullyConnected" operation
+  operation::FullyConnected::Param param;
+  param.weights_format = FullyConnectedWeightsFormat::Default;
+  param.activation = Activation::NONE;
+  auto fc_op = operation::FullyConnected(inputs, outputs, param);
+  return tgraph.addOperation(std::make_unique<train::operation::FullyConnected>(fc_op));
+}
+
+OperationIndex addLossOperation(train::TrainableGraph &tgraph, const OperandIndexSequence inputs,
+                                const OperandIndexSequence outputs)
+{
+  // Add "Loss" operation
+  auto loss_op = operation::Loss(inputs, outputs);
+  return tgraph.addOperation(std::make_unique<train::operation::Loss>(loss_op, train::LossInfo{}));
+}
+
+TEST(TrainableGraph, topological_sort_linear)
+{
+  train::TrainableGraph tgraph;
+
+  Shape shape{1, 2, 2, 1};
+  TypeInfo type{DataType::FLOAT32};
+
+  /*
+  (input) âŽ¼[EA]⎼> (y_pred)
+                          â•²
+                           [Loss]⎼> (output)
+                          â•±
+                  (y_true)
+  */
+
+  auto input = tgraph.addOperand(shape, type);
+  auto y_pred = tgraph.addOperand(shape, type);
+  auto y_true = tgraph.addOperand(shape, type);
+  auto output = tgraph.addOperand(shape, type);
+
+  tgraph.addInput({input});
+  tgraph.addInput({y_true});
+  tgraph.addOutput({output});
+
+  addElementwiseActivationOperation(tgraph, {input}, {y_pred});
+  addLossOperation(tgraph, {y_pred, y_true}, {output});
+
+  EXPECT_NO_THROW(tgraph.topolSortOperations());
+  EXPECT_NO_THROW(tgraph.btopolSortOperations());
+}
+
+TEST(TrainableGraph, topological_sort_nonlinear)
+{
+  train::TrainableGraph tgraph;
+
+  Shape shape{1, 2, 2, 1};
+  TypeInfo type{DataType::FLOAT32};
+
+  /*
+                          [EA]⎼> (lhs)
+                         â•±            â•²
+  (input) âŽ¼[EA]⎼> (split)              [Add]⎼> (y_pred)
+                         â•²            â•±                â•²
+                          [EA]⎼> (rhs)                  [Loss]⎼> (output)
+                                                       â•±
+                                               (y_true)
+  */
+
+  auto input = tgraph.addOperand(shape, type);
+  auto split = tgraph.addOperand(shape, type);
+  auto lhs = tgraph.addOperand(shape, type);
+  auto rhs = tgraph.addOperand(shape, type);
+  auto y_pred = tgraph.addOperand(shape, type);
+  auto y_true = tgraph.addOperand(shape, type);
+  auto output = tgraph.addOperand(shape, type);
+
+  tgraph.addInput({input});
+  tgraph.addInput({y_true});
+  tgraph.addOutput({output});
+
+  addElementwiseActivationOperation(tgraph, {input}, {split});
+  addElementwiseActivationOperation(tgraph, {split}, {lhs});
+  addElementwiseActivationOperation(tgraph, {split}, {rhs});
+  addAddOperation(tgraph, {lhs, rhs}, {y_pred});
+  addLossOperation(tgraph, {y_pred, y_true}, {output});
+
+  EXPECT_NO_THROW(tgraph.topolSortOperations());
+  EXPECT_NO_THROW(tgraph.btopolSortOperations());
+}
+
+TEST(TrainableGraph, neg_topological_sort_cycle)
+{
+  train::TrainableGraph tgraph;
+
+  Shape shape{1, 2, 2, 1};
+  TypeInfo type{DataType::FLOAT32};
+
+  /*
+  (input) âŽ¼[Add]⎼> (v) âŽ¼[EA]
+            |            |
+                         v
+           (u) <⎼[EA]⎼ (y_pred)
+                               â•²
+                                [Loss]⎼> (output)
+                               â•±
+                       (y_true)
+  */
+
+  auto input = tgraph.addOperand(shape, type);
+  auto u = tgraph.addOperand(shape, type);
+  auto v = tgraph.addOperand(shape, type);
+  auto y_pred = tgraph.addOperand(shape, type);
+  auto y_true = tgraph.addOperand(shape, type);
+  auto output = tgraph.addOperand(shape, type);
+
+  tgraph.addInput({input});
+  tgraph.addInput({y_true});
+  tgraph.addOutput({output});
+
+  addAddOperation(tgraph, {input, u}, {v});
+  addElementwiseActivationOperation(tgraph, {v}, {y_pred});
+  addElementwiseActivationOperation(tgraph, {y_pred}, {u});
+  addLossOperation(tgraph, {y_pred, y_true}, {output});
+
+  EXPECT_ANY_THROW(tgraph.topolSortOperations());
+  EXPECT_ANY_THROW(tgraph.btopolSortOperations());
+}
+
+TEST(TrainableGraph, truncating_backward_topological_order_nonlinear)
+{
+  {
+    train::TrainableGraph tgraph;
+
+    Shape shape{1, 2, 2, 1};
+    TypeInfo type{DataType::FLOAT32};
+
+    /*
+              [EA1]⎼> (u)
+             â•±           â•²
+            â•±  (weight1) âŽ¼[FC1]⎼> (v)
+           â•±             â•±           â•²
+          â•±       (bias1)             [Add]⎼> (y_pred)
+   (input)                           â•±                â•²
+          â•²                         â•±                  [Loss]⎼> (output)
+           [EA2]⎼> (w)             â•±                  â•±
+                      â•²           â•±           (y_true)
+            (weight2) âŽ¼[FC2]⎼> (x)
+                      â•±
+              (bias2)
+    */
+
+    auto input = tgraph.addOperand(shape, type);
+    auto u = tgraph.addOperand(shape, type);
+    auto weight1 = tgraph.addOperand(shape, type);
+    auto bias1 = tgraph.addOperand(shape, type);
+    auto v = tgraph.addOperand(shape, type);
+    auto w = tgraph.addOperand(shape, type);
+    auto weight2 = tgraph.addOperand(shape, type);
+    auto bias2 = tgraph.addOperand(shape, type);
+    auto x = tgraph.addOperand(shape, type);
+    auto y_pred = tgraph.addOperand(shape, type);
+    auto y_true = tgraph.addOperand(shape, type);
+    auto output = tgraph.addOperand(shape, type);
+
+    tgraph.addInput({input});
+    tgraph.addInput({weight1});
+    tgraph.addInput({bias1});
+    tgraph.addInput({weight2});
+    tgraph.addInput({bias2});
+    tgraph.addInput({y_true});
+    tgraph.addOutput({output});
+
+    auto ea1 = addElementwiseActivationOperation(tgraph, {input}, {u});
+    auto fc1 = addFullyConnectedOperation(tgraph, {u, weight1, bias1}, {v});
+    auto ea2 = addElementwiseActivationOperation(tgraph, {input}, {w});
+    auto fc2 = addFullyConnectedOperation(tgraph, {w, weight2, bias2}, {x});
+    auto add = addAddOperation(tgraph, {v, x}, {y_pred});
+    auto loss = addLossOperation(tgraph, {y_pred, y_true}, {output});
+
+    std::vector<OperationIndex> expected_truncation_1{loss, add, fc1, fc2};
+    std::vector<OperationIndex> expected_truncation_2{loss, add, fc2, fc1};
+    std::vector<OperationIndex> truncation =
+      tgraph.truncateBackwardOrder(tgraph.btopolSortOperations());
+
+    ASSERT_TRUE(truncation == expected_truncation_1 || truncation == expected_truncation_2);
+  }
+
+  {
+    train::TrainableGraph tgraph;
+
+    Shape shape{1, 2, 2, 1};
+    TypeInfo type{DataType::FLOAT32};
+
+    /*
+   (input1) âŽ¼[FC3]⎼> (r) âŽ¼âŽ¼[Add]⎼> (s) âŽ¼[EA1]⎼> (u)
+            â•±             â•±                       â•²
+   (weight3)             â•±              (weight1) âŽ¼[FC1]⎼> (v)
+                        â•±                         â•±           â•²
+                       â•±                         â•±             â•²
+                      â•±                   (bias1)               [Add]⎼> (y_pred)
+               (input)                                         â•±                â•²
+                      â•²                                       â•±                  [Loss]⎼> (output)
+                       â•²                                     â•±                  â•±
+                        [Add]⎼> (t) âŽ¼[EA2]⎼> (w)            â•±                  â•±
+                       â•±                       â•²           â•±           (y_true)
+               (input2)              (weight2) âŽ¼[FC2]⎼> (x)
+                                               â•±
+                                        (bias2)
+    */
+
+    auto input1 = tgraph.addOperand(shape, type);
+    auto weight3 = tgraph.addOperand(shape, type);
+    auto r = tgraph.addOperand(shape, type);
+    auto input = tgraph.addOperand(shape, type);
+    auto s = tgraph.addOperand(shape, type);
+    auto input2 = tgraph.addOperand(shape, type);
+    auto t = tgraph.addOperand(shape, type);
+    auto u = tgraph.addOperand(shape, type);
+    auto weight1 = tgraph.addOperand(shape, type);
+    auto bias1 = tgraph.addOperand(shape, type);
+    auto v = tgraph.addOperand(shape, type);
+    auto w = tgraph.addOperand(shape, type);
+    auto weight2 = tgraph.addOperand(shape, type);
+    auto bias2 = tgraph.addOperand(shape, type);
+    auto x = tgraph.addOperand(shape, type);
+    auto y_pred = tgraph.addOperand(shape, type);
+    auto y_true = tgraph.addOperand(shape, type);
+    auto output = tgraph.addOperand(shape, type);
+
+    tgraph.addInput({input});
+    tgraph.addInput({weight1});
+    tgraph.addInput({bias1});
+    tgraph.addInput({weight2});
+    tgraph.addInput({bias2});
+    tgraph.addInput({y_true});
+    tgraph.addOutput({output});
+
+    auto fc3 = addFullyConnectedOperation(tgraph, {input1, weight3}, {r});
+    auto add1 = addAddOperation(tgraph, {r, input}, {s});
+    auto add2 = addAddOperation(tgraph, {input, input2}, {t});
+    auto ea1 = addElementwiseActivationOperation(tgraph, {s}, {u});
+    auto fc1 = addFullyConnectedOperation(tgraph, {u, weight1, bias1}, {v});
+    auto ea2 = addElementwiseActivationOperation(tgraph, {t}, {w});
+    auto fc2 = addFullyConnectedOperation(tgraph, {w, weight2, bias2}, {x});
+    auto add = addAddOperation(tgraph, {v, x}, {y_pred});
+    auto loss = addLossOperation(tgraph, {y_pred, y_true}, {output});
+
+    // This expected indices are base on dfs
+    std::vector<OperationIndex> expected_truncation_1{loss, add, fc1, ea1, add1, fc3, fc2};
+    std::vector<OperationIndex> expected_truncation_2{loss, add, fc2, fc1, ea1, add1, fc3};
+    std::vector<OperationIndex> truncation =
+      tgraph.truncateBackwardOrder(tgraph.btopolSortOperations());
+
+    ASSERT_TRUE(truncation == expected_truncation_1 || truncation == expected_truncation_2);
+  }
+}
+
+TEST(TrainableGraph, essential_backward_topological_order_nonlinear)
+{
+  {
+    train::TrainableGraph tgraph;
+
+    Shape shape{1, 2, 2, 1};
+    TypeInfo type{DataType::FLOAT32};
+
+    /*
+   (input1) âŽ¼[FC3]⎼> (r) âŽ¼âŽ¼[Add]⎼> (s) âŽ¼[EA1]⎼> (u)
+            â•±             â•±                       â•²
+   (weight3)             â•±              (weight1) âŽ¼[FC1]⎼> (v)
+                        â•±                         â•±           â•²
+                       â•±                         â•±             â•²
+                      â•±                   (bias1)               [Add]⎼> (y_pred)
+               (input)                                         â•±                â•²
+                      â•²                                       â•±                  [Loss]⎼> (output)
+                       â•²                                     â•±                  â•±
+                        [Add]⎼> (t) âŽ¼[EA2]⎼> (w)            â•±                  â•±
+                       â•±                       â•²           â•±           (y_true)
+               (input2)              (weight2) âŽ¼[FC2]⎼> (x)
+                                               â•±
+                                        (bias2)
+    */
+
+    auto input1 = tgraph.addOperand(shape, type);
+    auto weight3 = tgraph.addOperand(shape, type);
+    auto r = tgraph.addOperand(shape, type);
+    auto input = tgraph.addOperand(shape, type);
+    auto s = tgraph.addOperand(shape, type);
+    auto input2 = tgraph.addOperand(shape, type);
+    auto t = tgraph.addOperand(shape, type);
+    auto u = tgraph.addOperand(shape, type);
+    auto weight1 = tgraph.addOperand(shape, type);
+    auto bias1 = tgraph.addOperand(shape, type);
+    auto v = tgraph.addOperand(shape, type);
+    auto w = tgraph.addOperand(shape, type);
+    auto weight2 = tgraph.addOperand(shape, type);
+    auto bias2 = tgraph.addOperand(shape, type);
+    auto x = tgraph.addOperand(shape, type);
+    auto y_pred = tgraph.addOperand(shape, type);
+    auto y_true = tgraph.addOperand(shape, type);
+    auto output = tgraph.addOperand(shape, type);
+
+    tgraph.addInput({input});
+    tgraph.addInput({weight1});
+    tgraph.addInput({bias1});
+    tgraph.addInput({weight2});
+    tgraph.addInput({bias2});
+    tgraph.addInput({y_true});
+    tgraph.addOutput({output});
+
+    auto fc3 = addFullyConnectedOperation(tgraph, {input1, weight3}, {r});
+    auto add1 = addAddOperation(tgraph, {r, input}, {s});
+    auto add2 = addAddOperation(tgraph, {input, input2}, {t});
+    auto ea1 = addElementwiseActivationOperation(tgraph, {s}, {u});
+    auto fc1 = addFullyConnectedOperation(tgraph, {u, weight1, bias1}, {v});
+    auto ea2 = addElementwiseActivationOperation(tgraph, {t}, {w});
+    auto fc2 = addFullyConnectedOperation(tgraph, {w, weight2, bias2}, {x});
+    auto add = addAddOperation(tgraph, {v, x}, {y_pred});
+    auto loss = addLossOperation(tgraph, {y_pred, y_true}, {output});
+
+    tgraph.enableBackward(fc2);
+    tgraph.enableBackward(fc3);
+
+    // These expected indices are base on dfs
+    std::vector<OperationIndex> expected_truncation_1{loss, add, fc1, ea1, add1, fc3, fc2};
+    std::vector<OperationIndex> expected_truncation_2{loss, add, fc2, fc1, ea1, add1, fc3};
+    std::vector<OperationIndex> essential = tgraph.essentialBackwardOrder();
+
+    ASSERT_TRUE(essential == expected_truncation_1 || essential == expected_truncation_2);
+  }
+}
diff --git a/runtime/onert/core/src/ir/train/TrainingInfo.cc b/runtime/onert/core/src/ir/train/TrainingInfo.cc
new file mode 100644 (file)
index 0000000..1027811
--- /dev/null
@@ -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/TrainingInfo.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+bool TrainingInfo::isValid() const
+{
+  if (_batch_size == 0)
+    return false;
+
+  if (_optimizer_info.optim_code == OptimizerCode::Undefined)
+    return false;
+
+  if (_optimizer_info.learning_rate <= 0.0f)
+    return false;
+
+  if (_loss_info.loss_code == LossCode::Undefined)
+    return false;
+
+  if (_loss_info.reduction_type == LossReductionType::Undefined)
+    return false;
+
+  // If there are invalid combination, add more condition-check here
+  return true;
+}
+
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/UseDefChain.cc b/runtime/onert/core/src/ir/train/UseDefChain.cc
new file mode 100644 (file)
index 0000000..9cb9bb7
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/UseDefChain.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+void UseDefChain::insertTrainingUse(const TrainingOperationIndex &idx) { _uses.insert(idx); }
+
+void UseDefChain::removeTrainingUse(const TrainingOperationIndex &idx) { _uses.erase(idx); }
+
+void UseDefChain::insertTrainingDef(const TrainingOperationIndex &idx)
+{
+  // defs must be valid
+  assert(idx.valid());
+  _defs.insert(idx);
+}
+
+void UseDefChain::removeTrainingDef(const TrainingOperationIndex &idx) { _defs.erase(idx); }
+
+void UseDefChain::clearTrainingUseDefs()
+{
+  _uses.clear();
+  _defs.clear();
+}
+
+bool UseDefChain::operator==(const UseDefChain &other) const
+{
+  return &_operand == &other._operand && _uses == other._uses && _defs == other._defs;
+}
+
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/UseDefGenerator.cc b/runtime/onert/core/src/ir/train/UseDefGenerator.cc
new file mode 100644 (file)
index 0000000..615b165
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "UseDefGenerator.h"
+
+#include "ir/train/TrainableGraph.h"
+#include "ir/train/Index.h"
+#include "../verifier/Verifier.h"
+
+#include <cassert>
+#include <memory>
+
+// TODO Reduce duplicate code
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+UseDefGenerator::UseDefGenerator(const TrainableGraph &tgraph)
+  : _tgraph{tgraph}, _node_to_idx{}, _training_usedefs{}
+{
+  const auto order = _tgraph.topolSortOperations();
+  for (const auto &index : order)
+  {
+    const auto &node = _tgraph.operation(index);
+    assert(_node_to_idx.find(&node) == _node_to_idx.end());
+    _node_to_idx[&node] = index;
+  }
+
+  // Check whether loss exists
+  assert(std::any_of(order.begin(), order.end(),
+                     [&](const auto &index) {
+                       return _tgraph.operation(index).opcode() == ir::OpCode::Loss;
+                     }) &&
+         "Loss does not exist");
+}
+
+UseDefChains UseDefGenerator::operator()()
+{
+  const auto &graph = _tgraph.graph();
+  assert(ir::verifier::EdgeChecker().verify(graph));
+
+  _training_usedefs.clear();
+  graph.operands().iterate([&](const ir::OperandIndex &idx, const ir::Operand &operand) {
+    // Initialize as emtpy UseDefChain
+    const auto empty_usedef_chain = UseDefChain{operand};
+    _training_usedefs.emplace(TrainingOperandIndex{idx, true}, empty_usedef_chain);
+    _training_usedefs.emplace(TrainingOperandIndex{idx, false}, empty_usedef_chain);
+  });
+
+  initForForwardingNodes();
+
+  initForBackwardingNodes();
+
+  return _training_usedefs;
+}
+
+void UseDefGenerator::visit(const train::operation::Loss &node)
+{
+  assert(_node_to_idx.find(&node) != _node_to_idx.end());
+  const auto &op_index = _node_to_idx.at(&node);
+  const auto backwarding_op_index = TrainingOperationIndex{op_index, false};
+
+  for (const auto &in_index : node.getInputs() | ir::Remove::UNDEFINED | ir::Remove::DUPLICATED)
+  {
+    // Insert use of forwarding inputs
+    const auto in_forwarding_index = TrainingOperandIndex{in_index, true};
+    insertUse(in_forwarding_index, backwarding_op_index);
+  }
+
+  // Set def of backwarding(backprop) y_pred
+  const auto &y_pred_index = node.getInputs().at(train::operation::Loss::Input::Y_PRED);
+  assert(!_tgraph.operands().at(y_pred_index).isConstant());
+  const auto y_pred_outgoing_index = TrainingOperandIndex{y_pred_index, false};
+  insertBackPropDef(y_pred_outgoing_index, backwarding_op_index);
+
+  // Set def of backwarding(backprop) y_true
+  const auto &y_true_index = node.getInputs().at(train::operation::Loss::Input::Y_TRUE);
+  assert(!_tgraph.operands().at(y_true_index).isConstant());
+  const auto y_true_outgoing_index = TrainingOperandIndex{y_true_index, false};
+  insertBackPropDef(y_true_outgoing_index, backwarding_op_index);
+
+  // Remove use of backwarding output
+  const auto &out_index = node.getOutputs().at(0);
+  const auto incoming_index = TrainingOperandIndex{out_index, false};
+  auto &usedef_chain = _training_usedefs.at(incoming_index);
+  usedef_chain.removeTrainingUse(backwarding_op_index);
+}
+
+void UseDefGenerator::insertUse(const TrainingOperandIndex &operand_index,
+                                const TrainingOperationIndex &op_index)
+{
+  assert(_training_usedefs.find(operand_index) != _training_usedefs.end());
+  auto &usedef_chain = _training_usedefs.at(operand_index);
+  usedef_chain.insertTrainingUse(op_index);
+}
+
+void UseDefGenerator::insertDef(const TrainingOperandIndex &operand_index,
+                                const TrainingOperationIndex &op_index)
+{
+  assert(operand_index.valid());
+
+  assert(_training_usedefs.find(operand_index) != _training_usedefs.end());
+  auto &usedef_chain = _training_usedefs.at(operand_index);
+  usedef_chain.insertTrainingDef(op_index);
+}
+
+void UseDefGenerator::insertBackPropDef(const TrainingOperandIndex &operand_index,
+                                        const TrainingOperationIndex &op_index)
+{
+  // NOTE There is no need to set def of constant backwarding(backprop) inputs
+  //      because it won't be back-propagated.
+  if (!_tgraph.operands().at(operand_index.index()).isConstant())
+  {
+    insertDef(operand_index, op_index);
+  }
+}
+
+void UseDefGenerator::initForForwardingNodes()
+{
+  // Initialize training def-uses of forwarding operands for only forwarding nodes
+  // (i.e. forwarding nodes that do not have any backwarding node)
+  _tgraph.operands().iterate([&](const ir::OperandIndex &idx, const ir::Operand &operand) {
+    // Append forwarding def-uses as it is
+    const bool is_forward = true;
+    const auto forwarding_operand_index = TrainingOperandIndex{idx, is_forward};
+
+    const auto def = operand.getDef();
+    if (def.valid())
+    {
+      insertDef(forwarding_operand_index, TrainingOperationIndex{def, is_forward});
+      auto &usedef_chain = _training_usedefs.at(forwarding_operand_index);
+      usedef_chain.insertTrainingDef(TrainingOperationIndex{def, is_forward});
+    }
+
+    assert(_training_usedefs.at(forwarding_operand_index).getTrainingUses().size() == 0);
+    const auto uses = operand.getUses();
+    for (const auto &use : uses)
+      insertUse(forwarding_operand_index, TrainingOperationIndex{use, is_forward});
+  });
+}
+
+void UseDefGenerator::initForBackwardingNodes()
+{
+  const auto backward_order = _tgraph.essentialBackwardOrder();
+  // Initialize training uses of forwarding operands and def-uses of backwarding operands for
+  // backwarding nodes (i.e. backwarding nodes that do not have any forwarding node)
+  for (const auto &op_index : backward_order)
+  {
+    const auto &node = _tgraph.operation(op_index);
+
+    // Insert use of backwarding operands(only output)
+    {
+      if (node.getOutputs().size() > 1)
+        throw std::runtime_error(
+          "UseDefGenerator does not support multiple outputs of training operation");
+
+      const auto &output = node.getOutputs().at(0);
+      const auto backwarding_op_index = TrainingOperationIndex{op_index, false};
+      const auto incoming_index = TrainingOperandIndex{output, false};
+      insertUse(incoming_index, backwarding_op_index);
+    }
+
+    // Insert uses of forwarding operands and insert defs of backwarding operands
+    node.accept(*this);
+  }
+}
+
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/UseDefGenerator.h b/runtime/onert/core/src/ir/train/UseDefGenerator.h
new file mode 100644 (file)
index 0000000..369d9a2
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_USEDEFINITIALIZER_H__
+#define __ONERT_IR_TRAIN_USEDEFINITIALIZER_H__
+
+#include "ir/train/TrainableOperationVisitor.h"
+
+#include "ir/train/UseDefChains.h"
+#include "ir/train/Operations.Include.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+class TrainableGraph;
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+
+struct UseDefGeneratorBase : public TrainableOperationVisitor
+{
+  virtual ~UseDefGeneratorBase() = default;
+
+protected:
+#define OP(InternalName)                                                                \
+  virtual void visit(const operation::InternalName &) override                          \
+  {                                                                                     \
+    throw std::runtime_error("UseDefGenerator: NYI for operation '" #InternalName "'"); \
+  }
+#include "ir/train/Operations.lst"
+#undef OP
+};
+
+class UseDefGenerator : public UseDefGeneratorBase
+{
+public:
+  UseDefGenerator(void) = delete;
+  UseDefGenerator(const TrainableGraph &tgraph);
+
+public:
+  UseDefChains operator()();
+
+public:
+  void visit(const train::operation::Loss &node) override;
+
+private:
+  void insertUse(const TrainingOperandIndex &operand_index, const TrainingOperationIndex &op_index);
+  void insertDef(const TrainingOperandIndex &operand_index, const TrainingOperationIndex &op_index);
+  void insertBackPropDef(const TrainingOperandIndex &operand_index,
+                         const TrainingOperationIndex &op_index);
+  void initForForwardingNodes();
+  void initForBackwardingNodes();
+
+private:
+  const TrainableGraph &_tgraph;
+  std::unordered_map<const ITrainableOperation *, OperationIndex> _node_to_idx;
+  UseDefChains _training_usedefs;
+};
+
+} // namespace train
+} // namespace ir
+} // namespace onert
+
+#endif // __ONERT_IR_TRAIN_USEDEFINITIALIZER_H__
diff --git a/runtime/onert/core/src/ir/train/operation/BinaryArithmetic.cc b/runtime/onert/core/src/ir/train/operation/BinaryArithmetic.cc
new file mode 100644 (file)
index 0000000..473d387
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/BinaryArithmetic.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> BinaryArithmetic::clone() const
+{
+  return std::make_unique<BinaryArithmetic>(*this);
+}
+
+void BinaryArithmetic::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void BinaryArithmetic::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+BinaryArithmetic::BinaryArithmetic(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/DepthwiseConv2D.cc b/runtime/onert/core/src/ir/train/operation/DepthwiseConv2D.cc
new file mode 100644 (file)
index 0000000..2a72896
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/DepthwiseConv2D.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> DepthwiseConv2D::clone() const
+{
+  return std::make_unique<DepthwiseConv2D>(*this);
+}
+
+void DepthwiseConv2D::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void DepthwiseConv2D::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+DepthwiseConv2D::DepthwiseConv2D(const OperationType &operation)
+  : OperationType{operation.getInputs(), operation.getOutputs(), operation.param()}
+{
+  // DO NOTHING
+}
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
index abd7992..3a89e0f 100644 (file)
@@ -36,8 +36,8 @@ 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()}
+Loss::Loss(const OperationType &operation, const LossInfo &param)
+  : OperationType{operation.getInputs(), operation.getOutputs()}, _param{param}
 {
   // DO NOTHING
 }
diff --git a/runtime/onert/core/src/ir/train/operation/Pad.cc b/runtime/onert/core/src/ir/train/operation/Pad.cc
new file mode 100644 (file)
index 0000000..56394f5
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/Pad.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> Pad::clone() const { return std::make_unique<Pad>(*this); }
+
+void Pad::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void Pad::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+Pad::Pad(const OperationType &operation)
+  : OperationType{operation.getInputs(), operation.getOutputs()}
+{
+  // DO NOTHING
+}
+
+} // namespace operation
+} // namespace train
+} // namespace ir
+} // namespace onert
diff --git a/runtime/onert/core/src/ir/train/operation/Reduce.cc b/runtime/onert/core/src/ir/train/operation/Reduce.cc
new file mode 100644 (file)
index 0000000..51986a0
--- /dev/null
@@ -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/Reduce.h"
+
+#include "ir/OperationVisitor.h"
+#include "ir/train/TrainableOperationVisitor.h"
+
+namespace onert
+{
+namespace ir
+{
+namespace train
+{
+namespace operation
+{
+
+std::unique_ptr<ITrainableOperation> Reduce::clone() const
+{
+  return std::make_unique<Reduce>(*this);
+}
+
+void Reduce::accept(OperationVisitor &v) const { v.visit(*this); }
+
+void Reduce::accept(TrainableOperationVisitor &v) const { v.visit(*this); }
+
+Reduce::Reduce(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/UntrainableOperation.test.cc b/runtime/onert/core/src/ir/train/operation/UntrainableOperation.test.cc
new file mode 100644 (file)
index 0000000..e3472ec
--- /dev/null
@@ -0,0 +1,1239 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/UntrainableOperation.h"
+
+#include "ir/Operations.Include.h"
+
+#include <gtest/gtest.h>
+
+using namespace ::onert::ir;
+
+operation::AddN generateAddN()
+{
+  return operation::AddN{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::ArgMinMax generateArgMinMax()
+{
+  operation::ArgMinMax::Param param;
+  param.output_type = DataType::FLOAT32;
+
+  return operation::ArgMinMax{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::BatchMatMul generateBatchMatMul()
+{
+  operation::BatchMatMul::Param param;
+  param.adj_x = true;
+  param.adj_y = true;
+
+  return operation::BatchMatMul{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::BatchToSpaceND generateBatchToSpaceND()
+{
+  return operation::BatchToSpaceND{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::BCQFullyConnected generateBCQFullyConnected()
+{
+  operation::BCQFullyConnected::Param param;
+  param.activation = Activation::NONE;
+  param.weights_hidden_size = 1;
+
+  return operation::BCQFullyConnected{OperandIndexSequence{1, 2, 3, 4, 5}, OperandIndexSequence{0},
+                                      param};
+}
+
+operation::BCQGather generateBCQGather()
+{
+  operation::BCQGather::Param param;
+  param.axis = 0;
+  param.input_hidden_size = 1;
+
+  return operation::BCQGather{OperandIndexSequence{1, 2, 3, 4}, OperandIndexSequence{0}, param};
+}
+
+operation::BinaryArithmetic generateBinaryArithmetic()
+{
+  operation::BinaryArithmetic::Param param;
+  param.activation = Activation::NONE;
+  param.arithmetic_type = operation::BinaryArithmetic::ArithmeticType::ADD;
+
+  return operation::BinaryArithmetic{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::BroadcastTo generateBroadcastTo()
+{
+  return operation::BroadcastTo{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::Bulk generateBulk()
+{
+  operation::Bulk::Param param;
+  param.binary_path = "";
+  param.origin_input_shapes = std::vector<onert::ir::Shape>{};
+  param.origin_output_shapes = std::vector<onert::ir::Shape>{};
+
+  return operation::Bulk{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::Comparison generateComparison()
+{
+  operation::Comparison::Param param;
+  param.comparison_type = operation::Comparison::ComparisonType::Equal;
+
+  return operation::Comparison{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::Concat generateConcat()
+{
+  operation::Concat::Param param;
+  param.axis = 0;
+
+  return operation::Concat{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}, param};
+}
+
+operation::Conv2D generateConv2D()
+{
+  operation::Conv2D::Param param;
+  param.activation = Activation::NONE;
+  param.dilation = Dilation{};
+  param.padding = Padding{};
+  param.stride = Stride{};
+
+  return operation::Conv2D{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}, param};
+}
+
+operation::ConvertFp16ToFp32 generateConvertFp16ToFp32()
+{
+  return operation::ConvertFp16ToFp32{OperandIndexSequence{1}, OperandIndexSequence{0}};
+}
+
+operation::ConvertFp32ToFp16 generateConvertFp32ToFp16()
+{
+  return operation::ConvertFp32ToFp16{OperandIndexSequence{1}, OperandIndexSequence{0}};
+}
+
+operation::Custom generateCustom()
+{
+  return operation::Custom{OperandConstraint::createExact(1u), OperandIndexSequence{1},
+                           OperandIndexSequence{0}, std::string("id"),
+                           operation::Custom::Userdata{}};
+}
+
+operation::DepthToSpace generateDepthToSpace()
+{
+  operation::DepthToSpace::Param param;
+  param.block_size = 1;
+
+  return operation::DepthToSpace{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::DepthwiseConv2D generateDepthwiseConv2D()
+{
+  operation::DepthwiseConv2D::Param param;
+  param.activation = Activation::NONE;
+  param.dilation = Dilation{};
+  param.multiplier = 1u;
+  param.padding = Padding{};
+  param.stride = Stride{};
+
+  return operation::DepthwiseConv2D{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}, param};
+}
+
+operation::DetectionPostProcess generateDetectionPostProcess()
+{
+  operation::DetectionPostProcess::Param param;
+
+  return operation::DetectionPostProcess{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0},
+                                         param};
+}
+
+operation::Einsum generateEinsum()
+{
+  operation::Einsum::Param param;
+  param.equation = "";
+
+  return operation::Einsum{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::ElementwiseActivation generateElementwiseActivation()
+{
+  operation::ElementwiseActivation::Param param;
+  param.alpha = 0.f;
+  param.beta = 0.f;
+  param.op_type = operation::ElementwiseActivation::Type::ELU;
+
+  return operation::ElementwiseActivation{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::ElementwiseBinary generateElementwiseBinary()
+{
+  operation::ElementwiseBinary::Param param;
+  param.op_type = operation::ElementwiseBinary::ElementwiseBinaryType::FLOOR_DIV;
+
+  return operation::ElementwiseBinary{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::ElementwiseUnary generateElementwiseUnary()
+{
+  operation::ElementwiseUnary::Param param;
+  param.op_type = operation::ElementwiseUnary::Type::ABS;
+
+  return operation::ElementwiseUnary{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::EmbeddingLookup generateEmbeddingLookup()
+{
+  return operation::EmbeddingLookup{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::ExpandDims generateExpandDims()
+{
+  return operation::ExpandDims{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::Fill generateFill()
+{
+  return operation::Fill{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::FullyConnected generateFullyConnected()
+{
+  operation::FullyConnected::Param param;
+  param.activation = Activation::NONE;
+  param.weights_format = FullyConnectedWeightsFormat::Default;
+
+  return operation::FullyConnected{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}, param};
+}
+
+operation::FusedBatchNorm generateFusedBatchNorm()
+{
+  operation::FusedBatchNorm::Param param;
+  param.is_training = false;
+  param.epsilon = 0.f;
+  param.data_format = "";
+
+  return operation::FusedBatchNorm{OperandIndexSequence{1, 2, 3, 4, 5}, OperandIndexSequence{0},
+                                   param};
+}
+
+operation::Gather generateGather()
+{
+  operation::Gather::Param param;
+  param.axis = 0;
+
+  return operation::Gather{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::HashtableLookup generateHashtableLookup()
+{
+  return operation::HashtableLookup{OperandIndexSequence{2, 3, 4}, OperandIndexSequence{0, 1}};
+}
+
+operation::If generateIf()
+{
+  operation::If::Param param;
+  param.else_subg_index = 1;
+  param.then_subg_index = 2;
+
+  return operation::If{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}, param};
+}
+
+operation::InstanceNorm generateInstanceNorm()
+{
+  operation::InstanceNorm::Param param;
+  param.activation = Activation::NONE;
+  param.epsilon = 0.f;
+
+  return operation::InstanceNorm{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}, param};
+}
+
+operation::L2Normalization generateL2Normalization()
+{
+  return operation::L2Normalization{OperandIndexSequence{1}, OperandIndexSequence{0}};
+}
+
+operation::LocalResponseNormalization generateLocalResponseNormalization()
+{
+  operation::LocalResponseNormalization::Param param;
+  param.alpha = 0.f;
+  param.beta = 0.f;
+  param.bias = 0.f;
+  param.radius = 1;
+
+  return operation::LocalResponseNormalization{OperandIndexSequence{1}, OperandIndexSequence{0},
+                                               param};
+}
+
+operation::LogSoftmax generateLogSoftmax()
+{
+  operation::LogSoftmax::Param param;
+  param.axis = 0;
+  param.beta = 0.f;
+
+  return operation::LogSoftmax{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::LSTM generateLSTM()
+{
+  operation::LSTM::Param param;
+  param.activation = Activation::NONE;
+  param.cell_threshold = 1.f;
+  param.projection_threshold = 1.f;
+  param.time_major = true;
+
+  return operation::LSTM{
+    OperandIndexSequence{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
+    OperandIndexSequence{0}, param};
+}
+
+operation::MatrixBandPart generateMatrixBandPart()
+{
+  return operation::MatrixBandPart{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}};
+}
+
+operation::OneHot generateOneHot()
+{
+  operation::OneHot::Param param;
+  param.axis = 0;
+
+  return operation::OneHot{OperandIndexSequence{1, 2, 3, 4}, OperandIndexSequence{0}, param};
+}
+
+operation::Pack generatePack()
+{
+  operation::Pack::Param param;
+  param.axis = 0;
+  param.num = 1;
+
+  return operation::Pack{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::Pad generatePad()
+{
+  return operation::Pad{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}};
+}
+
+operation::Permute generatePermute()
+{
+  return operation::Permute{OperandIndex{1}, OperandIndex{0}, operation::Permute::Type::COPY};
+}
+
+operation::Pool2D generatePool2D()
+{
+  operation::Pool2D::Param param;
+  param.activation = Activation::NONE;
+  param.kh = 1;
+  param.kw = 1;
+  param.op_type = operation::Pool2D::PoolType::AVG;
+  param.padding = Padding{};
+  param.stride = Stride{};
+
+  return operation::Pool2D{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::Pow generatePow()
+{
+  return operation::Pow{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::PReLU generatePReLU()
+{
+  return operation::PReLU{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::Range generateRange()
+{
+  return operation::Range{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}};
+}
+
+operation::Rank generateRank()
+{
+  return operation::Rank{OperandIndexSequence{1}, OperandIndexSequence{0}};
+}
+
+operation::Reduce generateReduce()
+{
+  operation::Reduce::Param param;
+  param.keep_dims = true;
+  param.reduce_type = operation::Reduce::ReduceType::ALL;
+
+  return operation::Reduce{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::Reshape generateReshape()
+{
+  operation::Reshape::Param param;
+  param.new_shape = std::vector<int32_t>{1};
+
+  return operation::Reshape{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::ResizeBilinear generateResizeBilinear()
+{
+  operation::ResizeBilinear::Param param;
+  param.align_corners = true;
+  param.half_pixel_centers = true;
+  param.height_out = 1;
+  param.width_out = 1;
+
+  return operation::ResizeBilinear{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::ResizeNearestNeighbor generateResizeNearestNeighbor()
+{
+  operation::ResizeNearestNeighbor::Param param;
+  param.align_corners = true;
+  param.height_out = 1;
+  param.width_out = 1;
+
+  return operation::ResizeNearestNeighbor{OperandIndexSequence{1, 2}, OperandIndexSequence{0},
+                                          param};
+}
+
+operation::Reverse generateReverse()
+{
+  return operation::Reverse{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::RNN generateRNN()
+{
+  operation::RNN::Param param;
+  param.activation = Activation::NONE;
+
+  return operation::RNN{OperandIndexSequence{1, 2, 3, 4, 5}, OperandIndexSequence{0}, param};
+}
+
+operation::Select generateSelect()
+{
+  return operation::Select{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}};
+}
+
+operation::Shape generateShape()
+{
+  return operation::Shape{OperandIndexSequence{1}, OperandIndexSequence{0}};
+}
+
+operation::Slice generateSlice()
+{
+  return operation::Slice{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}};
+}
+
+operation::Softmax generateSoftmax()
+{
+  operation::Softmax::Param param;
+  param.beta = 0.1f;
+
+  return operation::Softmax{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::SpaceToBatchND generateSpaceToBatchND()
+{
+  return operation::SpaceToBatchND{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}};
+}
+
+operation::SpaceToDepth generateSpaceToDepth()
+{
+  operation::SpaceToDepth::Param param;
+  param.block_size = 1;
+
+  return operation::SpaceToDepth{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::Split generateSplit()
+{
+  operation::Split::Param param;
+  param.num_splits = 1;
+
+  return operation::Split{OperandIndexSequence{1, 2}, OperandIndexSequence{0}, param};
+}
+
+operation::SplitV generateSplitV()
+{
+  operation::SplitV::Param param;
+  param.num_splits = 1;
+
+  return operation::SplitV{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}, param};
+}
+
+operation::SquaredDifference generateSquaredDifference()
+{
+  return operation::SquaredDifference{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::Squeeze generateSqueeze()
+{
+  operation::Squeeze::Param param;
+  param.dims[0] = 1;
+  param.ndim = 1;
+
+  return operation::Squeeze{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::StatelessRandomUniform generateStatelessRandomUniform()
+{
+  return operation::StatelessRandomUniform{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::StridedSlice generateStridedSlice()
+{
+  operation::StridedSlice::Param param;
+  param.begin_mask = 1;
+  param.end_mask = 1;
+  param.shrink_axis_mask = 1;
+
+  return operation::StridedSlice{OperandIndexSequence{1, 2, 3, 4}, OperandIndexSequence{0}, param};
+}
+
+operation::Tile generateTile()
+{
+  return operation::Tile{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::TopKV2 generateTopKV2()
+{
+  operation::TopKV2::Param param;
+  param.k = 1;
+
+  return operation::TopKV2{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::Transpose generateTranspose()
+{
+  return operation::Transpose{OperandIndexSequence{1, 2}, OperandIndexSequence{0}};
+}
+
+operation::TransposeConv generateTransposeConv()
+{
+  operation::TransposeConv::Param param;
+  param.padding = Padding();
+  param.stride = Stride();
+
+  return operation::TransposeConv{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}, param};
+}
+
+operation::Unpack generateUnpack()
+{
+  operation::Unpack::Param param;
+  param.axis = 0;
+  param.num = 1;
+
+  return operation::Unpack{OperandIndexSequence{1}, OperandIndexSequence{0}, param};
+}
+
+operation::While generateWhile()
+{
+  operation::While::Param param;
+  param.cond_subg_index = 1;
+  param.body_subg_index = 2;
+
+  return operation::While{OperandIndexSequence{1, 2, 3}, OperandIndexSequence{0}, param};
+}
+
+class MockOperationVisitor : public OperationVisitor
+{
+public:
+  void invoke(Operation &op) { op.accept(*this); }
+
+#define OP(InternalName) \
+  virtual void visit(const operation::InternalName &) override { visit_flag = true; }
+#include "ir/Operations.lst"
+#undef OP
+
+public:
+  // TODO Replace this flag with using GMOCK if necessary
+  bool visit_flag{false};
+};
+
+template <typename OperationType> auto generateUntrainableOperation(const OperationType &op)
+{
+  return std::make_unique<train::operation::UntrainableOperation<OperationType>>(op);
+}
+
+template <typename OperationType> void verifyOp(const OperationType &op)
+{
+  auto untrainable = generateUntrainableOperation(op);
+  EXPECT_EQ(untrainable->opcode(), op.opcode());
+  EXPECT_EQ(untrainable->getInputs(), op.getInputs());
+  EXPECT_EQ(untrainable->getOutputs(), op.getOutputs());
+
+  // Check clone
+  auto clone = untrainable->clone();
+  EXPECT_TRUE(clone != nullptr);
+  EXPECT_EQ(clone->hasTrainableParameter(), untrainable->hasTrainableParameter());
+  EXPECT_EQ(clone->opcode(), untrainable->opcode());
+  EXPECT_EQ(clone->getInputs(), untrainable->getInputs());
+  EXPECT_EQ(clone->getOutputs(), untrainable->getOutputs());
+
+  // Check downcast
+  const auto derived =
+    dynamic_cast<train::operation::UntrainableOperation<OperationType> *>(clone.get());
+  EXPECT_TRUE(derived != nullptr);
+  EXPECT_EQ(clone->hasTrainableParameter(), untrainable->hasTrainableParameter());
+  EXPECT_EQ(derived->opcode(), op.opcode());
+  EXPECT_EQ(derived->getInputs(), op.getInputs());
+  EXPECT_EQ(derived->getOutputs(), op.getOutputs());
+
+  // Check visitor
+  MockOperationVisitor visitor;
+
+  visitor.visit_flag = false;
+  visitor.invoke(*untrainable);
+  EXPECT_TRUE(visitor.visit_flag);
+}
+
+TEST(UntrainableOperation, testAllOps)
+{
+  const auto addn = generateAddN();
+  verifyOp(addn);
+
+  const auto argminmax = generateArgMinMax();
+  verifyOp(argminmax);
+
+  const auto batch_matmul = generateBatchMatMul();
+  verifyOp(batch_matmul);
+
+  const auto batch_to_spacend = generateBatchToSpaceND();
+  verifyOp(batch_to_spacend);
+
+  const auto bcq_fc = generateBCQFullyConnected();
+  verifyOp(bcq_fc);
+
+  const auto bcq_gather = generateBCQGather();
+  verifyOp(bcq_gather);
+
+  const auto binary_arithmetic = generateBinaryArithmetic();
+  verifyOp(binary_arithmetic);
+
+  const auto broadcast = generateBroadcastTo();
+  verifyOp(broadcast);
+
+  const auto bulk = generateBulk();
+  verifyOp(bulk);
+
+  const auto comparison = generateComparison();
+  verifyOp(comparison);
+
+  const auto concat = generateConcat();
+  verifyOp(concat);
+
+  const auto conv2d = generateConv2D();
+  verifyOp(conv2d);
+
+  const auto fp16_to_fp32 = generateConvertFp16ToFp32();
+  verifyOp(fp16_to_fp32);
+
+  const auto fp32_to_fp16 = generateConvertFp32ToFp16();
+  verifyOp(fp32_to_fp16);
+
+  const auto custom = generateCustom();
+  verifyOp(custom);
+
+  const auto depth_to_space = generateDepthToSpace();
+  verifyOp(depth_to_space);
+
+  const auto depthwise_conv2d = generateDepthwiseConv2D();
+  verifyOp(depthwise_conv2d);
+
+  const auto detection = generateDetectionPostProcess();
+  verifyOp(detection);
+
+  const auto einsum = generateEinsum();
+  verifyOp(einsum);
+
+  const auto activation = generateElementwiseActivation();
+  verifyOp(activation);
+
+  const auto binary = generateElementwiseBinary();
+  verifyOp(binary);
+
+  const auto unary = generateElementwiseUnary();
+  verifyOp(unary);
+
+  const auto embed = generateEmbeddingLookup();
+  verifyOp(embed);
+
+  const auto expand_dims = generateExpandDims();
+  verifyOp(expand_dims);
+
+  const auto fill = generateFill();
+  verifyOp(fill);
+
+  const auto fc = generateFullyConnected();
+  verifyOp(fc);
+
+  const auto fused_batch_norm = generateFusedBatchNorm();
+  verifyOp(fused_batch_norm);
+
+  const auto gather = generateGather();
+  verifyOp(gather);
+
+  const auto hashtable = generateHashtableLookup();
+  verifyOp(hashtable);
+
+  const auto if_op = generateIf();
+  verifyOp(if_op);
+
+  const auto in_norm = generateInstanceNorm();
+  verifyOp(in_norm);
+
+  const auto l2_norm = generateL2Normalization();
+  verifyOp(l2_norm);
+
+  const auto local_norm = generateLocalResponseNormalization();
+  verifyOp(local_norm);
+
+  const auto log_softmax = generateLogSoftmax();
+  verifyOp(log_softmax);
+
+  const auto lstm = generateLSTM();
+  verifyOp(lstm);
+
+  const auto maxrix_band_part = generateMatrixBandPart();
+  verifyOp(maxrix_band_part);
+
+  const auto one_hot = generateOneHot();
+  verifyOp(one_hot);
+
+  const auto pack = generatePack();
+  verifyOp(pack);
+
+  const auto pad = generatePad();
+  verifyOp(pad);
+
+  const auto permute = generatePermute();
+  verifyOp(permute);
+
+  const auto pool2d = generatePool2D();
+  verifyOp(pool2d);
+
+  const auto pow = generatePow();
+  verifyOp(pow);
+
+  const auto prelu = generatePReLU();
+  verifyOp(prelu);
+
+  const auto range = generateRange();
+  verifyOp(range);
+
+  const auto rank = generateRank();
+  verifyOp(rank);
+
+  const auto reduce = generateReduce();
+  verifyOp(reduce);
+
+  const auto reshape = generateReshape();
+  verifyOp(reshape);
+
+  const auto resize_bilinear = generateResizeBilinear();
+  verifyOp(resize_bilinear);
+
+  const auto resize_nearest_neighbor = generateResizeNearestNeighbor();
+  verifyOp(resize_nearest_neighbor);
+
+  const auto reverse = generateReverse();
+  verifyOp(reverse);
+
+  const auto rnn = generateRNN();
+  verifyOp(rnn);
+
+  const auto select = generateSelect();
+  verifyOp(select);
+
+  const auto shape = generateShape();
+  verifyOp(shape);
+
+  const auto slice = generateSlice();
+  verifyOp(slice);
+
+  const auto softmax = generateSoftmax();
+  verifyOp(softmax);
+
+  const auto space_to_batchnd = generateSpaceToBatchND();
+  verifyOp(space_to_batchnd);
+
+  const auto space_to_depth = generateSpaceToDepth();
+  verifyOp(space_to_depth);
+
+  const auto split = generateSplit();
+  verifyOp(split);
+
+  const auto splitv = generateSplitV();
+  verifyOp(splitv);
+
+  const auto squared_diff = generateSquaredDifference();
+  verifyOp(squared_diff);
+
+  const auto squeeze = generateSqueeze();
+  verifyOp(squeeze);
+
+  const auto stateless_random_uniform = generateStatelessRandomUniform();
+  verifyOp(stateless_random_uniform);
+
+  const auto strided_slice = generateStridedSlice();
+  verifyOp(strided_slice);
+
+  const auto tile = generateTile();
+  verifyOp(tile);
+
+  const auto topkv2 = generateTopKV2();
+  verifyOp(topkv2);
+
+  const auto transpose = generateTranspose();
+  verifyOp(transpose);
+
+  const auto transpose_conv = generateTransposeConv();
+  verifyOp(transpose_conv);
+
+  const auto unpack = generateUnpack();
+  verifyOp(unpack);
+
+  const auto while_op = generateWhile();
+  verifyOp(while_op);
+}
+
+class MockTrainableOperationVisitor : public train::TrainableOperationVisitor
+{
+public:
+  void invoke(train::ITrainableOperation &op) { op.accept(*this); }
+
+#define OP(InternalName) \
+  virtual void visit(const train::operation::InternalName &) override {}
+#include "ir/train/ITrainableOperation.h"
+#undef OP
+};
+
+TEST(UntrainableOperation, neg_TrainableOperationVisitor)
+{
+  MockTrainableOperationVisitor visitor;
+
+  {
+    const auto addn = generateAddN();
+    auto untrainable = generateUntrainableOperation(addn);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    auto argminmax = generateArgMinMax();
+    auto untrainable = generateUntrainableOperation(argminmax);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto batch_matmul = generateBatchMatMul();
+    auto untrainable = generateUntrainableOperation(batch_matmul);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto batch_to_spacend = generateBatchToSpaceND();
+    auto untrainable = generateUntrainableOperation(batch_to_spacend);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto bcq_fc = generateBCQFullyConnected();
+    auto untrainable = generateUntrainableOperation(bcq_fc);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto bcq_gather = generateBCQGather();
+    auto untrainable = generateUntrainableOperation(bcq_gather);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto binary_arithmetic = generateBinaryArithmetic();
+    auto untrainable = generateUntrainableOperation(binary_arithmetic);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto broadcast = generateBroadcastTo();
+    auto untrainable = generateUntrainableOperation(broadcast);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto bulk = generateBulk();
+    auto untrainable = generateUntrainableOperation(bulk);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto comparison = generateComparison();
+    auto untrainable = generateUntrainableOperation(comparison);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto concat = generateConcat();
+    auto untrainable = generateUntrainableOperation(concat);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto conv2d = generateConv2D();
+    auto untrainable = generateUntrainableOperation(conv2d);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto fp16_to_fp32 = generateConvertFp16ToFp32();
+    auto untrainable = generateUntrainableOperation(fp16_to_fp32);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto fp32_to_fp16 = generateConvertFp32ToFp16();
+    auto untrainable = generateUntrainableOperation(fp32_to_fp16);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto custom = generateCustom();
+    auto untrainable = generateUntrainableOperation(custom);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto depth_to_space = generateDepthToSpace();
+    auto untrainable = generateUntrainableOperation(depth_to_space);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto depthwise_conv2d = generateDepthwiseConv2D();
+    auto untrainable = generateUntrainableOperation(depthwise_conv2d);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto detection = generateDetectionPostProcess();
+    auto untrainable = generateUntrainableOperation(detection);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto einsum = generateEinsum();
+    auto untrainable = generateUntrainableOperation(einsum);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto activation = generateElementwiseActivation();
+    auto untrainable = generateUntrainableOperation(activation);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto binary = generateElementwiseBinary();
+    auto untrainable = generateUntrainableOperation(binary);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto unary = generateElementwiseUnary();
+    auto untrainable = generateUntrainableOperation(unary);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto embed = generateEmbeddingLookup();
+    auto untrainable = generateUntrainableOperation(embed);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto expand_dims = generateExpandDims();
+    auto untrainable = generateUntrainableOperation(expand_dims);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto fill = generateFill();
+    auto untrainable = generateUntrainableOperation(fill);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto fc = generateFullyConnected();
+    auto untrainable = generateUntrainableOperation(fc);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto fused_batch_norm = generateFusedBatchNorm();
+    auto untrainable = generateUntrainableOperation(fused_batch_norm);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto gather = generateGather();
+    auto untrainable = generateUntrainableOperation(gather);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto hashtable = generateHashtableLookup();
+    auto untrainable = generateUntrainableOperation(hashtable);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto if_op = generateIf();
+    auto untrainable = generateUntrainableOperation(if_op);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto in_norm = generateInstanceNorm();
+    auto untrainable = generateUntrainableOperation(in_norm);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto l2_norm = generateL2Normalization();
+    auto untrainable = generateUntrainableOperation(l2_norm);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto local_norm = generateLocalResponseNormalization();
+    auto untrainable = generateUntrainableOperation(local_norm);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto log_softmax = generateLogSoftmax();
+    auto untrainable = generateUntrainableOperation(log_softmax);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto lstm = generateLSTM();
+    auto untrainable = generateUntrainableOperation(lstm);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto matrix_band_part = generateMatrixBandPart();
+    auto untrainable = generateUntrainableOperation(matrix_band_part);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto one_hot = generateOneHot();
+    auto untrainable = generateUntrainableOperation(one_hot);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto pack = generatePack();
+    auto untrainable = generateUntrainableOperation(pack);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto pad = generatePad();
+    auto untrainable = generateUntrainableOperation(pad);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto permute = generatePermute();
+    auto untrainable = generateUntrainableOperation(permute);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto pool2d = generatePool2D();
+    auto untrainable = generateUntrainableOperation(pool2d);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto pow = generatePow();
+    auto untrainable = generateUntrainableOperation(pow);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto prelu = generatePReLU();
+    auto untrainable = generateUntrainableOperation(prelu);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto range = generateRange();
+    auto untrainable = generateUntrainableOperation(range);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto rank = generateRank();
+    auto untrainable = generateUntrainableOperation(rank);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto reduce = generateReduce();
+    auto untrainable = generateUntrainableOperation(reduce);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto reshape = generateReshape();
+    auto untrainable = generateUntrainableOperation(reshape);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto resize_bilinear = generateResizeBilinear();
+    auto untrainable = generateUntrainableOperation(resize_bilinear);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto resize_nearest_neighbor = generateResizeNearestNeighbor();
+    auto untrainable = generateUntrainableOperation(resize_nearest_neighbor);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto reverse = generateReverse();
+    auto untrainable = generateUntrainableOperation(reverse);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto rnn = generateRNN();
+    auto untrainable = generateUntrainableOperation(rnn);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto select = generateSelect();
+    auto untrainable = generateUntrainableOperation(select);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto shape = generateShape();
+    auto untrainable = generateUntrainableOperation(shape);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto slice = generateSlice();
+    auto untrainable = generateUntrainableOperation(slice);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto softmax = generateSoftmax();
+    auto untrainable = generateUntrainableOperation(softmax);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto space_to_batchnd = generateSpaceToBatchND();
+    auto untrainable = generateUntrainableOperation(space_to_batchnd);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto space_to_depth = generateSpaceToDepth();
+    auto untrainable = generateUntrainableOperation(space_to_depth);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto split = generateSplit();
+    auto untrainable = generateUntrainableOperation(split);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto splitv = generateSplitV();
+    auto untrainable = generateUntrainableOperation(splitv);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto squared_diff = generateSquaredDifference();
+    auto untrainable = generateUntrainableOperation(squared_diff);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto squeeze = generateSqueeze();
+    auto untrainable = generateUntrainableOperation(squeeze);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto stateless_random_uniform = generateStatelessRandomUniform();
+    auto untrainable = generateUntrainableOperation(stateless_random_uniform);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto strided_slice = generateStridedSlice();
+    auto untrainable = generateUntrainableOperation(strided_slice);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto tile = generateTile();
+    auto untrainable = generateUntrainableOperation(tile);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto topkv2 = generateTopKV2();
+    auto untrainable = generateUntrainableOperation(topkv2);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto transpose = generateTranspose();
+    auto untrainable = generateUntrainableOperation(transpose);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto transpose_conv = generateTransposeConv();
+    auto untrainable = generateUntrainableOperation(transpose_conv);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto unpack = generateUnpack();
+    auto untrainable = generateUntrainableOperation(unpack);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+
+  {
+    const auto while_op = generateWhile();
+    auto untrainable = generateUntrainableOperation(while_op);
+    EXPECT_ANY_THROW(visitor.invoke(*untrainable));
+  }
+}
index 6260d29..bcded0c 100644 (file)
 
 #include "util/logging.h"
 
+namespace
+{
+
+using namespace onert::ir;
+
+std::set<train::TrainingOperationIndex>
+extractOperations(const train::UseDefChains &training_usedefs)
+{
+  // Extract TrainingOperations from training_usedefs
+  std::set<train::TrainingOperationIndex> operations;
+  for (const auto &pair : training_usedefs)
+  {
+    const auto &output = pair.first;
+    const auto &usedefs = pair.second;
+    const auto &defs = usedefs.getTrainingDefs();
+    for (const auto &node_index : defs)
+      if (node_index.valid() && output.valid())
+        operations.insert(node_index);
+  }
+
+  return operations;
+}
+
+std::unordered_map<train::TrainingOperationIndex, std::vector<train::TrainingOperandIndex>>
+extractNodeInputs(const train::UseDefChains &training_usedefs)
+{
+  // Extract inputs of TrainingOperations from training_usedefs
+  std::unordered_map<train::TrainingOperationIndex, std::vector<train::TrainingOperandIndex>>
+    node_inputs;
+  for (const auto &pair : training_usedefs)
+  {
+    const auto &input = pair.first;
+    const auto &usedefs = pair.second;
+    const auto &uses = usedefs.getTrainingUses();
+    for (const auto &node_index : uses)
+      if (node_index.valid() && input.valid())
+        node_inputs[node_index].emplace_back(input);
+  }
+
+  return node_inputs;
+}
+
+std::unordered_map<train::TrainingOperationIndex, std::vector<train::TrainingOperandIndex>>
+extractNodeOutputs(const train::UseDefChains &training_usedefs)
+{
+  // Extract outputs of TrainingOperations from training_usedefs
+  std::unordered_map<train::TrainingOperationIndex, std::vector<train::TrainingOperandIndex>>
+    node_outputs;
+  for (const auto &pair : training_usedefs)
+  {
+    const auto &output = pair.first;
+    const auto &usedefs = pair.second;
+    const auto &defs = usedefs.getTrainingDefs();
+    for (const auto &node_index : defs)
+      if (node_index.valid() && output.valid())
+        node_outputs[node_index].emplace_back(output);
+  }
+
+  return node_outputs;
+}
+
+} // namespace
+
 namespace onert
 {
 namespace ir
@@ -68,6 +131,46 @@ bool DAGChecker::verify(const Graph &graph) const noexcept
   return !cyclic;
 }
 
+// TODO Merge with the above DAGChecker::verify(const Graph &)
+bool DAGChecker::verify(const train::UseDefChains &training_usedefs) const noexcept
+{
+  bool cyclic = false;
+  const auto operations = extractOperations(training_usedefs);
+  auto outputs_map = extractNodeOutputs(training_usedefs);
+
+  std::unordered_map<train::TrainingOperationIndex, bool> visited;
+  for (const auto &node_index : operations)
+    visited[node_index] = false;
+  auto on_stack = visited; // Copy from visited
+
+  std::function<void(const train::TrainingOperationIndex &index)> dfs_recursive =
+    [&](const train::TrainingOperationIndex &index) -> void {
+    if (on_stack[index])
+      cyclic = true;
+    if (visited[index])
+      return;
+    visited[index] = true;
+    on_stack[index] = true;
+
+    auto &node_outputs = outputs_map[index];
+    for (const auto &output : node_outputs)
+    {
+      const auto &uses = training_usedefs.at(output).getTrainingUses();
+      for (const auto &use : uses)
+      {
+        dfs_recursive(use);
+      }
+    }
+
+    on_stack[index] = false;
+  };
+
+  for (const auto &node_index : operations)
+    dfs_recursive(node_index);
+
+  return !cyclic;
+}
+
 //
 // EdgeConsistencyVerifier
 //
@@ -139,6 +242,67 @@ bool InputOutputChecker::verify(const Graph &graph) const noexcept
   return true;
 }
 
+// TODO Merge with the above EdgeChecker::verify(const Graph &)
+bool EdgeChecker::verify(const train::UseDefChains &training_usedefs) const noexcept
+{
+  const auto operations = extractOperations(training_usedefs);
+  auto inputs_map = extractNodeInputs(training_usedefs);
+  auto outputs_map = extractNodeOutputs(training_usedefs);
+  uint32_t errors = 0;
+  for (const auto &index : operations)
+  {
+    const auto &node_inputs = inputs_map[index];
+    for (const auto &operand_index : node_inputs)
+    {
+      try
+      {
+        const auto &uses = training_usedefs.at(operand_index).getTrainingUses();
+        bool operand_has_use = (uses.find(index) != uses.end());
+        if (!operand_has_use)
+        {
+          VERBOSE(EdgeChecker) << "[ERROR] EDGE MISMATCH : Missing USE edge - Operand "
+                               << operand_index << " to Operation " << index << std::endl;
+          errors += 1;
+        }
+      }
+      catch (const std::out_of_range &e)
+      {
+        VERBOSE(EdgeChecker) << "[ERROR] OPEARAND NOT FOUND : Operation " << index
+                             << " has Operand " << operand_index
+                             << ", but the operand object is not present in the graph" << std::endl;
+        errors += 1;
+      }
+    }
+
+    const auto &node_outputs = outputs_map[index];
+    for (const auto &operand_index : node_outputs)
+    {
+      try
+      {
+        const auto &defs = training_usedefs.at(operand_index).getTrainingDefs();
+        bool operand_has_def = (defs.find(index) != defs.end());
+        if (!operand_has_def)
+        {
+          VERBOSE(EdgeChecker) << "[ERROR] EDGE MISMATCH : Missing DEF edge - Operand"
+                               << operand_index << " to Operation " << index << std::endl;
+          errors += 1;
+        }
+      }
+      catch (const std::out_of_range &e)
+      {
+        VERBOSE(EdgeChecker) << "[ERROR] OPEARAND NOT FOUND : Operation " << index
+                             << " has Operand " << operand_index
+                             << ", but the operand object is not present in the graph" << std::endl;
+        errors += 1;
+      }
+    }
+  }
+
+  VERBOSE(EdgeChecker) << "Total Number of errors : " << errors << std::endl;
+
+  return errors == 0;
+}
+
 } // namespace verifier
 } // namespace ir
 } // namespace onert
index fa13119..9f1dd8e 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef __ONERT_GRAPH_VERIFIER_VERIFIER_H__
 #define __ONERT_GRAPH_VERIFIER_VERIFIER_H__
 
+#include "ir/train/UseDefChains.h"
+
 namespace onert
 {
 namespace ir
@@ -53,12 +55,14 @@ class DAGChecker : public IVerifier
 {
 public:
   bool verify(const Graph &graph) const noexcept override;
+  bool verify(const train::UseDefChains &training_defuses) const noexcept;
 };
 
 class EdgeChecker : public IVerifier
 {
 public:
   bool verify(const Graph &graph) const noexcept override;
+  bool verify(const train::UseDefChains &training_defuses) const noexcept;
 };
 
 /**
diff --git a/runtime/onert/core/src/loader/BaseLoader.h b/runtime/onert/core/src/loader/BaseLoader.h
new file mode 100644 (file)
index 0000000..c3a50b0
--- /dev/null
@@ -0,0 +1,1794 @@
+/*
+ * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_LOADER_BASE_LOADER_H__
+#define __ONERT_LOADER_BASE_LOADER_H__
+
+#include "ir/Graph.h"
+#include "ir/Shape.h"
+#include "ir/Operations.Include.h"
+
+#include "flatbuffers/flexbuffers.h"
+
+#include <map>
+#include <memory>
+#include <fstream>
+#include <limits>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <util/logging.h>
+
+namespace onert
+{
+namespace loader
+{
+
+template <typename LoaderDomain> class BaseLoader
+{
+protected:
+  using Verifier = typename LoaderDomain::Verifier;
+  using ActivationFunctionType = typename LoaderDomain::ActivationFunctionType;
+  using Buffer = typename LoaderDomain::Buffer;
+  using BuiltinOperator = typename LoaderDomain::BuiltinOperator;
+  using CustomOptionsFormat = typename LoaderDomain::CustomOptionsFormat;
+  using Metadata = typename LoaderDomain::Metadata;
+  using Model = typename LoaderDomain::Model;
+  using Operator = typename LoaderDomain::Operator;
+  using Padding = typename LoaderDomain::Padding;
+  using Pool2DOptions = typename LoaderDomain::Pool2DOptions;
+  using SubGraph = typename LoaderDomain::SubGraph;
+  using Tensor = typename LoaderDomain::Tensor;
+  using TensorType = typename LoaderDomain::TensorType;
+  using DimensionType = typename LoaderDomain::DimensionType;
+  using SparseIndexVector = typename LoaderDomain::SparseIndexVector;
+
+protected:
+  bool isOptionalInputTensor(std::int32_t idx) { return idx == -1; }
+  virtual bool allowOptionalInputTensor(BuiltinOperator) = 0;
+
+public:
+  /**
+   * @brief Construct a new Loader object
+   *
+   * @param model reference to model
+   */
+  explicit BaseLoader(std::unique_ptr<ir::Model> &model)
+    : _base{nullptr}, _pagesize(getpagesize()), _fd(-1), _model(model), _domain_model{nullptr}
+  {
+    _use_mmaped_data = util::getConfigBool(util::config::USE_MMAPED_DATA);
+  }
+
+  /**
+   * @brief Load a model from file
+   *
+   * @param file_path
+   */
+  void loadFromFile(const std::string &file_path);
+  /**
+   * @brief Load a model from a buffer
+   *
+   * @param buffer buffer pointer
+   * @param size buffer size
+   */
+  void loadFromBuffer(uint8_t *buffer, size_t size);
+
+protected:
+  ~BaseLoader() = default;
+  void loadModel();
+
+  // Helper functions
+  ir::Activation convertActivation(ActivationFunctionType type);
+  ir::DataType tensorTypeToDataType(TensorType type);
+  ir::OperandIndex tensorIdxToOperandIdx(int32_t tensorIdx);
+  flexbuffers::Map getCustomOpAttrMap(const Operator *op);
+
+  // Create operands form tflite::Tensor
+  ir::OperandIndex loadOperand(const Tensor *tensor, ir::Graph &subg);
+  void loadQuantization(const Tensor *tensor, ir::TypeInfo &typeInfo);
+  void loadSparsity(const Tensor *tensor, ir::TypeInfo &typeInfo);
+  void loadOperationIO(const Operator *op, ir::OperandIndexSequence &inputs,
+                       ir::OperandIndexSequence &outputs);
+  // Create operations from Operator
+  void loadOperation(const Operator *op, ir::Graph &subg);
+  // Load Strides and Paddings from options to param
+  template <typename Param, typename OptionsType>
+  void loadStridesAndPaddings(Param &param, const OptionsType *options);
+  // Load Pool2D param
+  template <typename Param> void loadPool2DOptions(Param &param, const Pool2DOptions *options);
+  // Get BuiltinOperator
+  BuiltinOperator getBuiltinOperator(const Operator *op)
+  {
+    auto const builtin_opcode = _domain_model->operator_codes()->Get(op->opcode_index());
+    auto builtin_op = builtin_opcode->builtin_code();
+    if (builtin_op < BuiltinOperator::BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES)
+      builtin_op = static_cast<BuiltinOperator>(builtin_opcode->deprecated_builtin_code());
+
+    return builtin_op;
+  }
+
+private:
+  std::unique_ptr<ir::Data> loadMetadata(const uint32_t buffer_idx);
+  virtual std::unique_ptr<ir::Graph> loadSubgraph(const SubGraph *subg) = 0;
+  // Operations
+  template <typename OpIR, typename... Args>
+  const OpIR *loadOperationTo(const Operator *op, ir::Graph &subg, Args &&...args);
+
+  void loadAddV2(const Operator *op, ir::Graph &subg);
+  void loadArgMinMax(const Operator *op, ir::Graph &subg, bool is_argmax);
+  void loadBatchMatMul(const Operator *op, ir::Graph &subg);
+  void loadBinaryArithmetic(const Operator *op, ir::Graph &subg,
+                            ir::operation::BinaryArithmetic::ArithmeticType op_type);
+  void loadComparison(const Operator *op, ir::Graph &subg);
+  void loadConcatenation(const Operator *op, ir::Graph &subg);
+  void loadConv2D(const Operator *op, ir::Graph &subg);
+  void loadCustom(const Operator *op, ir::Graph &subg);
+  void loadDepthToSpace(const Operator *op, ir::Graph &subg);
+  void loadDepthwiseConv2D(const Operator *op, ir::Graph &subg);
+  void loadEinsum(const Operator *op, ir::Graph &subg);
+  void loadElementwiseActivation(const Operator *op, ir::Graph &subg,
+                                 ir::operation::ElementwiseActivation::Type op_type,
+                                 float alpha = 0.f, float beta = 0.f);
+  void loadElementwiseBinary(const Operator *op, ir::Graph &subg,
+                             ir::operation::ElementwiseBinary::ElementwiseBinaryType op_type);
+  void loadElementwiseUnary(const Operator *op, ir::Graph &subg,
+                            ir::operation::ElementwiseUnary::Type op_type);
+  void loadFC(const Operator *op, ir::Graph &subg);
+  void loadFusedBatchNorm(const Operator *op, ir::Graph &subg);
+  void loadGather(const Operator *op, ir::Graph &subg);
+  void loadIf(const Operator *op, ir::Graph &subg);
+  void loadLeakyRelu(const Operator *op, ir::Graph &subg);
+  void loadLogSoftmax(const Operator *op, ir::Graph &subg);
+  void loadDetectionPostProcess(const Operator *op, ir::Graph &subg);
+  void loadOneHot(const Operator *op, ir::Graph &subg);
+  void loadPack(const Operator *op, ir::Graph &subg);
+  void loadPool2D(const Operator *op, ir::Graph &subg, ir::operation::Pool2D::PoolType op_type);
+  void loadReduce(const Operator *op, ir::Graph &subg,
+                  ir::operation::Reduce::ReduceType reduce_type);
+  void loadReduceAll(const Operator *op, ir::Graph &subg);
+  void loadReshape(const Operator *op, ir::Graph &subg);
+  void loadResizeBilinear(const Operator *op, ir::Graph &subg);
+  void loadResizeNearestNeighbor(const Operator *op, ir::Graph &subg);
+  void loadSoftmax(const Operator *op, ir::Graph &subg);
+  void loadSpaceToDepth(const Operator *op, ir::Graph &subg);
+  void loadSplit(const Operator *op, ir::Graph &subg);
+  void loadSplitV(const Operator *op, ir::Graph &subg);
+  void loadSqueeze(const Operator *op, ir::Graph &subg);
+  void loadStridedSlice(const Operator *op, ir::Graph &subg);
+  void loadTransposeConv(const Operator *op, ir::Graph &subg);
+  void loadUnidirectionalSequenceLSTM(const Operator *op, ir::Graph &subg);
+  void loadUnpack(const Operator *op, ir::Graph &subg);
+  void loadWhile(const Operator *op, ir::Graph &subg);
+
+  void verifySubgraphIndex(int subg_index)
+  {
+    const auto num_subgraphs = _domain_model->subgraphs()->size();
+    if (subg_index < 0 || subg_index >= static_cast<int32_t>(num_subgraphs))
+      throw std::runtime_error{std::string{"Invalid subgraph index - "} +
+                               std::to_string(subg_index)};
+  }
+
+protected:
+  // Base address for mapped region for loading (if needed)
+  uint8_t *_base;
+  // Memory page size
+  int32_t _pagesize;
+  // loaded file description
+  int _fd;
+  // Reference to ir::model (to be loaded from _domain_model)
+  std::unique_ptr<ir::Model> &_model;
+  const Model *_domain_model;
+  // Maps Tensor indices to onert Operands.
+  std::vector<ir::OperandIndex> _tensor_to_operand;
+  std::unordered_map<ir::OperandIndex, std::string> _tensor_names;
+  // Verifier
+  std::unique_ptr<Verifier> _verifier;
+  // Boolean flag to use MMAPED_DATA
+  bool _use_mmaped_data = false;
+
+  std::unordered_map<uint32_t /* Buffer Index in circle file */, std::shared_ptr<ir::Data>>
+    _buf_to_data;
+};
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::BaseLoader::loadFromFile(const std::string &file_path)
+{
+  _fd = open(file_path.c_str(), O_RDONLY);
+  if (_fd < 0)
+  {
+    throw std::runtime_error("Failed to open file " + file_path);
+  }
+
+  struct stat file_stat;
+  if (fstat(_fd, &file_stat) != 0)
+  {
+    throw std::runtime_error("Fstat failed or file " + file_path + " is not a regular file");
+  }
+  int size = file_stat.st_size;
+
+  // Map model file into memory region
+  _base = static_cast<uint8_t *>(mmap(NULL, size, PROT_READ, MAP_PRIVATE, _fd, 0));
+  if (_base == MAP_FAILED)
+  {
+    close(_fd);
+    throw std::runtime_error("mmap failed - " + std::string(strerror(errno)));
+  }
+
+  _verifier = std::make_unique<Verifier>(reinterpret_cast<const std::uint8_t *>(_base), size);
+
+  loadModel();
+  munmap(_base, size);
+
+  close(_fd);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::BaseLoader::loadFromBuffer(uint8_t *buffer, size_t size)
+{
+  _base = buffer;
+  _verifier = std::make_unique<Verifier>(reinterpret_cast<const std::uint8_t *>(_base), size);
+  loadModel();
+}
+
+template <typename LoaderDomain>
+std::unique_ptr<ir::Data>
+BaseLoader<LoaderDomain>::BaseLoader::loadMetadata(const uint32_t buffer_idx)
+{
+  assert(_domain_model != nullptr);
+  const auto *data = _domain_model->buffers()->Get(buffer_idx)->data();
+  if (data == nullptr)
+    throw std::runtime_error("Metadata buffer is not found");
+
+  if (_fd == -1) // Model is from memory
+  {
+    return std::make_unique<ir::ExternalData>(data->data(), data->size());
+  }
+  else // Model is loaded(mmap'd) from a file
+  {
+    size_t data_size = data->size();
+    ptrdiff_t offset_start = data->data() - _base;
+    ptrdiff_t offset_end = offset_start + data_size;
+
+    ptrdiff_t page_start = (offset_start / _pagesize) * _pagesize;
+    size_t mapping_size = offset_end - page_start;
+
+    // Since metadata is not access often in inference/training time, always use mmaped-data
+    // Ref : https://github.com/Samsung/ONE/issues/3961#issuecomment-681750231
+    return std::make_unique<ir::MMapedData>(_fd, page_start, mapping_size, offset_start, data_size);
+  }
+}
+
+template <typename LoaderDomain>
+ir::Activation
+BaseLoader<LoaderDomain>::BaseLoader::convertActivation(const ActivationFunctionType type)
+{
+  switch (type)
+  {
+    case ActivationFunctionType::ActivationFunctionType_NONE:
+      return ir::Activation::NONE;
+    case ActivationFunctionType::ActivationFunctionType_RELU:
+      return ir::Activation::RELU;
+    case ActivationFunctionType::ActivationFunctionType_RELU_N1_TO_1:
+      return ir::Activation::RELU1;
+    case ActivationFunctionType::ActivationFunctionType_RELU6:
+      return ir::Activation::RELU6;
+    case ActivationFunctionType::ActivationFunctionType_TANH:
+      return ir::Activation::TANH;
+    default:
+      throw std::runtime_error(std::string("Unsupported or invalid activation type: ") +
+                               std::to_string(static_cast<int>(type)));
+  }
+}
+
+template <typename LoaderDomain>
+ir::DataType BaseLoader<LoaderDomain>::BaseLoader::tensorTypeToDataType(const TensorType type)
+{
+  switch (type)
+  {
+    case TensorType::TensorType_FLOAT32:
+      return ir::DataType::FLOAT32;
+    case TensorType::TensorType_FLOAT16:
+      return ir::DataType::FLOAT16;
+    case TensorType::TensorType_INT32:
+      return ir::DataType::INT32;
+    case TensorType::TensorType_UINT8:
+      return ir::DataType::QUANT_UINT8_ASYMM;
+    case TensorType::TensorType_INT64:
+      return ir::DataType::INT64;
+    // case TensorType::TensorType_STRING:
+    case TensorType::TensorType_BOOL:
+      return ir::DataType::BOOL8;
+    case TensorType::TensorType_INT16:
+      return ir::DataType::QUANT_INT16_ASYMM;
+    // case TensorType::TensorType_COMPLEX64
+    case TensorType::TensorType_INT8:
+      return ir::DataType::QUANT_INT8_ASYMM;
+    // case TensorType::TensorType_FLOAT64
+    case TensorType::TensorType_UINT32:
+      return ir::DataType::UINT32;
+    default:
+      throw std::runtime_error(
+        std::string("Unsupported tensor type: ").append(EnumNameTensorType(type)));
+  }
+}
+
+template <typename LoaderDomain>
+ir::OperandIndex BaseLoader<LoaderDomain>::BaseLoader::tensorIdxToOperandIdx(int32_t tensorIdx)
+{
+  return isOptionalInputTensor(tensorIdx) ? ir::OperandIndex() : _tensor_to_operand[tensorIdx];
+}
+
+template <typename LoaderDomain>
+flexbuffers::Map BaseLoader<LoaderDomain>::BaseLoader::getCustomOpAttrMap(const Operator *op)
+{
+  size_t custom_op_data_size = op->custom_options()->size();
+  auto custom_op_data = op->custom_options()->Data();
+  auto data_root = flexbuffers::GetRoot(custom_op_data, custom_op_data_size);
+  return data_root.AsMap();
+}
+
+/* Copy is copied from tensorflow lite */
+template <typename T> bool Copy(const T *data_ptr, std::vector<uint16_t> &arr)
+{
+  if (data_ptr->values() == nullptr)
+  {
+    return false;
+  }
+
+  int size = data_ptr->values()->size();
+  arr.reserve(size);
+  for (int i = 0; i < size; i++)
+  {
+    arr.emplace_back(static_cast<uint16_t>(data_ptr->values()->Get(i)));
+  }
+  return true;
+}
+
+template <typename LoaderDomain>
+ir::OperandIndex BaseLoader<LoaderDomain>::loadOperand(const Tensor *tensor, ir::Graph &subg)
+{
+  ir::Shape shape;
+  // Shape
+  const auto *tensor_shape = tensor->shape();
+  if (tensor_shape != nullptr)
+  {
+    for (const auto &dim : *tensor_shape)
+    {
+      shape.append(dim);
+    }
+  }
+
+  // Note for tensor->shape_signature()
+  // We don't handle shape signature
+  //    How we handle:
+  //       If shape_signature[k] == -1, we will use tensor->shape()[k] == 1
+  //       If app wants to change the input shape, call nnfw_apply_input_tensorinfo() can
+  //       be used.
+
+  // TypeInfo
+  ir::TypeInfo type_info(tensorTypeToDataType(tensor->type()));
+  loadQuantization(tensor, type_info);
+  loadSparsity(tensor, type_info);
+
+  // Create operand
+  const auto operand_index = subg.addOperand(shape, type_info);
+
+  // Constant tensors are indicated by non-empty data.
+  const auto *data = _domain_model->buffers()->Get(tensor->buffer())->data();
+  if (data != nullptr)
+  {
+    using std::ptrdiff_t;
+    std::shared_ptr<ir::Data> data_obj;
+
+    if (_fd == -1) // Model is from memory
+    {
+      data_obj = std::make_shared<ir::ExternalData>(data->data(), data->size());
+    }
+    else // Model is loaded(mmap'd) from a file
+    {
+      size_t data_size = data->size();
+      ptrdiff_t unaligned_offset_start = data->data() - _base;
+      ptrdiff_t offset_end = unaligned_offset_start + data_size;
+
+      // Calculated aligned offset from base address of mapped region
+      // munmap accepts memory address which is a multiple of the pagesize
+      ptrdiff_t aligned_offset_start = (unaligned_offset_start / _pagesize) * _pagesize;
+      size_t mmap_size = offset_end - aligned_offset_start;
+
+      uint32_t buf_idx = tensor->buffer();
+      auto buffer_found = _buf_to_data.find(buf_idx);
+
+      if (buffer_found != _buf_to_data.end())
+      {
+        // Another tensor points this buffer and its matching Data(either CachedData or MMapedData)
+        // was already created. Let's reuse the Data
+        data_obj = buffer_found->second;
+      }
+      else if (_use_mmaped_data)
+      {
+        data_obj = std::make_shared<ir::MMapedData>(_fd, aligned_offset_start, mmap_size,
+                                                    unaligned_offset_start, data_size);
+        _buf_to_data[buf_idx] = data_obj;
+      }
+      else
+      {
+        size_t offset = unaligned_offset_start - aligned_offset_start;
+        uint8_t *mmap_base = static_cast<uint8_t *>(
+          mmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE, _fd, aligned_offset_start));
+
+        data_obj = std::make_shared<ir::CachedData>(mmap_base + offset, data_size);
+        _buf_to_data[buf_idx] = data_obj;
+
+        munmap(mmap_base, mmap_size);
+      }
+    }
+    subg.setOperandValue(operand_index, std::move(data_obj));
+  }
+
+  _tensor_names.emplace(operand_index, tensor->name()->str());
+
+  // Variable
+  if (tensor->is_variable())
+  {
+    if (data != nullptr)
+      throw std::runtime_error("Variable tensor with buffer is not supported!");
+
+    subg.operands().at(operand_index).info().setAsVariable();
+  }
+
+  return operand_index;
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadQuantization(const Tensor *tensor, ir::TypeInfo &typeInfo)
+{
+  auto q_params = tensor->quantization();
+  if (q_params == nullptr || q_params->scale() == nullptr || q_params->scale()->size() == 0)
+  {
+    typeInfo.quantization(0., 0);
+    return;
+  }
+  if (q_params->zero_point() == nullptr)
+  {
+    throw std::runtime_error("Quantization params: scale is not null, but zero_point is null.");
+  }
+  const size_t num_scales = q_params->scale()->size();
+  if (num_scales != q_params->zero_point()->size())
+  {
+    throw std::runtime_error("Quantization params: scale size != zero_point size");
+  }
+  std::vector<float> scales;
+  std::vector<int32_t> zero_points;
+  scales.resize(num_scales);
+  zero_points.resize(num_scales);
+  for (size_t i = 0; i < num_scales; ++i)
+  {
+    scales[i] = q_params->scale()->Get(i);
+    // zero_point is defined as long (i64) in schema while TypeInfo's zero_point is int32_t.
+    // int64_t is used instead of long because long is 4 byte in most 32bit architecture.
+    int64_t zero_point = q_params->zero_point()->Get(i);
+    if (zero_point < std::numeric_limits<int32_t>::min() ||
+        zero_point > std::numeric_limits<int32_t>::max())
+      throw std::runtime_error("Zero_point is out of int32 range.");
+    zero_points[i] = static_cast<int32_t>(zero_point);
+  }
+  auto details = q_params->details_as_CustomQuantization();
+  if (details != nullptr)
+    throw std::runtime_error("Custom Quantization is not supported");
+  typeInfo.quantization(std::move(scales), std::move(zero_points));
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadSparsity(const Tensor *tensor, ir::TypeInfo &typeInfo)
+{
+  auto src_sparsity = tensor->sparsity();
+  if (src_sparsity != nullptr)
+  {
+    std::vector<uint16_t> w1_segments;
+    std::vector<uint16_t> w1_indices;
+    // check traversal_order
+    if (src_sparsity->traversal_order())
+    {
+      const int traversal_order_size = src_sparsity->traversal_order()->size();
+      for (int i = 0; i < traversal_order_size; ++i)
+      {
+        if (i != src_sparsity->traversal_order()->Get(i))
+          throw std::runtime_error("traversal_order [0, 1, ..., n-1] is only supported.");
+      }
+    }
+    // check block_map
+    int block_rank = 0;
+    if (src_sparsity->block_map())
+    {
+      block_rank = src_sparsity->block_map()->size();
+      for (int i = 0; i < block_rank; ++i)
+      {
+        if (i != src_sparsity->block_map()->Get(i))
+          throw std::runtime_error("block_map [0, 1, ..., n-1] is only supported.");
+      }
+    }
+    // load metadata
+    const auto dim_metadata_size = src_sparsity->dim_metadata()->size();
+    const auto dense_rank = tensor->shape() ? tensor->shape()->size() : 0;
+    if (dense_rank + block_rank != dim_metadata_size)
+      throw std::runtime_error("sparsity dim_metadata length is wrong.");
+    bool random_sparsity = dim_metadata_size == 2 && block_rank == 0;
+    bool block2D_sparsity = dim_metadata_size == 4 && block_rank == 2;
+    if (dim_metadata_size != !random_sparsity && !block2D_sparsity)
+      throw std::runtime_error(
+        "sparsity is supported only for 2D tensor with random or 16x1 block sparsity.");
+
+    const auto *src_metadata = src_sparsity->dim_metadata()->Get(0);
+    if (src_metadata->format() != DimensionType::DimensionType_DENSE)
+      throw std::runtime_error("sparse tensor dim[0] is not DENSE");
+    src_metadata = src_sparsity->dim_metadata()->Get(1);
+    if (src_metadata->format() != DimensionType::DimensionType_SPARSE_CSR)
+      throw std::runtime_error("sparse tensor dim[0] is not SPARSE_CSR");
+    auto ParseSparseIndexVector = [src_metadata, &w1_segments, &w1_indices]() {
+      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:
+          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;
+        case SparseIndexVector::SparseIndexVector_Uint8Vector:
+          status = Copy(src_metadata->array_segments_as_Uint8Vector(), w1_segments);
+          break;
+        default:
+          return false;
+      }
+      if (status != true)
+        return false;
+      switch (src_metadata->array_indices_type())
+      {
+        case SparseIndexVector::SparseIndexVector_Int32Vector:
+          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:
+          return Copy(src_metadata->array_indices_as_Uint8Vector(), w1_indices);
+        default:
+          break;
+      }
+      return false;
+    };
+    if (ParseSparseIndexVector() == false)
+      throw std::runtime_error("Error during parsing sparsity index information");
+    // Get block size
+    std::vector<int32_t> block_size;
+    for (int i = 0; i < block_rank; ++i)
+    {
+      auto block_metadata = src_sparsity->dim_metadata()->Get(dense_rank + i);
+      if (block_metadata->format() != DimensionType::DimensionType_DENSE)
+        throw std::runtime_error("block dimension must be DENSE.");
+      block_size.push_back(block_metadata->dense_size());
+    }
+    typeInfo.sparsity(std::make_shared<ir::Sparsity>(std::move(w1_segments), std::move(w1_indices),
+                                                     std::move(block_size)));
+  }
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadOperationIO(const Operator *op, ir::OperandIndexSequence &inputs,
+                                               ir::OperandIndexSequence &outputs)
+{
+  for (const std::int32_t idx : *op->inputs())
+  {
+    // Optional tensors are not supported yet except for FULLY_CONNECTED and BCQ_FULLY_CONNECTED
+    auto check_optional_input = [&]() {
+      auto builtin_code = getBuiltinOperator(op);
+      if (isOptionalInputTensor(idx) && !allowOptionalInputTensor(builtin_code))
+        throw std::runtime_error(
+          std::string("loader doesn't support optional input tensor yet for ")
+            .append(EnumNameBuiltinOperator(builtin_code)));
+    };
+    check_optional_input();
+    inputs.append(tensorIdxToOperandIdx(idx));
+  }
+
+  for (const std::int32_t idx : *op->outputs())
+  {
+    outputs.append(tensorIdxToOperandIdx(idx));
+  }
+}
+
+template <typename LoaderDomain>
+template <typename Param, typename OptionsType>
+void BaseLoader<LoaderDomain>::loadStridesAndPaddings(Param &param, const OptionsType *options)
+{
+  // Strides
+  param.stride.vertical = options->stride_h();
+  param.stride.horizontal = options->stride_w();
+  // Paddings
+  switch (options->padding())
+  {
+    case Padding::Padding_SAME:
+      param.padding.type = ir::PaddingType::SAME;
+      break;
+    case Padding::Padding_VALID:
+      param.padding.type = ir::PaddingType::VALID;
+      break;
+    default:
+      throw std::runtime_error{"Invalid padding type"};
+  }
+  // param paddings indexes unused
+}
+
+template <typename LoaderDomain>
+template <typename Param>
+void BaseLoader<LoaderDomain>::loadPool2DOptions(Param &param, const Pool2DOptions *options)
+{
+  // Strides and Paddings
+  if (options->stride_h() <= 0 || options->stride_w() <= 0)
+    throw std::runtime_error{"Invalid stride vertical or horizontal - both must be bigger than 0"};
+  loadStridesAndPaddings(param, options);
+  // Filter width and height
+  // Strides
+  if (options->filter_width() <= 0 || options->filter_height() <= 0)
+    throw std::runtime_error{"Invalid filter width or height - both must be bigger than 0"};
+  param.kw = options->filter_width();
+  param.kh = options->filter_height();
+  // Activation
+  param.activation = convertActivation(options->fused_activation_function());
+}
+
+template <typename LoaderDomain>
+template <typename OpIR, typename... Args>
+const OpIR *BaseLoader<LoaderDomain>::loadOperationTo(const Operator *op, ir::Graph &subg,
+                                                      Args &&...args)
+{
+  static_assert(sizeof...(args) <= 1, "You can't have more than 1 arguments!");
+  ir::OperandIndexSequence inputs;
+  ir::OperandIndexSequence outputs;
+
+  loadOperationIO(op, inputs, outputs);
+
+  std::unique_ptr<OpIR> new_op(new OpIR(inputs, outputs, std::forward<Args>(args)...));
+  auto ret = new_op.get();
+  subg.addOperation(std::move(new_op));
+
+  return ret;
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadConv2D(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Conv2D::Param param;
+  const auto *options = op->builtin_options_as_Conv2DOptions();
+  param.activation = convertActivation(options->fused_activation_function());
+  loadStridesAndPaddings(param, options);
+  param.dilation.width_factor = options->dilation_w_factor();
+  param.dilation.height_factor = options->dilation_h_factor();
+
+  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>
+void BaseLoader<LoaderDomain>::loadDepthwiseConv2D(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::DepthwiseConv2D::Param param;
+  const auto *options = op->builtin_options_as_DepthwiseConv2DOptions();
+  param.activation = convertActivation(options->fused_activation_function());
+  loadStridesAndPaddings(param, options);
+  param.multiplier = options->depth_multiplier();
+  // Dilation h/w factor unused
+  param.dilation.width_factor = options->dilation_w_factor();
+  param.dilation.height_factor = options->dilation_h_factor();
+
+  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>
+void BaseLoader<LoaderDomain>::loadTransposeConv(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::TransposeConv::Param param;
+  const auto *options = op->builtin_options_as_TransposeConvOptions();
+  loadStridesAndPaddings(param, options);
+
+  loadOperationTo<ir::operation::TransposeConv>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadPool2D(const Operator *op, ir::Graph &subg,
+                                          ir::operation::Pool2D::PoolType op_type)
+{
+  ir::operation::Pool2D::Param param;
+  param.op_type = op_type;
+  const auto *options = op->builtin_options_as_Pool2DOptions();
+
+  loadPool2DOptions(param, options);
+
+  loadOperationTo<ir::operation::Pool2D>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadReshape(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Reshape::Param param{};
+  const auto *options = op->builtin_options_as_ReshapeOptions();
+  if (options != nullptr)
+  {
+    const auto *new_shape = options->new_shape();
+    if (new_shape)
+    {
+      for (uint i = 0; i < new_shape->size(); ++i)
+      {
+        param.new_shape.push_back(new_shape->Get(i));
+      }
+    }
+  }
+
+  loadOperationTo<ir::operation::Reshape>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadSoftmax(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Softmax::Param param;
+  const auto *options = op->builtin_options_as_SoftmaxOptions();
+  // Beta
+  param.beta = options->beta();
+
+  loadOperationTo<ir::operation::Softmax>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadConcatenation(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Concat::Param param;
+  const auto *options = op->builtin_options_as_ConcatenationOptions();
+  // Axis
+  param.axis = options->axis();
+  // activation unused
+
+  loadOperationTo<ir::operation::Concat>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadFC(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::FullyConnected::Param param;
+  const auto *options = op->builtin_options_as_FullyConnectedOptions();
+
+  param.activation = convertActivation(options->fused_activation_function());
+  param.weights_format = static_cast<ir::FullyConnectedWeightsFormat>(options->weights_format());
+
+  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 =
+    subg.operands().at(fc->getInputs().at(ir::operation::FullyConnected::WEIGHT));
+  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>
+void BaseLoader<LoaderDomain>::loadAddV2(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::BinaryArithmetic::Param param;
+  param.arithmetic_type = ir::operation::BinaryArithmetic::ArithmeticType::ADD;
+
+  if (op->custom_options() == nullptr)
+  {
+    param.activation = ir::Activation::NONE;
+  }
+  else
+  {
+    const auto attr_map = getCustomOpAttrMap(op);
+    const auto fused_activation_func = static_cast<typename LoaderDomain::ActivationFunctionType>(
+      attr_map["fused_activation_function"].AsInt8());
+    param.activation = convertActivation(fused_activation_func);
+  }
+
+  loadOperationTo<ir::operation::BinaryArithmetic>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadDepthToSpace(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::DepthToSpace::Param param;
+  const auto *options = op->builtin_options_as_DepthToSpaceOptions();
+  param.block_size = options->block_size();
+
+  loadOperationTo<ir::operation::DepthToSpace>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadBinaryArithmetic(
+  const Operator *op, ir::Graph &subg, ir::operation::BinaryArithmetic::ArithmeticType op_type)
+{
+  ir::operation::BinaryArithmetic::Param param;
+  param.arithmetic_type = op_type;
+  switch (op_type)
+  {
+    case ir::operation::BinaryArithmetic::ArithmeticType::ADD:
+    {
+      const auto *add_options = op->builtin_options_as_AddOptions();
+      param.activation = convertActivation(add_options->fused_activation_function());
+      break;
+    }
+    case ir::operation::BinaryArithmetic::ArithmeticType::SUB:
+    {
+      const auto *sub_options = op->builtin_options_as_SubOptions();
+      param.activation = convertActivation(sub_options->fused_activation_function());
+      break;
+    }
+    case ir::operation::BinaryArithmetic::ArithmeticType::MUL:
+    {
+      const auto *mul_options = op->builtin_options_as_MulOptions();
+      param.activation = convertActivation(mul_options->fused_activation_function());
+      break;
+    }
+    case ir::operation::BinaryArithmetic::ArithmeticType::DIV:
+    {
+      const auto *div_options = op->builtin_options_as_DivOptions();
+      param.activation = convertActivation(div_options->fused_activation_function());
+      break;
+    }
+    default:
+      assert(false &&
+             "The function 'loadBinaryArithmetic' supports only BinaryArithmetic operations");
+      break;
+  }
+
+  loadOperationTo<ir::operation::BinaryArithmetic>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadPack(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Pack::Param param;
+  const auto *options = op->builtin_options_as_PackOptions();
+  param.num = options->values_count();
+  param.axis = options->axis();
+
+  loadOperationTo<ir::operation::Pack>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadElementwiseActivation(
+  const Operator *op, ir::Graph &subg, ir::operation::ElementwiseActivation::Type op_type,
+  float alpha, float beta)
+{
+  ir::operation::ElementwiseActivation::Param param;
+  param.op_type = op_type;
+  param.alpha = alpha;
+  param.beta = beta;
+
+  loadOperationTo<ir::operation::ElementwiseActivation>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadResizeBilinear(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::ResizeBilinear::Param param;
+  // heigh_out and width_out is used on NNAPI only
+  assert(op->inputs()->size() == 2);
+  param.height_out = 0;
+  param.width_out = 0;
+  param.align_corners = op->builtin_options_as_ResizeBilinearOptions()->align_corners();
+  param.half_pixel_centers = op->builtin_options_as_ResizeBilinearOptions()->half_pixel_centers();
+
+  loadOperationTo<ir::operation::ResizeBilinear>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadResizeNearestNeighbor(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::ResizeNearestNeighbor::Param param;
+  // heigh_out and width_out is used on NNAPI only
+  assert(op->inputs()->size() == 2);
+  param.height_out = 0;
+  param.width_out = 0;
+  param.align_corners = op->builtin_options_as_ResizeNearestNeighborOptions()->align_corners();
+
+  loadOperationTo<ir::operation::ResizeNearestNeighbor>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadReduce(const Operator *op, ir::Graph &subg,
+                                          ir::operation::Reduce::ReduceType reduce_type)
+{
+  ir::operation::Reduce::Param param;
+  param.reduce_type = reduce_type;
+  param.keep_dims = op->builtin_options_as_ReducerOptions()->keep_dims();
+
+  loadOperationTo<ir::operation::Reduce>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadReduceAll(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Reduce::Param param;
+  param.reduce_type = ir::operation::Reduce::ReduceType::ALL;
+  if (op->custom_options() == nullptr)
+  {
+    param.keep_dims = false;
+  }
+  else
+  {
+    const auto attr_map = getCustomOpAttrMap(op);
+    param.keep_dims = attr_map["keep_dims"].AsBool();
+  }
+
+  loadOperationTo<ir::operation::Reduce>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadElementwiseBinary(
+  const Operator *op, ir::Graph &subg,
+  ir::operation::ElementwiseBinary::ElementwiseBinaryType op_type)
+{
+  ir::operation::ElementwiseBinary::Param param;
+  param.op_type = op_type;
+
+  loadOperationTo<ir::operation::ElementwiseBinary>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadElementwiseUnary(const Operator *op, ir::Graph &subg,
+                                                    ir::operation::ElementwiseUnary::Type op_type)
+{
+  ir::operation::ElementwiseUnary::Param param;
+  param.op_type = op_type;
+
+  const auto eu = loadOperationTo<ir::operation::ElementwiseUnary>(op, subg, param);
+  if (op_type == ir::operation::ElementwiseUnary::Type::CAST)
+  {
+    auto qasymm8ToUint8 = [](ir::Operand &operand) {
+      if (operand.typeInfo().type() == ir::DataType::QUANT_UINT8_ASYMM)
+      {
+        operand.type(ir::DataType::UINT8);
+      }
+    };
+    qasymm8ToUint8(
+      subg.operands().at(eu->getInputs().at(ir::operation::ElementwiseUnary::Input::INPUT)));
+    qasymm8ToUint8(subg.operands().at(eu->getOutputs().at(0)));
+  }
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadGather(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Gather::Param param;
+  param.axis = op->builtin_options_as_GatherOptions()->axis();
+
+  loadOperationTo<ir::operation::Gather>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadDetectionPostProcess(const Operator *op, ir::Graph &subg)
+{
+  const auto &m = getCustomOpAttrMap(op);
+
+  ir::operation::DetectionPostProcess::Param param;
+
+  param.max_detections = m["max_detections"].AsInt32();
+
+  // TODO fixme
+  param.max_classes_per_detection = m["max_classes_per_detection"].AsInt32();
+  if (m["detections_per_class"].IsNull())
+    param.max_boxes_per_class = 100;
+  else
+    param.max_boxes_per_class = m["detections_per_class"].AsInt32();
+
+  if (m["use_regular_nms"].IsNull())
+    param.do_fast_eval = true;
+  else
+    param.do_fast_eval = !m["use_regular_nms"].AsBool();
+
+  param.score_threshold = m["nms_score_threshold"].AsFloat();
+  param.iou_threshold = m["nms_iou_threshold"].AsFloat();
+
+  // TODO add num classes support
+  param.num_classes = m["num_classes"].AsInt32();
+
+  param.scale.y_scale = m["y_scale"].AsFloat();
+  param.scale.x_scale = m["x_scale"].AsFloat();
+  param.scale.h_scale = m["h_scale"].AsFloat();
+  param.scale.w_scale = m["w_scale"].AsFloat();
+
+  // TODO depends on input model framework
+  param.center_size_boxes = true;
+
+  loadOperationTo<ir::operation::DetectionPostProcess>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadBatchMatMul(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::BatchMatMul::Param param;
+
+  const auto builtin_op = getBuiltinOperator(op);
+
+  switch (builtin_op)
+  {
+    case BuiltinOperator::BuiltinOperator_BATCH_MATMUL:
+      // Handled on each loader: different option name
+      //  Circle: adjoint_lhs, adjoint_rhs
+      //  TFLite: adj_x, adj_y
+      throw std::runtime_error(
+        std::string("Cannot handle here: ").append(EnumNameBuiltinOperator(builtin_op)) + " as " +
+        EnumNameBuiltinOperator(BuiltinOperator::BuiltinOperator_BATCH_MATMUL));
+    case BuiltinOperator::BuiltinOperator_CUSTOM:
+      if (op->custom_options() == nullptr)
+      {
+        param.adj_x = false;
+        param.adj_y = false;
+      }
+      else
+      {
+        const auto attr_map = getCustomOpAttrMap(op);
+        param.adj_x = attr_map["adj_x"].AsBool();
+        param.adj_y = attr_map["adj_y"].AsBool();
+      }
+      break;
+    default:
+      throw std::runtime_error(
+        std::string("Wrong loaded operation: ").append(EnumNameBuiltinOperator(builtin_op)) +
+        " as " + EnumNameBuiltinOperator(BuiltinOperator::BuiltinOperator_BATCH_MATMUL));
+  }
+
+  loadOperationTo<ir::operation::BatchMatMul>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadSpaceToDepth(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::SpaceToDepth::Param param;
+  const auto *options = op->builtin_options_as_SpaceToDepthOptions();
+  param.block_size = options->block_size();
+
+  loadOperationTo<ir::operation::SpaceToDepth>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadCustom(const Operator *op, ir::Graph &subg)
+{
+  ir::OperandIndexSequence inputs;
+  ir::OperandIndexSequence outputs;
+
+  assert(op->custom_options_format() == CustomOptionsFormat::CustomOptionsFormat_FLEXBUFFERS &&
+         "Unsupported custom operation options format");
+
+  auto *op_code = _domain_model->operator_codes()->Get(op->opcode_index());
+  auto custom_op_name = op_code->custom_code()->str();
+
+  enum class BuiltinOP
+  {
+    AddV2,
+    ReduceAll,
+    MatrixBandPart,
+    BatchMatMul,
+    Einsum,
+    BroadcastTo,
+    FusedBatchNorm,
+    StatelessRandomUniform,
+    Erf,
+    DetectionPostProcess
+  };
+
+  // Mapping from custom op name string to BuiltinOP enum
+  std::map<std::string, BuiltinOP> builtin_map = {
+    {"AddV2", BuiltinOP::AddV2},
+    {"All", BuiltinOP::ReduceAll},
+    {"MatrixBandPart", BuiltinOP::MatrixBandPart},
+    {"BatchMatMulV2", BuiltinOP::BatchMatMul},
+    {"Einsum", BuiltinOP::Einsum},
+    {"FusedBatchNormV3", BuiltinOP::FusedBatchNorm},
+    {"BroadcastTo", BuiltinOP::BroadcastTo},
+    {"StatelessRandomUniform", BuiltinOP::StatelessRandomUniform},
+    {"Erf", BuiltinOP::Erf},
+    {"TFLite_Detection_PostProcess", BuiltinOP::DetectionPostProcess},
+  };
+
+  try
+  {
+    // Throw out_of_range if it is unknown custom op
+    auto custom_op_id = builtin_map.at(custom_op_name);
+    switch (custom_op_id)
+    {
+      case BuiltinOP::AddV2:
+        loadAddV2(op, subg);
+        break;
+      case BuiltinOP::ReduceAll:
+        loadReduceAll(op, subg);
+        break;
+      case BuiltinOP::MatrixBandPart:
+        loadOperationTo<ir::operation::MatrixBandPart>(op, subg);
+        break;
+      case BuiltinOP::BatchMatMul:
+        loadBatchMatMul(op, subg);
+        break;
+      case BuiltinOP::Einsum:
+        loadEinsum(op, subg);
+        break;
+      case BuiltinOP::BroadcastTo:
+        loadOperationTo<ir::operation::BroadcastTo>(op, subg);
+        break;
+      case BuiltinOP::FusedBatchNorm:
+        loadFusedBatchNorm(op, subg);
+        break;
+      case BuiltinOP::StatelessRandomUniform:
+        loadOperationTo<ir::operation::StatelessRandomUniform>(op, subg);
+        break;
+      case BuiltinOP::Erf:
+        loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::ERF);
+        break;
+      case BuiltinOP::DetectionPostProcess:
+        loadDetectionPostProcess(op, subg);
+        break;
+      default:
+        throw std::runtime_error{
+          "Loader: Custom OP map is defined but operation loader function is not defined"};
+    }
+
+    return;
+  }
+  catch (...)
+  {
+    loadOperationIO(op, inputs, outputs);
+
+    auto constraint = ir::OperandConstraint::createExact(inputs.size());
+
+    size_t custom_op_data_size = op->custom_options()->size();
+    auto custom_op_data = new char[custom_op_data_size];
+    std::copy(op->custom_options()->begin(), op->custom_options()->end(), custom_op_data);
+
+    ir::operation::Custom::Userdata userdata{};
+    userdata.data = custom_op_data;
+    userdata.size = custom_op_data_size;
+
+    auto new_op = std::make_unique<ir::operation::Custom>(constraint, inputs, outputs,
+                                                          custom_op_name, userdata);
+
+    subg.addOperation(std::move(new_op));
+  }
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadSqueeze(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Squeeze::Param param;
+  const auto *options = op->builtin_options_as_SqueezeOptions();
+  const auto *dims = options->squeeze_dims();
+  if (dims)
+  {
+    if (dims->size() > sizeof(param.dims) / sizeof(param.dims[0]))
+      throw std::runtime_error("Squeeze: 'param.ndims' is out of range.");
+    param.ndim = dims->size();
+    for (int i = 0; i < param.ndim; ++i)
+      param.dims[i] = dims->Get(i);
+  }
+  else
+    param.ndim = 0;
+
+  loadOperationTo<ir::operation::Squeeze>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadSplit(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Split::Param param;
+  const auto *options = op->builtin_options_as_SplitOptions();
+  param.num_splits = options->num_splits();
+
+  loadOperationTo<ir::operation::Split>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadSplitV(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::SplitV::Param param;
+  const auto *options = op->builtin_options_as_SplitVOptions();
+  param.num_splits = options->num_splits();
+
+  loadOperationTo<ir::operation::SplitV>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadStridedSlice(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::StridedSlice::Param param;
+  const auto *options = op->builtin_options_as_StridedSliceOptions();
+  param.begin_mask = options->begin_mask();
+  param.end_mask = options->end_mask();
+  param.shrink_axis_mask = options->shrink_axis_mask();
+
+  loadOperationTo<ir::operation::StridedSlice>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadUnpack(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Unpack::Param param;
+  const auto *options = op->builtin_options_as_UnpackOptions();
+  param.num = options->num();
+  param.axis = options->axis();
+
+  loadOperationTo<ir::operation::Unpack>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadComparison(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Comparison::Param param;
+  const auto builtin_op = getBuiltinOperator(op);
+
+  switch (builtin_op)
+  {
+    case BuiltinOperator::BuiltinOperator_EQUAL:
+      param.comparison_type = ir::operation::Comparison::ComparisonType::Equal;
+      break;
+    case BuiltinOperator::BuiltinOperator_NOT_EQUAL:
+      param.comparison_type = ir::operation::Comparison::ComparisonType::NotEqual;
+      break;
+    case BuiltinOperator::BuiltinOperator_GREATER_EQUAL:
+      param.comparison_type = ir::operation::Comparison::ComparisonType::GreaterEqual;
+      break;
+    case BuiltinOperator::BuiltinOperator_GREATER:
+      param.comparison_type = ir::operation::Comparison::ComparisonType::Greater;
+      break;
+    case BuiltinOperator::BuiltinOperator_LESS_EQUAL:
+      param.comparison_type = ir::operation::Comparison::ComparisonType::LessEqual;
+      break;
+    case BuiltinOperator::BuiltinOperator_LESS:
+      param.comparison_type = ir::operation::Comparison::ComparisonType::Less;
+      break;
+    default:
+      throw std::runtime_error(
+        std::string("Unsupported operation: ").append(EnumNameBuiltinOperator(builtin_op)));
+  }
+
+  loadOperationTo<ir::operation::Comparison>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadEinsum(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::Einsum::Param param;
+  if (op->custom_options() == nullptr)
+  {
+    throw std::runtime_error{"Einsum: empty equation"};
+  }
+  else
+  {
+    const auto attr_map = getCustomOpAttrMap(op);
+    param.equation = attr_map["equation"].ToString();
+  }
+
+  const auto es = loadOperationTo<ir::operation::Einsum>(op, subg, param);
+  if (es->getInputs().size() != 2)
+  {
+    throw std::runtime_error{"Einsum: NYI input - only support two inputs"};
+  }
+}
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadFusedBatchNorm(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::FusedBatchNorm::Param param;
+  if (op->custom_options() == nullptr)
+  {
+    throw std::runtime_error{"FusedBatchNorm: empty option"};
+  }
+  else
+  {
+    const auto attr_map = getCustomOpAttrMap(op);
+    param.is_training = attr_map["is_training"].AsBool();
+    param.epsilon = attr_map["epsilon"].AsFloat();
+    param.data_format = attr_map["data_format"].ToString();
+  }
+
+  const auto fbn = loadOperationTo<ir::operation::FusedBatchNorm>(op, subg, param);
+
+  if (fbn->getInputs().size() != 5)
+  {
+    throw std::runtime_error{"FusedBatchNorm: NYI input - only support five inputs"};
+  }
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadOneHot(const Operator *op, ir::Graph &subg)
+{
+  if (op->inputs()->size() != 4 || op->outputs()->size() != 1)
+    throw std::runtime_error("OneHot Op has wrong number of input or output tensors.");
+
+  // Set parameter
+  ir::operation::OneHot::Param param;
+  param.axis = op->builtin_options_as_OneHotOptions()->axis();
+
+  loadOperationTo<ir::operation::OneHot>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadIf(const Operator *op, ir::Graph &subg)
+{
+  const auto *options = op->builtin_options_as_IfOptions();
+  const int32_t then_index = options->then_subgraph_index();
+  const int32_t else_index = options->else_subgraph_index();
+
+  verifySubgraphIndex(then_index);
+  verifySubgraphIndex(else_index);
+
+  ir::operation::If::Param param;
+  param.then_subg_index = ir::SubgraphIndex{static_cast<uint16_t>(then_index)};
+  param.else_subg_index = ir::SubgraphIndex{static_cast<uint16_t>(else_index)};
+
+  loadOperationTo<ir::operation::If>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadWhile(const Operator *op, ir::Graph &subg)
+{
+  const auto *options = op->builtin_options_as_WhileOptions();
+  const int32_t cond_index = options->cond_subgraph_index();
+  const int32_t body_index = options->body_subgraph_index();
+
+  verifySubgraphIndex(cond_index);
+  verifySubgraphIndex(body_index);
+
+  ir::operation::While::Param param;
+  param.cond_subg_index = ir::SubgraphIndex{static_cast<uint16_t>(cond_index)};
+  param.body_subg_index = ir::SubgraphIndex{static_cast<uint16_t>(body_index)};
+
+  loadOperationTo<ir::operation::While>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadArgMinMax(const Operator *op, ir::Graph &subg, bool is_argmax)
+{
+  ir::operation::ArgMinMax::Param param;
+  const auto output_type = is_argmax ? op->builtin_options_as_ArgMaxOptions()->output_type()
+                                     : op->builtin_options_as_ArgMinOptions()->output_type();
+  param.output_type = tensorTypeToDataType(output_type);
+  param.is_arg_max = is_argmax;
+
+  loadOperationTo<ir::operation::ArgMinMax>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadLogSoftmax(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::LogSoftmax::Param param;
+  // In tflite, beta is fixed to 1.0 and axis is fixed to -1.
+  param.beta = 1.0f;
+  param.axis = -1;
+
+  loadOperationTo<ir::operation::LogSoftmax>(op, subg, param);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadLeakyRelu(const Operator *op, ir::Graph &subg)
+{
+  float alpha = op->builtin_options_as_LeakyReluOptions()->alpha();
+  loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::LEAKY_RELU, alpha,
+                            1.f);
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadUnidirectionalSequenceLSTM(const Operator *op, ir::Graph &subg)
+{
+  ir::operation::LSTM::Param param;
+  const auto *options = op->builtin_options_as_UnidirectionalSequenceLSTMOptions();
+  param.activation = convertActivation(options->fused_activation_function());
+  param.cell_threshold = options->cell_clip();
+  param.projection_threshold = options->proj_clip();
+  param.time_major = options->time_major();
+  // The asymmetric_quantize_inputs option is unused yet
+
+  ir::OperandIndexSequence inputs;
+  for (const std::int32_t idx : *op->inputs())
+  {
+    inputs.append(tensorIdxToOperandIdx(idx));
+  }
+
+  ir::OperandIndexSequence outputs;
+  // loader doesn't support optional output tensor yet
+  if (op->outputs()->size() != 1)
+  {
+    auto builtin_code = getBuiltinOperator(op);
+    throw std::runtime_error(std::string("loader doesn't support optional output tensor yet for ")
+                               .append(EnumNameBuiltinOperator(builtin_code)));
+  }
+  for (size_t i = 0; i < ir::operation::LSTM::Output::OUTPUT; ++i)
+  {
+    // Add optional outputs
+    outputs.append(ir::OperandIndex());
+  }
+  outputs.append(tensorIdxToOperandIdx(op->outputs()->Get(0)));
+
+  std::unique_ptr<ir::operation::LSTM> new_op(new ir::operation::LSTM(inputs, outputs, param));
+  subg.addOperation(std::move(new_op));
+}
+
+template <typename LoaderDomain>
+void BaseLoader<LoaderDomain>::loadOperation(const Operator *op, ir::Graph &subg)
+{
+  auto const builtin_op = getBuiltinOperator(op);
+
+  switch (builtin_op)
+  {
+    case BuiltinOperator::BuiltinOperator_ADD_N:
+      loadOperationTo<ir::operation::AddN>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_CONV_2D:
+      loadConv2D(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_AVERAGE_POOL_2D:
+      loadPool2D(op, subg, ir::operation::Pool2D::PoolType::AVG);
+      return;
+    case BuiltinOperator::BuiltinOperator_DEPTHWISE_CONV_2D:
+      loadDepthwiseConv2D(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_TRANSPOSE_CONV:
+      loadTransposeConv(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_RESHAPE:
+      loadReshape(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_SOFTMAX:
+      loadSoftmax(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_MAX_POOL_2D:
+      loadPool2D(op, subg, ir::operation::Pool2D::PoolType::MAX);
+      return;
+    case BuiltinOperator::BuiltinOperator_CONCATENATION:
+      loadConcatenation(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_FLOOR:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::FLOOR);
+      return;
+    case BuiltinOperator::BuiltinOperator_FULLY_CONNECTED:
+      loadFC(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_ADD:
+      loadBinaryArithmetic(op, subg, ir::operation::BinaryArithmetic::ArithmeticType::ADD);
+      return;
+    case BuiltinOperator::BuiltinOperator_SUB:
+      loadBinaryArithmetic(op, subg, ir::operation::BinaryArithmetic::ArithmeticType::SUB);
+      return;
+    case BuiltinOperator::BuiltinOperator_MUL:
+      loadBinaryArithmetic(op, subg, ir::operation::BinaryArithmetic::ArithmeticType::MUL);
+      return;
+    case BuiltinOperator::BuiltinOperator_DIV:
+      loadBinaryArithmetic(op, subg, ir::operation::BinaryArithmetic::ArithmeticType::DIV);
+      return;
+    case BuiltinOperator::BuiltinOperator_PACK:
+      loadPack(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_ELU:
+      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::ELU);
+      return;
+    case BuiltinOperator::BuiltinOperator_RELU:
+      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::RELU,
+                                ir::operation::ElementwiseActivation::infinity, 0.f);
+      return;
+    case BuiltinOperator::BuiltinOperator_RELU_N1_TO_1:
+      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::RELU, 1.f,
+                                -1.f);
+      return;
+    case BuiltinOperator::BuiltinOperator_RELU6:
+      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::RELU, 6.f,
+                                0.f);
+      return;
+    case BuiltinOperator::BuiltinOperator_RESIZE_BILINEAR:
+      loadResizeBilinear(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR:
+      loadResizeNearestNeighbor(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_RSQRT:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::RSQRT);
+      return;
+    case BuiltinOperator::BuiltinOperator_SELECT:
+    case BuiltinOperator::BuiltinOperator_SELECT_V2:
+      loadOperationTo<ir::operation::Select>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_SQRT:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::SQRT);
+      return;
+    case BuiltinOperator::BuiltinOperator_SQUARE:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::SQUARE);
+      return;
+    case BuiltinOperator::BuiltinOperator_SQUARED_DIFFERENCE:
+      loadOperationTo<ir::operation::SquaredDifference>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_TANH:
+      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::TANH, 1.f,
+                                1.f);
+      return;
+    case BuiltinOperator::BuiltinOperator_TRANSPOSE:
+      loadOperationTo<ir::operation::Transpose>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_MEAN:
+      loadReduce(op, subg, ir::operation::Reduce::ReduceType::MEAN);
+      return;
+    case BuiltinOperator::BuiltinOperator_REDUCE_ANY:
+      loadReduce(op, subg, ir::operation::Reduce::ReduceType::ANY);
+      return;
+    case BuiltinOperator::BuiltinOperator_REDUCE_MAX:
+      loadReduce(op, subg, ir::operation::Reduce::ReduceType::MAX);
+      return;
+    case BuiltinOperator::BuiltinOperator_REVERSE_V2:
+      loadOperationTo<ir::operation::Reverse>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_PAD:
+    case BuiltinOperator::BuiltinOperator_PADV2:
+      loadOperationTo<ir::operation::Pad>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_LOGISTIC:
+      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::LOGISTIC);
+      return;
+    case BuiltinOperator::BuiltinOperator_EXP:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::EXP);
+      return;
+    case BuiltinOperator::BuiltinOperator_EXPAND_DIMS:
+      loadOperationTo<ir::operation::ExpandDims>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_GATHER:
+      loadGather(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_SPACE_TO_BATCH_ND:
+      loadOperationTo<ir::operation::SpaceToBatchND>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_BATCH_TO_SPACE_ND:
+      loadOperationTo<ir::operation::BatchToSpaceND>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_SUM:
+      loadReduce(op, subg, ir::operation::Reduce::ReduceType::SUM);
+      return;
+    case BuiltinOperator::BuiltinOperator_CUSTOM:
+      loadCustom(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_SQUEEZE:
+      loadSqueeze(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_PRELU:
+      loadOperationTo<ir::operation::PReLU>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_SPLIT:
+      loadSplit(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_SPLIT_V:
+      loadSplitV(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_SLICE:
+      loadOperationTo<ir::operation::Slice>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_STRIDED_SLICE:
+      loadStridedSlice(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_UNPACK:
+      loadUnpack(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_FLOOR_DIV:
+      loadElementwiseBinary(op, subg,
+                            ir::operation::ElementwiseBinary::ElementwiseBinaryType::FLOOR_DIV);
+      return;
+    case BuiltinOperator::BuiltinOperator_FLOOR_MOD:
+      loadElementwiseBinary(op, subg,
+                            ir::operation::ElementwiseBinary::ElementwiseBinaryType::FLOOR_MOD);
+      return;
+    case BuiltinOperator::BuiltinOperator_MINIMUM:
+      loadElementwiseBinary(op, subg, ir::operation::ElementwiseBinary::ElementwiseBinaryType::MIN);
+      return;
+    case BuiltinOperator::BuiltinOperator_MAXIMUM:
+      loadElementwiseBinary(op, subg, ir::operation::ElementwiseBinary::ElementwiseBinaryType::MAX);
+      return;
+    case BuiltinOperator::BuiltinOperator_CAST:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::CAST);
+      return;
+    case BuiltinOperator::BuiltinOperator_EQUAL:
+    case BuiltinOperator::BuiltinOperator_NOT_EQUAL:
+    case BuiltinOperator::BuiltinOperator_GREATER_EQUAL:
+    case BuiltinOperator::BuiltinOperator_GREATER:
+    case BuiltinOperator::BuiltinOperator_LESS_EQUAL:
+    case BuiltinOperator::BuiltinOperator_LESS:
+      loadComparison(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_ONE_HOT:
+      loadOneHot(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_ABS:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::ABS);
+      return;
+    case BuiltinOperator::BuiltinOperator_COS:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::COS);
+      return;
+    case BuiltinOperator::BuiltinOperator_SIN:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::SIN);
+      return;
+    case BuiltinOperator::BuiltinOperator_SHAPE:
+      loadOperationTo<ir::operation::Shape>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_REDUCE_PROD:
+      loadReduce(op, subg, ir::operation::Reduce::ReduceType::PROD);
+      return;
+    case BuiltinOperator::BuiltinOperator_IF:
+      loadIf(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_WHILE:
+      loadWhile(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_NEG:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::NEG);
+      return;
+    case BuiltinOperator::BuiltinOperator_ARG_MAX:
+      loadArgMinMax(op, subg, true);
+      return;
+    case BuiltinOperator::BuiltinOperator_ARG_MIN:
+      loadArgMinMax(op, subg, false);
+      return;
+    case BuiltinOperator::BuiltinOperator_LOG:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::LOG);
+      return;
+    case BuiltinOperator::BuiltinOperator_ROUND:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::ROUND);
+      return;
+    case BuiltinOperator::BuiltinOperator_POW:
+      loadOperationTo<ir::operation::Pow>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_LOGICAL_NOT:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::LOGICAL_NOT);
+      return;
+    case BuiltinOperator::BuiltinOperator_LOGICAL_AND:
+      loadElementwiseBinary(op, subg,
+                            ir::operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_AND);
+      return;
+    case BuiltinOperator::BuiltinOperator_LOGICAL_OR:
+      loadElementwiseBinary(op, subg,
+                            ir::operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_OR);
+      return;
+    case BuiltinOperator::BuiltinOperator_FILL:
+      loadOperationTo<ir::operation::Fill>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_ZEROS_LIKE:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::ZEROS_LIKE);
+      return;
+    case BuiltinOperator::BuiltinOperator_TILE:
+      loadOperationTo<ir::operation::Tile>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_RANGE:
+      loadOperationTo<ir::operation::Range>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_BATCH_MATMUL:
+      loadBatchMatMul(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_LOG_SOFTMAX:
+      loadLogSoftmax(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_QUANTIZE:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::QUANTIZE);
+      return;
+    case BuiltinOperator::BuiltinOperator_DEQUANTIZE:
+      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::DEQUANTIZE);
+      return;
+    case BuiltinOperator::BuiltinOperator_SPACE_TO_DEPTH:
+      loadSpaceToDepth(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_L2_NORMALIZATION:
+      loadOperationTo<ir::operation::L2Normalization>(op, subg);
+      break;
+    case BuiltinOperator::BuiltinOperator_LEAKY_RELU:
+      loadLeakyRelu(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_RANK:
+      loadOperationTo<ir::operation::Rank>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM:
+      loadUnidirectionalSequenceLSTM(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_DEPTH_TO_SPACE:
+      loadDepthToSpace(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_EMBEDDING_LOOKUP:
+      loadOperationTo<ir::operation::EmbeddingLookup>(op, subg);
+      return;
+    case BuiltinOperator::BuiltinOperator_HASHTABLE_LOOKUP:
+      loadOperationTo<ir::operation::HashtableLookup>(op, subg);
+      return;
+    default:
+      throw std::runtime_error(
+        std::string("Unsupported operation: ").append(EnumNameBuiltinOperator(builtin_op)));
+  }
+}
+
+template <typename LoaderDomain> void BaseLoader<LoaderDomain>::loadModel()
+{
+  LoaderDomain::VerifyModelBuffer(*_verifier.get());
+  _domain_model = LoaderDomain::GetModel(_base);
+
+  auto model = std::make_unique<ir::Model>();
+  // Version unused
+  // const auto version = _model->version();
+  // Description unused
+
+  // Load Metadata
+  auto const metadata_list = _domain_model->metadata();
+  if (metadata_list != nullptr)
+  {
+    for (uint32_t i = 0; i < metadata_list->size(); ++i)
+    {
+      const auto metadata = metadata_list->Get(i);
+      if (metadata->name() == nullptr)
+        continue; // metadata should have name
+
+      std::unique_ptr<const ir::Data> data = loadMetadata(metadata->buffer());
+      model->add_metadata(metadata->name()->str(), std::move(data));
+    }
+  }
+
+  // const auto *description = _model->description();
+  // Load subgraphs and map operations on subgraph
+  const auto subgraphs = _domain_model->subgraphs();
+  if (subgraphs->size() - 1 > ir::SubgraphIndex::max())
+    throw std::runtime_error{"The number of subgraphs cannot exceed " +
+                             std::to_string(ir::SubgraphIndex::max() + 1)};
+  for (uint16_t subgraph_index = 0; subgraph_index < subgraphs->size(); ++subgraph_index)
+  {
+    auto subg = loadSubgraph((*_domain_model->subgraphs())[subgraph_index]);
+    // NOTE: Used () instead of {}, which does not check narrowing.
+    // It is okay since overflow is checked the above if-statement.
+    model->push(ir::SubgraphIndex(subgraph_index), std::move(subg));
+  }
+  _model = std::move(model);
+}
+
+} // namespace loader
+} // namespace onert
+
+#endif //__ONERT_LOADER_BASE_LOADER_H__
diff --git a/runtime/onert/core/src/loader/CircleLoader.cc b/runtime/onert/core/src/loader/CircleLoader.cc
new file mode 100644 (file)
index 0000000..442a0f5
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "loader/CircleLoader.h"
+
+#include "BaseLoader.h"
+#include "circle_schema_generated.h"
+
+namespace onert
+{
+namespace loader
+{
+
+namespace
+{
+
+struct LoaderDomain
+{
+  using Verifier = flatbuffers::Verifier;
+  using ActivationFunctionType = circle::ActivationFunctionType;
+  using Buffer = circle::Buffer;
+  using BuiltinOperator = circle::BuiltinOperator;
+  using CustomOptionsFormat = circle::CustomOptionsFormat;
+  using Metadata = circle::Metadata;
+  using Model = circle::Model;
+  using Operator = circle::Operator;
+  using Padding = circle::Padding;
+  using Pool2DOptions = circle::Pool2DOptions;
+  using Tensor = circle::Tensor;
+  using TensorType = circle::TensorType;
+  using SubGraph = circle::SubGraph;
+  using DimensionType = circle::DimensionType;
+  using SparseIndexVector = circle::SparseIndexVector;
+
+  static const char *EnumNameBuiltinOperator(BuiltinOperator e)
+  {
+    return circle::EnumNameBuiltinOperator(e);
+  }
+  static const char *EnumNameActivationFunctionType(ActivationFunctionType e)
+  {
+    return circle::EnumNameActivationFunctionType(e);
+  }
+  static const char *EnumNameTensorType(TensorType e) { return circle::EnumNameTensorType(e); }
+  static const Model *GetModel(const void *buf) { return circle::GetModel(buf); }
+  static bool VerifyModelBuffer(Verifier &verifier) { return circle::VerifyModelBuffer(verifier); }
+};
+
+class CircleLoader final : public loader::BaseLoader<LoaderDomain>
+{
+protected:
+  // Different option name
+  //  Circle: adjoint_lhs, adjoint_rhs
+  //  TFLite: adj_x, adj_y
+  void loadBatchMatMul(const Operator *op, ir::Graph &subg);
+
+  // Only circle operations
+  void loadInstanceNorm(const Operator *op, ir::Graph &subg);
+  void loadBCQFullyConnected(const Operator *op, ir::Graph &subg);
+  void loadBCQGather(const Operator *op, ir::Graph &subg);
+
+public:
+  using BaseLoader::BaseLoader;
+
+  bool allowOptionalInputTensor(BuiltinOperator op) override
+  {
+    switch (op)
+    {
+      case BuiltinOperator::BuiltinOperator_FULLY_CONNECTED:
+      case BuiltinOperator::BuiltinOperator_BCQ_FULLY_CONNECTED:
+      case BuiltinOperator::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+private:
+  std::unique_ptr<ir::Graph> loadSubgraph(const circle::SubGraph *circle_subg) override
+  {
+    auto subg = std::make_unique<ir::Graph>();
+    // Load tensors
+    _tensor_to_operand.resize(circle_subg->tensors()->size());
+    for (flatbuffers::uoffset_t i = 0; i < circle_subg->tensors()->size(); ++i)
+    {
+      _tensor_to_operand[i] = loadOperand(circle_subg->tensors()->Get(i), *subg);
+      subg->operands().at(_tensor_to_operand[i]).setOriginIndex(ir::OriginIndex(i));
+    }
+    // Set inputs
+    for (const std::int32_t input_ind : *circle_subg->inputs())
+    {
+      subg->addInput(tensorIdxToOperandIdx(input_ind),
+                     _tensor_names.at(_tensor_to_operand[input_ind]));
+    }
+    // Set outputs
+    for (const std::int32_t output_ind : *circle_subg->outputs())
+    {
+      subg->addOutput(tensorIdxToOperandIdx(output_ind),
+                      _tensor_names.at(_tensor_to_operand[output_ind]));
+    }
+    // Create operations
+    for (const auto *op : *circle_subg->operators())
+    {
+      CircleLoader::loadOperation(op, *subg);
+    }
+
+    // TODO Remove frontend layout feature
+    subg->setLayout(ir::Layout::NHWC);
+
+    subg->verify();
+
+    return subg;
+  }
+
+  void loadOperation(const circle::Operator *op, ir::Graph &subg)
+  {
+    auto const builtin_op = getBuiltinOperator(op);
+
+    switch (builtin_op)
+    {
+      case circle::BuiltinOperator::BuiltinOperator_BATCH_MATMUL:
+        loadBatchMatMul(op, subg);
+        return;
+      case circle::BuiltinOperator::BuiltinOperator_INSTANCE_NORM:
+        loadInstanceNorm(op, subg);
+        return;
+      case circle::BuiltinOperator::BuiltinOperator_BCQ_FULLY_CONNECTED:
+        loadBCQFullyConnected(op, subg);
+        return;
+      case circle::BuiltinOperator::BuiltinOperator_BCQ_GATHER:
+        loadBCQGather(op, subg);
+        return;
+      default:
+        BaseLoader::loadOperation(op, subg);
+        return;
+    }
+  }
+};
+
+void CircleLoader::loadBatchMatMul(const Operator *op, ir::Graph &subg)
+{
+  ir::OperandIndexSequence inputs;
+  ir::OperandIndexSequence outputs;
+
+  loadOperationIO(op, inputs, outputs);
+
+  ir::operation::BatchMatMul::Param param;
+  const auto *options = op->builtin_options_as_BatchMatMulOptions();
+
+  param.adj_x = options->adjoint_lhs();
+  param.adj_y = options->adjoint_rhs();
+
+  std::unique_ptr<ir::Operation> new_op(new ir::operation::BatchMatMul(inputs, outputs, param));
+  subg.addOperation(std::move(new_op));
+}
+
+void CircleLoader::loadInstanceNorm(const Operator *op, ir::Graph &subg)
+{
+  ir::OperandIndexSequence inputs;
+  ir::OperandIndexSequence outputs;
+
+  loadOperationIO(op, inputs, outputs);
+
+  ir::operation::InstanceNorm::Param param;
+  const auto *options = op->builtin_options_as_InstanceNormOptions();
+
+  param.activation = convertActivation(options->fused_activation_function());
+  // Use default value 1e-5 if value of epsilon is zero
+  param.epsilon = options->epsilon() == 0.f ? 1e-5 : options->epsilon();
+
+  std::unique_ptr<ir::Operation> new_op(new ir::operation::InstanceNorm(inputs, outputs, param));
+  subg.addOperation(std::move(new_op));
+}
+
+void CircleLoader::loadBCQGather(const Operator *op, ir::Graph &subg)
+{
+  ir::OperandIndexSequence inputs;
+  ir::OperandIndexSequence outputs;
+
+  loadOperationIO(op, inputs, outputs);
+
+  ir::operation::BCQGather::Param param;
+  const auto *options = op->builtin_options_as_BCQGatherOptions();
+  param.input_hidden_size = options->input_hidden_size();
+  param.axis = options->axis();
+
+  std::unique_ptr<ir::Operation> new_op(new ir::operation::BCQGather(inputs, outputs, param));
+  subg.addOperation(std::move(new_op));
+}
+
+void CircleLoader::loadBCQFullyConnected(const Operator *op, ir::Graph &subg)
+{
+  ir::OperandIndexSequence inputs;
+  ir::OperandIndexSequence outputs;
+
+  loadOperationIO(op, inputs, outputs);
+
+  ir::operation::BCQFullyConnected::Param param;
+  const auto *options = op->builtin_options_as_BCQFullyConnectedOptions();
+  param.weights_hidden_size = options->weights_hidden_size();
+  param.activation = convertActivation(options->fused_activation_function());
+
+  std::unique_ptr<ir::Operation> new_op(
+    new ir::operation::BCQFullyConnected(inputs, outputs, param));
+  subg.addOperation(std::move(new_op));
+}
+
+} // namespace
+
+std::unique_ptr<ir::Model> loadCircleModel(const std::string &filename)
+{
+  auto model = std::make_unique<ir::Model>();
+  CircleLoader loader(model);
+  loader.loadFromFile(filename);
+  return model;
+}
+
+std::unique_ptr<ir::Model> loadCircleModel(uint8_t *buffer, size_t size)
+{
+  auto model = std::make_unique<ir::Model>();
+  CircleLoader loader(model);
+  loader.loadFromBuffer(buffer, size);
+  return model;
+}
+
+} // namespace loader
+} // namespace onert
diff --git a/runtime/onert/core/src/loader/ModelLoader.cc b/runtime/onert/core/src/loader/ModelLoader.cc
new file mode 100644 (file)
index 0000000..1f3b467
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "loader/ModelLoader.h"
+
+#include "loader/ILoader.h"
+
+#include <dlfcn.h>
+
+namespace onert
+{
+namespace loader
+{
+
+std::unique_ptr<ir::Model> loadModel(const std::string &filename, const std::string &type)
+{
+  // Custom loader library name should be lib<type>_loader.so
+  std::string libname = "lib" + type + "_loader.so";
+
+  // Open custom loader library
+  void *handle = dlopen(libname.c_str(), RTLD_LAZY);
+  if (!handle)
+    throw std::runtime_error("Failed to open " + type + " loader");
+
+  // Get custom loader create function
+  using create_func_t = ILoader *(*)();
+  auto create_fn = reinterpret_cast<create_func_t>(dlsym(handle, "onert_loader_create"));
+  if (!create_fn)
+  {
+    dlclose(handle);
+    throw std::runtime_error("Failed to find loader create function");
+  }
+
+  // Get custom loader destroy function
+  using destroy_func_t = void (*)(ILoader *);
+  auto destroy_fn = reinterpret_cast<destroy_func_t>(dlsym(handle, "onert_loader_destroy"));
+  if (!destroy_fn)
+  {
+    dlclose(handle);
+    throw std::runtime_error("Failed to find loader destroy function");
+  }
+
+  // Create custom loader
+  auto loader = create_fn();
+  if (!loader)
+  {
+    dlclose(handle);
+    throw std::runtime_error("Failed to find loader create function");
+  }
+
+  // Load model
+  auto model = loader->loadFromFile(filename);
+
+  // Destroy custom loader
+  destroy_fn(loader);
+
+  // Close custom loader library
+  //
+  // NOTE:
+  //  It assumes that custom loader will not be used frequently on runtime session.
+  //  If custom loader is used frequently, it should not close custom loader library and
+  //  save handler to reuse it.
+  dlclose(handle);
+
+  if (model)
+    return model;
+
+  throw std::runtime_error("Failed to load model " + filename);
+}
+
+} // namespace loader
+} // namespace onert
diff --git a/runtime/onert/core/src/loader/TFLiteLoader.cc b/runtime/onert/core/src/loader/TFLiteLoader.cc
new file mode 100644 (file)
index 0000000..745f390
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "loader/TFLiteLoader.h"
+
+#include "BaseLoader.h"
+#include "tflite_schema_generated.h"
+
+namespace onert
+{
+namespace loader
+{
+
+namespace
+{
+
+struct LoaderDomain
+{
+  using Verifier = flatbuffers::Verifier;
+  using ActivationFunctionType = onert_tflite::ActivationFunctionType;
+  using Buffer = onert_tflite::Buffer;
+  using BuiltinOperator = onert_tflite::BuiltinOperator;
+  using CustomOptionsFormat = onert_tflite::CustomOptionsFormat;
+  using Model = onert_tflite::Model;
+  using Metadata = onert_tflite::Metadata;
+  using Operator = onert_tflite::Operator;
+  using Padding = onert_tflite::Padding;
+  using Pool2DOptions = onert_tflite::Pool2DOptions;
+  using Tensor = onert_tflite::Tensor;
+  using TensorType = onert_tflite::TensorType;
+  using SubGraph = onert_tflite::SubGraph;
+  using DimensionType = onert_tflite::DimensionType;
+  using SparseIndexVector = onert_tflite::SparseIndexVector;
+
+  static const char *EnumNameBuiltinOperator(BuiltinOperator e)
+  {
+    return onert_tflite::EnumNameBuiltinOperator(e);
+  }
+  static const char *EnumNameActivationFunctionType(ActivationFunctionType e)
+  {
+    return onert_tflite::EnumNameActivationFunctionType(e);
+  }
+  static const char *EnumNameTensorType(TensorType e)
+  {
+    return onert_tflite::EnumNameTensorType(e);
+  }
+  static const Model *GetModel(const void *buf) { return onert_tflite::GetModel(buf); }
+  static bool VerifyModelBuffer(Verifier &verifier)
+  {
+    return onert_tflite::VerifyModelBuffer(verifier);
+  }
+};
+
+class TFLiteLoader final : public loader::BaseLoader<LoaderDomain>
+{
+protected:
+  // Different option name
+  //  Circle: adjoint_lhs, adjoint_rhs
+  //  TFLite: adj_x, adj_y
+  void loadBatchMatMul(const Operator *op, ir::Graph &subg);
+
+public:
+  using BaseLoader::BaseLoader;
+
+  bool allowOptionalInputTensor(BuiltinOperator op) override
+  {
+    switch (op)
+    {
+      case BuiltinOperator::BuiltinOperator_FULLY_CONNECTED:
+      case BuiltinOperator::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+private:
+  std::unique_ptr<ir::Graph> loadSubgraph(const onert_tflite::SubGraph *tflite_subg) override
+  {
+    auto subg = std::make_unique<ir::Graph>();
+    // Load tensors
+    _tensor_to_operand.resize(tflite_subg->tensors()->size());
+    for (flatbuffers::uoffset_t i = 0; i < tflite_subg->tensors()->size(); ++i)
+    {
+      _tensor_to_operand[i] = loadOperand(tflite_subg->tensors()->Get(i), *subg);
+    }
+    // Set inputs
+    for (const std::int32_t input_ind : *tflite_subg->inputs())
+    {
+      subg->addInput(tensorIdxToOperandIdx(input_ind),
+                     _tensor_names.at(_tensor_to_operand[input_ind]));
+    }
+    // Set outputs
+    for (const std::int32_t output_ind : *tflite_subg->outputs())
+    {
+      subg->addOutput(tensorIdxToOperandIdx(output_ind),
+                      _tensor_names.at(_tensor_to_operand[output_ind]));
+    }
+    // Create operations
+    for (const auto *op : *tflite_subg->operators())
+    {
+      loadOperation(op, *subg);
+    }
+
+    subg->verify();
+
+    return subg;
+  }
+
+  void loadOperation(const onert_tflite::Operator *op, ir::Graph &subg)
+  {
+    auto const builtin_op = getBuiltinOperator(op);
+
+    switch (builtin_op)
+    {
+      case onert_tflite::BuiltinOperator::BuiltinOperator_BATCH_MATMUL:
+        loadBatchMatMul(op, subg);
+        return;
+      default:
+        BaseLoader::loadOperation(op, subg);
+        return;
+    }
+  }
+};
+
+void TFLiteLoader::loadBatchMatMul(const Operator *op, ir::Graph &subg)
+{
+  ir::OperandIndexSequence inputs;
+  ir::OperandIndexSequence outputs;
+
+  loadOperationIO(op, inputs, outputs);
+
+  ir::operation::BatchMatMul::Param param;
+  const auto *options = op->builtin_options_as_BatchMatMulOptions();
+
+  param.adj_x = options->adj_x();
+  param.adj_y = options->adj_y();
+
+  std::unique_ptr<ir::Operation> new_op(new ir::operation::BatchMatMul(inputs, outputs, param));
+  subg.addOperation(std::move(new_op));
+}
+
+} // namespace
+
+std::unique_ptr<ir::Model> loadTFLiteModel(const std::string &filename)
+{
+  auto model = std::make_unique<ir::Model>();
+  TFLiteLoader loader(model);
+  loader.loadFromFile(filename);
+  return model;
+}
+
+} // namespace loader
+} // namespace onert
diff --git a/runtime/onert/core/src/loader/TrainInfoLoader.cc b/runtime/onert/core/src/loader/TrainInfoLoader.cc
new file mode 100644 (file)
index 0000000..bb75daa
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "loader/TrainInfoLoader.h"
+
+#include "circle_traininfo_generated.h"
+#include "flatbuffers/flatbuffers.h"
+
+namespace onert
+{
+namespace loader
+{
+
+const char *const TRAININFO_METADATA_NAME = "CIRCLE_TRAINING";
+
+namespace
+{
+
+ir::train::OptimizerInfo loadOptimizerInfo(const circle::ModelTraining *circle_model)
+{
+  assert(circle_model != nullptr);
+
+  // fill ir_opt from cirlce_opt
+  ir::train::OptimizerInfo ir_opt;
+  const circle::Optimizer circle_opt = circle_model->optimizer();
+
+  switch (circle_opt)
+  {
+    case circle::Optimizer_SGD:
+      ir_opt.optim_code = ir::train::OptimizerCode::SGD;
+      ir_opt.learning_rate = circle_model->optimizer_opt_as_SGDOptions()->learning_rate();
+      break;
+    case circle::Optimizer_ADAM:
+      ir_opt.optim_code = ir::train::OptimizerCode::Adam;
+      ir_opt.learning_rate = circle_model->optimizer_opt_as_AdamOptions()->learning_rate();
+      break;
+    default:
+      throw std::runtime_error("unknown optimzer");
+  }
+  return ir_opt;
+}
+
+ir::train::LossInfo loadLossInfo(const circle::ModelTraining *circle_model)
+{
+  assert(circle_model != nullptr);
+
+  // fill ir_loss from circle_loss
+  ir::train::LossInfo ir_loss;
+  const circle::LossFn circle_loss = circle_model->lossfn();
+  const circle::LossReductionType circle_loss_rdt = circle_model->loss_reduction_type();
+
+  switch (circle_loss)
+  {
+    case circle::LossFn::LossFn_CATEGORICAL_CROSSENTROPY:
+      ir_loss.loss_code = ir::train::LossCode::CategoricalCrossentropy;
+      break;
+    case circle::LossFn::LossFn_MEAN_SQUARED_ERROR:
+      ir_loss.loss_code = ir::train::LossCode::MeanSquaredError;
+      break;
+    case circle::LossFn::LossFn_SPARSE_CATEGORICAL_CROSSENTROPY:
+      // TODO enable this conversion after core support sparse_categorial_crossentropy
+      throw std::runtime_error{"'sparse_categorical_crossentropy' is not supported yet"};
+    default:
+      throw std::runtime_error{"unknown loss function"};
+  }
+
+  switch (circle_loss_rdt)
+  {
+    case circle::LossReductionType::LossReductionType_SumOverBatchSize:
+      ir_loss.reduction_type = ir::train::LossReductionType::SumOverBatchSize;
+      break;
+    case circle::LossReductionType::LossReductionType_Sum:
+      ir_loss.reduction_type = ir::train::LossReductionType::Sum;
+      break;
+    default:
+      throw std::runtime_error{"unknown loss reduction type"};
+  }
+
+  return ir_loss;
+}
+
+std::set<ir::OperationIndex> loadTrainableOps(const circle::ModelTraining *circle_model)
+{
+  assert(circle_model != nullptr);
+
+  std::set<ir::OperationIndex> ir_trainable_ops;
+  const auto lists = circle_model->trainable_ops();
+  if (lists != nullptr)
+  {
+    for (::flatbuffers::uoffset_t i = 0; i < lists->size(); ++i)
+    {
+      const uint32_t op_index = lists->Get(i);
+      ir_trainable_ops.emplace(ir::OperationIndex{op_index});
+    }
+  }
+  return ir_trainable_ops;
+}
+} // namespace
+
+std::unique_ptr<ir::train::TrainingInfo> loadTrainingInfo(const uint8_t *buffer, const size_t size)
+{
+  assert(buffer != nullptr);
+
+  flatbuffers::Verifier v(buffer, size);
+  bool verified = circle::VerifyModelTrainingBuffer(v);
+  if (not verified)
+    throw std::runtime_error{"TrainingInfo buffer is not accessible"};
+
+  const circle::ModelTraining *circle_model =
+    circle::GetModelTraining(static_cast<const void *>(buffer));
+
+  assert(circle_model != nullptr);
+
+  auto tinfo = std::make_unique<ir::train::TrainingInfo>();
+  {
+    tinfo->setVersion(circle_model->version());
+    tinfo->setBatchSize(circle_model->batch_size());
+    tinfo->setOptimizerInfo(loadOptimizerInfo(circle_model));
+    tinfo->setLossInfo(loadLossInfo(circle_model));
+    tinfo->setTrainableOps(loadTrainableOps(circle_model));
+  }
+  return tinfo;
+}
+
+} // namespace loader
+} // namespace onert
diff --git a/runtime/onert/core/src/loader/tflite_schema_generated.h b/runtime/onert/core/src/loader/tflite_schema_generated.h
new file mode 100644 (file)
index 0000000..9d89184
--- /dev/null
@@ -0,0 +1,11989 @@
+/*
+ * Copyright (c) 2019-2024 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.
+ */
+// automatically generated by the FlatBuffers compiler, do not modify
+
+#ifndef FLATBUFFERS_GENERATED_TFLITESCHEMA_ONERT_TFLITE_H_
+#define FLATBUFFERS_GENERATED_TFLITESCHEMA_ONERT_TFLITE_H_
+
+#include "flatbuffers/flatbuffers.h"
+
+// Ensure the included flatbuffers.h is the same version as when this file was
+// generated, otherwise it may not be compatible.
+static_assert(FLATBUFFERS_VERSION_MAJOR == 23 && FLATBUFFERS_VERSION_MINOR == 5 &&
+                FLATBUFFERS_VERSION_REVISION == 26,
+              "Non-compatible flatbuffers version included");
+
+namespace onert_tflite
+{
+
+struct CustomQuantization;
+struct CustomQuantizationBuilder;
+
+struct QuantizationParameters;
+struct QuantizationParametersBuilder;
+
+struct Int32Vector;
+struct Int32VectorBuilder;
+
+struct Uint16Vector;
+struct Uint16VectorBuilder;
+
+struct Uint8Vector;
+struct Uint8VectorBuilder;
+
+struct DimensionMetadata;
+struct DimensionMetadataBuilder;
+
+struct SparsityParameters;
+struct SparsityParametersBuilder;
+
+struct Tensor;
+struct TensorBuilder;
+
+struct Conv2DOptions;
+struct Conv2DOptionsBuilder;
+
+struct Conv3DOptions;
+struct Conv3DOptionsBuilder;
+
+struct Pool2DOptions;
+struct Pool2DOptionsBuilder;
+
+struct DepthwiseConv2DOptions;
+struct DepthwiseConv2DOptionsBuilder;
+
+struct ConcatEmbeddingsOptions;
+struct ConcatEmbeddingsOptionsBuilder;
+
+struct LSHProjectionOptions;
+struct LSHProjectionOptionsBuilder;
+
+struct SVDFOptions;
+struct SVDFOptionsBuilder;
+
+struct RNNOptions;
+struct RNNOptionsBuilder;
+
+struct SequenceRNNOptions;
+struct SequenceRNNOptionsBuilder;
+
+struct BidirectionalSequenceRNNOptions;
+struct BidirectionalSequenceRNNOptionsBuilder;
+
+struct FullyConnectedOptions;
+struct FullyConnectedOptionsBuilder;
+
+struct SoftmaxOptions;
+struct SoftmaxOptionsBuilder;
+
+struct ConcatenationOptions;
+struct ConcatenationOptionsBuilder;
+
+struct AddOptions;
+struct AddOptionsBuilder;
+
+struct MulOptions;
+struct MulOptionsBuilder;
+
+struct L2NormOptions;
+struct L2NormOptionsBuilder;
+
+struct LocalResponseNormalizationOptions;
+struct LocalResponseNormalizationOptionsBuilder;
+
+struct LSTMOptions;
+struct LSTMOptionsBuilder;
+
+struct UnidirectionalSequenceLSTMOptions;
+struct UnidirectionalSequenceLSTMOptionsBuilder;
+
+struct BidirectionalSequenceLSTMOptions;
+struct BidirectionalSequenceLSTMOptionsBuilder;
+
+struct ResizeBilinearOptions;
+struct ResizeBilinearOptionsBuilder;
+
+struct ResizeNearestNeighborOptions;
+struct ResizeNearestNeighborOptionsBuilder;
+
+struct CallOptions;
+struct CallOptionsBuilder;
+
+struct PadOptions;
+struct PadOptionsBuilder;
+
+struct PadV2Options;
+struct PadV2OptionsBuilder;
+
+struct ReshapeOptions;
+struct ReshapeOptionsBuilder;
+
+struct SpaceToBatchNDOptions;
+struct SpaceToBatchNDOptionsBuilder;
+
+struct BatchToSpaceNDOptions;
+struct BatchToSpaceNDOptionsBuilder;
+
+struct SkipGramOptions;
+struct SkipGramOptionsBuilder;
+
+struct SpaceToDepthOptions;
+struct SpaceToDepthOptionsBuilder;
+
+struct DepthToSpaceOptions;
+struct DepthToSpaceOptionsBuilder;
+
+struct SubOptions;
+struct SubOptionsBuilder;
+
+struct DivOptions;
+struct DivOptionsBuilder;
+
+struct TopKV2Options;
+struct TopKV2OptionsBuilder;
+
+struct EmbeddingLookupSparseOptions;
+struct EmbeddingLookupSparseOptionsBuilder;
+
+struct GatherOptions;
+struct GatherOptionsBuilder;
+
+struct TransposeOptions;
+struct TransposeOptionsBuilder;
+
+struct ExpOptions;
+struct ExpOptionsBuilder;
+
+struct CosOptions;
+struct CosOptionsBuilder;
+
+struct ReducerOptions;
+struct ReducerOptionsBuilder;
+
+struct SqueezeOptions;
+struct SqueezeOptionsBuilder;
+
+struct SplitOptions;
+struct SplitOptionsBuilder;
+
+struct SplitVOptions;
+struct SplitVOptionsBuilder;
+
+struct StridedSliceOptions;
+struct StridedSliceOptionsBuilder;
+
+struct LogSoftmaxOptions;
+struct LogSoftmaxOptionsBuilder;
+
+struct CastOptions;
+struct CastOptionsBuilder;
+
+struct DequantizeOptions;
+struct DequantizeOptionsBuilder;
+
+struct MaximumMinimumOptions;
+struct MaximumMinimumOptionsBuilder;
+
+struct TileOptions;
+struct TileOptionsBuilder;
+
+struct ArgMaxOptions;
+struct ArgMaxOptionsBuilder;
+
+struct ArgMinOptions;
+struct ArgMinOptionsBuilder;
+
+struct GreaterOptions;
+struct GreaterOptionsBuilder;
+
+struct GreaterEqualOptions;
+struct GreaterEqualOptionsBuilder;
+
+struct LessOptions;
+struct LessOptionsBuilder;
+
+struct LessEqualOptions;
+struct LessEqualOptionsBuilder;
+
+struct NegOptions;
+struct NegOptionsBuilder;
+
+struct SelectOptions;
+struct SelectOptionsBuilder;
+
+struct SliceOptions;
+struct SliceOptionsBuilder;
+
+struct TransposeConvOptions;
+struct TransposeConvOptionsBuilder;
+
+struct ExpandDimsOptions;
+struct ExpandDimsOptionsBuilder;
+
+struct SparseToDenseOptions;
+struct SparseToDenseOptionsBuilder;
+
+struct EqualOptions;
+struct EqualOptionsBuilder;
+
+struct NotEqualOptions;
+struct NotEqualOptionsBuilder;
+
+struct ShapeOptions;
+struct ShapeOptionsBuilder;
+
+struct RankOptions;
+struct RankOptionsBuilder;
+
+struct PowOptions;
+struct PowOptionsBuilder;
+
+struct FakeQuantOptions;
+struct FakeQuantOptionsBuilder;
+
+struct PackOptions;
+struct PackOptionsBuilder;
+
+struct LogicalOrOptions;
+struct LogicalOrOptionsBuilder;
+
+struct OneHotOptions;
+struct OneHotOptionsBuilder;
+
+struct AbsOptions;
+struct AbsOptionsBuilder;
+
+struct HardSwishOptions;
+struct HardSwishOptionsBuilder;
+
+struct LogicalAndOptions;
+struct LogicalAndOptionsBuilder;
+
+struct LogicalNotOptions;
+struct LogicalNotOptionsBuilder;
+
+struct UnpackOptions;
+struct UnpackOptionsBuilder;
+
+struct FloorDivOptions;
+struct FloorDivOptionsBuilder;
+
+struct SquareOptions;
+struct SquareOptionsBuilder;
+
+struct ZerosLikeOptions;
+struct ZerosLikeOptionsBuilder;
+
+struct FillOptions;
+struct FillOptionsBuilder;
+
+struct FloorModOptions;
+struct FloorModOptionsBuilder;
+
+struct RangeOptions;
+struct RangeOptionsBuilder;
+
+struct LeakyReluOptions;
+struct LeakyReluOptionsBuilder;
+
+struct SquaredDifferenceOptions;
+struct SquaredDifferenceOptionsBuilder;
+
+struct MirrorPadOptions;
+struct MirrorPadOptionsBuilder;
+
+struct UniqueOptions;
+struct UniqueOptionsBuilder;
+
+struct ReverseV2Options;
+struct ReverseV2OptionsBuilder;
+
+struct AddNOptions;
+struct AddNOptionsBuilder;
+
+struct GatherNdOptions;
+struct GatherNdOptionsBuilder;
+
+struct WhereOptions;
+struct WhereOptionsBuilder;
+
+struct ReverseSequenceOptions;
+struct ReverseSequenceOptionsBuilder;
+
+struct MatrixDiagOptions;
+struct MatrixDiagOptionsBuilder;
+
+struct QuantizeOptions;
+struct QuantizeOptionsBuilder;
+
+struct MatrixSetDiagOptions;
+struct MatrixSetDiagOptionsBuilder;
+
+struct IfOptions;
+struct IfOptionsBuilder;
+
+struct CallOnceOptions;
+struct CallOnceOptionsBuilder;
+
+struct WhileOptions;
+struct WhileOptionsBuilder;
+
+struct NonMaxSuppressionV4Options;
+struct NonMaxSuppressionV4OptionsBuilder;
+
+struct NonMaxSuppressionV5Options;
+struct NonMaxSuppressionV5OptionsBuilder;
+
+struct ScatterNdOptions;
+struct ScatterNdOptionsBuilder;
+
+struct SelectV2Options;
+struct SelectV2OptionsBuilder;
+
+struct DensifyOptions;
+struct DensifyOptionsBuilder;
+
+struct SegmentSumOptions;
+struct SegmentSumOptionsBuilder;
+
+struct BatchMatMulOptions;
+struct BatchMatMulOptionsBuilder;
+
+struct CumsumOptions;
+struct CumsumOptionsBuilder;
+
+struct BroadcastToOptions;
+struct BroadcastToOptionsBuilder;
+
+struct Rfft2dOptions;
+struct Rfft2dOptionsBuilder;
+
+struct HashtableOptions;
+struct HashtableOptionsBuilder;
+
+struct HashtableFindOptions;
+struct HashtableFindOptionsBuilder;
+
+struct HashtableImportOptions;
+struct HashtableImportOptionsBuilder;
+
+struct HashtableSizeOptions;
+struct HashtableSizeOptionsBuilder;
+
+struct VarHandleOptions;
+struct VarHandleOptionsBuilder;
+
+struct ReadVariableOptions;
+struct ReadVariableOptionsBuilder;
+
+struct AssignVariableOptions;
+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;
+
+struct Operator;
+struct OperatorBuilder;
+
+struct SubGraph;
+struct SubGraphBuilder;
+
+struct Buffer;
+struct BufferBuilder;
+
+struct Metadata;
+struct MetadataBuilder;
+
+struct TensorMap;
+struct TensorMapBuilder;
+
+struct SignatureDef;
+struct SignatureDefBuilder;
+
+struct Model;
+struct ModelBuilder;
+
+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_UINT16 = 16,
+  TensorType_MIN = TensorType_FLOAT32,
+  TensorType_MAX = TensorType_UINT16
+};
+
+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_UINT16};
+  return values;
+}
+
+inline const char *const *EnumNamesTensorType()
+{
+  static const char *const names[18] = {"FLOAT32", "FLOAT16",    "INT32",  "UINT8",     "INT64",
+                                        "STRING",  "BOOL",       "INT16",  "COMPLEX64", "INT8",
+                                        "FLOAT64", "COMPLEX128", "UINT64", "RESOURCE",  "VARIANT",
+                                        "UINT32",  "UINT16",     nullptr};
+  return names;
+}
+
+inline const char *EnumNameTensorType(TensorType e)
+{
+  if (::flatbuffers::IsOutRange(e, TensorType_FLOAT32, TensorType_UINT16))
+    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<onert_tflite::CustomQuantization>
+{
+  static const QuantizationDetails enum_value = QuantizationDetails_CustomQuantization;
+};
+
+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<onert_tflite::Int32Vector>
+{
+  static const SparseIndexVector enum_value = SparseIndexVector_Int32Vector;
+};
+
+template <> struct SparseIndexVectorTraits<onert_tflite::Uint16Vector>
+{
+  static const SparseIndexVector enum_value = SparseIndexVector_Uint16Vector;
+};
+
+template <> struct SparseIndexVectorTraits<onert_tflite::Uint8Vector>
+{
+  static const SparseIndexVector enum_value = SparseIndexVector_Uint8Vector;
+};
+
+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_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_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_ATAN2
+};
+
+inline const BuiltinOperator (&EnumValuesBuiltinOperator())[157]
+{
+  static const BuiltinOperator values[] = {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,
+                                           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[158] = {"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",
+                                         "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_ATAN2))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  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_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_ATan2Options
+};
+
+inline const BuiltinOptions (&EnumValuesBuiltinOptions())[122]
+{
+  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_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[123] = {"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",
+                                         "BucketizeOptions",
+                                         "GeluOptions",
+                                         "DynamicUpdateSliceOptions",
+                                         "UnsortedSegmentProdOptions",
+                                         "UnsortedSegmentMaxOptions",
+                                         "UnsortedSegmentSumOptions",
+                                         "ATan2Options",
+                                         nullptr};
+  return names;
+}
+
+inline const char *EnumNameBuiltinOptions(BuiltinOptions e)
+{
+  if (::flatbuffers::IsOutRange(e, BuiltinOptions_NONE, BuiltinOptions_ATan2Options))
+    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<onert_tflite::Conv2DOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_Conv2DOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::DepthwiseConv2DOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DepthwiseConv2DOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ConcatEmbeddingsOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ConcatEmbeddingsOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::LSHProjectionOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LSHProjectionOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::Pool2DOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_Pool2DOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SVDFOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SVDFOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::RNNOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_RNNOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::FullyConnectedOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_FullyConnectedOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SoftmaxOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SoftmaxOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ConcatenationOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ConcatenationOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::AddOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_AddOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::L2NormOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_L2NormOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::LocalResponseNormalizationOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LocalResponseNormalizationOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::LSTMOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LSTMOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ResizeBilinearOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ResizeBilinearOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::CallOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_CallOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ReshapeOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ReshapeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SkipGramOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SkipGramOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SpaceToDepthOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SpaceToDepthOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::EmbeddingLookupSparseOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_EmbeddingLookupSparseOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::MulOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_MulOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::PadOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_PadOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::GatherOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GatherOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::BatchToSpaceNDOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BatchToSpaceNDOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SpaceToBatchNDOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SpaceToBatchNDOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::TransposeOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_TransposeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ReducerOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ReducerOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SubOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SubOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::DivOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DivOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SqueezeOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SqueezeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SequenceRNNOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SequenceRNNOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::StridedSliceOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_StridedSliceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ExpOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ExpOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::TopKV2Options>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_TopKV2Options;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SplitOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SplitOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::LogSoftmaxOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LogSoftmaxOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::CastOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_CastOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::DequantizeOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DequantizeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::MaximumMinimumOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_MaximumMinimumOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ArgMaxOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ArgMaxOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::LessOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LessOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::NegOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_NegOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::PadV2Options>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_PadV2Options;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::GreaterOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GreaterOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::GreaterEqualOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GreaterEqualOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::LessEqualOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LessEqualOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SelectOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SelectOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SliceOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SliceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::TransposeConvOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_TransposeConvOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SparseToDenseOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SparseToDenseOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::TileOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_TileOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ExpandDimsOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ExpandDimsOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::EqualOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_EqualOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::NotEqualOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_NotEqualOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ShapeOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ShapeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::PowOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_PowOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ArgMinOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ArgMinOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::FakeQuantOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_FakeQuantOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::PackOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_PackOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::LogicalOrOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LogicalOrOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::OneHotOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_OneHotOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::LogicalAndOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LogicalAndOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::LogicalNotOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LogicalNotOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::UnpackOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_UnpackOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::FloorDivOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_FloorDivOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SquareOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SquareOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ZerosLikeOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ZerosLikeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::FillOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_FillOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::BidirectionalSequenceLSTMOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceLSTMOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::BidirectionalSequenceRNNOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceRNNOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::UnidirectionalSequenceLSTMOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_UnidirectionalSequenceLSTMOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::FloorModOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_FloorModOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::RangeOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_RangeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ResizeNearestNeighborOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ResizeNearestNeighborOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::LeakyReluOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_LeakyReluOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SquaredDifferenceOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SquaredDifferenceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::MirrorPadOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_MirrorPadOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::AbsOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_AbsOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SplitVOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SplitVOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::UniqueOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_UniqueOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ReverseV2Options>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ReverseV2Options;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::AddNOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_AddNOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::GatherNdOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_GatherNdOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::CosOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_CosOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::WhereOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_WhereOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::RankOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_RankOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ReverseSequenceOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ReverseSequenceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::MatrixDiagOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_MatrixDiagOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::QuantizeOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_QuantizeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::MatrixSetDiagOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_MatrixSetDiagOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::HardSwishOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_HardSwishOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::IfOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_IfOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::WhileOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_WhileOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::DepthToSpaceOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DepthToSpaceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::NonMaxSuppressionV4Options>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV4Options;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::NonMaxSuppressionV5Options>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV5Options;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ScatterNdOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ScatterNdOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SelectV2Options>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SelectV2Options;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::DensifyOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_DensifyOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::SegmentSumOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_SegmentSumOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::BatchMatMulOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BatchMatMulOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::CumsumOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_CumsumOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::CallOnceOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_CallOnceOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::BroadcastToOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_BroadcastToOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::Rfft2dOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_Rfft2dOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::Conv3DOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_Conv3DOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::HashtableOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_HashtableOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::HashtableFindOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_HashtableFindOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::HashtableImportOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_HashtableImportOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::HashtableSizeOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_HashtableSizeOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::VarHandleOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_VarHandleOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::ReadVariableOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_ReadVariableOptions;
+};
+
+template <> struct BuiltinOptionsTraits<onert_tflite::AssignVariableOptions>
+{
+  static const BuiltinOptions enum_value = BuiltinOptions_AssignVariableOptions;
+};
+
+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,
+                                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_MIN = FullyConnectedOptionsWeightsFormat_DEFAULT,
+  FullyConnectedOptionsWeightsFormat_MAX = FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8
+};
+
+inline const FullyConnectedOptionsWeightsFormat (&EnumValuesFullyConnectedOptionsWeightsFormat())[2]
+{
+  static const FullyConnectedOptionsWeightsFormat values[] = {
+    FullyConnectedOptionsWeightsFormat_DEFAULT,
+    FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8};
+  return values;
+}
+
+inline const char *const *EnumNamesFullyConnectedOptionsWeightsFormat()
+{
+  static const char *const names[3] = {"DEFAULT", "SHUFFLED4x16INT8", nullptr};
+  return names;
+}
+
+inline const char *EnumNameFullyConnectedOptionsWeightsFormat(FullyConnectedOptionsWeightsFormat e)
+{
+  if (::flatbuffers::IsOutRange(e, FullyConnectedOptionsWeightsFormat_DEFAULT,
+                                FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8))
+    return "";
+  const size_t index = static_cast<size_t>(e);
+  return EnumNamesFullyConnectedOptionsWeightsFormat()[index];
+}
+
+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];
+}
+
+struct CustomQuantization FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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();
+  }
+};
+
+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 onert_tflite::CreateCustomQuantization(_fbb, custom__);
+}
+
+struct QuantizationParameters FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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);
+  }
+  onert_tflite::QuantizationDetails details_type() const
+  {
+    return static_cast<onert_tflite::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 onert_tflite::CustomQuantization *details_as_CustomQuantization() const
+  {
+    return details_type() == onert_tflite::QuantizationDetails_CustomQuantization
+             ? static_cast<const onert_tflite::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, 1) &&
+           VerifyOffset(verifier, VT_DETAILS) &&
+           VerifyQuantizationDetails(verifier, details(), details_type()) &&
+           VerifyField<int32_t>(verifier, VT_QUANTIZED_DIMENSION, 4) && verifier.EndTable();
+  }
+};
+
+template <>
+inline const onert_tflite::CustomQuantization *
+QuantizationParameters::details_as<onert_tflite::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(onert_tflite::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,
+  onert_tflite::QuantizationDetails details_type = onert_tflite::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,
+  onert_tflite::QuantizationDetails details_type = onert_tflite::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 onert_tflite::CreateQuantizationParameters(_fbb, min__, max__, scale__, zero_point__,
+                                                    details_type, details, quantized_dimension);
+}
+
+struct Int32Vector FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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();
+  }
+};
+
+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 onert_tflite::CreateInt32Vector(_fbb, values__);
+}
+
+struct Uint16Vector FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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();
+  }
+};
+
+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 onert_tflite::CreateUint16Vector(_fbb, values__);
+}
+
+struct Uint8Vector FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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();
+  }
+};
+
+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 onert_tflite::CreateUint8Vector(_fbb, values__);
+}
+
+struct DimensionMetadata FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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
+  };
+  onert_tflite::DimensionType format() const
+  {
+    return static_cast<onert_tflite::DimensionType>(GetField<int8_t>(VT_FORMAT, 0));
+  }
+  int32_t dense_size() const { return GetField<int32_t>(VT_DENSE_SIZE, 0); }
+  onert_tflite::SparseIndexVector array_segments_type() const
+  {
+    return static_cast<onert_tflite::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 onert_tflite::Int32Vector *array_segments_as_Int32Vector() const
+  {
+    return array_segments_type() == onert_tflite::SparseIndexVector_Int32Vector
+             ? static_cast<const onert_tflite::Int32Vector *>(array_segments())
+             : nullptr;
+  }
+  const onert_tflite::Uint16Vector *array_segments_as_Uint16Vector() const
+  {
+    return array_segments_type() == onert_tflite::SparseIndexVector_Uint16Vector
+             ? static_cast<const onert_tflite::Uint16Vector *>(array_segments())
+             : nullptr;
+  }
+  const onert_tflite::Uint8Vector *array_segments_as_Uint8Vector() const
+  {
+    return array_segments_type() == onert_tflite::SparseIndexVector_Uint8Vector
+             ? static_cast<const onert_tflite::Uint8Vector *>(array_segments())
+             : nullptr;
+  }
+  onert_tflite::SparseIndexVector array_indices_type() const
+  {
+    return static_cast<onert_tflite::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 onert_tflite::Int32Vector *array_indices_as_Int32Vector() const
+  {
+    return array_indices_type() == onert_tflite::SparseIndexVector_Int32Vector
+             ? static_cast<const onert_tflite::Int32Vector *>(array_indices())
+             : nullptr;
+  }
+  const onert_tflite::Uint16Vector *array_indices_as_Uint16Vector() const
+  {
+    return array_indices_type() == onert_tflite::SparseIndexVector_Uint16Vector
+             ? static_cast<const onert_tflite::Uint16Vector *>(array_indices())
+             : nullptr;
+  }
+  const onert_tflite::Uint8Vector *array_indices_as_Uint8Vector() const
+  {
+    return array_indices_type() == onert_tflite::SparseIndexVector_Uint8Vector
+             ? static_cast<const onert_tflite::Uint8Vector *>(array_indices())
+             : nullptr;
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_FORMAT, 1) &&
+           VerifyField<int32_t>(verifier, VT_DENSE_SIZE, 4) &&
+           VerifyField<uint8_t>(verifier, VT_ARRAY_SEGMENTS_TYPE, 1) &&
+           VerifyOffset(verifier, VT_ARRAY_SEGMENTS) &&
+           VerifySparseIndexVector(verifier, array_segments(), array_segments_type()) &&
+           VerifyField<uint8_t>(verifier, VT_ARRAY_INDICES_TYPE, 1) &&
+           VerifyOffset(verifier, VT_ARRAY_INDICES) &&
+           VerifySparseIndexVector(verifier, array_indices(), array_indices_type()) &&
+           verifier.EndTable();
+  }
+};
+
+template <>
+inline const onert_tflite::Int32Vector *
+DimensionMetadata::array_segments_as<onert_tflite::Int32Vector>() const
+{
+  return array_segments_as_Int32Vector();
+}
+
+template <>
+inline const onert_tflite::Uint16Vector *
+DimensionMetadata::array_segments_as<onert_tflite::Uint16Vector>() const
+{
+  return array_segments_as_Uint16Vector();
+}
+
+template <>
+inline const onert_tflite::Uint8Vector *
+DimensionMetadata::array_segments_as<onert_tflite::Uint8Vector>() const
+{
+  return array_segments_as_Uint8Vector();
+}
+
+template <>
+inline const onert_tflite::Int32Vector *
+DimensionMetadata::array_indices_as<onert_tflite::Int32Vector>() const
+{
+  return array_indices_as_Int32Vector();
+}
+
+template <>
+inline const onert_tflite::Uint16Vector *
+DimensionMetadata::array_indices_as<onert_tflite::Uint16Vector>() const
+{
+  return array_indices_as_Uint16Vector();
+}
+
+template <>
+inline const onert_tflite::Uint8Vector *
+DimensionMetadata::array_indices_as<onert_tflite::Uint8Vector>() const
+{
+  return array_indices_as_Uint8Vector();
+}
+
+struct DimensionMetadataBuilder
+{
+  typedef DimensionMetadata Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_format(onert_tflite::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(onert_tflite::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(onert_tflite::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,
+  onert_tflite::DimensionType format = onert_tflite::DimensionType_DENSE, int32_t dense_size = 0,
+  onert_tflite::SparseIndexVector array_segments_type = onert_tflite::SparseIndexVector_NONE,
+  ::flatbuffers::Offset<void> array_segments = 0,
+  onert_tflite::SparseIndexVector array_indices_type = onert_tflite::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();
+}
+
+struct SparsityParameters FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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<onert_tflite::DimensionMetadata>> *
+  dim_metadata() const
+  {
+    return GetPointer<
+      const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::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();
+  }
+};
+
+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<onert_tflite::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<onert_tflite::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<onert_tflite::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<onert_tflite::DimensionMetadata>>(*dim_metadata)
+      : 0;
+  return onert_tflite::CreateSparsityParameters(_fbb, traversal_order__, block_map__,
+                                                dim_metadata__);
+}
+
+struct Tensor FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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,
+    VT_HAS_RANK = 20
+  };
+  const ::flatbuffers::Vector<int32_t> *shape() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<int32_t> *>(VT_SHAPE);
+  }
+  onert_tflite::TensorType type() const
+  {
+    return static_cast<onert_tflite::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 onert_tflite::QuantizationParameters *quantization() const
+  {
+    return GetPointer<const onert_tflite::QuantizationParameters *>(VT_QUANTIZATION);
+  }
+  bool is_variable() const { return GetField<uint8_t>(VT_IS_VARIABLE, 0) != 0; }
+  const onert_tflite::SparsityParameters *sparsity() const
+  {
+    return GetPointer<const onert_tflite::SparsityParameters *>(VT_SPARSITY);
+  }
+  const ::flatbuffers::Vector<int32_t> *shape_signature() const
+  {
+    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) &&
+           verifier.VerifyVector(shape()) && VerifyField<int8_t>(verifier, VT_TYPE, 1) &&
+           VerifyField<uint32_t>(verifier, VT_BUFFER, 4) && VerifyOffset(verifier, VT_NAME) &&
+           verifier.VerifyString(name()) && VerifyOffset(verifier, VT_QUANTIZATION) &&
+           verifier.VerifyTable(quantization()) &&
+           VerifyField<uint8_t>(verifier, VT_IS_VARIABLE, 1) &&
+           VerifyOffset(verifier, VT_SPARSITY) && verifier.VerifyTable(sparsity()) &&
+           VerifyOffset(verifier, VT_SHAPE_SIGNATURE) && verifier.VerifyVector(shape_signature()) &&
+           VerifyField<uint8_t>(verifier, VT_HAS_RANK, 1) && verifier.EndTable();
+  }
+};
+
+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(onert_tflite::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<onert_tflite::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<onert_tflite::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);
+  }
+  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();
+  }
+  ::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,
+  onert_tflite::TensorType type = onert_tflite::TensorType_FLOAT32, uint32_t buffer = 0,
+  ::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, bool has_rank = false)
+{
+  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_has_rank(has_rank);
+  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,
+  onert_tflite::TensorType type = onert_tflite::TensorType_FLOAT32, uint32_t buffer = 0,
+  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, 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__, has_rank);
+}
+
+struct Conv2DOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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
+  };
+  onert_tflite::Padding padding() const
+  {
+    return static_cast<onert_tflite::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); }
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_W, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_H, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_W_FACTOR, 4) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_H_FACTOR, 4) && verifier.EndTable();
+  }
+};
+
+struct Conv2DOptionsBuilder
+{
+  typedef Conv2DOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_padding(onert_tflite::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(onert_tflite::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,
+                    onert_tflite::Padding padding = onert_tflite::Padding_SAME,
+                    int32_t stride_w = 0, int32_t stride_h = 0,
+                    onert_tflite::ActivationFunctionType fused_activation_function =
+                      onert_tflite::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();
+}
+
+struct Conv3DOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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
+  };
+  onert_tflite::Padding padding() const
+  {
+    return static_cast<onert_tflite::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); }
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_D, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_W, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_H, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_D_FACTOR, 4) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_W_FACTOR, 4) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_H_FACTOR, 4) && verifier.EndTable();
+  }
+};
+
+struct Conv3DOptionsBuilder
+{
+  typedef Conv3DOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_padding(onert_tflite::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(onert_tflite::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,
+                    onert_tflite::Padding padding = onert_tflite::Padding_SAME,
+                    int32_t stride_d = 0, int32_t stride_w = 0, int32_t stride_h = 0,
+                    onert_tflite::ActivationFunctionType fused_activation_function =
+                      onert_tflite::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();
+}
+
+struct Pool2DOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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
+  };
+  onert_tflite::Padding padding() const
+  {
+    return static_cast<onert_tflite::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); }
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::ActivationFunctionType>(
+      GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_PADDING, 1) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_W, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_H, 4) &&
+           VerifyField<int32_t>(verifier, VT_FILTER_WIDTH, 4) &&
+           VerifyField<int32_t>(verifier, VT_FILTER_HEIGHT, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && verifier.EndTable();
+  }
+};
+
+struct Pool2DOptionsBuilder
+{
+  typedef Pool2DOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_padding(onert_tflite::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(onert_tflite::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,
+                    onert_tflite::Padding padding = onert_tflite::Padding_SAME,
+                    int32_t stride_w = 0, int32_t stride_h = 0, int32_t filter_width = 0,
+                    int32_t filter_height = 0,
+                    onert_tflite::ActivationFunctionType fused_activation_function =
+                      onert_tflite::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();
+}
+
+struct DepthwiseConv2DOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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
+  };
+  onert_tflite::Padding padding() const
+  {
+    return static_cast<onert_tflite::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); }
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_W, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_H, 4) &&
+           VerifyField<int32_t>(verifier, VT_DEPTH_MULTIPLIER, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_W_FACTOR, 4) &&
+           VerifyField<int32_t>(verifier, VT_DILATION_H_FACTOR, 4) && verifier.EndTable();
+  }
+};
+
+struct DepthwiseConv2DOptionsBuilder
+{
+  typedef DepthwiseConv2DOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_padding(onert_tflite::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(onert_tflite::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,
+                             onert_tflite::Padding padding = onert_tflite::Padding_SAME,
+                             int32_t stride_w = 0, int32_t stride_h = 0,
+                             int32_t depth_multiplier = 0,
+                             onert_tflite::ActivationFunctionType fused_activation_function =
+                               onert_tflite::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();
+}
+
+struct ConcatEmbeddingsOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           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();
+  }
+};
+
+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 onert_tflite::CreateConcatEmbeddingsOptions(_fbb, num_channels, num_columns_per_channel__,
+                                                     embedding_dim_per_channel__);
+}
+
+struct LSHProjectionOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef LSHProjectionOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_TYPE = 4
+  };
+  onert_tflite::LSHProjectionType type() const
+  {
+    return static_cast<onert_tflite::LSHProjectionType>(GetField<int8_t>(VT_TYPE, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_TYPE, 1) &&
+           verifier.EndTable();
+  }
+};
+
+struct LSHProjectionOptionsBuilder
+{
+  typedef LSHProjectionOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_type(onert_tflite::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,
+  onert_tflite::LSHProjectionType type = onert_tflite::LSHProjectionType_UNKNOWN)
+{
+  LSHProjectionOptionsBuilder builder_(_fbb);
+  builder_.add_type(type);
+  return builder_.Finish();
+}
+
+struct SVDFOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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); }
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && verifier.EndTable();
+  }
+};
+
+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(onert_tflite::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,
+                  onert_tflite::ActivationFunctionType fused_activation_function =
+                    onert_tflite::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();
+}
+
+struct RNNOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef RNNOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_FUSED_ACTIVATION_FUNCTION = 4,
+    VT_ASYMMETRIC_QUANTIZE_INPUTS = 6
+  };
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && verifier.EndTable();
+  }
+};
+
+struct RNNOptionsBuilder
+{
+  typedef RNNOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(onert_tflite::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,
+                 onert_tflite::ActivationFunctionType fused_activation_function =
+                   onert_tflite::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();
+}
+
+struct SequenceRNNOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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; }
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && verifier.EndTable();
+  }
+};
+
+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(onert_tflite::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,
+                         onert_tflite::ActivationFunctionType fused_activation_function =
+                           onert_tflite::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();
+}
+
+struct BidirectionalSequenceRNNOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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; }
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) &&
+           VerifyField<uint8_t>(verifier, VT_MERGE_OUTPUTS, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && verifier.EndTable();
+  }
+};
+
+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(onert_tflite::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,
+  onert_tflite::ActivationFunctionType fused_activation_function =
+    onert_tflite::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();
+}
+
+struct FullyConnectedOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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
+  };
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::ActivationFunctionType>(
+      GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+  }
+  onert_tflite::FullyConnectedOptionsWeightsFormat weights_format() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<int8_t>(verifier, VT_WEIGHTS_FORMAT, 1) &&
+           VerifyField<uint8_t>(verifier, VT_KEEP_NUM_DIMS, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && verifier.EndTable();
+  }
+};
+
+struct FullyConnectedOptionsBuilder
+{
+  typedef FullyConnectedOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(onert_tflite::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(onert_tflite::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,
+                            onert_tflite::ActivationFunctionType fused_activation_function =
+                              onert_tflite::ActivationFunctionType_NONE,
+                            onert_tflite::FullyConnectedOptionsWeightsFormat weights_format =
+                              onert_tflite::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();
+}
+
+struct SoftmaxOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct ConcatenationOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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); }
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::ActivationFunctionType>(
+      GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_AXIS, 4) &&
+           VerifyField<int8_t>(verifier, VT_FUSED_ACTIVATION_FUNCTION, 1) && verifier.EndTable();
+  }
+};
+
+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(onert_tflite::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,
+                           onert_tflite::ActivationFunctionType fused_activation_function =
+                             onert_tflite::ActivationFunctionType_NONE)
+{
+  ConcatenationOptionsBuilder builder_(_fbb);
+  builder_.add_axis(axis);
+  builder_.add_fused_activation_function(fused_activation_function);
+  return builder_.Finish();
+}
+
+struct AddOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef AddOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_FUSED_ACTIVATION_FUNCTION = 4,
+    VT_POT_SCALE_INT16 = 6
+  };
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_POT_SCALE_INT16, 1) && verifier.EndTable();
+  }
+};
+
+struct AddOptionsBuilder
+{
+  typedef AddOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(onert_tflite::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,
+                 onert_tflite::ActivationFunctionType fused_activation_function =
+                   onert_tflite::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();
+}
+
+struct MulOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef MulOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_FUSED_ACTIVATION_FUNCTION = 4
+  };
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) && verifier.EndTable();
+  }
+};
+
+struct MulOptionsBuilder
+{
+  typedef MulOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(onert_tflite::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,
+                 onert_tflite::ActivationFunctionType fused_activation_function =
+                   onert_tflite::ActivationFunctionType_NONE)
+{
+  MulOptionsBuilder builder_(_fbb);
+  builder_.add_fused_activation_function(fused_activation_function);
+  return builder_.Finish();
+}
+
+struct L2NormOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef L2NormOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_FUSED_ACTIVATION_FUNCTION = 4
+  };
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) && verifier.EndTable();
+  }
+};
+
+struct L2NormOptionsBuilder
+{
+  typedef L2NormOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(onert_tflite::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,
+                    onert_tflite::ActivationFunctionType fused_activation_function =
+                      onert_tflite::ActivationFunctionType_NONE)
+{
+  L2NormOptionsBuilder builder_(_fbb);
+  builder_.add_fused_activation_function(fused_activation_function);
+  return builder_.Finish();
+}
+
+struct LocalResponseNormalizationOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           VerifyField<float>(verifier, VT_BIAS, 4) && VerifyField<float>(verifier, VT_ALPHA, 4) &&
+           VerifyField<float>(verifier, VT_BETA, 4) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct LSTMOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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
+  };
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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); }
+  onert_tflite::LSTMKernelType kernel_type() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<float>(verifier, VT_CELL_CLIP, 4) &&
+           VerifyField<float>(verifier, VT_PROJ_CLIP, 4) &&
+           VerifyField<int8_t>(verifier, VT_KERNEL_TYPE, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && verifier.EndTable();
+  }
+};
+
+struct LSTMOptionsBuilder
+{
+  typedef LSTMOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(onert_tflite::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(onert_tflite::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,
+                  onert_tflite::ActivationFunctionType fused_activation_function =
+                    onert_tflite::ActivationFunctionType_NONE,
+                  float cell_clip = 0.0f, float proj_clip = 0.0f,
+                  onert_tflite::LSTMKernelType kernel_type = onert_tflite::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();
+}
+
+struct UnidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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
+  };
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<float>(verifier, VT_CELL_CLIP, 4) &&
+           VerifyField<float>(verifier, VT_PROJ_CLIP, 4) &&
+           VerifyField<uint8_t>(verifier, VT_TIME_MAJOR, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && verifier.EndTable();
+  }
+};
+
+struct UnidirectionalSequenceLSTMOptionsBuilder
+{
+  typedef UnidirectionalSequenceLSTMOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(onert_tflite::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,
+  onert_tflite::ActivationFunctionType fused_activation_function =
+    onert_tflite::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();
+}
+
+struct BidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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
+  };
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<float>(verifier, VT_CELL_CLIP, 4) &&
+           VerifyField<float>(verifier, VT_PROJ_CLIP, 4) &&
+           VerifyField<uint8_t>(verifier, VT_MERGE_OUTPUTS, 1) &&
+           VerifyField<uint8_t>(verifier, VT_TIME_MAJOR, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && verifier.EndTable();
+  }
+};
+
+struct BidirectionalSequenceLSTMOptionsBuilder
+{
+  typedef BidirectionalSequenceLSTMOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(onert_tflite::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,
+  onert_tflite::ActivationFunctionType fused_activation_function =
+    onert_tflite::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();
+}
+
+struct ResizeBilinearOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_HALF_PIXEL_CENTERS, 1) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct ResizeNearestNeighborOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_HALF_PIXEL_CENTERS, 1) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct CallOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct PadOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef PadOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct PadV2Options FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef PadV2OptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct ReshapeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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();
+  }
+};
+
+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 onert_tflite::CreateReshapeOptions(_fbb, new_shape__);
+}
+
+struct SpaceToBatchNDOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SpaceToBatchNDOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct BatchToSpaceNDOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef BatchToSpaceNDOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SkipGramOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           VerifyField<int32_t>(verifier, VT_MAX_SKIP_SIZE, 4) &&
+           VerifyField<uint8_t>(verifier, VT_INCLUDE_ALL_NGRAMS, 1) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SpaceToDepthOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct DepthToSpaceOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SubOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SubOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_FUSED_ACTIVATION_FUNCTION = 4,
+    VT_POT_SCALE_INT16 = 6
+  };
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_POT_SCALE_INT16, 1) && verifier.EndTable();
+  }
+};
+
+struct SubOptionsBuilder
+{
+  typedef SubOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(onert_tflite::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,
+                 onert_tflite::ActivationFunctionType fused_activation_function =
+                   onert_tflite::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();
+}
+
+struct DivOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef DivOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_FUSED_ACTIVATION_FUNCTION = 4
+  };
+  onert_tflite::ActivationFunctionType fused_activation_function() const
+  {
+    return static_cast<onert_tflite::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, 1) && verifier.EndTable();
+  }
+};
+
+struct DivOptionsBuilder
+{
+  typedef DivOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_fused_activation_function(onert_tflite::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,
+                 onert_tflite::ActivationFunctionType fused_activation_function =
+                   onert_tflite::ActivationFunctionType_NONE)
+{
+  DivOptionsBuilder builder_(_fbb);
+  builder_.add_fused_activation_function(fused_activation_function);
+  return builder_.Finish();
+}
+
+struct TopKV2Options FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef TopKV2OptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct EmbeddingLookupSparseOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef EmbeddingLookupSparseOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_COMBINER = 4
+  };
+  onert_tflite::CombinerType combiner() const
+  {
+    return static_cast<onert_tflite::CombinerType>(GetField<int8_t>(VT_COMBINER, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_COMBINER, 1) &&
+           verifier.EndTable();
+  }
+};
+
+struct EmbeddingLookupSparseOptionsBuilder
+{
+  typedef EmbeddingLookupSparseOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_combiner(onert_tflite::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,
+  onert_tflite::CombinerType combiner = onert_tflite::CombinerType_SUM)
+{
+  EmbeddingLookupSparseOptionsBuilder builder_(_fbb);
+  builder_.add_combiner(combiner);
+  return builder_.Finish();
+}
+
+struct GatherOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           VerifyField<int32_t>(verifier, VT_BATCH_DIMS, 4) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct TransposeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef TransposeOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct ExpOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ExpOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct CosOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef CosOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct ReducerOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 1) &&
+           verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SqueezeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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();
+  }
+};
+
+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 onert_tflite::CreateSqueezeOptions(_fbb, squeeze_dims__);
+}
+
+struct SplitOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SplitVOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct StridedSliceOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           VerifyField<int32_t>(verifier, VT_END_MASK, 4) &&
+           VerifyField<int32_t>(verifier, VT_ELLIPSIS_MASK, 4) &&
+           VerifyField<int32_t>(verifier, VT_NEW_AXIS_MASK, 4) &&
+           VerifyField<int32_t>(verifier, VT_SHRINK_AXIS_MASK, 4) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct LogSoftmaxOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef LogSoftmaxOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct CastOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef CastOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_IN_DATA_TYPE = 4,
+    VT_OUT_DATA_TYPE = 6
+  };
+  onert_tflite::TensorType in_data_type() const
+  {
+    return static_cast<onert_tflite::TensorType>(GetField<int8_t>(VT_IN_DATA_TYPE, 0));
+  }
+  onert_tflite::TensorType out_data_type() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<int8_t>(verifier, VT_OUT_DATA_TYPE, 1) && verifier.EndTable();
+  }
+};
+
+struct CastOptionsBuilder
+{
+  typedef CastOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_in_data_type(onert_tflite::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(onert_tflite::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,
+                  onert_tflite::TensorType in_data_type = onert_tflite::TensorType_FLOAT32,
+                  onert_tflite::TensorType out_data_type = onert_tflite::TensorType_FLOAT32)
+{
+  CastOptionsBuilder builder_(_fbb);
+  builder_.add_out_data_type(out_data_type);
+  builder_.add_in_data_type(in_data_type);
+  return builder_.Finish();
+}
+
+struct DequantizeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef DequantizeOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct MaximumMinimumOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef MaximumMinimumOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct TileOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef TileOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct ArgMaxOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ArgMaxOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_OUTPUT_TYPE = 4
+  };
+  onert_tflite::TensorType output_type() const
+  {
+    return static_cast<onert_tflite::TensorType>(GetField<int8_t>(VT_OUTPUT_TYPE, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_OUTPUT_TYPE, 1) &&
+           verifier.EndTable();
+  }
+};
+
+struct ArgMaxOptionsBuilder
+{
+  typedef ArgMaxOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_output_type(onert_tflite::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,
+                    onert_tflite::TensorType output_type = onert_tflite::TensorType_FLOAT32)
+{
+  ArgMaxOptionsBuilder builder_(_fbb);
+  builder_.add_output_type(output_type);
+  return builder_.Finish();
+}
+
+struct ArgMinOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ArgMinOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_OUTPUT_TYPE = 4
+  };
+  onert_tflite::TensorType output_type() const
+  {
+    return static_cast<onert_tflite::TensorType>(GetField<int8_t>(VT_OUTPUT_TYPE, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_OUTPUT_TYPE, 1) &&
+           verifier.EndTable();
+  }
+};
+
+struct ArgMinOptionsBuilder
+{
+  typedef ArgMinOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_output_type(onert_tflite::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,
+                    onert_tflite::TensorType output_type = onert_tflite::TensorType_FLOAT32)
+{
+  ArgMinOptionsBuilder builder_(_fbb);
+  builder_.add_output_type(output_type);
+  return builder_.Finish();
+}
+
+struct GreaterOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef GreaterOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct GreaterEqualOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef GreaterEqualOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct LessOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef LessOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct LessEqualOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef LessEqualOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct NegOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef NegOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SelectOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SelectOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SliceOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SliceOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct TransposeConvOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef TransposeConvOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_PADDING = 4,
+    VT_STRIDE_W = 6,
+    VT_STRIDE_H = 8
+  };
+  onert_tflite::Padding padding() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_W, 4) &&
+           VerifyField<int32_t>(verifier, VT_STRIDE_H, 4) && verifier.EndTable();
+  }
+};
+
+struct TransposeConvOptionsBuilder
+{
+  typedef TransposeConvOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_padding(onert_tflite::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,
+                           onert_tflite::Padding padding = onert_tflite::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();
+}
+
+struct ExpandDimsOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ExpandDimsOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SparseToDenseOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 1) &&
+           verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct EqualOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef EqualOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct NotEqualOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef NotEqualOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct ShapeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ShapeOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_OUT_TYPE = 4
+  };
+  onert_tflite::TensorType out_type() const
+  {
+    return static_cast<onert_tflite::TensorType>(GetField<int8_t>(VT_OUT_TYPE, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_OUT_TYPE, 1) &&
+           verifier.EndTable();
+  }
+};
+
+struct ShapeOptionsBuilder
+{
+  typedef ShapeOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_out_type(onert_tflite::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,
+                   onert_tflite::TensorType out_type = onert_tflite::TensorType_FLOAT32)
+{
+  ShapeOptionsBuilder builder_(_fbb);
+  builder_.add_out_type(out_type);
+  return builder_.Finish();
+}
+
+struct RankOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef RankOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct PowOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef PowOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct FakeQuantOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           VerifyField<float>(verifier, VT_MAX, 4) &&
+           VerifyField<int32_t>(verifier, VT_NUM_BITS, 4) &&
+           VerifyField<uint8_t>(verifier, VT_NARROW_RANGE, 1) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct PackOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           VerifyField<int32_t>(verifier, VT_AXIS, 4) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct LogicalOrOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef LogicalOrOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct OneHotOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct AbsOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef AbsOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct HardSwishOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef HardSwishOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct LogicalAndOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef LogicalAndOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct LogicalNotOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef LogicalNotOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct UnpackOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           VerifyField<int32_t>(verifier, VT_AXIS, 4) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct FloorDivOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef FloorDivOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SquareOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SquareOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct ZerosLikeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ZerosLikeOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct FillOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef FillOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct FloorModOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef FloorModOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct RangeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef RangeOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct LeakyReluOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SquaredDifferenceOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SquaredDifferenceOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct MirrorPadOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef MirrorPadOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_MODE = 4
+  };
+  onert_tflite::MirrorPadMode mode() const
+  {
+    return static_cast<onert_tflite::MirrorPadMode>(GetField<int8_t>(VT_MODE, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_MODE, 1) &&
+           verifier.EndTable();
+  }
+};
+
+struct MirrorPadOptionsBuilder
+{
+  typedef MirrorPadOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_mode(onert_tflite::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,
+                       onert_tflite::MirrorPadMode mode = onert_tflite::MirrorPadMode_REFLECT)
+{
+  MirrorPadOptionsBuilder builder_(_fbb);
+  builder_.add_mode(mode);
+  return builder_.Finish();
+}
+
+struct UniqueOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef UniqueOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_IDX_OUT_TYPE = 4
+  };
+  onert_tflite::TensorType idx_out_type() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           verifier.EndTable();
+  }
+};
+
+struct UniqueOptionsBuilder
+{
+  typedef UniqueOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_idx_out_type(onert_tflite::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,
+                    onert_tflite::TensorType idx_out_type = onert_tflite::TensorType_INT32)
+{
+  UniqueOptionsBuilder builder_(_fbb);
+  builder_.add_idx_out_type(idx_out_type);
+  return builder_.Finish();
+}
+
+struct ReverseV2Options FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ReverseV2OptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct AddNOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef AddNOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct GatherNdOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef GatherNdOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct WhereOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef WhereOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct ReverseSequenceOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           VerifyField<int32_t>(verifier, VT_BATCH_DIM, 4) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct MatrixDiagOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef MatrixDiagOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct QuantizeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef QuantizeOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct MatrixSetDiagOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef MatrixSetDiagOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct IfOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           VerifyField<int32_t>(verifier, VT_ELSE_SUBGRAPH_INDEX, 4) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct CallOnceOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct WhileOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           VerifyField<int32_t>(verifier, VT_BODY_SUBGRAPH_INDEX, 4) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct NonMaxSuppressionV4Options FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef NonMaxSuppressionV4OptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct NonMaxSuppressionV5Options FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef NonMaxSuppressionV5OptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct ScatterNdOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ScatterNdOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SelectV2Options FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SelectV2OptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct DensifyOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef DensifyOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct SegmentSumOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SegmentSumOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct BatchMatMulOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef BatchMatMulOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_ADJ_X = 4,
+    VT_ADJ_Y = 6,
+    VT_ASYMMETRIC_QUANTIZE_INPUTS = 8
+  };
+  bool adj_x() const { return GetField<uint8_t>(VT_ADJ_X, 0) != 0; }
+  bool adj_y() const { return GetField<uint8_t>(VT_ADJ_Y, 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_ADJ_X, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ADJ_Y, 1) &&
+           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS, 1) && verifier.EndTable();
+  }
+};
+
+struct BatchMatMulOptionsBuilder
+{
+  typedef BatchMatMulOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_adj_x(bool adj_x)
+  {
+    fbb_.AddElement<uint8_t>(BatchMatMulOptions::VT_ADJ_X, static_cast<uint8_t>(adj_x), 0);
+  }
+  void add_adj_y(bool adj_y)
+  {
+    fbb_.AddElement<uint8_t>(BatchMatMulOptions::VT_ADJ_Y, static_cast<uint8_t>(adj_y), 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 adj_x = false,
+                         bool adj_y = false, bool asymmetric_quantize_inputs = false)
+{
+  BatchMatMulOptionsBuilder builder_(_fbb);
+  builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
+  builder_.add_adj_y(adj_y);
+  builder_.add_adj_x(adj_x);
+  return builder_.Finish();
+}
+
+struct CumsumOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 1) &&
+           VerifyField<uint8_t>(verifier, VT_REVERSE, 1) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct BroadcastToOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef BroadcastToOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct Rfft2dOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef Rfft2dOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct HashtableOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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); }
+  onert_tflite::TensorType key_dtype() const
+  {
+    return static_cast<onert_tflite::TensorType>(GetField<int8_t>(VT_KEY_DTYPE, 0));
+  }
+  onert_tflite::TensorType value_dtype() const
+  {
+    return static_cast<onert_tflite::TensorType>(GetField<int8_t>(VT_VALUE_DTYPE, 0));
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<int32_t>(verifier, VT_TABLE_ID, 4) &&
+           VerifyField<int8_t>(verifier, VT_KEY_DTYPE, 1) &&
+           VerifyField<int8_t>(verifier, VT_VALUE_DTYPE, 1) && verifier.EndTable();
+  }
+};
+
+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(onert_tflite::TensorType key_dtype)
+  {
+    fbb_.AddElement<int8_t>(HashtableOptions::VT_KEY_DTYPE, static_cast<int8_t>(key_dtype), 0);
+  }
+  void add_value_dtype(onert_tflite::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,
+                       onert_tflite::TensorType key_dtype = onert_tflite::TensorType_FLOAT32,
+                       onert_tflite::TensorType value_dtype = onert_tflite::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();
+}
+
+struct HashtableFindOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef HashtableFindOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct HashtableImportOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef HashtableImportOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct HashtableSizeOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef HashtableSizeOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct VarHandleOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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();
+  }
+};
+
+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 onert_tflite::CreateVarHandleOptions(_fbb, container__, shared_name__);
+}
+
+struct ReadVariableOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef ReadVariableOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct AssignVariableOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef AssignVariableOptionsBuilder Builder;
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && verifier.EndTable();
+  }
+};
+
+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();
+}
+
+struct RandomOptions FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef RandomOptionsBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_SEED = 4,
+    VT_SEED2 = 6
+  };
+  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<int64_t>(verifier, VT_SEED, 8) &&
+           VerifyField<int64_t>(verifier, VT_SEED2, 8) && verifier.EndTable();
+  }
+};
+
+struct RandomOptionsBuilder
+{
+  typedef RandomOptions Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  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();
+  }
+  ::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, int64_t seed = 0, int64_t seed2 = 0)
+{
+  RandomOptionsBuilder builder_(_fbb);
+  builder_.add_seed2(seed2);
+  builder_.add_seed(seed);
+  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, 1) &&
+           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;
+  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); }
+  onert_tflite::BuiltinOperator builtin_code() const
+  {
+    return static_cast<onert_tflite::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, 1) &&
+           VerifyOffset(verifier, VT_CUSTOM_CODE) && verifier.VerifyString(custom_code()) &&
+           VerifyField<int32_t>(verifier, VT_VERSION, 4) &&
+           VerifyField<int32_t>(verifier, VT_BUILTIN_CODE, 4) && verifier.EndTable();
+  }
+};
+
+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(onert_tflite::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,
+                   onert_tflite::BuiltinOperator builtin_code = onert_tflite::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,
+  onert_tflite::BuiltinOperator builtin_code = onert_tflite::BuiltinOperator_ADD)
+{
+  auto custom_code__ = custom_code ? _fbb.CreateString(custom_code) : 0;
+  return onert_tflite::CreateOperatorCode(_fbb, deprecated_builtin_code, custom_code__, version,
+                                          builtin_code);
+}
+
+struct Operator FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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);
+  }
+  onert_tflite::BuiltinOptions builtin_options_type() const
+  {
+    return static_cast<onert_tflite::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 onert_tflite::Conv2DOptions *builtin_options_as_Conv2DOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_Conv2DOptions
+             ? static_cast<const onert_tflite::Conv2DOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::DepthwiseConv2DOptions *builtin_options_as_DepthwiseConv2DOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_DepthwiseConv2DOptions
+             ? static_cast<const onert_tflite::DepthwiseConv2DOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ConcatEmbeddingsOptions *builtin_options_as_ConcatEmbeddingsOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ConcatEmbeddingsOptions
+             ? static_cast<const onert_tflite::ConcatEmbeddingsOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::LSHProjectionOptions *builtin_options_as_LSHProjectionOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_LSHProjectionOptions
+             ? static_cast<const onert_tflite::LSHProjectionOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::Pool2DOptions *builtin_options_as_Pool2DOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_Pool2DOptions
+             ? static_cast<const onert_tflite::Pool2DOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SVDFOptions *builtin_options_as_SVDFOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SVDFOptions
+             ? static_cast<const onert_tflite::SVDFOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::RNNOptions *builtin_options_as_RNNOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_RNNOptions
+             ? static_cast<const onert_tflite::RNNOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::FullyConnectedOptions *builtin_options_as_FullyConnectedOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_FullyConnectedOptions
+             ? static_cast<const onert_tflite::FullyConnectedOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SoftmaxOptions *builtin_options_as_SoftmaxOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SoftmaxOptions
+             ? static_cast<const onert_tflite::SoftmaxOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ConcatenationOptions *builtin_options_as_ConcatenationOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ConcatenationOptions
+             ? static_cast<const onert_tflite::ConcatenationOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::AddOptions *builtin_options_as_AddOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_AddOptions
+             ? static_cast<const onert_tflite::AddOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::L2NormOptions *builtin_options_as_L2NormOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_L2NormOptions
+             ? static_cast<const onert_tflite::L2NormOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::LocalResponseNormalizationOptions *
+  builtin_options_as_LocalResponseNormalizationOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_LocalResponseNormalizationOptions
+             ? static_cast<const onert_tflite::LocalResponseNormalizationOptions *>(
+                 builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::LSTMOptions *builtin_options_as_LSTMOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_LSTMOptions
+             ? static_cast<const onert_tflite::LSTMOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ResizeBilinearOptions *builtin_options_as_ResizeBilinearOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ResizeBilinearOptions
+             ? static_cast<const onert_tflite::ResizeBilinearOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::CallOptions *builtin_options_as_CallOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_CallOptions
+             ? static_cast<const onert_tflite::CallOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ReshapeOptions *builtin_options_as_ReshapeOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ReshapeOptions
+             ? static_cast<const onert_tflite::ReshapeOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SkipGramOptions *builtin_options_as_SkipGramOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SkipGramOptions
+             ? static_cast<const onert_tflite::SkipGramOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SpaceToDepthOptions *builtin_options_as_SpaceToDepthOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SpaceToDepthOptions
+             ? static_cast<const onert_tflite::SpaceToDepthOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::EmbeddingLookupSparseOptions *
+  builtin_options_as_EmbeddingLookupSparseOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_EmbeddingLookupSparseOptions
+             ? static_cast<const onert_tflite::EmbeddingLookupSparseOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::MulOptions *builtin_options_as_MulOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_MulOptions
+             ? static_cast<const onert_tflite::MulOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::PadOptions *builtin_options_as_PadOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_PadOptions
+             ? static_cast<const onert_tflite::PadOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::GatherOptions *builtin_options_as_GatherOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_GatherOptions
+             ? static_cast<const onert_tflite::GatherOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::BatchToSpaceNDOptions *builtin_options_as_BatchToSpaceNDOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_BatchToSpaceNDOptions
+             ? static_cast<const onert_tflite::BatchToSpaceNDOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SpaceToBatchNDOptions *builtin_options_as_SpaceToBatchNDOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SpaceToBatchNDOptions
+             ? static_cast<const onert_tflite::SpaceToBatchNDOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::TransposeOptions *builtin_options_as_TransposeOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_TransposeOptions
+             ? static_cast<const onert_tflite::TransposeOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ReducerOptions *builtin_options_as_ReducerOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ReducerOptions
+             ? static_cast<const onert_tflite::ReducerOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SubOptions *builtin_options_as_SubOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SubOptions
+             ? static_cast<const onert_tflite::SubOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::DivOptions *builtin_options_as_DivOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_DivOptions
+             ? static_cast<const onert_tflite::DivOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SqueezeOptions *builtin_options_as_SqueezeOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SqueezeOptions
+             ? static_cast<const onert_tflite::SqueezeOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SequenceRNNOptions *builtin_options_as_SequenceRNNOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SequenceRNNOptions
+             ? static_cast<const onert_tflite::SequenceRNNOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::StridedSliceOptions *builtin_options_as_StridedSliceOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_StridedSliceOptions
+             ? static_cast<const onert_tflite::StridedSliceOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ExpOptions *builtin_options_as_ExpOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ExpOptions
+             ? static_cast<const onert_tflite::ExpOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::TopKV2Options *builtin_options_as_TopKV2Options() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_TopKV2Options
+             ? static_cast<const onert_tflite::TopKV2Options *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SplitOptions *builtin_options_as_SplitOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SplitOptions
+             ? static_cast<const onert_tflite::SplitOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::LogSoftmaxOptions *builtin_options_as_LogSoftmaxOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_LogSoftmaxOptions
+             ? static_cast<const onert_tflite::LogSoftmaxOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::CastOptions *builtin_options_as_CastOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_CastOptions
+             ? static_cast<const onert_tflite::CastOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::DequantizeOptions *builtin_options_as_DequantizeOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_DequantizeOptions
+             ? static_cast<const onert_tflite::DequantizeOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::MaximumMinimumOptions *builtin_options_as_MaximumMinimumOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_MaximumMinimumOptions
+             ? static_cast<const onert_tflite::MaximumMinimumOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ArgMaxOptions *builtin_options_as_ArgMaxOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ArgMaxOptions
+             ? static_cast<const onert_tflite::ArgMaxOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::LessOptions *builtin_options_as_LessOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_LessOptions
+             ? static_cast<const onert_tflite::LessOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::NegOptions *builtin_options_as_NegOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_NegOptions
+             ? static_cast<const onert_tflite::NegOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::PadV2Options *builtin_options_as_PadV2Options() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_PadV2Options
+             ? static_cast<const onert_tflite::PadV2Options *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::GreaterOptions *builtin_options_as_GreaterOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_GreaterOptions
+             ? static_cast<const onert_tflite::GreaterOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::GreaterEqualOptions *builtin_options_as_GreaterEqualOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_GreaterEqualOptions
+             ? static_cast<const onert_tflite::GreaterEqualOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::LessEqualOptions *builtin_options_as_LessEqualOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_LessEqualOptions
+             ? static_cast<const onert_tflite::LessEqualOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SelectOptions *builtin_options_as_SelectOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SelectOptions
+             ? static_cast<const onert_tflite::SelectOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SliceOptions *builtin_options_as_SliceOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SliceOptions
+             ? static_cast<const onert_tflite::SliceOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::TransposeConvOptions *builtin_options_as_TransposeConvOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_TransposeConvOptions
+             ? static_cast<const onert_tflite::TransposeConvOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SparseToDenseOptions *builtin_options_as_SparseToDenseOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SparseToDenseOptions
+             ? static_cast<const onert_tflite::SparseToDenseOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::TileOptions *builtin_options_as_TileOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_TileOptions
+             ? static_cast<const onert_tflite::TileOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ExpandDimsOptions *builtin_options_as_ExpandDimsOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ExpandDimsOptions
+             ? static_cast<const onert_tflite::ExpandDimsOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::EqualOptions *builtin_options_as_EqualOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_EqualOptions
+             ? static_cast<const onert_tflite::EqualOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::NotEqualOptions *builtin_options_as_NotEqualOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_NotEqualOptions
+             ? static_cast<const onert_tflite::NotEqualOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ShapeOptions *builtin_options_as_ShapeOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ShapeOptions
+             ? static_cast<const onert_tflite::ShapeOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::PowOptions *builtin_options_as_PowOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_PowOptions
+             ? static_cast<const onert_tflite::PowOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ArgMinOptions *builtin_options_as_ArgMinOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ArgMinOptions
+             ? static_cast<const onert_tflite::ArgMinOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::FakeQuantOptions *builtin_options_as_FakeQuantOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_FakeQuantOptions
+             ? static_cast<const onert_tflite::FakeQuantOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::PackOptions *builtin_options_as_PackOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_PackOptions
+             ? static_cast<const onert_tflite::PackOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::LogicalOrOptions *builtin_options_as_LogicalOrOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_LogicalOrOptions
+             ? static_cast<const onert_tflite::LogicalOrOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::OneHotOptions *builtin_options_as_OneHotOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_OneHotOptions
+             ? static_cast<const onert_tflite::OneHotOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::LogicalAndOptions *builtin_options_as_LogicalAndOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_LogicalAndOptions
+             ? static_cast<const onert_tflite::LogicalAndOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::LogicalNotOptions *builtin_options_as_LogicalNotOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_LogicalNotOptions
+             ? static_cast<const onert_tflite::LogicalNotOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::UnpackOptions *builtin_options_as_UnpackOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_UnpackOptions
+             ? static_cast<const onert_tflite::UnpackOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::FloorDivOptions *builtin_options_as_FloorDivOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_FloorDivOptions
+             ? static_cast<const onert_tflite::FloorDivOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SquareOptions *builtin_options_as_SquareOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SquareOptions
+             ? static_cast<const onert_tflite::SquareOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ZerosLikeOptions *builtin_options_as_ZerosLikeOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ZerosLikeOptions
+             ? static_cast<const onert_tflite::ZerosLikeOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::FillOptions *builtin_options_as_FillOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_FillOptions
+             ? static_cast<const onert_tflite::FillOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::BidirectionalSequenceLSTMOptions *
+  builtin_options_as_BidirectionalSequenceLSTMOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_BidirectionalSequenceLSTMOptions
+             ? static_cast<const onert_tflite::BidirectionalSequenceLSTMOptions *>(
+                 builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::BidirectionalSequenceRNNOptions *
+  builtin_options_as_BidirectionalSequenceRNNOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_BidirectionalSequenceRNNOptions
+             ? static_cast<const onert_tflite::BidirectionalSequenceRNNOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::UnidirectionalSequenceLSTMOptions *
+  builtin_options_as_UnidirectionalSequenceLSTMOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_UnidirectionalSequenceLSTMOptions
+             ? static_cast<const onert_tflite::UnidirectionalSequenceLSTMOptions *>(
+                 builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::FloorModOptions *builtin_options_as_FloorModOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_FloorModOptions
+             ? static_cast<const onert_tflite::FloorModOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::RangeOptions *builtin_options_as_RangeOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_RangeOptions
+             ? static_cast<const onert_tflite::RangeOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ResizeNearestNeighborOptions *
+  builtin_options_as_ResizeNearestNeighborOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ResizeNearestNeighborOptions
+             ? static_cast<const onert_tflite::ResizeNearestNeighborOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::LeakyReluOptions *builtin_options_as_LeakyReluOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_LeakyReluOptions
+             ? static_cast<const onert_tflite::LeakyReluOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SquaredDifferenceOptions *builtin_options_as_SquaredDifferenceOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SquaredDifferenceOptions
+             ? static_cast<const onert_tflite::SquaredDifferenceOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::MirrorPadOptions *builtin_options_as_MirrorPadOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_MirrorPadOptions
+             ? static_cast<const onert_tflite::MirrorPadOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::AbsOptions *builtin_options_as_AbsOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_AbsOptions
+             ? static_cast<const onert_tflite::AbsOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SplitVOptions *builtin_options_as_SplitVOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SplitVOptions
+             ? static_cast<const onert_tflite::SplitVOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::UniqueOptions *builtin_options_as_UniqueOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_UniqueOptions
+             ? static_cast<const onert_tflite::UniqueOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ReverseV2Options *builtin_options_as_ReverseV2Options() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ReverseV2Options
+             ? static_cast<const onert_tflite::ReverseV2Options *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::AddNOptions *builtin_options_as_AddNOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_AddNOptions
+             ? static_cast<const onert_tflite::AddNOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::GatherNdOptions *builtin_options_as_GatherNdOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_GatherNdOptions
+             ? static_cast<const onert_tflite::GatherNdOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::CosOptions *builtin_options_as_CosOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_CosOptions
+             ? static_cast<const onert_tflite::CosOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::WhereOptions *builtin_options_as_WhereOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_WhereOptions
+             ? static_cast<const onert_tflite::WhereOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::RankOptions *builtin_options_as_RankOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_RankOptions
+             ? static_cast<const onert_tflite::RankOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ReverseSequenceOptions *builtin_options_as_ReverseSequenceOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ReverseSequenceOptions
+             ? static_cast<const onert_tflite::ReverseSequenceOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::MatrixDiagOptions *builtin_options_as_MatrixDiagOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_MatrixDiagOptions
+             ? static_cast<const onert_tflite::MatrixDiagOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::QuantizeOptions *builtin_options_as_QuantizeOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_QuantizeOptions
+             ? static_cast<const onert_tflite::QuantizeOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::MatrixSetDiagOptions *builtin_options_as_MatrixSetDiagOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_MatrixSetDiagOptions
+             ? static_cast<const onert_tflite::MatrixSetDiagOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::HardSwishOptions *builtin_options_as_HardSwishOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_HardSwishOptions
+             ? static_cast<const onert_tflite::HardSwishOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::IfOptions *builtin_options_as_IfOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_IfOptions
+             ? static_cast<const onert_tflite::IfOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::WhileOptions *builtin_options_as_WhileOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_WhileOptions
+             ? static_cast<const onert_tflite::WhileOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::DepthToSpaceOptions *builtin_options_as_DepthToSpaceOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_DepthToSpaceOptions
+             ? static_cast<const onert_tflite::DepthToSpaceOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::NonMaxSuppressionV4Options *
+  builtin_options_as_NonMaxSuppressionV4Options() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_NonMaxSuppressionV4Options
+             ? static_cast<const onert_tflite::NonMaxSuppressionV4Options *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::NonMaxSuppressionV5Options *
+  builtin_options_as_NonMaxSuppressionV5Options() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_NonMaxSuppressionV5Options
+             ? static_cast<const onert_tflite::NonMaxSuppressionV5Options *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ScatterNdOptions *builtin_options_as_ScatterNdOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ScatterNdOptions
+             ? static_cast<const onert_tflite::ScatterNdOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SelectV2Options *builtin_options_as_SelectV2Options() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SelectV2Options
+             ? static_cast<const onert_tflite::SelectV2Options *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::DensifyOptions *builtin_options_as_DensifyOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_DensifyOptions
+             ? static_cast<const onert_tflite::DensifyOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::SegmentSumOptions *builtin_options_as_SegmentSumOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_SegmentSumOptions
+             ? static_cast<const onert_tflite::SegmentSumOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::BatchMatMulOptions *builtin_options_as_BatchMatMulOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_BatchMatMulOptions
+             ? static_cast<const onert_tflite::BatchMatMulOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::CumsumOptions *builtin_options_as_CumsumOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_CumsumOptions
+             ? static_cast<const onert_tflite::CumsumOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::CallOnceOptions *builtin_options_as_CallOnceOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_CallOnceOptions
+             ? static_cast<const onert_tflite::CallOnceOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::BroadcastToOptions *builtin_options_as_BroadcastToOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_BroadcastToOptions
+             ? static_cast<const onert_tflite::BroadcastToOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::Rfft2dOptions *builtin_options_as_Rfft2dOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_Rfft2dOptions
+             ? static_cast<const onert_tflite::Rfft2dOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::Conv3DOptions *builtin_options_as_Conv3DOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_Conv3DOptions
+             ? static_cast<const onert_tflite::Conv3DOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::HashtableOptions *builtin_options_as_HashtableOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_HashtableOptions
+             ? static_cast<const onert_tflite::HashtableOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::HashtableFindOptions *builtin_options_as_HashtableFindOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_HashtableFindOptions
+             ? static_cast<const onert_tflite::HashtableFindOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::HashtableImportOptions *builtin_options_as_HashtableImportOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_HashtableImportOptions
+             ? static_cast<const onert_tflite::HashtableImportOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::HashtableSizeOptions *builtin_options_as_HashtableSizeOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_HashtableSizeOptions
+             ? static_cast<const onert_tflite::HashtableSizeOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::VarHandleOptions *builtin_options_as_VarHandleOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_VarHandleOptions
+             ? static_cast<const onert_tflite::VarHandleOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::ReadVariableOptions *builtin_options_as_ReadVariableOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_ReadVariableOptions
+             ? static_cast<const onert_tflite::ReadVariableOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::AssignVariableOptions *builtin_options_as_AssignVariableOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_AssignVariableOptions
+             ? static_cast<const onert_tflite::AssignVariableOptions *>(builtin_options())
+             : nullptr;
+  }
+  const onert_tflite::RandomOptions *builtin_options_as_RandomOptions() const
+  {
+    return builtin_options_type() == onert_tflite::BuiltinOptions_RandomOptions
+             ? 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);
+  }
+  onert_tflite::CustomOptionsFormat custom_options_format() const
+  {
+    return static_cast<onert_tflite::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, 4) &&
+           VerifyOffset(verifier, VT_INPUTS) && verifier.VerifyVector(inputs()) &&
+           VerifyOffset(verifier, VT_OUTPUTS) && verifier.VerifyVector(outputs()) &&
+           VerifyField<uint8_t>(verifier, VT_BUILTIN_OPTIONS_TYPE, 1) &&
+           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, 1) &&
+           VerifyOffset(verifier, VT_MUTATING_VARIABLE_INPUTS) &&
+           verifier.VerifyVector(mutating_variable_inputs()) &&
+           VerifyOffset(verifier, VT_INTERMEDIATES) && verifier.VerifyVector(intermediates()) &&
+           verifier.EndTable();
+  }
+};
+
+template <>
+inline const onert_tflite::Conv2DOptions *
+Operator::builtin_options_as<onert_tflite::Conv2DOptions>() const
+{
+  return builtin_options_as_Conv2DOptions();
+}
+
+template <>
+inline const onert_tflite::DepthwiseConv2DOptions *
+Operator::builtin_options_as<onert_tflite::DepthwiseConv2DOptions>() const
+{
+  return builtin_options_as_DepthwiseConv2DOptions();
+}
+
+template <>
+inline const onert_tflite::ConcatEmbeddingsOptions *
+Operator::builtin_options_as<onert_tflite::ConcatEmbeddingsOptions>() const
+{
+  return builtin_options_as_ConcatEmbeddingsOptions();
+}
+
+template <>
+inline const onert_tflite::LSHProjectionOptions *
+Operator::builtin_options_as<onert_tflite::LSHProjectionOptions>() const
+{
+  return builtin_options_as_LSHProjectionOptions();
+}
+
+template <>
+inline const onert_tflite::Pool2DOptions *
+Operator::builtin_options_as<onert_tflite::Pool2DOptions>() const
+{
+  return builtin_options_as_Pool2DOptions();
+}
+
+template <>
+inline const onert_tflite::SVDFOptions *
+Operator::builtin_options_as<onert_tflite::SVDFOptions>() const
+{
+  return builtin_options_as_SVDFOptions();
+}
+
+template <>
+inline const onert_tflite::RNNOptions *
+Operator::builtin_options_as<onert_tflite::RNNOptions>() const
+{
+  return builtin_options_as_RNNOptions();
+}
+
+template <>
+inline const onert_tflite::FullyConnectedOptions *
+Operator::builtin_options_as<onert_tflite::FullyConnectedOptions>() const
+{
+  return builtin_options_as_FullyConnectedOptions();
+}
+
+template <>
+inline const onert_tflite::SoftmaxOptions *
+Operator::builtin_options_as<onert_tflite::SoftmaxOptions>() const
+{
+  return builtin_options_as_SoftmaxOptions();
+}
+
+template <>
+inline const onert_tflite::ConcatenationOptions *
+Operator::builtin_options_as<onert_tflite::ConcatenationOptions>() const
+{
+  return builtin_options_as_ConcatenationOptions();
+}
+
+template <>
+inline const onert_tflite::AddOptions *
+Operator::builtin_options_as<onert_tflite::AddOptions>() const
+{
+  return builtin_options_as_AddOptions();
+}
+
+template <>
+inline const onert_tflite::L2NormOptions *
+Operator::builtin_options_as<onert_tflite::L2NormOptions>() const
+{
+  return builtin_options_as_L2NormOptions();
+}
+
+template <>
+inline const onert_tflite::LocalResponseNormalizationOptions *
+Operator::builtin_options_as<onert_tflite::LocalResponseNormalizationOptions>() const
+{
+  return builtin_options_as_LocalResponseNormalizationOptions();
+}
+
+template <>
+inline const onert_tflite::LSTMOptions *
+Operator::builtin_options_as<onert_tflite::LSTMOptions>() const
+{
+  return builtin_options_as_LSTMOptions();
+}
+
+template <>
+inline const onert_tflite::ResizeBilinearOptions *
+Operator::builtin_options_as<onert_tflite::ResizeBilinearOptions>() const
+{
+  return builtin_options_as_ResizeBilinearOptions();
+}
+
+template <>
+inline const onert_tflite::CallOptions *
+Operator::builtin_options_as<onert_tflite::CallOptions>() const
+{
+  return builtin_options_as_CallOptions();
+}
+
+template <>
+inline const onert_tflite::ReshapeOptions *
+Operator::builtin_options_as<onert_tflite::ReshapeOptions>() const
+{
+  return builtin_options_as_ReshapeOptions();
+}
+
+template <>
+inline const onert_tflite::SkipGramOptions *
+Operator::builtin_options_as<onert_tflite::SkipGramOptions>() const
+{
+  return builtin_options_as_SkipGramOptions();
+}
+
+template <>
+inline const onert_tflite::SpaceToDepthOptions *
+Operator::builtin_options_as<onert_tflite::SpaceToDepthOptions>() const
+{
+  return builtin_options_as_SpaceToDepthOptions();
+}
+
+template <>
+inline const onert_tflite::EmbeddingLookupSparseOptions *
+Operator::builtin_options_as<onert_tflite::EmbeddingLookupSparseOptions>() const
+{
+  return builtin_options_as_EmbeddingLookupSparseOptions();
+}
+
+template <>
+inline const onert_tflite::MulOptions *
+Operator::builtin_options_as<onert_tflite::MulOptions>() const
+{
+  return builtin_options_as_MulOptions();
+}
+
+template <>
+inline const onert_tflite::PadOptions *
+Operator::builtin_options_as<onert_tflite::PadOptions>() const
+{
+  return builtin_options_as_PadOptions();
+}
+
+template <>
+inline const onert_tflite::GatherOptions *
+Operator::builtin_options_as<onert_tflite::GatherOptions>() const
+{
+  return builtin_options_as_GatherOptions();
+}
+
+template <>
+inline const onert_tflite::BatchToSpaceNDOptions *
+Operator::builtin_options_as<onert_tflite::BatchToSpaceNDOptions>() const
+{
+  return builtin_options_as_BatchToSpaceNDOptions();
+}
+
+template <>
+inline const onert_tflite::SpaceToBatchNDOptions *
+Operator::builtin_options_as<onert_tflite::SpaceToBatchNDOptions>() const
+{
+  return builtin_options_as_SpaceToBatchNDOptions();
+}
+
+template <>
+inline const onert_tflite::TransposeOptions *
+Operator::builtin_options_as<onert_tflite::TransposeOptions>() const
+{
+  return builtin_options_as_TransposeOptions();
+}
+
+template <>
+inline const onert_tflite::ReducerOptions *
+Operator::builtin_options_as<onert_tflite::ReducerOptions>() const
+{
+  return builtin_options_as_ReducerOptions();
+}
+
+template <>
+inline const onert_tflite::SubOptions *
+Operator::builtin_options_as<onert_tflite::SubOptions>() const
+{
+  return builtin_options_as_SubOptions();
+}
+
+template <>
+inline const onert_tflite::DivOptions *
+Operator::builtin_options_as<onert_tflite::DivOptions>() const
+{
+  return builtin_options_as_DivOptions();
+}
+
+template <>
+inline const onert_tflite::SqueezeOptions *
+Operator::builtin_options_as<onert_tflite::SqueezeOptions>() const
+{
+  return builtin_options_as_SqueezeOptions();
+}
+
+template <>
+inline const onert_tflite::SequenceRNNOptions *
+Operator::builtin_options_as<onert_tflite::SequenceRNNOptions>() const
+{
+  return builtin_options_as_SequenceRNNOptions();
+}
+
+template <>
+inline const onert_tflite::StridedSliceOptions *
+Operator::builtin_options_as<onert_tflite::StridedSliceOptions>() const
+{
+  return builtin_options_as_StridedSliceOptions();
+}
+
+template <>
+inline const onert_tflite::ExpOptions *
+Operator::builtin_options_as<onert_tflite::ExpOptions>() const
+{
+  return builtin_options_as_ExpOptions();
+}
+
+template <>
+inline const onert_tflite::TopKV2Options *
+Operator::builtin_options_as<onert_tflite::TopKV2Options>() const
+{
+  return builtin_options_as_TopKV2Options();
+}
+
+template <>
+inline const onert_tflite::SplitOptions *
+Operator::builtin_options_as<onert_tflite::SplitOptions>() const
+{
+  return builtin_options_as_SplitOptions();
+}
+
+template <>
+inline const onert_tflite::LogSoftmaxOptions *
+Operator::builtin_options_as<onert_tflite::LogSoftmaxOptions>() const
+{
+  return builtin_options_as_LogSoftmaxOptions();
+}
+
+template <>
+inline const onert_tflite::CastOptions *
+Operator::builtin_options_as<onert_tflite::CastOptions>() const
+{
+  return builtin_options_as_CastOptions();
+}
+
+template <>
+inline const onert_tflite::DequantizeOptions *
+Operator::builtin_options_as<onert_tflite::DequantizeOptions>() const
+{
+  return builtin_options_as_DequantizeOptions();
+}
+
+template <>
+inline const onert_tflite::MaximumMinimumOptions *
+Operator::builtin_options_as<onert_tflite::MaximumMinimumOptions>() const
+{
+  return builtin_options_as_MaximumMinimumOptions();
+}
+
+template <>
+inline const onert_tflite::ArgMaxOptions *
+Operator::builtin_options_as<onert_tflite::ArgMaxOptions>() const
+{
+  return builtin_options_as_ArgMaxOptions();
+}
+
+template <>
+inline const onert_tflite::LessOptions *
+Operator::builtin_options_as<onert_tflite::LessOptions>() const
+{
+  return builtin_options_as_LessOptions();
+}
+
+template <>
+inline const onert_tflite::NegOptions *
+Operator::builtin_options_as<onert_tflite::NegOptions>() const
+{
+  return builtin_options_as_NegOptions();
+}
+
+template <>
+inline const onert_tflite::PadV2Options *
+Operator::builtin_options_as<onert_tflite::PadV2Options>() const
+{
+  return builtin_options_as_PadV2Options();
+}
+
+template <>
+inline const onert_tflite::GreaterOptions *
+Operator::builtin_options_as<onert_tflite::GreaterOptions>() const
+{
+  return builtin_options_as_GreaterOptions();
+}
+
+template <>
+inline const onert_tflite::GreaterEqualOptions *
+Operator::builtin_options_as<onert_tflite::GreaterEqualOptions>() const
+{
+  return builtin_options_as_GreaterEqualOptions();
+}
+
+template <>
+inline const onert_tflite::LessEqualOptions *
+Operator::builtin_options_as<onert_tflite::LessEqualOptions>() const
+{
+  return builtin_options_as_LessEqualOptions();
+}
+
+template <>
+inline const onert_tflite::SelectOptions *
+Operator::builtin_options_as<onert_tflite::SelectOptions>() const
+{
+  return builtin_options_as_SelectOptions();
+}
+
+template <>
+inline const onert_tflite::SliceOptions *
+Operator::builtin_options_as<onert_tflite::SliceOptions>() const
+{
+  return builtin_options_as_SliceOptions();
+}
+
+template <>
+inline const onert_tflite::TransposeConvOptions *
+Operator::builtin_options_as<onert_tflite::TransposeConvOptions>() const
+{
+  return builtin_options_as_TransposeConvOptions();
+}
+
+template <>
+inline const onert_tflite::SparseToDenseOptions *
+Operator::builtin_options_as<onert_tflite::SparseToDenseOptions>() const
+{
+  return builtin_options_as_SparseToDenseOptions();
+}
+
+template <>
+inline const onert_tflite::TileOptions *
+Operator::builtin_options_as<onert_tflite::TileOptions>() const
+{
+  return builtin_options_as_TileOptions();
+}
+
+template <>
+inline const onert_tflite::ExpandDimsOptions *
+Operator::builtin_options_as<onert_tflite::ExpandDimsOptions>() const
+{
+  return builtin_options_as_ExpandDimsOptions();
+}
+
+template <>
+inline const onert_tflite::EqualOptions *
+Operator::builtin_options_as<onert_tflite::EqualOptions>() const
+{
+  return builtin_options_as_EqualOptions();
+}
+
+template <>
+inline const onert_tflite::NotEqualOptions *
+Operator::builtin_options_as<onert_tflite::NotEqualOptions>() const
+{
+  return builtin_options_as_NotEqualOptions();
+}
+
+template <>
+inline const onert_tflite::ShapeOptions *
+Operator::builtin_options_as<onert_tflite::ShapeOptions>() const
+{
+  return builtin_options_as_ShapeOptions();
+}
+
+template <>
+inline const onert_tflite::PowOptions *
+Operator::builtin_options_as<onert_tflite::PowOptions>() const
+{
+  return builtin_options_as_PowOptions();
+}
+
+template <>
+inline const onert_tflite::ArgMinOptions *
+Operator::builtin_options_as<onert_tflite::ArgMinOptions>() const
+{
+  return builtin_options_as_ArgMinOptions();
+}
+
+template <>
+inline const onert_tflite::FakeQuantOptions *
+Operator::builtin_options_as<onert_tflite::FakeQuantOptions>() const
+{
+  return builtin_options_as_FakeQuantOptions();
+}
+
+template <>
+inline const onert_tflite::PackOptions *
+Operator::builtin_options_as<onert_tflite::PackOptions>() const
+{
+  return builtin_options_as_PackOptions();
+}
+
+template <>
+inline const onert_tflite::LogicalOrOptions *
+Operator::builtin_options_as<onert_tflite::LogicalOrOptions>() const
+{
+  return builtin_options_as_LogicalOrOptions();
+}
+
+template <>
+inline const onert_tflite::OneHotOptions *
+Operator::builtin_options_as<onert_tflite::OneHotOptions>() const
+{
+  return builtin_options_as_OneHotOptions();
+}
+
+template <>
+inline const onert_tflite::LogicalAndOptions *
+Operator::builtin_options_as<onert_tflite::LogicalAndOptions>() const
+{
+  return builtin_options_as_LogicalAndOptions();
+}
+
+template <>
+inline const onert_tflite::LogicalNotOptions *
+Operator::builtin_options_as<onert_tflite::LogicalNotOptions>() const
+{
+  return builtin_options_as_LogicalNotOptions();
+}
+
+template <>
+inline const onert_tflite::UnpackOptions *
+Operator::builtin_options_as<onert_tflite::UnpackOptions>() const
+{
+  return builtin_options_as_UnpackOptions();
+}
+
+template <>
+inline const onert_tflite::FloorDivOptions *
+Operator::builtin_options_as<onert_tflite::FloorDivOptions>() const
+{
+  return builtin_options_as_FloorDivOptions();
+}
+
+template <>
+inline const onert_tflite::SquareOptions *
+Operator::builtin_options_as<onert_tflite::SquareOptions>() const
+{
+  return builtin_options_as_SquareOptions();
+}
+
+template <>
+inline const onert_tflite::ZerosLikeOptions *
+Operator::builtin_options_as<onert_tflite::ZerosLikeOptions>() const
+{
+  return builtin_options_as_ZerosLikeOptions();
+}
+
+template <>
+inline const onert_tflite::FillOptions *
+Operator::builtin_options_as<onert_tflite::FillOptions>() const
+{
+  return builtin_options_as_FillOptions();
+}
+
+template <>
+inline const onert_tflite::BidirectionalSequenceLSTMOptions *
+Operator::builtin_options_as<onert_tflite::BidirectionalSequenceLSTMOptions>() const
+{
+  return builtin_options_as_BidirectionalSequenceLSTMOptions();
+}
+
+template <>
+inline const onert_tflite::BidirectionalSequenceRNNOptions *
+Operator::builtin_options_as<onert_tflite::BidirectionalSequenceRNNOptions>() const
+{
+  return builtin_options_as_BidirectionalSequenceRNNOptions();
+}
+
+template <>
+inline const onert_tflite::UnidirectionalSequenceLSTMOptions *
+Operator::builtin_options_as<onert_tflite::UnidirectionalSequenceLSTMOptions>() const
+{
+  return builtin_options_as_UnidirectionalSequenceLSTMOptions();
+}
+
+template <>
+inline const onert_tflite::FloorModOptions *
+Operator::builtin_options_as<onert_tflite::FloorModOptions>() const
+{
+  return builtin_options_as_FloorModOptions();
+}
+
+template <>
+inline const onert_tflite::RangeOptions *
+Operator::builtin_options_as<onert_tflite::RangeOptions>() const
+{
+  return builtin_options_as_RangeOptions();
+}
+
+template <>
+inline const onert_tflite::ResizeNearestNeighborOptions *
+Operator::builtin_options_as<onert_tflite::ResizeNearestNeighborOptions>() const
+{
+  return builtin_options_as_ResizeNearestNeighborOptions();
+}
+
+template <>
+inline const onert_tflite::LeakyReluOptions *
+Operator::builtin_options_as<onert_tflite::LeakyReluOptions>() const
+{
+  return builtin_options_as_LeakyReluOptions();
+}
+
+template <>
+inline const onert_tflite::SquaredDifferenceOptions *
+Operator::builtin_options_as<onert_tflite::SquaredDifferenceOptions>() const
+{
+  return builtin_options_as_SquaredDifferenceOptions();
+}
+
+template <>
+inline const onert_tflite::MirrorPadOptions *
+Operator::builtin_options_as<onert_tflite::MirrorPadOptions>() const
+{
+  return builtin_options_as_MirrorPadOptions();
+}
+
+template <>
+inline const onert_tflite::AbsOptions *
+Operator::builtin_options_as<onert_tflite::AbsOptions>() const
+{
+  return builtin_options_as_AbsOptions();
+}
+
+template <>
+inline const onert_tflite::SplitVOptions *
+Operator::builtin_options_as<onert_tflite::SplitVOptions>() const
+{
+  return builtin_options_as_SplitVOptions();
+}
+
+template <>
+inline const onert_tflite::UniqueOptions *
+Operator::builtin_options_as<onert_tflite::UniqueOptions>() const
+{
+  return builtin_options_as_UniqueOptions();
+}
+
+template <>
+inline const onert_tflite::ReverseV2Options *
+Operator::builtin_options_as<onert_tflite::ReverseV2Options>() const
+{
+  return builtin_options_as_ReverseV2Options();
+}
+
+template <>
+inline const onert_tflite::AddNOptions *
+Operator::builtin_options_as<onert_tflite::AddNOptions>() const
+{
+  return builtin_options_as_AddNOptions();
+}
+
+template <>
+inline const onert_tflite::GatherNdOptions *
+Operator::builtin_options_as<onert_tflite::GatherNdOptions>() const
+{
+  return builtin_options_as_GatherNdOptions();
+}
+
+template <>
+inline const onert_tflite::CosOptions *
+Operator::builtin_options_as<onert_tflite::CosOptions>() const
+{
+  return builtin_options_as_CosOptions();
+}
+
+template <>
+inline const onert_tflite::WhereOptions *
+Operator::builtin_options_as<onert_tflite::WhereOptions>() const
+{
+  return builtin_options_as_WhereOptions();
+}
+
+template <>
+inline const onert_tflite::RankOptions *
+Operator::builtin_options_as<onert_tflite::RankOptions>() const
+{
+  return builtin_options_as_RankOptions();
+}
+
+template <>
+inline const onert_tflite::ReverseSequenceOptions *
+Operator::builtin_options_as<onert_tflite::ReverseSequenceOptions>() const
+{
+  return builtin_options_as_ReverseSequenceOptions();
+}
+
+template <>
+inline const onert_tflite::MatrixDiagOptions *
+Operator::builtin_options_as<onert_tflite::MatrixDiagOptions>() const
+{
+  return builtin_options_as_MatrixDiagOptions();
+}
+
+template <>
+inline const onert_tflite::QuantizeOptions *
+Operator::builtin_options_as<onert_tflite::QuantizeOptions>() const
+{
+  return builtin_options_as_QuantizeOptions();
+}
+
+template <>
+inline const onert_tflite::MatrixSetDiagOptions *
+Operator::builtin_options_as<onert_tflite::MatrixSetDiagOptions>() const
+{
+  return builtin_options_as_MatrixSetDiagOptions();
+}
+
+template <>
+inline const onert_tflite::HardSwishOptions *
+Operator::builtin_options_as<onert_tflite::HardSwishOptions>() const
+{
+  return builtin_options_as_HardSwishOptions();
+}
+
+template <>
+inline const onert_tflite::IfOptions *Operator::builtin_options_as<onert_tflite::IfOptions>() const
+{
+  return builtin_options_as_IfOptions();
+}
+
+template <>
+inline const onert_tflite::WhileOptions *
+Operator::builtin_options_as<onert_tflite::WhileOptions>() const
+{
+  return builtin_options_as_WhileOptions();
+}
+
+template <>
+inline const onert_tflite::DepthToSpaceOptions *
+Operator::builtin_options_as<onert_tflite::DepthToSpaceOptions>() const
+{
+  return builtin_options_as_DepthToSpaceOptions();
+}
+
+template <>
+inline const onert_tflite::NonMaxSuppressionV4Options *
+Operator::builtin_options_as<onert_tflite::NonMaxSuppressionV4Options>() const
+{
+  return builtin_options_as_NonMaxSuppressionV4Options();
+}
+
+template <>
+inline const onert_tflite::NonMaxSuppressionV5Options *
+Operator::builtin_options_as<onert_tflite::NonMaxSuppressionV5Options>() const
+{
+  return builtin_options_as_NonMaxSuppressionV5Options();
+}
+
+template <>
+inline const onert_tflite::ScatterNdOptions *
+Operator::builtin_options_as<onert_tflite::ScatterNdOptions>() const
+{
+  return builtin_options_as_ScatterNdOptions();
+}
+
+template <>
+inline const onert_tflite::SelectV2Options *
+Operator::builtin_options_as<onert_tflite::SelectV2Options>() const
+{
+  return builtin_options_as_SelectV2Options();
+}
+
+template <>
+inline const onert_tflite::DensifyOptions *
+Operator::builtin_options_as<onert_tflite::DensifyOptions>() const
+{
+  return builtin_options_as_DensifyOptions();
+}
+
+template <>
+inline const onert_tflite::SegmentSumOptions *
+Operator::builtin_options_as<onert_tflite::SegmentSumOptions>() const
+{
+  return builtin_options_as_SegmentSumOptions();
+}
+
+template <>
+inline const onert_tflite::BatchMatMulOptions *
+Operator::builtin_options_as<onert_tflite::BatchMatMulOptions>() const
+{
+  return builtin_options_as_BatchMatMulOptions();
+}
+
+template <>
+inline const onert_tflite::CumsumOptions *
+Operator::builtin_options_as<onert_tflite::CumsumOptions>() const
+{
+  return builtin_options_as_CumsumOptions();
+}
+
+template <>
+inline const onert_tflite::CallOnceOptions *
+Operator::builtin_options_as<onert_tflite::CallOnceOptions>() const
+{
+  return builtin_options_as_CallOnceOptions();
+}
+
+template <>
+inline const onert_tflite::BroadcastToOptions *
+Operator::builtin_options_as<onert_tflite::BroadcastToOptions>() const
+{
+  return builtin_options_as_BroadcastToOptions();
+}
+
+template <>
+inline const onert_tflite::Rfft2dOptions *
+Operator::builtin_options_as<onert_tflite::Rfft2dOptions>() const
+{
+  return builtin_options_as_Rfft2dOptions();
+}
+
+template <>
+inline const onert_tflite::Conv3DOptions *
+Operator::builtin_options_as<onert_tflite::Conv3DOptions>() const
+{
+  return builtin_options_as_Conv3DOptions();
+}
+
+template <>
+inline const onert_tflite::HashtableOptions *
+Operator::builtin_options_as<onert_tflite::HashtableOptions>() const
+{
+  return builtin_options_as_HashtableOptions();
+}
+
+template <>
+inline const onert_tflite::HashtableFindOptions *
+Operator::builtin_options_as<onert_tflite::HashtableFindOptions>() const
+{
+  return builtin_options_as_HashtableFindOptions();
+}
+
+template <>
+inline const onert_tflite::HashtableImportOptions *
+Operator::builtin_options_as<onert_tflite::HashtableImportOptions>() const
+{
+  return builtin_options_as_HashtableImportOptions();
+}
+
+template <>
+inline const onert_tflite::HashtableSizeOptions *
+Operator::builtin_options_as<onert_tflite::HashtableSizeOptions>() const
+{
+  return builtin_options_as_HashtableSizeOptions();
+}
+
+template <>
+inline const onert_tflite::VarHandleOptions *
+Operator::builtin_options_as<onert_tflite::VarHandleOptions>() const
+{
+  return builtin_options_as_VarHandleOptions();
+}
+
+template <>
+inline const onert_tflite::ReadVariableOptions *
+Operator::builtin_options_as<onert_tflite::ReadVariableOptions>() const
+{
+  return builtin_options_as_ReadVariableOptions();
+}
+
+template <>
+inline const onert_tflite::AssignVariableOptions *
+Operator::builtin_options_as<onert_tflite::AssignVariableOptions>() const
+{
+  return builtin_options_as_AssignVariableOptions();
+}
+
+template <>
+inline const onert_tflite::RandomOptions *
+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;
+  ::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(onert_tflite::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(onert_tflite::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,
+  onert_tflite::BuiltinOptions builtin_options_type = onert_tflite::BuiltinOptions_NONE,
+  ::flatbuffers::Offset<void> builtin_options = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<uint8_t>> custom_options = 0,
+  onert_tflite::CustomOptionsFormat custom_options_format =
+    onert_tflite::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,
+  onert_tflite::BuiltinOptions builtin_options_type = onert_tflite::BuiltinOptions_NONE,
+  ::flatbuffers::Offset<void> builtin_options = 0,
+  const std::vector<uint8_t> *custom_options = nullptr,
+  onert_tflite::CustomOptionsFormat custom_options_format =
+    onert_tflite::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 onert_tflite::CreateOperator(_fbb, opcode_index, inputs__, outputs__, builtin_options_type,
+                                      builtin_options, custom_options__, custom_options_format,
+                                      mutating_variable_inputs__, intermediates__);
+}
+
+struct SubGraph FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  typedef SubGraphBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
+  {
+    VT_TENSORS = 4,
+    VT_INPUTS = 6,
+    VT_OUTPUTS = 8,
+    VT_OPERATORS = 10,
+    VT_NAME = 12
+  };
+  const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::Tensor>> *tensors() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::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<onert_tflite::Operator>> *operators() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::Operator>> *>(
+      VT_OPERATORS);
+  }
+  const ::flatbuffers::String *name() const
+  {
+    return GetPointer<const ::flatbuffers::String *>(VT_NAME);
+  }
+  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()) && verifier.EndTable();
+  }
+};
+
+struct SubGraphBuilder
+{
+  typedef SubGraph Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_tensors(
+    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::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<onert_tflite::Operator>>>
+      operators)
+  {
+    fbb_.AddOffset(SubGraph::VT_OPERATORS, operators);
+  }
+  void add_name(::flatbuffers::Offset<::flatbuffers::String> name)
+  {
+    fbb_.AddOffset(SubGraph::VT_NAME, name);
+  }
+  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<onert_tflite::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<onert_tflite::Operator>>>
+    operators = 0,
+  ::flatbuffers::Offset<::flatbuffers::String> name = 0)
+{
+  SubGraphBuilder builder_(_fbb);
+  builder_.add_name(name);
+  builder_.add_operators(operators);
+  builder_.add_outputs(outputs);
+  builder_.add_inputs(inputs);
+  builder_.add_tensors(tensors);
+  return builder_.Finish();
+}
+
+inline ::flatbuffers::Offset<SubGraph> CreateSubGraphDirect(
+  ::flatbuffers::FlatBufferBuilder &_fbb,
+  const std::vector<::flatbuffers::Offset<onert_tflite::Tensor>> *tensors = nullptr,
+  const std::vector<int32_t> *inputs = nullptr, const std::vector<int32_t> *outputs = nullptr,
+  const std::vector<::flatbuffers::Offset<onert_tflite::Operator>> *operators = nullptr,
+  const char *name = nullptr)
+{
+  auto tensors__ =
+    tensors ? _fbb.CreateVector<::flatbuffers::Offset<onert_tflite::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<onert_tflite::Operator>>(*operators) : 0;
+  auto name__ = name ? _fbb.CreateString(name) : 0;
+  return onert_tflite::CreateSubGraph(_fbb, tensors__, inputs__, outputs__, operators__, name__);
+}
+
+struct Buffer FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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();
+  }
+};
+
+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 onert_tflite::CreateBuffer(_fbb, data__);
+}
+
+struct Metadata FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           verifier.EndTable();
+  }
+};
+
+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 onert_tflite::CreateMetadata(_fbb, name__, buffer);
+}
+
+struct TensorMap FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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, 4) &&
+           verifier.EndTable();
+  }
+};
+
+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 onert_tflite::CreateTensorMap(_fbb, name__, tensor_index);
+}
+
+struct SignatureDef FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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<onert_tflite::TensorMap>> *inputs() const
+  {
+    return GetPointer<
+      const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::TensorMap>> *>(VT_INPUTS);
+  }
+  const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::TensorMap>> *outputs() const
+  {
+    return GetPointer<
+      const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::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, 4) && verifier.EndTable();
+  }
+};
+
+struct SignatureDefBuilder
+{
+  typedef SignatureDef Table;
+  ::flatbuffers::FlatBufferBuilder &fbb_;
+  ::flatbuffers::uoffset_t start_;
+  void add_inputs(
+    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::TensorMap>>>
+      inputs)
+  {
+    fbb_.AddOffset(SignatureDef::VT_INPUTS, inputs);
+  }
+  void add_outputs(
+    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::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<onert_tflite::TensorMap>>>
+    inputs = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::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<onert_tflite::TensorMap>> *inputs = nullptr,
+  const std::vector<::flatbuffers::Offset<onert_tflite::TensorMap>> *outputs = nullptr,
+  const char *signature_key = nullptr, uint32_t subgraph_index = 0)
+{
+  auto inputs__ =
+    inputs ? _fbb.CreateVector<::flatbuffers::Offset<onert_tflite::TensorMap>>(*inputs) : 0;
+  auto outputs__ =
+    outputs ? _fbb.CreateVector<::flatbuffers::Offset<onert_tflite::TensorMap>>(*outputs) : 0;
+  auto signature_key__ = signature_key ? _fbb.CreateString(signature_key) : 0;
+  return onert_tflite::CreateSignatureDef(_fbb, inputs__, outputs__, signature_key__,
+                                          subgraph_index);
+}
+
+struct Model FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table
+{
+  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<onert_tflite::OperatorCode>> *
+  operator_codes() const
+  {
+    return GetPointer<
+      const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::OperatorCode>> *>(
+      VT_OPERATOR_CODES);
+  }
+  const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::SubGraph>> *subgraphs() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::SubGraph>> *>(
+      VT_SUBGRAPHS);
+  }
+  const ::flatbuffers::String *description() const
+  {
+    return GetPointer<const ::flatbuffers::String *>(VT_DESCRIPTION);
+  }
+  const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::Buffer>> *buffers() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::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<onert_tflite::Metadata>> *metadata() const
+  {
+    return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::Metadata>> *>(
+      VT_METADATA);
+  }
+  const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::SignatureDef>> *
+  signature_defs() const
+  {
+    return GetPointer<
+      const ::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::SignatureDef>> *>(
+      VT_SIGNATURE_DEFS);
+  }
+  bool Verify(::flatbuffers::Verifier &verifier) const
+  {
+    return VerifyTableStart(verifier) && VerifyField<uint32_t>(verifier, VT_VERSION, 4) &&
+           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();
+  }
+};
+
+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<onert_tflite::OperatorCode>>>
+      operator_codes)
+  {
+    fbb_.AddOffset(Model::VT_OPERATOR_CODES, operator_codes);
+  }
+  void add_subgraphs(
+    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::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<onert_tflite::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<onert_tflite::Metadata>>>
+      metadata)
+  {
+    fbb_.AddOffset(Model::VT_METADATA, metadata);
+  }
+  void add_signature_defs(
+    ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::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<onert_tflite::OperatorCode>>>
+    operator_codes = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::SubGraph>>>
+    subgraphs = 0,
+  ::flatbuffers::Offset<::flatbuffers::String> description = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::Buffer>>>
+    buffers = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<int32_t>> metadata_buffer = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::Metadata>>>
+    metadata = 0,
+  ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<onert_tflite::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<onert_tflite::OperatorCode>> *operator_codes = nullptr,
+  const std::vector<::flatbuffers::Offset<onert_tflite::SubGraph>> *subgraphs = nullptr,
+  const char *description = nullptr,
+  const std::vector<::flatbuffers::Offset<onert_tflite::Buffer>> *buffers = nullptr,
+  const std::vector<int32_t> *metadata_buffer = nullptr,
+  const std::vector<::flatbuffers::Offset<onert_tflite::Metadata>> *metadata = nullptr,
+  const std::vector<::flatbuffers::Offset<onert_tflite::SignatureDef>> *signature_defs = nullptr)
+{
+  auto operator_codes__ =
+    operator_codes
+      ? _fbb.CreateVector<::flatbuffers::Offset<onert_tflite::OperatorCode>>(*operator_codes)
+      : 0;
+  auto subgraphs__ =
+    subgraphs ? _fbb.CreateVector<::flatbuffers::Offset<onert_tflite::SubGraph>>(*subgraphs) : 0;
+  auto description__ = description ? _fbb.CreateString(description) : 0;
+  auto buffers__ =
+    buffers ? _fbb.CreateVector<::flatbuffers::Offset<onert_tflite::Buffer>>(*buffers) : 0;
+  auto metadata_buffer__ = metadata_buffer ? _fbb.CreateVector<int32_t>(*metadata_buffer) : 0;
+  auto metadata__ =
+    metadata ? _fbb.CreateVector<::flatbuffers::Offset<onert_tflite::Metadata>>(*metadata) : 0;
+  auto signature_defs__ =
+    signature_defs
+      ? _fbb.CreateVector<::flatbuffers::Offset<onert_tflite::SignatureDef>>(*signature_defs)
+      : 0;
+  return onert_tflite::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 onert_tflite::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 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 onert_tflite::Int32Vector *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case SparseIndexVector_Uint16Vector:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::Uint16Vector *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case SparseIndexVector_Uint8Vector:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::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 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 onert_tflite::Conv2DOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_DepthwiseConv2DOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::DepthwiseConv2DOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ConcatEmbeddingsOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ConcatEmbeddingsOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_LSHProjectionOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::LSHProjectionOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_Pool2DOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::Pool2DOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SVDFOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SVDFOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_RNNOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::RNNOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_FullyConnectedOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::FullyConnectedOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SoftmaxOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SoftmaxOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ConcatenationOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ConcatenationOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_AddOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::AddOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_L2NormOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::L2NormOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_LocalResponseNormalizationOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::LocalResponseNormalizationOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_LSTMOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::LSTMOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ResizeBilinearOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ResizeBilinearOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_CallOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::CallOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ReshapeOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ReshapeOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SkipGramOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SkipGramOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SpaceToDepthOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SpaceToDepthOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_EmbeddingLookupSparseOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::EmbeddingLookupSparseOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_MulOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::MulOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_PadOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::PadOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_GatherOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::GatherOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_BatchToSpaceNDOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::BatchToSpaceNDOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SpaceToBatchNDOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SpaceToBatchNDOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_TransposeOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::TransposeOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ReducerOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ReducerOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SubOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SubOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_DivOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::DivOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SqueezeOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SqueezeOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SequenceRNNOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SequenceRNNOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_StridedSliceOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::StridedSliceOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ExpOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ExpOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_TopKV2Options:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::TopKV2Options *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SplitOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SplitOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_LogSoftmaxOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::LogSoftmaxOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_CastOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::CastOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_DequantizeOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::DequantizeOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_MaximumMinimumOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::MaximumMinimumOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ArgMaxOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ArgMaxOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_LessOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::LessOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_NegOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::NegOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_PadV2Options:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::PadV2Options *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_GreaterOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::GreaterOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_GreaterEqualOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::GreaterEqualOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_LessEqualOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::LessEqualOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SelectOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SelectOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SliceOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SliceOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_TransposeConvOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::TransposeConvOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SparseToDenseOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SparseToDenseOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_TileOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::TileOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ExpandDimsOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ExpandDimsOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_EqualOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::EqualOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_NotEqualOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::NotEqualOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ShapeOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ShapeOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_PowOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::PowOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ArgMinOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ArgMinOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_FakeQuantOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::FakeQuantOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_PackOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::PackOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_LogicalOrOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::LogicalOrOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_OneHotOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::OneHotOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_LogicalAndOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::LogicalAndOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_LogicalNotOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::LogicalNotOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_UnpackOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::UnpackOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_FloorDivOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::FloorDivOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SquareOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SquareOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ZerosLikeOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ZerosLikeOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_FillOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::FillOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_BidirectionalSequenceLSTMOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::BidirectionalSequenceLSTMOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_BidirectionalSequenceRNNOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::BidirectionalSequenceRNNOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_UnidirectionalSequenceLSTMOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::UnidirectionalSequenceLSTMOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_FloorModOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::FloorModOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_RangeOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::RangeOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ResizeNearestNeighborOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ResizeNearestNeighborOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_LeakyReluOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::LeakyReluOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SquaredDifferenceOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SquaredDifferenceOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_MirrorPadOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::MirrorPadOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_AbsOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::AbsOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SplitVOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SplitVOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_UniqueOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::UniqueOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ReverseV2Options:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ReverseV2Options *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_AddNOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::AddNOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_GatherNdOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::GatherNdOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_CosOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::CosOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_WhereOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::WhereOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_RankOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::RankOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ReverseSequenceOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ReverseSequenceOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_MatrixDiagOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::MatrixDiagOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_QuantizeOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::QuantizeOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_MatrixSetDiagOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::MatrixSetDiagOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_HardSwishOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::HardSwishOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_IfOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::IfOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_WhileOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::WhileOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_DepthToSpaceOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::DepthToSpaceOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_NonMaxSuppressionV4Options:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::NonMaxSuppressionV4Options *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_NonMaxSuppressionV5Options:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::NonMaxSuppressionV5Options *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ScatterNdOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ScatterNdOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SelectV2Options:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SelectV2Options *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_DensifyOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::DensifyOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_SegmentSumOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::SegmentSumOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_BatchMatMulOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::BatchMatMulOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_CumsumOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::CumsumOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_CallOnceOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::CallOnceOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_BroadcastToOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::BroadcastToOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_Rfft2dOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::Rfft2dOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_Conv3DOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::Conv3DOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_HashtableOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::HashtableOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_HashtableFindOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::HashtableFindOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_HashtableImportOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::HashtableImportOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_HashtableSizeOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::HashtableSizeOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_VarHandleOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::VarHandleOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_ReadVariableOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::ReadVariableOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_AssignVariableOptions:
+    {
+      auto ptr = reinterpret_cast<const onert_tflite::AssignVariableOptions *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
+    case BuiltinOptions_RandomOptions:
+    {
+      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;
+  }
+}
+
+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 const onert_tflite::Model *GetModel(const void *buf)
+{
+  return ::flatbuffers::GetRoot<onert_tflite::Model>(buf);
+}
+
+inline const onert_tflite::Model *GetSizePrefixedModel(const void *buf)
+{
+  return ::flatbuffers::GetSizePrefixedRoot<onert_tflite::Model>(buf);
+}
+
+inline const char *ModelIdentifier() { return "TFL3"; }
+
+inline bool ModelBufferHasIdentifier(const void *buf)
+{
+  return ::flatbuffers::BufferHasIdentifier(buf, ModelIdentifier());
+}
+
+inline bool SizePrefixedModelBufferHasIdentifier(const void *buf)
+{
+  return ::flatbuffers::BufferHasIdentifier(buf, ModelIdentifier(), true);
+}
+
+inline bool VerifyModelBuffer(::flatbuffers::Verifier &verifier)
+{
+  return verifier.VerifyBuffer<onert_tflite::Model>(ModelIdentifier());
+}
+
+inline bool VerifySizePrefixedModelBuffer(::flatbuffers::Verifier &verifier)
+{
+  return verifier.VerifySizePrefixedBuffer<onert_tflite::Model>(ModelIdentifier());
+}
+
+inline const char *ModelExtension() { return "tflite"; }
+
+inline void FinishModelBuffer(::flatbuffers::FlatBufferBuilder &fbb,
+                              ::flatbuffers::Offset<onert_tflite::Model> root)
+{
+  fbb.Finish(root, ModelIdentifier());
+}
+
+inline void FinishSizePrefixedModelBuffer(::flatbuffers::FlatBufferBuilder &fbb,
+                                          ::flatbuffers::Offset<onert_tflite::Model> root)
+{
+  fbb.FinishSizePrefixed(root, ModelIdentifier());
+}
+
+} // namespace onert_tflite
+
+#endif // FLATBUFFERS_GENERATED_TFLITESCHEMA_ONERT_TFLITE_H_
diff --git a/runtime/onert/core/src/odc/CodegenLoader.cc b/runtime/onert/core/src/odc/CodegenLoader.cc
new file mode 100644 (file)
index 0000000..764074f
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "CodegenLoader.h"
+
+#include <dlfcn.h>
+#include <iostream>
+#include <memory>
+
+static const char *SHARED_LIB_EXT =
+#if defined(__APPLE__) && defined(__MACH__)
+  ".dylib";
+#else
+  ".so";
+#endif
+
+namespace onert
+{
+namespace odc
+{
+
+CodegenLoader &CodegenLoader::instance()
+{
+  static CodegenLoader singleton;
+  return singleton;
+}
+
+void CodegenLoader::loadLibrary(const char *target)
+{
+  if (get() != nullptr)
+    return;
+
+  const std::string codegen_so = "lib" + std::string{target} + SHARED_LIB_EXT;
+#ifdef __ANDROID__
+  void *handle = dlopen(codegen_so.c_str(), RTLD_LAZY | RTLD_LOCAL);
+#else
+  void *handle = dlmopen(LM_ID_NEWLM, codegen_so.c_str(), RTLD_LAZY | RTLD_LOCAL);
+#endif
+  if (handle == nullptr)
+  {
+    throw std::runtime_error("CodegenLoader: " + std::string{dlerror()});
+  }
+
+  const auto factory = (factory_t)dlsym(handle, "create_codegen");
+  if (factory == nullptr)
+  {
+    const std::string dlerror_msg = dlerror();
+    dlclose(handle);
+    throw std::runtime_error("CodegenLoader: " + dlerror_msg);
+  }
+
+  const auto destroyer = (codegen_destory_t)dlsym(handle, "destroy_codegen");
+  _codegen = std::unique_ptr<ICodegen, codegen_destory_t>(factory(), destroyer);
+  if (_codegen == nullptr)
+  {
+    dlclose(handle);
+    throw std::runtime_error("CodegenLoader: unable to create codegen");
+  }
+
+  // Save backend handle (avoid warning by handle lost without dlclose())
+  _dlhandle = std::unique_ptr<void, dlhandle_destroy_t>{
+    handle, [filename = codegen_so](void *h) {
+      if (dlclose(h))
+        throw std::runtime_error("CodegenLoader: Failed to unload backend " + filename);
+    }};
+}
+
+void CodegenLoader::unloadLibrary()
+{
+  if (get() == nullptr)
+    return;
+
+  _codegen.reset(nullptr);
+  _dlhandle.reset(nullptr);
+}
+
+} // namespace odc
+} // namespace onert
diff --git a/runtime/onert/core/src/odc/CodegenLoader.h b/runtime/onert/core/src/odc/CodegenLoader.h
new file mode 100644 (file)
index 0000000..3972560
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_CODEGEN_LOADER_H__
+#define __ONERT_ODC_CODEGEN_LOADER_H__
+
+#include "odc/ICodegen.h"
+
+#include <functional>
+#include <memory>
+
+namespace onert
+{
+namespace odc
+{
+
+/**
+ * @brief Class to manage loading and unloading of dynamic library containing
+ *        implementation of ICodegen interface.
+ */
+class CodegenLoader
+{
+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 ICodegen
+   */
+  using factory_t = ICodegen *(*)();
+  /**
+   * @brief Typedef for function pointer to destroy instance of ICodegen
+   */
+  using codegen_destory_t = void (*)(ICodegen *);
+
+  /**
+   * @brief Get singleton instance of CodegenLoader
+   * @return Reference to singleton instance of CodegenLoader
+   */
+  static CodegenLoader &instance();
+
+  // delete copy constructor and assignment operator
+  CodegenLoader(CodegenLoader const &) = delete;
+  CodegenLoader &operator=(CodegenLoader const &) = delete;
+
+private:
+  // cannot create instance of CodegenLoader outside of this class
+  CodegenLoader() = default;
+  ~CodegenLoader() = default;
+
+public:
+  /**
+   * @brief   Load dynamic library containing implementation of ICodegen
+   * @param[in] target Target backend name
+   *                   This target string will be used to find a backend library.
+   *                   The name of target backend library should follow the following rules:
+   *                     'lib' + {backend extension} + '-gen' + {lib extension}
+   *                   And the target string should be a name except 'lib' and {lib extension}.
+   *                   For example, if the backend extension is 'aaa', the backend library name
+   *                   should be 'libaaa-gen.so', and the target string should be 'aaa-gen'.
+   */
+  void loadLibrary(const char *target);
+  /**
+   * @brief  Unload dynamic library containing implementation of ICodegen
+   */
+  void unloadLibrary();
+  /**
+   * @brief   Get instance of ICodegen created through factory method
+   * @return  Pointer to instance of ICodegen
+   */
+  const ICodegen *get() const { return _codegen.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<ICodegen, codegen_destory_t> _codegen{nullptr, nullptr};
+};
+
+} // namespace odc
+} // namespace onert
+
+#endif // __ONERT_ODC_CODEGEN_LOADER_H__
diff --git a/runtime/onert/core/src/odc/CodegenManager.cc b/runtime/onert/core/src/odc/CodegenManager.cc
new file mode 100644 (file)
index 0000000..45f10a6
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "CodegenLoader.h"
+#include "odc/CodegenManager.h"
+#include "util/Utils.h"
+
+#include <mutex>
+
+namespace onert
+{
+namespace odc
+{
+
+bool CodegenManager::codegen(const std::string &model_path, const char *target,
+                             CodegenPreference pref)
+{
+  if (target == nullptr)
+    throw std::runtime_error("Target string is not set");
+
+  if (_export_model_path.empty())
+    throw std::runtime_error("Export model path is not set");
+
+  if (model_path.empty())
+    throw std::runtime_error("Model path does not exist");
+
+  // codegen function is thread-unsafe
+  static std::mutex lock;
+  std::lock_guard<std::mutex> guard(lock);
+
+  auto &codegen_loader = CodegenLoader::instance();
+  codegen_loader.loadLibrary(target);
+  const auto code_generator = codegen_loader.get();
+  // TODO Use compile preference
+  UNUSED_RELEASE(pref);
+  const auto result = code_generator->codegen(model_path.c_str(), _export_model_path.c_str());
+  codegen_loader.unloadLibrary();
+
+  return (result == 0);
+}
+
+} // namespace odc
+} // namespace onert
index 71572a7..fc5725b 100644 (file)
@@ -25,21 +25,21 @@ namespace onert
 namespace odc
 {
 
-bool QuantizeManager::quantize()
+bool QuantizeManager::quantize(const std::string &model_path)
 {
+  if (model_path.empty() || _export_model_path.empty())
+    return false;
+
   // 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);
+  auto result = quantizer->quantize(model_path.c_str(), _export_model_path.c_str(), _qtype);
 
   // TODO Unload quantize library to reduce memory usage
 
index 4e155a6..3c9f45c 100644 (file)
 using namespace onert::odc;
 
 // Test export model path is not set
-TEST(odc_QuantizeManager, neg_export_model_path)
+TEST(odc_QuantizeManager, neg_export_model_path_not_set)
 {
-  QuantizeManager manager("model_path");
-  ASSERT_THROW(manager.quantize(), std::runtime_error);
+  QuantizeManager manager;
+  manager.quantizeType(ODC_QTYPE_WO_I8_SYM);
+  ASSERT_EQ(manager.quantize("model_path"), false);
 }
 
 // Test invalid model path
 TEST(odc_QuantizeManager, neg_invalid_model_path)
 {
-  QuantizeManager manager("invalid_model_path.circle");
+  QuantizeManager manager;
   manager.exportModelPath("export_model_path.circle");
-  ASSERT_EQ(manager.quantize(), false);
+  manager.quantizeType(ODC_QTYPE_WO_I8_SYM);
+  ASSERT_EQ(manager.quantize("invalid_model_path.circle"), false);
 }
index 0a35a85..672820a 100644 (file)
@@ -90,11 +90,11 @@ public:
   /**
    * @brief Retuens a singleton object
    */
-  static EventWriter *get(const std::string &filename)
+  static EventWriter *get(const std::string &workspace_dir)
   {
     std::unique_lock<std::mutex> lock{_mutex};
 
-    static EventWriter singleton(filename);
+    static EventWriter singleton(workspace_dir);
     return &singleton;
   }
 
@@ -115,11 +115,11 @@ public:
   void readyToFlush(std::unique_ptr<EventRecorder> &&recorder);
 
 private:
-  EventWriter(const std::string &filepath) : _ref_count(0)
+  EventWriter(const std::string &workspace_dir) : _ref_count(0)
   {
-    std::string snpe_log_name(filepath);
-    std::string chrome_tracing_log_name(filepath + ".chrome.json");
-    std::string md_table_log_name(filepath + ".table.md");
+    std::string snpe_log_name(workspace_dir + "/trace.json");
+    std::string chrome_tracing_log_name(workspace_dir + "/trace.chrome.json");
+    std::string md_table_log_name(workspace_dir + "/trace.table.md");
 
     _actual_writers[WriteFormat::SNPE_BENCHMARK] = std::make_unique<SNPEWriter>(snpe_log_name);
     _actual_writers[WriteFormat::CHROME_TRACING] =
index 862d6f7..2a6fde4 100644 (file)
@@ -185,7 +185,6 @@ ir::Shape inferReduceShape(const ir::Shape &input_shape, const std::vector<int>
   else
   {
     // Calculates size of reducing axis.
-    int num_reduce_axis = num_axis;
     for (int i = 0; i < num_axis; ++i)
     {
       int current = axes[i];
@@ -204,14 +203,12 @@ ir::Shape inferReduceShape(const ir::Shape &input_shape, const std::vector<int>
         }
         if (current == previous)
         {
-          --num_reduce_axis;
           break;
         }
       }
     }
     // Determines output dimensions.
     ir::Shape out_shape;
-    int num_skip_axis = 0;
     for (int idx = 0; idx < input_num_dims; ++idx)
     {
       bool is_axis = false;
@@ -219,7 +216,6 @@ ir::Shape inferReduceShape(const ir::Shape &input_shape, const std::vector<int>
       {
         if (axes[axis_idx] == idx || axes[axis_idx] + input_num_dims == idx)
         {
-          ++num_skip_axis;
           is_axis = true;
           break;
         }
@@ -604,11 +600,12 @@ template <typename T> ir::Shape inferRangeShape(T start_val, T limit_val, T delt
 template ir::Shape inferRangeShape(int start_val, int limit_val, int delta_val);
 template ir::Shape inferRangeShape(float start_val, float limit_val, float delta_val);
 
-ir::Shape inferReshapeShape(const int32_t *shape_buf, const int32_t shape_num_elements,
-                            const size_t total_num_elements)
+ir::Shape inferReshapeShape(const ir::Shape &input_shape, const int32_t *shape_buf,
+                            const int32_t shape_num_elements)
 {
   ir::Shape ret(shape_num_elements);
   int32_t flatten_dim = ir::Shape::kUnspecifiedDim;
+  auto total_num_elements = input_shape.num_elements();
   for (int32_t i = 0; i < shape_num_elements; ++i)
   {
     if (shape_buf[i] < 0)
@@ -628,7 +625,15 @@ ir::Shape inferReshapeShape(const int32_t *shape_buf, const int32_t shape_num_el
 
   // Check reshapable
   if (total_num_elements != static_cast<size_t>(ret.num_elements()))
-    throw std::runtime_error("Reshape: 2nd param is not compatible with the shape of input");
+  {
+    // Multi batch case
+    // TODO Handle multi batch case more precisely on runtime level
+    if ((ret.dim(0) == 1) &&
+        (total_num_elements == static_cast<size_t>(ret.num_elements() * input_shape.dim(0))))
+      ret.dim(0) = input_shape.dim(0);
+    else
+      throw std::runtime_error("Reshape: 2nd param is not compatible with the shape of input");
+  }
 
   return ret;
 }
diff --git a/runtime/onert/frontend/base_loader/CMakeLists.txt b/runtime/onert/frontend/base_loader/CMakeLists.txt
deleted file mode 100644 (file)
index 6f70071..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-if(NOT BUILD_TFLITE_LOADER AND NOT BUILD_CIRCLE_LOADER)
-  return()
-endif(NOT BUILD_TFLITE_LOADER AND NOT BUILD_CIRCLE_LOADER)
-
-nnfw_find_package(FlatBuffers REQUIRED)
-
-add_library(base_loader INTERFACE)
-target_include_directories(base_loader INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include)
-
-target_link_libraries(base_loader INTERFACE onert_core)
-target_link_libraries(base_loader INTERFACE flatbuffers::flatbuffers)
diff --git a/runtime/onert/frontend/base_loader/include/base_loader.h b/runtime/onert/frontend/base_loader/include/base_loader.h
deleted file mode 100644 (file)
index a6b1fb4..0000000
+++ /dev/null
@@ -1,1735 +0,0 @@
-/*
- * Copyright 2017 The TensorFlow Authors. All Rights Reserved.
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __BASE_LOADER_BASE_LOADER_H__
-#define __BASE_LOADER_BASE_LOADER_H__
-
-#include "ir/Graph.h"
-#include "ir/Shape.h"
-#include "ir/Operations.Include.h"
-
-#include "flatbuffers/flexbuffers.h"
-
-#include <map>
-#include <memory>
-#include <fstream>
-#include <limits>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <util/logging.h>
-
-namespace onert
-{
-namespace base_loader
-{
-
-template <typename LoaderDomain> class BaseLoader
-{
-protected:
-  using Verifier = typename LoaderDomain::Verifier;
-  using ActivationFunctionType = typename LoaderDomain::ActivationFunctionType;
-  using Buffer = typename LoaderDomain::Buffer;
-  using BuiltinOperator = typename LoaderDomain::BuiltinOperator;
-  using CustomOptionsFormat = typename LoaderDomain::CustomOptionsFormat;
-  using Model = typename LoaderDomain::Model;
-  using Operator = typename LoaderDomain::Operator;
-  using Padding = typename LoaderDomain::Padding;
-  using Pool2DOptions = typename LoaderDomain::Pool2DOptions;
-  using SubGraph = typename LoaderDomain::SubGraph;
-  using Tensor = typename LoaderDomain::Tensor;
-  using TensorType = typename LoaderDomain::TensorType;
-  using DimensionType = typename LoaderDomain::DimensionType;
-  using SparseIndexVector = typename LoaderDomain::SparseIndexVector;
-
-protected:
-  bool isOptionalInputTensor(std::int32_t idx) { return idx == -1; }
-  virtual bool allowOptionalInputTensor(BuiltinOperator) = 0;
-
-public:
-  /**
-   * @brief Construct a new Loader object
-   *
-   * @param model reference to model
-   */
-  explicit BaseLoader(std::unique_ptr<ir::Model> &model)
-    : _base{nullptr}, _pagesize(getpagesize()), _fd(-1), _model(model), _domain_model{nullptr}
-  {
-    _use_mmaped_data = util::getConfigBool(util::config::USE_MMAPED_DATA);
-  }
-
-  /**
-   * @brief Load a model from file
-   *
-   * @param file_path
-   */
-  void loadFromFile(const std::string &file_path);
-  /**
-   * @brief Load a model from a buffer
-   *
-   * @param buffer buffer pointer
-   * @param size buffer size
-   */
-  void loadFromBuffer(uint8_t *buffer, size_t size);
-
-protected:
-  ~BaseLoader() = default;
-  void loadModel();
-
-  // Helper functions
-  ir::Activation convertActivation(ActivationFunctionType type);
-  ir::DataType tensorTypeToDataType(TensorType type);
-  ir::OperandIndex tensorIdxToOperandIdx(int32_t tensorIdx);
-  flexbuffers::Map getCustomOpAttrMap(const Operator *op);
-
-  // Create operands form tflite::Tensor
-  ir::OperandIndex loadOperand(const Tensor *tensor, ir::Graph &subg);
-  void loadQuantization(const Tensor *tensor, ir::TypeInfo &typeInfo);
-  void loadSparsity(const Tensor *tensor, ir::TypeInfo &typeInfo);
-  void loadOperationIO(const Operator *op, ir::OperandIndexSequence &inputs,
-                       ir::OperandIndexSequence &outputs);
-  // Create operations from Operator
-  void loadOperation(const Operator *op, ir::Graph &subg);
-  // Load Strides and Paddings from options to param
-  template <typename Param, typename OptionsType>
-  void loadStridesAndPaddings(Param &param, const OptionsType *options);
-  // Load Pool2D param
-  template <typename Param> void loadPool2DOptions(Param &param, const Pool2DOptions *options);
-  // Get BuiltinOperator
-  BuiltinOperator getBuiltinOperator(const Operator *op)
-  {
-    auto const builtin_opcode = _domain_model->operator_codes()->Get(op->opcode_index());
-    auto builtin_op = builtin_opcode->builtin_code();
-    if (builtin_op < BuiltinOperator::BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES)
-      builtin_op = static_cast<BuiltinOperator>(builtin_opcode->deprecated_builtin_code());
-
-    return builtin_op;
-  }
-
-private:
-  virtual std::unique_ptr<ir::Graph> loadSubgraph(const SubGraph *subg) = 0;
-  // Operations
-  template <typename OpIR, typename... Args>
-  const OpIR *loadOperationTo(const Operator *op, ir::Graph &subg, Args &&... args);
-
-  void loadAddV2(const Operator *op, ir::Graph &subg);
-  void loadArgMinMax(const Operator *op, ir::Graph &subg, bool is_argmax);
-  void loadBatchMatMul(const Operator *op, ir::Graph &subg);
-  void loadBinaryArithmetic(const Operator *op, ir::Graph &subg,
-                            ir::operation::BinaryArithmetic::ArithmeticType op_type);
-  void loadComparison(const Operator *op, ir::Graph &subg);
-  void loadConcatenation(const Operator *op, ir::Graph &subg);
-  void loadConv2D(const Operator *op, ir::Graph &subg);
-  void loadCustom(const Operator *op, ir::Graph &subg);
-  void loadDepthToSpace(const Operator *op, ir::Graph &subg);
-  void loadDepthwiseConv2D(const Operator *op, ir::Graph &subg);
-  void loadEinsum(const Operator *op, ir::Graph &subg);
-  void loadElementwiseActivation(const Operator *op, ir::Graph &subg,
-                                 ir::operation::ElementwiseActivation::Type op_type,
-                                 float alpha = 0.f, float beta = 0.f);
-  void loadElementwiseBinary(const Operator *op, ir::Graph &subg,
-                             ir::operation::ElementwiseBinary::ElementwiseBinaryType op_type);
-  void loadElementwiseUnary(const Operator *op, ir::Graph &subg,
-                            ir::operation::ElementwiseUnary::Type op_type);
-  void loadFC(const Operator *op, ir::Graph &subg);
-  void loadFusedBatchNorm(const Operator *op, ir::Graph &subg);
-  void loadGather(const Operator *op, ir::Graph &subg);
-  void loadIf(const Operator *op, ir::Graph &subg);
-  void loadLeakyRelu(const Operator *op, ir::Graph &subg);
-  void loadLogSoftmax(const Operator *op, ir::Graph &subg);
-  void loadDetectionPostProcess(const Operator *op, ir::Graph &subg);
-  void loadOneHot(const Operator *op, ir::Graph &subg);
-  void loadPack(const Operator *op, ir::Graph &subg);
-  void loadPool2D(const Operator *op, ir::Graph &subg, ir::operation::Pool2D::PoolType op_type);
-  void loadReduce(const Operator *op, ir::Graph &subg,
-                  ir::operation::Reduce::ReduceType reduce_type);
-  void loadReduceAll(const Operator *op, ir::Graph &subg);
-  void loadReshape(const Operator *op, ir::Graph &subg);
-  void loadResizeBilinear(const Operator *op, ir::Graph &subg);
-  void loadResizeNearestNeighbor(const Operator *op, ir::Graph &subg);
-  void loadSoftmax(const Operator *op, ir::Graph &subg);
-  void loadSpaceToDepth(const Operator *op, ir::Graph &subg);
-  void loadSplit(const Operator *op, ir::Graph &subg);
-  void loadSplitV(const Operator *op, ir::Graph &subg);
-  void loadSqueeze(const Operator *op, ir::Graph &subg);
-  void loadStridedSlice(const Operator *op, ir::Graph &subg);
-  void loadTransposeConv(const Operator *op, ir::Graph &subg);
-  void loadUnidirectionalSequenceLSTM(const Operator *op, ir::Graph &subg);
-  void loadUnpack(const Operator *op, ir::Graph &subg);
-  void loadWhile(const Operator *op, ir::Graph &subg);
-
-  void verifySubgraphIndex(int subg_index)
-  {
-    const auto num_subgraphs = _domain_model->subgraphs()->size();
-    if (subg_index < 0 || subg_index >= static_cast<int32_t>(num_subgraphs))
-      throw std::runtime_error{std::string{"Invalid subgraph index - "} +
-                               std::to_string(subg_index)};
-  }
-
-protected:
-  // Base address for mapped region for loading (if needed)
-  uint8_t *_base;
-  // Memory page size
-  int32_t _pagesize;
-  // loaded file description
-  int _fd;
-  // Reference to ir::model (to be loaded from _domain_model)
-  std::unique_ptr<ir::Model> &_model;
-  const Model *_domain_model;
-  // Maps Tensor indices to onert Operands.
-  std::vector<ir::OperandIndex> _tensor_to_operand;
-  std::unordered_map<ir::OperandIndex, std::string> _tensor_names;
-  // Verifier
-  std::unique_ptr<Verifier> _verifier;
-  // Boolean flag to use MMAPED_DATA
-  bool _use_mmaped_data = false;
-
-  std::unordered_map<uint32_t /* Buffer Index in circle file */, std::shared_ptr<ir::Data>>
-    _buf_to_data;
-};
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::BaseLoader::loadFromFile(const std::string &file_path)
-{
-  _fd = open(file_path.c_str(), O_RDONLY);
-  if (_fd < 0)
-  {
-    throw std::runtime_error("Failed to open file " + file_path);
-  }
-
-  struct stat file_stat;
-  if (fstat(_fd, &file_stat) != 0)
-  {
-    throw std::runtime_error("Fstat failed or file " + file_path + " is not a regular file");
-  }
-  int size = file_stat.st_size;
-
-  // Map model file into memory region
-  _base = static_cast<uint8_t *>(mmap(NULL, size, PROT_READ, MAP_PRIVATE, _fd, 0));
-  if (_base == MAP_FAILED)
-  {
-    close(_fd);
-    throw std::runtime_error("mmap failed - " + std::string(strerror(errno)));
-  }
-
-  _verifier = std::make_unique<Verifier>(reinterpret_cast<const std::uint8_t *>(_base), size);
-
-  loadModel();
-  munmap(_base, size);
-
-  close(_fd);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::BaseLoader::loadFromBuffer(uint8_t *buffer, size_t size)
-{
-  _base = buffer;
-  _verifier = std::make_unique<Verifier>(reinterpret_cast<const std::uint8_t *>(_base), size);
-  loadModel();
-}
-
-template <typename LoaderDomain>
-ir::Activation
-BaseLoader<LoaderDomain>::BaseLoader::convertActivation(const ActivationFunctionType type)
-{
-  switch (type)
-  {
-    case ActivationFunctionType::ActivationFunctionType_NONE:
-      return ir::Activation::NONE;
-    case ActivationFunctionType::ActivationFunctionType_RELU:
-      return ir::Activation::RELU;
-    case ActivationFunctionType::ActivationFunctionType_RELU_N1_TO_1:
-      return ir::Activation::RELU1;
-    case ActivationFunctionType::ActivationFunctionType_RELU6:
-      return ir::Activation::RELU6;
-    case ActivationFunctionType::ActivationFunctionType_TANH:
-      return ir::Activation::TANH;
-    default:
-      throw std::runtime_error(std::string("Unsupported or invalid activation type: ") +
-                               std::to_string(static_cast<int>(type)));
-  }
-}
-
-template <typename LoaderDomain>
-ir::DataType BaseLoader<LoaderDomain>::BaseLoader::tensorTypeToDataType(const TensorType type)
-{
-  switch (type)
-  {
-    case TensorType::TensorType_FLOAT32:
-      return ir::DataType::FLOAT32;
-    case TensorType::TensorType_FLOAT16:
-      return ir::DataType::FLOAT16;
-    case TensorType::TensorType_INT32:
-      return ir::DataType::INT32;
-    case TensorType::TensorType_UINT8:
-      return ir::DataType::QUANT_UINT8_ASYMM;
-    case TensorType::TensorType_INT64:
-      return ir::DataType::INT64;
-    // case TensorType::TensorType_STRING:
-    case TensorType::TensorType_BOOL:
-      return ir::DataType::BOOL8;
-    case TensorType::TensorType_INT16:
-      return ir::DataType::QUANT_INT16_ASYMM;
-    // case TensorType::TensorType_COMPLEX64
-    case TensorType::TensorType_INT8:
-      return ir::DataType::QUANT_INT8_ASYMM;
-    // case TensorType::TensorType_FLOAT64
-    case TensorType::TensorType_UINT32:
-      return ir::DataType::UINT32;
-    default:
-      throw std::runtime_error(
-        std::string("Unsupported tensor type: ").append(EnumNameTensorType(type)));
-  }
-}
-
-template <typename LoaderDomain>
-ir::OperandIndex BaseLoader<LoaderDomain>::BaseLoader::tensorIdxToOperandIdx(int32_t tensorIdx)
-{
-  return isOptionalInputTensor(tensorIdx) ? ir::OperandIndex() : _tensor_to_operand[tensorIdx];
-}
-
-template <typename LoaderDomain>
-flexbuffers::Map BaseLoader<LoaderDomain>::BaseLoader::getCustomOpAttrMap(const Operator *op)
-{
-  size_t custom_op_data_size = op->custom_options()->size();
-  auto custom_op_data = op->custom_options()->Data();
-  auto data_root = flexbuffers::GetRoot(custom_op_data, custom_op_data_size);
-  return data_root.AsMap();
-}
-
-/* Copy is copied from tensorflow lite */
-template <typename T> bool Copy(const T *data_ptr, std::vector<uint16_t> &arr)
-{
-  if (data_ptr->values() == nullptr)
-  {
-    return false;
-  }
-
-  int size = data_ptr->values()->size();
-  arr.reserve(size);
-  for (int i = 0; i < size; i++)
-  {
-    arr.emplace_back(static_cast<uint16_t>(data_ptr->values()->Get(i)));
-  }
-  return true;
-}
-
-template <typename LoaderDomain>
-ir::OperandIndex BaseLoader<LoaderDomain>::loadOperand(const Tensor *tensor, ir::Graph &subg)
-{
-  ir::Shape shape;
-  // Shape
-  const auto *tensor_shape = tensor->shape();
-  if (tensor_shape != nullptr)
-  {
-    for (const auto &dim : *tensor_shape)
-    {
-      shape.append(dim);
-    }
-  }
-
-  // Note for tensor->shape_signature()
-  // We don't handle shape signature
-  //    How we handle:
-  //       If shape_signature[k] == -1, we will use tensor->shape()[k] == 1
-  //       If app wants to change the input shape, call nnfw_apply_input_tensorinfo() can
-  //       be used.
-
-  // TypeInfo
-  ir::TypeInfo type_info(tensorTypeToDataType(tensor->type()));
-  loadQuantization(tensor, type_info);
-  loadSparsity(tensor, type_info);
-
-  // Create operand
-  const auto operand_index = subg.addOperand(shape, type_info);
-
-  // Constant tensors are indicated by non-empty data.
-  const auto *data = _domain_model->buffers()->Get(tensor->buffer())->data();
-  if (data != nullptr)
-  {
-    using std::ptrdiff_t;
-    std::shared_ptr<ir::Data> data_obj;
-
-    if (_fd == -1) // Model is from memory
-    {
-      data_obj = std::make_shared<ir::ExternalData>(data->data(), data->size());
-    }
-    else // Model is loaded(mmap'd) from a file
-    {
-      size_t data_size = data->size();
-      ptrdiff_t unaligned_offset_start = data->data() - _base;
-      ptrdiff_t offset_end = unaligned_offset_start + data_size;
-
-      // Calculated aligned offset from base address of mapped region
-      // munmap accepts memory address which is a multiple of the pagesize
-      ptrdiff_t aligned_offset_start = (unaligned_offset_start / _pagesize) * _pagesize;
-      size_t mmap_size = offset_end - aligned_offset_start;
-
-      uint32_t buf_idx = tensor->buffer();
-      auto buffer_found = _buf_to_data.find(buf_idx);
-
-      if (buffer_found != _buf_to_data.end())
-      {
-        // Another tensor points this buffer and its matching Data(either CachedData or MMapedData)
-        // was already created. Let's reuse the Data
-        data_obj = buffer_found->second;
-      }
-      else if (_use_mmaped_data)
-      {
-        data_obj = std::make_shared<ir::MMapedData>(_fd, aligned_offset_start, mmap_size,
-                                                    unaligned_offset_start, data_size);
-        _buf_to_data[buf_idx] = data_obj;
-      }
-      else
-      {
-        size_t offset = unaligned_offset_start - aligned_offset_start;
-        uint8_t *mmap_base = static_cast<uint8_t *>(
-          mmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE, _fd, aligned_offset_start));
-
-        data_obj = std::make_shared<ir::CachedData>(mmap_base + offset, data_size);
-        _buf_to_data[buf_idx] = data_obj;
-
-        munmap(mmap_base, mmap_size);
-      }
-    }
-    subg.setOperandValue(operand_index, std::move(data_obj));
-  }
-
-  _tensor_names.emplace(operand_index, tensor->name()->str());
-
-  // Variable
-  if (tensor->is_variable())
-  {
-    if (data != nullptr)
-      throw std::runtime_error("Variable tensor with buffer is not supported!");
-
-    subg.operands().at(operand_index).info().setAsVariable();
-  }
-
-  return operand_index;
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadQuantization(const Tensor *tensor, ir::TypeInfo &typeInfo)
-{
-  auto q_params = tensor->quantization();
-  if (q_params == nullptr || q_params->scale() == nullptr || q_params->scale()->size() == 0)
-  {
-    typeInfo.quantization(0., 0);
-    return;
-  }
-  if (q_params->zero_point() == nullptr)
-  {
-    throw std::runtime_error("Quantization params: scale is not null, but zero_point is null.");
-  }
-  const size_t num_scales = q_params->scale()->size();
-  if (num_scales != q_params->zero_point()->size())
-  {
-    throw std::runtime_error("Quantization params: scale size != zero_point size");
-  }
-  std::vector<float> scales;
-  std::vector<int32_t> zero_points;
-  scales.resize(num_scales);
-  zero_points.resize(num_scales);
-  for (size_t i = 0; i < num_scales; ++i)
-  {
-    scales[i] = q_params->scale()->Get(i);
-    // zero_point is defined as long (i64) in schema while TypeInfo's zero_point is int32_t.
-    // int64_t is used instead of long because long is 4 byte in most 32bit architecture.
-    int64_t zero_point = q_params->zero_point()->Get(i);
-    if (zero_point < std::numeric_limits<int32_t>::min() ||
-        zero_point > std::numeric_limits<int32_t>::max())
-      throw std::runtime_error("Zero_point is out of int32 range.");
-    zero_points[i] = static_cast<int32_t>(zero_point);
-  }
-  auto details = q_params->details_as_CustomQuantization();
-  if (details != nullptr)
-    throw std::runtime_error("Custom Quantization is not supported");
-  typeInfo.quantization(std::move(scales), std::move(zero_points));
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadSparsity(const Tensor *tensor, ir::TypeInfo &typeInfo)
-{
-  auto src_sparsity = tensor->sparsity();
-  if (src_sparsity != nullptr)
-  {
-    std::vector<uint16_t> w1_segments;
-    std::vector<uint16_t> w1_indices;
-    // check traversal_order
-    if (src_sparsity->traversal_order())
-    {
-      const int traversal_order_size = src_sparsity->traversal_order()->size();
-      for (int i = 0; i < traversal_order_size; ++i)
-      {
-        if (i != src_sparsity->traversal_order()->Get(i))
-          throw std::runtime_error("traversal_order [0, 1, ..., n-1] is only supported.");
-      }
-    }
-    // check block_map
-    int block_rank = 0;
-    if (src_sparsity->block_map())
-    {
-      block_rank = src_sparsity->block_map()->size();
-      for (int i = 0; i < block_rank; ++i)
-      {
-        if (i != src_sparsity->block_map()->Get(i))
-          throw std::runtime_error("block_map [0, 1, ..., n-1] is only supported.");
-      }
-    }
-    // load metadata
-    const auto dim_metadata_size = src_sparsity->dim_metadata()->size();
-    const auto dense_rank = tensor->shape() ? tensor->shape()->size() : 0;
-    if (dense_rank + block_rank != dim_metadata_size)
-      throw std::runtime_error("sparsity dim_metadata length is wrong.");
-    bool random_sparsity = dim_metadata_size == 2 && block_rank == 0;
-    bool block2D_sparsity = dim_metadata_size == 4 && block_rank == 2;
-    if (dim_metadata_size != !random_sparsity && !block2D_sparsity)
-      throw std::runtime_error(
-        "sparsity is supported only for 2D tensor with random or 16x1 block sparsity.");
-
-    const auto *src_metadata = src_sparsity->dim_metadata()->Get(0);
-    if (src_metadata->format() != DimensionType::DimensionType_DENSE)
-      throw std::runtime_error("sparse tensor dim[0] is not DENSE");
-    src_metadata = src_sparsity->dim_metadata()->Get(1);
-    if (src_metadata->format() != DimensionType::DimensionType_SPARSE_CSR)
-      throw std::runtime_error("sparse tensor dim[0] is not SPARSE_CSR");
-    auto ParseSparseIndexVector = [src_metadata, &w1_segments, &w1_indices]() {
-      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:
-          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;
-        case SparseIndexVector::SparseIndexVector_Uint8Vector:
-          status = Copy(src_metadata->array_segments_as_Uint8Vector(), w1_segments);
-          break;
-        default:
-          return false;
-      }
-      if (status != true)
-        return false;
-      switch (src_metadata->array_indices_type())
-      {
-        case SparseIndexVector::SparseIndexVector_Int32Vector:
-          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:
-          return Copy(src_metadata->array_indices_as_Uint8Vector(), w1_indices);
-        default:
-          break;
-      }
-      return false;
-    };
-    if (ParseSparseIndexVector() == false)
-      throw std::runtime_error("Error during parsing sparsity index information");
-    // Get block size
-    std::vector<int32_t> block_size;
-    for (int i = 0; i < block_rank; ++i)
-    {
-      auto block_metadata = src_sparsity->dim_metadata()->Get(dense_rank + i);
-      if (block_metadata->format() != DimensionType::DimensionType_DENSE)
-        throw std::runtime_error("block dimension must be DENSE.");
-      block_size.push_back(block_metadata->dense_size());
-    }
-    typeInfo.sparsity(std::make_shared<ir::Sparsity>(std::move(w1_segments), std::move(w1_indices),
-                                                     std::move(block_size)));
-  }
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadOperationIO(const Operator *op, ir::OperandIndexSequence &inputs,
-                                               ir::OperandIndexSequence &outputs)
-{
-  for (const std::int32_t idx : *op->inputs())
-  {
-    // Optional tensors are not supported yet except for FULLY_CONNECTED and BCQ_FULLY_CONNECTED
-    auto check_optional_input = [&]() {
-      auto builtin_code = getBuiltinOperator(op);
-      if (isOptionalInputTensor(idx) && !allowOptionalInputTensor(builtin_code))
-        throw std::runtime_error(
-          std::string("loader doesn't support optional input tensor yet for ")
-            .append(EnumNameBuiltinOperator(builtin_code)));
-    };
-    check_optional_input();
-    inputs.append(tensorIdxToOperandIdx(idx));
-  }
-
-  for (const std::int32_t idx : *op->outputs())
-  {
-    outputs.append(tensorIdxToOperandIdx(idx));
-  }
-}
-
-template <typename LoaderDomain>
-template <typename Param, typename OptionsType>
-void BaseLoader<LoaderDomain>::loadStridesAndPaddings(Param &param, const OptionsType *options)
-{
-  // Strides
-  param.stride.vertical = options->stride_h();
-  param.stride.horizontal = options->stride_w();
-  // Paddings
-  switch (options->padding())
-  {
-    case Padding::Padding_SAME:
-      param.padding.type = ir::PaddingType::SAME;
-      break;
-    case Padding::Padding_VALID:
-      param.padding.type = ir::PaddingType::VALID;
-      break;
-    default:
-      throw std::runtime_error{"Invalid padding type"};
-  }
-  // param paddings indexes unused
-}
-
-template <typename LoaderDomain>
-template <typename Param>
-void BaseLoader<LoaderDomain>::loadPool2DOptions(Param &param, const Pool2DOptions *options)
-{
-  // Strides and Paddings
-  if (options->stride_h() <= 0 || options->stride_w() <= 0)
-    throw std::runtime_error{"Invalid stride vertical or horizontal - both must be bigger than 0"};
-  loadStridesAndPaddings(param, options);
-  // Filter width and height
-  // Strides
-  if (options->filter_width() <= 0 || options->filter_height() <= 0)
-    throw std::runtime_error{"Invalid filter width or height - both must be bigger than 0"};
-  param.kw = options->filter_width();
-  param.kh = options->filter_height();
-  // Activation
-  param.activation = convertActivation(options->fused_activation_function());
-}
-
-template <typename LoaderDomain>
-template <typename OpIR, typename... Args>
-const OpIR *BaseLoader<LoaderDomain>::loadOperationTo(const Operator *op, ir::Graph &subg,
-                                                      Args &&... args)
-{
-  static_assert(sizeof...(args) <= 1, "You can't have more than 1 arguments!");
-  ir::OperandIndexSequence inputs;
-  ir::OperandIndexSequence outputs;
-
-  loadOperationIO(op, inputs, outputs);
-
-  std::unique_ptr<OpIR> new_op(new OpIR(inputs, outputs, std::forward<Args>(args)...));
-  auto ret = new_op.get();
-  subg.addOperation(std::move(new_op));
-
-  return ret;
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadConv2D(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Conv2D::Param param;
-  const auto *options = op->builtin_options_as_Conv2DOptions();
-  param.activation = convertActivation(options->fused_activation_function());
-  loadStridesAndPaddings(param, options);
-  param.dilation.width_factor = options->dilation_w_factor();
-  param.dilation.height_factor = options->dilation_h_factor();
-
-  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>
-void BaseLoader<LoaderDomain>::loadDepthwiseConv2D(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::DepthwiseConv2D::Param param;
-  const auto *options = op->builtin_options_as_DepthwiseConv2DOptions();
-  param.activation = convertActivation(options->fused_activation_function());
-  loadStridesAndPaddings(param, options);
-  param.multiplier = options->depth_multiplier();
-  // Dilation h/w factor unused
-  param.dilation.width_factor = options->dilation_w_factor();
-  param.dilation.height_factor = options->dilation_h_factor();
-
-  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>
-void BaseLoader<LoaderDomain>::loadTransposeConv(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::TransposeConv::Param param;
-  const auto *options = op->builtin_options_as_TransposeConvOptions();
-  loadStridesAndPaddings(param, options);
-
-  loadOperationTo<ir::operation::TransposeConv>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadPool2D(const Operator *op, ir::Graph &subg,
-                                          ir::operation::Pool2D::PoolType op_type)
-{
-  ir::operation::Pool2D::Param param;
-  param.op_type = op_type;
-  const auto *options = op->builtin_options_as_Pool2DOptions();
-
-  loadPool2DOptions(param, options);
-
-  loadOperationTo<ir::operation::Pool2D>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadReshape(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Reshape::Param param{};
-  const auto *options = op->builtin_options_as_ReshapeOptions();
-  if (options != nullptr)
-  {
-    const auto *new_shape = options->new_shape();
-    if (new_shape)
-    {
-      for (uint i = 0; i < new_shape->size(); ++i)
-      {
-        param.new_shape.push_back(new_shape->Get(i));
-      }
-    }
-  }
-
-  loadOperationTo<ir::operation::Reshape>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadSoftmax(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Softmax::Param param;
-  const auto *options = op->builtin_options_as_SoftmaxOptions();
-  // Beta
-  param.beta = options->beta();
-
-  loadOperationTo<ir::operation::Softmax>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadConcatenation(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Concat::Param param;
-  const auto *options = op->builtin_options_as_ConcatenationOptions();
-  // Axis
-  param.axis = options->axis();
-  // activation unused
-
-  loadOperationTo<ir::operation::Concat>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadFC(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::FullyConnected::Param param;
-  const auto *options = op->builtin_options_as_FullyConnectedOptions();
-
-  param.activation = convertActivation(options->fused_activation_function());
-  param.weights_format = static_cast<ir::FullyConnectedWeightsFormat>(options->weights_format());
-
-  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 =
-    subg.operands().at(fc->getInputs().at(ir::operation::FullyConnected::WEIGHT));
-  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>
-void BaseLoader<LoaderDomain>::loadAddV2(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::BinaryArithmetic::Param param;
-  param.arithmetic_type = ir::operation::BinaryArithmetic::ArithmeticType::ADD;
-
-  if (op->custom_options() == nullptr)
-  {
-    param.activation = ir::Activation::NONE;
-  }
-  else
-  {
-    const auto attr_map = getCustomOpAttrMap(op);
-    const auto fused_activation_func = static_cast<typename LoaderDomain::ActivationFunctionType>(
-      attr_map["fused_activation_function"].AsInt8());
-    param.activation = convertActivation(fused_activation_func);
-  }
-
-  loadOperationTo<ir::operation::BinaryArithmetic>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadDepthToSpace(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::DepthToSpace::Param param;
-  const auto *options = op->builtin_options_as_DepthToSpaceOptions();
-  param.block_size = options->block_size();
-
-  loadOperationTo<ir::operation::DepthToSpace>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadBinaryArithmetic(
-  const Operator *op, ir::Graph &subg, ir::operation::BinaryArithmetic::ArithmeticType op_type)
-{
-  ir::operation::BinaryArithmetic::Param param;
-  param.arithmetic_type = op_type;
-  switch (op_type)
-  {
-    case ir::operation::BinaryArithmetic::ArithmeticType::ADD:
-    {
-      const auto *add_options = op->builtin_options_as_AddOptions();
-      param.activation = convertActivation(add_options->fused_activation_function());
-      break;
-    }
-    case ir::operation::BinaryArithmetic::ArithmeticType::SUB:
-    {
-      const auto *sub_options = op->builtin_options_as_SubOptions();
-      param.activation = convertActivation(sub_options->fused_activation_function());
-      break;
-    }
-    case ir::operation::BinaryArithmetic::ArithmeticType::MUL:
-    {
-      const auto *mul_options = op->builtin_options_as_MulOptions();
-      param.activation = convertActivation(mul_options->fused_activation_function());
-      break;
-    }
-    case ir::operation::BinaryArithmetic::ArithmeticType::DIV:
-    {
-      const auto *div_options = op->builtin_options_as_DivOptions();
-      param.activation = convertActivation(div_options->fused_activation_function());
-      break;
-    }
-    default:
-      assert(false &&
-             "The function 'loadBinaryArithmetic' supports only BinaryArithmetic operations");
-      break;
-  }
-
-  loadOperationTo<ir::operation::BinaryArithmetic>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadPack(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Pack::Param param;
-  const auto *options = op->builtin_options_as_PackOptions();
-  param.num = options->values_count();
-  param.axis = options->axis();
-
-  loadOperationTo<ir::operation::Pack>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadElementwiseActivation(
-  const Operator *op, ir::Graph &subg, ir::operation::ElementwiseActivation::Type op_type,
-  float alpha, float beta)
-{
-  ir::operation::ElementwiseActivation::Param param;
-  param.op_type = op_type;
-  param.alpha = alpha;
-  param.beta = beta;
-
-  loadOperationTo<ir::operation::ElementwiseActivation>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadResizeBilinear(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::ResizeBilinear::Param param;
-  param.align_corners = op->builtin_options_as_ResizeBilinearOptions()->align_corners();
-  param.half_pixel_centers = op->builtin_options_as_ResizeBilinearOptions()->half_pixel_centers();
-
-  loadOperationTo<ir::operation::ResizeBilinear>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadResizeNearestNeighbor(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::ResizeNearestNeighbor::Param param;
-  param.align_corners = op->builtin_options_as_ResizeNearestNeighborOptions()->align_corners();
-
-  loadOperationTo<ir::operation::ResizeNearestNeighbor>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadReduce(const Operator *op, ir::Graph &subg,
-                                          ir::operation::Reduce::ReduceType reduce_type)
-{
-  ir::operation::Reduce::Param param;
-  param.reduce_type = reduce_type;
-  param.keep_dims = op->builtin_options_as_ReducerOptions()->keep_dims();
-
-  loadOperationTo<ir::operation::Reduce>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadReduceAll(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Reduce::Param param;
-  param.reduce_type = ir::operation::Reduce::ReduceType::ALL;
-  if (op->custom_options() == nullptr)
-  {
-    param.keep_dims = false;
-  }
-  else
-  {
-    const auto attr_map = getCustomOpAttrMap(op);
-    param.keep_dims = attr_map["keep_dims"].AsBool();
-  }
-
-  loadOperationTo<ir::operation::Reduce>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadElementwiseBinary(
-  const Operator *op, ir::Graph &subg,
-  ir::operation::ElementwiseBinary::ElementwiseBinaryType op_type)
-{
-  ir::operation::ElementwiseBinary::Param param;
-  param.op_type = op_type;
-
-  loadOperationTo<ir::operation::ElementwiseBinary>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadElementwiseUnary(const Operator *op, ir::Graph &subg,
-                                                    ir::operation::ElementwiseUnary::Type op_type)
-{
-  ir::operation::ElementwiseUnary::Param param;
-  param.op_type = op_type;
-
-  const auto eu = loadOperationTo<ir::operation::ElementwiseUnary>(op, subg, param);
-  if (op_type == ir::operation::ElementwiseUnary::Type::CAST)
-  {
-    auto qasymm8ToUint8 = [](ir::Operand &operand) {
-      if (operand.typeInfo().type() == ir::DataType::QUANT_UINT8_ASYMM)
-      {
-        operand.type(ir::DataType::UINT8);
-      }
-    };
-    qasymm8ToUint8(
-      subg.operands().at(eu->getInputs().at(ir::operation::ElementwiseUnary::Input::INPUT)));
-    qasymm8ToUint8(subg.operands().at(eu->getOutputs().at(0)));
-  }
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadGather(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Gather::Param param;
-  param.axis = op->builtin_options_as_GatherOptions()->axis();
-
-  loadOperationTo<ir::operation::Gather>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadDetectionPostProcess(const Operator *op, ir::Graph &subg)
-{
-  const auto &m = getCustomOpAttrMap(op);
-
-  ir::operation::DetectionPostProcess::Param param;
-
-  param.max_detections = m["max_detections"].AsInt32();
-
-  // TODO fixme
-  param.max_classes_per_detection = m["max_classes_per_detection"].AsInt32();
-  if (m["detections_per_class"].IsNull())
-    param.max_boxes_per_class = 100;
-  else
-    param.max_boxes_per_class = m["detections_per_class"].AsInt32();
-
-  if (m["use_regular_nms"].IsNull())
-    param.do_fast_eval = true;
-  else
-    param.do_fast_eval = !m["use_regular_nms"].AsBool();
-
-  param.score_threshold = m["nms_score_threshold"].AsFloat();
-  param.iou_threshold = m["nms_iou_threshold"].AsFloat();
-
-  // TODO add num classes support
-  param.num_classes = m["num_classes"].AsInt32();
-
-  param.scale.y_scale = m["y_scale"].AsFloat();
-  param.scale.x_scale = m["x_scale"].AsFloat();
-  param.scale.h_scale = m["h_scale"].AsFloat();
-  param.scale.w_scale = m["w_scale"].AsFloat();
-
-  // TODO depends on input model framework
-  param.center_size_boxes = true;
-
-  loadOperationTo<ir::operation::DetectionPostProcess>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadBatchMatMul(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::BatchMatMul::Param param;
-
-  const auto builtin_op = getBuiltinOperator(op);
-
-  switch (builtin_op)
-  {
-    case BuiltinOperator::BuiltinOperator_BATCH_MATMUL:
-      // Handled on each loader: different option name
-      //  Circle: adjoint_lhs, adjoint_rhs
-      //  TFLite: adj_x, adj_y
-      throw std::runtime_error(
-        std::string("Cannot handle here: ").append(EnumNameBuiltinOperator(builtin_op)) + " as " +
-        EnumNameBuiltinOperator(BuiltinOperator::BuiltinOperator_BATCH_MATMUL));
-    case BuiltinOperator::BuiltinOperator_CUSTOM:
-      if (op->custom_options() == nullptr)
-      {
-        param.adj_x = false;
-        param.adj_y = false;
-      }
-      else
-      {
-        const auto attr_map = getCustomOpAttrMap(op);
-        param.adj_x = attr_map["adj_x"].AsBool();
-        param.adj_y = attr_map["adj_y"].AsBool();
-      }
-      break;
-    default:
-      throw std::runtime_error(
-        std::string("Wrong loaded operation: ").append(EnumNameBuiltinOperator(builtin_op)) +
-        " as " + EnumNameBuiltinOperator(BuiltinOperator::BuiltinOperator_BATCH_MATMUL));
-  }
-
-  loadOperationTo<ir::operation::BatchMatMul>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadSpaceToDepth(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::SpaceToDepth::Param param;
-  const auto *options = op->builtin_options_as_SpaceToDepthOptions();
-  param.block_size = options->block_size();
-
-  loadOperationTo<ir::operation::SpaceToDepth>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadCustom(const Operator *op, ir::Graph &subg)
-{
-  ir::OperandIndexSequence inputs;
-  ir::OperandIndexSequence outputs;
-
-  assert(op->custom_options_format() == CustomOptionsFormat::CustomOptionsFormat_FLEXBUFFERS &&
-         "Unsupported custom operation options format");
-
-  auto *op_code = _domain_model->operator_codes()->Get(op->opcode_index());
-  auto custom_op_name = op_code->custom_code()->str();
-
-  enum class BuiltinOP
-  {
-    AddV2,
-    ReduceAll,
-    MatrixBandPart,
-    BatchMatMul,
-    Einsum,
-    BroadcastTo,
-    FusedBatchNorm,
-    StatelessRandomUniform,
-    Erf,
-    DetectionPostProcess
-  };
-
-  // Mapping from custom op name string to BuiltinOP enum
-  std::map<std::string, BuiltinOP> builtin_map = {
-    {"AddV2", BuiltinOP::AddV2},
-    {"All", BuiltinOP::ReduceAll},
-    {"MatrixBandPart", BuiltinOP::MatrixBandPart},
-    {"BatchMatMulV2", BuiltinOP::BatchMatMul},
-    {"Einsum", BuiltinOP::Einsum},
-    {"FusedBatchNormV3", BuiltinOP::FusedBatchNorm},
-    {"BroadcastTo", BuiltinOP::BroadcastTo},
-    {"StatelessRandomUniform", BuiltinOP::StatelessRandomUniform},
-    {"Erf", BuiltinOP::Erf},
-    {"TFLite_Detection_PostProcess", BuiltinOP::DetectionPostProcess},
-  };
-
-  try
-  {
-    // Throw out_of_range if it is unknown custom op
-    auto custom_op_id = builtin_map.at(custom_op_name);
-    switch (custom_op_id)
-    {
-      case BuiltinOP::AddV2:
-        loadAddV2(op, subg);
-        break;
-      case BuiltinOP::ReduceAll:
-        loadReduceAll(op, subg);
-        break;
-      case BuiltinOP::MatrixBandPart:
-        loadOperationTo<ir::operation::MatrixBandPart>(op, subg);
-        break;
-      case BuiltinOP::BatchMatMul:
-        loadBatchMatMul(op, subg);
-        break;
-      case BuiltinOP::Einsum:
-        loadEinsum(op, subg);
-        break;
-      case BuiltinOP::BroadcastTo:
-        loadOperationTo<ir::operation::BroadcastTo>(op, subg);
-        break;
-      case BuiltinOP::FusedBatchNorm:
-        loadFusedBatchNorm(op, subg);
-        break;
-      case BuiltinOP::StatelessRandomUniform:
-        loadOperationTo<ir::operation::StatelessRandomUniform>(op, subg);
-        break;
-      case BuiltinOP::Erf:
-        loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::ERF);
-        break;
-      case BuiltinOP::DetectionPostProcess:
-        loadDetectionPostProcess(op, subg);
-        break;
-      default:
-        throw std::runtime_error{
-          "Loader: Custom OP map is defined but operation loader function is not defined"};
-    }
-
-    return;
-  }
-  catch (...)
-  {
-    loadOperationIO(op, inputs, outputs);
-
-    auto constraint = ir::OperandConstraint::createExact(inputs.size());
-
-    size_t custom_op_data_size = op->custom_options()->size();
-    auto custom_op_data = new char[custom_op_data_size];
-    std::copy(op->custom_options()->begin(), op->custom_options()->end(), custom_op_data);
-
-    ir::operation::Custom::Userdata userdata{};
-    userdata.data = custom_op_data;
-    userdata.size = custom_op_data_size;
-
-    auto new_op = std::make_unique<ir::operation::Custom>(constraint, inputs, outputs,
-                                                          custom_op_name, userdata);
-
-    subg.addOperation(std::move(new_op));
-  }
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadSqueeze(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Squeeze::Param param;
-  const auto *options = op->builtin_options_as_SqueezeOptions();
-  const auto *dims = options->squeeze_dims();
-  if (dims)
-  {
-    if (dims->size() > sizeof(param.dims) / sizeof(param.dims[0]))
-      throw std::runtime_error("Squeeze: 'param.ndims' is out of range.");
-    param.ndim = dims->size();
-    for (int i = 0; i < param.ndim; ++i)
-      param.dims[i] = dims->Get(i);
-  }
-
-  loadOperationTo<ir::operation::Squeeze>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadSplit(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Split::Param param;
-  const auto *options = op->builtin_options_as_SplitOptions();
-  param.num_splits = options->num_splits();
-
-  loadOperationTo<ir::operation::Split>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadSplitV(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::SplitV::Param param;
-  const auto *options = op->builtin_options_as_SplitVOptions();
-  param.num_splits = options->num_splits();
-
-  loadOperationTo<ir::operation::SplitV>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadStridedSlice(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::StridedSlice::Param param;
-  const auto *options = op->builtin_options_as_StridedSliceOptions();
-  param.begin_mask = options->begin_mask();
-  param.end_mask = options->end_mask();
-  param.shrink_axis_mask = options->shrink_axis_mask();
-
-  loadOperationTo<ir::operation::StridedSlice>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadUnpack(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Unpack::Param param;
-  const auto *options = op->builtin_options_as_UnpackOptions();
-  param.num = options->num();
-  param.axis = options->axis();
-
-  loadOperationTo<ir::operation::Unpack>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadComparison(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Comparison::Param param;
-  const auto builtin_op = getBuiltinOperator(op);
-
-  switch (builtin_op)
-  {
-    case BuiltinOperator::BuiltinOperator_EQUAL:
-      param.comparison_type = ir::operation::Comparison::ComparisonType::Equal;
-      break;
-    case BuiltinOperator::BuiltinOperator_NOT_EQUAL:
-      param.comparison_type = ir::operation::Comparison::ComparisonType::NotEqual;
-      break;
-    case BuiltinOperator::BuiltinOperator_GREATER_EQUAL:
-      param.comparison_type = ir::operation::Comparison::ComparisonType::GreaterEqual;
-      break;
-    case BuiltinOperator::BuiltinOperator_GREATER:
-      param.comparison_type = ir::operation::Comparison::ComparisonType::Greater;
-      break;
-    case BuiltinOperator::BuiltinOperator_LESS_EQUAL:
-      param.comparison_type = ir::operation::Comparison::ComparisonType::LessEqual;
-      break;
-    case BuiltinOperator::BuiltinOperator_LESS:
-      param.comparison_type = ir::operation::Comparison::ComparisonType::Less;
-      break;
-    default:
-      throw std::runtime_error(
-        std::string("Unsupported operation: ").append(EnumNameBuiltinOperator(builtin_op)));
-  }
-
-  loadOperationTo<ir::operation::Comparison>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadEinsum(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::Einsum::Param param;
-  if (op->custom_options() == nullptr)
-  {
-    throw std::runtime_error{"Einsum: empty equation"};
-  }
-  else
-  {
-    const auto attr_map = getCustomOpAttrMap(op);
-    param.equation = attr_map["equation"].ToString();
-  }
-
-  const auto es = loadOperationTo<ir::operation::Einsum>(op, subg, param);
-  if (es->getInputs().size() != 2)
-  {
-    throw std::runtime_error{"Einsum: NYI input - only support two inputs"};
-  }
-}
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadFusedBatchNorm(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::FusedBatchNorm::Param param;
-  if (op->custom_options() == nullptr)
-  {
-    throw std::runtime_error{"FusedBatchNorm: empty option"};
-  }
-  else
-  {
-    const auto attr_map = getCustomOpAttrMap(op);
-    param.is_training = attr_map["is_training"].AsBool();
-    param.epsilon = attr_map["epsilon"].AsFloat();
-    param.data_format = attr_map["data_format"].ToString();
-  }
-
-  const auto fbn = loadOperationTo<ir::operation::FusedBatchNorm>(op, subg, param);
-
-  if (fbn->getInputs().size() != 5)
-  {
-    throw std::runtime_error{"FusedBatchNorm: NYI input - only support five inputs"};
-  }
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadOneHot(const Operator *op, ir::Graph &subg)
-{
-  if (op->inputs()->size() != 4 || op->outputs()->size() != 1)
-    throw std::runtime_error("OneHot Op has wrong number of input or output tensors.");
-
-  // Set parameter
-  ir::operation::OneHot::Param param;
-  param.axis = op->builtin_options_as_OneHotOptions()->axis();
-
-  loadOperationTo<ir::operation::OneHot>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadIf(const Operator *op, ir::Graph &subg)
-{
-  const auto *options = op->builtin_options_as_IfOptions();
-  const int32_t then_index = options->then_subgraph_index();
-  const int32_t else_index = options->else_subgraph_index();
-
-  verifySubgraphIndex(then_index);
-  verifySubgraphIndex(else_index);
-
-  ir::operation::If::Param param;
-  param.then_subg_index = ir::SubgraphIndex{static_cast<uint16_t>(then_index)};
-  param.else_subg_index = ir::SubgraphIndex{static_cast<uint16_t>(else_index)};
-
-  loadOperationTo<ir::operation::If>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadWhile(const Operator *op, ir::Graph &subg)
-{
-  const auto *options = op->builtin_options_as_WhileOptions();
-  const int32_t cond_index = options->cond_subgraph_index();
-  const int32_t body_index = options->body_subgraph_index();
-
-  verifySubgraphIndex(cond_index);
-  verifySubgraphIndex(body_index);
-
-  ir::operation::While::Param param;
-  param.cond_subg_index = ir::SubgraphIndex{static_cast<uint16_t>(cond_index)};
-  param.body_subg_index = ir::SubgraphIndex{static_cast<uint16_t>(body_index)};
-
-  loadOperationTo<ir::operation::While>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadArgMinMax(const Operator *op, ir::Graph &subg, bool is_argmax)
-{
-  ir::operation::ArgMinMax::Param param;
-  const auto output_type = is_argmax ? op->builtin_options_as_ArgMaxOptions()->output_type()
-                                     : op->builtin_options_as_ArgMinOptions()->output_type();
-  param.output_type = tensorTypeToDataType(output_type);
-  param.is_arg_max = is_argmax;
-
-  loadOperationTo<ir::operation::ArgMinMax>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadLogSoftmax(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::LogSoftmax::Param param;
-  // In tflite, beta is fixed to 1.0 and axis is fixed to -1.
-  param.beta = 1.0f;
-  param.axis = -1;
-
-  loadOperationTo<ir::operation::LogSoftmax>(op, subg, param);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadLeakyRelu(const Operator *op, ir::Graph &subg)
-{
-  float alpha = op->builtin_options_as_LeakyReluOptions()->alpha();
-  loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::LEAKY_RELU, alpha,
-                            1.f);
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadUnidirectionalSequenceLSTM(const Operator *op, ir::Graph &subg)
-{
-  ir::operation::LSTM::Param param;
-  const auto *options = op->builtin_options_as_UnidirectionalSequenceLSTMOptions();
-  param.activation = convertActivation(options->fused_activation_function());
-  param.cell_threshold = options->cell_clip();
-  param.projection_threshold = options->proj_clip();
-  param.time_major = options->time_major();
-  // The asymmetric_quantize_inputs option is unused yet
-
-  ir::OperandIndexSequence inputs;
-  for (const std::int32_t idx : *op->inputs())
-  {
-    inputs.append(tensorIdxToOperandIdx(idx));
-  }
-
-  ir::OperandIndexSequence outputs;
-  // loader doesn't support optional output tensor yet
-  if (op->outputs()->size() != 1)
-  {
-    auto builtin_code = getBuiltinOperator(op);
-    throw std::runtime_error(std::string("loader doesn't support optional output tensor yet for ")
-                               .append(EnumNameBuiltinOperator(builtin_code)));
-  }
-  for (size_t i = 0; i < ir::operation::LSTM::Output::OUTPUT; ++i)
-  {
-    // Add optional outputs
-    outputs.append(ir::OperandIndex());
-  }
-  outputs.append(tensorIdxToOperandIdx(op->outputs()->Get(0)));
-
-  std::unique_ptr<ir::operation::LSTM> new_op(new ir::operation::LSTM(inputs, outputs, param));
-  subg.addOperation(std::move(new_op));
-}
-
-template <typename LoaderDomain>
-void BaseLoader<LoaderDomain>::loadOperation(const Operator *op, ir::Graph &subg)
-{
-  auto const builtin_op = getBuiltinOperator(op);
-
-  switch (builtin_op)
-  {
-    case BuiltinOperator::BuiltinOperator_ADD_N:
-      loadOperationTo<ir::operation::AddN>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_CONV_2D:
-      loadConv2D(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_AVERAGE_POOL_2D:
-      loadPool2D(op, subg, ir::operation::Pool2D::PoolType::AVG);
-      return;
-    case BuiltinOperator::BuiltinOperator_DEPTHWISE_CONV_2D:
-      loadDepthwiseConv2D(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_TRANSPOSE_CONV:
-      loadTransposeConv(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_RESHAPE:
-      loadReshape(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_SOFTMAX:
-      loadSoftmax(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_MAX_POOL_2D:
-      loadPool2D(op, subg, ir::operation::Pool2D::PoolType::MAX);
-      return;
-    case BuiltinOperator::BuiltinOperator_CONCATENATION:
-      loadConcatenation(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_FLOOR:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::FLOOR);
-      return;
-    case BuiltinOperator::BuiltinOperator_FULLY_CONNECTED:
-      loadFC(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_ADD:
-      loadBinaryArithmetic(op, subg, ir::operation::BinaryArithmetic::ArithmeticType::ADD);
-      return;
-    case BuiltinOperator::BuiltinOperator_SUB:
-      loadBinaryArithmetic(op, subg, ir::operation::BinaryArithmetic::ArithmeticType::SUB);
-      return;
-    case BuiltinOperator::BuiltinOperator_MUL:
-      loadBinaryArithmetic(op, subg, ir::operation::BinaryArithmetic::ArithmeticType::MUL);
-      return;
-    case BuiltinOperator::BuiltinOperator_DIV:
-      loadBinaryArithmetic(op, subg, ir::operation::BinaryArithmetic::ArithmeticType::DIV);
-      return;
-    case BuiltinOperator::BuiltinOperator_PACK:
-      loadPack(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_ELU:
-      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::ELU);
-      return;
-    case BuiltinOperator::BuiltinOperator_RELU:
-      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::RELU,
-                                ir::operation::ElementwiseActivation::infinity, 0.f);
-      return;
-    case BuiltinOperator::BuiltinOperator_RELU_N1_TO_1:
-      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::RELU, 1.f,
-                                -1.f);
-      return;
-    case BuiltinOperator::BuiltinOperator_RELU6:
-      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::RELU, 6.f,
-                                0.f);
-      return;
-    case BuiltinOperator::BuiltinOperator_RESIZE_BILINEAR:
-      loadResizeBilinear(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR:
-      loadResizeNearestNeighbor(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_RSQRT:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::RSQRT);
-      return;
-    case BuiltinOperator::BuiltinOperator_SELECT:
-    case BuiltinOperator::BuiltinOperator_SELECT_V2:
-      loadOperationTo<ir::operation::Select>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_SQRT:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::SQRT);
-      return;
-    case BuiltinOperator::BuiltinOperator_SQUARE:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::SQUARE);
-      return;
-    case BuiltinOperator::BuiltinOperator_SQUARED_DIFFERENCE:
-      loadOperationTo<ir::operation::SquaredDifference>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_TANH:
-      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::TANH, 1.f,
-                                1.f);
-      return;
-    case BuiltinOperator::BuiltinOperator_TRANSPOSE:
-      loadOperationTo<ir::operation::Transpose>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_MEAN:
-      loadReduce(op, subg, ir::operation::Reduce::ReduceType::MEAN);
-      return;
-    case BuiltinOperator::BuiltinOperator_REDUCE_ANY:
-      loadReduce(op, subg, ir::operation::Reduce::ReduceType::ANY);
-      return;
-    case BuiltinOperator::BuiltinOperator_REDUCE_MAX:
-      loadReduce(op, subg, ir::operation::Reduce::ReduceType::MAX);
-      return;
-    case BuiltinOperator::BuiltinOperator_REVERSE_V2:
-      loadOperationTo<ir::operation::Reverse>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_PAD:
-    case BuiltinOperator::BuiltinOperator_PADV2:
-      loadOperationTo<ir::operation::Pad>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_LOGISTIC:
-      loadElementwiseActivation(op, subg, ir::operation::ElementwiseActivation::Type::LOGISTIC);
-      return;
-    case BuiltinOperator::BuiltinOperator_EXP:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::EXP);
-      return;
-    case BuiltinOperator::BuiltinOperator_EXPAND_DIMS:
-      loadOperationTo<ir::operation::ExpandDims>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_GATHER:
-      loadGather(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_SPACE_TO_BATCH_ND:
-      loadOperationTo<ir::operation::SpaceToBatchND>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_BATCH_TO_SPACE_ND:
-      loadOperationTo<ir::operation::BatchToSpaceND>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_SUM:
-      loadReduce(op, subg, ir::operation::Reduce::ReduceType::SUM);
-      return;
-    case BuiltinOperator::BuiltinOperator_CUSTOM:
-      loadCustom(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_SQUEEZE:
-      loadSqueeze(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_PRELU:
-      loadOperationTo<ir::operation::PReLU>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_SPLIT:
-      loadSplit(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_SPLIT_V:
-      loadSplitV(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_SLICE:
-      loadOperationTo<ir::operation::Slice>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_STRIDED_SLICE:
-      loadStridedSlice(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_UNPACK:
-      loadUnpack(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_FLOOR_DIV:
-      loadElementwiseBinary(op, subg,
-                            ir::operation::ElementwiseBinary::ElementwiseBinaryType::FLOOR_DIV);
-      return;
-    case BuiltinOperator::BuiltinOperator_MINIMUM:
-      loadElementwiseBinary(op, subg, ir::operation::ElementwiseBinary::ElementwiseBinaryType::MIN);
-      return;
-    case BuiltinOperator::BuiltinOperator_MAXIMUM:
-      loadElementwiseBinary(op, subg, ir::operation::ElementwiseBinary::ElementwiseBinaryType::MAX);
-      return;
-    case BuiltinOperator::BuiltinOperator_CAST:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::CAST);
-      return;
-    case BuiltinOperator::BuiltinOperator_EQUAL:
-    case BuiltinOperator::BuiltinOperator_NOT_EQUAL:
-    case BuiltinOperator::BuiltinOperator_GREATER_EQUAL:
-    case BuiltinOperator::BuiltinOperator_GREATER:
-    case BuiltinOperator::BuiltinOperator_LESS_EQUAL:
-    case BuiltinOperator::BuiltinOperator_LESS:
-      loadComparison(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_ONE_HOT:
-      loadOneHot(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_ABS:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::ABS);
-      return;
-    case BuiltinOperator::BuiltinOperator_COS:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::COS);
-      return;
-    case BuiltinOperator::BuiltinOperator_SIN:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::SIN);
-      return;
-    case BuiltinOperator::BuiltinOperator_SHAPE:
-      loadOperationTo<ir::operation::Shape>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_REDUCE_PROD:
-      loadReduce(op, subg, ir::operation::Reduce::ReduceType::PROD);
-      return;
-    case BuiltinOperator::BuiltinOperator_IF:
-      loadIf(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_WHILE:
-      loadWhile(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_NEG:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::NEG);
-      return;
-    case BuiltinOperator::BuiltinOperator_ARG_MAX:
-      loadArgMinMax(op, subg, true);
-      return;
-    case BuiltinOperator::BuiltinOperator_ARG_MIN:
-      loadArgMinMax(op, subg, false);
-      return;
-    case BuiltinOperator::BuiltinOperator_LOG:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::LOG);
-      return;
-    case BuiltinOperator::BuiltinOperator_ROUND:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::ROUND);
-      return;
-    case BuiltinOperator::BuiltinOperator_POW:
-      loadOperationTo<ir::operation::Pow>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_LOGICAL_NOT:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::LOGICAL_NOT);
-      return;
-    case BuiltinOperator::BuiltinOperator_LOGICAL_AND:
-      loadElementwiseBinary(op, subg,
-                            ir::operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_AND);
-      return;
-    case BuiltinOperator::BuiltinOperator_LOGICAL_OR:
-      loadElementwiseBinary(op, subg,
-                            ir::operation::ElementwiseBinary::ElementwiseBinaryType::LOGICAL_OR);
-      return;
-    case BuiltinOperator::BuiltinOperator_FILL:
-      loadOperationTo<ir::operation::Fill>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_ZEROS_LIKE:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::ZEROS_LIKE);
-      return;
-    case BuiltinOperator::BuiltinOperator_TILE:
-      loadOperationTo<ir::operation::Tile>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_RANGE:
-      loadOperationTo<ir::operation::Range>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_BATCH_MATMUL:
-      loadBatchMatMul(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_LOG_SOFTMAX:
-      loadLogSoftmax(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_QUANTIZE:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::QUANTIZE);
-      return;
-    case BuiltinOperator::BuiltinOperator_DEQUANTIZE:
-      loadElementwiseUnary(op, subg, ir::operation::ElementwiseUnary::Type::DEQUANTIZE);
-      return;
-    case BuiltinOperator::BuiltinOperator_SPACE_TO_DEPTH:
-      loadSpaceToDepth(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_L2_NORMALIZATION:
-      loadOperationTo<ir::operation::L2Normalization>(op, subg);
-      break;
-    case BuiltinOperator::BuiltinOperator_LEAKY_RELU:
-      loadLeakyRelu(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_RANK:
-      loadOperationTo<ir::operation::Rank>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM:
-      loadUnidirectionalSequenceLSTM(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_DEPTH_TO_SPACE:
-      loadDepthToSpace(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_EMBEDDING_LOOKUP:
-      loadOperationTo<ir::operation::EmbeddingLookup>(op, subg);
-      return;
-    case BuiltinOperator::BuiltinOperator_HASHTABLE_LOOKUP:
-      loadOperationTo<ir::operation::HashtableLookup>(op, subg);
-      return;
-    default:
-      throw std::runtime_error(
-        std::string("Unsupported operation: ").append(EnumNameBuiltinOperator(builtin_op)));
-  }
-}
-
-template <typename LoaderDomain> void BaseLoader<LoaderDomain>::loadModel()
-{
-  LoaderDomain::VerifyModelBuffer(*_verifier.get());
-  _domain_model = LoaderDomain::GetModel(_base);
-  // Version unused
-  // const auto version = _model->version();
-  // Description unused
-  // const auto *description = _model->description();
-  // Metabuffer unsued
-  // const auto *metadata_buffer = _model->metadata_buffer();
-  // Load subgraphs and map operations on subgraph
-  const auto subgraphs = _domain_model->subgraphs();
-  auto model = std::make_unique<ir::Model>();
-  if (subgraphs->size() - 1 > ir::SubgraphIndex::max())
-    throw std::runtime_error{"The number of subgraphs cannot exceed " +
-                             std::to_string(ir::SubgraphIndex::max() + 1)};
-  for (uint16_t subgraph_index = 0; subgraph_index < subgraphs->size(); ++subgraph_index)
-  {
-    auto subg = loadSubgraph((*_domain_model->subgraphs())[subgraph_index]);
-    // NOTE: Used () instead of {}, which does not check narrowing.
-    // It is okay since overflow is checked the above if-statement.
-    model->push(ir::SubgraphIndex(subgraph_index), std::move(subg));
-  }
-  _model = std::move(model);
-}
-
-} // namespace base_loader
-} // namespace onert
-
-#endif //__BASE_LOADER_BASE_LOADER_H__
diff --git a/runtime/onert/frontend/circle/CMakeLists.txt b/runtime/onert/frontend/circle/CMakeLists.txt
deleted file mode 100644 (file)
index fffe5cc..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-if (NOT BUILD_CIRCLE_LOADER)
-    return()
-endif ()
-
-set(CIRCLE_LOADER_SOURCES src/circle_loader.cc)
-
-add_library(circle_loader STATIC ${CIRCLE_LOADER_SOURCES})
-set_target_properties(circle_loader PROPERTIES POSITION_INDEPENDENT_CODE ON)
-
-target_include_directories(circle_loader PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
-
-target_link_libraries(circle_loader PRIVATE onert_core)
-target_link_libraries(circle_loader PRIVATE base_loader nnfw_common nnfw_coverage)
-target_link_libraries(circle_loader PRIVATE circle_schema)
diff --git a/runtime/onert/frontend/circle/include/circle_loader.h b/runtime/onert/frontend/circle/include/circle_loader.h
deleted file mode 100644 (file)
index 87e5d70..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __CIRCLE_CIRCLE_LOADER_H__
-#define __CIRCLE_CIRCLE_LOADER_H__
-
-#include "ir/Graph.h"
-
-#include <memory>
-
-namespace onert
-{
-namespace circle_loader
-{
-std::unique_ptr<ir::Model> loadModel(const std::string &filename);
-std::unique_ptr<ir::Model> loadModel(uint8_t *buffer, size_t size);
-} // namespace circle_loader
-} // namespace onert
-
-#endif // __CIRCLE_CIRCLE_LOADER_H__
diff --git a/runtime/onert/frontend/circle/src/circle_loader.cc b/runtime/onert/frontend/circle/src/circle_loader.cc
deleted file mode 100644 (file)
index 5bf626d..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "circle_loader.h"
-#include "base_loader.h"
-#include "circle_schema_generated.h"
-
-namespace onert
-{
-namespace circle_loader
-{
-
-namespace
-{
-
-ir::Layout convertDataFormat(circle::DataFormat data_format)
-{
-  switch (data_format)
-  {
-    case circle::DataFormat::DataFormat_CHANNELS_FIRST:
-      return ir::Layout::NCHW;
-    case circle::DataFormat::DataFormat_CHANNELS_LAST:
-      return ir::Layout::NHWC;
-    default:
-      throw std::runtime_error("Unsupported DataFormat");
-  }
-}
-
-struct LoaderDomain
-{
-  using Verifier = flatbuffers::Verifier;
-  using ActivationFunctionType = circle::ActivationFunctionType;
-  using Buffer = circle::Buffer;
-  using BuiltinOperator = circle::BuiltinOperator;
-  using CustomOptionsFormat = circle::CustomOptionsFormat;
-  using Model = circle::Model;
-  using Operator = circle::Operator;
-  using Padding = circle::Padding;
-  using Pool2DOptions = circle::Pool2DOptions;
-  using Tensor = circle::Tensor;
-  using TensorType = circle::TensorType;
-  using SubGraph = circle::SubGraph;
-  using DimensionType = circle::DimensionType;
-  using SparseIndexVector = circle::SparseIndexVector;
-
-  static const char *EnumNameBuiltinOperator(BuiltinOperator e)
-  {
-    return circle::EnumNameBuiltinOperator(e);
-  }
-  static const char *EnumNameActivationFunctionType(ActivationFunctionType e)
-  {
-    return circle::EnumNameActivationFunctionType(e);
-  }
-  static const char *EnumNameTensorType(TensorType e) { return circle::EnumNameTensorType(e); }
-  static const Model *GetModel(const void *buf) { return circle::GetModel(buf); }
-  static bool VerifyModelBuffer(Verifier &verifier) { return circle::VerifyModelBuffer(verifier); }
-};
-
-class CircleLoader final : public base_loader::BaseLoader<LoaderDomain>
-{
-protected:
-  // Different option name
-  //  Circle: adjoint_lhs, adjoint_rhs
-  //  TFLite: adj_x, adj_y
-  void loadBatchMatMul(const Operator *op, ir::Graph &subg);
-
-  // Only circle operations
-  void loadInstanceNorm(const Operator *op, ir::Graph &subg);
-  void loadBCQFullyConnected(const Operator *op, ir::Graph &subg);
-  void loadBCQGather(const Operator *op, ir::Graph &subg);
-
-public:
-  using BaseLoader::BaseLoader;
-
-  bool allowOptionalInputTensor(BuiltinOperator op) override
-  {
-    switch (op)
-    {
-      case BuiltinOperator::BuiltinOperator_FULLY_CONNECTED:
-      case BuiltinOperator::BuiltinOperator_BCQ_FULLY_CONNECTED:
-      case BuiltinOperator::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM:
-        return true;
-      default:
-        return false;
-    }
-  }
-
-private:
-  std::unique_ptr<ir::Graph> loadSubgraph(const circle::SubGraph *circle_subg) override
-  {
-    auto subg = std::make_unique<ir::Graph>();
-    // Load tensors
-    _tensor_to_operand.resize(circle_subg->tensors()->size());
-    for (flatbuffers::uoffset_t i = 0; i < circle_subg->tensors()->size(); ++i)
-    {
-      _tensor_to_operand[i] = loadOperand(circle_subg->tensors()->Get(i), *subg);
-    }
-    // Set inputs
-    for (const std::int32_t input_ind : *circle_subg->inputs())
-    {
-      subg->addInput(tensorIdxToOperandIdx(input_ind),
-                     _tensor_names.at(_tensor_to_operand[input_ind]));
-    }
-    // Set outputs
-    for (const std::int32_t output_ind : *circle_subg->outputs())
-    {
-      subg->addOutput(tensorIdxToOperandIdx(output_ind),
-                      _tensor_names.at(_tensor_to_operand[output_ind]));
-    }
-    // Create operations
-    for (const auto *op : *circle_subg->operators())
-    {
-      CircleLoader::loadOperation(op, *subg);
-    }
-
-    subg->setLayout(convertDataFormat(circle_subg->data_format()));
-
-    subg->verify();
-
-    return subg;
-  }
-
-  void loadOperation(const circle::Operator *op, ir::Graph &subg)
-  {
-    auto const builtin_op = getBuiltinOperator(op);
-
-    switch (builtin_op)
-    {
-      case circle::BuiltinOperator::BuiltinOperator_BATCH_MATMUL:
-        loadBatchMatMul(op, subg);
-        return;
-      case circle::BuiltinOperator::BuiltinOperator_INSTANCE_NORM:
-        loadInstanceNorm(op, subg);
-        return;
-      case circle::BuiltinOperator::BuiltinOperator_BCQ_FULLY_CONNECTED:
-        loadBCQFullyConnected(op, subg);
-        return;
-      case circle::BuiltinOperator::BuiltinOperator_BCQ_GATHER:
-        loadBCQGather(op, subg);
-        return;
-      default:
-        BaseLoader::loadOperation(op, subg);
-        return;
-    }
-  }
-};
-
-void CircleLoader::loadBatchMatMul(const Operator *op, ir::Graph &subg)
-{
-  ir::OperandIndexSequence inputs;
-  ir::OperandIndexSequence outputs;
-
-  loadOperationIO(op, inputs, outputs);
-
-  ir::operation::BatchMatMul::Param param;
-  const auto *options = op->builtin_options_as_BatchMatMulOptions();
-
-  param.adj_x = options->adjoint_lhs();
-  param.adj_y = options->adjoint_rhs();
-
-  std::unique_ptr<ir::Operation> new_op(new ir::operation::BatchMatMul(inputs, outputs, param));
-  subg.addOperation(std::move(new_op));
-}
-
-void CircleLoader::loadInstanceNorm(const Operator *op, ir::Graph &subg)
-{
-  ir::OperandIndexSequence inputs;
-  ir::OperandIndexSequence outputs;
-
-  loadOperationIO(op, inputs, outputs);
-
-  ir::operation::InstanceNorm::Param param;
-  const auto *options = op->builtin_options_as_InstanceNormOptions();
-
-  param.activation = convertActivation(options->fused_activation_function());
-  // Use default value 1e-5 if value of epsilon is zero
-  param.epsilon = options->epsilon() == 0.f ? 1e-5 : options->epsilon();
-
-  std::unique_ptr<ir::Operation> new_op(new ir::operation::InstanceNorm(inputs, outputs, param));
-  subg.addOperation(std::move(new_op));
-}
-
-void CircleLoader::loadBCQGather(const Operator *op, ir::Graph &subg)
-{
-  ir::OperandIndexSequence inputs;
-  ir::OperandIndexSequence outputs;
-
-  loadOperationIO(op, inputs, outputs);
-
-  ir::operation::BCQGather::Param param;
-  const auto *options = op->builtin_options_as_BCQGatherOptions();
-  param.input_hidden_size = options->input_hidden_size();
-  param.axis = options->axis();
-
-  std::unique_ptr<ir::Operation> new_op(new ir::operation::BCQGather(inputs, outputs, param));
-  subg.addOperation(std::move(new_op));
-}
-
-void CircleLoader::loadBCQFullyConnected(const Operator *op, ir::Graph &subg)
-{
-  ir::OperandIndexSequence inputs;
-  ir::OperandIndexSequence outputs;
-
-  loadOperationIO(op, inputs, outputs);
-
-  ir::operation::BCQFullyConnected::Param param;
-  const auto *options = op->builtin_options_as_BCQFullyConnectedOptions();
-  param.weights_hidden_size = options->weights_hidden_size();
-  param.activation = convertActivation(options->fused_activation_function());
-
-  std::unique_ptr<ir::Operation> new_op(
-    new ir::operation::BCQFullyConnected(inputs, outputs, param));
-  subg.addOperation(std::move(new_op));
-}
-
-} // namespace
-
-std::unique_ptr<ir::Model> loadModel(const std::string &filename)
-{
-  auto model = std::make_unique<ir::Model>();
-  CircleLoader loader(model);
-  loader.loadFromFile(filename);
-  return model;
-}
-
-std::unique_ptr<ir::Model> loadModel(uint8_t *buffer, size_t size)
-{
-  auto model = std::make_unique<ir::Model>();
-  CircleLoader loader(model);
-  loader.loadFromBuffer(buffer, size);
-  return model;
-}
-
-} // namespace circle_loader
-} // namespace onert
diff --git a/runtime/onert/frontend/circle_schema/CMakeLists.txt b/runtime/onert/frontend/circle_schema/CMakeLists.txt
deleted file mode 100644 (file)
index 208103f..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-add_library(circle_schema INTERFACE)
-
-nnfw_find_package(FlatBuffers REQUIRED)
-
-target_link_libraries(circle_schema INTERFACE flatbuffers::flatbuffers)
-
-target_include_directories(circle_schema INTERFACE include)
diff --git a/runtime/onert/frontend/circle_schema/include/circle_schema_generated.h b/runtime/onert/frontend/circle_schema/include/circle_schema_generated.h
deleted file mode 100644 (file)
index dd6f9dc..0000000
+++ /dev/null
@@ -1,12689 +0,0 @@
-/*
- * 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");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_CIRCLESCHEMA_CIRCLE_H_
-#define FLATBUFFERS_GENERATED_CIRCLESCHEMA_CIRCLE_H_
-
-#include "flatbuffers/flatbuffers.h"
-
-namespace circle
-{
-
-struct CustomQuantization;
-struct CustomQuantizationBuilder;
-
-struct QuantizationParameters;
-struct QuantizationParametersBuilder;
-
-struct Int32Vector;
-struct Int32VectorBuilder;
-
-struct Uint16Vector;
-struct Uint16VectorBuilder;
-
-struct Uint8Vector;
-struct Uint8VectorBuilder;
-
-struct DimensionMetadata;
-struct DimensionMetadataBuilder;
-
-struct SparsityParameters;
-struct SparsityParametersBuilder;
-
-struct VariantSubType;
-struct VariantSubTypeBuilder;
-
-struct Tensor;
-struct TensorBuilder;
-
-struct Conv2DOptions;
-struct Conv2DOptionsBuilder;
-
-struct Conv3DOptions;
-struct Conv3DOptionsBuilder;
-
-struct Pool2DOptions;
-struct Pool2DOptionsBuilder;
-
-struct DepthwiseConv2DOptions;
-struct DepthwiseConv2DOptionsBuilder;
-
-struct ConcatEmbeddingsOptions;
-struct ConcatEmbeddingsOptionsBuilder;
-
-struct LSHProjectionOptions;
-struct LSHProjectionOptionsBuilder;
-
-struct SVDFOptions;
-struct SVDFOptionsBuilder;
-
-struct RNNOptions;
-struct RNNOptionsBuilder;
-
-struct SequenceRNNOptions;
-struct SequenceRNNOptionsBuilder;
-
-struct BidirectionalSequenceRNNOptions;
-struct BidirectionalSequenceRNNOptionsBuilder;
-
-struct FullyConnectedOptions;
-struct FullyConnectedOptionsBuilder;
-
-struct SoftmaxOptions;
-struct SoftmaxOptionsBuilder;
-
-struct ConcatenationOptions;
-struct ConcatenationOptionsBuilder;
-
-struct AddOptions;
-struct AddOptionsBuilder;
-
-struct MulOptions;
-struct MulOptionsBuilder;
-
-struct L2NormOptions;
-struct L2NormOptionsBuilder;
-
-struct LocalResponseNormalizationOptions;
-struct LocalResponseNormalizationOptionsBuilder;
-
-struct LSTMOptions;
-struct LSTMOptionsBuilder;
-
-struct UnidirectionalSequenceLSTMOptions;
-struct UnidirectionalSequenceLSTMOptionsBuilder;
-
-struct BidirectionalSequenceLSTMOptions;
-struct BidirectionalSequenceLSTMOptionsBuilder;
-
-struct ResizeBilinearOptions;
-struct ResizeBilinearOptionsBuilder;
-
-struct ResizeNearestNeighborOptions;
-struct ResizeNearestNeighborOptionsBuilder;
-
-struct CallOptions;
-struct CallOptionsBuilder;
-
-struct PadOptions;
-struct PadOptionsBuilder;
-
-struct PadV2Options;
-struct PadV2OptionsBuilder;
-
-struct ReshapeOptions;
-struct ReshapeOptionsBuilder;
-
-struct SpaceToBatchNDOptions;
-struct SpaceToBatchNDOptionsBuilder;
-
-struct BatchToSpaceNDOptions;
-struct BatchToSpaceNDOptionsBuilder;
-
-struct SkipGramOptions;
-struct SkipGramOptionsBuilder;
-
-struct SpaceToDepthOptions;
-struct SpaceToDepthOptionsBuilder;
-
-struct DepthToSpaceOptions;
-struct DepthToSpaceOptionsBuilder;
-
-struct SubOptions;
-struct SubOptionsBuilder;
-
-struct DivOptions;
-struct DivOptionsBuilder;
-
-struct TopKV2Options;
-struct TopKV2OptionsBuilder;
-
-struct EmbeddingLookupSparseOptions;
-struct EmbeddingLookupSparseOptionsBuilder;
-
-struct GatherOptions;
-struct GatherOptionsBuilder;
-
-struct TransposeOptions;
-struct TransposeOptionsBuilder;
-
-struct ExpOptions;
-struct ExpOptionsBuilder;
-
-struct CosOptions;
-struct CosOptionsBuilder;
-
-struct ReducerOptions;
-struct ReducerOptionsBuilder;
-
-struct SqueezeOptions;
-struct SqueezeOptionsBuilder;
-
-struct SplitOptions;
-struct SplitOptionsBuilder;
-
-struct SplitVOptions;
-struct SplitVOptionsBuilder;
-
-struct StridedSliceOptions;
-struct StridedSliceOptionsBuilder;
-
-struct LogSoftmaxOptions;
-struct LogSoftmaxOptionsBuilder;
-
-struct CastOptions;
-struct CastOptionsBuilder;
-
-struct DequantizeOptions;
-struct DequantizeOptionsBuilder;
-
-struct MaximumMinimumOptions;
-struct MaximumMinimumOptionsBuilder;
-
-struct TileOptions;
-struct TileOptionsBuilder;
-
-struct ArgMaxOptions;
-struct ArgMaxOptionsBuilder;
-
-struct ArgMinOptions;
-struct ArgMinOptionsBuilder;
-
-struct GreaterOptions;
-struct GreaterOptionsBuilder;
-
-struct GreaterEqualOptions;
-struct GreaterEqualOptionsBuilder;
-
-struct LessOptions;
-struct LessOptionsBuilder;
-
-struct LessEqualOptions;
-struct LessEqualOptionsBuilder;
-
-struct NegOptions;
-struct NegOptionsBuilder;
-
-struct SelectOptions;
-struct SelectOptionsBuilder;
-
-struct SliceOptions;
-struct SliceOptionsBuilder;
-
-struct TransposeConvOptions;
-struct TransposeConvOptionsBuilder;
-
-struct ExpandDimsOptions;
-struct ExpandDimsOptionsBuilder;
-
-struct SparseToDenseOptions;
-struct SparseToDenseOptionsBuilder;
-
-struct EqualOptions;
-struct EqualOptionsBuilder;
-
-struct NotEqualOptions;
-struct NotEqualOptionsBuilder;
-
-struct ShapeOptions;
-struct ShapeOptionsBuilder;
-
-struct RankOptions;
-struct RankOptionsBuilder;
-
-struct PowOptions;
-struct PowOptionsBuilder;
-
-struct FakeQuantOptions;
-struct FakeQuantOptionsBuilder;
-
-struct PackOptions;
-struct PackOptionsBuilder;
-
-struct LogicalOrOptions;
-struct LogicalOrOptionsBuilder;
-
-struct OneHotOptions;
-struct OneHotOptionsBuilder;
-
-struct AbsOptions;
-struct AbsOptionsBuilder;
-
-struct HardSwishOptions;
-struct HardSwishOptionsBuilder;
-
-struct LogicalAndOptions;
-struct LogicalAndOptionsBuilder;
-
-struct LogicalNotOptions;
-struct LogicalNotOptionsBuilder;
-
-struct UnpackOptions;
-struct UnpackOptionsBuilder;
-
-struct FloorDivOptions;
-struct FloorDivOptionsBuilder;
-
-struct SquareOptions;
-struct SquareOptionsBuilder;
-
-struct ZerosLikeOptions;
-struct ZerosLikeOptionsBuilder;
-
-struct FillOptions;
-struct FillOptionsBuilder;
-
-struct FloorModOptions;
-struct FloorModOptionsBuilder;
-
-struct RangeOptions;
-struct RangeOptionsBuilder;
-
-struct LeakyReluOptions;
-struct LeakyReluOptionsBuilder;
-
-struct SquaredDifferenceOptions;
-struct SquaredDifferenceOptionsBuilder;
-
-struct MirrorPadOptions;
-struct MirrorPadOptionsBuilder;
-
-struct UniqueOptions;
-struct UniqueOptionsBuilder;
-
-struct ReverseV2Options;
-struct ReverseV2OptionsBuilder;
-
-struct AddNOptions;
-struct AddNOptionsBuilder;
-
-struct GatherNdOptions;
-struct GatherNdOptionsBuilder;
-
-struct WhereOptions;
-struct WhereOptionsBuilder;
-
-struct ReverseSequenceOptions;
-struct ReverseSequenceOptionsBuilder;
-
-struct MatrixDiagOptions;
-struct MatrixDiagOptionsBuilder;
-
-struct QuantizeOptions;
-struct QuantizeOptionsBuilder;
-
-struct MatrixSetDiagOptions;
-struct MatrixSetDiagOptionsBuilder;
-
-struct IfOptions;
-struct IfOptionsBuilder;
-
-struct CallOnceOptions;
-struct CallOnceOptionsBuilder;
-
-struct WhileOptions;
-struct WhileOptionsBuilder;
-
-struct NonMaxSuppressionV4Options;
-struct NonMaxSuppressionV4OptionsBuilder;
-
-struct NonMaxSuppressionV5Options;
-struct NonMaxSuppressionV5OptionsBuilder;
-
-struct ScatterNdOptions;
-struct ScatterNdOptionsBuilder;
-
-struct SelectV2Options;
-struct SelectV2OptionsBuilder;
-
-struct DensifyOptions;
-struct DensifyOptionsBuilder;
-
-struct SegmentSumOptions;
-struct SegmentSumOptionsBuilder;
-
-struct BatchMatMulOptions;
-struct BatchMatMulOptionsBuilder;
-
-struct CumsumOptions;
-struct CumsumOptionsBuilder;
-
-struct BroadcastToOptions;
-struct BroadcastToOptionsBuilder;
-
-struct Rfft2dOptions;
-struct Rfft2dOptionsBuilder;
-
-struct HashtableOptions;
-struct HashtableOptionsBuilder;
-
-struct HashtableFindOptions;
-struct HashtableFindOptionsBuilder;
-
-struct HashtableImportOptions;
-struct HashtableImportOptionsBuilder;
-
-struct HashtableSizeOptions;
-struct HashtableSizeOptionsBuilder;
-
-struct VarHandleOptions;
-struct VarHandleOptionsBuilder;
-
-struct ReadVariableOptions;
-struct ReadVariableOptionsBuilder;
-
-struct AssignVariableOptions;
-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;
-
-struct BCQFullyConnectedOptions;
-struct BCQFullyConnectedOptionsBuilder;
-
-struct InstanceNormOptions;
-struct InstanceNormOptionsBuilder;
-
-struct OperatorCode;
-struct OperatorCodeBuilder;
-
-struct Operator;
-struct OperatorBuilder;
-
-struct SubGraph;
-struct SubGraphBuilder;
-
-struct Buffer;
-struct BufferBuilder;
-
-struct Metadata;
-struct MetadataBuilder;
-
-struct TensorMap;
-struct TensorMapBuilder;
-
-struct SignatureDef;
-struct SignatureDefBuilder;
-
-struct Model;
-struct ModelBuilder;
-
-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_UINT16 = 16,
-  TensorType_INT4 = 17,
-  TensorType_MIN = TensorType_FLOAT32,
-  TensorType_MAX = TensorType_INT4
-};
-
-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_UINT16,    TensorType_INT4};
-  return values;
-}
-
-inline const char *const *EnumNamesTensorType()
-{
-  static const char *const names[19] = {"FLOAT32", "FLOAT16",    "INT32",  "UINT8",     "INT64",
-                                        "STRING",  "BOOL",       "INT16",  "COMPLEX64", "INT8",
-                                        "FLOAT64", "COMPLEX128", "UINT64", "RESOURCE",  "VARIANT",
-                                        "UINT32",  "UINT16",     "INT4",   nullptr};
-  return names;
-}
-
-inline const char *EnumNameTensorType(TensorType e)
-{
-  if (flatbuffers::IsOutRange(e, TensorType_FLOAT32, TensorType_INT4))
-    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;
-};
-
-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;
-};
-
-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_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_RIGHT_SHIFT
-};
-
-inline const BuiltinOperator (&EnumValuesBuiltinOperator())[165]
-{
-  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,
-                                           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[167] = {"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",
-                                         "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_RIGHT_SHIFT))
-    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_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,
-  BuiltinOptions_MIN = BuiltinOptions_NONE,
-  BuiltinOptions_MAX = BuiltinOptions_InstanceNormOptions
-};
-
-inline const BuiltinOptions (&EnumValuesBuiltinOptions())[130]
-{
-  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_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};
-  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",
-                                         "BucketizeOptions",
-                                         "GeluOptions",
-                                         "DynamicUpdateSliceOptions",
-                                         "UnsortedSegmentProdOptions",
-                                         "UnsortedSegmentMaxOptions",
-                                         "UnsortedSegmentMinOptions",
-                                         "UnsortedSegmentSumOptions",
-                                         "ATan2Options",
-                                         "SignOptions",
-                                         "BitcastOptions",
-                                         "BitwiseXorOptions",
-                                         "RightShiftOptions",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "",
-                                         "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::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;
-};
-
-template <> struct BuiltinOptionsTraits<circle::BCQFullyConnectedOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_BCQFullyConnectedOptions;
-};
-
-template <> struct BuiltinOptionsTraits<circle::InstanceNormOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_InstanceNormOptions;
-};
-
-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 CustomQuantization FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-struct QuantizationParameters FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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);
-}
-
-struct Int32Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-struct Uint16Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-struct Uint8Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-struct DimensionMetadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SparsityParameters FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-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;
-  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,
-    VT_HAS_RANK = 20,
-    VT_VARIANT_TENSORS = 22
-  };
-  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 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) &&
-           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()) &&
-           VerifyField<uint8_t>(verifier, VT_HAS_RANK) &&
-           VerifyOffset(verifier, VT_VARIANT_TENSORS) && verifier.VerifyVector(variant_tensors()) &&
-           verifier.VerifyVectorOfTables(variant_tensors()) && verifier.EndTable();
-  }
-};
-
-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);
-  }
-  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();
-  }
-  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, 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();
-}
-
-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, 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__, has_rank, variant_tensors__);
-}
-
-struct Conv2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct Conv3DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct Pool2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct DepthwiseConv2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct ConcatEmbeddingsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-struct LSHProjectionOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SVDFOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct RNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SequenceRNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct BidirectionalSequenceRNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct FullyConnectedOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SoftmaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct ConcatenationOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct AddOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct MulOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct L2NormOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct LocalResponseNormalizationOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct LSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct UnidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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,
-    VT_DIAGONAL_RECURRENT_TENSORS = 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 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 diagonal_recurrent_tensors() const
-  {
-    return GetField<uint8_t>(VT_DIAGONAL_RECURRENT_TENSORS, 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) &&
-           VerifyField<uint8_t>(verifier, VT_DIAGONAL_RECURRENT_TENSORS) && verifier.EndTable();
-  }
-};
-
-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);
-  }
-  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)
-  {
-    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, 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);
-  return builder_.Finish();
-}
-
-struct BidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct ResizeBilinearOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct ResizeNearestNeighborOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct CallOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct PadOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef PadOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct PadV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef PadV2OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ReshapeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-struct SpaceToBatchNDOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SpaceToBatchNDOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct BatchToSpaceNDOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef BatchToSpaceNDOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SkipGramOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SpaceToDepthOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct DepthToSpaceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SubOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct DivOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct TopKV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef TopKV2OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct EmbeddingLookupSparseOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct GatherOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct TransposeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef TransposeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ExpOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ExpOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct CosOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef CosOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ReducerOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SqueezeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-struct SplitOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SplitVOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct StridedSliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct LogSoftmaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LogSoftmaxOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct CastOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct DequantizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef DequantizeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct MaximumMinimumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef MaximumMinimumOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct TileOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef TileOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ArgMaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct ArgMinOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct GreaterOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef GreaterOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct GreaterEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef GreaterEqualOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct LessOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LessOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct LessEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LessEqualOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct NegOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef NegOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SelectOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SelectOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SliceOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct TransposeConvOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef TransposeConvOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_PADDING = 4,
-    VT_STRIDE_W = 6,
-    VT_STRIDE_H = 8,
-    VT_FUSED_ACTIVATION_FUNCTION = 10
-  };
-  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));
-  }
-  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) && verifier.EndTable();
-  }
-};
-
-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);
-  }
-  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();
-  }
-  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,
-  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();
-}
-
-struct ExpandDimsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ExpandDimsOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SparseToDenseOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct EqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef EqualOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct NotEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef NotEqualOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ShapeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct RankOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef RankOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct PowOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef PowOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct FakeQuantOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct PackOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct LogicalOrOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LogicalOrOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct OneHotOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct AbsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef AbsOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct HardSwishOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef HardSwishOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct LogicalAndOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LogicalAndOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct LogicalNotOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LogicalNotOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct UnpackOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct FloorDivOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef FloorDivOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SquareOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SquareOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ZerosLikeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ZerosLikeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct FillOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef FillOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct FloorModOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef FloorModOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct RangeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef RangeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct LeakyReluOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SquaredDifferenceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SquaredDifferenceOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct MirrorPadOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct UniqueOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct ReverseV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ReverseV2OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct AddNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef AddNOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct GatherNdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef GatherNdOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct WhereOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef WhereOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ReverseSequenceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct MatrixDiagOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef MatrixDiagOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct QuantizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef QuantizeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct MatrixSetDiagOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef MatrixSetDiagOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct IfOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct CallOnceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct WhileOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct NonMaxSuppressionV4Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef NonMaxSuppressionV4OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct NonMaxSuppressionV5Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef NonMaxSuppressionV5OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ScatterNdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ScatterNdOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SelectV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SelectV2OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct DensifyOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef DensifyOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SegmentSumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SegmentSumOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct BatchMatMulOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct CumsumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct BroadcastToOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef BroadcastToOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct Rfft2dOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef Rfft2dOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct HashtableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct HashtableFindOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef HashtableFindOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct HashtableImportOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef HashtableImportOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct HashtableSizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef HashtableSizeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct VarHandleOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-struct ReadVariableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ReadVariableOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct AssignVariableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef AssignVariableOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct RandomOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef RandomOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_SEED = 4,
-    VT_SEED2 = 6
-  };
-  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<int64_t>(verifier, VT_SEED) &&
-           VerifyField<int64_t>(verifier, VT_SEED2) && verifier.EndTable();
-  }
-};
-
-struct RandomOptionsBuilder
-{
-  typedef RandomOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  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();
-  }
-  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,
-                                                              int64_t seed = 0, int64_t seed2 = 0)
-{
-  RandomOptionsBuilder builder_(_fbb);
-  builder_.add_seed2(seed2);
-  builder_.add_seed(seed);
-  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;
-  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();
-  }
-};
-
-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();
-}
-
-struct BCQFullyConnectedOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct InstanceNormOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct OperatorCode FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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);
-}
-
-struct Operator FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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::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
-             ? 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();
-  }
-};
-
-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::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
-{
-  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__);
-}
-
-struct SubGraph FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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);
-}
-
-struct Buffer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-struct Metadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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);
-}
-
-struct TensorMap FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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);
-}
-
-struct SignatureDef FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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);
-}
-
-struct Model FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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__);
-}
-
-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 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 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_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);
-      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 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());
-}
-
-} // namespace circle
-
-#endif // FLATBUFFERS_GENERATED_CIRCLESCHEMA_CIRCLE_H_
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.cc b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.cc
deleted file mode 100644 (file)
index 3b5edc1..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "ANeuralNetworksCompilation.h"
-
-#include "util/logging.h"
-
-using namespace onert;
-
-// TODO Support multiple subgraphs
-ANeuralNetworksCompilation::ANeuralNetworksCompilation(const ANeuralNetworksModel *model) noexcept
-  : _model{model->getModel()}, _coptions{compiler::CompilerOptions::fromGlobalConfig()},
-    _compiler{std::make_shared<compiler::Compiler>(_model, *_coptions)}
-{
-  if (model->allowedToFp16())
-    _coptions->enableToFp16();
-}
-
-bool ANeuralNetworksCompilation::finish() noexcept
-{
-  try
-  {
-    _artifact = _compiler->compile();
-    _compiler = nullptr;
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.h b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksCompilation.h
deleted file mode 100644 (file)
index 3898f1d..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __COMPILATION_H__
-#define __COMPILATION_H__
-
-#include "ANeuralNetworksModel.h"
-
-#include "compiler/Compiler.h"
-#include "ir/Graph.h"
-#include "ir/Model.h"
-#include "exec/IExecutors.h"
-#include "util/TracingCtx.h"
-
-struct ANeuralNetworksCompilation
-{
-public:
-  ANeuralNetworksCompilation(const ANeuralNetworksModel *model) noexcept;
-
-public:
-  bool finish() noexcept;
-  bool isFinished() noexcept { return _compiler == nullptr; }
-
-  void publish(std::shared_ptr<onert::exec::IExecutors> &executors) noexcept
-  {
-    executors = _artifact ? _artifact->_executors : nullptr;
-  }
-
-private:
-  std::shared_ptr<onert::ir::Model> _model;
-  std::unique_ptr<onert::compiler::CompilerOptions> _coptions;
-  std::shared_ptr<onert::compiler::Compiler> _compiler;
-  std::shared_ptr<onert::compiler::CompilerArtifact> _artifact;
-};
-
-#endif
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.cc b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksExecution.cc
deleted file mode 100644 (file)
index 21c7cdd..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "ANeuralNetworksExecution.h"
-#include "NNAPIConvert.h"
-#include "util/logging.h"
-
-const onert::ir::OperandIndex ANeuralNetworksExecution::getInputOperandIndex(int32_t index) noexcept
-{
-  if (index < 0)
-  {
-    // Negative index: return invalid index
-    return onert::ir::OperandIndex{};
-  }
-
-  uint32_t cast_index = static_cast<uint32_t>(index);
-  if (cast_index >= _execution->primary_subgraph().getInputs().size())
-  {
-    // Return invalid index
-    return onert::ir::OperandIndex{};
-  }
-
-  onert::ir::IOIndex input_index{cast_index};
-  const auto operand_index = _execution->primary_subgraph().getInputs().at(input_index);
-  return operand_index;
-}
-
-const onert::ir::OperandIndex
-ANeuralNetworksExecution::getOutputOperandIndex(int32_t index) noexcept
-{
-  if (index < 0)
-  {
-    // Negative index: return invalid index
-    return onert::ir::OperandIndex{};
-  }
-
-  uint32_t cast_index = static_cast<uint32_t>(index);
-  if (cast_index >= _execution->primary_subgraph().getOutputs().size())
-  {
-    // Return invalid index
-    return onert::ir::OperandIndex{};
-  }
-
-  onert::ir::IOIndex output_index{cast_index};
-  const auto operand_index = _execution->primary_subgraph().getOutputs().at(output_index);
-  return operand_index;
-}
-
-bool ANeuralNetworksExecution::compareDataType(const ANeuralNetworksOperandType *type,
-                                               const onert::ir::OperandIndex index) noexcept
-{
-  try
-  {
-    const auto operand_type = _execution->primary_subgraph().operands().at(index).typeInfo();
-    const auto typeInfo = NNAPIConvert::getTypeInfo(type);
-
-    if (operand_type != typeInfo)
-    {
-      // Data type mismatch
-      return false;
-    }
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-bool ANeuralNetworksExecution::compareShape(const ANeuralNetworksOperandType *type,
-                                            const onert::ir::OperandIndex index) noexcept
-{
-  // Passed shape should be specified
-  if (hasUnspecifiedDims(index))
-  {
-    return false;
-  }
-
-  const auto &operand_shape = _execution->primary_subgraph().operands().at(index).shape();
-  const auto &shape_from_type = NNAPIConvert::getShape(type);
-
-  return operand_shape == shape_from_type;
-}
-
-bool ANeuralNetworksExecution::IsOptionalInput(const onert::ir::OperandIndex index) noexcept
-{
-  const auto &operand_shape = _execution->primary_subgraph().operands().at(index).shape();
-  for (int32_t i = 0; i < operand_shape.rank(); ++i)
-  {
-    if (operand_shape.dim(i) != 0)
-      return false;
-  }
-  return true;
-}
-
-bool ANeuralNetworksExecution::hasUnspecifiedDims(const onert::ir::OperandIndex index) noexcept
-{
-  const auto operand_shape = _execution->primary_subgraph().operands().at(index).shape();
-
-  return operand_shape.hasUnspecifiedDims();
-}
-
-size_t ANeuralNetworksExecution::getOperandSize(const onert::ir::OperandIndex index) noexcept
-{
-  try
-  {
-    return _execution->primary_subgraph().operands().at(index).operandSize();
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return 0;
-  }
-}
-
-bool ANeuralNetworksExecution::setInput(uint32_t index, const ANeuralNetworksOperandType *type,
-                                        const void *buffer, size_t length) noexcept
-{
-  try
-  {
-    onert::ir::IOIndex input_index{index};
-    const auto operand_index = getInputOperandIndex(index);
-
-    const auto type_info = _execution->primary_subgraph().operands().at(operand_index).typeInfo();
-    const auto shape = (type != nullptr)
-                         ? NNAPIConvert::getShape(type)
-                         : _execution->primary_subgraph().operands().at(operand_index).shape();
-
-    // NOTE The nnapi does not provide setting io_layout and not support changing layout. In other
-    // words, we can assume that io_layout from nnapi always is the same as layout of the used
-    // model.
-    // TODO Set layout of model
-    _execution->setInput(input_index, type_info, shape, buffer, length, onert::ir::Layout::NHWC);
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-bool ANeuralNetworksExecution::setOptionalInput(uint32_t index,
-                                                const ANeuralNetworksOperandType *type,
-                                                const void *buffer, size_t length) noexcept
-{
-  assert(type == nullptr);
-  assert(buffer == nullptr);
-  assert(length == 0);
-  try
-  {
-    onert::ir::IOIndex input_index{index};
-    const auto operand_index = getInputOperandIndex(index);
-
-    const auto type_info = _execution->primary_subgraph().operands().at(operand_index).typeInfo();
-    const auto shape = (type != nullptr)
-                         ? NNAPIConvert::getShape(type)
-                         : _execution->primary_subgraph().operands().at(operand_index).shape();
-
-    // ANeuralNetworksExecution::setInput() uses only shape information
-    ANeuralNetworksOperandType optional_input_type;
-    optional_input_type.dimensionCount = shape.rank();
-    std::vector<uint32_t> dims(optional_input_type.dimensionCount);
-    for (uint32_t i = 0; i < optional_input_type.dimensionCount; ++i)
-    {
-      dims.at(i) = shape.dim(i);
-    }
-    optional_input_type.dimensions = dims.data();
-
-    return setInput(index, &optional_input_type, buffer, length);
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-bool ANeuralNetworksExecution::setOutput(uint32_t index, const ANeuralNetworksOperandType *type,
-                                         void *buffer, size_t length) noexcept
-{
-  try
-  {
-    onert::ir::IOIndex output_index{index};
-    const auto operand_index = getOutputOperandIndex(index);
-
-    const auto type_info = _execution->primary_subgraph().operands().at(operand_index).typeInfo();
-    const auto shape = (type != nullptr)
-                         ? NNAPIConvert::getShape(type)
-                         : _execution->primary_subgraph().operands().at(operand_index).shape();
-
-    // NOTE The nnapi does not provide setting io_layout and not support changing layout. In other
-    // words, we can assume that io_layout from nnapi always is the same as layout of the used
-    // model.
-    // TODO Set layout of model
-    _execution->setOutput(output_index, type_info, shape, buffer, length, onert::ir::Layout::NHWC);
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-bool ANeuralNetworksExecution::startExecute(void) noexcept
-{
-  try
-  {
-    _execution->startExecute();
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-bool ANeuralNetworksExecution::execute(void) noexcept
-{
-  try
-  {
-    _execution->execute();
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-const std::shared_ptr<onert::exec::Execution> ANeuralNetworksExecution::instance(void) noexcept
-{
-  return _execution;
-}
-
-bool ANeuralNetworksExecution::getOutputOperandRank(uint32_t index, uint32_t *rank) noexcept
-{
-  try
-  {
-    onert::ir::IOIndex output_index{index};
-
-    // Check execution is finished
-    if (!_execution->isFinished())
-    {
-      return false;
-    }
-
-    const auto shape = _execution->getOutputShape(output_index);
-    if (shape.hasUnspecifiedDims())
-    {
-      throw std::runtime_error{"Internal error: Output tensor has unspecified dims"};
-    }
-
-    *rank = shape.rank();
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-bool ANeuralNetworksExecution::getOutputOperandDimensions(uint32_t index, uint32_t *dimensions)
-{
-  try
-  {
-    onert::ir::IOIndex output_index{index};
-
-    // Check execution is finished
-    if (!_execution->isFinished())
-    {
-      return false;
-    }
-
-    const auto shape = _execution->getOutputShape(output_index);
-    if (shape.hasUnspecifiedDims())
-    {
-      throw std::runtime_error{"Internal error: Output tensor has unspecified dims"};
-    }
-
-    for (int i = 0; i < shape.rank(); i++)
-    {
-      auto dim = shape.dim(i);
-
-      if (dim <= 0)
-      {
-        throw std::runtime_error{"Invalid dimension value"};
-      }
-
-      dimensions[i] = static_cast<uint32_t>(dim);
-    }
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
diff --git a/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc b/runtime/onert/frontend/nnapi/wrapper/ANeuralNetworksModel.cc
deleted file mode 100644 (file)
index 837dac9..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "ANeuralNetworksModel.h"
-#include "OperationFactory.h"
-#include "NNAPIConvert.h"
-
-#include "ir/Operations.Include.h"
-#include "util/logging.h"
-
-#include <memory>
-
-//
-// ANeuralNetworksModel
-//
-ANeuralNetworksModel::ANeuralNetworksModel() noexcept
-  : _finished_building{false}, _optional_operands{}, _operand_usages{}, _allowFloat32toFloat16{
-                                                                          false}
-{
-  _graph = std::make_shared<onert::ir::Graph>();
-}
-
-bool ANeuralNetworksModel::addOperand(const ANeuralNetworksOperandType *type) noexcept
-{
-  try
-  {
-    const auto shape = NNAPIConvert::getShape(type);
-    const auto typeInfo = NNAPIConvert::getTypeInfo(type);
-    _graph->addOperand(shape, typeInfo);
-    _operand_usages.emplace_back(OperandUsage::NOT_DEFINED);
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-bool ANeuralNetworksModel::setOperandValue(uint32_t index, const void *buffer, size_t length,
-                                           bool optional, bool copy) noexcept
-{
-  const onert::ir::OperandIndex ind{index};
-
-  try
-  {
-    _operand_usages[index] = OperandUsage::CONSTANT;
-
-    // Remain operands.at(ind).data()->base() as nullptr for optional operand
-    // This will be filled when model finished
-    if (optional)
-    {
-      setOptionalOperand(ind);
-    }
-
-    using onert::ir::CachedData;
-    using onert::ir::ExternalData;
-    if (copy)
-    {
-      _graph->operands().at(ind).data(
-        std::make_unique<CachedData>(reinterpret_cast<const uint8_t *>(buffer), length));
-    }
-    else
-    {
-      _graph->operands().at(ind).data(
-        std::make_unique<ExternalData>(reinterpret_cast<const uint8_t *>(buffer), length));
-    }
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-bool ANeuralNetworksModel::addOperation(ANeuralNetworksOperationType type, uint32_t inputCount,
-                                        const uint32_t *inputs, uint32_t outputCount,
-                                        const uint32_t *outputs) noexcept
-{
-  try
-  {
-    for (uint32_t i = 0; i < outputCount; i++)
-    {
-      _operand_usages[outputs[i]] = OperandUsage::OPERATION_OUTPUT;
-    }
-
-    auto &factory = OperationFactory::get();
-    OperationFactory::Param param{inputCount, inputs, outputCount, outputs};
-
-    auto node = factory.create(type, param, _graph->operands());
-    _graph->addOperation(std::unique_ptr<onert::ir::Operation>{node});
-
-    // TODO Move these codes to delegate.cpp
-    if (type == ANEURALNETWORKS_FULLY_CONNECTED)
-    {
-      const auto &input_operand =
-        _graph->operands().at(node->getInputs().at(onert::ir::operation::FullyConnected::INPUT));
-      auto &weights_operand =
-        _graph->operands().at(node->getInputs().at(onert::ir::operation::FullyConnected::WEIGHT));
-      if (input_operand.typeInfo().type() == onert::ir::DataType::FLOAT32 &&
-          weights_operand.typeInfo().type() == onert::ir::DataType::QUANT_UINT8_ASYMM)
-      {
-        weights_operand.type(onert::ir::DataType::QUANT_INT8_SYMM);
-      }
-    }
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-bool ANeuralNetworksModel::addOperationEx(ANeuralNetworksOperationTypeEx type, uint32_t inputCount,
-                                          const uint32_t *inputs, uint32_t outputCount,
-                                          const uint32_t *outputs) noexcept
-{
-  try
-  {
-    for (uint32_t i = 0; i < outputCount; i++)
-    {
-      _operand_usages[outputs[i]] = OperandUsage::OPERATION_OUTPUT;
-    }
-
-    auto &factory = OperationFactory::get();
-    OperationFactory::Param param{inputCount, inputs, outputCount, outputs};
-
-    auto node = factory.create(type, param, _graph->operands());
-    _graph->addOperation(std::unique_ptr<onert::ir::Operation>{node});
-  }
-  catch (const std::exception &e)
-  {
-    return false;
-  }
-  return true;
-}
-
-bool ANeuralNetworksModel::addModelInput(uint32_t index) noexcept
-{
-  try
-  {
-    _operand_usages[index] = OperandUsage::MODEL_INPUT;
-
-    const onert::ir::OperandIndex ind{index};
-    _graph->addInput(ind);
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-bool ANeuralNetworksModel::addModelOutput(uint32_t index) noexcept
-{
-  try
-  {
-    const onert::ir::OperandIndex ind{index};
-
-    // Duplicated output is not allowed
-    if (_graph->getOutputs().contains(ind))
-    {
-      return false;
-    }
-
-    _graph->addOutput(ind);
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << std::endl;
-
-    return false;
-  }
-
-  return true;
-}
-
-void ANeuralNetworksModel::allowFloat32toFloat16(bool allow) noexcept
-{
-  _allowFloat32toFloat16 = allow;
-}
-
-bool ANeuralNetworksModel::finish() noexcept
-{
-  try
-  {
-    fillOptionalOperand();
-
-    _graph->verify();
-    _operand_usages.clear();
-    _finished_building = true;
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << '\n';
-
-    return false;
-  }
-
-  return true;
-}
-
-bool ANeuralNetworksModel::isFinished() noexcept { return _finished_building; }
-
-bool ANeuralNetworksModel::isExistOperand(uint32_t index) noexcept
-{
-  return _graph->operands().exist(onert::ir::OperandIndex{index});
-}
-
-size_t ANeuralNetworksModel::operandSize(uint32_t index) noexcept
-{
-  try
-  {
-    return _graph->operands().at(onert::ir::OperandIndex{index}).operandSize();
-  }
-  catch (const std::exception &e)
-  {
-    VERBOSE(EXCEPTION) << e.what() << '\n';
-
-    return 0;
-  }
-}
-
-bool ANeuralNetworksModel::isUsageSet(uint32_t index) noexcept
-{
-  return (_operand_usages[index] != OperandUsage::NOT_DEFINED);
-}
-
-bool ANeuralNetworksModel::isOperationOutput(uint32_t index) noexcept
-{
-  return (_operand_usages[index] == OperandUsage::OPERATION_OUTPUT);
-}
-
-void ANeuralNetworksModel::setOptionalOperand(const onert::ir::OperandIndex idx)
-{
-  _optional_operands.insert(idx);
-}
-
-void ANeuralNetworksModel::fillOptionalOperand(void)
-{
-  _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())
-      {
-        throw std::runtime_error{"Optional operand is not supported yet"};
-      }
-    }
-  });
-}
-
-std::shared_ptr<onert::ir::Model> ANeuralNetworksModel::getModel() const
-{
-  auto model = std::make_shared<onert::ir::Model>();
-
-  model->push(onert::ir::SubgraphIndex{0}, _graph);
-  // TODO Find all child subgraphs and copy them to all_subgs
-  // Must find the same subgraph by using to compare pointer of subgraphs and set subgraph's index
-  // to operands of control flow operations
-  // Must clean all child subgraphs's pointer to prevent memory leak in case of that graph has
-  // subgraph itself recursively
-
-  return model;
-}
diff --git a/runtime/onert/frontend/tflite/CMakeLists.txt b/runtime/onert/frontend/tflite/CMakeLists.txt
deleted file mode 100644 (file)
index 792feeb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-if(NOT BUILD_TFLITE_LOADER)
-  return()
-endif(NOT BUILD_TFLITE_LOADER)
-
-set(TFLITE_LOADER_SOURCES src/tflite_loader.cc)
-
-add_library(tflite_loader STATIC ${TFLITE_LOADER_SOURCES})
-set_target_properties(tflite_loader PROPERTIES POSITION_INDEPENDENT_CODE ON)
-
-target_include_directories(tflite_loader PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
-
-target_link_libraries(tflite_loader PRIVATE onert_core)
-target_link_libraries(tflite_loader PRIVATE base_loader nnfw_common nnfw_coverage)
diff --git a/runtime/onert/frontend/tflite/include/tflite_loader.h b/runtime/onert/frontend/tflite/include/tflite_loader.h
deleted file mode 100644 (file)
index cf17863..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES 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_TFLITE_LOADER_H__
-#define __TFLITE_TFLITE_LOADER_H__
-
-#include "ir/Graph.h"
-
-#include <memory>
-
-namespace onert
-{
-namespace tflite_loader
-{
-
-std::unique_ptr<ir::Model> loadModel(const std::string &filename);
-
-} // namespace tflite_loader
-} // namespace onert
-
-#endif // __TFLITE_TFLITE_LOADER_H__
diff --git a/runtime/onert/frontend/tflite/src/tflite_loader.cc b/runtime/onert/frontend/tflite/src/tflite_loader.cc
deleted file mode 100644 (file)
index dc85646..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "tflite_loader.h"
-#include "base_loader.h"
-#include "tflite_schema_generated.h"
-
-namespace onert
-{
-namespace tflite_loader
-{
-
-namespace
-{
-
-struct LoaderDomain
-{
-  using Verifier = flatbuffers::Verifier;
-  using ActivationFunctionType = onert_tflite::ActivationFunctionType;
-  using Buffer = onert_tflite::Buffer;
-  using BuiltinOperator = onert_tflite::BuiltinOperator;
-  using CustomOptionsFormat = onert_tflite::CustomOptionsFormat;
-  using Model = onert_tflite::Model;
-  using Operator = onert_tflite::Operator;
-  using Padding = onert_tflite::Padding;
-  using Pool2DOptions = onert_tflite::Pool2DOptions;
-  using Tensor = onert_tflite::Tensor;
-  using TensorType = onert_tflite::TensorType;
-  using SubGraph = onert_tflite::SubGraph;
-  using DimensionType = onert_tflite::DimensionType;
-  using SparseIndexVector = onert_tflite::SparseIndexVector;
-
-  static const char *EnumNameBuiltinOperator(BuiltinOperator e)
-  {
-    return onert_tflite::EnumNameBuiltinOperator(e);
-  }
-  static const char *EnumNameActivationFunctionType(ActivationFunctionType e)
-  {
-    return onert_tflite::EnumNameActivationFunctionType(e);
-  }
-  static const char *EnumNameTensorType(TensorType e)
-  {
-    return onert_tflite::EnumNameTensorType(e);
-  }
-  static const Model *GetModel(const void *buf) { return onert_tflite::GetModel(buf); }
-  static bool VerifyModelBuffer(Verifier &verifier)
-  {
-    return onert_tflite::VerifyModelBuffer(verifier);
-  }
-};
-
-class TFLiteLoader final : public base_loader::BaseLoader<LoaderDomain>
-{
-protected:
-  // Different option name
-  //  Circle: adjoint_lhs, adjoint_rhs
-  //  TFLite: adj_x, adj_y
-  void loadBatchMatMul(const Operator *op, ir::Graph &subg);
-
-public:
-  using BaseLoader::BaseLoader;
-
-  bool allowOptionalInputTensor(BuiltinOperator op) override
-  {
-    switch (op)
-    {
-      case BuiltinOperator::BuiltinOperator_FULLY_CONNECTED:
-      case BuiltinOperator::BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM:
-        return true;
-      default:
-        return false;
-    }
-  }
-
-private:
-  std::unique_ptr<ir::Graph> loadSubgraph(const onert_tflite::SubGraph *tflite_subg) override
-  {
-    auto subg = std::make_unique<ir::Graph>();
-    // Load tensors
-    _tensor_to_operand.resize(tflite_subg->tensors()->size());
-    for (flatbuffers::uoffset_t i = 0; i < tflite_subg->tensors()->size(); ++i)
-    {
-      _tensor_to_operand[i] = loadOperand(tflite_subg->tensors()->Get(i), *subg);
-    }
-    // Set inputs
-    for (const std::int32_t input_ind : *tflite_subg->inputs())
-    {
-      subg->addInput(tensorIdxToOperandIdx(input_ind),
-                     _tensor_names.at(_tensor_to_operand[input_ind]));
-    }
-    // Set outputs
-    for (const std::int32_t output_ind : *tflite_subg->outputs())
-    {
-      subg->addOutput(tensorIdxToOperandIdx(output_ind),
-                      _tensor_names.at(_tensor_to_operand[output_ind]));
-    }
-    // Create operations
-    for (const auto *op : *tflite_subg->operators())
-    {
-      loadOperation(op, *subg);
-    }
-
-    subg->verify();
-
-    return subg;
-  }
-
-  void loadOperation(const onert_tflite::Operator *op, ir::Graph &subg)
-  {
-    auto const builtin_op = getBuiltinOperator(op);
-
-    switch (builtin_op)
-    {
-      case onert_tflite::BuiltinOperator::BuiltinOperator_BATCH_MATMUL:
-        loadBatchMatMul(op, subg);
-        return;
-      default:
-        BaseLoader::loadOperation(op, subg);
-        return;
-    }
-  }
-};
-
-void TFLiteLoader::loadBatchMatMul(const Operator *op, ir::Graph &subg)
-{
-  ir::OperandIndexSequence inputs;
-  ir::OperandIndexSequence outputs;
-
-  loadOperationIO(op, inputs, outputs);
-
-  ir::operation::BatchMatMul::Param param;
-  const auto *options = op->builtin_options_as_BatchMatMulOptions();
-
-  param.adj_x = options->adj_x();
-  param.adj_y = options->adj_y();
-
-  std::unique_ptr<ir::Operation> new_op(new ir::operation::BatchMatMul(inputs, outputs, param));
-  subg.addOperation(std::move(new_op));
-}
-
-} // namespace
-
-std::unique_ptr<ir::Model> loadModel(const std::string &filename)
-{
-  auto model = std::make_unique<ir::Model>();
-  TFLiteLoader loader(model);
-  loader.loadFromFile(filename);
-  return model;
-}
-
-} // namespace tflite_loader
-} // namespace onert
diff --git a/runtime/onert/frontend/tflite/src/tflite_schema_generated.h b/runtime/onert/frontend/tflite/src/tflite_schema_generated.h
deleted file mode 100644 (file)
index 7ad3c75..0000000
+++ /dev/null
@@ -1,11929 +0,0 @@
-/*
- * 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");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_TFLITESCHEMA_ONERT_TFLITE_H_
-#define FLATBUFFERS_GENERATED_TFLITESCHEMA_ONERT_TFLITE_H_
-
-#include "flatbuffers/flatbuffers.h"
-
-namespace onert_tflite
-{
-
-struct CustomQuantization;
-struct CustomQuantizationBuilder;
-
-struct QuantizationParameters;
-struct QuantizationParametersBuilder;
-
-struct Int32Vector;
-struct Int32VectorBuilder;
-
-struct Uint16Vector;
-struct Uint16VectorBuilder;
-
-struct Uint8Vector;
-struct Uint8VectorBuilder;
-
-struct DimensionMetadata;
-struct DimensionMetadataBuilder;
-
-struct SparsityParameters;
-struct SparsityParametersBuilder;
-
-struct Tensor;
-struct TensorBuilder;
-
-struct Conv2DOptions;
-struct Conv2DOptionsBuilder;
-
-struct Conv3DOptions;
-struct Conv3DOptionsBuilder;
-
-struct Pool2DOptions;
-struct Pool2DOptionsBuilder;
-
-struct DepthwiseConv2DOptions;
-struct DepthwiseConv2DOptionsBuilder;
-
-struct ConcatEmbeddingsOptions;
-struct ConcatEmbeddingsOptionsBuilder;
-
-struct LSHProjectionOptions;
-struct LSHProjectionOptionsBuilder;
-
-struct SVDFOptions;
-struct SVDFOptionsBuilder;
-
-struct RNNOptions;
-struct RNNOptionsBuilder;
-
-struct SequenceRNNOptions;
-struct SequenceRNNOptionsBuilder;
-
-struct BidirectionalSequenceRNNOptions;
-struct BidirectionalSequenceRNNOptionsBuilder;
-
-struct FullyConnectedOptions;
-struct FullyConnectedOptionsBuilder;
-
-struct SoftmaxOptions;
-struct SoftmaxOptionsBuilder;
-
-struct ConcatenationOptions;
-struct ConcatenationOptionsBuilder;
-
-struct AddOptions;
-struct AddOptionsBuilder;
-
-struct MulOptions;
-struct MulOptionsBuilder;
-
-struct L2NormOptions;
-struct L2NormOptionsBuilder;
-
-struct LocalResponseNormalizationOptions;
-struct LocalResponseNormalizationOptionsBuilder;
-
-struct LSTMOptions;
-struct LSTMOptionsBuilder;
-
-struct UnidirectionalSequenceLSTMOptions;
-struct UnidirectionalSequenceLSTMOptionsBuilder;
-
-struct BidirectionalSequenceLSTMOptions;
-struct BidirectionalSequenceLSTMOptionsBuilder;
-
-struct ResizeBilinearOptions;
-struct ResizeBilinearOptionsBuilder;
-
-struct ResizeNearestNeighborOptions;
-struct ResizeNearestNeighborOptionsBuilder;
-
-struct CallOptions;
-struct CallOptionsBuilder;
-
-struct PadOptions;
-struct PadOptionsBuilder;
-
-struct PadV2Options;
-struct PadV2OptionsBuilder;
-
-struct ReshapeOptions;
-struct ReshapeOptionsBuilder;
-
-struct SpaceToBatchNDOptions;
-struct SpaceToBatchNDOptionsBuilder;
-
-struct BatchToSpaceNDOptions;
-struct BatchToSpaceNDOptionsBuilder;
-
-struct SkipGramOptions;
-struct SkipGramOptionsBuilder;
-
-struct SpaceToDepthOptions;
-struct SpaceToDepthOptionsBuilder;
-
-struct DepthToSpaceOptions;
-struct DepthToSpaceOptionsBuilder;
-
-struct SubOptions;
-struct SubOptionsBuilder;
-
-struct DivOptions;
-struct DivOptionsBuilder;
-
-struct TopKV2Options;
-struct TopKV2OptionsBuilder;
-
-struct EmbeddingLookupSparseOptions;
-struct EmbeddingLookupSparseOptionsBuilder;
-
-struct GatherOptions;
-struct GatherOptionsBuilder;
-
-struct TransposeOptions;
-struct TransposeOptionsBuilder;
-
-struct ExpOptions;
-struct ExpOptionsBuilder;
-
-struct CosOptions;
-struct CosOptionsBuilder;
-
-struct ReducerOptions;
-struct ReducerOptionsBuilder;
-
-struct SqueezeOptions;
-struct SqueezeOptionsBuilder;
-
-struct SplitOptions;
-struct SplitOptionsBuilder;
-
-struct SplitVOptions;
-struct SplitVOptionsBuilder;
-
-struct StridedSliceOptions;
-struct StridedSliceOptionsBuilder;
-
-struct LogSoftmaxOptions;
-struct LogSoftmaxOptionsBuilder;
-
-struct CastOptions;
-struct CastOptionsBuilder;
-
-struct DequantizeOptions;
-struct DequantizeOptionsBuilder;
-
-struct MaximumMinimumOptions;
-struct MaximumMinimumOptionsBuilder;
-
-struct TileOptions;
-struct TileOptionsBuilder;
-
-struct ArgMaxOptions;
-struct ArgMaxOptionsBuilder;
-
-struct ArgMinOptions;
-struct ArgMinOptionsBuilder;
-
-struct GreaterOptions;
-struct GreaterOptionsBuilder;
-
-struct GreaterEqualOptions;
-struct GreaterEqualOptionsBuilder;
-
-struct LessOptions;
-struct LessOptionsBuilder;
-
-struct LessEqualOptions;
-struct LessEqualOptionsBuilder;
-
-struct NegOptions;
-struct NegOptionsBuilder;
-
-struct SelectOptions;
-struct SelectOptionsBuilder;
-
-struct SliceOptions;
-struct SliceOptionsBuilder;
-
-struct TransposeConvOptions;
-struct TransposeConvOptionsBuilder;
-
-struct ExpandDimsOptions;
-struct ExpandDimsOptionsBuilder;
-
-struct SparseToDenseOptions;
-struct SparseToDenseOptionsBuilder;
-
-struct EqualOptions;
-struct EqualOptionsBuilder;
-
-struct NotEqualOptions;
-struct NotEqualOptionsBuilder;
-
-struct ShapeOptions;
-struct ShapeOptionsBuilder;
-
-struct RankOptions;
-struct RankOptionsBuilder;
-
-struct PowOptions;
-struct PowOptionsBuilder;
-
-struct FakeQuantOptions;
-struct FakeQuantOptionsBuilder;
-
-struct PackOptions;
-struct PackOptionsBuilder;
-
-struct LogicalOrOptions;
-struct LogicalOrOptionsBuilder;
-
-struct OneHotOptions;
-struct OneHotOptionsBuilder;
-
-struct AbsOptions;
-struct AbsOptionsBuilder;
-
-struct HardSwishOptions;
-struct HardSwishOptionsBuilder;
-
-struct LogicalAndOptions;
-struct LogicalAndOptionsBuilder;
-
-struct LogicalNotOptions;
-struct LogicalNotOptionsBuilder;
-
-struct UnpackOptions;
-struct UnpackOptionsBuilder;
-
-struct FloorDivOptions;
-struct FloorDivOptionsBuilder;
-
-struct SquareOptions;
-struct SquareOptionsBuilder;
-
-struct ZerosLikeOptions;
-struct ZerosLikeOptionsBuilder;
-
-struct FillOptions;
-struct FillOptionsBuilder;
-
-struct FloorModOptions;
-struct FloorModOptionsBuilder;
-
-struct RangeOptions;
-struct RangeOptionsBuilder;
-
-struct LeakyReluOptions;
-struct LeakyReluOptionsBuilder;
-
-struct SquaredDifferenceOptions;
-struct SquaredDifferenceOptionsBuilder;
-
-struct MirrorPadOptions;
-struct MirrorPadOptionsBuilder;
-
-struct UniqueOptions;
-struct UniqueOptionsBuilder;
-
-struct ReverseV2Options;
-struct ReverseV2OptionsBuilder;
-
-struct AddNOptions;
-struct AddNOptionsBuilder;
-
-struct GatherNdOptions;
-struct GatherNdOptionsBuilder;
-
-struct WhereOptions;
-struct WhereOptionsBuilder;
-
-struct ReverseSequenceOptions;
-struct ReverseSequenceOptionsBuilder;
-
-struct MatrixDiagOptions;
-struct MatrixDiagOptionsBuilder;
-
-struct QuantizeOptions;
-struct QuantizeOptionsBuilder;
-
-struct MatrixSetDiagOptions;
-struct MatrixSetDiagOptionsBuilder;
-
-struct IfOptions;
-struct IfOptionsBuilder;
-
-struct CallOnceOptions;
-struct CallOnceOptionsBuilder;
-
-struct WhileOptions;
-struct WhileOptionsBuilder;
-
-struct NonMaxSuppressionV4Options;
-struct NonMaxSuppressionV4OptionsBuilder;
-
-struct NonMaxSuppressionV5Options;
-struct NonMaxSuppressionV5OptionsBuilder;
-
-struct ScatterNdOptions;
-struct ScatterNdOptionsBuilder;
-
-struct SelectV2Options;
-struct SelectV2OptionsBuilder;
-
-struct DensifyOptions;
-struct DensifyOptionsBuilder;
-
-struct SegmentSumOptions;
-struct SegmentSumOptionsBuilder;
-
-struct BatchMatMulOptions;
-struct BatchMatMulOptionsBuilder;
-
-struct CumsumOptions;
-struct CumsumOptionsBuilder;
-
-struct BroadcastToOptions;
-struct BroadcastToOptionsBuilder;
-
-struct Rfft2dOptions;
-struct Rfft2dOptionsBuilder;
-
-struct HashtableOptions;
-struct HashtableOptionsBuilder;
-
-struct HashtableFindOptions;
-struct HashtableFindOptionsBuilder;
-
-struct HashtableImportOptions;
-struct HashtableImportOptionsBuilder;
-
-struct HashtableSizeOptions;
-struct HashtableSizeOptionsBuilder;
-
-struct VarHandleOptions;
-struct VarHandleOptionsBuilder;
-
-struct ReadVariableOptions;
-struct ReadVariableOptionsBuilder;
-
-struct AssignVariableOptions;
-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;
-
-struct Operator;
-struct OperatorBuilder;
-
-struct SubGraph;
-struct SubGraphBuilder;
-
-struct Buffer;
-struct BufferBuilder;
-
-struct Metadata;
-struct MetadataBuilder;
-
-struct TensorMap;
-struct TensorMapBuilder;
-
-struct SignatureDef;
-struct SignatureDefBuilder;
-
-struct Model;
-struct ModelBuilder;
-
-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_UINT16 = 16,
-  TensorType_MIN = TensorType_FLOAT32,
-  TensorType_MAX = TensorType_UINT16
-};
-
-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_UINT16};
-  return values;
-}
-
-inline const char *const *EnumNamesTensorType()
-{
-  static const char *const names[18] = {"FLOAT32", "FLOAT16",    "INT32",  "UINT8",     "INT64",
-                                        "STRING",  "BOOL",       "INT16",  "COMPLEX64", "INT8",
-                                        "FLOAT64", "COMPLEX128", "UINT64", "RESOURCE",  "VARIANT",
-                                        "UINT32",  "UINT16",     nullptr};
-  return names;
-}
-
-inline const char *EnumNameTensorType(TensorType e)
-{
-  if (flatbuffers::IsOutRange(e, TensorType_FLOAT32, TensorType_UINT16))
-    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<onert_tflite::CustomQuantization>
-{
-  static const QuantizationDetails enum_value = QuantizationDetails_CustomQuantization;
-};
-
-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<onert_tflite::Int32Vector>
-{
-  static const SparseIndexVector enum_value = SparseIndexVector_Int32Vector;
-};
-
-template <> struct SparseIndexVectorTraits<onert_tflite::Uint16Vector>
-{
-  static const SparseIndexVector enum_value = SparseIndexVector_Uint16Vector;
-};
-
-template <> struct SparseIndexVectorTraits<onert_tflite::Uint8Vector>
-{
-  static const SparseIndexVector enum_value = SparseIndexVector_Uint8Vector;
-};
-
-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_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_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_ATAN2
-};
-
-inline const BuiltinOperator (&EnumValuesBuiltinOperator())[157]
-{
-  static const BuiltinOperator values[] = {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,
-                                           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[158] = {"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",
-                                         "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_ATAN2))
-    return "";
-  const size_t index = static_cast<size_t>(e);
-  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_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_ATan2Options
-};
-
-inline const BuiltinOptions (&EnumValuesBuiltinOptions())[122]
-{
-  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_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[123] = {"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",
-                                         "BucketizeOptions",
-                                         "GeluOptions",
-                                         "DynamicUpdateSliceOptions",
-                                         "UnsortedSegmentProdOptions",
-                                         "UnsortedSegmentMaxOptions",
-                                         "UnsortedSegmentSumOptions",
-                                         "ATan2Options",
-                                         nullptr};
-  return names;
-}
-
-inline const char *EnumNameBuiltinOptions(BuiltinOptions e)
-{
-  if (flatbuffers::IsOutRange(e, BuiltinOptions_NONE, BuiltinOptions_ATan2Options))
-    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<onert_tflite::Conv2DOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_Conv2DOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::DepthwiseConv2DOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_DepthwiseConv2DOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ConcatEmbeddingsOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ConcatEmbeddingsOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::LSHProjectionOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_LSHProjectionOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::Pool2DOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_Pool2DOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SVDFOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SVDFOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::RNNOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_RNNOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::FullyConnectedOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_FullyConnectedOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SoftmaxOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SoftmaxOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ConcatenationOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ConcatenationOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::AddOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_AddOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::L2NormOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_L2NormOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::LocalResponseNormalizationOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_LocalResponseNormalizationOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::LSTMOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_LSTMOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ResizeBilinearOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ResizeBilinearOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::CallOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_CallOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ReshapeOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ReshapeOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SkipGramOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SkipGramOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SpaceToDepthOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SpaceToDepthOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::EmbeddingLookupSparseOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_EmbeddingLookupSparseOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::MulOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_MulOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::PadOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_PadOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::GatherOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_GatherOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::BatchToSpaceNDOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_BatchToSpaceNDOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SpaceToBatchNDOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SpaceToBatchNDOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::TransposeOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_TransposeOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ReducerOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ReducerOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SubOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SubOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::DivOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_DivOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SqueezeOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SqueezeOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SequenceRNNOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SequenceRNNOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::StridedSliceOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_StridedSliceOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ExpOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ExpOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::TopKV2Options>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_TopKV2Options;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SplitOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SplitOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::LogSoftmaxOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_LogSoftmaxOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::CastOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_CastOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::DequantizeOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_DequantizeOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::MaximumMinimumOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_MaximumMinimumOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ArgMaxOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ArgMaxOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::LessOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_LessOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::NegOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_NegOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::PadV2Options>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_PadV2Options;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::GreaterOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_GreaterOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::GreaterEqualOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_GreaterEqualOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::LessEqualOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_LessEqualOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SelectOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SelectOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SliceOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SliceOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::TransposeConvOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_TransposeConvOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SparseToDenseOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SparseToDenseOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::TileOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_TileOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ExpandDimsOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ExpandDimsOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::EqualOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_EqualOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::NotEqualOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_NotEqualOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ShapeOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ShapeOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::PowOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_PowOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ArgMinOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ArgMinOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::FakeQuantOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_FakeQuantOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::PackOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_PackOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::LogicalOrOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_LogicalOrOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::OneHotOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_OneHotOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::LogicalAndOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_LogicalAndOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::LogicalNotOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_LogicalNotOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::UnpackOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_UnpackOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::FloorDivOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_FloorDivOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SquareOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SquareOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ZerosLikeOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ZerosLikeOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::FillOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_FillOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::BidirectionalSequenceLSTMOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceLSTMOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::BidirectionalSequenceRNNOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_BidirectionalSequenceRNNOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::UnidirectionalSequenceLSTMOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_UnidirectionalSequenceLSTMOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::FloorModOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_FloorModOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::RangeOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_RangeOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ResizeNearestNeighborOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ResizeNearestNeighborOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::LeakyReluOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_LeakyReluOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SquaredDifferenceOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SquaredDifferenceOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::MirrorPadOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_MirrorPadOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::AbsOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_AbsOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SplitVOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SplitVOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::UniqueOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_UniqueOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ReverseV2Options>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ReverseV2Options;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::AddNOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_AddNOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::GatherNdOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_GatherNdOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::CosOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_CosOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::WhereOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_WhereOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::RankOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_RankOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ReverseSequenceOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ReverseSequenceOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::MatrixDiagOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_MatrixDiagOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::QuantizeOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_QuantizeOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::MatrixSetDiagOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_MatrixSetDiagOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::HardSwishOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_HardSwishOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::IfOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_IfOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::WhileOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_WhileOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::DepthToSpaceOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_DepthToSpaceOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::NonMaxSuppressionV4Options>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV4Options;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::NonMaxSuppressionV5Options>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_NonMaxSuppressionV5Options;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ScatterNdOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ScatterNdOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SelectV2Options>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SelectV2Options;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::DensifyOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_DensifyOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::SegmentSumOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_SegmentSumOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::BatchMatMulOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_BatchMatMulOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::CumsumOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_CumsumOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::CallOnceOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_CallOnceOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::BroadcastToOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_BroadcastToOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::Rfft2dOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_Rfft2dOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::Conv3DOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_Conv3DOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::HashtableOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_HashtableOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::HashtableFindOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_HashtableFindOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::HashtableImportOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_HashtableImportOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::HashtableSizeOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_HashtableSizeOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::VarHandleOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_VarHandleOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::ReadVariableOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_ReadVariableOptions;
-};
-
-template <> struct BuiltinOptionsTraits<onert_tflite::AssignVariableOptions>
-{
-  static const BuiltinOptions enum_value = BuiltinOptions_AssignVariableOptions;
-};
-
-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,
-                                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_MIN = FullyConnectedOptionsWeightsFormat_DEFAULT,
-  FullyConnectedOptionsWeightsFormat_MAX = FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8
-};
-
-inline const FullyConnectedOptionsWeightsFormat (&EnumValuesFullyConnectedOptionsWeightsFormat())[2]
-{
-  static const FullyConnectedOptionsWeightsFormat values[] = {
-    FullyConnectedOptionsWeightsFormat_DEFAULT,
-    FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8};
-  return values;
-}
-
-inline const char *const *EnumNamesFullyConnectedOptionsWeightsFormat()
-{
-  static const char *const names[3] = {"DEFAULT", "SHUFFLED4x16INT8", nullptr};
-  return names;
-}
-
-inline const char *EnumNameFullyConnectedOptionsWeightsFormat(FullyConnectedOptionsWeightsFormat e)
-{
-  if (flatbuffers::IsOutRange(e, FullyConnectedOptionsWeightsFormat_DEFAULT,
-                              FullyConnectedOptionsWeightsFormat_SHUFFLED4x16INT8))
-    return "";
-  const size_t index = static_cast<size_t>(e);
-  return EnumNamesFullyConnectedOptionsWeightsFormat()[index];
-}
-
-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];
-}
-
-struct CustomQuantization FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateCustomQuantization(_fbb, custom__);
-}
-
-struct QuantizationParameters FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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);
-  }
-  onert_tflite::QuantizationDetails details_type() const
-  {
-    return static_cast<onert_tflite::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 onert_tflite::CustomQuantization *details_as_CustomQuantization() const
-  {
-    return details_type() == onert_tflite::QuantizationDetails_CustomQuantization
-             ? static_cast<const onert_tflite::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();
-  }
-};
-
-template <>
-inline const onert_tflite::CustomQuantization *
-QuantizationParameters::details_as<onert_tflite::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(onert_tflite::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,
-  onert_tflite::QuantizationDetails details_type = onert_tflite::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,
-  onert_tflite::QuantizationDetails details_type = onert_tflite::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 onert_tflite::CreateQuantizationParameters(_fbb, min__, max__, scale__, zero_point__,
-                                                    details_type, details, quantized_dimension);
-}
-
-struct Int32Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateInt32Vector(_fbb, values__);
-}
-
-struct Uint16Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateUint16Vector(_fbb, values__);
-}
-
-struct Uint8Vector FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateUint8Vector(_fbb, values__);
-}
-
-struct DimensionMetadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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
-  };
-  onert_tflite::DimensionType format() const
-  {
-    return static_cast<onert_tflite::DimensionType>(GetField<int8_t>(VT_FORMAT, 0));
-  }
-  int32_t dense_size() const { return GetField<int32_t>(VT_DENSE_SIZE, 0); }
-  onert_tflite::SparseIndexVector array_segments_type() const
-  {
-    return static_cast<onert_tflite::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 onert_tflite::Int32Vector *array_segments_as_Int32Vector() const
-  {
-    return array_segments_type() == onert_tflite::SparseIndexVector_Int32Vector
-             ? static_cast<const onert_tflite::Int32Vector *>(array_segments())
-             : nullptr;
-  }
-  const onert_tflite::Uint16Vector *array_segments_as_Uint16Vector() const
-  {
-    return array_segments_type() == onert_tflite::SparseIndexVector_Uint16Vector
-             ? static_cast<const onert_tflite::Uint16Vector *>(array_segments())
-             : nullptr;
-  }
-  const onert_tflite::Uint8Vector *array_segments_as_Uint8Vector() const
-  {
-    return array_segments_type() == onert_tflite::SparseIndexVector_Uint8Vector
-             ? static_cast<const onert_tflite::Uint8Vector *>(array_segments())
-             : nullptr;
-  }
-  onert_tflite::SparseIndexVector array_indices_type() const
-  {
-    return static_cast<onert_tflite::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 onert_tflite::Int32Vector *array_indices_as_Int32Vector() const
-  {
-    return array_indices_type() == onert_tflite::SparseIndexVector_Int32Vector
-             ? static_cast<const onert_tflite::Int32Vector *>(array_indices())
-             : nullptr;
-  }
-  const onert_tflite::Uint16Vector *array_indices_as_Uint16Vector() const
-  {
-    return array_indices_type() == onert_tflite::SparseIndexVector_Uint16Vector
-             ? static_cast<const onert_tflite::Uint16Vector *>(array_indices())
-             : nullptr;
-  }
-  const onert_tflite::Uint8Vector *array_indices_as_Uint8Vector() const
-  {
-    return array_indices_type() == onert_tflite::SparseIndexVector_Uint8Vector
-             ? static_cast<const onert_tflite::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();
-  }
-};
-
-template <>
-inline const onert_tflite::Int32Vector *
-DimensionMetadata::array_segments_as<onert_tflite::Int32Vector>() const
-{
-  return array_segments_as_Int32Vector();
-}
-
-template <>
-inline const onert_tflite::Uint16Vector *
-DimensionMetadata::array_segments_as<onert_tflite::Uint16Vector>() const
-{
-  return array_segments_as_Uint16Vector();
-}
-
-template <>
-inline const onert_tflite::Uint8Vector *
-DimensionMetadata::array_segments_as<onert_tflite::Uint8Vector>() const
-{
-  return array_segments_as_Uint8Vector();
-}
-
-template <>
-inline const onert_tflite::Int32Vector *
-DimensionMetadata::array_indices_as<onert_tflite::Int32Vector>() const
-{
-  return array_indices_as_Int32Vector();
-}
-
-template <>
-inline const onert_tflite::Uint16Vector *
-DimensionMetadata::array_indices_as<onert_tflite::Uint16Vector>() const
-{
-  return array_indices_as_Uint16Vector();
-}
-
-template <>
-inline const onert_tflite::Uint8Vector *
-DimensionMetadata::array_indices_as<onert_tflite::Uint8Vector>() const
-{
-  return array_indices_as_Uint8Vector();
-}
-
-struct DimensionMetadataBuilder
-{
-  typedef DimensionMetadata Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_format(onert_tflite::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(onert_tflite::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(onert_tflite::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,
-  onert_tflite::DimensionType format = onert_tflite::DimensionType_DENSE, int32_t dense_size = 0,
-  onert_tflite::SparseIndexVector array_segments_type = onert_tflite::SparseIndexVector_NONE,
-  flatbuffers::Offset<void> array_segments = 0,
-  onert_tflite::SparseIndexVector array_indices_type = onert_tflite::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();
-}
-
-struct SparsityParameters FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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<onert_tflite::DimensionMetadata>> *
-  dim_metadata() const
-  {
-    return GetPointer<
-      const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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();
-  }
-};
-
-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<onert_tflite::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<onert_tflite::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<onert_tflite::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<onert_tflite::DimensionMetadata>>(*dim_metadata)
-      : 0;
-  return onert_tflite::CreateSparsityParameters(_fbb, traversal_order__, block_map__,
-                                                dim_metadata__);
-}
-
-struct Tensor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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,
-    VT_HAS_RANK = 20
-  };
-  const flatbuffers::Vector<int32_t> *shape() const
-  {
-    return GetPointer<const flatbuffers::Vector<int32_t> *>(VT_SHAPE);
-  }
-  onert_tflite::TensorType type() const
-  {
-    return static_cast<onert_tflite::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 onert_tflite::QuantizationParameters *quantization() const
-  {
-    return GetPointer<const onert_tflite::QuantizationParameters *>(VT_QUANTIZATION);
-  }
-  bool is_variable() const { return GetField<uint8_t>(VT_IS_VARIABLE, 0) != 0; }
-  const onert_tflite::SparsityParameters *sparsity() const
-  {
-    return GetPointer<const onert_tflite::SparsityParameters *>(VT_SPARSITY);
-  }
-  const flatbuffers::Vector<int32_t> *shape_signature() const
-  {
-    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) &&
-           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()) &&
-           VerifyField<uint8_t>(verifier, VT_HAS_RANK) && verifier.EndTable();
-  }
-};
-
-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(onert_tflite::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<onert_tflite::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<onert_tflite::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);
-  }
-  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();
-  }
-  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,
-  onert_tflite::TensorType type = onert_tflite::TensorType_FLOAT32, uint32_t buffer = 0,
-  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, bool has_rank = false)
-{
-  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_has_rank(has_rank);
-  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,
-  onert_tflite::TensorType type = onert_tflite::TensorType_FLOAT32, uint32_t buffer = 0,
-  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, 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__, has_rank);
-}
-
-struct Conv2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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
-  };
-  onert_tflite::Padding padding() const
-  {
-    return static_cast<onert_tflite::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); }
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct Conv2DOptionsBuilder
-{
-  typedef Conv2DOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_padding(onert_tflite::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(onert_tflite::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,
-                    onert_tflite::Padding padding = onert_tflite::Padding_SAME,
-                    int32_t stride_w = 0, int32_t stride_h = 0,
-                    onert_tflite::ActivationFunctionType fused_activation_function =
-                      onert_tflite::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();
-}
-
-struct Conv3DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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
-  };
-  onert_tflite::Padding padding() const
-  {
-    return static_cast<onert_tflite::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); }
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct Conv3DOptionsBuilder
-{
-  typedef Conv3DOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_padding(onert_tflite::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(onert_tflite::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, onert_tflite::Padding padding = onert_tflite::Padding_SAME,
-  int32_t stride_d = 0, int32_t stride_w = 0, int32_t stride_h = 0,
-  onert_tflite::ActivationFunctionType fused_activation_function =
-    onert_tflite::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();
-}
-
-struct Pool2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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
-  };
-  onert_tflite::Padding padding() const
-  {
-    return static_cast<onert_tflite::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); }
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct Pool2DOptionsBuilder
-{
-  typedef Pool2DOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_padding(onert_tflite::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(onert_tflite::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, onert_tflite::Padding padding = onert_tflite::Padding_SAME,
-  int32_t stride_w = 0, int32_t stride_h = 0, int32_t filter_width = 0, int32_t filter_height = 0,
-  onert_tflite::ActivationFunctionType fused_activation_function =
-    onert_tflite::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();
-}
-
-struct DepthwiseConv2DOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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
-  };
-  onert_tflite::Padding padding() const
-  {
-    return static_cast<onert_tflite::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); }
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct DepthwiseConv2DOptionsBuilder
-{
-  typedef DepthwiseConv2DOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_padding(onert_tflite::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(onert_tflite::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, onert_tflite::Padding padding = onert_tflite::Padding_SAME,
-  int32_t stride_w = 0, int32_t stride_h = 0, int32_t depth_multiplier = 0,
-  onert_tflite::ActivationFunctionType fused_activation_function =
-    onert_tflite::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();
-}
-
-struct ConcatEmbeddingsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateConcatEmbeddingsOptions(_fbb, num_channels, num_columns_per_channel__,
-                                                     embedding_dim_per_channel__);
-}
-
-struct LSHProjectionOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LSHProjectionOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_TYPE = 4
-  };
-  onert_tflite::LSHProjectionType type() const
-  {
-    return static_cast<onert_tflite::LSHProjectionType>(GetField<int8_t>(VT_TYPE, 0));
-  }
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_TYPE) &&
-           verifier.EndTable();
-  }
-};
-
-struct LSHProjectionOptionsBuilder
-{
-  typedef LSHProjectionOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_type(onert_tflite::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,
-  onert_tflite::LSHProjectionType type = onert_tflite::LSHProjectionType_UNKNOWN)
-{
-  LSHProjectionOptionsBuilder builder_(_fbb);
-  builder_.add_type(type);
-  return builder_.Finish();
-}
-
-struct SVDFOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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); }
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-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(onert_tflite::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,
-                  onert_tflite::ActivationFunctionType fused_activation_function =
-                    onert_tflite::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();
-}
-
-struct RNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef RNNOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_FUSED_ACTIVATION_FUNCTION = 4,
-    VT_ASYMMETRIC_QUANTIZE_INPUTS = 6
-  };
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct RNNOptionsBuilder
-{
-  typedef RNNOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_fused_activation_function(onert_tflite::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,
-                 onert_tflite::ActivationFunctionType fused_activation_function =
-                   onert_tflite::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();
-}
-
-struct SequenceRNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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; }
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-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(onert_tflite::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,
-                         onert_tflite::ActivationFunctionType fused_activation_function =
-                           onert_tflite::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();
-}
-
-struct BidirectionalSequenceRNNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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; }
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-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(onert_tflite::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,
-  onert_tflite::ActivationFunctionType fused_activation_function =
-    onert_tflite::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();
-}
-
-struct FullyConnectedOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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
-  };
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::ActivationFunctionType>(
-      GetField<int8_t>(VT_FUSED_ACTIVATION_FUNCTION, 0));
-  }
-  onert_tflite::FullyConnectedOptionsWeightsFormat weights_format() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct FullyConnectedOptionsBuilder
-{
-  typedef FullyConnectedOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_fused_activation_function(onert_tflite::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(onert_tflite::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,
-                            onert_tflite::ActivationFunctionType fused_activation_function =
-                              onert_tflite::ActivationFunctionType_NONE,
-                            onert_tflite::FullyConnectedOptionsWeightsFormat weights_format =
-                              onert_tflite::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();
-}
-
-struct SoftmaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct ConcatenationOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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); }
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-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(onert_tflite::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,
-                           onert_tflite::ActivationFunctionType fused_activation_function =
-                             onert_tflite::ActivationFunctionType_NONE)
-{
-  ConcatenationOptionsBuilder builder_(_fbb);
-  builder_.add_axis(axis);
-  builder_.add_fused_activation_function(fused_activation_function);
-  return builder_.Finish();
-}
-
-struct AddOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef AddOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_FUSED_ACTIVATION_FUNCTION = 4,
-    VT_POT_SCALE_INT16 = 6
-  };
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct AddOptionsBuilder
-{
-  typedef AddOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_fused_activation_function(onert_tflite::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,
-                 onert_tflite::ActivationFunctionType fused_activation_function =
-                   onert_tflite::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();
-}
-
-struct MulOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef MulOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_FUSED_ACTIVATION_FUNCTION = 4
-  };
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct MulOptionsBuilder
-{
-  typedef MulOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_fused_activation_function(onert_tflite::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,
-                 onert_tflite::ActivationFunctionType fused_activation_function =
-                   onert_tflite::ActivationFunctionType_NONE)
-{
-  MulOptionsBuilder builder_(_fbb);
-  builder_.add_fused_activation_function(fused_activation_function);
-  return builder_.Finish();
-}
-
-struct L2NormOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef L2NormOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_FUSED_ACTIVATION_FUNCTION = 4
-  };
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct L2NormOptionsBuilder
-{
-  typedef L2NormOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_fused_activation_function(onert_tflite::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,
-                    onert_tflite::ActivationFunctionType fused_activation_function =
-                      onert_tflite::ActivationFunctionType_NONE)
-{
-  L2NormOptionsBuilder builder_(_fbb);
-  builder_.add_fused_activation_function(fused_activation_function);
-  return builder_.Finish();
-}
-
-struct LocalResponseNormalizationOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct LSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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
-  };
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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); }
-  onert_tflite::LSTMKernelType kernel_type() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct LSTMOptionsBuilder
-{
-  typedef LSTMOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_fused_activation_function(onert_tflite::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(onert_tflite::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,
-                  onert_tflite::ActivationFunctionType fused_activation_function =
-                    onert_tflite::ActivationFunctionType_NONE,
-                  float cell_clip = 0.0f, float proj_clip = 0.0f,
-                  onert_tflite::LSTMKernelType kernel_type = onert_tflite::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();
-}
-
-struct UnidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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
-  };
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct UnidirectionalSequenceLSTMOptionsBuilder
-{
-  typedef UnidirectionalSequenceLSTMOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_fused_activation_function(onert_tflite::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,
-  onert_tflite::ActivationFunctionType fused_activation_function =
-    onert_tflite::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();
-}
-
-struct BidirectionalSequenceLSTMOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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
-  };
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct BidirectionalSequenceLSTMOptionsBuilder
-{
-  typedef BidirectionalSequenceLSTMOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_fused_activation_function(onert_tflite::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,
-  onert_tflite::ActivationFunctionType fused_activation_function =
-    onert_tflite::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();
-}
-
-struct ResizeBilinearOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct ResizeNearestNeighborOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct CallOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct PadOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef PadOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct PadV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef PadV2OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ReshapeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateReshapeOptions(_fbb, new_shape__);
-}
-
-struct SpaceToBatchNDOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SpaceToBatchNDOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct BatchToSpaceNDOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef BatchToSpaceNDOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SkipGramOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SpaceToDepthOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct DepthToSpaceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SubOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SubOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_FUSED_ACTIVATION_FUNCTION = 4,
-    VT_POT_SCALE_INT16 = 6
-  };
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct SubOptionsBuilder
-{
-  typedef SubOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_fused_activation_function(onert_tflite::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,
-                 onert_tflite::ActivationFunctionType fused_activation_function =
-                   onert_tflite::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();
-}
-
-struct DivOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef DivOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_FUSED_ACTIVATION_FUNCTION = 4
-  };
-  onert_tflite::ActivationFunctionType fused_activation_function() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct DivOptionsBuilder
-{
-  typedef DivOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_fused_activation_function(onert_tflite::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,
-                 onert_tflite::ActivationFunctionType fused_activation_function =
-                   onert_tflite::ActivationFunctionType_NONE)
-{
-  DivOptionsBuilder builder_(_fbb);
-  builder_.add_fused_activation_function(fused_activation_function);
-  return builder_.Finish();
-}
-
-struct TopKV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef TopKV2OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct EmbeddingLookupSparseOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef EmbeddingLookupSparseOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_COMBINER = 4
-  };
-  onert_tflite::CombinerType combiner() const
-  {
-    return static_cast<onert_tflite::CombinerType>(GetField<int8_t>(VT_COMBINER, 0));
-  }
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_COMBINER) &&
-           verifier.EndTable();
-  }
-};
-
-struct EmbeddingLookupSparseOptionsBuilder
-{
-  typedef EmbeddingLookupSparseOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_combiner(onert_tflite::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,
-  onert_tflite::CombinerType combiner = onert_tflite::CombinerType_SUM)
-{
-  EmbeddingLookupSparseOptionsBuilder builder_(_fbb);
-  builder_.add_combiner(combiner);
-  return builder_.Finish();
-}
-
-struct GatherOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct TransposeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef TransposeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ExpOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ExpOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct CosOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef CosOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ReducerOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SqueezeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateSqueezeOptions(_fbb, squeeze_dims__);
-}
-
-struct SplitOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SplitVOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct StridedSliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct LogSoftmaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LogSoftmaxOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct CastOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef CastOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_IN_DATA_TYPE = 4,
-    VT_OUT_DATA_TYPE = 6
-  };
-  onert_tflite::TensorType in_data_type() const
-  {
-    return static_cast<onert_tflite::TensorType>(GetField<int8_t>(VT_IN_DATA_TYPE, 0));
-  }
-  onert_tflite::TensorType out_data_type() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct CastOptionsBuilder
-{
-  typedef CastOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_in_data_type(onert_tflite::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(onert_tflite::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,
-                  onert_tflite::TensorType in_data_type = onert_tflite::TensorType_FLOAT32,
-                  onert_tflite::TensorType out_data_type = onert_tflite::TensorType_FLOAT32)
-{
-  CastOptionsBuilder builder_(_fbb);
-  builder_.add_out_data_type(out_data_type);
-  builder_.add_in_data_type(in_data_type);
-  return builder_.Finish();
-}
-
-struct DequantizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef DequantizeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct MaximumMinimumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef MaximumMinimumOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct TileOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef TileOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ArgMaxOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ArgMaxOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_OUTPUT_TYPE = 4
-  };
-  onert_tflite::TensorType output_type() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct ArgMaxOptionsBuilder
-{
-  typedef ArgMaxOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_output_type(onert_tflite::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,
-                    onert_tflite::TensorType output_type = onert_tflite::TensorType_FLOAT32)
-{
-  ArgMaxOptionsBuilder builder_(_fbb);
-  builder_.add_output_type(output_type);
-  return builder_.Finish();
-}
-
-struct ArgMinOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ArgMinOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_OUTPUT_TYPE = 4
-  };
-  onert_tflite::TensorType output_type() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct ArgMinOptionsBuilder
-{
-  typedef ArgMinOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_output_type(onert_tflite::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,
-                    onert_tflite::TensorType output_type = onert_tflite::TensorType_FLOAT32)
-{
-  ArgMinOptionsBuilder builder_(_fbb);
-  builder_.add_output_type(output_type);
-  return builder_.Finish();
-}
-
-struct GreaterOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef GreaterOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct GreaterEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef GreaterEqualOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct LessOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LessOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct LessEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LessEqualOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct NegOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef NegOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SelectOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SelectOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SliceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SliceOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct TransposeConvOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef TransposeConvOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_PADDING = 4,
-    VT_STRIDE_W = 6,
-    VT_STRIDE_H = 8
-  };
-  onert_tflite::Padding padding() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct TransposeConvOptionsBuilder
-{
-  typedef TransposeConvOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_padding(onert_tflite::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,
-                           onert_tflite::Padding padding = onert_tflite::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();
-}
-
-struct ExpandDimsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ExpandDimsOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SparseToDenseOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct EqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef EqualOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct NotEqualOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef NotEqualOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ShapeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ShapeOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_OUT_TYPE = 4
-  };
-  onert_tflite::TensorType out_type() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct ShapeOptionsBuilder
-{
-  typedef ShapeOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_out_type(onert_tflite::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,
-                   onert_tflite::TensorType out_type = onert_tflite::TensorType_FLOAT32)
-{
-  ShapeOptionsBuilder builder_(_fbb);
-  builder_.add_out_type(out_type);
-  return builder_.Finish();
-}
-
-struct RankOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef RankOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct PowOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef PowOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct FakeQuantOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct PackOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct LogicalOrOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LogicalOrOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct OneHotOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct AbsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef AbsOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct HardSwishOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef HardSwishOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct LogicalAndOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LogicalAndOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct LogicalNotOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef LogicalNotOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct UnpackOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct FloorDivOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef FloorDivOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SquareOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SquareOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ZerosLikeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ZerosLikeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct FillOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef FillOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct FloorModOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef FloorModOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct RangeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef RangeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct LeakyReluOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct SquaredDifferenceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SquaredDifferenceOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct MirrorPadOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef MirrorPadOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_MODE = 4
-  };
-  onert_tflite::MirrorPadMode mode() const
-  {
-    return static_cast<onert_tflite::MirrorPadMode>(GetField<int8_t>(VT_MODE, 0));
-  }
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && VerifyField<int8_t>(verifier, VT_MODE) &&
-           verifier.EndTable();
-  }
-};
-
-struct MirrorPadOptionsBuilder
-{
-  typedef MirrorPadOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_mode(onert_tflite::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,
-                       onert_tflite::MirrorPadMode mode = onert_tflite::MirrorPadMode_REFLECT)
-{
-  MirrorPadOptionsBuilder builder_(_fbb);
-  builder_.add_mode(mode);
-  return builder_.Finish();
-}
-
-struct UniqueOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef UniqueOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_IDX_OUT_TYPE = 4
-  };
-  onert_tflite::TensorType idx_out_type() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-struct UniqueOptionsBuilder
-{
-  typedef UniqueOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_idx_out_type(onert_tflite::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,
-                    onert_tflite::TensorType idx_out_type = onert_tflite::TensorType_INT32)
-{
-  UniqueOptionsBuilder builder_(_fbb);
-  builder_.add_idx_out_type(idx_out_type);
-  return builder_.Finish();
-}
-
-struct ReverseV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ReverseV2OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct AddNOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef AddNOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct GatherNdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef GatherNdOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct WhereOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef WhereOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ReverseSequenceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct MatrixDiagOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef MatrixDiagOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct QuantizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef QuantizeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct MatrixSetDiagOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef MatrixSetDiagOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct IfOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct CallOnceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct WhileOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct NonMaxSuppressionV4Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef NonMaxSuppressionV4OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct NonMaxSuppressionV5Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef NonMaxSuppressionV5OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct ScatterNdOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ScatterNdOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SelectV2Options FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SelectV2OptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct DensifyOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef DensifyOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct SegmentSumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SegmentSumOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct BatchMatMulOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef BatchMatMulOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_ADJ_X = 4,
-    VT_ADJ_Y = 6,
-    VT_ASYMMETRIC_QUANTIZE_INPUTS = 8
-  };
-  bool adj_x() const { return GetField<uint8_t>(VT_ADJ_X, 0) != 0; }
-  bool adj_y() const { return GetField<uint8_t>(VT_ADJ_Y, 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_ADJ_X) &&
-           VerifyField<uint8_t>(verifier, VT_ADJ_Y) &&
-           VerifyField<uint8_t>(verifier, VT_ASYMMETRIC_QUANTIZE_INPUTS) && verifier.EndTable();
-  }
-};
-
-struct BatchMatMulOptionsBuilder
-{
-  typedef BatchMatMulOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_adj_x(bool adj_x)
-  {
-    fbb_.AddElement<uint8_t>(BatchMatMulOptions::VT_ADJ_X, static_cast<uint8_t>(adj_x), 0);
-  }
-  void add_adj_y(bool adj_y)
-  {
-    fbb_.AddElement<uint8_t>(BatchMatMulOptions::VT_ADJ_Y, static_cast<uint8_t>(adj_y), 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 adj_x = false,
-                         bool adj_y = false, bool asymmetric_quantize_inputs = false)
-{
-  BatchMatMulOptionsBuilder builder_(_fbb);
-  builder_.add_asymmetric_quantize_inputs(asymmetric_quantize_inputs);
-  builder_.add_adj_y(adj_y);
-  builder_.add_adj_x(adj_x);
-  return builder_.Finish();
-}
-
-struct CumsumOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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();
-}
-
-struct BroadcastToOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef BroadcastToOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct Rfft2dOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef Rfft2dOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct HashtableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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); }
-  onert_tflite::TensorType key_dtype() const
-  {
-    return static_cast<onert_tflite::TensorType>(GetField<int8_t>(VT_KEY_DTYPE, 0));
-  }
-  onert_tflite::TensorType value_dtype() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-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(onert_tflite::TensorType key_dtype)
-  {
-    fbb_.AddElement<int8_t>(HashtableOptions::VT_KEY_DTYPE, static_cast<int8_t>(key_dtype), 0);
-  }
-  void add_value_dtype(onert_tflite::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,
-                       onert_tflite::TensorType key_dtype = onert_tflite::TensorType_FLOAT32,
-                       onert_tflite::TensorType value_dtype = onert_tflite::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();
-}
-
-struct HashtableFindOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef HashtableFindOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct HashtableImportOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef HashtableImportOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct HashtableSizeOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef HashtableSizeOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct VarHandleOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateVarHandleOptions(_fbb, container__, shared_name__);
-}
-
-struct ReadVariableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef ReadVariableOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct AssignVariableOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef AssignVariableOptionsBuilder Builder;
-  bool Verify(flatbuffers::Verifier &verifier) const
-  {
-    return VerifyTableStart(verifier) && verifier.EndTable();
-  }
-};
-
-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();
-}
-
-struct RandomOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef RandomOptionsBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_SEED = 4,
-    VT_SEED2 = 6
-  };
-  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<int64_t>(verifier, VT_SEED) &&
-           VerifyField<int64_t>(verifier, VT_SEED2) && verifier.EndTable();
-  }
-};
-
-struct RandomOptionsBuilder
-{
-  typedef RandomOptions Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  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();
-  }
-  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,
-                                                              int64_t seed = 0, int64_t seed2 = 0)
-{
-  RandomOptionsBuilder builder_(_fbb);
-  builder_.add_seed2(seed2);
-  builder_.add_seed(seed);
-  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;
-  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); }
-  onert_tflite::BuiltinOperator builtin_code() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-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(onert_tflite::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,
-                   onert_tflite::BuiltinOperator builtin_code = onert_tflite::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,
-  onert_tflite::BuiltinOperator builtin_code = onert_tflite::BuiltinOperator_ADD)
-{
-  auto custom_code__ = custom_code ? _fbb.CreateString(custom_code) : 0;
-  return onert_tflite::CreateOperatorCode(_fbb, deprecated_builtin_code, custom_code__, version,
-                                          builtin_code);
-}
-
-struct Operator FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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);
-  }
-  onert_tflite::BuiltinOptions builtin_options_type() const
-  {
-    return static_cast<onert_tflite::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 onert_tflite::Conv2DOptions *builtin_options_as_Conv2DOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_Conv2DOptions
-             ? static_cast<const onert_tflite::Conv2DOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::DepthwiseConv2DOptions *builtin_options_as_DepthwiseConv2DOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_DepthwiseConv2DOptions
-             ? static_cast<const onert_tflite::DepthwiseConv2DOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ConcatEmbeddingsOptions *builtin_options_as_ConcatEmbeddingsOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ConcatEmbeddingsOptions
-             ? static_cast<const onert_tflite::ConcatEmbeddingsOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::LSHProjectionOptions *builtin_options_as_LSHProjectionOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_LSHProjectionOptions
-             ? static_cast<const onert_tflite::LSHProjectionOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::Pool2DOptions *builtin_options_as_Pool2DOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_Pool2DOptions
-             ? static_cast<const onert_tflite::Pool2DOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SVDFOptions *builtin_options_as_SVDFOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SVDFOptions
-             ? static_cast<const onert_tflite::SVDFOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::RNNOptions *builtin_options_as_RNNOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_RNNOptions
-             ? static_cast<const onert_tflite::RNNOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::FullyConnectedOptions *builtin_options_as_FullyConnectedOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_FullyConnectedOptions
-             ? static_cast<const onert_tflite::FullyConnectedOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SoftmaxOptions *builtin_options_as_SoftmaxOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SoftmaxOptions
-             ? static_cast<const onert_tflite::SoftmaxOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ConcatenationOptions *builtin_options_as_ConcatenationOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ConcatenationOptions
-             ? static_cast<const onert_tflite::ConcatenationOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::AddOptions *builtin_options_as_AddOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_AddOptions
-             ? static_cast<const onert_tflite::AddOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::L2NormOptions *builtin_options_as_L2NormOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_L2NormOptions
-             ? static_cast<const onert_tflite::L2NormOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::LocalResponseNormalizationOptions *
-  builtin_options_as_LocalResponseNormalizationOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_LocalResponseNormalizationOptions
-             ? static_cast<const onert_tflite::LocalResponseNormalizationOptions *>(
-                 builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::LSTMOptions *builtin_options_as_LSTMOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_LSTMOptions
-             ? static_cast<const onert_tflite::LSTMOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ResizeBilinearOptions *builtin_options_as_ResizeBilinearOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ResizeBilinearOptions
-             ? static_cast<const onert_tflite::ResizeBilinearOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::CallOptions *builtin_options_as_CallOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_CallOptions
-             ? static_cast<const onert_tflite::CallOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ReshapeOptions *builtin_options_as_ReshapeOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ReshapeOptions
-             ? static_cast<const onert_tflite::ReshapeOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SkipGramOptions *builtin_options_as_SkipGramOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SkipGramOptions
-             ? static_cast<const onert_tflite::SkipGramOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SpaceToDepthOptions *builtin_options_as_SpaceToDepthOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SpaceToDepthOptions
-             ? static_cast<const onert_tflite::SpaceToDepthOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::EmbeddingLookupSparseOptions *
-  builtin_options_as_EmbeddingLookupSparseOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_EmbeddingLookupSparseOptions
-             ? static_cast<const onert_tflite::EmbeddingLookupSparseOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::MulOptions *builtin_options_as_MulOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_MulOptions
-             ? static_cast<const onert_tflite::MulOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::PadOptions *builtin_options_as_PadOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_PadOptions
-             ? static_cast<const onert_tflite::PadOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::GatherOptions *builtin_options_as_GatherOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_GatherOptions
-             ? static_cast<const onert_tflite::GatherOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::BatchToSpaceNDOptions *builtin_options_as_BatchToSpaceNDOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_BatchToSpaceNDOptions
-             ? static_cast<const onert_tflite::BatchToSpaceNDOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SpaceToBatchNDOptions *builtin_options_as_SpaceToBatchNDOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SpaceToBatchNDOptions
-             ? static_cast<const onert_tflite::SpaceToBatchNDOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::TransposeOptions *builtin_options_as_TransposeOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_TransposeOptions
-             ? static_cast<const onert_tflite::TransposeOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ReducerOptions *builtin_options_as_ReducerOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ReducerOptions
-             ? static_cast<const onert_tflite::ReducerOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SubOptions *builtin_options_as_SubOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SubOptions
-             ? static_cast<const onert_tflite::SubOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::DivOptions *builtin_options_as_DivOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_DivOptions
-             ? static_cast<const onert_tflite::DivOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SqueezeOptions *builtin_options_as_SqueezeOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SqueezeOptions
-             ? static_cast<const onert_tflite::SqueezeOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SequenceRNNOptions *builtin_options_as_SequenceRNNOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SequenceRNNOptions
-             ? static_cast<const onert_tflite::SequenceRNNOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::StridedSliceOptions *builtin_options_as_StridedSliceOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_StridedSliceOptions
-             ? static_cast<const onert_tflite::StridedSliceOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ExpOptions *builtin_options_as_ExpOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ExpOptions
-             ? static_cast<const onert_tflite::ExpOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::TopKV2Options *builtin_options_as_TopKV2Options() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_TopKV2Options
-             ? static_cast<const onert_tflite::TopKV2Options *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SplitOptions *builtin_options_as_SplitOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SplitOptions
-             ? static_cast<const onert_tflite::SplitOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::LogSoftmaxOptions *builtin_options_as_LogSoftmaxOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_LogSoftmaxOptions
-             ? static_cast<const onert_tflite::LogSoftmaxOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::CastOptions *builtin_options_as_CastOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_CastOptions
-             ? static_cast<const onert_tflite::CastOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::DequantizeOptions *builtin_options_as_DequantizeOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_DequantizeOptions
-             ? static_cast<const onert_tflite::DequantizeOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::MaximumMinimumOptions *builtin_options_as_MaximumMinimumOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_MaximumMinimumOptions
-             ? static_cast<const onert_tflite::MaximumMinimumOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ArgMaxOptions *builtin_options_as_ArgMaxOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ArgMaxOptions
-             ? static_cast<const onert_tflite::ArgMaxOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::LessOptions *builtin_options_as_LessOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_LessOptions
-             ? static_cast<const onert_tflite::LessOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::NegOptions *builtin_options_as_NegOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_NegOptions
-             ? static_cast<const onert_tflite::NegOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::PadV2Options *builtin_options_as_PadV2Options() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_PadV2Options
-             ? static_cast<const onert_tflite::PadV2Options *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::GreaterOptions *builtin_options_as_GreaterOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_GreaterOptions
-             ? static_cast<const onert_tflite::GreaterOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::GreaterEqualOptions *builtin_options_as_GreaterEqualOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_GreaterEqualOptions
-             ? static_cast<const onert_tflite::GreaterEqualOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::LessEqualOptions *builtin_options_as_LessEqualOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_LessEqualOptions
-             ? static_cast<const onert_tflite::LessEqualOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SelectOptions *builtin_options_as_SelectOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SelectOptions
-             ? static_cast<const onert_tflite::SelectOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SliceOptions *builtin_options_as_SliceOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SliceOptions
-             ? static_cast<const onert_tflite::SliceOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::TransposeConvOptions *builtin_options_as_TransposeConvOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_TransposeConvOptions
-             ? static_cast<const onert_tflite::TransposeConvOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SparseToDenseOptions *builtin_options_as_SparseToDenseOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SparseToDenseOptions
-             ? static_cast<const onert_tflite::SparseToDenseOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::TileOptions *builtin_options_as_TileOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_TileOptions
-             ? static_cast<const onert_tflite::TileOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ExpandDimsOptions *builtin_options_as_ExpandDimsOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ExpandDimsOptions
-             ? static_cast<const onert_tflite::ExpandDimsOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::EqualOptions *builtin_options_as_EqualOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_EqualOptions
-             ? static_cast<const onert_tflite::EqualOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::NotEqualOptions *builtin_options_as_NotEqualOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_NotEqualOptions
-             ? static_cast<const onert_tflite::NotEqualOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ShapeOptions *builtin_options_as_ShapeOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ShapeOptions
-             ? static_cast<const onert_tflite::ShapeOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::PowOptions *builtin_options_as_PowOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_PowOptions
-             ? static_cast<const onert_tflite::PowOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ArgMinOptions *builtin_options_as_ArgMinOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ArgMinOptions
-             ? static_cast<const onert_tflite::ArgMinOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::FakeQuantOptions *builtin_options_as_FakeQuantOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_FakeQuantOptions
-             ? static_cast<const onert_tflite::FakeQuantOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::PackOptions *builtin_options_as_PackOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_PackOptions
-             ? static_cast<const onert_tflite::PackOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::LogicalOrOptions *builtin_options_as_LogicalOrOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_LogicalOrOptions
-             ? static_cast<const onert_tflite::LogicalOrOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::OneHotOptions *builtin_options_as_OneHotOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_OneHotOptions
-             ? static_cast<const onert_tflite::OneHotOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::LogicalAndOptions *builtin_options_as_LogicalAndOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_LogicalAndOptions
-             ? static_cast<const onert_tflite::LogicalAndOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::LogicalNotOptions *builtin_options_as_LogicalNotOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_LogicalNotOptions
-             ? static_cast<const onert_tflite::LogicalNotOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::UnpackOptions *builtin_options_as_UnpackOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_UnpackOptions
-             ? static_cast<const onert_tflite::UnpackOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::FloorDivOptions *builtin_options_as_FloorDivOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_FloorDivOptions
-             ? static_cast<const onert_tflite::FloorDivOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SquareOptions *builtin_options_as_SquareOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SquareOptions
-             ? static_cast<const onert_tflite::SquareOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ZerosLikeOptions *builtin_options_as_ZerosLikeOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ZerosLikeOptions
-             ? static_cast<const onert_tflite::ZerosLikeOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::FillOptions *builtin_options_as_FillOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_FillOptions
-             ? static_cast<const onert_tflite::FillOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::BidirectionalSequenceLSTMOptions *
-  builtin_options_as_BidirectionalSequenceLSTMOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_BidirectionalSequenceLSTMOptions
-             ? static_cast<const onert_tflite::BidirectionalSequenceLSTMOptions *>(
-                 builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::BidirectionalSequenceRNNOptions *
-  builtin_options_as_BidirectionalSequenceRNNOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_BidirectionalSequenceRNNOptions
-             ? static_cast<const onert_tflite::BidirectionalSequenceRNNOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::UnidirectionalSequenceLSTMOptions *
-  builtin_options_as_UnidirectionalSequenceLSTMOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_UnidirectionalSequenceLSTMOptions
-             ? static_cast<const onert_tflite::UnidirectionalSequenceLSTMOptions *>(
-                 builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::FloorModOptions *builtin_options_as_FloorModOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_FloorModOptions
-             ? static_cast<const onert_tflite::FloorModOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::RangeOptions *builtin_options_as_RangeOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_RangeOptions
-             ? static_cast<const onert_tflite::RangeOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ResizeNearestNeighborOptions *
-  builtin_options_as_ResizeNearestNeighborOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ResizeNearestNeighborOptions
-             ? static_cast<const onert_tflite::ResizeNearestNeighborOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::LeakyReluOptions *builtin_options_as_LeakyReluOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_LeakyReluOptions
-             ? static_cast<const onert_tflite::LeakyReluOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SquaredDifferenceOptions *builtin_options_as_SquaredDifferenceOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SquaredDifferenceOptions
-             ? static_cast<const onert_tflite::SquaredDifferenceOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::MirrorPadOptions *builtin_options_as_MirrorPadOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_MirrorPadOptions
-             ? static_cast<const onert_tflite::MirrorPadOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::AbsOptions *builtin_options_as_AbsOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_AbsOptions
-             ? static_cast<const onert_tflite::AbsOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SplitVOptions *builtin_options_as_SplitVOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SplitVOptions
-             ? static_cast<const onert_tflite::SplitVOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::UniqueOptions *builtin_options_as_UniqueOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_UniqueOptions
-             ? static_cast<const onert_tflite::UniqueOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ReverseV2Options *builtin_options_as_ReverseV2Options() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ReverseV2Options
-             ? static_cast<const onert_tflite::ReverseV2Options *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::AddNOptions *builtin_options_as_AddNOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_AddNOptions
-             ? static_cast<const onert_tflite::AddNOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::GatherNdOptions *builtin_options_as_GatherNdOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_GatherNdOptions
-             ? static_cast<const onert_tflite::GatherNdOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::CosOptions *builtin_options_as_CosOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_CosOptions
-             ? static_cast<const onert_tflite::CosOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::WhereOptions *builtin_options_as_WhereOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_WhereOptions
-             ? static_cast<const onert_tflite::WhereOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::RankOptions *builtin_options_as_RankOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_RankOptions
-             ? static_cast<const onert_tflite::RankOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ReverseSequenceOptions *builtin_options_as_ReverseSequenceOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ReverseSequenceOptions
-             ? static_cast<const onert_tflite::ReverseSequenceOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::MatrixDiagOptions *builtin_options_as_MatrixDiagOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_MatrixDiagOptions
-             ? static_cast<const onert_tflite::MatrixDiagOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::QuantizeOptions *builtin_options_as_QuantizeOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_QuantizeOptions
-             ? static_cast<const onert_tflite::QuantizeOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::MatrixSetDiagOptions *builtin_options_as_MatrixSetDiagOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_MatrixSetDiagOptions
-             ? static_cast<const onert_tflite::MatrixSetDiagOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::HardSwishOptions *builtin_options_as_HardSwishOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_HardSwishOptions
-             ? static_cast<const onert_tflite::HardSwishOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::IfOptions *builtin_options_as_IfOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_IfOptions
-             ? static_cast<const onert_tflite::IfOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::WhileOptions *builtin_options_as_WhileOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_WhileOptions
-             ? static_cast<const onert_tflite::WhileOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::DepthToSpaceOptions *builtin_options_as_DepthToSpaceOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_DepthToSpaceOptions
-             ? static_cast<const onert_tflite::DepthToSpaceOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::NonMaxSuppressionV4Options *
-  builtin_options_as_NonMaxSuppressionV4Options() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_NonMaxSuppressionV4Options
-             ? static_cast<const onert_tflite::NonMaxSuppressionV4Options *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::NonMaxSuppressionV5Options *
-  builtin_options_as_NonMaxSuppressionV5Options() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_NonMaxSuppressionV5Options
-             ? static_cast<const onert_tflite::NonMaxSuppressionV5Options *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ScatterNdOptions *builtin_options_as_ScatterNdOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ScatterNdOptions
-             ? static_cast<const onert_tflite::ScatterNdOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SelectV2Options *builtin_options_as_SelectV2Options() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SelectV2Options
-             ? static_cast<const onert_tflite::SelectV2Options *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::DensifyOptions *builtin_options_as_DensifyOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_DensifyOptions
-             ? static_cast<const onert_tflite::DensifyOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::SegmentSumOptions *builtin_options_as_SegmentSumOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_SegmentSumOptions
-             ? static_cast<const onert_tflite::SegmentSumOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::BatchMatMulOptions *builtin_options_as_BatchMatMulOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_BatchMatMulOptions
-             ? static_cast<const onert_tflite::BatchMatMulOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::CumsumOptions *builtin_options_as_CumsumOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_CumsumOptions
-             ? static_cast<const onert_tflite::CumsumOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::CallOnceOptions *builtin_options_as_CallOnceOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_CallOnceOptions
-             ? static_cast<const onert_tflite::CallOnceOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::BroadcastToOptions *builtin_options_as_BroadcastToOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_BroadcastToOptions
-             ? static_cast<const onert_tflite::BroadcastToOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::Rfft2dOptions *builtin_options_as_Rfft2dOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_Rfft2dOptions
-             ? static_cast<const onert_tflite::Rfft2dOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::Conv3DOptions *builtin_options_as_Conv3DOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_Conv3DOptions
-             ? static_cast<const onert_tflite::Conv3DOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::HashtableOptions *builtin_options_as_HashtableOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_HashtableOptions
-             ? static_cast<const onert_tflite::HashtableOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::HashtableFindOptions *builtin_options_as_HashtableFindOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_HashtableFindOptions
-             ? static_cast<const onert_tflite::HashtableFindOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::HashtableImportOptions *builtin_options_as_HashtableImportOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_HashtableImportOptions
-             ? static_cast<const onert_tflite::HashtableImportOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::HashtableSizeOptions *builtin_options_as_HashtableSizeOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_HashtableSizeOptions
-             ? static_cast<const onert_tflite::HashtableSizeOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::VarHandleOptions *builtin_options_as_VarHandleOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_VarHandleOptions
-             ? static_cast<const onert_tflite::VarHandleOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::ReadVariableOptions *builtin_options_as_ReadVariableOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_ReadVariableOptions
-             ? static_cast<const onert_tflite::ReadVariableOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::AssignVariableOptions *builtin_options_as_AssignVariableOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_AssignVariableOptions
-             ? static_cast<const onert_tflite::AssignVariableOptions *>(builtin_options())
-             : nullptr;
-  }
-  const onert_tflite::RandomOptions *builtin_options_as_RandomOptions() const
-  {
-    return builtin_options_type() == onert_tflite::BuiltinOptions_RandomOptions
-             ? 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);
-  }
-  onert_tflite::CustomOptionsFormat custom_options_format() const
-  {
-    return static_cast<onert_tflite::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();
-  }
-};
-
-template <>
-inline const onert_tflite::Conv2DOptions *
-Operator::builtin_options_as<onert_tflite::Conv2DOptions>() const
-{
-  return builtin_options_as_Conv2DOptions();
-}
-
-template <>
-inline const onert_tflite::DepthwiseConv2DOptions *
-Operator::builtin_options_as<onert_tflite::DepthwiseConv2DOptions>() const
-{
-  return builtin_options_as_DepthwiseConv2DOptions();
-}
-
-template <>
-inline const onert_tflite::ConcatEmbeddingsOptions *
-Operator::builtin_options_as<onert_tflite::ConcatEmbeddingsOptions>() const
-{
-  return builtin_options_as_ConcatEmbeddingsOptions();
-}
-
-template <>
-inline const onert_tflite::LSHProjectionOptions *
-Operator::builtin_options_as<onert_tflite::LSHProjectionOptions>() const
-{
-  return builtin_options_as_LSHProjectionOptions();
-}
-
-template <>
-inline const onert_tflite::Pool2DOptions *
-Operator::builtin_options_as<onert_tflite::Pool2DOptions>() const
-{
-  return builtin_options_as_Pool2DOptions();
-}
-
-template <>
-inline const onert_tflite::SVDFOptions *
-Operator::builtin_options_as<onert_tflite::SVDFOptions>() const
-{
-  return builtin_options_as_SVDFOptions();
-}
-
-template <>
-inline const onert_tflite::RNNOptions *
-Operator::builtin_options_as<onert_tflite::RNNOptions>() const
-{
-  return builtin_options_as_RNNOptions();
-}
-
-template <>
-inline const onert_tflite::FullyConnectedOptions *
-Operator::builtin_options_as<onert_tflite::FullyConnectedOptions>() const
-{
-  return builtin_options_as_FullyConnectedOptions();
-}
-
-template <>
-inline const onert_tflite::SoftmaxOptions *
-Operator::builtin_options_as<onert_tflite::SoftmaxOptions>() const
-{
-  return builtin_options_as_SoftmaxOptions();
-}
-
-template <>
-inline const onert_tflite::ConcatenationOptions *
-Operator::builtin_options_as<onert_tflite::ConcatenationOptions>() const
-{
-  return builtin_options_as_ConcatenationOptions();
-}
-
-template <>
-inline const onert_tflite::AddOptions *
-Operator::builtin_options_as<onert_tflite::AddOptions>() const
-{
-  return builtin_options_as_AddOptions();
-}
-
-template <>
-inline const onert_tflite::L2NormOptions *
-Operator::builtin_options_as<onert_tflite::L2NormOptions>() const
-{
-  return builtin_options_as_L2NormOptions();
-}
-
-template <>
-inline const onert_tflite::LocalResponseNormalizationOptions *
-Operator::builtin_options_as<onert_tflite::LocalResponseNormalizationOptions>() const
-{
-  return builtin_options_as_LocalResponseNormalizationOptions();
-}
-
-template <>
-inline const onert_tflite::LSTMOptions *
-Operator::builtin_options_as<onert_tflite::LSTMOptions>() const
-{
-  return builtin_options_as_LSTMOptions();
-}
-
-template <>
-inline const onert_tflite::ResizeBilinearOptions *
-Operator::builtin_options_as<onert_tflite::ResizeBilinearOptions>() const
-{
-  return builtin_options_as_ResizeBilinearOptions();
-}
-
-template <>
-inline const onert_tflite::CallOptions *
-Operator::builtin_options_as<onert_tflite::CallOptions>() const
-{
-  return builtin_options_as_CallOptions();
-}
-
-template <>
-inline const onert_tflite::ReshapeOptions *
-Operator::builtin_options_as<onert_tflite::ReshapeOptions>() const
-{
-  return builtin_options_as_ReshapeOptions();
-}
-
-template <>
-inline const onert_tflite::SkipGramOptions *
-Operator::builtin_options_as<onert_tflite::SkipGramOptions>() const
-{
-  return builtin_options_as_SkipGramOptions();
-}
-
-template <>
-inline const onert_tflite::SpaceToDepthOptions *
-Operator::builtin_options_as<onert_tflite::SpaceToDepthOptions>() const
-{
-  return builtin_options_as_SpaceToDepthOptions();
-}
-
-template <>
-inline const onert_tflite::EmbeddingLookupSparseOptions *
-Operator::builtin_options_as<onert_tflite::EmbeddingLookupSparseOptions>() const
-{
-  return builtin_options_as_EmbeddingLookupSparseOptions();
-}
-
-template <>
-inline const onert_tflite::MulOptions *
-Operator::builtin_options_as<onert_tflite::MulOptions>() const
-{
-  return builtin_options_as_MulOptions();
-}
-
-template <>
-inline const onert_tflite::PadOptions *
-Operator::builtin_options_as<onert_tflite::PadOptions>() const
-{
-  return builtin_options_as_PadOptions();
-}
-
-template <>
-inline const onert_tflite::GatherOptions *
-Operator::builtin_options_as<onert_tflite::GatherOptions>() const
-{
-  return builtin_options_as_GatherOptions();
-}
-
-template <>
-inline const onert_tflite::BatchToSpaceNDOptions *
-Operator::builtin_options_as<onert_tflite::BatchToSpaceNDOptions>() const
-{
-  return builtin_options_as_BatchToSpaceNDOptions();
-}
-
-template <>
-inline const onert_tflite::SpaceToBatchNDOptions *
-Operator::builtin_options_as<onert_tflite::SpaceToBatchNDOptions>() const
-{
-  return builtin_options_as_SpaceToBatchNDOptions();
-}
-
-template <>
-inline const onert_tflite::TransposeOptions *
-Operator::builtin_options_as<onert_tflite::TransposeOptions>() const
-{
-  return builtin_options_as_TransposeOptions();
-}
-
-template <>
-inline const onert_tflite::ReducerOptions *
-Operator::builtin_options_as<onert_tflite::ReducerOptions>() const
-{
-  return builtin_options_as_ReducerOptions();
-}
-
-template <>
-inline const onert_tflite::SubOptions *
-Operator::builtin_options_as<onert_tflite::SubOptions>() const
-{
-  return builtin_options_as_SubOptions();
-}
-
-template <>
-inline const onert_tflite::DivOptions *
-Operator::builtin_options_as<onert_tflite::DivOptions>() const
-{
-  return builtin_options_as_DivOptions();
-}
-
-template <>
-inline const onert_tflite::SqueezeOptions *
-Operator::builtin_options_as<onert_tflite::SqueezeOptions>() const
-{
-  return builtin_options_as_SqueezeOptions();
-}
-
-template <>
-inline const onert_tflite::SequenceRNNOptions *
-Operator::builtin_options_as<onert_tflite::SequenceRNNOptions>() const
-{
-  return builtin_options_as_SequenceRNNOptions();
-}
-
-template <>
-inline const onert_tflite::StridedSliceOptions *
-Operator::builtin_options_as<onert_tflite::StridedSliceOptions>() const
-{
-  return builtin_options_as_StridedSliceOptions();
-}
-
-template <>
-inline const onert_tflite::ExpOptions *
-Operator::builtin_options_as<onert_tflite::ExpOptions>() const
-{
-  return builtin_options_as_ExpOptions();
-}
-
-template <>
-inline const onert_tflite::TopKV2Options *
-Operator::builtin_options_as<onert_tflite::TopKV2Options>() const
-{
-  return builtin_options_as_TopKV2Options();
-}
-
-template <>
-inline const onert_tflite::SplitOptions *
-Operator::builtin_options_as<onert_tflite::SplitOptions>() const
-{
-  return builtin_options_as_SplitOptions();
-}
-
-template <>
-inline const onert_tflite::LogSoftmaxOptions *
-Operator::builtin_options_as<onert_tflite::LogSoftmaxOptions>() const
-{
-  return builtin_options_as_LogSoftmaxOptions();
-}
-
-template <>
-inline const onert_tflite::CastOptions *
-Operator::builtin_options_as<onert_tflite::CastOptions>() const
-{
-  return builtin_options_as_CastOptions();
-}
-
-template <>
-inline const onert_tflite::DequantizeOptions *
-Operator::builtin_options_as<onert_tflite::DequantizeOptions>() const
-{
-  return builtin_options_as_DequantizeOptions();
-}
-
-template <>
-inline const onert_tflite::MaximumMinimumOptions *
-Operator::builtin_options_as<onert_tflite::MaximumMinimumOptions>() const
-{
-  return builtin_options_as_MaximumMinimumOptions();
-}
-
-template <>
-inline const onert_tflite::ArgMaxOptions *
-Operator::builtin_options_as<onert_tflite::ArgMaxOptions>() const
-{
-  return builtin_options_as_ArgMaxOptions();
-}
-
-template <>
-inline const onert_tflite::LessOptions *
-Operator::builtin_options_as<onert_tflite::LessOptions>() const
-{
-  return builtin_options_as_LessOptions();
-}
-
-template <>
-inline const onert_tflite::NegOptions *
-Operator::builtin_options_as<onert_tflite::NegOptions>() const
-{
-  return builtin_options_as_NegOptions();
-}
-
-template <>
-inline const onert_tflite::PadV2Options *
-Operator::builtin_options_as<onert_tflite::PadV2Options>() const
-{
-  return builtin_options_as_PadV2Options();
-}
-
-template <>
-inline const onert_tflite::GreaterOptions *
-Operator::builtin_options_as<onert_tflite::GreaterOptions>() const
-{
-  return builtin_options_as_GreaterOptions();
-}
-
-template <>
-inline const onert_tflite::GreaterEqualOptions *
-Operator::builtin_options_as<onert_tflite::GreaterEqualOptions>() const
-{
-  return builtin_options_as_GreaterEqualOptions();
-}
-
-template <>
-inline const onert_tflite::LessEqualOptions *
-Operator::builtin_options_as<onert_tflite::LessEqualOptions>() const
-{
-  return builtin_options_as_LessEqualOptions();
-}
-
-template <>
-inline const onert_tflite::SelectOptions *
-Operator::builtin_options_as<onert_tflite::SelectOptions>() const
-{
-  return builtin_options_as_SelectOptions();
-}
-
-template <>
-inline const onert_tflite::SliceOptions *
-Operator::builtin_options_as<onert_tflite::SliceOptions>() const
-{
-  return builtin_options_as_SliceOptions();
-}
-
-template <>
-inline const onert_tflite::TransposeConvOptions *
-Operator::builtin_options_as<onert_tflite::TransposeConvOptions>() const
-{
-  return builtin_options_as_TransposeConvOptions();
-}
-
-template <>
-inline const onert_tflite::SparseToDenseOptions *
-Operator::builtin_options_as<onert_tflite::SparseToDenseOptions>() const
-{
-  return builtin_options_as_SparseToDenseOptions();
-}
-
-template <>
-inline const onert_tflite::TileOptions *
-Operator::builtin_options_as<onert_tflite::TileOptions>() const
-{
-  return builtin_options_as_TileOptions();
-}
-
-template <>
-inline const onert_tflite::ExpandDimsOptions *
-Operator::builtin_options_as<onert_tflite::ExpandDimsOptions>() const
-{
-  return builtin_options_as_ExpandDimsOptions();
-}
-
-template <>
-inline const onert_tflite::EqualOptions *
-Operator::builtin_options_as<onert_tflite::EqualOptions>() const
-{
-  return builtin_options_as_EqualOptions();
-}
-
-template <>
-inline const onert_tflite::NotEqualOptions *
-Operator::builtin_options_as<onert_tflite::NotEqualOptions>() const
-{
-  return builtin_options_as_NotEqualOptions();
-}
-
-template <>
-inline const onert_tflite::ShapeOptions *
-Operator::builtin_options_as<onert_tflite::ShapeOptions>() const
-{
-  return builtin_options_as_ShapeOptions();
-}
-
-template <>
-inline const onert_tflite::PowOptions *
-Operator::builtin_options_as<onert_tflite::PowOptions>() const
-{
-  return builtin_options_as_PowOptions();
-}
-
-template <>
-inline const onert_tflite::ArgMinOptions *
-Operator::builtin_options_as<onert_tflite::ArgMinOptions>() const
-{
-  return builtin_options_as_ArgMinOptions();
-}
-
-template <>
-inline const onert_tflite::FakeQuantOptions *
-Operator::builtin_options_as<onert_tflite::FakeQuantOptions>() const
-{
-  return builtin_options_as_FakeQuantOptions();
-}
-
-template <>
-inline const onert_tflite::PackOptions *
-Operator::builtin_options_as<onert_tflite::PackOptions>() const
-{
-  return builtin_options_as_PackOptions();
-}
-
-template <>
-inline const onert_tflite::LogicalOrOptions *
-Operator::builtin_options_as<onert_tflite::LogicalOrOptions>() const
-{
-  return builtin_options_as_LogicalOrOptions();
-}
-
-template <>
-inline const onert_tflite::OneHotOptions *
-Operator::builtin_options_as<onert_tflite::OneHotOptions>() const
-{
-  return builtin_options_as_OneHotOptions();
-}
-
-template <>
-inline const onert_tflite::LogicalAndOptions *
-Operator::builtin_options_as<onert_tflite::LogicalAndOptions>() const
-{
-  return builtin_options_as_LogicalAndOptions();
-}
-
-template <>
-inline const onert_tflite::LogicalNotOptions *
-Operator::builtin_options_as<onert_tflite::LogicalNotOptions>() const
-{
-  return builtin_options_as_LogicalNotOptions();
-}
-
-template <>
-inline const onert_tflite::UnpackOptions *
-Operator::builtin_options_as<onert_tflite::UnpackOptions>() const
-{
-  return builtin_options_as_UnpackOptions();
-}
-
-template <>
-inline const onert_tflite::FloorDivOptions *
-Operator::builtin_options_as<onert_tflite::FloorDivOptions>() const
-{
-  return builtin_options_as_FloorDivOptions();
-}
-
-template <>
-inline const onert_tflite::SquareOptions *
-Operator::builtin_options_as<onert_tflite::SquareOptions>() const
-{
-  return builtin_options_as_SquareOptions();
-}
-
-template <>
-inline const onert_tflite::ZerosLikeOptions *
-Operator::builtin_options_as<onert_tflite::ZerosLikeOptions>() const
-{
-  return builtin_options_as_ZerosLikeOptions();
-}
-
-template <>
-inline const onert_tflite::FillOptions *
-Operator::builtin_options_as<onert_tflite::FillOptions>() const
-{
-  return builtin_options_as_FillOptions();
-}
-
-template <>
-inline const onert_tflite::BidirectionalSequenceLSTMOptions *
-Operator::builtin_options_as<onert_tflite::BidirectionalSequenceLSTMOptions>() const
-{
-  return builtin_options_as_BidirectionalSequenceLSTMOptions();
-}
-
-template <>
-inline const onert_tflite::BidirectionalSequenceRNNOptions *
-Operator::builtin_options_as<onert_tflite::BidirectionalSequenceRNNOptions>() const
-{
-  return builtin_options_as_BidirectionalSequenceRNNOptions();
-}
-
-template <>
-inline const onert_tflite::UnidirectionalSequenceLSTMOptions *
-Operator::builtin_options_as<onert_tflite::UnidirectionalSequenceLSTMOptions>() const
-{
-  return builtin_options_as_UnidirectionalSequenceLSTMOptions();
-}
-
-template <>
-inline const onert_tflite::FloorModOptions *
-Operator::builtin_options_as<onert_tflite::FloorModOptions>() const
-{
-  return builtin_options_as_FloorModOptions();
-}
-
-template <>
-inline const onert_tflite::RangeOptions *
-Operator::builtin_options_as<onert_tflite::RangeOptions>() const
-{
-  return builtin_options_as_RangeOptions();
-}
-
-template <>
-inline const onert_tflite::ResizeNearestNeighborOptions *
-Operator::builtin_options_as<onert_tflite::ResizeNearestNeighborOptions>() const
-{
-  return builtin_options_as_ResizeNearestNeighborOptions();
-}
-
-template <>
-inline const onert_tflite::LeakyReluOptions *
-Operator::builtin_options_as<onert_tflite::LeakyReluOptions>() const
-{
-  return builtin_options_as_LeakyReluOptions();
-}
-
-template <>
-inline const onert_tflite::SquaredDifferenceOptions *
-Operator::builtin_options_as<onert_tflite::SquaredDifferenceOptions>() const
-{
-  return builtin_options_as_SquaredDifferenceOptions();
-}
-
-template <>
-inline const onert_tflite::MirrorPadOptions *
-Operator::builtin_options_as<onert_tflite::MirrorPadOptions>() const
-{
-  return builtin_options_as_MirrorPadOptions();
-}
-
-template <>
-inline const onert_tflite::AbsOptions *
-Operator::builtin_options_as<onert_tflite::AbsOptions>() const
-{
-  return builtin_options_as_AbsOptions();
-}
-
-template <>
-inline const onert_tflite::SplitVOptions *
-Operator::builtin_options_as<onert_tflite::SplitVOptions>() const
-{
-  return builtin_options_as_SplitVOptions();
-}
-
-template <>
-inline const onert_tflite::UniqueOptions *
-Operator::builtin_options_as<onert_tflite::UniqueOptions>() const
-{
-  return builtin_options_as_UniqueOptions();
-}
-
-template <>
-inline const onert_tflite::ReverseV2Options *
-Operator::builtin_options_as<onert_tflite::ReverseV2Options>() const
-{
-  return builtin_options_as_ReverseV2Options();
-}
-
-template <>
-inline const onert_tflite::AddNOptions *
-Operator::builtin_options_as<onert_tflite::AddNOptions>() const
-{
-  return builtin_options_as_AddNOptions();
-}
-
-template <>
-inline const onert_tflite::GatherNdOptions *
-Operator::builtin_options_as<onert_tflite::GatherNdOptions>() const
-{
-  return builtin_options_as_GatherNdOptions();
-}
-
-template <>
-inline const onert_tflite::CosOptions *
-Operator::builtin_options_as<onert_tflite::CosOptions>() const
-{
-  return builtin_options_as_CosOptions();
-}
-
-template <>
-inline const onert_tflite::WhereOptions *
-Operator::builtin_options_as<onert_tflite::WhereOptions>() const
-{
-  return builtin_options_as_WhereOptions();
-}
-
-template <>
-inline const onert_tflite::RankOptions *
-Operator::builtin_options_as<onert_tflite::RankOptions>() const
-{
-  return builtin_options_as_RankOptions();
-}
-
-template <>
-inline const onert_tflite::ReverseSequenceOptions *
-Operator::builtin_options_as<onert_tflite::ReverseSequenceOptions>() const
-{
-  return builtin_options_as_ReverseSequenceOptions();
-}
-
-template <>
-inline const onert_tflite::MatrixDiagOptions *
-Operator::builtin_options_as<onert_tflite::MatrixDiagOptions>() const
-{
-  return builtin_options_as_MatrixDiagOptions();
-}
-
-template <>
-inline const onert_tflite::QuantizeOptions *
-Operator::builtin_options_as<onert_tflite::QuantizeOptions>() const
-{
-  return builtin_options_as_QuantizeOptions();
-}
-
-template <>
-inline const onert_tflite::MatrixSetDiagOptions *
-Operator::builtin_options_as<onert_tflite::MatrixSetDiagOptions>() const
-{
-  return builtin_options_as_MatrixSetDiagOptions();
-}
-
-template <>
-inline const onert_tflite::HardSwishOptions *
-Operator::builtin_options_as<onert_tflite::HardSwishOptions>() const
-{
-  return builtin_options_as_HardSwishOptions();
-}
-
-template <>
-inline const onert_tflite::IfOptions *Operator::builtin_options_as<onert_tflite::IfOptions>() const
-{
-  return builtin_options_as_IfOptions();
-}
-
-template <>
-inline const onert_tflite::WhileOptions *
-Operator::builtin_options_as<onert_tflite::WhileOptions>() const
-{
-  return builtin_options_as_WhileOptions();
-}
-
-template <>
-inline const onert_tflite::DepthToSpaceOptions *
-Operator::builtin_options_as<onert_tflite::DepthToSpaceOptions>() const
-{
-  return builtin_options_as_DepthToSpaceOptions();
-}
-
-template <>
-inline const onert_tflite::NonMaxSuppressionV4Options *
-Operator::builtin_options_as<onert_tflite::NonMaxSuppressionV4Options>() const
-{
-  return builtin_options_as_NonMaxSuppressionV4Options();
-}
-
-template <>
-inline const onert_tflite::NonMaxSuppressionV5Options *
-Operator::builtin_options_as<onert_tflite::NonMaxSuppressionV5Options>() const
-{
-  return builtin_options_as_NonMaxSuppressionV5Options();
-}
-
-template <>
-inline const onert_tflite::ScatterNdOptions *
-Operator::builtin_options_as<onert_tflite::ScatterNdOptions>() const
-{
-  return builtin_options_as_ScatterNdOptions();
-}
-
-template <>
-inline const onert_tflite::SelectV2Options *
-Operator::builtin_options_as<onert_tflite::SelectV2Options>() const
-{
-  return builtin_options_as_SelectV2Options();
-}
-
-template <>
-inline const onert_tflite::DensifyOptions *
-Operator::builtin_options_as<onert_tflite::DensifyOptions>() const
-{
-  return builtin_options_as_DensifyOptions();
-}
-
-template <>
-inline const onert_tflite::SegmentSumOptions *
-Operator::builtin_options_as<onert_tflite::SegmentSumOptions>() const
-{
-  return builtin_options_as_SegmentSumOptions();
-}
-
-template <>
-inline const onert_tflite::BatchMatMulOptions *
-Operator::builtin_options_as<onert_tflite::BatchMatMulOptions>() const
-{
-  return builtin_options_as_BatchMatMulOptions();
-}
-
-template <>
-inline const onert_tflite::CumsumOptions *
-Operator::builtin_options_as<onert_tflite::CumsumOptions>() const
-{
-  return builtin_options_as_CumsumOptions();
-}
-
-template <>
-inline const onert_tflite::CallOnceOptions *
-Operator::builtin_options_as<onert_tflite::CallOnceOptions>() const
-{
-  return builtin_options_as_CallOnceOptions();
-}
-
-template <>
-inline const onert_tflite::BroadcastToOptions *
-Operator::builtin_options_as<onert_tflite::BroadcastToOptions>() const
-{
-  return builtin_options_as_BroadcastToOptions();
-}
-
-template <>
-inline const onert_tflite::Rfft2dOptions *
-Operator::builtin_options_as<onert_tflite::Rfft2dOptions>() const
-{
-  return builtin_options_as_Rfft2dOptions();
-}
-
-template <>
-inline const onert_tflite::Conv3DOptions *
-Operator::builtin_options_as<onert_tflite::Conv3DOptions>() const
-{
-  return builtin_options_as_Conv3DOptions();
-}
-
-template <>
-inline const onert_tflite::HashtableOptions *
-Operator::builtin_options_as<onert_tflite::HashtableOptions>() const
-{
-  return builtin_options_as_HashtableOptions();
-}
-
-template <>
-inline const onert_tflite::HashtableFindOptions *
-Operator::builtin_options_as<onert_tflite::HashtableFindOptions>() const
-{
-  return builtin_options_as_HashtableFindOptions();
-}
-
-template <>
-inline const onert_tflite::HashtableImportOptions *
-Operator::builtin_options_as<onert_tflite::HashtableImportOptions>() const
-{
-  return builtin_options_as_HashtableImportOptions();
-}
-
-template <>
-inline const onert_tflite::HashtableSizeOptions *
-Operator::builtin_options_as<onert_tflite::HashtableSizeOptions>() const
-{
-  return builtin_options_as_HashtableSizeOptions();
-}
-
-template <>
-inline const onert_tflite::VarHandleOptions *
-Operator::builtin_options_as<onert_tflite::VarHandleOptions>() const
-{
-  return builtin_options_as_VarHandleOptions();
-}
-
-template <>
-inline const onert_tflite::ReadVariableOptions *
-Operator::builtin_options_as<onert_tflite::ReadVariableOptions>() const
-{
-  return builtin_options_as_ReadVariableOptions();
-}
-
-template <>
-inline const onert_tflite::AssignVariableOptions *
-Operator::builtin_options_as<onert_tflite::AssignVariableOptions>() const
-{
-  return builtin_options_as_AssignVariableOptions();
-}
-
-template <>
-inline const onert_tflite::RandomOptions *
-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;
-  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(onert_tflite::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(onert_tflite::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,
-  onert_tflite::BuiltinOptions builtin_options_type = onert_tflite::BuiltinOptions_NONE,
-  flatbuffers::Offset<void> builtin_options = 0,
-  flatbuffers::Offset<flatbuffers::Vector<uint8_t>> custom_options = 0,
-  onert_tflite::CustomOptionsFormat custom_options_format =
-    onert_tflite::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,
-  onert_tflite::BuiltinOptions builtin_options_type = onert_tflite::BuiltinOptions_NONE,
-  flatbuffers::Offset<void> builtin_options = 0,
-  const std::vector<uint8_t> *custom_options = nullptr,
-  onert_tflite::CustomOptionsFormat custom_options_format =
-    onert_tflite::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 onert_tflite::CreateOperator(_fbb, opcode_index, inputs__, outputs__, builtin_options_type,
-                                      builtin_options, custom_options__, custom_options_format,
-                                      mutating_variable_inputs__, intermediates__);
-}
-
-struct SubGraph FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  typedef SubGraphBuilder Builder;
-  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE
-  {
-    VT_TENSORS = 4,
-    VT_INPUTS = 6,
-    VT_OUTPUTS = 8,
-    VT_OPERATORS = 10,
-    VT_NAME = 12
-  };
-  const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::Tensor>> *tensors() const
-  {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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<onert_tflite::Operator>> *operators() const
-  {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::Operator>> *>(
-      VT_OPERATORS);
-  }
-  const flatbuffers::String *name() const
-  {
-    return GetPointer<const flatbuffers::String *>(VT_NAME);
-  }
-  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()) && verifier.EndTable();
-  }
-};
-
-struct SubGraphBuilder
-{
-  typedef SubGraph Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_tensors(
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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<onert_tflite::Operator>>> operators)
-  {
-    fbb_.AddOffset(SubGraph::VT_OPERATORS, operators);
-  }
-  void add_name(flatbuffers::Offset<flatbuffers::String> name)
-  {
-    fbb_.AddOffset(SubGraph::VT_NAME, name);
-  }
-  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<onert_tflite::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<onert_tflite::Operator>>> operators =
-    0,
-  flatbuffers::Offset<flatbuffers::String> name = 0)
-{
-  SubGraphBuilder builder_(_fbb);
-  builder_.add_name(name);
-  builder_.add_operators(operators);
-  builder_.add_outputs(outputs);
-  builder_.add_inputs(inputs);
-  builder_.add_tensors(tensors);
-  return builder_.Finish();
-}
-
-inline flatbuffers::Offset<SubGraph> CreateSubGraphDirect(
-  flatbuffers::FlatBufferBuilder &_fbb,
-  const std::vector<flatbuffers::Offset<onert_tflite::Tensor>> *tensors = nullptr,
-  const std::vector<int32_t> *inputs = nullptr, const std::vector<int32_t> *outputs = nullptr,
-  const std::vector<flatbuffers::Offset<onert_tflite::Operator>> *operators = nullptr,
-  const char *name = nullptr)
-{
-  auto tensors__ =
-    tensors ? _fbb.CreateVector<flatbuffers::Offset<onert_tflite::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<onert_tflite::Operator>>(*operators) : 0;
-  auto name__ = name ? _fbb.CreateString(name) : 0;
-  return onert_tflite::CreateSubGraph(_fbb, tensors__, inputs__, outputs__, operators__, name__);
-}
-
-struct Buffer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateBuffer(_fbb, data__);
-}
-
-struct Metadata FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateMetadata(_fbb, name__, buffer);
-}
-
-struct TensorMap FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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();
-  }
-};
-
-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 onert_tflite::CreateTensorMap(_fbb, name__, tensor_index);
-}
-
-struct SignatureDef FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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<onert_tflite::TensorMap>> *inputs() const
-  {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::TensorMap>> *>(
-      VT_INPUTS);
-  }
-  const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::TensorMap>> *outputs() const
-  {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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();
-  }
-};
-
-struct SignatureDefBuilder
-{
-  typedef SignatureDef Table;
-  flatbuffers::FlatBufferBuilder &fbb_;
-  flatbuffers::uoffset_t start_;
-  void add_inputs(
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onert_tflite::TensorMap>>> inputs)
-  {
-    fbb_.AddOffset(SignatureDef::VT_INPUTS, inputs);
-  }
-  void add_outputs(
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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<onert_tflite::TensorMap>>> inputs = 0,
-  flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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<onert_tflite::TensorMap>> *inputs = nullptr,
-  const std::vector<flatbuffers::Offset<onert_tflite::TensorMap>> *outputs = nullptr,
-  const char *signature_key = nullptr, uint32_t subgraph_index = 0)
-{
-  auto inputs__ =
-    inputs ? _fbb.CreateVector<flatbuffers::Offset<onert_tflite::TensorMap>>(*inputs) : 0;
-  auto outputs__ =
-    outputs ? _fbb.CreateVector<flatbuffers::Offset<onert_tflite::TensorMap>>(*outputs) : 0;
-  auto signature_key__ = signature_key ? _fbb.CreateString(signature_key) : 0;
-  return onert_tflite::CreateSignatureDef(_fbb, inputs__, outputs__, signature_key__,
-                                          subgraph_index);
-}
-
-struct Model FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
-{
-  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<onert_tflite::OperatorCode>> *operator_codes() const
-  {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::OperatorCode>> *>(
-      VT_OPERATOR_CODES);
-  }
-  const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::SubGraph>> *subgraphs() const
-  {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::SubGraph>> *>(
-      VT_SUBGRAPHS);
-  }
-  const flatbuffers::String *description() const
-  {
-    return GetPointer<const flatbuffers::String *>(VT_DESCRIPTION);
-  }
-  const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::Buffer>> *buffers() const
-  {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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<onert_tflite::Metadata>> *metadata() const
-  {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::Metadata>> *>(
-      VT_METADATA);
-  }
-  const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::SignatureDef>> *signature_defs() const
-  {
-    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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();
-  }
-};
-
-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<onert_tflite::OperatorCode>>>
-      operator_codes)
-  {
-    fbb_.AddOffset(Model::VT_OPERATOR_CODES, operator_codes);
-  }
-  void add_subgraphs(
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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<onert_tflite::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<onert_tflite::Metadata>>> metadata)
-  {
-    fbb_.AddOffset(Model::VT_METADATA, metadata);
-  }
-  void add_signature_defs(
-    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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<onert_tflite::OperatorCode>>>
-    operator_codes = 0,
-  flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onert_tflite::SubGraph>>> subgraphs =
-    0,
-  flatbuffers::Offset<flatbuffers::String> description = 0,
-  flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onert_tflite::Buffer>>> buffers = 0,
-  flatbuffers::Offset<flatbuffers::Vector<int32_t>> metadata_buffer = 0,
-  flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onert_tflite::Metadata>>> metadata =
-    0,
-  flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<onert_tflite::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<onert_tflite::OperatorCode>> *operator_codes = nullptr,
-  const std::vector<flatbuffers::Offset<onert_tflite::SubGraph>> *subgraphs = nullptr,
-  const char *description = nullptr,
-  const std::vector<flatbuffers::Offset<onert_tflite::Buffer>> *buffers = nullptr,
-  const std::vector<int32_t> *metadata_buffer = nullptr,
-  const std::vector<flatbuffers::Offset<onert_tflite::Metadata>> *metadata = nullptr,
-  const std::vector<flatbuffers::Offset<onert_tflite::SignatureDef>> *signature_defs = nullptr)
-{
-  auto operator_codes__ =
-    operator_codes
-      ? _fbb.CreateVector<flatbuffers::Offset<onert_tflite::OperatorCode>>(*operator_codes)
-      : 0;
-  auto subgraphs__ =
-    subgraphs ? _fbb.CreateVector<flatbuffers::Offset<onert_tflite::SubGraph>>(*subgraphs) : 0;
-  auto description__ = description ? _fbb.CreateString(description) : 0;
-  auto buffers__ =
-    buffers ? _fbb.CreateVector<flatbuffers::Offset<onert_tflite::Buffer>>(*buffers) : 0;
-  auto metadata_buffer__ = metadata_buffer ? _fbb.CreateVector<int32_t>(*metadata_buffer) : 0;
-  auto metadata__ =
-    metadata ? _fbb.CreateVector<flatbuffers::Offset<onert_tflite::Metadata>>(*metadata) : 0;
-  auto signature_defs__ =
-    signature_defs
-      ? _fbb.CreateVector<flatbuffers::Offset<onert_tflite::SignatureDef>>(*signature_defs)
-      : 0;
-  return onert_tflite::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 onert_tflite::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 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 onert_tflite::Int32Vector *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case SparseIndexVector_Uint16Vector:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::Uint16Vector *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case SparseIndexVector_Uint8Vector:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::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 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 onert_tflite::Conv2DOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_DepthwiseConv2DOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::DepthwiseConv2DOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ConcatEmbeddingsOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ConcatEmbeddingsOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_LSHProjectionOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::LSHProjectionOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_Pool2DOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::Pool2DOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SVDFOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SVDFOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_RNNOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::RNNOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_FullyConnectedOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::FullyConnectedOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SoftmaxOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SoftmaxOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ConcatenationOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ConcatenationOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_AddOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::AddOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_L2NormOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::L2NormOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_LocalResponseNormalizationOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::LocalResponseNormalizationOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_LSTMOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::LSTMOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ResizeBilinearOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ResizeBilinearOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_CallOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::CallOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ReshapeOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ReshapeOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SkipGramOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SkipGramOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SpaceToDepthOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SpaceToDepthOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_EmbeddingLookupSparseOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::EmbeddingLookupSparseOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_MulOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::MulOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_PadOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::PadOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_GatherOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::GatherOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_BatchToSpaceNDOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::BatchToSpaceNDOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SpaceToBatchNDOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SpaceToBatchNDOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_TransposeOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::TransposeOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ReducerOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ReducerOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SubOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SubOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_DivOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::DivOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SqueezeOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SqueezeOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SequenceRNNOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SequenceRNNOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_StridedSliceOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::StridedSliceOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ExpOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ExpOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_TopKV2Options:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::TopKV2Options *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SplitOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SplitOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_LogSoftmaxOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::LogSoftmaxOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_CastOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::CastOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_DequantizeOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::DequantizeOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_MaximumMinimumOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::MaximumMinimumOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ArgMaxOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ArgMaxOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_LessOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::LessOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_NegOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::NegOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_PadV2Options:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::PadV2Options *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_GreaterOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::GreaterOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_GreaterEqualOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::GreaterEqualOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_LessEqualOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::LessEqualOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SelectOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SelectOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SliceOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SliceOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_TransposeConvOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::TransposeConvOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SparseToDenseOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SparseToDenseOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_TileOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::TileOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ExpandDimsOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ExpandDimsOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_EqualOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::EqualOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_NotEqualOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::NotEqualOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ShapeOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ShapeOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_PowOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::PowOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ArgMinOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ArgMinOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_FakeQuantOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::FakeQuantOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_PackOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::PackOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_LogicalOrOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::LogicalOrOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_OneHotOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::OneHotOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_LogicalAndOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::LogicalAndOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_LogicalNotOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::LogicalNotOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_UnpackOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::UnpackOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_FloorDivOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::FloorDivOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SquareOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SquareOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ZerosLikeOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ZerosLikeOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_FillOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::FillOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_BidirectionalSequenceLSTMOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::BidirectionalSequenceLSTMOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_BidirectionalSequenceRNNOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::BidirectionalSequenceRNNOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_UnidirectionalSequenceLSTMOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::UnidirectionalSequenceLSTMOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_FloorModOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::FloorModOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_RangeOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::RangeOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ResizeNearestNeighborOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ResizeNearestNeighborOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_LeakyReluOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::LeakyReluOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SquaredDifferenceOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SquaredDifferenceOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_MirrorPadOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::MirrorPadOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_AbsOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::AbsOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SplitVOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SplitVOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_UniqueOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::UniqueOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ReverseV2Options:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ReverseV2Options *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_AddNOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::AddNOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_GatherNdOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::GatherNdOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_CosOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::CosOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_WhereOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::WhereOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_RankOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::RankOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ReverseSequenceOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ReverseSequenceOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_MatrixDiagOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::MatrixDiagOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_QuantizeOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::QuantizeOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_MatrixSetDiagOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::MatrixSetDiagOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_HardSwishOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::HardSwishOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_IfOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::IfOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_WhileOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::WhileOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_DepthToSpaceOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::DepthToSpaceOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_NonMaxSuppressionV4Options:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::NonMaxSuppressionV4Options *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_NonMaxSuppressionV5Options:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::NonMaxSuppressionV5Options *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ScatterNdOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ScatterNdOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SelectV2Options:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SelectV2Options *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_DensifyOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::DensifyOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_SegmentSumOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::SegmentSumOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_BatchMatMulOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::BatchMatMulOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_CumsumOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::CumsumOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_CallOnceOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::CallOnceOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_BroadcastToOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::BroadcastToOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_Rfft2dOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::Rfft2dOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_Conv3DOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::Conv3DOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_HashtableOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::HashtableOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_HashtableFindOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::HashtableFindOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_HashtableImportOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::HashtableImportOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_HashtableSizeOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::HashtableSizeOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_VarHandleOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::VarHandleOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_ReadVariableOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::ReadVariableOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_AssignVariableOptions:
-    {
-      auto ptr = reinterpret_cast<const onert_tflite::AssignVariableOptions *>(obj);
-      return verifier.VerifyTable(ptr);
-    }
-    case BuiltinOptions_RandomOptions:
-    {
-      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;
-  }
-}
-
-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 const onert_tflite::Model *GetModel(const void *buf)
-{
-  return flatbuffers::GetRoot<onert_tflite::Model>(buf);
-}
-
-inline const onert_tflite::Model *GetSizePrefixedModel(const void *buf)
-{
-  return flatbuffers::GetSizePrefixedRoot<onert_tflite::Model>(buf);
-}
-
-inline const char *ModelIdentifier() { return "TFL3"; }
-
-inline bool ModelBufferHasIdentifier(const void *buf)
-{
-  return flatbuffers::BufferHasIdentifier(buf, ModelIdentifier());
-}
-
-inline bool VerifyModelBuffer(flatbuffers::Verifier &verifier)
-{
-  return verifier.VerifyBuffer<onert_tflite::Model>(ModelIdentifier());
-}
-
-inline bool VerifySizePrefixedModelBuffer(flatbuffers::Verifier &verifier)
-{
-  return verifier.VerifySizePrefixedBuffer<onert_tflite::Model>(ModelIdentifier());
-}
-
-inline const char *ModelExtension() { return "tflite"; }
-
-inline void FinishModelBuffer(flatbuffers::FlatBufferBuilder &fbb,
-                              flatbuffers::Offset<onert_tflite::Model> root)
-{
-  fbb.Finish(root, ModelIdentifier());
-}
-
-inline void FinishSizePrefixedModelBuffer(flatbuffers::FlatBufferBuilder &fbb,
-                                          flatbuffers::Offset<onert_tflite::Model> root)
-{
-  fbb.FinishSizePrefixed(root, ModelIdentifier());
-}
-
-} // namespace onert_tflite
-
-#endif // FLATBUFFERS_GENERATED_TFLITESCHEMA_ONERT_TFLITE_H_
diff --git a/runtime/onert/frontend/tflite/tflite_schema-1.13.1.fbs b/runtime/onert/frontend/tflite/tflite_schema-1.13.1.fbs
deleted file mode 100644 (file)
index ae6b523..0000000
+++ /dev/null
@@ -1,795 +0,0 @@
-// 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.
-
-// Change namespace to onert_tflite
-namespace onert_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,
-}
-
-// 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 quantization parameters above are ignored and the
-  // value of the QuantizationDetails union below should be used.
-  details:QuantizationDetails;
-}
-
-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;
-}
-
-// 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 {
-  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,
-  // TODO(aselle): Consider rename to CONCATENATE_EMBEDDINGS
-  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,
-}
-
-// 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,
-}
-
-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;
-}
-
-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: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;
-}
-
-// An implementation of TensorFlow RNNCell.
-table RNNOptions {
-  fused_activation_function:ActivationFunctionType;
-}
-
-// An implementation of TensorFlow dynamic_rnn with RNNCell.
-table SequenceRNNOptions {
-  time_major:bool;
-  fused_activation_function:ActivationFunctionType;
-}
-
-// An implementation of TensorFlow bidrectional_dynamic_rnn with RNNCell.
-table BidirectionalSequenceRNNOptions {
-  time_major:bool;
-  fused_activation_function:ActivationFunctionType;
-  merge_outputs: bool;
-}
-
-enum FullyConnectedOptionsWeightsFormat: byte {
-  DEFAULT = 0,
-  SHUFFLED4x16INT8 = 1,
-}
-
-// 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;
-}
-
-table SoftmaxOptions {
-  beta: float;
-}
-
-// An implementation of TensorFlow concat.
-table ConcatenationOptions {
-  axis:int;
-  fused_activation_function:ActivationFunctionType;
-}
-
-table AddOptions {
-  fused_activation_function:ActivationFunctionType;
-}
-
-table MulOptions {
-  fused_activation_function:ActivationFunctionType;
-}
-
-table L2NormOptions {
-  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;
-}
-
-// 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;
-}
-
-table BidirectionalSequenceLSTMOptions {
-  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;
-}
-
-table ResizeBilinearOptions {
-  new_height: int (deprecated);
-  new_width: int (deprecated);
-  align_corners: bool;
-}
-
-table ResizeNearestNeighborOptions {
-  align_corners: 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 SubOptions {
-  fused_activation_function:ActivationFunctionType;
-}
-
-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;
-}
-
-table TransposeOptions {
-}
-
-table ExpOptions {
-}
-
-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 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 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;
-}
-
-// 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;
-  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;
-}
-
-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 and output tensors 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];
-}
-
-// 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 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.
-  metadata_buffer:[int];
-}
-
-root_type Model;
diff --git a/runtime/onert/frontend/trix/CMakeLists.txt b/runtime/onert/frontend/trix/CMakeLists.txt
deleted file mode 100644 (file)
index 8d9063f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-if (NOT BUILD_TRIX_LOADER)
-  return()
-endif ()
-
-nnfw_find_package(TRIXEngine QUIET 2.5.0)
-if(TRIXEngine_FOUND)
-  list(APPEND SOURCES src/trix_loader.cc)
-else()
-  list(APPEND SOURCES src/trix_loader_dummy.cc)
-endif(TRIXEngine_FOUND)
-
-add_library(trix_loader STATIC ${SOURCES})
-set_target_properties(trix_loader PROPERTIES POSITION_INDEPENDENT_CODE ON)
-target_include_directories(trix_loader PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
-target_link_libraries(trix_loader PRIVATE onert_core)
-target_link_libraries(trix_loader PRIVATE nnfw_common nnfw_coverage)
-
-if(TRIXEngine_FOUND)
-  target_include_directories(trix_loader PUBLIC ${TRIXEngine_INCLUDE_DIR})
-  target_link_libraries(trix_loader PRIVATE trix_engine)
-endif(TRIXEngine_FOUND)
diff --git a/runtime/onert/frontend/trix/include/trix_loader.h b/runtime/onert/frontend/trix/include/trix_loader.h
deleted file mode 100644 (file)
index 26d6a3c..0000000
+++ /dev/null
@@ -1,34 +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.
- */
-
-#ifndef __TRIX_TRIX_LOADER_H__
-#define __TRIX_TRIX_LOADER_H__
-
-#include "ir/Graph.h"
-#include <memory>
-
-namespace onert
-{
-namespace trix_loader
-{
-/**
- * @throw runtime_error when tvn path is wrong or tvn is invalid
- */
-std::unique_ptr<ir::Model> loadModel(const std::string &filename);
-} // namespace trix_loader
-} // namespace onert
-
-#endif // __TRIX_TRIX_LOADER_H__
diff --git a/runtime/onert/frontend/trix/src/trix_loader.cc b/runtime/onert/frontend/trix/src/trix_loader.cc
deleted file mode 100644 (file)
index cdf2396..0000000
+++ /dev/null
@@ -1,270 +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 "trix_loader.h"
-
-#include "ir/Graph.h"
-#include "ir/operation/Bulk.h"
-
-#include <libnpuhost.h>
-#include <npubinfmt.h>
-#include <typedef.h>
-
-namespace onert
-{
-namespace trix_loader
-{
-
-/**
- * @brief A tvn metadata reader
- */
-class TrixMetaReader
-{
-public:
-  TrixMetaReader() = default;
-  ~TrixMetaReader() { free(_meta); }
-
-  void init(const char *path);
-  data_layout input_seg_layout(uint32_t n) const { return _meta->input_seg_layout[n]; }
-  data_layout output_seg_layout(uint32_t n) const { return _meta->output_seg_layout[n]; }
-  data_type input_seg_quant_type(uint32_t n) const { return _meta->input_seg_quant_type[n]; }
-  data_type output_seg_quant_type(uint32_t n) const { return _meta->output_seg_quant_type[n]; }
-  float input_seg_quant_scale(uint32_t n) const { return _meta->input_seg_quant_s[n]; }
-  float output_seg_quant_scale(uint32_t n) const { return _meta->output_seg_quant_s[n]; }
-  int32_t input_seg_quant_zp(uint32_t n) { return _meta->input_seg_quant_z[n]; }
-  int32_t output_seg_quant_zp(uint32_t n) { return _meta->output_seg_quant_z[n]; }
-  uint32_t input_seg_num() const { return _meta->input_seg_num; }
-  uint32_t output_seg_num() const { return _meta->output_seg_num; }
-  uint32_t input_seg_dims(uint32_t n, uint32_t axis) const
-  {
-    return _meta->input_seg_dims[n][axis];
-  }
-  uint32_t output_seg_dims(uint32_t n, uint32_t axis) const
-  {
-    return _meta->output_seg_dims[n][axis];
-  }
-
-private:
-  npubin_meta *_meta = nullptr;
-};
-
-void TrixMetaReader::init(const char *path)
-{
-  assert(path);
-  _meta = getNPUmodel_metadata(path, false);
-  if (_meta == nullptr)
-  {
-    throw std::runtime_error("Failed to get TRIX model metadata");
-  }
-  if (NPUBIN_VERSION(_meta->magiccode) != 3)
-  {
-    throw std::runtime_error("TRIX model metadata version mismatched.");
-  }
-}
-
-class TrixLoader
-{
-public:
-  /**
-   * @brief Construct a new Loader object
-   *
-   * @param model reference on model
-   */
-  explicit TrixLoader(std::unique_ptr<ir::Model> &model) : _model(model) {}
-
-  /**
-   * @brief Load a model from file
-   * @param file_path
-   */
-  void loadFromFile(const std::string &file_path);
-
-private:
-  /*
-   * @brief Load actually
-   * @throw runtime_error when tvn path is wrong or tvn is invalid
-   */
-  void loadModel();
-  std::unique_ptr<ir::Graph> loadSubgraph();
-  void loadOperands(ir::Graph &subg);
-  ir::OperandIndex loadOperandFromInput(uint32_t i, ir::Graph &subg);
-  ir::OperandIndex loadOperandFromOutput(uint32_t i, ir::Graph &subg);
-  void loadBulk(ir::Graph &subg);
-  void loadOperationIO(ir::OperandIndexSequence &inputs, ir::OperandIndexSequence &outputs);
-  ir::OperandIndex inputIdxToOperandIdx(uint32_t i) const;
-  ir::OperandIndex outputIdxToOperandIdx(uint32_t i) const;
-  ir::DataType toDataType(const data_type type) const;
-
-private:
-protected:
-  /** path to model (e.g. tvn) */
-  std::string _model_path;
-  /** original IO shapes */
-  std::vector<ir::Shape> _origin_input_shapes;
-  std::vector<ir::Shape> _origin_output_shapes;
-  /** Reference on loadable subgraphs */
-  std::unique_ptr<ir::Model> &_model;
-  TrixMetaReader _meta;
-};
-
-ir::DataType TrixLoader::toDataType(const data_type type) const
-{
-  switch (type)
-  {
-    case DATA_TYPE_QASYMM8:
-      return ir::DataType::QUANT_UINT8_ASYMM;
-    case DATA_TYPE_QSYMM16:
-      return ir::DataType::QUANT_INT16_SYMM;
-    default:
-      throw std::runtime_error("Unsupported data type from trix model");
-  }
-}
-
-ir::OperandIndex TrixLoader::inputIdxToOperandIdx(uint32_t i) const { return ir::OperandIndex(i); }
-ir::OperandIndex TrixLoader::outputIdxToOperandIdx(uint32_t i) const
-{
-  return ir::OperandIndex(_meta.input_seg_num() + i);
-}
-
-void TrixLoader::loadOperationIO(ir::OperandIndexSequence &inputs,
-                                 ir::OperandIndexSequence &outputs)
-{
-  for (uint32_t i = 0; i < _meta.input_seg_num(); ++i)
-  {
-    inputs.append(inputIdxToOperandIdx(i));
-  }
-
-  for (uint32_t i = 0; i < _meta.output_seg_num(); ++i)
-  {
-    outputs.append(outputIdxToOperandIdx(i));
-  }
-}
-
-void TrixLoader::loadBulk(ir::Graph &subg)
-{
-  ir::operation::Bulk::Param param;
-  param.binary_path = _model_path;
-  param.origin_input_shapes = _origin_input_shapes;
-  param.origin_output_shapes = _origin_output_shapes;
-
-  ir::OperandIndexSequence inputs;
-  ir::OperandIndexSequence outputs;
-
-  loadOperationIO(inputs, outputs);
-
-  std::unique_ptr<ir::operation::Bulk> bulk(new ir::operation::Bulk(inputs, outputs, param));
-  subg.addOperation(std::move(bulk));
-}
-
-ir::OperandIndex TrixLoader::loadOperandFromInput(uint32_t idx, ir::Graph &subg)
-{
-  // Shape
-  ir::Shape shape;
-  for (uint32_t d = 0; d < MAX_RANK; ++d)
-    shape.append(_meta.input_seg_dims(idx, d));
-
-  // TypeInfo
-  ir::TypeInfo type_info(toDataType(_meta.input_seg_quant_type(idx)),
-                         _meta.input_seg_quant_scale(idx), _meta.input_seg_quant_zp(idx));
-
-  _origin_input_shapes.push_back(shape);
-  // Create operand
-  const auto operand_index = subg.addOperand(shape, type_info);
-  return operand_index;
-}
-
-ir::OperandIndex TrixLoader::loadOperandFromOutput(uint32_t idx, ir::Graph &subg)
-{
-  // Shape
-  ir::Shape shape;
-  for (uint32_t d = 0; d < MAX_RANK; ++d)
-    shape.append(_meta.output_seg_dims(idx, d));
-
-  // TypeInfo
-  ir::TypeInfo type_info(toDataType(_meta.output_seg_quant_type(idx)),
-                         _meta.output_seg_quant_scale(idx), _meta.output_seg_quant_zp(idx));
-
-  _origin_output_shapes.push_back(shape);
-  // Create operand
-  const auto operand_index = subg.addOperand(shape, type_info);
-  return operand_index;
-}
-
-void TrixLoader::loadOperands(ir::Graph &subg)
-{
-  auto in_num = _meta.input_seg_num();
-  for (uint32_t i = 0; i < in_num; ++i)
-  {
-    loadOperandFromInput(i, subg);
-  }
-  auto out_num = _meta.output_seg_num();
-  for (uint32_t i = 0; i < out_num; ++i)
-  {
-    loadOperandFromOutput(i, subg);
-  }
-}
-
-std::unique_ptr<ir::Graph> TrixLoader::loadSubgraph()
-{
-  auto subg = std::make_unique<ir::Graph>();
-  _meta.init(_model_path.c_str());
-
-  // Load tensors
-  loadOperands(*subg);
-
-  // Set inputs
-  for (uint32_t i = 0; i < _meta.input_seg_num(); ++i)
-  {
-    subg->addInput(inputIdxToOperandIdx(i), "tvn_input" + std::to_string(i));
-  }
-  // Set outputs
-  for (uint32_t i = 0; i < _meta.output_seg_num(); ++i)
-  {
-    subg->addOutput(outputIdxToOperandIdx(i), "tvn_out" + std::to_string(i));
-  }
-  // Create operations
-  loadBulk(*subg);
-
-  // TODO: NHWC only supported at this moment.
-  subg->setLayout(ir::Layout::NHWC);
-  subg->verify();
-  return subg;
-}
-
-void TrixLoader::loadModel()
-{
-  // one subgraph only
-  auto subg = loadSubgraph();
-  _model->push(ir::SubgraphIndex(0), std::move(subg));
-}
-
-void TrixLoader::loadFromFile(const std::string &file_path)
-{
-  // model path will be used to set Bulk param
-  _model_path = file_path;
-  // metadata is initialized from model path since it is loadFromFile
-  _meta.init(_model_path.c_str());
-  loadModel();
-}
-
-std::unique_ptr<ir::Model> loadModel(const std::string &filename)
-{
-  auto model = std::make_unique<ir::Model>();
-  TrixLoader loader(model);
-  loader.loadFromFile(filename);
-  return model;
-}
-} // namespace trix_loader
-} // namespace onert
diff --git a/runtime/onert/frontend/trix/src/trix_loader_dummy.cc b/runtime/onert/frontend/trix/src/trix_loader_dummy.cc
deleted file mode 100644 (file)
index eecbd22..0000000
+++ /dev/null
@@ -1,31 +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 "trix_loader.h"
-
-// Dummy implementation to avoid build error for target, which doesn't have trix_engine
-
-namespace onert
-{
-namespace trix_loader
-{
-std::unique_ptr<ir::Model> loadModel(const std::string &)
-{
-  auto model = std::make_unique<ir::Model>();
-  return model;
-}
-} // namespace trix_loader
-} // namespace onert
diff --git a/runtime/onert/loader/trix/CMakeLists.txt b/runtime/onert/loader/trix/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5471704
--- /dev/null
@@ -0,0 +1,23 @@
+if (NOT BUILD_TRIX_LOADER)
+  return()
+endif ()
+
+nnfw_find_package(TRIXEngine QUIET 2.5.0)
+if(TRIXEngine_FOUND)
+  message(STATUS "ONERT frontend: Found TRIXEngine")
+  list(APPEND SOURCES TrixLoader.cc)
+else()
+  message(STATUS "ONERT frontend: Failed to find TRIXEngine")
+  return()
+endif(TRIXEngine_FOUND)
+
+# Loader library name should be lib<type>_loader.so
+add_library(tvn_loader SHARED ${SOURCES})
+set_target_properties(tvn_loader PROPERTIES
+  POSITION_INDEPENDENT_CODE ON
+  INSTALL_RPATH "$ORIGIN:$ORIGIN/../..")
+target_link_libraries(tvn_loader PRIVATE onert_core)
+target_link_libraries(tvn_loader PRIVATE nnfw_common nnfw_coverage)
+target_link_libraries(tvn_loader PRIVATE trix_engine)
+
+install(TARGETS tvn_loader DESTINATION lib/nnfw/loader)
diff --git a/runtime/onert/loader/trix/TrixLoader.cc b/runtime/onert/loader/trix/TrixLoader.cc
new file mode 100644 (file)
index 0000000..d787435
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * 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 "ir/Graph.h"
+#include "ir/operation/Bulk.h"
+#include "loader/ILoader.h"
+
+#include <libnpuhost.h>
+#include <npubinfmt.h>
+#include <typedef.h>
+
+namespace onert
+{
+namespace trix_loader
+{
+
+/**
+ * @brief A tvn metadata reader
+ */
+class TrixMetaReader
+{
+public:
+  TrixMetaReader() = default;
+  ~TrixMetaReader() { free(_meta); }
+
+  void init(const char *path);
+  data_layout input_seg_layout(uint32_t n) const { return _meta->input_seg_layout[n]; }
+  data_layout output_seg_layout(uint32_t n) const { return _meta->output_seg_layout[n]; }
+  data_type input_seg_quant_type(uint32_t n) const { return _meta->input_seg_quant_type[n]; }
+  data_type output_seg_quant_type(uint32_t n) const { return _meta->output_seg_quant_type[n]; }
+  float input_seg_quant_scale(uint32_t n) const { return _meta->input_seg_quant_s[n]; }
+  float output_seg_quant_scale(uint32_t n) const { return _meta->output_seg_quant_s[n]; }
+  int32_t input_seg_quant_zp(uint32_t n) { return _meta->input_seg_quant_z[n]; }
+  int32_t output_seg_quant_zp(uint32_t n) { return _meta->output_seg_quant_z[n]; }
+  uint32_t input_seg_num() const { return _meta->input_seg_num; }
+  uint32_t output_seg_num() const { return _meta->output_seg_num; }
+  uint32_t input_seg_dims(uint32_t n, uint32_t axis) const
+  {
+    return _meta->input_seg_dims[n][axis];
+  }
+  uint32_t output_seg_dims(uint32_t n, uint32_t axis) const
+  {
+    return _meta->output_seg_dims[n][axis];
+  }
+
+private:
+  npubin_meta *_meta = nullptr;
+};
+
+void TrixMetaReader::init(const char *path)
+{
+  assert(path);
+  _meta = getNPUmodel_metadata(path, false);
+  if (_meta == nullptr)
+  {
+    throw std::runtime_error("Failed to get TRIX model metadata");
+  }
+  if (NPUBIN_VERSION(_meta->magiccode) != 3)
+  {
+    throw std::runtime_error("TRIX model metadata version mismatched.");
+  }
+}
+
+class TrixLoader : public onert::loader::ILoader
+{
+public:
+  /**
+   * @brief Construct a new Loader object
+   */
+  TrixLoader() = default;
+
+  /**
+   * @brief Load a model from file
+   * @param file_path
+   */
+  std::unique_ptr<ir::Model> loadFromFile(const std::string &file_path) override;
+
+private:
+  /*
+   * @brief Load actually
+   * @throw runtime_error when tvn path is wrong or tvn is invalid
+   */
+  void loadModel(std::unique_ptr<ir::Model> &model);
+  std::unique_ptr<ir::Graph> loadSubgraph();
+  void loadOperands(ir::Graph &subg);
+  ir::OperandIndex loadOperandFromInput(uint32_t i, ir::Graph &subg);
+  ir::OperandIndex loadOperandFromOutput(uint32_t i, ir::Graph &subg);
+  void loadBulk(ir::Graph &subg);
+  void loadOperationIO(ir::OperandIndexSequence &inputs, ir::OperandIndexSequence &outputs);
+  ir::OperandIndex inputIdxToOperandIdx(uint32_t i) const;
+  ir::OperandIndex outputIdxToOperandIdx(uint32_t i) const;
+  ir::DataType toDataType(const data_type type) const;
+
+private:
+  /** path to model (e.g. tvn) */
+  std::string _model_path;
+  /** original IO shapes */
+  std::vector<ir::Shape> _origin_input_shapes;
+  std::vector<ir::Shape> _origin_output_shapes;
+  TrixMetaReader _meta;
+};
+
+ir::DataType TrixLoader::toDataType(const data_type type) const
+{
+  switch (type)
+  {
+    case DATA_TYPE_QASYMM8:
+      return ir::DataType::QUANT_UINT8_ASYMM;
+    case DATA_TYPE_QSYMM16:
+      return ir::DataType::QUANT_INT16_SYMM;
+    default:
+      throw std::runtime_error("Unsupported data type from trix model");
+  }
+}
+
+ir::OperandIndex TrixLoader::inputIdxToOperandIdx(uint32_t i) const { return ir::OperandIndex(i); }
+ir::OperandIndex TrixLoader::outputIdxToOperandIdx(uint32_t i) const
+{
+  return ir::OperandIndex(_meta.input_seg_num() + i);
+}
+
+void TrixLoader::loadOperationIO(ir::OperandIndexSequence &inputs,
+                                 ir::OperandIndexSequence &outputs)
+{
+  for (uint32_t i = 0; i < _meta.input_seg_num(); ++i)
+  {
+    inputs.append(inputIdxToOperandIdx(i));
+  }
+
+  for (uint32_t i = 0; i < _meta.output_seg_num(); ++i)
+  {
+    outputs.append(outputIdxToOperandIdx(i));
+  }
+}
+
+void TrixLoader::loadBulk(ir::Graph &subg)
+{
+  ir::operation::Bulk::Param param;
+  param.binary_path = _model_path;
+  param.origin_input_shapes = _origin_input_shapes;
+  param.origin_output_shapes = _origin_output_shapes;
+
+  ir::OperandIndexSequence inputs;
+  ir::OperandIndexSequence outputs;
+
+  loadOperationIO(inputs, outputs);
+
+  std::unique_ptr<ir::operation::Bulk> bulk(new ir::operation::Bulk(inputs, outputs, param));
+  subg.addOperation(std::move(bulk));
+}
+
+ir::OperandIndex TrixLoader::loadOperandFromInput(uint32_t idx, ir::Graph &subg)
+{
+  // Shape
+  ir::Shape shape;
+  for (uint32_t d = 0; d < MAX_RANK; ++d)
+    shape.append(_meta.input_seg_dims(idx, d));
+
+  // TypeInfo
+  ir::TypeInfo type_info(toDataType(_meta.input_seg_quant_type(idx)),
+                         _meta.input_seg_quant_scale(idx), _meta.input_seg_quant_zp(idx));
+
+  _origin_input_shapes.push_back(shape);
+  // Create operand
+  const auto operand_index = subg.addOperand(shape, type_info);
+  return operand_index;
+}
+
+ir::OperandIndex TrixLoader::loadOperandFromOutput(uint32_t idx, ir::Graph &subg)
+{
+  // Shape
+  ir::Shape shape;
+  for (uint32_t d = 0; d < MAX_RANK; ++d)
+    shape.append(_meta.output_seg_dims(idx, d));
+
+  // TypeInfo
+  ir::TypeInfo type_info(toDataType(_meta.output_seg_quant_type(idx)),
+                         _meta.output_seg_quant_scale(idx), _meta.output_seg_quant_zp(idx));
+
+  _origin_output_shapes.push_back(shape);
+  // Create operand
+  const auto operand_index = subg.addOperand(shape, type_info);
+  return operand_index;
+}
+
+void TrixLoader::loadOperands(ir::Graph &subg)
+{
+  auto in_num = _meta.input_seg_num();
+  for (uint32_t i = 0; i < in_num; ++i)
+  {
+    loadOperandFromInput(i, subg);
+  }
+  auto out_num = _meta.output_seg_num();
+  for (uint32_t i = 0; i < out_num; ++i)
+  {
+    loadOperandFromOutput(i, subg);
+  }
+}
+
+std::unique_ptr<ir::Graph> TrixLoader::loadSubgraph()
+{
+  auto subg = std::make_unique<ir::Graph>();
+  _meta.init(_model_path.c_str());
+
+  // Load tensors
+  loadOperands(*subg);
+
+  // Set inputs
+  for (uint32_t i = 0; i < _meta.input_seg_num(); ++i)
+  {
+    subg->addInput(inputIdxToOperandIdx(i), "tvn_input" + std::to_string(i));
+  }
+  // Set outputs
+  for (uint32_t i = 0; i < _meta.output_seg_num(); ++i)
+  {
+    subg->addOutput(outputIdxToOperandIdx(i), "tvn_out" + std::to_string(i));
+  }
+  // Create operations
+  loadBulk(*subg);
+
+  // TODO: NHWC only supported at this moment.
+  subg->setLayout(ir::Layout::NHWC);
+  subg->verify();
+  return subg;
+}
+
+void TrixLoader::loadModel(std::unique_ptr<ir::Model> &model)
+{
+  // one subgraph only
+  auto subg = loadSubgraph();
+  model->push(ir::SubgraphIndex(0), std::move(subg));
+}
+
+std::unique_ptr<ir::Model> TrixLoader::loadFromFile(const std::string &file_path)
+{
+  auto model = std::make_unique<ir::Model>();
+  // model path will be used to set Bulk param
+  _model_path = file_path;
+  // metadata is initialized from model path since it is loadFromFile
+  _meta.init(_model_path.c_str());
+  loadModel(model);
+  return model;
+}
+
+} // namespace trix_loader
+} // namespace onert
+
+extern "C" {
+
+onert::loader::ILoader *onert_loader_create() { return new onert::trix_loader::TrixLoader; }
+
+void onert_loader_destroy(onert::loader::ILoader *loader) { delete loader; }
+}
index e48878d..e363e2d 100644 (file)
@@ -1,8 +1,3 @@
-# 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")
@@ -19,6 +14,7 @@ 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)
+set_target_properties(onert_odc PROPERTIES INSTALL_RPATH "$ORIGIN/../../:$ORIGIN/")
 
 if(NOT ENABLE_TEST)
   return()
@@ -37,3 +33,4 @@ target_include_directories(${TEST_ONERT_ODC} PRIVATE $<TARGET_PROPERTY:onert_odc
 
 add_test(${TEST_ONERT_ODC} ${TEST_ONERT_ODC})
 install(TARGETS ${TEST_ONERT_ODC} DESTINATION unittest)
+set_target_properties(${TEST_ONERT_ODC} PROPERTIES INSTALL_RPATH "$ORIGIN/../lib/nnfw/odc:$ORIGIN/../lib/")
diff --git a/runtime/onert/odc/Embedder.cc b/runtime/onert/odc/Embedder.cc
new file mode 100644 (file)
index 0000000..ed379d6
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "Embedder.h"
+#include "MinMaxReader.h"
+
+#include <luci/CircleExporter.h>
+#include <luci/CircleFileExpContract.h>
+#include <luci/ImporterEx.h>
+#include <luci/IR/CircleNode.h>
+#include <luci/IR/CircleQuantParam.h>
+#include <luci/Profile/CircleNodeID.h>
+#include <luci/Service/Validate.h>
+
+#include <cassert>
+#include <cmath> // for std::floor
+#include <string>
+
+namespace
+{
+
+/* NOTE: getNthPercentile is copied from compiler/record-minmax/include/RecordFunction.h */
+/**
+ * @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;
+}
+
+} // namespace
+
+namespace onert
+{
+namespace odc
+{
+
+void Embedder::embed(luci::Module *module, const std::string &minmax_path,
+                     const EmbedderOptions &opt)
+{
+  if (module == nullptr)
+    throw std::runtime_error{"Input module is nullptr"};
+
+  MinMaxReader mmr{minmax_path};
+
+  for (size_t idx = 0; idx < module->size(); ++idx)
+  {
+    auto graph = module->graph(idx);
+
+    /* read subgraph inputs */
+    const auto input_nodes = loco::input_nodes(graph);
+    const auto n_inputs = input_nodes.size();
+    for (size_t input_idx = 0; input_idx < n_inputs; ++input_idx)
+    {
+      const auto *circle_input = loco::must_cast<const luci::CircleInput *>(input_nodes[input_idx]);
+      if (circle_input->index() != input_idx)
+        throw std::runtime_error("Input order in minmax recording does not match to circle");
+
+      auto minmax = mmr.readInput(0, idx, input_idx);
+      auto min = getNthPercentile(minmax.min_vector, opt.min_percentile);
+      auto max = getNthPercentile(minmax.max_vector, opt.max_percentile);
+      auto quantparam = std::make_unique<luci::CircleQuantParam>();
+      quantparam->min.push_back(min);
+      quantparam->max.push_back(max);
+      const auto *circle_node = loco::must_cast<const luci::CircleNode *>(input_nodes[input_idx]);
+      auto mutable_node = const_cast<luci::CircleNode *>(circle_node);
+      mutable_node->quantparam(std::move(quantparam));
+    }
+
+    /* read op outputs */
+    uint32_t n_nodes = graph->nodes()->size();
+    for (uint32_t i = 0; i < n_nodes; ++i)
+    {
+      auto node = loco::must_cast<luci::CircleNode *>(graph->nodes()->at(i));
+      if (not luci::has_node_id(node)) // Skip non-op nodes (e.g. input/const/output)
+        continue;
+      auto op_idx = luci::get_node_id(node);
+      auto minmax = mmr.readOP(0, idx, op_idx);
+      auto min = getNthPercentile(minmax.min_vector, opt.min_percentile);
+      auto max = getNthPercentile(minmax.max_vector, opt.max_percentile);
+      auto quantparam = std::make_unique<luci::CircleQuantParam>();
+      quantparam->min.push_back(min);
+      quantparam->max.push_back(max);
+      auto mutable_node = const_cast<luci::CircleNode *>(node);
+      mutable_node->quantparam(std::move(quantparam));
+    }
+
+    if (!luci::validate(graph))
+      throw std::runtime_error{"Circle after embedding minmax is invalid"};
+  }
+}
+
+} // namespace odc
+} // namespace onert
diff --git a/runtime/onert/odc/Embedder.h b/runtime/onert/odc/Embedder.h
new file mode 100644 (file)
index 0000000..58155b6
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_EMBEDDER_H__
+#define __ONERT_ODC_EMBEDDER_H__
+
+#include "luci/IR/Module.h"
+
+#include <string>
+
+namespace onert
+{
+namespace odc
+{
+struct EmbedderOptions
+{
+  float min_percentile = 0.0f; // dummy initial value to make SE tool happy
+  float max_percentile = 0.0f; // dummy initial value To make SE tool happy
+};
+
+class Embedder
+{
+public:
+  void embed(luci::Module *module, const std::string &minmax_path, const EmbedderOptions &opt);
+};
+} // namespace odc
+} // namespace onert
+
+#endif // __MINMAX_EMBEDDER_EMBEDDER_H__
diff --git a/runtime/onert/odc/MinMaxReader.cc b/runtime/onert/odc/MinMaxReader.cc
new file mode 100644 (file)
index 0000000..c9c9214
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "MinMaxReader.h"
+
+#include <cstdio>
+#include <stdexcept>
+#include <limits>
+
+namespace
+{
+
+void readMMFile(void *ptr, size_t size, size_t count, FILE *fp, const std::string &err_msg)
+{
+  if (std::fread(ptr, size, count, fp) != count)
+  {
+    std::fclose(fp);
+    throw std::runtime_error(err_msg);
+  }
+}
+
+void seekMMFile(FILE *fp, int64_t offset, int whence, const std::string &err_msg)
+{
+  if (std::fseek(fp, offset, whence) != 0)
+  {
+    std::fclose(fp);
+    throw std::runtime_error(err_msg);
+  }
+}
+
+void checkHeader(FILE *file)
+{
+  // Check magic code and version
+  // Match with runtime/onert/core/src/exec/MinMaxData.cc
+  // TODO Use util to share code and version
+  const uint32_t MAGIC_CODE = 0x4F4D4D44;
+  const uint32_t VERSION = 1;
+  {
+    uint32_t read_magic_code = 0;
+    uint32_t read_version = 0;
+
+    readMMFile(&read_magic_code, sizeof(uint32_t), 1, file,
+               "MinMaxReader: Failed to read magic code");
+    readMMFile(&read_version, sizeof(uint32_t), 1, file, "MinMaxReader: Failed to read version");
+
+    if (read_magic_code != MAGIC_CODE)
+    {
+      std::fclose(file);
+      throw std::runtime_error{"MinMaxReader: Invalid magic code"};
+    }
+
+    if (read_version != VERSION)
+    {
+      std::fclose(file);
+      throw std::runtime_error{"MinMaxReader: Invalid version"};
+    }
+  }
+}
+
+} // namespace
+
+namespace onert
+{
+namespace odc
+{
+
+MinMaxReader::MinMaxReader(const std::string &filepath) : _filepath(filepath)
+{
+  // DO NOTHING
+}
+
+// TODO: Handle multiple output
+MinMaxVectors MinMaxReader::readOP(uint32_t model_idx, uint32_t subg_idx, uint32_t op_idx) const
+{
+  // Find file to read
+  auto file = std::fopen(_filepath.c_str(), "rb");
+  if (!file)
+    throw std::runtime_error("Cannot open file: " + _filepath);
+
+  checkHeader(file);
+
+  // Read num_run
+  uint32_t num_run = 0;
+  readMMFile(&num_run, sizeof(uint32_t), 1, file, "Cannot read num_run from file");
+
+  MinMaxVectors mmv;
+  float minmax[2];
+  const int64_t data_size = sizeof(float) * 2 + sizeof(uint32_t) * 3;
+
+  // Check num_run overflow
+  if (num_run > std::numeric_limits<uint32_t>::max() / data_size)
+    throw std::runtime_error("num_run overflow");
+
+  for (uint32_t r = 0; r < num_run; ++r)
+  {
+    // Read num of operations and num of inputs
+    uint32_t num_op = 0;
+    readMMFile(&num_op, sizeof(uint32_t), 1, file, "Cannot read num of operations");
+    uint32_t num_input = 0;
+    readMMFile(&num_input, sizeof(uint32_t), 1, file, "Cannot read num of inputs");
+
+    // Check num_op overflow
+    if (num_op > std::numeric_limits<uint32_t>::max() / data_size / num_run)
+      throw std::runtime_error("num_op overflow");
+    // Check num_input overflow
+    if (num_input > std::numeric_limits<uint32_t>::max() / data_size / num_run)
+      throw std::runtime_error("num_input overflow");
+
+    // Find operation
+    for (uint32_t i = 0; i < num_op; ++i)
+    {
+      uint32_t model_id_from_file = 0;
+      uint32_t subg_idx_from_file = 0;
+      uint32_t op_idx_from_file = 0;
+
+      readMMFile(&model_id_from_file, sizeof(uint32_t), 1, file, "Cannot read model_id from file");
+      readMMFile(&subg_idx_from_file, sizeof(uint32_t), 1, file, "Cannot read subg_idx from file");
+      readMMFile(&op_idx_from_file, sizeof(uint32_t), 1, file, "Cannot read op_idx from file");
+
+      if (model_id_from_file == model_idx && subg_idx_from_file == subg_idx &&
+          op_idx_from_file == op_idx)
+      {
+        // Read minmax data
+        readMMFile(minmax, sizeof(float), 2, file, "Cannot read minmax data from file");
+        mmv.min_vector.emplace_back(minmax[0]);
+        mmv.max_vector.emplace_back(minmax[1]);
+
+        // Skip remain operation minmax data
+        const uint32_t remain_elem = num_op - i - 1;
+        seekMMFile(file, static_cast<int64_t>(data_size * remain_elem), SEEK_CUR,
+                   "Failed to skip remain minmax data");
+
+        break;
+      }
+
+      // Skip minmax data
+      seekMMFile(file, sizeof(float) * 2, SEEK_CUR, "Failed to skip minmax data");
+    }
+
+    // Skip input minmax data
+    seekMMFile(file, static_cast<int64_t>(data_size * num_input), SEEK_CUR,
+               "Failed to skip input minmax data");
+  }
+
+  std::fclose(file);
+  return mmv;
+}
+
+MinMaxVectors MinMaxReader::readInput(uint32_t model_idx, uint32_t subg_idx,
+                                      uint32_t input_idx) const
+{
+  // Find file to read
+  auto file = std::fopen(_filepath.c_str(), "rb");
+  if (!file)
+    throw std::runtime_error("Cannot open file: " + _filepath);
+
+  checkHeader(file);
+
+  // Read num_run
+  uint32_t num_run = 0;
+  readMMFile(&num_run, sizeof(uint32_t), 1, file, "Cannot read num_run from file");
+
+  MinMaxVectors mmv;
+  float minmax[2];
+  const int64_t data_size = sizeof(float) * 2 + sizeof(uint32_t) * 3;
+
+  // Check num_run overflow
+  if (num_run > std::numeric_limits<uint32_t>::max() / data_size)
+    throw std::runtime_error("num_run overflow");
+
+  for (uint32_t r = 0; r < num_run; ++r)
+  {
+    // Read num of operations and num of inputs
+    uint32_t num_op = 0;
+    readMMFile(&num_op, sizeof(uint32_t), 1, file, "Cannot read num of operations");
+    uint32_t num_input = 0;
+    readMMFile(&num_input, sizeof(uint32_t), 1, file, "Cannot read num of inputs");
+
+    // Check num_op overflow
+    if (num_op > std::numeric_limits<uint32_t>::max() / data_size / num_run)
+      throw std::runtime_error("num_op overflow");
+    // Check num_input overflow
+    if (num_input > std::numeric_limits<uint32_t>::max() / data_size / num_run)
+      throw std::runtime_error("num_input overflow");
+
+    // Skip operation minmax data
+    seekMMFile(file, static_cast<int64_t>(data_size * num_op), SEEK_CUR,
+               "Cannot skip operation minmax data");
+
+    // Find operation
+    for (uint32_t i = 0; i < num_input; ++i)
+    {
+      uint32_t model_id_from_file = 0;
+      uint32_t subg_idx_from_file = 0;
+      uint32_t input_idx_from_file = 0;
+
+      readMMFile(&model_id_from_file, sizeof(uint32_t), 1, file, "Cannot read model_id from file");
+      readMMFile(&subg_idx_from_file, sizeof(uint32_t), 1, file, "Cannot read subg_idx from file");
+      readMMFile(&input_idx_from_file, sizeof(uint32_t), 1, file,
+                 "Cannot read input_idx from file");
+
+      if (model_id_from_file == model_idx && subg_idx_from_file == subg_idx &&
+          input_idx_from_file == input_idx)
+      {
+        // Read minmax data
+        readMMFile(minmax, sizeof(float), 2, file, "Cannot read minmax data from file");
+        mmv.min_vector.emplace_back(minmax[0]);
+        mmv.max_vector.emplace_back(minmax[1]);
+
+        // Skip remain input minmax data
+        const uint32_t remain_elem = num_input - i - 1;
+        seekMMFile(file, static_cast<int64_t>(data_size * remain_elem), SEEK_CUR,
+                   "Cannot skip remain minmax data from file");
+        break;
+      }
+
+      // Skip minmax data
+      seekMMFile(file, sizeof(float) * 2, SEEK_CUR, "Cannot skip minmax data from file");
+    }
+  }
+
+  std::fclose(file);
+  return mmv;
+}
+
+} // namespace odc
+} // namespace onert
diff --git a/runtime/onert/odc/MinMaxReader.h b/runtime/onert/odc/MinMaxReader.h
new file mode 100644 (file)
index 0000000..98c79fc
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_MINMAX_READER_H__
+#define __ONERT_ODC_MINMAX_READER_H__
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace onert
+{
+namespace odc
+{
+
+// File structure
+// uint32_t magic code
+// uint32_t version
+// uint32_t num of runs
+
+// For each run
+// uint32_t num of operations
+// uint32_t num of inputs
+
+// For each operation
+// uint32_t model id
+// uint32_t subgraph id
+// uint32_t operation id
+// float min
+// float max
+
+// For each input
+// uint32_t model id
+// uint32_t subgraph id
+// uint32_t input id
+// float min
+// float max
+
+struct MinMaxVectors
+{
+  std::vector<float> min_vector;
+  std::vector<float> max_vector;
+};
+
+class MinMaxReader
+{
+public:
+  MinMaxReader(const std::string &filepath);
+  /**
+   * @brief Returns minmax recording for op {model_idx, subg_idx, op_idx}
+   *
+   * @return MinMaxVectors
+   */
+  MinMaxVectors readOP(uint32_t model_idx, uint32_t subg_idx, uint32_t op_idx) const;
+  /**
+   * @brief Returns minmax recording for input {model_idx, subg_idx, input_idx}
+   *
+   * @return MinMaxVectors
+   */
+  MinMaxVectors readInput(uint32_t model_idx, uint32_t subg_idx, uint32_t input_idx) const;
+
+private:
+  std::string _filepath;
+};
+
+} // namespace odc
+} // namespace onert
+
+#endif // __ONERT_ODC_MINMAX_READER_H__
index b8aec97..3c7b13f 100644 (file)
@@ -16,6 +16,9 @@
 
 #include "Quantizer.h"
 
+#include "Embedder.h"
+
+#include <util/ConfigSource.h>
 #include <luci/ImporterEx.h>
 #include <luci/CircleQuantizer.h>
 #include <luci/CircleExporter.h>
@@ -31,25 +34,97 @@ namespace onert
 namespace odc
 {
 
-int Quantizer::quantize(const char *in, const char *out, bool is_q16)
+using QuantizerOptions = luci::CircleQuantizer::Options;
+using QuantizeType = onert::odc::QuantizeType;
+
+namespace
+{
+
+void fillQuantizeOptionParam(QuantizerOptions *options, QuantizeType qtype)
+{
+  std::string output_type = "";
+  switch (qtype)
+  {
+    case QuantizeType::ODC_QTYPE_U8_ASYM:
+      output_type = "uint8";
+      break;
+    case QuantizeType::ODC_QTYPE_I16_SYM:
+      output_type = "int16";
+      break;
+    case QuantizeType::ODC_QTYPE_WO_I8_SYM:
+      output_type = "wo_int8";
+      break;
+    case QuantizeType::ODC_QTYPE_WO_I16_SYM:
+      output_type = "wo_int16";
+      break;
+    default:
+      throw std::runtime_error("Invalid quantization type");
+  }
+  options->param(QuantizerOptions::AlgorithmParameters::Quantize_output_model_dtype, output_type);
+  options->param(QuantizerOptions::AlgorithmParameters::Quantize_input_model_dtype, "float32");
+  options->param(QuantizerOptions::AlgorithmParameters::Quantize_granularity, "channel");
+
+  if (qtype == QuantizeType::ODC_QTYPE_U8_ASYM)
+  {
+    options->param(QuantizerOptions::AlgorithmParameters::Quantize_input_type, "uint8");
+    options->param(QuantizerOptions::AlgorithmParameters::Quantize_output_type, "uint8");
+  }
+  else if (qtype == QuantizeType::ODC_QTYPE_I16_SYM)
+  {
+    options->param(QuantizerOptions::AlgorithmParameters::Quantize_input_type, "int16");
+    options->param(QuantizerOptions::AlgorithmParameters::Quantize_output_type, "int16");
+  }
+}
+
+} // namespace
+
+int Quantizer::quantize(const char *in, const char *out, QuantizeType qtype)
 {
+  if (not in || not out)
+    return 1;
+
+  bool full_quantize = false;
+  if (qtype == QuantizeType::ODC_QTYPE_U8_ASYM || qtype == QuantizeType::ODC_QTYPE_I16_SYM)
+    full_quantize = true;
+
   // 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();
+  // Additional phase for full quantization
+  if (full_quantize)
   {
-    options->enable(luci::CircleQuantizer::Options::Algorithm::QuantizeWeights);
+    luci::CircleQuantizer quantizer;
+    auto options = quantizer.options();
+    fillQuantizeOptionParam(options, qtype);
+
+    // Fake quantization
+    options->enable(QuantizerOptions::Algorithm::QuantizeDequantizeWeights);
+    for (size_t idx = 0; idx < module->size(); ++idx)
+    {
+      auto graph = module->graph(idx);
+
+      // quantize the graph
+      quantizer.quantize(graph);
+    }
 
-    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");
+    // Record minmax by minmax-embedder
+    // TODO use workspace to find minmax file
+    auto minmax_path = util::getConfigString(util::config::WORKSPACE_DIR) + "/minmax.bin";
+    Embedder().embed(module.get(), minmax_path, {1.f, 99.f});
   }
 
+  luci::CircleQuantizer quantizer;
+  auto options = quantizer.options();
+  fillQuantizeOptionParam(options, qtype);
+
+  if (full_quantize)
+    options->enable(QuantizerOptions::Algorithm::QuantizeWithMinMax);
+  else
+    options->enable(QuantizerOptions::Algorithm::QuantizeWeights);
+
   for (size_t idx = 0; idx < module->size(); ++idx)
   {
     auto graph = module->graph(idx);
@@ -75,7 +150,6 @@ int Quantizer::quantize(const char *in, const char *out, bool is_q16)
   if (!exporter.invoke(&contract))
     return 1;
 
-  // Return 0 when luci::CircleQuantizer::Options::Algorithm::QuantizeWeights is ready
   return 0;
 }
 
index 8a03f59..c87794b 100644 (file)
@@ -30,7 +30,7 @@ public:
   Quantizer() = default;
   ~Quantizer() = default;
 
-  int quantize(const char *in, const char *out, bool is_q16);
+  int quantize(const char *in, const char *out, QuantizeType qtype) override;
 };
 
 } // namespace odc
index 22baed5..59c4324 100644 (file)
 using namespace onert::odc;
 
 // Test model input path is not set
-TEST(odc_Quantizer, neg_model_input_path)
+TEST(odc_Quantizer, neg_model_input_path_null)
 {
   Quantizer quantizer;
-  ASSERT_THROW(quantizer.quantize(nullptr, "out", false), std::logic_error);
+  ASSERT_NE(quantizer.quantize(nullptr, "out", QuantizeType::ODC_QTYPE_WO_I8_SYM), 0);
 }
 
 // Test model output path is not set
-TEST(odc_Quantizer, neg_model_output_path)
+TEST(odc_Quantizer, neg_model_output_path_null)
 {
   Quantizer quantizer;
-  ASSERT_NE(quantizer.quantize("in", nullptr, false), 0);
+  ASSERT_NE(quantizer.quantize("in", nullptr, QuantizeType::ODC_QTYPE_WO_I8_SYM), 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);
+  ASSERT_NE(
+    quantizer.quantize("invalid_model_input_path.circle", "out", QuantizeType::ODC_QTYPE_WO_I8_SYM),
+    0);
 }
diff --git a/runtime/onert/sample/minimal-python/README.md b/runtime/onert/sample/minimal-python/README.md
new file mode 100644 (file)
index 0000000..925bb63
--- /dev/null
@@ -0,0 +1,13 @@
+# minimal-python
+
+`minimal-python` is a simple driver to run `nnpackage` with nnfw python API.
+
+It takes `nnpackage` as input. It uses **nnfw python API** internally.
+
+It assumes model of float32 tensor type as an input.
+
+## Usage
+
+```
+$ python3 minimal.py path_to_nnpackage_directory
+```
diff --git a/runtime/onert/sample/minimal-python/src/minimal.py b/runtime/onert/sample/minimal-python/src/minimal.py
new file mode 100644 (file)
index 0000000..60e8569
--- /dev/null
@@ -0,0 +1,26 @@
+from nnfwapi.libnnfw_api_pybind import *
+import sys
+
+
+def main(nnpackage_path, backends="cpu", operations=""):
+    # Create session and load nnpackage
+    # operations is optional to assign a specific backends to each operation.
+    # The default value of backends is "cpu".
+    if operations:
+        session = nnfw_session(nnpackage_path, backends, operations)
+    else:
+        session = nnfw_session(nnpackage_path, backends)
+
+    # Prepare input. Here we just allocate dummy input arrays.
+    input_size = session.input_size()
+    session.set_inputs(input_size)
+
+    outputs = session.inference()
+
+    print(f"nnpackage {nnpackage_path.split('/')[-1]} runs successfully.")
+    return
+
+
+if __name__ == "__main__":
+    argv = sys.argv[1:]
+    main(*argv)
index fa7aaa9..9ec3a2d 100644 (file)
@@ -1,8 +1,10 @@
 nnfw_find_package(TRIXEngine QUIET 2.5.0)
 
 if(NOT TRIXEngine_FOUND)
+  message(STATUS "NPUD backend: Failed to find TRIXEngine")
   return()
 endif(NOT TRIXEngine_FOUND)
+message(STATUS "NPUD backend: Found TRIXEngine")
 
 file(GLOB_RECURSE SOURCES "*.cc")
 
index 1eb2f07..65f7d79 100644 (file)
@@ -2,4 +2,8 @@ if(NOT ENABLE_TEST)
   return()
 endif(NOT ENABLE_TEST)
 
+# Use C++17 for tests
+# TODO: Remove this when we use C++17 for all runtime directories
+set(CMAKE_CXX_STANDARD 17)
+
 add_subdirectories()
index 9b46a13..8edf74a 100644 (file)
@@ -2,7 +2,7 @@ if(NOT BUILD_ONERT)
   return()
 endif(NOT BUILD_ONERT)
 
-nnfw_find_package(FlatBuffers QUIET)
+nnfw_find_package(FlatBuffers EXACT 23.5.26 QUIET)
 if(NOT FlatBuffers_FOUND)
   message(STATUS "Skip build custom operation test: cannot find flatbuffers")
   return()
@@ -58,7 +58,7 @@ function(add_nnfw_custom_op_kernel NAME STATIC)
     add_library(${LIBNAME} SHARED ${ARGN})
   endif()
   target_link_libraries(${LIBNAME} PRIVATE nnfw-nnapi-header nnfw-dev)
-  target_link_libraries(${LIBNAME} PRIVATE flatbuffers::flatbuffers)
+  target_link_libraries(${LIBNAME} PRIVATE flatbuffers::flatbuffers-23.5.26)
 endfunction()
 
 # Install custom op kernel built with `add_nnfw_custom_op_kernel`
diff --git a/tests/libs/CMakeLists.txt b/tests/libs/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5ea6cda
--- /dev/null
@@ -0,0 +1 @@
+add_subdirectories()
diff --git a/tests/libs/benchmark/CMakeLists.txt b/tests/libs/benchmark/CMakeLists.txt
new file mode 100644 (file)
index 0000000..301a8ca
--- /dev/null
@@ -0,0 +1,5 @@
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+
+add_library(nnfw_lib_benchmark STATIC ${SOURCES})
+target_include_directories(nnfw_lib_benchmark PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
+target_link_libraries(nnfw_lib_benchmark PRIVATE ${LIB_PTHREAD} nnfw_lib_misc)
diff --git a/tests/libs/benchmark/include/benchmark/Accumulator.h b/tests/libs/benchmark/include/benchmark/Accumulator.h
new file mode 100644 (file)
index 0000000..ef3421a
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 benchmark.h
+ * @ingroup COM_AI_RUNTIME
+ * @brief This file contains benchmark::Accumulator class
+ */
+#ifndef __NNFW_BENCHMARK_ACCUMULATOR_H__
+#define __NNFW_BENCHMARK_ACCUMULATOR_H__
+
+#include <chrono>
+
+// Benckmark support
+namespace benchmark
+{
+
+/**
+ * @brief Class to accumulate time during benchmark
+ */
+template <typename T> class Accumulator
+{
+public:
+  /**
+   * @brief Construct a new Accumulator object
+   * @param[in] ref   Object to keep time duration
+   */
+  Accumulator(T &ref) : _ref(ref)
+  {
+    // DO NOTHING
+  }
+
+public:
+  /**
+   * @brief Return the reference of @c ref passed to constructor
+   * @return Reference of @c ref
+   */
+  T &operator()(void) { return _ref; }
+
+private:
+  T &_ref;
+};
+
+/**
+ * @brief Run passed function and returns accumulated time
+ * @tparam T            Period used by @c std::chrono::duration_cast
+ * @tparam Callable     Function type to benchmark
+ * @param[in] acc       Accumulated time after running @cb
+ * @param[in] cb        Function to run and benchmark
+ * @return Accumulated time
+ */
+template <typename T, typename Callable>
+Accumulator<T> &operator<<(Accumulator<T> &&acc, Callable cb)
+{
+  auto begin = std::chrono::high_resolution_clock::now();
+  cb();
+  auto end = std::chrono::high_resolution_clock::now();
+
+  acc() += std::chrono::duration_cast<T>(end - begin);
+
+  return acc;
+}
+
+template <typename T> Accumulator<T> measure(T &out) { return Accumulator<T>(out); }
+
+} // namespace benchmark
+
+#endif // __NNFW_BENCHMARK_ACCUMULATOR_H__
diff --git a/tests/libs/benchmark/include/benchmark/RandomGenerator.h b/tests/libs/benchmark/include/benchmark/RandomGenerator.h
new file mode 100644 (file)
index 0000000..b5e5a40
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file  RandomGenerator.h
+ * @brief This file contains classes for random value generation
+ */
+
+#ifndef __NNFW_BENCHMARK_RANDOM_GENERATOR_H__
+#define __NNFW_BENCHMARK_RANDOM_GENERATOR_H__
+
+#include "misc/tensor/Shape.h"
+#include "misc/tensor/Index.h"
+
+#include <random>
+
+namespace benchmark
+{
+
+/**
+ * @brief Class to generate random values
+ */
+class RandomGenerator
+{
+public:
+  /**
+   * @brief Construct a new RandomGenerator object
+   * @param[in] seed          Random seed value
+   * @param[in] mean          Mean value of normal random number generation
+   * @param[in] stddev        Standard deviation of random number generation
+   * @param[in] quantization  TfLiteQuantizationParams type to represent quantization value
+   *                          (not used yet)
+   */
+  RandomGenerator(uint32_t seed, float mean, float stddev) : _rand{seed}, _dist{mean, stddev}
+  {
+    // DO NOTHING
+  }
+
+public:
+  /**
+   * @brief  Generate random numbers for type T
+   * @param[in] s Shape value
+   * @param[in] i Index value
+   * @return Random generated value
+   * @note   This is same as T generate(void) as two input parameters are not used
+   */
+  template <typename T>
+  T generate(const ::nnfw::misc::tensor::Shape &, const ::nnfw::misc::tensor::Index &)
+  {
+    return generate<T>();
+  }
+
+  /**
+   * @brief  Generate random numbers for type T
+   * @return Random generated value
+   */
+  template <typename T> T generate(void) { return _dist(_rand); }
+
+private:
+  std::minstd_rand _rand;
+  std::normal_distribution<float> _dist;
+};
+
+template <> int8_t RandomGenerator::generate<int8_t>(void);
+template <> uint8_t RandomGenerator::generate<uint8_t>(void);
+template <> bool RandomGenerator::generate<bool>(void);
+template <> int32_t RandomGenerator::generate<int32_t>(void);
+template <> int64_t RandomGenerator::generate<int64_t>(void);
+
+} // namespace benchmark
+
+#endif // __NNFW_BENCHMARK_RANDOM_GENERATOR_H__
diff --git a/tests/libs/benchmark/src/RandomGenerator.cpp b/tests/libs/benchmark/src/RandomGenerator.cpp
new file mode 100644 (file)
index 0000000..19e9538
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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 "benchmark/RandomGenerator.h"
+
+namespace benchmark
+{
+
+template <> int8_t RandomGenerator::generate<int8_t>(void)
+{
+  // The value of type_range is 255.
+  float type_range = static_cast<float>(std::numeric_limits<int8_t>::max()) -
+                     static_cast<float>(std::numeric_limits<int8_t>::min());
+  // Most _dist values range from -5.0 to 5.0.
+  float min_range = -5.0f;
+  float max_range = 5.0f;
+  // NOTE shifted_relative_val has Gaussian distribution that origin mean was 0 and standard
+  // deviation was 2. And then its values are distributed and shift to that mean is 127.5 and range
+  // is about [0, 255].
+  float shifted_relative_val = (_dist(_rand) - min_range) * type_range / (max_range - min_range);
+
+  // shifted_relative_val is adjusted to be mapped to end points of the range, if it is out of range
+  // values.
+  if (shifted_relative_val < -128.0f)
+  {
+    return -128;
+  }
+  else if (shifted_relative_val > type_range)
+  {
+    return 127;
+  }
+
+  // Convert shifted_relative_val from float to int8
+  return static_cast<int8_t>(shifted_relative_val);
+}
+
+template <> uint8_t RandomGenerator::generate<uint8_t>(void)
+{
+  // The value of type_range is 255.
+  float type_range = static_cast<float>(std::numeric_limits<uint8_t>::max()) -
+                     static_cast<float>(std::numeric_limits<uint8_t>::min());
+  // Most _dist values range from -5.0 to 5.0.
+  float min_range = -5.0f;
+  float max_range = 5.0f;
+  // NOTE shifted_relative_val has Gaussian distribution that origin mean was 0 and standard
+  // deviation was 2. And then its values are distributed and shift to that mean is 127.5 and range
+  // is about [0, 255].
+  float shifted_relative_val = (_dist(_rand) - min_range) * type_range / (max_range - min_range);
+
+  // shifted_relative_val is adjusted to be mapped to end points of the range, if it is out of range
+  // values.
+  if (shifted_relative_val < 0.0f)
+  {
+    return 0;
+  }
+  else if (shifted_relative_val > type_range)
+  {
+    return 255;
+  }
+
+  // Convert shifted_relative_val from float to uint8
+  return static_cast<uint8_t>(shifted_relative_val);
+}
+
+template <> bool RandomGenerator::generate<bool>(void)
+{
+  std::uniform_int_distribution<> dist(0, 1); // [0, 1]
+  return dist(_rand);
+}
+
+template <> int32_t RandomGenerator::generate<int32_t>(void)
+{
+  // Instead of INT_MAX, 99 is chosen because int32_t input does not mean
+  // that the model can have any value in int32_t can hold.
+  // For example, one_hot operation gets indices as int32_t tensor.
+  // However, we usually expect it would hold a value in [0..depth).
+  // In our given model, depth was 10137.
+  const int int32_random_max = 99;
+  std::uniform_int_distribution<> dist(0, int32_random_max);
+  return dist(_rand);
+}
+
+template <> int64_t RandomGenerator::generate<int64_t>(void)
+{
+  // Instead of INT_MAX, 99 is chosen because int64_t input does not mean
+  // that the model can have any value in int64_t can hold.
+  // For example, one_hot operation gets indices as int64_t tensor.
+  // However, we usually expect it would hold a value in [0..depth).
+  // In our given model, depth was 10137.
+  const int64_t int64_random_max = 99;
+  std::uniform_int_distribution<> dist(0, int64_random_max);
+  return dist(_rand);
+}
+
+} // namespace benchmark
diff --git a/tests/libs/benchmark/src/Result.cpp b/tests/libs/benchmark/src/Result.cpp
new file mode 100644 (file)
index 0000000..05cbf38
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * 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 "benchmark/Result.h"
+#include "benchmark/Phases.h"
+#include "benchmark/CsvWriter.h"
+
+#include <string>
+#include <numeric>
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <iostream>
+#include <iomanip>
+
+namespace
+{
+
+template <class T, class R> R average(const std::vector<T> &v)
+{
+  T sum = std::accumulate(v.begin(), v.end(), 0);
+  R avg = sum / static_cast<R>(v.size());
+  return avg;
+}
+
+double averageTimeMs(const benchmark::Phase &phase)
+{
+  double avg_us = average<uint64_t, double>(phase.time);
+  return avg_us / 1e3;
+}
+
+double maxTimeMs(const benchmark::Phase &phase)
+{
+  auto it = max_element(std::begin(phase.time), std::end(phase.time));
+  return *it / 1e3;
+}
+
+double minTimeMs(const benchmark::Phase &phase)
+{
+  auto it = min_element(std::begin(phase.time), std::end(phase.time));
+  return *it / 1e3;
+}
+
+double geomeanTimeMs(const benchmark::Phase &phase)
+{
+  double log_sum = 0.0;
+  for (auto &&t_us : phase.time)
+  {
+    log_sum += std::log(t_us / 1e3);
+  }
+
+  // Calculating geometric mean with logs
+  //   "Geometric Mean of (V1, V2, ... Vn)"
+  // = (V1*V2*...*Vn)^(1/n)
+  // = exp(log((V1*V2*...*Vn)^(1/n)))
+  // = exp(log((V1*V2*...*Vn)/n)))
+  // = exp((log(V1) + log(V2) + ... + log(Vn))/n)
+  // = exp(_log_sum/num)
+  return std::exp(log_sum / static_cast<double>(phase.time.size()));
+}
+
+uint32_t averageMemoryKb(const benchmark::Phase &phase, int type)
+{
+  return average<uint32_t, uint32_t>(phase.memory[type]);
+}
+
+uint32_t peakMemory(
+  const uint32_t memory[benchmark::PhaseEnum::END_OF_PHASE][benchmark::MemoryType::END_OF_MEM_TYPE],
+  int type)
+{
+  using namespace benchmark;
+  // tricky. handle WARMUP as EXECUTE
+  return std::max({memory[PhaseEnum::MODEL_LOAD][type], memory[PhaseEnum::PREPARE][type],
+                   memory[PhaseEnum::WARMUP][type]});
+}
+
+void printResultTime(
+  const double time[benchmark::PhaseEnum::END_OF_PHASE][benchmark::FigureType::END_OF_FIG_TYPE])
+{
+  using namespace benchmark;
+
+  std::cout << "===================================" << std::endl;
+
+  std::streamsize ss_precision = std::cout.precision();
+  std::cout << std::setprecision(3);
+  std::cout << std::fixed;
+
+  for (int i = PhaseEnum::MODEL_LOAD; i <= PhaseEnum::EXECUTE; ++i)
+  {
+    // Note. Tricky. Ignore WARMUP
+    if (i == PhaseEnum::WARMUP)
+      continue;
+    std::cout << std::setw(12) << std::left << getPhaseString(i) << " takes "
+              << time[i][FigureType::MEAN] << " ms" << std::endl;
+  }
+
+  for (int j = FigureType::MEAN; j <= FigureType::GEOMEAN; ++j)
+  {
+    std::cout << "- " << std::setw(9) << std::left << getFigureTypeString(j) << ":  "
+              << time[PhaseEnum::EXECUTE][j] << " ms" << std::endl;
+  }
+
+  std::cout << std::setprecision(ss_precision);
+  std::cout << std::defaultfloat;
+
+  std::cout << "===================================" << std::endl;
+}
+
+void printResultMemory(
+  const uint32_t memory[benchmark::PhaseEnum::END_OF_PHASE][benchmark::MemoryType::END_OF_MEM_TYPE])
+{
+  using namespace benchmark;
+
+  for (int j = MemoryType::RSS; j <= MemoryType::PSS; ++j)
+  {
+    std::cout << getMemoryTypeString(j) << std::endl;
+    for (int i = PhaseEnum::MODEL_LOAD; i <= PhaseEnum::PREPARE; ++i)
+    {
+      std::cout << "- " << std::setw(12) << std::left << getPhaseString(i) << " takes "
+                << memory[i][j] << " kb" << std::endl;
+    }
+    // Tricky. Handle WARMUP as EXECUTE
+    std::cout << "- " << std::setw(12) << std::left << getPhaseString(PhaseEnum::EXECUTE)
+              << " takes " << memory[PhaseEnum::WARMUP][j] << " kb" << std::endl;
+    std::cout << "- " << std::setw(12) << std::left << "PEAK"
+              << " takes " << peakMemory(memory, j) << " kb" << std::endl;
+    std::cout << "===================================" << std::endl;
+  }
+}
+
+void printUsedPeakMemory(uint32_t init_memory, uint32_t peak_memory)
+{
+  uint32_t used_peak_memory = peak_memory - init_memory;
+  std::cout << "Used Peak Memory : " << used_peak_memory << " kb" << std::endl;
+  std::cout << "- HWM after run  : " << peak_memory << " kb" << std::endl;
+  std::cout << "- HWM before init: " << init_memory << " kb" << std::endl;
+  std::cout << "===================================" << std::endl;
+}
+
+} // namespace
+
+namespace benchmark
+{
+
+Result::Result(const Phases &phases)
+{
+  const auto &option = phases.option();
+  {
+    for (int i = PhaseEnum::MODEL_LOAD; i <= PhaseEnum::PREPARE; ++i)
+    {
+      const auto &phase = phases.at(gPhaseStrings[i]);
+      time[i][FigureType::MEAN] = averageTimeMs(phase);
+    }
+
+    int i = PhaseEnum::EXECUTE;
+    const auto &exec_phase = phases.at(gPhaseStrings[i]);
+    time[i][FigureType::MEAN] = averageTimeMs(exec_phase);
+    time[i][FigureType::MAX] = maxTimeMs(exec_phase);
+    time[i][FigureType::MIN] = minTimeMs(exec_phase);
+    time[i][FigureType::GEOMEAN] = geomeanTimeMs(exec_phase);
+  }
+  if (option.memory)
+  {
+    print_memory = true;
+    for (int i = PhaseEnum::MODEL_LOAD; i < PhaseEnum::EXECUTE; ++i)
+    {
+      const auto &phase = phases.at(gPhaseStrings[i]);
+      for (int j = MemoryType::RSS; j <= MemoryType::PSS; ++j)
+      {
+        memory[i][j] = averageMemoryKb(phase, j);
+      }
+    }
+  }
+  init_memory = phases.mem_before_init();
+  peak_memory = phases.mem_after_run();
+}
+
+void printResult(const Result &result)
+{
+  printResultTime(result.time);
+
+  if (result.print_memory == false)
+    return;
+
+  printResultMemory(result.memory);
+  printUsedPeakMemory(result.init_memory, result.peak_memory);
+}
+
+// TODO There are necessary for a kind of output data file so that it doesn't have to be csv file
+// format.
+void writeResult(const Result &result, const std::string &exec, const std::string &model,
+                 const std::string &backend)
+{
+  std::string csv_filename = exec + "-" + model + "-" + backend + ".csv";
+
+  // write to csv
+  CsvWriter writer(csv_filename);
+  writer << model << backend;
+
+  // TODO Add GEOMEAN
+  // time
+  auto time = result.time;
+  writer << time[PhaseEnum::MODEL_LOAD][FigureType::MEAN]
+         << time[PhaseEnum::PREPARE][FigureType::MEAN] << time[PhaseEnum::EXECUTE][FigureType::MIN]
+         << time[PhaseEnum::EXECUTE][FigureType::MAX] << time[PhaseEnum::EXECUTE][FigureType::MEAN];
+
+  // memory
+  auto memory = result.memory;
+  for (int j = MemoryType::RSS; j <= MemoryType::PSS; ++j)
+  {
+    // Tricky. Handle WARMUP as EXECUTE
+    for (int i = PhaseEnum::MODEL_LOAD; i <= PhaseEnum::WARMUP; ++i)
+    {
+      writer << memory[i][j];
+    }
+    writer << peakMemory(memory, j);
+  }
+
+  bool done = writer.done();
+
+  if (!done)
+  {
+    std::cerr << "Writing to " << csv_filename << " is failed" << std::endl;
+  }
+}
+
+} // namespace benchmark
diff --git a/tests/libs/tflite/CMakeLists.txt b/tests/libs/tflite/CMakeLists.txt
new file mode 100644 (file)
index 0000000..4898dd1
--- /dev/null
@@ -0,0 +1,24 @@
+nnfw_find_package(TensorFlowLite EXACT 2.16.1 QUIET)
+if(NOT TensorFlowLite_FOUND)
+  message(STATUS "Check tensorflow lite library extension build: need tensorflow lite library")
+  return()
+endif(NOT TensorFlowLite_FOUND)
+
+file(GLOB_RECURSE SOURCES "src/*.cpp")
+file(GLOB_RECURSE TESTS "src/*.test.cpp")
+list(REMOVE_ITEM SOURCES ${TESTS})
+
+add_library(nnfw_lib_tflite STATIC ${SOURCES})
+set_target_properties(nnfw_lib_tflite PROPERTIES POSITION_INDEPENDENT_CODE ON)
+target_include_directories(nnfw_lib_tflite PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
+target_link_libraries(nnfw_lib_tflite PUBLIC tensorflow-lite-2.16.1)
+target_link_libraries(nnfw_lib_tflite PUBLIC nnfw_lib_misc nnfw_lib_benchmark)
+target_link_libraries(nnfw_lib_tflite PRIVATE ${LIB_PTHREAD} dl)
+target_link_libraries(nnfw_lib_tflite PRIVATE nnfw_common)
+
+if(NOT ENABLE_TEST)
+  return()
+endif(NOT ENABLE_TEST)
+
+add_executable(nnfw_lib_tflite_test_TensorView src/TensorView.test.cpp)
+target_link_libraries(nnfw_lib_tflite_test_TensorView nnfw_lib_tflite)
diff --git a/tests/libs/tflite/include/tflite/Diff.h b/tests/libs/tflite/include/tflite/Diff.h
new file mode 100644 (file)
index 0000000..adcd959
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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     Diff.h
+ * @brief    This file contains classes for testing correctess of implementation
+ * @ingroup  COM_AI_RUNTIME
+ */
+
+#ifndef __NNFW_TFLITE_DIFF_H__
+#define __NNFW_TFLITE_DIFF_H__
+
+#include "TensorView.h"
+
+#include "misc/tensor/Index.h"
+#include "misc/tensor/Diff.h"
+#include "misc/tensor/Shape.h"
+#include "misc/tensor/Comparator.h"
+
+#include <tensorflow/lite/c/c_api.h>
+
+namespace nnfw
+{
+namespace tflite
+{
+
+/**
+ * @brief Class to define TfLite interpreter match application
+ */
+class TfLiteInterpMatchApp
+{
+public:
+  /**
+   * @brief Construct a new TfLiteInterpMatchApp object with Comparator
+   * @param[in] comparator   Comparator object for tensor comparation
+   */
+  TfLiteInterpMatchApp(const nnfw::misc::tensor::Comparator &comparator)
+    : _verbose{false}, _comparator(comparator)
+  {
+    // DO NOTHING
+  }
+
+public:
+  /**
+   * @brief Get reference verbose for debugging information
+   * @return Reference of verbose value
+   */
+  int &verbose(void) { return _verbose; }
+
+private:
+  int _verbose;
+
+public:
+  /**
+   * @brief Run two interpreter and return the output matching
+   * @param[in] expected    Interpreter object of expected
+   * @param[in] obtained  Interpreter object of obtained
+   * @return  @c true if two Interpreter results are same, otherwise @c false
+   */
+  bool run(TfLiteInterpreter &expected, TfLiteInterpreter &obtained) const;
+  /**
+   * @brief Compare two TensorView values and return the match result
+   * @param[in] expected  TensorView object to read expected values
+   * @param[in] obtained  TensorView object to read obtained values
+   * @param[in] id        Tensor ID value used for debug message
+   * @return  @c true if two TensorView values are same, otherwise @c false
+   */
+  template <typename T>
+  bool compareSingleTensorView(const TensorView<T> &expected, const TensorView<T> &obtained,
+                               int id) const;
+
+private:
+  const nnfw::misc::tensor::Comparator &_comparator;
+};
+
+} // namespace tflite
+} // namespace nnfw
+
+#endif // __NNFW_TFLITE_DIFF_H__
diff --git a/tests/libs/tflite/include/tflite/InterpreterSession.h b/tests/libs/tflite/include/tflite/InterpreterSession.h
new file mode 100644 (file)
index 0000000..0776fc1
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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     InterpreterSession.h
+ * @brief    This file contains InterpreterSession class
+ * @ingroup  COM_AI_RUNTIME
+ */
+
+#ifndef __NNFW_TFLITE_INTERPRETER_SESSION_H__
+#define __NNFW_TFLITE_INTERPRETER_SESSION_H__
+
+#include "Session.h"
+
+#include <tensorflow/lite/c/c_api.h>
+
+namespace nnfw
+{
+namespace tflite
+{
+
+/**
+ * @brief Class to define TfLite interpreter session which is inherited from Session class
+ */
+class InterpreterSession final : public Session
+{
+public:
+  /**
+   * @brief Construct a InterpreterSession object with interpreter of TfLite
+   * @param[in] interp The TfLite interpreter pointer
+   */
+  InterpreterSession(TfLiteInterpreter *interp) : _interp{interp}
+  {
+    // DO NOTHING
+  }
+
+public:
+  /**
+   * @brief Get TfLite interpreter pointer
+   * @return The TfLite interpreter
+   */
+  TfLiteInterpreter *interp(void) override { return _interp; }
+
+public:
+  /**
+   * @brief Prepare the TfLite interpreter session
+   * @return @c true if tensor preparation is successful, otherwise @c false
+   */
+  bool prepare(void) override
+  {
+    if (kTfLiteOk != TfLiteInterpreterAllocateTensors(_interp))
+    {
+      return false;
+    }
+
+    return true;
+  }
+
+  /**
+   * @brief Run the Invoke function of TfLite interpreter
+   * @return @c true if Invoke() is successful, otherwise @c false
+   */
+  bool run(void) override
+  {
+    // Return true if Invoke returns kTfLiteOk
+    return kTfLiteOk == TfLiteInterpreterInvoke(_interp);
+  }
+
+  /**
+   * @brief Tear down TfLite interpreter session
+   * @return @c true always
+   */
+  bool teardown(void) override
+  {
+    // Do NOTHING currently
+    return true;
+  }
+
+private:
+  TfLiteInterpreter *const _interp;
+};
+
+} // namespace tflite
+} // namespace nnfw
+
+#endif // __NNFW_TFLITE_INTERPRETER_SESSION_H__
diff --git a/tests/libs/tflite/include/tflite/RandomInputInitializer.h b/tests/libs/tflite/include/tflite/RandomInputInitializer.h
new file mode 100644 (file)
index 0000000..0bf6a47
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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 __NNFW_TFLITE_RANDOM_INPUT_INITIALIZER_H__
+#define __NNFW_TFLITE_RANDOM_INPUT_INITIALIZER_H__
+
+#include <benchmark/RandomGenerator.h>
+
+#include <tensorflow/lite/c/c_api.h>
+
+namespace nnfw
+{
+namespace tflite
+{
+
+class RandomInputInitializer
+{
+public:
+  RandomInputInitializer(benchmark::RandomGenerator &randgen) : _randgen{randgen}
+  {
+    // DO NOTHING
+  }
+
+  void run(TfLiteInterpreter &interp);
+
+private:
+  benchmark::RandomGenerator &_randgen;
+};
+
+} // namespace tflite
+} // namespace nnfw
+
+#endif // __NNFW_TFLITE_RANDOM_INPUT_INITIALIZER_H__
diff --git a/tests/libs/tflite/src/Diff.cpp b/tests/libs/tflite/src/Diff.cpp
new file mode 100644 (file)
index 0000000..809ad6f
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "tflite/Diff.h"
+
+#include "misc/fp32.h"
+#include "misc/tensor/Comparator.h"
+#include "misc/tensor/IndexFormatter.h"
+#include "misc/tensor/Zipper.h"
+
+#include <tensorflow/lite/c/c_api.h>
+
+#include <cassert>
+#include <cmath>
+#include <functional>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+
+namespace
+{
+
+class DiffSummary : public nnfw::misc::tensor::Comparator::Observer
+{
+public:
+  DiffSummary()
+    : max_abs_diff_index(0), max_abs_diff_expected{0.0f}, max_abs_diff_obtained{0.0f},
+      max_abs_diff_value{0.0f}, max_rel_diff_index(0), max_rel_diff_expected{0.0f},
+      max_rel_diff_obtained{0.0f}, max_rel_diff_value{0.0f}
+  {
+    // DO NOTHING
+  }
+
+public:
+  void notify(const nnfw::misc::tensor::Index &index, float expected, float obtained) override;
+
+public:
+  nnfw::misc::tensor::Index max_abs_diff_index;
+  float max_abs_diff_expected;
+  float max_abs_diff_obtained;
+  float max_abs_diff_value;
+
+  nnfw::misc::tensor::Index max_rel_diff_index;
+  float max_rel_diff_expected;
+  float max_rel_diff_obtained;
+  float max_rel_diff_value;
+};
+
+void DiffSummary::notify(const nnfw::misc::tensor::Index &index, float expected, float obtained)
+{
+  const auto abs_diff_value = std::fabs(expected - obtained);
+
+  if (max_abs_diff_value < abs_diff_value)
+  {
+    max_abs_diff_index = index;
+    max_abs_diff_value = abs_diff_value;
+    max_abs_diff_expected = expected;
+    max_abs_diff_obtained = obtained;
+  }
+
+  const auto rel_diff_value = nnfw::misc::fp32::relative_diff(expected, obtained);
+
+  if (max_rel_diff_value < rel_diff_value)
+  {
+    max_rel_diff_index = index;
+    max_rel_diff_value = rel_diff_value;
+    max_rel_diff_expected = expected;
+    max_rel_diff_obtained = obtained;
+  }
+}
+
+} // namespace
+
+namespace nnfw
+{
+namespace tflite
+{
+
+template <typename T>
+bool TfLiteInterpMatchApp::compareSingleTensorView(const TensorView<T> &expected,
+                                                   const TensorView<T> &obtained, int id) const
+{
+  std::vector<misc::tensor::Diff<T>> diffs;
+  assert(expected.shape() == obtained.shape());
+
+  using nnfw::misc::tensor::Index;
+  using nnfw::misc::tensor::zip;
+
+  zip(expected.shape(), expected, obtained)
+    << [&](const Index &index, T expected_value, T obtained_value) {
+         if (expected_value != obtained_value)
+         {
+           diffs.emplace_back(index, expected_value, obtained_value);
+         }
+       };
+
+  // TODO Unify summary generation code
+  if (diffs.size() == 0)
+  {
+    std::cout << "  Tensor #" << id << ": MATCHED" << std::endl;
+  }
+  else
+  {
+    std::cout << "  Tensor #" << id << ": UNMATCHED" << std::endl;
+    std::cout << "    " << diffs.size() << " diffs are detected" << std::endl;
+  }
+
+  if (diffs.size() > 0 && _verbose != 0)
+  {
+    std::cout << "    ---- Details ---" << std::endl;
+    for (const auto &diff : diffs)
+    {
+      std::cout << "    Diff at [" << nnfw::misc::tensor::IndexFormatter(diff.index) << "]"
+                << std::endl;
+      std::cout << "      expected: " << diff.expected << std::endl;
+      std::cout << "      obtained: " << diff.obtained << std::endl;
+    }
+  }
+
+  return diffs.size() == 0;
+}
+
+template <>
+bool TfLiteInterpMatchApp::compareSingleTensorView<float>(const TensorView<float> &expected,
+                                                          const TensorView<float> &obtained,
+                                                          int id) const
+{
+  DiffSummary summary;
+
+  assert(expected.shape() == obtained.shape());
+  auto diffs = _comparator.compare(expected.shape(), expected, obtained, &summary);
+
+  // TODO Unify summary generation code
+  if (diffs.size() == 0)
+  {
+    std::cout << "  Tensor #" << id << ": MATCHED" << std::endl;
+  }
+  else
+  {
+    std::cout << "  Tensor #" << id << ": UNMATCHED" << std::endl;
+    std::cout << "    " << diffs.size() << " diffs are detected" << std::endl;
+  }
+
+  // Print out max_diff
+  if (summary.max_abs_diff_value > 0)
+  {
+    std::cout << "    Max absolute diff at ["
+              << nnfw::misc::tensor::IndexFormatter(summary.max_abs_diff_index) << "]" << std::endl;
+    std::cout << "       expected: " << summary.max_abs_diff_expected << std::endl;
+    std::cout << "       obtained: " << summary.max_abs_diff_obtained << std::endl;
+    std::cout << "       absolute diff: " << summary.max_abs_diff_value << std::endl;
+  }
+
+  if (summary.max_rel_diff_value > 0)
+  {
+    const auto tolerance_level = summary.max_rel_diff_value / FLT_EPSILON;
+
+    std::cout << "    Max relative diff at ["
+              << nnfw::misc::tensor::IndexFormatter(summary.max_rel_diff_index) << "]" << std::endl;
+    std::cout << "       expected: " << summary.max_rel_diff_expected << std::endl;
+    std::cout << "       obtained: " << summary.max_rel_diff_obtained << std::endl;
+    std::cout << "       relative diff: " << summary.max_rel_diff_value << std::endl;
+    std::cout << "         (tolerance level = " << tolerance_level << ")" << std::endl;
+  }
+
+  if (diffs.size() > 0)
+  {
+    if (_verbose != 0)
+    {
+      std::cout << "    ---- Details ---" << std::endl;
+      for (const auto &diff : diffs)
+      {
+        const auto absolute_diff = std::fabs(diff.expected - diff.obtained);
+        const auto relative_diff = nnfw::misc::fp32::relative_diff(diff.expected, diff.obtained);
+        const auto tolerance_level = relative_diff / FLT_EPSILON;
+
+        std::cout << "    Diff at [" << nnfw::misc::tensor::IndexFormatter(diff.index) << "]"
+                  << std::endl;
+        std::cout << "      expected: " << diff.expected << std::endl;
+        std::cout << "      obtained: " << diff.obtained << std::endl;
+        std::cout << "      absolute diff: " << absolute_diff << std::endl;
+        std::cout << "      relative diff: " << relative_diff << std::endl;
+        std::cout << "         (tolerance level = " << tolerance_level << ")" << std::endl;
+      }
+    }
+
+    return false;
+  }
+  return true;
+}
+
+bool TfLiteInterpMatchApp::run(TfLiteInterpreter &expected, TfLiteInterpreter &obtained) const
+{
+  auto output_count = TfLiteInterpreterGetOutputTensorCount(&expected);
+  assert(output_count == TfLiteInterpreterGetOutputTensorCount(&obtained));
+
+  bool all_matched = true;
+
+  using Comparator = std::function<bool(int32_t, const TfLiteTensor *, const TfLiteTensor *)>;
+
+  std::map<TfLiteType, Comparator> comparators;
+
+  comparators[kTfLiteUInt8] = [this](int32_t id, const TfLiteTensor *expected_tensor,
+                                     const TfLiteTensor *obtained_tensor) {
+    const auto expected_view = TensorView<uint8_t>::make(expected_tensor);
+    const auto obtained_view = TensorView<uint8_t>::make(obtained_tensor);
+
+    return compareSingleTensorView(expected_view, obtained_view, id);
+  };
+
+  comparators[kTfLiteInt32] = [this](int32_t id, const TfLiteTensor *expected_tensor,
+                                     const TfLiteTensor *obtained_tensor) {
+    const auto expected_view = TensorView<int32_t>::make(expected_tensor);
+    const auto obtained_view = TensorView<int32_t>::make(obtained_tensor);
+
+    return compareSingleTensorView(expected_view, obtained_view, id);
+  };
+
+  comparators[kTfLiteFloat32] = [this](int32_t id, const TfLiteTensor *expected_tensor,
+                                       const TfLiteTensor *obtained_tensor) {
+    const auto expected_view = TensorView<float>::make(expected_tensor);
+    const auto obtained_view = TensorView<float>::make(obtained_tensor);
+
+    return compareSingleTensorView(expected_view, obtained_view, id);
+  };
+
+  comparators[kTfLiteBool] = [this](int32_t id, const TfLiteTensor *expected_tensor,
+                                    const TfLiteTensor *obtained_tensor) {
+    const auto expected_view = TensorView<bool>::make(expected_tensor);
+    const auto obtained_view = TensorView<bool>::make(obtained_tensor);
+
+    return compareSingleTensorView(expected_view, obtained_view, id);
+  };
+
+  for (int32_t idx = 0; idx < output_count; idx++)
+  {
+    auto const expected_tensor = TfLiteInterpreterGetOutputTensor(&expected, idx);
+    auto const obtained_tensor = TfLiteInterpreterGetOutputTensor(&obtained, idx);
+    auto const tensor_type = TfLiteTensorType(expected_tensor);
+    assert(tensor_type == TfLiteTensorType(obtained_tensor));
+
+    auto it = comparators.find(tensor_type);
+
+    if (it == comparators.end())
+    {
+      throw std::runtime_error{"Not supported output type"};
+    }
+
+    const auto &comparator = it->second;
+
+    if (!comparator(idx, expected_tensor, obtained_tensor))
+    {
+      all_matched = false;
+    }
+  }
+
+  return all_matched;
+}
+
+} // namespace tflite
+} // namespace nnfw
diff --git a/tests/libs/tflite/src/RandomInputInitializer.cpp b/tests/libs/tflite/src/RandomInputInitializer.cpp
new file mode 100644 (file)
index 0000000..53a93b9
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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 "tflite/RandomInputInitializer.h"
+#include "tflite/TensorView.h"
+
+#include <misc/tensor/IndexIterator.h>
+
+namespace nnfw
+{
+namespace tflite
+{
+namespace
+{
+
+template <typename T> void setValue(benchmark::RandomGenerator &randgen, const TfLiteTensor *tensor)
+{
+  auto tensor_view = TensorView<T>::make(tensor);
+
+  nnfw::misc::tensor::iterate(tensor_view.shape())
+    << [&](const nnfw::misc::tensor::Index &ind) { tensor_view.at(ind) = randgen.generate<T>(); };
+}
+
+} // namespace
+
+void RandomInputInitializer::run(TfLiteInterpreter &interp)
+{
+  const auto input_count = TfLiteInterpreterGetInputTensorCount(&interp);
+  for (int32_t idx = 0; idx < input_count; idx++)
+  {
+    auto tensor = TfLiteInterpreterGetInputTensor(&interp, idx);
+    auto const tensor_type = TfLiteTensorType(tensor);
+    switch (tensor_type)
+    {
+      case kTfLiteFloat32:
+        setValue<float>(_randgen, tensor);
+        break;
+      case kTfLiteInt32:
+        setValue<int32_t>(_randgen, tensor);
+        break;
+      case kTfLiteUInt8:
+        setValue<uint8_t>(_randgen, tensor);
+        break;
+      case kTfLiteBool:
+        setValue<bool>(_randgen, tensor);
+        break;
+      case kTfLiteInt8:
+        setValue<int8_t>(_randgen, tensor);
+        break;
+      default:
+        throw std::runtime_error{"Not supported input type"};
+    }
+  }
+}
+
+} // namespace tflite
+} // namespace nnfw
index 80c3cce..b7f9dcc 100644 (file)
@@ -9,9 +9,6 @@ endif(NOT BUILD_ONERT)
 
 nnfw_find_package(GTest)
 
-# NNAPI gtest requires c++17
-set(CMAKE_CXX_STANDARD 17)
-
 set(GENERATED_CPPS "${CMAKE_CURRENT_SOURCE_DIR}/src/generated/all_generated_V1_2_cts_tests.cpp"
                    "${CMAKE_CURRENT_SOURCE_DIR}/src/generated/all_generated_V1_1_cts_tests.cpp"
                    "${CMAKE_CURRENT_SOURCE_DIR}/src/generated/all_generated_V1_0_cts_tests.cpp"
index 93cc980..887ee9b 100644 (file)
@@ -10,9 +10,10 @@ endif(NOT BUILD_ONERT)
 nnfw_find_package(GTest)
 
 set(RUNTIME_NNFW_API_TEST nnfw_api_gtest)
-file(GLOB_RECURSE RUNTIME_NNFW_API_TEST_SRC "src/*.cc" "src/*.cpp")
+file(GLOB_RECURSE RUNTIME_NNFW_API_TEST_LIB "lib/*.cc" "lib/*.cpp")
+file(GLOB_RECURSE RUNTIME_NNFW_API_TEST_SRC "main.cc" "src/*.test.cc" "src/*.test.cpp")
 
-add_executable(${RUNTIME_NNFW_API_TEST} ${RUNTIME_NNFW_API_TEST_SRC})
+add_executable(${RUNTIME_NNFW_API_TEST} ${RUNTIME_NNFW_API_TEST_LIB} ${RUNTIME_NNFW_API_TEST_SRC})
 
 nnfw_find_package(ARMCompute QUIET)
 if(ARMCompute_FOUND)
@@ -29,8 +30,7 @@ if(Opencl_Headers_FOUND)
   target_compile_definitions(${RUNTIME_NNFW_API_TEST} PRIVATE TEST_GPU_CL_BACKEND)
 endif(Opencl_Headers_FOUND)
 
-set(RUNTIME_NNFW_API_TEST_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/include
-                                  ${CMAKE_CURRENT_SOURCE_DIR}/src)
+set(RUNTIME_NNFW_API_TEST_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/lib ${CMAKE_CURRENT_SOURCE_DIR}/src)
 target_include_directories(${RUNTIME_NNFW_API_TEST} PRIVATE ${RUNTIME_NNFW_API_TEST_INCLUDE})
 
 target_link_libraries(${RUNTIME_NNFW_API_TEST} nnfw-dev jsoncpp)
@@ -65,4 +65,3 @@ install(DIRECTORY ${NNPACKAGE_MODEL_DIR} DESTINATION ${NNPACKAGE_INSTALL_TARGET}
 # Install nnpackage test model (mobilenet)
 set(NNPACKAGE_MODEL_DIR ${NNAS_PROJECT_SOURCE_DIR}/runtime/contrib/TFLiteSharp/TFLiteTestApp/res/)
 install(DIRECTORY ${NNPACKAGE_MODEL_DIR} DESTINATION ${NNPACKAGE_INSTALL_TARGET}/mobilenet_v1_1.0_224)
-
diff --git a/tests/nnfw_api/lib/CircleGen.cc b/tests/nnfw_api/lib/CircleGen.cc
new file mode 100644 (file)
index 0000000..f8cd20e
--- /dev/null
@@ -0,0 +1,730 @@
+/*
+ * 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 "CircleGen.h"
+#include "flatbuffers/flexbuffers.h"
+
+CircleGen::CircleGen() : _subgraph_contexts(1) // Create primary subgraph
+{
+  // 0th buffer is always the empty buffer for non-const tensors
+  addBuffer(nullptr, 0);
+}
+
+template <typename T> uint32_t addBuffer(const std::vector<T> &buf_vec)
+{
+  auto buf = reinterpret_cast<const uint8_t *>(buf_vec.data());
+  auto size = buf_vec.size() * sizeof(T);
+  return addBuffer(buf, size);
+}
+
+uint32_t CircleGen::addBuffer(const uint8_t *buf, size_t size)
+{
+  uint32_t ind = _buffers.size();
+  _buffers.emplace_back(buildBuffer(buf, size));
+  return ind;
+}
+
+uint32_t CircleGen::addTensor(const TensorParams &params)
+{
+  uint32_t ind = curSubgCtx().tensors.size();
+  curSubgCtx().tensors.emplace_back(buildTensor(params));
+  return ind;
+}
+
+uint32_t CircleGen::addTensor(const TensorParams &params, float scale, int64_t zero_point)
+{
+  // TensorType_INT8: scale >= 0, zero_point: [-128, 127]
+  // TensorType_UINT8: scale >= 0, zero_point: [0, 255]
+  uint32_t ind = curSubgCtx().tensors.size();
+  curSubgCtx().tensors.emplace_back(buildTensor(params, scale, zero_point));
+  return ind;
+}
+
+uint32_t CircleGen::addTensor(const TensorParams &params, std::vector<float> &scale,
+                              std::vector<int64_t> &zero_point)
+{
+  uint32_t ind = curSubgCtx().tensors.size();
+  curSubgCtx().tensors.emplace_back(buildTensor(params, scale, zero_point));
+  return ind;
+}
+
+uint32_t CircleGen::addTensor(const TensorParams &params, const SparsityParams &sp)
+{
+  uint32_t ind = curSubgCtx().tensors.size();
+  curSubgCtx().tensors.emplace_back(buildTensor(params, sp));
+  return ind;
+}
+
+void CircleGen::setInputsAndOutputs(const std::vector<int> &inputs, const std::vector<int> &outputs)
+{
+  curSubgCtx().inputs = inputs;
+  curSubgCtx().outputs = outputs;
+}
+
+uint32_t CircleGen::nextSubgraph()
+{
+  uint32_t ind = _subgraph_contexts.size();
+  _subgraph_contexts.push_back({});
+  return ind;
+}
+
+uint32_t CircleGen::getCurrentSubgraphOpsSize() const
+{
+  return _subgraph_contexts.back().operators.size();
+}
+
+CircleBuffer CircleGen::finish()
+{
+  std::vector<flatbuffers::Offset<circle::SubGraph>> subgraphs;
+  for (auto &ctx : _subgraph_contexts)
+    subgraphs.push_back(buildSubGraph(ctx));
+  auto model =
+    circle::CreateModelDirect(_fbb, 3, &_opcodes, &subgraphs, "CircleGen generated", &_buffers);
+  _fbb.Finish(model);
+  return CircleBuffer{std::move(_fbb)};
+}
+
+// ===== Add Operator methods begin =====
+
+uint32_t CircleGen::addOperatorAdd(const OperatorParams &params,
+                                   circle::ActivationFunctionType actfn)
+{
+  auto options = circle::CreateAddOptions(_fbb, actfn).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_ADD,
+                                circle::BuiltinOptions_AddOptions, options);
+}
+
+uint32_t CircleGen::addOperatorAddN(const OperatorParams &params)
+{
+  auto options = circle::CreateAddNOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_ADD_N,
+                                circle::BuiltinOptions_AddNOptions, options);
+}
+
+uint32_t CircleGen::addOperatorArgMax(const OperatorParams &params, circle::TensorType output_type)
+{
+  auto options = circle::CreateArgMaxOptions(_fbb, output_type).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_ARG_MAX,
+                                circle::BuiltinOptions_ArgMaxOptions, options);
+}
+
+uint32_t CircleGen::addOperatorArgMin(const OperatorParams &params, circle::TensorType output_type)
+{
+  auto options = circle::CreateArgMaxOptions(_fbb, output_type).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_ARG_MIN,
+                                circle::BuiltinOptions_ArgMinOptions, options);
+}
+
+uint32_t CircleGen::addOperatorAveragePool2D(const OperatorParams &params, circle::Padding padding,
+                                             int stride_w, int stride_h, int filter_w, int filter_h,
+                                             circle::ActivationFunctionType actfn)
+{
+  auto options =
+    circle::CreatePool2DOptions(_fbb, padding, stride_w, stride_h, filter_w, filter_h, actfn)
+      .Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_AVERAGE_POOL_2D,
+                                circle::BuiltinOptions_Pool2DOptions, options);
+}
+
+uint32_t CircleGen::addOperatorCast(const OperatorParams &params, circle::TensorType input_type,
+                                    circle::TensorType output_type)
+{
+  auto options = circle::CreateCastOptions(_fbb, input_type, output_type).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_CAST,
+                                circle::BuiltinOptions_AddOptions, options);
+}
+
+uint32_t CircleGen::addOperatorConcatenation(const OperatorParams &params, int axis,
+                                             circle::ActivationFunctionType actfn)
+{
+  auto options = circle::CreateConcatenationOptions(_fbb, axis, actfn).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_CONCATENATION,
+                                circle::BuiltinOptions_ConcatenationOptions, options);
+}
+
+uint32_t CircleGen::addOperatorConv2D(const OperatorParams &params, circle::Padding padding,
+                                      int stride_w, int stride_h,
+                                      circle::ActivationFunctionType actfn, int dilation_w,
+                                      int dilation_h)
+{
+  auto options =
+    circle::CreateConv2DOptions(_fbb, padding, stride_w, stride_h, actfn, dilation_w, dilation_h)
+      .Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_CONV_2D,
+                                circle::BuiltinOptions_Conv2DOptions, options);
+}
+
+uint32_t CircleGen::addOperatorCos(const OperatorParams &params)
+{
+  auto options = circle::CreateCosOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_COS,
+                                circle::BuiltinOptions_CosOptions, options);
+}
+
+uint32_t CircleGen::addOperatorDepthToSpace(const OperatorParams &params, int32_t block_size)
+{
+  auto options = circle::CreateDepthToSpaceOptions(_fbb, block_size).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_DEPTH_TO_SPACE,
+                                circle::BuiltinOptions_DepthToSpaceOptions, options);
+}
+
+uint32_t CircleGen::addOperatorDepthwiseConv2D(const OperatorParams &params,
+                                               circle::Padding padding, int stride_w, int stride_h,
+                                               int depth_multiplier,
+                                               circle::ActivationFunctionType actfn, int dilation_w,
+                                               int dilation_h)
+{
+  auto options =
+    circle::CreateDepthwiseConv2DOptions(_fbb, padding, stride_w, stride_h, depth_multiplier, actfn,
+                                         dilation_w, dilation_h)
+      .Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_DEPTHWISE_CONV_2D,
+                                circle::BuiltinOptions_DepthwiseConv2DOptions, options);
+}
+
+uint32_t CircleGen::addOperatorDetectionPostProcess(const OperatorParams &params, int num_classes,
+                                                    float y_scale, float x_scale, float h_scale,
+                                                    float w_scale, float nms_score_threshold,
+                                                    float nms_iou_threshold, int max_detections,
+                                                    int max_classes_per_detection,
+                                                    int detections_per_class)
+{
+  // flexbuffer custom_option
+  auto flex_buffers = std::make_unique<flexbuffers::Builder>();
+  size_t map_start = flex_buffers->StartMap();
+  flex_buffers->Int("num_classes", num_classes);
+  flex_buffers->Float("y_scale", y_scale);
+  flex_buffers->Float("x_scale", x_scale);
+  flex_buffers->Float("h_scale", h_scale);
+  flex_buffers->Float("w_scale", w_scale);
+  flex_buffers->Float("nms_iou_threshold", nms_iou_threshold);
+  flex_buffers->Float("nms_score_threshold", nms_score_threshold);
+  flex_buffers->Int("max_detections", max_detections);
+  flex_buffers->Int("max_classes_per_detection", max_classes_per_detection);
+  flex_buffers->Int("detections_per_class", detections_per_class);
+  flex_buffers->EndMap(map_start);
+  flex_buffers->Finish();
+
+  return addCustomOperatorWithOptions(params, "TFLite_Detection_PostProcess",
+                                      circle::BuiltinOptions_NONE, 0, &flex_buffers->GetBuffer(),
+                                      circle::CustomOptionsFormat::CustomOptionsFormat_FLEXBUFFERS,
+                                      nullptr, nullptr);
+}
+
+uint32_t CircleGen::addOperatorElu(const OperatorParams &params)
+{
+  return addOperatorWithOptions(params, circle::BuiltinOperator_ELU, circle::BuiltinOptions_NONE,
+                                0);
+}
+
+uint32_t CircleGen::addOperatorEqual(const OperatorParams &params)
+{
+  auto options = circle::CreateEqualOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_EQUAL,
+                                circle::BuiltinOptions_EqualOptions, options);
+}
+
+uint32_t CircleGen::addOperatorExpandDims(const OperatorParams &params)
+{
+  auto options = circle::CreateEqualOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_EXPAND_DIMS,
+                                circle::BuiltinOptions_ExpandDimsOptions, options);
+}
+
+uint32_t
+CircleGen::addOperatorFullyConnected(const OperatorParams &params,
+                                     circle::FullyConnectedOptionsWeightsFormat weights_format)
+{
+  auto options =
+    circle::CreateFullyConnectedOptions(_fbb, circle::ActivationFunctionType_NONE, weights_format)
+      .Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_FULLY_CONNECTED,
+                                circle::BuiltinOptions_FullyConnectedOptions, options);
+}
+
+uint32_t CircleGen::addOperatorFill(const OperatorParams &params)
+{
+  auto options = circle::CreateFillOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_FILL,
+                                circle::BuiltinOptions_FillOptions, options);
+}
+
+uint32_t CircleGen::addOperatorFloor(const OperatorParams &params)
+{
+  return addOperatorWithOptions(params, circle::BuiltinOperator_FLOOR, circle::BuiltinOptions_NONE,
+                                0);
+}
+
+uint32_t CircleGen::addOperatorFloorDiv(const OperatorParams &params)
+{
+  return addOperatorWithOptions(params, circle::BuiltinOperator_FLOOR_DIV,
+                                circle::BuiltinOptions_NONE, 0);
+}
+
+uint32_t CircleGen::addOperatorFloorMod(const OperatorParams &params)
+{
+  return addOperatorWithOptions(params, circle::BuiltinOperator_FLOOR_MOD,
+                                circle::BuiltinOptions_NONE, 0);
+}
+
+uint32_t CircleGen::addOperatorGreater(const OperatorParams &params)
+{
+  auto options = circle::CreateLessOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_GREATER,
+                                circle::BuiltinOptions_GreaterOptions, options);
+}
+
+uint32_t CircleGen::addOperatorGreaterEqual(const OperatorParams &params)
+{
+  auto options = circle::CreateGreaterOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_GREATER_EQUAL,
+                                circle::BuiltinOptions_GreaterEqualOptions, options);
+}
+
+uint32_t CircleGen::addOperatorL2Normalization(const OperatorParams &params)
+{
+  auto options = circle::CreateL2NormOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_L2_NORMALIZATION,
+                                circle::BuiltinOptions_L2NormOptions, options);
+}
+
+uint32_t CircleGen::addOperatorLess(const OperatorParams &params)
+{
+  auto options = circle::CreateLessOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_LESS,
+                                circle::BuiltinOptions_LessOptions, options);
+}
+
+uint32_t CircleGen::addOperatorLessEqual(const OperatorParams &params)
+{
+  auto options = circle::CreateLessOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_LESS_EQUAL,
+                                circle::BuiltinOptions_LessEqualOptions, options);
+}
+
+uint32_t CircleGen::addOperatorLeakyRelu(const OperatorParams &params, float alpha)
+{
+  auto options = circle::CreateLeakyReluOptions(_fbb, alpha).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_LEAKY_RELU,
+                                circle::BuiltinOptions_LeakyReluOptions, options);
+}
+
+uint32_t CircleGen::addOperatorLogSoftmax(const OperatorParams &params)
+{
+  auto options = circle::CreateLogSoftmaxOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_LOG_SOFTMAX,
+                                circle::BuiltinOptions_LogSoftmaxOptions, options);
+}
+
+uint32_t CircleGen::addOperatorMaxPool2D(const OperatorParams &params, circle::Padding padding,
+                                         int stride_w, int stride_h, int filter_w, int filter_h,
+                                         circle::ActivationFunctionType actfn)
+{
+  auto options =
+    circle::CreatePool2DOptions(_fbb, padding, stride_w, stride_h, filter_w, filter_h, actfn)
+      .Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_MAX_POOL_2D,
+                                circle::BuiltinOptions_Pool2DOptions, options);
+}
+
+uint32_t CircleGen::addOperatorMean(const OperatorParams &params, bool keep_dims)
+{
+  auto options = circle::CreateReducerOptions(_fbb, keep_dims).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_MEAN,
+                                circle::BuiltinOptions_ReducerOptions, options);
+}
+
+uint32_t CircleGen::addOperatorMul(const OperatorParams &params,
+                                   circle::ActivationFunctionType actfn)
+{
+  auto options = circle::CreateMulOptions(_fbb, actfn).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_MUL,
+                                circle::BuiltinOptions_MulOptions, options);
+}
+
+uint32_t CircleGen::addOperatorNeg(const OperatorParams &params)
+{
+  auto options = circle::CreatePadOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_NEG,
+                                circle::BuiltinOptions_NegOptions, options);
+}
+
+uint32_t CircleGen::addOperatorNotEqual(const OperatorParams &params)
+{
+  auto options = circle::CreateEqualOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_NOT_EQUAL,
+                                circle::BuiltinOptions_NotEqualOptions, options);
+}
+
+uint32_t CircleGen::addOperatorOneHot(const OperatorParams &params, int32_t axis)
+{
+  auto options = circle::CreateOneHotOptions(_fbb, axis).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_ONE_HOT,
+                                circle::BuiltinOptions_OneHotOptions, options);
+}
+
+uint32_t CircleGen::addOperatorPad(const OperatorParams &params)
+{
+  auto options = circle::CreatePadOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_PAD,
+                                circle::BuiltinOptions_PadOptions, options);
+}
+
+uint32_t CircleGen::addOperatorPadV2(const OperatorParams &params)
+{
+  auto options = circle::CreatePadOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_PADV2,
+                                circle::BuiltinOptions_PadV2Options, options);
+}
+
+uint32_t CircleGen::addOperatorQuantize(const OperatorParams &params)
+{
+  auto options = circle::CreateQuantizeOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_QUANTIZE,
+                                circle::BuiltinOptions_QuantizeOptions, options);
+}
+
+uint32_t CircleGen::addOperatorRank(const OperatorParams &params)
+{
+  auto options = circle::CreateRankOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_RANK,
+                                circle::BuiltinOptions_RankOptions, options);
+}
+
+uint32_t CircleGen::addOperatorReduce(const OperatorParams &params,
+                                      circle::BuiltinOperator reduce_op, bool keep_dims)
+{
+  switch (reduce_op)
+  {
+    case circle::BuiltinOperator_REDUCE_ANY:
+    case circle::BuiltinOperator_REDUCE_MIN:
+    case circle::BuiltinOperator_REDUCE_MAX:
+    case circle::BuiltinOperator_REDUCE_PROD:
+      break;
+    default:
+      throw std::runtime_error{"Wrong reduce op"};
+  }
+  auto options = circle::CreateReducerOptions(_fbb, keep_dims).Union();
+  return addOperatorWithOptions(params, reduce_op, circle::BuiltinOptions_ReducerOptions, options);
+}
+
+uint32_t CircleGen::addOperatorRelu(const OperatorParams &params)
+{
+  return addOperatorWithOptions(params, circle::BuiltinOperator_RELU, circle::BuiltinOptions_NONE,
+                                0);
+}
+
+uint32_t CircleGen::addOperatorRelu6(const OperatorParams &params)
+{
+  return addOperatorWithOptions(params, circle::BuiltinOperator_RELU6, circle::BuiltinOptions_NONE,
+                                0);
+}
+
+uint32_t CircleGen::addOperatorReshape(const OperatorParams &params, const Shape *new_shape)
+{
+  auto options = circle::CreateReshapeOptionsDirect(_fbb, new_shape).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_RESHAPE,
+                                circle::BuiltinOptions_ReshapeOptions, options);
+}
+
+uint32_t CircleGen::addOperatorResizeBilinear(const OperatorParams &params, bool align_corners,
+                                              bool half_pixel_centers)
+{
+  auto options =
+    circle::CreateResizeBilinearOptions(_fbb, align_corners, half_pixel_centers).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_RESIZE_BILINEAR,
+                                circle::BuiltinOptions_ResizeBilinearOptions, options);
+}
+
+uint32_t CircleGen::addOperatorResizeNearestNeighbor(const OperatorParams &params)
+{
+  auto options = circle::CreateResizeNearestNeighborOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR,
+                                circle::BuiltinOptions_ResizeNearestNeighborOptions, options);
+}
+
+uint32_t CircleGen::addOperatorReverseV2(const OperatorParams &params)
+{
+  auto options = circle::CreateReverseV2Options(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_REVERSE_V2,
+                                circle::BuiltinOptions_ReverseV2Options, options);
+}
+
+uint32_t CircleGen::addOperatorShape(const OperatorParams &params, circle::TensorType type)
+{
+  auto options = circle::CreateShapeOptions(_fbb, type).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_SHAPE,
+                                circle::BuiltinOptions_RankOptions, options);
+}
+
+uint32_t CircleGen::addOperatorSelect(const OperatorParams &params)
+{
+  auto options = circle::CreateSelectOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_SELECT,
+                                circle::BuiltinOptions_SelectOptions, options);
+}
+
+uint32_t CircleGen::addOperatorSelectV2(const OperatorParams &params)
+{
+  auto options = circle::CreateSelectV2Options(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_SELECT_V2,
+                                circle::BuiltinOptions_SelectV2Options, options);
+}
+
+uint32_t CircleGen::addOperatorSlice(const OperatorParams &params)
+{
+  auto options = circle::CreateSliceOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_SLICE,
+                                circle::BuiltinOptions_SliceOptions, options);
+}
+
+uint32_t CircleGen::addOperatorSoftmax(const OperatorParams &params, float beta)
+{
+  auto options = circle::CreateSoftmaxOptions(_fbb, beta).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_SOFTMAX,
+                                circle::BuiltinOptions_SoftmaxOptions, options);
+}
+
+uint32_t CircleGen::addOperatorSplit(const OperatorParams &params, int32_t num_split)
+{
+  auto options = circle::CreateSplitOptions(_fbb, num_split).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_SPLIT,
+                                circle::BuiltinOptions_SplitOptions, options);
+}
+
+uint32_t CircleGen::addOperatorStridedSlice(const OperatorParams &params, int32_t begin_mask,
+                                            int32_t end_mask, int32_t ellipsis_mask,
+                                            int32_t new_axis_mask, int32_t shrink_axis_mask)
+{
+  auto options = circle::CreateStridedSliceOptions(_fbb, begin_mask, end_mask, ellipsis_mask,
+                                                   new_axis_mask, shrink_axis_mask)
+                   .Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_STRIDED_SLICE,
+                                circle::BuiltinOptions_StridedSliceOptions, options);
+}
+
+uint32_t CircleGen::addOperatorSub(const OperatorParams &params,
+                                   circle::ActivationFunctionType actfn)
+{
+  auto options = circle::CreateSubOptions(_fbb, actfn).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_SUB,
+                                circle::BuiltinOptions_SubOptions, options);
+}
+
+uint32_t CircleGen::addOperatorTile(const OperatorParams &params)
+{
+  auto options = circle::CreateTileOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_TILE,
+                                circle::BuiltinOptions_TileOptions, options);
+}
+
+uint32_t CircleGen::addOperatorWhile(const OperatorParams &params, uint32_t cond_subg,
+                                     uint32_t body_subg)
+{
+  auto options = circle::CreateWhileOptions(_fbb, cond_subg, body_subg).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_WHILE,
+                                circle::BuiltinOptions_WhileOptions, options);
+}
+
+uint32_t CircleGen::addOperatorIf(const OperatorParams &params, uint32_t then_subg,
+                                  uint32_t else_subg)
+{
+  auto options = circle::CreateIfOptions(_fbb, then_subg, else_subg).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_IF,
+                                circle::BuiltinOptions_IfOptions, options);
+}
+
+uint32_t CircleGen::addOperatorInstanceNorm(const OperatorParams &params, float epsilon,
+                                            circle::ActivationFunctionType actfn)
+{
+  auto options = circle::CreateInstanceNormOptions(_fbb, epsilon, actfn).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_INSTANCE_NORM,
+                                circle::BuiltinOptions_InstanceNormOptions, options);
+}
+
+uint32_t CircleGen::addOperatorTranspose(const OperatorParams &params)
+{
+  auto options = circle::CreateTransposeOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_TRANSPOSE,
+                                circle::BuiltinOptions_TransposeOptions, options);
+}
+
+uint32_t CircleGen::addOperatorSqrt(const OperatorParams &params)
+{
+  return addOperatorWithOptions(params, circle::BuiltinOperator_SQRT, circle::BuiltinOptions_NONE,
+                                0);
+}
+
+uint32_t CircleGen::addOperatorSquare(const OperatorParams &params)
+{
+  auto options = circle::CreateSquareOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_SQUARE,
+                                circle::BuiltinOptions_SquareOptions, options);
+}
+
+uint32_t CircleGen::addOperatorBatchToSpaceND(const OperatorParams &params)
+{
+  auto options = circle::CreateBatchToSpaceNDOptions(_fbb).Union();
+  return addOperatorWithOptions(params, circle::BuiltinOperator_BATCH_TO_SPACE_ND,
+                                circle::BuiltinOptions_BatchToSpaceNDOptions, options);
+}
+
+// NOTE Please add addOperator functions ABOVE this lie
+//
+// %  How to add a new addOperatorXXX fuction
+// 0. Copy code from one of the existing addOperatorXXX function
+// 1. Change the function signature (need BuiltinOperator params)
+// 2. Change enum BuiltinOperator
+// 3. Change enum BuiltinOptions
+// 4. Change CreateXXXOptions accordingly
+//
+// If operator don't have option table, remove CreateXXXOptions call,
+// call addOperatorWithOptions with options_type = circle::BuiltinOptions_NONE and options = 0
+
+// ===== Add Operator methods end =====
+
+uint32_t CircleGen::addOperatorWithOptions(const OperatorParams &params,
+                                           circle::BuiltinOperator opcode,
+                                           circle::BuiltinOptions options_type,
+                                           flatbuffers::Offset<void> options)
+{
+  uint32_t opcode_ind = addOperatorCode(opcode);
+  auto op = circle::CreateOperatorDirect(_fbb, opcode_ind, &params.inputs, &params.outputs,
+                                         options_type, options);
+
+  uint32_t ind = curSubgCtx().operators.size();
+  curSubgCtx().operators.emplace_back(op);
+  return ind;
+}
+
+uint32_t CircleGen::addCustomOperatorWithOptions(
+  const OperatorParams &params, std::string custom_code, circle::BuiltinOptions options_type,
+  flatbuffers::Offset<void> options, const std::vector<uint8_t> *custom_options,
+  circle::CustomOptionsFormat custom_options_format,
+  const std::vector<uint8_t> *mutating_variable_inputs, const std::vector<int32_t> *intermediates)
+
+{
+  uint32_t opcode_ind = addCustomOperatorCode(custom_code);
+  auto op = circle::CreateOperatorDirect(
+    _fbb, opcode_ind, &params.inputs, &params.outputs, options_type, options, custom_options,
+    custom_options_format, mutating_variable_inputs, intermediates);
+
+  uint32_t ind = curSubgCtx().operators.size();
+  curSubgCtx().operators.emplace_back(op);
+  return ind;
+}
+
+uint32_t CircleGen::addOperatorCode(circle::BuiltinOperator opcode)
+{
+  // TODO If the same OperatorCode is registered already, just return it
+  uint32_t ind = _opcodes.size();
+  _opcodes.emplace_back(circle::CreateOperatorCode(_fbb, opcode));
+  return ind;
+}
+
+uint32_t CircleGen::addCustomOperatorCode(std::string custom_code)
+{
+  // TODO If the same OperatorCode is registered already, just return it
+  uint32_t ind = _opcodes.size();
+  _opcodes.emplace_back(
+    circle::CreateOperatorCodeDirect(_fbb, circle::BuiltinOperator_CUSTOM, custom_code.c_str()));
+  return ind;
+}
+
+flatbuffers::Offset<circle::Buffer> CircleGen::buildBuffer(const uint8_t *buf, size_t size)
+{
+  if (buf == nullptr || size == 0)
+    return circle::CreateBuffer(_fbb);
+  auto buffer = _fbb.CreateVector(buf, size);
+  return circle::CreateBuffer(_fbb, buffer);
+}
+
+flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params)
+{
+  auto shape = _fbb.CreateVector(params.shape);
+  auto name = _fbb.CreateString(params.name);
+  return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name,
+                              0 /* QuantParam */, false /* is_variable */, 0 /* sparsity */,
+                              0 /* shape_signature */);
+}
+
+flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params, float scale,
+                                                           int64_t zero_point)
+{
+  auto shape = _fbb.CreateVector(params.shape);
+  auto name = _fbb.CreateString(params.name);
+  std::vector<float> scale_vector = {scale};
+  std::vector<int64_t> zero_point_vector = {zero_point};
+  auto quantization = circle::CreateQuantizationParametersDirect(_fbb, nullptr, nullptr,
+                                                                 &scale_vector, &zero_point_vector);
+  return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name, quantization,
+                              false /* is_variable */, 0 /* sparsity */, 0 /* shape_signature */);
+}
+
+flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params,
+                                                           std::vector<float> &scales,
+                                                           std::vector<int64_t> &zero_points)
+{
+  auto shape = _fbb.CreateVector(params.shape);
+  auto name = _fbb.CreateString(params.name);
+  auto quantization =
+    circle::CreateQuantizationParametersDirect(_fbb, nullptr, nullptr, &scales, &zero_points);
+  return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name, quantization,
+                              false /* is_variable */, 0 /* sparsity */, 0 /* shape_signature */);
+}
+
+flatbuffers::Offset<circle::SparsityParameters>
+CircleGen::buildSparsityParameters(const SparsityParams &sp)
+{
+  flatbuffers::Offset<flatbuffers::Vector<int32_t>> traversal_order;
+  flatbuffers::Offset<flatbuffers::Vector<int32_t>> block_map;
+  flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::DimensionMetadata>>>
+    dim_metadata;
+
+  traversal_order = _fbb.CreateVector(sp.traversal_order);
+  block_map = _fbb.CreateVector(sp.block_map);
+
+  std::vector<flatbuffers::Offset<circle::DimensionMetadata>> dim_metadata_vec;
+  for (auto &it : sp.dim_metadata)
+  {
+    auto fb_array_segments = circle::CreateUint16VectorDirect(_fbb, &it._array_segments.u16);
+    auto fb_array_indices = circle::CreateUint16VectorDirect(_fbb, &it._array_indices.u16);
+    auto dim_metadata = circle::CreateDimensionMetadata(
+      _fbb, it._format, it._dense_size, it._array_segments_type, fb_array_segments.Union(),
+      it._array_indices_type, fb_array_indices.Union());
+    dim_metadata_vec.emplace_back(dim_metadata);
+  }
+  dim_metadata = _fbb.CreateVector(dim_metadata_vec);
+
+  return circle::CreateSparsityParameters(_fbb, traversal_order, block_map, dim_metadata);
+}
+
+flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params,
+                                                           const SparsityParams &sp)
+{
+  auto shape = _fbb.CreateVector(params.shape);
+  auto name = _fbb.CreateString(params.name);
+  auto sparsity = buildSparsityParameters(sp);
+  return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name,
+                              0 /* QuantParam */, false /* is_variable */, sparsity,
+                              0 /* shape_signature */);
+}
+
+flatbuffers::Offset<circle::SubGraph> CircleGen::buildSubGraph(const SubgraphContext &ctx)
+{
+  return circle::CreateSubGraphDirect(_fbb, &ctx.tensors, &ctx.inputs, &ctx.outputs, &ctx.operators,
+                                      nullptr);
+}
diff --git a/tests/nnfw_api/lib/CircleGen.h b/tests/nnfw_api/lib/CircleGen.h
new file mode 100644 (file)
index 0000000..de2ef0b
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * 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 __NNFW_API_TEST_CIRCLE_GEN_H__
+#define __NNFW_API_TEST_CIRCLE_GEN_H__
+
+#include <circle_schema_generated.h>
+
+#include <vector>
+
+/**
+ * @brief Class for storing flatbuffer buffer
+ *
+ * This is a simple wrapper for a finished FlatBufferBuilder. It owns the buffer and a user can
+ * get the buffer pointer and size.
+ */
+class CircleBuffer
+{
+public:
+  CircleBuffer() = default;
+  explicit CircleBuffer(flatbuffers::FlatBufferBuilder &&fbb) : _fbb{std::move(fbb)}
+  {
+    _fbb.Finished(); // The build must have been finished, so check that here
+  }
+
+  uint8_t *buffer() const { return _fbb.GetBufferPointer(); }
+  size_t size() const { return _fbb.GetSize(); }
+
+private:
+  flatbuffers::FlatBufferBuilder _fbb;
+};
+
+/**
+ * @brief Circle flatbuffer file generator
+ *
+ * This is a helper class for generating circle file.
+ *
+ */
+class CircleGen
+{
+public:
+  using Shape = std::vector<int32_t>;
+
+  using SparseIndexVectorType = circle::SparseIndexVector;
+  using SparseDimensionType = circle::DimensionType;
+
+  struct SparseIndexVector
+  {
+    std::vector<uint16_t> u16;
+  };
+
+  struct DimMetaData
+  {
+    DimMetaData() = delete;
+    DimMetaData(SparseDimensionType format, std::vector<uint16_t> array_segments,
+                std::vector<uint16_t> array_indices)
+      : _format{format},
+        _array_segments_type(SparseIndexVectorType::SparseIndexVector_Uint16Vector),
+        _array_indices_type(SparseIndexVectorType::SparseIndexVector_Uint16Vector)
+    {
+      _array_segments.u16 = array_segments;
+      _array_indices.u16 = array_indices;
+    }
+    DimMetaData(SparseDimensionType format, int32_t dense_size)
+      : _format{format}, _dense_size{dense_size}
+    {
+    }
+    SparseDimensionType _format{circle::DimensionType_DENSE};
+    int32_t _dense_size{0};
+    SparseIndexVectorType _array_segments_type{circle::SparseIndexVector_NONE};
+    SparseIndexVector _array_segments;
+    SparseIndexVectorType _array_indices_type{circle::SparseIndexVector_NONE};
+    SparseIndexVector _array_indices;
+  };
+
+  struct SparsityParams
+  {
+    std::vector<int32_t> traversal_order;
+    std::vector<int32_t> block_map;
+    std::vector<DimMetaData> dim_metadata;
+  };
+
+  struct TensorParams
+  {
+    std::vector<int32_t> shape;
+    circle::TensorType tensor_type = circle::TensorType::TensorType_FLOAT32;
+    uint32_t buffer = 0;
+    std::string name;
+  };
+
+  struct OperatorParams
+  {
+    std::vector<int32_t> inputs;
+    std::vector<int32_t> outputs;
+    int version = 1;
+  };
+
+  struct SubgraphContext
+  {
+    std::vector<int> inputs;
+    std::vector<int> outputs;
+    std::vector<flatbuffers::Offset<circle::Tensor>> tensors;
+    std::vector<flatbuffers::Offset<circle::Operator>> operators;
+  };
+
+public:
+  CircleGen();
+
+  template <typename T> uint32_t addBuffer(const std::vector<T> &buf_vec)
+  {
+    auto buf = reinterpret_cast<const uint8_t *>(buf_vec.data());
+    auto size = buf_vec.size() * sizeof(T);
+    return addBuffer(buf, size);
+  }
+  uint32_t addBuffer(const uint8_t *buf, size_t size);
+  uint32_t addTensor(const TensorParams &params);
+  uint32_t addTensor(const TensorParams &params, float scale, int64_t zero_point);
+  uint32_t addTensor(const TensorParams &params, std::vector<float> &scale,
+                     std::vector<int64_t> &zero_point);
+  uint32_t addTensor(const TensorParams &params, const SparsityParams &sp);
+  void setInputsAndOutputs(const std::vector<int> &inputs, const std::vector<int> &outputs);
+  uint32_t nextSubgraph();
+  uint32_t getCurrentSubgraphOpsSize() const;
+  CircleBuffer finish();
+
+  // ===== Add Operator methods begin (SORTED IN ALPHABETICAL ORDER) =====
+
+  uint32_t addOperatorAdd(const OperatorParams &params, circle::ActivationFunctionType actfn);
+  uint32_t addOperatorAddN(const OperatorParams &params);
+  uint32_t addOperatorArgMax(const OperatorParams &params,
+                             circle::TensorType output_type = circle::TensorType::TensorType_INT32);
+  uint32_t addOperatorArgMin(const OperatorParams &params,
+                             circle::TensorType output_type = circle::TensorType::TensorType_INT32);
+  uint32_t addOperatorAveragePool2D(const OperatorParams &params, circle::Padding padding,
+                                    int stride_w, int stride_h, int filter_w, int filter_h,
+                                    circle::ActivationFunctionType actfn);
+  uint32_t addOperatorBatchToSpaceND(const OperatorParams &params);
+  uint32_t addOperatorCast(const OperatorParams &params, circle::TensorType input_type,
+                           circle::TensorType output_type);
+  uint32_t addOperatorConcatenation(const OperatorParams &params, int axis,
+                                    circle::ActivationFunctionType actfn);
+  uint32_t addOperatorConv2D(const OperatorParams &params, circle::Padding padding, int stride_w,
+                             int stride_h, circle::ActivationFunctionType actfn, int dilation_w = 1,
+                             int dilation_h = 1);
+  uint32_t addOperatorCos(const OperatorParams &params);
+  uint32_t addOperatorDepthToSpace(const OperatorParams &params, int32_t block_size);
+  uint32_t addOperatorDepthwiseConv2D(const OperatorParams &params, circle::Padding padding,
+                                      int stride_w, int stride_h, int depth_multiplier,
+                                      circle::ActivationFunctionType actfn, int dilation_w = 1,
+                                      int dilation_h = 1);
+  uint32_t addOperatorDetectionPostProcess(const OperatorParams &params, int num_classes,
+                                           float y_scale, float x_scale, float h_scale,
+                                           float w_scale, float nms_score_threshold,
+                                           float nms_iou_threshold, int max_detections,
+                                           int max_classes_per_detection, int detections_per_class);
+  uint32_t addOperatorElu(const OperatorParams &params);
+  uint32_t addOperatorEqual(const OperatorParams &params);
+  uint32_t addOperatorExpandDims(const OperatorParams &params);
+  uint32_t addOperatorFill(const OperatorParams &params);
+  uint32_t addOperatorFloor(const OperatorParams &params);
+  uint32_t addOperatorFloorDiv(const OperatorParams &params);
+  uint32_t addOperatorFloorMod(const OperatorParams &params);
+  uint32_t addOperatorFullyConnected(const OperatorParams &params,
+                                     circle::FullyConnectedOptionsWeightsFormat weights_format =
+                                       circle::FullyConnectedOptionsWeightsFormat_DEFAULT);
+  uint32_t addOperatorGreater(const OperatorParams &params);
+  uint32_t addOperatorGreaterEqual(const OperatorParams &params);
+  uint32_t addOperatorIf(const OperatorParams &params, uint32_t then_subg, uint32_t else_subg);
+  uint32_t addOperatorInstanceNorm(const OperatorParams &params, float epsilon,
+                                   circle::ActivationFunctionType actfn);
+  uint32_t addOperatorL2Normalization(const OperatorParams &params);
+  uint32_t addOperatorLeakyRelu(const OperatorParams &params, float alpha);
+  uint32_t addOperatorLess(const OperatorParams &params);
+  uint32_t addOperatorLessEqual(const OperatorParams &params);
+  uint32_t addOperatorLogSoftmax(const OperatorParams &params);
+  uint32_t addOperatorMul(const OperatorParams &params, circle::ActivationFunctionType actfn);
+  uint32_t addOperatorMaxPool2D(const OperatorParams &params, circle::Padding padding, int stride_w,
+                                int stride_h, int filter_w, int filter_h,
+                                circle::ActivationFunctionType actfn);
+  uint32_t addOperatorMean(const OperatorParams &params, bool keep_dims);
+  uint32_t addOperatorNeg(const OperatorParams &params);
+  uint32_t addOperatorNotEqual(const OperatorParams &params);
+  uint32_t addOperatorOneHot(const OperatorParams &params, int32_t axis);
+  uint32_t addOperatorPad(const OperatorParams &params);
+  uint32_t addOperatorPadV2(const OperatorParams &params);
+  uint32_t addOperatorQuantize(const OperatorParams &params);
+  uint32_t addOperatorRank(const OperatorParams &params);
+  uint32_t addOperatorReduce(const OperatorParams &params, circle::BuiltinOperator reduce_op,
+                             bool keep_dims);
+  /**
+   * @brief Create circle Reshape op
+   *        the second param new_shape can be optional just like circle::CreateReshapeOptionsDirect
+   */
+  uint32_t addOperatorRelu(const OperatorParams &params);
+  uint32_t addOperatorRelu6(const OperatorParams &params);
+  uint32_t addOperatorReshape(const OperatorParams &params, const Shape *new_shape = nullptr);
+  uint32_t addOperatorResizeBilinear(const OperatorParams &params, bool align_corners = false,
+                                     bool half_pixel_centers = false);
+  uint32_t addOperatorResizeNearestNeighbor(const OperatorParams &params);
+  uint32_t addOperatorReverseV2(const OperatorParams &params);
+  uint32_t addOperatorShape(const OperatorParams &params,
+                            circle::TensorType type = circle::TensorType::TensorType_INT32);
+  uint32_t addOperatorSelect(const OperatorParams &params);
+  uint32_t addOperatorSelectV2(const OperatorParams &params);
+  uint32_t addOperatorSlice(const OperatorParams &params);
+  uint32_t addOperatorSoftmax(const OperatorParams &params, float beta);
+  uint32_t addOperatorSplit(const OperatorParams &params, int32_t num_split);
+  uint32_t addOperatorSqrt(const OperatorParams &params);
+  uint32_t addOperatorSquare(const OperatorParams &params);
+  uint32_t addOperatorStridedSlice(const OperatorParams &params, 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);
+  uint32_t addOperatorSub(const OperatorParams &params, circle::ActivationFunctionType actfn);
+  uint32_t addOperatorTile(const OperatorParams &params);
+  uint32_t addOperatorTranspose(const OperatorParams &params);
+  uint32_t addOperatorWhile(const OperatorParams &params, uint32_t cond_subg, uint32_t body_subg);
+
+  // NOTE Please add addOperator functions ABOVE this line in ALPHABETICAL ORDER
+  // ===== Add Operator methods end =====
+
+private:
+  uint32_t addOperatorWithOptions(const OperatorParams &params, circle::BuiltinOperator opcode,
+                                  circle::BuiltinOptions options_type,
+                                  flatbuffers::Offset<void> options);
+  uint32_t addCustomOperatorWithOptions(const OperatorParams &params, std::string custom_code,
+                                        circle::BuiltinOptions options_type,
+                                        flatbuffers::Offset<void> options,
+                                        const std::vector<uint8_t> *custom_options,
+                                        circle::CustomOptionsFormat custom_options_format,
+                                        const std::vector<uint8_t> *mutating_variable_inputs,
+                                        const std::vector<int32_t> *intermediates);
+  uint32_t addOperatorCode(circle::BuiltinOperator opcode);
+  uint32_t addCustomOperatorCode(std::string custom_code);
+  flatbuffers::Offset<circle::Buffer> buildBuffer(const uint8_t *buf, size_t size);
+  flatbuffers::Offset<circle::Tensor> buildTensor(const TensorParams &params);
+  flatbuffers::Offset<circle::Tensor> buildTensor(const TensorParams &params, float scale,
+                                                  int64_t zero_point);
+  flatbuffers::Offset<circle::Tensor> buildTensor(const TensorParams &params,
+                                                  std::vector<float> &scales,
+                                                  std::vector<int64_t> &zero_points);
+  flatbuffers::Offset<circle::SparsityParameters> buildSparsityParameters(const SparsityParams &sp);
+  flatbuffers::Offset<circle::Tensor> buildTensor(const TensorParams &params,
+                                                  const SparsityParams &sp);
+  flatbuffers::Offset<circle::SubGraph> buildSubGraph(const SubgraphContext &ctx);
+
+  SubgraphContext &curSubgCtx() { return _subgraph_contexts.back(); }
+
+private:
+  flatbuffers::FlatBufferBuilder _fbb{1024};
+  std::vector<flatbuffers::Offset<circle::Buffer>> _buffers;
+  std::vector<flatbuffers::Offset<circle::OperatorCode>> _opcodes;
+  std::vector<SubgraphContext> _subgraph_contexts;
+};
+
+#endif // __NNFW_API_TEST_CIRCLE_GEN_H__
diff --git a/tests/nnfw_api/lib/CirclePlusGen.cc b/tests/nnfw_api/lib/CirclePlusGen.cc
new file mode 100644 (file)
index 0000000..05dc36f
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "CirclePlusGen.h"
+
+#include <numeric>
+#include <nnfw_experimental.h> // for NNFW_TRAIN_NUM_OF_TRAINABLE_OPS_SPECIAL_VALUES
+
+CircleBuffers CirclePlusGen::finish()
+{
+  CircleBuffers cbufs;
+  cbufs.circle = CircleGen::finish();
+  cbufs.circle_plus = createModelTraining();
+  return cbufs;
+}
+
+void CirclePlusGen::addTrainInfo(const TrainInfo &info) { _info = info; }
+
+CircleBuffer CirclePlusGen::createModelTraining()
+{
+  circle::OptimizerOptions optimizer_opt_type = circle::OptimizerOptions::OptimizerOptions_NONE;
+  flatbuffers::Offset<void> optimizer_opt = 0;
+  const circle::Optimizer optimizer = _info.optimizer;
+  switch (optimizer)
+  {
+    case circle::Optimizer_SGD:
+      optimizer_opt_type = circle::OptimizerOptions::OptimizerOptions_SGDOptions;
+      optimizer_opt = circle::CreateSGDOptions(_fbb_plus, _info.learning_rate).Union();
+      break;
+    case circle::Optimizer_ADAM:
+      optimizer_opt_type = circle::OptimizerOptions::OptimizerOptions_AdamOptions;
+      optimizer_opt = circle::CreateAdamOptions(_fbb_plus, _info.learning_rate).Union();
+      break;
+    default:
+      throw std::runtime_error("unknown optimzer");
+  }
+
+  circle::LossFnOptions lossfn_opt_type = circle::LossFnOptions_NONE;
+  flatbuffers::Offset<void> lossfn_opt = 0;
+  const circle::LossFn lossfn = _info.loss_fn;
+  switch (lossfn)
+  {
+    case circle::LossFn::LossFn_CATEGORICAL_CROSSENTROPY:
+      lossfn_opt_type = circle::LossFnOptions::LossFnOptions_CategoricalCrossentropyOptions;
+      lossfn_opt = circle::CreateCategoricalCrossentropyOptions(_fbb_plus).Union();
+      break;
+    case circle::LossFn::LossFn_MEAN_SQUARED_ERROR:
+      lossfn_opt_type = circle::LossFnOptions::LossFnOptions_MeanSquaredErrorOptions;
+      lossfn_opt = circle::CreateMeanSquaredErrorOptions(_fbb_plus).Union();
+      break;
+    case circle::LossFn::LossFn_SPARSE_CATEGORICAL_CROSSENTROPY:
+      // TODO enable this conversion after core support sparse_categorial_crossentropy
+      throw std::runtime_error{"'sparse_categorical_crossentropy' is not supported yet"};
+    default:
+      throw std::runtime_error{"unknown loss function"};
+  }
+
+  circle::LossReductionType loss_reduction_type = _info.loss_reduction_type;
+
+  int32_t batch_size = _info.batch_size;
+
+  const uint32_t ops_size = getCurrentSubgraphOpsSize();
+  std::vector<int32_t> trainable_ops;
+  if (NNFW_TRAIN_TRAINABLE_ALL == _info.num_of_trainable_ops)
+  {
+    for (uint32_t idx = 0; idx < ops_size; ++idx)
+    {
+      trainable_ops.push_back(idx);
+    }
+  }
+  else if (_info.num_of_trainable_ops > 0)
+    for (uint32_t i = 1; i <= static_cast<uint32_t>(_info.num_of_trainable_ops); ++i)
+    {
+      trainable_ops.push_back(ops_size - i);
+    }
+  else if (_info.num_of_trainable_ops <= NNFW_TRAIN_TRAINABLE_INCORRECT_STATE)
+  {
+    throw std::invalid_argument("Incorrect negative value of num_of_trainable_ops");
+  }
+
+  // NOTE: epochs will be removed
+  auto model_training = circle::CreateModelTraining(
+    _fbb_plus, 0, optimizer, optimizer_opt_type, optimizer_opt, lossfn, lossfn_opt_type, lossfn_opt,
+    0, batch_size, loss_reduction_type, _fbb_plus.CreateVector(trainable_ops));
+  _fbb_plus.Finish(model_training, circle::ModelTrainingIdentifier());
+
+  return CircleBuffer{std::move(_fbb_plus)};
+}
diff --git a/tests/nnfw_api/lib/CirclePlusGen.h b/tests/nnfw_api/lib/CirclePlusGen.h
new file mode 100644 (file)
index 0000000..8e28a88
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_API_TEST_CIRCLE_PLUS_GEN_H__
+#define __NNFW_API_TEST_CIRCLE_PLUS_GEN_H__
+
+#include "CircleGen.h"
+#include "circle_traininfo_generated.h"
+
+struct CircleBuffers
+{
+  CircleBuffer circle;
+  CircleBuffer circle_plus;
+};
+
+class CirclePlusGen : public CircleGen
+{
+public:
+  CirclePlusGen() = default;
+
+  struct TrainInfo
+  {
+    circle::Optimizer optimizer;
+    float learning_rate;
+    circle::LossFn loss_fn;
+    circle::LossReductionType loss_reduction_type;
+    int32_t batch_size;
+    int32_t num_of_trainable_ops = -1;
+  };
+
+public:
+  void addTrainInfo(const TrainInfo &info);
+
+  // NOTE: this is overriden from CircleGen::finish()
+  CircleBuffers finish();
+
+private:
+  CircleBuffer createModelTraining();
+
+private:
+  flatbuffers::FlatBufferBuilder _fbb_plus{1024};
+  TrainInfo _info;
+};
+
+#endif // __NNFW_API_TEST_CIRCLE_PLUS_GEN_H__
diff --git a/tests/nnfw_api/lib/GenModelTest.h b/tests/nnfw_api/lib/GenModelTest.h
new file mode 100644 (file)
index 0000000..9415e53
--- /dev/null
@@ -0,0 +1,475 @@
+/*
+ * 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 __NNFW_API_TEST_GEN_MODEL_TEST_H__
+#define __NNFW_API_TEST_GEN_MODEL_TEST_H__
+
+#include <gtest/gtest.h>
+#include <nnfw_internal.h>
+
+#include <fstream>
+#include <string>
+#include <unordered_map>
+
+#include "CircleGen.h"
+#include "fixtures.h"
+
+inline size_t sizeOfNnfwType(NNFW_TYPE type)
+{
+  switch (type)
+  {
+    case NNFW_TYPE_TENSOR_BOOL:
+    case NNFW_TYPE_TENSOR_UINT8:
+    case NNFW_TYPE_TENSOR_QUANT8_ASYMM:
+    case NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED:
+      return 1;
+    case NNFW_TYPE_TENSOR_FLOAT32:
+    case NNFW_TYPE_TENSOR_INT32:
+      return 4;
+    case NNFW_TYPE_TENSOR_INT64:
+      return 8;
+    default:
+      throw std::runtime_error{"Invalid tensor type"};
+  }
+}
+
+// TODO Unify this with `SessionObject` in `fixtures.h`
+struct SessionObjectGeneric
+{
+  nnfw_session *session = nullptr;
+  std::vector<std::vector<uint8_t>> inputs;
+  std::vector<std::vector<uint8_t>> outputs;
+};
+
+struct TestCaseData
+{
+  /**
+   * @brief A vector of input buffers
+   */
+  std::vector<std::vector<uint8_t>> inputs;
+
+  /**
+   * @brief A vector of output buffers
+   */
+  std::vector<std::vector<uint8_t>> outputs;
+
+  /**
+   * @brief Append vector data to inputs
+   *
+   * @tparam T Data type
+   * @param data vector data array
+   */
+  template <typename T> TestCaseData &addInput(const std::vector<T> &data)
+  {
+    addData(inputs, data);
+    return *this;
+  }
+
+  /**
+   * @brief Append vector data to inputs
+   *
+   * @tparam T Data type
+   * @param data vector data array
+   */
+  template <typename T> TestCaseData &addOutput(const std::vector<T> &data)
+  {
+    addData(outputs, data);
+    return *this;
+  }
+
+  /**
+   * @brief Call this when @c nnfw_run() for this test case is expected to be failed
+   */
+  TestCaseData &expectFailRun()
+  {
+    _expected_fail_run = true;
+    return *this;
+  }
+  bool expected_fail_run() const { return _expected_fail_run; }
+
+protected:
+  template <typename T>
+  static void addData(std::vector<std::vector<uint8_t>> &dest, const std::vector<T> &data)
+  {
+    size_t size = data.size() * sizeof(T);
+    dest.emplace_back();
+    dest.back().resize(size);
+    std::memcpy(dest.back().data(), data.data(), size);
+  }
+
+  bool _expected_fail_run = false;
+};
+
+template <>
+inline void TestCaseData::addData<bool>(std::vector<std::vector<uint8_t>> &dest,
+                                        const std::vector<bool> &data)
+{
+  size_t size = data.size() * sizeof(uint8_t);
+  dest.emplace_back();
+  dest.back().resize(size);
+  std::transform(data.cbegin(), data.cend(), dest.back().data(),
+                 [](bool b) { return static_cast<uint8_t>(b); });
+}
+
+/**
+ * @brief Create a TestCaseData with a uniform type
+ *
+ * A helper function for generating test cases that has the same data type for model inputs/outputs.
+ *
+ * @tparam T Uniform tensor type
+ * @param inputs Inputs tensor buffers
+ * @param outputs Output tensor buffers
+ * @return TestCaseData Generated test case data
+ */
+template <typename T>
+static TestCaseData uniformTCD(const std::vector<std::vector<T>> &inputs,
+                               const std::vector<std::vector<T>> &outputs)
+{
+  TestCaseData ret;
+  for (const auto &data : inputs)
+    ret.addInput(data);
+  for (const auto &data : outputs)
+    ret.addOutput(data);
+  return ret;
+}
+
+/**
+ * @brief A test configuration class
+ */
+class GenModelTestContext
+{
+public:
+  GenModelTestContext(CircleBuffer &&cbuf) : _cbuf{std::move(cbuf)}, _backends{"cpu"} {}
+
+  /**
+   * @brief  Return circle buffer
+   *
+   * @return CircleBuffer& the circle buffer
+   */
+  const CircleBuffer &cbuf() const { return _cbuf; }
+
+  /**
+   * @brief Return test cases
+   *
+   * @return std::vector<TestCaseData>& the test cases
+   */
+  const std::vector<TestCaseData> &test_cases() const { return _test_cases; }
+
+  /**
+   * @brief Return backends
+   *
+   * @return const std::vector<std::string>& the backends to be tested
+   */
+  const std::vector<std::string> &backends() const { return _backends; }
+
+  /**
+   * @brief Return test is defined to fail on model load
+   *
+   * @return bool test is defined to fail on model load
+   */
+  bool expected_fail_model_load() const { return _expected_fail_model_load; }
+
+  /**
+   * @brief Return test is defined to fail on compile
+   *
+   * @return bool test is defined to fail on compile
+   */
+  bool expected_fail_compile() const { return _expected_fail_compile; }
+
+  /**
+   * @brief Set the output buffer size of specified output tensor
+   *        Note that output tensor size of a model with dynamic tensor is calculated while
+   *        running the model.
+   *        Therefore, before runniing the model, the sufficient size of buffer should
+   *        be prepared by calling this method.
+   *        The size does not need to be the exact size.
+   */
+  void output_sizes(uint32_t ind, size_t size) { _output_sizes[ind] = size; }
+
+  size_t output_sizes(uint32_t ind) const { return _output_sizes.at(ind); }
+
+  bool hasOutputSizes(uint32_t ind) const { return _output_sizes.find(ind) != _output_sizes.end(); }
+
+  /**
+   * @brief Add a test case
+   *
+   * @param tc the test case to be added
+   */
+  void addTestCase(const TestCaseData &tc) { _test_cases.emplace_back(tc); }
+
+  /**
+   * @brief Add a test case
+   *
+   * @param tc the test case to be added
+   */
+  void setBackends(const std::vector<std::string> &backends)
+  {
+    _backends.clear();
+
+    for (auto backend : backends)
+    {
+#ifdef TEST_ACL_BACKEND
+      if (backend == "acl_cl" || backend == "acl_neon")
+      {
+        _backends.push_back(backend);
+      }
+#endif
+      if (backend == "cpu" || backend == "ruy" || backend == "train")
+      {
+        _backends.push_back(backend);
+      }
+#ifdef TEST_XNNPACK_BACKEND
+      if (backend == "xnnpack")
+      {
+        _backends.push_back(backend);
+      }
+#endif
+#ifdef TEST_GPU_CL_BACKEND
+      if (backend == "gpu_cl")
+      {
+        _backends.push_back(backend);
+      }
+#endif
+    }
+  }
+
+  /**
+   * @brief Expect failure while model load
+   */
+  void expectFailModelLoad() { _expected_fail_model_load = true; }
+
+  /**
+   * @brief Expect failure while compiling
+   */
+  void expectFailCompile() { _expected_fail_compile = true; }
+
+  /**
+   * @brief Expect failure while execution
+   */
+  void expectFailExecution() { _expected_fail_execution = true; }
+
+private:
+  CircleBuffer _cbuf;
+  std::vector<TestCaseData> _test_cases;
+  std::vector<std::string> _backends;
+  std::unordered_map<uint32_t, size_t> _output_sizes;
+  bool _expected_fail_model_load{false};
+  bool _expected_fail_compile{false};
+  bool _expected_fail_execution{false};
+};
+
+/**
+ * @brief Generated Model test fixture for a one time inference
+ *
+ * This fixture is for one-time inference test with variety of generated models.
+ * It is the test maker's responsiblity to create @c _context which contains
+ * test body, which are generated circle buffer, model input data and output data and
+ * backend list to be tested.
+ * The rest(calling API functions for execution) is done by @c Setup and @c TearDown .
+ *
+ */
+class GenModelTest : public ::testing::Test
+{
+protected:
+  void SetUp() override
+  { // DO NOTHING
+  }
+
+  void TearDown() override
+  {
+    for (std::string backend : _context->backends())
+    {
+      // NOTE If we can prepare many times for one model loading on same session,
+      //      we can move nnfw_create_session to SetUp and
+      //      nnfw_load_circle_from_buffer to outside forloop
+      NNFW_ENSURE_SUCCESS(nnfw_create_session(&_so.session));
+      auto &cbuf = _context->cbuf();
+      auto model_load_result =
+        nnfw_load_circle_from_buffer(_so.session, cbuf.buffer(), cbuf.size());
+      if (_context->expected_fail_model_load())
+      {
+        ASSERT_NE(model_load_result, NNFW_STATUS_NO_ERROR);
+        std::cerr << "Failed model loading as expected." << std::endl;
+        NNFW_ENSURE_SUCCESS(nnfw_close_session(_so.session));
+        continue;
+      }
+      NNFW_ENSURE_SUCCESS(model_load_result);
+      NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_so.session, backend.data()));
+
+      if (_context->expected_fail_compile())
+      {
+        ASSERT_NE(nnfw_prepare(_so.session), NNFW_STATUS_NO_ERROR);
+
+        NNFW_ENSURE_SUCCESS(nnfw_close_session(_so.session));
+        continue;
+      }
+      NNFW_ENSURE_SUCCESS(nnfw_prepare(_so.session));
+
+      // In/Out buffer settings
+      uint32_t num_inputs;
+      NNFW_ENSURE_SUCCESS(nnfw_input_size(_so.session, &num_inputs));
+      _so.inputs.resize(num_inputs);
+      for (uint32_t ind = 0; ind < _so.inputs.size(); ind++)
+      {
+        nnfw_tensorinfo ti;
+        NNFW_ENSURE_SUCCESS(nnfw_input_tensorinfo(_so.session, ind, &ti));
+        uint64_t input_elements = num_elems(&ti);
+        _so.inputs[ind].resize(input_elements * sizeOfNnfwType(ti.dtype));
+        if (_so.inputs[ind].size() == 0)
+        {
+          // Optional inputs
+          ASSERT_EQ(nnfw_set_input(_so.session, ind, ti.dtype, nullptr, 0), NNFW_STATUS_NO_ERROR);
+        }
+        else
+        {
+          ASSERT_EQ(nnfw_set_input(_so.session, ind, ti.dtype, _so.inputs[ind].data(),
+                                   _so.inputs[ind].size()),
+                    NNFW_STATUS_NO_ERROR);
+        }
+      }
+
+      uint32_t num_outputs;
+      NNFW_ENSURE_SUCCESS(nnfw_output_size(_so.session, &num_outputs));
+      _so.outputs.resize(num_outputs);
+      for (uint32_t ind = 0; ind < _so.outputs.size(); ind++)
+      {
+        nnfw_tensorinfo ti;
+        NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_so.session, ind, &ti));
+
+        auto size = 0;
+        {
+          if (_context->hasOutputSizes(ind))
+          {
+            size = _context->output_sizes(ind);
+          }
+          else
+          {
+            uint64_t output_elements = num_elems(&ti);
+            size = output_elements * sizeOfNnfwType(ti.dtype);
+          }
+          _so.outputs[ind].resize(size);
+        }
+
+        ASSERT_EQ(nnfw_set_output(_so.session, ind, ti.dtype, _so.outputs[ind].data(),
+                                  _so.outputs[ind].size()),
+                  NNFW_STATUS_NO_ERROR);
+      }
+
+      // Set input values, run, and check output values
+      for (auto &test_case : _context->test_cases())
+      {
+        auto &ref_inputs = test_case.inputs;
+        auto &ref_outputs = test_case.outputs;
+        ASSERT_EQ(_so.inputs.size(), ref_inputs.size());
+        for (uint32_t i = 0; i < _so.inputs.size(); i++)
+        {
+          // Fill the values
+          ASSERT_EQ(_so.inputs[i].size(), ref_inputs[i].size());
+          memcpy(_so.inputs[i].data(), ref_inputs[i].data(), ref_inputs[i].size());
+        }
+
+        if (test_case.expected_fail_run())
+        {
+          ASSERT_NE(nnfw_run(_so.session), NNFW_STATUS_NO_ERROR);
+          continue;
+        }
+
+        NNFW_ENSURE_SUCCESS(nnfw_run(_so.session));
+
+        ASSERT_EQ(_so.outputs.size(), ref_outputs.size());
+        for (uint32_t i = 0; i < _so.outputs.size(); i++)
+        {
+          nnfw_tensorinfo ti;
+          NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_so.session, i, &ti));
+
+          // Check output tensor values
+          auto &ref_output = ref_outputs[i];
+          auto &output = _so.outputs[i];
+          auto expected_tensor_size = ref_output.size();
+          auto actual_tensor_size = output.size();
+          ASSERT_EQ(expected_tensor_size, actual_tensor_size) << "Output #" << i;
+
+          switch (ti.dtype)
+          {
+            case NNFW_TYPE_TENSOR_BOOL:
+              compareBuffersExactBool(ref_output, output, i);
+              break;
+            case NNFW_TYPE_TENSOR_UINT8:
+            case NNFW_TYPE_TENSOR_QUANT8_ASYMM:
+              compareBuffersExact<uint8_t>(ref_output, output, i);
+              break;
+            case NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED:
+              compareBuffersExact<int8_t>(ref_output, output, i);
+              break;
+            case NNFW_TYPE_TENSOR_INT32:
+              compareBuffersExact<int32_t>(ref_output, output, i);
+              break;
+            case NNFW_TYPE_TENSOR_FLOAT32:
+              // TODO better way for handling FP error?
+              for (uint32_t e = 0; e < ref_output.size() / sizeof(float); e++)
+              {
+                float expected = reinterpret_cast<const float *>(ref_output.data())[e];
+                float actual = reinterpret_cast<const float *>(output.data())[e];
+                EXPECT_NEAR(expected, actual, 0.001)
+                  << "Output #" << i << ", Element Index : " << e;
+              }
+              break;
+            case NNFW_TYPE_TENSOR_INT64:
+              compareBuffersExact<int64_t>(ref_output, output, i);
+              break;
+            default:
+              throw std::runtime_error{"Invalid tensor type"};
+          }
+          // TODO Add shape comparison
+        }
+      }
+
+      NNFW_ENSURE_SUCCESS(nnfw_close_session(_so.session));
+    }
+  }
+
+private:
+  template <typename T>
+  void compareBuffersExact(const std::vector<uint8_t> &ref_buf, const std::vector<uint8_t> &act_buf,
+                           uint32_t index)
+  {
+    for (uint32_t e = 0; e < ref_buf.size() / sizeof(T); e++)
+    {
+      T expected = reinterpret_cast<const T *>(ref_buf.data())[e];
+      T actual = reinterpret_cast<const T *>(act_buf.data())[e];
+      EXPECT_EQ(expected, actual) << "Output #" << index << ", Element Index : " << e;
+    }
+  }
+
+  void compareBuffersExactBool(const std::vector<uint8_t> &ref_buf,
+                               const std::vector<uint8_t> &act_buf, uint32_t index)
+  {
+    for (uint32_t e = 0; e < ref_buf.size() / sizeof(uint8_t); e++)
+    {
+      uint8_t ref_raw = reinterpret_cast<const uint8_t *>(ref_buf.data())[e];
+      bool expected = (ref_raw != 0 ? true : false);
+      uint8_t act_raw = reinterpret_cast<const uint8_t *>(act_buf.data())[e];
+      bool actual = (act_raw != 0 ? true : false);
+      EXPECT_EQ(expected, actual) << "Output #" << index << ", Element Index : " << e;
+    }
+  }
+
+protected:
+  SessionObjectGeneric _so;
+  std::unique_ptr<GenModelTestContext> _context;
+};
+
+#endif // __NNFW_API_TEST_GEN_MODEL_TEST_H__
diff --git a/tests/nnfw_api/lib/GenModelTrain.h b/tests/nnfw_api/lib/GenModelTrain.h
new file mode 100644 (file)
index 0000000..3411959
--- /dev/null
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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_API_TEST_GEN_MODEL_TRAIN_H__
+#define __NNFW_API_TEST_GEN_MODEL_TRAIN_H__
+
+#include "GenModelTest.h"
+#include "CirclePlusGen.h"
+
+#include <numeric>
+#include <tuple>
+
+struct SessionObjectTraining : public SessionObjectGeneric
+{
+  std::vector<std::vector<uint8_t>> expects;
+};
+
+struct TrainCaseData
+{
+public:
+  using OneStepData =
+    std::vector<std::vector<uint8_t>>; // An input/output's data list to be used in one step
+  using DataSet = std::tuple<std::vector<OneStepData>,
+                             std::vector<OneStepData>>; // inputs dataset, expects dataset
+
+public:
+  /**
+   * @brief A dataset of inputs/expects
+   */
+  DataSet dataset;
+
+  /**
+   * @brief A vector of loss buffers
+   */
+  std::vector<std::vector<float>> losses;
+
+  /**
+   * @brief Append vector data list of inputs that are used in one step
+   *
+   * @tparam T Data type of inputs
+   * @param inputs Inputs that are used in one step
+   */
+
+  template <typename T> TrainCaseData &addInputs(const std::vector<std::vector<T>> &inputs)
+  {
+    auto &[inputs_dataset, unused] = dataset;
+    (void)unused;
+    addData(inputs_dataset.emplace_back(), inputs);
+
+    return *this;
+  }
+
+  /**
+   * @brief Append vector data list of expects that are used in one step
+   *
+   * @tparam T Data type of expects
+   * @param expects Expects that are used in one step
+   */
+  template <typename T> TrainCaseData &addExpects(const std::vector<std::vector<T>> &expects)
+  {
+    auto &[unused, expects_dataset] = dataset;
+    (void)unused;
+    addData(expects_dataset.emplace_back(), expects);
+
+    return *this;
+  }
+
+  /**
+   * @brief Append vector data to losses
+   *
+   * @tparam T Data type
+   * @param data vector data array
+   */
+  TrainCaseData &addLosses(const std::vector<float> &loss)
+  {
+    losses.emplace_back(loss);
+    return *this;
+  }
+
+  /**
+   * @brief Call this when @c nnfw_run() for this test case is expected to be failed
+   */
+  TrainCaseData &expectFailRun()
+  {
+    _expected_fail_run = true;
+    return *this;
+  }
+  bool expected_fail_run() const { return _expected_fail_run; }
+
+private:
+  /**
+   * @brief Append vector data list that are used in one step
+   *
+   * @tparam T Data type of vector data
+   * @param dest Destination to store vector data list
+   * @param data Vector data list to be stored
+   */
+  template <typename T>
+  void addData(OneStepData &dest, const std::vector<std::vector<T>> &data_list)
+  {
+    for (const auto &data : data_list)
+    {
+      addData(dest, data);
+    }
+  }
+
+  /**
+   * @brief Append vector data
+   *
+   * @tparam T Data type
+   * @param dest Destination to store vector data
+   * @param data A vector data to be stored
+   */
+  template <typename T> void addData(OneStepData &dest, const std::vector<T> &data)
+  {
+    size_t size = data.size() * sizeof(T);
+    dest.emplace_back().resize(size);
+    std::memcpy(dest.back().data(), data.data(), size);
+  }
+
+  bool _expected_fail_run = false;
+};
+
+template <>
+inline void TrainCaseData::addData<bool>(OneStepData &dest, const std::vector<bool> &src)
+{
+  size_t size = src.size() * sizeof(uint8_t);
+  dest.emplace_back().resize(size);
+  std::transform(src.cbegin(), src.cend(), dest.back().data(),
+                 [](bool b) { return static_cast<uint8_t>(b); });
+}
+
+/**
+ * @brief Create a TrainCaseData with a uniform type
+ *
+ * A helper function for generating train cases that has the same data type for model
+ * inputs/expects/losses.
+ *
+ * @tparam T Uniform tensor type
+ * @param inputs_dataset Inputs tensor buffers. format: dataset[steps[inputs[input_index]]]
+ * @param expects_dataset Outputs tensor buffers. format: dataset[steps[outputss[output_index]]]
+ * @param losses Expected loss buffers of last epoch. expected_losses[output_index]
+ * @return TrainCaseData Generated train case data
+ */
+template <typename T>
+static TrainCaseData uniformTCD(const std::vector<std::vector<std::vector<T>>> &inputs_dataset,
+                                const std::vector<std::vector<std::vector<T>>> &expects_dataset,
+                                const std::vector<std::vector<float>> &losses)
+{
+  assert(inputs_dataset.size() == expects_dataset.size());
+
+  TrainCaseData ret;
+  for (const auto &data : inputs_dataset)
+    ret.addInputs<T>(data);
+  for (const auto &data : expects_dataset)
+    ret.addExpects<T>(data);
+  for (const auto &loss : losses)
+    ret.addLosses(loss);
+  return ret;
+}
+
+/**
+ * @brief A train configuration class
+ */
+class GenModelTrainContext : public GenModelTestContext
+{
+public:
+  GenModelTrainContext(CircleBuffers &&cbufs)
+    : GenModelTestContext(std::move(cbufs.circle)), _cpbuf{std::move(cbufs.circle_plus)}, _epoch(0)
+  {
+    // DO NOTHING
+  }
+
+  /**
+   * @brief  Return circle plus buffer
+   *
+   * @return CircleBuffer& the circle plus buffer
+   */
+  const CircleBuffer &cpbuf() const { return _cpbuf; }
+
+  /**
+   * @brief Return train cases
+   *
+   * @return std::vector<TrainCaseData>& the train cases
+   */
+  const std::vector<TrainCaseData> &train_cases() const { return _train_cases; }
+
+  /**
+   * @brief Add a train case
+   *
+   * @param tc the train case to be added
+   */
+  void addTrainCase(const TrainCaseData &tc) { _train_cases.emplace_back(tc); }
+
+  int epoch() { return _epoch; }
+
+  void setEpoch(int32_t epoch)
+  {
+    if (epoch < 2)
+    {
+      throw std::runtime_error{"epoch should be equal or greater than 2"};
+    }
+    _epoch = epoch;
+  }
+
+private:
+  CircleBuffer _cpbuf;
+  std::vector<TrainCaseData> _train_cases;
+  int32_t _epoch;
+};
+
+/**
+ * @brief Generated Model test fixture for a one time training
+ *
+ * This fixture is for one-time training test with variety of generated models.
+ * It is the test maker's responsiblity to create @c _context which contains
+ * test body, which are generated circle buffer, model input data and output data and
+ * backend list to be tested.
+ * The rest(calling API functions for execution) is done by @c SetUp and @c TearDown .
+ *
+ */
+class GenModelTrain : public ::testing::Test
+{
+protected:
+  void SetUp() override
+  {
+    // DO NOTHING
+  }
+
+  void TearDown() override
+  {
+    // NOTE: Assume that the only backend is `train` backend
+    ASSERT_EQ(_context->backends().size(), 1);
+    ASSERT_STREQ(_context->backends()[0].c_str(), "train");
+
+    for (std::string backend : _context->backends())
+    {
+      // NOTE If we can prepare many times for one model loading on same session,
+      //      we can move nnfw_create_session to SetUp and
+      //      nnfw_load_circle_from_buffer to outside forloop
+      NNFW_ENSURE_SUCCESS(nnfw_create_session(&_so.session));
+      auto &cbuf = _context->cbuf();
+      auto model_load_result =
+        nnfw_load_circle_from_buffer(_so.session, cbuf.buffer(), cbuf.size());
+      if (_context->expected_fail_model_load())
+      {
+        ASSERT_NE(model_load_result, NNFW_STATUS_NO_ERROR);
+        std::cerr << "Failed model loading as expected." << std::endl;
+        NNFW_ENSURE_SUCCESS(nnfw_close_session(_so.session));
+        continue;
+      }
+      NNFW_ENSURE_SUCCESS(model_load_result);
+      NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_so.session, backend.data()));
+
+      if (_context->expected_fail_compile())
+      {
+        ASSERT_NE(nnfw_train_prepare(_so.session), NNFW_STATUS_NO_ERROR);
+
+        NNFW_ENSURE_SUCCESS(nnfw_close_session(_so.session));
+        continue;
+      }
+
+      // the nnfw_input_size() and nnfw_output_size() should be called before nnfw_train_prepare
+      uint32_t num_inputs;
+      NNFW_ENSURE_SUCCESS(nnfw_input_size(_so.session, &num_inputs));
+
+      uint32_t num_expecteds;
+      NNFW_ENSURE_SUCCESS(nnfw_output_size(_so.session, &num_expecteds));
+
+      // training information
+      nnfw_train_info tri;
+
+      // NOTE: This can be removed when circle schema and circle+ schema are merged and
+      // then `nnfw_load_circle_from_buffer` handles traininfo metadata of circle model
+      {
+        // code is copied from runtime/onert/core/src/loader/traininfo_loader.cc
+        auto &cpbuf = _context->cpbuf();
+        const uint8_t *buffer = cpbuf.buffer();
+        const size_t size = cpbuf.size();
+
+        assert(buffer != nullptr);
+        flatbuffers::Verifier v(buffer, size);
+        bool verified = circle::VerifyModelTrainingBuffer(v);
+        if (not verified)
+          throw std::runtime_error{"TrainingInfo buffer is not accessible"};
+
+        const circle::ModelTraining *circle_plus =
+          circle::GetModelTraining(static_cast<const void *>(buffer));
+
+        assert(circle_plus != nullptr);
+
+        tri = LoadTrainInfo(circle_plus);
+      }
+      NNFW_ENSURE_SUCCESS(nnfw_train_set_traininfo(_so.session, &tri));
+
+      // prepare for training
+      NNFW_ENSURE_SUCCESS(nnfw_train_prepare(_so.session));
+
+      // Prepare input
+      _so.inputs.resize(num_inputs);
+      std::vector<nnfw_tensorinfo> input_infos(num_inputs);
+      for (uint32_t ind = 0; ind < num_inputs; ind++)
+      {
+        nnfw_tensorinfo ti;
+        NNFW_ENSURE_SUCCESS(nnfw_input_tensorinfo(_so.session, ind, &ti));
+        uint64_t input_elements = num_elems(&ti);
+        _so.inputs[ind].resize(input_elements * sizeOfNnfwType(ti.dtype));
+
+        // Optional inputs are not supported yet
+        ASSERT_NE(_so.inputs[ind].size(), 0);
+
+        NNFW_ENSURE_SUCCESS(nnfw_train_set_input(_so.session, ind, _so.inputs[ind].data(), &ti));
+
+        input_infos.emplace_back(std::move(ti));
+      }
+
+      // Prepare expected output
+      _so.expects.resize(num_expecteds);
+      std::vector<nnfw_tensorinfo> expected_infos(num_expecteds);
+      for (uint32_t ind = 0; ind < num_expecteds; ind++)
+      {
+        nnfw_tensorinfo ti;
+        NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_so.session, ind, &ti));
+        uint64_t output_elements = num_elems(&ti);
+        _so.expects[ind].resize(output_elements * sizeOfNnfwType(ti.dtype));
+
+        // Setting the output buffer size of specified output tensor is not supported yet
+        ASSERT_EQ(_context->hasOutputSizes(ind), false);
+
+        NNFW_ENSURE_SUCCESS(
+          nnfw_train_set_expected(_so.session, ind, _so.expects[ind].data(), &ti));
+
+        expected_infos.emplace_back(std::move(ti));
+      }
+
+      const int num_epoch = _context->epoch();
+      ASSERT_GE(num_epoch, 2);
+      // Set input values & expected output values, train, and check loss
+      for (const auto &train_case : _context->train_cases())
+      {
+        const auto &[inputs_dataset, outputs_dataset] = train_case.dataset;
+        const auto num_step = inputs_dataset.size();
+        ASSERT_EQ(num_step, outputs_dataset.size());
+
+        // Prepare expected losses
+        const auto &ref_losses = train_case.losses;
+        ASSERT_EQ(ref_losses.size(), num_epoch);
+        std::vector<float> actual_losses(num_expecteds, 0.f);
+        for (uint32_t epoch = 0; epoch < num_epoch; ++epoch)
+        {
+          std::fill(actual_losses.begin(), actual_losses.end(), 0.f);
+
+          for (uint32_t step = 0; step < num_step; step++)
+          {
+            // Inputs
+            const auto &ref_inputs = inputs_dataset[step];
+            ASSERT_EQ(_so.inputs.size(), ref_inputs.size());
+            for (uint32_t i = 0; i < _so.inputs.size(); i++)
+            {
+              // Fill the values
+              ASSERT_EQ(_so.inputs[i].size(), ref_inputs[i].size());
+              memcpy(_so.inputs[i].data(), ref_inputs[i].data(), ref_inputs[i].size());
+            }
+
+            // Expected outputs
+            const auto &ref_expects = outputs_dataset[step];
+            ASSERT_EQ(_so.expects.size(), ref_expects.size());
+            for (uint32_t i = 0; i < _so.expects.size(); i++)
+            {
+              // Fill the values
+              ASSERT_EQ(_so.expects[i].size(), ref_expects[i].size());
+              memcpy(_so.expects[i].data(), ref_expects[i].data(), ref_expects[i].size());
+            }
+
+            if (train_case.expected_fail_run())
+            {
+              ASSERT_NE(nnfw_train(_so.session, true), NNFW_STATUS_NO_ERROR);
+              continue;
+            }
+
+            // Train
+            NNFW_ENSURE_SUCCESS(nnfw_train(_so.session, true));
+
+            // Store loss
+            for (int32_t i = 0; i < num_expecteds; ++i)
+            {
+              float temp = 0.f;
+              NNFW_ENSURE_SUCCESS(nnfw_train_get_loss(_so.session, i, &temp));
+              actual_losses[i] += temp;
+            }
+          }
+
+          // Recalculate loss
+          for (uint32_t i = 0; i < num_expecteds; ++i)
+          {
+            actual_losses[i] /= num_step;
+          }
+
+          ASSERT_EQ(ref_losses[epoch].size(), actual_losses.size());
+
+          // TODO better way for handling FP error?
+          for (uint32_t i = 0; i < actual_losses.size(); i++)
+          {
+            const float actual = actual_losses[i];
+            const float expected = ref_losses[epoch][i];
+            EXPECT_NEAR(expected, actual, 0.001)
+              << "Loss " << epoch + 1 << "/" << num_epoch << " #" << i;
+          }
+        }
+      }
+
+      NNFW_ENSURE_SUCCESS(nnfw_close_session(_so.session));
+    }
+  }
+
+private:
+  nnfw_train_info LoadTrainInfo(const circle::ModelTraining *circle_model)
+  {
+    nnfw_train_info tri;
+
+    const circle::Optimizer optimizer = circle_model->optimizer();
+    switch (optimizer)
+    {
+      case circle::Optimizer_SGD:
+        tri.opt = NNFW_TRAIN_OPTIMIZER_SGD;
+        tri.learning_rate = circle_model->optimizer_opt_as_SGDOptions()->learning_rate();
+        break;
+      case circle::Optimizer_ADAM:
+        tri.opt = NNFW_TRAIN_OPTIMIZER_ADAM;
+        tri.learning_rate = circle_model->optimizer_opt_as_AdamOptions()->learning_rate();
+        break;
+      default:
+        throw std::runtime_error("unknown optimzer");
+    }
+
+    const circle::LossFn loss_type = circle_model->lossfn();
+    switch (loss_type)
+    {
+      case circle::LossFn::LossFn_CATEGORICAL_CROSSENTROPY:
+        tri.loss_info.loss = NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY;
+        break;
+      case circle::LossFn::LossFn_MEAN_SQUARED_ERROR:
+        tri.loss_info.loss = NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR;
+        break;
+      case circle::LossFn::LossFn_SPARSE_CATEGORICAL_CROSSENTROPY:
+        // TODO enable this conversion after core support sparse_categorial_crossentropy
+        throw std::runtime_error{"'sparse_categorical_crossentropy' is not supported yet"};
+      default:
+        throw std::runtime_error{"unknown loss function"};
+    }
+
+    const circle::LossReductionType loss_reduction_type = circle_model->loss_reduction_type();
+    switch (loss_reduction_type)
+    {
+      case circle::LossReductionType::LossReductionType_SumOverBatchSize:
+        tri.loss_info.reduction_type = NNFW_TRAIN_LOSS_REDUCTION_SUM_OVER_BATCH_SIZE;
+        break;
+      case circle::LossReductionType::LossReductionType_Sum:
+        tri.loss_info.reduction_type = NNFW_TRAIN_LOSS_REDUCTION_SUM;
+        break;
+      default:
+        throw std::runtime_error{"unknown loss reduction type"};
+    }
+
+    tri.batch_size = circle_model->batch_size();
+    if (circle_model->trainable_ops()->size() > 0)
+    {
+      // remove possible duplicates and sort indexes
+      const std::set<int32_t> trainable_ops(circle_model->trainable_ops()->begin(),
+                                            circle_model->trainable_ops()->end());
+      const uint32_t first_trainable_idx = *trainable_ops.cbegin();
+      const uint32_t last_trainable_idx = *trainable_ops.crbegin();
+      const uint32_t trainable_indexes_range = last_trainable_idx - first_trainable_idx + 1;
+      const uint32_t ops_size =
+        circle::GetModel(_context->cbuf().buffer())->subgraphs()->Get(0)->operators()->size();
+
+      if (last_trainable_idx == ops_size - 1 && trainable_indexes_range == trainable_ops.size())
+      {
+        // check if all ops are trainable
+        if (0 == first_trainable_idx)
+        {
+          tri.num_of_trainable_ops = NNFW_TRAIN_TRAINABLE_ALL;
+        }
+        else
+        {
+          tri.num_of_trainable_ops = trainable_indexes_range;
+        }
+      }
+      else
+      {
+        throw std::runtime_error("Operations to be trained must be from the top of the model");
+      }
+    }
+    else
+    {
+      tri.num_of_trainable_ops = NNFW_TRAIN_TRAINABLE_NONE;
+    }
+
+    return tri;
+  }
+
+protected:
+  SessionObjectTraining _so;
+  std::unique_ptr<GenModelTrainContext> _context;
+};
+
+#endif // __NNFW_API_TEST_GEN_MODEL_TRAIN_H__
diff --git a/tests/nnfw_api/src/CircleGen.cc b/tests/nnfw_api/src/CircleGen.cc
deleted file mode 100644 (file)
index e460184..0000000
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * 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 "CircleGen.h"
-#include "flatbuffers/flexbuffers.h"
-
-CircleGen::CircleGen() : _subgraph_contexts(1) // Create primary subgraph
-{
-  // 0th buffer is always the empty buffer for non-const tensors
-  addBuffer(nullptr, 0);
-}
-
-template <typename T> uint32_t addBuffer(const std::vector<T> &buf_vec)
-{
-  auto buf = reinterpret_cast<const uint8_t *>(buf_vec.data());
-  auto size = buf_vec.size() * sizeof(T);
-  return addBuffer(buf, size);
-}
-
-uint32_t CircleGen::addBuffer(const uint8_t *buf, size_t size)
-{
-  uint32_t ind = _buffers.size();
-  _buffers.emplace_back(buildBuffer(buf, size));
-  return ind;
-}
-
-uint32_t CircleGen::addTensor(const TensorParams &params)
-{
-  uint32_t ind = curSubgCtx().tensors.size();
-  curSubgCtx().tensors.emplace_back(buildTensor(params));
-  return ind;
-}
-
-uint32_t CircleGen::addTensor(const TensorParams &params, float scale, int64_t zero_point)
-{
-  // TensorType_INT8: scale >= 0, zero_point: [-128, 127]
-  // TensorType_UINT8: scale >= 0, zero_point: [0, 255]
-  uint32_t ind = curSubgCtx().tensors.size();
-  curSubgCtx().tensors.emplace_back(buildTensor(params, scale, zero_point));
-  return ind;
-}
-
-uint32_t CircleGen::addTensor(const TensorParams &params, std::vector<float> &scale,
-                              std::vector<int64_t> &zero_point)
-{
-  uint32_t ind = curSubgCtx().tensors.size();
-  curSubgCtx().tensors.emplace_back(buildTensor(params, scale, zero_point));
-  return ind;
-}
-
-uint32_t CircleGen::addTensor(const TensorParams &params, const SparsityParams &sp)
-{
-  uint32_t ind = curSubgCtx().tensors.size();
-  curSubgCtx().tensors.emplace_back(buildTensor(params, sp));
-  return ind;
-}
-
-void CircleGen::setInputsAndOutputs(const std::vector<int> &inputs, const std::vector<int> &outputs)
-{
-  curSubgCtx().inputs = inputs;
-  curSubgCtx().outputs = outputs;
-}
-
-uint32_t CircleGen::nextSubgraph()
-{
-  uint32_t ind = _subgraph_contexts.size();
-  _subgraph_contexts.push_back({});
-  return ind;
-}
-
-CircleBuffer CircleGen::finish()
-{
-  std::vector<flatbuffers::Offset<circle::SubGraph>> subgraphs;
-  for (auto &ctx : _subgraph_contexts)
-    subgraphs.push_back(buildSubGraph(ctx));
-  auto model =
-    circle::CreateModelDirect(_fbb, 3, &_opcodes, &subgraphs, "CircleGen generated", &_buffers);
-  _fbb.Finish(model);
-  return CircleBuffer{std::move(_fbb)};
-}
-
-// ===== Add Operator methods begin =====
-
-uint32_t CircleGen::addOperatorAdd(const OperatorParams &params,
-                                   circle::ActivationFunctionType actfn)
-{
-  auto options = circle::CreateAddOptions(_fbb, actfn).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_ADD,
-                                circle::BuiltinOptions_AddOptions, options);
-}
-
-uint32_t CircleGen::addOperatorAddN(const OperatorParams &params)
-{
-  auto options = circle::CreateAddNOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_ADD_N,
-                                circle::BuiltinOptions_AddNOptions, options);
-}
-
-uint32_t CircleGen::addOperatorArgMax(const OperatorParams &params, circle::TensorType output_type)
-{
-  auto options = circle::CreateArgMaxOptions(_fbb, output_type).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_ARG_MAX,
-                                circle::BuiltinOptions_ArgMaxOptions, options);
-}
-
-uint32_t CircleGen::addOperatorArgMin(const OperatorParams &params, circle::TensorType output_type)
-{
-  auto options = circle::CreateArgMaxOptions(_fbb, output_type).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_ARG_MIN,
-                                circle::BuiltinOptions_ArgMinOptions, options);
-}
-
-uint32_t CircleGen::addOperatorAveragePool2D(const OperatorParams &params, circle::Padding padding,
-                                             int stride_w, int stride_h, int filter_w, int filter_h,
-                                             circle::ActivationFunctionType actfn)
-{
-  auto options =
-    circle::CreatePool2DOptions(_fbb, padding, stride_w, stride_h, filter_w, filter_h, actfn)
-      .Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_AVERAGE_POOL_2D,
-                                circle::BuiltinOptions_Pool2DOptions, options);
-}
-
-uint32_t CircleGen::addOperatorCast(const OperatorParams &params, circle::TensorType input_type,
-                                    circle::TensorType output_type)
-{
-  auto options = circle::CreateCastOptions(_fbb, input_type, output_type).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_CAST,
-                                circle::BuiltinOptions_AddOptions, options);
-}
-
-uint32_t CircleGen::addOperatorConcatenation(const OperatorParams &params, int axis,
-                                             circle::ActivationFunctionType actfn)
-{
-  auto options = circle::CreateConcatenationOptions(_fbb, axis, actfn).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_CONCATENATION,
-                                circle::BuiltinOptions_ConcatenationOptions, options);
-}
-
-uint32_t CircleGen::addOperatorConv2D(const OperatorParams &params, circle::Padding padding,
-                                      int stride_w, int stride_h,
-                                      circle::ActivationFunctionType actfn, int dilation_w,
-                                      int dilation_h)
-{
-  auto options =
-    circle::CreateConv2DOptions(_fbb, padding, stride_w, stride_h, actfn, dilation_w, dilation_h)
-      .Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_CONV_2D,
-                                circle::BuiltinOptions_Conv2DOptions, options);
-}
-
-uint32_t CircleGen::addOperatorCos(const OperatorParams &params)
-{
-  auto options = circle::CreateCosOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_COS,
-                                circle::BuiltinOptions_CosOptions, options);
-}
-
-uint32_t CircleGen::addOperatorDepthToSpace(const OperatorParams &params, int32_t block_size)
-{
-  auto options = circle::CreateDepthToSpaceOptions(_fbb, block_size).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_DEPTH_TO_SPACE,
-                                circle::BuiltinOptions_DepthToSpaceOptions, options);
-}
-
-uint32_t CircleGen::addOperatorDepthwiseConv2D(const OperatorParams &params,
-                                               circle::Padding padding, int stride_w, int stride_h,
-                                               int depth_multiplier,
-                                               circle::ActivationFunctionType actfn, int dilation_w,
-                                               int dilation_h)
-{
-  auto options =
-    circle::CreateDepthwiseConv2DOptions(_fbb, padding, stride_w, stride_h, depth_multiplier, actfn,
-                                         dilation_w, dilation_h)
-      .Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_DEPTHWISE_CONV_2D,
-                                circle::BuiltinOptions_DepthwiseConv2DOptions, options);
-}
-
-uint32_t CircleGen::addOperatorDetectionPostProcess(const OperatorParams &params, int num_classes,
-                                                    float y_scale, float x_scale, float h_scale,
-                                                    float w_scale, float nms_score_threshold,
-                                                    float nms_iou_threshold, int max_detections,
-                                                    int max_classes_per_detection,
-                                                    int detections_per_class)
-{
-  // flexbuffer custom_option
-  auto flex_buffers = std::make_unique<flexbuffers::Builder>();
-  size_t map_start = flex_buffers->StartMap();
-  flex_buffers->Int("num_classes", num_classes);
-  flex_buffers->Float("y_scale", y_scale);
-  flex_buffers->Float("x_scale", x_scale);
-  flex_buffers->Float("h_scale", h_scale);
-  flex_buffers->Float("w_scale", w_scale);
-  flex_buffers->Float("nms_iou_threshold", nms_iou_threshold);
-  flex_buffers->Float("nms_score_threshold", nms_score_threshold);
-  flex_buffers->Int("max_detections", max_detections);
-  flex_buffers->Int("max_classes_per_detection", max_classes_per_detection);
-  flex_buffers->Int("detections_per_class", detections_per_class);
-  flex_buffers->EndMap(map_start);
-  flex_buffers->Finish();
-
-  return addCustomOperatorWithOptions(params, "TFLite_Detection_PostProcess",
-                                      circle::BuiltinOptions_NONE, 0, &flex_buffers->GetBuffer(),
-                                      circle::CustomOptionsFormat::CustomOptionsFormat_FLEXBUFFERS,
-                                      nullptr, nullptr);
-}
-
-uint32_t CircleGen::addOperatorElu(const OperatorParams &params)
-{
-  return addOperatorWithOptions(params, circle::BuiltinOperator_ELU, circle::BuiltinOptions_NONE,
-                                0);
-}
-
-uint32_t CircleGen::addOperatorEqual(const OperatorParams &params)
-{
-  auto options = circle::CreateEqualOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_EQUAL,
-                                circle::BuiltinOptions_EqualOptions, options);
-}
-
-uint32_t CircleGen::addOperatorExpandDims(const OperatorParams &params)
-{
-  auto options = circle::CreateEqualOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_EXPAND_DIMS,
-                                circle::BuiltinOptions_ExpandDimsOptions, options);
-}
-
-uint32_t
-CircleGen::addOperatorFullyConnected(const OperatorParams &params,
-                                     circle::FullyConnectedOptionsWeightsFormat weights_format)
-{
-  auto options =
-    circle::CreateFullyConnectedOptions(_fbb, circle::ActivationFunctionType_NONE, weights_format)
-      .Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_FULLY_CONNECTED,
-                                circle::BuiltinOptions_FullyConnectedOptions, options);
-}
-
-uint32_t CircleGen::addOperatorFill(const OperatorParams &params)
-{
-  auto options = circle::CreateFillOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_FILL,
-                                circle::BuiltinOptions_FillOptions, options);
-}
-
-uint32_t CircleGen::addOperatorFloor(const OperatorParams &params)
-{
-  return addOperatorWithOptions(params, circle::BuiltinOperator_FLOOR, circle::BuiltinOptions_NONE,
-                                0);
-}
-
-uint32_t CircleGen::addOperatorFloorDiv(const OperatorParams &params)
-{
-  return addOperatorWithOptions(params, circle::BuiltinOperator_FLOOR_DIV,
-                                circle::BuiltinOptions_NONE, 0);
-}
-
-uint32_t CircleGen::addOperatorGreater(const OperatorParams &params)
-{
-  auto options = circle::CreateLessOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_GREATER,
-                                circle::BuiltinOptions_GreaterOptions, options);
-}
-
-uint32_t CircleGen::addOperatorGreaterEqual(const OperatorParams &params)
-{
-  auto options = circle::CreateGreaterOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_GREATER_EQUAL,
-                                circle::BuiltinOptions_GreaterEqualOptions, options);
-}
-
-uint32_t CircleGen::addOperatorL2Normalization(const OperatorParams &params)
-{
-  auto options = circle::CreateL2NormOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_L2_NORMALIZATION,
-                                circle::BuiltinOptions_L2NormOptions, options);
-}
-
-uint32_t CircleGen::addOperatorLess(const OperatorParams &params)
-{
-  auto options = circle::CreateLessOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_LESS,
-                                circle::BuiltinOptions_LessOptions, options);
-}
-
-uint32_t CircleGen::addOperatorLessEqual(const OperatorParams &params)
-{
-  auto options = circle::CreateLessOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_LESS_EQUAL,
-                                circle::BuiltinOptions_LessEqualOptions, options);
-}
-
-uint32_t CircleGen::addOperatorLeakyRelu(const OperatorParams &params, float alpha)
-{
-  auto options = circle::CreateLeakyReluOptions(_fbb, alpha).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_LEAKY_RELU,
-                                circle::BuiltinOptions_LeakyReluOptions, options);
-}
-
-uint32_t CircleGen::addOperatorLogSoftmax(const OperatorParams &params)
-{
-  auto options = circle::CreateLogSoftmaxOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_LOG_SOFTMAX,
-                                circle::BuiltinOptions_LogSoftmaxOptions, options);
-}
-
-uint32_t CircleGen::addOperatorMean(const OperatorParams &params, bool keep_dims)
-{
-  auto options = circle::CreateReducerOptions(_fbb, keep_dims).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_MEAN,
-                                circle::BuiltinOptions_ReducerOptions, options);
-}
-
-uint32_t CircleGen::addOperatorMul(const OperatorParams &params,
-                                   circle::ActivationFunctionType actfn)
-{
-  auto options = circle::CreateMulOptions(_fbb, actfn).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_MUL,
-                                circle::BuiltinOptions_MulOptions, options);
-}
-
-uint32_t CircleGen::addOperatorNeg(const OperatorParams &params)
-{
-  auto options = circle::CreatePadOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_NEG,
-                                circle::BuiltinOptions_NegOptions, options);
-}
-
-uint32_t CircleGen::addOperatorNotEqual(const OperatorParams &params)
-{
-  auto options = circle::CreateEqualOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_NOT_EQUAL,
-                                circle::BuiltinOptions_NotEqualOptions, options);
-}
-
-uint32_t CircleGen::addOperatorOneHot(const OperatorParams &params, int32_t axis)
-{
-  auto options = circle::CreateOneHotOptions(_fbb, axis).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_ONE_HOT,
-                                circle::BuiltinOptions_OneHotOptions, options);
-}
-
-uint32_t CircleGen::addOperatorPad(const OperatorParams &params)
-{
-  auto options = circle::CreatePadOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_PAD,
-                                circle::BuiltinOptions_PadOptions, options);
-}
-
-uint32_t CircleGen::addOperatorPadV2(const OperatorParams &params)
-{
-  auto options = circle::CreatePadOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_PADV2,
-                                circle::BuiltinOptions_PadV2Options, options);
-}
-
-uint32_t CircleGen::addOperatorQuantize(const OperatorParams &params)
-{
-  auto options = circle::CreateQuantizeOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_QUANTIZE,
-                                circle::BuiltinOptions_QuantizeOptions, options);
-}
-
-uint32_t CircleGen::addOperatorRank(const OperatorParams &params)
-{
-  auto options = circle::CreateRankOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_RANK,
-                                circle::BuiltinOptions_RankOptions, options);
-}
-
-uint32_t CircleGen::addOperatorReduce(const OperatorParams &params,
-                                      circle::BuiltinOperator reduce_op, bool keep_dims)
-{
-  switch (reduce_op)
-  {
-    case circle::BuiltinOperator_REDUCE_ANY:
-    case circle::BuiltinOperator_REDUCE_MIN:
-    case circle::BuiltinOperator_REDUCE_MAX:
-    case circle::BuiltinOperator_REDUCE_PROD:
-      break;
-    default:
-      throw std::runtime_error{"Wrong reduce op"};
-  }
-  auto options = circle::CreateReducerOptions(_fbb, keep_dims).Union();
-  return addOperatorWithOptions(params, reduce_op, circle::BuiltinOptions_ReducerOptions, options);
-}
-
-uint32_t CircleGen::addOperatorRelu(const OperatorParams &params)
-{
-  return addOperatorWithOptions(params, circle::BuiltinOperator_RELU, circle::BuiltinOptions_NONE,
-                                0);
-}
-
-uint32_t CircleGen::addOperatorRelu6(const OperatorParams &params)
-{
-  return addOperatorWithOptions(params, circle::BuiltinOperator_RELU6, circle::BuiltinOptions_NONE,
-                                0);
-}
-
-uint32_t CircleGen::addOperatorReshape(const OperatorParams &params, const Shape *new_shape)
-{
-  auto options = circle::CreateReshapeOptionsDirect(_fbb, new_shape).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_RESHAPE,
-                                circle::BuiltinOptions_ReshapeOptions, options);
-}
-
-uint32_t CircleGen::addOperatorResizeBilinear(const OperatorParams &params, bool align_corners,
-                                              bool half_pixel_centers)
-{
-  auto options =
-    circle::CreateResizeBilinearOptions(_fbb, align_corners, half_pixel_centers).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_RESIZE_BILINEAR,
-                                circle::BuiltinOptions_ResizeBilinearOptions, options);
-}
-
-uint32_t CircleGen::addOperatorResizeNearestNeighbor(const OperatorParams &params)
-{
-  auto options = circle::CreateResizeNearestNeighborOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR,
-                                circle::BuiltinOptions_ResizeNearestNeighborOptions, options);
-}
-
-uint32_t CircleGen::addOperatorReverseV2(const OperatorParams &params)
-{
-  auto options = circle::CreateReverseV2Options(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_REVERSE_V2,
-                                circle::BuiltinOptions_ReverseV2Options, options);
-}
-
-uint32_t CircleGen::addOperatorShape(const OperatorParams &params, circle::TensorType type)
-{
-  auto options = circle::CreateShapeOptions(_fbb, type).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_SHAPE,
-                                circle::BuiltinOptions_RankOptions, options);
-}
-
-uint32_t CircleGen::addOperatorSelect(const OperatorParams &params)
-{
-  auto options = circle::CreateSelectOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_SELECT,
-                                circle::BuiltinOptions_SelectOptions, options);
-}
-
-uint32_t CircleGen::addOperatorSelectV2(const OperatorParams &params)
-{
-  auto options = circle::CreateSelectV2Options(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_SELECT_V2,
-                                circle::BuiltinOptions_SelectV2Options, options);
-}
-
-uint32_t CircleGen::addOperatorSlice(const OperatorParams &params)
-{
-  auto options = circle::CreateSliceOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_SLICE,
-                                circle::BuiltinOptions_SliceOptions, options);
-}
-
-uint32_t CircleGen::addOperatorSoftmax(const OperatorParams &params, float beta)
-{
-  auto options = circle::CreateSoftmaxOptions(_fbb, beta).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_SOFTMAX,
-                                circle::BuiltinOptions_SoftmaxOptions, options);
-}
-
-uint32_t CircleGen::addOperatorSplit(const OperatorParams &params, int32_t num_split)
-{
-  auto options = circle::CreateSplitOptions(_fbb, num_split).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_SPLIT,
-                                circle::BuiltinOptions_SplitOptions, options);
-}
-
-uint32_t CircleGen::addOperatorStridedSlice(const OperatorParams &params, int32_t begin_mask,
-                                            int32_t end_mask, int32_t ellipsis_mask,
-                                            int32_t new_axis_mask, int32_t shrink_axis_mask)
-{
-  auto options = circle::CreateStridedSliceOptions(_fbb, begin_mask, end_mask, ellipsis_mask,
-                                                   new_axis_mask, shrink_axis_mask)
-                   .Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_STRIDED_SLICE,
-                                circle::BuiltinOptions_StridedSliceOptions, options);
-}
-
-uint32_t CircleGen::addOperatorSub(const OperatorParams &params,
-                                   circle::ActivationFunctionType actfn)
-{
-  auto options = circle::CreateSubOptions(_fbb, actfn).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_SUB,
-                                circle::BuiltinOptions_SubOptions, options);
-}
-
-uint32_t CircleGen::addOperatorTile(const OperatorParams &params)
-{
-  auto options = circle::CreateTileOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_TILE,
-                                circle::BuiltinOptions_TileOptions, options);
-}
-
-uint32_t CircleGen::addOperatorWhile(const OperatorParams &params, uint32_t cond_subg,
-                                     uint32_t body_subg)
-{
-  auto options = circle::CreateWhileOptions(_fbb, cond_subg, body_subg).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_WHILE,
-                                circle::BuiltinOptions_WhileOptions, options);
-}
-
-uint32_t CircleGen::addOperatorIf(const OperatorParams &params, uint32_t then_subg,
-                                  uint32_t else_subg)
-{
-  auto options = circle::CreateIfOptions(_fbb, then_subg, else_subg).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_IF,
-                                circle::BuiltinOptions_IfOptions, options);
-}
-
-uint32_t CircleGen::addOperatorInstanceNorm(const OperatorParams &params, float epsilon,
-                                            circle::ActivationFunctionType actfn)
-{
-  auto options = circle::CreateInstanceNormOptions(_fbb, epsilon, actfn).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_INSTANCE_NORM,
-                                circle::BuiltinOptions_InstanceNormOptions, options);
-}
-
-uint32_t CircleGen::addOperatorTranspose(const OperatorParams &params)
-{
-  auto options = circle::CreateTransposeOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_TRANSPOSE,
-                                circle::BuiltinOptions_TransposeOptions, options);
-}
-
-uint32_t CircleGen::addOperatorSqrt(const OperatorParams &params)
-{
-  return addOperatorWithOptions(params, circle::BuiltinOperator_SQRT, circle::BuiltinOptions_NONE,
-                                0);
-}
-
-uint32_t CircleGen::addOperatorSquare(const OperatorParams &params)
-{
-  auto options = circle::CreateSquareOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_SQUARE,
-                                circle::BuiltinOptions_SquareOptions, options);
-}
-
-uint32_t CircleGen::addOperatorBatchToSpaceND(const OperatorParams &params)
-{
-  auto options = circle::CreateBatchToSpaceNDOptions(_fbb).Union();
-  return addOperatorWithOptions(params, circle::BuiltinOperator_BATCH_TO_SPACE_ND,
-                                circle::BuiltinOptions_BatchToSpaceNDOptions, options);
-}
-
-// NOTE Please add addOperator functions ABOVE this lie
-//
-// %  How to add a new addOperatorXXX fuction
-// 0. Copy code from one of the existing addOperatorXXX function
-// 1. Change the function signature (need BuiltinOperator params)
-// 2. Change enum BuiltinOperator
-// 3. Change enum BuiltinOptions
-// 4. Change CreateXXXOptions accordingly
-//
-// If operator don't have option table, remove CreateXXXOptions call,
-// call addOperatorWithOptions with options_type = circle::BuiltinOptions_NONE and options = 0
-
-// ===== Add Operator methods end =====
-
-uint32_t CircleGen::addOperatorWithOptions(const OperatorParams &params,
-                                           circle::BuiltinOperator opcode,
-                                           circle::BuiltinOptions options_type,
-                                           flatbuffers::Offset<void> options)
-{
-  uint32_t opcode_ind = addOperatorCode(opcode);
-  auto op = circle::CreateOperatorDirect(_fbb, opcode_ind, &params.inputs, &params.outputs,
-                                         options_type, options);
-
-  uint32_t ind = curSubgCtx().operators.size();
-  curSubgCtx().operators.emplace_back(op);
-  return ind;
-}
-
-uint32_t CircleGen::addCustomOperatorWithOptions(
-  const OperatorParams &params, std::string custom_code, circle::BuiltinOptions options_type,
-  flatbuffers::Offset<void> options, const std::vector<uint8_t> *custom_options,
-  circle::CustomOptionsFormat custom_options_format,
-  const std::vector<uint8_t> *mutating_variable_inputs, const std::vector<int32_t> *intermediates)
-
-{
-  uint32_t opcode_ind = addCustomOperatorCode(custom_code);
-  auto op = circle::CreateOperatorDirect(
-    _fbb, opcode_ind, &params.inputs, &params.outputs, options_type, options, custom_options,
-    custom_options_format, mutating_variable_inputs, intermediates);
-
-  uint32_t ind = curSubgCtx().operators.size();
-  curSubgCtx().operators.emplace_back(op);
-  return ind;
-}
-
-uint32_t CircleGen::addOperatorCode(circle::BuiltinOperator opcode)
-{
-  // TODO If the same OperatorCode is registered already, just return it
-  uint32_t ind = _opcodes.size();
-  _opcodes.emplace_back(circle::CreateOperatorCode(_fbb, opcode));
-  return ind;
-}
-
-uint32_t CircleGen::addCustomOperatorCode(std::string custom_code)
-{
-  // TODO If the same OperatorCode is registered already, just return it
-  uint32_t ind = _opcodes.size();
-  _opcodes.emplace_back(
-    circle::CreateOperatorCodeDirect(_fbb, circle::BuiltinOperator_CUSTOM, custom_code.c_str()));
-  return ind;
-}
-
-flatbuffers::Offset<circle::Buffer> CircleGen::buildBuffer(const uint8_t *buf, size_t size)
-{
-  if (buf == nullptr || size == 0)
-    return circle::CreateBuffer(_fbb);
-  auto buffer = _fbb.CreateVector(buf, size);
-  return circle::CreateBuffer(_fbb, buffer);
-}
-
-flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params)
-{
-  auto shape = _fbb.CreateVector(params.shape);
-  auto name = _fbb.CreateString(params.name);
-  return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name,
-                              0 /* QuantParam */, false /* is_variable */, 0 /* sparsity */,
-                              0 /* shape_signature */);
-}
-
-flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params, float scale,
-                                                           int64_t zero_point)
-{
-  auto shape = _fbb.CreateVector(params.shape);
-  auto name = _fbb.CreateString(params.name);
-  std::vector<float> scale_vector = {scale};
-  std::vector<int64_t> zero_point_vector = {zero_point};
-  auto quantization = circle::CreateQuantizationParametersDirect(_fbb, nullptr, nullptr,
-                                                                 &scale_vector, &zero_point_vector);
-  return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name, quantization,
-                              false /* is_variable */, 0 /* sparsity */, 0 /* shape_signature */);
-}
-
-flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params,
-                                                           std::vector<float> &scales,
-                                                           std::vector<int64_t> &zero_points)
-{
-  auto shape = _fbb.CreateVector(params.shape);
-  auto name = _fbb.CreateString(params.name);
-  auto quantization =
-    circle::CreateQuantizationParametersDirect(_fbb, nullptr, nullptr, &scales, &zero_points);
-  return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name, quantization,
-                              false /* is_variable */, 0 /* sparsity */, 0 /* shape_signature */);
-}
-
-flatbuffers::Offset<circle::SparsityParameters>
-CircleGen::buildSparsityParameters(const SparsityParams &sp)
-{
-  flatbuffers::Offset<flatbuffers::Vector<int32_t>> traversal_order;
-  flatbuffers::Offset<flatbuffers::Vector<int32_t>> block_map;
-  flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<circle::DimensionMetadata>>>
-    dim_metadata;
-
-  traversal_order = _fbb.CreateVector(sp.traversal_order);
-  block_map = _fbb.CreateVector(sp.block_map);
-
-  std::vector<flatbuffers::Offset<circle::DimensionMetadata>> dim_metadata_vec;
-  for (auto &it : sp.dim_metadata)
-  {
-    auto fb_array_segments = circle::CreateUint16VectorDirect(_fbb, &it._array_segments.u16);
-    auto fb_array_indices = circle::CreateUint16VectorDirect(_fbb, &it._array_indices.u16);
-    auto dim_metadata = circle::CreateDimensionMetadata(
-      _fbb, it._format, it._dense_size, it._array_segments_type, fb_array_segments.Union(),
-      it._array_indices_type, fb_array_indices.Union());
-    dim_metadata_vec.emplace_back(dim_metadata);
-  }
-  dim_metadata = _fbb.CreateVector(dim_metadata_vec);
-
-  return circle::CreateSparsityParameters(_fbb, traversal_order, block_map, dim_metadata);
-}
-
-flatbuffers::Offset<circle::Tensor> CircleGen::buildTensor(const TensorParams &params,
-                                                           const SparsityParams &sp)
-{
-  auto shape = _fbb.CreateVector(params.shape);
-  auto name = _fbb.CreateString(params.name);
-  auto sparsity = buildSparsityParameters(sp);
-  return circle::CreateTensor(_fbb, shape, params.tensor_type, params.buffer, name,
-                              0 /* QuantParam */, false /* is_variable */, sparsity,
-                              0 /* shape_signature */);
-}
-
-flatbuffers::Offset<circle::SubGraph> CircleGen::buildSubGraph(const SubgraphContext &ctx)
-{
-  return circle::CreateSubGraphDirect(_fbb, &ctx.tensors, &ctx.inputs, &ctx.outputs, &ctx.operators,
-                                      nullptr);
-}
diff --git a/tests/nnfw_api/src/CircleGen.h b/tests/nnfw_api/src/CircleGen.h
deleted file mode 100644 (file)
index d780eb1..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * 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 __NNFW_API_TEST_CIRCLE_GEN_H__
-#define __NNFW_API_TEST_CIRCLE_GEN_H__
-
-#include <circle_schema_generated.h>
-
-#include <vector>
-
-/**
- * @brief Class for storing flatbuffer buffer
- *
- * This is a simple wrapper for a finished FlatBufferBuilder. It owns the buffer and a user can
- * get the buffer pointer and size.
- */
-class CircleBuffer
-{
-public:
-  CircleBuffer() = default;
-  explicit CircleBuffer(flatbuffers::FlatBufferBuilder &&fbb) : _fbb{std::move(fbb)}
-  {
-    _fbb.Finished(); // The build must have been finished, so check that here
-  }
-
-  uint8_t *buffer() const { return _fbb.GetBufferPointer(); }
-  size_t size() const { return _fbb.GetSize(); }
-
-private:
-  flatbuffers::FlatBufferBuilder _fbb;
-};
-
-/**
- * @brief Circle flatbuffer file generator
- *
- * This is a helper class for generating circle file.
- *
- */
-class CircleGen
-{
-public:
-  using Shape = std::vector<int32_t>;
-
-  using SparseIndexVectorType = circle::SparseIndexVector;
-  using SparseDimensionType = circle::DimensionType;
-
-  struct SparseIndexVector
-  {
-    std::vector<uint16_t> u16;
-  };
-
-  struct DimMetaData
-  {
-    DimMetaData() = delete;
-    DimMetaData(SparseDimensionType format, std::vector<uint16_t> array_segments,
-                std::vector<uint16_t> array_indices)
-      : _format{format},
-        _array_segments_type(SparseIndexVectorType::SparseIndexVector_Uint16Vector),
-        _array_indices_type(SparseIndexVectorType::SparseIndexVector_Uint16Vector)
-    {
-      _array_segments.u16 = array_segments;
-      _array_indices.u16 = array_indices;
-    }
-    DimMetaData(SparseDimensionType format, int32_t dense_size)
-      : _format{format}, _dense_size{dense_size}
-    {
-    }
-    SparseDimensionType _format{circle::DimensionType_DENSE};
-    int32_t _dense_size{0};
-    SparseIndexVectorType _array_segments_type{circle::SparseIndexVector_NONE};
-    SparseIndexVector _array_segments;
-    SparseIndexVectorType _array_indices_type{circle::SparseIndexVector_NONE};
-    SparseIndexVector _array_indices;
-  };
-
-  struct SparsityParams
-  {
-    std::vector<int32_t> traversal_order;
-    std::vector<int32_t> block_map;
-    std::vector<DimMetaData> dim_metadata;
-  };
-
-  struct TensorParams
-  {
-    std::vector<int32_t> shape;
-    circle::TensorType tensor_type = circle::TensorType::TensorType_FLOAT32;
-    uint32_t buffer = 0;
-    std::string name;
-  };
-
-  struct OperatorParams
-  {
-    std::vector<int32_t> inputs;
-    std::vector<int32_t> outputs;
-    int version = 1;
-  };
-
-  struct SubgraphContext
-  {
-    std::vector<int> inputs;
-    std::vector<int> outputs;
-    std::vector<flatbuffers::Offset<circle::Tensor>> tensors;
-    std::vector<flatbuffers::Offset<circle::Operator>> operators;
-  };
-
-public:
-  CircleGen();
-
-  template <typename T> uint32_t addBuffer(const std::vector<T> &buf_vec)
-  {
-    auto buf = reinterpret_cast<const uint8_t *>(buf_vec.data());
-    auto size = buf_vec.size() * sizeof(T);
-    return addBuffer(buf, size);
-  }
-  uint32_t addBuffer(const uint8_t *buf, size_t size);
-  uint32_t addTensor(const TensorParams &params);
-  uint32_t addTensor(const TensorParams &params, float scale, int64_t zero_point);
-  uint32_t addTensor(const TensorParams &params, std::vector<float> &scale,
-                     std::vector<int64_t> &zero_point);
-  uint32_t addTensor(const TensorParams &params, const SparsityParams &sp);
-  void setInputsAndOutputs(const std::vector<int> &inputs, const std::vector<int> &outputs);
-  uint32_t nextSubgraph();
-  CircleBuffer finish();
-
-  // ===== Add Operator methods begin (SORTED IN ALPHABETICAL ORDER) =====
-
-  uint32_t addOperatorAdd(const OperatorParams &params, circle::ActivationFunctionType actfn);
-  uint32_t addOperatorAddN(const OperatorParams &params);
-  uint32_t addOperatorArgMax(const OperatorParams &params,
-                             circle::TensorType output_type = circle::TensorType::TensorType_INT32);
-  uint32_t addOperatorArgMin(const OperatorParams &params,
-                             circle::TensorType output_type = circle::TensorType::TensorType_INT32);
-  uint32_t addOperatorAveragePool2D(const OperatorParams &params, circle::Padding padding,
-                                    int stride_w, int stride_h, int filter_w, int filter_h,
-                                    circle::ActivationFunctionType actfn);
-  uint32_t addOperatorBatchToSpaceND(const OperatorParams &params);
-  uint32_t addOperatorCast(const OperatorParams &params, circle::TensorType input_type,
-                           circle::TensorType output_type);
-  uint32_t addOperatorConcatenation(const OperatorParams &params, int axis,
-                                    circle::ActivationFunctionType actfn);
-  uint32_t addOperatorConv2D(const OperatorParams &params, circle::Padding padding, int stride_w,
-                             int stride_h, circle::ActivationFunctionType actfn, int dilation_w = 1,
-                             int dilation_h = 1);
-  uint32_t addOperatorCos(const OperatorParams &params);
-  uint32_t addOperatorDepthToSpace(const OperatorParams &params, int32_t block_size);
-  uint32_t addOperatorDepthwiseConv2D(const OperatorParams &params, circle::Padding padding,
-                                      int stride_w, int stride_h, int depth_multiplier,
-                                      circle::ActivationFunctionType actfn, int dilation_w = 1,
-                                      int dilation_h = 1);
-  uint32_t addOperatorDetectionPostProcess(const OperatorParams &params, int num_classes,
-                                           float y_scale, float x_scale, float h_scale,
-                                           float w_scale, float nms_score_threshold,
-                                           float nms_iou_threshold, int max_detections,
-                                           int max_classes_per_detection, int detections_per_class);
-  uint32_t addOperatorElu(const OperatorParams &params);
-  uint32_t addOperatorEqual(const OperatorParams &params);
-  uint32_t addOperatorExpandDims(const OperatorParams &params);
-  uint32_t addOperatorFill(const OperatorParams &params);
-  uint32_t addOperatorFloor(const OperatorParams &params);
-  uint32_t addOperatorFloorDiv(const OperatorParams &params);
-  uint32_t addOperatorFullyConnected(const OperatorParams &params,
-                                     circle::FullyConnectedOptionsWeightsFormat weights_format =
-                                       circle::FullyConnectedOptionsWeightsFormat_DEFAULT);
-  uint32_t addOperatorGreater(const OperatorParams &params);
-  uint32_t addOperatorGreaterEqual(const OperatorParams &params);
-  uint32_t addOperatorIf(const OperatorParams &params, uint32_t then_subg, uint32_t else_subg);
-  uint32_t addOperatorInstanceNorm(const OperatorParams &params, float epsilon,
-                                   circle::ActivationFunctionType actfn);
-  uint32_t addOperatorL2Normalization(const OperatorParams &params);
-  uint32_t addOperatorLeakyRelu(const OperatorParams &params, float alpha);
-  uint32_t addOperatorLess(const OperatorParams &params);
-  uint32_t addOperatorLessEqual(const OperatorParams &params);
-  uint32_t addOperatorLogSoftmax(const OperatorParams &params);
-  uint32_t addOperatorMul(const OperatorParams &params, circle::ActivationFunctionType actfn);
-  uint32_t addOperatorMean(const OperatorParams &params, bool keep_dims);
-  uint32_t addOperatorNeg(const OperatorParams &params);
-  uint32_t addOperatorNotEqual(const OperatorParams &params);
-  uint32_t addOperatorOneHot(const OperatorParams &params, int32_t axis);
-  uint32_t addOperatorPad(const OperatorParams &params);
-  uint32_t addOperatorPadV2(const OperatorParams &params);
-  uint32_t addOperatorQuantize(const OperatorParams &params);
-  uint32_t addOperatorRank(const OperatorParams &params);
-  uint32_t addOperatorReduce(const OperatorParams &params, circle::BuiltinOperator reduce_op,
-                             bool keep_dims);
-  /**
-   * @brief Create circle Reshape op
-   *        the second param new_shape can be optional just like circle::CreateReshapeOptionsDirect
-   */
-  uint32_t addOperatorRelu(const OperatorParams &params);
-  uint32_t addOperatorRelu6(const OperatorParams &params);
-  uint32_t addOperatorReshape(const OperatorParams &params, const Shape *new_shape = nullptr);
-  uint32_t addOperatorResizeBilinear(const OperatorParams &params, bool align_corners = false,
-                                     bool half_pixel_centers = false);
-  uint32_t addOperatorResizeNearestNeighbor(const OperatorParams &params);
-  uint32_t addOperatorReverseV2(const OperatorParams &params);
-  uint32_t addOperatorShape(const OperatorParams &params,
-                            circle::TensorType type = circle::TensorType::TensorType_INT32);
-  uint32_t addOperatorSelect(const OperatorParams &params);
-  uint32_t addOperatorSelectV2(const OperatorParams &params);
-  uint32_t addOperatorSlice(const OperatorParams &params);
-  uint32_t addOperatorSoftmax(const OperatorParams &params, float beta);
-  uint32_t addOperatorSplit(const OperatorParams &params, int32_t num_split);
-  uint32_t addOperatorSqrt(const OperatorParams &params);
-  uint32_t addOperatorSquare(const OperatorParams &params);
-  uint32_t addOperatorStridedSlice(const OperatorParams &params, 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);
-  uint32_t addOperatorSub(const OperatorParams &params, circle::ActivationFunctionType actfn);
-  uint32_t addOperatorTile(const OperatorParams &params);
-  uint32_t addOperatorTranspose(const OperatorParams &params);
-  uint32_t addOperatorWhile(const OperatorParams &params, uint32_t cond_subg, uint32_t body_subg);
-
-  // NOTE Please add addOperator functions ABOVE this line in ALPHABETICAL ORDER
-  // ===== Add Operator methods end =====
-
-private:
-  uint32_t addOperatorWithOptions(const OperatorParams &params, circle::BuiltinOperator opcode,
-                                  circle::BuiltinOptions options_type,
-                                  flatbuffers::Offset<void> options);
-  uint32_t addCustomOperatorWithOptions(const OperatorParams &params, std::string custom_code,
-                                        circle::BuiltinOptions options_type,
-                                        flatbuffers::Offset<void> options,
-                                        const std::vector<uint8_t> *custom_options,
-                                        circle::CustomOptionsFormat custom_options_format,
-                                        const std::vector<uint8_t> *mutating_variable_inputs,
-                                        const std::vector<int32_t> *intermediates);
-  uint32_t addOperatorCode(circle::BuiltinOperator opcode);
-  uint32_t addCustomOperatorCode(std::string custom_code);
-  flatbuffers::Offset<circle::Buffer> buildBuffer(const uint8_t *buf, size_t size);
-  flatbuffers::Offset<circle::Tensor> buildTensor(const TensorParams &params);
-  flatbuffers::Offset<circle::Tensor> buildTensor(const TensorParams &params, float scale,
-                                                  int64_t zero_point);
-  flatbuffers::Offset<circle::Tensor> buildTensor(const TensorParams &params,
-                                                  std::vector<float> &scales,
-                                                  std::vector<int64_t> &zero_points);
-  flatbuffers::Offset<circle::SparsityParameters> buildSparsityParameters(const SparsityParams &sp);
-  flatbuffers::Offset<circle::Tensor> buildTensor(const TensorParams &params,
-                                                  const SparsityParams &sp);
-  flatbuffers::Offset<circle::SubGraph> buildSubGraph(const SubgraphContext &ctx);
-
-  SubgraphContext &curSubgCtx() { return _subgraph_contexts.back(); }
-
-private:
-  flatbuffers::FlatBufferBuilder _fbb{1024};
-  std::vector<flatbuffers::Offset<circle::Buffer>> _buffers;
-  std::vector<flatbuffers::Offset<circle::OperatorCode>> _opcodes;
-  std::vector<SubgraphContext> _subgraph_contexts;
-};
-
-#endif // __NNFW_API_TEST_CIRCLE_GEN_H__
diff --git a/tests/nnfw_api/src/GenModelTest.h b/tests/nnfw_api/src/GenModelTest.h
deleted file mode 100644 (file)
index 90b7cfc..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * 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 __NNFW_API_TEST_GEN_MODEL_TEST_H__
-#define __NNFW_API_TEST_GEN_MODEL_TEST_H__
-
-#include <gtest/gtest.h>
-#include <nnfw_internal.h>
-
-#include <fstream>
-#include <string>
-#include <unordered_map>
-
-#include "CircleGen.h"
-#include "fixtures.h"
-
-inline size_t sizeOfNnfwType(NNFW_TYPE type)
-{
-  switch (type)
-  {
-    case NNFW_TYPE_TENSOR_BOOL:
-    case NNFW_TYPE_TENSOR_UINT8:
-    case NNFW_TYPE_TENSOR_QUANT8_ASYMM:
-    case NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED:
-      return 1;
-    case NNFW_TYPE_TENSOR_FLOAT32:
-    case NNFW_TYPE_TENSOR_INT32:
-      return 4;
-    case NNFW_TYPE_TENSOR_INT64:
-      return 8;
-    default:
-      throw std::runtime_error{"Invalid tensor type"};
-  }
-}
-
-// TODO Unify this with `SessionObject` in `fixtures.h`
-struct SessionObjectGeneric
-{
-  nnfw_session *session = nullptr;
-  std::vector<std::vector<uint8_t>> inputs;
-  std::vector<std::vector<uint8_t>> outputs;
-};
-
-struct TestCaseData
-{
-  /**
-   * @brief A vector of input buffers
-   */
-  std::vector<std::vector<uint8_t>> inputs;
-
-  /**
-   * @brief A vector of output buffers
-   */
-  std::vector<std::vector<uint8_t>> outputs;
-
-  /**
-   * @brief Append vector data to inputs
-   *
-   * @tparam T Data type
-   * @param data vector data array
-   */
-  template <typename T> TestCaseData &addInput(const std::vector<T> &data)
-  {
-    addData(inputs, data);
-    return *this;
-  }
-
-  /**
-   * @brief Append vector data to inputs
-   *
-   * @tparam T Data type
-   * @param data vector data array
-   */
-  template <typename T> TestCaseData &addOutput(const std::vector<T> &data)
-  {
-    addData(outputs, data);
-    return *this;
-  }
-
-  /**
-   * @brief Call this when @c nnfw_run() for this test case is expected to be failed
-   */
-  TestCaseData &expectFailRun()
-  {
-    _expected_fail_run = true;
-    return *this;
-  }
-  bool expected_fail_run() const { return _expected_fail_run; }
-
-private:
-  template <typename T>
-  static void addData(std::vector<std::vector<uint8_t>> &dest, const std::vector<T> &data)
-  {
-    size_t size = data.size() * sizeof(T);
-    dest.emplace_back();
-    dest.back().resize(size);
-    std::memcpy(dest.back().data(), data.data(), size);
-  }
-
-  bool _expected_fail_run = false;
-};
-
-template <>
-inline void TestCaseData::addData<bool>(std::vector<std::vector<uint8_t>> &dest,
-                                        const std::vector<bool> &data)
-{
-  size_t size = data.size() * sizeof(uint8_t);
-  dest.emplace_back();
-  dest.back().resize(size);
-  std::transform(data.cbegin(), data.cend(), dest.back().data(),
-                 [](bool b) { return static_cast<uint8_t>(b); });
-}
-
-/**
- * @brief Create a TestCaseData with a uniform type
- *
- * A helper function for generating test cases that has the same data type for model inputs/outputs.
- *
- * @tparam T Uniform tensor type
- * @param inputs Inputs tensor buffers
- * @param outputs Output tensor buffers
- * @return TestCaseData Generated test case data
- */
-template <typename T>
-static TestCaseData uniformTCD(const std::vector<std::vector<T>> &inputs,
-                               const std::vector<std::vector<T>> &outputs)
-{
-  TestCaseData ret;
-  for (const auto &data : inputs)
-    ret.addInput(data);
-  for (const auto &data : outputs)
-    ret.addOutput(data);
-  return ret;
-}
-
-/**
- * @brief A test configuration class
- */
-class GenModelTestContext
-{
-public:
-  GenModelTestContext(CircleBuffer &&cbuf) : _cbuf{std::move(cbuf)}, _backends{"cpu"} {}
-
-  /**
-   * @brief  Return circle buffer
-   *
-   * @return CircleBuffer& the circle buffer
-   */
-  const CircleBuffer &cbuf() const { return _cbuf; }
-
-  /**
-   * @brief Return test cases
-   *
-   * @return std::vector<TestCaseData>& the test cases
-   */
-  const std::vector<TestCaseData> &test_cases() const { return _test_cases; }
-
-  /**
-   * @brief Return backends
-   *
-   * @return const std::vector<std::string>& the backends to be tested
-   */
-  const std::vector<std::string> &backends() const { return _backends; }
-
-  /**
-   * @brief Return test is defined to fail on model load
-   *
-   * @return bool test is defined to fail on model load
-   */
-  bool expected_fail_model_load() const { return _expected_fail_model_load; }
-
-  /**
-   * @brief Return test is defined to fail on compile
-   *
-   * @return bool test is defined to fail on compile
-   */
-  bool expected_fail_compile() const { return _expected_fail_compile; }
-
-  /**
-   * @brief Set the output buffer size of specified output tensor
-   *        Note that output tensor size of a model with dynamic tensor is calculated while
-   *        running the model.
-   *        Therefore, before runniing the model, the sufficient size of buffer should
-   *        be prepared by calling this method.
-   *        The size does not need to be the exact size.
-   */
-  void output_sizes(uint32_t ind, size_t size) { _output_sizes[ind] = size; }
-
-  size_t output_sizes(uint32_t ind) const { return _output_sizes.at(ind); }
-
-  bool hasOutputSizes(uint32_t ind) const { return _output_sizes.find(ind) != _output_sizes.end(); }
-
-  /**
-   * @brief Add a test case
-   *
-   * @param tc the test case to be added
-   */
-  void addTestCase(const TestCaseData &tc) { _test_cases.emplace_back(tc); }
-
-  /**
-   * @brief Add a test case
-   *
-   * @param tc the test case to be added
-   */
-  void setBackends(const std::vector<std::string> &backends)
-  {
-    _backends.clear();
-
-    for (auto backend : backends)
-    {
-#ifdef TEST_ACL_BACKEND
-      if (backend == "acl_cl" || backend == "acl_neon")
-      {
-        _backends.push_back(backend);
-      }
-#endif
-      if (backend == "cpu" || backend == "ruy")
-      {
-        _backends.push_back(backend);
-      }
-#ifdef TEST_XNNPACK_BACKEND
-      if (backend == "xnnpack")
-      {
-        _backends.push_back(backend);
-      }
-#endif
-#ifdef TEST_GPU_CL_BACKEND
-      if (backend == "gpu_cl")
-      {
-        _backends.push_back(backend);
-      }
-#endif
-    }
-  }
-
-  /**
-   * @brief Expect failure while model load
-   */
-  void expectFailModelLoad() { _expected_fail_model_load = true; }
-
-  /**
-   * @brief Expect failure while compiling
-   */
-  void expectFailCompile() { _expected_fail_compile = true; }
-
-  /**
-   * @brief Expect failure while execution
-   */
-  void expectFailExecution() { _expected_fail_execution = true; }
-
-private:
-  CircleBuffer _cbuf;
-  std::vector<TestCaseData> _test_cases;
-  std::vector<std::string> _backends;
-  std::unordered_map<uint32_t, size_t> _output_sizes;
-  bool _expected_fail_model_load{false};
-  bool _expected_fail_compile{false};
-  bool _expected_fail_execution{false};
-};
-
-/**
- * @brief Generated Model test fixture for a one time inference
- *
- * This fixture is for one-time inference test with variety of generated models.
- * It is the test maker's responsiblity to create @c _context which contains
- * test body, which are generated circle buffer, model input data and output data and
- * backend list to be tested.
- * The rest(calling API functions for execution) is done by @c Setup and @c TearDown .
- *
- */
-class GenModelTest : public ::testing::Test
-{
-protected:
-  void SetUp() override
-  { // DO NOTHING
-  }
-
-  void TearDown() override
-  {
-    for (std::string backend : _context->backends())
-    {
-      // NOTE If we can prepare many times for one model loading on same session,
-      //      we can move nnfw_create_session to SetUp and
-      //      nnfw_load_circle_from_buffer to outside forloop
-      NNFW_ENSURE_SUCCESS(nnfw_create_session(&_so.session));
-      auto &cbuf = _context->cbuf();
-      auto model_load_result =
-        nnfw_load_circle_from_buffer(_so.session, cbuf.buffer(), cbuf.size());
-      if (_context->expected_fail_model_load())
-      {
-        ASSERT_NE(model_load_result, NNFW_STATUS_NO_ERROR);
-        std::cerr << "Failed model loading as expected." << std::endl;
-        NNFW_ENSURE_SUCCESS(nnfw_close_session(_so.session));
-        continue;
-      }
-      NNFW_ENSURE_SUCCESS(model_load_result);
-      NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_so.session, backend.data()));
-
-      if (_context->expected_fail_compile())
-      {
-        ASSERT_NE(nnfw_prepare(_so.session), NNFW_STATUS_NO_ERROR);
-
-        NNFW_ENSURE_SUCCESS(nnfw_close_session(_so.session));
-        continue;
-      }
-      NNFW_ENSURE_SUCCESS(nnfw_prepare(_so.session));
-
-      // In/Out buffer settings
-      uint32_t num_inputs;
-      NNFW_ENSURE_SUCCESS(nnfw_input_size(_so.session, &num_inputs));
-      _so.inputs.resize(num_inputs);
-      for (uint32_t ind = 0; ind < _so.inputs.size(); ind++)
-      {
-        nnfw_tensorinfo ti;
-        NNFW_ENSURE_SUCCESS(nnfw_input_tensorinfo(_so.session, ind, &ti));
-        uint64_t input_elements = num_elems(&ti);
-        _so.inputs[ind].resize(input_elements * sizeOfNnfwType(ti.dtype));
-        if (_so.inputs[ind].size() == 0)
-        {
-          // Optional inputs
-          ASSERT_EQ(nnfw_set_input(_so.session, ind, ti.dtype, nullptr, 0), NNFW_STATUS_NO_ERROR);
-        }
-        else
-        {
-          ASSERT_EQ(nnfw_set_input(_so.session, ind, ti.dtype, _so.inputs[ind].data(),
-                                   _so.inputs[ind].size()),
-                    NNFW_STATUS_NO_ERROR);
-        }
-      }
-
-      uint32_t num_outputs;
-      NNFW_ENSURE_SUCCESS(nnfw_output_size(_so.session, &num_outputs));
-      _so.outputs.resize(num_outputs);
-      for (uint32_t ind = 0; ind < _so.outputs.size(); ind++)
-      {
-        nnfw_tensorinfo ti;
-        NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_so.session, ind, &ti));
-
-        auto size = 0;
-        {
-          if (_context->hasOutputSizes(ind))
-          {
-            size = _context->output_sizes(ind);
-          }
-          else
-          {
-            uint64_t output_elements = num_elems(&ti);
-            size = output_elements * sizeOfNnfwType(ti.dtype);
-          }
-          _so.outputs[ind].resize(size);
-        }
-
-        ASSERT_EQ(nnfw_set_output(_so.session, ind, ti.dtype, _so.outputs[ind].data(),
-                                  _so.outputs[ind].size()),
-                  NNFW_STATUS_NO_ERROR);
-      }
-
-      // Set input values, run, and check output values
-      for (auto &test_case : _context->test_cases())
-      {
-        auto &ref_inputs = test_case.inputs;
-        auto &ref_outputs = test_case.outputs;
-        ASSERT_EQ(_so.inputs.size(), ref_inputs.size());
-        for (uint32_t i = 0; i < _so.inputs.size(); i++)
-        {
-          // Fill the values
-          ASSERT_EQ(_so.inputs[i].size(), ref_inputs[i].size());
-          memcpy(_so.inputs[i].data(), ref_inputs[i].data(), ref_inputs[i].size());
-        }
-
-        if (test_case.expected_fail_run())
-        {
-          ASSERT_NE(nnfw_run(_so.session), NNFW_STATUS_NO_ERROR);
-          continue;
-        }
-
-        NNFW_ENSURE_SUCCESS(nnfw_run(_so.session));
-
-        ASSERT_EQ(_so.outputs.size(), ref_outputs.size());
-        for (uint32_t i = 0; i < _so.outputs.size(); i++)
-        {
-          nnfw_tensorinfo ti;
-          NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_so.session, i, &ti));
-
-          // Check output tensor values
-          auto &ref_output = ref_outputs[i];
-          auto &output = _so.outputs[i];
-          auto expected_tensor_size = ref_output.size();
-          auto actual_tensor_size = output.size();
-          ASSERT_EQ(expected_tensor_size, actual_tensor_size) << "Output #" << i;
-
-          switch (ti.dtype)
-          {
-            case NNFW_TYPE_TENSOR_BOOL:
-              compareBuffersExactBool(ref_output, output, i);
-              break;
-            case NNFW_TYPE_TENSOR_UINT8:
-            case NNFW_TYPE_TENSOR_QUANT8_ASYMM:
-              compareBuffersExact<uint8_t>(ref_output, output, i);
-              break;
-            case NNFW_TYPE_TENSOR_QUANT8_ASYMM_SIGNED:
-              compareBuffersExact<int8_t>(ref_output, output, i);
-              break;
-            case NNFW_TYPE_TENSOR_INT32:
-              compareBuffersExact<int32_t>(ref_output, output, i);
-              break;
-            case NNFW_TYPE_TENSOR_FLOAT32:
-              // TODO better way for handling FP error?
-              for (uint32_t e = 0; e < ref_output.size() / sizeof(float); e++)
-              {
-                float expected = reinterpret_cast<const float *>(ref_output.data())[e];
-                float actual = reinterpret_cast<const float *>(output.data())[e];
-                EXPECT_NEAR(expected, actual, 0.001)
-                  << "Output #" << i << ", Element Index : " << e;
-              }
-              break;
-            case NNFW_TYPE_TENSOR_INT64:
-              compareBuffersExact<int64_t>(ref_output, output, i);
-              break;
-            default:
-              throw std::runtime_error{"Invalid tensor type"};
-          }
-          // TODO Add shape comparison
-        }
-      }
-
-      NNFW_ENSURE_SUCCESS(nnfw_close_session(_so.session));
-    }
-  }
-
-private:
-  template <typename T>
-  void compareBuffersExact(const std::vector<uint8_t> &ref_buf, const std::vector<uint8_t> &act_buf,
-                           uint32_t index)
-  {
-    for (uint32_t e = 0; e < ref_buf.size() / sizeof(T); e++)
-    {
-      T expected = reinterpret_cast<const T *>(ref_buf.data())[e];
-      T actual = reinterpret_cast<const T *>(act_buf.data())[e];
-      EXPECT_EQ(expected, actual) << "Output #" << index << ", Element Index : " << e;
-    }
-  }
-
-  void compareBuffersExactBool(const std::vector<uint8_t> &ref_buf,
-                               const std::vector<uint8_t> &act_buf, uint32_t index)
-  {
-    for (uint32_t e = 0; e < ref_buf.size() / sizeof(uint8_t); e++)
-    {
-      uint8_t ref_raw = reinterpret_cast<const uint8_t *>(ref_buf.data())[e];
-      bool expected = (ref_raw != 0 ? true : false);
-      uint8_t act_raw = reinterpret_cast<const uint8_t *>(act_buf.data())[e];
-      bool actual = (act_raw != 0 ? true : false);
-      EXPECT_EQ(expected, actual) << "Output #" << index << ", Element Index : " << e;
-    }
-  }
-
-protected:
-  SessionObjectGeneric _so;
-  std::unique_ptr<GenModelTestContext> _context;
-};
-
-#endif // __NNFW_API_TEST_GEN_MODEL_TEST_H__
diff --git a/tests/nnfw_api/src/GenModelTests.test.cc b/tests/nnfw_api/src/GenModelTests.test.cc
deleted file mode 100644 (file)
index 53a3571..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @file This file contains miscellaneous GenModelTest test cases.
- *
- */
-
-#include "GenModelTest.h"
-
-#include <memory>
-
-TEST_F(GenModelTest, UnusedConstOutputOnly)
-{
-  // A single tensor which is constant
-  CircleGen cgen;
-  uint32_t const_buf = cgen.addBuffer(std::vector<float>{9, 8, 7, 6});
-  int out_const = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, const_buf});
-  cgen.setInputsAndOutputs({}, {out_const});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({}, {{9, 8, 7, 6}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, UnusedConstOutputAndAdd)
-{
-  // A single tensor which is constant + an Add op
-  CircleGen cgen;
-  uint32_t rhs_buf = cgen.addBuffer(std::vector<float>{5, 4, 7, 4});
-  uint32_t const_buf = cgen.addBuffer(std::vector<float>{9, 8, 7, 6});
-  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
-  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, rhs_buf});
-  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
-  int out_const = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, const_buf});
-  cgen.addOperatorAdd({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({lhs}, {out, out_const});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{1, 3, 2, 4}}, {{6, 7, 9, 8}, {9, 8, 7, 6}}));
-  _context->addTestCase(uniformTCD<float>({{0, 1, 2, 3}}, {{5, 5, 9, 7}, {9, 8, 7, 6}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, UsedConstOutput)
-{
-  // (( Input 1 )) ---------\
-  //                         |=> [ Add ] -> (( Output 1 ))
-  // (( Const Output 2 )) --<
-  //                         |=> [ Add ] -> (( Output 0 ))
-  // (( Input 0 )) ---------/
-  CircleGen cgen;
-  uint32_t rhs_buf = cgen.addBuffer(std::vector<float>{6, 4, 8, 1});
-  int in0 = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
-  int in1 = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
-  int out0 = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
-  int out1 = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
-  int const_out2 = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, rhs_buf});
-  cgen.addOperatorAdd({{in0, const_out2}, {out0}}, circle::ActivationFunctionType_NONE);
-  cgen.addOperatorAdd({{const_out2, in1}, {out1}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in0, in1}, {out0, out1, const_out2});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{1, 1, 1, 1}, {-1, -1, -1, -1}},
-                                          {{7, 5, 9, 2}, {5, 3, 7, 0}, {6, 4, 8, 1}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, TensorBothInputOutput)
-{
-  // A single tensor which is an input and an output at the same time
-  CircleGen cgen;
-  int t = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.setInputsAndOutputs({t}, {t});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{1, 3, 2, 4}}, {{1, 3, 2, 4}}));
-  _context->addTestCase(uniformTCD<float>({{100, 300, 200, 400}}, {{100, 300, 200, 400}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, TensorBothInputOutputCrossed)
-{
-  // Two tensors which are an input and an output at the same time
-  // But the order of inputs and outputs is changed.
-  CircleGen cgen;
-  int t1 = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
-  int t2 = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
-  cgen.setInputsAndOutputs({t1, t2}, {t2, t1});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{1}, {2}}, {{2}, {1}}));
-  _context->addTestCase(uniformTCD<float>({{100}, {200}}, {{200}, {100}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneTensor_TwoOutputs)
-{
-  CircleGen cgen;
-  int lhs = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
-  int rhs = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
-  int out = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorAdd({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({lhs, rhs}, {out, out}); // Same tensors are used twice as output
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{1, 1}, {2, 2}}, {{3, 3}, {3, 3}}));
-  _context->addTestCase(uniformTCD<float>({{2, 4}, {7, 4}}, {{9, 8}, {9, 8}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneTensor_ThreeOutputs)
-{
-  CircleGen cgen;
-  int lhs = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
-  int rhs = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
-  int out = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorAdd({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({lhs, rhs}, {out, out, out}); // Same tensors are used 3 times as output
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{1}, {2}}, {{3}, {3}, {3}}));
-  _context->addTestCase(uniformTCD<float>({{2}, {7}}, {{9}, {9}, {9}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneTensor_InputAndTwoOutputs)
-{
-  CircleGen cgen;
-  int t = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.setInputsAndOutputs({t}, {t, t}); // Same tensor is an input and 2 outputs
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{1, 1}}, {{1, 1}, {1, 1}}));
-  _context->addTestCase(uniformTCD<float>({{2, 4}}, {{2, 4}, {2, 4}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneTensor_InputAndTwoOutputsUsed)
-{
-  CircleGen cgen;
-  int t = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
-  int o = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorNeg({{t}, {o}});
-  cgen.setInputsAndOutputs({t}, {t, t, o}); // Same tensor is an input and 2 outputs
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{1, 1}}, {{1, 1}, {1, 1}, {-1, -1}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneTensor_ConstAndThreeOutputs)
-{
-  CircleGen cgen;
-  uint32_t const_buf = cgen.addBuffer(std::vector<float>{2, 5});
-  int t = cgen.addTensor({{2}, circle::TensorType_FLOAT32, const_buf});
-  cgen.setInputsAndOutputs({}, {t, t, t}); // A const tensor is 3 outputs
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({}, {{2, 5}, {2, 5}, {2, 5}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, Reshape_with_shape_param_as_const)
-{
-  CircleGen cgen;
-  auto i32 = circle::TensorType::TensorType_INT32;
-
-  int input = cgen.addTensor({{4}, i32});
-
-  std::vector<int32_t> new_shape_data{2, 2}; // const of value [2, 2]
-  uint32_t new_shape_buf = cgen.addBuffer(new_shape_data);
-  int new_shape = cgen.addTensor({{2}, i32, new_shape_buf});
-
-  int out = cgen.addTensor({{2, 2}, i32});
-
-  // reshape with new_shape param
-  cgen.addOperatorReshape({{input, new_shape}, {out}}, &new_shape_data);
-  cgen.setInputsAndOutputs({input}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<int32_t>({{1, 2, 3, 4}}, {{1, 2, 3, 4}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_Reshape_with_shape_param_as_const)
-{
-  // We will ses if Reshape with shape param can generate error during compilation if param is wrong
-  CircleGen cgen;
-  auto i32 = circle::TensorType::TensorType_INT32;
-
-  int input = cgen.addTensor({{4}, i32});
-
-  std::vector<int32_t> wrong_new_shape_data{2, 3}; // not match with input shape
-  uint32_t new_shape_buf = cgen.addBuffer(wrong_new_shape_data);
-  int new_shape = cgen.addTensor({{2}, i32, new_shape_buf});
-
-  int out = cgen.addTensor({{2, 2}, i32});
-
-  cgen.addOperatorReshape({{input, new_shape}, {out}}, &wrong_new_shape_data);
-  cgen.setInputsAndOutputs({input}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<int32_t>({{1, 2, 3, 4}}, {{1, 2, 3, 4}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  _context->expectFailCompile();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, Reshape_with_shape_param_as_const_float)
-{
-  CircleGen cgen;
-  auto f32 = circle::TensorType::TensorType_FLOAT32;
-  int input = cgen.addTensor({{4}, f32});
-
-  std::vector<int32_t> new_shape_data{2, 2}; // const of value [2, 2]
-  uint32_t new_shape_buf = cgen.addBuffer(new_shape_data);
-  int new_shape = cgen.addTensor({{2}, f32, new_shape_buf});
-  int out = cgen.addTensor({{2, 2}, f32});
-
-  // reshape with new_shape param
-  cgen.addOperatorReshape({{input, new_shape}, {out}}, &new_shape_data);
-  cgen.setInputsAndOutputs({input}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{1, 2, 3, 4}}, {{1, 2, 3, 4}}));
-  _context->setBackends({"gpu_cl"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_Reshape_with_shape_param_as_const_float)
-{
-  // We will ses if Reshape with shape param can generate error during compilation if param is wrong
-  CircleGen cgen;
-  auto f32 = circle::TensorType::TensorType_FLOAT32;
-
-  int input = cgen.addTensor({{4}, f32});
-
-  std::vector<int32_t> wrong_new_shape_data{2, 3}; // not match with input shape
-  uint32_t new_shape_buf = cgen.addBuffer(wrong_new_shape_data);
-  int new_shape = cgen.addTensor({{2}, f32, new_shape_buf});
-
-  int out = cgen.addTensor({{2, 2}, f32});
-
-  cgen.addOperatorReshape({{input, new_shape}, {out}}, &wrong_new_shape_data);
-  cgen.setInputsAndOutputs({input}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{1, 2, 3, 4}}, {{1, 2, 3, 4}}));
-  _context->setBackends({"gpu_cl"});
-
-  _context->expectFailCompile();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, Reshape_without_shape_param)
-{
-  CircleGen cgen;
-  auto i32 = circle::TensorType::TensorType_INT32;
-
-  int input = cgen.addTensor({{4}, i32});
-  int new_shape = cgen.addTensor({{2}, i32}); // reshape to 2D tensor
-  int out = cgen.addTensor({{}, i32}); // exact shape is not unknown since ouput is dynamic tensor
-
-  // reshape with new_shape param
-  cgen.addOperatorReshape({{input, new_shape}, {out}} /* no new_shape param */);
-  cgen.setInputsAndOutputs({input, new_shape}, {out});
-
-  CircleGen::Shape new_shape_val{2, 2};
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<int32_t>({{1, 2, 3, 4}, new_shape_val}, {{1, 2, 3, 4}}));
-  _context->output_sizes(0, sizeof(int32_t) * 4);
-  _context->setBackends({"cpu" /* "acl_cl", "acl_neon" does not support dynamic tensor */});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_Reshape_without_shape_param)
-{
-  // We will ses if Reshape without shape param can generate error whiile running
-  CircleGen cgen;
-  auto i32 = circle::TensorType::TensorType_INT32;
-
-  int input = cgen.addTensor({{4}, i32});
-  int new_shape = cgen.addTensor({{2}, i32}); // reshape to 2D tensor
-  int out = cgen.addTensor({{}, i32}); // exact shape is not unknown since ouput is dynamic tensor
-
-  // reshape with new_shape param
-  cgen.addOperatorReshape({{input, new_shape}, {out}} /* no new_shape param */);
-  cgen.setInputsAndOutputs({input, new_shape}, {out});
-
-  CircleGen::Shape wrong_new_shape_val{2, 3};
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  auto tc = uniformTCD<int32_t>({{1, 2, 3, 4}, wrong_new_shape_val}, {{1, 2, 3, 4}});
-  tc.expectFailRun();
-  _context->addTestCase(tc);
-  _context->setBackends({"cpu" /* "acl_cl", "acl_neon" does not support dynamic tensor */});
-
-  SUCCEED();
-}
-
-// test to check model that has op->while->op
-TEST_F(GenModelTest, while_with_input_output)
-{
-  // The model looks just like the below pseudocode
-  //
-  //   x = cast(int to float)
-  //   while (x < 100.0)
-  //   {
-  //     x = x + 10.0;
-  //   }
-  //   x = cast(float to int)
-
-  CircleGen cgen;
-  std::vector<float> incr_data{10};
-  uint32_t incr_buf = cgen.addBuffer(incr_data);
-  std::vector<float> end_data{100};
-  uint32_t end_buf = cgen.addBuffer(end_data);
-
-  // primary subgraph
-  {
-    int model_in = cgen.addTensor({{1}, circle::TensorType_INT32});
-    int cast_out = cgen.addTensor({{1}, circle::TensorType_FLOAT32});
-    int while_out = cgen.addTensor({{1}, circle::TensorType_FLOAT32});
-    int model_out = cgen.addTensor({{1}, circle::TensorType_INT32});
-
-    cgen.addOperatorCast({{model_in}, {cast_out}}, circle::TensorType_INT32,
-                         circle::TensorType_FLOAT32);
-    cgen.addOperatorWhile({{cast_out}, {while_out}}, 1, 2);
-    cgen.addOperatorCast({{while_out}, {model_out}}, circle::TensorType_FLOAT32,
-                         circle::TensorType_INT32);
-
-    cgen.setInputsAndOutputs({model_in}, {model_out});
-  }
-
-  // cond subgraph
-  {
-    cgen.nextSubgraph();
-    int x = cgen.addTensor({{1}, circle::TensorType_FLOAT32});
-    int end = cgen.addTensor({{1}, circle::TensorType_FLOAT32, end_buf});
-    int result = cgen.addTensor({{1}, circle::TensorType_BOOL});
-    cgen.addOperatorLess({{x, end}, {result}});
-    cgen.setInputsAndOutputs({x}, {result});
-  }
-
-  // body subgraph
-  {
-    cgen.nextSubgraph();
-    int x_in = cgen.addTensor({{1}, circle::TensorType_FLOAT32});
-    int incr = cgen.addTensor({{1}, circle::TensorType_FLOAT32, incr_buf});
-    int x_out = cgen.addTensor({{1}, circle::TensorType_FLOAT32});
-    cgen.addOperatorAdd({{x_in, incr}, {x_out}}, circle::ActivationFunctionType_NONE);
-    cgen.setInputsAndOutputs({x_in}, {x_out});
-  }
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<int>({{0}}, {{100}}));
-  _context->setBackends({"cpu"});
-
-  SUCCEED();
-}
diff --git a/tests/nnfw_api/src/GenModelTests/BranchModelTrain.test.cc b/tests/nnfw_api/src/GenModelTests/BranchModelTrain.test.cc
new file mode 100644 (file)
index 0000000..4cf36f3
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+TEST_F(GenModelTrain, BranchOps_FC_Add)
+{
+  // (( Input 0 )) -> [ FC ] ----\
+  //                              |=> [ Add ] -> (( Output 0 ))
+  // (( Input 1 )) --------------/
+  {
+    CirclePlusGen cgen;
+
+    uint32_t weight_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    int input0 = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int input1 = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int weight = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+    int bias = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+    int fc_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorFullyConnected({{input0, weight, bias}, {fc_output}});
+    cgen.addOperatorAdd({{fc_output, input1}, {output}},
+                        circle::ActivationFunctionType::ActivationFunctionType_NONE);
+    cgen.setInputsAndOutputs({input0, input1}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(uniformTCD<float>(
+      {{{1, 3}, {0, 1, 2, 3, 4, 5, 6, 7}}, {{2, 1}, {7, 6, 5, 4, 3, 2, 1, 0}}}, // inputs
+      {{{2, 1, 5, 5, 2, 1, 5, 5}}, {{2, 1, 5, 5, 2, 1, 5, 6}}},                 // expected
+      {{9.2218f}, {8.9554f}, {8.7044f}, {8.4678f}}                              // loss
+      ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, BranchOps_FC_Sub)
+{
+  // (( Input 0 )) --------------\
+  //                              |=> [ Sub ] -> (( Output 0 ))
+  // (( Input 1 )) -> [ FC ] ----/
+  {
+    CirclePlusGen cgen;
+
+    uint32_t weight_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    int input0 = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int input1 = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int weight = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+    int bias = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+    int fc_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorFullyConnected({{input1, weight, bias}, {fc_output}});
+    cgen.addOperatorSub({{input0, fc_output}, {output}},
+                        circle::ActivationFunctionType::ActivationFunctionType_NONE);
+    cgen.setInputsAndOutputs({input0, input1}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(uniformTCD<float>(
+      {{{0, 1, 2, 3, 4, 5, 1, 3}, {6, 7}}, {{5, 4, 3, 2, 1, 0, 2, 1}, {7, 6}}}, // inputs
+      {{{2, 1, 5, 5, 2, 1, 5, 5}}, {{2, 1, 5, 5, 2, 1, 5, 6}}},                 // expected
+      {{7.3265f}, {4.6811f}, {3.6735f}, {3.2863f}}                              // loss
+      ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+
+  // (( Input 0 )) -> [ FC ] -> (fc_out) --------------------------╲
+  //                                    â•²                           |=> [ Add ] -> (( Output 0 ))
+  //                                     â•²-> [ Relu6 ]⎼> (ea_out) -╱
+  {
+    CirclePlusGen cgen;
+
+    uint32_t weight_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    int input0 = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int weight = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+    int bias = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+    int fc_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int ea_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorFullyConnected({{input0, weight, bias}, {fc_output}});
+    cgen.addOperatorRelu6({{fc_output}, {ea_output}});
+    cgen.addOperatorAdd({{fc_output, ea_output}, {output}},
+                        circle::ActivationFunctionType::ActivationFunctionType_NONE);
+    cgen.setInputsAndOutputs({input0}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{1, 3}}, {{2, 1}}},                                     // inputs
+                        {{{2, 1, 5, 5, 2, 1, 5, 5}}, {{2, 1, 5, 5, 2, 1, 5, 6}}}, // expected
+                        // TODO Modify loss values to results of tensorflow
+                        {{14.0124f}, {11.0036f}, {8.1681f}, {6.0974f}} // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+
+  // (( Input 0 )) -> [ FC ] -> (fc1_out) ------------------------╲
+  //                                     â•²                         |=> [ Sub ] -> (( Output 0 ))
+  //                                      â•²-> [ FC ]⎼> (fc2_out) -╱
+  {
+    CirclePlusGen cgen;
+
+    uint32_t weight1_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias1_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    uint32_t weight2_buf = cgen.addBuffer(std::vector<float>(8 * 8, 0.f));
+    uint32_t bias2_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    int input0 = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int weight1 = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight1_buf});
+    int bias1 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias1_buf});
+    int fc1_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int weight2 = cgen.addTensor({{8, 8}, circle::TensorType::TensorType_FLOAT32, weight2_buf});
+    int bias2 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias2_buf});
+    int fc2_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorFullyConnected({{input0, weight1, bias1}, {fc1_output}});
+    cgen.addOperatorFullyConnected({{fc1_output, weight2, bias2}, {fc2_output}});
+    cgen.addOperatorSub({{fc1_output, fc2_output}, {output}},
+                        circle::ActivationFunctionType::ActivationFunctionType_NONE);
+    cgen.setInputsAndOutputs({input0}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{6, 7}}, {{7, 6}}},                                     // inputs
+                        {{{2, 1, 5, 7, 2, 5, 5, 5}}, {{2, 1, 5, 2, 2, 1, 3, 6}}}, // expected
+                        // TODO Modify loss values to results of tensorflow
+                        {{12.9477f}, {5.79475f}, {3.0031f}, {2.3388f}} // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, BranchOps_FC_Mul)
+{
+  // (( Input 0 )) -> [ FC ] ----\
+  //                              |=> [ Mul ] -> [ FC ] -> (( Output 0 ))
+  // (( Input 1 )) -> [ FC ] ----/
+  {
+    CirclePlusGen cgen;
+
+    uint32_t weight0_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias0_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    uint32_t weight1_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias1_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    uint32_t weight2_buf = cgen.addBuffer(std::vector<float>(8 * 8, 0.f));
+    uint32_t bias2_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    int input0 = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int input1 = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int weight0 = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight0_buf});
+    int weight1 = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight1_buf});
+    int weight2 = cgen.addTensor({{8, 8}, circle::TensorType::TensorType_FLOAT32, weight2_buf});
+    int bias0 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias0_buf});
+    int bias1 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias1_buf});
+    int bias2 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias2_buf});
+    int fc_output0 = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int fc_output1 = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int mul_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorFullyConnected({{input0, weight0, bias0}, {fc_output0}});
+    cgen.addOperatorFullyConnected({{input1, weight1, bias1}, {fc_output1}});
+    cgen.addOperatorMul({{fc_output0, fc_output1}, {mul_output}},
+                        circle::ActivationFunctionType::ActivationFunctionType_NONE);
+    cgen.addOperatorFullyConnected({{mul_output, weight2, bias2}, {output}});
+    cgen.setInputsAndOutputs({input0, input1}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{0, 3}, {6, 7}}, {{5, 4}, {7, 6}}},                     // inputs
+                        {{{3, 2, 1, 2, 5, 6, 1, 0}}, {{2, 1, 5, 5, 2, 1, 5, 6}}}, // expected
+                        {{12.5488f}, {12.4590f}, {12.3701f}, {12.2822f}}          // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+
+  // (( Input 0 )) -> [ FC ] -> (fc1_out) ------------------------╲
+  //                                     â•²                         |=> [ Mul ] -> (( Output 0 ))
+  //                                      â•²-> [ FC ]⎼> (fc2_out) -╱
+  {
+    CirclePlusGen cgen;
+
+    uint32_t weight1_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias1_buf = cgen.addBuffer(std::vector<float>(8, 1.f));
+    uint32_t weight2_buf = cgen.addBuffer(std::vector<float>(8 * 8, 0.f));
+    uint32_t bias2_buf = cgen.addBuffer(std::vector<float>(8, 1.f));
+    int input0 = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int weight1 = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight1_buf});
+    int bias1 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias1_buf});
+    int fc1_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int weight2 = cgen.addTensor({{8, 8}, circle::TensorType::TensorType_FLOAT32, weight2_buf});
+    int bias2 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias2_buf});
+    int fc2_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorFullyConnected({{input0, weight1, bias1}, {fc1_output}});
+    cgen.addOperatorFullyConnected({{fc1_output, weight2, bias2}, {fc2_output}});
+    cgen.addOperatorMul({{fc1_output, fc2_output}, {output}},
+                        circle::ActivationFunctionType::ActivationFunctionType_RELU6);
+    cgen.setInputsAndOutputs({input0}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{2, 3}}, {{5, 4}}},                                     // inputs
+                        {{{3, 2, 1, 2, 5, 6, 1, 3}}, {{2, 1, 5, 5, 2, 1, 5, 6}}}, // expected
+                        // TODO Modify loss values to results of tensorflow
+                        {{7.6864f}, {5.6564f}, {3.7944f}, {3.1894f}} // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
diff --git a/tests/nnfw_api/src/GenModelTests/General.test.cc b/tests/nnfw_api/src/GenModelTests/General.test.cc
new file mode 100644 (file)
index 0000000..2a279db
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file This file contains miscellaneous GenModelTest and GenModelTrain test cases.
+ *
+ */
+
+#include "GenModelTest.h"
+#include "GenModelTrain.h"
+
+#include <memory>
+
+TEST_F(GenModelTest, UnusedConstOutputOnly)
+{
+  // A single tensor which is constant
+  CircleGen cgen;
+  uint32_t const_buf = cgen.addBuffer(std::vector<float>{9, 8, 7, 6});
+  int out_const = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, const_buf});
+  cgen.setInputsAndOutputs({}, {out_const});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({}, {{9, 8, 7, 6}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, UnusedConstOutputAndAdd)
+{
+  // A single tensor which is constant + an Add op
+  CircleGen cgen;
+  uint32_t rhs_buf = cgen.addBuffer(std::vector<float>{5, 4, 7, 4});
+  uint32_t const_buf = cgen.addBuffer(std::vector<float>{9, 8, 7, 6});
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, rhs_buf});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out_const = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, const_buf});
+  cgen.addOperatorAdd({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs}, {out, out_const});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{1, 3, 2, 4}}, {{6, 7, 9, 8}, {9, 8, 7, 6}}));
+  _context->addTestCase(uniformTCD<float>({{0, 1, 2, 3}}, {{5, 5, 9, 7}, {9, 8, 7, 6}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, UsedConstOutput)
+{
+  // (( Input 1 )) ---------\
+  //                         |=> [ Add ] -> (( Output 1 ))
+  // (( Const Output 2 )) --<
+  //                         |=> [ Add ] -> (( Output 0 ))
+  // (( Input 0 )) ---------/
+  CircleGen cgen;
+  uint32_t rhs_buf = cgen.addBuffer(std::vector<float>{6, 4, 8, 1});
+  int in0 = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int in1 = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out0 = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out1 = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int const_out2 = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, rhs_buf});
+  cgen.addOperatorAdd({{in0, const_out2}, {out0}}, circle::ActivationFunctionType_NONE);
+  cgen.addOperatorAdd({{const_out2, in1}, {out1}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in0, in1}, {out0, out1, const_out2});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{1, 1, 1, 1}, {-1, -1, -1, -1}},
+                                          {{7, 5, 9, 2}, {5, 3, 7, 0}, {6, 4, 8, 1}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, TensorBothInputOutput)
+{
+  // A single tensor which is an input and an output at the same time
+  CircleGen cgen;
+  int t = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.setInputsAndOutputs({t}, {t});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{1, 3, 2, 4}}, {{1, 3, 2, 4}}));
+  _context->addTestCase(uniformTCD<float>({{100, 300, 200, 400}}, {{100, 300, 200, 400}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, TensorBothInputOutputCrossed)
+{
+  // Two tensors which are an input and an output at the same time
+  // But the order of inputs and outputs is changed.
+  CircleGen cgen;
+  int t1 = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
+  int t2 = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.setInputsAndOutputs({t1, t2}, {t2, t1});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{1}, {2}}, {{2}, {1}}));
+  _context->addTestCase(uniformTCD<float>({{100}, {200}}, {{200}, {100}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneTensor_TwoOutputs)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorAdd({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out, out}); // Same tensors are used twice as output
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{1, 1}, {2, 2}}, {{3, 3}, {3, 3}}));
+  _context->addTestCase(uniformTCD<float>({{2, 4}, {7, 4}}, {{9, 8}, {9, 8}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneTensor_ThreeOutputs)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorAdd({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out, out, out}); // Same tensors are used 3 times as output
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{1}, {2}}, {{3}, {3}, {3}}));
+  _context->addTestCase(uniformTCD<float>({{2}, {7}}, {{9}, {9}, {9}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneTensor_InputAndTwoOutputs)
+{
+  CircleGen cgen;
+  int t = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.setInputsAndOutputs({t}, {t, t}); // Same tensor is an input and 2 outputs
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{1, 1}}, {{1, 1}, {1, 1}}));
+  _context->addTestCase(uniformTCD<float>({{2, 4}}, {{2, 4}, {2, 4}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneTensor_InputAndTwoOutputsUsed)
+{
+  CircleGen cgen;
+  int t = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
+  int o = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorNeg({{t}, {o}});
+  cgen.setInputsAndOutputs({t}, {t, t, o}); // Same tensor is an input and 2 outputs
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{1, 1}}, {{1, 1}, {1, 1}, {-1, -1}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneTensor_ConstAndThreeOutputs)
+{
+  CircleGen cgen;
+  uint32_t const_buf = cgen.addBuffer(std::vector<float>{2, 5});
+  int t = cgen.addTensor({{2}, circle::TensorType_FLOAT32, const_buf});
+  cgen.setInputsAndOutputs({}, {t, t, t}); // A const tensor is 3 outputs
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({}, {{2, 5}, {2, 5}, {2, 5}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, Reshape_with_shape_param_as_const)
+{
+  CircleGen cgen;
+  auto i32 = circle::TensorType::TensorType_INT32;
+
+  int input = cgen.addTensor({{4}, i32});
+
+  std::vector<int32_t> new_shape_data{2, 2}; // const of value [2, 2]
+  uint32_t new_shape_buf = cgen.addBuffer(new_shape_data);
+  int new_shape = cgen.addTensor({{2}, i32, new_shape_buf});
+
+  int out = cgen.addTensor({{2, 2}, i32});
+
+  // reshape with new_shape param
+  cgen.addOperatorReshape({{input, new_shape}, {out}}, &new_shape_data);
+  cgen.setInputsAndOutputs({input}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<int32_t>({{1, 2, 3, 4}}, {{1, 2, 3, 4}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_Reshape_with_shape_param_as_const)
+{
+  // We will ses if Reshape with shape param can generate error during compilation if param is wrong
+  CircleGen cgen;
+  auto i32 = circle::TensorType::TensorType_INT32;
+
+  int input = cgen.addTensor({{4}, i32});
+
+  std::vector<int32_t> wrong_new_shape_data{2, 3}; // not match with input shape
+  uint32_t new_shape_buf = cgen.addBuffer(wrong_new_shape_data);
+  int new_shape = cgen.addTensor({{2}, i32, new_shape_buf});
+
+  int out = cgen.addTensor({{2, 2}, i32});
+
+  cgen.addOperatorReshape({{input, new_shape}, {out}}, &wrong_new_shape_data);
+  cgen.setInputsAndOutputs({input}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<int32_t>({{1, 2, 3, 4}}, {{1, 2, 3, 4}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, Reshape_with_shape_param_as_const_float)
+{
+  CircleGen cgen;
+  auto f32 = circle::TensorType::TensorType_FLOAT32;
+  int input = cgen.addTensor({{4}, f32});
+
+  std::vector<int32_t> new_shape_data{2, 2}; // const of value [2, 2]
+  uint32_t new_shape_buf = cgen.addBuffer(new_shape_data);
+  int new_shape = cgen.addTensor({{2}, f32, new_shape_buf});
+  int out = cgen.addTensor({{2, 2}, f32});
+
+  // reshape with new_shape param
+  cgen.addOperatorReshape({{input, new_shape}, {out}}, &new_shape_data);
+  cgen.setInputsAndOutputs({input}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{1, 2, 3, 4}}, {{1, 2, 3, 4}}));
+  _context->setBackends({"gpu_cl"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_Reshape_with_shape_param_as_const_float)
+{
+  // We will ses if Reshape with shape param can generate error during compilation if param is wrong
+  CircleGen cgen;
+  auto f32 = circle::TensorType::TensorType_FLOAT32;
+
+  int input = cgen.addTensor({{4}, f32});
+
+  std::vector<int32_t> wrong_new_shape_data{2, 3}; // not match with input shape
+  uint32_t new_shape_buf = cgen.addBuffer(wrong_new_shape_data);
+  int new_shape = cgen.addTensor({{2}, f32, new_shape_buf});
+
+  int out = cgen.addTensor({{2, 2}, f32});
+
+  cgen.addOperatorReshape({{input, new_shape}, {out}}, &wrong_new_shape_data);
+  cgen.setInputsAndOutputs({input}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{1, 2, 3, 4}}, {{1, 2, 3, 4}}));
+  _context->setBackends({"gpu_cl"});
+
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, Reshape_without_shape_param)
+{
+  CircleGen cgen;
+  auto i32 = circle::TensorType::TensorType_INT32;
+
+  int input = cgen.addTensor({{4}, i32});
+  int new_shape = cgen.addTensor({{2}, i32}); // reshape to 2D tensor
+  int out = cgen.addTensor({{}, i32}); // exact shape is not unknown since ouput is dynamic tensor
+
+  // reshape with new_shape param
+  cgen.addOperatorReshape({{input, new_shape}, {out}} /* no new_shape param */);
+  cgen.setInputsAndOutputs({input, new_shape}, {out});
+
+  CircleGen::Shape new_shape_val{2, 2};
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<int32_t>({{1, 2, 3, 4}, new_shape_val}, {{1, 2, 3, 4}}));
+  _context->output_sizes(0, sizeof(int32_t) * 4);
+  _context->setBackends({"cpu" /* "acl_cl", "acl_neon" does not support dynamic tensor */});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_Reshape_without_shape_param)
+{
+  // We will ses if Reshape without shape param can generate error whiile running
+  CircleGen cgen;
+  auto i32 = circle::TensorType::TensorType_INT32;
+
+  int input = cgen.addTensor({{4}, i32});
+  int new_shape = cgen.addTensor({{2}, i32}); // reshape to 2D tensor
+  int out = cgen.addTensor({{}, i32}); // exact shape is not unknown since ouput is dynamic tensor
+
+  // reshape with new_shape param
+  cgen.addOperatorReshape({{input, new_shape}, {out}} /* no new_shape param */);
+  cgen.setInputsAndOutputs({input, new_shape}, {out});
+
+  CircleGen::Shape wrong_new_shape_val{2, 3};
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  auto tc = uniformTCD<int32_t>({{1, 2, 3, 4}, wrong_new_shape_val}, {{1, 2, 3, 4}});
+  tc.expectFailRun();
+  _context->addTestCase(tc);
+  _context->setBackends({"cpu" /* "acl_cl", "acl_neon" does not support dynamic tensor */});
+
+  SUCCEED();
+}
+
+// test to check model that has op->while->op
+TEST_F(GenModelTest, while_with_input_output)
+{
+  // The model looks just like the below pseudocode
+  //
+  //   x = cast(int to float)
+  //   while (x < 100.0)
+  //   {
+  //     x = x + 10.0;
+  //   }
+  //   x = cast(float to int)
+
+  CircleGen cgen;
+  std::vector<float> incr_data{10};
+  uint32_t incr_buf = cgen.addBuffer(incr_data);
+  std::vector<float> end_data{100};
+  uint32_t end_buf = cgen.addBuffer(end_data);
+
+  // primary subgraph
+  {
+    int model_in = cgen.addTensor({{1}, circle::TensorType_INT32});
+    int cast_out = cgen.addTensor({{1}, circle::TensorType_FLOAT32});
+    int while_out = cgen.addTensor({{1}, circle::TensorType_FLOAT32});
+    int model_out = cgen.addTensor({{1}, circle::TensorType_INT32});
+
+    cgen.addOperatorCast({{model_in}, {cast_out}}, circle::TensorType_INT32,
+                         circle::TensorType_FLOAT32);
+    cgen.addOperatorWhile({{cast_out}, {while_out}}, 1, 2);
+    cgen.addOperatorCast({{while_out}, {model_out}}, circle::TensorType_FLOAT32,
+                         circle::TensorType_INT32);
+
+    cgen.setInputsAndOutputs({model_in}, {model_out});
+  }
+
+  // cond subgraph
+  {
+    cgen.nextSubgraph();
+    int x = cgen.addTensor({{1}, circle::TensorType_FLOAT32});
+    int end = cgen.addTensor({{1}, circle::TensorType_FLOAT32, end_buf});
+    int result = cgen.addTensor({{1}, circle::TensorType_BOOL});
+    cgen.addOperatorLess({{x, end}, {result}});
+    cgen.setInputsAndOutputs({x}, {result});
+  }
+
+  // body subgraph
+  {
+    cgen.nextSubgraph();
+    int x_in = cgen.addTensor({{1}, circle::TensorType_FLOAT32});
+    int incr = cgen.addTensor({{1}, circle::TensorType_FLOAT32, incr_buf});
+    int x_out = cgen.addTensor({{1}, circle::TensorType_FLOAT32});
+    cgen.addOperatorAdd({{x_in, incr}, {x_out}}, circle::ActivationFunctionType_NONE);
+    cgen.setInputsAndOutputs({x_in}, {x_out});
+  }
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<int>({{0}}, {{100}}));
+  _context->setBackends({"cpu"});
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/ModelTestDynamicTensor.test.cc b/tests/nnfw_api/src/GenModelTests/ModelTestDynamicTensor.test.cc
new file mode 100644 (file)
index 0000000..0f7625b
--- /dev/null
@@ -0,0 +1,997 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <nnfw_internal.h>
+
+#include "common.h"
+#include "fixtures.h"
+#include "CircleGen.h"
+#include "GenModelTest.h"
+#include "NNPackages.h"
+
+// This macro can be used instead of using NNFW_ENSURE_SUCCESS especially with negative test.
+// E.g., setInputOutput() is written with this macro and the following check is available to check
+// if there's any error while setting input or output:
+//
+//  EXPECT_ANY_THROW(setInputOutput(...));
+//
+#define THROW_WHEN_NNFW_ERROR(result)                                  \
+  do                                                                   \
+  {                                                                    \
+    if (result != NNFW_STATUS_NO_ERROR)                                \
+      throw std::runtime_error("returning error on calling nnfw api"); \
+  } while (false)
+
+template <class CPP_TYPE> struct nnfw_type;
+
+template <> struct nnfw_type<float>
+{
+  static const NNFW_TYPE dtype = NNFW_TYPE_TENSOR_FLOAT32;
+};
+
+template <> struct nnfw_type<int32_t>
+{
+  static const NNFW_TYPE dtype = NNFW_TYPE_TENSOR_INT32;
+};
+
+// TODO Add more struct nnfw_type for other types when needed
+
+template <class T_INPUT, class T_OUT>
+void setInputOutput(nnfw_session *session, const std::vector<T_INPUT> &input,
+                    std::vector<T_OUT> &actual_output)
+{
+  NNFW_STATUS result;
+  result = nnfw_set_input(session, 0, nnfw_type<T_INPUT>::dtype, input.data(),
+                          sizeof(T_INPUT) * input.size());
+  THROW_WHEN_NNFW_ERROR(result);
+
+  result = nnfw_set_output(session, 0, nnfw_type<T_OUT>::dtype, actual_output.data(),
+                           sizeof(T_OUT) * actual_output.size());
+  THROW_WHEN_NNFW_ERROR(result);
+}
+
+template <class T_INPUT0, class T_INPUT1, class T_OUT>
+void setInputOutput(nnfw_session *session, const std::vector<T_INPUT0> &input0,
+                    const std::vector<T_INPUT1> &input1, std::vector<T_OUT> &actual_output)
+{
+  NNFW_STATUS result;
+  result = nnfw_set_input(session, 0, nnfw_type<T_INPUT0>::dtype, input0.data(),
+                          sizeof(T_INPUT0) * input0.size());
+  THROW_WHEN_NNFW_ERROR(result);
+
+  result = nnfw_set_input(session, 1, nnfw_type<T_INPUT1>::dtype, input1.data(),
+                          sizeof(T_INPUT1) * input1.size());
+  THROW_WHEN_NNFW_ERROR(result);
+
+  result = nnfw_set_output(session, 0, nnfw_type<T_OUT>::dtype, actual_output.data(),
+                           sizeof(T_OUT) * actual_output.size());
+  THROW_WHEN_NNFW_ERROR(result);
+}
+
+template <class T_OUTPUT>
+void verifyOutput(nnfw_session *session, const nnfw_tensorinfo expected_ti,
+                  const std::vector<T_OUTPUT> &expected, const std::vector<T_OUTPUT> &actual)
+{
+  uint32_t output_num = -1;
+  nnfw_tensorinfo t_out;
+  NNFW_ENSURE_SUCCESS(nnfw_output_size(session, &output_num));
+  NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(session, 0, &t_out));
+
+  ASSERT_EQ(output_num, 1);
+
+  // nnfw_tensorinfo of output
+  tensorInfoEqual(t_out, expected_ti);
+
+  // value of output
+  ASSERT_EQ(expected.size(), actual.size());
+  for (int i = 0; i < expected.size(); i++)
+  {
+    bool is_output_float = std::is_same<T_OUTPUT, float>::value;
+    if (is_output_float)
+      ASSERT_FLOAT_EQ(expected[i], actual[i]);
+    else
+      ASSERT_EQ(expected[i], actual[i]);
+  }
+}
+
+/**
+ * @brief Testing the following model:
+ *
+ * Testing the following model:
+ *       #1 = const(value = [-1.5, -1.0, -0.5, 0.5, 1.0, 1.5], shape=[2, 3])
+ *       #2 = placeholder (shape = [2])      <-------- this is an input
+ *       #3 = reshape(#1, #2)
+ *
+ * @note Run this test with "cpu" backend
+ */
+auto build_dynamic_Reshape()
+{
+  CircleGen cgen;
+
+  auto f32 = circle::TensorType::TensorType_FLOAT32;
+  auto i32 = circle::TensorType::TensorType_INT32;
+
+  std::vector<float> new_shape_data{-1.5, -1.0, -0.5, 0.5, 1.0, 1.5};
+  uint32_t input_buf = cgen.addBuffer(new_shape_data); // shape = [2, 3]
+  int input = cgen.addTensor({{2, 3}, f32, input_buf});
+  int new_shape = cgen.addTensor({{2}, i32});
+  int out = cgen.addTensor({{}, f32}); // scalar, meaning output shape is unspecified
+
+  CircleGen::Shape empty_new_shape;
+  cgen.addOperatorReshape({{input, new_shape}, {out}}, &empty_new_shape);
+  cgen.setInputsAndOutputs({new_shape}, {out});
+  auto cbuf = cgen.finish();
+  return cbuf;
+}
+
+TEST_F(GenModelTest, dynamic_reshape_from_2x3_to_3x2)
+{
+  const std::vector<int> new_shape{3, 2};
+  const std::vector<float> expected{-1.5, -1.0, -0.5, 0.5, 1.0, 1.5};
+
+  _context = std::make_unique<GenModelTestContext>(build_dynamic_Reshape());
+  {
+    _context->addTestCase(TestCaseData{}.addInput(new_shape).addOutput(expected));
+    _context->setBackends({"cpu"}); // Currently, dynamic tensor runs on "cpu" only
+    _context->output_sizes(0, sizeof(float) * expected.size());
+  }
+  // GenModelTest::teardown() will do the rest
+  SUCCEED();
+}
+
+/**
+ * @brief Negative test.
+ *        Reshape's first input has 6 values but trying to reshaping to [3, 3]
+ */
+TEST_F(GenModelTest, neg_reshape_from_2x3_to_wrong_3x3)
+{
+  const std::vector<int> wrong_shape{3, 3}; // wrong shape input
+  const std::vector<float> expected{0};     // whatever
+
+  _context = std::make_unique<GenModelTestContext>(build_dynamic_Reshape());
+  {
+
+    _context->addTestCase(TestCaseData{}.addInput(wrong_shape).addOutput(expected).expectFailRun());
+    _context->setBackends({"cpu"}); // Currently, dynamic tensor runs on "cpu" only
+    _context->output_sizes(0, sizeof(float) * expected.size());
+  }
+  // GenModelTest::teardown() will do the rest
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, reshape_multiple_executions)
+{
+  std::vector<int> new_shape;
+  std::vector<float> expected = {-1.5, -1.0, -0.5, 0.5, 1.0, 1.5};
+
+  _context = std::make_unique<GenModelTestContext>(build_dynamic_Reshape());
+  {
+    _context->addTestCase(TestCaseData{}.addInput<int>({3, 2}).addOutput(expected));
+    _context->addTestCase(TestCaseData{}.addInput<int>({1, 6}).addOutput(expected));
+    _context->addTestCase(TestCaseData{}.addInput<int>({6, 1}).addOutput(expected));
+
+    _context->setBackends({"cpu"}); // Currently, dynamic tensor runs on "cpu" only
+    _context->output_sizes(0, sizeof(float) * expected.size());
+  }
+  // GenModelTest::teardown() will do the rest
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_reshape_multiple_executions)
+{
+  std::vector<int> new_shape;
+  std::vector<float> expected = {-1.5, -1.0, -0.5, 0.5, 1.0, 1.5};
+
+  auto add_tcd = [&](const decltype(new_shape) &&new_shape, bool expect_fail_on_run) {
+    TestCaseData tcd;
+    tcd.addInput(new_shape).addOutput(expected);
+    if (expect_fail_on_run)
+      tcd.expectFailRun();
+    _context->addTestCase(tcd);
+  };
+
+  _context = std::make_unique<GenModelTestContext>(build_dynamic_Reshape());
+  {
+    bool EXPECT_FAIL_ON_RUN = true;
+    bool EXPECT_SUCCESS_ON_RUN = !EXPECT_FAIL_ON_RUN;
+
+    add_tcd({3, 2}, EXPECT_SUCCESS_ON_RUN);
+    add_tcd({1, 100}, EXPECT_FAIL_ON_RUN); // 1th tcd. wrong shape
+    add_tcd({6, 1}, EXPECT_SUCCESS_ON_RUN);
+
+    _context->setBackends({"cpu"}); // Currently, dynamic tensor runs on "cpu" only
+    _context->output_sizes(0, sizeof(float) * expected.size());
+  }
+  // GenModelTest::teardown() will do the rest
+  SUCCEED();
+}
+
+//
+// Unknown Dimension Test
+//    Trying to set unknown dim to other value before calling nnfw_prepare()
+//
+
+/**
+ * @brief Testing the following model:
+ *
+ *        #0 = placeholder([None, None])   # initially, shape is [1, 1]
+ *        #1 = placeholder([2, 3])
+ *        #2 = concat (#0, #1, axis=0)
+ *
+ *        Calling sequence:
+ *        - nnfw_set_input_tensorinfo(#0, [1, 3])    # now, [1, 3]
+ *        - nnfw_prepare()                 # this should work
+ *        - nnfw_set_input()
+ *        - nnfw_run()
+ *
+ * @note Run this test with "cpu" backend
+ */
+auto build_model_buf_Concatenation_unknwon_dims()
+{
+  // Model is not important
+  CircleGen cgen;
+  auto f32 = circle::TensorType::TensorType_FLOAT32;
+  int in1 = cgen.addTensor({{1, 1}, f32}); // consider this [None, None]
+  int in2 = cgen.addTensor({{2, 3}, f32});
+  int out = cgen.addTensor({{}, f32}); // scalar, meaning output shape is unspecified
+  cgen.addOperatorConcatenation({{in1, in2}, {out}}, 0, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in1, in2}, {out});
+  auto cbuf = cgen.finish();
+  return cbuf;
+}
+
+TEST(TestDynamicTensor, concat_unknown_dim_input0_to_2x3)
+{
+  nnfw_session *session = nullptr;
+  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
+  const auto model_buf = build_model_buf_Concatenation_unknwon_dims();
+  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, model_buf.buffer(), model_buf.size()));
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
+
+  const std::vector<float> input0 = {1, 2, 3};          // of shape [1, 3]
+  const std::vector<float> input1 = {4, 5, 6, 7, 8, 9}; // of shape [2, 3]
+
+  const std::vector<float> expected = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+  std::vector<float> actual_output(expected.size());
+
+  // input reshaping to [1, 3]
+  nnfw_tensorinfo ti = {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 3}};
+  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(session, 0, &ti));
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
+
+  setInputOutput(session, input0, input1, actual_output);
+
+  // Do inference
+  NNFW_STATUS res = nnfw_run(session);
+  NNFW_ENSURE_SUCCESS(res);
+
+  verifyOutput(session, {NNFW_TYPE_TENSOR_FLOAT32, 2, {3, 3}}, expected, actual_output);
+}
+
+/**
+ * @brief Negative Test: Testing the following model:
+ *
+ *        #0 = placeholder([None, None])         # initially, [1, 1]
+ *        #1 = placeholder([2, 3])
+ *        #2 = concat (#0, #1, axis=0)
+ *
+ *        Calling sequence:
+ *        - nnfw_set_input tensorinfo(#0, [3, 1]) # now [3, 1]
+ *        - nnfw_prepare()                        # should fail (shape mismatch)
+ *        - nnfw_set_input()
+ *        - nnfw_run()
+ *
+ * @note Run this test with "cpu" backend and "linear" executor
+ */
+TEST(TestDynamicTensor, neg_concat_input0_to_wrong_shape)
+{
+  nnfw_session *session = nullptr;
+  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
+  const auto model_buf = build_model_buf_Concatenation_unknwon_dims();
+  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, model_buf.buffer(), model_buf.size()));
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
+
+  const std::vector<float> input0 = {1, 2, 3};          // of shape [3, 1], wrong shape
+  const std::vector<float> input1 = {4, 5, 6, 7, 8, 9}; // of shape [2, 3]
+
+  std::vector<float> actual_output(100); // whatever size
+
+  // input reshaping to [3, 1]
+  nnfw_tensorinfo ti = {NNFW_TYPE_TENSOR_FLOAT32, 2, {3, 1}};
+  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(session, 0, &ti));
+
+  ASSERT_EQ(nnfw_prepare(session), NNFW_STATUS_ERROR);
+}
+
+//
+// test about calling nnfw_set_input_tensorinfo() after compilation
+//
+
+/**
+ * @brief Testing the following model, which has a binary operation:
+ *
+ *        #0 = placeholder([])
+ *        #1 = placeholder([1, 2, 3])
+ *        #2 = add (#0, #1)
+ *        #3 = add (#2, #2)
+ *
+ *        Calling sequence:
+ *        - nnfw_prepare()
+ *        - nnfw_set_input_tensorinfo(#0, [2, 2, 3]) // This will make #3 tensor's shape [2, 2, 3]
+ *        - nnfw_set_input()
+ *        - nnfw_run()
+ *
+ * @note Run this test with "cpu" backend
+ */
+auto build_model_buf_Add_unspecified_rank()
+{
+  // Model is not important
+  CircleGen cgen;
+  auto f32 = circle::TensorType::TensorType_FLOAT32;
+  int in1 = cgen.addTensor({{}, f32}); // scalar, meaning shape is unspecified
+  int in2 = cgen.addTensor({{1, 2, 3}, f32});
+  int op_out = cgen.addTensor({{}, f32}); // unspecified
+  int out = cgen.addTensor({{}, f32});    // unspecified
+  cgen.addOperatorAdd({{in1, in2}, {op_out}}, circle::ActivationFunctionType_NONE);
+  cgen.addOperatorAdd({{op_out, op_out}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in1, in2}, {out});
+  auto cbuf = cgen.finish();
+  return cbuf;
+}
+
+TEST(TestDynamicTensor, set_input_tensorinfo_after_compilation_add)
+{
+  nnfw_session *session = nullptr;
+  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
+  const auto model_buf = build_model_buf_Add_unspecified_rank();
+  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, model_buf.buffer(), model_buf.size()));
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
+
+  // input reshaping to [2, 2, 3]
+  nnfw_tensorinfo input0_ti = {NNFW_TYPE_TENSOR_FLOAT32, 3, {2, 2, 3}};
+
+  std::vector<float> input0 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
+  std::vector<float> input1 = {0.1, 0.1, 0.1, 0.1, 0.1, 0.1};
+  std::vector<float> actual_output(12);
+  std::vector<float> expected_output = {1.1 * 2, 2.1 * 2, 3.1 * 2, 4.1 * 2,  5.1 * 2,  6.1 * 2,
+                                        7.1 * 2, 8.1 * 2, 9.1 * 2, 10.1 * 2, 11.1 * 2, 12.1 * 2};
+
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(session, 0, &input0_ti));
+
+  setInputOutput(session, input0, input1, actual_output);
+
+  // Do inference
+  NNFW_STATUS res = nnfw_run(session);
+  NNFW_ENSURE_SUCCESS(res);
+
+  verifyOutput(session, {NNFW_TYPE_TENSOR_FLOAT32, 3, {2, 3, 3}}, expected_output, actual_output);
+}
+
+/**
+ * @brief Testing the following model, which has a unary operation:
+ *
+ *        #0 = placeholder(shape = [4, 4])
+ *        #1 = neg (#0)
+ *
+ *        Calling sequence:
+ *        - nnfw_prepare()
+ *        - nnfw_set_input_tensorinfo(#0, [20, 50])
+ *        - nnfw_set_input()
+ *        - nnfw_run()
+ *
+ * @note Run this test with "cpu" backend
+ */
+
+auto build_model_buf_NEG()
+{
+  // Model is not important
+  CircleGen cgen;
+  int in = cgen.addTensor({{4, 4}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{4, 4}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorNeg({{in}, {out}});
+  cgen.setInputsAndOutputs({in}, {out});
+  auto cbuf = cgen.finish();
+  return cbuf;
+}
+
+TEST(TestDynamicTensor, set_input_tensorinfo_after_compilation_neg)
+{
+  nnfw_session *session = nullptr;
+  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
+  const auto model_buf = build_model_buf_NEG();
+  nnfw_load_circle_from_buffer(session, model_buf.buffer(), model_buf.size());
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
+
+  nnfw_tensorinfo input0_ti_original = {NNFW_TYPE_TENSOR_FLOAT32, 2, {4, 4}};
+
+  // input reshaping to [20, 50]
+  nnfw_tensorinfo input0_ti;
+  {
+    input0_ti.dtype = NNFW_TYPE_TENSOR_FLOAT32;
+    input0_ti.rank = 2;
+    input0_ti.dims[0] = 20;
+    input0_ti.dims[1] = 50;
+  }
+
+  std::vector<float> input0(20 * 50);
+  std::vector<float> actual_output(20 * 50);
+  std::vector<float> expected_output(20 * 50);
+
+  for (int i = 0; i < input0.size(); i++)
+  {
+    input0[i] = i * 1.1;
+    expected_output[i] = -1 * input0[i];
+  }
+
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
+
+  // input shape check
+  {
+    nnfw_tensorinfo ti = {};
+    NNFW_ENSURE_SUCCESS(nnfw_input_tensorinfo(session, 0, &ti));
+    ASSERT_TRUE(tensorInfoEqual(input0_ti_original, ti));
+  }
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(session, 0, &input0_ti));
+
+  // input shape check
+  {
+    nnfw_tensorinfo ti = {};
+    NNFW_ENSURE_SUCCESS(nnfw_input_tensorinfo(session, 0, &ti));
+    ASSERT_TRUE(tensorInfoEqual(input0_ti, ti));
+  }
+
+  setInputOutput(session, input0, actual_output);
+
+  // Do inference
+  NNFW_STATUS res = nnfw_run(session);
+  NNFW_ENSURE_SUCCESS(res);
+
+  // output value check
+  verifyOutput(session, {NNFW_TYPE_TENSOR_FLOAT32, 2, {20, 50}}, expected_output, actual_output);
+}
+
+using TestWhileDynamicModelLoaded = ValidationTestModelLoaded<NNPackages::WHILE_DYNAMIC>;
+
+// clang-format off
+const static std::vector<float> while_dynamic_input0{ 0.4325029254, 0.7332934141, 0.2969786823, 0.1540192217, 0.4608841240, 0.1523699313, 0.4334940016, 0.1022945493, 0.6928671598, 0.5891978741, 0.8283287883, 0.7041553259, 0.5243381262, 0.5623597503, 0.3395180404, 0.3212788701, 0.5248492956, 0.2551939189, 0.1338981092, 0.6406514645, 0.7089318633, 0.8164196610, 0.7689018846, 0.3551857173, 0.7668499351, 0.4942102134, 0.7345644236, 0.4689270556, 0.3495515287, 0.0768318549, 0.0868133679, 0.7823525667, 0.0791761801, 0.4397472143, 0.8150953054, 0.5074489713, 0.0895665437, 0.9451501966, 0.1064314246, 0.8803006411, 0.9903403521, 0.1259460151, 0.1889930069, 0.7466737032, 0.0553287826, 0.9712036252, 0.6352610588, 0.6301708817, 0.3079694211, 0.5367568731, 0.4070350230, 0.6815373302, 0.6948529482, 0.6158187985, 0.1485853940, 0.9162485600, 0.3622985184, 0.2672208250, 0.3396688998, 0.4135381579, 0.6450354457, 0.2386536747, 0.7072004080, 0.5289406180, 0.0643024296, 0.1969666779, 0.8667400479, 0.3396836221, 0.5878564715, 0.4551178813, 0.4318033755, 0.4376230836, 0.8211942315, 0.0230764486, 0.9005268812, 0.2147378176, 0.6036583781, 0.7161545157, 0.8246262074, 0.2989832759, 0.5491395593, 0.9779474735, 0.2006554008, 0.8227099776, 0.6018718481, 0.0132929254, 0.2212856710, 0.2032340616, 0.3059777319, 0.9094917178, 0.5409486890, 0.5595687032, 0.2436837852, 0.5649250150, 0.6730466485, 0.4421939552, 0.1432305574, 0.7053307891, 0.6284835935, 0.9216189384, 0.8686438799, 0.8385053873, 0.6248987913, 0.7697140574, 0.9808958173, 0.7571622133, 0.2297872156, 0.4201298952, 0.1305913031, 0.4572514296, 0.3072260618, 0.4668756723, 0.1919649392, 0.2050305754, 0.6062370539, 0.0006580966, 0.6217135191, 0.5123317838, 0.7305839658, 0.0610331446, 0.3614645600, 0.6455501914, 0.2919872701, 0.6446499228, 0.6293424964, 0.6947519779, 0.2680567801, 0.9756787419, 0.6422977448, 0.6911727786, 0.0343145914, 0.4764069021, 0.0876256451, 0.2926266789, 0.0487026349, 0.3558900952, 0.7788275480, 0.8566400409, 0.4791142642, 0.0595066175, 0.9609330297, 0.4075229764, 0.8758037090, 0.3485401869, 0.7945867181, 0.3457054794, 0.3327955306, 0.2870546579, 0.5697714090, 0.6144676208, 0.3251711428, 0.2342026234, 0.4153896868, 0.2149699926, 0.1064170301, 0.7240911722, 0.8196219206, 0.0208647959, 0.3081029952, 0.5742419958, 0.3027088642, 0.5005563498, 0.1707910597, 0.3358575106, 0.2290909439, 0.7788143754, 0.7611069679, 0.3525909781, 0.2308424413, 0.2585839927, 0.5973339677, 0.3728699684, 0.4975571036, 0.0781342834, 0.7119221091, 0.3926881850, 0.5501778126, 0.7364945412, 0.4965503812, 0.8785862923, 0.6024044752, 0.2638861239, 0.9093352556, 0.9069826007, 0.0359279662, 0.4043401778, 0.3457658887, 0.1013033912, 0.1810855120, 0.4946146905, 0.0194541160, 0.5453770161, 0.7965603471, 0.5493819714, 0.2422309667, 0.8376919031, 0.8350337148, 0.1898939908, 0.4576793313, 0.9535705447, 0.1353026628, 0.9474196434, 0.4256035388, 0.0255583692, 0.9593925476, 0.9245427847, 0.9780472517, 0.4356954992, 0.5673046708, 0.7346579432, 0.8614835143, 0.8782553673, 0.3395713866, 0.0013978065, 0.7640301585, 0.2504623234, 0.3626150787, 0.6888222694, 0.9404846430, 0.3519821763, 0.6855628490, 0.2415955663, 0.2107568830, 0.7718742490, 0.3419062793, 0.1280658394, 0.5126360059, 0.1722176671, 0.6543742418, 0.4206473231, 0.2138152719, 0.4514643848, 0.4293326437, 0.0042719250, 0.3195750117, 0.3874749541, 0.6262724400, 0.1620737463, 0.7417458892, 0.8521968126, 0.6405420303, 0.0713626966, 0.0474211276, 0.9068223834, 0.8541609645, 0.4279667437, 0.9738950133, 0.7167884707, 0.6812457442, 0.7938374281, 0.2077793330, 0.5163270831, 0.8487322927, 0.6320008039, 0.5116547942, 0.0056989277, 0.5253843665, 0.1517033428, 0.9921303988, 0.8305052519, 0.0771176443, 0.4621275961, 0.0299932379, 0.8129007220, 0.0946875364, 0.4544205368, 0.0143135618, 0.6373457313, 0.8202091455, 0.3447127640, 0.8560513258, 0.8079835773, 0.9697201252, 0.1521986276, 0.2269581258, 0.2245485932, 0.3396310210, 0.2649262249, 0.7799206972, 0.4020069242, 0.4444113672, 0.8123176098, 0.6460852027, 0.2041657269, 0.7889582515, 0.6526331902, 0.6626461744, 0.6049868464, 0.6901782155, 0.3364612758, 0.3053490818, 0.1905532777, 0.5362346172, 0.3618801832, 0.3485457003, 0.4509411156, 0.5986957550, 0.7858221531, 0.8822937012, 0.8280826807, 0.5261783004, 0.7312974334, 0.6962512732, 0.5243815780, 0.2492258698, 0.1734466404, 0.2547666430, 0.9950503111, 0.1781345457, 0.5630541444, 0.4552696049, 0.8874762058, 0.5965846777, 0.3575465977, 0.1213323772, 0.2790489793, 0.3157011569, 0.6218565702, 0.0304181967, 0.4112739265, 0.7361903787, 0.6753587723, 0.3667163849, 0.6275368929, 0.4185036719, 0.4791659117, 0.1246187463, 0.6651734114, 0.1778147966, 0.8796271682, 0.3000938296, 0.5996896029, 0.5020698309, 0.1601593345, 0.4467433393, 0.0287379269, 0.9011575580, 0.2722401917, 0.1642841995, 0.9468663335, 0.0238759480, 0.7811399102, 0.2070412934, 0.3746992052, 0.8473496437, 0.3498605192, 0.2693480551, 0.1523104310, 0.9660695791, 0.8762652278, 0.1654927284, 0.8743498921, 0.3143339157, 0.3896550536, 0.7256560922, 0.2408472896, 0.0930071324, 0.3269865215, 0.8070673347, 0.1218842566, 0.9943904281, 0.6901395917, 0.9491872787, 0.3617239892, 0.5459694862, 0.9408421516, 0.5354272127, 0.0377946161, 0.3319100142, 0.9823720455, 0.2373940945, 0.2439561784, 0.0767217800, 0.1102360934, 0.6404867172, 0.7430088520, 0.0165513344, 0.9841650128, 0.0532640740, 0.1635770351, 0.3721100390, 0.0598411299, 0.6548883319, 0.3812481761, 0.8741319180, 0.6431996226, 0.0550124273, 0.2009697258, 0.6922588348, 0.0673767105, 0.3385711610, 0.6945076585, 0.7870846987, 0.3323138356, 0.1601967812, 0.9595350623, 0.6049567461, 0.2068863660, 0.2562771440, 0.1041606516, 0.3444063365, 0.1464221030, 0.8932089210, 0.2040112168, 0.3407483399, 0.3251829743, 0.4777953327, 0.0534981787, 0.3613175154, 0.6707065105, 0.1188806742, 0.8228670359, 0.9907929897, 0.1556126177, 0.5561179519, 0.0124231419, 0.2054836601, 0.5855912566, 0.8455434442, 0.2268345803, 0.1841085702, 0.1096092239, 0.8316007257, 0.5046240687, 0.2195746899, 0.9222528338, 0.3633532226, 0.9383196831, 0.8803531528, 0.5124011636, 0.3909464478, 0.2731699646, 0.1102369502, 0.7489478588, 0.0600390583, 0.9290241599, 0.1041191891, 0.9347958565, 0.5584807396, 0.7331624031, 0.2267376930, 0.2868649662, 0.0016489516, 0.2301262319, 0.5107504129, 0.6500277519, 0.6766125560, 0.2019786686, 0.5890167952, 0.7182423472, 0.6890133023, 0.4442900419, 0.5760958791, 0.1364797056, 0.8246579766, 0.2527448535, 0.5444371700, 0.1561367512, 0.7551656961, 0.7171260715, 0.4264259040, 0.3883202970, 0.9166873693, 0.6557167768, 0.0264711548, 0.0761224255, 0.4693228602, 0.5476956964, 0.6261154413, 0.7666952610, 0.9579501152, 0.2581985295, 0.2322760671, 0.8342292905, 0.8143266439, 0.5771137476, 0.5815665126, 0.9772894382, 0.2359700650, 0.6501487494, 0.7841209769, 0.2793208659, 0.1745450795, 0.9626912475, 0.2373798192, 0.1235965416, 0.4632637799, 0.3763884604, 0.9971673489, 0.3533810079, 0.3203127384, 0.6102763414, 0.3859500289, 0.5929466486, 0.6658803821, 0.4130606949, 0.0352911949, 0.9713683128, 0.7546037436, 0.9780107737, 0.3970599473, 0.0187621433, 0.4941402078, 0.7670620680, 0.5360869765, 0.9634684920, 0.5996263027, 0.1895584762, 0.1214910895, 0.7381310463, 0.4301493466, 0.7403219938, 0.4817020297, 0.1843791455, 0.6473838091, 0.4138627350, 0.6825908422, 0.4481185675, 0.2030784935, 0.8468620777, 0.8059213758, 0.7525423169, 0.1854387224, 0.9046887755, 0.6654230952, 0.2029620409, 0.7164457440, 0.4172891080, 0.7797588110, 0.4135729969, 0.0026064927, 0.8375009894, 0.8355652690, 0.9187932014, 0.6724888086, 0.0276171323, 0.9106697440, 0.4562708735, 0.3417910039, 0.1569930464, 0.2029796541, 0.5049355626, 0.8143045306, 0.2432538420, 0.1068324223, 0.6258177757, 0.9749278426, 0.5378444791, 0.1657523215, 0.1930697113, 0.4833569825, 0.8000370264, 0.4315882921, 0.7571453452, 0.6069541574, 0.2073590159, 0.8702615499, 0.1951662153, 0.9303797483, 0.9241660833, 0.2795540988, 0.4241578877, 0.2383123934, 0.8627647758, 0.1700671613, 0.9635605216, 0.2514486313, 0.7766968012, 0.7126773596, 0.7009662986, 0.1317531914, 0.1318600327, 0.5509422421, 0.2159194350, 0.7851343751, 0.7231494188, 0.3523120880, 0.4999881089, 0.8202708960, 0.6340972185, 0.9181259274, 0.0057039275, 0.7197939754, 0.3580873907, 0.1026016176, 0.9657412767, 0.1973488480, 0.8099604845, 0.3302915096, 0.7635477781, 0.7097011805, 0.6271768212, 0.6583901644, 0.2334843278, 0.9448583126, 0.7434690595, 0.4068029821, 0.8815746307, 0.6311643124, 0.3891237080, 0.1507531852, 0.5215465426, 0.3248603344, 0.5837653279, 0.6689655185, 0.1362081915, 0.5130022764, 0.8519401550, 0.4397114217, 0.4129846096, 0.8706676960, 0.4183416367, 0.1135022715, 0.3501874208, 0.1142706573, 0.4111732543, 0.3972048163, 0.0740565360, 0.8445752263, 0.5659885406, 0.1107598469, 0.1261267066, 0.3106530905, 0.9623307586, 0.0014953646, 0.0421718284, 0.9182401299, 0.6180395484, 0.7947646379, 0.4402076006, 0.7980208993, 0.6131495237, 0.8885827065, 0.9406354427, 0.4568731785, 0.8838264346, 0.7086120248, 0.2050074339, 0.8598041534, 0.6360205412, 0.6444933414, 0.1086360887, 0.2146544755, 0.4044065177, 0.8566969037, 0.0974318087, 0.9650754929, 0.7885782719, 0.5817304850, 0.0668027699, 0.2600722611, 0.9546993971, 0.2609280050, 0.2063084394, 0.2960519791, 0.8144530654, 0.5386683941, 0.2757037580, 0.3237824142, 0.3469774723, 0.5878881812, 0.8034821153, 0.7495883107, 0.8035441637, 0.6059562564, 0.2713213861, 0.4108335674, 0.5539482832, 0.5046381950, 0.8435614705, 0.3766961098, 0.7583506107, 0.6175935268, 0.3487794399, 0.0058784639, 0.2900554240, 0.9057408571, 0.1079123169, 0.3200630546, 0.7326458693, 0.0237412248, 0.2757625282, 0.8461791873, 0.6101186872, 0.3705151379, 0.6318973899, 0.4013423026, 0.0222425349, 0.0391604938, 0.6966052055, 0.3186582327, 0.3277960122, 0.3301376998, 0.0874366611, 0.3782529831, 0.1412206143, 0.2574128807, 0.3423563242, 0.7656893730, 0.2097123116, 0.8109381199, 0.4845644534, 0.1744513661, 0.3877931535, 0.5369505286, 0.0147142150, 0.2457712293, 0.4901090264, 0.6373463869, 0.2244705260, 0.6722853184, 0.2888159454, 0.5694347620, 0.3042352200, 0.3482132256, 0.5619021654, 0.6760555506, 0.2648956776, 0.9160912037, 0.8973199129, 0.8901007175, 0.8260267973, 0.2438062280, 0.8338996172, 0.7751584649, 0.1436893344, 0.3578631580, 0.8111414909, 0.9454294443, 0.6478928924, 0.0714371502, 0.0711339787, 0.6473786235, 0.0266824700, 0.2442116290, 0.5528301001, 0.2558279037, 0.3684701622, 0.6729193330, 0.8132147193, 0.5830360651, 0.8655517101, 0.0593610443, 0.9748560190, 0.0221947283, 0.6729801893, 0.5001031756, 0.5116565824, 0.2824120522, 0.4552524984, 0.1693765223, 0.1908069402, 0.7663541436, 0.5339511037, 0.0649234429, 0.6125215292, 0.6771115661, 0.6019635797, 0.6840563416, 0.9653987288, 0.1369341463, 0.8428027630, 0.5227881670, 0.5990189910, 0.0936695337, 0.3645765185, 0.9354769588, 0.6745044589, 0.2816980183, 0.3783183694, 0.7331027389, 0.4139548242, 0.1671119779, 0.6703656316, 0.8604171872, 0.6643752456, 0.7547178268, 0.1386961490, 0.4443438351, 0.3267543018, 0.3348949254, 0.9952459931, 0.4534417391, 0.2089741081 };
+const static std::vector<float> while_dynamic_output0{ 0.0388205424, 0.0426156297, 0.0980401114, 0.0568757951, 0.1230962500, 0.0412184112, 0.0595490113, 0.4391007423, 0.0377574340, 0.0629260018 };
+// clang-format on
+
+TEST_F(TestWhileDynamicModelLoaded, run_verify)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session, "cpu"));
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session));
+
+  std::vector<float> actual_output0(10);
+
+  nnfw_tensorinfo ti = {NNFW_TYPE_TENSOR_FLOAT32, 3, {1, 28, 28}};
+  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(_session, 0, &ti));
+
+  setInputOutput(_session, while_dynamic_input0, actual_output0);
+
+  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+
+  // output check
+  verifyOutput(_session, {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 10}}, while_dynamic_output0,
+               actual_output0);
+}
+
+TEST_F(TestWhileDynamicModelLoaded, neg_run_verify)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session, "cpu"));
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session));
+
+  nnfw_tensorinfo ti = {NNFW_TYPE_TENSOR_FLOAT32, 3, {1, 28, 28}};
+  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(_session, 0, &ti));
+
+  // Insufficient size of output (10 or more is sufficient)
+  std::vector<float> actual_output0(9);
+
+  setInputOutput(_session, while_dynamic_input0, actual_output0);
+
+  ASSERT_EQ(nnfw_run(_session), NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE);
+}
+
+using TestIfDynamicModelLoaded = ValidationTestModelLoaded<NNPackages::IF_DYNAMIC>;
+
+// clang-format off
+const static std::vector<float> if_dynamic_input0{ 0.7106545568, 0.2156167328, 0.0837147385, 0.0381200500, 0.8007305861, 0.2976274490, 0.8563324213, 0.7781477571, 0.5745304823, 0.8303883672, 0.0862579569, 0.0544887781, 0.1988027841, 0.2230974138, 0.4716774523, 0.4606758952, 0.4920695722, 0.1058474109, 0.0391142406, 0.9550740719, 0.9775217772, 0.1644495875, 0.6734005809, 0.2771040201, 0.4015675485, 0.9389892220, 0.5739571452, 0.6168602109, 0.4262073934, 0.1955287308, 0.6361171603, 0.3251913190, 0.9311535358, 0.9403554797, 0.2734249830, 0.8866292834, 0.5992837548, 0.2142961770, 0.7889495492, 0.0741494149, 0.1030917764, 0.4724597037, 0.3861218989, 0.8098146915, 0.2832616270, 0.6557519436, 0.5689851642, 0.8294774294, 0.4495503902, 0.5395354629, 0.7472639680, 0.4290334582, 0.6575341225, 0.3844197690, 0.5194811821, 0.9411858320, 0.8186575174, 0.6588338614, 0.5179415941, 0.7074140310, 0.1678132862, 0.7229011655, 0.3164389431, 0.6544682384, 0.7210181952, 0.0454275832, 0.6507202387, 0.4012205899, 0.2719061375, 0.2579342127, 0.1064170823, 0.5994709730, 0.1010676920, 0.3968397975, 0.5670611858, 0.1786351353, 0.9127767086, 0.9268618822, 0.6603804827, 0.3673154712, 0.3415949941, 0.5930755138, 0.3685272932, 0.6884198189, 0.1833280921, 0.3941298127, 0.0632725284, 0.1516269594, 0.2316887528, 0.8105147481, 0.1674028039, 0.2784884572, 0.5205677748, 0.4399658442, 0.6527903080, 0.6785870790, 0.2533956766, 0.0617546029, 0.5094803572, 0.5204600096, 0.0249194298, 0.0450648703, 0.1241398007, 0.3705165386, 0.9986394048, 0.6402000785, 0.4894598126, 0.8702902794, 0.4500190616, 0.8115220070, 0.8781826496, 0.6121248603, 0.9077111483, 0.4646541476, 0.7442384362, 0.5584337115, 0.0265889056, 0.9247944951, 0.5661407709, 0.9730864167, 0.6722183824, 0.9564477801, 0.6998952627, 0.6105464697, 0.8297851086, 0.7167860270, 0.6002981067, 0.4256598651, 0.1964918524, 0.9581518769, 0.3121621907, 0.8813912272, 0.3803862929, 0.8825226426, 0.9783715010, 0.1397246420, 0.6996101737, 0.1947445422, 0.9981691837, 0.9528205395, 0.1440794915, 0.2994889319, 0.9605104923, 0.7394120097, 0.8036665916, 0.1226263046, 0.5607838035, 0.5100311637, 0.9977583289, 0.1812620014, 0.8162402511, 0.6829946637, 0.8054547906, 0.5318715572, 0.2573204339, 0.6401459575, 0.9395645857, 0.0523465686, 0.1189657971, 0.4010948837, 0.5229173303, 0.3700955212, 0.8600971103, 0.2058345824, 0.0952973440, 0.6578513980, 0.8096982241, 0.3292799890, 0.3189097345, 0.2228140533, 0.7665079832, 0.3701375425, 0.7601019740, 0.8501300216, 0.5380855203, 0.7509619594, 0.8447382450, 0.6025870442, 0.6957519054, 0.6805172563, 0.5877657533, 0.3472520709, 0.0291769207, 0.0723123997, 0.4284786880, 0.5264689922, 0.4927068353, 0.7379829884, 0.9378200173, 0.8644418716, 0.8671935797, 0.9434295297, 0.5507473350, 0.0760083497, 0.1079615131, 0.1603826135, 0.2987570167, 0.4970068038, 0.0533443913, 0.7932291627, 0.4054899216, 0.8708239794, 0.8852948546, 0.7709504366, 0.2500700951, 0.7328734398, 0.1770015359, 0.4787373245, 0.6746702790, 0.6232759953, 0.8252257109, 0.5074343681, 0.4582579136, 0.7136889100, 0.1850759387, 0.0999758169, 0.9016878009, 0.0968299136, 0.9786298275, 0.7106815577, 0.5932894945, 0.5901473165, 0.8644450903, 0.8777941465, 0.3545308709, 0.5543619394, 0.4764245450, 0.4866352081, 0.7842248678, 0.8535351157, 0.8261910677, 0.4928103089, 0.4883008599, 0.9132300615, 0.0520589016, 0.0571883246, 0.8107213974, 0.2263001502, 0.4195134640, 0.1585850269, 0.6892622709, 0.9932649732, 0.9146085382, 0.3438154757, 0.3597939610, 0.8383805156, 0.1434784085, 0.1592836231, 0.3735914230, 0.5118701458, 0.6597173810, 0.5932899714, 0.7643446326, 0.7639417052, 0.7257087231, 0.8367394209, 0.7241969705, 0.2863937616, 0.7383541465, 0.3918549418, 0.8693540096, 0.8002281189, 0.0121407788, 0.3702836633, 0.3193098009, 0.2857846618, 0.3450623155, 0.8419249654, 0.4484305680, 0.0768098459, 0.1011011526, 0.9832069874, 0.2806532979, 0.6486470103, 0.0038275064, 0.5200383663, 0.5825559497, 0.8526763320, 0.2604954541, 0.4765493274, 0.8257845044, 0.9679267406, 0.3583108485, 0.5755933523, 0.6114814878, 0.5805739164, 0.1076851040, 0.0532303862, 0.3102329671, 0.2268214077, 0.3422079682, 0.3890814781, 0.2123251557, 0.6259000301, 0.9530308843, 0.2377676368, 0.4969599247, 0.3911451399, 0.6869695187, 0.4768487513, 0.0319234431, 0.5153809190, 0.7592291832, 0.5699093938, 0.6517769098, 0.1294958293, 0.5191193819, 0.9886645675, 0.2082915604, 0.9330775738, 0.1966033280, 0.7179551721, 0.4047450423, 0.3280299902, 0.7132403255, 0.7453812361, 0.1643252373, 0.0279585645, 0.0323586352, 0.0771650672, 0.8751529455, 0.3228718042, 0.0091584828, 0.2462333292, 0.2639203966, 0.1246995181, 0.7825807929, 0.0825880542, 0.5019466281, 0.5546332598, 0.2470002472, 0.3974646032, 0.3941309452, 0.2988025546, 0.5270965099, 0.0565799475, 0.7965186834, 0.8401004672, 0.8962592483, 0.2836867571, 0.9854408503, 0.1736569554, 0.3543607295, 0.1489263922, 0.0296417754, 0.8644942045, 0.5768237114, 0.5055403709, 0.7033663988, 0.7610059381, 0.7680964470, 0.9276048541, 0.4661210179, 0.1926902831, 0.8331482410, 0.3478438258, 0.4423305690, 0.1226840168, 0.2631755769, 0.7300418615, 0.8501742482, 0.7732837200, 0.1645421237, 0.9328539968, 0.3299001455, 0.1737864316, 0.6760513186, 0.6878529191, 0.8000500202, 0.7643007040, 0.8427000046, 0.7743517756, 0.4847290516, 0.5107879639, 0.1321444362, 0.2521093190, 0.6971111894, 0.9226302505, 0.7618960738, 0.0798677281, 0.9345219731, 0.3526974618, 0.5779649615, 0.6659775376, 0.0080328183, 0.6179481745, 0.3388322592, 0.8871348500, 0.3849443495, 0.5805974007, 0.4485530853, 0.0118454825, 0.1535516083, 0.9892683029, 0.6305456758, 0.8417525887, 0.9201779366, 0.5443179011, 0.3694557250, 0.9480580688, 0.0420885272, 0.3705308735, 0.1857404709, 0.2711791396, 0.3184533417, 0.2894020677, 0.8524381518, 0.1369639933, 0.5524237156, 0.2515565455, 0.2611325383, 0.7106022239, 0.7720850706, 0.5917789340, 0.1294544786, 0.1406515092, 0.4081685841, 0.7773256898, 0.0337970816, 0.2720888555, 0.6040735841, 0.4713420272, 0.2154571265, 0.7050493360, 0.5699684024, 0.8653516769, 0.2943878472, 0.0710595697, 0.7601916790, 0.8260607719, 0.5490139127, 0.2270360142, 0.6353984475, 0.0237506367, 0.1613635123, 0.2657604814, 0.9112974405, 0.3940451145, 0.9857107997, 0.6584201455, 0.2996906042, 0.6385321617, 0.3025711179, 0.5442391634, 0.5316760540, 0.9278558493, 0.2960957289, 0.2758596539, 0.8092618585, 0.7210826278, 0.5532572269, 0.0433825813, 0.4293606579, 0.9231137037, 0.7861453891, 0.0529759154, 0.2881730795, 0.4177611172, 0.0751738325, 0.2110737860, 0.0087767169, 0.9394732714, 0.7669738531, 0.1285874546, 0.0892729312, 0.7701640129, 0.3619799912, 0.1591310948, 0.5716432333, 0.3634774089, 0.5689123273, 0.1703432053, 0.7500917912, 0.8368289471, 0.6899937391, 0.8733949065, 0.3469920754, 0.9645365477, 0.9452517629, 0.0622390397, 0.0313139819, 0.9253467917, 0.5542111993, 0.4027656317, 0.5191525817, 0.3981988430, 0.7461462021, 0.6761778593, 0.2998072505, 0.8195981979, 0.6851982474, 0.0545753241, 0.1639913172, 0.8172791600, 0.7425212264, 0.1970316321, 0.1586989313, 0.3941454589, 0.8775137067, 0.3532845676, 0.1445332468, 0.4015854299, 0.7155395746, 0.4261780679, 0.7957311273, 0.8265135884, 0.5879834294, 0.7252638340, 0.3942884803, 0.7504889965, 0.5733796358, 0.7747340798, 0.9431585670, 0.5627400875, 0.3371616900, 0.6190663576, 0.5733695626, 0.2214016914, 0.8767938614, 0.2509712279, 0.6909803748, 0.3777657151, 0.6170743704, 0.7373610735, 0.0204360615, 0.7325904369, 0.4920690358, 0.5081653595, 0.9917234182, 0.2093250901, 0.8361138105, 0.7211740017, 0.2606147230, 0.3064637780, 0.1124278903, 0.6320124269, 0.2425052077, 0.4785803258, 0.4747911394, 0.8021139503, 0.3956191838, 0.7217889428, 0.7445480227, 0.1360257119, 0.3709513843, 0.5552678704, 0.2192365974, 0.9431814551, 0.8592399359, 0.7907270789, 0.5545215607, 0.6895139813, 0.1169689223, 0.2043674886, 0.0381150991, 0.7708708644, 0.4759636819, 0.9230924845, 0.6857032776, 0.4432366490, 0.3041133285, 0.7970084548, 0.5629503727, 0.2329168320, 0.2320910394, 0.8098289967, 0.8152811527, 0.9269255996, 0.2628753185, 0.7178934216, 0.1607068628, 0.6057552695, 0.5256694555, 0.5559988022, 0.8001552820, 0.5592993498, 0.5585735440, 0.7596833110, 0.4926379025, 0.8108907342, 0.5142205954, 0.8292154074, 0.9844856262, 0.9281103611, 0.8271671534, 0.8411998153, 0.4101325572, 0.9839829803, 0.1782312542, 0.5126013756, 0.4867194891, 0.9041156173, 0.8752650619, 0.9434064627, 0.5353408456, 0.3405859768, 0.9340458512, 0.1240679324, 0.5371315479, 0.3755141199, 0.2990591526, 0.0670647249, 0.0626592115, 0.7673836946, 0.2539713681, 0.4617587030, 0.9303754568, 0.4884444177, 0.9808034897, 0.7934950590, 0.9362392426, 0.8001930714, 0.8370914459, 0.4767935276, 0.8847136497, 0.8713309765, 0.8301703334, 0.9254899621, 0.5875709057, 0.4544037282, 0.2598260045, 0.7427998781, 0.7183818817, 0.9003841877, 0.0916625410, 0.2609814405, 0.6743535399, 0.7733583450, 0.7338136435, 0.7596724033, 0.7973198891, 0.0015392932, 0.2874146104, 0.1189730167, 0.4800435603, 0.7962353230, 0.4249678552, 0.7483268380, 0.0146148857, 0.6297842860, 0.3471757770, 0.9144366980, 0.8106345534, 0.1789025515, 0.7346886992, 0.1539165080, 0.4280290008, 0.2338476181, 0.3317435384, 0.9998268485, 0.3580373228, 0.9422348738, 0.1251947135, 0.5737128258, 0.6803853512, 0.0485891216, 0.8118965626, 0.7890921235, 0.7665926218, 0.8405004144, 0.3489693701, 0.1429360062, 0.1063490957, 0.5086215734, 0.1312662065, 0.0978318676, 0.4471830130, 0.0830681920, 0.0757851526, 0.1809245348, 0.9280508757, 0.4107315242, 0.5944178104, 0.5625417829, 0.2328256220, 0.9285324812, 0.9903659821, 0.9403946996, 0.5126894712, 0.0232842807, 0.3405880928, 0.6531285644, 0.8213183880, 0.7210904360, 0.4180826247, 0.7917050719, 0.7738851309, 0.1693093032, 0.4396123290, 0.7139748335, 0.8910710216, 0.5668603778, 0.4374921620, 0.8098046780, 0.4076835811, 0.1027061120, 0.5390046835, 0.0044658147, 0.8642644286, 0.8590582609, 0.2715446949, 0.8128718734, 0.7381446362, 0.3621498942, 0.5211849809, 0.6139976382, 0.8567240834, 0.1329502016, 0.2441152930, 0.4219030440, 0.1751736850, 0.6326612234, 0.3929811120, 0.0947103724, 0.1078760102, 0.8769059777, 0.1599343121, 0.6111860275, 0.0368208028, 0.0899466202, 0.9127882719, 0.1146656275, 0.4647151828, 0.3303563893, 0.5797663927, 0.8400436044, 0.2845958769, 0.2181742340, 0.9651557207, 0.1241061762, 0.0102593508, 0.6999664903, 0.8487475514, 0.6001151800, 0.9682601690, 0.6127328873, 0.1502806544, 0.2512893379, 0.3930048048, 0.3448313475, 0.5263126493, 0.7319667935, 0.9264212251, 0.4489789009, 0.0418849625, 0.5219999552, 0.3397078812, 0.4435234964, 0.4758536220, 0.1290920675, 0.1649249196, 0.1736114621, 0.5685442686, 0.3253444433, 0.0540574715, 0.2022368759, 0.0260062832, 0.9889448285, 0.2064949423, 0.3756456375, 0.8462600112, 0.8166462779, 0.1788506061, 0.6607533097, 0.1638182998, 0.7888727188, 0.3304887116, 0.3085075021, 0.6626392603, 0.2860932350, 0.1577534527, 0.0126363616, 0.1958409399, 0.2475458980, 0.1514713019, 0.5241229534, 0.9845717549, 0.8002693653, 0.3091083765, 0.3348104060, 0.1341333240, 0.3546191454, 0.3800157905, 0.0364337005 };
+const static std::vector<float> if_dynamic_output0{ 0.0444660522, 0.0271649156, 0.0191113371, 0.0014375688, 0.0690929219, 0.0001767588, 0.0030322229, 0.0118752792, 0.0419745520, 0.7816683054 };
+// clang-format on
+
+TEST_F(TestIfDynamicModelLoaded, run_verify)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session, "cpu"));
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session));
+
+  nnfw_tensorinfo ti_output0_expected = {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 10}};
+
+  // Output tensor sizes are inferenced after `nnfw_prepare`
+  {
+    nnfw_tensorinfo ti;
+    NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_session, 0, &ti));
+    ASSERT_TRUE(tensorInfoEqual(ti, ti_output0_expected));
+  }
+
+  std::vector<float> actual_output0(10);
+  setInputOutput(_session, if_dynamic_input0, actual_output0);
+
+  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+
+  // Check output tensor sizes again
+  {
+    nnfw_tensorinfo ti;
+    NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_session, 0, &ti));
+    ASSERT_TRUE(tensorInfoEqual(ti, ti_output0_expected));
+  }
+
+  // Output value check
+  for (int i = 0; i < actual_output0.size(); ++i)
+    ASSERT_NEAR(if_dynamic_output0[i], actual_output0[i], 0.00001);
+}
+
+class CombinationTest1 : public ::testing::Test
+{
+protected:
+  void SetUp() override
+  {
+    CircleGen cgen;
+
+    // Creating a graph which has dynamic tensors after compilation.
+    // #3 and #4 are dynamic. This model was used to check if internal dynamic tensors could
+    // make any side-effect.
+    //
+    // #0 = input 0 of shape [1]
+    // #1 = input 1 of shape [2]
+    // #2 = cast(#0, int to float)
+    // #3 = reshape(const of shape [4] , #1)
+    // #4 = add(#2, #3)
+
+    constexpr circle::TensorType CIRCLE_DTYPE = circle::TensorType::TensorType_FLOAT32;
+
+    int cast_in = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32});
+    int cast_out = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
+
+    cgen.addOperatorCast({{cast_in}, {cast_out}}, circle::TensorType::TensorType_INT32,
+                         circle::TensorType::TensorType_FLOAT32);
+
+    std::vector<float> reshape_in_data{0, 1, 2, 3}; // defining constant tensor
+    uint32_t reshape_in_buf = cgen.addBuffer(reshape_in_data);
+    int reshape_in = cgen.addTensor({{4}, CIRCLE_DTYPE, reshape_in_buf});
+    int reshape_shape_in = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32});
+    int reshape_out = cgen.addTensor({{}, CIRCLE_DTYPE}); // dynamic tensor of shape {}
+
+    cgen.addOperatorReshape({{reshape_in, reshape_shape_in}, {reshape_out}});
+
+    int out = cgen.addTensor({{}, CIRCLE_DTYPE}); // dynamic tensor of shape {}
+    cgen.addOperatorAdd({{cast_out, reshape_out}, {out}}, circle::ActivationFunctionType_NONE);
+    cgen.setInputsAndOutputs({cast_in, reshape_shape_in}, {out});
+
+    _circle_buffer = cgen.finish();
+  }
+
+  void TearDown() override
+  { // DO NOTHING
+  }
+
+  void setSession(nnfw_session *session) { _session = session; }
+
+  CircleBuffer &getCircleBuffer() { return _circle_buffer; }
+
+  void run_WITHOUT_set_input_tensorinfo(const std::vector<int32_t> &cast_input,
+                                        const std::vector<int32_t> &reshape_shape_input,
+                                        const nnfw_tensorinfo &expected_ti,
+                                        const std::vector<float> &expected,
+                                        std::vector<float> &actual)
+  {
+    setInputOutput(_session, cast_input, reshape_shape_input, actual);
+    NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+    verifyOutput(_session, expected_ti, expected, actual);
+  }
+
+  void run_WITH_set_input_tensorinfo(int32_t new_dim_0, const std::vector<int32_t> &cast_input,
+                                     const std::vector<int32_t> &reshape_shape_input,
+                                     const nnfw_tensorinfo &expected_ti,
+                                     const std::vector<float> &expected, std::vector<float> &actual)
+  {
+    nnfw_tensorinfo t_in;
+    t_in.dtype = NNFW_TYPE_TENSOR_INT32;
+    t_in.rank = 1;
+    t_in.dims[0] = new_dim_0;
+    NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(_session, 0, &t_in));
+
+    setInputOutput(_session, cast_input, reshape_shape_input, actual);
+    NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+    verifyOutput(_session, expected_ti, expected, actual);
+  }
+
+private:
+  nnfw_session *_session;
+  CircleBuffer _circle_buffer;
+};
+
+// test for https://github.com/Samsung/ONE/issues/4625
+TEST_F(CombinationTest1, combination_of_set_input_tensorinfo_and_nnfw_run)
+{
+  constexpr NNFW_TYPE NNFW_DTYPE = NNFW_TYPE_TENSOR_FLOAT32;
+  std::vector<int32_t> cast_in_buf;
+  std::vector<int32_t> reshape_shape_in_buf;
+  std::vector<float> actual(4), expected(4);
+
+  nnfw_session *session = nullptr;
+  auto &cbuf = getCircleBuffer();
+
+  auto create_prepare_session = [&](const CircleBuffer &cbuf) {
+    NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
+    NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, cbuf.buffer(), cbuf.size()));
+    NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
+    NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
+  };
+
+  // combinations of executions of static and dynamic tensors
+  // 1) no change on the shape of #0 -> change #0 to shape [1] -> no change. use previous shape
+  // 2) no change on the shape of #0 -> change #0 to shape [2] -> no change. use previous shape
+  // 3) no change on the shape of #0 -> change #0 to shape [2] -> change #0 to shape [1]
+
+  // 1) no change on the shape of #0 -> change #0 to shape [1] -> no input change
+  //       static                             dynamic                      dynamic
+  create_prepare_session(cbuf);
+  {
+    setSession(session);
+
+    // no change on the shape of #0
+    cast_in_buf = {10};
+    reshape_shape_in_buf = {1, 4};
+    expected = {10, 11, 12, 13};
+    run_WITHOUT_set_input_tensorinfo(cast_in_buf, reshape_shape_in_buf,
+                                     {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
+
+    // change to the default shape [1] of #0, this treats 0# dynamic
+    int32_t new_dim_0 = 1;
+    cast_in_buf = {10};
+    reshape_shape_in_buf = {1, 4};
+    expected = {10, 11, 12, 13};
+    run_WITH_set_input_tensorinfo(new_dim_0, cast_in_buf, reshape_shape_in_buf,
+                                  {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
+
+    // no change. Use previous shape
+    run_WITHOUT_set_input_tensorinfo(cast_in_buf, reshape_shape_in_buf,
+                                     {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
+
+    NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
+  }
+
+  // 2) no change on the shape of #0 -> change #0 to shape [2] -> no change(use previous shape)
+  //       static                             dynamic                      dynamic
+  create_prepare_session(cbuf);
+  {
+    setSession(session);
+
+    // no change on the shape of #0
+    cast_in_buf = {10};
+    reshape_shape_in_buf = {1, 4};
+    expected = {10, 11, 12, 13};
+    run_WITHOUT_set_input_tensorinfo(cast_in_buf, reshape_shape_in_buf,
+                                     {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
+
+    // change shape of #0 to [2], this treats 0# dynamic
+    int32_t new_dim_0 = 2;
+    cast_in_buf = {10, 20};
+    reshape_shape_in_buf = {2, 2};
+    expected = {10, 21, 12, 23};
+    run_WITH_set_input_tensorinfo(new_dim_0, cast_in_buf, reshape_shape_in_buf,
+                                  {NNFW_TYPE_TENSOR_FLOAT32, 2, {2, 2}}, expected, actual);
+
+    // no change. Use previous shape
+    run_WITH_set_input_tensorinfo(new_dim_0, cast_in_buf, reshape_shape_in_buf,
+                                  {NNFW_TYPE_TENSOR_FLOAT32, 2, {2, 2}}, expected, actual);
+
+    NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
+  }
+
+  // 3) no change on the shape of #0 -> change #0 to shape [2] -> change #0 to shape [1]
+  //       static                             dynamic                      dynamic
+  create_prepare_session(cbuf);
+  {
+    setSession(session);
+
+    // no change on the shape of #0
+    cast_in_buf = {10};
+    reshape_shape_in_buf = {1, 4};
+    expected = {10, 11, 12, 13};
+    run_WITHOUT_set_input_tensorinfo(cast_in_buf, reshape_shape_in_buf,
+                                     {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
+
+    // change shape of #0 to [2], this treats 0# dynamic
+    int32_t new_dim_0 = 2;
+    cast_in_buf = {10, 20};
+    reshape_shape_in_buf = {2, 2};
+    expected = {10, 21, 12, 23};
+    run_WITH_set_input_tensorinfo(new_dim_0, cast_in_buf, reshape_shape_in_buf,
+                                  {NNFW_TYPE_TENSOR_FLOAT32, 2, {2, 2}}, expected, actual);
+
+    // change #0 to shape [1]
+    new_dim_0 = 1;
+    cast_in_buf = {100};
+    reshape_shape_in_buf = {1, 4};
+    expected = {100, 101, 102, 103};
+    run_WITH_set_input_tensorinfo(new_dim_0, cast_in_buf, reshape_shape_in_buf,
+                                  {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
+
+    NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
+  }
+}
+
+TEST_F(CombinationTest1, neg_combination_of_set_input_tensorinfo_and_nnfw_run)
+{
+  nnfw_session *session = nullptr;
+  auto &cbuf = getCircleBuffer();
+  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
+  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, cbuf.buffer(), cbuf.size()));
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
+
+  setSession(session);
+
+  std::vector<int32_t> cast_in_buf;
+  std::vector<int32_t> reshape_shape_in_buf;
+  std::vector<float> actual(4), expected(4);
+
+  // no change on the shape of #0
+  cast_in_buf = {10};
+  reshape_shape_in_buf = {1, 4};
+  expected = {10, 11, 12, 13};
+  setInputOutput(session, cast_in_buf, reshape_shape_in_buf, actual);
+  NNFW_ENSURE_SUCCESS(nnfw_run(session));
+
+  // change the shape of #0 to [4]
+  cast_in_buf = {10, 20, 30, 40};
+  reshape_shape_in_buf = {1, 4};
+  expected = {10, 21, 32, 43};
+  run_WITH_set_input_tensorinfo(4, cast_in_buf, reshape_shape_in_buf,
+                                {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
+  setInputOutput(session, cast_in_buf, reshape_shape_in_buf, actual);
+  NNFW_ENSURE_SUCCESS(nnfw_run(session));
+
+  // run without changing #0 but caller thought that it is now shape [1]
+  cast_in_buf = {10};
+  reshape_shape_in_buf = {1, 4};
+  expected = {10, 11, 12, 13};
+  setInputOutput(session, cast_in_buf, reshape_shape_in_buf, actual);
+  // This should throw an error
+  EXPECT_EQ(nnfw_run(session), NNFW_STATUS_ERROR);
+
+  NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
+}
+
+// Class to test set_input_tensorinfo() against "two" inputs
+class CombinationTest2 : public ::testing::Test
+{
+protected:
+  void SetUp() override
+  {
+    CircleGen cgen;
+
+    // creating a graph with two inputs
+    //
+    // #0 = input 0 of shape [1]
+    // #1 = input 1 of shape [1]
+    // #2 = add(#0, #1)
+
+    constexpr circle::TensorType CIRCLE_DTYPE = circle::TensorType::TensorType_FLOAT32;
+
+    int in0 = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32});
+    int in1 = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32});
+    int out = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32});
+
+    cgen.addOperatorAdd({{in0, in1}, {out}}, circle::ActivationFunctionType_NONE);
+    cgen.setInputsAndOutputs({in0, in1}, {out});
+
+    _circle_buffer = cgen.finish();
+  }
+
+  void TearDown() override
+  { // DO NOTHING
+  }
+
+  void setSession(nnfw_session *session) { _session = session; }
+
+  CircleBuffer &getCircleBuffer() { return _circle_buffer; }
+
+  void run_WITHOUT_set_input_tensorinfo(const std::vector<int32_t> &in0,
+                                        const std::vector<int32_t> &in1,
+                                        const nnfw_tensorinfo &expected_ti,
+                                        const std::vector<int32_t> &expected,
+                                        std::vector<int32_t> &actual)
+  {
+    setInputOutput(_session, in0, in1, actual);
+    NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+    verifyOutput(_session, expected_ti, expected, actual);
+  }
+
+  // Pass -1 for t0_new_dim_0 (or t1_new_dim_0)
+  // if shape of tensor 0 (or tensor 1) does not changed from the shape in a model
+  void run_WITH_set_input_tensorinfo(int32_t t0_new_dim_0, int32_t t1_new_dim_0,
+                                     const std::vector<int32_t> &in0,
+                                     const std::vector<int32_t> &in1,
+                                     const nnfw_tensorinfo &expected_ti,
+                                     const std::vector<int32_t> &expected,
+                                     std::vector<int32_t> &actual)
+  {
+    if (t0_new_dim_0 >= 0)
+    {
+      nnfw_tensorinfo t_in;
+      t_in.dtype = NNFW_TYPE_TENSOR_INT32;
+      t_in.rank = 1;
+      t_in.dims[0] = t0_new_dim_0;
+      NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(_session, 0, &t_in));
+    }
+
+    if (t1_new_dim_0 >= 0)
+    {
+      nnfw_tensorinfo t_in;
+      t_in.dtype = NNFW_TYPE_TENSOR_INT32;
+      t_in.rank = 1;
+      t_in.dims[0] = t1_new_dim_0;
+      NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(_session, 1, &t_in));
+    }
+
+    setInputOutput(_session, in0, in1, actual);
+    NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+    verifyOutput(_session, expected_ti, expected, actual);
+  }
+
+private:
+  nnfw_session *_session;
+  CircleBuffer _circle_buffer;
+};
+
+// test for https://github.com/Samsung/ONE/issues/4625
+TEST_F(CombinationTest2, combination_set_input_tensorinfo_for_two_inputs)
+{
+  nnfw_session *session = nullptr;
+
+  // combinations of executions of static and dynamic tensors for "two" inputs (#0, #1)
+  // 0. both input shapes are [1] (input shapes of the model are [1], [1])
+  // 1. change shape of #0 to [2]
+  // 2. change shape of #0 to [1], change shape of #1 to [2]
+  // 3. change shape of #0 to [2], (shape of #1 is still [2])
+  // 4. don't call set_input_tensorinfo (both are still [2] and [2])
+  // 5. change shape of #0 to [1], change shape of #1 to [1]
+  std::vector<int32_t> in0, in1;
+  std::vector<int32_t> actual, expected;
+  nnfw_tensorinfo expected_ti;
+
+  auto &cbuf = getCircleBuffer();
+
+  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
+  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, cbuf.buffer(), cbuf.size()));
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
+  setSession(session);
+
+  constexpr int32_t NO_CHANGE = -1;
+
+  // 0. both input shapes are [1]
+  in0 = {10};
+  in1 = {100};
+  expected = {110};
+  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {1}};
+  actual.resize(1);
+  run_WITHOUT_set_input_tensorinfo(in0, in1, expected_ti, expected, actual);
+
+  // 1. change shape of #0 to [2]
+  int32_t new_dim_0 = 2;
+  int32_t new_dim_1 = NO_CHANGE;
+  in0 = {10, 20};
+  in1 = {100};
+  expected = {110, 120};
+  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {2}};
+  actual.resize(2);
+  run_WITH_set_input_tensorinfo(new_dim_0, new_dim_1, in0, in1, expected_ti, expected, actual);
+
+  // 2. change shape of #0 to [1], change shape of #1 to [2]
+  new_dim_0 = 1;
+  new_dim_1 = 2;
+  in0 = {1000};
+  in1 = {10, 20};
+  expected = {1010, 1020};
+  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {2}};
+  actual.resize(2);
+  run_WITH_set_input_tensorinfo(new_dim_0, new_dim_1, in0, in1, expected_ti, expected, actual);
+
+  // // 3. change shape of #0 to [2], (shape of #1 is still [2])
+  new_dim_0 = 2;
+  new_dim_1 = NO_CHANGE;
+  in0 = {10, 20};
+  in1 = {100, 200};
+  expected = {110, 220};
+  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {2}};
+  actual.resize(2);
+  run_WITH_set_input_tensorinfo(new_dim_0, new_dim_1, in0, in1, expected_ti, expected, actual);
+
+  // // 4. don't call set_input_tensorinfo (both are still [2] and [2])
+  in0 = {11, 22};
+  in1 = {1000, 2000};
+  expected = {1011, 2022};
+  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {2}};
+  actual.resize(2);
+  run_WITHOUT_set_input_tensorinfo(in0, in1, expected_ti, expected, actual);
+
+  // // 5. change shape of #0 to [1], change shape of #1 to [1]
+  new_dim_0 = 1;
+  new_dim_1 = 1;
+  in0 = {50};
+  in1 = {500};
+  expected = {550};
+  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {1}};
+  actual.resize(1);
+  run_WITH_set_input_tensorinfo(new_dim_0, new_dim_1, in0, in1, expected_ti, expected, actual);
+
+  NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
+}
+
+TEST_F(CombinationTest2, neg_combination_set_input_tensorinfo_for_two_inputs)
+{
+  nnfw_session *session = nullptr;
+
+  // change shape of #1 to [2]
+  // then, do not call nnfw_set_input_tensorinfo for #1
+  std::vector<int32_t> in0, in1;
+  std::vector<int32_t> expected_shape;
+  std::vector<int32_t> actual, expected;
+  nnfw_tensorinfo expected_ti;
+
+  auto &cbuf = getCircleBuffer();
+
+  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
+  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, cbuf.buffer(), cbuf.size()));
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
+  setSession(session);
+
+  constexpr int32_t NO_CHANGE = -1;
+
+  // change shape of #1 to [2]
+  int32_t new_dim_0 = NO_CHANGE;
+  int32_t new_dim_1 = 2;
+  in0 = {10};
+  in1 = {100, 200};
+  expected = {110, 210};
+  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {2}};
+  actual.resize(2);
+  run_WITH_set_input_tensorinfo(new_dim_0, new_dim_1, in0, in1, expected_ti, expected, actual);
+
+  // then, do not call nnfw_set_input_tensorinfo for #1, thinking that
+  // #1 has now shape [1], which is wrong
+  in0 = {10};
+  in1 = {100};
+  expected = {110};                               // wrong
+  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {1}}; // wrong
+  actual.resize(1);                               // wrong
+  setInputOutput(session, in0, in1, actual);
+  EXPECT_EQ(nnfw_run(session), NNFW_STATUS_ERROR);
+
+  NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
+}
diff --git a/tests/nnfw_api/src/GenModelTests/Trainability.test.cc b/tests/nnfw_api/src/GenModelTests/Trainability.test.cc
new file mode 100644 (file)
index 0000000..878c412
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+namespace
+{
+CirclePlusGen gen_test_model(const int32_t num_of_trainable_ops)
+{
+  CirclePlusGen cgen;
+
+  const uint32_t weight_buf = cgen.addBuffer(std::vector<float>(2 * 3 * 3, 0.f));
+  const uint32_t bias_buf = cgen.addBuffer(std::vector<float>(2, 0.f));
+  const int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+  const int weight =
+    cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  const int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  const int conv_out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+  const int add_lhs = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+  const int add_out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorConv2D({{in, weight, bias}, {conv_out}}, circle::Padding_VALID, 1, 1,
+                         circle::ActivationFunctionType_NONE, 1, 1);
+  cgen.addOperatorAdd({{conv_out, add_lhs}, {add_out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in, add_lhs}, {add_out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     num_of_trainable_ops});
+
+  return cgen;
+}
+} // namespace
+
+TEST_F(GenModelTrain, TestModel_Trainability_full_training_enabled)
+{
+  auto cgen = gen_test_model(NNFW_TRAIN_TRAINABLE_ALL);
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(uniformTCD<float>(
+    {{{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4},
+      std::vector<float>(1 * 3 * 3 * 2, 2.0f)}}, // input dataset
+    {{{47, -4, -25, 9, 10, 10, -13, 11, -14, -26, -12, 26, 20, 40, 1, 3, 11,
+       4}}},                                             // expected dataset
+    {{385.5556f}, {310.1241f}, {256.4867f}, {217.1853f}} // losses
+    ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(4);
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, TestModel_Trainability_one_op_training_enabled)
+{
+  auto cgen = gen_test_model(1);
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(uniformTCD<float>(
+    {{{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4},
+      std::vector<float>(1 * 3 * 3 * 2, 2.0f)}}, // input dataset
+    {{{47, -4, -25, 9, 10, 10, -13, 11, -14, -26, -12, 26, 20, 40, 1, 3, 11,
+       4}}},                                             // expected dataset
+    {{385.5555f}, {385.5555f}, {385.5555f}, {385.5555f}} // losses
+    ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(4);
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, TestModel_Trainability_one_op_training_disabled)
+{
+  auto cgen = gen_test_model(NNFW_TRAIN_TRAINABLE_NONE);
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(uniformTCD<float>(
+    {{{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4},
+      std::vector<float>(1 * 3 * 3 * 2, 2.0f)}}, // input dataset
+    {{{47, -4, -25, 9, 10, 10, -13, 11, -14, -26, -12, 26, 20, 40, 1, 3, 11,
+       4}}},                                             // expected dataset
+    {{385.5555f}, {385.5555f}, {385.5555f}, {385.5555f}} // losses
+    ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(4);
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Add.test.cc b/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Add.test.cc
new file mode 100644 (file)
index 0000000..d8b0e0d
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+// NOTE The positive training tests for Add op exist in `BranchModelTrain.test.cc`
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Add_InvalidShape)
+{
+  CirclePlusGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorAdd({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Add_InvalidType)
+{
+  CirclePlusGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
+  int rhs = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorAdd({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/MaxPool2D.test.cc b/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/MaxPool2D.test.cc
new file mode 100644 (file)
index 0000000..0b199c3
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+namespace
+{
+
+auto getDefaultPool2DOptions()
+{
+  return std::tuple<circle::Padding, int, int, int, int, circle::ActivationFunctionType>(
+    circle::Padding_SAME, 1, 1, 1, 1, circle::ActivationFunctionType_NONE);
+}
+
+} // namespace
+
+TEST_F(GenModelTrain, NonTrainableOps_Conv2D_MaxPool2D)
+{
+  // (( Input 0 )) -> [ Conv2D ] -> [ MaxPool2D ] -> (( Output 0 ))
+  // Padding : Same
+  // stride height : 1, stride width : 1
+  // filter height : 1, filter hight : 1
+  // Activation : None
+  {
+    CirclePlusGen cgen;
+    uint32_t weight_buf = cgen.addBuffer(std::vector<float>(2 * 3 * 3, 0.f));
+    uint32_t bias_buf = cgen.addBuffer(std::vector<float>(2, 0.f));
+    int input = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+    int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+    int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+    int conv_output = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+    const auto [padding, stride_w, stride_h, filter_w, filter_h, actfn] = getDefaultPool2DOptions();
+
+    cgen.addOperatorConv2D({{input, weight, bias}, {conv_output}}, circle::Padding_VALID, 1, 1,
+                           circle::ActivationFunctionType_NONE, 1, 1);
+    cgen.addOperatorMaxPool2D({{conv_output}, {output}}, padding, stride_w, stride_h, filter_w,
+                              filter_h, actfn);
+    cgen.setInputsAndOutputs({input}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{4, 0,  -5, 1, 0,  4, -1, 1, -1, -3, 3,  -2, -4,
+                           1, -2, 2,  4, -4, 2, 2,  0, 4,  -1, -2, 4}}},            // inputs
+                        {{{1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 1}}}, // expected
+                        {{31.6667f}, {28.6837f}, {26.1765f}, {24.0089f}}            // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, NonTrainableOps_Conv2D_MaxPool2D_Depth1_Filter2)
+{
+  // (( Input 0 )) -> [ Conv2D ] -> [ MaxPool2D ] -> (( Output 0 ))
+  // Padding : Same
+  // stride height : 1, stride width : 1
+  // filter height : 2, filter hight : 2
+  // Activation : None
+  {
+    CirclePlusGen cgen;
+    uint32_t weight_buf = cgen.addBuffer(std::vector<float>(1 * 3 * 3, 0.f));
+    uint32_t bias_buf = cgen.addBuffer(std::vector<float>(1, 0.f));
+    int input = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+    int weight = cgen.addTensor({{1, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+    int bias = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+    int conv_output = cgen.addTensor({{1, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+    auto [padding, stride_w, stride_h, filter_w, filter_h, actfn] = getDefaultPool2DOptions();
+    // padding = circle::Padding_VALID;
+    filter_w = 2;
+    filter_h = 2;
+
+    cgen.addOperatorConv2D({{input, weight, bias}, {conv_output}}, circle::Padding_VALID, 1, 1,
+                           circle::ActivationFunctionType_NONE, 1, 1);
+    cgen.addOperatorMaxPool2D({{conv_output}, {output}}, padding, stride_w, stride_h, filter_w,
+                              filter_h, actfn);
+    cgen.setInputsAndOutputs({input}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{4, 0,  -5, 1, 0,  4, -1, 1, -1, -3, 3,  -2, -4,
+                           1, -2, 2,  4, -4, 2, 2,  0, 4,  -1, -2, 4}}}, // inputs
+                        {{{1, 2, 3, 4, 5, 6, 7, 8, 9}}},                 // expected
+                        {{31.6667f}, {25.9453f}, {15.4067f}, {8.4666f}}  // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, NonTrainableOps_Conv2D_MaxPool2D_Depth2_Filter2)
+{
+  // (( Input 0 )) -> [ Conv2D ] -> [ MaxPool2D ] -> (( Output 0 ))
+  // Padding : Same
+  // stride height : 1, stride width : 1
+  // filter height : 2, filter hight : 2
+  // Activation : None
+  {
+    CirclePlusGen cgen;
+    uint32_t weight_buf = cgen.addBuffer(std::vector<float>(2 * 3 * 3, 0.f));
+    uint32_t bias_buf = cgen.addBuffer(std::vector<float>(2, 0.f));
+    int input = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+    int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+    int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+    int conv_output = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+    auto [padding, stride_w, stride_h, filter_w, filter_h, actfn] = getDefaultPool2DOptions();
+    // padding = circle::Padding_VALID;
+    filter_w = 2;
+    filter_h = 2;
+
+    cgen.addOperatorConv2D({{input, weight, bias}, {conv_output}}, circle::Padding_VALID, 1, 1,
+                           circle::ActivationFunctionType_NONE, 1, 1);
+    cgen.addOperatorMaxPool2D({{conv_output}, {output}}, padding, stride_w, stride_h, filter_w,
+                              filter_h, actfn);
+    cgen.setInputsAndOutputs({input}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{4, 0,  -5, 1, 0,  4, -1, 1, -1, -3, 3,  -2, -4,
+                           1, -2, 2,  4, -4, 2, 2,  0, 4,  -1, -2, 4}}},            // inputs
+                        {{{1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 1}}}, // expected
+                        {{31.6667f}, {27.8823f}, {16.9743f}, {9.3556f}}             // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, NonTrainableOps_Conv2D_MaxPool2D_Stride2Filter2)
+{
+  // (( Input 0 )) -> [ Conv2D ] -> [ MaxPool2D ] -> (( Output 0 ))
+  // Padding : Same
+  // stride height : 2, stride width : 2
+  // filter height : 2, filter hight : 2
+  // Activation : None
+  {
+    CirclePlusGen cgen;
+    uint32_t weight_buf = cgen.addBuffer(std::vector<float>(2 * 3 * 3, 0.f));
+    uint32_t bias_buf = cgen.addBuffer(std::vector<float>(2, 0.f));
+    int input = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+    int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+    int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+    int conv_output = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+    auto [padding, stride_w, stride_h, filter_w, filter_h, actfn] = getDefaultPool2DOptions();
+    stride_w = 2;
+    stride_h = 2;
+    filter_w = 2;
+    filter_h = 2;
+
+    cgen.addOperatorConv2D({{input, weight, bias}, {conv_output}}, circle::Padding_VALID, 1, 1,
+                           circle::ActivationFunctionType_NONE, 1, 1);
+    cgen.addOperatorMaxPool2D({{conv_output}, {output}}, padding, stride_w, stride_h, filter_w,
+                              filter_h, actfn);
+    cgen.setInputsAndOutputs({input}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{4, 0,  -5, 1, 0,  4, -1, 1, -1, -3, 3,  -2, -4,
+                           1, -2, 2,  4, -4, 2, 2,  0, 4,  -1, -2, 4}}}, // inputs
+                        {{{1, 2, 3, 4, 5, 6, 7, 8}}},                    // expected
+                        {{25.5000f}, {19.2126f}, {12.9202f}, {9.0784f}}  // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_MaxPool2D_InvalidShape)
+{
+  CirclePlusGen cgen;
+  int input = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int output = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  const auto [padding, stride_w, stride_h, filter_w, filter_h, actfn] = getDefaultPool2DOptions();
+
+  cgen.addOperatorMaxPool2D({{input}, {output}}, padding, stride_w, stride_h, filter_w, filter_h,
+                            actfn);
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_MaxPool2D_InvalidType)
+{
+  CirclePlusGen cgen;
+  int input = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
+  int output = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  const auto [padding, stride_w, stride_h, filter_w, filter_h, actfn] = getDefaultPool2DOptions();
+  cgen.addOperatorMaxPool2D({{input}, {output}}, padding, stride_w, stride_h, filter_w, filter_h,
+                            actfn);
+  cgen.setInputsAndOutputs({input, padding}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Mean.test.cc b/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Mean.test.cc
new file mode 100644 (file)
index 0000000..d04ac7a
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+TEST_F(GenModelTrain, NonTrainableOps_FC_Mean)
+{
+  // (( Input 0 )) -> [ FC ] -> [ Mean ] -> (( Output 0 ))
+  {
+    CirclePlusGen cgen;
+
+    uint32_t weight_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    uint32_t axis_buf = cgen.addBuffer(std::vector<int32_t>{1});
+    int input = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int weight = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+    int bias = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+    int fc_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int axis = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32, axis_buf});
+    int output = cgen.addTensor({{1, 1}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorFullyConnected({{input, weight, bias}, {fc_output}});
+    bool keep_dims = true;
+    cgen.addOperatorMean({{fc_output, axis}, {output}}, keep_dims);
+    cgen.setInputsAndOutputs({input}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(uniformTCD<float>({{{1, 3}}, {{2, 1}}}, // inputs
+                                             {{{5}}, {{3}}},       // expected
+                                             {{16.7778f}, {15.5544f}, {14.4203f}, {13.3691f}}
+                                             // loss
+                                             ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Mean_InvalidShape)
+{
+  CirclePlusGen cgen;
+  int input = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+  int axis = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32});
+  // Invalid shape: input and output's ranks should be equal if keep_dims is true
+  int out = cgen.addTensor({{1, 2, 3}, circle::TensorType::TensorType_FLOAT32});
+  bool keep_dims = true;
+  cgen.addOperatorMean({{input, axis}, {out}, keep_dims}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({input, axis}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Mean_InvalidType)
+{
+  CirclePlusGen cgen;
+  // Invalid  type: input tensor type should be FLOAT32
+  int input = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_INT32});
+  int axis = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32});
+  int out = cgen.addTensor({{1, 1}, circle::TensorType::TensorType_FLOAT32});
+  bool keep_dims = true;
+  cgen.addOperatorMean({{input, axis}, {out}, keep_dims}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({input, axis}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Mul.test.cc b/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Mul.test.cc
new file mode 100644 (file)
index 0000000..51dbab4
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+// NOTE The positive training tests for Mul op exist in `BranchModelTrain.test.cc`
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Mul_InvalidShape)
+{
+  CirclePlusGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Mul_InvalidType)
+{
+  CirclePlusGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
+  int rhs = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Pad.test.cc b/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Pad.test.cc
new file mode 100644 (file)
index 0000000..baa3e83
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+TEST_F(GenModelTrain, NonTrainableOps_FC_Pad)
+{
+  // (( Input 0 )) -> [ FC ] -> [ Pad ] -> (( Output 0 ))
+  {
+    CirclePlusGen cgen;
+    uint32_t weight_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias_buf = cgen.addBuffer(std::vector<float>(2, 0.f));
+    uint32_t padding_buf = cgen.addBuffer(std::vector<int32_t>{0, 0, 1, 1});
+    int input = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int weight = cgen.addTensor({{2, 8}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+    int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+    int fc_output = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int padding = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_INT32, padding_buf});
+    int output = cgen.addTensor({{1, 4}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorFullyConnected({{input, weight, bias}, {fc_output}});
+    cgen.addOperatorPad({{fc_output, padding}, {output}});
+    cgen.setInputsAndOutputs({input}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{0, 1, 2, 3, 4, 5, 6, 7}}, {{7, 6, 5, 4, 3, 2, 1, 0}}}, // inputs
+                        {{{0, 13, 52, 0}}, {{0, 31, 24, 0}}},                     // expected
+                        {{462.7862f}, {32.8115f}, {5.8401f}, {1.3900f}}           // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Pad_InvalidShape)
+{
+  CirclePlusGen cgen;
+  std::vector<int32_t> padding_data{0, 0, 1, 1, 1, 1, 0, 0};
+  uint32_t padding_buf = cgen.addBuffer(padding_data);
+  int input = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int padding = cgen.addTensor({{4, 2}, circle::TensorType::TensorType_INT32, padding_buf});
+  // Invalid shape: output shape should be equal to input shape
+  int output = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorPad({{input, padding}, {output}});
+  cgen.setInputsAndOutputs({input, padding}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Pad_InvalidType)
+{
+  CirclePlusGen cgen;
+  std::vector<int32_t> padding_data{0, 0, 1, 1, 1, 1, 0, 0};
+  uint32_t padding_buf = cgen.addBuffer(padding_data);
+  // Invalid  type: input tensor type should be FLOAT32
+  int input = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
+  int padding = cgen.addTensor({{4, 2}, circle::TensorType::TensorType_INT32, padding_buf});
+  int output = cgen.addTensor({{1, 4, 4, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorPad({{input, padding}, {output}});
+  cgen.setInputsAndOutputs({input, padding}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Relu.test.cc b/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Relu.test.cc
new file mode 100644 (file)
index 0000000..5f79640
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+TEST_F(GenModelTrain, NonTrainableOps_FC_Relu_FC)
+{
+  // (( Input 0 )) -> [ FC ] -> [ Relu ] -> [ FC ] -> (( Output 0 ))
+  {
+    CirclePlusGen cgen;
+
+    uint32_t weight1_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias1_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    uint32_t weight2_buf = cgen.addBuffer(std::vector<float>(8 * 8, 0.f));
+    uint32_t bias2_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    int input = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int weight1 = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight1_buf});
+    int bias1 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias1_buf});
+    int weight2 = cgen.addTensor({{8, 8}, circle::TensorType::TensorType_FLOAT32, weight2_buf});
+    int bias2 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias2_buf});
+    int fc_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int relu_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorFullyConnected({{input, weight1, bias1}, {fc_output}});
+    cgen.addOperatorRelu({{fc_output}, {relu_output}});
+    cgen.addOperatorFullyConnected({{relu_output, weight2, bias2}, {output}});
+    cgen.setInputsAndOutputs({input}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{1, 3}}, {{2, 1}}},                                     // inputs
+                        {{{0, 1, 5, 5, 2, 1, 5, 5}}, {{2, 1, 5, 5, 0, 1, 5, 6}}}, // expected
+                        {{13.9041f}, {13.7684f}, {13.6340f}, {13.5010f}}          // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Relu_InvalidShape)
+{
+  CirclePlusGen cgen;
+
+  int input = cgen.addTensor({{2, 1}, circle::TensorType::TensorType_FLOAT32});
+  // Invalid shape: output shape should be equal to input shape
+  int output = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorRelu({{input}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Relu_InvalidType)
+{
+  CirclePlusGen cgen;
+
+  // Invalid  type: input tensor type should be FLOAT32
+  int input = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_INT32});
+  int output = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorRelu({{input}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Relu6.test.cc b/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Relu6.test.cc
new file mode 100644 (file)
index 0000000..3f57b32
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+TEST_F(GenModelTrain, NonTrainableOps_FC_Relu6_FC)
+{
+  // (( Input 0 )) -> [ FC ] -> [ Relu6 ] -> [ FC ] -> (( Output 0 ))
+  {
+    CirclePlusGen cgen;
+
+    uint32_t weight1_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias1_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    uint32_t weight2_buf = cgen.addBuffer(std::vector<float>(8 * 8, 0.f));
+    uint32_t bias2_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    int input = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int weight1 = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight1_buf});
+    int bias1 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias1_buf});
+    int weight2 = cgen.addTensor({{8, 8}, circle::TensorType::TensorType_FLOAT32, weight2_buf});
+    int bias2 = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias2_buf});
+    int fc_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int relu_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorFullyConnected({{input, weight1, bias1}, {fc_output}});
+    cgen.addOperatorRelu({{fc_output}, {relu_output}});
+    cgen.addOperatorFullyConnected({{relu_output, weight2, bias2}, {output}});
+    cgen.setInputsAndOutputs({input}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{1, 3}}, {{2, 1}}},                                     // inputs
+                        {{{2, 0, 6, 5, 2, 1, 6, 5}}, {{2, 1, 6, 5, 0, 1, 6, 6}}}, // expected
+                        {{16.8338f}, {16.6680f}, {16.5038f}, {16.3412f}}          // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Relu6_InvalidShape)
+{
+  CirclePlusGen cgen;
+
+  int input = cgen.addTensor({{2, 1}, circle::TensorType::TensorType_FLOAT32});
+  // Invalid shape: output shape should be equal to input shape
+  int output = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorRelu({{input}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Relu6_InvalidType)
+{
+  CirclePlusGen cgen;
+
+  // Invalid type: input tensor type should be FLOAT32
+  int input = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_INT32});
+  int output = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorRelu({{input}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Reshape.test.cc b/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Reshape.test.cc
new file mode 100644 (file)
index 0000000..85b0e05
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+#include <memory>
+
+TEST_F(GenModelTrain, NonTrainableOps_FC_Reshape)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(2 * 3 * 3, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(2, 0.f));
+  const auto new_shape = CircleGen::Shape{1, 18};
+  uint32_t shape_buf = cgen.addBuffer(std::vector<int32_t>(new_shape));
+  int input = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int conv_output = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+  int shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, shape_buf});
+  int output = cgen.addTensor({{1, 18}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorConv2D({{input, weight, bias}, {conv_output}}, circle::Padding_VALID, 1, 1,
+                         circle::ActivationFunctionType_NONE, 1, 1);
+  cgen.addOperatorReshape({{conv_output, shape}, {output}}, &new_shape);
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(
+    uniformTCD<float>({{{4, 0,  -5, 1, 0,  4, -1, 1, -1, -3, 3,  -2, -4,
+                         1, -2, 2,  4, -4, 2, 2,  0, 4,  -1, -2, 4}}}, // input dataset
+                      {{{47, -4, -25, 9, 10, 10, -13, 11, -14, -26, -12, 26, 20, 40, 1, 3, 11,
+                         4}}},                                             // expected dataset
+                      {{403.3333f}, {324.0978f}, {267.7882f}, {226.5260f}} // losses
+                      ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(4);
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Reshape_InvalidShape)
+{
+  CirclePlusGen cgen;
+
+  uint32_t shape_buf = cgen.addBuffer(std::vector<float>{2, 3});
+  int input = cgen.addTensor({{1, 4}, circle::TensorType::TensorType_FLOAT32});
+  int shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, shape_buf});
+  // Invalid shape: The number of output elements should be equal to input
+  int output = cgen.addTensor({{2, 3}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorReshape({{input, shape}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Reshape_InvalidType)
+{
+  CirclePlusGen cgen;
+
+  uint32_t shape_buf = cgen.addBuffer(std::vector<float>{2, 2});
+  // Invalid type: input tensor type should be FLOAT32
+  int input = cgen.addTensor({{1, 4}, circle::TensorType::TensorType_INT32});
+  int shape = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, shape_buf});
+  int output = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorReshape({{input, shape}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Softmax.test.cc b/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Softmax.test.cc
new file mode 100644 (file)
index 0000000..a6ba8ff
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+TEST_F(GenModelTrain, NonTrainableOps_FC_Softmax)
+{
+  // (( Input 0 )) -> [ FC ] -> [ Softmax ] -> (( Output 0 ))
+  {
+    CirclePlusGen cgen;
+
+    uint32_t weight_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+    uint32_t bias_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+    int input = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+    int weight = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+    int bias = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+    int fc_output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+    const float beta = 1.0f;
+    cgen.addOperatorFullyConnected({{input, weight, bias}, {fc_output}});
+    cgen.addOperatorSoftmax({{fc_output}, {output}}, beta);
+    cgen.setInputsAndOutputs({input}, {output});
+
+    float learning_rate = 0.01f;
+    int32_t batch_size = 1;
+    cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                       circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                       circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                       NNFW_TRAIN_TRAINABLE_ALL});
+
+    _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+    _context->addTrainCase(
+      uniformTCD<float>({{{1, 3}}, {{2, 1}}},                                     // inputs
+                        {{{0, 1, 0, 0, 0, 0, 0, 0}}, {{0, 0, 0, 0, 0, 1, 0, 0}}}, // expected
+                        {{0.1094f}, {0.1093f}, {0.1092f}, {0.1092f}}              // loss
+                        ));
+
+    _context->setBackends({"train"});
+    _context->setEpoch(4);
+
+    SUCCEED();
+  }
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Softmax_InvalidShape)
+{
+  CirclePlusGen cgen;
+
+  int input = cgen.addTensor({{2, 1}, circle::TensorType::TensorType_FLOAT32});
+  // Invalid shape: output shape should be equal to input shape
+  int output = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32});
+  const float beta = 1.0f;
+  cgen.addOperatorSoftmax({{input}, {output}}, beta);
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Softmax_InvalidType)
+{
+  CirclePlusGen cgen;
+
+  // Invalid type: input tensor type should be FLOAT32
+  int input = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_INT32});
+  int output = cgen.addTensor({{2, 2}, circle::TensorType::TensorType_FLOAT32});
+  const float beta = 1.0f;
+  cgen.addOperatorSoftmax({{input}, {output}}, beta);
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Sub.test.cc b/tests/nnfw_api/src/GenModelTests/nontrainable_op_trains/Sub.test.cc
new file mode 100644 (file)
index 0000000..3056137
--- /dev/null
@@ -0,0 +1,66 @@
+
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+// NOTE The positive training tests for Sub op exist in `BranchModelTrain.test.cc`
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Sub_InvalidShape)
+{
+  CirclePlusGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorSub({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_NonTrainableOps_Sub_InvalidType)
+{
+  CirclePlusGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
+  int rhs = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorSub({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/one_op_tests/Conv2D.test.cc b/tests/nnfw_api/src/GenModelTests/one_op_tests/Conv2D.test.cc
new file mode 100644 (file)
index 0000000..efa7677
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * 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 "GenModelTest.h"
+
+TEST_F(GenModelTest, OneOp_Conv2D)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{2, 3};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
+                         circle::ActivationFunctionType_NONE, 1, 1);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>(
+    {{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4}},
+    {{47, -4, -25, 9, 10, 10, -13, 11, -14, -26, -12, 26, 20, 40, 1, 3, 11, 4}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu", "ruy", "xnnpack", "gpu_cl"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_Conv2D_Stride)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{2, 3};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 2, 2,
+                         circle::ActivationFunctionType_NONE, 1, 1);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>(
+    {{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4}},
+    {{22, 27, -10, -2, 5, -8, 7, 3, -14, -26, -10, 18, 4, -13, -28, 9, 14, 1}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu", "ruy", "xnnpack"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_Conv2D_Dilation)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{2, 3};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
+                         circle::ActivationFunctionType_NONE, 2, 2);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>(
+    {{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4}},
+    {{-52, 7}}));
+  _context->setBackends({"cpu", "ruy", "xnnpack"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_Conv2D_I8)
+{
+  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<int32_t> bias_data{0, 2, 4};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
+  int weight =
+    cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf}, 0.5, 0);
+  int bias = cgen.addTensor({{3}, circle::TensorType::TensorType_INT32, bias_buf}, 1.0, 0);
+  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 1.0, 0);
+  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<int8_t>({{10, 10, 10}}, {{15, 38, 61}}));
+  _context->setBackends({"cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_Conv2D_I8_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<int32_t> bias_data{0, 0, 0};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
+  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({{3}, circle::TensorType::TensorType_INT32, bias_buf}, 1.0, 0);
+  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 1.0, 0);
+  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<int8_t>({{10, 10, 10}}, {{15, 30, 60}}));
+  _context->setBackends({"cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_Conv2D_U8_PerChannel)
+{
+  CircleGen cgen;
+  // weight
+  std::vector<uint8_t> weight_data{2, 6, 2, 1, 2, 3, 2, 3, 4};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> weight_scales = {.5, 1, 2};
+  std::vector<int64_t> weight_zeropoints = {2, 0, 1};
+  int weight = cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_UINT8, weight_buf},
+                              weight_scales, weight_zeropoints);
+  // bias
+  std::vector<int32_t> bias_data{4, -8, -4};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int bias = cgen.addTensor({{3}, circle::TensorType::TensorType_INT32, bias_buf}, 1., 0);
+
+  // in and out
+  int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_UINT8}, 2., 1);
+  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_UINT8}, 4., 2);
+
+  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<uint8_t>({{5, 3, 7}}, {{5, 11, 24}}));
+  _context->setBackends({"cpu"});
+
+  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({{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;
+  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{2, 3};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT16});
+  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
+                         circle::ActivationFunctionType_NONE, 1, 1);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_Conv2D_Stride)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{2, 3};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 0, 0,
+                         circle::ActivationFunctionType_NONE, 1, 1);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_Conv2D_Dilation)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{2, 3};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
+                         circle::ActivationFunctionType_NONE, 0, 0);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_Conv2D_I8_NonZero_ZeroPoint)
+{
+  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<int32_t> bias_data{0, 2, 4};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
+  int weight =
+    cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf}, 0.5, 17);
+  int bias = cgen.addTensor({{3}, circle::TensorType::TensorType_INT32, bias_buf}, 1.0, 0);
+  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 1.0, 0);
+  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->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_Conv2D_I8_NonZero_ZeroPoints)
+{
+  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<int32_t> bias_data{0, 2, 4};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
+  std::vector<float> weight_scales = {0.5, 1, 0.5};
+  std::vector<int64_t> weight_zeropoints = {0, 0, 10};
+  int weight = cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf},
+                              weight_scales, weight_zeropoints);
+  int bias = cgen.addTensor({{3}, circle::TensorType::TensorType_INT32, bias_buf}, 1.0, 0);
+  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32}, 1.0, 0);
+  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->expectFailModelLoad();
+
+  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({{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/GenModelTests/one_op_tests/DepthwiseConv2D.test.cc b/tests/nnfw_api/src/GenModelTests/one_op_tests/DepthwiseConv2D.test.cc
new file mode 100644 (file)
index 0000000..9283324
--- /dev/null
@@ -0,0 +1,567 @@
+/*
+ * 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 "GenModelTest.h"
+
+TEST_F(GenModelTest, OneOp_DepthwiseConv2D)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{1, 2, 3, 4};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  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());
+  _context->addTestCase(uniformTCD<float>({{1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12}},
+                                          {{71, -34, 99, -20, 91, -26, 127, -4}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_DepthwiseConv2D_No_Multiplier)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{0.5f, -0.5f};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 3, 1, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
+                                  circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(
+    uniformTCD<float>({{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}},
+                      {{16.5f, 27.5f, 28.5f, 43.5f, 8.5f, 15.5f, 12.5f, 23.5f}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu", "gpu_cl"});
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_DepthwiseConv2D_No_Multiplier_RELU6)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{0.5f, -0.5f};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 3, 1, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
+                                  circle::ActivationFunctionType_RELU6);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}},
+                                          {{6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu", "gpu_cl"});
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_DepthwiseConv2D_3x3)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
+                                 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{0.0f, 0.0f};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
+                                  circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(
+    uniformTCD<float>({{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}},
+                      {{6.0f, 16.0f, 8.0f, 16.0f, 10.0f, 16.0f, 12.0f, 16.0f}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu", "gpu_cl"});
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_DepthwiseConv2D_Dilation)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{0, 0, 0, 0};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 4, 4, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
+                                  circle::ActivationFunctionType_NONE, 2, 2);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{
+                                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+                                            0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                          }},
+                                          {{13, 14, 0, 0, 0, 0, 11, 12, 5, 6, 0, 0, 0, 0, 3, 4}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_DepthwiseConv2D_Dilation_N_Stride)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{1, 2, 3, 4};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{0, 0, 0, 0};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 6, 6, 1}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 2, 2, 1,
+                                  circle::ActivationFunctionType_NONE, 3, 3);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<float>({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
+                                            0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+                                          {{4, 0, 3, 0, 0, 0, 2, 0, 1}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack", "gpu_cl"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_DepthwiseConv2D_U8_PerChannel)
+{
+  CircleGen cgen;
+  // weight
+  // clang-format off
+  std::vector<uint8_t> weight_data{2, 1, 2,
+                                   6, 2, 3,
+                                   2, 3, 4,
+                                   4, 4, 5};
+  // clang-format on
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> weight_scales = {.5, 1, 2};
+  std::vector<int64_t> weight_zeropoints = {2, 0, 1};
+  int weight = cgen.addTensor({{1, 2, 2, 3}, circle::TensorType::TensorType_UINT8, weight_buf},
+                              weight_scales, weight_zeropoints);
+  // bias
+  std::vector<int32_t> bias_data{4, -8, -4};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int bias = cgen.addTensor({{3}, circle::TensorType::TensorType_INT32, bias_buf}, 1., 0);
+
+  // in and out
+  int in = cgen.addTensor({{1, 2, 2, 3}, circle::TensorType::TensorType_UINT8}, 2., 1);
+  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_UINT8}, 4., 2);
+
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 1,
+                                  circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  // clang-format off
+  _context->addTestCase(uniformTCD<uint8_t>({{5, 5, 5,  // NHWC
+                                              3, 3, 3,
+                                              7, 7, 7,
+                                              9, 9, 9}
+                                            },
+                                            {{9,
+                                              27,
+                                              56}
+                                            }));
+  // clang-format on
+  _context->setBackends({"cpu"});
+
+  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({{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;
+  std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{1, 2, 3, 4};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 0, 0, 2,
+                                  circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Dilation)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{0, 0, 0, 0};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 4, 4, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
+                                  circle::ActivationFunctionType_NONE, 0, 0);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Type)
+{
+  CircleGen cgen;
+  std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<float> bias_data{1, 2, 3, 4};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_UINT8});
+  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());
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+// Generate a model for negative test cases
+CircleBuffer genNegTestDepthwiseConv2DModel(circle::Padding padding, int stride_w, int stride_h,
+                                            int depth_multiplier,
+                                            circle::ActivationFunctionType actfn)
+{
+  CircleGen cgen;
+  uint32_t ker_buf = cgen.addBuffer(std::vector<uint8_t>{0, 1, 2, 3, 0, 1, 2, 3});
+  uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>{0, 0});
+  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType_UINT8}, 0.5, 0);
+  int ker = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType_UINT8, ker_buf}, 0.5, 0);
+  int bias = cgen.addTensor({{2}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
+  int out = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType_UINT8}, 1, 0);
+  cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, padding, stride_w, stride_h,
+                                  depth_multiplier, actfn, 0, 0);
+  cgen.setInputsAndOutputs({in}, {out});
+  return cgen.finish();
+}
+
+template <typename T> struct DepthwiseConv2DQuantTestParam
+{
+  int stride = 1; // Used for both height and width
+  int input_depth = 1;
+  int depth_multiplier = 1;
+  std::vector<T> ref_output;
+};
+
+template <typename T>
+class DepthwiseConv2DQuantTest
+  : public GenModelTest,
+    public ::testing::WithParamInterface<DepthwiseConv2DQuantTestParam<T>>
+{
+};
+
+using DepthwiseConv2DQuantTestParamU8 = DepthwiseConv2DQuantTestParam<uint8_t>;
+using DepthwiseConv2DQuantTestU8 = DepthwiseConv2DQuantTest<uint8_t>;
+
+// Test with different InputDepth and DepthMultiplier. The values are intended to test optimized CPU
+// kernels.
+INSTANTIATE_TEST_SUITE_P(
+  GenModelTest, DepthwiseConv2DQuantTestU8,
+  ::testing::Values(
+    // Stride == 1
+    DepthwiseConv2DQuantTestParamU8{1, 8, 1, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
+    DepthwiseConv2DQuantTestParamU8{1, 4, 2, std::vector<uint8_t>{0, 0, 2, 3, 0, 2, 6, 9}},
+    DepthwiseConv2DQuantTestParamU8{
+      1, 2, 8, std::vector<uint8_t>{0, 1, 2, 3, 0, 1, 2, 3, 0, 2, 4, 6, 0, 2, 4, 6}},
+    DepthwiseConv2DQuantTestParamU8{1, 2, 2, std::vector<uint8_t>{0, 1, 4, 6}},
+    DepthwiseConv2DQuantTestParamU8{1, 2, 1, std::vector<uint8_t>{2, 5}},
+    DepthwiseConv2DQuantTestParamU8{1, 1, 2, std::vector<uint8_t>{2, 4}},
+    DepthwiseConv2DQuantTestParamU8{1, 1, 4, std::vector<uint8_t>{0, 2, 3, 5}},
+    DepthwiseConv2DQuantTestParamU8{1, 4, 1, std::vector<uint8_t>{0, 1, 4, 9}},
+    DepthwiseConv2DQuantTestParamU8{
+      1, 4, 4, std::vector<uint8_t>{0, 0, 0, 0, 0, 1, 2, 3, 0, 2, 4, 6, 0, 3, 6, 9}},
+    DepthwiseConv2DQuantTestParamU8{1, 12, 1,
+                                    std::vector<uint8_t>{0, 3, 7, 12, 0, 4, 7, 12, 0, 4, 9, 16}},
+    // Stride == 2
+    DepthwiseConv2DQuantTestParamU8{2, 4, 1, std::vector<uint8_t>{0, 1, 4, 9}},
+    DepthwiseConv2DQuantTestParamU8{2, 2, 1, std::vector<uint8_t>{2, 5}},
+    DepthwiseConv2DQuantTestParamU8{2, 1, 8, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5}},
+    DepthwiseConv2DQuantTestParamU8{2, 1, 32, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3,
+                                                                   5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2,
+                                                                   3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
+    DepthwiseConv2DQuantTestParamU8{
+      2, 1, 20, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
+    DepthwiseConv2DQuantTestParamU8{
+      2, 1, 16, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
+    DepthwiseConv2DQuantTestParamU8{2, 8, 1, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
+    DepthwiseConv2DQuantTestParamU8{
+      2, 8, 2, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8}},
+    DepthwiseConv2DQuantTestParamU8{
+      2, 16, 1, std::vector<uint8_t>{0, 3, 8, 16, 0, 4, 7, 12, 0, 3, 7, 13, 0, 4, 7, 12}}));
+
+CircleBuffer genDepthwiseConv2DQuantU8Model(int stride, int input_depth, int depth_multiplier)
+{
+  assert(1 <= stride && stride <= 2);
+  assert(1 <= input_depth && input_depth <= 16);
+  assert(1 <= depth_multiplier && depth_multiplier <= 32);
+
+  const int output_depth = input_depth * depth_multiplier;
+  assert(1 <= output_depth && output_depth <= 32);
+
+  CircleGen cgen;
+  uint32_t ker_buf = cgen.addBuffer(std::vector<uint8_t>{
+    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
+    2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
+    2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3});
+  uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>(output_depth, 0));
+  int in = cgen.addTensor({{1, 2, 2, input_depth}, circle::TensorType_UINT8}, 0.5, 0);
+  int ker = cgen.addTensor({{1, 2, 2, output_depth}, circle::TensorType_UINT8, ker_buf}, 0.5, 0);
+  int bias = cgen.addTensor({{output_depth}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
+  int out = cgen.addTensor({{1, 1, 1, output_depth}, circle::TensorType_UINT8}, 1, 0);
+  cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, circle::Padding::Padding_VALID, stride,
+                                  stride, depth_multiplier, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+  return cgen.finish();
+}
+
+TEST_P(DepthwiseConv2DQuantTestU8, Test)
+{
+  // Same input is used for all tests but output differs
+  static const std::vector<uint8_t> input64{
+    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2,
+    2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 3, 5, 8, 8, 5, 3, 2, 1, 2, 3, 4, 5, 4, 3, 2};
+
+  auto &param = GetParam();
+  _context = std::make_unique<GenModelTestContext>(
+    genDepthwiseConv2DQuantU8Model(param.stride, param.input_depth, param.depth_multiplier));
+  std::vector<uint8_t> ref_input(input64.begin(), input64.begin() + param.input_depth * 4);
+  _context->addTestCase(uniformTCD<uint8_t>({ref_input}, {param.ref_output}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+using DepthwiseConv2DQuantTestParamI8 = DepthwiseConv2DQuantTestParam<int8_t>;
+using DepthwiseConv2DQuantTestI8 = DepthwiseConv2DQuantTest<int8_t>;
+
+// Test with different InputDepth and DepthMultiplier. The values are intended to test optimized CPU
+// kernels.
+INSTANTIATE_TEST_SUITE_P(
+  GenModelTest, DepthwiseConv2DQuantTestI8,
+  ::testing::Values(
+    // Stride == 1
+    DepthwiseConv2DQuantTestParamI8{1, 8, 1, std::vector<int8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
+    DepthwiseConv2DQuantTestParamI8{1, 4, 2, std::vector<int8_t>{0, 0, 2, 3, 0, 2, 6, 9}},
+    DepthwiseConv2DQuantTestParamI8{
+      1, 2, 8, std::vector<int8_t>{0, 1, 2, 3, 0, 1, 2, 3, 0, 2, 4, 6, 0, 2, 4, 6}},
+    DepthwiseConv2DQuantTestParamI8{1, 2, 2, std::vector<int8_t>{0, 1, 4, 6}},
+    DepthwiseConv2DQuantTestParamI8{1, 2, 1, std::vector<int8_t>{2, 5}},
+    DepthwiseConv2DQuantTestParamI8{1, 1, 2, std::vector<int8_t>{2, 4}},
+    DepthwiseConv2DQuantTestParamI8{1, 1, 4, std::vector<int8_t>{0, 2, 3, 5}},
+    DepthwiseConv2DQuantTestParamI8{1, 4, 1, std::vector<int8_t>{0, 1, 4, 9}},
+    DepthwiseConv2DQuantTestParamI8{
+      1, 4, 4, std::vector<int8_t>{0, 0, 0, 0, 0, 1, 2, 3, 0, 2, 4, 6, 0, 3, 6, 9}},
+    DepthwiseConv2DQuantTestParamI8{1, 12, 1,
+                                    std::vector<int8_t>{0, 3, 7, 12, 0, 4, 7, 12, 0, 4, 9, 16}},
+    // Stride == 2
+    DepthwiseConv2DQuantTestParamI8{2, 4, 1, std::vector<int8_t>{0, 1, 4, 9}},
+    DepthwiseConv2DQuantTestParamI8{2, 2, 1, std::vector<int8_t>{2, 5}},
+    DepthwiseConv2DQuantTestParamI8{2, 1, 8, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5}},
+    DepthwiseConv2DQuantTestParamI8{2, 1, 32, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3,
+                                                                  5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2,
+                                                                  3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
+    DepthwiseConv2DQuantTestParamI8{
+      2, 1, 20, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
+    DepthwiseConv2DQuantTestParamI8{
+      2, 1, 16, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
+    DepthwiseConv2DQuantTestParamI8{2, 8, 1, std::vector<int8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
+    DepthwiseConv2DQuantTestParamI8{
+      2, 8, 2, std::vector<int8_t>{0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8}},
+    DepthwiseConv2DQuantTestParamI8{
+      2, 16, 1, std::vector<int8_t>{0, 3, 8, 16, 0, 4, 7, 12, 0, 3, 7, 13, 0, 4, 7, 12}}));
+
+CircleBuffer genDepthwiseConv2DQuantI8Model(int stride, int input_depth, int depth_multiplier)
+{
+  assert(1 <= stride && stride <= 2);
+  assert(1 <= input_depth && input_depth <= 16);
+  assert(1 <= depth_multiplier && depth_multiplier <= 32);
+
+  const int output_depth = input_depth * depth_multiplier;
+  assert(1 <= output_depth && output_depth <= 32);
+
+  CircleGen cgen;
+  uint32_t ker_buf = cgen.addBuffer(std::vector<int8_t>{
+    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
+    2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
+    2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3});
+  uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>(output_depth, 0));
+  int in = cgen.addTensor({{1, 2, 2, input_depth}, circle::TensorType_INT8}, 0.5, 0);
+  int ker = cgen.addTensor({{1, 2, 2, output_depth}, circle::TensorType_INT8, ker_buf}, 0.5, 0);
+  int bias = cgen.addTensor({{output_depth}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
+  int out = cgen.addTensor({{1, 1, 1, output_depth}, circle::TensorType_INT8}, 1, 0);
+  cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, circle::Padding::Padding_VALID, stride,
+                                  stride, depth_multiplier, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+  return cgen.finish();
+}
+
+TEST_P(DepthwiseConv2DQuantTestI8, Test)
+{
+  // Same input is used for all tests but output differs
+  static const std::vector<int8_t> input64{
+    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2,
+    2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 3, 5, 8, 8, 5, 3, 2, 1, 2, 3, 4, 5, 4, 3, 2};
+
+  auto &param = GetParam();
+  _context = std::make_unique<GenModelTestContext>(
+    genDepthwiseConv2DQuantI8Model(param.stride, param.input_depth, param.depth_multiplier));
+  std::vector<int8_t> ref_input(input64.begin(), input64.begin() + param.input_depth * 4);
+  _context->addTestCase(uniformTCD<int8_t>({ref_input}, {param.ref_output}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_InvalidPaddingType)
+{
+  _context = std::make_unique<GenModelTestContext>(genNegTestDepthwiseConv2DModel(
+    static_cast<circle::Padding>(99), 1, 1, 1, circle::ActivationFunctionType_NONE));
+  _context->expectFailModelLoad();
+  _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack"});
+
+  SUCCEED();
+}
+
+// TODO add other invalid operation tests like above
+
+TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_I8_NonZero_ZeroPoints)
+{
+  CircleGen cgen;
+  std::vector<int8_t> weight_data{1, 2, 3, 4, 5, 6, 7, 8};
+  uint32_t weight_buf = cgen.addBuffer(weight_data);
+  std::vector<int32_t> bias_data{0, 2};
+  uint32_t bias_buf = cgen.addBuffer(bias_data);
+  int in = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_INT8}, 0.5, 0);
+  std::vector<float> weight_scales = {0.5, 1};
+  std::vector<int64_t> weight_zeropoints = {0, 10};
+  int weight = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_INT8, weight_buf},
+                              weight_scales, weight_zeropoints);
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32}, 1.0, 0);
+  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());
+  _context->setBackends({"cpu"});
+  _context->expectFailModelLoad();
+
+  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({{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/nnfw_api/src/GenModelTests/one_op_tests/FloorMod.test.cc b/tests/nnfw_api/src/GenModelTests/one_op_tests/FloorMod.test.cc
new file mode 100644 (file)
index 0000000..803559b
--- /dev/null
@@ -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 "GenModelTest.h"
+
+#include <memory>
+
+TEST_F(GenModelTest, OneOp_FloorMod_VarToVar_Float)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorFloorMod({{lhs, rhs}, {out}});
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(
+    uniformTCD<float>({{4.0, -3.0, -7.8, 26.2}, {2.0, 2.0, -3.0, -4.0}}, {{0.0, 1.0, -1.8, -1.8}}));
+  _context->setBackends({"cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_FloorMod_VarToVar_Float_Broadcast)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorFloorMod({{lhs, rhs}, {out}});
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(
+    uniformTCD<float>({{4.0, -3.0, -6.8, 24.2}, {-3.0}}, {{-2.0, 0.0, -0.8, -2.8}}));
+  _context->setBackends({"cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_FloorMod_VarToVar_InvalidType1)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorFloorMod({{lhs, rhs}, {out}});
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->setBackends({"cpu"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_FloorMod_Broadcast_InvalidType1)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorFloorMod({{lhs, rhs}, {out}});
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->setBackends({"cpu"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_FloorMod_VarToVar_Int64)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT64});
+  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT64});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT64});
+  cgen.addOperatorFloorMod({{lhs, rhs}, {out}});
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(
+    uniformTCD<int64_t>({{10, 21, -68, 242}, {1, 2, -3, -4}}, {{0, 1, -2, -2}}));
+  _context->setBackends({"cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_FloorMod_VarToVar_Int64_Broadcast)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT64});
+  int rhs = cgen.addTensor({{1}, circle::TensorType::TensorType_INT64});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT64});
+  cgen.addOperatorFloorMod({{lhs, rhs}, {out}});
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<int64_t>({{10, 21, -67, 242}, {-3}}, {{-2, 0, -1, -1}}));
+  _context->setBackends({"cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_FloorMod_VarToVar_InvalidType2)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
+  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
+  cgen.addOperatorFloorMod({{lhs, rhs}, {out}});
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->setBackends({"cpu"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_FloorMod_Broadcast_InvalidType2)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
+  int rhs = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT32});
+  cgen.addOperatorFloorMod({{lhs, rhs}, {out}});
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->setBackends({"cpu"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/one_op_tests/Mul.test.cc b/tests/nnfw_api/src/GenModelTests/one_op_tests/Mul.test.cc
new file mode 100644 (file)
index 0000000..585ef3c
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * 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 "GenModelTest.h"
+
+#include <memory>
+
+TEST_F(GenModelTest, OneOp_Mul_Uint8_VarVar)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 1.0, 3);
+  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 2.0, 1);
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 0.5, 2);
+  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<uint8_t>({{3, 12, 5, 2}, {5, 4, 7, 0}}, {{2, 110, 50, 6}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_Mul_Int8_VarVar)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT8}, 1.0, 2);
+  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT8}, 2.0, 3);
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT8}, 0.5, -6);
+  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<int8_t>({{1, 3, 2, 4}, {5, -4, -7, 4}}, {{-14, -34, -6, 2}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_MulBroadcast_Uint8_VarVar)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 1.0, 3);
+  int rhs = cgen.addTensor({{1, 1, 1, 1}, circle::TensorType::TensorType_UINT8}, 2.0, 1);
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 0.5, 2);
+  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<uint8_t>({{3, 12, 5, 4}, {5}}, {{2, 146, 34, 18}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_MulBroadcast_Int8_VarVar)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT8}, 1.0, 2);
+  int rhs = cgen.addTensor({{1, 1, 1, 1}, circle::TensorType::TensorType_INT8}, 2.0, 3);
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT8}, 0.5, -6);
+  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<int8_t>({{1, 3, 2, 4}, {5}}, {{-14, 2, -6, 10}}));
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, OneOp_MulBroadcast_Bool_VarVar)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_BOOL});
+  int rhs = cgen.addTensor({{1, 1, 2, 1}, circle::TensorType::TensorType_BOOL});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_BOOL});
+  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->addTestCase(uniformTCD<uint8_t>({{true, false, false, true}, {true, false}},
+                                            {{true, false, false, false}}));
+  _context->setBackends({"cpu"});
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_Mul_InvalidType)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 0.1, 2);
+  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_Mul_InvalidShape)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_Mul_OneOperand)
+{
+  CircleGen cgen;
+  int in = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorMul({{in}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_Mul_ThreeOperands)
+{
+  CircleGen cgen;
+  int in = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorMul({{in, in, in}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTest, neg_OneOp_Mul_Invalid_Broadcast_Bool)
+{
+  CircleGen cgen;
+  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  int rhs = cgen.addTensor({{1, 1, 3, 1}, circle::TensorType::TensorType_FLOAT32});
+  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({lhs, rhs}, {out});
+
+  _context = std::make_unique<GenModelTestContext>(cgen.finish());
+  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/one_op_trains/Conv2D.test.cc b/tests/nnfw_api/src/GenModelTests/one_op_trains/Conv2D.test.cc
new file mode 100644 (file)
index 0000000..6fb3279
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+TEST_F(GenModelTrain, OneOp_Conv2D)
+{
+  CirclePlusGen cgen;
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(2 * 3 * 3, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(2, 0.f));
+  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
+                         circle::ActivationFunctionType_NONE, 1, 1);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(
+    uniformTCD<float>({{{4, 0,  -5, 1, 0,  4, -1, 1, -1, -3, 3,  -2, -4,
+                         1, -2, 2,  4, -4, 2, 2,  0, 4,  -1, -2, 4}}}, // input dataset
+                      {{{47, -4, -25, 9, 10, 10, -13, 11, -14, -26, -12, 26, 20, 40, 1, 3, 11,
+                         4}}},                                             // expected dataset
+                      {{403.3333f}, {324.0978f}, {267.7882f}, {226.5260f}} // losses
+                      ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(4);
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/one_op_trains/DepthwiseConvolution.test.cc b/tests/nnfw_api/src/GenModelTests/one_op_trains/DepthwiseConvolution.test.cc
new file mode 100644 (file)
index 0000000..69e7a1f
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+#include <memory>
+
+TEST_F(GenModelTrain, OneOp_DepthwiseConv2D)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(2 * 2 * 4, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(4, 0.f));
+  int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  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});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(
+    uniformTCD<float>({{{1, 2, 7, 8, 3, 4, 9, 1, 5, 6, 11, 2}}},   // input dataset
+                      {{{1, -4, 1, -3, 2, -2, 2, -4}}},            // expected dataset
+                      {{6.8750f}, {2.5275f}, {1.6320f}, {1.1701f}} // losses
+                      ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(4);
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, OneOp_DepthwiseConv2D_No_Multiplier)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(3 * 2, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(2, 0.f));
+  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 3, 1, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
+                                  circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(
+    uniformTCD<float>({{{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}}}, // input dataset
+                      {{{6.5f, 7.5f, 8.5f, 3.5f, 8.5f, 5.5f, 2.5f, 3.5f}}}, // expected dataset
+                      {{38.0000f}, {26.6868f}, {19.8101f}, {15.5431f}}      // losses
+                      ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(4);
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, OneOp_DepthwiseConv2D_No_Multiplier_RELU6)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(3 * 2, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(2, 0.f));
+  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 3, 1, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
+                                  circle::ActivationFunctionType_RELU6);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(
+    uniformTCD<float>({{{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}}}, // input dataset
+                      {{{6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f}}}, // expected dataset
+                      {{36.0000f}, {36.0000f}, {36.0000f}, {36.0000f}}      // losses
+                      ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(4);
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, OneOp_DepthwiseConv2D_3x3)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(3 * 3 * 2, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(2, 0.f));
+  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
+                                  circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(uniformTCD<float>(
+    {{{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}}},       // input dataset
+    {{{6.0f, 16.0f, 8.0f, 16.0f, 10.0f, 16.0f, 12.0f, 16.0f}}}, // expected dataset
+    {{171.0000f}, {69.5150f}, {29.9159f}, {13.7338f}}           // losses
+    ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(4);
+
+  SUCCEED();
+}
+
+// TODO Add tests for dilation
+
+TEST_F(GenModelTrain, neg_OneOp_DepthwiseConv2D_Stride)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(2 * 2 * 4, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(4, 0.f));
+  int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 0, 0, 2,
+                                  circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_OneOp_DepthwiseConv2D_Dilation)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(2 * 2 * 4, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(4, 0.f));
+  int in = cgen.addTensor({{1, 4, 4, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
+                                  circle::ActivationFunctionType_NONE, 0, 0);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_OneOp_DepthwiseConv2D_Type)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(2 * 2 * 4, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(4, 0.f));
+  int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_UINT8});
+  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
+                                  circle::ActivationFunctionType_NONE);
+  cgen.setInputsAndOutputs({in}, {out});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/GenModelTests/one_op_trains/FullyConnected.test.cc b/tests/nnfw_api/src/GenModelTests/one_op_trains/FullyConnected.test.cc
new file mode 100644 (file)
index 0000000..9f5ba66
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "GenModelTrain.h"
+
+#include <memory>
+
+TEST_F(GenModelTrain, OneOp_FullyConnected)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(8, 0.f));
+  int input = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{8}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorFullyConnected({{input, weight, bias}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(
+    uniformTCD<float>({{{1, 3}}, {{2, 1}}},                                     // inputs
+                      {{{2, 1, 5, 5, 2, 1, 5, 5}}, {{2, 1, 5, 5, 2, 1, 5, 6}}}, // expected
+                      {{14.2234f}, {13.2278f}, {12.3045f}, {11.4484f}}          // loss
+                      ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(4);
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, OneOp_FullyConnected_OptionalBias)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(8 * 2, 0.f));
+  int input = cgen.addTensor({{1, 2}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{8, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int output = cgen.addTensor({{1, 8}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorFullyConnected({{input, weight, -1 /* Optional bias */}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 2;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->addTrainCase(
+    uniformTCD<float>({{{1, 3, 2, 1}}},                                            // inputs
+                      {{{2, 1, 5, 5, 2, 1, 5, 5, 2, 1, 5, 5, 2, 1, 5, 6}}},        // expected
+                      {{14.4375f}, {13.9950f}, {13.5668f}, {13.1523f}, {12.7512f}} // loss
+                      ));
+
+  _context->setBackends({"train"});
+  // To apply backward to loss, epoch should be >= 2
+  _context->setEpoch(5);
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_OneOp_FullyConnected_FourOperand)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(16 * 4, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(16, 0.f));
+  int input = cgen.addTensor({{1, 4}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{16, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{16}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int wrong = cgen.addTensor({{16}, circle::TensorType::TensorType_FLOAT32});
+  int output = cgen.addTensor({{1, 16}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorFullyConnected({{input, weight, bias, wrong}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_OneOp_FullyConnected_InvalidWeightShape)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(16 * 4, 0.f));
+  uint32_t bias_buf = cgen.addBuffer(std::vector<float>(16, 0.f));
+  int input = cgen.addTensor({{1, 4}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{15, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int bias = cgen.addTensor({{16}, circle::TensorType::TensorType_FLOAT32, bias_buf});
+  int wrong = cgen.addTensor({{16}, circle::TensorType::TensorType_FLOAT32});
+  int output = cgen.addTensor({{1, 16}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorFullyConnected({{input, weight, bias, wrong}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailModelLoad();
+
+  SUCCEED();
+}
+
+TEST_F(GenModelTrain, neg_OneOp_FullyConnected_NoBias)
+{
+  CirclePlusGen cgen;
+
+  uint32_t weight_buf = cgen.addBuffer(std::vector<float>(16 * 4, 0.f));
+  int input = cgen.addTensor({{1, 4}, circle::TensorType::TensorType_FLOAT32});
+  int weight = cgen.addTensor({{16, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
+  int output = cgen.addTensor({{1, 16}, circle::TensorType::TensorType_FLOAT32});
+  cgen.addOperatorFullyConnected({{input, weight /* Missing bias */}, {output}});
+  cgen.setInputsAndOutputs({input}, {output});
+
+  float learning_rate = 0.01f;
+  int32_t batch_size = 1;
+  cgen.addTrainInfo({circle::Optimizer::Optimizer_SGD, learning_rate,
+                     circle::LossFn::LossFn_MEAN_SQUARED_ERROR,
+                     circle::LossReductionType::LossReductionType_SumOverBatchSize, batch_size,
+                     NNFW_TRAIN_TRAINABLE_ALL});
+
+  _context = std::make_unique<GenModelTrainContext>(cgen.finish());
+  _context->setBackends({"train"});
+  _context->expectFailCompile();
+
+  SUCCEED();
+}
diff --git a/tests/nnfw_api/src/ModelTestDynamicTensor.test.cc b/tests/nnfw_api/src/ModelTestDynamicTensor.test.cc
deleted file mode 100644 (file)
index 1ed8f95..0000000
+++ /dev/null
@@ -1,995 +0,0 @@
-/*
- * 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 <gtest/gtest.h>
-#include <nnfw_internal.h>
-
-#include "common.h"
-#include "fixtures.h"
-#include "CircleGen.h"
-#include "GenModelTest.h"
-#include "NNPackages.h"
-
-// This macro can be used instead of using NNFW_ENSURE_SUCCESS especially with negative test.
-// E.g., setInputOutput() is written with this macro and the following check is available to check
-// if there's any error while setting input or output:
-//
-//  EXPECT_ANY_THROW(setInputOutput(...));
-//
-#define THROW_WHEN_NNFW_ERROR(result)                                  \
-  do                                                                   \
-  {                                                                    \
-    if (result != NNFW_STATUS_NO_ERROR)                                \
-      throw std::runtime_error("returning error on calling nnfw api"); \
-  } while (false)
-
-template <class CPP_TYPE> struct nnfw_type;
-
-template <> struct nnfw_type<float>
-{
-  static const NNFW_TYPE dtype = NNFW_TYPE_TENSOR_FLOAT32;
-};
-
-template <> struct nnfw_type<int32_t>
-{
-  static const NNFW_TYPE dtype = NNFW_TYPE_TENSOR_INT32;
-};
-
-// TODO Add more struct nnfw_type for other types when needed
-
-template <class T_INPUT, class T_OUT>
-void setInputOutput(nnfw_session *session, const std::vector<T_INPUT> &input,
-                    std::vector<T_OUT> &actual_output)
-{
-  NNFW_STATUS result;
-  result = nnfw_set_input(session, 0, nnfw_type<T_INPUT>::dtype, input.data(),
-                          sizeof(T_INPUT) * input.size());
-  THROW_WHEN_NNFW_ERROR(result);
-
-  result = nnfw_set_output(session, 0, nnfw_type<T_OUT>::dtype, actual_output.data(),
-                           sizeof(T_OUT) * actual_output.size());
-  THROW_WHEN_NNFW_ERROR(result);
-}
-
-template <class T_INPUT0, class T_INPUT1, class T_OUT>
-void setInputOutput(nnfw_session *session, const std::vector<T_INPUT0> &input0,
-                    const std::vector<T_INPUT1> &input1, std::vector<T_OUT> &actual_output)
-{
-  NNFW_STATUS result;
-  result = nnfw_set_input(session, 0, nnfw_type<T_INPUT0>::dtype, input0.data(),
-                          sizeof(T_INPUT0) * input0.size());
-  THROW_WHEN_NNFW_ERROR(result);
-
-  result = nnfw_set_input(session, 1, nnfw_type<T_INPUT1>::dtype, input1.data(),
-                          sizeof(T_INPUT1) * input1.size());
-  THROW_WHEN_NNFW_ERROR(result);
-
-  result = nnfw_set_output(session, 0, nnfw_type<T_OUT>::dtype, actual_output.data(),
-                           sizeof(T_OUT) * actual_output.size());
-  THROW_WHEN_NNFW_ERROR(result);
-}
-
-template <class T_OUTPUT>
-void verifyOutput(nnfw_session *session, const nnfw_tensorinfo expected_ti,
-                  const std::vector<T_OUTPUT> &expected, const std::vector<T_OUTPUT> &actual)
-{
-  uint32_t output_num = -1;
-  nnfw_tensorinfo t_out;
-  NNFW_ENSURE_SUCCESS(nnfw_output_size(session, &output_num));
-  NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(session, 0, &t_out));
-
-  ASSERT_EQ(output_num, 1);
-
-  // nnfw_tensorinfo of output
-  tensorInfoEqual(t_out, expected_ti);
-
-  // value of output
-  ASSERT_EQ(expected.size(), actual.size());
-  for (int i = 0; i < expected.size(); i++)
-  {
-    bool is_output_float = std::is_same<T_OUTPUT, float>::value;
-    if (is_output_float)
-      ASSERT_FLOAT_EQ(expected[i], actual[i]);
-    else
-      ASSERT_EQ(expected[i], actual[i]);
-  }
-}
-
-/**
- * @brief Testing the following model:
- *
- * Testing the following model:
- *       #1 = const(value = [-1.5, -1.0, -0.5, 0.5, 1.0, 1.5], shape=[2, 3])
- *       #2 = placeholder (shape = [2])      <-------- this is an input
- *       #3 = reshape(#1, #2)
- *
- * @note Run this test with "cpu" backend
- */
-auto build_dynamic_Reshape()
-{
-  CircleGen cgen;
-
-  auto f32 = circle::TensorType::TensorType_FLOAT32;
-  auto i32 = circle::TensorType::TensorType_INT32;
-
-  std::vector<float> new_shape_data{-1.5, -1.0, -0.5, 0.5, 1.0, 1.5};
-  uint32_t input_buf = cgen.addBuffer(new_shape_data); // shape = [2, 3]
-  int input = cgen.addTensor({{2, 3}, f32, input_buf});
-  int new_shape = cgen.addTensor({{2}, i32});
-  int out = cgen.addTensor({{}, f32}); // scalar, meaning output shape is unspecified
-
-  CircleGen::Shape empty_new_shape;
-  cgen.addOperatorReshape({{input, new_shape}, {out}}, &empty_new_shape);
-  cgen.setInputsAndOutputs({new_shape}, {out});
-  auto cbuf = cgen.finish();
-  return cbuf;
-}
-
-TEST_F(GenModelTest, dynamic_reshape_from_2x3_to_3x2)
-{
-  const std::vector<int> new_shape{3, 2};
-  const std::vector<float> expected{-1.5, -1.0, -0.5, 0.5, 1.0, 1.5};
-
-  _context = std::make_unique<GenModelTestContext>(build_dynamic_Reshape());
-  {
-    _context->addTestCase(TestCaseData{}.addInput(new_shape).addOutput(expected));
-    _context->setBackends({"cpu"}); // Currently, dynamic tensor runs on "cpu" only
-    _context->output_sizes(0, sizeof(float) * expected.size());
-  }
-  // GenModelTest::teardown() will do the rest
-  SUCCEED();
-}
-
-/**
- * @brief Negative test.
- *        Reshape's first input has 6 values but trying to reshaping to [3, 3]
- */
-TEST_F(GenModelTest, neg_reshape_from_2x3_to_wrong_3x3)
-{
-  const std::vector<int> wrong_shape{3, 3}; // wrong shape input
-  const std::vector<float> expected{0};     // whatever
-
-  _context = std::make_unique<GenModelTestContext>(build_dynamic_Reshape());
-  {
-
-    _context->addTestCase(TestCaseData{}.addInput(wrong_shape).addOutput(expected).expectFailRun());
-    _context->setBackends({"cpu"}); // Currently, dynamic tensor runs on "cpu" only
-    _context->output_sizes(0, sizeof(float) * expected.size());
-  }
-  // GenModelTest::teardown() will do the rest
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, reshape_multiple_executions)
-{
-  std::vector<int> new_shape;
-  std::vector<float> expected = {-1.5, -1.0, -0.5, 0.5, 1.0, 1.5};
-
-  _context = std::make_unique<GenModelTestContext>(build_dynamic_Reshape());
-  {
-    _context->addTestCase(TestCaseData{}.addInput<int>({3, 2}).addOutput(expected));
-    _context->addTestCase(TestCaseData{}.addInput<int>({1, 6}).addOutput(expected));
-    _context->addTestCase(TestCaseData{}.addInput<int>({6, 1}).addOutput(expected));
-
-    _context->setBackends({"cpu"}); // Currently, dynamic tensor runs on "cpu" only
-    _context->output_sizes(0, sizeof(float) * expected.size());
-  }
-  // GenModelTest::teardown() will do the rest
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_reshape_multiple_executions)
-{
-  std::vector<int> new_shape;
-  std::vector<float> expected = {-1.5, -1.0, -0.5, 0.5, 1.0, 1.5};
-
-  auto add_tcd = [&](const decltype(new_shape) &&new_shape, bool expect_fail_on_run) {
-    TestCaseData tcd;
-    tcd.addInput(new_shape).addOutput(expected);
-    if (expect_fail_on_run)
-      tcd.expectFailRun();
-    _context->addTestCase(tcd);
-  };
-
-  _context = std::make_unique<GenModelTestContext>(build_dynamic_Reshape());
-  {
-    bool EXPECT_FAIL_ON_RUN = true;
-    bool EXPECT_SUCCESS_ON_RUN = !EXPECT_FAIL_ON_RUN;
-
-    add_tcd({3, 2}, EXPECT_SUCCESS_ON_RUN);
-    add_tcd({1, 100}, EXPECT_FAIL_ON_RUN); // 1th tcd. wrong shape
-    add_tcd({6, 1}, EXPECT_SUCCESS_ON_RUN);
-
-    _context->setBackends({"cpu"}); // Currently, dynamic tensor runs on "cpu" only
-    _context->output_sizes(0, sizeof(float) * expected.size());
-  }
-  // GenModelTest::teardown() will do the rest
-  SUCCEED();
-}
-
-//
-// Unknown Dimension Test
-//    Trying to set unknown dim to other value before calling nnfw_prepare()
-//
-
-/**
- * @brief Testing the following model:
- *
- *        #0 = placeholder([None, None])   # initially, shape is [1, 1]
- *        #1 = placeholder([2, 3])
- *        #2 = concat (#0, #1, axis=0)
- *
- *        Calling sequence:
- *        - nnfw_set_input_tensorinfo(#0, [1, 3])    # now, [1, 3]
- *        - nnfw_prepare()                 # this should work
- *        - nnfw_set_input()
- *        - nnfw_run()
- *
- * @note Run this test with "cpu" backend
- */
-auto build_model_buf_Concatenation_unknwon_dims()
-{
-  // Model is not important
-  CircleGen cgen;
-  auto f32 = circle::TensorType::TensorType_FLOAT32;
-  int in1 = cgen.addTensor({{1, 1}, f32}); // consider this [None, None]
-  int in2 = cgen.addTensor({{2, 3}, f32});
-  int out = cgen.addTensor({{}, f32}); // scalar, meaning output shape is unspecified
-  cgen.addOperatorConcatenation({{in1, in2}, {out}}, 0, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in1, in2}, {out});
-  auto cbuf = cgen.finish();
-  return cbuf;
-}
-
-TEST(TestDynamicTensor, concat_unknown_dim_input0_to_2x3)
-{
-  nnfw_session *session = nullptr;
-  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
-  const auto model_buf = build_model_buf_Concatenation_unknwon_dims();
-  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, model_buf.buffer(), model_buf.size()));
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
-
-  const std::vector<float> input0 = {1, 2, 3};          // of shape [1, 3]
-  const std::vector<float> input1 = {4, 5, 6, 7, 8, 9}; // of shape [2, 3]
-
-  const std::vector<float> expected = {1, 2, 3, 4, 5, 6, 7, 8, 9};
-  std::vector<float> actual_output(expected.size());
-
-  // input reshaping to [1, 3]
-  nnfw_tensorinfo ti = {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 3}};
-  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(session, 0, &ti));
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
-
-  setInputOutput(session, input0, input1, actual_output);
-
-  // Do inference
-  NNFW_STATUS res = nnfw_run(session);
-  NNFW_ENSURE_SUCCESS(res);
-
-  verifyOutput(session, {NNFW_TYPE_TENSOR_FLOAT32, 2, {3, 3}}, expected, actual_output);
-}
-
-/**
- * @brief Negative Test: Testing the following model:
- *
- *        #0 = placeholder([None, None])         # initially, [1, 1]
- *        #1 = placeholder([2, 3])
- *        #2 = concat (#0, #1, axis=0)
- *
- *        Calling sequence:
- *        - nnfw_set_input tensorinfo(#0, [3, 1]) # now [3, 1]
- *        - nnfw_prepare()                        # should fail (shape mismatch)
- *        - nnfw_set_input()
- *        - nnfw_run()
- *
- * @note Run this test with "cpu" backend and "linear" executor
- */
-TEST(TestDynamicTensor, neg_concat_input0_to_wrong_shape)
-{
-  nnfw_session *session = nullptr;
-  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
-  const auto model_buf = build_model_buf_Concatenation_unknwon_dims();
-  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, model_buf.buffer(), model_buf.size()));
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
-
-  const std::vector<float> input0 = {1, 2, 3};          // of shape [3, 1], wrong shape
-  const std::vector<float> input1 = {4, 5, 6, 7, 8, 9}; // of shape [2, 3]
-
-  std::vector<float> actual_output(100); // whatever size
-
-  // input reshaping to [3, 1]
-  nnfw_tensorinfo ti = {NNFW_TYPE_TENSOR_FLOAT32, 2, {3, 1}};
-  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(session, 0, &ti));
-
-  ASSERT_EQ(nnfw_prepare(session), NNFW_STATUS_ERROR);
-}
-
-//
-// test about calling nnfw_set_input_tensorinfo() after compilation
-//
-
-/**
- * @brief Testing the following model, which has a binary operation:
- *
- *        #0 = placeholder([])
- *        #1 = placeholder([1, 2, 3])
- *        #2 = add (#0, #1)
- *        #3 = add (#2, #2)
- *
- *        Calling sequence:
- *        - nnfw_prepare()
- *        - nnfw_set_input_tensorinfo(#0, [2, 2, 3]) // This will make #3 tensor's shape [2, 2, 3]
- *        - nnfw_set_input()
- *        - nnfw_run()
- *
- * @note Run this test with "cpu" backend
- */
-auto build_model_buf_Add_unspecified_rank()
-{
-  // Model is not important
-  CircleGen cgen;
-  auto f32 = circle::TensorType::TensorType_FLOAT32;
-  int in1 = cgen.addTensor({{}, f32}); // scalar, meaning shape is unspecified
-  int in2 = cgen.addTensor({{1, 2, 3}, f32});
-  int op_out = cgen.addTensor({{}, f32}); // unspecified
-  int out = cgen.addTensor({{}, f32});    // unspecified
-  cgen.addOperatorAdd({{in1, in2}, {op_out}}, circle::ActivationFunctionType_NONE);
-  cgen.addOperatorAdd({{op_out, op_out}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in1, in2}, {out});
-  auto cbuf = cgen.finish();
-  return cbuf;
-}
-
-TEST(TestDynamicTensor, set_input_tensorinfo_after_compilation_add)
-{
-  nnfw_session *session = nullptr;
-  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
-  const auto model_buf = build_model_buf_Add_unspecified_rank();
-  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, model_buf.buffer(), model_buf.size()));
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
-
-  // input reshaping to [2, 2, 3]
-  nnfw_tensorinfo input0_ti = {NNFW_TYPE_TENSOR_FLOAT32, 3, {2, 2, 3}};
-
-  std::vector<float> input0 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
-  std::vector<float> input1 = {0.1, 0.1, 0.1, 0.1, 0.1, 0.1};
-  std::vector<float> actual_output(12);
-  std::vector<float> expected_output = {1.1 * 2, 2.1 * 2, 3.1 * 2, 4.1 * 2,  5.1 * 2,  6.1 * 2,
-                                        7.1 * 2, 8.1 * 2, 9.1 * 2, 10.1 * 2, 11.1 * 2, 12.1 * 2};
-
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(session, 0, &input0_ti));
-
-  setInputOutput(session, input0, input1, actual_output);
-
-  // Do inference
-  NNFW_STATUS res = nnfw_run(session);
-  NNFW_ENSURE_SUCCESS(res);
-
-  verifyOutput(session, {NNFW_TYPE_TENSOR_FLOAT32, 3, {2, 3, 3}}, expected_output, actual_output);
-}
-
-/**
- * @brief Testing the following model, which has a unary operation:
- *
- *        #0 = placeholder(shape = [4, 4])
- *        #1 = neg (#0)
- *
- *        Calling sequence:
- *        - nnfw_prepare()
- *        - nnfw_set_input_tensorinfo(#0, [20, 50])
- *        - nnfw_set_input()
- *        - nnfw_run()
- *
- * @note Run this test with "cpu" backend
- */
-
-auto build_model_buf_NEG()
-{
-  // Model is not important
-  CircleGen cgen;
-  int in = cgen.addTensor({{4, 4}, circle::TensorType::TensorType_FLOAT32});
-  int out = cgen.addTensor({{4, 4}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorNeg({{in}, {out}});
-  cgen.setInputsAndOutputs({in}, {out});
-  auto cbuf = cgen.finish();
-  return cbuf;
-}
-
-TEST(TestDynamicTensor, set_input_tensorinfo_after_compilation_neg)
-{
-  nnfw_session *session = nullptr;
-  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
-  const auto model_buf = build_model_buf_NEG();
-  nnfw_load_circle_from_buffer(session, model_buf.buffer(), model_buf.size());
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
-
-  nnfw_tensorinfo input0_ti_original = {NNFW_TYPE_TENSOR_FLOAT32, 2, {4, 4}};
-
-  // input reshaping to [20, 50]
-  nnfw_tensorinfo input0_ti;
-  {
-    input0_ti.dtype = NNFW_TYPE_TENSOR_FLOAT32;
-    input0_ti.rank = 2;
-    input0_ti.dims[0] = 20;
-    input0_ti.dims[1] = 50;
-  }
-
-  std::vector<float> input0(20 * 50);
-  std::vector<float> actual_output(20 * 50);
-  std::vector<float> expected_output(20 * 50);
-
-  for (int i = 0; i < input0.size(); i++)
-  {
-    input0[i] = i * 1.1;
-    expected_output[i] = -1 * input0[i];
-  }
-
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
-
-  // input shape check
-  {
-    nnfw_tensorinfo ti = {};
-    NNFW_ENSURE_SUCCESS(nnfw_input_tensorinfo(session, 0, &ti));
-    ASSERT_TRUE(tensorInfoEqual(input0_ti_original, ti));
-  }
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(session, 0, &input0_ti));
-
-  // input shape check
-  {
-    nnfw_tensorinfo ti = {};
-    NNFW_ENSURE_SUCCESS(nnfw_input_tensorinfo(session, 0, &ti));
-    ASSERT_TRUE(tensorInfoEqual(input0_ti, ti));
-  }
-
-  setInputOutput(session, input0, actual_output);
-
-  // Do inference
-  NNFW_STATUS res = nnfw_run(session);
-  NNFW_ENSURE_SUCCESS(res);
-
-  // output value check
-  verifyOutput(session, {NNFW_TYPE_TENSOR_FLOAT32, 2, {20, 50}}, expected_output, actual_output);
-}
-
-using TestWhileDynamicModelLoaded = ValidationTestModelLoaded<NNPackages::WHILE_DYNAMIC>;
-
-// clang-format off
-const static std::vector<float> while_dynamic_input0{ 0.4325029254, 0.7332934141, 0.2969786823, 0.1540192217, 0.4608841240, 0.1523699313, 0.4334940016, 0.1022945493, 0.6928671598, 0.5891978741, 0.8283287883, 0.7041553259, 0.5243381262, 0.5623597503, 0.3395180404, 0.3212788701, 0.5248492956, 0.2551939189, 0.1338981092, 0.6406514645, 0.7089318633, 0.8164196610, 0.7689018846, 0.3551857173, 0.7668499351, 0.4942102134, 0.7345644236, 0.4689270556, 0.3495515287, 0.0768318549, 0.0868133679, 0.7823525667, 0.0791761801, 0.4397472143, 0.8150953054, 0.5074489713, 0.0895665437, 0.9451501966, 0.1064314246, 0.8803006411, 0.9903403521, 0.1259460151, 0.1889930069, 0.7466737032, 0.0553287826, 0.9712036252, 0.6352610588, 0.6301708817, 0.3079694211, 0.5367568731, 0.4070350230, 0.6815373302, 0.6948529482, 0.6158187985, 0.1485853940, 0.9162485600, 0.3622985184, 0.2672208250, 0.3396688998, 0.4135381579, 0.6450354457, 0.2386536747, 0.7072004080, 0.5289406180, 0.0643024296, 0.1969666779, 0.8667400479, 0.3396836221, 0.5878564715, 0.4551178813, 0.4318033755, 0.4376230836, 0.8211942315, 0.0230764486, 0.9005268812, 0.2147378176, 0.6036583781, 0.7161545157, 0.8246262074, 0.2989832759, 0.5491395593, 0.9779474735, 0.2006554008, 0.8227099776, 0.6018718481, 0.0132929254, 0.2212856710, 0.2032340616, 0.3059777319, 0.9094917178, 0.5409486890, 0.5595687032, 0.2436837852, 0.5649250150, 0.6730466485, 0.4421939552, 0.1432305574, 0.7053307891, 0.6284835935, 0.9216189384, 0.8686438799, 0.8385053873, 0.6248987913, 0.7697140574, 0.9808958173, 0.7571622133, 0.2297872156, 0.4201298952, 0.1305913031, 0.4572514296, 0.3072260618, 0.4668756723, 0.1919649392, 0.2050305754, 0.6062370539, 0.0006580966, 0.6217135191, 0.5123317838, 0.7305839658, 0.0610331446, 0.3614645600, 0.6455501914, 0.2919872701, 0.6446499228, 0.6293424964, 0.6947519779, 0.2680567801, 0.9756787419, 0.6422977448, 0.6911727786, 0.0343145914, 0.4764069021, 0.0876256451, 0.2926266789, 0.0487026349, 0.3558900952, 0.7788275480, 0.8566400409, 0.4791142642, 0.0595066175, 0.9609330297, 0.4075229764, 0.8758037090, 0.3485401869, 0.7945867181, 0.3457054794, 0.3327955306, 0.2870546579, 0.5697714090, 0.6144676208, 0.3251711428, 0.2342026234, 0.4153896868, 0.2149699926, 0.1064170301, 0.7240911722, 0.8196219206, 0.0208647959, 0.3081029952, 0.5742419958, 0.3027088642, 0.5005563498, 0.1707910597, 0.3358575106, 0.2290909439, 0.7788143754, 0.7611069679, 0.3525909781, 0.2308424413, 0.2585839927, 0.5973339677, 0.3728699684, 0.4975571036, 0.0781342834, 0.7119221091, 0.3926881850, 0.5501778126, 0.7364945412, 0.4965503812, 0.8785862923, 0.6024044752, 0.2638861239, 0.9093352556, 0.9069826007, 0.0359279662, 0.4043401778, 0.3457658887, 0.1013033912, 0.1810855120, 0.4946146905, 0.0194541160, 0.5453770161, 0.7965603471, 0.5493819714, 0.2422309667, 0.8376919031, 0.8350337148, 0.1898939908, 0.4576793313, 0.9535705447, 0.1353026628, 0.9474196434, 0.4256035388, 0.0255583692, 0.9593925476, 0.9245427847, 0.9780472517, 0.4356954992, 0.5673046708, 0.7346579432, 0.8614835143, 0.8782553673, 0.3395713866, 0.0013978065, 0.7640301585, 0.2504623234, 0.3626150787, 0.6888222694, 0.9404846430, 0.3519821763, 0.6855628490, 0.2415955663, 0.2107568830, 0.7718742490, 0.3419062793, 0.1280658394, 0.5126360059, 0.1722176671, 0.6543742418, 0.4206473231, 0.2138152719, 0.4514643848, 0.4293326437, 0.0042719250, 0.3195750117, 0.3874749541, 0.6262724400, 0.1620737463, 0.7417458892, 0.8521968126, 0.6405420303, 0.0713626966, 0.0474211276, 0.9068223834, 0.8541609645, 0.4279667437, 0.9738950133, 0.7167884707, 0.6812457442, 0.7938374281, 0.2077793330, 0.5163270831, 0.8487322927, 0.6320008039, 0.5116547942, 0.0056989277, 0.5253843665, 0.1517033428, 0.9921303988, 0.8305052519, 0.0771176443, 0.4621275961, 0.0299932379, 0.8129007220, 0.0946875364, 0.4544205368, 0.0143135618, 0.6373457313, 0.8202091455, 0.3447127640, 0.8560513258, 0.8079835773, 0.9697201252, 0.1521986276, 0.2269581258, 0.2245485932, 0.3396310210, 0.2649262249, 0.7799206972, 0.4020069242, 0.4444113672, 0.8123176098, 0.6460852027, 0.2041657269, 0.7889582515, 0.6526331902, 0.6626461744, 0.6049868464, 0.6901782155, 0.3364612758, 0.3053490818, 0.1905532777, 0.5362346172, 0.3618801832, 0.3485457003, 0.4509411156, 0.5986957550, 0.7858221531, 0.8822937012, 0.8280826807, 0.5261783004, 0.7312974334, 0.6962512732, 0.5243815780, 0.2492258698, 0.1734466404, 0.2547666430, 0.9950503111, 0.1781345457, 0.5630541444, 0.4552696049, 0.8874762058, 0.5965846777, 0.3575465977, 0.1213323772, 0.2790489793, 0.3157011569, 0.6218565702, 0.0304181967, 0.4112739265, 0.7361903787, 0.6753587723, 0.3667163849, 0.6275368929, 0.4185036719, 0.4791659117, 0.1246187463, 0.6651734114, 0.1778147966, 0.8796271682, 0.3000938296, 0.5996896029, 0.5020698309, 0.1601593345, 0.4467433393, 0.0287379269, 0.9011575580, 0.2722401917, 0.1642841995, 0.9468663335, 0.0238759480, 0.7811399102, 0.2070412934, 0.3746992052, 0.8473496437, 0.3498605192, 0.2693480551, 0.1523104310, 0.9660695791, 0.8762652278, 0.1654927284, 0.8743498921, 0.3143339157, 0.3896550536, 0.7256560922, 0.2408472896, 0.0930071324, 0.3269865215, 0.8070673347, 0.1218842566, 0.9943904281, 0.6901395917, 0.9491872787, 0.3617239892, 0.5459694862, 0.9408421516, 0.5354272127, 0.0377946161, 0.3319100142, 0.9823720455, 0.2373940945, 0.2439561784, 0.0767217800, 0.1102360934, 0.6404867172, 0.7430088520, 0.0165513344, 0.9841650128, 0.0532640740, 0.1635770351, 0.3721100390, 0.0598411299, 0.6548883319, 0.3812481761, 0.8741319180, 0.6431996226, 0.0550124273, 0.2009697258, 0.6922588348, 0.0673767105, 0.3385711610, 0.6945076585, 0.7870846987, 0.3323138356, 0.1601967812, 0.9595350623, 0.6049567461, 0.2068863660, 0.2562771440, 0.1041606516, 0.3444063365, 0.1464221030, 0.8932089210, 0.2040112168, 0.3407483399, 0.3251829743, 0.4777953327, 0.0534981787, 0.3613175154, 0.6707065105, 0.1188806742, 0.8228670359, 0.9907929897, 0.1556126177, 0.5561179519, 0.0124231419, 0.2054836601, 0.5855912566, 0.8455434442, 0.2268345803, 0.1841085702, 0.1096092239, 0.8316007257, 0.5046240687, 0.2195746899, 0.9222528338, 0.3633532226, 0.9383196831, 0.8803531528, 0.5124011636, 0.3909464478, 0.2731699646, 0.1102369502, 0.7489478588, 0.0600390583, 0.9290241599, 0.1041191891, 0.9347958565, 0.5584807396, 0.7331624031, 0.2267376930, 0.2868649662, 0.0016489516, 0.2301262319, 0.5107504129, 0.6500277519, 0.6766125560, 0.2019786686, 0.5890167952, 0.7182423472, 0.6890133023, 0.4442900419, 0.5760958791, 0.1364797056, 0.8246579766, 0.2527448535, 0.5444371700, 0.1561367512, 0.7551656961, 0.7171260715, 0.4264259040, 0.3883202970, 0.9166873693, 0.6557167768, 0.0264711548, 0.0761224255, 0.4693228602, 0.5476956964, 0.6261154413, 0.7666952610, 0.9579501152, 0.2581985295, 0.2322760671, 0.8342292905, 0.8143266439, 0.5771137476, 0.5815665126, 0.9772894382, 0.2359700650, 0.6501487494, 0.7841209769, 0.2793208659, 0.1745450795, 0.9626912475, 0.2373798192, 0.1235965416, 0.4632637799, 0.3763884604, 0.9971673489, 0.3533810079, 0.3203127384, 0.6102763414, 0.3859500289, 0.5929466486, 0.6658803821, 0.4130606949, 0.0352911949, 0.9713683128, 0.7546037436, 0.9780107737, 0.3970599473, 0.0187621433, 0.4941402078, 0.7670620680, 0.5360869765, 0.9634684920, 0.5996263027, 0.1895584762, 0.1214910895, 0.7381310463, 0.4301493466, 0.7403219938, 0.4817020297, 0.1843791455, 0.6473838091, 0.4138627350, 0.6825908422, 0.4481185675, 0.2030784935, 0.8468620777, 0.8059213758, 0.7525423169, 0.1854387224, 0.9046887755, 0.6654230952, 0.2029620409, 0.7164457440, 0.4172891080, 0.7797588110, 0.4135729969, 0.0026064927, 0.8375009894, 0.8355652690, 0.9187932014, 0.6724888086, 0.0276171323, 0.9106697440, 0.4562708735, 0.3417910039, 0.1569930464, 0.2029796541, 0.5049355626, 0.8143045306, 0.2432538420, 0.1068324223, 0.6258177757, 0.9749278426, 0.5378444791, 0.1657523215, 0.1930697113, 0.4833569825, 0.8000370264, 0.4315882921, 0.7571453452, 0.6069541574, 0.2073590159, 0.8702615499, 0.1951662153, 0.9303797483, 0.9241660833, 0.2795540988, 0.4241578877, 0.2383123934, 0.8627647758, 0.1700671613, 0.9635605216, 0.2514486313, 0.7766968012, 0.7126773596, 0.7009662986, 0.1317531914, 0.1318600327, 0.5509422421, 0.2159194350, 0.7851343751, 0.7231494188, 0.3523120880, 0.4999881089, 0.8202708960, 0.6340972185, 0.9181259274, 0.0057039275, 0.7197939754, 0.3580873907, 0.1026016176, 0.9657412767, 0.1973488480, 0.8099604845, 0.3302915096, 0.7635477781, 0.7097011805, 0.6271768212, 0.6583901644, 0.2334843278, 0.9448583126, 0.7434690595, 0.4068029821, 0.8815746307, 0.6311643124, 0.3891237080, 0.1507531852, 0.5215465426, 0.3248603344, 0.5837653279, 0.6689655185, 0.1362081915, 0.5130022764, 0.8519401550, 0.4397114217, 0.4129846096, 0.8706676960, 0.4183416367, 0.1135022715, 0.3501874208, 0.1142706573, 0.4111732543, 0.3972048163, 0.0740565360, 0.8445752263, 0.5659885406, 0.1107598469, 0.1261267066, 0.3106530905, 0.9623307586, 0.0014953646, 0.0421718284, 0.9182401299, 0.6180395484, 0.7947646379, 0.4402076006, 0.7980208993, 0.6131495237, 0.8885827065, 0.9406354427, 0.4568731785, 0.8838264346, 0.7086120248, 0.2050074339, 0.8598041534, 0.6360205412, 0.6444933414, 0.1086360887, 0.2146544755, 0.4044065177, 0.8566969037, 0.0974318087, 0.9650754929, 0.7885782719, 0.5817304850, 0.0668027699, 0.2600722611, 0.9546993971, 0.2609280050, 0.2063084394, 0.2960519791, 0.8144530654, 0.5386683941, 0.2757037580, 0.3237824142, 0.3469774723, 0.5878881812, 0.8034821153, 0.7495883107, 0.8035441637, 0.6059562564, 0.2713213861, 0.4108335674, 0.5539482832, 0.5046381950, 0.8435614705, 0.3766961098, 0.7583506107, 0.6175935268, 0.3487794399, 0.0058784639, 0.2900554240, 0.9057408571, 0.1079123169, 0.3200630546, 0.7326458693, 0.0237412248, 0.2757625282, 0.8461791873, 0.6101186872, 0.3705151379, 0.6318973899, 0.4013423026, 0.0222425349, 0.0391604938, 0.6966052055, 0.3186582327, 0.3277960122, 0.3301376998, 0.0874366611, 0.3782529831, 0.1412206143, 0.2574128807, 0.3423563242, 0.7656893730, 0.2097123116, 0.8109381199, 0.4845644534, 0.1744513661, 0.3877931535, 0.5369505286, 0.0147142150, 0.2457712293, 0.4901090264, 0.6373463869, 0.2244705260, 0.6722853184, 0.2888159454, 0.5694347620, 0.3042352200, 0.3482132256, 0.5619021654, 0.6760555506, 0.2648956776, 0.9160912037, 0.8973199129, 0.8901007175, 0.8260267973, 0.2438062280, 0.8338996172, 0.7751584649, 0.1436893344, 0.3578631580, 0.8111414909, 0.9454294443, 0.6478928924, 0.0714371502, 0.0711339787, 0.6473786235, 0.0266824700, 0.2442116290, 0.5528301001, 0.2558279037, 0.3684701622, 0.6729193330, 0.8132147193, 0.5830360651, 0.8655517101, 0.0593610443, 0.9748560190, 0.0221947283, 0.6729801893, 0.5001031756, 0.5116565824, 0.2824120522, 0.4552524984, 0.1693765223, 0.1908069402, 0.7663541436, 0.5339511037, 0.0649234429, 0.6125215292, 0.6771115661, 0.6019635797, 0.6840563416, 0.9653987288, 0.1369341463, 0.8428027630, 0.5227881670, 0.5990189910, 0.0936695337, 0.3645765185, 0.9354769588, 0.6745044589, 0.2816980183, 0.3783183694, 0.7331027389, 0.4139548242, 0.1671119779, 0.6703656316, 0.8604171872, 0.6643752456, 0.7547178268, 0.1386961490, 0.4443438351, 0.3267543018, 0.3348949254, 0.9952459931, 0.4534417391, 0.2089741081 };
-const static std::vector<float> while_dynamic_output0{ 0.0388205424, 0.0426156297, 0.0980401114, 0.0568757951, 0.1230962500, 0.0412184112, 0.0595490113, 0.4391007423, 0.0377574340, 0.0629260018 };
-// clang-format on
-
-TEST_F(TestWhileDynamicModelLoaded, run_verify)
-{
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session, "cpu"));
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session));
-
-  std::vector<float> actual_output0(10);
-
-  nnfw_tensorinfo ti = {NNFW_TYPE_TENSOR_FLOAT32, 3, {1, 28, 28}};
-  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(_session, 0, &ti));
-
-  setInputOutput(_session, while_dynamic_input0, actual_output0);
-
-  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-
-  // output check
-  verifyOutput(_session, {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 10}}, while_dynamic_output0,
-               actual_output0);
-}
-
-TEST_F(TestWhileDynamicModelLoaded, neg_run_verify)
-{
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session, "cpu"));
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session));
-
-  nnfw_tensorinfo ti = {NNFW_TYPE_TENSOR_FLOAT32, 3, {1, 28, 28}};
-  NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(_session, 0, &ti));
-
-  // Insufficient size of output (10 or more is sufficient)
-  std::vector<float> actual_output0(9);
-
-  setInputOutput(_session, while_dynamic_input0, actual_output0);
-
-  ASSERT_EQ(nnfw_run(_session), NNFW_STATUS_INSUFFICIENT_OUTPUT_SIZE);
-}
-
-using TestIfDynamicModelLoaded = ValidationTestModelLoaded<NNPackages::IF_DYNAMIC>;
-
-// clang-format off
-const static std::vector<float> if_dynamic_input0{ 0.7106545568, 0.2156167328, 0.0837147385, 0.0381200500, 0.8007305861, 0.2976274490, 0.8563324213, 0.7781477571, 0.5745304823, 0.8303883672, 0.0862579569, 0.0544887781, 0.1988027841, 0.2230974138, 0.4716774523, 0.4606758952, 0.4920695722, 0.1058474109, 0.0391142406, 0.9550740719, 0.9775217772, 0.1644495875, 0.6734005809, 0.2771040201, 0.4015675485, 0.9389892220, 0.5739571452, 0.6168602109, 0.4262073934, 0.1955287308, 0.6361171603, 0.3251913190, 0.9311535358, 0.9403554797, 0.2734249830, 0.8866292834, 0.5992837548, 0.2142961770, 0.7889495492, 0.0741494149, 0.1030917764, 0.4724597037, 0.3861218989, 0.8098146915, 0.2832616270, 0.6557519436, 0.5689851642, 0.8294774294, 0.4495503902, 0.5395354629, 0.7472639680, 0.4290334582, 0.6575341225, 0.3844197690, 0.5194811821, 0.9411858320, 0.8186575174, 0.6588338614, 0.5179415941, 0.7074140310, 0.1678132862, 0.7229011655, 0.3164389431, 0.6544682384, 0.7210181952, 0.0454275832, 0.6507202387, 0.4012205899, 0.2719061375, 0.2579342127, 0.1064170823, 0.5994709730, 0.1010676920, 0.3968397975, 0.5670611858, 0.1786351353, 0.9127767086, 0.9268618822, 0.6603804827, 0.3673154712, 0.3415949941, 0.5930755138, 0.3685272932, 0.6884198189, 0.1833280921, 0.3941298127, 0.0632725284, 0.1516269594, 0.2316887528, 0.8105147481, 0.1674028039, 0.2784884572, 0.5205677748, 0.4399658442, 0.6527903080, 0.6785870790, 0.2533956766, 0.0617546029, 0.5094803572, 0.5204600096, 0.0249194298, 0.0450648703, 0.1241398007, 0.3705165386, 0.9986394048, 0.6402000785, 0.4894598126, 0.8702902794, 0.4500190616, 0.8115220070, 0.8781826496, 0.6121248603, 0.9077111483, 0.4646541476, 0.7442384362, 0.5584337115, 0.0265889056, 0.9247944951, 0.5661407709, 0.9730864167, 0.6722183824, 0.9564477801, 0.6998952627, 0.6105464697, 0.8297851086, 0.7167860270, 0.6002981067, 0.4256598651, 0.1964918524, 0.9581518769, 0.3121621907, 0.8813912272, 0.3803862929, 0.8825226426, 0.9783715010, 0.1397246420, 0.6996101737, 0.1947445422, 0.9981691837, 0.9528205395, 0.1440794915, 0.2994889319, 0.9605104923, 0.7394120097, 0.8036665916, 0.1226263046, 0.5607838035, 0.5100311637, 0.9977583289, 0.1812620014, 0.8162402511, 0.6829946637, 0.8054547906, 0.5318715572, 0.2573204339, 0.6401459575, 0.9395645857, 0.0523465686, 0.1189657971, 0.4010948837, 0.5229173303, 0.3700955212, 0.8600971103, 0.2058345824, 0.0952973440, 0.6578513980, 0.8096982241, 0.3292799890, 0.3189097345, 0.2228140533, 0.7665079832, 0.3701375425, 0.7601019740, 0.8501300216, 0.5380855203, 0.7509619594, 0.8447382450, 0.6025870442, 0.6957519054, 0.6805172563, 0.5877657533, 0.3472520709, 0.0291769207, 0.0723123997, 0.4284786880, 0.5264689922, 0.4927068353, 0.7379829884, 0.9378200173, 0.8644418716, 0.8671935797, 0.9434295297, 0.5507473350, 0.0760083497, 0.1079615131, 0.1603826135, 0.2987570167, 0.4970068038, 0.0533443913, 0.7932291627, 0.4054899216, 0.8708239794, 0.8852948546, 0.7709504366, 0.2500700951, 0.7328734398, 0.1770015359, 0.4787373245, 0.6746702790, 0.6232759953, 0.8252257109, 0.5074343681, 0.4582579136, 0.7136889100, 0.1850759387, 0.0999758169, 0.9016878009, 0.0968299136, 0.9786298275, 0.7106815577, 0.5932894945, 0.5901473165, 0.8644450903, 0.8777941465, 0.3545308709, 0.5543619394, 0.4764245450, 0.4866352081, 0.7842248678, 0.8535351157, 0.8261910677, 0.4928103089, 0.4883008599, 0.9132300615, 0.0520589016, 0.0571883246, 0.8107213974, 0.2263001502, 0.4195134640, 0.1585850269, 0.6892622709, 0.9932649732, 0.9146085382, 0.3438154757, 0.3597939610, 0.8383805156, 0.1434784085, 0.1592836231, 0.3735914230, 0.5118701458, 0.6597173810, 0.5932899714, 0.7643446326, 0.7639417052, 0.7257087231, 0.8367394209, 0.7241969705, 0.2863937616, 0.7383541465, 0.3918549418, 0.8693540096, 0.8002281189, 0.0121407788, 0.3702836633, 0.3193098009, 0.2857846618, 0.3450623155, 0.8419249654, 0.4484305680, 0.0768098459, 0.1011011526, 0.9832069874, 0.2806532979, 0.6486470103, 0.0038275064, 0.5200383663, 0.5825559497, 0.8526763320, 0.2604954541, 0.4765493274, 0.8257845044, 0.9679267406, 0.3583108485, 0.5755933523, 0.6114814878, 0.5805739164, 0.1076851040, 0.0532303862, 0.3102329671, 0.2268214077, 0.3422079682, 0.3890814781, 0.2123251557, 0.6259000301, 0.9530308843, 0.2377676368, 0.4969599247, 0.3911451399, 0.6869695187, 0.4768487513, 0.0319234431, 0.5153809190, 0.7592291832, 0.5699093938, 0.6517769098, 0.1294958293, 0.5191193819, 0.9886645675, 0.2082915604, 0.9330775738, 0.1966033280, 0.7179551721, 0.4047450423, 0.3280299902, 0.7132403255, 0.7453812361, 0.1643252373, 0.0279585645, 0.0323586352, 0.0771650672, 0.8751529455, 0.3228718042, 0.0091584828, 0.2462333292, 0.2639203966, 0.1246995181, 0.7825807929, 0.0825880542, 0.5019466281, 0.5546332598, 0.2470002472, 0.3974646032, 0.3941309452, 0.2988025546, 0.5270965099, 0.0565799475, 0.7965186834, 0.8401004672, 0.8962592483, 0.2836867571, 0.9854408503, 0.1736569554, 0.3543607295, 0.1489263922, 0.0296417754, 0.8644942045, 0.5768237114, 0.5055403709, 0.7033663988, 0.7610059381, 0.7680964470, 0.9276048541, 0.4661210179, 0.1926902831, 0.8331482410, 0.3478438258, 0.4423305690, 0.1226840168, 0.2631755769, 0.7300418615, 0.8501742482, 0.7732837200, 0.1645421237, 0.9328539968, 0.3299001455, 0.1737864316, 0.6760513186, 0.6878529191, 0.8000500202, 0.7643007040, 0.8427000046, 0.7743517756, 0.4847290516, 0.5107879639, 0.1321444362, 0.2521093190, 0.6971111894, 0.9226302505, 0.7618960738, 0.0798677281, 0.9345219731, 0.3526974618, 0.5779649615, 0.6659775376, 0.0080328183, 0.6179481745, 0.3388322592, 0.8871348500, 0.3849443495, 0.5805974007, 0.4485530853, 0.0118454825, 0.1535516083, 0.9892683029, 0.6305456758, 0.8417525887, 0.9201779366, 0.5443179011, 0.3694557250, 0.9480580688, 0.0420885272, 0.3705308735, 0.1857404709, 0.2711791396, 0.3184533417, 0.2894020677, 0.8524381518, 0.1369639933, 0.5524237156, 0.2515565455, 0.2611325383, 0.7106022239, 0.7720850706, 0.5917789340, 0.1294544786, 0.1406515092, 0.4081685841, 0.7773256898, 0.0337970816, 0.2720888555, 0.6040735841, 0.4713420272, 0.2154571265, 0.7050493360, 0.5699684024, 0.8653516769, 0.2943878472, 0.0710595697, 0.7601916790, 0.8260607719, 0.5490139127, 0.2270360142, 0.6353984475, 0.0237506367, 0.1613635123, 0.2657604814, 0.9112974405, 0.3940451145, 0.9857107997, 0.6584201455, 0.2996906042, 0.6385321617, 0.3025711179, 0.5442391634, 0.5316760540, 0.9278558493, 0.2960957289, 0.2758596539, 0.8092618585, 0.7210826278, 0.5532572269, 0.0433825813, 0.4293606579, 0.9231137037, 0.7861453891, 0.0529759154, 0.2881730795, 0.4177611172, 0.0751738325, 0.2110737860, 0.0087767169, 0.9394732714, 0.7669738531, 0.1285874546, 0.0892729312, 0.7701640129, 0.3619799912, 0.1591310948, 0.5716432333, 0.3634774089, 0.5689123273, 0.1703432053, 0.7500917912, 0.8368289471, 0.6899937391, 0.8733949065, 0.3469920754, 0.9645365477, 0.9452517629, 0.0622390397, 0.0313139819, 0.9253467917, 0.5542111993, 0.4027656317, 0.5191525817, 0.3981988430, 0.7461462021, 0.6761778593, 0.2998072505, 0.8195981979, 0.6851982474, 0.0545753241, 0.1639913172, 0.8172791600, 0.7425212264, 0.1970316321, 0.1586989313, 0.3941454589, 0.8775137067, 0.3532845676, 0.1445332468, 0.4015854299, 0.7155395746, 0.4261780679, 0.7957311273, 0.8265135884, 0.5879834294, 0.7252638340, 0.3942884803, 0.7504889965, 0.5733796358, 0.7747340798, 0.9431585670, 0.5627400875, 0.3371616900, 0.6190663576, 0.5733695626, 0.2214016914, 0.8767938614, 0.2509712279, 0.6909803748, 0.3777657151, 0.6170743704, 0.7373610735, 0.0204360615, 0.7325904369, 0.4920690358, 0.5081653595, 0.9917234182, 0.2093250901, 0.8361138105, 0.7211740017, 0.2606147230, 0.3064637780, 0.1124278903, 0.6320124269, 0.2425052077, 0.4785803258, 0.4747911394, 0.8021139503, 0.3956191838, 0.7217889428, 0.7445480227, 0.1360257119, 0.3709513843, 0.5552678704, 0.2192365974, 0.9431814551, 0.8592399359, 0.7907270789, 0.5545215607, 0.6895139813, 0.1169689223, 0.2043674886, 0.0381150991, 0.7708708644, 0.4759636819, 0.9230924845, 0.6857032776, 0.4432366490, 0.3041133285, 0.7970084548, 0.5629503727, 0.2329168320, 0.2320910394, 0.8098289967, 0.8152811527, 0.9269255996, 0.2628753185, 0.7178934216, 0.1607068628, 0.6057552695, 0.5256694555, 0.5559988022, 0.8001552820, 0.5592993498, 0.5585735440, 0.7596833110, 0.4926379025, 0.8108907342, 0.5142205954, 0.8292154074, 0.9844856262, 0.9281103611, 0.8271671534, 0.8411998153, 0.4101325572, 0.9839829803, 0.1782312542, 0.5126013756, 0.4867194891, 0.9041156173, 0.8752650619, 0.9434064627, 0.5353408456, 0.3405859768, 0.9340458512, 0.1240679324, 0.5371315479, 0.3755141199, 0.2990591526, 0.0670647249, 0.0626592115, 0.7673836946, 0.2539713681, 0.4617587030, 0.9303754568, 0.4884444177, 0.9808034897, 0.7934950590, 0.9362392426, 0.8001930714, 0.8370914459, 0.4767935276, 0.8847136497, 0.8713309765, 0.8301703334, 0.9254899621, 0.5875709057, 0.4544037282, 0.2598260045, 0.7427998781, 0.7183818817, 0.9003841877, 0.0916625410, 0.2609814405, 0.6743535399, 0.7733583450, 0.7338136435, 0.7596724033, 0.7973198891, 0.0015392932, 0.2874146104, 0.1189730167, 0.4800435603, 0.7962353230, 0.4249678552, 0.7483268380, 0.0146148857, 0.6297842860, 0.3471757770, 0.9144366980, 0.8106345534, 0.1789025515, 0.7346886992, 0.1539165080, 0.4280290008, 0.2338476181, 0.3317435384, 0.9998268485, 0.3580373228, 0.9422348738, 0.1251947135, 0.5737128258, 0.6803853512, 0.0485891216, 0.8118965626, 0.7890921235, 0.7665926218, 0.8405004144, 0.3489693701, 0.1429360062, 0.1063490957, 0.5086215734, 0.1312662065, 0.0978318676, 0.4471830130, 0.0830681920, 0.0757851526, 0.1809245348, 0.9280508757, 0.4107315242, 0.5944178104, 0.5625417829, 0.2328256220, 0.9285324812, 0.9903659821, 0.9403946996, 0.5126894712, 0.0232842807, 0.3405880928, 0.6531285644, 0.8213183880, 0.7210904360, 0.4180826247, 0.7917050719, 0.7738851309, 0.1693093032, 0.4396123290, 0.7139748335, 0.8910710216, 0.5668603778, 0.4374921620, 0.8098046780, 0.4076835811, 0.1027061120, 0.5390046835, 0.0044658147, 0.8642644286, 0.8590582609, 0.2715446949, 0.8128718734, 0.7381446362, 0.3621498942, 0.5211849809, 0.6139976382, 0.8567240834, 0.1329502016, 0.2441152930, 0.4219030440, 0.1751736850, 0.6326612234, 0.3929811120, 0.0947103724, 0.1078760102, 0.8769059777, 0.1599343121, 0.6111860275, 0.0368208028, 0.0899466202, 0.9127882719, 0.1146656275, 0.4647151828, 0.3303563893, 0.5797663927, 0.8400436044, 0.2845958769, 0.2181742340, 0.9651557207, 0.1241061762, 0.0102593508, 0.6999664903, 0.8487475514, 0.6001151800, 0.9682601690, 0.6127328873, 0.1502806544, 0.2512893379, 0.3930048048, 0.3448313475, 0.5263126493, 0.7319667935, 0.9264212251, 0.4489789009, 0.0418849625, 0.5219999552, 0.3397078812, 0.4435234964, 0.4758536220, 0.1290920675, 0.1649249196, 0.1736114621, 0.5685442686, 0.3253444433, 0.0540574715, 0.2022368759, 0.0260062832, 0.9889448285, 0.2064949423, 0.3756456375, 0.8462600112, 0.8166462779, 0.1788506061, 0.6607533097, 0.1638182998, 0.7888727188, 0.3304887116, 0.3085075021, 0.6626392603, 0.2860932350, 0.1577534527, 0.0126363616, 0.1958409399, 0.2475458980, 0.1514713019, 0.5241229534, 0.9845717549, 0.8002693653, 0.3091083765, 0.3348104060, 0.1341333240, 0.3546191454, 0.3800157905, 0.0364337005 };
-const static std::vector<float> if_dynamic_output0{ 0.0444660522, 0.0271649156, 0.0191113371, 0.0014375688, 0.0690929219, 0.0001767588, 0.0030322229, 0.0118752792, 0.0419745520, 0.7816683054 };
-// clang-format on
-
-TEST_F(TestIfDynamicModelLoaded, run_verify)
-{
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session, "cpu"));
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session));
-
-  nnfw_tensorinfo ti_output0_expected = {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 10}};
-
-  // Output tensor sizes are inferenced after `nnfw_prepare`
-  {
-    nnfw_tensorinfo ti;
-    NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_session, 0, &ti));
-    ASSERT_TRUE(tensorInfoEqual(ti, ti_output0_expected));
-  }
-
-  std::vector<float> actual_output0(10);
-  setInputOutput(_session, if_dynamic_input0, actual_output0);
-
-  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-
-  // Check output tensor sizes again
-  {
-    nnfw_tensorinfo ti;
-    NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_session, 0, &ti));
-    ASSERT_TRUE(tensorInfoEqual(ti, ti_output0_expected));
-  }
-
-  // Output value check
-  for (int i = 0; i < actual_output0.size(); ++i)
-    ASSERT_NEAR(if_dynamic_output0[i], actual_output0[i], 0.00001);
-}
-
-class CombinationTest1 : public ::testing::Test
-{
-protected:
-  void SetUp() override
-  {
-    CircleGen cgen;
-
-    // Creating a graph which has dynamic tensors after compilation.
-    // #3 and #4 are dynamic. This model was used to check if internal dynamic tensors could
-    // make any side-effect.
-    //
-    // #0 = input 0 of shape [1]
-    // #1 = input 1 of shape [2]
-    // #2 = cast(#0, int to float)
-    // #3 = reshape(const of shape [4] , #1)
-    // #4 = add(#2, #3)
-
-    constexpr circle::TensorType CIRCLE_DTYPE = circle::TensorType::TensorType_FLOAT32;
-
-    int cast_in = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32});
-    int cast_out = cgen.addTensor({{1}, circle::TensorType::TensorType_FLOAT32});
-
-    cgen.addOperatorCast({{cast_in}, {cast_out}}, circle::TensorType::TensorType_INT32,
-                         circle::TensorType::TensorType_FLOAT32);
-
-    std::vector<float> reshape_in_data{0, 1, 2, 3}; // defining constant tensor
-    uint32_t reshape_in_buf = cgen.addBuffer(reshape_in_data);
-    int reshape_in = cgen.addTensor({{4}, CIRCLE_DTYPE, reshape_in_buf});
-    int reshape_shape_in = cgen.addTensor({{2}, circle::TensorType::TensorType_INT32});
-    int reshape_out = cgen.addTensor({{}, CIRCLE_DTYPE}); // dynamic tensor of shape {}
-
-    cgen.addOperatorReshape({{reshape_in, reshape_shape_in}, {reshape_out}});
-
-    int out = cgen.addTensor({{}, CIRCLE_DTYPE}); // dynamic tensor of shape {}
-    cgen.addOperatorAdd({{cast_out, reshape_out}, {out}}, circle::ActivationFunctionType_NONE);
-    cgen.setInputsAndOutputs({cast_in, reshape_shape_in}, {out});
-
-    _circle_buffer = cgen.finish();
-  }
-
-  void TearDown() override
-  { // DO NOTHING
-  }
-
-  void setSession(nnfw_session *session) { _session = session; }
-
-  CircleBuffer &getCircleBuffer() { return _circle_buffer; }
-
-  void run_WITHOUT_set_input_tensorinfo(const std::vector<int32_t> &cast_input,
-                                        const std::vector<int32_t> &reshape_shape_input,
-                                        const nnfw_tensorinfo &expected_ti,
-                                        const std::vector<float> &expected,
-                                        std::vector<float> &actual)
-  {
-    setInputOutput(_session, cast_input, reshape_shape_input, actual);
-    NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-    verifyOutput(_session, expected_ti, expected, actual);
-  }
-
-  void run_WITH_set_input_tensorinfo(int32_t new_dim_0, const std::vector<int32_t> &cast_input,
-                                     const std::vector<int32_t> &reshape_shape_input,
-                                     const nnfw_tensorinfo &expected_ti,
-                                     const std::vector<float> &expected, std::vector<float> &actual)
-  {
-    nnfw_tensorinfo t_in;
-    t_in.dtype = NNFW_TYPE_TENSOR_INT32;
-    t_in.rank = 1;
-    t_in.dims[0] = new_dim_0;
-    NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(_session, 0, &t_in));
-
-    setInputOutput(_session, cast_input, reshape_shape_input, actual);
-    NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-    verifyOutput(_session, expected_ti, expected, actual);
-  }
-
-private:
-  nnfw_session *_session;
-  CircleBuffer _circle_buffer;
-};
-
-// test for https://github.com/Samsung/ONE/issues/4625
-TEST_F(CombinationTest1, combination_of_set_input_tensorinfo_and_nnfw_run)
-{
-  constexpr NNFW_TYPE NNFW_DTYPE = NNFW_TYPE_TENSOR_FLOAT32;
-  std::vector<int32_t> cast_in_buf;
-  std::vector<int32_t> reshape_shape_in_buf;
-  std::vector<float> actual(4), expected(4);
-
-  nnfw_session *session = nullptr;
-  auto &cbuf = getCircleBuffer();
-
-  auto create_prepare_session = [&](const CircleBuffer &cbuf) {
-    NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
-    NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, cbuf.buffer(), cbuf.size()));
-    NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
-    NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
-  };
-
-  // combinations of executions of static and dynamic tensors
-  // 1) no change on the shape of #0 -> change #0 to shape [1] -> no change. use previous shape
-  // 2) no change on the shape of #0 -> change #0 to shape [2] -> no change. use previous shape
-  // 3) no change on the shape of #0 -> change #0 to shape [2] -> change #0 to shape [1]
-
-  // 1) no change on the shape of #0 -> change #0 to shape [1] -> no input change
-  //       static                             dynamic                      dynamic
-  create_prepare_session(cbuf);
-  {
-    setSession(session);
-
-    // no change on the shape of #0
-    cast_in_buf = {10};
-    reshape_shape_in_buf = {1, 4};
-    expected = {10, 11, 12, 13};
-    run_WITHOUT_set_input_tensorinfo(cast_in_buf, reshape_shape_in_buf,
-                                     {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
-
-    // change to the default shape [1] of #0, this treats 0# dynamic
-    int32_t new_dim_0 = 1;
-    cast_in_buf = {10};
-    reshape_shape_in_buf = {1, 4};
-    expected = {10, 11, 12, 13};
-    run_WITH_set_input_tensorinfo(new_dim_0, cast_in_buf, reshape_shape_in_buf,
-                                  {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
-
-    // no change. Use previous shape
-    run_WITHOUT_set_input_tensorinfo(cast_in_buf, reshape_shape_in_buf,
-                                     {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
-
-    NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
-  }
-
-  // 2) no change on the shape of #0 -> change #0 to shape [2] -> no change(use previous shape)
-  //       static                             dynamic                      dynamic
-  create_prepare_session(cbuf);
-  {
-    setSession(session);
-
-    // no change on the shape of #0
-    cast_in_buf = {10};
-    reshape_shape_in_buf = {1, 4};
-    expected = {10, 11, 12, 13};
-    run_WITHOUT_set_input_tensorinfo(cast_in_buf, reshape_shape_in_buf,
-                                     {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
-
-    // change shape of #0 to [2], this treats 0# dynamic
-    int32_t new_dim_0 = 2;
-    cast_in_buf = {10, 20};
-    reshape_shape_in_buf = {2, 2};
-    expected = {10, 21, 12, 23};
-    run_WITH_set_input_tensorinfo(new_dim_0, cast_in_buf, reshape_shape_in_buf,
-                                  {NNFW_TYPE_TENSOR_FLOAT32, 2, {2, 2}}, expected, actual);
-
-    // no change. Use previous shape
-    run_WITH_set_input_tensorinfo(new_dim_0, cast_in_buf, reshape_shape_in_buf,
-                                  {NNFW_TYPE_TENSOR_FLOAT32, 2, {2, 2}}, expected, actual);
-
-    NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
-  }
-
-  // 3) no change on the shape of #0 -> change #0 to shape [2] -> change #0 to shape [1]
-  //       static                             dynamic                      dynamic
-  create_prepare_session(cbuf);
-  {
-    setSession(session);
-
-    // no change on the shape of #0
-    cast_in_buf = {10};
-    reshape_shape_in_buf = {1, 4};
-    expected = {10, 11, 12, 13};
-    run_WITHOUT_set_input_tensorinfo(cast_in_buf, reshape_shape_in_buf,
-                                     {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
-
-    // change shape of #0 to [2], this treats 0# dynamic
-    int32_t new_dim_0 = 2;
-    cast_in_buf = {10, 20};
-    reshape_shape_in_buf = {2, 2};
-    expected = {10, 21, 12, 23};
-    run_WITH_set_input_tensorinfo(new_dim_0, cast_in_buf, reshape_shape_in_buf,
-                                  {NNFW_TYPE_TENSOR_FLOAT32, 2, {2, 2}}, expected, actual);
-
-    // change #0 to shape [1]
-    new_dim_0 = 1;
-    cast_in_buf = {100};
-    reshape_shape_in_buf = {1, 4};
-    expected = {100, 101, 102, 103};
-    run_WITH_set_input_tensorinfo(new_dim_0, cast_in_buf, reshape_shape_in_buf,
-                                  {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
-
-    NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
-  }
-}
-
-TEST_F(CombinationTest1, neg_combination_of_set_input_tensorinfo_and_nnfw_run)
-{
-  nnfw_session *session = nullptr;
-  auto &cbuf = getCircleBuffer();
-  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
-  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, cbuf.buffer(), cbuf.size()));
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
-
-  setSession(session);
-
-  std::vector<int32_t> cast_in_buf;
-  std::vector<int32_t> reshape_shape_in_buf;
-  std::vector<float> actual(4), expected(4);
-
-  // no change on the shape of #0
-  cast_in_buf = {10};
-  reshape_shape_in_buf = {1, 4};
-  expected = {10, 11, 12, 13};
-  setInputOutput(session, cast_in_buf, reshape_shape_in_buf, actual);
-  NNFW_ENSURE_SUCCESS(nnfw_run(session));
-
-  // change the shape of #0 to [4]
-  cast_in_buf = {10, 20, 30, 40};
-  reshape_shape_in_buf = {1, 4};
-  expected = {10, 21, 32, 43};
-  run_WITH_set_input_tensorinfo(4, cast_in_buf, reshape_shape_in_buf,
-                                {NNFW_TYPE_TENSOR_FLOAT32, 2, {1, 4}}, expected, actual);
-  setInputOutput(session, cast_in_buf, reshape_shape_in_buf, actual);
-  NNFW_ENSURE_SUCCESS(nnfw_run(session));
-
-  // run without changing #0 but caller thought that it is now shape [1]
-  cast_in_buf = {10};
-  reshape_shape_in_buf = {1, 4};
-  expected = {10, 11, 12, 13};
-  // This should throw an error
-  EXPECT_ANY_THROW(setInputOutput(session, cast_in_buf, reshape_shape_in_buf, actual));
-
-  NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
-}
-
-// Class to test set_input_tensorinfo() against "two" inputs
-class CombinationTest2 : public ::testing::Test
-{
-protected:
-  void SetUp() override
-  {
-    CircleGen cgen;
-
-    // creating a graph with two inputs
-    //
-    // #0 = input 0 of shape [1]
-    // #1 = input 1 of shape [1]
-    // #2 = add(#0, #1)
-
-    constexpr circle::TensorType CIRCLE_DTYPE = circle::TensorType::TensorType_FLOAT32;
-
-    int in0 = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32});
-    int in1 = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32});
-    int out = cgen.addTensor({{1}, circle::TensorType::TensorType_INT32});
-
-    cgen.addOperatorAdd({{in0, in1}, {out}}, circle::ActivationFunctionType_NONE);
-    cgen.setInputsAndOutputs({in0, in1}, {out});
-
-    _circle_buffer = cgen.finish();
-  }
-
-  void TearDown() override
-  { // DO NOTHING
-  }
-
-  void setSession(nnfw_session *session) { _session = session; }
-
-  CircleBuffer &getCircleBuffer() { return _circle_buffer; }
-
-  void run_WITHOUT_set_input_tensorinfo(const std::vector<int32_t> &in0,
-                                        const std::vector<int32_t> &in1,
-                                        const nnfw_tensorinfo &expected_ti,
-                                        const std::vector<int32_t> &expected,
-                                        std::vector<int32_t> &actual)
-  {
-    setInputOutput(_session, in0, in1, actual);
-    NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-    verifyOutput(_session, expected_ti, expected, actual);
-  }
-
-  // Pass -1 for t0_new_dim_0 (or t1_new_dim_0)
-  // if shape of tensor 0 (or tensor 1) does not changed from the shape in a model
-  void run_WITH_set_input_tensorinfo(int32_t t0_new_dim_0, int32_t t1_new_dim_0,
-                                     const std::vector<int32_t> &in0,
-                                     const std::vector<int32_t> &in1,
-                                     const nnfw_tensorinfo &expected_ti,
-                                     const std::vector<int32_t> &expected,
-                                     std::vector<int32_t> &actual)
-  {
-    if (t0_new_dim_0 >= 0)
-    {
-      nnfw_tensorinfo t_in;
-      t_in.dtype = NNFW_TYPE_TENSOR_INT32;
-      t_in.rank = 1;
-      t_in.dims[0] = t0_new_dim_0;
-      NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(_session, 0, &t_in));
-    }
-
-    if (t1_new_dim_0 >= 0)
-    {
-      nnfw_tensorinfo t_in;
-      t_in.dtype = NNFW_TYPE_TENSOR_INT32;
-      t_in.rank = 1;
-      t_in.dims[0] = t1_new_dim_0;
-      NNFW_ENSURE_SUCCESS(nnfw_set_input_tensorinfo(_session, 1, &t_in));
-    }
-
-    setInputOutput(_session, in0, in1, actual);
-    NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-    verifyOutput(_session, expected_ti, expected, actual);
-  }
-
-private:
-  nnfw_session *_session;
-  CircleBuffer _circle_buffer;
-};
-
-// test for https://github.com/Samsung/ONE/issues/4625
-TEST_F(CombinationTest2, combination_set_input_tensorinfo_for_two_inputs)
-{
-  nnfw_session *session = nullptr;
-
-  // combinations of executions of static and dynamic tensors for "two" inputs (#0, #1)
-  // 0. both input shapes are [1] (input shapes of the model are [1], [1])
-  // 1. change shape of #0 to [2]
-  // 2. change shape of #0 to [1], change shape of #1 to [2]
-  // 3. change shape of #0 to [2], (shape of #1 is still [2])
-  // 4. don't call set_input_tensorinfo (both are still [2] and [2])
-  // 5. change shape of #0 to [1], change shape of #1 to [1]
-  std::vector<int32_t> in0, in1;
-  std::vector<int32_t> actual, expected;
-  nnfw_tensorinfo expected_ti;
-
-  auto &cbuf = getCircleBuffer();
-
-  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
-  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, cbuf.buffer(), cbuf.size()));
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
-  setSession(session);
-
-  constexpr int32_t NO_CHANGE = -1;
-
-  // 0. both input shapes are [1]
-  in0 = {10};
-  in1 = {100};
-  expected = {110};
-  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {1}};
-  actual.resize(1);
-  run_WITHOUT_set_input_tensorinfo(in0, in1, expected_ti, expected, actual);
-
-  // 1. change shape of #0 to [2]
-  int32_t new_dim_0 = 2;
-  int32_t new_dim_1 = NO_CHANGE;
-  in0 = {10, 20};
-  in1 = {100};
-  expected = {110, 120};
-  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {2}};
-  actual.resize(2);
-  run_WITH_set_input_tensorinfo(new_dim_0, new_dim_1, in0, in1, expected_ti, expected, actual);
-
-  // 2. change shape of #0 to [1], change shape of #1 to [2]
-  new_dim_0 = 1;
-  new_dim_1 = 2;
-  in0 = {1000};
-  in1 = {10, 20};
-  expected = {1010, 1020};
-  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {2}};
-  actual.resize(2);
-  run_WITH_set_input_tensorinfo(new_dim_0, new_dim_1, in0, in1, expected_ti, expected, actual);
-
-  // // 3. change shape of #0 to [2], (shape of #1 is still [2])
-  new_dim_0 = 2;
-  new_dim_1 = NO_CHANGE;
-  in0 = {10, 20};
-  in1 = {100, 200};
-  expected = {110, 220};
-  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {2}};
-  actual.resize(2);
-  run_WITH_set_input_tensorinfo(new_dim_0, new_dim_1, in0, in1, expected_ti, expected, actual);
-
-  // // 4. don't call set_input_tensorinfo (both are still [2] and [2])
-  in0 = {11, 22};
-  in1 = {1000, 2000};
-  expected = {1011, 2022};
-  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {2}};
-  actual.resize(2);
-  run_WITHOUT_set_input_tensorinfo(in0, in1, expected_ti, expected, actual);
-
-  // // 5. change shape of #0 to [1], change shape of #1 to [1]
-  new_dim_0 = 1;
-  new_dim_1 = 1;
-  in0 = {50};
-  in1 = {500};
-  expected = {550};
-  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {1}};
-  actual.resize(1);
-  run_WITH_set_input_tensorinfo(new_dim_0, new_dim_1, in0, in1, expected_ti, expected, actual);
-
-  NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
-}
-
-TEST_F(CombinationTest2, neg_combination_set_input_tensorinfo_for_two_inputs)
-{
-  nnfw_session *session = nullptr;
-
-  // change shape of #1 to [2]
-  // then, do not call nnfw_set_input_tensorinfo for #1
-  std::vector<int32_t> in0, in1;
-  std::vector<int32_t> expected_shape;
-  std::vector<int32_t> actual, expected;
-  nnfw_tensorinfo expected_ti;
-
-  auto &cbuf = getCircleBuffer();
-
-  NNFW_ENSURE_SUCCESS(nnfw_create_session(&session));
-  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(session, cbuf.buffer(), cbuf.size()));
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(session, "cpu"));
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(session));
-  setSession(session);
-
-  constexpr int32_t NO_CHANGE = -1;
-
-  // change shape of #1 to [2]
-  int32_t new_dim_0 = NO_CHANGE;
-  int32_t new_dim_1 = 2;
-  in0 = {10};
-  in1 = {100, 200};
-  expected = {110, 210};
-  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {2}};
-  actual.resize(2);
-  run_WITH_set_input_tensorinfo(new_dim_0, new_dim_1, in0, in1, expected_ti, expected, actual);
-
-  // then, do not call nnfw_set_input_tensorinfo for #1, thinking that
-  // #1 has now shape [1], which is wrong
-  in0 = {10};
-  in1 = {100};
-  expected = {110};                               // wrong
-  expected_ti = {NNFW_TYPE_TENSOR_INT32, 1, {1}}; // wrong
-  actual.resize(1);                               // wrong
-  EXPECT_ANY_THROW(run_WITHOUT_set_input_tensorinfo(in0, in1, expected_ti, expected, actual));
-
-  NNFW_ENSURE_SUCCESS(nnfw_close_session(session));
-}
diff --git a/tests/nnfw_api/src/NNPackageTests/AddModelLoaded.test.cc b/tests/nnfw_api/src/NNPackageTests/AddModelLoaded.test.cc
new file mode 100644 (file)
index 0000000..d0fe617
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * 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 "fixtures.h"
+#include "NNPackages.h"
+
+#include "nnfw_internal.h"
+
+using ValidationTestAddModelLoaded = ValidationTestModelLoaded<NNPackages::ADD>;
+
+TEST_F(ValidationTestAddModelLoaded, prepare_001)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session));
+
+  SUCCEED();
+}
+
+TEST_F(ValidationTestAddModelLoaded, set_available_backends_001)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session, "cpu"));
+
+  SUCCEED();
+}
+
+TEST_F(ValidationTestAddModelLoaded, get_input_size)
+{
+  uint32_t size = 0;
+  NNFW_ENSURE_SUCCESS(nnfw_input_size(_session, &size));
+  ASSERT_EQ(size, 1);
+}
+
+TEST_F(ValidationTestAddModelLoaded, get_output_size)
+{
+  uint32_t size = 0;
+  NNFW_ENSURE_SUCCESS(nnfw_output_size(_session, &size));
+  ASSERT_EQ(size, 1);
+}
+
+TEST_F(ValidationTestAddModelLoaded, output_tensorinfo)
+{
+  nnfw_tensorinfo tensor_info;
+  NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_session, 0, &tensor_info));
+  ASSERT_EQ(tensor_info.rank, 1);
+  ASSERT_EQ(tensor_info.dims[0], 1);
+}
+
+TEST_F(ValidationTestAddModelLoaded, input_output_tensorindex)
+{
+  uint32_t in_ind = 100;
+  NNFW_ENSURE_SUCCESS(nnfw_input_tensorindex(_session, "X_input", &in_ind));
+  ASSERT_EQ(in_ind, 0);
+
+  uint32_t out_ind = 100;
+  NNFW_ENSURE_SUCCESS(nnfw_output_tensorindex(_session, "ADD_TOP", &out_ind));
+  ASSERT_EQ(out_ind, 0);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_run)
+{
+  // nnfw_prepare is not called
+  ASSERT_EQ(nnfw_run(_session), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_set_input)
+{
+  // nnfw_prepare is not called
+  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
+            NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_set_output)
+{
+  // nnfw_prepare is not called
+  ASSERT_EQ(nnfw_set_output(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
+            NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_get_input_size)
+{
+  ASSERT_EQ(nnfw_input_size(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_get_output_size)
+{
+  ASSERT_EQ(nnfw_output_size(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_load_model)
+{
+  // load model twice
+  ASSERT_EQ(nnfw_load_model_from_file(
+              _session, NNPackages::get().getModelAbsolutePath(NNPackages::ADD).c_str()),
+            NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_output_tensorinfo)
+{
+  // tensor_info is null
+  ASSERT_EQ(nnfw_output_tensorinfo(_session, 0, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_input_output_tensorindex)
+{
+  uint32_t in_ind = 100;
+  ASSERT_EQ(nnfw_input_tensorindex(_session, "ADD_TOP", &in_ind), NNFW_STATUS_ERROR);
+  ASSERT_EQ(in_ind, 100);
+  ASSERT_EQ(nnfw_input_tensorindex(_session, "y_var", &in_ind), NNFW_STATUS_ERROR);
+  ASSERT_EQ(in_ind, 100);
+
+  uint32_t out_ind = 100;
+  ASSERT_EQ(nnfw_output_tensorindex(_session, "X_input", &out_ind), NNFW_STATUS_ERROR);
+  ASSERT_EQ(out_ind, 100);
+}
+
+TEST_F(ValidationTestAddModelLoaded, experimental_input_tensorindex)
+{
+  uint32_t ind = 999;
+  NNFW_ENSURE_SUCCESS(nnfw_input_tensorindex(_session, "X_input", &ind));
+  ASSERT_EQ(ind, 0);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_experimental_input_tensorindex_name_null)
+{
+  uint32_t ind = 999;
+  ASSERT_EQ(nnfw_input_tensorindex(_session, nullptr, &ind), NNFW_STATUS_UNEXPECTED_NULL);
+  ASSERT_EQ(ind, 999);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_experimental_input_tensorindex_index_null)
+{
+  ASSERT_EQ(nnfw_input_tensorindex(_session, "X_input", nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_experimental_input_name_too_long)
+{
+  std::string long_name(1024, 'x'); // Too long
+  uint32_t ind = 999;
+  ASSERT_EQ(nnfw_output_tensorindex(_session, long_name.c_str(), &ind), NNFW_STATUS_ERROR);
+  ASSERT_EQ(ind, 999);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_experimental_input_no_such_name)
+{
+  uint32_t ind = 999;
+  ASSERT_EQ(nnfw_output_tensorindex(_session, "NO_SUCH_TENSOR_NAME", &ind), NNFW_STATUS_ERROR);
+  ASSERT_EQ(ind, 999);
+}
+
+TEST_F(ValidationTestAddModelLoaded, experimental_output_tensorindex)
+{
+  uint32_t ind = 999;
+  NNFW_ENSURE_SUCCESS(nnfw_output_tensorindex(_session, "ADD_TOP", &ind));
+  ASSERT_EQ(ind, 0);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_experimental_output_tensorindex_name_null)
+{
+  uint32_t ind = 999;
+  ASSERT_EQ(nnfw_output_tensorindex(_session, nullptr, &ind), NNFW_STATUS_UNEXPECTED_NULL);
+  ASSERT_EQ(ind, 999);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_experimental_output_tensorindex_index_null)
+{
+  ASSERT_EQ(nnfw_output_tensorindex(_session, "ADD_TOP", nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_experimental_output_name_too_long)
+{
+  std::string long_name(1024, 'x'); // Too long
+  uint32_t ind = 999;
+  ASSERT_EQ(nnfw_output_tensorindex(_session, long_name.c_str(), &ind), NNFW_STATUS_ERROR);
+  ASSERT_EQ(ind, 999);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_experimental_output_no_such_name)
+{
+  uint32_t ind = 999;
+  ASSERT_EQ(nnfw_output_tensorindex(_session, "NO_SUCH_TENSOR_NAME", &ind), NNFW_STATUS_ERROR);
+  ASSERT_EQ(ind, 999);
+}
+
+TEST_F(ValidationTestAddModelLoaded, set_backends_per_operation)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_set_backends_per_operation(_session, "0=cpu;1=acl_cl"));
+  SUCCEED();
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_set_backends_per_operation)
+{
+  EXPECT_EQ(nnfw_set_backends_per_operation(_session, nullptr), NNFW_STATUS_ERROR);
+  EXPECT_EQ(nnfw_set_backends_per_operation(_session, "0?cpu;1?acl_cl"), NNFW_STATUS_ERROR);
+  EXPECT_EQ(nnfw_set_backends_per_operation(_session, "0=cpu:1=acl_cl"), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddModelLoaded, debug_set_config)
+{
+  // At least one test for all valid keys
+  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "GRAPH_DOT_DUMP", "0"));
+  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "GRAPH_DOT_DUMP", "1"));
+  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "GRAPH_DOT_DUMP", "2"));
+  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "EXECUTOR", "Linear"));
+  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "OP_BACKEND_ALLOPS", "cpu"));
+  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "USE_SCHEDULER", "0"));
+  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "USE_SCHEDULER", "1"));
+  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "PROFILING_MODE", "0"));
+  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "PROFILING_MODE", "1"));
+  SUCCEED();
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_debug_set_config)
+{
+  // unexpected null args
+  ASSERT_EQ(nnfw_set_config(_session, nullptr, "1"), NNFW_STATUS_UNEXPECTED_NULL);
+  ASSERT_EQ(nnfw_set_config(_session, "EXECUTOR", nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+
+  // wrong keys
+  ASSERT_EQ(nnfw_set_config(_session, "", "1"), NNFW_STATUS_ERROR);
+  ASSERT_EQ(nnfw_set_config(_session, "BAD_KEY", "1"), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddModelLoaded, debug_get_config)
+{
+  // At least one test for all valid keys
+  char buf[1024];
+  NNFW_ENSURE_SUCCESS(nnfw_get_config(_session, "EXECUTOR", buf, sizeof(buf)));
+  NNFW_ENSURE_SUCCESS(nnfw_get_config(_session, "BACKENDS", buf, sizeof(buf)));
+  SUCCEED();
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_debug_get_config)
+{
+  // unexpected null args
+  char buf[1024];
+  ASSERT_EQ(nnfw_get_config(_session, nullptr, buf, sizeof(buf)), NNFW_STATUS_UNEXPECTED_NULL);
+  ASSERT_EQ(nnfw_get_config(_session, "EXECUTOR", nullptr, 0), NNFW_STATUS_UNEXPECTED_NULL);
+
+  // buffer is too small
+  ASSERT_EQ(nnfw_get_config(_session, "EXECUTOR", buf, 1), NNFW_STATUS_ERROR);
+  ASSERT_EQ(nnfw_get_config(_session, "BACKENDS", buf, 1), NNFW_STATUS_ERROR);
+
+  // wrong keys
+  ASSERT_EQ(nnfw_get_config(_session, "", buf, sizeof(buf)), NNFW_STATUS_ERROR);
+  ASSERT_EQ(nnfw_get_config(_session, "BAD_KEY", buf, sizeof(buf)), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_set_workspace)
+{
+  // Call after prepare
+  EXPECT_EQ(nnfw_set_workspace(_session, "."), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestAddModelLoaded, set_prepare_config)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_set_prepare_config(_session, NNFW_PREPARE_CONFIG_PROFILE, nullptr));
+  SUCCEED();
+}
+
+TEST_F(ValidationTestAddModelLoaded, neg_set_execute_config)
+{
+  EXPECT_EQ(nnfw_set_execute_config(_session, NNFW_RUN_CONFIG_DUMP_MINMAX, nullptr),
+            NNFW_STATUS_INVALID_STATE);
+  EXPECT_EQ(nnfw_set_execute_config(_session, NNFW_RUN_CONFIG_TRACE, nullptr),
+            NNFW_STATUS_INVALID_STATE);
+  EXPECT_EQ(nnfw_set_execute_config(_session, NNFW_RUN_CONFIG_PROFILE, nullptr),
+            NNFW_STATUS_INVALID_STATE);
+}
diff --git a/tests/nnfw_api/src/NNPackageTests/AddSessionPrepared.test.cc b/tests/nnfw_api/src/NNPackageTests/AddSessionPrepared.test.cc
new file mode 100644 (file)
index 0000000..3a93739
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * 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 "fixtures.h"
+#include "NNPackages.h"
+
+using ValidationTestAddSessionPrepared = ValidationTestSessionPrepared<NNPackages::ADD>;
+
+TEST_F(ValidationTestAddSessionPrepared, run)
+{
+  SetInOutBuffers();
+  _input[0] = 3.0;
+  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+  ASSERT_FLOAT_EQ(_output[0], 5.0);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, run_twice)
+{
+  SetInOutBuffers();
+  _input[0] = 4.0;
+  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+  ASSERT_FLOAT_EQ(_output[0], 6.0);
+
+  _input[0] = 5.0f;
+  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+  ASSERT_FLOAT_EQ(_output[0], 7.0);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, run_many_times_dynamic_input)
+{
+  for (int v = 1; v <= 5; v++) // 5 times with different shapes
+  {
+    nnfw_tensorinfo ti_input = {NNFW_TYPE_TENSOR_FLOAT32, 4, {1, 1, 1, v}};
+    SetInOutBuffersDynamic(&ti_input);
+
+    for (int i = 0; i < v; i++)
+      _input[i] = i * 10.0;
+
+    NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+
+    // Check if the shape inference is correct
+    nnfw_tensorinfo ti_output;
+    ASSERT_EQ(nnfw_output_tensorinfo(_session, 0, &ti_output), NNFW_STATUS_NO_ERROR);
+    EXPECT_EQ(num_elems(&ti_input), num_elems(&ti_output));
+
+    for (int i = 0; i < v; i++)
+      ASSERT_FLOAT_EQ(_output[i], i * 10.0 + 2.0) << "i : " << i;
+  }
+}
+
+TEST_F(ValidationTestAddSessionPrepared, run_async)
+{
+  SetInOutBuffers();
+  _input[0] = 3.0;
+  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session));
+  NNFW_ENSURE_SUCCESS(nnfw_await(_session));
+  ASSERT_FLOAT_EQ(_output[0], 5.0);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, set_input_001)
+{
+  char input[32];
+  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, input, sizeof(input)),
+            NNFW_STATUS_NO_ERROR);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, get_input_size)
+{
+  uint32_t size = 0;
+  NNFW_ENSURE_SUCCESS(nnfw_input_size(_session, &size));
+  ASSERT_EQ(size, 1);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, get_output_size)
+{
+  uint32_t size = 0;
+  NNFW_ENSURE_SUCCESS(nnfw_output_size(_session, &size));
+  ASSERT_EQ(size, 1);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, output_tensorinfo)
+{
+  nnfw_tensorinfo tensor_info;
+  NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_session, 0, &tensor_info));
+  ASSERT_EQ(tensor_info.rank, 1);
+  ASSERT_EQ(tensor_info.dims[0], 1);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_await_without_async_run)
+{
+  SetInOutBuffers();
+  ASSERT_EQ(nnfw_await(_session), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_await_after_sync_run)
+{
+  SetInOutBuffers();
+  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
+  ASSERT_EQ(nnfw_await(_session), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_await_twice)
+{
+  SetInOutBuffers();
+  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session));
+  NNFW_ENSURE_SUCCESS(nnfw_await(_session));
+  ASSERT_EQ(nnfw_await(_session), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_run_during_async_run)
+{
+  SetInOutBuffers();
+  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session));
+  EXPECT_EQ(nnfw_run(_session), NNFW_STATUS_INVALID_STATE);
+  NNFW_ENSURE_SUCCESS(nnfw_await(_session));
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_set_input_001)
+{
+  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 1), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_set_input_002)
+{
+  char input[1]; // buffer size is too small
+  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, input, sizeof(input)));
+  EXPECT_EQ(nnfw_run(_session), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, set_output_001)
+{
+  char buffer[32];
+  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, buffer, sizeof(buffer)),
+            NNFW_STATUS_NO_ERROR);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_set_output_001)
+{
+  ASSERT_EQ(nnfw_set_output(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 1), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_set_output_002)
+{
+  char input[1]; // buffer size is too small
+  NNFW_ENSURE_SUCCESS(nnfw_set_output(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, input, sizeof(input)));
+  EXPECT_EQ(nnfw_run(_session), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_get_input_size)
+{
+  ASSERT_EQ(nnfw_input_size(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_get_output_size)
+{
+  ASSERT_EQ(nnfw_output_size(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_load_model)
+{
+  // Load model twice
+  ASSERT_EQ(nnfw_load_model_from_file(
+              _session, NNPackages::get().getModelAbsolutePath(NNPackages::ADD).c_str()),
+            NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_prepare)
+{
+  // Call Prepare twice
+  ASSERT_EQ(nnfw_prepare(_session), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_run_without_set_output)
+{
+  uint8_t input[4];
+  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, input, sizeof(input)));
+  // `nnfw_set_output()` is not called
+  ASSERT_EQ(nnfw_run(_session), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_internal_set_config)
+{
+  // All arguments are valid, but the session state is wrong
+  ASSERT_EQ(nnfw_set_config(_session, "GRAPH_DOT_DUMP", "0"), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_set_workspace)
+{
+  // Call after prepare
+  EXPECT_EQ(nnfw_set_workspace(_session, "."), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, neg_set_prepare_config)
+{
+  EXPECT_EQ(nnfw_set_prepare_config(_session, NNFW_PREPARE_CONFIG_PROFILE, nullptr),
+            NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestAddSessionPrepared, set_execute_config)
+{
+  // Execution config should set after nnfw_prepare
+  NNFW_ENSURE_SUCCESS(nnfw_set_execute_config(_session, NNFW_RUN_CONFIG_DUMP_MINMAX, nullptr));
+  NNFW_ENSURE_SUCCESS(nnfw_set_execute_config(_session, NNFW_RUN_CONFIG_TRACE, nullptr));
+  NNFW_ENSURE_SUCCESS(nnfw_set_execute_config(_session, NNFW_RUN_CONFIG_PROFILE, nullptr));
+  SUCCEED();
+}
+
+// TODO Validation check when "nnfw_run" is called without input & output tensor setting
diff --git a/tests/nnfw_api/src/NNPackageTests/MultipleSessions.test.cc b/tests/nnfw_api/src/NNPackageTests/MultipleSessions.test.cc
new file mode 100644 (file)
index 0000000..1d430d2
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * 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 "fixtures.h"
+#include "GenModelTests/one_op_tests/WhileTestModel.h"
+
+TEST_F(ValidationTestTwoSessions, neg_two_sessions_create)
+{
+  ASSERT_EQ(nnfw_create_session(&_session1), NNFW_STATUS_NO_ERROR);
+  ASSERT_EQ(nnfw_create_session(nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+
+  ASSERT_EQ(nnfw_close_session(_session1), NNFW_STATUS_NO_ERROR);
+}
+
+class AveragePoolModel
+{
+public:
+  AveragePoolModel(int N, int H, int W, int C)
+  {
+    CircleGen cgen;
+    int in = cgen.addTensor({{N, H, W, C}, circle::TensorType::TensorType_FLOAT32});
+    int out = cgen.addTensor({{N, H / 2, W / 2, C}, circle::TensorType::TensorType_FLOAT32});
+    cgen.addOperatorAveragePool2D({{in}, {out}}, circle::Padding_SAME, 2, 2, 2, 2,
+                                  circle::ActivationFunctionType_NONE);
+    cgen.setInputsAndOutputs({in}, {out});
+    cbuf = cgen.finish();
+  };
+
+  CircleBuffer cbuf;
+};
+
+TEST_F(ValidationTestTwoSessionsCreated, two_sessions_run_simple_AaveragePool_model)
+{
+  constexpr int N = 64, H = 64, W = 64, C = 3;
+  AveragePoolModel model(N, H, W, C);
+
+  NNFW_ENSURE_SUCCESS(
+    nnfw_load_circle_from_buffer(_session1, model.cbuf.buffer(), model.cbuf.size()));
+  NNFW_ENSURE_SUCCESS(
+    nnfw_load_circle_from_buffer(_session2, model.cbuf.buffer(), model.cbuf.size()));
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session1, "cpu"));
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session2, "cpu"));
+
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session1));
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session2));
+
+  constexpr int input_count = N * H * W * C;
+  constexpr int output_count = N * H / 2 * W / 2 * C;
+
+  std::vector<float> in_buf1(input_count); // any value
+  std::vector<float> out_buf1(output_count);
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session1, 0, NNFW_TYPE_TENSOR_FLOAT32, in_buf1.data(),
+                                     in_buf1.size() * sizeof(float)));
+  NNFW_ENSURE_SUCCESS(nnfw_set_output(_session1, 0, NNFW_TYPE_TENSOR_FLOAT32, out_buf1.data(),
+                                      out_buf1.size() * sizeof(float)));
+
+  std::vector<float> in_buf2(input_count); // any value
+  std::vector<float> out_buf2(output_count);
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session2, 0, NNFW_TYPE_TENSOR_FLOAT32, in_buf2.data(),
+                                     in_buf2.size() * sizeof(float)));
+  NNFW_ENSURE_SUCCESS(nnfw_set_output(_session2, 0, NNFW_TYPE_TENSOR_FLOAT32, out_buf2.data(),
+                                      out_buf2.size() * sizeof(float)));
+
+  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session1));
+  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session2));
+
+  NNFW_ENSURE_SUCCESS(nnfw_await(_session1));
+  NNFW_ENSURE_SUCCESS(nnfw_await(_session2));
+
+  SUCCEED();
+}
+
+TEST_F(ValidationTestTwoSessionsCreated, neg_two_sessions_model_load)
+{
+  constexpr int N = 64, H = 64, W = 64, C = 3;
+  AveragePoolModel model(N, H, W, C);
+
+  NNFW_ENSURE_SUCCESS(
+    nnfw_load_circle_from_buffer(_session1, model.cbuf.buffer(), model.cbuf.size()));
+  ASSERT_EQ(nnfw_load_circle_from_buffer(nullptr, model.cbuf.buffer(), model.cbuf.size()),
+            NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestTwoSessionsCreated, two_sessions_run_simple_While_model)
+{
+  WhileModelLoop10 model;
+
+  NNFW_ENSURE_SUCCESS(
+    nnfw_load_circle_from_buffer(_session1, model.cbuf.buffer(), model.cbuf.size()));
+  NNFW_ENSURE_SUCCESS(
+    nnfw_load_circle_from_buffer(_session2, model.cbuf.buffer(), model.cbuf.size()));
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session1, "cpu"));
+  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session2, "cpu"));
+
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session1));
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session2));
+
+  std::vector<float> in_buf1(model.inputCount()); // any value
+  std::vector<float> out_buf1(model.outputputCount());
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session1, 0, NNFW_TYPE_TENSOR_FLOAT32, in_buf1.data(),
+                                     in_buf1.size() * model.sizeOfDType()));
+  NNFW_ENSURE_SUCCESS(nnfw_set_output(_session1, 0, NNFW_TYPE_TENSOR_FLOAT32, out_buf1.data(),
+                                      out_buf1.size() * model.sizeOfDType()));
+
+  std::vector<float> in_buf2(model.inputCount()); // any value
+  std::vector<float> out_buf2(model.outputputCount());
+
+  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session2, 0, NNFW_TYPE_TENSOR_FLOAT32, in_buf2.data(),
+                                     in_buf2.size() * model.sizeOfDType()));
+  NNFW_ENSURE_SUCCESS(nnfw_set_output(_session2, 0, NNFW_TYPE_TENSOR_FLOAT32, out_buf2.data(),
+                                      out_buf2.size() * model.sizeOfDType()));
+
+  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session1));
+  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session2));
+
+  NNFW_ENSURE_SUCCESS(nnfw_await(_session1));
+  NNFW_ENSURE_SUCCESS(nnfw_await(_session2));
+
+  SUCCEED();
+}
+
+// TODO Write two-session-test with large models run by threads
diff --git a/tests/nnfw_api/src/NNPackageTests/SessionCreated.test.cc b/tests/nnfw_api/src/NNPackageTests/SessionCreated.test.cc
new file mode 100644 (file)
index 0000000..d410fe8
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * 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 "NNPackages.h"
+#include "fixtures.h"
+
+TEST_F(ValidationTestSessionCreated, load_session_001)
+{
+  // Existing model must
+  ASSERT_EQ(nnfw_load_model_from_file(
+              _session, NNPackages::get().getModelAbsolutePath(NNPackages::ADD).c_str()),
+            NNFW_STATUS_NO_ERROR);
+}
+
+TEST_F(ValidationTestSessionCreated, close_and_create_again)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_close_session(_session));
+  NNFW_ENSURE_SUCCESS(nnfw_create_session(&_session));
+
+  SUCCEED();
+}
+
+TEST_F(ValidationTestSessionCreated, neg_load_session_1)
+{
+  ASSERT_EQ(nnfw_load_model_from_file(
+              _session, NNPackages::get().getModelAbsolutePath("nonexisting_directory").c_str()),
+            NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_load_session_2)
+{
+  ASSERT_EQ(nnfw_load_model_from_file(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_load_session_3)
+{
+  // Too long path
+  const std::string long_path(1024, 'x');
+  ASSERT_EQ(nnfw_load_model_from_file(
+              _session, NNPackages::get().getModelAbsolutePath(long_path.c_str()).c_str()),
+            NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_load_invalid_package_1)
+{
+  ASSERT_EQ(
+    nnfw_load_model_from_file(
+      _session, NNPackages::get().getModelAbsolutePath(NNPackages::ADD_NO_MANIFEST).c_str()),
+    NNFW_STATUS_ERROR);
+  ASSERT_EQ(nnfw_prepare(_session), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_load_invalid_package_2)
+{
+  ASSERT_EQ(
+    nnfw_load_model_from_file(
+      _session, NNPackages::get().getModelAbsolutePath(NNPackages::ADD_INVALID_MANIFEST).c_str()),
+    NNFW_STATUS_ERROR);
+  ASSERT_EQ(nnfw_prepare(_session), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_prepare_001)
+{
+  // nnfw_load_model_from_file was not called
+  ASSERT_EQ(nnfw_prepare(_session), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_run_001)
+{
+  // nnfw_load_model_from_file and nnfw_prepare was not called
+  ASSERT_EQ(nnfw_run(_session), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_set_input_001)
+{
+  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
+            NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_set_output_001)
+{
+  ASSERT_EQ(nnfw_set_output(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
+            NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_get_input_size)
+{
+  uint32_t size = 10000;
+  ASSERT_EQ(nnfw_input_size(_session, &size), NNFW_STATUS_INVALID_STATE);
+  ASSERT_EQ(size, 10000); // Remain unchanged
+}
+
+TEST_F(ValidationTestSessionCreated, neg_get_output_size)
+{
+  uint32_t size = 10000;
+  ASSERT_EQ(nnfw_output_size(_session, &size), NNFW_STATUS_INVALID_STATE);
+  ASSERT_EQ(size, 10000); // Remain unchanged
+}
+
+TEST_F(ValidationTestSessionCreated, neg_output_tensorinfo)
+{
+  nnfw_tensorinfo tensor_info;
+  // model is not loaded
+  ASSERT_EQ(nnfw_output_tensorinfo(_session, 0, &tensor_info), NNFW_STATUS_INVALID_STATE);
+  // model is not loaded and tensor_info is null
+  ASSERT_EQ(nnfw_output_tensorinfo(_session, 0, nullptr), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_internal_set_config)
+{
+  // All arguments are valid, but the session state is wrong
+  ASSERT_EQ(nnfw_set_config(_session, "GRAPH_DOT_DUMP", "0"), NNFW_STATUS_INVALID_STATE);
+}
+
+TEST_F(ValidationTestSessionCreated, set_workspace)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_set_workspace(_session, "."));
+  SUCCEED();
+}
+
+TEST_F(ValidationTestSessionCreated, neg_set_workspace)
+{
+  ASSERT_EQ(nnfw_set_workspace(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_set_execute_config_with_no_workspace)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_set_workspace(_session, ""));
+  auto cbuf = genAddModel();
+  NNFW_ENSURE_SUCCESS(nnfw_load_circle_from_buffer(_session, cbuf.buffer(), cbuf.size()));
+  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session));
+
+  // Some execution config requires workspace
+  EXPECT_EQ(nnfw_set_execute_config(_session, NNFW_RUN_CONFIG_DUMP_MINMAX, nullptr),
+            NNFW_STATUS_ERROR);
+  EXPECT_EQ(nnfw_set_execute_config(_session, NNFW_RUN_CONFIG_TRACE, nullptr), NNFW_STATUS_ERROR);
+}
diff --git a/tests/nnfw_api/src/NNPackageTests/SingleSession.test.cc b/tests/nnfw_api/src/NNPackageTests/SingleSession.test.cc
new file mode 100644 (file)
index 0000000..fbc6c8a
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * 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 "NNPackages.h"
+#include "fixtures.h"
+
+TEST_F(ValidationTestSingleSession, create_001)
+{
+  NNFW_ENSURE_SUCCESS(nnfw_create_session(&_session));
+  NNFW_ENSURE_SUCCESS(nnfw_close_session(_session));
+
+  SUCCEED();
+}
+
+TEST_F(ValidationTestSingleSession, query_info_u32)
+{
+  uint32_t val = 0;
+  NNFW_ENSURE_SUCCESS(nnfw_query_info_u32(nullptr, NNFW_INFO_ID_VERSION, &val));
+
+  SUCCEED();
+}
+
+TEST_F(ValidationTestSingleSession, neg_create_001)
+{
+  ASSERT_EQ(nnfw_create_session(nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSingleSession, neg_run_001)
+{
+  ASSERT_EQ(nnfw_run(nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSingleSession, neg_set_input_001)
+{
+  // Invalid session
+  ASSERT_EQ(nnfw_set_input(nullptr, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
+            NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSingleSession, neg_set_input_002)
+{
+  char input[32];
+  ASSERT_EQ(nnfw_set_input(nullptr, 0, NNFW_TYPE_TENSOR_FLOAT32, input, sizeof(input)),
+            NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSingleSession, neg_set_output_001)
+{
+  // Invalid session
+  ASSERT_EQ(nnfw_set_output(nullptr, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
+            NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSingleSession, neg_set_output_002)
+{
+  char buffer[32];
+  ASSERT_EQ(nnfw_set_output(nullptr, 0, NNFW_TYPE_TENSOR_FLOAT32, buffer, sizeof(buffer)),
+            NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSingleSession, neg_get_input_size)
+{
+  uint32_t size = 10000;
+  ASSERT_EQ(nnfw_input_size(nullptr, &size), NNFW_STATUS_UNEXPECTED_NULL);
+  ASSERT_EQ(size, 10000);
+}
+
+TEST_F(ValidationTestSingleSession, neg_get_output_size)
+{
+  uint32_t size = 10000;
+  ASSERT_EQ(nnfw_output_size(nullptr, &size), NNFW_STATUS_UNEXPECTED_NULL);
+  ASSERT_EQ(size, 10000);
+}
+
+TEST_F(ValidationTestSingleSession, neg_load_model)
+{
+  // Invalid state
+  ASSERT_EQ(nnfw_load_model_from_file(
+              nullptr, NNPackages::get().getModelAbsolutePath(NNPackages::ADD).c_str()),
+            NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSingleSession, neg_prepare_001)
+{
+  ASSERT_EQ(nnfw_prepare(nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSingleSession, neg_query_info_u32)
+{
+  ASSERT_EQ(nnfw_query_info_u32(nullptr, NNFW_INFO_ID_VERSION, nullptr), NNFW_STATUS_ERROR);
+}
+
+TEST_F(ValidationTestSingleSession, neg_output_tensorinfo)
+{
+  nnfw_tensorinfo tensor_info;
+  ASSERT_EQ(nnfw_output_tensorinfo(nullptr, 0, &tensor_info), NNFW_STATUS_UNEXPECTED_NULL);
+  ASSERT_EQ(nnfw_output_tensorinfo(nullptr, 0, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSingleSession, neg_experimental_input_tensorindex_session_null)
+{
+  uint32_t ind = 999;
+  ASSERT_EQ(nnfw_input_tensorindex(nullptr, "X_input", &ind), NNFW_STATUS_UNEXPECTED_NULL);
+  ASSERT_EQ(ind, 999);
+}
+
+TEST_F(ValidationTestSingleSession, neg_experimental_output_tensorindex_session_null)
+{
+  uint32_t ind = 999;
+  ASSERT_EQ(nnfw_output_tensorindex(nullptr, "ADD_TOP", &ind), NNFW_STATUS_UNEXPECTED_NULL);
+  ASSERT_EQ(ind, 999);
+}
+
+TEST_F(ValidationTestSingleSession, neg_internal_set_config)
+{
+  ASSERT_EQ(nnfw_set_config(nullptr, "GRAPH_DOT_DUMP", "0"), NNFW_STATUS_UNEXPECTED_NULL);
+}
+
+TEST_F(ValidationTestSessionCreated, neg_deprecated_api)
+{
+  EXPECT_EQ(nnfw_apply_tensorinfo(nullptr, 0, nnfw_tensorinfo{}), NNFW_STATUS_DEPRECATED_API);
+  EXPECT_EQ(nnfw_prepare_pipeline(nullptr, nullptr), NNFW_STATUS_DEPRECATED_API);
+  EXPECT_EQ(nnfw_push_pipeline_input(nullptr, nullptr, nullptr), NNFW_STATUS_DEPRECATED_API);
+  EXPECT_EQ(nnfw_pop_pipeline_output(nullptr, nullptr), NNFW_STATUS_DEPRECATED_API);
+  EXPECT_EQ(nnfw_set_op_backend(nullptr, nullptr, nullptr), NNFW_STATUS_DEPRECATED_API);
+}
diff --git a/tests/nnfw_api/src/ValidationTestAddModelLoaded.test.cc b/tests/nnfw_api/src/ValidationTestAddModelLoaded.test.cc
deleted file mode 100644 (file)
index 0b77593..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * 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 "fixtures.h"
-#include "NNPackages.h"
-
-#include "nnfw_internal.h"
-
-using ValidationTestAddModelLoaded = ValidationTestModelLoaded<NNPackages::ADD>;
-
-TEST_F(ValidationTestAddModelLoaded, prepare_001)
-{
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session));
-
-  SUCCEED();
-}
-
-TEST_F(ValidationTestAddModelLoaded, set_available_backends_001)
-{
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session, "cpu"));
-
-  SUCCEED();
-}
-
-TEST_F(ValidationTestAddModelLoaded, get_input_size)
-{
-  uint32_t size = 0;
-  NNFW_ENSURE_SUCCESS(nnfw_input_size(_session, &size));
-  ASSERT_EQ(size, 1);
-}
-
-TEST_F(ValidationTestAddModelLoaded, get_output_size)
-{
-  uint32_t size = 0;
-  NNFW_ENSURE_SUCCESS(nnfw_output_size(_session, &size));
-  ASSERT_EQ(size, 1);
-}
-
-TEST_F(ValidationTestAddModelLoaded, output_tensorinfo)
-{
-  nnfw_tensorinfo tensor_info;
-  NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_session, 0, &tensor_info));
-  ASSERT_EQ(tensor_info.rank, 1);
-  ASSERT_EQ(tensor_info.dims[0], 1);
-}
-
-TEST_F(ValidationTestAddModelLoaded, input_output_tensorindex)
-{
-  uint32_t in_ind = 100;
-  NNFW_ENSURE_SUCCESS(nnfw_input_tensorindex(_session, "X_input", &in_ind));
-  ASSERT_EQ(in_ind, 0);
-
-  uint32_t out_ind = 100;
-  NNFW_ENSURE_SUCCESS(nnfw_output_tensorindex(_session, "ADD_TOP", &out_ind));
-  ASSERT_EQ(out_ind, 0);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_run)
-{
-  // nnfw_prepare is not called
-  ASSERT_EQ(nnfw_run(_session), NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_set_input)
-{
-  // nnfw_prepare is not called
-  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
-            NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_set_output)
-{
-  // nnfw_prepare is not called
-  ASSERT_EQ(nnfw_set_output(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
-            NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_get_input_size)
-{
-  ASSERT_EQ(nnfw_input_size(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_get_output_size)
-{
-  ASSERT_EQ(nnfw_output_size(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_load_model)
-{
-  // load model twice
-  ASSERT_EQ(nnfw_load_model_from_file(
-              _session, NNPackages::get().getModelAbsolutePath(NNPackages::ADD).c_str()),
-            NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_output_tensorinfo)
-{
-  // tensor_info is null
-  ASSERT_EQ(nnfw_output_tensorinfo(_session, 0, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_input_output_tensorindex)
-{
-  uint32_t in_ind = 100;
-  ASSERT_EQ(nnfw_input_tensorindex(_session, "ADD_TOP", &in_ind), NNFW_STATUS_ERROR);
-  ASSERT_EQ(in_ind, 100);
-  ASSERT_EQ(nnfw_input_tensorindex(_session, "y_var", &in_ind), NNFW_STATUS_ERROR);
-  ASSERT_EQ(in_ind, 100);
-
-  uint32_t out_ind = 100;
-  ASSERT_EQ(nnfw_output_tensorindex(_session, "X_input", &out_ind), NNFW_STATUS_ERROR);
-  ASSERT_EQ(out_ind, 100);
-}
-
-TEST_F(ValidationTestAddModelLoaded, experimental_input_tensorindex)
-{
-  uint32_t ind = 999;
-  NNFW_ENSURE_SUCCESS(nnfw_input_tensorindex(_session, "X_input", &ind));
-  ASSERT_EQ(ind, 0);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_experimental_input_tensorindex_name_null)
-{
-  uint32_t ind = 999;
-  ASSERT_EQ(nnfw_input_tensorindex(_session, nullptr, &ind), NNFW_STATUS_UNEXPECTED_NULL);
-  ASSERT_EQ(ind, 999);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_experimental_input_tensorindex_index_null)
-{
-  ASSERT_EQ(nnfw_input_tensorindex(_session, "X_input", nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_experimental_input_name_too_long)
-{
-  std::string long_name(1024, 'x'); // Too long
-  uint32_t ind = 999;
-  ASSERT_EQ(nnfw_output_tensorindex(_session, long_name.c_str(), &ind), NNFW_STATUS_ERROR);
-  ASSERT_EQ(ind, 999);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_experimental_input_no_such_name)
-{
-  uint32_t ind = 999;
-  ASSERT_EQ(nnfw_output_tensorindex(_session, "NO_SUCH_TENSOR_NAME", &ind), NNFW_STATUS_ERROR);
-  ASSERT_EQ(ind, 999);
-}
-
-TEST_F(ValidationTestAddModelLoaded, experimental_output_tensorindex)
-{
-  uint32_t ind = 999;
-  NNFW_ENSURE_SUCCESS(nnfw_output_tensorindex(_session, "ADD_TOP", &ind));
-  ASSERT_EQ(ind, 0);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_experimental_output_tensorindex_name_null)
-{
-  uint32_t ind = 999;
-  ASSERT_EQ(nnfw_output_tensorindex(_session, nullptr, &ind), NNFW_STATUS_UNEXPECTED_NULL);
-  ASSERT_EQ(ind, 999);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_experimental_output_tensorindex_index_null)
-{
-  ASSERT_EQ(nnfw_output_tensorindex(_session, "ADD_TOP", nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_experimental_output_name_too_long)
-{
-  std::string long_name(1024, 'x'); // Too long
-  uint32_t ind = 999;
-  ASSERT_EQ(nnfw_output_tensorindex(_session, long_name.c_str(), &ind), NNFW_STATUS_ERROR);
-  ASSERT_EQ(ind, 999);
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_experimental_output_no_such_name)
-{
-  uint32_t ind = 999;
-  ASSERT_EQ(nnfw_output_tensorindex(_session, "NO_SUCH_TENSOR_NAME", &ind), NNFW_STATUS_ERROR);
-  ASSERT_EQ(ind, 999);
-}
-
-TEST_F(ValidationTestAddModelLoaded, debug_set_config)
-{
-  // At least one test for all valid keys
-  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "TRACE_FILEPATH", ""));
-  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "GRAPH_DOT_DUMP", "0"));
-  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "GRAPH_DOT_DUMP", "1"));
-  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "GRAPH_DOT_DUMP", "2"));
-  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "EXECUTOR", "Linear"));
-  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "OP_BACKEND_ALLOPS", "cpu"));
-  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "USE_SCHEDULER", "0"));
-  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "USE_SCHEDULER", "1"));
-  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "PROFILING_MODE", "0"));
-  NNFW_ENSURE_SUCCESS(nnfw_set_config(_session, "PROFILING_MODE", "1"));
-  SUCCEED();
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_debug_set_config)
-{
-  // unexpected null args
-  ASSERT_EQ(nnfw_set_config(_session, nullptr, "1"), NNFW_STATUS_UNEXPECTED_NULL);
-  ASSERT_EQ(nnfw_set_config(_session, "EXECUTOR", nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-
-  // wrong keys
-  ASSERT_EQ(nnfw_set_config(_session, "", "1"), NNFW_STATUS_ERROR);
-  ASSERT_EQ(nnfw_set_config(_session, "BAD_KEY", "1"), NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestAddModelLoaded, debug_get_config)
-{
-  // At least one test for all valid keys
-  char buf[1024];
-  NNFW_ENSURE_SUCCESS(nnfw_get_config(_session, "EXECUTOR", buf, sizeof(buf)));
-  NNFW_ENSURE_SUCCESS(nnfw_get_config(_session, "BACKENDS", buf, sizeof(buf)));
-  SUCCEED();
-}
-
-TEST_F(ValidationTestAddModelLoaded, neg_debug_get_config)
-{
-  // unexpected null args
-  char buf[1024];
-  ASSERT_EQ(nnfw_get_config(_session, nullptr, buf, sizeof(buf)), NNFW_STATUS_UNEXPECTED_NULL);
-  ASSERT_EQ(nnfw_get_config(_session, "EXECUTOR", nullptr, 0), NNFW_STATUS_UNEXPECTED_NULL);
-
-  // buffer is too small
-  ASSERT_EQ(nnfw_get_config(_session, "EXECUTOR", buf, 1), NNFW_STATUS_ERROR);
-  ASSERT_EQ(nnfw_get_config(_session, "BACKENDS", buf, 1), NNFW_STATUS_ERROR);
-
-  // wrong keys
-  ASSERT_EQ(nnfw_get_config(_session, "", buf, sizeof(buf)), NNFW_STATUS_ERROR);
-  ASSERT_EQ(nnfw_get_config(_session, "BAD_KEY", buf, sizeof(buf)), NNFW_STATUS_ERROR);
-}
diff --git a/tests/nnfw_api/src/ValidationTestAddSessionPrepared.test.cc b/tests/nnfw_api/src/ValidationTestAddSessionPrepared.test.cc
deleted file mode 100644 (file)
index d668a1c..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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 "fixtures.h"
-#include "NNPackages.h"
-
-using ValidationTestAddSessionPrepared = ValidationTestSessionPrepared<NNPackages::ADD>;
-
-TEST_F(ValidationTestAddSessionPrepared, run)
-{
-  SetInOutBuffers();
-  _input[0] = 3.0;
-  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-  ASSERT_FLOAT_EQ(_output[0], 5.0);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, run_twice)
-{
-  SetInOutBuffers();
-  _input[0] = 4.0;
-  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-  ASSERT_FLOAT_EQ(_output[0], 6.0);
-
-  _input[0] = 5.0f;
-  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-  ASSERT_FLOAT_EQ(_output[0], 7.0);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, run_many_times_dynamic_input)
-{
-  for (int v = 1; v <= 5; v++) // 5 times with different shapes
-  {
-    nnfw_tensorinfo ti_input = {NNFW_TYPE_TENSOR_FLOAT32, 4, {1, 1, 1, v}};
-    SetInOutBuffersDynamic(&ti_input);
-
-    for (int i = 0; i < v; i++)
-      _input[i] = i * 10.0;
-
-    NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-
-    // Check if the shape inference is correct
-    nnfw_tensorinfo ti_output;
-    ASSERT_EQ(nnfw_output_tensorinfo(_session, 0, &ti_output), NNFW_STATUS_NO_ERROR);
-    EXPECT_EQ(num_elems(&ti_input), num_elems(&ti_output));
-
-    for (int i = 0; i < v; i++)
-      ASSERT_FLOAT_EQ(_output[i], i * 10.0 + 2.0) << "i : " << i;
-  }
-}
-
-TEST_F(ValidationTestAddSessionPrepared, run_async)
-{
-  SetInOutBuffers();
-  _input[0] = 3.0;
-  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session));
-  NNFW_ENSURE_SUCCESS(nnfw_await(_session));
-  ASSERT_FLOAT_EQ(_output[0], 5.0);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, set_input_001)
-{
-  char input[32];
-  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, input, sizeof(input)),
-            NNFW_STATUS_NO_ERROR);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, get_input_size)
-{
-  uint32_t size = 0;
-  NNFW_ENSURE_SUCCESS(nnfw_input_size(_session, &size));
-  ASSERT_EQ(size, 1);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, get_output_size)
-{
-  uint32_t size = 0;
-  NNFW_ENSURE_SUCCESS(nnfw_output_size(_session, &size));
-  ASSERT_EQ(size, 1);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, output_tensorinfo)
-{
-  nnfw_tensorinfo tensor_info;
-  NNFW_ENSURE_SUCCESS(nnfw_output_tensorinfo(_session, 0, &tensor_info));
-  ASSERT_EQ(tensor_info.rank, 1);
-  ASSERT_EQ(tensor_info.dims[0], 1);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_await_without_async_run)
-{
-  SetInOutBuffers();
-  ASSERT_EQ(nnfw_await(_session), NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_await_after_sync_run)
-{
-  SetInOutBuffers();
-  NNFW_ENSURE_SUCCESS(nnfw_run(_session));
-  ASSERT_EQ(nnfw_await(_session), NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_await_twice)
-{
-  SetInOutBuffers();
-  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session));
-  NNFW_ENSURE_SUCCESS(nnfw_await(_session));
-  ASSERT_EQ(nnfw_await(_session), NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_run_during_async_run)
-{
-  SetInOutBuffers();
-  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session));
-  EXPECT_EQ(nnfw_run(_session), NNFW_STATUS_INVALID_STATE);
-  NNFW_ENSURE_SUCCESS(nnfw_await(_session));
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_set_input_001)
-{
-  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 1), NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_set_input_002)
-{
-  char input[1]; // buffer size is too small
-  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, input, sizeof(input)),
-            NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, set_output_001)
-{
-  char buffer[32];
-  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, buffer, sizeof(buffer)),
-            NNFW_STATUS_NO_ERROR);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_set_output_001)
-{
-  ASSERT_EQ(nnfw_set_output(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 1), NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_set_output_002)
-{
-  char input[1]; // buffer size is too small
-  ASSERT_EQ(nnfw_set_output(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, input, sizeof(input)),
-            NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_get_input_size)
-{
-  ASSERT_EQ(nnfw_input_size(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_get_output_size)
-{
-  ASSERT_EQ(nnfw_output_size(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_load_model)
-{
-  // Load model twice
-  ASSERT_EQ(nnfw_load_model_from_file(
-              _session, NNPackages::get().getModelAbsolutePath(NNPackages::ADD).c_str()),
-            NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_prepare)
-{
-  // Call Prepare twice
-  ASSERT_EQ(nnfw_prepare(_session), NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_run_without_set_output)
-{
-  uint8_t input[4];
-  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, input, sizeof(input)));
-  // `nnfw_set_output()` is not called
-  ASSERT_EQ(nnfw_run(_session), NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestAddSessionPrepared, neg_internal_set_config)
-{
-  // All arguments are valid, but the session state is wrong
-  ASSERT_EQ(nnfw_set_config(_session, "TRACE_FILEPATH", ""), NNFW_STATUS_INVALID_STATE);
-  ASSERT_EQ(nnfw_set_config(_session, "GRAPH_DOT_DUMP", "0"), NNFW_STATUS_INVALID_STATE);
-}
-
-// TODO Validation check when "nnfw_run" is called without input & output tensor setting
diff --git a/tests/nnfw_api/src/ValidationTestMultipleSessions.test.cc b/tests/nnfw_api/src/ValidationTestMultipleSessions.test.cc
deleted file mode 100644 (file)
index ef00dc6..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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 "fixtures.h"
-#include "one_op_tests/WhileTestModel.h"
-
-TEST_F(ValidationTestTwoSessions, neg_two_sessions_create)
-{
-  ASSERT_EQ(nnfw_create_session(&_session1), NNFW_STATUS_NO_ERROR);
-  ASSERT_EQ(nnfw_create_session(nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-
-  ASSERT_EQ(nnfw_close_session(_session1), NNFW_STATUS_NO_ERROR);
-}
-
-class AveragePoolModel
-{
-public:
-  AveragePoolModel(int N, int H, int W, int C)
-  {
-    CircleGen cgen;
-    int in = cgen.addTensor({{N, H, W, C}, circle::TensorType::TensorType_FLOAT32});
-    int out = cgen.addTensor({{N, H / 2, W / 2, C}, circle::TensorType::TensorType_FLOAT32});
-    cgen.addOperatorAveragePool2D({{in}, {out}}, circle::Padding_SAME, 2, 2, 2, 2,
-                                  circle::ActivationFunctionType_NONE);
-    cgen.setInputsAndOutputs({in}, {out});
-    cbuf = cgen.finish();
-  };
-
-  CircleBuffer cbuf;
-};
-
-TEST_F(ValidationTestTwoSessionsCreated, two_sessions_run_simple_AaveragePool_model)
-{
-  constexpr int N = 64, H = 64, W = 64, C = 3;
-  AveragePoolModel model(N, H, W, C);
-
-  NNFW_ENSURE_SUCCESS(
-    nnfw_load_circle_from_buffer(_session1, model.cbuf.buffer(), model.cbuf.size()));
-  NNFW_ENSURE_SUCCESS(
-    nnfw_load_circle_from_buffer(_session2, model.cbuf.buffer(), model.cbuf.size()));
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session1, "cpu"));
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session2, "cpu"));
-
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session1));
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session2));
-
-  constexpr int input_count = N * H * W * C;
-  constexpr int output_count = N * H / 2 * W / 2 * C;
-
-  std::vector<float> in_buf1(input_count); // any value
-  std::vector<float> out_buf1(output_count);
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session1, 0, NNFW_TYPE_TENSOR_FLOAT32, in_buf1.data(),
-                                     in_buf1.size() * sizeof(float)));
-  NNFW_ENSURE_SUCCESS(nnfw_set_output(_session1, 0, NNFW_TYPE_TENSOR_FLOAT32, out_buf1.data(),
-                                      out_buf1.size() * sizeof(float)));
-
-  std::vector<float> in_buf2(input_count); // any value
-  std::vector<float> out_buf2(output_count);
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session2, 0, NNFW_TYPE_TENSOR_FLOAT32, in_buf2.data(),
-                                     in_buf2.size() * sizeof(float)));
-  NNFW_ENSURE_SUCCESS(nnfw_set_output(_session2, 0, NNFW_TYPE_TENSOR_FLOAT32, out_buf2.data(),
-                                      out_buf2.size() * sizeof(float)));
-
-  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session1));
-  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session2));
-
-  NNFW_ENSURE_SUCCESS(nnfw_await(_session1));
-  NNFW_ENSURE_SUCCESS(nnfw_await(_session2));
-
-  SUCCEED();
-}
-
-TEST_F(ValidationTestTwoSessionsCreated, neg_two_sessions_model_load)
-{
-  constexpr int N = 64, H = 64, W = 64, C = 3;
-  AveragePoolModel model(N, H, W, C);
-
-  NNFW_ENSURE_SUCCESS(
-    nnfw_load_circle_from_buffer(_session1, model.cbuf.buffer(), model.cbuf.size()));
-  ASSERT_EQ(nnfw_load_circle_from_buffer(nullptr, model.cbuf.buffer(), model.cbuf.size()),
-            NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestTwoSessionsCreated, two_sessions_run_simple_While_model)
-{
-  WhileModelLoop10 model;
-
-  NNFW_ENSURE_SUCCESS(
-    nnfw_load_circle_from_buffer(_session1, model.cbuf.buffer(), model.cbuf.size()));
-  NNFW_ENSURE_SUCCESS(
-    nnfw_load_circle_from_buffer(_session2, model.cbuf.buffer(), model.cbuf.size()));
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session1, "cpu"));
-  NNFW_ENSURE_SUCCESS(nnfw_set_available_backends(_session2, "cpu"));
-
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session1));
-  NNFW_ENSURE_SUCCESS(nnfw_prepare(_session2));
-
-  std::vector<float> in_buf1(model.inputCount()); // any value
-  std::vector<float> out_buf1(model.outputputCount());
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session1, 0, NNFW_TYPE_TENSOR_FLOAT32, in_buf1.data(),
-                                     in_buf1.size() * model.sizeOfDType()));
-  NNFW_ENSURE_SUCCESS(nnfw_set_output(_session1, 0, NNFW_TYPE_TENSOR_FLOAT32, out_buf1.data(),
-                                      out_buf1.size() * model.sizeOfDType()));
-
-  std::vector<float> in_buf2(model.inputCount()); // any value
-  std::vector<float> out_buf2(model.outputputCount());
-
-  NNFW_ENSURE_SUCCESS(nnfw_set_input(_session2, 0, NNFW_TYPE_TENSOR_FLOAT32, in_buf2.data(),
-                                     in_buf2.size() * model.sizeOfDType()));
-  NNFW_ENSURE_SUCCESS(nnfw_set_output(_session2, 0, NNFW_TYPE_TENSOR_FLOAT32, out_buf2.data(),
-                                      out_buf2.size() * model.sizeOfDType()));
-
-  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session1));
-  NNFW_ENSURE_SUCCESS(nnfw_run_async(_session2));
-
-  NNFW_ENSURE_SUCCESS(nnfw_await(_session1));
-  NNFW_ENSURE_SUCCESS(nnfw_await(_session2));
-
-  SUCCEED();
-}
-
-// TODO Write two-session-test with large models run by threads
diff --git a/tests/nnfw_api/src/ValidationTestSessionCreated.test.cc b/tests/nnfw_api/src/ValidationTestSessionCreated.test.cc
deleted file mode 100644 (file)
index cb07919..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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 "NNPackages.h"
-#include "fixtures.h"
-
-TEST_F(ValidationTestSessionCreated, load_session_001)
-{
-  // Existing model must
-  ASSERT_EQ(nnfw_load_model_from_file(
-              _session, NNPackages::get().getModelAbsolutePath(NNPackages::ADD).c_str()),
-            NNFW_STATUS_NO_ERROR);
-}
-
-TEST_F(ValidationTestSessionCreated, close_and_create_again)
-{
-  NNFW_ENSURE_SUCCESS(nnfw_close_session(_session));
-  NNFW_ENSURE_SUCCESS(nnfw_create_session(&_session));
-
-  SUCCEED();
-}
-
-TEST_F(ValidationTestSessionCreated, neg_load_session_1)
-{
-  ASSERT_EQ(nnfw_load_model_from_file(
-              _session, NNPackages::get().getModelAbsolutePath("nonexisting_directory").c_str()),
-            NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestSessionCreated, neg_load_session_2)
-{
-  ASSERT_EQ(nnfw_load_model_from_file(_session, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestSessionCreated, neg_load_session_3)
-{
-  // Too long path
-  const std::string long_path(1024, 'x');
-  ASSERT_EQ(nnfw_load_model_from_file(
-              _session, NNPackages::get().getModelAbsolutePath(long_path.c_str()).c_str()),
-            NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestSessionCreated, neg_load_invalid_package_1)
-{
-  ASSERT_EQ(
-    nnfw_load_model_from_file(
-      _session, NNPackages::get().getModelAbsolutePath(NNPackages::ADD_NO_MANIFEST).c_str()),
-    NNFW_STATUS_ERROR);
-  ASSERT_EQ(nnfw_prepare(_session), NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestSessionCreated, neg_load_invalid_package_2)
-{
-  ASSERT_EQ(
-    nnfw_load_model_from_file(
-      _session, NNPackages::get().getModelAbsolutePath(NNPackages::ADD_INVALID_MANIFEST).c_str()),
-    NNFW_STATUS_ERROR);
-  ASSERT_EQ(nnfw_prepare(_session), NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestSessionCreated, neg_prepare_001)
-{
-  // nnfw_load_model_from_file was not called
-  ASSERT_EQ(nnfw_prepare(_session), NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestSessionCreated, neg_run_001)
-{
-  // nnfw_load_model_from_file and nnfw_prepare was not called
-  ASSERT_EQ(nnfw_run(_session), NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestSessionCreated, neg_set_input_001)
-{
-  ASSERT_EQ(nnfw_set_input(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
-            NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestSessionCreated, neg_set_output_001)
-{
-  ASSERT_EQ(nnfw_set_output(_session, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
-            NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestSessionCreated, neg_get_input_size)
-{
-  uint32_t size = 10000;
-  ASSERT_EQ(nnfw_input_size(_session, &size), NNFW_STATUS_INVALID_STATE);
-  ASSERT_EQ(size, 10000); // Remain unchanged
-}
-
-TEST_F(ValidationTestSessionCreated, neg_get_output_size)
-{
-  uint32_t size = 10000;
-  ASSERT_EQ(nnfw_output_size(_session, &size), NNFW_STATUS_INVALID_STATE);
-  ASSERT_EQ(size, 10000); // Remain unchanged
-}
-
-TEST_F(ValidationTestSessionCreated, neg_output_tensorinfo)
-{
-  nnfw_tensorinfo tensor_info;
-  // model is not loaded
-  ASSERT_EQ(nnfw_output_tensorinfo(_session, 0, &tensor_info), NNFW_STATUS_INVALID_STATE);
-  // model is not loaded and tensor_info is null
-  ASSERT_EQ(nnfw_output_tensorinfo(_session, 0, nullptr), NNFW_STATUS_INVALID_STATE);
-}
-
-TEST_F(ValidationTestSessionCreated, neg_internal_set_config)
-{
-  // All arguments are valid, but the session state is wrong
-  ASSERT_EQ(nnfw_set_config(_session, "TRACE_FILEPATH", ""), NNFW_STATUS_INVALID_STATE);
-  ASSERT_EQ(nnfw_set_config(_session, "GRAPH_DOT_DUMP", "0"), NNFW_STATUS_INVALID_STATE);
-}
diff --git a/tests/nnfw_api/src/ValidationTestSingleSession.test.cc b/tests/nnfw_api/src/ValidationTestSingleSession.test.cc
deleted file mode 100644 (file)
index 852d5cd..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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 "NNPackages.h"
-#include "fixtures.h"
-
-TEST_F(ValidationTestSingleSession, create_001)
-{
-  NNFW_ENSURE_SUCCESS(nnfw_create_session(&_session));
-  NNFW_ENSURE_SUCCESS(nnfw_close_session(_session));
-
-  SUCCEED();
-}
-
-TEST_F(ValidationTestSingleSession, query_info_u32)
-{
-  uint32_t val = 0;
-  NNFW_ENSURE_SUCCESS(nnfw_query_info_u32(nullptr, NNFW_INFO_ID_VERSION, &val));
-
-  SUCCEED();
-}
-
-TEST_F(ValidationTestSingleSession, neg_create_001)
-{
-  ASSERT_EQ(nnfw_create_session(nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestSingleSession, neg_run_001)
-{
-  ASSERT_EQ(nnfw_run(nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestSingleSession, neg_set_input_001)
-{
-  // Invalid session
-  ASSERT_EQ(nnfw_set_input(nullptr, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
-            NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestSingleSession, neg_set_input_002)
-{
-  char input[32];
-  ASSERT_EQ(nnfw_set_input(nullptr, 0, NNFW_TYPE_TENSOR_FLOAT32, input, sizeof(input)),
-            NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestSingleSession, neg_set_output_001)
-{
-  // Invalid session
-  ASSERT_EQ(nnfw_set_output(nullptr, 0, NNFW_TYPE_TENSOR_FLOAT32, nullptr, 0),
-            NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestSingleSession, neg_set_output_002)
-{
-  char buffer[32];
-  ASSERT_EQ(nnfw_set_output(nullptr, 0, NNFW_TYPE_TENSOR_FLOAT32, buffer, sizeof(buffer)),
-            NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestSingleSession, neg_get_input_size)
-{
-  uint32_t size = 10000;
-  ASSERT_EQ(nnfw_input_size(nullptr, &size), NNFW_STATUS_UNEXPECTED_NULL);
-  ASSERT_EQ(size, 10000);
-}
-
-TEST_F(ValidationTestSingleSession, neg_get_output_size)
-{
-  uint32_t size = 10000;
-  ASSERT_EQ(nnfw_output_size(nullptr, &size), NNFW_STATUS_UNEXPECTED_NULL);
-  ASSERT_EQ(size, 10000);
-}
-
-TEST_F(ValidationTestSingleSession, neg_load_model)
-{
-  // Invalid state
-  ASSERT_EQ(nnfw_load_model_from_file(
-              nullptr, NNPackages::get().getModelAbsolutePath(NNPackages::ADD).c_str()),
-            NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestSingleSession, neg_prepare_001)
-{
-  ASSERT_EQ(nnfw_prepare(nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestSingleSession, neg_query_info_u32)
-{
-  ASSERT_EQ(nnfw_query_info_u32(nullptr, NNFW_INFO_ID_VERSION, nullptr), NNFW_STATUS_ERROR);
-}
-
-TEST_F(ValidationTestSingleSession, neg_output_tensorinfo)
-{
-  nnfw_tensorinfo tensor_info;
-  ASSERT_EQ(nnfw_output_tensorinfo(nullptr, 0, &tensor_info), NNFW_STATUS_UNEXPECTED_NULL);
-  ASSERT_EQ(nnfw_output_tensorinfo(nullptr, 0, nullptr), NNFW_STATUS_UNEXPECTED_NULL);
-}
-
-TEST_F(ValidationTestSingleSession, neg_experimental_input_tensorindex_session_null)
-{
-  uint32_t ind = 999;
-  ASSERT_EQ(nnfw_input_tensorindex(nullptr, "X_input", &ind), NNFW_STATUS_UNEXPECTED_NULL);
-  ASSERT_EQ(ind, 999);
-}
-
-TEST_F(ValidationTestSingleSession, neg_experimental_output_tensorindex_session_null)
-{
-  uint32_t ind = 999;
-  ASSERT_EQ(nnfw_output_tensorindex(nullptr, "ADD_TOP", &ind), NNFW_STATUS_UNEXPECTED_NULL);
-  ASSERT_EQ(ind, 999);
-}
-
-TEST_F(ValidationTestSingleSession, neg_internal_set_config)
-{
-  ASSERT_EQ(nnfw_set_config(nullptr, "TRACE_FILEPATH", ""), NNFW_STATUS_UNEXPECTED_NULL);
-  ASSERT_EQ(nnfw_set_config(nullptr, "GRAPH_DOT_DUMP", "0"), NNFW_STATUS_UNEXPECTED_NULL);
-}
diff --git a/tests/nnfw_api/src/one_op_tests/Conv2D.test.cc b/tests/nnfw_api/src/one_op_tests/Conv2D.test.cc
deleted file mode 100644 (file)
index 46632f1..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * 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 "GenModelTest.h"
-
-TEST_F(GenModelTest, OneOp_Conv2D)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{2, 3};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
-                         circle::ActivationFunctionType_NONE, 1, 1);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>(
-    {{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4}},
-    {{47, -4, -25, 9, 10, 10, -13, 11, -14, -26, -12, 26, 20, 40, 1, 3, 11, 4}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu", "ruy", "xnnpack", "gpu_cl"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_Conv2D_Stride)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{2, 3};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 2, 2,
-                         circle::ActivationFunctionType_NONE, 1, 1);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>(
-    {{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4}},
-    {{22, 27, -10, -2, 5, -8, 7, 3, -14, -26, -10, 18, 4, -13, -28, 9, 14, 1}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu", "ruy", "xnnpack"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_Conv2D_Dilation)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{2, 3};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
-                         circle::ActivationFunctionType_NONE, 2, 2);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>(
-    {{4, 0, -5, 1, 0, 4, -1, 1, -1, -3, 3, -2, -4, 1, -2, 2, 4, -4, 2, 2, 0, 4, -1, -2, 4}},
-    {{-52, 7}}));
-  _context->setBackends({"cpu", "ruy", "xnnpack"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_Conv2D_I8)
-{
-  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<int32_t> bias_data{0, 2, 4};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
-  int weight =
-    cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf}, 0.5, 0);
-  int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT32, bias_buf}, 1.0, 0);
-  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 1.0, 0);
-  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<int8_t>({{10, 10, 10}}, {{15, 38, 61}}));
-  _context->setBackends({"cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_Conv2D_I8_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<int32_t> bias_data{0, 0, 0};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
-  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_INT32, bias_buf}, 1.0, 0);
-  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 1.0, 0);
-  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<int8_t>({{10, 10, 10}}, {{15, 30, 60}}));
-  _context->setBackends({"cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_Conv2D_U8_PerChannel)
-{
-  CircleGen cgen;
-  // weight
-  std::vector<uint8_t> weight_data{2, 6, 2, 1, 2, 3, 2, 3, 4};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> weight_scales = {.5, 1, 2};
-  std::vector<int64_t> weight_zeropoints = {2, 0, 1};
-  int weight = cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_UINT8, weight_buf},
-                              weight_scales, weight_zeropoints);
-  // bias
-  std::vector<int32_t> bias_data{4, -8, -4};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT32, bias_buf}, 1., 0);
-
-  // in and out
-  int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_UINT8}, 2., 1);
-  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_UINT8}, 4., 2);
-
-  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<uint8_t>({{5, 3, 7}}, {{5, 11, 24}}));
-  _context->setBackends({"cpu"});
-
-  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;
-  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{2, 3};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT16});
-  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
-                         circle::ActivationFunctionType_NONE, 1, 1);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->expectFailModelLoad();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_Conv2D_Stride)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{2, 3};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 0, 0,
-                         circle::ActivationFunctionType_NONE, 1, 1);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->expectFailModelLoad();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_Conv2D_Dilation)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{-2, 3, -5, 3, 4, 4, 0, 0, -4, -1, -4, -2, 0, 2, 0, -1, 4, 0};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{2, 3};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 5, 5, 1}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{2, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1,
-                         circle::ActivationFunctionType_NONE, 0, 0);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->expectFailModelLoad();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_Conv2D_I8_NonZero_ZeroPoint)
-{
-  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<int32_t> bias_data{0, 2, 4};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
-  int weight =
-    cgen.addTensor({{3, 1, 1, 3}, circle::TensorType::TensorType_INT8, weight_buf}, 0.5, 17);
-  int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT32, bias_buf}, 1.0, 0);
-  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 1.0, 0);
-  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->expectFailModelLoad();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_Conv2D_I8_NonZero_ZeroPoints)
-{
-  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<int32_t> bias_data{0, 2, 4};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT8}, 0.5, 0);
-  std::vector<float> weight_scales = {0.5, 1, 0.5};
-  std::vector<int64_t> weight_zeropoints = {0, 0, 10};
-  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_INT32, bias_buf}, 1.0, 0);
-  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_FLOAT32}, 1.0, 0);
-  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->expectFailModelLoad();
-
-  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
deleted file mode 100644 (file)
index 55f43dc..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * 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 "GenModelTest.h"
-
-TEST_F(GenModelTest, OneOp_DepthwiseConv2D)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{1, 2, 3, 4};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  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());
-  _context->addTestCase(uniformTCD<float>({{1, 2, 7, 8, 3, 4, 9, 10, 5, 6, 11, 12}},
-                                          {{71, -34, 99, -20, 91, -26, 127, -4}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_DepthwiseConv2D_No_Multiplier)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{0.5f, -0.5f};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{1, 3, 1, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
-                                  circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(
-    uniformTCD<float>({{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}},
-                      {{16.5f, 27.5f, 28.5f, 43.5f, 8.5f, 15.5f, 12.5f, 23.5f}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu", "gpu_cl"});
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_DepthwiseConv2D_No_Multiplier_RELU6)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{0.5f, -0.5f};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{1, 3, 1, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
-                                  circle::ActivationFunctionType_RELU6);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}},
-                                          {{6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f, 6.0f}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu", "gpu_cl"});
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_DepthwiseConv2D_3x3)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-                                 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{0.0f, 0.0f};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 1, 1, 1,
-                                  circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(
-    uniformTCD<float>({{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}},
-                      {{6.0f, 16.0f, 8.0f, 16.0f, 10.0f, 16.0f, 12.0f, 16.0f}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu", "gpu_cl"});
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_DepthwiseConv2D_Dilation)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{0, 0, 0, 0};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 4, 4, 2}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
-                                  circle::ActivationFunctionType_NONE, 2, 2);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{
-                                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
-                                            0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                          }},
-                                          {{13, 14, 0, 0, 0, 0, 11, 12, 5, 6, 0, 0, 0, 0, 3, 4}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_DepthwiseConv2D_Dilation_N_Stride)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{1, 2, 3, 4};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{0, 0, 0, 0};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 6, 6, 1}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 1}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 3, 3, 1}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_SAME, 2, 2, 1,
-                                  circle::ActivationFunctionType_NONE, 3, 3);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<float>({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
-                                            0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
-                                          {{4, 0, 3, 0, 0, 0, 2, 0, 1}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack", "gpu_cl"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_DepthwiseConv2D_U8_PerChannel)
-{
-  CircleGen cgen;
-  // weight
-  // clang-format off
-  std::vector<uint8_t> weight_data{2, 1, 2,
-                                   6, 2, 3,
-                                   2, 3, 4,
-                                   4, 4, 5};
-  // clang-format on
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> weight_scales = {.5, 1, 2};
-  std::vector<int64_t> weight_zeropoints = {2, 0, 1};
-  int weight = cgen.addTensor({{1, 2, 2, 3}, circle::TensorType::TensorType_UINT8, weight_buf},
-                              weight_scales, weight_zeropoints);
-  // bias
-  std::vector<int32_t> bias_data{4, -8, -4};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int bias = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_INT32, bias_buf}, 1., 0);
-
-  // in and out
-  int in = cgen.addTensor({{1, 2, 2, 3}, circle::TensorType::TensorType_UINT8}, 2., 1);
-  int out = cgen.addTensor({{1, 1, 1, 3}, circle::TensorType::TensorType_UINT8}, 4., 2);
-
-  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 1,
-                                  circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  // clang-format off
-  _context->addTestCase(uniformTCD<uint8_t>({{5, 5, 5,  // NHWC
-                                              3, 3, 3,
-                                              7, 7, 7,
-                                              9, 9, 9}
-                                            },
-                                            {{9,
-                                              27,
-                                              56}
-                                            }));
-  // clang-format on
-  _context->setBackends({"cpu"});
-
-  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;
-  std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{1, 2, 3, 4};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 0, 0, 2,
-                                  circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->expectFailModelLoad();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Dilation)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{0, 0, 0, 0};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 4, 4, 2}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorDepthwiseConv2D({{in, weight, bias}, {out}}, circle::Padding_VALID, 1, 1, 2,
-                                  circle::ActivationFunctionType_NONE, 0, 0);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->expectFailModelLoad();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_Type)
-{
-  CircleGen cgen;
-  std::vector<float> weight_data{1, 2, 3, 4, -9, 10, -11, 12, 5, 6, 7, 8, 13, -14, 15, -16};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<float> bias_data{1, 2, 3, 4};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 3, 2, 2}, circle::TensorType::TensorType_FLOAT32});
-  int weight = cgen.addTensor({{1, 2, 2, 4}, circle::TensorType::TensorType_FLOAT32, weight_buf});
-  int bias = cgen.addTensor({{1, 1, 1, 4}, circle::TensorType::TensorType_FLOAT32, bias_buf});
-  int out = cgen.addTensor({{1, 2, 1, 4}, circle::TensorType::TensorType_UINT8});
-  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());
-  _context->expectFailModelLoad();
-
-  SUCCEED();
-}
-
-// Generate a model for negative test cases
-CircleBuffer genNegTestDepthwiseConv2DModel(circle::Padding padding, int stride_w, int stride_h,
-                                            int depth_multiplier,
-                                            circle::ActivationFunctionType actfn)
-{
-  CircleGen cgen;
-  uint32_t ker_buf = cgen.addBuffer(std::vector<uint8_t>{0, 1, 2, 3, 0, 1, 2, 3});
-  uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>{0, 0});
-  int in = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType_UINT8}, 0.5, 0);
-  int ker = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType_UINT8, ker_buf}, 0.5, 0);
-  int bias = cgen.addTensor({{2}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
-  int out = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType_UINT8}, 1, 0);
-  cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, padding, stride_w, stride_h,
-                                  depth_multiplier, actfn, 0, 0);
-  cgen.setInputsAndOutputs({in}, {out});
-  return cgen.finish();
-}
-
-template <typename T> struct DepthwiseConv2DQuantTestParam
-{
-  int stride = 1; // Used for both height and width
-  int input_depth = 1;
-  int depth_multiplier = 1;
-  std::vector<T> ref_output;
-};
-
-template <typename T>
-class DepthwiseConv2DQuantTest
-  : public GenModelTest,
-    public ::testing::WithParamInterface<DepthwiseConv2DQuantTestParam<T>>
-{
-};
-
-using DepthwiseConv2DQuantTestParamU8 = DepthwiseConv2DQuantTestParam<uint8_t>;
-using DepthwiseConv2DQuantTestU8 = DepthwiseConv2DQuantTest<uint8_t>;
-
-// Test with different InputDepth and DepthMultiplier. The values are intended to test optimized CPU
-// kernels.
-INSTANTIATE_TEST_SUITE_P(
-  GenModelTest, DepthwiseConv2DQuantTestU8,
-  ::testing::Values(
-    // Stride == 1
-    DepthwiseConv2DQuantTestParamU8{1, 8, 1, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
-    DepthwiseConv2DQuantTestParamU8{1, 4, 2, std::vector<uint8_t>{0, 0, 2, 3, 0, 2, 6, 9}},
-    DepthwiseConv2DQuantTestParamU8{
-      1, 2, 8, std::vector<uint8_t>{0, 1, 2, 3, 0, 1, 2, 3, 0, 2, 4, 6, 0, 2, 4, 6}},
-    DepthwiseConv2DQuantTestParamU8{1, 2, 2, std::vector<uint8_t>{0, 1, 4, 6}},
-    DepthwiseConv2DQuantTestParamU8{1, 2, 1, std::vector<uint8_t>{2, 5}},
-    DepthwiseConv2DQuantTestParamU8{1, 1, 2, std::vector<uint8_t>{2, 4}},
-    DepthwiseConv2DQuantTestParamU8{1, 1, 4, std::vector<uint8_t>{0, 2, 3, 5}},
-    DepthwiseConv2DQuantTestParamU8{1, 4, 1, std::vector<uint8_t>{0, 1, 4, 9}},
-    DepthwiseConv2DQuantTestParamU8{
-      1, 4, 4, std::vector<uint8_t>{0, 0, 0, 0, 0, 1, 2, 3, 0, 2, 4, 6, 0, 3, 6, 9}},
-    DepthwiseConv2DQuantTestParamU8{1, 12, 1,
-                                    std::vector<uint8_t>{0, 3, 7, 12, 0, 4, 7, 12, 0, 4, 9, 16}},
-    // Stride == 2
-    DepthwiseConv2DQuantTestParamU8{2, 4, 1, std::vector<uint8_t>{0, 1, 4, 9}},
-    DepthwiseConv2DQuantTestParamU8{2, 2, 1, std::vector<uint8_t>{2, 5}},
-    DepthwiseConv2DQuantTestParamU8{2, 1, 8, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5}},
-    DepthwiseConv2DQuantTestParamU8{2, 1, 32, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3,
-                                                                   5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2,
-                                                                   3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
-    DepthwiseConv2DQuantTestParamU8{
-      2, 1, 20, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
-    DepthwiseConv2DQuantTestParamU8{
-      2, 1, 16, std::vector<uint8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
-    DepthwiseConv2DQuantTestParamU8{2, 8, 1, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
-    DepthwiseConv2DQuantTestParamU8{
-      2, 8, 2, std::vector<uint8_t>{0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8}},
-    DepthwiseConv2DQuantTestParamU8{
-      2, 16, 1, std::vector<uint8_t>{0, 3, 8, 16, 0, 4, 7, 12, 0, 3, 7, 13, 0, 4, 7, 12}}));
-
-CircleBuffer genDepthwiseConv2DQuantU8Model(int stride, int input_depth, int depth_multiplier)
-{
-  assert(1 <= stride && stride <= 2);
-  assert(1 <= input_depth && input_depth <= 16);
-  assert(1 <= depth_multiplier && depth_multiplier <= 32);
-
-  const int output_depth = input_depth * depth_multiplier;
-  assert(1 <= output_depth && output_depth <= 32);
-
-  CircleGen cgen;
-  uint32_t ker_buf = cgen.addBuffer(std::vector<uint8_t>{
-    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
-    2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
-    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
-    2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
-    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3});
-  uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>(output_depth, 0));
-  int in = cgen.addTensor({{1, 2, 2, input_depth}, circle::TensorType_UINT8}, 0.5, 0);
-  int ker = cgen.addTensor({{1, 2, 2, output_depth}, circle::TensorType_UINT8, ker_buf}, 0.5, 0);
-  int bias = cgen.addTensor({{output_depth}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
-  int out = cgen.addTensor({{1, 1, 1, output_depth}, circle::TensorType_UINT8}, 1, 0);
-  cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, circle::Padding::Padding_VALID, stride,
-                                  stride, depth_multiplier, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in}, {out});
-  return cgen.finish();
-}
-
-TEST_P(DepthwiseConv2DQuantTestU8, Test)
-{
-  // Same input is used for all tests but output differs
-  static const std::vector<uint8_t> input64{
-    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2,
-    2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 3, 5, 8, 8, 5, 3, 2, 1, 2, 3, 4, 5, 4, 3, 2};
-
-  auto &param = GetParam();
-  _context = std::make_unique<GenModelTestContext>(
-    genDepthwiseConv2DQuantU8Model(param.stride, param.input_depth, param.depth_multiplier));
-  std::vector<uint8_t> ref_input(input64.begin(), input64.begin() + param.input_depth * 4);
-  _context->addTestCase(uniformTCD<uint8_t>({ref_input}, {param.ref_output}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-using DepthwiseConv2DQuantTestParamI8 = DepthwiseConv2DQuantTestParam<int8_t>;
-using DepthwiseConv2DQuantTestI8 = DepthwiseConv2DQuantTest<int8_t>;
-
-// Test with different InputDepth and DepthMultiplier. The values are intended to test optimized CPU
-// kernels.
-INSTANTIATE_TEST_SUITE_P(
-  GenModelTest, DepthwiseConv2DQuantTestI8,
-  ::testing::Values(
-    // Stride == 1
-    DepthwiseConv2DQuantTestParamI8{1, 8, 1, std::vector<int8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
-    DepthwiseConv2DQuantTestParamI8{1, 4, 2, std::vector<int8_t>{0, 0, 2, 3, 0, 2, 6, 9}},
-    DepthwiseConv2DQuantTestParamI8{
-      1, 2, 8, std::vector<int8_t>{0, 1, 2, 3, 0, 1, 2, 3, 0, 2, 4, 6, 0, 2, 4, 6}},
-    DepthwiseConv2DQuantTestParamI8{1, 2, 2, std::vector<int8_t>{0, 1, 4, 6}},
-    DepthwiseConv2DQuantTestParamI8{1, 2, 1, std::vector<int8_t>{2, 5}},
-    DepthwiseConv2DQuantTestParamI8{1, 1, 2, std::vector<int8_t>{2, 4}},
-    DepthwiseConv2DQuantTestParamI8{1, 1, 4, std::vector<int8_t>{0, 2, 3, 5}},
-    DepthwiseConv2DQuantTestParamI8{1, 4, 1, std::vector<int8_t>{0, 1, 4, 9}},
-    DepthwiseConv2DQuantTestParamI8{
-      1, 4, 4, std::vector<int8_t>{0, 0, 0, 0, 0, 1, 2, 3, 0, 2, 4, 6, 0, 3, 6, 9}},
-    DepthwiseConv2DQuantTestParamI8{1, 12, 1,
-                                    std::vector<int8_t>{0, 3, 7, 12, 0, 4, 7, 12, 0, 4, 9, 16}},
-    // Stride == 2
-    DepthwiseConv2DQuantTestParamI8{2, 4, 1, std::vector<int8_t>{0, 1, 4, 9}},
-    DepthwiseConv2DQuantTestParamI8{2, 2, 1, std::vector<int8_t>{2, 5}},
-    DepthwiseConv2DQuantTestParamI8{2, 1, 8, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5}},
-    DepthwiseConv2DQuantTestParamI8{2, 1, 32, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3,
-                                                                  5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2,
-                                                                  3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
-    DepthwiseConv2DQuantTestParamI8{
-      2, 1, 20, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
-    DepthwiseConv2DQuantTestParamI8{
-      2, 1, 16, std::vector<int8_t>{0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5, 0, 2, 3, 5}},
-    DepthwiseConv2DQuantTestParamI8{2, 8, 1, std::vector<int8_t>{0, 3, 5, 8, 0, 3, 5, 8}},
-    DepthwiseConv2DQuantTestParamI8{
-      2, 8, 2, std::vector<int8_t>{0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8, 0, 3, 5, 8}},
-    DepthwiseConv2DQuantTestParamI8{
-      2, 16, 1, std::vector<int8_t>{0, 3, 8, 16, 0, 4, 7, 12, 0, 3, 7, 13, 0, 4, 7, 12}}));
-
-CircleBuffer genDepthwiseConv2DQuantI8Model(int stride, int input_depth, int depth_multiplier)
-{
-  assert(1 <= stride && stride <= 2);
-  assert(1 <= input_depth && input_depth <= 16);
-  assert(1 <= depth_multiplier && depth_multiplier <= 32);
-
-  const int output_depth = input_depth * depth_multiplier;
-  assert(1 <= output_depth && output_depth <= 32);
-
-  CircleGen cgen;
-  uint32_t ker_buf = cgen.addBuffer(std::vector<int8_t>{
-    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
-    2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
-    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1,
-    2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
-    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3});
-  uint32_t bias_buf = cgen.addBuffer(std::vector<int32_t>(output_depth, 0));
-  int in = cgen.addTensor({{1, 2, 2, input_depth}, circle::TensorType_INT8}, 0.5, 0);
-  int ker = cgen.addTensor({{1, 2, 2, output_depth}, circle::TensorType_INT8, ker_buf}, 0.5, 0);
-  int bias = cgen.addTensor({{output_depth}, circle::TensorType_INT32, bias_buf}, 0.25, 0);
-  int out = cgen.addTensor({{1, 1, 1, output_depth}, circle::TensorType_INT8}, 1, 0);
-  cgen.addOperatorDepthwiseConv2D({{in, ker, bias}, {out}}, circle::Padding::Padding_VALID, stride,
-                                  stride, depth_multiplier, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in}, {out});
-  return cgen.finish();
-}
-
-TEST_P(DepthwiseConv2DQuantTestI8, Test)
-{
-  // Same input is used for all tests but output differs
-  static const std::vector<int8_t> input64{
-    0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2, 5, 4, 3, 2,
-    2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 4, 6, 8, 2, 3, 5, 8, 8, 5, 3, 2, 1, 2, 3, 4, 5, 4, 3, 2};
-
-  auto &param = GetParam();
-  _context = std::make_unique<GenModelTestContext>(
-    genDepthwiseConv2DQuantI8Model(param.stride, param.input_depth, param.depth_multiplier));
-  std::vector<int8_t> ref_input(input64.begin(), input64.begin() + param.input_depth * 4);
-  _context->addTestCase(uniformTCD<int8_t>({ref_input}, {param.ref_output}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_InvalidPaddingType)
-{
-  _context = std::make_unique<GenModelTestContext>(genNegTestDepthwiseConv2DModel(
-    static_cast<circle::Padding>(99), 1, 1, 1, circle::ActivationFunctionType_NONE));
-  _context->expectFailModelLoad();
-  _context->setBackends({"acl_cl", "acl_neon", "cpu", "xnnpack"});
-
-  SUCCEED();
-}
-
-// TODO add other invalid operation tests like above
-
-TEST_F(GenModelTest, neg_OneOp_DepthwiseConv2D_I8_NonZero_ZeroPoints)
-{
-  CircleGen cgen;
-  std::vector<int8_t> weight_data{1, 2, 3, 4, 5, 6, 7, 8};
-  uint32_t weight_buf = cgen.addBuffer(weight_data);
-  std::vector<int32_t> bias_data{0, 2};
-  uint32_t bias_buf = cgen.addBuffer(bias_data);
-  int in = cgen.addTensor({{1, 3, 3, 2}, circle::TensorType::TensorType_INT8}, 0.5, 0);
-  std::vector<float> weight_scales = {0.5, 1};
-  std::vector<int64_t> weight_zeropoints = {0, 10};
-  int weight = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_INT8, weight_buf},
-                              weight_scales, weight_zeropoints);
-  int bias = cgen.addTensor({{1, 1, 1, 2}, circle::TensorType::TensorType_INT32, bias_buf});
-  int out = cgen.addTensor({{1, 2, 2, 2}, circle::TensorType::TensorType_FLOAT32}, 1.0, 0);
-  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());
-  _context->setBackends({"cpu"});
-  _context->expectFailModelLoad();
-
-  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/nnfw_api/src/one_op_tests/Mul.test.cc b/tests/nnfw_api/src/one_op_tests/Mul.test.cc
deleted file mode 100644 (file)
index 0c79446..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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 "GenModelTest.h"
-
-#include <memory>
-
-TEST_F(GenModelTest, OneOp_Mul_Uint8_VarVar)
-{
-  CircleGen cgen;
-  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 1.0, 3);
-  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 2.0, 1);
-  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 0.5, 2);
-  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({lhs, rhs}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<uint8_t>({{3, 12, 5, 2}, {5, 4, 7, 0}}, {{2, 110, 50, 6}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_Mul_Int8_VarVar)
-{
-  CircleGen cgen;
-  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT8}, 1.0, 2);
-  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT8}, 2.0, 3);
-  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT8}, 0.5, -6);
-  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({lhs, rhs}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<int8_t>({{1, 3, 2, 4}, {5, -4, -7, 4}}, {{-14, -34, -6, 2}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_MulBroadcast_Uint8_VarVar)
-{
-  CircleGen cgen;
-  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 1.0, 3);
-  int rhs = cgen.addTensor({{1, 1, 1, 1}, circle::TensorType::TensorType_UINT8}, 2.0, 1);
-  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 0.5, 2);
-  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({lhs, rhs}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<uint8_t>({{3, 12, 5, 4}, {5}}, {{2, 146, 34, 18}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, OneOp_MulBroadcast_Int8_VarVar)
-{
-  CircleGen cgen;
-  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT8}, 1.0, 2);
-  int rhs = cgen.addTensor({{1, 1, 1, 1}, circle::TensorType::TensorType_INT8}, 2.0, 3);
-  int out = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_INT8}, 0.5, -6);
-  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({lhs, rhs}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->addTestCase(uniformTCD<int8_t>({{1, 3, 2, 4}, {5}}, {{-14, 2, -6, 10}}));
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_Mul_InvalidType)
-{
-  CircleGen cgen;
-  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
-  int rhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_UINT8}, 0.1, 2);
-  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({lhs, rhs}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-  _context->expectFailModelLoad();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_Mul_InvalidShape)
-{
-  CircleGen cgen;
-  int lhs = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
-  int rhs = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
-  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorMul({{lhs, rhs}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({lhs, rhs}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-  _context->expectFailCompile();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_Mul_OneOperand)
-{
-  CircleGen cgen;
-  int in = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
-  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorMul({{in}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-  _context->expectFailModelLoad();
-
-  SUCCEED();
-}
-
-TEST_F(GenModelTest, neg_OneOp_Mul_ThreeOperands)
-{
-  CircleGen cgen;
-  int in = cgen.addTensor({{1, 2, 2, 1}, circle::TensorType::TensorType_FLOAT32});
-  int out = cgen.addTensor({{1, 2, 3, 1}, circle::TensorType::TensorType_FLOAT32});
-  cgen.addOperatorMul({{in, in, in}, {out}}, circle::ActivationFunctionType_NONE);
-  cgen.setInputsAndOutputs({in}, {out});
-
-  _context = std::make_unique<GenModelTestContext>(cgen.finish());
-  _context->setBackends({"acl_cl", "acl_neon", "cpu"});
-  _context->expectFailModelLoad();
-
-  SUCCEED();
-}
index 923f90c..dbcdc75 100644 (file)
@@ -92,7 +92,7 @@ $BRIDGE shell tar -zxf $TEST_ROOT/nnpkg.tar.gz -C $TEST_ROOT/nnpkg
 $BRIDGE shell rm $TEST_ROOT/nnpkg.tar.gz
 
 # 1. Run
-$BRIDGE shell LD_LIBRARY_PATH=$TEST_ROOT/Product/out/lib TRACE_FILEPATH=$TEST_ROOT/trace.json BACKENDS=$BACKENDS $TEST_ROOT/Product/out/bin/onert_run --nnpackage $NNPKG_PATH_TARGET -r $NUM_RUNS
+$BRIDGE shell LD_LIBRARY_PATH=$TEST_ROOT/Product/out/lib TRACING_MODE=1 WORKSPACE_DIR=$TEST_ROOT BACKENDS=$BACKENDS $TEST_ROOT/Product/out/bin/onert_run --nnpackage $NNPKG_PATH_TARGET -r $NUM_RUNS
 
 # 2. Pull result file
 echo "Pulling data from target to trace.json"
index 798bf9d..58dabbf 100644 (file)
 #ifndef __ONERT_RUN_ALLOCATION_H__
 #define __ONERT_RUN_ALLOCATION_H__
 
+#include <cassert>
 #include <cstdlib>
 #include <cstdint>
 
+#include "nnfw.h"
+
 namespace onert_run
 {
 class Allocation
@@ -28,10 +31,21 @@ public:
   Allocation() : data_(nullptr) {}
   ~Allocation() { free(data_); }
   void *data() const { return data_; }
-  void *alloc(uint64_t sz) { return data_ = malloc(sz); }
+  void *alloc(uint64_t size, NNFW_TYPE dtype)
+  {
+    size_ = size;
+    type_ = dtype;
+
+    assert(data_ == nullptr);
+    return data_ = malloc(size);
+  }
+  uint64_t size() const { return size_; }
+  NNFW_TYPE type() const { return type_; }
 
 private:
-  void *data_;
+  void *data_ = nullptr;
+  uint64_t size_ = 0;
+  NNFW_TYPE type_ = NNFW_TYPE_TENSOR_FLOAT32;
 };
 } // namespace onert_run
 
index a64d81d..5650f48 100644 (file)
@@ -231,6 +231,18 @@ void Args::Initialize(void)
     }
   };
 
+  auto process_output_shape = [&](const std::string &shape_str) {
+    try
+    {
+      handleShapeJsonParam(_output_shape, shape_str);
+    }
+    catch (const std::exception &e)
+    {
+      std::cerr << "error with '--output_shape' option: " << shape_str << std::endl;
+      exit(1);
+    }
+  };
+
   auto process_shape_run = [&](const std::string &shape_str) {
 #if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
     if (shape_str == "H5" || shape_str == "h5")
@@ -265,13 +277,17 @@ void Args::Initialize(void)
     ("load,l", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _load_filename = v; }), "Input filename")
 #endif
     ("dump:raw", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _dump_raw_filename = v; }), "Raw Output filename")
+    ("dump_input:raw", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _dump_raw_input_filename = v; }), "Raw Input filename for dump")
     ("load:raw", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _load_raw_filename = v; }), "Raw Input filename")
     ("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")
     ("num_runs,r", po::value<int>()->default_value(1)->notifier([&](const auto &v) { _num_runs = v; }), "The number of runs")
+    ("fixed_input", "Use same random input data on each run (avaliable on random input)")
+    ("force_float", "Ignore model's input and output type and use float type buffer")
     ("warmup_runs,w", po::value<int>()->default_value(0)->notifier([&](const auto &v) { _warmup_runs = v; }), "The number of warmup runs")
+    ("minmax_runs", po::value<int>()->default_value(0)->notifier([&](const auto &v) { _minmax_runs = v; }), "The number of minmax recording runs before full quantization")
     ("run_delay,t", po::value<int>()->default_value(-1)->notifier([&](const auto &v) { _run_delay = v; }), "Delay time(us) between runs (as default no delay")
     ("gpumem_poll,g", po::value<bool>()->default_value(false)->notifier([&](const auto &v) { _gpumem_poll = v; }), "Check gpu memory polling separately")
     ("mem_poll,m", po::value<bool>()->default_value(false)->notifier([&](const auto &v) { _mem_poll = v; }), "Check memory polling")
@@ -294,15 +310,31 @@ void Args::Initialize(void)
 #endif
          "For detailed description, please consutl the description of nnfw_set_input_tensorinfo()\n"
          )
+    ("output_shape", po::value<std::string>()->default_value("[]")->notifier(process_output_shape),
+         "Set output shape for dump.\n"
+         "Size should be same.\n"
+         "'[0, [1, 2], 2, []]': set 0th tensor to [1, 2] and 2nd tensor to [] (scalar).\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")
-    ("quantize,q", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _quantize = v; }), "Request quantization with type (int8 or int16)")
+    ("quantize,q", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _quantize = v; }),
+          "Request quantization with type\n"
+          "uint8, int16: full quantization\n"
+          "int8_wo, int16_wo: weight only quantization\n")
     ("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.")
+    ("codegen,c", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _codegen = v; }),
+         "Target backend name for code generation\n"
+         "The target string will be used to find a backend library.\n"
+         "This string should be in the following format:\n"
+         "{backend extension} + '-gen'.\n"
+         "For detailed description, please see the description of nnfw_codegen()")
+    ("cpath", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _codegen_model_path = v; }),
+         "Path to export target-dependent model.\n"
+         "If it is not set, the generated model will be exported to the same directory of the original model/package with target backend extension.")
     ;
   // clang-format on
 
@@ -355,6 +387,13 @@ void Args::Parse(const int argc, char **argv)
         std::string("Require one of options modelfile, nnpackage, or path."));
   }
 
+  if (vm.count("fixed_input"))
+  {
+    _fixed_input = true;
+  }
+  if (vm.count("force_float"))
+    _force_float = true;
+
   try
   {
     po::notify(vm);
index 97d9b1a..9e474c2 100644 (file)
@@ -55,9 +55,13 @@ public:
   WhenToUseH5Shape getWhenToUseH5Shape(void) const { return _when_to_use_h5_shape; }
 #endif
   const std::string &getDumpRawFilename(void) const { return _dump_raw_filename; }
+  const std::string &getDumpRawInputFilename(void) const { return _dump_raw_input_filename; }
   const std::string &getLoadRawFilename(void) const { return _load_raw_filename; }
   const int getNumRuns(void) const { return _num_runs; }
+  const bool getFixedInput(void) const { return _fixed_input; }
+  const bool getForceFloat(void) const { return _force_float; }
   const int getWarmupRuns(void) const { return _warmup_runs; }
+  const int getMinmaxRuns(void) const { return _minmax_runs; }
   const int getRunDelay(void) const { return _run_delay; }
   std::unordered_map<uint32_t, uint32_t> getOutputSizes(void) const { return _output_sizes; }
   const bool getGpuMemoryPoll(void) const { return _gpumem_poll; }
@@ -66,11 +70,14 @@ public:
   const bool printVersion(void) const { return _print_version; }
   TensorShapeMap &getShapeMapForPrepare() { return _shape_prepare; }
   TensorShapeMap &getShapeMapForRun() { return _shape_run; }
+  TensorShapeMap &getOutputShapeMap() { return _output_shape; }
   /// @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; }
+  const std::string &getCodegen(void) const { return _codegen; }
+  const std::string &getCodegenModelPath(void) const { return _codegen_model_path; }
 
 private:
   void Initialize();
@@ -88,11 +95,16 @@ private:
   WhenToUseH5Shape _when_to_use_h5_shape = WhenToUseH5Shape::NOT_PROVIDED;
 #endif
   std::string _dump_raw_filename;
+  std::string _dump_raw_input_filename;
   std::string _load_raw_filename;
   TensorShapeMap _shape_prepare;
   TensorShapeMap _shape_run;
+  TensorShapeMap _output_shape;
   int _num_runs;
+  bool _fixed_input = false;
+  bool _force_float = false;
   int _warmup_runs;
+  int _minmax_runs;
   int _run_delay;
   std::unordered_map<uint32_t, uint32_t> _output_sizes;
   bool _gpumem_poll;
@@ -103,6 +115,8 @@ private:
   bool _use_single_model = false;
   std::string _quantize;
   std::string _quantized_model_path;
+  std::string _codegen;
+  std::string _codegen_model_path;
 };
 
 } // end of namespace onert_run
diff --git a/tests/tools/onert_run/src/formatter.h b/tests/tools/onert_run/src/formatter.h
deleted file mode 100644 (file)
index 5b73d23..0000000
+++ /dev/null
@@ -1,47 +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.
- */
-
-#ifndef __ONERT_RUN_FORMATTER_H__
-#define __ONERT_RUN_FORMATTER_H__
-
-#include <string>
-#include <vector>
-
-#include "types.h"
-#include "allocation.h"
-
-struct nnfw_session;
-
-namespace onert_run
-{
-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_run
-
-#endif // __ONERT_RUN_FORMATTER_H__
index 5ea6e4c..bef7e44 100644 (file)
@@ -36,7 +36,7 @@ onert_run::TensorShape getShape(H5::DataSet &data_set)
 
   onert_run::TensorShape shape;
   for (auto dim : h5_shape)
-    shape.emplace_back(static_cast<int>(dim));
+    shape.emplace_back(static_cast<int32_t>(dim));
 
   return shape;
 }
@@ -46,10 +46,9 @@ namespace onert_run
 {
 static const char *h5_value_grpname = "value";
 
-std::vector<TensorShape> H5Formatter::readTensorShapes(const std::string &filename)
+std::vector<TensorShape> H5Formatter::readTensorShapes(const std::string &filename,
+                                                       uint32_t num_inputs)
 {
-  uint32_t num_inputs;
-  NNPR_ENSURE_STATUS(nnfw_input_size(session_, &num_inputs));
   std::vector<TensorShape> tensor_shapes;
 
   try
@@ -86,8 +85,7 @@ std::vector<TensorShape> H5Formatter::readTensorShapes(const std::string &filena
 
 void H5Formatter::loadInputs(const std::string &filename, std::vector<Allocation> &inputs)
 {
-  uint32_t num_inputs;
-  NNPR_ENSURE_STATUS(nnfw_input_size(session_, &num_inputs));
+  uint32_t num_inputs = inputs.size();
   try
   {
     // Turn off the automatic error printing.
@@ -97,18 +95,11 @@ void H5Formatter::loadInputs(const std::string &filename, std::vector<Allocation
     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);
-
+      auto bufsz = inputs[i].size();
       H5::DataSet data_set = value_group.openDataSet(std::to_string(i));
       H5::DataType type = data_set.getDataType();
-      switch (ti.dtype)
+      switch (inputs[i].type())
       {
         case NNFW_TYPE_TENSOR_FLOAT32:
           if (type == H5::PredType::IEEE_F32BE || type == H5::PredType::IEEE_F32LE)
@@ -148,8 +139,6 @@ void H5Formatter::loadInputs(const std::string &filename, std::vector<Allocation
         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)
@@ -164,10 +153,13 @@ void H5Formatter::loadInputs(const std::string &filename, std::vector<Allocation
   }
 };
 
-void H5Formatter::dumpOutputs(const std::string &filename, std::vector<Allocation> &outputs)
+void H5Formatter::dumpOutputs(const std::string &filename, const std::vector<Allocation> &outputs,
+                              const std::vector<TensorShape> &shape_map)
 {
-  uint32_t num_outputs;
-  NNPR_ENSURE_STATUS(nnfw_output_size(session_, &num_outputs));
+  uint32_t num_outputs = outputs.size();
+  if (num_outputs != shape_map.size())
+    throw std::runtime_error("Number of outputs and shape map are not matched");
+
   try
   {
     // Turn off the automatic error printing.
@@ -177,21 +169,20 @@ void H5Formatter::dumpOutputs(const std::string &filename, std::vector<Allocatio
     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)
+      auto shape = shape_map[i];
+      std::vector<hsize_t> dims(shape.size());
+      for (uint32_t j = 0; j < shape.size(); ++j)
       {
-        if (ti.dims[j] >= 0)
-          dims[j] = static_cast<hsize_t>(ti.dims[j]);
+        if (shape[j] >= 0)
+          dims[j] = static_cast<hsize_t>(shape[j]);
         else
         {
           std::cerr << "Negative dimension in output tensor" << std::endl;
           exit(-1);
         }
       }
-      H5::DataSpace data_space(ti.rank, dims.data());
-      switch (ti.dtype)
+      H5::DataSpace data_space(shape.size(), dims.data());
+      switch (outputs[i].type())
       {
         case NNFW_TYPE_TENSOR_FLOAT32:
         {
index 7ebb33f..64c8074 100644 (file)
@@ -18,7 +18,6 @@
 #define __ONERT_RUN_H5FORMATTER_H__
 
 #include "allocation.h"
-#include "formatter.h"
 #include "types.h"
 
 #include <string>
@@ -28,13 +27,14 @@ struct nnfw_session;
 
 namespace onert_run
 {
-class H5Formatter : public Formatter
+class H5Formatter
 {
 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;
+  H5Formatter() = default;
+  std::vector<TensorShape> readTensorShapes(const std::string &filename, uint32_t num_inputs);
+  void loadInputs(const std::string &filename, std::vector<Allocation> &inputs);
+  void dumpOutputs(const std::string &filename, const std::vector<Allocation> &outputs,
+                   const std::vector<TensorShape> &shape_map);
 };
 } // namespace onert_run
 
index 0bc64bb..b32242a 100644 (file)
@@ -49,7 +49,8 @@ void overwriteShapeMap(onert_run::TensorShapeMap &shape_map,
     shape_map[i] = shapes[i];
 }
 
-std::string genQuantizedModelPathFromModelPath(const std::string &model_path, bool is_q16)
+std::string genQuantizedModelPathFromModelPath(const std::string &model_path,
+                                               NNFW_QUANTIZE_TYPE qtype)
 {
   auto const extension_pos = model_path.find(".circle");
   if (extension_pos == std::string::npos)
@@ -57,11 +58,23 @@ std::string genQuantizedModelPathFromModelPath(const std::string &model_path, bo
     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";
+  switch (qtype)
+  {
+    case NNFW_QUANTIZE_TYPE_U8_ASYM:
+      return model_path.substr(0, extension_pos) + "_quantized_q8.circle";
+    case NNFW_QUANTIZE_TYPE_I16_SYM:
+      return model_path.substr(0, extension_pos) + "_quantized_q16.circle";
+    case NNFW_QUANTIZE_TYPE_WO_I8_SYM:
+      return model_path.substr(0, extension_pos) + "_quantized_q8wo.circle";
+    case NNFW_QUANTIZE_TYPE_WO_I16_SYM:
+      return model_path.substr(0, extension_pos) + "_quantized_q16wo.circle";
+  }
+
+  throw std::runtime_error{"Invalid quantization type"};
 }
 
-std::string genQuantizedModelPathFromPackagePath(const std::string &package_path, bool is_q16)
+std::string genQuantizedModelPathFromPackagePath(const std::string &package_path,
+                                                 NNFW_QUANTIZE_TYPE qtype)
 {
   auto package_path_without_slash = package_path;
   if (package_path_without_slash.back() == '/')
@@ -72,8 +85,19 @@ std::string genQuantizedModelPathFromPackagePath(const std::string &package_path
   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";
+  switch (qtype)
+  {
+    case NNFW_QUANTIZE_TYPE_U8_ASYM:
+      return package_path_without_slash + "/" + package_name + "_quantized_q8.circle";
+    case NNFW_QUANTIZE_TYPE_I16_SYM:
+      return package_path_without_slash + "/" + package_name + "_quantized_q16.circle";
+    case NNFW_QUANTIZE_TYPE_WO_I8_SYM:
+      return package_path_without_slash + "/" + package_name + "_quantized_q8wo.circle";
+    case NNFW_QUANTIZE_TYPE_WO_I16_SYM:
+      return package_path_without_slash + "/" + package_name + "_quantized_q16wo.circle";
+  }
+
+  throw std::runtime_error{"Invalid quantization type"};
 }
 
 int main(const int argc, char **argv)
@@ -113,17 +137,66 @@ int main(const int argc, char **argv)
         NNPR_ENSURE_STATUS(nnfw_load_model_from_file(session, args.getPackageFilename().c_str()));
     });
 
+    uint32_t num_inputs;
+    uint32_t num_outputs;
+    NNPR_ENSURE_STATUS(nnfw_input_size(session, &num_inputs));
+    NNPR_ENSURE_STATUS(nnfw_output_size(session, &num_outputs));
+
     // Quantize model
     auto quantize = args.getQuantize();
     if (!quantize.empty())
     {
       NNFW_QUANTIZE_TYPE quantize_type = NNFW_QUANTIZE_TYPE_NOT_SET;
-      if (quantize == "int8")
+      if (quantize == "uint8")
         quantize_type = NNFW_QUANTIZE_TYPE_U8_ASYM;
       if (quantize == "int16")
         quantize_type = NNFW_QUANTIZE_TYPE_I16_SYM;
+      if (quantize == "int8_wo")
+        quantize_type = NNFW_QUANTIZE_TYPE_WO_I8_SYM;
+      if (quantize == "int16_wo")
+        quantize_type = NNFW_QUANTIZE_TYPE_WO_I16_SYM;
       NNPR_ENSURE_STATUS(nnfw_set_quantization_type(session, quantize_type));
 
+      if ((quantize_type == NNFW_QUANTIZE_TYPE_U8_ASYM ||
+           quantize_type == NNFW_QUANTIZE_TYPE_I16_SYM) &&
+          args.getMinmaxRuns() > 0)
+      {
+        // Collect min/max data
+        std::vector<Allocation> inputs(num_inputs);
+        std::vector<Allocation> outputs(num_outputs);
+
+        NNPR_ENSURE_STATUS(nnfw_prepare(session));
+        for (uint32_t i = 0; i < num_inputs; 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, ti.dtype);
+          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));
+        }
+        for (uint32_t i = 0; i < num_outputs; i++)
+        {
+          nnfw_tensorinfo ti;
+          NNPR_ENSURE_STATUS(nnfw_output_tensorinfo(session, i, &ti));
+          uint64_t output_size_in_bytes = bufsize_for(&ti);
+          outputs[i].alloc(output_size_in_bytes, ti.dtype);
+          NNPR_ENSURE_STATUS(
+            nnfw_set_output(session, i, ti.dtype, outputs[i].data(), output_size_in_bytes));
+          NNPR_ENSURE_STATUS(nnfw_set_output_layout(session, i, NNFW_LAYOUT_CHANNELS_LAST));
+        }
+
+        auto random_generator = RandomGenerator();
+        nnfw_set_execute_config(session, NNFW_RUN_CONFIG_DUMP_MINMAX, nullptr);
+        for (uint32_t i = 0; i < args.getMinmaxRuns(); i++)
+        {
+          random_generator.generate(inputs);
+          NNPR_ENSURE_STATUS(nnfw_run(session));
+        }
+        nnfw_reset_execute_config(session);
+      }
+
       if (args.getQuantizedModelPath() != "")
         NNPR_ENSURE_STATUS(
           nnfw_set_quantized_model_path(session, args.getQuantizedModelPath().c_str()));
@@ -132,111 +205,123 @@ int main(const int argc, char **argv)
         if (args.useSingleModel())
           NNPR_ENSURE_STATUS(nnfw_set_quantized_model_path(
             session,
-            genQuantizedModelPathFromModelPath(args.getModelFilename(), quantize == "int16")
-              .c_str()));
+            genQuantizedModelPathFromModelPath(args.getModelFilename(), quantize_type).c_str()));
         else
           NNPR_ENSURE_STATUS(nnfw_set_quantized_model_path(
-            session,
-            genQuantizedModelPathFromPackagePath(args.getPackageFilename(), quantize == "int16")
-              .c_str()));
+            session, genQuantizedModelPathFromPackagePath(args.getPackageFilename(), quantize_type)
+                       .c_str()));
       }
 
       NNPR_ENSURE_STATUS(nnfw_quantize(session));
     }
 
+    // Generate target backend code
+    auto codegen = args.getCodegen();
+    if (!codegen.empty())
+    {
+      NNPR_ENSURE_STATUS(nnfw_set_codegen_model_path(session, args.getCodegenModelPath().c_str()));
+      NNPR_ENSURE_STATUS(nnfw_codegen(session, codegen.c_str(), NNFW_CODEGEN_PREF_DEFAULT));
+    }
+
     char *available_backends = std::getenv("BACKENDS");
     if (available_backends)
       NNPR_ENSURE_STATUS(nnfw_set_available_backends(session, available_backends));
 
-    uint32_t num_inputs;
-    NNPR_ENSURE_STATUS(nnfw_input_size(session, &num_inputs));
-
     // verify input and output
+    for (uint32_t i = 0; i < num_inputs; ++i)
+    {
+      nnfw_tensorinfo ti;
+      NNPR_ENSURE_STATUS(nnfw_input_tensorinfo(session, i, &ti));
 
-    auto verifyInputTypes = [session]() {
-      uint32_t sz;
-      NNPR_ENSURE_STATUS(nnfw_input_size(session, &sz));
-      for (uint32_t i = 0; i < sz; ++i)
+      if (ti.dtype < NNFW_TYPE_TENSOR_FLOAT32 || ti.dtype > NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED)
       {
-        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);
-        }
+        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 < num_outputs; ++i)
+    {
+      nnfw_tensorinfo ti;
+      NNPR_ENSURE_STATUS(nnfw_output_tensorinfo(session, i, &ti));
 
-      for (uint32_t i = 0; i < sz; ++i)
+      if (ti.dtype < NNFW_TYPE_TENSOR_FLOAT32 || ti.dtype > NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED)
       {
-        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);
-        }
+        std::cerr << "E: not supported output type" << std::endl;
+        exit(-1);
       }
-    };
+    }
 
-    auto setTensorInfo = [session](const TensorShapeMap &tensor_shape_map) {
-      for (auto tensor_shape : tensor_shape_map)
+    std::vector<Allocation> inputs(num_inputs);
+    std::vector<Allocation> outputs(num_outputs);
+
+    auto setInputTensorInfo = [&](const TensorShapeMap &tensor_shape_map, bool allocate) {
+      for (uint32_t i = 0; i < num_inputs; i++)
       {
-        auto ind = tensor_shape.first;
-        auto &shape = tensor_shape.second;
         nnfw_tensorinfo ti;
-        // to fill dtype
-        NNPR_ENSURE_STATUS(nnfw_input_tensorinfo(session, ind, &ti));
+        NNPR_ENSURE_STATUS(nnfw_input_tensorinfo(session, i, &ti));
 
-        bool set_input = false;
-        if (ti.rank != shape.size())
+        // Find updated shape index and update tensor info
+        auto found = tensor_shape_map.find(i);
+        if (found != tensor_shape_map.end())
         {
-          set_input = true;
-        }
-        else
-        {
-          for (int i = 0; i < ti.rank; i++)
+          auto &shape = found->second;
+          bool set_input = false;
+          if (ti.rank != shape.size())
+          {
+            set_input = true;
+          }
+          else
           {
-            if (ti.dims[i] != shape.at(i))
+            for (int32_t i = 0; i < ti.rank; i++)
             {
-              set_input = true;
-              break;
+              if (ti.dims[i] != shape.at(i))
+              {
+                set_input = true;
+                break;
+              }
             }
           }
+
+          if (set_input)
+          {
+            ti.rank = shape.size();
+            for (int i = 0; i < ti.rank; i++)
+              ti.dims[i] = shape.at(i);
+            NNPR_ENSURE_STATUS(nnfw_set_input_tensorinfo(session, i, &ti));
+          }
         }
-        if (!set_input)
-          continue;
 
-        ti.rank = shape.size();
-        for (int i = 0; i < ti.rank; i++)
-          ti.dims[i] = shape.at(i);
-        NNPR_ENSURE_STATUS(nnfw_set_input_tensorinfo(session, ind, &ti));
+        // Allocate memory for input data and set buffer
+        if (allocate)
+        {
+          if (args.getForceFloat())
+            ti.dtype = NNFW_TYPE_TENSOR_FLOAT32;
+
+          auto input_size_in_bytes = bufsize_for(&ti);
+          inputs[i].alloc(input_size_in_bytes, ti.dtype);
+
+          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));
+        }
       }
     };
 
-    verifyInputTypes();
-    verifyOutputTypes();
-
 // set input shape before compilation
 #if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
 
-    auto fill_shape_from_h5 = [&session](const std::string &h5_file, TensorShapeMap &shape_map) {
+    auto fill_shape_from_h5 = [&](const std::string &h5_file, TensorShapeMap &shape_map) {
       assert(!h5_file.empty());
-      auto shapes = H5Formatter(session).readTensorShapes(h5_file);
+      auto shapes = H5Formatter().readTensorShapes(h5_file, num_inputs);
       overwriteShapeMap(shape_map, shapes);
     };
 
     if (args.getWhenToUseH5Shape() == WhenToUseH5Shape::PREPARE)
       fill_shape_from_h5(args.getLoadFilename(), args.getShapeMapForPrepare());
 #endif
-    setTensorInfo(args.getShapeMapForPrepare());
+    // Set shape info, but don't alloc yet
+    setInputTensorInfo(args.getShapeMapForPrepare(), false);
 
     // prepare execution
 
@@ -245,52 +330,50 @@ int main(const int argc, char **argv)
       NNPR_ENSURE_STATUS(nnfw_prepare(session));
     });
 
-// set input shape after compilation and before execution
+    // Set input shape and buffer after compilation and before execution
 #if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
     if (args.getWhenToUseH5Shape() == WhenToUseH5Shape::RUN ||
         (!args.getLoadFilename().empty() && !args.shapeParamProvided()))
       fill_shape_from_h5(args.getLoadFilename(), args.getShapeMapForRun());
 #endif
-    setTensorInfo(args.getShapeMapForRun());
+    setInputTensorInfo(args.getShapeMapForRun(), true);
 
-    // prepare input
-    std::vector<Allocation> inputs(num_inputs);
-#if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
-    if (!args.getLoadFilename().empty())
-      H5Formatter(session).loadInputs(args.getLoadFilename(), inputs);
-    else if (!args.getLoadRawFilename().empty())
-      RawFormatter(session).loadInputs(args.getLoadRawFilename(), inputs);
-    else
-      RandomGenerator(session).generate(inputs);
-#else
+    // Prepare input data
+    auto random_generator = RandomGenerator();
+    bool regenerate_input = false;
     if (!args.getLoadRawFilename().empty())
-      RawFormatter(session).loadInputs(args.getLoadRawFilename(), inputs);
-    else
-      RandomGenerator(session).generate(inputs);
+      RawFormatter().loadInputs(args.getLoadRawFilename(), inputs);
+#if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
+    else if (!args.getLoadFilename().empty())
+      H5Formatter().loadInputs(args.getLoadFilename(), inputs);
 #endif
+    else
+    {
+      random_generator.generate(inputs);
+      // Set regenerate_input to true if input is random data and num_runs > 1
+      // Ignore random generator is not used
+      if (args.getNumRuns() > 1 && !args.getFixedInput())
+        regenerate_input = true;
+    }
 
-    // prepare output
-    uint32_t num_outputs = 0;
-    NNPR_ENSURE_STATUS(nnfw_output_size(session, &num_outputs));
-    std::vector<Allocation> outputs(num_outputs);
+    // Prepare output buffer
     auto output_sizes = args.getOutputSizes();
     for (uint32_t i = 0; i < num_outputs; i++)
     {
       nnfw_tensorinfo ti;
-      uint64_t output_size_in_bytes = 0;
+      NNPR_ENSURE_STATUS(nnfw_output_tensorinfo(session, i, &ti));
+      if (args.getForceFloat())
+        ti.dtype = NNFW_TYPE_TENSOR_FLOAT32;
+
+      uint64_t output_size_in_bytes = bufsize_for(&ti);
       {
         auto found = output_sizes.find(i);
-        if (found == output_sizes.end())
-        {
-          NNPR_ENSURE_STATUS(nnfw_output_tensorinfo(session, i, &ti));
-          output_size_in_bytes = bufsize_for(&ti);
-        }
-        else
+        if (output_sizes.find(i) != output_sizes.end())
         {
           output_size_in_bytes = found->second;
         }
       }
-      outputs[i].alloc(output_size_in_bytes);
+      outputs[i].alloc(output_size_in_bytes, ti.dtype);
       NNPR_ENSURE_STATUS(
         nnfw_set_output(session, i, ti.dtype, outputs[i].data(), output_size_in_bytes));
       NNPR_ENSURE_STATUS(nnfw_set_output_layout(session, i, NNFW_LAYOUT_CHANNELS_LAST));
@@ -307,6 +390,10 @@ int main(const int argc, char **argv)
       phases.run(
         "EXECUTE",
         [&](const benchmark::Phase &, uint32_t) { NNPR_ENSURE_STATUS(nnfw_run(session)); },
+        [&](const benchmark::Phase &, uint32_t) {
+          if (regenerate_input)
+            random_generator.generate(inputs);
+        },
         args.getNumRuns(), true);
     }
     else
@@ -327,17 +414,60 @@ int main(const int argc, char **argv)
           std::cout << "... "
                     << "run " << nth + 1 << " takes " << phase.time[nth] / 1e3 << " ms"
                     << std::endl;
+          if (regenerate_input)
+            random_generator.generate(inputs);
         },
         args.getNumRuns(), true);
     }
 
+    // Check dump conditions
+    // Do not dump if not fixed random input
+    if (regenerate_input)
+    {
+      bool cannot_dump = false;
+#if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
+      if (!args.getDumpFilename().empty())
+        cannot_dump = true;
+#endif
+      if (!args.getDumpRawInputFilename().empty() || !args.getDumpRawFilename().empty())
+        cannot_dump = true;
+      if (cannot_dump)
+        throw std::runtime_error("Cannot dump input/output with inputs regeneration");
+    }
+
 #if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
     // dump output tensors
     if (!args.getDumpFilename().empty())
-      H5Formatter(session).dumpOutputs(args.getDumpFilename(), outputs);
+    {
+      std::vector<TensorShape> output_shapes;
+      auto output_shape_map = args.getOutputShapeMap();
+      for (uint32_t i = 0; i < num_outputs; i++)
+      {
+        nnfw_tensorinfo ti;
+        NNPR_ENSURE_STATUS(nnfw_output_tensorinfo(session, i, &ti));
+
+        auto found = output_shape_map.find(i);
+        if (found != output_shape_map.end())
+        {
+          output_shapes.emplace_back(found->second);
+        }
+        else
+        {
+          TensorShape shape;
+          for (uint32_t j = 0; j < ti.rank; j++)
+            shape.emplace_back(ti.dims[j]);
+
+          output_shapes.emplace_back(shape);
+        }
+      }
+
+      H5Formatter().dumpOutputs(args.getDumpFilename(), outputs, output_shapes);
+    }
 #endif
+    if (!args.getDumpRawInputFilename().empty())
+      RawFormatter().dumpInputs(args.getDumpRawInputFilename(), inputs);
     if (!args.getDumpRawFilename().empty())
-      RawFormatter(session).dumpOutputs(args.getDumpRawFilename(), outputs);
+      RawFormatter().dumpOutputs(args.getDumpRawFilename(), outputs);
 
     NNPR_ENSURE_STATUS(nnfw_close_session(session));
 
index 1a8a504..a899544 100644 (file)
 #include "randomgen.h"
 #include "nnfw.h"
 #include "nnfw_util.h"
-#include "misc/RandomGenerator.h"
+#include "benchmark/RandomGenerator.h"
 
 #include <iostream>
 
 namespace onert_run
 {
 
-template <class T> void randomData(nnfw::misc::RandomGenerator &randgen, void *data, uint64_t size)
+template <class T> void randomData(benchmark::RandomGenerator &randgen, void *data, uint64_t size)
 {
-  for (uint64_t i = 0; i < size; i++)
+  uint64_t elems = size / sizeof(T);
+  assert(size % sizeof(T) == 0); // size should be multiple of sizeof(T)
+
+  for (uint64_t i = 0; i < elems; 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)
+    auto input_size_in_bytes = inputs[i].size();
+    switch (inputs[i].type())
     {
       case NNFW_TYPE_TENSOR_FLOAT32:
-        randomData<float>(randgen, inputs[i].data(), num_elems(&ti));
+        randomData<float>(generator_, inputs[i].data(), input_size_in_bytes);
         break;
       case NNFW_TYPE_TENSOR_QUANT8_ASYMM:
-        randomData<uint8_t>(randgen, inputs[i].data(), num_elems(&ti));
+        randomData<uint8_t>(generator_, inputs[i].data(), input_size_in_bytes);
         break;
       case NNFW_TYPE_TENSOR_BOOL:
-        randomData<bool>(randgen, inputs[i].data(), num_elems(&ti));
+        randomData<bool>(generator_, inputs[i].data(), input_size_in_bytes);
         break;
       case NNFW_TYPE_TENSOR_UINT8:
-        randomData<uint8_t>(randgen, inputs[i].data(), num_elems(&ti));
+        randomData<uint8_t>(generator_, inputs[i].data(), input_size_in_bytes);
         break;
       case NNFW_TYPE_TENSOR_INT32:
-        randomData<int32_t>(randgen, inputs[i].data(), num_elems(&ti));
+        randomData<int32_t>(generator_, inputs[i].data(), input_size_in_bytes);
         break;
       case NNFW_TYPE_TENSOR_INT64:
-        randomData<int64_t>(randgen, inputs[i].data(), num_elems(&ti));
+        randomData<int64_t>(generator_, inputs[i].data(), input_size_in_bytes);
         break;
       case NNFW_TYPE_TENSOR_QUANT16_SYMM_SIGNED:
-        randomData<int16_t>(randgen, inputs[i].data(), num_elems(&ti));
+        randomData<int16_t>(generator_, inputs[i].data(), input_size_in_bytes);
         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));
   }
 };
 
index 58afb41..f8492b2 100644 (file)
 #include <vector>
 
 #include "allocation.h"
-
-struct nnfw_session;
+#include "benchmark/RandomGenerator.h"
 
 namespace onert_run
 {
 class RandomGenerator
 {
 public:
-  RandomGenerator(nnfw_session *sess) : session_(sess) {}
+  RandomGenerator() : generator_(1, 0.0f, 2.0f)
+  {
+    // DO NOTHING
+  }
   void generate(std::vector<Allocation> &inputs);
 
 private:
-  nnfw_session *session_;
+  benchmark::RandomGenerator generator_;
 };
 } // namespace onert_run
 
index 7cfab99..8dda6e0 100644 (file)
@@ -26,8 +26,7 @@ namespace onert_run
 {
 void RawFormatter::loadInputs(const std::string &filename, std::vector<Allocation> &inputs)
 {
-  uint32_t num_inputs;
-  NNPR_ENSURE_STATUS(nnfw_input_size(session_, &num_inputs));
+  uint32_t num_inputs = inputs.size();
 
   // Support multiple inputs
   // Option 1: Get comman-separated input file list like --load:raw a,b,c
@@ -40,13 +39,7 @@ void RawFormatter::loadInputs(const std::string &filename, std::vector<Allocatio
   {
     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);
-
+      auto bufsz = inputs[i].size();
       std::ifstream file(filename + "." + std::to_string(i), std::ios::ate | std::ios::binary);
       auto filesz = file.tellg();
       if (bufsz != filesz)
@@ -58,9 +51,6 @@ void RawFormatter::loadInputs(const std::string &filename, std::vector<Allocatio
       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)
@@ -70,17 +60,14 @@ void RawFormatter::loadInputs(const std::string &filename, std::vector<Allocatio
   }
 };
 
-void RawFormatter::dumpOutputs(const std::string &filename, std::vector<Allocation> &outputs)
+void RawFormatter::dumpOutputs(const std::string &filename, const std::vector<Allocation> &outputs)
 {
-  uint32_t num_outputs;
-  NNPR_ENSURE_STATUS(nnfw_output_size(session_, &num_outputs));
+  uint32_t num_outputs = outputs.size();
   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);
+      auto bufsz = outputs[i].size();
 
       std::ofstream file(filename + "." + std::to_string(i), std::ios::out | std::ios::binary);
       file.write(reinterpret_cast<const char *>(outputs[i].data()), bufsz);
@@ -94,4 +81,26 @@ void RawFormatter::dumpOutputs(const std::string &filename, std::vector<Allocati
     std::exit(-1);
   }
 }
+
+void RawFormatter::dumpInputs(const std::string &filename, const std::vector<Allocation> &inputs)
+{
+  uint32_t num_inputs = inputs.size();
+  try
+  {
+    for (uint32_t i = 0; i < num_inputs; i++)
+    {
+      auto bufsz = inputs[i].size();
+
+      std::ofstream file(filename + "." + std::to_string(i), std::ios::out | std::ios::binary);
+      file.write(reinterpret_cast<const char *>(inputs[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 dumpRandomInputs on onert_run : " << e.what() << std::endl;
+    std::exit(-1);
+  }
+}
 } // end of namespace onert_run
index b6eaab6..79741e9 100644 (file)
@@ -18,7 +18,6 @@
 #define __ONERT_RUN_RAWFORMATTER_H__
 
 #include "allocation.h"
-#include "formatter.h"
 #include "types.h"
 
 #include <string>
@@ -28,12 +27,13 @@ struct nnfw_session;
 
 namespace onert_run
 {
-class RawFormatter : public Formatter
+class RawFormatter
 {
 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;
+  RawFormatter() = default;
+  void loadInputs(const std::string &filename, std::vector<Allocation> &inputs);
+  void dumpOutputs(const std::string &filename, const std::vector<Allocation> &outputs);
+  void dumpInputs(const std::string &filename, const std::vector<Allocation> &inputs);
 };
 } // namespace onert_run
 
index 563c5e4..c3e364f 100644 (file)
 #ifndef __ONERT_RUN_TYPES_H__
 #define __ONERT_RUN_TYPES_H__
 
+#include <cstdint>
+#include <vector>
+
 namespace onert_run
 {
 
-using TensorShape = std::vector<int>;
+using TensorShape = std::vector<int32_t>;
 
 } // end of namespace onert_run
 
index f047b2a..75dbd2f 100644 (file)
@@ -12,6 +12,7 @@ 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")
+list(APPEND ONERT_TRAIN_SRCS "src/metrics.cc")
 
 nnfw_find_package(Boost REQUIRED program_options)
 nnfw_find_package(HDF5 QUIET)
index a201237..df67677 100644 (file)
@@ -6,8 +6,92 @@ The input models that can be supported by this tool are as follows.
 - circle
 - nnpackage
 
+## Prerequisites
+
+Required software tools:
+  - libhdf5-dev
+  - libboost-program-options-dev
+
+```
+sudo apt install -y libhdf5-dev libboost-program-options-dev
+```
+
 ## Usage
 
-### Simple train
+You could train your model using the command like below.  
+
+```bash
+onert_train \
+--path [circle file or nnpackage] \
+--load_input:raw [training input data] \
+--load_expected:raw [training output data] \
+--batch_size 32 \ 
+--epoch 5 \
+--optimizer 1 \             # sgd
+--learning_rate 0.01 \   
+--loss 2 \                  # cateogrical crossentropy
+--loss_reduction_type 1     # sum over batch size
+--num_of_trainable_ops 30    # number of operations to be trained from the back
+```
+
+`onert_train --help` would help you to set each parameter.
+
+## Example
+
+To deliver a quick insight to use `onert_train`, let's train a simple mnist model. You could get a mnist tensroflow model code from [here](https://www.kaggle.com/code/amyjang/tensorflow-mnist-cnn-tutorial). 
+
+Before using `onert_train`, training data files and a model file have to be ready.
+
+### Prepare training data files
+
+`onert_train` expects that a preprocessed dataset is given as binary files. <br/>
+For convenience, we provide a tool([tf dataset convert](https://github.com/Samsung/ONE/tree/master/tools/generate_datafile/tf_dataset_converter)) that preprocesses tensorflow dataset and save it as binary files.
+
+You could use the tool like this. For detailed usage, please refer [here](https://github.com/Samsung/ONE/tree/master/tools/generate_datafile/tf_dataset_converter#readme).
+```bash
+# Move to tf_dataset_convert directory 
+$ cd ONE/tools/generate_datafile/tf_dataset_converter
+
+# install prerequisites
+$ pip3 install -r requirements.txt
+
+# generate binary data files
+$ python3 main.py \ 
+--dataset-name mnist \ 
+--prefix-name mnist \ 
+--model mnist 
+
+# check data files are generated
+# There are 'mnist.train.input.1000.bin' and 'mnist.train.output.1000.bin'
+$ tree out
+```
+
+### Prepare a circle model file
+
+`onert_train` use a `*.circle` file or a nnpackage as input. <br/>
+
+<!-- This readme is for the ONE developers, so they might know the onecc usage.--> 
+You could convert tf/tflite/onnx model file into circle file using [`onecc`](https://github.com/Samsung/ONE/tree/master/compiler/one-cmds). <br/> 
+If you start with tensorflow code, you could first save it as saved format and then convert it to a circle file by using `onecc`. 
+
+<!--TODO : Add how to inject training parameter in the circle model -->
+### Run onert_train
+Now you're ready to run `onert_train`. <br/>
+Please pass your model file to `--modelfile` and data files to `--load_input:raw` and `--load_expected:raw`. <br/>
+Also, you could set training parameter using options like `--batch_size`, `--epoch`.. etc.
+Please pay special attention for `num_of_trainable_ops` to determine number of operations to be trained from the back..
 
-### Simple inference to trained model
+```bash 
+$ onert_train \
+--modelfile mnist.circle \
+--load_input:raw mnist.train.input.1000.bin \
+--load_expected:raw mnist.train.output.1000.bin \
+--batch_size 32 \ 
+--epoch 5 \
+--optimizer 2 \          # adam
+--learning_rate 0.001 \
+--loss 2 \               # cateogrical crossentropy
+--loss_reduction_type 1  # sum over batch size
+--num_of_trainable_ops 10
+```
index dbdd384..dd0ce55 100644 (file)
  */
 
 #include "args.h"
+#include "nnfw_util.h"
+#include "misc/to_underlying.h"
 
 #include <functional>
 #include <iostream>
+#include <numeric>
 #include <sys/stat.h>
 #include <json/json.h>
 
@@ -96,6 +99,34 @@ void checkPackage(const std::string &package_filename)
   }
 }
 
+// check the value is in the valid_args list and return the corresponded enum
+template <typename T>
+T checkValidation(const std::string &arg_name, const std::vector<T> &valid_args, int value)
+{
+  for (const auto arg : valid_args)
+  {
+    if (value == nnfw::misc::to_underlying(arg))
+      return arg;
+  }
+  std::cerr << arg_name + " " + std::to_string(value) + " is unsupported argument\n";
+  exit(1);
+}
+
+// generate a help message based on the valid_args and default_arg
+template <typename T>
+std::string genHelpMsg(const std::string &arg_name, const std::vector<T> &valid_args)
+{
+  std::string msg = arg_name + "\n";
+  msg += "If not given, model's hyper parameter is used\n";
+  for (const auto arg : valid_args)
+  {
+    const auto num = nnfw::misc::to_underlying(arg);
+    msg += std::to_string(num) + ": " + onert_train::to_string(arg) + "\n";
+  }
+  msg.erase(msg.length() - 1); // remove last \n
+  return msg;
+}
+
 } // namespace
 
 namespace onert_train
@@ -150,6 +181,11 @@ void Args::Initialize(void)
     }
   };
 
+  auto process_export_circle = [&](const std::string &path) { _export_circle_filename = path; };
+  auto process_export_circleplus = [&](const std::string &path) {
+    _export_circleplus_filename = path;
+  };
+
   auto process_load_raw_inputfile = [&](const std::string &input_filename) {
     _load_raw_input_filename = input_filename;
 
@@ -164,6 +200,15 @@ void Args::Initialize(void)
     checkModelfile(_load_raw_expected_filename);
   };
 
+  auto process_validation_split = [&](const float v) {
+    if (v < 0.f || v > 1.f)
+    {
+      std::cerr << "Invalid validation_split. Float between 0 and 1." << std::endl;
+      exit(1);
+    }
+    _validation_split = v;
+  };
+
   auto process_output_sizes = [&](const std::string &output_sizes_json_str) {
     Json::Value root;
     Json::Reader reader;
@@ -198,38 +243,56 @@ void Args::Initialize(void)
     ("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")
+    ("export_circle", po::value<std::string>()->notifier(process_export_circle), "Path to export circle")
+    ("export_circleplus", po::value<std::string>()->notifier(process_export_circleplus), "Path to export circle+")
     ("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"
+         "and the data for input1 and input2 must be held sequentially as data_length."
     )
     ("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"
+         "(Same data policy with load_input:raw)"
     )
-    ("mem_poll,m", po::value<bool>()->default_value(false)->notifier([&](const auto &v) { _mem_poll = v; }), "Check memory polling")
+    ("mem_poll,m", po::value<bool>()->default_value(false)->notifier([&](const auto &v) { _mem_poll = v; }), "Check memory polling (default: false)")
     ("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")
+    ("batch_size", po::value<int>()->notifier([&](const auto &v) { _batch_size = v; }), 
+      "Batch size\n"
+      "If not given, model's hyper parameter is used")
+    ("learning_rate", po::value<float>()->notifier([&](const auto &v) { _learning_rate = v; }), 
+      "Learning rate\n"
+      "If not given, model's hyper parameter is used")
+    ("loss", po::value<int>()
+      ->notifier([&](const auto& v){_loss_type = checkValidation("loss", valid_loss, v);}),
+      genHelpMsg("Loss type", valid_loss).c_str()
+    )
+    ("loss_reduction_type", po::value<int>()
+      ->notifier([&](const auto &v){_loss_reduction_type = checkValidation("loss_reduction_type", valid_loss_rdt, v);}),
+      genHelpMsg("Loss Reduction type", valid_loss_rdt).c_str()
+    )
+    ("optimizer", po::value<int>()
+      ->notifier([&](const auto& v){_optimizer_type = checkValidation("optimizer", valid_optim, v);}),
+      genHelpMsg("Optimizer type", valid_optim).c_str()
+    )
+    ("metric", po::value<int>()->default_value(-1)->notifier([&] (const auto &v) { _metric_type = v; }),
+      "Metric type\n"
+      "Simply calculates the metric value using the variables (default: none)\n"
+      "0: CATEGORICAL_ACCURACY")
+    ("validation_split", po::value<float>()->default_value(0.0f)->notifier(process_validation_split),
+         "Float between 0 and 1(0 < float < 1). Fraction of the training data to be used as validation data.")
     ("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")
+         "2: prints all of messages to print")
     ("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")
+        "e.g. '[0, 40, 2, 80]' to set 0th tensor to 40 and 2nd tensor to 80.")
+    ("num_of_trainable_ops", po::value<int>()->notifier([&](const auto &ops_num) { _num_of_trainable_ops = ops_num; }),
+        "Number of the layers to be trained from the back of the model. \"-1\" means that all layers will be trained. "
+        "\"0\" means that no layer will be trained.")
     ;
   // clang-format on
 
@@ -246,7 +309,7 @@ void Args::Parse(const int argc, char **argv)
   if (vm.count("help"))
   {
     std::cout << "onert_train\n\n";
-    std::cout << "Usage: " << argv[0] << "[model path] [<options>]\n\n";
+    std::cout << "Usage: " << argv[0] << " [model path] [<options>]\n\n";
     std::cout << _options;
     std::cout << "\n";
 
index cbd87e1..f9d8405 100644 (file)
 #ifndef __ONERT_TRAIN_ARGS_H__
 #define __ONERT_TRAIN_ARGS_H__
 
+#include <optional>
 #include <string>
 #include <unordered_map>
 #include <vector>
+#include <set>
 #include <boost/program_options.hpp>
 
+#include "nnfw_experimental.h"
 #include "types.h"
 
 namespace po = boost::program_options;
@@ -48,43 +51,75 @@ public:
 
   const std::string &getPackageFilename(void) const { return _package_filename; }
   const std::string &getModelFilename(void) const { return _model_filename; }
+  const std::string &getExportCircleFilename(void) const { return _export_circle_filename; }
+  const std::string &getExportCirclePlusFilename(void) const { return _export_circleplus_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 std::optional<int> getBatchSize(void) const { return _batch_size; }
+  const std::optional<float> getLearningRate(void) const { return _learning_rate; }
+  const std::optional<NNFW_TRAIN_LOSS> getLossType(void) const { return _loss_type; }
+  const std::optional<NNFW_TRAIN_LOSS_REDUCTION> getLossReductionType(void) const
+  {
+    return _loss_reduction_type;
+  }
+  const std::optional<NNFW_TRAIN_OPTIMIZER> getOptimizerType(void) const { return _optimizer_type; }
+  const int getMetricType(void) const { return _metric_type; }
+  const float getValidationSplit(void) const { return _validation_split; }
   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; }
+  uint32_t num_of_trainable_ops(void) const { return _num_of_trainable_ops; }
 
 private:
   void Initialize();
   void Parse(const int argc, char **argv);
 
 private:
+  // supported loss list and it's default value
+  const std::vector<NNFW_TRAIN_LOSS> valid_loss = {
+    NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR,
+    NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY,
+  };
+
+  // supported loss reduction type list and it's default value
+  const std::vector<NNFW_TRAIN_LOSS_REDUCTION> valid_loss_rdt = {
+    NNFW_TRAIN_LOSS_REDUCTION_SUM_OVER_BATCH_SIZE,
+    NNFW_TRAIN_LOSS_REDUCTION_SUM,
+  };
+
+  // supported optimizer list and it's default value
+  const std::vector<NNFW_TRAIN_OPTIMIZER> valid_optim = {
+    NNFW_TRAIN_OPTIMIZER_SGD,
+    NNFW_TRAIN_OPTIMIZER_ADAM,
+  };
+
+private:
   po::positional_options_description _positional;
   po::options_description _options;
 
   std::string _package_filename;
   std::string _model_filename;
+  std::string _export_circle_filename;
+  std::string _export_circleplus_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;
+  std::optional<int> _batch_size;
+  std::optional<float> _learning_rate;
+  std::optional<NNFW_TRAIN_LOSS> _loss_type;
+  std::optional<NNFW_TRAIN_LOSS_REDUCTION> _loss_reduction_type;
+  std::optional<NNFW_TRAIN_OPTIMIZER> _optimizer_type;
+  int _metric_type;
+  float _validation_split;
   bool _print_version = false;
   int _verbose_level;
   std::unordered_map<uint32_t, uint32_t> _output_sizes;
+  int32_t _num_of_trainable_ops;
 };
 
 } // end of namespace onert_train
diff --git a/tests/tools/onert_train/src/dataloader.h b/tests/tools/onert_train/src/dataloader.h
new file mode 100644 (file)
index 0000000..f4bd4fe
--- /dev/null
@@ -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_TRAIN_DATALOADER_H__
+#define __ONERT_TRAIN_DATALOADER_H__
+
+#include "allocation.h"
+#include "nnfw.h"
+
+#include <functional>
+#include <vector>
+#include <tuple>
+#include <fstream>
+
+namespace onert_train
+{
+
+using Generator = std::function<bool(uint32_t,                  /** index **/
+                                     std::vector<Allocation> &, /** input **/
+                                     std::vector<Allocation> & /** expected **/)>;
+
+class DataLoader
+{
+public:
+  DataLoader(const std::vector<nnfw_tensorinfo> &input_infos,
+             const std::vector<nnfw_tensorinfo> &expected_infos)
+    : _input_infos{input_infos}, _expected_infos{expected_infos}
+  {
+    // DO NOTHING
+  }
+  virtual ~DataLoader() = default;
+
+  virtual std::tuple<Generator, uint32_t>
+  loadData(const uint32_t batch_size, const float from = 0.0f, const float to = 1.0f) = 0;
+
+protected:
+  std::vector<nnfw_tensorinfo> _input_infos;
+  std::vector<nnfw_tensorinfo> _expected_infos;
+  std::ifstream _input_file;
+  std::ifstream _expected_file;
+  uint32_t _data_length;
+};
+
+} // namespace onert_train
+
+#endif // __ONERT_TRAIN_DATALOADER_H__
index f7c8610..ab9be90 100644 (file)
 #ifndef __ONERT_TRAIN_MEASURE_H__
 #define __ONERT_TRAIN_MEASURE_H__
 
+#include "benchmark/MemoryInfo.h"
+#include "benchmark/MemoryPoller.h"
+
 #include <algorithm>
 #include <ctime>
+#include <iostream>
+#include <iomanip>
+#include <numeric>
 #include <vector>
 
 namespace
@@ -34,55 +40,226 @@ uint64_t nowMicros()
 namespace onert_train
 {
 
+enum PhaseType
+{
+  MODEL_LOAD,
+  PREPARE,
+  EXECUTE,
+  END_OF_PHASE
+};
+
+const std::string getPhaseTypeStr(PhaseType type)
+{
+  switch (type)
+  {
+    case MODEL_LOAD:
+      return "MODEL_LOAD";
+    case PREPARE:
+      return "PREPARE";
+    case EXECUTE:
+      return "EXECUTE";
+    default:
+      throw std::runtime_error("Invalid phase type");
+  }
+}
+
+benchmark::PhaseEnum convertToPhaseEnum(PhaseType type)
+{
+  switch (type)
+  {
+    case MODEL_LOAD:
+      return benchmark::PhaseEnum::MODEL_LOAD;
+    case PREPARE:
+      return benchmark::PhaseEnum::PREPARE;
+    case EXECUTE:
+      return benchmark::PhaseEnum::EXECUTE;
+    default:
+      throw std::runtime_error("Invalid phase type");
+  }
+}
+
+enum AggregateType
+{
+  AVERAGE,
+  SUM,
+  END_OF_AGGREGATE_TYPE
+};
+
+enum MemoryType
+{
+  RSS,
+  HWM,
+  PSS,
+  END_OF_MEM_TYPE
+};
+
+const std::string getMemoryTypeStr(MemoryType type)
+{
+  switch (type)
+  {
+    case RSS:
+      return "RSS";
+    case HWM:
+      return "HWM";
+    case PSS:
+      return "PSS";
+    default:
+      throw std::runtime_error("Invalid memory type");
+  }
+}
+
 struct Step
 {
   uint64_t time; // us
-  // TODO Support memory usage
+};
+
+struct Phase
+{
+  uint64_t time;                                // us
+  uint32_t memory[MemoryType::END_OF_MEM_TYPE]; // kB
 };
 
 class Measure
 {
 public:
-  Measure() = default;
+  Measure(bool check_mem_poll) : _check_mem_poll(check_mem_poll)
+  {
+    if (_check_mem_poll)
+    {
+      assert(benchmark::prepareVmRSS());
+      _mem_poll = std::make_unique<benchmark::MemoryPoller>(std::chrono::milliseconds(100), false);
+    }
+  }
 
   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); });
+    _step_results.clear();
+    _step_results.resize(epoch);
+    std::for_each(_step_results.begin(), _step_results.end(), [step](auto &v) { v.resize(step); });
+  }
+
+  void run(const PhaseType phaseType, const std::function<void()> &func)
+  {
+    auto phaseEnum = convertToPhaseEnum(phaseType);
+
+    if (_check_mem_poll)
+    {
+      _mem_poll->start(phaseEnum);
+    }
+    _phase_results[phaseType].time = nowMicros();
+
+    func();
+
+    _phase_results[phaseType].time = nowMicros() - _phase_results[phaseType].time;
+    if (_check_mem_poll)
+    {
+      _mem_poll->end(phaseEnum);
+
+      _phase_results[phaseType].memory[MemoryType::RSS] = _mem_poll->getRssMap().at(phaseEnum);
+      _phase_results[phaseType].memory[MemoryType::HWM] = _mem_poll->getHwmMap().at(phaseEnum);
+      _phase_results[phaseType].memory[MemoryType::PSS] = _mem_poll->getPssMap().at(phaseEnum);
+    }
   }
 
   void run(const int epoch, const int step, const std::function<void()> &func)
   {
-    if (_results.empty() || _results.size() <= epoch || _results[epoch].size() <= step)
+    if (_step_results.empty() || _step_results.size() <= epoch ||
+        _step_results[epoch].size() <= step)
     {
       throw std::runtime_error("Please set the number of epochs and steps first");
     }
 
-    _results[epoch][step].time = nowMicros();
+    _step_results[epoch][step].time = nowMicros();
 
     func();
 
-    _results[epoch][step].time = nowMicros() - _results[epoch][step].time;
+    _step_results[epoch][step].time = nowMicros() - _step_results[epoch][step].time;
+  }
+
+  double sumTimeMicro(const int epoch)
+  {
+    double sum = 0u;
+    std::for_each(_step_results[epoch].begin(), _step_results[epoch].end(),
+                  [&sum](auto &v) { sum += v.time; });
+    return sum;
   }
 
-  double timeMicros(const int epoch)
+  double timeMicros(const int epoch, const AggregateType aggType)
   {
-    if (_results.empty() || _results.size() <= epoch)
+    if (_step_results.empty() || _step_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();
+    switch (aggType)
+    {
+      case AVERAGE:
+        return sumTimeMicro(epoch) / _step_results[epoch].size();
+      case SUM:
+        return sumTimeMicro(epoch);
+      default:
+        throw std::runtime_error("Invalid aggregate type");
+    }
   }
 
-  double timeMs(const int epoch) { return timeMicros(epoch) / 1e3; }
+  void printTimeMs(const int epoch, const AggregateType aggType)
+  {
+    std::cout.precision(3);
+    std::cout << " - time: " << timeMicros(epoch, aggType) / 1e3 << "ms/step";
+  }
+
+  void printResultTime()
+  {
+    std::cout << "===================================" << std::endl;
+    for (int i = 0; i < PhaseType::END_OF_PHASE; ++i)
+    {
+      auto type = static_cast<PhaseType>(i);
+      std::cout << std::setw(12) << std::left << getPhaseTypeStr(type) << " takes "
+                << _phase_results[type].time / 1e3 << " ms" << std::endl;
+      if (i == PhaseType::EXECUTE)
+      {
+        for (int j = 0; j < _step_results.size(); ++j)
+        {
+          std::cout << "- "
+                    << "Epoch " << j + 1 << std::setw(12) << std::right << " takes "
+                    << timeMicros(j, AggregateType::SUM) / 1e3 << " ms" << std::endl;
+        }
+      }
+    }
+    std::cout << "===================================" << std::endl;
+  }
+
+  void printResultMemory()
+  {
+    for (int i = 0; i < MemoryType::END_OF_MEM_TYPE; ++i)
+    {
+      auto type = static_cast<MemoryType>(i);
+      std::cout << getMemoryTypeStr(type) << std::endl;
+      for (int j = 0; j < PhaseType::END_OF_PHASE; ++j)
+      {
+        auto phaseType = static_cast<PhaseType>(j);
+        std::cout << "- " << std::setw(12) << std::left << getPhaseTypeStr(phaseType) << " takes "
+                  << _phase_results[phaseType].memory[i] << " kb" << std::endl;
+      }
+      std::cout << "===================================" << std::endl;
+    }
+  }
+
+  void printResult()
+  {
+    printResultTime();
+    if (_check_mem_poll)
+    {
+      printResultMemory();
+    }
+  }
 
 private:
-  std::vector<std::vector<Step>> _results;
+  std::unordered_map<PhaseType, Phase> _phase_results;
+  std::vector<std::vector<Step>> _step_results;
+
+  bool _check_mem_poll;
+  std::unique_ptr<benchmark::MemoryPoller> _mem_poll;
 };
 
 } // namespace onert_train
diff --git a/tests/tools/onert_train/src/metrics.cc b/tests/tools/onert_train/src/metrics.cc
new file mode 100644 (file)
index 0000000..1cdb058
--- /dev/null
@@ -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.
+ */
+
+#include "metrics.h"
+#include "nnfw_util.h"
+
+#include <algorithm>
+#include <stdexcept>
+
+namespace onert_train
+{
+
+Metrics::Metrics(const std::vector<Allocation> &output, const std::vector<Allocation> &expected,
+                 const std::vector<nnfw_tensorinfo> &infos)
+  : _output{output}, _expected{expected}, _infos{infos}
+{
+  // DO NOTHING
+}
+
+template <typename T>
+float Metrics::categoricalAccuracy(const T *output, const T *expected, uint32_t batch,
+                                   uint64_t size)
+{
+  int correct = 0;
+  for (int b = 0; b < batch; ++b)
+  {
+    int begin_offset = b * size;
+    int end_offset = begin_offset + size;
+    std::vector<T> boutput(output + begin_offset, output + end_offset);
+    std::vector<T> bexpected(expected + begin_offset, expected + end_offset);
+    auto output_idx =
+      std::distance(boutput.begin(), std::max_element(boutput.begin(), boutput.end()));
+    auto expected_idx =
+      std::distance(bexpected.begin(), std::max_element(bexpected.begin(), bexpected.end()));
+    if (output_idx == expected_idx)
+      correct++;
+  }
+  return static_cast<float>(correct) / batch;
+}
+
+float Metrics::categoricalAccuracy(int32_t index)
+{
+  auto batch = _infos[index].dims[0];
+  auto size = num_elems(&_infos[index]) / batch;
+  switch (_infos[index].dtype)
+  {
+    case NNFW_TYPE_TENSOR_FLOAT32:
+      return categoricalAccuracy(static_cast<const float *>(_output[index].data()),
+                                 static_cast<const float *>(_expected[index].data()), batch, size);
+    default:
+      throw std::runtime_error("Not supported tensor type in calculateAccuracy");
+  }
+}
+
+} // namespace onert_train
diff --git a/tests/tools/onert_train/src/metrics.h b/tests/tools/onert_train/src/metrics.h
new file mode 100644 (file)
index 0000000..0922c79
--- /dev/null
@@ -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_METRICS_H__
+#define __ONERT_TRAIN_METRICS_H__
+
+#include "allocation.h"
+#include "nnfw.h"
+#include <vector>
+
+namespace onert_train
+{
+class Metrics
+{
+public:
+  Metrics(const std::vector<Allocation> &output, const std::vector<Allocation> &expected,
+          const std::vector<nnfw_tensorinfo> &infos);
+
+private:
+  template <typename T>
+  float categoricalAccuracy(const T *output, const T *expected, uint32_t batch, uint64_t size);
+
+public:
+  float categoricalAccuracy(int32_t index);
+
+private:
+  const std::vector<Allocation> &_output;
+  const std::vector<Allocation> &_expected;
+  const std::vector<nnfw_tensorinfo> &_infos;
+};
+
+} // namespace onert_train
+
+#endif // __ONERT_TRAIN_METRICS_H__
index 8dd2aa8..07d3f18 100644 (file)
 
 #include <cassert>
 #include <string>
+#include <iostream>
+#include <unordered_map>
+
 #include "nnfw.h"
+#include "nnfw_experimental.h"
 
 namespace onert_train
 {
@@ -46,4 +50,68 @@ uint64_t bufsize_for(const nnfw_tensorinfo *ti)
   return elmsize[ti->dtype] * num_elems(ti);
 }
 
+std::string to_string(NNFW_TRAIN_OPTIMIZER opt)
+{
+  static const std::unordered_map<NNFW_TRAIN_OPTIMIZER, std::string> name_map{
+    {NNFW_TRAIN_OPTIMIZER_UNDEFINED, "undefined"},
+    {NNFW_TRAIN_OPTIMIZER_SGD, "sgd"},
+    {NNFW_TRAIN_OPTIMIZER_ADAM, "adam"},
+  };
+  return name_map.at(opt);
+}
+
+std::string to_string(NNFW_TRAIN_LOSS loss)
+{
+  static const std::unordered_map<NNFW_TRAIN_LOSS, std::string> name_map{
+    {NNFW_TRAIN_LOSS_UNDEFINED, "undefined"},
+    {NNFW_TRAIN_LOSS_MEAN_SQUARED_ERROR, "mean squared error"},
+    {NNFW_TRAIN_LOSS_CATEGORICAL_CROSSENTROPY, "categorical crossentropy"},
+  };
+  return name_map.at(loss);
+}
+
+std::string to_string(NNFW_TRAIN_LOSS_REDUCTION loss_rdt)
+{
+  static const std::unordered_map<NNFW_TRAIN_LOSS_REDUCTION, std::string> name_map{
+    {NNFW_TRAIN_LOSS_REDUCTION_UNDEFINED, "undefined"},
+    {NNFW_TRAIN_LOSS_REDUCTION_SUM_OVER_BATCH_SIZE, "sum over batch size"},
+    {NNFW_TRAIN_LOSS_REDUCTION_SUM, "sum"}};
+  return name_map.at(loss_rdt);
+}
+
+std::ostream &operator<<(std::ostream &os, const NNFW_TRAIN_OPTIMIZER &opt)
+{
+  os << to_string(opt);
+  return os;
+}
+
+std::ostream &operator<<(std::ostream &os, const NNFW_TRAIN_LOSS &loss)
+{
+  os << to_string(loss);
+  return os;
+}
+
+std::ostream &operator<<(std::ostream &os, const NNFW_TRAIN_LOSS_REDUCTION &loss_reduction)
+{
+  os << to_string(loss_reduction);
+  return os;
+}
+
+std::ostream &operator<<(std::ostream &os, const nnfw_loss_info &loss_info)
+{
+  os << "{loss = " << loss_info.loss << ", reduction = " << loss_info.reduction_type << "}";
+  return os;
+}
+
+std::ostream &operator<<(std::ostream &os, const nnfw_train_info &info)
+{
+  os << "- learning_rate        = " << info.learning_rate << "\n";
+  os << "- batch_size           = " << info.batch_size << "\n";
+  os << "- loss_info            = " << info.loss_info << "\n";
+  os << "- optimizer            = " << info.opt << "\n";
+  os << "- num_of_trainable_ops = " << info.num_of_trainable_ops << "\n";
+
+  return os;
+}
+
 } // namespace onert_train
index 674e18f..a6cee6c 100644 (file)
@@ -18,6 +18,9 @@
 #define __ONERT_TRAIN_NNFW_UTIL_H__
 
 #include "nnfw.h"
+#include "nnfw_experimental.h"
+
+#include <ostream>
 
 #define NNPR_ENSURE_STATUS(a)        \
   do                                 \
@@ -32,6 +35,10 @@ namespace onert_train
 {
 uint64_t num_elems(const nnfw_tensorinfo *ti);
 uint64_t bufsize_for(const nnfw_tensorinfo *ti);
-} // end of namespace onert_train
 
+std::string to_string(NNFW_TRAIN_OPTIMIZER opt);
+std::string to_string(NNFW_TRAIN_LOSS loss);
+std::string to_string(NNFW_TRAIN_LOSS_REDUCTION loss_rdt);
+std::ostream &operator<<(std::ostream &os, const nnfw_train_info &info);
+} // end of namespace onert_train
 #endif // __ONERT_TRAIN_NNFW_UTIL_H__
index 678d13f..5f66e9c 100644 (file)
@@ -24,7 +24,9 @@
 #include "nnfw_experimental.h"
 #include "randomgen.h"
 #include "rawformatter.h"
+#include "dataloader.h"
 #include "rawdataloader.h"
+#include "metrics.h"
 
 #include <boost/program_options.hpp>
 #include <cassert>
@@ -56,13 +58,15 @@ int main(const int argc, char **argv)
 
     // TODO Apply verbose level to phases
     const int verbose = args.getVerboseLevel();
-    benchmark::Phases phases(benchmark::PhaseOption{});
+
+    // prepare measure tool
+    Measure measure(args.getMemoryPoll());
 
     nnfw_session *session = nullptr;
     NNPR_ENSURE_STATUS(nnfw_create_session(&session));
 
     // ModelLoad
-    phases.run("MODEL_LOAD", [&](const benchmark::Phase &, uint32_t) {
+    measure.run(PhaseType::MODEL_LOAD, [&]() {
       if (args.useSingleModel())
         NNPR_ENSURE_STATUS(
           nnfw_load_model_from_modelfile(session, args.getModelFilename().c_str()));
@@ -117,45 +121,43 @@ int main(const int argc, char **argv)
     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);
-      }
+    auto getMetricTypeStr = [](int type) {
+      if (type < 0)
+        return "";
+      // Metric type
+      // 0: Categorical Accuracy
+      std::vector<int> acc = {0};
+      auto it = std::find(acc.begin(), acc.end(), type);
+      if (it == acc.end())
+        return "metric";
+      return "categorical_accuracy";
     };
 
-    // prepare training info
+    // get training information
     nnfw_train_info tri;
-    tri.batch_size = args.getBatchSize();
-    tri.learning_rate = args.getLearningRate();
-    tri.loss = convertLossType(args.getLossType());
-    tri.opt = convertOptType(args.getOptimizerType());
+    NNPR_ENSURE_STATUS(nnfw_train_get_traininfo(session, &tri));
+
+    // overwrite training information using the arguments
+    tri.batch_size = args.getBatchSize().value_or(tri.batch_size);
+    tri.learning_rate = args.getLearningRate().value_or(tri.learning_rate);
+    tri.loss_info.loss = args.getLossType().value_or(tri.loss_info.loss);
+    tri.loss_info.reduction_type =
+      args.getLossReductionType().value_or(tri.loss_info.reduction_type);
+    tri.opt = args.getOptimizerType().value_or(tri.opt);
+
+    tri.num_of_trainable_ops = args.num_of_trainable_ops();
+
+    std::cout << "== training parameter ==" << std::endl;
+    std::cout << tri;
+    std::cout << "========================" << std::endl;
+
+    // set training information
+    NNPR_ENSURE_STATUS(nnfw_train_set_traininfo(session, &tri));
 
     // 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));
-    });
+    measure.run(PhaseType::PREPARE, [&]() { NNPR_ENSURE_STATUS(nnfw_train_prepare(session)); });
 
     // prepare input and expected tensor info lists
     std::vector<nnfw_tensorinfo> input_infos;
@@ -164,6 +166,7 @@ int main(const int argc, char **argv)
     // prepare data buffers
     std::vector<Allocation> input_data(num_inputs);
     std::vector<Allocation> expected_data(num_expecteds);
+    std::vector<Allocation> output_data(num_expecteds);
 
     for (uint32_t i = 0; i < num_inputs; ++i)
     {
@@ -177,20 +180,33 @@ int main(const int argc, char **argv)
     {
       nnfw_tensorinfo ti;
       NNPR_ENSURE_STATUS(nnfw_output_tensorinfo(session, i, &ti));
-      expected_data[i].alloc(bufsize_for(&ti));
+
+      // For validation
+      uint64_t output_size_in_bytes = bufsize_for(&ti);
+      output_data[i].alloc(output_size_in_bytes);
+      NNPR_ENSURE_STATUS(
+        nnfw_train_set_output(session, i, ti.dtype, output_data[i].data(), output_size_in_bytes));
+
+      expected_data[i].alloc(output_size_in_bytes);
       expected_infos.emplace_back(std::move(ti));
     }
 
-    auto data_length = args.getDataLength();
-
-    Generator generator;
-    RawDataLoader rawDataLoader;
+    uint32_t tdata_length;
+    Generator tdata_generator;
+    uint32_t vdata_length;
+    Generator vdata_generator;
+    std::unique_ptr<DataLoader> dataLoader;
 
     if (!args.getLoadRawInputFilename().empty() && !args.getLoadRawExpectedFilename().empty())
     {
-      generator =
-        rawDataLoader.loadData(args.getLoadRawInputFilename(), args.getLoadRawExpectedFilename(),
-                               input_infos, expected_infos, data_length, tri.batch_size);
+      dataLoader = std::make_unique<RawDataLoader>(args.getLoadRawInputFilename(),
+                                                   args.getLoadRawExpectedFilename(), input_infos,
+                                                   expected_infos);
+
+      auto train_to = 1.0f - args.getValidationSplit();
+      std::tie(tdata_generator, tdata_length) = dataLoader->loadData(tri.batch_size, 0.f, train_to);
+      std::tie(vdata_generator, vdata_length) =
+        dataLoader->loadData(tri.batch_size, train_to, 1.0f);
     }
     else
     {
@@ -199,68 +215,172 @@ int main(const int argc, char **argv)
       exit(-1);
     }
 
-    Measure measure;
+    if (tdata_length < tri.batch_size)
+    {
+      std::cerr << "E: training data is not enough for training."
+                   "Reduce batch_size or add more data"
+                << std::endl;
+      exit(-1);
+    }
+
+    // If the user does not give the validation_split value,
+    // the vdata_length is 0 by default and it does not execute
+    // validation loop.
+    if (vdata_length != 0 && vdata_length < tri.batch_size)
+    {
+      std::cerr << "E: validation data is not enough for validation."
+                   "Reduce batch_size or adjust validation_split value"
+                << std::endl;
+      exit(-1);
+    }
+
     std::vector<float> losses(num_expecteds);
-    phases.run("EXECUTE", [&](const benchmark::Phase &, uint32_t) {
-      const int num_step = data_length / tri.batch_size;
+    std::vector<float> metrics(num_expecteds);
+    measure.run(PhaseType::EXECUTE, [&]() {
+      const int num_step = tdata_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)
+        //
+        // TRAINING
+        //
         {
-          // get batchsize data
-          if (!generator(n, input_data, expected_data))
-            break;
-
-          // prepare input
-          for (uint32_t i = 0; i < num_inputs; ++i)
+          std::fill(losses.begin(), losses.end(), 0);
+          std::fill(metrics.begin(), metrics.end(), 0);
+          for (uint32_t n = 0; n < num_step; ++n)
           {
-            NNPR_ENSURE_STATUS(
-              nnfw_train_set_input(session, i, input_data[i].data(), &input_infos[i]));
+            // get batchsize data
+            if (!tdata_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
+            Metrics metric(output_data, expected_data, expected_infos);
+            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;
+              if (args.getMetricType() == 0)
+                metrics[i] += metric.categoricalAccuracy(i);
+            }
           }
 
-          // prepare output
+          // print loss
+          std::cout << std::fixed;
+          std::cout << "Epoch " << epoch + 1 << "/" << num_epoch;
+          measure.printTimeMs(epoch, AggregateType::AVERAGE);
+          std::cout.precision(4);
+          std::cout << " - loss: ";
           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]));
+            std::cout << "[" << i << "] " << losses[i] / num_step;
           }
-
-          // train
-          measure.run(epoch, n, [&]() { NNPR_ENSURE_STATUS(nnfw_train(session, true)); });
-
-          // store loss
-          for (int32_t i = 0; i < num_expecteds; ++i)
+          // TODO use init-statement in selection statements (c++17)
+          std::string str;
+          if ((str = getMetricTypeStr(args.getMetricType())) != "")
           {
-            float temp = 0.f;
-            NNPR_ENSURE_STATUS(nnfw_train_get_loss(session, i, &temp));
-            losses[i] += temp;
+            std::cout << " - " << str << ": ";
+            for (uint32_t i = 0; i < num_expecteds; ++i)
+            {
+              std::cout << "[" << i << "] " << metrics[i] / num_step;
+            }
           }
         }
 
-        // 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)
+        //
+        // VALIDATION
+        //
+        if (vdata_length > 0)
         {
-          std::cout << "[" << i << "] " << losses[i] / num_step;
+          std::fill(losses.begin(), losses.end(), 0);
+          std::fill(metrics.begin(), metrics.end(), 0);
+          const int num_valid_step = vdata_length / tri.batch_size;
+          for (uint32_t n = 0; n < num_valid_step; ++n)
+          {
+            // get batchsize validation data
+            if (!vdata_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]));
+            }
+
+            // validation
+            NNPR_ENSURE_STATUS(nnfw_train(session, false));
+
+            // get validation loss and accuracy
+            Metrics metric(output_data, expected_data, expected_infos);
+            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;
+              if (args.getMetricType() == 0)
+                metrics[i] += metric.categoricalAccuracy(i);
+            }
+          }
+
+          // print validation loss and accuracy
+          std::cout << std::fixed;
+          std::cout.precision(4);
+          std::cout << " - val_loss: ";
+          for (uint32_t i = 0; i < num_expecteds; ++i)
+          {
+            std::cout << "[" << i << "] " << losses[i] / num_valid_step;
+          }
+          // TODO use init-statement in selection statements (c++17)
+          std::string str;
+          if ((str = getMetricTypeStr(args.getMetricType())) != "")
+          {
+            std::cout << " - val_" << str << ": ";
+            for (uint32_t i = 0; i < num_expecteds; ++i)
+            {
+              std::cout << "[" << i << "] " << metrics[i] / num_valid_step;
+            }
+          }
         }
-        std::cout /* << "- accuracy: " << accuracy*/ << std::endl;
+
+        std::cout << std::endl;
       }
     });
 
-    NNPR_ENSURE_STATUS(nnfw_close_session(session));
+    if (auto name = args.getExportCircleFilename(); name != "")
+      NNPR_ENSURE_STATUS(nnfw_train_export_circle(session, name.c_str()));
 
-    // prepare result
-    benchmark::Result result(phases);
+    if (auto name = args.getExportCirclePlusFilename(); name != "")
+      NNPR_ENSURE_STATUS(nnfw_train_export_circleplus(session, name.c_str()));
+
+    NNPR_ENSURE_STATUS(nnfw_close_session(session));
 
-    // to stdout
-    benchmark::printResult(result);
+    measure.printResult();
 
     return 0;
   }
index 72599cb..eb5476f 100644 (file)
 #include "randomgen.h"
 #include "nnfw.h"
 #include "nnfw_util.h"
-#include "misc/RandomGenerator.h"
+#include "benchmark/RandomGenerator.h"
 
 #include <iostream>
 
 namespace onert_train
 {
 
-template <class T> void randomData(nnfw::misc::RandomGenerator &randgen, void *data, uint64_t size)
+template <class T> void randomData(benchmark::RandomGenerator &randgen, void *data, uint64_t size)
 {
   for (uint64_t i = 0; i < size; i++)
     reinterpret_cast<T *>(data)[i] = randgen.generate<T>();
@@ -34,7 +34,7 @@ void RandomGenerator::generate(std::vector<Allocation> &inputs)
 {
   // generate random data
   const int seed = 1;
-  nnfw::misc::RandomGenerator randgen{seed, 0.0f, 2.0f};
+  benchmark::RandomGenerator randgen{seed, 0.0f, 2.0f};
   for (uint32_t i = 0; i < inputs.size(); ++i)
   {
     nnfw_tensorinfo ti;
index a3672a9..e7b435a 100644 (file)
 #include <iostream>
 #include <stdexcept>
 #include <numeric>
+#include <cassert>
 
 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)
+uint64_t getRawTensorSize(const std::vector<nnfw_tensorinfo> &infos)
 {
-  std::vector<uint32_t> input_origins(input_infos.size());
-  uint32_t start = 0;
-  for (uint32_t i = 0; i < input_infos.size(); ++i)
+  // NOTE The input_infos has already applied the batch_size.
+  //      In order to know the size of the tensor stored in the actual file,
+  //      the batch_size information must be excluded.
+  uint64_t total = 0;
+  for (uint32_t i = 0; i < infos.size(); ++i)
   {
-    input_origins.at(i) = start;
-    start += (bufsize_for(&input_infos[i]) / batch_size * data_length);
+    total += (bufsize_for(&infos[i]) / infos[i].dims[0]);
   }
+  return total;
+}
+} // namespace onert_train
 
-  std::vector<uint32_t> expected_origins(expected_infos.size());
-  start = 0;
-  for (uint32_t i = 0; i < expected_infos.size(); ++i)
+namespace onert_train
+{
+
+RawDataLoader::RawDataLoader(const std::string &input_file, const std::string &expected_file,
+                             const std::vector<nnfw_tensorinfo> &input_infos,
+                             const std::vector<nnfw_tensorinfo> &expected_infos)
+  : DataLoader(input_infos, expected_infos)
+{
+  _input_file = std::ifstream(input_file, std::ios::binary);
+  _expected_file = std::ifstream(expected_file, std::ios::binary);
+
+  _input_file.seekg(0, std::ios::end);
+  uint32_t input_file_size = _input_file.tellg();
+  uint32_t input_data_length = input_file_size / getRawTensorSize(_input_infos);
+
+  _expected_file.seekg(0, std::ios::end);
+  uint32_t expected_file_size = _expected_file.tellg();
+  uint32_t expected_data_length = expected_file_size / getRawTensorSize(_expected_infos);
+
+  if (input_data_length != expected_data_length)
   {
-    expected_origins.at(i) = start;
-    start += (bufsize_for(&expected_infos[i]) / batch_size * data_length);
+    throw std::runtime_error("The length of input data and expected data does not match.");
   }
 
-  try
+  _data_length = input_data_length;
+}
+
+std::tuple<Generator, uint32_t> RawDataLoader::loadData(const uint32_t batch_size, const float from,
+                                                        const float to)
+{
+  assert(from >= 0.f && from <= 1.f);
+  assert(to >= 0.f && to <= 1.f);
+  assert(from <= to);
+
+  int32_t split_size = _data_length * (to - from);
+  int32_t split_start = _data_length * from;
+  std::vector<uint32_t> input_origins(_input_infos.size());
+  uint32_t start = 0;
+  for (uint32_t i = 0; i < _input_infos.size(); ++i)
   {
-    _input_file = std::ifstream(input_file, std::ios::ate | std::ios::binary);
-    _expected_file = std::ifstream(expected_file, std::ios::ate | std::ios::binary);
+    auto hwc_size = bufsize_for(&_input_infos[i]) / batch_size;
+    input_origins.at(i) = start + (hwc_size * split_start);
+    start += (hwc_size * _data_length);
   }
-  catch (const std::exception &e)
+
+  std::vector<uint32_t> expected_origins(_expected_infos.size());
+  start = 0;
+  for (uint32_t i = 0; i < _expected_infos.size(); ++i)
   {
-    std::cerr << e.what() << std::endl;
-    std::exit(-1);
+    auto hwc_size = bufsize_for(&_expected_infos[i]) / batch_size;
+    expected_origins.at(i) = start + (hwc_size * split_start);
+    start += (hwc_size * _data_length);
   }
 
-  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;
-  };
+  return std::make_tuple(
+    [input_origins, expected_origins, 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;
+    },
+    split_size);
 }
 
 } // namespace onert_train
index 3fb2927..d2075f8 100644 (file)
 #ifndef __ONERT_TRAIN_RAWDATALOADER_H__
 #define __ONERT_TRAIN_RAWDATALOADER_H__
 
-#include "allocation.h"
-#include "nnfw.h"
-
-#include <functional>
-#include <string>
-#include <vector>
-#include <fstream>
+#include "dataloader.h"
 
 namespace onert_train
 {
 
-using Generator = std::function<bool(uint32_t,                  /** index **/
-                                     std::vector<Allocation> &, /** input **/
-                                     std::vector<Allocation> & /** expected **/)>;
-
-class RawDataLoader
+class RawDataLoader : public DataLoader
 {
 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);
+  RawDataLoader(const std::string &input_file, const std::string &expected_file,
+                const std::vector<nnfw_tensorinfo> &input_infos,
+                const std::vector<nnfw_tensorinfo> &expected_infos);
 
-private:
-  std::ifstream _input_file;
-  std::ifstream _expected_file;
+  std::tuple<Generator, uint32_t> loadData(const uint32_t batch_size, const float from = 0.0f,
+                                           const float to = 1.0f) override;
 };
 
 } // namespace onert_train
index b2930b3..0264014 100644 (file)
@@ -174,9 +174,12 @@ TEST_F(RawDataLoaderTest, loadDatas_1)
   }
 
   // Load test datas
-  RawDataLoader loader;
-  Generator generator =
-    loader.loadData(input_file, expected_file, in_infos, expected_infos, data_length, batch_size);
+  RawDataLoader loader(input_file, expected_file, in_infos, expected_infos);
+  Generator generator;
+  uint32_t test_data_length;
+  std::tie(generator, test_data_length) = loader.loadData(batch_size);
+
+  EXPECT_EQ(data_length, test_data_length);
 
   // Allocate inputs and expecteds data memory
   std::vector<Allocation> inputs(num_input);
index 54e3f61..54da8c8 100644 (file)
@@ -11,13 +11,10 @@ endif(NOT BUILD_ONERT)
 list(APPEND SOURCES "src/tflite_comparator.cc")
 list(APPEND SOURCES "src/args.cc")
 
-nnfw_find_package(Boost REQUIRED program_options system filesystem)
-
 add_executable(tflite_comparator ${SOURCES})
-target_include_directories(tflite_comparator PRIVATE ${Boost_INCLUDE_DIRS})
 
 target_link_libraries(tflite_comparator nnfw-dev)
 target_link_libraries(tflite_comparator nnfw_lib_tflite nnfw_lib_misc)
-target_link_libraries(tflite_comparator ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY})
+target_link_libraries(tflite_comparator arser)
 
 install(TARGETS tflite_comparator DESTINATION bin)
index ecab20b..66a7aa7 100644 (file)
 
 #include <iostream>
 
-#include <boost/filesystem.hpp>
-
 namespace TFLiteRun
 {
 
 Args::Args(const int argc, char **argv) noexcept
+  : _arser("Load tflite model by onert and TFLite, and compare their output")
 {
   Initialize();
   Parse(argc, argv);
@@ -31,59 +30,39 @@ Args::Args(const int argc, char **argv) noexcept
 
 void Args::Initialize(void)
 {
-  // General options
-  po::options_description general("General options");
-
-  // clang-format off
-  general.add_options()
-    ("help,h", "Display available options")
-    ("tflite", po::value<std::string>()->default_value("")->required(), "Input tflite model file for serialization")
-    ("data,d", po::value<std::vector<std::string>>()->multitoken()->default_value(std::vector<std::string>{}, ""), "Input data file for model");
-  // clang-format on
+  // positional argument
+  _arser.add_argument("tflite")
+    .type(arser::DataType::STR)
+    .help("Input tflite model file for serialization");
 
-  _options.add(general);
-  _positional.add("tflite", 1);
+  // optional argument
+  _arser.add_argument("--data", "-d")
+    .type(arser::DataType::STR)
+    .accumulated()
+    .help("Input data file for model");
 }
 
-void Args::print(char **argv)
-{
-  std::cout << "tflite_comparator" << std::endl << std::endl;
-  std::cout << "Load tflite model by onert and TFLite, and compare their output" << std::endl;
-  std::cout << "Usage:" << std::endl;
-  std::cout << argv[0] << " --tflite model_file.tflite --data input_data.dat" << std::endl;
-  std::cout << _options;
-  std::cout << std::endl;
-}
+void Args::print(char **) { std::cout << _arser; }
 
 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);
-  po::notify(vm);
-
-  if (vm.count("help"))
-  {
-    print(argv);
-
-    exit(0);
-  }
-
   try
   {
-    if (vm.count("tflite"))
+    _arser.parse(argc, argv);
+
+    if (_arser["tflite"])
     {
-      _tflite_filename = vm["tflite"].as<std::string>();
+      _tflite_filename = _arser.get<std::string>("tflite");
     }
 
-    if (vm.count("data"))
+    if (_arser["--data"])
     {
-      _data_filenames = vm["data"].as<std::vector<std::string>>();
+      _data_filenames = _arser.get<std::vector<std::string>>("--data");
     }
   }
-  catch (const std::bad_cast &e)
+  catch (const std::exception &e)
   {
-    std::cerr << e.what() << '\n';
+    std::cerr << e.what() << std::endl;
     print(argv);
     exit(1);
   }
index 4d0e8ff..1062535 100644 (file)
@@ -18,9 +18,7 @@
 #define __TFLITE_LOADER_TOOLS_SRC_ARGS_H__
 
 #include <string>
-#include <boost/program_options.hpp>
-
-namespace po = boost::program_options;
+#include <arser/arser.h>
 
 namespace TFLiteRun
 {
@@ -39,8 +37,7 @@ private:
   void Parse(const int argc, char **argv);
 
 private:
-  po::options_description _options;
-  po::positional_options_description _positional;
+  arser::Arser _arser;
 
   std::string _tflite_filename;
   std::vector<std::string> _data_filenames;
index 383a4e4..7431696 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <misc/EnvVar.h>
 #include <misc/fp32.h>
-#include <misc/RandomGenerator.h>
+#include <benchmark/RandomGenerator.h>
 
 #include <tflite/Assert.h>
 #include <tflite/InterpreterSession.h>
@@ -62,7 +62,7 @@ void readData(const std::string &path, std::vector<uint8_t> &dest)
 }
 
 template <typename T>
-void randomData(nnfw::misc::RandomGenerator &randgen, std::vector<uint8_t> &dest)
+void randomData(benchmark::RandomGenerator &randgen, std::vector<uint8_t> &dest)
 {
   size_t elements = dest.size() / sizeof(T);
   assert(dest.size() % sizeof(T) == 0);
@@ -75,7 +75,7 @@ void randomData(nnfw::misc::RandomGenerator &randgen, std::vector<uint8_t> &dest
   memcpy(dest.data(), vec.data(), elements * sizeof(T));
 }
 
-void randomBoolData(nnfw::misc::RandomGenerator &randgen, std::vector<uint8_t> &dest)
+void randomBoolData(benchmark::RandomGenerator &randgen, std::vector<uint8_t> &dest)
 {
   size_t elements = dest.size();
   std::vector<uint8_t> vec(elements);
@@ -168,6 +168,31 @@ bool isClose<float>(const float *ref_buf, const std::vector<uint8_t> &act_buf, u
   return match;
 }
 
+template <>
+bool isClose(const uint8_t *ref_buf, const std::vector<uint8_t> &act_buf, uint32_t index)
+{
+  // TODO better way for handling quant error?
+  auto tolerance = static_cast<uint64_t>(nnfw::misc::EnvVar("TOLERANCE").asInt(0));
+  bool match = true;
+
+  for (uint32_t e = 0; e < act_buf.size() / sizeof(uint8_t); e++)
+  {
+    // Calculate diff by int64_t type to print value, not character (uint8_t)
+    int32_t ref = ref_buf[e];
+    int32_t act = reinterpret_cast<const uint8_t *>(act_buf.data())[e];
+    int32_t diff = static_cast<int32_t>(((ref > act) ? (ref - act) : (act - ref)));
+
+    if (ref != act && diff > tolerance)
+    {
+      std::cerr << "Output #" << index << ", Element Index : " << e << ", ref: " << ref
+                << ", act: " << act << " (diff: " << diff << ")" << std::endl;
+      match = false;
+    }
+  }
+
+  return match;
+}
+
 bool exact(const uint8_t *ref_buf, const std::vector<uint8_t> &act_buf, uint32_t index)
 {
   bool match = true;
@@ -242,7 +267,7 @@ int main(const int argc, char **argv)
   }
 
   const int seed = 1; /* TODO Add an option for seed value */
-  nnfw::misc::RandomGenerator randgen{seed, 0.0f, 2.0f};
+  benchmark::RandomGenerator randgen{seed, 0.0f, 2.0f};
 
   for (uint32_t i = 0; i < num_inputs; i++)
   {
index bbe1992..ed574ac 100644 (file)
@@ -7,26 +7,13 @@ list(APPEND TFLITE_RUN_SRCS "src/args.cc")
 list(APPEND TFLITE_RUN_SRCS "src/tensor_dumper.cc")
 list(APPEND TFLITE_RUN_SRCS "src/tensor_loader.cc")
 
-nnfw_find_package(Boost REQUIRED program_options)
-
 add_executable(tflite_run ${TFLITE_RUN_SRCS})
-target_include_directories(tflite_run PRIVATE src)
-target_include_directories(tflite_run PRIVATE ${Boost_INCLUDE_DIRS})
-
-target_link_libraries(tflite_run nnfw_lib_tflite)
-target_link_libraries(tflite_run ${Boost_PROGRAM_OPTIONS_LIBRARY})
 
-target_link_libraries(tflite_run nnfw_lib_benchmark)
+target_link_libraries(tflite_run nnfw_lib_tflite nnfw_lib_benchmark)
+target_link_libraries(tflite_run arser)
 
 install(TARGETS tflite_run DESTINATION bin)
 
-# TEST BUILD
-nnfw_find_package(GTest)
-
-if(NOT GTest_FOUND)
-  return()
-endif(NOT GTest_FOUND)
-
 ## Add test cpp file
 add_executable(tflite_test src/tflite_test.cc)
 ## Link test executable against gtest & gtest_main
index f8f581b..532e7e9 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "args.h"
 
-#include <iostream>
+#include <unistd.h>
 
 namespace TFLiteRun
 {
@@ -37,117 +37,117 @@ Args::Args(const int argc, char **argv) noexcept
 
 void Args::Initialize(void)
 {
-  auto process_input = [&](const std::string &v) {
-    _input_filename = v;
-
-    if (!_input_filename.empty())
-    {
-      if (access(_input_filename.c_str(), F_OK) == -1)
-      {
-        std::cerr << "input image file not found: " << _input_filename << "\n";
-      }
-    }
-  };
-
-  auto process_tflite = [&](const std::string &v) {
-    _tflite_filename = v;
-
-    if (_tflite_filename.empty())
-    {
-      // TODO Print usage instead of the below message
-      std::cerr << "Please specify tflite file. Run with `--help` for usage."
-                << "\n";
-
-      exit(1);
-    }
-    else
-    {
-      if (access(_tflite_filename.c_str(), F_OK) == -1)
-      {
-        std::cerr << "tflite file not found: " << _tflite_filename << "\n";
-        exit(1);
-      }
-    }
-  };
-
   try
   {
-    // General options
-    po::options_description general("General options");
-
-    // clang-format off
-  general.add_options()
-    ("help,h", "Display available options")
-    ("input,i", po::value<std::string>()->default_value("")->notifier(process_input), "Input filename")
-    ("dump,d", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _dump_filename = v; }), "Output filename")
-    ("ishapes", po::value<std::vector<int>>()->multitoken()->notifier([&](const auto &v) { _input_shapes = v; }), "Input shapes")
-    ("compare,c", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _compare_filename = v; }), "filename to be compared with")
-    ("tflite", po::value<std::string>()->required()->notifier(process_tflite))
-    ("num_runs,r", po::value<int>()->default_value(1)->notifier([&](const auto &v) { _num_runs = v; }), "The number of runs")
-    ("warmup_runs,w", po::value<int>()->default_value(0)->notifier([&](const auto &v) { _warmup_runs = v; }), "The number of warmup runs")
-    ("run_delay,t", po::value<int>()->default_value(-1)->notifier([&](const auto &v) { _run_delay = v; }), "Delay time(ms) between runs (as default no delay)")
-    ("gpumem_poll,g", po::value<bool>()->default_value(false)->notifier([&](const auto &v) { _gpumem_poll = v; }), "Check gpu memory polling separately")
-    ("mem_poll,m", po::value<bool>()->default_value(false), "Check memory polling")
-    ("write_report,p", po::value<bool>()->default_value(false)->notifier([&](const auto &v) { _write_report = v; }), "Write report")
-    ("validate", po::value<bool>()->default_value(true)->notifier([&](const auto &v) { _tflite_validate = v; }), "Validate tflite model")
-    ("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")
-    ;
-    // clang-format on
-
-    _options.add(general);
-    _positional.add("tflite", 1);
+    _arser.add_argument("--input", "-i")
+      .type(arser::DataType::STR)
+      .default_value("")
+      .help("Input filename");
+    _arser.add_argument("--dump", "-d")
+      .type(arser::DataType::STR)
+      .default_value("")
+      .help("Output filename");
+    _arser.add_argument("--ishapes").type(arser::DataType::INT32_VEC).help("Input shapes");
+    _arser.add_argument("--compare", "-c")
+      .type(arser::DataType::STR)
+      .default_value("")
+      .help("Filename to be compared with");
+    _arser.add_argument("--num_runs", "-r")
+      .type(arser::DataType::INT32)
+      .default_value(1)
+      .help("The number of runs");
+    _arser.add_argument("--warmup_runs", "-w")
+      .type(arser::DataType::INT32)
+      .default_value(0)
+      .help("The number of warmup runs");
+    _arser.add_argument("--run_delay", "-t")
+      .type(arser::DataType::INT32)
+      .default_value(-1)
+      .help("Delay time(ms) between runs (as default no delay)");
+    _arser.add_argument("--gpumem_poll", "-g")
+      .nargs(0)
+      .default_value(false)
+      .help("Check gpu memory polling separately");
+    _arser.add_argument("--mem_poll", "-m")
+      .nargs(0)
+      .default_value(false)
+      .help("Check memory polling");
+    _arser.add_argument("--write_report", "-p").nargs(0).default_value(false).help("Write report");
+    _arser.add_argument("--verbose_level", "-v")
+      .type(arser::DataType::INT32)
+      .default_value(0)
+      .help("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");
+    _arser.add_argument("tflite").type(arser::DataType::STR);
   }
-  catch (const std::bad_cast &e)
+  catch (const std::runtime_error &err)
   {
-    std::cerr << "error by bad cast during initialization of boost::program_options" << e.what()
-              << '\n';
+    std::cerr << err.what() << std::endl;
+    std::cout << _arser;
     exit(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);
 
+  try
   {
-    auto conflicting_options = [&](const std::string &o1, const std::string &o2) {
-      if ((vm.count(o1) && !vm[o1].defaulted()) && (vm.count(o2) && !vm[o2].defaulted()))
+    _arser.parse(argc, argv);
+
+    // Get parsed options
+    _input_filename = _arser.get<std::string>("--input");
+    _dump_filename = _arser.get<std::string>("--dump");
+    _input_shapes = _arser.get<std::vector<int>>("--ishapes");
+    _compare_filename = _arser.get<std::string>("--compare");
+    _num_runs = _arser.get<int>("--num_runs");
+    _warmup_runs = _arser.get<int>("--warmup_runs");
+    _run_delay = _arser.get<int>("--run_delay");
+    _gpumem_poll = _arser.get<bool>("--gpumem_poll");
+    _mem_poll = _arser.get<bool>("--mem_poll");
+    _write_report = _arser.get<bool>("--write_report");
+    _verbose_level = _arser.get<int>("--verbose_level");
+    _tflite_filename = _arser.get<std::string>("tflite");
+
+    // Validation check
+    if (!_input_filename.empty())
+    {
+      if (access(_input_filename.c_str(), F_OK) == -1)
       {
-        throw boost::program_options::error(std::string("Two options '") + o1 + "' and '" + o2 +
-                                            "' cannot be given at once.");
+        std::cerr << "Input image file not found: " << _input_filename << std::endl;
+        exit(1);
       }
-    };
-
-    conflicting_options("input", "compare");
-  }
-
-  if (vm.count("help"))
-  {
-    std::cout << "tflite_run\n\n";
-    std::cout << "Usage: " << argv[0] << " <.tflite> [<options>]\n\n";
-    std::cout << _options;
-    std::cout << "\n";
+    }
 
-    exit(0);
-  }
+    if (!_tflite_filename.empty())
+    {
+      if (access(_tflite_filename.c_str(), F_OK) == -1)
+      {
+        std::cerr << "TFLite file not found: " << _tflite_filename << std::endl;
+        exit(1);
+      }
+    }
 
-  po::notify(vm);
+    // Check conflict option
+    if (!_input_filename.empty() && !_compare_filename.empty())
+    {
+      std::cerr << "Two options '--input' and '--compare' cannot be given at once" << std::endl;
+      exit(1);
+    }
 
-  // This must be run after `notify` as `_warm_up_runs` must have been processed before.
-  if (vm.count("mem_poll"))
-  {
-    _mem_poll = vm["mem_poll"].as<bool>();
     // Instead of EXECUTE to avoid overhead, memory polling runs on WARMUP
     if (_mem_poll && _warmup_runs == 0)
     {
       _warmup_runs = 1;
     }
   }
+  catch (const std::exception &e)
+  {
+    std::cerr << e.what() << std::endl;
+    exit(1);
+  }
 }
 
 } // end of namespace TFLiteRun
index 054e47b..9360e4e 100644 (file)
@@ -18,9 +18,7 @@
 #define __TFLITE_RUN_ARGS_H__
 
 #include <string>
-#include <boost/program_options.hpp>
-
-namespace po = boost::program_options;
+#include <arser/arser.h>
 
 namespace TFLiteRun
 {
@@ -42,7 +40,6 @@ public:
   const bool getGpuMemoryPoll(void) const { return _gpumem_poll; }
   const bool getMemoryPoll(void) const { return _mem_poll; }
   const bool getWriteReport(void) const { return _write_report; }
-  const bool getModelValidate(void) const { return _tflite_validate; }
   const int getVerboseLevel(void) const { return _verbose_level; }
 
 private:
@@ -50,8 +47,7 @@ private:
   void Parse(const int argc, char **argv);
 
 private:
-  po::positional_options_description _positional;
-  po::options_description _options;
+  arser::Arser _arser;
 
   std::string _tflite_filename;
   std::string _dump_filename;
@@ -64,7 +60,6 @@ private:
   bool _gpumem_poll;
   bool _mem_poll;
   bool _write_report;
-  bool _tflite_validate;
   int _verbose_level;
 };
 
index a1e3d2e..4aa4a3f 100644 (file)
@@ -17,7 +17,6 @@
 #include "args.h"
 #include "tensor_dumper.h"
 #include "tensor_loader.h"
-#include "misc/benchmark.h"
 #include "misc/EnvVar.h"
 #include "misc/fp32.h"
 #include "tflite/Diff.h"
@@ -142,7 +141,7 @@ int main(const int argc, char **argv)
   else
   {
     const int seed = 1; /* TODO Add an option for seed value */
-    nnfw::misc::RandomGenerator randgen{seed, 0.0f, 2.0f};
+    benchmark::RandomGenerator randgen{seed, 0.0f, 2.0f};
 
     RandomInputInitializer initializer{randgen};
     initializer.run(*interpreter);
index 5ea6cda..b589135 100644 (file)
@@ -1 +1,5 @@
+# Use C++17 for tools
+# TODO: Remove this when we use C++17 for all runtime directories
+set(CMAKE_CXX_STANDARD 17)
+
 add_subdirectories()
diff --git a/tools/circle_plus_gen/README.md b/tools/circle_plus_gen/README.md
new file mode 100644 (file)
index 0000000..e79387d
--- /dev/null
@@ -0,0 +1,127 @@
+# Circle+ generator
+
+Circle+ is a circle file which contains training hyperparameters. <br/> 
+This tool generates a circle+ by adding training hyperparameters to a circle file.<br/>
+It also helps handle circle+ file, such as checking whether the circle file contains training hyperparameters. <br/> 
+
+## Requirements
+
+This tool tested on python3.8. 
+
+1. (optional) Set python virtaul environment.
+
+    ```
+    python3 -m venv venv
+    source ./venv/bin/activate
+    ```
+
+2. Install required pakcages. 
+
+    Currently, only `flatbuffers` is needed.
+    ```bash
+    python3 -m pip install -r requirements.txt
+    ```
+
+## Add training hyperparameters using json file
+
+You can add a training hyperparameters to a circle file.
+To begin with, you need to write the hyperparameters in a json file. Here's [an example](./example/train_tparam.json) of a json file. <br/>
+To write own json file, please refer detailed documenet [here](./how-to-write-tparam-json.md).
+
+
+```bash 
+cat example/train_tparam.json
+
+# {
+#   "optimizer": {
+#       "type": "adam",
+#       "args": {
+#           "learningRate": 0.01,
+#           "beta1": 0.9,
+#           "beta2": 0.999,
+#           "epsilon": 1e-07
+#       }
+#   },
+#   "loss": {
+#       "type": "categorical crossentropy",
+#       "args": {
+#           "fromLogits": true,
+#           "reduction": "sum over batch size"
+#       }
+#   },
+#   "batchSize": 32,
+#   "fineFuning": 0
+# }
+```
+
+Next, execute the `main.py` script to add the hyperparameters to the `*.circle` file.
+
+```bash
+python3 main.py example/sample.circle example/train_tparam.json out.circle
+
+# expected output
+# 
+# load training hyperparameters
+# {
+#     "optimizer": {
+#         "type": "adam",
+#         "args": {
+#          ... 
+#     },
+#     "batchSize": 32,
+#     "fineFuning": 0
+# }
+# succesfully add hyperparameters to the circle file
+# saved in out.circle
+```
+
+If you don't give `out.circle` as an argument, the input circle file(here, `example/sample.circle`) will be overwritten. 
+
+
+## Print training hyperparameters in circle file
+
+You can check whether the circle file contains the training hyperparameters.</br>
+If you run the `main.py` without providing a json file, it will display training hyperparameters in the given circle file.
+
+Try this with the files in [example](./example/).
+```bash
+python3 main.py example/sample.circle
+
+# expected output
+#
+# check hyperparameters in example/sample.circle
+# No hyperparameters
+```
+```bash
+python3 main.py example/sample_tparam.circle
+
+# expected output 
+#
+# check hyperparameters in example/sample_tparam.circle
+# {
+#     "optimizer": {
+#         "type": "sgd",
+#         "args": {
+#             "learningRate": 0.0010000000474974513
+#         }
+#     },
+#     "loss": {
+#         "type": "sparse categorical crossentropy",
+#         "args": {
+#             "fromLogits": true,
+#             "reduction": "SumOverBatchSize"
+#         }
+#     },
+#     "batchSize": 64,
+#    "fineTuning": -1
+# }
+```
+
+If it doesn't work well with example files, please check their md5sum to make sure they're not broken. 
+
+```bash
+$ md5sum example/sample.circle example/sample_tparam.circle
+
+df287dea52cf5bf16bc9dc720e8bca04  example/sample.circle
+6e736e0544acc7ccb727cbc8f77add94  example/sample_tparam.circle
+```
diff --git a/tools/circle_plus_gen/example/sample.circle b/tools/circle_plus_gen/example/sample.circle
new file mode 100644 (file)
index 0000000..be622c7
Binary files /dev/null and b/tools/circle_plus_gen/example/sample.circle differ
diff --git a/tools/circle_plus_gen/example/sample_tparam.circle b/tools/circle_plus_gen/example/sample_tparam.circle
new file mode 100644 (file)
index 0000000..4631c3d
Binary files /dev/null and b/tools/circle_plus_gen/example/sample_tparam.circle differ
diff --git a/tools/circle_plus_gen/example/tparam_sgd_scce.json b/tools/circle_plus_gen/example/tparam_sgd_scce.json
new file mode 100644 (file)
index 0000000..34f5112
--- /dev/null
@@ -0,0 +1,17 @@
+{  
+    "optimizer": {  
+        "type": "sgd",  
+        "args": {  
+            "learning_rate": 0.001
+        }  
+    },  
+    "loss": {  
+        "type": "sparse categorical crossentropy",  
+        "args": {  
+            "from_logits": true,  
+            "reduction": "sum over batch size"  
+        }  
+    },  
+    "batchSize": 64, 
+    "fineFuning" : 2 
+}  
diff --git a/tools/circle_plus_gen/example/train_tparam.json b/tools/circle_plus_gen/example/train_tparam.json
new file mode 100644 (file)
index 0000000..60c64b2
--- /dev/null
@@ -0,0 +1,20 @@
+{
+  "optimizer": {
+      "type": "adam",
+      "args": {
+          "learningRate": 0.01,
+          "beta1": 0.9,
+          "beta2": 0.999,
+          "epsilon": 1e-07
+      }
+  },
+  "loss": {
+      "type": "categorical crossentropy",
+      "args": {
+          "fromLogits": true,
+          "reduction": "sum over batch size"
+      }
+  },
+  "batchSize": 32,
+  "fineFuning": 0
+}
diff --git a/tools/circle_plus_gen/how-to-write-tparam-json.md b/tools/circle_plus_gen/how-to-write-tparam-json.md
new file mode 100644 (file)
index 0000000..9fd79c4
--- /dev/null
@@ -0,0 +1,94 @@
+# How to write Hyperparameters JSON file
+
+The Hyperparameters JSON file is used to store hyperparameters that should be configured before training. For quicker understanding, please refer to the examples([#1](./example/train_tparam.json), [#2](./example/tparam_sgd_scce.json)) of the JSON file. 
+<br/>
+
+The json file consists of **a single JSON object** containing the following keys and corresponding values : 
+
+```json
+{
+  "optimizer" : {...}, 
+  "loss" : {...},
+  "batchSize" : 32,
+  "fineTuning" : 0, 
+}
+```
+
+- "optimizer" : refer [optimizer](#optimizer) for writing corresponding value
+- "loss" : refer [loss](#loss) for writing corresponding value
+- "batchSize" : a number of examples processeed during each iteration 
+- "fineTuning" : refer [fineTuning] for writing corresponding value
+
+## optimizer
+
+An object describing optimization algorithm. This should include two keys : 
+
+* `type` : a string to indicate optimizer 
+  * You can find the `type` strings for each optimizers from [OptimizerNamer.names](https://github.com/Samsung/ONE/blob/master/tools/circle_plus_gen/lib/utils.py#L17).
+  * For example, If you like to use 'adam' optimizer, you should write 'adam' for type.
+* `args` : an object holding additional arguments to the chosen optimizer. These may vary depending on the optimizer type, but typically include 'learningRate'. 
+  * You can obtain args lists from `table [optimizer]Options`. Please refer to [here](https://github.com/Samsung/ONE/blob/master/runtime/libs/circle-schema/include/circle_traininfo.fbs). 
+  * For example, to use 'adam' optimizer, you should fill the args with 
+  [`table AdamOptions`](https://github.com/Samsung/ONE/blob/1a1a52afd87154720c28420d9a6804191421d5de/runtime/libs/circle-schema/include/circle_traininfo.fbs#L63-L66) attributes. 
+
+  ```json
+  {
+    ... 
+    "optimizer": {
+      "type": "adam",
+      "args": {
+          "learning_rate": 0.01,
+          "beta_1": 0.9,
+          "beta_2": 0.999,
+          "epsilon": 1e-07
+      }
+    }, 
+    ... 
+  } 
+  ``` 
+
+**Supported Optimizers:** <br/>
+  * adam 
+  * sgd 
+
+
+## loss
+
+An object describing the loss function. This should include two keys :
+
+* `type`: a string specifying which loss function to use.
+  * You can find the `type` strings at [LossNamer.names](https://github.com/Samsung/ONE/blob/master/tools/circle_plus_gen/lib/utils.py#L34). 
+  * For example, If you choose 'mse', you can use either 'mean squared error' or 'mse' for the type. 
+
+* `args`: an object holding additional arguments specific to the chosen loss function. These may vary depending on the loss function type. 
+  * You can obtain args list from `table [loss]Options` attributes. please refer [here](https://github.com/Samsung/ONE/blob/master/runtime/libs/circle-schema/include/circle_traininfo.fbs). 
+  * In addition to `table [loss]Options` attribute, **you should add a `reduction`** to specify how loss value will be shown. 
+  * For example, to use 'mse' loss function, since there is nothing in the [`table MeanSquaredErrorOptions`](https://github.com/Samsung/ONE/blob/1a1a52afd87154720c28420d9a6804191421d5de/runtime/libs/circle-schema/include/circle_traininfo.fbs#L97-L98), you only need to add `reduction` to `args`.
+
+
+  ```json
+  {
+    ...
+    "loss":{
+      "type" : "mse",
+      "args" : {
+        "reduction" : "sum over batch size"
+      }
+    }
+    ...
+  }
+  ```
+
+**Supported Loss Functions:**
+  * sparse categorical crossentropy 
+  * categorical crossentropy  
+  * mean squared error 
+
+## fineTuning
+
+An integer value, describing how many number of operations will be trained.
+
+Also, 0 and 1 can be used to indicate the following meanings:
+
+* 0 : entire model will be trained
+* -1 : entire model will NOT be trained, This can be used for inference
diff --git a/tools/circle_plus_gen/lib/__init__.py b/tools/circle_plus_gen/lib/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/circle_plus_gen/lib/circle_plus.py b/tools/circle_plus_gen/lib/circle_plus.py
new file mode 100644 (file)
index 0000000..94989e7
--- /dev/null
@@ -0,0 +1,119 @@
+import flatbuffers
+import typing
+
+from schema import circle_schema_generated as cir_gen
+from lib.train_param import TrainParam
+
+
+def _not_none(elem, elem_name=""):
+    '''Make sure that elem is not empty'''
+    if elem == None:
+        raise RuntimeError(f"{elem_name} is none")
+    return
+
+
+class CirclePlus():
+    ''' Wrapper class of circle_schema_generated.ModelT'''
+    TINFO_META_TAG = b"CIRCLE_TRAINING"
+    CIRCLE_IDENTIFIER = b"CIR0"
+
+    def __init__(self):
+        self.model: cir_gen.ModelT = cir_gen.ModelT()
+
+    @classmethod
+    def from_file(cls, circle_file: str):
+        '''Create CirclePlus based on circle file'''
+        new_circle_plus = cls()
+        with open(circle_file, 'rb') as f:
+            new_circle_plus.model = cir_gen.ModelT.InitFromPackedBuf(f.read())
+        return new_circle_plus
+
+    def get_train_param(self) -> typing.Union[TrainParam, None]:
+        '''Return TrainInfo, if it exists'''
+        metadata = self.model.metadata
+        buffers = self.model.buffers
+
+        if metadata == None:
+            return None
+
+        for m in metadata:
+            if m.name == self.TINFO_META_TAG:
+                buff: cir_gen.BufferT = buffers[m.buffer]
+                tparam: TrainParam = TrainParam.from_buff(buff.data)
+                return tparam
+
+        return None
+
+    def _add_metadata(self, meta_name, meta_buf):
+        buffer_obj = cir_gen.BufferT()
+        buffer_obj.data = meta_buf
+
+        # If there are train_param, Replace it
+        if self.get_train_param() is not None:
+            for m in self.model.metadata:
+                if m.name == self.TINFO_META_TAG:
+                    self.model.buffers[m.buffer] = buffer_obj
+
+        # There are no train_param, So add a new buffer and metadata
+        else:
+            if self.model.metadata == None:
+                self.model.metadata = []
+
+            if self.model.buffers == None:
+                self.model.buffers = []
+
+            self.model.buffers.append(buffer_obj)
+
+            metadata_obj = cir_gen.MetadataT()
+            metadata_obj.name = meta_name
+            metadata_obj.buffer = len(self.model.buffers) - 1
+            self.model.metadata.append(metadata_obj)
+
+    def set_train_param(self, train_param: TrainParam):
+        '''Add train_param to the model's metadata field'''
+        tparam_buff = train_param.to_buff()
+        self._add_metadata(self.TINFO_META_TAG, tparam_buff)
+
+    def get_number_of_operators(self, subgraph_idx=0) -> int:
+        '''Return the number of operators in the subgraph'''
+        subgraphs: typing.List[cir_gen.SubGraphT] = self.model.subgraphs
+        _not_none(subgraphs, "subgraphs")
+
+        operators: typing.List[cir_gen.OperatorT] = subgraphs[subgraph_idx].operators
+        if operators == None:
+            return 0
+        return len(operators)
+
+    def get_operator_names(self, subgraph_idx=0) -> typing.List[str]:
+        '''Return a list of operator names according to the order of operations in the subgraph'''
+        subgraphs: typing.List[cir_gen.SubGraphT] = self.model.subgraphs
+        opcodes: typing.List[cir_gen.OperatorCodeT] = self.model.operatorCodes
+        _not_none(subgraphs, "subgraphs")
+        _not_none(opcodes, "operatorCodes")
+
+        operators: typing.List[cir_gen.OperatorT] = subgraphs[subgraph_idx].operators
+        _not_none(operators, "operators")
+
+        opcodes_str = cir_gen.BuiltinOperator.__dict__.keys()  # ['GRU', 'BCQ_GATHER' .. ]
+        opcodes_int = cir_gen.BuiltinOperator.__dict__.values()  # [-5, -4, -3....]
+        opcode_dict = dict(zip(opcodes_int,
+                               opcodes_str))  #{-5:'GRU', -4:'BCQ_GATHER', ...}
+
+        opcode_in_order = []
+        for op in operators:
+            op_int = opcodes[op.opcodeIndex].builtinCode
+            if op_int in opcode_dict:
+                op_str = opcode_dict[op_int]
+            else:
+                op_str = "UNKNOWN"  # might be custom_op
+            opcode_in_order.append(op_str)
+
+        return opcode_in_order
+
+    def export(self, circle_file: str):
+        '''Export model to the circle file'''
+        builder = flatbuffers.Builder(0)
+        builder.Finish(self.model.Pack(builder), self.CIRCLE_IDENTIFIER)
+
+        with open(circle_file, 'wb') as f:
+            f.write(builder.Output())
diff --git a/tools/circle_plus_gen/lib/json_parser.py b/tools/circle_plus_gen/lib/json_parser.py
new file mode 100644 (file)
index 0000000..8c2c1eb
--- /dev/null
@@ -0,0 +1,170 @@
+import re
+from typing import Tuple, List, Union
+
+from lib import utils
+from schema import circle_traininfo_generated as ctr_gen
+
+
+def to_camel_case(string: str):
+    if not '_' in string:
+        # string is already camel case
+        return string
+
+    captialized_str: str = "".join(x.capitalize() for x in string.lower().split("_"))
+    return string[0].lower() + captialized_str[1:]
+
+
+def _generate_optimizer(
+        opt_type: utils.OPTIM_OPTIONS_T, args: dict
+) -> Tuple[ctr_gen.Optimizer, ctr_gen.OptimizerOptions, utils.OPTIM_OPTIONS_T]:
+
+    options_t_str: str = opt_type.__name__  # e.g. SGDOptionsT
+    options_str: str = options_t_str[:-1]  # e.g. SGDOptions
+    optimizer_camel: str = options_str.replace("Options", "")  # e.g. SGD
+    optimizer_str: str = re.sub(r'(?<=[a-z])(?=[A-Z])', '_',
+                                optimizer_camel).upper()  # e.g. SGD
+
+    optimizer = getattr(ctr_gen.Optimizer, optimizer_str)
+    optimizer_opt_type = getattr(ctr_gen.OptimizerOptions, options_str)
+
+    # set attributes for *OptionsT
+    # e.g. SGDOptionsT.learningRate = 0.001
+    optimizer_opt = opt_type()
+    for (key, value) in args.items():
+        key = to_camel_case(key)
+        setattr(optimizer_opt, key, value)
+
+    return optimizer, optimizer_opt_type, optimizer_opt
+
+
+def load_optimizer(
+        opt_obj: dict
+) -> Tuple[ctr_gen.Optimizer, ctr_gen.OptimizerOptions, utils.OPTIM_OPTIONS_T]:
+    ''' 
+    Return objects for circle_traininfo_generated.ModelTrainingT.[optimizer, optimizerOptType, OptimizerOpt]
+    
+    An example of given arguments and return values : 
+    
+        opt_obj : {
+          "type" : "sgd", 
+          "args" : {"learningRate = 0.1"}
+        }
+        return : (Optimizer.SGD, OptimizerOptions.SGDOptions, object of SGDOptionsT)
+    '''
+    opt_type = opt_obj["type"]
+    opt_args = opt_obj["args"]
+
+    names_of = utils.OptimizerNamer()
+    supported_opt = [ctr_gen.SGDOptionsT, ctr_gen.AdamOptionsT]
+
+    # find type(e.g. SGDOptionsT) from opt_type("sgd")
+    type = None
+    for t in supported_opt:
+        if opt_type.lower() in names_of(t):
+            type = t
+            break
+    if type == None:
+        raise ValueError(f"not supported optimizer.type={opt_type}")
+
+    return _generate_optimizer(type, opt_args)
+
+
+def _generate_lossfn(
+        lossfn_type: utils.LOSSFN_OPTIONS_T, args: dict
+) -> Tuple[ctr_gen.LossFn, ctr_gen.LossFnOptions, utils.LOSSFN_OPTIONS_T]:
+
+    options_t_str: str = lossfn_type.__name__  # e.g. CategoricalCrossentropyOptionsT
+    options_str: str = options_t_str[:-1]  # e.g. CategoricalCrossentropyOptions
+    lossfn_camel: str = options_str.replace("Options", "")  # e.g. CategoricalCrossentropy
+    lossfn_str: str = re.sub(r'(?<=[a-z])(?=[A-Z])', '_',
+                             lossfn_camel).upper()  # e.g. CATEGORICAL_CROSSENTROPY
+
+    lossfn = getattr(ctr_gen.LossFn, lossfn_str)
+    lossfn_opt_type = getattr(ctr_gen.LossFnOptions, options_str)
+
+    # set attributes for *OptionsT
+    # e.g. CategoricalCrossentropyOptionsT.fromLogits = True
+    lossfn_opt = lossfn_type()
+    for (key, value) in args.items():
+        key = to_camel_case(key)
+        setattr(lossfn_opt, key, value)
+
+    return lossfn, lossfn_opt_type, lossfn_opt
+
+
+def load_lossfn(loss_obj: dict):
+    '''
+    Return objects for circle_traininfo_generated.ModelTrainingT.[lossfn, lossfnOptType, lossfnOpt]
+
+    An example of given arguments and return values :
+    
+        loss_obj : {
+          "type" : "categorical crossentropy", 
+          "args" : {"fromLogits = True"}
+        }
+        return : (LossFn.CATEGORICAL_CROSSENTROPY, 
+                  LossFnOptions.CategoricalCrossentropyOptions,
+                  object of CategoricalCrossentropyOptionsT)
+    '''
+    loss_type = loss_obj["type"]
+    loss_args = loss_obj["args"].copy()
+    loss_args.pop("reduction")
+
+    names_of = utils.LossNamer()
+    # yapf:disable
+    supported_loss = [
+        ctr_gen.SparseCategoricalCrossentropyOptionsT,
+        ctr_gen.CategoricalCrossentropyOptionsT,
+        ctr_gen.MeanSquaredErrorOptionsT
+    ]
+    # yapf: enable
+
+    # find type(e.g. MeanSquaredErrorOptionsT) from loss_type(e.g. "mean squared error")
+    type = None
+    for t in supported_loss:
+        if loss_type.lower() in names_of(t):
+            type = t
+            break
+    if type == None:
+        raise ValueError(f"not supported loss.type={loss_type}")
+
+    return _generate_lossfn(type, loss_args)
+
+
+def load_loss_reduction(s: str):
+    ''' Return LossReductionType enum which is correspond to given string
+    '''
+    names_of = utils.LossReductionNamer()
+    supported_rdt = [
+        ctr_gen.LossReductionType.SumOverBatchSize, ctr_gen.LossReductionType.Sum
+    ]
+
+    type = None
+    for t in supported_rdt:
+        if s.lower() in names_of(t):
+            type = t
+            break
+    if type == None:
+        raise ValueError(f"not supported loss.args.reduction={s}")
+
+    return type
+
+
+def load_fine_tuning(n: int, num_op: int) -> List[int]:
+    '''Return [int] to set ModelTrainingT.trainableOps
+    '''
+    if n == 0:  # full training
+        return list(range(0, num_op))
+
+    elif n == -1:  # not training
+        return []
+
+    elif 0 < n and n <= num_op:  # fine tuning
+        start_idx = num_op - n
+        return list(range(start_idx, num_op))
+
+    elif n > num_op:
+        raise ValueError(f"number of operators({num_op}) < fine_tuning({n})")
+
+    else:
+        raise ValueError(f"not supported train {s}")
diff --git a/tools/circle_plus_gen/lib/train_param.py b/tools/circle_plus_gen/lib/train_param.py
new file mode 100644 (file)
index 0000000..092122e
--- /dev/null
@@ -0,0 +1,105 @@
+import flatbuffers
+import json
+
+from lib.utils import *
+from lib.json_parser import *
+from schema import circle_traininfo_generated as ctr_gen
+
+
+class TrainParam():
+    '''Wrapper class of circle_traninfo_generated.ModelTrainingT'''
+    TRAINING_PARAM_IDENTIFIER = b"CTR0"
+
+    def __init__(self):
+        self.train_param = ctr_gen.ModelTrainingT()
+
+    @classmethod
+    def from_buff(cls, buff):
+        '''Create TrainInfo from packed(serialized) buffer'''
+        new_tparam = cls()
+        new_tparam.train_param = ctr_gen.ModelTrainingT.InitFromPackedBuf(bytearray(buff))
+        return new_tparam
+
+    def to_buff(self):
+        '''Serialize train_param and return its buffer'''
+        builder = flatbuffers.Builder(0)
+        builder.Finish(self.train_param.Pack(builder), self.TRAINING_PARAM_IDENTIFIER)
+        return builder.Output()
+
+    @classmethod
+    def from_json(cls, json_file: str, num_op: int):
+        '''Create TrainInfo from json file'''
+        with open(json_file, 'rt') as f:
+            json_obj = json.load(f)
+
+        tparam = ctr_gen.ModelTrainingT()
+
+        # load optimzier
+        optim, optim_opt_type, optim_opt = load_optimizer(json_obj["optimizer"])
+        tparam.optimizer = optim
+        tparam.optimizerOptType = optim_opt_type
+        tparam.optimizerOpt = optim_opt
+
+        # load lossfn
+        lossfn, lossfn_opt_type, lossfn_opt = load_lossfn(json_obj["loss"])
+        tparam.lossfn = lossfn
+        tparam.lossfnOptType = lossfn_opt_type
+        tparam.lossfnOpt = lossfn_opt
+
+        tparam.batchSize = json_obj["batchSize"]
+
+        # load lossReductionType
+        if "reduction" in json_obj["loss"].keys():
+            tparam.lossReductionType = load_loss_reduction(json_obj["loss"]["reduction"])
+
+        # load fine_tuning
+        fine_tuning = 0  # if not given, full training is default
+        if "fineTuning" in json_obj:
+            fine_tuning = json_obj["fineTuning"]
+        try:
+            tparam.trainableOps = load_fine_tuning(fine_tuning, num_op)
+        except ValueError as e:
+            print(e)
+            raise (f"failed to parse \'fineTuning\'")
+
+        new_tparam = cls()
+        new_tparam.train_param = tparam
+        return new_tparam
+
+    def dump_as_json(self, num_op: int) -> str:
+        '''Return JSON formmated string'''
+        tparam = self.train_param
+        name_opt = OptimizerNamer()
+        name_loss = LossNamer()
+        name_rdt = LossReductionNamer()
+
+        json_form = {}
+        json_form["optimizer"] = {
+            "type": name_opt(type(tparam.optimizerOpt))[0],
+            "args": tparam.optimizerOpt.__dict__
+        }
+        json_form["loss"] = {
+            "type": name_loss(type(tparam.lossfnOpt))[0],
+            "args": tparam.lossfnOpt.__dict__,
+        }
+        json_form["loss"]["args"]["reduction"] = name_rdt(tparam.lossReductionType)[0]
+        json_form["batchSize"] = tparam.batchSize
+
+        ft = []
+        if tparam.trainableOps != None:
+            ft = list(tparam.trainableOps)
+        num_ft = len(ft)
+
+        if num_ft == 0:
+            json_form["fineTuning"] = -1
+
+        elif ft == list(range(0, num_op)):
+            json_form["fineTuning"] = 0
+
+        elif num_ft < num_op and list(range(num_op - num_ft, num_op)) == ft:
+            json_form["fineTuning"] = num_ft
+
+        else:
+            raise ValueError(f"fail to dump fineTuning{ft}")
+
+        return json.dumps(json_form, indent=4)
diff --git a/tools/circle_plus_gen/lib/utils.py b/tools/circle_plus_gen/lib/utils.py
new file mode 100644 (file)
index 0000000..0f27c5a
--- /dev/null
@@ -0,0 +1,64 @@
+from typing import Union, Type, List
+from schema import circle_traininfo_generated as ctr_gen
+
+# yapf:disable
+# type alias
+OPTIM_OPTIONS_T = Union[Type[ctr_gen.SGDOptionsT],
+                      Type[ctr_gen.AdamOptionsT]]
+
+LOSSFN_OPTIONS_T = Union[Type[ctr_gen.SparseCategoricalCrossentropyOptionsT],
+                         Type[ctr_gen.CategoricalCrossentropyOptionsT],
+                         Type[ctr_gen.MeanSquaredErrorOptionsT]]
+# yapf:enable
+
+
+class OptimizerNamer:
+    '''Return name(string) based on ModelTraining.OptimizerOpt'''
+    names = {
+        ctr_gen.SGDOptionsT: ['sgd', 'stocasticgradientdescent'],
+        ctr_gen.AdamOptionsT: ['adam']
+    }
+
+    def __call__(self, opt: OPTIM_OPTIONS_T) -> List[str]:
+        try:
+            name = self.names[opt]
+        except:
+            print(f"unknown optimizer {type(opt)}")
+        return name
+
+
+class LossNamer:
+    '''Return name(string) based on ModelTraining.LossfnOpt'''
+
+    # yapf:disable
+    names = {
+        ctr_gen.SparseCategoricalCrossentropyOptionsT:
+            ['sparse categorical crossentropy', 'sparsecategoricalcrossentropy', 'sparsecce'],
+        ctr_gen.CategoricalCrossentropyOptionsT:
+            ['categorical crossentropy', 'categoricalcrossentropy', 'cce'],
+        ctr_gen.MeanSquaredErrorOptionsT:
+            ['mean squared error', 'mse']
+    }
+    # yapf:eanble
+
+    def __call__(self, lossfn:LOSSFN_OPTIONS_T) -> List[str]:
+        try:
+            name = self.names[lossfn]
+        except:
+            print(f"unknown lossfn {type(lossfn)}")
+        return name
+
+
+class LossReductionNamer:
+    '''Return name(string) based on ModelTraining.LossReductionType '''
+    names = {
+        ctr_gen.LossReductionType.SumOverBatchSize: ['sum over batch size', 'sumoverbatchsize'],
+        ctr_gen.LossReductionType.Sum: ['sum'],
+    }
+
+    def __call__(self, rdt:ctr_gen.LossReductionType) -> List[str]:
+        try:
+            name = self.names[rdt]
+        except:
+            print(f"unknown loss reduction type {rdt}")
+        return name
diff --git a/tools/circle_plus_gen/main.py b/tools/circle_plus_gen/main.py
new file mode 100644 (file)
index 0000000..82683ee
--- /dev/null
@@ -0,0 +1,68 @@
+import argparse
+import typing
+
+from lib.circle_plus import CirclePlus
+from lib.train_param import TrainParam
+
+
+def get_cmd_args():
+    parser = argparse.ArgumentParser(
+        prog='circle_plus_gen',
+        description='circle_plus_gen help handle circle file with training hyperparameters'
+    )
+
+    parser.add_argument('input', help='input circle file')
+    parser.add_argument(
+        'hyperparameters', nargs='?', help='training hyperparameters json file')
+    parser.add_argument(
+        'output',
+        nargs='?',
+        help='output circle file, if not given input circle file will be overwritten')
+
+    args = parser.parse_args()
+    return args
+
+
+def print_training_hparameters(circle_model: CirclePlus):
+    '''
+    if circle_model has training hyperparameters, print it out
+    '''
+    tinfo: typing.Union[TrainParam, None] = circle_model.get_train_param()
+    num_op = circle_model.get_number_of_operators()
+
+    if tinfo == None:
+        print("No hyperparameters")
+    else:
+        print(tinfo.dump_as_json(num_op))
+        # TODO print list of trainable operators
+
+
+def inject_hparams(in_file, hparams_file, out_file=None) -> None:
+    '''
+    Inject hparams_file's contents into in_file's circle model, and save it as out_file 
+    '''
+    # if out_file isn't given, rewrite in_file
+    if out_file is None:
+        out_file = in_file
+
+    circle_model: CirclePlus = CirclePlus.from_file(in_file)
+    num_op = circle_model.get_number_of_operators()
+    tparams: TrainParam = TrainParam.from_json(hparams_file, num_op)
+    circle_model.set_train_param(tparams)
+    print("succesfully add hyperparameters to the circle file")
+
+    print_training_hparameters(circle_model)
+
+    circle_model.export(out_file)
+    print(f"saved in {out_file}")
+
+
+if __name__ == "__main__":
+    args = get_cmd_args()
+
+    if args.hyperparameters is None:
+        circle_model = CirclePlus.from_file(args.input)
+        print_training_hparameters(circle_model)
+
+    else:
+        inject_hparams(args.input, args.hyperparameters, args.output)
diff --git a/tools/circle_plus_gen/requirements.txt b/tools/circle_plus_gen/requirements.txt
new file mode 100644 (file)
index 0000000..a5ab82d
--- /dev/null
@@ -0,0 +1 @@
+flatbuffers==24.3.25
diff --git a/tools/circle_plus_gen/schema/__init__.py b/tools/circle_plus_gen/schema/__init__.py
new file mode 100644 (file)
index 0000000..8346615
--- /dev/null
@@ -0,0 +1,5 @@
+# In this directory, *_generated.py is auto generated by flatc.
+#
+# (For devleopers) You could easily update *_generated.py using '_gen.py' in this folder.
+#   $ pip3 install wget
+#   $ python3 _gen.py
diff --git a/tools/circle_plus_gen/schema/_gen.py b/tools/circle_plus_gen/schema/_gen.py
new file mode 100644 (file)
index 0000000..38e5ba0
--- /dev/null
@@ -0,0 +1,89 @@
+'''
+(For developers) generate circle_schema_generated.py and circle_traininfo_generated.py
+
+In short, this script downloads flatc and runs the following commands :
+./flatc --python --gen-onefile --gen-object-api ../../../nnpackage/schema/circle_schema.fbs
+./flatc --python --gen-onefile --gen-object-api ../../../runtime/libs/circle-schema/include/circle_traininfo.fbs
+'''
+
+import wget
+import zipfile
+import os.path
+import stat
+import subprocess
+
+FLATC_V23_5_26 = 'https://github.com/google/flatbuffers/releases/download/v23.5.26/Linux.flatc.binary.g++-10.zip'
+FLATC_ZIP = 'flatc.zip'
+FLATC_EXE = 'flatc'
+
+root_dir = subprocess.run(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE)
+ONE_REPO = root_dir.stdout.decode('utf-8')[:-1]  # remove \n
+CIRCLE_SCHEMA = ONE_REPO + '/nnpackage/schema/circle_schema.fbs'
+TINFO_SCHEMA = ONE_REPO + '/runtime/libs/circle-schema/include/circle_traininfo.fbs'
+
+
+class FlatcCaller:
+    def __call__(self, schema_paths):
+        self.__download_flatc()
+        for schema_path in schema_paths:
+            self.__generate_python_schema(schema_path)
+        self.__clear_flatc()
+
+    def __download_flatc(self):
+        '''Download flatc and unip it in current directory'''
+        wget.download(FLATC_V23_5_26, FLATC_ZIP)
+
+        # unzip 'flatc' in current directory
+        with zipfile.ZipFile(FLATC_ZIP, 'r') as zip:
+            for f in zip.infolist():
+                if f.filename == FLATC_EXE:
+                    zip.extract(f, '.')
+
+        if not os.path.isfile(FLATC_EXE):
+            raise RuntimeError('Failed to download flatc')
+
+        # add permission to execute
+        perm = os.stat(FLATC_EXE)
+        os.chmod(FLATC_EXE, perm.st_mode | stat.S_IXUSR)
+
+    def __generate_python_schema(self, schema_path, out_dir='.'):
+        '''execute flatc to compile *.fbs into python file'''
+        if not os.path.isfile(FLATC_EXE):
+            raise RuntimeError('Failed to find flatc')
+        if not os.stat(FLATC_EXE).st_mode | stat.S_IXUSR:
+            raise RuntimeError('No permission to execute flatc')
+
+        # '--gen-object-api' is necessaary to mutate flatbuffer data
+        cmd = [
+            './' + FLATC_EXE, '--python', '--gen-onefile', '--gen-object-api', '-o',
+            out_dir, schema_path
+        ]
+        try:
+            subprocess.check_call(cmd)
+        except Exception as e:
+            print("failed to compile using flatc", e)
+
+    def __clear_flatc(self):
+        if os.path.exists(FLATC_ZIP):
+            os.remove(FLATC_ZIP)
+        if os.path.exists(FLATC_EXE):
+            os.remove(FLATC_EXE)
+
+
+def add_commit_id():
+    '''Prepend commit id to *_generated.py'''
+    commit_id = subprocess.run(['git', 'rev-parse', 'HEAD'], stdout=subprocess.PIPE)
+    commit_id = commit_id.stdout.decode('utf-8')[:-1]  # remove -\n
+
+    gen_files = os.listdir('./')
+    for gen_file in gen_files:
+        if '_generated.py' in gen_file:
+            with open(gen_file, 'r+') as f:
+                data = f.read()
+                f.seek(0)
+                f.write(f"# generated based on commit({commit_id})\n" + data)
+
+
+run_flatc = FlatcCaller()
+run_flatc([CIRCLE_SCHEMA, TINFO_SCHEMA])
+add_commit_id()
diff --git a/tools/circle_plus_gen/schema/circle_schema_generated.py b/tools/circle_plus_gen/schema/circle_schema_generated.py
new file mode 100644 (file)
index 0000000..528a76b
--- /dev/null
@@ -0,0 +1,19995 @@
+# generated based on commit(b3ff53668e165843d99a108d16ab14bc2cfca669)
+# automatically generated by the FlatBuffers compiler, do not modify
+
+# namespace: circle
+
+import flatbuffers
+from flatbuffers.compat import import_numpy
+np = import_numpy()
+
+
+class TensorType(object):
+    UINT4 = -1
+    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
+    RESOURCE = 13
+    VARIANT = 14
+    UINT32 = 15
+    UINT16 = 16
+    INT4 = 17
+
+
+class QuantizationDetails(object):
+    NONE = 0
+    CustomQuantization = 1
+
+
+def QuantizationDetailsCreator(unionType, table):
+    from flatbuffers.table import Table
+    if not isinstance(table, Table):
+        return None
+    if unionType == QuantizationDetails().CustomQuantization:
+        return CustomQuantizationT.InitFromBuf(table.Bytes, table.Pos)
+    return None
+
+
+class DimensionType(object):
+    DENSE = 0
+    SPARSE_CSR = 1
+
+
+class SparseIndexVector(object):
+    NONE = 0
+    Int32Vector = 1
+    Uint16Vector = 2
+    Uint8Vector = 3
+
+
+def SparseIndexVectorCreator(unionType, table):
+    from flatbuffers.table import Table
+    if not isinstance(table, Table):
+        return None
+    if unionType == SparseIndexVector().Int32Vector:
+        return Int32VectorT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == SparseIndexVector().Uint16Vector:
+        return Uint16VectorT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == SparseIndexVector().Uint8Vector:
+        return Uint8VectorT.InitFromBuf(table.Bytes, table.Pos)
+    return None
+
+
+class BuiltinOperator(object):
+    GRU = -5
+    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
+    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 = 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
+    STABLEHLO_LOGISTIC = 162
+    STABLEHLO_ADD = 163
+    STABLEHLO_DIVIDE = 164
+    STABLEHLO_MULTIPLY = 165
+    STABLEHLO_MAXIMUM = 166
+    STABLEHLO_RESHAPE = 167
+    STABLEHLO_CLAMP = 168
+    STABLEHLO_CONCATENATE = 169
+    STABLEHLO_BROADCAST_IN_DIM = 170
+    STABLEHLO_CONVOLUTION = 171
+    STABLEHLO_SLICE = 172
+    STABLEHLO_CUSTOM_CALL = 173
+    STABLEHLO_REDUCE = 174
+    STABLEHLO_ABS = 175
+    STABLEHLO_AND = 176
+    STABLEHLO_COSINE = 177
+    STABLEHLO_EXPONENTIAL = 178
+    STABLEHLO_FLOOR = 179
+    STABLEHLO_LOG = 180
+    STABLEHLO_MINIMUM = 181
+    STABLEHLO_NEGATE = 182
+    STABLEHLO_OR = 183
+    STABLEHLO_POWER = 184
+    STABLEHLO_REMAINDER = 185
+    STABLEHLO_RSQRT = 186
+    STABLEHLO_SELECT = 187
+    STABLEHLO_SUBTRACT = 188
+    STABLEHLO_TANH = 189
+    STABLEHLO_SCATTER = 190
+    STABLEHLO_COMPARE = 191
+    STABLEHLO_CONVERT = 192
+    STABLEHLO_DYNAMIC_SLICE = 193
+    STABLEHLO_DYNAMIC_UPDATE_SLICE = 194
+    STABLEHLO_PAD = 195
+    STABLEHLO_IOTA = 196
+    STABLEHLO_DOT_GENERAL = 197
+    STABLEHLO_REDUCE_WINDOW = 198
+    STABLEHLO_SORT = 199
+    STABLEHLO_WHILE = 200
+    STABLEHLO_GATHER = 201
+    STABLEHLO_TRANSPOSE = 202
+    DILATE = 203
+    STABLEHLO_RNG_BIT_GENERATOR = 204
+    REDUCE_WINDOW = 205
+
+
+class BuiltinOptions(object):
+    NONE = 0
+    Conv2DOptions = 1
+    DepthwiseConv2DOptions = 2
+    ConcatEmbeddingsOptions = 3
+    LSHProjectionOptions = 4
+    Pool2DOptions = 5
+    SVDFOptions = 6
+    RNNOptions = 7
+    FullyConnectedOptions = 8
+    SoftmaxOptions = 9
+    ConcatenationOptions = 10
+    AddOptions = 11
+    L2NormOptions = 12
+    LocalResponseNormalizationOptions = 13
+    LSTMOptions = 14
+    ResizeBilinearOptions = 15
+    CallOptions = 16
+    ReshapeOptions = 17
+    SkipGramOptions = 18
+    SpaceToDepthOptions = 19
+    EmbeddingLookupSparseOptions = 20
+    MulOptions = 21
+    PadOptions = 22
+    GatherOptions = 23
+    BatchToSpaceNDOptions = 24
+    SpaceToBatchNDOptions = 25
+    TransposeOptions = 26
+    ReducerOptions = 27
+    SubOptions = 28
+    DivOptions = 29
+    SqueezeOptions = 30
+    SequenceRNNOptions = 31
+    StridedSliceOptions = 32
+    ExpOptions = 33
+    TopKV2Options = 34
+    SplitOptions = 35
+    LogSoftmaxOptions = 36
+    CastOptions = 37
+    DequantizeOptions = 38
+    MaximumMinimumOptions = 39
+    ArgMaxOptions = 40
+    LessOptions = 41
+    NegOptions = 42
+    PadV2Options = 43
+    GreaterOptions = 44
+    GreaterEqualOptions = 45
+    LessEqualOptions = 46
+    SelectOptions = 47
+    SliceOptions = 48
+    TransposeConvOptions = 49
+    SparseToDenseOptions = 50
+    TileOptions = 51
+    ExpandDimsOptions = 52
+    EqualOptions = 53
+    NotEqualOptions = 54
+    ShapeOptions = 55
+    PowOptions = 56
+    ArgMinOptions = 57
+    FakeQuantOptions = 58
+    PackOptions = 59
+    LogicalOrOptions = 60
+    OneHotOptions = 61
+    LogicalAndOptions = 62
+    LogicalNotOptions = 63
+    UnpackOptions = 64
+    FloorDivOptions = 65
+    SquareOptions = 66
+    ZerosLikeOptions = 67
+    FillOptions = 68
+    BidirectionalSequenceLSTMOptions = 69
+    BidirectionalSequenceRNNOptions = 70
+    UnidirectionalSequenceLSTMOptions = 71
+    FloorModOptions = 72
+    RangeOptions = 73
+    ResizeNearestNeighborOptions = 74
+    LeakyReluOptions = 75
+    SquaredDifferenceOptions = 76
+    MirrorPadOptions = 77
+    AbsOptions = 78
+    SplitVOptions = 79
+    UniqueOptions = 80
+    ReverseV2Options = 81
+    AddNOptions = 82
+    GatherNdOptions = 83
+    CosOptions = 84
+    WhereOptions = 85
+    RankOptions = 86
+    ReverseSequenceOptions = 87
+    MatrixDiagOptions = 88
+    QuantizeOptions = 89
+    MatrixSetDiagOptions = 90
+    HardSwishOptions = 91
+    IfOptions = 92
+    WhileOptions = 93
+    DepthToSpaceOptions = 94
+    NonMaxSuppressionV4Options = 95
+    NonMaxSuppressionV5Options = 96
+    ScatterNdOptions = 97
+    SelectV2Options = 98
+    DensifyOptions = 99
+    SegmentSumOptions = 100
+    BatchMatMulOptions = 101
+    CumsumOptions = 102
+    CallOnceOptions = 103
+    BroadcastToOptions = 104
+    Rfft2dOptions = 105
+    Conv3DOptions = 106
+    HashtableOptions = 107
+    HashtableFindOptions = 108
+    HashtableImportOptions = 109
+    HashtableSizeOptions = 110
+    VarHandleOptions = 111
+    ReadVariableOptions = 112
+    AssignVariableOptions = 113
+    RandomOptions = 114
+    BucketizeOptions = 115
+    GeluOptions = 116
+    DynamicUpdateSliceOptions = 117
+    UnsortedSegmentProdOptions = 118
+    UnsortedSegmentMaxOptions = 119
+    UnsortedSegmentMinOptions = 120
+    UnsortedSegmentSumOptions = 121
+    ATan2Options = 122
+    SignOptions = 123
+    BitcastOptions = 124
+    BitwiseXorOptions = 125
+    RightShiftOptions = 126
+    GRUOptions = 251
+    BCQGatherOptions = 252
+    BCQFullyConnectedOptions = 253
+    InstanceNormOptions = 254
+
+
+def BuiltinOptionsCreator(unionType, table):
+    from flatbuffers.table import Table
+    if not isinstance(table, Table):
+        return None
+    if unionType == BuiltinOptions().Conv2DOptions:
+        return Conv2DOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().DepthwiseConv2DOptions:
+        return DepthwiseConv2DOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ConcatEmbeddingsOptions:
+        return ConcatEmbeddingsOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().LSHProjectionOptions:
+        return LSHProjectionOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().Pool2DOptions:
+        return Pool2DOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SVDFOptions:
+        return SVDFOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().RNNOptions:
+        return RNNOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().FullyConnectedOptions:
+        return FullyConnectedOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SoftmaxOptions:
+        return SoftmaxOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ConcatenationOptions:
+        return ConcatenationOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().AddOptions:
+        return AddOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().L2NormOptions:
+        return L2NormOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().LocalResponseNormalizationOptions:
+        return LocalResponseNormalizationOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().LSTMOptions:
+        return LSTMOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ResizeBilinearOptions:
+        return ResizeBilinearOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().CallOptions:
+        return CallOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ReshapeOptions:
+        return ReshapeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SkipGramOptions:
+        return SkipGramOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SpaceToDepthOptions:
+        return SpaceToDepthOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().EmbeddingLookupSparseOptions:
+        return EmbeddingLookupSparseOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().MulOptions:
+        return MulOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().PadOptions:
+        return PadOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().GatherOptions:
+        return GatherOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().BatchToSpaceNDOptions:
+        return BatchToSpaceNDOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SpaceToBatchNDOptions:
+        return SpaceToBatchNDOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().TransposeOptions:
+        return TransposeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ReducerOptions:
+        return ReducerOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SubOptions:
+        return SubOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().DivOptions:
+        return DivOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SqueezeOptions:
+        return SqueezeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SequenceRNNOptions:
+        return SequenceRNNOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().StridedSliceOptions:
+        return StridedSliceOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ExpOptions:
+        return ExpOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().TopKV2Options:
+        return TopKV2OptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SplitOptions:
+        return SplitOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().LogSoftmaxOptions:
+        return LogSoftmaxOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().CastOptions:
+        return CastOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().DequantizeOptions:
+        return DequantizeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().MaximumMinimumOptions:
+        return MaximumMinimumOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ArgMaxOptions:
+        return ArgMaxOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().LessOptions:
+        return LessOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().NegOptions:
+        return NegOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().PadV2Options:
+        return PadV2OptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().GreaterOptions:
+        return GreaterOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().GreaterEqualOptions:
+        return GreaterEqualOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().LessEqualOptions:
+        return LessEqualOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SelectOptions:
+        return SelectOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SliceOptions:
+        return SliceOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().TransposeConvOptions:
+        return TransposeConvOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SparseToDenseOptions:
+        return SparseToDenseOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().TileOptions:
+        return TileOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ExpandDimsOptions:
+        return ExpandDimsOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().EqualOptions:
+        return EqualOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().NotEqualOptions:
+        return NotEqualOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ShapeOptions:
+        return ShapeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().PowOptions:
+        return PowOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ArgMinOptions:
+        return ArgMinOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().FakeQuantOptions:
+        return FakeQuantOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().PackOptions:
+        return PackOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().LogicalOrOptions:
+        return LogicalOrOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().OneHotOptions:
+        return OneHotOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().LogicalAndOptions:
+        return LogicalAndOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().LogicalNotOptions:
+        return LogicalNotOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().UnpackOptions:
+        return UnpackOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().FloorDivOptions:
+        return FloorDivOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SquareOptions:
+        return SquareOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ZerosLikeOptions:
+        return ZerosLikeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().FillOptions:
+        return FillOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().BidirectionalSequenceLSTMOptions:
+        return BidirectionalSequenceLSTMOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().BidirectionalSequenceRNNOptions:
+        return BidirectionalSequenceRNNOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().UnidirectionalSequenceLSTMOptions:
+        return UnidirectionalSequenceLSTMOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().FloorModOptions:
+        return FloorModOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().RangeOptions:
+        return RangeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ResizeNearestNeighborOptions:
+        return ResizeNearestNeighborOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().LeakyReluOptions:
+        return LeakyReluOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SquaredDifferenceOptions:
+        return SquaredDifferenceOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().MirrorPadOptions:
+        return MirrorPadOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().AbsOptions:
+        return AbsOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SplitVOptions:
+        return SplitVOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().UniqueOptions:
+        return UniqueOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ReverseV2Options:
+        return ReverseV2OptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().AddNOptions:
+        return AddNOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().GatherNdOptions:
+        return GatherNdOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().CosOptions:
+        return CosOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().WhereOptions:
+        return WhereOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().RankOptions:
+        return RankOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ReverseSequenceOptions:
+        return ReverseSequenceOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().MatrixDiagOptions:
+        return MatrixDiagOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().QuantizeOptions:
+        return QuantizeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().MatrixSetDiagOptions:
+        return MatrixSetDiagOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().HardSwishOptions:
+        return HardSwishOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().IfOptions:
+        return IfOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().WhileOptions:
+        return WhileOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().DepthToSpaceOptions:
+        return DepthToSpaceOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().NonMaxSuppressionV4Options:
+        return NonMaxSuppressionV4OptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().NonMaxSuppressionV5Options:
+        return NonMaxSuppressionV5OptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ScatterNdOptions:
+        return ScatterNdOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SelectV2Options:
+        return SelectV2OptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().DensifyOptions:
+        return DensifyOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SegmentSumOptions:
+        return SegmentSumOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().BatchMatMulOptions:
+        return BatchMatMulOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().CumsumOptions:
+        return CumsumOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().CallOnceOptions:
+        return CallOnceOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().BroadcastToOptions:
+        return BroadcastToOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().Rfft2dOptions:
+        return Rfft2dOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().Conv3DOptions:
+        return Conv3DOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().HashtableOptions:
+        return HashtableOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().HashtableFindOptions:
+        return HashtableFindOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().HashtableImportOptions:
+        return HashtableImportOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().HashtableSizeOptions:
+        return HashtableSizeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().VarHandleOptions:
+        return VarHandleOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ReadVariableOptions:
+        return ReadVariableOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().AssignVariableOptions:
+        return AssignVariableOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().RandomOptions:
+        return RandomOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().BucketizeOptions:
+        return BucketizeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().GeluOptions:
+        return GeluOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().DynamicUpdateSliceOptions:
+        return DynamicUpdateSliceOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().UnsortedSegmentProdOptions:
+        return UnsortedSegmentProdOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().UnsortedSegmentMaxOptions:
+        return UnsortedSegmentMaxOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().UnsortedSegmentMinOptions:
+        return UnsortedSegmentMinOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().UnsortedSegmentSumOptions:
+        return UnsortedSegmentSumOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().ATan2Options:
+        return ATan2OptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().SignOptions:
+        return SignOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().BitcastOptions:
+        return BitcastOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().BitwiseXorOptions:
+        return BitwiseXorOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().RightShiftOptions:
+        return RightShiftOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().GRUOptions:
+        return GRUOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().BCQGatherOptions:
+        return BCQGatherOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().BCQFullyConnectedOptions:
+        return BCQFullyConnectedOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions().InstanceNormOptions:
+        return InstanceNormOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    return None
+
+
+class BuiltinOptions2(object):
+    NONE = 0
+    StablehloConcatenateOptions = 1
+    StablehloBroadcastInDimOptions = 2
+    StablehloSliceOptions = 3
+    StablehloConvolutionOptions = 4
+    StablehloCustomCallOptions = 5
+    StablehloReduceOptions = 6
+    StablehloScatterOptions = 7
+    StablehloCompareOptions = 8
+    StablehloDynamicSliceOptions = 9
+    StablehloPadOptions = 10
+    StablehloIotaOptions = 11
+    StablehloDotGeneralOptions = 12
+    StablehloReduceWindowOptions = 13
+    StablehloSortOptions = 14
+    StablehloWhileOptions = 15
+    StablehloGatherOptions = 16
+    StablehloTransposeOptions = 17
+    DilateOptions = 18
+    StablehloRngBitGeneratorOptions = 19
+    ReduceWindowOptions = 20
+
+
+def BuiltinOptions2Creator(unionType, table):
+    from flatbuffers.table import Table
+    if not isinstance(table, Table):
+        return None
+    if unionType == BuiltinOptions2().StablehloConcatenateOptions:
+        return StablehloConcatenateOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloBroadcastInDimOptions:
+        return StablehloBroadcastInDimOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloSliceOptions:
+        return StablehloSliceOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloConvolutionOptions:
+        return StablehloConvolutionOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloCustomCallOptions:
+        return StablehloCustomCallOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloReduceOptions:
+        return StablehloReduceOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloScatterOptions:
+        return StablehloScatterOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloCompareOptions:
+        return StablehloCompareOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloDynamicSliceOptions:
+        return StablehloDynamicSliceOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloPadOptions:
+        return StablehloPadOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloIotaOptions:
+        return StablehloIotaOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloDotGeneralOptions:
+        return StablehloDotGeneralOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloReduceWindowOptions:
+        return StablehloReduceWindowOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloSortOptions:
+        return StablehloSortOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloWhileOptions:
+        return StablehloWhileOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloGatherOptions:
+        return StablehloGatherOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloTransposeOptions:
+        return StablehloTransposeOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().DilateOptions:
+        return DilateOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().StablehloRngBitGeneratorOptions:
+        return StablehloRngBitGeneratorOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == BuiltinOptions2().ReduceWindowOptions:
+        return ReduceWindowOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    return None
+
+
+class StablehloPrecisionConfig(object):
+    DEFAULT = 0
+    HIGH = 1
+    HIGHEST = 2
+
+
+class StablehloComparisonDirection(object):
+    STABLEHLO_COMPARISON_DIRECTION_EQ = 0
+    STABLEHLO_COMPARISON_DIRECTION_NE = 1
+    STABLEHLO_COMPARISON_DIRECTION_GE = 2
+    STABLEHLO_COMPARISON_DIRECTION_GT = 3
+    STABLEHLO_COMPARISON_DIRECTION_LE = 4
+    STABLEHLO_COMPARISON_DIRECTION_LT = 5
+
+
+class StablehloComparisonType(object):
+    STABLEHLO_COMPARISON_TYPE_NOTYPE = 0
+    STABLEHLO_COMPARISON_TYPE_FLOAT = 1
+    STABLEHLO_COMPARISON_TYPE_FLOAT_TOTAL_ORDER = 2
+    STABLEHLO_COMPARISON_TYPE_SIGNED = 3
+    STABLEHLO_COMPARISON_TYPE_UNSIGNED = 4
+
+
+class RngAlgorithm(object):
+    DEFAULT = 0
+    PHILOX = 1
+    THREEFRY = 2
+
+
+class Padding(object):
+    SAME = 0
+    VALID = 1
+
+
+class ActivationFunctionType(object):
+    NONE = 0
+    RELU = 1
+    RELU_N1_TO_1 = 2
+    RELU6 = 3
+    TANH = 4
+    SIGN_BIT = 5
+
+
+class LSHProjectionType(object):
+    UNKNOWN = 0
+    SPARSE = 1
+    DENSE = 2
+
+
+class FullyConnectedOptionsWeightsFormat(object):
+    DEFAULT = 0
+    SHUFFLED4x16INT8 = 1
+    SHUFFLED16x1FLOAT32 = 127
+
+
+class LSTMKernelType(object):
+    FULL = 0
+    BASIC = 1
+
+
+class CombinerType(object):
+    SUM = 0
+    MEAN = 1
+    SQRTN = 2
+
+
+class MirrorPadMode(object):
+    REFLECT = 0
+    SYMMETRIC = 1
+
+
+class ReduceWindowFunction(object):
+    UNSUPPORTED = 0
+    ADD = 1
+    MUL = 2
+    MINIMUM = 3
+    MAXIMUM = 4
+    ALL = 5
+    ANY = 6
+
+
+class CustomOptionsFormat(object):
+    FLEXBUFFERS = 0
+
+
+class DataFormat(object):
+    CHANNELS_LAST = 0
+    CHANNELS_FIRST = 1
+
+
+class CustomQuantization(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = CustomQuantization()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsCustomQuantization(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def CustomQuantizationBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # CustomQuantization
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # CustomQuantization
+    def Custom(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Uint8Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
+        return 0
+
+    # CustomQuantization
+    def CustomAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o)
+        return 0
+
+    # CustomQuantization
+    def CustomLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # CustomQuantization
+    def CustomIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+
+def CustomQuantizationStart(builder):
+    builder.StartObject(1)
+
+
+def CustomQuantizationAddCustom(builder, custom):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(custom), 0)
+
+
+def CustomQuantizationStartCustomVector(builder, numElems):
+    return builder.StartVector(1, numElems, 1)
+
+
+def CustomQuantizationEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class CustomQuantizationT(object):
+
+    # CustomQuantizationT
+    def __init__(self):
+        self.custom = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        customQuantization = CustomQuantization()
+        customQuantization.Init(buf, pos)
+        return cls.InitFromObj(customQuantization)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, customQuantization):
+        x = CustomQuantizationT()
+        x._UnPack(customQuantization)
+        return x
+
+    # CustomQuantizationT
+    def _UnPack(self, customQuantization):
+        if customQuantization is None:
+            return
+        if not customQuantization.CustomIsNone():
+            if np is None:
+                self.custom = []
+                for i in range(customQuantization.CustomLength()):
+                    self.custom.append(customQuantization.Custom(i))
+            else:
+                self.custom = customQuantization.CustomAsNumpy()
+
+    # CustomQuantizationT
+    def Pack(self, builder):
+        if self.custom is not None:
+            if np is not None and type(self.custom) is np.ndarray:
+                custom = builder.CreateNumpyVector(self.custom)
+            else:
+                CustomQuantizationStartCustomVector(builder, len(self.custom))
+                for i in reversed(range(len(self.custom))):
+                    builder.PrependUint8(self.custom[i])
+                custom = builder.EndVector()
+        CustomQuantizationStart(builder)
+        if self.custom is not None:
+            CustomQuantizationAddCustom(builder, custom)
+        customQuantization = CustomQuantizationEnd(builder)
+        return customQuantization
+
+
+class QuantizationParameters(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = QuantizationParameters()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsQuantizationParameters(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def QuantizationParametersBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # QuantizationParameters
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # QuantizationParameters
+    def Min(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Float32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # QuantizationParameters
+    def MinAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float32Flags, o)
+        return 0
+
+    # QuantizationParameters
+    def MinLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # QuantizationParameters
+    def MinIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # QuantizationParameters
+    def Max(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Float32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # QuantizationParameters
+    def MaxAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float32Flags, o)
+        return 0
+
+    # QuantizationParameters
+    def MaxLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # QuantizationParameters
+    def MaxIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # QuantizationParameters
+    def Scale(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Float32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # QuantizationParameters
+    def ScaleAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float32Flags, o)
+        return 0
+
+    # QuantizationParameters
+    def ScaleLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # QuantizationParameters
+    def ScaleIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+    # QuantizationParameters
+    def ZeroPoint(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # QuantizationParameters
+    def ZeroPointAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # QuantizationParameters
+    def ZeroPointLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # QuantizationParameters
+    def ZeroPointIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        return o == 0
+
+    # QuantizationParameters
+    def DetailsType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos)
+        return 0
+
+    # QuantizationParameters
+    def Details(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            from flatbuffers.table import Table
+            obj = Table(bytearray(), 0)
+            self._tab.Union(obj, o)
+            return obj
+        return None
+
+    # QuantizationParameters
+    def QuantizedDimension(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def QuantizationParametersStart(builder):
+    builder.StartObject(7)
+
+
+def QuantizationParametersAddMin(builder, min):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(min), 0)
+
+
+def QuantizationParametersStartMinVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def QuantizationParametersAddMax(builder, max):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(max), 0)
+
+
+def QuantizationParametersStartMaxVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def QuantizationParametersAddScale(builder, scale):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(scale), 0)
+
+
+def QuantizationParametersStartScaleVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def QuantizationParametersAddZeroPoint(builder, zeroPoint):
+    builder.PrependUOffsetTRelativeSlot(
+        3, flatbuffers.number_types.UOffsetTFlags.py_type(zeroPoint), 0)
+
+
+def QuantizationParametersStartZeroPointVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def QuantizationParametersAddDetailsType(builder, detailsType):
+    builder.PrependUint8Slot(4, detailsType, 0)
+
+
+def QuantizationParametersAddDetails(builder, details):
+    builder.PrependUOffsetTRelativeSlot(
+        5, flatbuffers.number_types.UOffsetTFlags.py_type(details), 0)
+
+
+def QuantizationParametersAddQuantizedDimension(builder, quantizedDimension):
+    builder.PrependInt32Slot(6, quantizedDimension, 0)
+
+
+def QuantizationParametersEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List, Union
+except:
+    pass
+
+
+class QuantizationParametersT(object):
+
+    # QuantizationParametersT
+    def __init__(self):
+        self.min = None  # type: List[float]
+        self.max = None  # type: List[float]
+        self.scale = None  # type: List[float]
+        self.zeroPoint = None  # type: List[int]
+        self.detailsType = 0  # type: int
+        self.details = None  # type: Union[None, CustomQuantizationT]
+        self.quantizedDimension = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        quantizationParameters = QuantizationParameters()
+        quantizationParameters.Init(buf, pos)
+        return cls.InitFromObj(quantizationParameters)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, quantizationParameters):
+        x = QuantizationParametersT()
+        x._UnPack(quantizationParameters)
+        return x
+
+    # QuantizationParametersT
+    def _UnPack(self, quantizationParameters):
+        if quantizationParameters is None:
+            return
+        if not quantizationParameters.MinIsNone():
+            if np is None:
+                self.min = []
+                for i in range(quantizationParameters.MinLength()):
+                    self.min.append(quantizationParameters.Min(i))
+            else:
+                self.min = quantizationParameters.MinAsNumpy()
+        if not quantizationParameters.MaxIsNone():
+            if np is None:
+                self.max = []
+                for i in range(quantizationParameters.MaxLength()):
+                    self.max.append(quantizationParameters.Max(i))
+            else:
+                self.max = quantizationParameters.MaxAsNumpy()
+        if not quantizationParameters.ScaleIsNone():
+            if np is None:
+                self.scale = []
+                for i in range(quantizationParameters.ScaleLength()):
+                    self.scale.append(quantizationParameters.Scale(i))
+            else:
+                self.scale = quantizationParameters.ScaleAsNumpy()
+        if not quantizationParameters.ZeroPointIsNone():
+            if np is None:
+                self.zeroPoint = []
+                for i in range(quantizationParameters.ZeroPointLength()):
+                    self.zeroPoint.append(quantizationParameters.ZeroPoint(i))
+            else:
+                self.zeroPoint = quantizationParameters.ZeroPointAsNumpy()
+        self.detailsType = quantizationParameters.DetailsType()
+        self.details = QuantizationDetailsCreator(self.detailsType,
+                                                  quantizationParameters.Details())
+        self.quantizedDimension = quantizationParameters.QuantizedDimension()
+
+    # QuantizationParametersT
+    def Pack(self, builder):
+        if self.min is not None:
+            if np is not None and type(self.min) is np.ndarray:
+                min = builder.CreateNumpyVector(self.min)
+            else:
+                QuantizationParametersStartMinVector(builder, len(self.min))
+                for i in reversed(range(len(self.min))):
+                    builder.PrependFloat32(self.min[i])
+                min = builder.EndVector()
+        if self.max is not None:
+            if np is not None and type(self.max) is np.ndarray:
+                max = builder.CreateNumpyVector(self.max)
+            else:
+                QuantizationParametersStartMaxVector(builder, len(self.max))
+                for i in reversed(range(len(self.max))):
+                    builder.PrependFloat32(self.max[i])
+                max = builder.EndVector()
+        if self.scale is not None:
+            if np is not None and type(self.scale) is np.ndarray:
+                scale = builder.CreateNumpyVector(self.scale)
+            else:
+                QuantizationParametersStartScaleVector(builder, len(self.scale))
+                for i in reversed(range(len(self.scale))):
+                    builder.PrependFloat32(self.scale[i])
+                scale = builder.EndVector()
+        if self.zeroPoint is not None:
+            if np is not None and type(self.zeroPoint) is np.ndarray:
+                zeroPoint = builder.CreateNumpyVector(self.zeroPoint)
+            else:
+                QuantizationParametersStartZeroPointVector(builder, len(self.zeroPoint))
+                for i in reversed(range(len(self.zeroPoint))):
+                    builder.PrependInt64(self.zeroPoint[i])
+                zeroPoint = builder.EndVector()
+        if self.details is not None:
+            details = self.details.Pack(builder)
+        QuantizationParametersStart(builder)
+        if self.min is not None:
+            QuantizationParametersAddMin(builder, min)
+        if self.max is not None:
+            QuantizationParametersAddMax(builder, max)
+        if self.scale is not None:
+            QuantizationParametersAddScale(builder, scale)
+        if self.zeroPoint is not None:
+            QuantizationParametersAddZeroPoint(builder, zeroPoint)
+        QuantizationParametersAddDetailsType(builder, self.detailsType)
+        if self.details is not None:
+            QuantizationParametersAddDetails(builder, details)
+        QuantizationParametersAddQuantizedDimension(builder, self.quantizedDimension)
+        quantizationParameters = QuantizationParametersEnd(builder)
+        return quantizationParameters
+
+
+class Int32Vector(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Int32Vector()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsInt32Vector(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def Int32VectorBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Int32Vector
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Int32Vector
+    def Values(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # Int32Vector
+    def ValuesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # Int32Vector
+    def ValuesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Int32Vector
+    def ValuesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+
+def Int32VectorStart(builder):
+    builder.StartObject(1)
+
+
+def Int32VectorAddValues(builder, values):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(values), 0)
+
+
+def Int32VectorStartValuesVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def Int32VectorEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class Int32VectorT(object):
+
+    # Int32VectorT
+    def __init__(self):
+        self.values = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        int32Vector = Int32Vector()
+        int32Vector.Init(buf, pos)
+        return cls.InitFromObj(int32Vector)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, int32Vector):
+        x = Int32VectorT()
+        x._UnPack(int32Vector)
+        return x
+
+    # Int32VectorT
+    def _UnPack(self, int32Vector):
+        if int32Vector is None:
+            return
+        if not int32Vector.ValuesIsNone():
+            if np is None:
+                self.values = []
+                for i in range(int32Vector.ValuesLength()):
+                    self.values.append(int32Vector.Values(i))
+            else:
+                self.values = int32Vector.ValuesAsNumpy()
+
+    # Int32VectorT
+    def Pack(self, builder):
+        if self.values is not None:
+            if np is not None and type(self.values) is np.ndarray:
+                values = builder.CreateNumpyVector(self.values)
+            else:
+                Int32VectorStartValuesVector(builder, len(self.values))
+                for i in reversed(range(len(self.values))):
+                    builder.PrependInt32(self.values[i])
+                values = builder.EndVector()
+        Int32VectorStart(builder)
+        if self.values is not None:
+            Int32VectorAddValues(builder, values)
+        int32Vector = Int32VectorEnd(builder)
+        return int32Vector
+
+
+class Uint16Vector(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Uint16Vector()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsUint16Vector(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def Uint16VectorBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Uint16Vector
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Uint16Vector
+    def Values(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Uint16Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 2))
+        return 0
+
+    # Uint16Vector
+    def ValuesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint16Flags, o)
+        return 0
+
+    # Uint16Vector
+    def ValuesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Uint16Vector
+    def ValuesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+
+def Uint16VectorStart(builder):
+    builder.StartObject(1)
+
+
+def Uint16VectorAddValues(builder, values):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(values), 0)
+
+
+def Uint16VectorStartValuesVector(builder, numElems):
+    return builder.StartVector(2, numElems, 2)
+
+
+def Uint16VectorEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class Uint16VectorT(object):
+
+    # Uint16VectorT
+    def __init__(self):
+        self.values = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        uint16Vector = Uint16Vector()
+        uint16Vector.Init(buf, pos)
+        return cls.InitFromObj(uint16Vector)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, uint16Vector):
+        x = Uint16VectorT()
+        x._UnPack(uint16Vector)
+        return x
+
+    # Uint16VectorT
+    def _UnPack(self, uint16Vector):
+        if uint16Vector is None:
+            return
+        if not uint16Vector.ValuesIsNone():
+            if np is None:
+                self.values = []
+                for i in range(uint16Vector.ValuesLength()):
+                    self.values.append(uint16Vector.Values(i))
+            else:
+                self.values = uint16Vector.ValuesAsNumpy()
+
+    # Uint16VectorT
+    def Pack(self, builder):
+        if self.values is not None:
+            if np is not None and type(self.values) is np.ndarray:
+                values = builder.CreateNumpyVector(self.values)
+            else:
+                Uint16VectorStartValuesVector(builder, len(self.values))
+                for i in reversed(range(len(self.values))):
+                    builder.PrependUint16(self.values[i])
+                values = builder.EndVector()
+        Uint16VectorStart(builder)
+        if self.values is not None:
+            Uint16VectorAddValues(builder, values)
+        uint16Vector = Uint16VectorEnd(builder)
+        return uint16Vector
+
+
+class Uint8Vector(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Uint8Vector()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsUint8Vector(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def Uint8VectorBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Uint8Vector
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Uint8Vector
+    def Values(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Uint8Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
+        return 0
+
+    # Uint8Vector
+    def ValuesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o)
+        return 0
+
+    # Uint8Vector
+    def ValuesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Uint8Vector
+    def ValuesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+
+def Uint8VectorStart(builder):
+    builder.StartObject(1)
+
+
+def Uint8VectorAddValues(builder, values):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(values), 0)
+
+
+def Uint8VectorStartValuesVector(builder, numElems):
+    return builder.StartVector(1, numElems, 1)
+
+
+def Uint8VectorEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class Uint8VectorT(object):
+
+    # Uint8VectorT
+    def __init__(self):
+        self.values = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        uint8Vector = Uint8Vector()
+        uint8Vector.Init(buf, pos)
+        return cls.InitFromObj(uint8Vector)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, uint8Vector):
+        x = Uint8VectorT()
+        x._UnPack(uint8Vector)
+        return x
+
+    # Uint8VectorT
+    def _UnPack(self, uint8Vector):
+        if uint8Vector is None:
+            return
+        if not uint8Vector.ValuesIsNone():
+            if np is None:
+                self.values = []
+                for i in range(uint8Vector.ValuesLength()):
+                    self.values.append(uint8Vector.Values(i))
+            else:
+                self.values = uint8Vector.ValuesAsNumpy()
+
+    # Uint8VectorT
+    def Pack(self, builder):
+        if self.values is not None:
+            if np is not None and type(self.values) is np.ndarray:
+                values = builder.CreateNumpyVector(self.values)
+            else:
+                Uint8VectorStartValuesVector(builder, len(self.values))
+                for i in reversed(range(len(self.values))):
+                    builder.PrependUint8(self.values[i])
+                values = builder.EndVector()
+        Uint8VectorStart(builder)
+        if self.values is not None:
+            Uint8VectorAddValues(builder, values)
+        uint8Vector = Uint8VectorEnd(builder)
+        return uint8Vector
+
+
+class DimensionMetadata(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = DimensionMetadata()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsDimensionMetadata(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def DimensionMetadataBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # DimensionMetadata
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # DimensionMetadata
+    def Format(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # DimensionMetadata
+    def DenseSize(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # DimensionMetadata
+    def ArraySegmentsType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos)
+        return 0
+
+    # DimensionMetadata
+    def ArraySegments(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            from flatbuffers.table import Table
+            obj = Table(bytearray(), 0)
+            self._tab.Union(obj, o)
+            return obj
+        return None
+
+    # DimensionMetadata
+    def ArrayIndicesType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos)
+        return 0
+
+    # DimensionMetadata
+    def ArrayIndices(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            from flatbuffers.table import Table
+            obj = Table(bytearray(), 0)
+            self._tab.Union(obj, o)
+            return obj
+        return None
+
+
+def DimensionMetadataStart(builder):
+    builder.StartObject(6)
+
+
+def DimensionMetadataAddFormat(builder, format):
+    builder.PrependInt8Slot(0, format, 0)
+
+
+def DimensionMetadataAddDenseSize(builder, denseSize):
+    builder.PrependInt32Slot(1, denseSize, 0)
+
+
+def DimensionMetadataAddArraySegmentsType(builder, arraySegmentsType):
+    builder.PrependUint8Slot(2, arraySegmentsType, 0)
+
+
+def DimensionMetadataAddArraySegments(builder, arraySegments):
+    builder.PrependUOffsetTRelativeSlot(
+        3, flatbuffers.number_types.UOffsetTFlags.py_type(arraySegments), 0)
+
+
+def DimensionMetadataAddArrayIndicesType(builder, arrayIndicesType):
+    builder.PrependUint8Slot(4, arrayIndicesType, 0)
+
+
+def DimensionMetadataAddArrayIndices(builder, arrayIndices):
+    builder.PrependUOffsetTRelativeSlot(
+        5, flatbuffers.number_types.UOffsetTFlags.py_type(arrayIndices), 0)
+
+
+def DimensionMetadataEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import Union
+except:
+    pass
+
+
+class DimensionMetadataT(object):
+
+    # DimensionMetadataT
+    def __init__(self):
+        self.format = 0  # type: int
+        self.denseSize = 0  # type: int
+        self.arraySegmentsType = 0  # type: int
+        self.arraySegments = None  # type: Union[None, Int32VectorT, Uint16VectorT, Uint8VectorT]
+        self.arrayIndicesType = 0  # type: int
+        self.arrayIndices = None  # type: Union[None, Int32VectorT, Uint16VectorT, Uint8VectorT]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        dimensionMetadata = DimensionMetadata()
+        dimensionMetadata.Init(buf, pos)
+        return cls.InitFromObj(dimensionMetadata)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, dimensionMetadata):
+        x = DimensionMetadataT()
+        x._UnPack(dimensionMetadata)
+        return x
+
+    # DimensionMetadataT
+    def _UnPack(self, dimensionMetadata):
+        if dimensionMetadata is None:
+            return
+        self.format = dimensionMetadata.Format()
+        self.denseSize = dimensionMetadata.DenseSize()
+        self.arraySegmentsType = dimensionMetadata.ArraySegmentsType()
+        self.arraySegments = SparseIndexVectorCreator(self.arraySegmentsType,
+                                                      dimensionMetadata.ArraySegments())
+        self.arrayIndicesType = dimensionMetadata.ArrayIndicesType()
+        self.arrayIndices = SparseIndexVectorCreator(self.arrayIndicesType,
+                                                     dimensionMetadata.ArrayIndices())
+
+    # DimensionMetadataT
+    def Pack(self, builder):
+        if self.arraySegments is not None:
+            arraySegments = self.arraySegments.Pack(builder)
+        if self.arrayIndices is not None:
+            arrayIndices = self.arrayIndices.Pack(builder)
+        DimensionMetadataStart(builder)
+        DimensionMetadataAddFormat(builder, self.format)
+        DimensionMetadataAddDenseSize(builder, self.denseSize)
+        DimensionMetadataAddArraySegmentsType(builder, self.arraySegmentsType)
+        if self.arraySegments is not None:
+            DimensionMetadataAddArraySegments(builder, arraySegments)
+        DimensionMetadataAddArrayIndicesType(builder, self.arrayIndicesType)
+        if self.arrayIndices is not None:
+            DimensionMetadataAddArrayIndices(builder, arrayIndices)
+        dimensionMetadata = DimensionMetadataEnd(builder)
+        return dimensionMetadata
+
+
+class SparsityParameters(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SparsityParameters()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSparsityParameters(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SparsityParametersBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SparsityParameters
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SparsityParameters
+    def TraversalOrder(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # SparsityParameters
+    def TraversalOrderAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # SparsityParameters
+    def TraversalOrderLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # SparsityParameters
+    def TraversalOrderIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # SparsityParameters
+    def BlockMap(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # SparsityParameters
+    def BlockMapAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # SparsityParameters
+    def BlockMapLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # SparsityParameters
+    def BlockMapIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # SparsityParameters
+    def DimMetadata(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = DimensionMetadata()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # SparsityParameters
+    def DimMetadataLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # SparsityParameters
+    def DimMetadataIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+
+def SparsityParametersStart(builder):
+    builder.StartObject(3)
+
+
+def SparsityParametersAddTraversalOrder(builder, traversalOrder):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(traversalOrder), 0)
+
+
+def SparsityParametersStartTraversalOrderVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def SparsityParametersAddBlockMap(builder, blockMap):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(blockMap), 0)
+
+
+def SparsityParametersStartBlockMapVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def SparsityParametersAddDimMetadata(builder, dimMetadata):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(dimMetadata), 0)
+
+
+def SparsityParametersStartDimMetadataVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def SparsityParametersEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class SparsityParametersT(object):
+
+    # SparsityParametersT
+    def __init__(self):
+        self.traversalOrder = None  # type: List[int]
+        self.blockMap = None  # type: List[int]
+        self.dimMetadata = None  # type: List[DimensionMetadataT]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        sparsityParameters = SparsityParameters()
+        sparsityParameters.Init(buf, pos)
+        return cls.InitFromObj(sparsityParameters)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, sparsityParameters):
+        x = SparsityParametersT()
+        x._UnPack(sparsityParameters)
+        return x
+
+    # SparsityParametersT
+    def _UnPack(self, sparsityParameters):
+        if sparsityParameters is None:
+            return
+        if not sparsityParameters.TraversalOrderIsNone():
+            if np is None:
+                self.traversalOrder = []
+                for i in range(sparsityParameters.TraversalOrderLength()):
+                    self.traversalOrder.append(sparsityParameters.TraversalOrder(i))
+            else:
+                self.traversalOrder = sparsityParameters.TraversalOrderAsNumpy()
+        if not sparsityParameters.BlockMapIsNone():
+            if np is None:
+                self.blockMap = []
+                for i in range(sparsityParameters.BlockMapLength()):
+                    self.blockMap.append(sparsityParameters.BlockMap(i))
+            else:
+                self.blockMap = sparsityParameters.BlockMapAsNumpy()
+        if not sparsityParameters.DimMetadataIsNone():
+            self.dimMetadata = []
+            for i in range(sparsityParameters.DimMetadataLength()):
+                if sparsityParameters.DimMetadata(i) is None:
+                    self.dimMetadata.append(None)
+                else:
+                    dimensionMetadata_ = DimensionMetadataT.InitFromObj(
+                        sparsityParameters.DimMetadata(i))
+                    self.dimMetadata.append(dimensionMetadata_)
+
+    # SparsityParametersT
+    def Pack(self, builder):
+        if self.traversalOrder is not None:
+            if np is not None and type(self.traversalOrder) is np.ndarray:
+                traversalOrder = builder.CreateNumpyVector(self.traversalOrder)
+            else:
+                SparsityParametersStartTraversalOrderVector(builder,
+                                                            len(self.traversalOrder))
+                for i in reversed(range(len(self.traversalOrder))):
+                    builder.PrependInt32(self.traversalOrder[i])
+                traversalOrder = builder.EndVector()
+        if self.blockMap is not None:
+            if np is not None and type(self.blockMap) is np.ndarray:
+                blockMap = builder.CreateNumpyVector(self.blockMap)
+            else:
+                SparsityParametersStartBlockMapVector(builder, len(self.blockMap))
+                for i in reversed(range(len(self.blockMap))):
+                    builder.PrependInt32(self.blockMap[i])
+                blockMap = builder.EndVector()
+        if self.dimMetadata is not None:
+            dimMetadatalist = []
+            for i in range(len(self.dimMetadata)):
+                dimMetadatalist.append(self.dimMetadata[i].Pack(builder))
+            SparsityParametersStartDimMetadataVector(builder, len(self.dimMetadata))
+            for i in reversed(range(len(self.dimMetadata))):
+                builder.PrependUOffsetTRelative(dimMetadatalist[i])
+            dimMetadata = builder.EndVector()
+        SparsityParametersStart(builder)
+        if self.traversalOrder is not None:
+            SparsityParametersAddTraversalOrder(builder, traversalOrder)
+        if self.blockMap is not None:
+            SparsityParametersAddBlockMap(builder, blockMap)
+        if self.dimMetadata is not None:
+            SparsityParametersAddDimMetadata(builder, dimMetadata)
+        sparsityParameters = SparsityParametersEnd(builder)
+        return sparsityParameters
+
+
+class VariantSubType(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = VariantSubType()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsVariantSubType(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def VariantSubTypeBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # VariantSubType
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # VariantSubType
+    def Shape(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # VariantSubType
+    def ShapeAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # VariantSubType
+    def ShapeLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # VariantSubType
+    def ShapeIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # VariantSubType
+    def Type(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # VariantSubType
+    def HasRank(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def VariantSubTypeStart(builder):
+    builder.StartObject(3)
+
+
+def VariantSubTypeAddShape(builder, shape):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(shape), 0)
+
+
+def VariantSubTypeStartShapeVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def VariantSubTypeAddType(builder, type):
+    builder.PrependInt8Slot(1, type, 0)
+
+
+def VariantSubTypeAddHasRank(builder, hasRank):
+    builder.PrependBoolSlot(2, hasRank, 0)
+
+
+def VariantSubTypeEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class VariantSubTypeT(object):
+
+    # VariantSubTypeT
+    def __init__(self):
+        self.shape = None  # type: List[int]
+        self.type = 0  # type: int
+        self.hasRank = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        variantSubType = VariantSubType()
+        variantSubType.Init(buf, pos)
+        return cls.InitFromObj(variantSubType)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, variantSubType):
+        x = VariantSubTypeT()
+        x._UnPack(variantSubType)
+        return x
+
+    # VariantSubTypeT
+    def _UnPack(self, variantSubType):
+        if variantSubType is None:
+            return
+        if not variantSubType.ShapeIsNone():
+            if np is None:
+                self.shape = []
+                for i in range(variantSubType.ShapeLength()):
+                    self.shape.append(variantSubType.Shape(i))
+            else:
+                self.shape = variantSubType.ShapeAsNumpy()
+        self.type = variantSubType.Type()
+        self.hasRank = variantSubType.HasRank()
+
+    # VariantSubTypeT
+    def Pack(self, builder):
+        if self.shape is not None:
+            if np is not None and type(self.shape) is np.ndarray:
+                shape = builder.CreateNumpyVector(self.shape)
+            else:
+                VariantSubTypeStartShapeVector(builder, len(self.shape))
+                for i in reversed(range(len(self.shape))):
+                    builder.PrependInt32(self.shape[i])
+                shape = builder.EndVector()
+        VariantSubTypeStart(builder)
+        if self.shape is not None:
+            VariantSubTypeAddShape(builder, shape)
+        VariantSubTypeAddType(builder, self.type)
+        VariantSubTypeAddHasRank(builder, self.hasRank)
+        variantSubType = VariantSubTypeEnd(builder)
+        return variantSubType
+
+
+class Tensor(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Tensor()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsTensor(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def TensorBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Tensor
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Tensor
+    def Shape(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # Tensor
+    def ShapeAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # Tensor
+    def ShapeLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Tensor
+    def ShapeIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # Tensor
+    def Type(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # Tensor
+    def Buffer(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
+        return 0
+
+    # Tensor
+    def Name(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+    # Tensor
+    def Quantization(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            x = self._tab.Indirect(o + self._tab.Pos)
+            obj = QuantizationParameters()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # Tensor
+    def IsVariable(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # Tensor
+    def Sparsity(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            x = self._tab.Indirect(o + self._tab.Pos)
+            obj = SparsityParameters()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # Tensor
+    def ShapeSignature(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # Tensor
+    def ShapeSignatureAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # Tensor
+    def ShapeSignatureLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Tensor
+    def ShapeSignatureIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        return o == 0
+
+    # Tensor
+    def HasRank(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # Tensor
+    def VariantTensors(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = VariantSubType()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # Tensor
+    def VariantTensorsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Tensor
+    def VariantTensorsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
+        return o == 0
+
+
+def TensorStart(builder):
+    builder.StartObject(10)
+
+
+def TensorAddShape(builder, shape):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(shape), 0)
+
+
+def TensorStartShapeVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def TensorAddType(builder, type):
+    builder.PrependInt8Slot(1, type, 0)
+
+
+def TensorAddBuffer(builder, buffer):
+    builder.PrependUint32Slot(2, buffer, 0)
+
+
+def TensorAddName(builder, name):
+    builder.PrependUOffsetTRelativeSlot(
+        3, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
+
+
+def TensorAddQuantization(builder, quantization):
+    builder.PrependUOffsetTRelativeSlot(
+        4, flatbuffers.number_types.UOffsetTFlags.py_type(quantization), 0)
+
+
+def TensorAddIsVariable(builder, isVariable):
+    builder.PrependBoolSlot(5, isVariable, 0)
+
+
+def TensorAddSparsity(builder, sparsity):
+    builder.PrependUOffsetTRelativeSlot(
+        6, flatbuffers.number_types.UOffsetTFlags.py_type(sparsity), 0)
+
+
+def TensorAddShapeSignature(builder, shapeSignature):
+    builder.PrependUOffsetTRelativeSlot(
+        7, flatbuffers.number_types.UOffsetTFlags.py_type(shapeSignature), 0)
+
+
+def TensorStartShapeSignatureVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def TensorAddHasRank(builder, hasRank):
+    builder.PrependBoolSlot(8, hasRank, 0)
+
+
+def TensorAddVariantTensors(builder, variantTensors):
+    builder.PrependUOffsetTRelativeSlot(
+        9, flatbuffers.number_types.UOffsetTFlags.py_type(variantTensors), 0)
+
+
+def TensorStartVariantTensorsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def TensorEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List, Optional
+except:
+    pass
+
+
+class TensorT(object):
+
+    # TensorT
+    def __init__(self):
+        self.shape = None  # type: List[int]
+        self.type = 0  # type: int
+        self.buffer = 0  # type: int
+        self.name = None  # type: str
+        self.quantization = None  # type: Optional[QuantizationParametersT]
+        self.isVariable = False  # type: bool
+        self.sparsity = None  # type: Optional[SparsityParametersT]
+        self.shapeSignature = None  # type: List[int]
+        self.hasRank = False  # type: bool
+        self.variantTensors = None  # type: List[VariantSubTypeT]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        tensor = Tensor()
+        tensor.Init(buf, pos)
+        return cls.InitFromObj(tensor)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, tensor):
+        x = TensorT()
+        x._UnPack(tensor)
+        return x
+
+    # TensorT
+    def _UnPack(self, tensor):
+        if tensor is None:
+            return
+        if not tensor.ShapeIsNone():
+            if np is None:
+                self.shape = []
+                for i in range(tensor.ShapeLength()):
+                    self.shape.append(tensor.Shape(i))
+            else:
+                self.shape = tensor.ShapeAsNumpy()
+        self.type = tensor.Type()
+        self.buffer = tensor.Buffer()
+        self.name = tensor.Name()
+        if tensor.Quantization() is not None:
+            self.quantization = QuantizationParametersT.InitFromObj(tensor.Quantization())
+        self.isVariable = tensor.IsVariable()
+        if tensor.Sparsity() is not None:
+            self.sparsity = SparsityParametersT.InitFromObj(tensor.Sparsity())
+        if not tensor.ShapeSignatureIsNone():
+            if np is None:
+                self.shapeSignature = []
+                for i in range(tensor.ShapeSignatureLength()):
+                    self.shapeSignature.append(tensor.ShapeSignature(i))
+            else:
+                self.shapeSignature = tensor.ShapeSignatureAsNumpy()
+        self.hasRank = tensor.HasRank()
+        if not tensor.VariantTensorsIsNone():
+            self.variantTensors = []
+            for i in range(tensor.VariantTensorsLength()):
+                if tensor.VariantTensors(i) is None:
+                    self.variantTensors.append(None)
+                else:
+                    variantSubType_ = VariantSubTypeT.InitFromObj(
+                        tensor.VariantTensors(i))
+                    self.variantTensors.append(variantSubType_)
+
+    # TensorT
+    def Pack(self, builder):
+        if self.shape is not None:
+            if np is not None and type(self.shape) is np.ndarray:
+                shape = builder.CreateNumpyVector(self.shape)
+            else:
+                TensorStartShapeVector(builder, len(self.shape))
+                for i in reversed(range(len(self.shape))):
+                    builder.PrependInt32(self.shape[i])
+                shape = builder.EndVector()
+        if self.name is not None:
+            name = builder.CreateString(self.name)
+        if self.quantization is not None:
+            quantization = self.quantization.Pack(builder)
+        if self.sparsity is not None:
+            sparsity = self.sparsity.Pack(builder)
+        if self.shapeSignature is not None:
+            if np is not None and type(self.shapeSignature) is np.ndarray:
+                shapeSignature = builder.CreateNumpyVector(self.shapeSignature)
+            else:
+                TensorStartShapeSignatureVector(builder, len(self.shapeSignature))
+                for i in reversed(range(len(self.shapeSignature))):
+                    builder.PrependInt32(self.shapeSignature[i])
+                shapeSignature = builder.EndVector()
+        if self.variantTensors is not None:
+            variantTensorslist = []
+            for i in range(len(self.variantTensors)):
+                variantTensorslist.append(self.variantTensors[i].Pack(builder))
+            TensorStartVariantTensorsVector(builder, len(self.variantTensors))
+            for i in reversed(range(len(self.variantTensors))):
+                builder.PrependUOffsetTRelative(variantTensorslist[i])
+            variantTensors = builder.EndVector()
+        TensorStart(builder)
+        if self.shape is not None:
+            TensorAddShape(builder, shape)
+        TensorAddType(builder, self.type)
+        TensorAddBuffer(builder, self.buffer)
+        if self.name is not None:
+            TensorAddName(builder, name)
+        if self.quantization is not None:
+            TensorAddQuantization(builder, quantization)
+        TensorAddIsVariable(builder, self.isVariable)
+        if self.sparsity is not None:
+            TensorAddSparsity(builder, sparsity)
+        if self.shapeSignature is not None:
+            TensorAddShapeSignature(builder, shapeSignature)
+        TensorAddHasRank(builder, self.hasRank)
+        if self.variantTensors is not None:
+            TensorAddVariantTensors(builder, variantTensors)
+        tensor = TensorEnd(builder)
+        return tensor
+
+
+class StablehloGatherOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloGatherOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloGatherOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloGatherOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloGatherOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloGatherOptions
+    def OffsetDims(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloGatherOptions
+    def OffsetDimsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloGatherOptions
+    def OffsetDimsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloGatherOptions
+    def OffsetDimsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # StablehloGatherOptions
+    def CollapsedSliceDims(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloGatherOptions
+    def CollapsedSliceDimsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloGatherOptions
+    def CollapsedSliceDimsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloGatherOptions
+    def CollapsedSliceDimsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # StablehloGatherOptions
+    def StartIndexMap(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloGatherOptions
+    def StartIndexMapAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloGatherOptions
+    def StartIndexMapLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloGatherOptions
+    def StartIndexMapIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+    # StablehloGatherOptions
+    def IndexVectorDim(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloGatherOptions
+    def SliceSizes(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloGatherOptions
+    def SliceSizesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloGatherOptions
+    def SliceSizesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloGatherOptions
+    def SliceSizesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        return o == 0
+
+    # StablehloGatherOptions
+    def IndicesAreSorted(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def StablehloGatherOptionsStart(builder):
+    builder.StartObject(6)
+
+
+def StablehloGatherOptionsAddOffsetDims(builder, offsetDims):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(offsetDims), 0)
+
+
+def StablehloGatherOptionsStartOffsetDimsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloGatherOptionsAddCollapsedSliceDims(builder, collapsedSliceDims):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(collapsedSliceDims), 0)
+
+
+def StablehloGatherOptionsStartCollapsedSliceDimsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloGatherOptionsAddStartIndexMap(builder, startIndexMap):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(startIndexMap), 0)
+
+
+def StablehloGatherOptionsStartStartIndexMapVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloGatherOptionsAddIndexVectorDim(builder, indexVectorDim):
+    builder.PrependInt64Slot(3, indexVectorDim, 0)
+
+
+def StablehloGatherOptionsAddSliceSizes(builder, sliceSizes):
+    builder.PrependUOffsetTRelativeSlot(
+        4, flatbuffers.number_types.UOffsetTFlags.py_type(sliceSizes), 0)
+
+
+def StablehloGatherOptionsStartSliceSizesVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloGatherOptionsAddIndicesAreSorted(builder, indicesAreSorted):
+    builder.PrependBoolSlot(5, indicesAreSorted, 0)
+
+
+def StablehloGatherOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloGatherOptionsT(object):
+
+    # StablehloGatherOptionsT
+    def __init__(self):
+        self.offsetDims = None  # type: List[int]
+        self.collapsedSliceDims = None  # type: List[int]
+        self.startIndexMap = None  # type: List[int]
+        self.indexVectorDim = 0  # type: int
+        self.sliceSizes = None  # type: List[int]
+        self.indicesAreSorted = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloGatherOptions = StablehloGatherOptions()
+        stablehloGatherOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloGatherOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloGatherOptions):
+        x = StablehloGatherOptionsT()
+        x._UnPack(stablehloGatherOptions)
+        return x
+
+    # StablehloGatherOptionsT
+    def _UnPack(self, stablehloGatherOptions):
+        if stablehloGatherOptions is None:
+            return
+        if not stablehloGatherOptions.OffsetDimsIsNone():
+            if np is None:
+                self.offsetDims = []
+                for i in range(stablehloGatherOptions.OffsetDimsLength()):
+                    self.offsetDims.append(stablehloGatherOptions.OffsetDims(i))
+            else:
+                self.offsetDims = stablehloGatherOptions.OffsetDimsAsNumpy()
+        if not stablehloGatherOptions.CollapsedSliceDimsIsNone():
+            if np is None:
+                self.collapsedSliceDims = []
+                for i in range(stablehloGatherOptions.CollapsedSliceDimsLength()):
+                    self.collapsedSliceDims.append(
+                        stablehloGatherOptions.CollapsedSliceDims(i))
+            else:
+                self.collapsedSliceDims = stablehloGatherOptions.CollapsedSliceDimsAsNumpy(
+                )
+        if not stablehloGatherOptions.StartIndexMapIsNone():
+            if np is None:
+                self.startIndexMap = []
+                for i in range(stablehloGatherOptions.StartIndexMapLength()):
+                    self.startIndexMap.append(stablehloGatherOptions.StartIndexMap(i))
+            else:
+                self.startIndexMap = stablehloGatherOptions.StartIndexMapAsNumpy()
+        self.indexVectorDim = stablehloGatherOptions.IndexVectorDim()
+        if not stablehloGatherOptions.SliceSizesIsNone():
+            if np is None:
+                self.sliceSizes = []
+                for i in range(stablehloGatherOptions.SliceSizesLength()):
+                    self.sliceSizes.append(stablehloGatherOptions.SliceSizes(i))
+            else:
+                self.sliceSizes = stablehloGatherOptions.SliceSizesAsNumpy()
+        self.indicesAreSorted = stablehloGatherOptions.IndicesAreSorted()
+
+    # StablehloGatherOptionsT
+    def Pack(self, builder):
+        if self.offsetDims is not None:
+            if np is not None and type(self.offsetDims) is np.ndarray:
+                offsetDims = builder.CreateNumpyVector(self.offsetDims)
+            else:
+                StablehloGatherOptionsStartOffsetDimsVector(builder, len(self.offsetDims))
+                for i in reversed(range(len(self.offsetDims))):
+                    builder.PrependInt64(self.offsetDims[i])
+                offsetDims = builder.EndVector()
+        if self.collapsedSliceDims is not None:
+            if np is not None and type(self.collapsedSliceDims) is np.ndarray:
+                collapsedSliceDims = builder.CreateNumpyVector(self.collapsedSliceDims)
+            else:
+                StablehloGatherOptionsStartCollapsedSliceDimsVector(
+                    builder, len(self.collapsedSliceDims))
+                for i in reversed(range(len(self.collapsedSliceDims))):
+                    builder.PrependInt64(self.collapsedSliceDims[i])
+                collapsedSliceDims = builder.EndVector()
+        if self.startIndexMap is not None:
+            if np is not None and type(self.startIndexMap) is np.ndarray:
+                startIndexMap = builder.CreateNumpyVector(self.startIndexMap)
+            else:
+                StablehloGatherOptionsStartStartIndexMapVector(builder,
+                                                               len(self.startIndexMap))
+                for i in reversed(range(len(self.startIndexMap))):
+                    builder.PrependInt64(self.startIndexMap[i])
+                startIndexMap = builder.EndVector()
+        if self.sliceSizes is not None:
+            if np is not None and type(self.sliceSizes) is np.ndarray:
+                sliceSizes = builder.CreateNumpyVector(self.sliceSizes)
+            else:
+                StablehloGatherOptionsStartSliceSizesVector(builder, len(self.sliceSizes))
+                for i in reversed(range(len(self.sliceSizes))):
+                    builder.PrependInt64(self.sliceSizes[i])
+                sliceSizes = builder.EndVector()
+        StablehloGatherOptionsStart(builder)
+        if self.offsetDims is not None:
+            StablehloGatherOptionsAddOffsetDims(builder, offsetDims)
+        if self.collapsedSliceDims is not None:
+            StablehloGatherOptionsAddCollapsedSliceDims(builder, collapsedSliceDims)
+        if self.startIndexMap is not None:
+            StablehloGatherOptionsAddStartIndexMap(builder, startIndexMap)
+        StablehloGatherOptionsAddIndexVectorDim(builder, self.indexVectorDim)
+        if self.sliceSizes is not None:
+            StablehloGatherOptionsAddSliceSizes(builder, sliceSizes)
+        StablehloGatherOptionsAddIndicesAreSorted(builder, self.indicesAreSorted)
+        stablehloGatherOptions = StablehloGatherOptionsEnd(builder)
+        return stablehloGatherOptions
+
+
+class StablehloTransposeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloTransposeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloTransposeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloTransposeOptionsBufferHasIdentifier(cls,
+                                                     buf,
+                                                     offset,
+                                                     size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloTransposeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloTransposeOptions
+    def Permutation(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloTransposeOptions
+    def PermutationAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloTransposeOptions
+    def PermutationLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloTransposeOptions
+    def PermutationIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+
+def StablehloTransposeOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def StablehloTransposeOptionsAddPermutation(builder, permutation):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(permutation), 0)
+
+
+def StablehloTransposeOptionsStartPermutationVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloTransposeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloTransposeOptionsT(object):
+
+    # StablehloTransposeOptionsT
+    def __init__(self):
+        self.permutation = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloTransposeOptions = StablehloTransposeOptions()
+        stablehloTransposeOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloTransposeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloTransposeOptions):
+        x = StablehloTransposeOptionsT()
+        x._UnPack(stablehloTransposeOptions)
+        return x
+
+    # StablehloTransposeOptionsT
+    def _UnPack(self, stablehloTransposeOptions):
+        if stablehloTransposeOptions is None:
+            return
+        if not stablehloTransposeOptions.PermutationIsNone():
+            if np is None:
+                self.permutation = []
+                for i in range(stablehloTransposeOptions.PermutationLength()):
+                    self.permutation.append(stablehloTransposeOptions.Permutation(i))
+            else:
+                self.permutation = stablehloTransposeOptions.PermutationAsNumpy()
+
+    # StablehloTransposeOptionsT
+    def Pack(self, builder):
+        if self.permutation is not None:
+            if np is not None and type(self.permutation) is np.ndarray:
+                permutation = builder.CreateNumpyVector(self.permutation)
+            else:
+                StablehloTransposeOptionsStartPermutationVector(
+                    builder, len(self.permutation))
+                for i in reversed(range(len(self.permutation))):
+                    builder.PrependInt64(self.permutation[i])
+                permutation = builder.EndVector()
+        StablehloTransposeOptionsStart(builder)
+        if self.permutation is not None:
+            StablehloTransposeOptionsAddPermutation(builder, permutation)
+        stablehloTransposeOptions = StablehloTransposeOptionsEnd(builder)
+        return stablehloTransposeOptions
+
+
+class StablehloDotGeneralOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloDotGeneralOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloDotGeneralOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloDotGeneralOptionsBufferHasIdentifier(cls,
+                                                      buf,
+                                                      offset,
+                                                      size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloDotGeneralOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloDotGeneralOptions
+    def LhsBatchingDimensions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloDotGeneralOptions
+    def LhsBatchingDimensionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloDotGeneralOptions
+    def LhsBatchingDimensionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloDotGeneralOptions
+    def LhsBatchingDimensionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # StablehloDotGeneralOptions
+    def RhsBatchingDimensions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloDotGeneralOptions
+    def RhsBatchingDimensionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloDotGeneralOptions
+    def RhsBatchingDimensionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloDotGeneralOptions
+    def RhsBatchingDimensionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # StablehloDotGeneralOptions
+    def LhsContractingDimensions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloDotGeneralOptions
+    def LhsContractingDimensionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloDotGeneralOptions
+    def LhsContractingDimensionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloDotGeneralOptions
+    def LhsContractingDimensionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+    # StablehloDotGeneralOptions
+    def RhsContractingDimensions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloDotGeneralOptions
+    def RhsContractingDimensionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloDotGeneralOptions
+    def RhsContractingDimensionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloDotGeneralOptions
+    def RhsContractingDimensionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        return o == 0
+
+    # StablehloDotGeneralOptions
+    def PrecisionConfig(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Uint32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # StablehloDotGeneralOptions
+    def PrecisionConfigAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint32Flags, o)
+        return 0
+
+    # StablehloDotGeneralOptions
+    def PrecisionConfigLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloDotGeneralOptions
+    def PrecisionConfigIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        return o == 0
+
+
+def StablehloDotGeneralOptionsStart(builder):
+    builder.StartObject(5)
+
+
+def StablehloDotGeneralOptionsAddLhsBatchingDimensions(builder, lhsBatchingDimensions):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(lhsBatchingDimensions), 0)
+
+
+def StablehloDotGeneralOptionsStartLhsBatchingDimensionsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloDotGeneralOptionsAddRhsBatchingDimensions(builder, rhsBatchingDimensions):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(rhsBatchingDimensions), 0)
+
+
+def StablehloDotGeneralOptionsStartRhsBatchingDimensionsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloDotGeneralOptionsAddLhsContractingDimensions(builder,
+                                                          lhsContractingDimensions):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(lhsContractingDimensions), 0)
+
+
+def StablehloDotGeneralOptionsStartLhsContractingDimensionsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloDotGeneralOptionsAddRhsContractingDimensions(builder,
+                                                          rhsContractingDimensions):
+    builder.PrependUOffsetTRelativeSlot(
+        3, flatbuffers.number_types.UOffsetTFlags.py_type(rhsContractingDimensions), 0)
+
+
+def StablehloDotGeneralOptionsStartRhsContractingDimensionsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloDotGeneralOptionsAddPrecisionConfig(builder, precisionConfig):
+    builder.PrependUOffsetTRelativeSlot(
+        4, flatbuffers.number_types.UOffsetTFlags.py_type(precisionConfig), 0)
+
+
+def StablehloDotGeneralOptionsStartPrecisionConfigVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def StablehloDotGeneralOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloDotGeneralOptionsT(object):
+
+    # StablehloDotGeneralOptionsT
+    def __init__(self):
+        self.lhsBatchingDimensions = None  # type: List[int]
+        self.rhsBatchingDimensions = None  # type: List[int]
+        self.lhsContractingDimensions = None  # type: List[int]
+        self.rhsContractingDimensions = None  # type: List[int]
+        self.precisionConfig = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloDotGeneralOptions = StablehloDotGeneralOptions()
+        stablehloDotGeneralOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloDotGeneralOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloDotGeneralOptions):
+        x = StablehloDotGeneralOptionsT()
+        x._UnPack(stablehloDotGeneralOptions)
+        return x
+
+    # StablehloDotGeneralOptionsT
+    def _UnPack(self, stablehloDotGeneralOptions):
+        if stablehloDotGeneralOptions is None:
+            return
+        if not stablehloDotGeneralOptions.LhsBatchingDimensionsIsNone():
+            if np is None:
+                self.lhsBatchingDimensions = []
+                for i in range(stablehloDotGeneralOptions.LhsBatchingDimensionsLength()):
+                    self.lhsBatchingDimensions.append(
+                        stablehloDotGeneralOptions.LhsBatchingDimensions(i))
+            else:
+                self.lhsBatchingDimensions = stablehloDotGeneralOptions.LhsBatchingDimensionsAsNumpy(
+                )
+        if not stablehloDotGeneralOptions.RhsBatchingDimensionsIsNone():
+            if np is None:
+                self.rhsBatchingDimensions = []
+                for i in range(stablehloDotGeneralOptions.RhsBatchingDimensionsLength()):
+                    self.rhsBatchingDimensions.append(
+                        stablehloDotGeneralOptions.RhsBatchingDimensions(i))
+            else:
+                self.rhsBatchingDimensions = stablehloDotGeneralOptions.RhsBatchingDimensionsAsNumpy(
+                )
+        if not stablehloDotGeneralOptions.LhsContractingDimensionsIsNone():
+            if np is None:
+                self.lhsContractingDimensions = []
+                for i in range(
+                        stablehloDotGeneralOptions.LhsContractingDimensionsLength()):
+                    self.lhsContractingDimensions.append(
+                        stablehloDotGeneralOptions.LhsContractingDimensions(i))
+            else:
+                self.lhsContractingDimensions = stablehloDotGeneralOptions.LhsContractingDimensionsAsNumpy(
+                )
+        if not stablehloDotGeneralOptions.RhsContractingDimensionsIsNone():
+            if np is None:
+                self.rhsContractingDimensions = []
+                for i in range(
+                        stablehloDotGeneralOptions.RhsContractingDimensionsLength()):
+                    self.rhsContractingDimensions.append(
+                        stablehloDotGeneralOptions.RhsContractingDimensions(i))
+            else:
+                self.rhsContractingDimensions = stablehloDotGeneralOptions.RhsContractingDimensionsAsNumpy(
+                )
+        if not stablehloDotGeneralOptions.PrecisionConfigIsNone():
+            if np is None:
+                self.precisionConfig = []
+                for i in range(stablehloDotGeneralOptions.PrecisionConfigLength()):
+                    self.precisionConfig.append(
+                        stablehloDotGeneralOptions.PrecisionConfig(i))
+            else:
+                self.precisionConfig = stablehloDotGeneralOptions.PrecisionConfigAsNumpy()
+
+    # StablehloDotGeneralOptionsT
+    def Pack(self, builder):
+        if self.lhsBatchingDimensions is not None:
+            if np is not None and type(self.lhsBatchingDimensions) is np.ndarray:
+                lhsBatchingDimensions = builder.CreateNumpyVector(
+                    self.lhsBatchingDimensions)
+            else:
+                StablehloDotGeneralOptionsStartLhsBatchingDimensionsVector(
+                    builder, len(self.lhsBatchingDimensions))
+                for i in reversed(range(len(self.lhsBatchingDimensions))):
+                    builder.PrependInt64(self.lhsBatchingDimensions[i])
+                lhsBatchingDimensions = builder.EndVector()
+        if self.rhsBatchingDimensions is not None:
+            if np is not None and type(self.rhsBatchingDimensions) is np.ndarray:
+                rhsBatchingDimensions = builder.CreateNumpyVector(
+                    self.rhsBatchingDimensions)
+            else:
+                StablehloDotGeneralOptionsStartRhsBatchingDimensionsVector(
+                    builder, len(self.rhsBatchingDimensions))
+                for i in reversed(range(len(self.rhsBatchingDimensions))):
+                    builder.PrependInt64(self.rhsBatchingDimensions[i])
+                rhsBatchingDimensions = builder.EndVector()
+        if self.lhsContractingDimensions is not None:
+            if np is not None and type(self.lhsContractingDimensions) is np.ndarray:
+                lhsContractingDimensions = builder.CreateNumpyVector(
+                    self.lhsContractingDimensions)
+            else:
+                StablehloDotGeneralOptionsStartLhsContractingDimensionsVector(
+                    builder, len(self.lhsContractingDimensions))
+                for i in reversed(range(len(self.lhsContractingDimensions))):
+                    builder.PrependInt64(self.lhsContractingDimensions[i])
+                lhsContractingDimensions = builder.EndVector()
+        if self.rhsContractingDimensions is not None:
+            if np is not None and type(self.rhsContractingDimensions) is np.ndarray:
+                rhsContractingDimensions = builder.CreateNumpyVector(
+                    self.rhsContractingDimensions)
+            else:
+                StablehloDotGeneralOptionsStartRhsContractingDimensionsVector(
+                    builder, len(self.rhsContractingDimensions))
+                for i in reversed(range(len(self.rhsContractingDimensions))):
+                    builder.PrependInt64(self.rhsContractingDimensions[i])
+                rhsContractingDimensions = builder.EndVector()
+        if self.precisionConfig is not None:
+            if np is not None and type(self.precisionConfig) is np.ndarray:
+                precisionConfig = builder.CreateNumpyVector(self.precisionConfig)
+            else:
+                StablehloDotGeneralOptionsStartPrecisionConfigVector(
+                    builder, len(self.precisionConfig))
+                for i in reversed(range(len(self.precisionConfig))):
+                    builder.PrependUint32(self.precisionConfig[i])
+                precisionConfig = builder.EndVector()
+        StablehloDotGeneralOptionsStart(builder)
+        if self.lhsBatchingDimensions is not None:
+            StablehloDotGeneralOptionsAddLhsBatchingDimensions(builder,
+                                                               lhsBatchingDimensions)
+        if self.rhsBatchingDimensions is not None:
+            StablehloDotGeneralOptionsAddRhsBatchingDimensions(builder,
+                                                               rhsBatchingDimensions)
+        if self.lhsContractingDimensions is not None:
+            StablehloDotGeneralOptionsAddLhsContractingDimensions(
+                builder, lhsContractingDimensions)
+        if self.rhsContractingDimensions is not None:
+            StablehloDotGeneralOptionsAddRhsContractingDimensions(
+                builder, rhsContractingDimensions)
+        if self.precisionConfig is not None:
+            StablehloDotGeneralOptionsAddPrecisionConfig(builder, precisionConfig)
+        stablehloDotGeneralOptions = StablehloDotGeneralOptionsEnd(builder)
+        return stablehloDotGeneralOptions
+
+
+class StablehloReduceWindowOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloReduceWindowOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloReduceWindowOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloReduceWindowOptionsBufferHasIdentifier(cls,
+                                                        buf,
+                                                        offset,
+                                                        size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloReduceWindowOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloReduceWindowOptions
+    def WindowDimensions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloReduceWindowOptions
+    def WindowDimensionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloReduceWindowOptions
+    def WindowDimensionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloReduceWindowOptions
+    def WindowDimensionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # StablehloReduceWindowOptions
+    def WindowStrides(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloReduceWindowOptions
+    def WindowStridesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloReduceWindowOptions
+    def WindowStridesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloReduceWindowOptions
+    def WindowStridesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # StablehloReduceWindowOptions
+    def BaseDilations(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloReduceWindowOptions
+    def BaseDilationsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloReduceWindowOptions
+    def BaseDilationsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloReduceWindowOptions
+    def BaseDilationsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+    # StablehloReduceWindowOptions
+    def WindowDilations(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloReduceWindowOptions
+    def WindowDilationsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloReduceWindowOptions
+    def WindowDilationsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloReduceWindowOptions
+    def WindowDilationsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        return o == 0
+
+    # StablehloReduceWindowOptions
+    def Padding(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloReduceWindowOptions
+    def PaddingAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloReduceWindowOptions
+    def PaddingLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloReduceWindowOptions
+    def PaddingIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        return o == 0
+
+    # StablehloReduceWindowOptions
+    def BodySubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def StablehloReduceWindowOptionsStart(builder):
+    builder.StartObject(6)
+
+
+def StablehloReduceWindowOptionsAddWindowDimensions(builder, windowDimensions):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(windowDimensions), 0)
+
+
+def StablehloReduceWindowOptionsStartWindowDimensionsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloReduceWindowOptionsAddWindowStrides(builder, windowStrides):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(windowStrides), 0)
+
+
+def StablehloReduceWindowOptionsStartWindowStridesVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloReduceWindowOptionsAddBaseDilations(builder, baseDilations):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(baseDilations), 0)
+
+
+def StablehloReduceWindowOptionsStartBaseDilationsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloReduceWindowOptionsAddWindowDilations(builder, windowDilations):
+    builder.PrependUOffsetTRelativeSlot(
+        3, flatbuffers.number_types.UOffsetTFlags.py_type(windowDilations), 0)
+
+
+def StablehloReduceWindowOptionsStartWindowDilationsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloReduceWindowOptionsAddPadding(builder, padding):
+    builder.PrependUOffsetTRelativeSlot(
+        4, flatbuffers.number_types.UOffsetTFlags.py_type(padding), 0)
+
+
+def StablehloReduceWindowOptionsStartPaddingVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloReduceWindowOptionsAddBodySubgraphIndex(builder, bodySubgraphIndex):
+    builder.PrependInt32Slot(5, bodySubgraphIndex, 0)
+
+
+def StablehloReduceWindowOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloReduceWindowOptionsT(object):
+
+    # StablehloReduceWindowOptionsT
+    def __init__(self):
+        self.windowDimensions = None  # type: List[int]
+        self.windowStrides = None  # type: List[int]
+        self.baseDilations = None  # type: List[int]
+        self.windowDilations = None  # type: List[int]
+        self.padding = None  # type: List[int]
+        self.bodySubgraphIndex = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloReduceWindowOptions = StablehloReduceWindowOptions()
+        stablehloReduceWindowOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloReduceWindowOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloReduceWindowOptions):
+        x = StablehloReduceWindowOptionsT()
+        x._UnPack(stablehloReduceWindowOptions)
+        return x
+
+    # StablehloReduceWindowOptionsT
+    def _UnPack(self, stablehloReduceWindowOptions):
+        if stablehloReduceWindowOptions is None:
+            return
+        if not stablehloReduceWindowOptions.WindowDimensionsIsNone():
+            if np is None:
+                self.windowDimensions = []
+                for i in range(stablehloReduceWindowOptions.WindowDimensionsLength()):
+                    self.windowDimensions.append(
+                        stablehloReduceWindowOptions.WindowDimensions(i))
+            else:
+                self.windowDimensions = stablehloReduceWindowOptions.WindowDimensionsAsNumpy(
+                )
+        if not stablehloReduceWindowOptions.WindowStridesIsNone():
+            if np is None:
+                self.windowStrides = []
+                for i in range(stablehloReduceWindowOptions.WindowStridesLength()):
+                    self.windowStrides.append(
+                        stablehloReduceWindowOptions.WindowStrides(i))
+            else:
+                self.windowStrides = stablehloReduceWindowOptions.WindowStridesAsNumpy()
+        if not stablehloReduceWindowOptions.BaseDilationsIsNone():
+            if np is None:
+                self.baseDilations = []
+                for i in range(stablehloReduceWindowOptions.BaseDilationsLength()):
+                    self.baseDilations.append(
+                        stablehloReduceWindowOptions.BaseDilations(i))
+            else:
+                self.baseDilations = stablehloReduceWindowOptions.BaseDilationsAsNumpy()
+        if not stablehloReduceWindowOptions.WindowDilationsIsNone():
+            if np is None:
+                self.windowDilations = []
+                for i in range(stablehloReduceWindowOptions.WindowDilationsLength()):
+                    self.windowDilations.append(
+                        stablehloReduceWindowOptions.WindowDilations(i))
+            else:
+                self.windowDilations = stablehloReduceWindowOptions.WindowDilationsAsNumpy(
+                )
+        if not stablehloReduceWindowOptions.PaddingIsNone():
+            if np is None:
+                self.padding = []
+                for i in range(stablehloReduceWindowOptions.PaddingLength()):
+                    self.padding.append(stablehloReduceWindowOptions.Padding(i))
+            else:
+                self.padding = stablehloReduceWindowOptions.PaddingAsNumpy()
+        self.bodySubgraphIndex = stablehloReduceWindowOptions.BodySubgraphIndex()
+
+    # StablehloReduceWindowOptionsT
+    def Pack(self, builder):
+        if self.windowDimensions is not None:
+            if np is not None and type(self.windowDimensions) is np.ndarray:
+                windowDimensions = builder.CreateNumpyVector(self.windowDimensions)
+            else:
+                StablehloReduceWindowOptionsStartWindowDimensionsVector(
+                    builder, len(self.windowDimensions))
+                for i in reversed(range(len(self.windowDimensions))):
+                    builder.PrependInt64(self.windowDimensions[i])
+                windowDimensions = builder.EndVector()
+        if self.windowStrides is not None:
+            if np is not None and type(self.windowStrides) is np.ndarray:
+                windowStrides = builder.CreateNumpyVector(self.windowStrides)
+            else:
+                StablehloReduceWindowOptionsStartWindowStridesVector(
+                    builder, len(self.windowStrides))
+                for i in reversed(range(len(self.windowStrides))):
+                    builder.PrependInt64(self.windowStrides[i])
+                windowStrides = builder.EndVector()
+        if self.baseDilations is not None:
+            if np is not None and type(self.baseDilations) is np.ndarray:
+                baseDilations = builder.CreateNumpyVector(self.baseDilations)
+            else:
+                StablehloReduceWindowOptionsStartBaseDilationsVector(
+                    builder, len(self.baseDilations))
+                for i in reversed(range(len(self.baseDilations))):
+                    builder.PrependInt64(self.baseDilations[i])
+                baseDilations = builder.EndVector()
+        if self.windowDilations is not None:
+            if np is not None and type(self.windowDilations) is np.ndarray:
+                windowDilations = builder.CreateNumpyVector(self.windowDilations)
+            else:
+                StablehloReduceWindowOptionsStartWindowDilationsVector(
+                    builder, len(self.windowDilations))
+                for i in reversed(range(len(self.windowDilations))):
+                    builder.PrependInt64(self.windowDilations[i])
+                windowDilations = builder.EndVector()
+        if self.padding is not None:
+            if np is not None and type(self.padding) is np.ndarray:
+                padding = builder.CreateNumpyVector(self.padding)
+            else:
+                StablehloReduceWindowOptionsStartPaddingVector(builder, len(self.padding))
+                for i in reversed(range(len(self.padding))):
+                    builder.PrependInt64(self.padding[i])
+                padding = builder.EndVector()
+        StablehloReduceWindowOptionsStart(builder)
+        if self.windowDimensions is not None:
+            StablehloReduceWindowOptionsAddWindowDimensions(builder, windowDimensions)
+        if self.windowStrides is not None:
+            StablehloReduceWindowOptionsAddWindowStrides(builder, windowStrides)
+        if self.baseDilations is not None:
+            StablehloReduceWindowOptionsAddBaseDilations(builder, baseDilations)
+        if self.windowDilations is not None:
+            StablehloReduceWindowOptionsAddWindowDilations(builder, windowDilations)
+        if self.padding is not None:
+            StablehloReduceWindowOptionsAddPadding(builder, padding)
+        StablehloReduceWindowOptionsAddBodySubgraphIndex(builder, self.bodySubgraphIndex)
+        stablehloReduceWindowOptions = StablehloReduceWindowOptionsEnd(builder)
+        return stablehloReduceWindowOptions
+
+
+class StablehloWhileOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloWhileOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloWhileOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloWhileOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloWhileOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloWhileOptions
+    def CondSubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloWhileOptions
+    def BodySubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def StablehloWhileOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def StablehloWhileOptionsAddCondSubgraphIndex(builder, condSubgraphIndex):
+    builder.PrependInt32Slot(0, condSubgraphIndex, 0)
+
+
+def StablehloWhileOptionsAddBodySubgraphIndex(builder, bodySubgraphIndex):
+    builder.PrependInt32Slot(1, bodySubgraphIndex, 0)
+
+
+def StablehloWhileOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class StablehloWhileOptionsT(object):
+
+    # StablehloWhileOptionsT
+    def __init__(self):
+        self.condSubgraphIndex = 0  # type: int
+        self.bodySubgraphIndex = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloWhileOptions = StablehloWhileOptions()
+        stablehloWhileOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloWhileOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloWhileOptions):
+        x = StablehloWhileOptionsT()
+        x._UnPack(stablehloWhileOptions)
+        return x
+
+    # StablehloWhileOptionsT
+    def _UnPack(self, stablehloWhileOptions):
+        if stablehloWhileOptions is None:
+            return
+        self.condSubgraphIndex = stablehloWhileOptions.CondSubgraphIndex()
+        self.bodySubgraphIndex = stablehloWhileOptions.BodySubgraphIndex()
+
+    # StablehloWhileOptionsT
+    def Pack(self, builder):
+        StablehloWhileOptionsStart(builder)
+        StablehloWhileOptionsAddCondSubgraphIndex(builder, self.condSubgraphIndex)
+        StablehloWhileOptionsAddBodySubgraphIndex(builder, self.bodySubgraphIndex)
+        stablehloWhileOptions = StablehloWhileOptionsEnd(builder)
+        return stablehloWhileOptions
+
+
+class StablehloSortOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloSortOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloSortOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloSortOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloSortOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloSortOptions
+    def Dimension(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloSortOptions
+    def IsStable(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # StablehloSortOptions
+    def ComparatorSubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def StablehloSortOptionsStart(builder):
+    builder.StartObject(3)
+
+
+def StablehloSortOptionsAddDimension(builder, dimension):
+    builder.PrependInt64Slot(0, dimension, 0)
+
+
+def StablehloSortOptionsAddIsStable(builder, isStable):
+    builder.PrependBoolSlot(1, isStable, 0)
+
+
+def StablehloSortOptionsAddComparatorSubgraphIndex(builder, comparatorSubgraphIndex):
+    builder.PrependInt32Slot(2, comparatorSubgraphIndex, 0)
+
+
+def StablehloSortOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class StablehloSortOptionsT(object):
+
+    # StablehloSortOptionsT
+    def __init__(self):
+        self.dimension = 0  # type: int
+        self.isStable = False  # type: bool
+        self.comparatorSubgraphIndex = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloSortOptions = StablehloSortOptions()
+        stablehloSortOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloSortOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloSortOptions):
+        x = StablehloSortOptionsT()
+        x._UnPack(stablehloSortOptions)
+        return x
+
+    # StablehloSortOptionsT
+    def _UnPack(self, stablehloSortOptions):
+        if stablehloSortOptions is None:
+            return
+        self.dimension = stablehloSortOptions.Dimension()
+        self.isStable = stablehloSortOptions.IsStable()
+        self.comparatorSubgraphIndex = stablehloSortOptions.ComparatorSubgraphIndex()
+
+    # StablehloSortOptionsT
+    def Pack(self, builder):
+        StablehloSortOptionsStart(builder)
+        StablehloSortOptionsAddDimension(builder, self.dimension)
+        StablehloSortOptionsAddIsStable(builder, self.isStable)
+        StablehloSortOptionsAddComparatorSubgraphIndex(builder,
+                                                       self.comparatorSubgraphIndex)
+        stablehloSortOptions = StablehloSortOptionsEnd(builder)
+        return stablehloSortOptions
+
+
+class StablehloConcatenateOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloConcatenateOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloConcatenateOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloConcatenateOptionsBufferHasIdentifier(cls,
+                                                       buf,
+                                                       offset,
+                                                       size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloConcatenateOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloConcatenateOptions
+    def Dimension(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+
+def StablehloConcatenateOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def StablehloConcatenateOptionsAddDimension(builder, dimension):
+    builder.PrependInt64Slot(0, dimension, 0)
+
+
+def StablehloConcatenateOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class StablehloConcatenateOptionsT(object):
+
+    # StablehloConcatenateOptionsT
+    def __init__(self):
+        self.dimension = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloConcatenateOptions = StablehloConcatenateOptions()
+        stablehloConcatenateOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloConcatenateOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloConcatenateOptions):
+        x = StablehloConcatenateOptionsT()
+        x._UnPack(stablehloConcatenateOptions)
+        return x
+
+    # StablehloConcatenateOptionsT
+    def _UnPack(self, stablehloConcatenateOptions):
+        if stablehloConcatenateOptions is None:
+            return
+        self.dimension = stablehloConcatenateOptions.Dimension()
+
+    # StablehloConcatenateOptionsT
+    def Pack(self, builder):
+        StablehloConcatenateOptionsStart(builder)
+        StablehloConcatenateOptionsAddDimension(builder, self.dimension)
+        stablehloConcatenateOptions = StablehloConcatenateOptionsEnd(builder)
+        return stablehloConcatenateOptions
+
+
+class StablehloBroadcastInDimOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloBroadcastInDimOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloBroadcastInDimOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloBroadcastInDimOptionsBufferHasIdentifier(cls,
+                                                          buf,
+                                                          offset,
+                                                          size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloBroadcastInDimOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloBroadcastInDimOptions
+    def BroadcastDimensions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloBroadcastInDimOptions
+    def BroadcastDimensionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloBroadcastInDimOptions
+    def BroadcastDimensionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloBroadcastInDimOptions
+    def BroadcastDimensionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+
+def StablehloBroadcastInDimOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def StablehloBroadcastInDimOptionsAddBroadcastDimensions(builder, broadcastDimensions):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(broadcastDimensions), 0)
+
+
+def StablehloBroadcastInDimOptionsStartBroadcastDimensionsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloBroadcastInDimOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloBroadcastInDimOptionsT(object):
+
+    # StablehloBroadcastInDimOptionsT
+    def __init__(self):
+        self.broadcastDimensions = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloBroadcastInDimOptions = StablehloBroadcastInDimOptions()
+        stablehloBroadcastInDimOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloBroadcastInDimOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloBroadcastInDimOptions):
+        x = StablehloBroadcastInDimOptionsT()
+        x._UnPack(stablehloBroadcastInDimOptions)
+        return x
+
+    # StablehloBroadcastInDimOptionsT
+    def _UnPack(self, stablehloBroadcastInDimOptions):
+        if stablehloBroadcastInDimOptions is None:
+            return
+        if not stablehloBroadcastInDimOptions.BroadcastDimensionsIsNone():
+            if np is None:
+                self.broadcastDimensions = []
+                for i in range(
+                        stablehloBroadcastInDimOptions.BroadcastDimensionsLength()):
+                    self.broadcastDimensions.append(
+                        stablehloBroadcastInDimOptions.BroadcastDimensions(i))
+            else:
+                self.broadcastDimensions = stablehloBroadcastInDimOptions.BroadcastDimensionsAsNumpy(
+                )
+
+    # StablehloBroadcastInDimOptionsT
+    def Pack(self, builder):
+        if self.broadcastDimensions is not None:
+            if np is not None and type(self.broadcastDimensions) is np.ndarray:
+                broadcastDimensions = builder.CreateNumpyVector(self.broadcastDimensions)
+            else:
+                StablehloBroadcastInDimOptionsStartBroadcastDimensionsVector(
+                    builder, len(self.broadcastDimensions))
+                for i in reversed(range(len(self.broadcastDimensions))):
+                    builder.PrependInt64(self.broadcastDimensions[i])
+                broadcastDimensions = builder.EndVector()
+        StablehloBroadcastInDimOptionsStart(builder)
+        if self.broadcastDimensions is not None:
+            StablehloBroadcastInDimOptionsAddBroadcastDimensions(
+                builder, broadcastDimensions)
+        stablehloBroadcastInDimOptions = StablehloBroadcastInDimOptionsEnd(builder)
+        return stablehloBroadcastInDimOptions
+
+
+class StablehloCompareOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloCompareOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloCompareOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloCompareOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloCompareOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloCompareOptions
+    def ComparisonDirection(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloCompareOptions
+    def CompareType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
+        return 0
+
+
+def StablehloCompareOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def StablehloCompareOptionsAddComparisonDirection(builder, comparisonDirection):
+    builder.PrependUint32Slot(0, comparisonDirection, 0)
+
+
+def StablehloCompareOptionsAddCompareType(builder, compareType):
+    builder.PrependUint32Slot(1, compareType, 0)
+
+
+def StablehloCompareOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class StablehloCompareOptionsT(object):
+
+    # StablehloCompareOptionsT
+    def __init__(self):
+        self.comparisonDirection = 0  # type: int
+        self.compareType = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloCompareOptions = StablehloCompareOptions()
+        stablehloCompareOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloCompareOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloCompareOptions):
+        x = StablehloCompareOptionsT()
+        x._UnPack(stablehloCompareOptions)
+        return x
+
+    # StablehloCompareOptionsT
+    def _UnPack(self, stablehloCompareOptions):
+        if stablehloCompareOptions is None:
+            return
+        self.comparisonDirection = stablehloCompareOptions.ComparisonDirection()
+        self.compareType = stablehloCompareOptions.CompareType()
+
+    # StablehloCompareOptionsT
+    def Pack(self, builder):
+        StablehloCompareOptionsStart(builder)
+        StablehloCompareOptionsAddComparisonDirection(builder, self.comparisonDirection)
+        StablehloCompareOptionsAddCompareType(builder, self.compareType)
+        stablehloCompareOptions = StablehloCompareOptionsEnd(builder)
+        return stablehloCompareOptions
+
+
+class StablehloDynamicSliceOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloDynamicSliceOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloDynamicSliceOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloDynamicSliceOptionsBufferHasIdentifier(cls,
+                                                        buf,
+                                                        offset,
+                                                        size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloDynamicSliceOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloDynamicSliceOptions
+    def SliceSizes(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloDynamicSliceOptions
+    def SliceSizesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloDynamicSliceOptions
+    def SliceSizesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloDynamicSliceOptions
+    def SliceSizesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+
+def StablehloDynamicSliceOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def StablehloDynamicSliceOptionsAddSliceSizes(builder, sliceSizes):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(sliceSizes), 0)
+
+
+def StablehloDynamicSliceOptionsStartSliceSizesVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloDynamicSliceOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloDynamicSliceOptionsT(object):
+
+    # StablehloDynamicSliceOptionsT
+    def __init__(self):
+        self.sliceSizes = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloDynamicSliceOptions = StablehloDynamicSliceOptions()
+        stablehloDynamicSliceOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloDynamicSliceOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloDynamicSliceOptions):
+        x = StablehloDynamicSliceOptionsT()
+        x._UnPack(stablehloDynamicSliceOptions)
+        return x
+
+    # StablehloDynamicSliceOptionsT
+    def _UnPack(self, stablehloDynamicSliceOptions):
+        if stablehloDynamicSliceOptions is None:
+            return
+        if not stablehloDynamicSliceOptions.SliceSizesIsNone():
+            if np is None:
+                self.sliceSizes = []
+                for i in range(stablehloDynamicSliceOptions.SliceSizesLength()):
+                    self.sliceSizes.append(stablehloDynamicSliceOptions.SliceSizes(i))
+            else:
+                self.sliceSizes = stablehloDynamicSliceOptions.SliceSizesAsNumpy()
+
+    # StablehloDynamicSliceOptionsT
+    def Pack(self, builder):
+        if self.sliceSizes is not None:
+            if np is not None and type(self.sliceSizes) is np.ndarray:
+                sliceSizes = builder.CreateNumpyVector(self.sliceSizes)
+            else:
+                StablehloDynamicSliceOptionsStartSliceSizesVector(
+                    builder, len(self.sliceSizes))
+                for i in reversed(range(len(self.sliceSizes))):
+                    builder.PrependInt64(self.sliceSizes[i])
+                sliceSizes = builder.EndVector()
+        StablehloDynamicSliceOptionsStart(builder)
+        if self.sliceSizes is not None:
+            StablehloDynamicSliceOptionsAddSliceSizes(builder, sliceSizes)
+        stablehloDynamicSliceOptions = StablehloDynamicSliceOptionsEnd(builder)
+        return stablehloDynamicSliceOptions
+
+
+class StablehloPadOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloPadOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloPadOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloPadOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloPadOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloPadOptions
+    def EdgePaddingLow(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloPadOptions
+    def EdgePaddingLowAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloPadOptions
+    def EdgePaddingLowLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloPadOptions
+    def EdgePaddingLowIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # StablehloPadOptions
+    def EdgePaddingHigh(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloPadOptions
+    def EdgePaddingHighAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloPadOptions
+    def EdgePaddingHighLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloPadOptions
+    def EdgePaddingHighIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # StablehloPadOptions
+    def InteriorPadding(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloPadOptions
+    def InteriorPaddingAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloPadOptions
+    def InteriorPaddingLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloPadOptions
+    def InteriorPaddingIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+
+def StablehloPadOptionsStart(builder):
+    builder.StartObject(3)
+
+
+def StablehloPadOptionsAddEdgePaddingLow(builder, edgePaddingLow):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(edgePaddingLow), 0)
+
+
+def StablehloPadOptionsStartEdgePaddingLowVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloPadOptionsAddEdgePaddingHigh(builder, edgePaddingHigh):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(edgePaddingHigh), 0)
+
+
+def StablehloPadOptionsStartEdgePaddingHighVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloPadOptionsAddInteriorPadding(builder, interiorPadding):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(interiorPadding), 0)
+
+
+def StablehloPadOptionsStartInteriorPaddingVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloPadOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloPadOptionsT(object):
+
+    # StablehloPadOptionsT
+    def __init__(self):
+        self.edgePaddingLow = None  # type: List[int]
+        self.edgePaddingHigh = None  # type: List[int]
+        self.interiorPadding = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloPadOptions = StablehloPadOptions()
+        stablehloPadOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloPadOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloPadOptions):
+        x = StablehloPadOptionsT()
+        x._UnPack(stablehloPadOptions)
+        return x
+
+    # StablehloPadOptionsT
+    def _UnPack(self, stablehloPadOptions):
+        if stablehloPadOptions is None:
+            return
+        if not stablehloPadOptions.EdgePaddingLowIsNone():
+            if np is None:
+                self.edgePaddingLow = []
+                for i in range(stablehloPadOptions.EdgePaddingLowLength()):
+                    self.edgePaddingLow.append(stablehloPadOptions.EdgePaddingLow(i))
+            else:
+                self.edgePaddingLow = stablehloPadOptions.EdgePaddingLowAsNumpy()
+        if not stablehloPadOptions.EdgePaddingHighIsNone():
+            if np is None:
+                self.edgePaddingHigh = []
+                for i in range(stablehloPadOptions.EdgePaddingHighLength()):
+                    self.edgePaddingHigh.append(stablehloPadOptions.EdgePaddingHigh(i))
+            else:
+                self.edgePaddingHigh = stablehloPadOptions.EdgePaddingHighAsNumpy()
+        if not stablehloPadOptions.InteriorPaddingIsNone():
+            if np is None:
+                self.interiorPadding = []
+                for i in range(stablehloPadOptions.InteriorPaddingLength()):
+                    self.interiorPadding.append(stablehloPadOptions.InteriorPadding(i))
+            else:
+                self.interiorPadding = stablehloPadOptions.InteriorPaddingAsNumpy()
+
+    # StablehloPadOptionsT
+    def Pack(self, builder):
+        if self.edgePaddingLow is not None:
+            if np is not None and type(self.edgePaddingLow) is np.ndarray:
+                edgePaddingLow = builder.CreateNumpyVector(self.edgePaddingLow)
+            else:
+                StablehloPadOptionsStartEdgePaddingLowVector(builder,
+                                                             len(self.edgePaddingLow))
+                for i in reversed(range(len(self.edgePaddingLow))):
+                    builder.PrependInt64(self.edgePaddingLow[i])
+                edgePaddingLow = builder.EndVector()
+        if self.edgePaddingHigh is not None:
+            if np is not None and type(self.edgePaddingHigh) is np.ndarray:
+                edgePaddingHigh = builder.CreateNumpyVector(self.edgePaddingHigh)
+            else:
+                StablehloPadOptionsStartEdgePaddingHighVector(builder,
+                                                              len(self.edgePaddingHigh))
+                for i in reversed(range(len(self.edgePaddingHigh))):
+                    builder.PrependInt64(self.edgePaddingHigh[i])
+                edgePaddingHigh = builder.EndVector()
+        if self.interiorPadding is not None:
+            if np is not None and type(self.interiorPadding) is np.ndarray:
+                interiorPadding = builder.CreateNumpyVector(self.interiorPadding)
+            else:
+                StablehloPadOptionsStartInteriorPaddingVector(builder,
+                                                              len(self.interiorPadding))
+                for i in reversed(range(len(self.interiorPadding))):
+                    builder.PrependInt64(self.interiorPadding[i])
+                interiorPadding = builder.EndVector()
+        StablehloPadOptionsStart(builder)
+        if self.edgePaddingLow is not None:
+            StablehloPadOptionsAddEdgePaddingLow(builder, edgePaddingLow)
+        if self.edgePaddingHigh is not None:
+            StablehloPadOptionsAddEdgePaddingHigh(builder, edgePaddingHigh)
+        if self.interiorPadding is not None:
+            StablehloPadOptionsAddInteriorPadding(builder, interiorPadding)
+        stablehloPadOptions = StablehloPadOptionsEnd(builder)
+        return stablehloPadOptions
+
+
+class StablehloIotaOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloIotaOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloIotaOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloIotaOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloIotaOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloIotaOptions
+    def IotaDimension(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+
+def StablehloIotaOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def StablehloIotaOptionsAddIotaDimension(builder, iotaDimension):
+    builder.PrependInt64Slot(0, iotaDimension, 0)
+
+
+def StablehloIotaOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class StablehloIotaOptionsT(object):
+
+    # StablehloIotaOptionsT
+    def __init__(self):
+        self.iotaDimension = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloIotaOptions = StablehloIotaOptions()
+        stablehloIotaOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloIotaOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloIotaOptions):
+        x = StablehloIotaOptionsT()
+        x._UnPack(stablehloIotaOptions)
+        return x
+
+    # StablehloIotaOptionsT
+    def _UnPack(self, stablehloIotaOptions):
+        if stablehloIotaOptions is None:
+            return
+        self.iotaDimension = stablehloIotaOptions.IotaDimension()
+
+    # StablehloIotaOptionsT
+    def Pack(self, builder):
+        StablehloIotaOptionsStart(builder)
+        StablehloIotaOptionsAddIotaDimension(builder, self.iotaDimension)
+        stablehloIotaOptions = StablehloIotaOptionsEnd(builder)
+        return stablehloIotaOptions
+
+
+class StablehloCustomCallOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloCustomCallOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloCustomCallOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloCustomCallOptionsBufferHasIdentifier(cls,
+                                                      buf,
+                                                      offset,
+                                                      size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloCustomCallOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloCustomCallOptions
+    def CallTargetName(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+    # StablehloCustomCallOptions
+    def HasSideEffect(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # StablehloCustomCallOptions
+    def BackendConfig(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+    # StablehloCustomCallOptions
+    def ApiVersion(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloCustomCallOptions
+    def CalledComputations(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # StablehloCustomCallOptions
+    def CalledComputationsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # StablehloCustomCallOptions
+    def CalledComputationsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloCustomCallOptions
+    def CalledComputationsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        return o == 0
+
+    # StablehloCustomCallOptions
+    def CustomAttributes(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Uint8Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
+        return 0
+
+    # StablehloCustomCallOptions
+    def CustomAttributesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o)
+        return 0
+
+    # StablehloCustomCallOptions
+    def CustomAttributesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloCustomCallOptions
+    def CustomAttributesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        return o == 0
+
+
+def StablehloCustomCallOptionsStart(builder):
+    builder.StartObject(6)
+
+
+def StablehloCustomCallOptionsAddCallTargetName(builder, callTargetName):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(callTargetName), 0)
+
+
+def StablehloCustomCallOptionsAddHasSideEffect(builder, hasSideEffect):
+    builder.PrependBoolSlot(1, hasSideEffect, 0)
+
+
+def StablehloCustomCallOptionsAddBackendConfig(builder, backendConfig):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(backendConfig), 0)
+
+
+def StablehloCustomCallOptionsAddApiVersion(builder, apiVersion):
+    builder.PrependInt32Slot(3, apiVersion, 0)
+
+
+def StablehloCustomCallOptionsAddCalledComputations(builder, calledComputations):
+    builder.PrependUOffsetTRelativeSlot(
+        4, flatbuffers.number_types.UOffsetTFlags.py_type(calledComputations), 0)
+
+
+def StablehloCustomCallOptionsStartCalledComputationsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def StablehloCustomCallOptionsAddCustomAttributes(builder, customAttributes):
+    builder.PrependUOffsetTRelativeSlot(
+        5, flatbuffers.number_types.UOffsetTFlags.py_type(customAttributes), 0)
+
+
+def StablehloCustomCallOptionsStartCustomAttributesVector(builder, numElems):
+    return builder.StartVector(1, numElems, 1)
+
+
+def StablehloCustomCallOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloCustomCallOptionsT(object):
+
+    # StablehloCustomCallOptionsT
+    def __init__(self):
+        self.callTargetName = None  # type: str
+        self.hasSideEffect = False  # type: bool
+        self.backendConfig = None  # type: str
+        self.apiVersion = 0  # type: int
+        self.calledComputations = None  # type: List[int]
+        self.customAttributes = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloCustomCallOptions = StablehloCustomCallOptions()
+        stablehloCustomCallOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloCustomCallOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloCustomCallOptions):
+        x = StablehloCustomCallOptionsT()
+        x._UnPack(stablehloCustomCallOptions)
+        return x
+
+    # StablehloCustomCallOptionsT
+    def _UnPack(self, stablehloCustomCallOptions):
+        if stablehloCustomCallOptions is None:
+            return
+        self.callTargetName = stablehloCustomCallOptions.CallTargetName()
+        self.hasSideEffect = stablehloCustomCallOptions.HasSideEffect()
+        self.backendConfig = stablehloCustomCallOptions.BackendConfig()
+        self.apiVersion = stablehloCustomCallOptions.ApiVersion()
+        if not stablehloCustomCallOptions.CalledComputationsIsNone():
+            if np is None:
+                self.calledComputations = []
+                for i in range(stablehloCustomCallOptions.CalledComputationsLength()):
+                    self.calledComputations.append(
+                        stablehloCustomCallOptions.CalledComputations(i))
+            else:
+                self.calledComputations = stablehloCustomCallOptions.CalledComputationsAsNumpy(
+                )
+        if not stablehloCustomCallOptions.CustomAttributesIsNone():
+            if np is None:
+                self.customAttributes = []
+                for i in range(stablehloCustomCallOptions.CustomAttributesLength()):
+                    self.customAttributes.append(
+                        stablehloCustomCallOptions.CustomAttributes(i))
+            else:
+                self.customAttributes = stablehloCustomCallOptions.CustomAttributesAsNumpy(
+                )
+
+    # StablehloCustomCallOptionsT
+    def Pack(self, builder):
+        if self.callTargetName is not None:
+            callTargetName = builder.CreateString(self.callTargetName)
+        if self.backendConfig is not None:
+            backendConfig = builder.CreateString(self.backendConfig)
+        if self.calledComputations is not None:
+            if np is not None and type(self.calledComputations) is np.ndarray:
+                calledComputations = builder.CreateNumpyVector(self.calledComputations)
+            else:
+                StablehloCustomCallOptionsStartCalledComputationsVector(
+                    builder, len(self.calledComputations))
+                for i in reversed(range(len(self.calledComputations))):
+                    builder.PrependInt32(self.calledComputations[i])
+                calledComputations = builder.EndVector()
+        if self.customAttributes is not None:
+            if np is not None and type(self.customAttributes) is np.ndarray:
+                customAttributes = builder.CreateNumpyVector(self.customAttributes)
+            else:
+                StablehloCustomCallOptionsStartCustomAttributesVector(
+                    builder, len(self.customAttributes))
+                for i in reversed(range(len(self.customAttributes))):
+                    builder.PrependUint8(self.customAttributes[i])
+                customAttributes = builder.EndVector()
+        StablehloCustomCallOptionsStart(builder)
+        if self.callTargetName is not None:
+            StablehloCustomCallOptionsAddCallTargetName(builder, callTargetName)
+        StablehloCustomCallOptionsAddHasSideEffect(builder, self.hasSideEffect)
+        if self.backendConfig is not None:
+            StablehloCustomCallOptionsAddBackendConfig(builder, backendConfig)
+        StablehloCustomCallOptionsAddApiVersion(builder, self.apiVersion)
+        if self.calledComputations is not None:
+            StablehloCustomCallOptionsAddCalledComputations(builder, calledComputations)
+        if self.customAttributes is not None:
+            StablehloCustomCallOptionsAddCustomAttributes(builder, customAttributes)
+        stablehloCustomCallOptions = StablehloCustomCallOptionsEnd(builder)
+        return stablehloCustomCallOptions
+
+
+class StablehloReduceOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloReduceOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloReduceOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloReduceOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloReduceOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloReduceOptions
+    def Dimensions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloReduceOptions
+    def DimensionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloReduceOptions
+    def DimensionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloReduceOptions
+    def DimensionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # StablehloReduceOptions
+    def BodySubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def StablehloReduceOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def StablehloReduceOptionsAddDimensions(builder, dimensions):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(dimensions), 0)
+
+
+def StablehloReduceOptionsStartDimensionsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloReduceOptionsAddBodySubgraphIndex(builder, bodySubgraphIndex):
+    builder.PrependInt32Slot(1, bodySubgraphIndex, 0)
+
+
+def StablehloReduceOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloReduceOptionsT(object):
+
+    # StablehloReduceOptionsT
+    def __init__(self):
+        self.dimensions = None  # type: List[int]
+        self.bodySubgraphIndex = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloReduceOptions = StablehloReduceOptions()
+        stablehloReduceOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloReduceOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloReduceOptions):
+        x = StablehloReduceOptionsT()
+        x._UnPack(stablehloReduceOptions)
+        return x
+
+    # StablehloReduceOptionsT
+    def _UnPack(self, stablehloReduceOptions):
+        if stablehloReduceOptions is None:
+            return
+        if not stablehloReduceOptions.DimensionsIsNone():
+            if np is None:
+                self.dimensions = []
+                for i in range(stablehloReduceOptions.DimensionsLength()):
+                    self.dimensions.append(stablehloReduceOptions.Dimensions(i))
+            else:
+                self.dimensions = stablehloReduceOptions.DimensionsAsNumpy()
+        self.bodySubgraphIndex = stablehloReduceOptions.BodySubgraphIndex()
+
+    # StablehloReduceOptionsT
+    def Pack(self, builder):
+        if self.dimensions is not None:
+            if np is not None and type(self.dimensions) is np.ndarray:
+                dimensions = builder.CreateNumpyVector(self.dimensions)
+            else:
+                StablehloReduceOptionsStartDimensionsVector(builder, len(self.dimensions))
+                for i in reversed(range(len(self.dimensions))):
+                    builder.PrependInt64(self.dimensions[i])
+                dimensions = builder.EndVector()
+        StablehloReduceOptionsStart(builder)
+        if self.dimensions is not None:
+            StablehloReduceOptionsAddDimensions(builder, dimensions)
+        StablehloReduceOptionsAddBodySubgraphIndex(builder, self.bodySubgraphIndex)
+        stablehloReduceOptions = StablehloReduceOptionsEnd(builder)
+        return stablehloReduceOptions
+
+
+class StablehloSliceOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloSliceOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloSliceOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloSliceOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloSliceOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloSliceOptions
+    def StartIndices(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloSliceOptions
+    def StartIndicesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloSliceOptions
+    def StartIndicesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloSliceOptions
+    def StartIndicesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # StablehloSliceOptions
+    def LimitIndices(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloSliceOptions
+    def LimitIndicesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloSliceOptions
+    def LimitIndicesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloSliceOptions
+    def LimitIndicesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # StablehloSliceOptions
+    def Strides(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloSliceOptions
+    def StridesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloSliceOptions
+    def StridesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloSliceOptions
+    def StridesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+
+def StablehloSliceOptionsStart(builder):
+    builder.StartObject(3)
+
+
+def StablehloSliceOptionsAddStartIndices(builder, startIndices):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(startIndices), 0)
+
+
+def StablehloSliceOptionsStartStartIndicesVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloSliceOptionsAddLimitIndices(builder, limitIndices):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(limitIndices), 0)
+
+
+def StablehloSliceOptionsStartLimitIndicesVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloSliceOptionsAddStrides(builder, strides):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(strides), 0)
+
+
+def StablehloSliceOptionsStartStridesVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloSliceOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloSliceOptionsT(object):
+
+    # StablehloSliceOptionsT
+    def __init__(self):
+        self.startIndices = None  # type: List[int]
+        self.limitIndices = None  # type: List[int]
+        self.strides = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloSliceOptions = StablehloSliceOptions()
+        stablehloSliceOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloSliceOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloSliceOptions):
+        x = StablehloSliceOptionsT()
+        x._UnPack(stablehloSliceOptions)
+        return x
+
+    # StablehloSliceOptionsT
+    def _UnPack(self, stablehloSliceOptions):
+        if stablehloSliceOptions is None:
+            return
+        if not stablehloSliceOptions.StartIndicesIsNone():
+            if np is None:
+                self.startIndices = []
+                for i in range(stablehloSliceOptions.StartIndicesLength()):
+                    self.startIndices.append(stablehloSliceOptions.StartIndices(i))
+            else:
+                self.startIndices = stablehloSliceOptions.StartIndicesAsNumpy()
+        if not stablehloSliceOptions.LimitIndicesIsNone():
+            if np is None:
+                self.limitIndices = []
+                for i in range(stablehloSliceOptions.LimitIndicesLength()):
+                    self.limitIndices.append(stablehloSliceOptions.LimitIndices(i))
+            else:
+                self.limitIndices = stablehloSliceOptions.LimitIndicesAsNumpy()
+        if not stablehloSliceOptions.StridesIsNone():
+            if np is None:
+                self.strides = []
+                for i in range(stablehloSliceOptions.StridesLength()):
+                    self.strides.append(stablehloSliceOptions.Strides(i))
+            else:
+                self.strides = stablehloSliceOptions.StridesAsNumpy()
+
+    # StablehloSliceOptionsT
+    def Pack(self, builder):
+        if self.startIndices is not None:
+            if np is not None and type(self.startIndices) is np.ndarray:
+                startIndices = builder.CreateNumpyVector(self.startIndices)
+            else:
+                StablehloSliceOptionsStartStartIndicesVector(builder,
+                                                             len(self.startIndices))
+                for i in reversed(range(len(self.startIndices))):
+                    builder.PrependInt64(self.startIndices[i])
+                startIndices = builder.EndVector()
+        if self.limitIndices is not None:
+            if np is not None and type(self.limitIndices) is np.ndarray:
+                limitIndices = builder.CreateNumpyVector(self.limitIndices)
+            else:
+                StablehloSliceOptionsStartLimitIndicesVector(builder,
+                                                             len(self.limitIndices))
+                for i in reversed(range(len(self.limitIndices))):
+                    builder.PrependInt64(self.limitIndices[i])
+                limitIndices = builder.EndVector()
+        if self.strides is not None:
+            if np is not None and type(self.strides) is np.ndarray:
+                strides = builder.CreateNumpyVector(self.strides)
+            else:
+                StablehloSliceOptionsStartStridesVector(builder, len(self.strides))
+                for i in reversed(range(len(self.strides))):
+                    builder.PrependInt64(self.strides[i])
+                strides = builder.EndVector()
+        StablehloSliceOptionsStart(builder)
+        if self.startIndices is not None:
+            StablehloSliceOptionsAddStartIndices(builder, startIndices)
+        if self.limitIndices is not None:
+            StablehloSliceOptionsAddLimitIndices(builder, limitIndices)
+        if self.strides is not None:
+            StablehloSliceOptionsAddStrides(builder, strides)
+        stablehloSliceOptions = StablehloSliceOptionsEnd(builder)
+        return stablehloSliceOptions
+
+
+class StablehloConvolutionOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloConvolutionOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloConvolutionOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloConvolutionOptionsBufferHasIdentifier(cls,
+                                                       buf,
+                                                       offset,
+                                                       size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloConvolutionOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloConvolutionOptions
+    def WindowStrides(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloConvolutionOptions
+    def WindowStridesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def WindowStridesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def WindowStridesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # StablehloConvolutionOptions
+    def Padding(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloConvolutionOptions
+    def PaddingAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def PaddingLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def PaddingIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # StablehloConvolutionOptions
+    def LhsDilation(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloConvolutionOptions
+    def LhsDilationAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def LhsDilationLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def LhsDilationIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+    # StablehloConvolutionOptions
+    def RhsDilation(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloConvolutionOptions
+    def RhsDilationAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def RhsDilationLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def RhsDilationIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        return o == 0
+
+    # StablehloConvolutionOptions
+    def WindowReversal(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.BoolFlags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
+        return 0
+
+    # StablehloConvolutionOptions
+    def WindowReversalAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.BoolFlags, o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def WindowReversalLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def WindowReversalIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        return o == 0
+
+    # StablehloConvolutionOptions
+    def InputBatchDimension(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloConvolutionOptions
+    def InputFeatureDimension(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloConvolutionOptions
+    def InputSpatialDimensions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloConvolutionOptions
+    def InputSpatialDimensionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def InputSpatialDimensionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def InputSpatialDimensionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        return o == 0
+
+    # StablehloConvolutionOptions
+    def KernelInputFeatureDimension(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloConvolutionOptions
+    def KernelOutputFeatureDimension(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloConvolutionOptions
+    def KernelSpatialDimensions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloConvolutionOptions
+    def KernelSpatialDimensionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def KernelSpatialDimensionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def KernelSpatialDimensionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24))
+        return o == 0
+
+    # StablehloConvolutionOptions
+    def OutputBatchDimension(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(26))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloConvolutionOptions
+    def OutputFeatureDimension(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(28))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloConvolutionOptions
+    def OutputSpatialDimensions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(30))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloConvolutionOptions
+    def OutputSpatialDimensionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(30))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def OutputSpatialDimensionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(30))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def OutputSpatialDimensionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(30))
+        return o == 0
+
+    # StablehloConvolutionOptions
+    def FeatureGroupCount(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(32))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloConvolutionOptions
+    def BatchGroupCount(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(34))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloConvolutionOptions
+    def PrecisionConfig(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(36))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Uint32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # StablehloConvolutionOptions
+    def PrecisionConfigAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(36))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint32Flags, o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def PrecisionConfigLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(36))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloConvolutionOptions
+    def PrecisionConfigIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(36))
+        return o == 0
+
+
+def StablehloConvolutionOptionsStart(builder):
+    builder.StartObject(17)
+
+
+def StablehloConvolutionOptionsAddWindowStrides(builder, windowStrides):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(windowStrides), 0)
+
+
+def StablehloConvolutionOptionsStartWindowStridesVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloConvolutionOptionsAddPadding(builder, padding):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(padding), 0)
+
+
+def StablehloConvolutionOptionsStartPaddingVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloConvolutionOptionsAddLhsDilation(builder, lhsDilation):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(lhsDilation), 0)
+
+
+def StablehloConvolutionOptionsStartLhsDilationVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloConvolutionOptionsAddRhsDilation(builder, rhsDilation):
+    builder.PrependUOffsetTRelativeSlot(
+        3, flatbuffers.number_types.UOffsetTFlags.py_type(rhsDilation), 0)
+
+
+def StablehloConvolutionOptionsStartRhsDilationVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloConvolutionOptionsAddWindowReversal(builder, windowReversal):
+    builder.PrependUOffsetTRelativeSlot(
+        4, flatbuffers.number_types.UOffsetTFlags.py_type(windowReversal), 0)
+
+
+def StablehloConvolutionOptionsStartWindowReversalVector(builder, numElems):
+    return builder.StartVector(1, numElems, 1)
+
+
+def StablehloConvolutionOptionsAddInputBatchDimension(builder, inputBatchDimension):
+    builder.PrependInt64Slot(5, inputBatchDimension, 0)
+
+
+def StablehloConvolutionOptionsAddInputFeatureDimension(builder, inputFeatureDimension):
+    builder.PrependInt64Slot(6, inputFeatureDimension, 0)
+
+
+def StablehloConvolutionOptionsAddInputSpatialDimensions(builder, inputSpatialDimensions):
+    builder.PrependUOffsetTRelativeSlot(
+        7, flatbuffers.number_types.UOffsetTFlags.py_type(inputSpatialDimensions), 0)
+
+
+def StablehloConvolutionOptionsStartInputSpatialDimensionsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloConvolutionOptionsAddKernelInputFeatureDimension(
+        builder, kernelInputFeatureDimension):
+    builder.PrependInt64Slot(8, kernelInputFeatureDimension, 0)
+
+
+def StablehloConvolutionOptionsAddKernelOutputFeatureDimension(
+        builder, kernelOutputFeatureDimension):
+    builder.PrependInt64Slot(9, kernelOutputFeatureDimension, 0)
+
+
+def StablehloConvolutionOptionsAddKernelSpatialDimensions(builder,
+                                                          kernelSpatialDimensions):
+    builder.PrependUOffsetTRelativeSlot(
+        10, flatbuffers.number_types.UOffsetTFlags.py_type(kernelSpatialDimensions), 0)
+
+
+def StablehloConvolutionOptionsStartKernelSpatialDimensionsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloConvolutionOptionsAddOutputBatchDimension(builder, outputBatchDimension):
+    builder.PrependInt64Slot(11, outputBatchDimension, 0)
+
+
+def StablehloConvolutionOptionsAddOutputFeatureDimension(builder, outputFeatureDimension):
+    builder.PrependInt64Slot(12, outputFeatureDimension, 0)
+
+
+def StablehloConvolutionOptionsAddOutputSpatialDimensions(builder,
+                                                          outputSpatialDimensions):
+    builder.PrependUOffsetTRelativeSlot(
+        13, flatbuffers.number_types.UOffsetTFlags.py_type(outputSpatialDimensions), 0)
+
+
+def StablehloConvolutionOptionsStartOutputSpatialDimensionsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloConvolutionOptionsAddFeatureGroupCount(builder, featureGroupCount):
+    builder.PrependInt64Slot(14, featureGroupCount, 0)
+
+
+def StablehloConvolutionOptionsAddBatchGroupCount(builder, batchGroupCount):
+    builder.PrependInt64Slot(15, batchGroupCount, 0)
+
+
+def StablehloConvolutionOptionsAddPrecisionConfig(builder, precisionConfig):
+    builder.PrependUOffsetTRelativeSlot(
+        16, flatbuffers.number_types.UOffsetTFlags.py_type(precisionConfig), 0)
+
+
+def StablehloConvolutionOptionsStartPrecisionConfigVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def StablehloConvolutionOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloConvolutionOptionsT(object):
+
+    # StablehloConvolutionOptionsT
+    def __init__(self):
+        self.windowStrides = None  # type: List[int]
+        self.padding = None  # type: List[int]
+        self.lhsDilation = None  # type: List[int]
+        self.rhsDilation = None  # type: List[int]
+        self.windowReversal = None  # type: List[bool]
+        self.inputBatchDimension = 0  # type: int
+        self.inputFeatureDimension = 0  # type: int
+        self.inputSpatialDimensions = None  # type: List[int]
+        self.kernelInputFeatureDimension = 0  # type: int
+        self.kernelOutputFeatureDimension = 0  # type: int
+        self.kernelSpatialDimensions = None  # type: List[int]
+        self.outputBatchDimension = 0  # type: int
+        self.outputFeatureDimension = 0  # type: int
+        self.outputSpatialDimensions = None  # type: List[int]
+        self.featureGroupCount = 0  # type: int
+        self.batchGroupCount = 0  # type: int
+        self.precisionConfig = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloConvolutionOptions = StablehloConvolutionOptions()
+        stablehloConvolutionOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloConvolutionOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloConvolutionOptions):
+        x = StablehloConvolutionOptionsT()
+        x._UnPack(stablehloConvolutionOptions)
+        return x
+
+    # StablehloConvolutionOptionsT
+    def _UnPack(self, stablehloConvolutionOptions):
+        if stablehloConvolutionOptions is None:
+            return
+        if not stablehloConvolutionOptions.WindowStridesIsNone():
+            if np is None:
+                self.windowStrides = []
+                for i in range(stablehloConvolutionOptions.WindowStridesLength()):
+                    self.windowStrides.append(
+                        stablehloConvolutionOptions.WindowStrides(i))
+            else:
+                self.windowStrides = stablehloConvolutionOptions.WindowStridesAsNumpy()
+        if not stablehloConvolutionOptions.PaddingIsNone():
+            if np is None:
+                self.padding = []
+                for i in range(stablehloConvolutionOptions.PaddingLength()):
+                    self.padding.append(stablehloConvolutionOptions.Padding(i))
+            else:
+                self.padding = stablehloConvolutionOptions.PaddingAsNumpy()
+        if not stablehloConvolutionOptions.LhsDilationIsNone():
+            if np is None:
+                self.lhsDilation = []
+                for i in range(stablehloConvolutionOptions.LhsDilationLength()):
+                    self.lhsDilation.append(stablehloConvolutionOptions.LhsDilation(i))
+            else:
+                self.lhsDilation = stablehloConvolutionOptions.LhsDilationAsNumpy()
+        if not stablehloConvolutionOptions.RhsDilationIsNone():
+            if np is None:
+                self.rhsDilation = []
+                for i in range(stablehloConvolutionOptions.RhsDilationLength()):
+                    self.rhsDilation.append(stablehloConvolutionOptions.RhsDilation(i))
+            else:
+                self.rhsDilation = stablehloConvolutionOptions.RhsDilationAsNumpy()
+        if not stablehloConvolutionOptions.WindowReversalIsNone():
+            if np is None:
+                self.windowReversal = []
+                for i in range(stablehloConvolutionOptions.WindowReversalLength()):
+                    self.windowReversal.append(
+                        stablehloConvolutionOptions.WindowReversal(i))
+            else:
+                self.windowReversal = stablehloConvolutionOptions.WindowReversalAsNumpy()
+        self.inputBatchDimension = stablehloConvolutionOptions.InputBatchDimension()
+        self.inputFeatureDimension = stablehloConvolutionOptions.InputFeatureDimension()
+        if not stablehloConvolutionOptions.InputSpatialDimensionsIsNone():
+            if np is None:
+                self.inputSpatialDimensions = []
+                for i in range(
+                        stablehloConvolutionOptions.InputSpatialDimensionsLength()):
+                    self.inputSpatialDimensions.append(
+                        stablehloConvolutionOptions.InputSpatialDimensions(i))
+            else:
+                self.inputSpatialDimensions = stablehloConvolutionOptions.InputSpatialDimensionsAsNumpy(
+                )
+        self.kernelInputFeatureDimension = stablehloConvolutionOptions.KernelInputFeatureDimension(
+        )
+        self.kernelOutputFeatureDimension = stablehloConvolutionOptions.KernelOutputFeatureDimension(
+        )
+        if not stablehloConvolutionOptions.KernelSpatialDimensionsIsNone():
+            if np is None:
+                self.kernelSpatialDimensions = []
+                for i in range(
+                        stablehloConvolutionOptions.KernelSpatialDimensionsLength()):
+                    self.kernelSpatialDimensions.append(
+                        stablehloConvolutionOptions.KernelSpatialDimensions(i))
+            else:
+                self.kernelSpatialDimensions = stablehloConvolutionOptions.KernelSpatialDimensionsAsNumpy(
+                )
+        self.outputBatchDimension = stablehloConvolutionOptions.OutputBatchDimension()
+        self.outputFeatureDimension = stablehloConvolutionOptions.OutputFeatureDimension()
+        if not stablehloConvolutionOptions.OutputSpatialDimensionsIsNone():
+            if np is None:
+                self.outputSpatialDimensions = []
+                for i in range(
+                        stablehloConvolutionOptions.OutputSpatialDimensionsLength()):
+                    self.outputSpatialDimensions.append(
+                        stablehloConvolutionOptions.OutputSpatialDimensions(i))
+            else:
+                self.outputSpatialDimensions = stablehloConvolutionOptions.OutputSpatialDimensionsAsNumpy(
+                )
+        self.featureGroupCount = stablehloConvolutionOptions.FeatureGroupCount()
+        self.batchGroupCount = stablehloConvolutionOptions.BatchGroupCount()
+        if not stablehloConvolutionOptions.PrecisionConfigIsNone():
+            if np is None:
+                self.precisionConfig = []
+                for i in range(stablehloConvolutionOptions.PrecisionConfigLength()):
+                    self.precisionConfig.append(
+                        stablehloConvolutionOptions.PrecisionConfig(i))
+            else:
+                self.precisionConfig = stablehloConvolutionOptions.PrecisionConfigAsNumpy(
+                )
+
+    # StablehloConvolutionOptionsT
+    def Pack(self, builder):
+        if self.windowStrides is not None:
+            if np is not None and type(self.windowStrides) is np.ndarray:
+                windowStrides = builder.CreateNumpyVector(self.windowStrides)
+            else:
+                StablehloConvolutionOptionsStartWindowStridesVector(
+                    builder, len(self.windowStrides))
+                for i in reversed(range(len(self.windowStrides))):
+                    builder.PrependInt64(self.windowStrides[i])
+                windowStrides = builder.EndVector()
+        if self.padding is not None:
+            if np is not None and type(self.padding) is np.ndarray:
+                padding = builder.CreateNumpyVector(self.padding)
+            else:
+                StablehloConvolutionOptionsStartPaddingVector(builder, len(self.padding))
+                for i in reversed(range(len(self.padding))):
+                    builder.PrependInt64(self.padding[i])
+                padding = builder.EndVector()
+        if self.lhsDilation is not None:
+            if np is not None and type(self.lhsDilation) is np.ndarray:
+                lhsDilation = builder.CreateNumpyVector(self.lhsDilation)
+            else:
+                StablehloConvolutionOptionsStartLhsDilationVector(
+                    builder, len(self.lhsDilation))
+                for i in reversed(range(len(self.lhsDilation))):
+                    builder.PrependInt64(self.lhsDilation[i])
+                lhsDilation = builder.EndVector()
+        if self.rhsDilation is not None:
+            if np is not None and type(self.rhsDilation) is np.ndarray:
+                rhsDilation = builder.CreateNumpyVector(self.rhsDilation)
+            else:
+                StablehloConvolutionOptionsStartRhsDilationVector(
+                    builder, len(self.rhsDilation))
+                for i in reversed(range(len(self.rhsDilation))):
+                    builder.PrependInt64(self.rhsDilation[i])
+                rhsDilation = builder.EndVector()
+        if self.windowReversal is not None:
+            if np is not None and type(self.windowReversal) is np.ndarray:
+                windowReversal = builder.CreateNumpyVector(self.windowReversal)
+            else:
+                StablehloConvolutionOptionsStartWindowReversalVector(
+                    builder, len(self.windowReversal))
+                for i in reversed(range(len(self.windowReversal))):
+                    builder.PrependBool(self.windowReversal[i])
+                windowReversal = builder.EndVector()
+        if self.inputSpatialDimensions is not None:
+            if np is not None and type(self.inputSpatialDimensions) is np.ndarray:
+                inputSpatialDimensions = builder.CreateNumpyVector(
+                    self.inputSpatialDimensions)
+            else:
+                StablehloConvolutionOptionsStartInputSpatialDimensionsVector(
+                    builder, len(self.inputSpatialDimensions))
+                for i in reversed(range(len(self.inputSpatialDimensions))):
+                    builder.PrependInt64(self.inputSpatialDimensions[i])
+                inputSpatialDimensions = builder.EndVector()
+        if self.kernelSpatialDimensions is not None:
+            if np is not None and type(self.kernelSpatialDimensions) is np.ndarray:
+                kernelSpatialDimensions = builder.CreateNumpyVector(
+                    self.kernelSpatialDimensions)
+            else:
+                StablehloConvolutionOptionsStartKernelSpatialDimensionsVector(
+                    builder, len(self.kernelSpatialDimensions))
+                for i in reversed(range(len(self.kernelSpatialDimensions))):
+                    builder.PrependInt64(self.kernelSpatialDimensions[i])
+                kernelSpatialDimensions = builder.EndVector()
+        if self.outputSpatialDimensions is not None:
+            if np is not None and type(self.outputSpatialDimensions) is np.ndarray:
+                outputSpatialDimensions = builder.CreateNumpyVector(
+                    self.outputSpatialDimensions)
+            else:
+                StablehloConvolutionOptionsStartOutputSpatialDimensionsVector(
+                    builder, len(self.outputSpatialDimensions))
+                for i in reversed(range(len(self.outputSpatialDimensions))):
+                    builder.PrependInt64(self.outputSpatialDimensions[i])
+                outputSpatialDimensions = builder.EndVector()
+        if self.precisionConfig is not None:
+            if np is not None and type(self.precisionConfig) is np.ndarray:
+                precisionConfig = builder.CreateNumpyVector(self.precisionConfig)
+            else:
+                StablehloConvolutionOptionsStartPrecisionConfigVector(
+                    builder, len(self.precisionConfig))
+                for i in reversed(range(len(self.precisionConfig))):
+                    builder.PrependUint32(self.precisionConfig[i])
+                precisionConfig = builder.EndVector()
+        StablehloConvolutionOptionsStart(builder)
+        if self.windowStrides is not None:
+            StablehloConvolutionOptionsAddWindowStrides(builder, windowStrides)
+        if self.padding is not None:
+            StablehloConvolutionOptionsAddPadding(builder, padding)
+        if self.lhsDilation is not None:
+            StablehloConvolutionOptionsAddLhsDilation(builder, lhsDilation)
+        if self.rhsDilation is not None:
+            StablehloConvolutionOptionsAddRhsDilation(builder, rhsDilation)
+        if self.windowReversal is not None:
+            StablehloConvolutionOptionsAddWindowReversal(builder, windowReversal)
+        StablehloConvolutionOptionsAddInputBatchDimension(builder,
+                                                          self.inputBatchDimension)
+        StablehloConvolutionOptionsAddInputFeatureDimension(builder,
+                                                            self.inputFeatureDimension)
+        if self.inputSpatialDimensions is not None:
+            StablehloConvolutionOptionsAddInputSpatialDimensions(
+                builder, inputSpatialDimensions)
+        StablehloConvolutionOptionsAddKernelInputFeatureDimension(
+            builder, self.kernelInputFeatureDimension)
+        StablehloConvolutionOptionsAddKernelOutputFeatureDimension(
+            builder, self.kernelOutputFeatureDimension)
+        if self.kernelSpatialDimensions is not None:
+            StablehloConvolutionOptionsAddKernelSpatialDimensions(
+                builder, kernelSpatialDimensions)
+        StablehloConvolutionOptionsAddOutputBatchDimension(builder,
+                                                           self.outputBatchDimension)
+        StablehloConvolutionOptionsAddOutputFeatureDimension(builder,
+                                                             self.outputFeatureDimension)
+        if self.outputSpatialDimensions is not None:
+            StablehloConvolutionOptionsAddOutputSpatialDimensions(
+                builder, outputSpatialDimensions)
+        StablehloConvolutionOptionsAddFeatureGroupCount(builder, self.featureGroupCount)
+        StablehloConvolutionOptionsAddBatchGroupCount(builder, self.batchGroupCount)
+        if self.precisionConfig is not None:
+            StablehloConvolutionOptionsAddPrecisionConfig(builder, precisionConfig)
+        stablehloConvolutionOptions = StablehloConvolutionOptionsEnd(builder)
+        return stablehloConvolutionOptions
+
+
+class StablehloScatterOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloScatterOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloScatterOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloScatterOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloScatterOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloScatterOptions
+    def IndicesAreSorted(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # StablehloScatterOptions
+    def UpdateWindowDims(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloScatterOptions
+    def UpdateWindowDimsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloScatterOptions
+    def UpdateWindowDimsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloScatterOptions
+    def UpdateWindowDimsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # StablehloScatterOptions
+    def InsertedWindowDims(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloScatterOptions
+    def InsertedWindowDimsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloScatterOptions
+    def InsertedWindowDimsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloScatterOptions
+    def InsertedWindowDimsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+    # StablehloScatterOptions
+    def ScatterDimsToOperandDims(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int64Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 8))
+        return 0
+
+    # StablehloScatterOptions
+    def ScatterDimsToOperandDimsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int64Flags, o)
+        return 0
+
+    # StablehloScatterOptions
+    def ScatterDimsToOperandDimsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # StablehloScatterOptions
+    def ScatterDimsToOperandDimsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        return o == 0
+
+    # StablehloScatterOptions
+    def IndexVectorDim(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # StablehloScatterOptions
+    def UniqueIndices(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # StablehloScatterOptions
+    def UpdateComputationSubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def StablehloScatterOptionsStart(builder):
+    builder.StartObject(7)
+
+
+def StablehloScatterOptionsAddIndicesAreSorted(builder, indicesAreSorted):
+    builder.PrependBoolSlot(0, indicesAreSorted, 0)
+
+
+def StablehloScatterOptionsAddUpdateWindowDims(builder, updateWindowDims):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(updateWindowDims), 0)
+
+
+def StablehloScatterOptionsStartUpdateWindowDimsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloScatterOptionsAddInsertedWindowDims(builder, insertedWindowDims):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(insertedWindowDims), 0)
+
+
+def StablehloScatterOptionsStartInsertedWindowDimsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloScatterOptionsAddScatterDimsToOperandDims(builder, scatterDimsToOperandDims):
+    builder.PrependUOffsetTRelativeSlot(
+        3, flatbuffers.number_types.UOffsetTFlags.py_type(scatterDimsToOperandDims), 0)
+
+
+def StablehloScatterOptionsStartScatterDimsToOperandDimsVector(builder, numElems):
+    return builder.StartVector(8, numElems, 8)
+
+
+def StablehloScatterOptionsAddIndexVectorDim(builder, indexVectorDim):
+    builder.PrependInt64Slot(4, indexVectorDim, 0)
+
+
+def StablehloScatterOptionsAddUniqueIndices(builder, uniqueIndices):
+    builder.PrependBoolSlot(5, uniqueIndices, 0)
+
+
+def StablehloScatterOptionsAddUpdateComputationSubgraphIndex(
+        builder, updateComputationSubgraphIndex):
+    builder.PrependInt32Slot(6, updateComputationSubgraphIndex, 0)
+
+
+def StablehloScatterOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class StablehloScatterOptionsT(object):
+
+    # StablehloScatterOptionsT
+    def __init__(self):
+        self.indicesAreSorted = False  # type: bool
+        self.updateWindowDims = None  # type: List[int]
+        self.insertedWindowDims = None  # type: List[int]
+        self.scatterDimsToOperandDims = None  # type: List[int]
+        self.indexVectorDim = 0  # type: int
+        self.uniqueIndices = False  # type: bool
+        self.updateComputationSubgraphIndex = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloScatterOptions = StablehloScatterOptions()
+        stablehloScatterOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloScatterOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloScatterOptions):
+        x = StablehloScatterOptionsT()
+        x._UnPack(stablehloScatterOptions)
+        return x
+
+    # StablehloScatterOptionsT
+    def _UnPack(self, stablehloScatterOptions):
+        if stablehloScatterOptions is None:
+            return
+        self.indicesAreSorted = stablehloScatterOptions.IndicesAreSorted()
+        if not stablehloScatterOptions.UpdateWindowDimsIsNone():
+            if np is None:
+                self.updateWindowDims = []
+                for i in range(stablehloScatterOptions.UpdateWindowDimsLength()):
+                    self.updateWindowDims.append(
+                        stablehloScatterOptions.UpdateWindowDims(i))
+            else:
+                self.updateWindowDims = stablehloScatterOptions.UpdateWindowDimsAsNumpy()
+        if not stablehloScatterOptions.InsertedWindowDimsIsNone():
+            if np is None:
+                self.insertedWindowDims = []
+                for i in range(stablehloScatterOptions.InsertedWindowDimsLength()):
+                    self.insertedWindowDims.append(
+                        stablehloScatterOptions.InsertedWindowDims(i))
+            else:
+                self.insertedWindowDims = stablehloScatterOptions.InsertedWindowDimsAsNumpy(
+                )
+        if not stablehloScatterOptions.ScatterDimsToOperandDimsIsNone():
+            if np is None:
+                self.scatterDimsToOperandDims = []
+                for i in range(stablehloScatterOptions.ScatterDimsToOperandDimsLength()):
+                    self.scatterDimsToOperandDims.append(
+                        stablehloScatterOptions.ScatterDimsToOperandDims(i))
+            else:
+                self.scatterDimsToOperandDims = stablehloScatterOptions.ScatterDimsToOperandDimsAsNumpy(
+                )
+        self.indexVectorDim = stablehloScatterOptions.IndexVectorDim()
+        self.uniqueIndices = stablehloScatterOptions.UniqueIndices()
+        self.updateComputationSubgraphIndex = stablehloScatterOptions.UpdateComputationSubgraphIndex(
+        )
+
+    # StablehloScatterOptionsT
+    def Pack(self, builder):
+        if self.updateWindowDims is not None:
+            if np is not None and type(self.updateWindowDims) is np.ndarray:
+                updateWindowDims = builder.CreateNumpyVector(self.updateWindowDims)
+            else:
+                StablehloScatterOptionsStartUpdateWindowDimsVector(
+                    builder, len(self.updateWindowDims))
+                for i in reversed(range(len(self.updateWindowDims))):
+                    builder.PrependInt64(self.updateWindowDims[i])
+                updateWindowDims = builder.EndVector()
+        if self.insertedWindowDims is not None:
+            if np is not None and type(self.insertedWindowDims) is np.ndarray:
+                insertedWindowDims = builder.CreateNumpyVector(self.insertedWindowDims)
+            else:
+                StablehloScatterOptionsStartInsertedWindowDimsVector(
+                    builder, len(self.insertedWindowDims))
+                for i in reversed(range(len(self.insertedWindowDims))):
+                    builder.PrependInt64(self.insertedWindowDims[i])
+                insertedWindowDims = builder.EndVector()
+        if self.scatterDimsToOperandDims is not None:
+            if np is not None and type(self.scatterDimsToOperandDims) is np.ndarray:
+                scatterDimsToOperandDims = builder.CreateNumpyVector(
+                    self.scatterDimsToOperandDims)
+            else:
+                StablehloScatterOptionsStartScatterDimsToOperandDimsVector(
+                    builder, len(self.scatterDimsToOperandDims))
+                for i in reversed(range(len(self.scatterDimsToOperandDims))):
+                    builder.PrependInt64(self.scatterDimsToOperandDims[i])
+                scatterDimsToOperandDims = builder.EndVector()
+        StablehloScatterOptionsStart(builder)
+        StablehloScatterOptionsAddIndicesAreSorted(builder, self.indicesAreSorted)
+        if self.updateWindowDims is not None:
+            StablehloScatterOptionsAddUpdateWindowDims(builder, updateWindowDims)
+        if self.insertedWindowDims is not None:
+            StablehloScatterOptionsAddInsertedWindowDims(builder, insertedWindowDims)
+        if self.scatterDimsToOperandDims is not None:
+            StablehloScatterOptionsAddScatterDimsToOperandDims(builder,
+                                                               scatterDimsToOperandDims)
+        StablehloScatterOptionsAddIndexVectorDim(builder, self.indexVectorDim)
+        StablehloScatterOptionsAddUniqueIndices(builder, self.uniqueIndices)
+        StablehloScatterOptionsAddUpdateComputationSubgraphIndex(
+            builder, self.updateComputationSubgraphIndex)
+        stablehloScatterOptions = StablehloScatterOptionsEnd(builder)
+        return stablehloScatterOptions
+
+
+class StablehloRngBitGeneratorOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StablehloRngBitGeneratorOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStablehloRngBitGeneratorOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StablehloRngBitGeneratorOptionsBufferHasIdentifier(cls,
+                                                           buf,
+                                                           offset,
+                                                           size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StablehloRngBitGeneratorOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StablehloRngBitGeneratorOptions
+    def Algorithm(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def StablehloRngBitGeneratorOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def StablehloRngBitGeneratorOptionsAddAlgorithm(builder, algorithm):
+    builder.PrependInt8Slot(0, algorithm, 0)
+
+
+def StablehloRngBitGeneratorOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class StablehloRngBitGeneratorOptionsT(object):
+
+    # StablehloRngBitGeneratorOptionsT
+    def __init__(self):
+        self.algorithm = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stablehloRngBitGeneratorOptions = StablehloRngBitGeneratorOptions()
+        stablehloRngBitGeneratorOptions.Init(buf, pos)
+        return cls.InitFromObj(stablehloRngBitGeneratorOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stablehloRngBitGeneratorOptions):
+        x = StablehloRngBitGeneratorOptionsT()
+        x._UnPack(stablehloRngBitGeneratorOptions)
+        return x
+
+    # StablehloRngBitGeneratorOptionsT
+    def _UnPack(self, stablehloRngBitGeneratorOptions):
+        if stablehloRngBitGeneratorOptions is None:
+            return
+        self.algorithm = stablehloRngBitGeneratorOptions.Algorithm()
+
+    # StablehloRngBitGeneratorOptionsT
+    def Pack(self, builder):
+        StablehloRngBitGeneratorOptionsStart(builder)
+        StablehloRngBitGeneratorOptionsAddAlgorithm(builder, self.algorithm)
+        stablehloRngBitGeneratorOptions = StablehloRngBitGeneratorOptionsEnd(builder)
+        return stablehloRngBitGeneratorOptions
+
+
+class Conv2DOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Conv2DOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsConv2DOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def Conv2DOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Conv2DOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Conv2DOptions
+    def Padding(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # Conv2DOptions
+    def StrideW(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # Conv2DOptions
+    def StrideH(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # Conv2DOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # Conv2DOptions
+    def DilationWFactor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 1
+
+    # Conv2DOptions
+    def DilationHFactor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 1
+
+    # Conv2DOptions
+    def QuantizedBiasType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def Conv2DOptionsStart(builder):
+    builder.StartObject(7)
+
+
+def Conv2DOptionsAddPadding(builder, padding):
+    builder.PrependInt8Slot(0, padding, 0)
+
+
+def Conv2DOptionsAddStrideW(builder, strideW):
+    builder.PrependInt32Slot(1, strideW, 0)
+
+
+def Conv2DOptionsAddStrideH(builder, strideH):
+    builder.PrependInt32Slot(2, strideH, 0)
+
+
+def Conv2DOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(3, fusedActivationFunction, 0)
+
+
+def Conv2DOptionsAddDilationWFactor(builder, dilationWFactor):
+    builder.PrependInt32Slot(4, dilationWFactor, 1)
+
+
+def Conv2DOptionsAddDilationHFactor(builder, dilationHFactor):
+    builder.PrependInt32Slot(5, dilationHFactor, 1)
+
+
+def Conv2DOptionsAddQuantizedBiasType(builder, quantizedBiasType):
+    builder.PrependInt8Slot(6, quantizedBiasType, 0)
+
+
+def Conv2DOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class Conv2DOptionsT(object):
+
+    # Conv2DOptionsT
+    def __init__(self):
+        self.padding = 0  # type: int
+        self.strideW = 0  # type: int
+        self.strideH = 0  # type: int
+        self.fusedActivationFunction = 0  # type: int
+        self.dilationWFactor = 1  # type: int
+        self.dilationHFactor = 1  # type: int
+        self.quantizedBiasType = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        conv2Doptions = Conv2DOptions()
+        conv2Doptions.Init(buf, pos)
+        return cls.InitFromObj(conv2Doptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, conv2Doptions):
+        x = Conv2DOptionsT()
+        x._UnPack(conv2Doptions)
+        return x
+
+    # Conv2DOptionsT
+    def _UnPack(self, conv2Doptions):
+        if conv2Doptions is None:
+            return
+        self.padding = conv2Doptions.Padding()
+        self.strideW = conv2Doptions.StrideW()
+        self.strideH = conv2Doptions.StrideH()
+        self.fusedActivationFunction = conv2Doptions.FusedActivationFunction()
+        self.dilationWFactor = conv2Doptions.DilationWFactor()
+        self.dilationHFactor = conv2Doptions.DilationHFactor()
+        self.quantizedBiasType = conv2Doptions.QuantizedBiasType()
+
+    # Conv2DOptionsT
+    def Pack(self, builder):
+        Conv2DOptionsStart(builder)
+        Conv2DOptionsAddPadding(builder, self.padding)
+        Conv2DOptionsAddStrideW(builder, self.strideW)
+        Conv2DOptionsAddStrideH(builder, self.strideH)
+        Conv2DOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        Conv2DOptionsAddDilationWFactor(builder, self.dilationWFactor)
+        Conv2DOptionsAddDilationHFactor(builder, self.dilationHFactor)
+        Conv2DOptionsAddQuantizedBiasType(builder, self.quantizedBiasType)
+        conv2Doptions = Conv2DOptionsEnd(builder)
+        return conv2Doptions
+
+
+class Conv3DOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Conv3DOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsConv3DOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def Conv3DOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Conv3DOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Conv3DOptions
+    def Padding(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # Conv3DOptions
+    def StrideD(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # Conv3DOptions
+    def StrideW(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # Conv3DOptions
+    def StrideH(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # Conv3DOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # Conv3DOptions
+    def DilationDFactor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 1
+
+    # Conv3DOptions
+    def DilationWFactor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 1
+
+    # Conv3DOptions
+    def DilationHFactor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 1
+
+
+def Conv3DOptionsStart(builder):
+    builder.StartObject(8)
+
+
+def Conv3DOptionsAddPadding(builder, padding):
+    builder.PrependInt8Slot(0, padding, 0)
+
+
+def Conv3DOptionsAddStrideD(builder, strideD):
+    builder.PrependInt32Slot(1, strideD, 0)
+
+
+def Conv3DOptionsAddStrideW(builder, strideW):
+    builder.PrependInt32Slot(2, strideW, 0)
+
+
+def Conv3DOptionsAddStrideH(builder, strideH):
+    builder.PrependInt32Slot(3, strideH, 0)
+
+
+def Conv3DOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(4, fusedActivationFunction, 0)
+
+
+def Conv3DOptionsAddDilationDFactor(builder, dilationDFactor):
+    builder.PrependInt32Slot(5, dilationDFactor, 1)
+
+
+def Conv3DOptionsAddDilationWFactor(builder, dilationWFactor):
+    builder.PrependInt32Slot(6, dilationWFactor, 1)
+
+
+def Conv3DOptionsAddDilationHFactor(builder, dilationHFactor):
+    builder.PrependInt32Slot(7, dilationHFactor, 1)
+
+
+def Conv3DOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class Conv3DOptionsT(object):
+
+    # Conv3DOptionsT
+    def __init__(self):
+        self.padding = 0  # type: int
+        self.strideD = 0  # type: int
+        self.strideW = 0  # type: int
+        self.strideH = 0  # type: int
+        self.fusedActivationFunction = 0  # type: int
+        self.dilationDFactor = 1  # type: int
+        self.dilationWFactor = 1  # type: int
+        self.dilationHFactor = 1  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        conv3Doptions = Conv3DOptions()
+        conv3Doptions.Init(buf, pos)
+        return cls.InitFromObj(conv3Doptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, conv3Doptions):
+        x = Conv3DOptionsT()
+        x._UnPack(conv3Doptions)
+        return x
+
+    # Conv3DOptionsT
+    def _UnPack(self, conv3Doptions):
+        if conv3Doptions is None:
+            return
+        self.padding = conv3Doptions.Padding()
+        self.strideD = conv3Doptions.StrideD()
+        self.strideW = conv3Doptions.StrideW()
+        self.strideH = conv3Doptions.StrideH()
+        self.fusedActivationFunction = conv3Doptions.FusedActivationFunction()
+        self.dilationDFactor = conv3Doptions.DilationDFactor()
+        self.dilationWFactor = conv3Doptions.DilationWFactor()
+        self.dilationHFactor = conv3Doptions.DilationHFactor()
+
+    # Conv3DOptionsT
+    def Pack(self, builder):
+        Conv3DOptionsStart(builder)
+        Conv3DOptionsAddPadding(builder, self.padding)
+        Conv3DOptionsAddStrideD(builder, self.strideD)
+        Conv3DOptionsAddStrideW(builder, self.strideW)
+        Conv3DOptionsAddStrideH(builder, self.strideH)
+        Conv3DOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        Conv3DOptionsAddDilationDFactor(builder, self.dilationDFactor)
+        Conv3DOptionsAddDilationWFactor(builder, self.dilationWFactor)
+        Conv3DOptionsAddDilationHFactor(builder, self.dilationHFactor)
+        conv3Doptions = Conv3DOptionsEnd(builder)
+        return conv3Doptions
+
+
+class Pool2DOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Pool2DOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsPool2DOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def Pool2DOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Pool2DOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Pool2DOptions
+    def Padding(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # Pool2DOptions
+    def StrideW(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # Pool2DOptions
+    def StrideH(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # Pool2DOptions
+    def FilterWidth(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # Pool2DOptions
+    def FilterHeight(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # Pool2DOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def Pool2DOptionsStart(builder):
+    builder.StartObject(6)
+
+
+def Pool2DOptionsAddPadding(builder, padding):
+    builder.PrependInt8Slot(0, padding, 0)
+
+
+def Pool2DOptionsAddStrideW(builder, strideW):
+    builder.PrependInt32Slot(1, strideW, 0)
+
+
+def Pool2DOptionsAddStrideH(builder, strideH):
+    builder.PrependInt32Slot(2, strideH, 0)
+
+
+def Pool2DOptionsAddFilterWidth(builder, filterWidth):
+    builder.PrependInt32Slot(3, filterWidth, 0)
+
+
+def Pool2DOptionsAddFilterHeight(builder, filterHeight):
+    builder.PrependInt32Slot(4, filterHeight, 0)
+
+
+def Pool2DOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(5, fusedActivationFunction, 0)
+
+
+def Pool2DOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class Pool2DOptionsT(object):
+
+    # Pool2DOptionsT
+    def __init__(self):
+        self.padding = 0  # type: int
+        self.strideW = 0  # type: int
+        self.strideH = 0  # type: int
+        self.filterWidth = 0  # type: int
+        self.filterHeight = 0  # type: int
+        self.fusedActivationFunction = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        pool2Doptions = Pool2DOptions()
+        pool2Doptions.Init(buf, pos)
+        return cls.InitFromObj(pool2Doptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, pool2Doptions):
+        x = Pool2DOptionsT()
+        x._UnPack(pool2Doptions)
+        return x
+
+    # Pool2DOptionsT
+    def _UnPack(self, pool2Doptions):
+        if pool2Doptions is None:
+            return
+        self.padding = pool2Doptions.Padding()
+        self.strideW = pool2Doptions.StrideW()
+        self.strideH = pool2Doptions.StrideH()
+        self.filterWidth = pool2Doptions.FilterWidth()
+        self.filterHeight = pool2Doptions.FilterHeight()
+        self.fusedActivationFunction = pool2Doptions.FusedActivationFunction()
+
+    # Pool2DOptionsT
+    def Pack(self, builder):
+        Pool2DOptionsStart(builder)
+        Pool2DOptionsAddPadding(builder, self.padding)
+        Pool2DOptionsAddStrideW(builder, self.strideW)
+        Pool2DOptionsAddStrideH(builder, self.strideH)
+        Pool2DOptionsAddFilterWidth(builder, self.filterWidth)
+        Pool2DOptionsAddFilterHeight(builder, self.filterHeight)
+        Pool2DOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        pool2Doptions = Pool2DOptionsEnd(builder)
+        return pool2Doptions
+
+
+class DepthwiseConv2DOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = DepthwiseConv2DOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsDepthwiseConv2DOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def DepthwiseConv2DOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # DepthwiseConv2DOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # DepthwiseConv2DOptions
+    def Padding(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # DepthwiseConv2DOptions
+    def StrideW(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # DepthwiseConv2DOptions
+    def StrideH(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # DepthwiseConv2DOptions
+    def DepthMultiplier(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # DepthwiseConv2DOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # DepthwiseConv2DOptions
+    def DilationWFactor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 1
+
+    # DepthwiseConv2DOptions
+    def DilationHFactor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 1
+
+
+def DepthwiseConv2DOptionsStart(builder):
+    builder.StartObject(7)
+
+
+def DepthwiseConv2DOptionsAddPadding(builder, padding):
+    builder.PrependInt8Slot(0, padding, 0)
+
+
+def DepthwiseConv2DOptionsAddStrideW(builder, strideW):
+    builder.PrependInt32Slot(1, strideW, 0)
+
+
+def DepthwiseConv2DOptionsAddStrideH(builder, strideH):
+    builder.PrependInt32Slot(2, strideH, 0)
+
+
+def DepthwiseConv2DOptionsAddDepthMultiplier(builder, depthMultiplier):
+    builder.PrependInt32Slot(3, depthMultiplier, 0)
+
+
+def DepthwiseConv2DOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(4, fusedActivationFunction, 0)
+
+
+def DepthwiseConv2DOptionsAddDilationWFactor(builder, dilationWFactor):
+    builder.PrependInt32Slot(5, dilationWFactor, 1)
+
+
+def DepthwiseConv2DOptionsAddDilationHFactor(builder, dilationHFactor):
+    builder.PrependInt32Slot(6, dilationHFactor, 1)
+
+
+def DepthwiseConv2DOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class DepthwiseConv2DOptionsT(object):
+
+    # DepthwiseConv2DOptionsT
+    def __init__(self):
+        self.padding = 0  # type: int
+        self.strideW = 0  # type: int
+        self.strideH = 0  # type: int
+        self.depthMultiplier = 0  # type: int
+        self.fusedActivationFunction = 0  # type: int
+        self.dilationWFactor = 1  # type: int
+        self.dilationHFactor = 1  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        depthwiseConv2Doptions = DepthwiseConv2DOptions()
+        depthwiseConv2Doptions.Init(buf, pos)
+        return cls.InitFromObj(depthwiseConv2Doptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, depthwiseConv2Doptions):
+        x = DepthwiseConv2DOptionsT()
+        x._UnPack(depthwiseConv2Doptions)
+        return x
+
+    # DepthwiseConv2DOptionsT
+    def _UnPack(self, depthwiseConv2Doptions):
+        if depthwiseConv2Doptions is None:
+            return
+        self.padding = depthwiseConv2Doptions.Padding()
+        self.strideW = depthwiseConv2Doptions.StrideW()
+        self.strideH = depthwiseConv2Doptions.StrideH()
+        self.depthMultiplier = depthwiseConv2Doptions.DepthMultiplier()
+        self.fusedActivationFunction = depthwiseConv2Doptions.FusedActivationFunction()
+        self.dilationWFactor = depthwiseConv2Doptions.DilationWFactor()
+        self.dilationHFactor = depthwiseConv2Doptions.DilationHFactor()
+
+    # DepthwiseConv2DOptionsT
+    def Pack(self, builder):
+        DepthwiseConv2DOptionsStart(builder)
+        DepthwiseConv2DOptionsAddPadding(builder, self.padding)
+        DepthwiseConv2DOptionsAddStrideW(builder, self.strideW)
+        DepthwiseConv2DOptionsAddStrideH(builder, self.strideH)
+        DepthwiseConv2DOptionsAddDepthMultiplier(builder, self.depthMultiplier)
+        DepthwiseConv2DOptionsAddFusedActivationFunction(builder,
+                                                         self.fusedActivationFunction)
+        DepthwiseConv2DOptionsAddDilationWFactor(builder, self.dilationWFactor)
+        DepthwiseConv2DOptionsAddDilationHFactor(builder, self.dilationHFactor)
+        depthwiseConv2Doptions = DepthwiseConv2DOptionsEnd(builder)
+        return depthwiseConv2Doptions
+
+
+class ConcatEmbeddingsOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ConcatEmbeddingsOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsConcatEmbeddingsOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ConcatEmbeddingsOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ConcatEmbeddingsOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ConcatEmbeddingsOptions
+    def NumChannels(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # ConcatEmbeddingsOptions
+    def NumColumnsPerChannel(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # ConcatEmbeddingsOptions
+    def NumColumnsPerChannelAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # ConcatEmbeddingsOptions
+    def NumColumnsPerChannelLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # ConcatEmbeddingsOptions
+    def NumColumnsPerChannelIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # ConcatEmbeddingsOptions
+    def EmbeddingDimPerChannel(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # ConcatEmbeddingsOptions
+    def EmbeddingDimPerChannelAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # ConcatEmbeddingsOptions
+    def EmbeddingDimPerChannelLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # ConcatEmbeddingsOptions
+    def EmbeddingDimPerChannelIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+
+def ConcatEmbeddingsOptionsStart(builder):
+    builder.StartObject(3)
+
+
+def ConcatEmbeddingsOptionsAddNumChannels(builder, numChannels):
+    builder.PrependInt32Slot(0, numChannels, 0)
+
+
+def ConcatEmbeddingsOptionsAddNumColumnsPerChannel(builder, numColumnsPerChannel):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(numColumnsPerChannel), 0)
+
+
+def ConcatEmbeddingsOptionsStartNumColumnsPerChannelVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def ConcatEmbeddingsOptionsAddEmbeddingDimPerChannel(builder, embeddingDimPerChannel):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(embeddingDimPerChannel), 0)
+
+
+def ConcatEmbeddingsOptionsStartEmbeddingDimPerChannelVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def ConcatEmbeddingsOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class ConcatEmbeddingsOptionsT(object):
+
+    # ConcatEmbeddingsOptionsT
+    def __init__(self):
+        self.numChannels = 0  # type: int
+        self.numColumnsPerChannel = None  # type: List[int]
+        self.embeddingDimPerChannel = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        concatEmbeddingsOptions = ConcatEmbeddingsOptions()
+        concatEmbeddingsOptions.Init(buf, pos)
+        return cls.InitFromObj(concatEmbeddingsOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, concatEmbeddingsOptions):
+        x = ConcatEmbeddingsOptionsT()
+        x._UnPack(concatEmbeddingsOptions)
+        return x
+
+    # ConcatEmbeddingsOptionsT
+    def _UnPack(self, concatEmbeddingsOptions):
+        if concatEmbeddingsOptions is None:
+            return
+        self.numChannels = concatEmbeddingsOptions.NumChannels()
+        if not concatEmbeddingsOptions.NumColumnsPerChannelIsNone():
+            if np is None:
+                self.numColumnsPerChannel = []
+                for i in range(concatEmbeddingsOptions.NumColumnsPerChannelLength()):
+                    self.numColumnsPerChannel.append(
+                        concatEmbeddingsOptions.NumColumnsPerChannel(i))
+            else:
+                self.numColumnsPerChannel = concatEmbeddingsOptions.NumColumnsPerChannelAsNumpy(
+                )
+        if not concatEmbeddingsOptions.EmbeddingDimPerChannelIsNone():
+            if np is None:
+                self.embeddingDimPerChannel = []
+                for i in range(concatEmbeddingsOptions.EmbeddingDimPerChannelLength()):
+                    self.embeddingDimPerChannel.append(
+                        concatEmbeddingsOptions.EmbeddingDimPerChannel(i))
+            else:
+                self.embeddingDimPerChannel = concatEmbeddingsOptions.EmbeddingDimPerChannelAsNumpy(
+                )
+
+    # ConcatEmbeddingsOptionsT
+    def Pack(self, builder):
+        if self.numColumnsPerChannel is not None:
+            if np is not None and type(self.numColumnsPerChannel) is np.ndarray:
+                numColumnsPerChannel = builder.CreateNumpyVector(
+                    self.numColumnsPerChannel)
+            else:
+                ConcatEmbeddingsOptionsStartNumColumnsPerChannelVector(
+                    builder, len(self.numColumnsPerChannel))
+                for i in reversed(range(len(self.numColumnsPerChannel))):
+                    builder.PrependInt32(self.numColumnsPerChannel[i])
+                numColumnsPerChannel = builder.EndVector()
+        if self.embeddingDimPerChannel is not None:
+            if np is not None and type(self.embeddingDimPerChannel) is np.ndarray:
+                embeddingDimPerChannel = builder.CreateNumpyVector(
+                    self.embeddingDimPerChannel)
+            else:
+                ConcatEmbeddingsOptionsStartEmbeddingDimPerChannelVector(
+                    builder, len(self.embeddingDimPerChannel))
+                for i in reversed(range(len(self.embeddingDimPerChannel))):
+                    builder.PrependInt32(self.embeddingDimPerChannel[i])
+                embeddingDimPerChannel = builder.EndVector()
+        ConcatEmbeddingsOptionsStart(builder)
+        ConcatEmbeddingsOptionsAddNumChannels(builder, self.numChannels)
+        if self.numColumnsPerChannel is not None:
+            ConcatEmbeddingsOptionsAddNumColumnsPerChannel(builder, numColumnsPerChannel)
+        if self.embeddingDimPerChannel is not None:
+            ConcatEmbeddingsOptionsAddEmbeddingDimPerChannel(builder,
+                                                             embeddingDimPerChannel)
+        concatEmbeddingsOptions = ConcatEmbeddingsOptionsEnd(builder)
+        return concatEmbeddingsOptions
+
+
+class LSHProjectionOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = LSHProjectionOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsLSHProjectionOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def LSHProjectionOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # LSHProjectionOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # LSHProjectionOptions
+    def Type(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def LSHProjectionOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def LSHProjectionOptionsAddType(builder, type):
+    builder.PrependInt8Slot(0, type, 0)
+
+
+def LSHProjectionOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class LSHProjectionOptionsT(object):
+
+    # LSHProjectionOptionsT
+    def __init__(self):
+        self.type = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        lshprojectionOptions = LSHProjectionOptions()
+        lshprojectionOptions.Init(buf, pos)
+        return cls.InitFromObj(lshprojectionOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, lshprojectionOptions):
+        x = LSHProjectionOptionsT()
+        x._UnPack(lshprojectionOptions)
+        return x
+
+    # LSHProjectionOptionsT
+    def _UnPack(self, lshprojectionOptions):
+        if lshprojectionOptions is None:
+            return
+        self.type = lshprojectionOptions.Type()
+
+    # LSHProjectionOptionsT
+    def Pack(self, builder):
+        LSHProjectionOptionsStart(builder)
+        LSHProjectionOptionsAddType(builder, self.type)
+        lshprojectionOptions = LSHProjectionOptionsEnd(builder)
+        return lshprojectionOptions
+
+
+class SVDFOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SVDFOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSVDFOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SVDFOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SVDFOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SVDFOptions
+    def Rank(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # SVDFOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # SVDFOptions
+    def AsymmetricQuantizeInputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def SVDFOptionsStart(builder):
+    builder.StartObject(3)
+
+
+def SVDFOptionsAddRank(builder, rank):
+    builder.PrependInt32Slot(0, rank, 0)
+
+
+def SVDFOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(1, fusedActivationFunction, 0)
+
+
+def SVDFOptionsAddAsymmetricQuantizeInputs(builder, asymmetricQuantizeInputs):
+    builder.PrependBoolSlot(2, asymmetricQuantizeInputs, 0)
+
+
+def SVDFOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SVDFOptionsT(object):
+
+    # SVDFOptionsT
+    def __init__(self):
+        self.rank = 0  # type: int
+        self.fusedActivationFunction = 0  # type: int
+        self.asymmetricQuantizeInputs = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        svdfoptions = SVDFOptions()
+        svdfoptions.Init(buf, pos)
+        return cls.InitFromObj(svdfoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, svdfoptions):
+        x = SVDFOptionsT()
+        x._UnPack(svdfoptions)
+        return x
+
+    # SVDFOptionsT
+    def _UnPack(self, svdfoptions):
+        if svdfoptions is None:
+            return
+        self.rank = svdfoptions.Rank()
+        self.fusedActivationFunction = svdfoptions.FusedActivationFunction()
+        self.asymmetricQuantizeInputs = svdfoptions.AsymmetricQuantizeInputs()
+
+    # SVDFOptionsT
+    def Pack(self, builder):
+        SVDFOptionsStart(builder)
+        SVDFOptionsAddRank(builder, self.rank)
+        SVDFOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        SVDFOptionsAddAsymmetricQuantizeInputs(builder, self.asymmetricQuantizeInputs)
+        svdfoptions = SVDFOptionsEnd(builder)
+        return svdfoptions
+
+
+class RNNOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = RNNOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsRNNOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def RNNOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # RNNOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # RNNOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # RNNOptions
+    def AsymmetricQuantizeInputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def RNNOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def RNNOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def RNNOptionsAddAsymmetricQuantizeInputs(builder, asymmetricQuantizeInputs):
+    builder.PrependBoolSlot(1, asymmetricQuantizeInputs, 0)
+
+
+def RNNOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class RNNOptionsT(object):
+
+    # RNNOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+        self.asymmetricQuantizeInputs = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        rnnoptions = RNNOptions()
+        rnnoptions.Init(buf, pos)
+        return cls.InitFromObj(rnnoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, rnnoptions):
+        x = RNNOptionsT()
+        x._UnPack(rnnoptions)
+        return x
+
+    # RNNOptionsT
+    def _UnPack(self, rnnoptions):
+        if rnnoptions is None:
+            return
+        self.fusedActivationFunction = rnnoptions.FusedActivationFunction()
+        self.asymmetricQuantizeInputs = rnnoptions.AsymmetricQuantizeInputs()
+
+    # RNNOptionsT
+    def Pack(self, builder):
+        RNNOptionsStart(builder)
+        RNNOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        RNNOptionsAddAsymmetricQuantizeInputs(builder, self.asymmetricQuantizeInputs)
+        rnnoptions = RNNOptionsEnd(builder)
+        return rnnoptions
+
+
+class SequenceRNNOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SequenceRNNOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSequenceRNNOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SequenceRNNOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SequenceRNNOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SequenceRNNOptions
+    def TimeMajor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # SequenceRNNOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # SequenceRNNOptions
+    def AsymmetricQuantizeInputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def SequenceRNNOptionsStart(builder):
+    builder.StartObject(3)
+
+
+def SequenceRNNOptionsAddTimeMajor(builder, timeMajor):
+    builder.PrependBoolSlot(0, timeMajor, 0)
+
+
+def SequenceRNNOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(1, fusedActivationFunction, 0)
+
+
+def SequenceRNNOptionsAddAsymmetricQuantizeInputs(builder, asymmetricQuantizeInputs):
+    builder.PrependBoolSlot(2, asymmetricQuantizeInputs, 0)
+
+
+def SequenceRNNOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SequenceRNNOptionsT(object):
+
+    # SequenceRNNOptionsT
+    def __init__(self):
+        self.timeMajor = False  # type: bool
+        self.fusedActivationFunction = 0  # type: int
+        self.asymmetricQuantizeInputs = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        sequenceRnnoptions = SequenceRNNOptions()
+        sequenceRnnoptions.Init(buf, pos)
+        return cls.InitFromObj(sequenceRnnoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, sequenceRnnoptions):
+        x = SequenceRNNOptionsT()
+        x._UnPack(sequenceRnnoptions)
+        return x
+
+    # SequenceRNNOptionsT
+    def _UnPack(self, sequenceRnnoptions):
+        if sequenceRnnoptions is None:
+            return
+        self.timeMajor = sequenceRnnoptions.TimeMajor()
+        self.fusedActivationFunction = sequenceRnnoptions.FusedActivationFunction()
+        self.asymmetricQuantizeInputs = sequenceRnnoptions.AsymmetricQuantizeInputs()
+
+    # SequenceRNNOptionsT
+    def Pack(self, builder):
+        SequenceRNNOptionsStart(builder)
+        SequenceRNNOptionsAddTimeMajor(builder, self.timeMajor)
+        SequenceRNNOptionsAddFusedActivationFunction(builder,
+                                                     self.fusedActivationFunction)
+        SequenceRNNOptionsAddAsymmetricQuantizeInputs(builder,
+                                                      self.asymmetricQuantizeInputs)
+        sequenceRnnoptions = SequenceRNNOptionsEnd(builder)
+        return sequenceRnnoptions
+
+
+class BidirectionalSequenceRNNOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = BidirectionalSequenceRNNOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBidirectionalSequenceRNNOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BidirectionalSequenceRNNOptionsBufferHasIdentifier(cls,
+                                                           buf,
+                                                           offset,
+                                                           size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # BidirectionalSequenceRNNOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # BidirectionalSequenceRNNOptions
+    def TimeMajor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # BidirectionalSequenceRNNOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # BidirectionalSequenceRNNOptions
+    def MergeOutputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # BidirectionalSequenceRNNOptions
+    def AsymmetricQuantizeInputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def BidirectionalSequenceRNNOptionsStart(builder):
+    builder.StartObject(4)
+
+
+def BidirectionalSequenceRNNOptionsAddTimeMajor(builder, timeMajor):
+    builder.PrependBoolSlot(0, timeMajor, 0)
+
+
+def BidirectionalSequenceRNNOptionsAddFusedActivationFunction(builder,
+                                                              fusedActivationFunction):
+    builder.PrependInt8Slot(1, fusedActivationFunction, 0)
+
+
+def BidirectionalSequenceRNNOptionsAddMergeOutputs(builder, mergeOutputs):
+    builder.PrependBoolSlot(2, mergeOutputs, 0)
+
+
+def BidirectionalSequenceRNNOptionsAddAsymmetricQuantizeInputs(builder,
+                                                               asymmetricQuantizeInputs):
+    builder.PrependBoolSlot(3, asymmetricQuantizeInputs, 0)
+
+
+def BidirectionalSequenceRNNOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class BidirectionalSequenceRNNOptionsT(object):
+
+    # BidirectionalSequenceRNNOptionsT
+    def __init__(self):
+        self.timeMajor = False  # type: bool
+        self.fusedActivationFunction = 0  # type: int
+        self.mergeOutputs = False  # type: bool
+        self.asymmetricQuantizeInputs = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        bidirectionalSequenceRnnoptions = BidirectionalSequenceRNNOptions()
+        bidirectionalSequenceRnnoptions.Init(buf, pos)
+        return cls.InitFromObj(bidirectionalSequenceRnnoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, bidirectionalSequenceRnnoptions):
+        x = BidirectionalSequenceRNNOptionsT()
+        x._UnPack(bidirectionalSequenceRnnoptions)
+        return x
+
+    # BidirectionalSequenceRNNOptionsT
+    def _UnPack(self, bidirectionalSequenceRnnoptions):
+        if bidirectionalSequenceRnnoptions is None:
+            return
+        self.timeMajor = bidirectionalSequenceRnnoptions.TimeMajor()
+        self.fusedActivationFunction = bidirectionalSequenceRnnoptions.FusedActivationFunction(
+        )
+        self.mergeOutputs = bidirectionalSequenceRnnoptions.MergeOutputs()
+        self.asymmetricQuantizeInputs = bidirectionalSequenceRnnoptions.AsymmetricQuantizeInputs(
+        )
+
+    # BidirectionalSequenceRNNOptionsT
+    def Pack(self, builder):
+        BidirectionalSequenceRNNOptionsStart(builder)
+        BidirectionalSequenceRNNOptionsAddTimeMajor(builder, self.timeMajor)
+        BidirectionalSequenceRNNOptionsAddFusedActivationFunction(
+            builder, self.fusedActivationFunction)
+        BidirectionalSequenceRNNOptionsAddMergeOutputs(builder, self.mergeOutputs)
+        BidirectionalSequenceRNNOptionsAddAsymmetricQuantizeInputs(
+            builder, self.asymmetricQuantizeInputs)
+        bidirectionalSequenceRnnoptions = BidirectionalSequenceRNNOptionsEnd(builder)
+        return bidirectionalSequenceRnnoptions
+
+
+class FullyConnectedOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = FullyConnectedOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsFullyConnectedOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def FullyConnectedOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # FullyConnectedOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # FullyConnectedOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # FullyConnectedOptions
+    def WeightsFormat(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # FullyConnectedOptions
+    def KeepNumDims(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # FullyConnectedOptions
+    def AsymmetricQuantizeInputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # FullyConnectedOptions
+    def QuantizedBiasType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def FullyConnectedOptionsStart(builder):
+    builder.StartObject(5)
+
+
+def FullyConnectedOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def FullyConnectedOptionsAddWeightsFormat(builder, weightsFormat):
+    builder.PrependInt8Slot(1, weightsFormat, 0)
+
+
+def FullyConnectedOptionsAddKeepNumDims(builder, keepNumDims):
+    builder.PrependBoolSlot(2, keepNumDims, 0)
+
+
+def FullyConnectedOptionsAddAsymmetricQuantizeInputs(builder, asymmetricQuantizeInputs):
+    builder.PrependBoolSlot(3, asymmetricQuantizeInputs, 0)
+
+
+def FullyConnectedOptionsAddQuantizedBiasType(builder, quantizedBiasType):
+    builder.PrependInt8Slot(4, quantizedBiasType, 0)
+
+
+def FullyConnectedOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class FullyConnectedOptionsT(object):
+
+    # FullyConnectedOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+        self.weightsFormat = 0  # type: int
+        self.keepNumDims = False  # type: bool
+        self.asymmetricQuantizeInputs = False  # type: bool
+        self.quantizedBiasType = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        fullyConnectedOptions = FullyConnectedOptions()
+        fullyConnectedOptions.Init(buf, pos)
+        return cls.InitFromObj(fullyConnectedOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, fullyConnectedOptions):
+        x = FullyConnectedOptionsT()
+        x._UnPack(fullyConnectedOptions)
+        return x
+
+    # FullyConnectedOptionsT
+    def _UnPack(self, fullyConnectedOptions):
+        if fullyConnectedOptions is None:
+            return
+        self.fusedActivationFunction = fullyConnectedOptions.FusedActivationFunction()
+        self.weightsFormat = fullyConnectedOptions.WeightsFormat()
+        self.keepNumDims = fullyConnectedOptions.KeepNumDims()
+        self.asymmetricQuantizeInputs = fullyConnectedOptions.AsymmetricQuantizeInputs()
+        self.quantizedBiasType = fullyConnectedOptions.QuantizedBiasType()
+
+    # FullyConnectedOptionsT
+    def Pack(self, builder):
+        FullyConnectedOptionsStart(builder)
+        FullyConnectedOptionsAddFusedActivationFunction(builder,
+                                                        self.fusedActivationFunction)
+        FullyConnectedOptionsAddWeightsFormat(builder, self.weightsFormat)
+        FullyConnectedOptionsAddKeepNumDims(builder, self.keepNumDims)
+        FullyConnectedOptionsAddAsymmetricQuantizeInputs(builder,
+                                                         self.asymmetricQuantizeInputs)
+        FullyConnectedOptionsAddQuantizedBiasType(builder, self.quantizedBiasType)
+        fullyConnectedOptions = FullyConnectedOptionsEnd(builder)
+        return fullyConnectedOptions
+
+
+class SoftmaxOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SoftmaxOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSoftmaxOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SoftmaxOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SoftmaxOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SoftmaxOptions
+    def Beta(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+
+def SoftmaxOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def SoftmaxOptionsAddBeta(builder, beta):
+    builder.PrependFloat32Slot(0, beta, 0.0)
+
+
+def SoftmaxOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SoftmaxOptionsT(object):
+
+    # SoftmaxOptionsT
+    def __init__(self):
+        self.beta = 0.0  # type: float
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        softmaxOptions = SoftmaxOptions()
+        softmaxOptions.Init(buf, pos)
+        return cls.InitFromObj(softmaxOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, softmaxOptions):
+        x = SoftmaxOptionsT()
+        x._UnPack(softmaxOptions)
+        return x
+
+    # SoftmaxOptionsT
+    def _UnPack(self, softmaxOptions):
+        if softmaxOptions is None:
+            return
+        self.beta = softmaxOptions.Beta()
+
+    # SoftmaxOptionsT
+    def Pack(self, builder):
+        SoftmaxOptionsStart(builder)
+        SoftmaxOptionsAddBeta(builder, self.beta)
+        softmaxOptions = SoftmaxOptionsEnd(builder)
+        return softmaxOptions
+
+
+class ConcatenationOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ConcatenationOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsConcatenationOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ConcatenationOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ConcatenationOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ConcatenationOptions
+    def Axis(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # ConcatenationOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def ConcatenationOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def ConcatenationOptionsAddAxis(builder, axis):
+    builder.PrependInt32Slot(0, axis, 0)
+
+
+def ConcatenationOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(1, fusedActivationFunction, 0)
+
+
+def ConcatenationOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ConcatenationOptionsT(object):
+
+    # ConcatenationOptionsT
+    def __init__(self):
+        self.axis = 0  # type: int
+        self.fusedActivationFunction = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        concatenationOptions = ConcatenationOptions()
+        concatenationOptions.Init(buf, pos)
+        return cls.InitFromObj(concatenationOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, concatenationOptions):
+        x = ConcatenationOptionsT()
+        x._UnPack(concatenationOptions)
+        return x
+
+    # ConcatenationOptionsT
+    def _UnPack(self, concatenationOptions):
+        if concatenationOptions is None:
+            return
+        self.axis = concatenationOptions.Axis()
+        self.fusedActivationFunction = concatenationOptions.FusedActivationFunction()
+
+    # ConcatenationOptionsT
+    def Pack(self, builder):
+        ConcatenationOptionsStart(builder)
+        ConcatenationOptionsAddAxis(builder, self.axis)
+        ConcatenationOptionsAddFusedActivationFunction(builder,
+                                                       self.fusedActivationFunction)
+        concatenationOptions = ConcatenationOptionsEnd(builder)
+        return concatenationOptions
+
+
+class AddOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = AddOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsAddOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def AddOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # AddOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # AddOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # AddOptions
+    def PotScaleInt16(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return True
+
+
+def AddOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def AddOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def AddOptionsAddPotScaleInt16(builder, potScaleInt16):
+    builder.PrependBoolSlot(1, potScaleInt16, 1)
+
+
+def AddOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class AddOptionsT(object):
+
+    # AddOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+        self.potScaleInt16 = True  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        addOptions = AddOptions()
+        addOptions.Init(buf, pos)
+        return cls.InitFromObj(addOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, addOptions):
+        x = AddOptionsT()
+        x._UnPack(addOptions)
+        return x
+
+    # AddOptionsT
+    def _UnPack(self, addOptions):
+        if addOptions is None:
+            return
+        self.fusedActivationFunction = addOptions.FusedActivationFunction()
+        self.potScaleInt16 = addOptions.PotScaleInt16()
+
+    # AddOptionsT
+    def Pack(self, builder):
+        AddOptionsStart(builder)
+        AddOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        AddOptionsAddPotScaleInt16(builder, self.potScaleInt16)
+        addOptions = AddOptionsEnd(builder)
+        return addOptions
+
+
+class MulOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = MulOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsMulOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def MulOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # MulOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # MulOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def MulOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def MulOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def MulOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class MulOptionsT(object):
+
+    # MulOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        mulOptions = MulOptions()
+        mulOptions.Init(buf, pos)
+        return cls.InitFromObj(mulOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, mulOptions):
+        x = MulOptionsT()
+        x._UnPack(mulOptions)
+        return x
+
+    # MulOptionsT
+    def _UnPack(self, mulOptions):
+        if mulOptions is None:
+            return
+        self.fusedActivationFunction = mulOptions.FusedActivationFunction()
+
+    # MulOptionsT
+    def Pack(self, builder):
+        MulOptionsStart(builder)
+        MulOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        mulOptions = MulOptionsEnd(builder)
+        return mulOptions
+
+
+class L2NormOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = L2NormOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsL2NormOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def L2NormOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # L2NormOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # L2NormOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def L2NormOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def L2NormOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def L2NormOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class L2NormOptionsT(object):
+
+    # L2NormOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        l2NormOptions = L2NormOptions()
+        l2NormOptions.Init(buf, pos)
+        return cls.InitFromObj(l2NormOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, l2NormOptions):
+        x = L2NormOptionsT()
+        x._UnPack(l2NormOptions)
+        return x
+
+    # L2NormOptionsT
+    def _UnPack(self, l2NormOptions):
+        if l2NormOptions is None:
+            return
+        self.fusedActivationFunction = l2NormOptions.FusedActivationFunction()
+
+    # L2NormOptionsT
+    def Pack(self, builder):
+        L2NormOptionsStart(builder)
+        L2NormOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        l2NormOptions = L2NormOptionsEnd(builder)
+        return l2NormOptions
+
+
+class LocalResponseNormalizationOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = LocalResponseNormalizationOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsLocalResponseNormalizationOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def LocalResponseNormalizationOptionsBufferHasIdentifier(cls,
+                                                             buf,
+                                                             offset,
+                                                             size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # LocalResponseNormalizationOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # LocalResponseNormalizationOptions
+    def Radius(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # LocalResponseNormalizationOptions
+    def Bias(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # LocalResponseNormalizationOptions
+    def Alpha(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # LocalResponseNormalizationOptions
+    def Beta(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+
+def LocalResponseNormalizationOptionsStart(builder):
+    builder.StartObject(4)
+
+
+def LocalResponseNormalizationOptionsAddRadius(builder, radius):
+    builder.PrependInt32Slot(0, radius, 0)
+
+
+def LocalResponseNormalizationOptionsAddBias(builder, bias):
+    builder.PrependFloat32Slot(1, bias, 0.0)
+
+
+def LocalResponseNormalizationOptionsAddAlpha(builder, alpha):
+    builder.PrependFloat32Slot(2, alpha, 0.0)
+
+
+def LocalResponseNormalizationOptionsAddBeta(builder, beta):
+    builder.PrependFloat32Slot(3, beta, 0.0)
+
+
+def LocalResponseNormalizationOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class LocalResponseNormalizationOptionsT(object):
+
+    # LocalResponseNormalizationOptionsT
+    def __init__(self):
+        self.radius = 0  # type: int
+        self.bias = 0.0  # type: float
+        self.alpha = 0.0  # type: float
+        self.beta = 0.0  # type: float
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        localResponseNormalizationOptions = LocalResponseNormalizationOptions()
+        localResponseNormalizationOptions.Init(buf, pos)
+        return cls.InitFromObj(localResponseNormalizationOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, localResponseNormalizationOptions):
+        x = LocalResponseNormalizationOptionsT()
+        x._UnPack(localResponseNormalizationOptions)
+        return x
+
+    # LocalResponseNormalizationOptionsT
+    def _UnPack(self, localResponseNormalizationOptions):
+        if localResponseNormalizationOptions is None:
+            return
+        self.radius = localResponseNormalizationOptions.Radius()
+        self.bias = localResponseNormalizationOptions.Bias()
+        self.alpha = localResponseNormalizationOptions.Alpha()
+        self.beta = localResponseNormalizationOptions.Beta()
+
+    # LocalResponseNormalizationOptionsT
+    def Pack(self, builder):
+        LocalResponseNormalizationOptionsStart(builder)
+        LocalResponseNormalizationOptionsAddRadius(builder, self.radius)
+        LocalResponseNormalizationOptionsAddBias(builder, self.bias)
+        LocalResponseNormalizationOptionsAddAlpha(builder, self.alpha)
+        LocalResponseNormalizationOptionsAddBeta(builder, self.beta)
+        localResponseNormalizationOptions = LocalResponseNormalizationOptionsEnd(builder)
+        return localResponseNormalizationOptions
+
+
+class LSTMOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = LSTMOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsLSTMOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def LSTMOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # LSTMOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # LSTMOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # LSTMOptions
+    def CellClip(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # LSTMOptions
+    def ProjClip(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # LSTMOptions
+    def KernelType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # LSTMOptions
+    def AsymmetricQuantizeInputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def LSTMOptionsStart(builder):
+    builder.StartObject(5)
+
+
+def LSTMOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def LSTMOptionsAddCellClip(builder, cellClip):
+    builder.PrependFloat32Slot(1, cellClip, 0.0)
+
+
+def LSTMOptionsAddProjClip(builder, projClip):
+    builder.PrependFloat32Slot(2, projClip, 0.0)
+
+
+def LSTMOptionsAddKernelType(builder, kernelType):
+    builder.PrependInt8Slot(3, kernelType, 0)
+
+
+def LSTMOptionsAddAsymmetricQuantizeInputs(builder, asymmetricQuantizeInputs):
+    builder.PrependBoolSlot(4, asymmetricQuantizeInputs, 0)
+
+
+def LSTMOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class LSTMOptionsT(object):
+
+    # LSTMOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+        self.cellClip = 0.0  # type: float
+        self.projClip = 0.0  # type: float
+        self.kernelType = 0  # type: int
+        self.asymmetricQuantizeInputs = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        lstmoptions = LSTMOptions()
+        lstmoptions.Init(buf, pos)
+        return cls.InitFromObj(lstmoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, lstmoptions):
+        x = LSTMOptionsT()
+        x._UnPack(lstmoptions)
+        return x
+
+    # LSTMOptionsT
+    def _UnPack(self, lstmoptions):
+        if lstmoptions is None:
+            return
+        self.fusedActivationFunction = lstmoptions.FusedActivationFunction()
+        self.cellClip = lstmoptions.CellClip()
+        self.projClip = lstmoptions.ProjClip()
+        self.kernelType = lstmoptions.KernelType()
+        self.asymmetricQuantizeInputs = lstmoptions.AsymmetricQuantizeInputs()
+
+    # LSTMOptionsT
+    def Pack(self, builder):
+        LSTMOptionsStart(builder)
+        LSTMOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        LSTMOptionsAddCellClip(builder, self.cellClip)
+        LSTMOptionsAddProjClip(builder, self.projClip)
+        LSTMOptionsAddKernelType(builder, self.kernelType)
+        LSTMOptionsAddAsymmetricQuantizeInputs(builder, self.asymmetricQuantizeInputs)
+        lstmoptions = LSTMOptionsEnd(builder)
+        return lstmoptions
+
+
+class UnidirectionalSequenceLSTMOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = UnidirectionalSequenceLSTMOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsUnidirectionalSequenceLSTMOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def UnidirectionalSequenceLSTMOptionsBufferHasIdentifier(cls,
+                                                             buf,
+                                                             offset,
+                                                             size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # UnidirectionalSequenceLSTMOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # UnidirectionalSequenceLSTMOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # UnidirectionalSequenceLSTMOptions
+    def CellClip(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # UnidirectionalSequenceLSTMOptions
+    def ProjClip(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # UnidirectionalSequenceLSTMOptions
+    def TimeMajor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # UnidirectionalSequenceLSTMOptions
+    def AsymmetricQuantizeInputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # UnidirectionalSequenceLSTMOptions
+    def DiagonalRecurrentTensors(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def UnidirectionalSequenceLSTMOptionsStart(builder):
+    builder.StartObject(6)
+
+
+def UnidirectionalSequenceLSTMOptionsAddFusedActivationFunction(
+        builder, fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def UnidirectionalSequenceLSTMOptionsAddCellClip(builder, cellClip):
+    builder.PrependFloat32Slot(1, cellClip, 0.0)
+
+
+def UnidirectionalSequenceLSTMOptionsAddProjClip(builder, projClip):
+    builder.PrependFloat32Slot(2, projClip, 0.0)
+
+
+def UnidirectionalSequenceLSTMOptionsAddTimeMajor(builder, timeMajor):
+    builder.PrependBoolSlot(3, timeMajor, 0)
+
+
+def UnidirectionalSequenceLSTMOptionsAddAsymmetricQuantizeInputs(
+        builder, asymmetricQuantizeInputs):
+    builder.PrependBoolSlot(4, asymmetricQuantizeInputs, 0)
+
+
+def UnidirectionalSequenceLSTMOptionsAddDiagonalRecurrentTensors(
+        builder, diagonalRecurrentTensors):
+    builder.PrependBoolSlot(5, diagonalRecurrentTensors, 0)
+
+
+def UnidirectionalSequenceLSTMOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class UnidirectionalSequenceLSTMOptionsT(object):
+
+    # UnidirectionalSequenceLSTMOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+        self.cellClip = 0.0  # type: float
+        self.projClip = 0.0  # type: float
+        self.timeMajor = False  # type: bool
+        self.asymmetricQuantizeInputs = False  # type: bool
+        self.diagonalRecurrentTensors = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        unidirectionalSequenceLstmoptions = UnidirectionalSequenceLSTMOptions()
+        unidirectionalSequenceLstmoptions.Init(buf, pos)
+        return cls.InitFromObj(unidirectionalSequenceLstmoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, unidirectionalSequenceLstmoptions):
+        x = UnidirectionalSequenceLSTMOptionsT()
+        x._UnPack(unidirectionalSequenceLstmoptions)
+        return x
+
+    # UnidirectionalSequenceLSTMOptionsT
+    def _UnPack(self, unidirectionalSequenceLstmoptions):
+        if unidirectionalSequenceLstmoptions is None:
+            return
+        self.fusedActivationFunction = unidirectionalSequenceLstmoptions.FusedActivationFunction(
+        )
+        self.cellClip = unidirectionalSequenceLstmoptions.CellClip()
+        self.projClip = unidirectionalSequenceLstmoptions.ProjClip()
+        self.timeMajor = unidirectionalSequenceLstmoptions.TimeMajor()
+        self.asymmetricQuantizeInputs = unidirectionalSequenceLstmoptions.AsymmetricQuantizeInputs(
+        )
+        self.diagonalRecurrentTensors = unidirectionalSequenceLstmoptions.DiagonalRecurrentTensors(
+        )
+
+    # UnidirectionalSequenceLSTMOptionsT
+    def Pack(self, builder):
+        UnidirectionalSequenceLSTMOptionsStart(builder)
+        UnidirectionalSequenceLSTMOptionsAddFusedActivationFunction(
+            builder, self.fusedActivationFunction)
+        UnidirectionalSequenceLSTMOptionsAddCellClip(builder, self.cellClip)
+        UnidirectionalSequenceLSTMOptionsAddProjClip(builder, self.projClip)
+        UnidirectionalSequenceLSTMOptionsAddTimeMajor(builder, self.timeMajor)
+        UnidirectionalSequenceLSTMOptionsAddAsymmetricQuantizeInputs(
+            builder, self.asymmetricQuantizeInputs)
+        UnidirectionalSequenceLSTMOptionsAddDiagonalRecurrentTensors(
+            builder, self.diagonalRecurrentTensors)
+        unidirectionalSequenceLstmoptions = UnidirectionalSequenceLSTMOptionsEnd(builder)
+        return unidirectionalSequenceLstmoptions
+
+
+class BidirectionalSequenceLSTMOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = BidirectionalSequenceLSTMOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBidirectionalSequenceLSTMOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BidirectionalSequenceLSTMOptionsBufferHasIdentifier(cls,
+                                                            buf,
+                                                            offset,
+                                                            size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # BidirectionalSequenceLSTMOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # BidirectionalSequenceLSTMOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # BidirectionalSequenceLSTMOptions
+    def CellClip(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # BidirectionalSequenceLSTMOptions
+    def ProjClip(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # BidirectionalSequenceLSTMOptions
+    def MergeOutputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # BidirectionalSequenceLSTMOptions
+    def TimeMajor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return True
+
+    # BidirectionalSequenceLSTMOptions
+    def AsymmetricQuantizeInputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def BidirectionalSequenceLSTMOptionsStart(builder):
+    builder.StartObject(6)
+
+
+def BidirectionalSequenceLSTMOptionsAddFusedActivationFunction(builder,
+                                                               fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def BidirectionalSequenceLSTMOptionsAddCellClip(builder, cellClip):
+    builder.PrependFloat32Slot(1, cellClip, 0.0)
+
+
+def BidirectionalSequenceLSTMOptionsAddProjClip(builder, projClip):
+    builder.PrependFloat32Slot(2, projClip, 0.0)
+
+
+def BidirectionalSequenceLSTMOptionsAddMergeOutputs(builder, mergeOutputs):
+    builder.PrependBoolSlot(3, mergeOutputs, 0)
+
+
+def BidirectionalSequenceLSTMOptionsAddTimeMajor(builder, timeMajor):
+    builder.PrependBoolSlot(4, timeMajor, 1)
+
+
+def BidirectionalSequenceLSTMOptionsAddAsymmetricQuantizeInputs(
+        builder, asymmetricQuantizeInputs):
+    builder.PrependBoolSlot(5, asymmetricQuantizeInputs, 0)
+
+
+def BidirectionalSequenceLSTMOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class BidirectionalSequenceLSTMOptionsT(object):
+
+    # BidirectionalSequenceLSTMOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+        self.cellClip = 0.0  # type: float
+        self.projClip = 0.0  # type: float
+        self.mergeOutputs = False  # type: bool
+        self.timeMajor = True  # type: bool
+        self.asymmetricQuantizeInputs = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        bidirectionalSequenceLstmoptions = BidirectionalSequenceLSTMOptions()
+        bidirectionalSequenceLstmoptions.Init(buf, pos)
+        return cls.InitFromObj(bidirectionalSequenceLstmoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, bidirectionalSequenceLstmoptions):
+        x = BidirectionalSequenceLSTMOptionsT()
+        x._UnPack(bidirectionalSequenceLstmoptions)
+        return x
+
+    # BidirectionalSequenceLSTMOptionsT
+    def _UnPack(self, bidirectionalSequenceLstmoptions):
+        if bidirectionalSequenceLstmoptions is None:
+            return
+        self.fusedActivationFunction = bidirectionalSequenceLstmoptions.FusedActivationFunction(
+        )
+        self.cellClip = bidirectionalSequenceLstmoptions.CellClip()
+        self.projClip = bidirectionalSequenceLstmoptions.ProjClip()
+        self.mergeOutputs = bidirectionalSequenceLstmoptions.MergeOutputs()
+        self.timeMajor = bidirectionalSequenceLstmoptions.TimeMajor()
+        self.asymmetricQuantizeInputs = bidirectionalSequenceLstmoptions.AsymmetricQuantizeInputs(
+        )
+
+    # BidirectionalSequenceLSTMOptionsT
+    def Pack(self, builder):
+        BidirectionalSequenceLSTMOptionsStart(builder)
+        BidirectionalSequenceLSTMOptionsAddFusedActivationFunction(
+            builder, self.fusedActivationFunction)
+        BidirectionalSequenceLSTMOptionsAddCellClip(builder, self.cellClip)
+        BidirectionalSequenceLSTMOptionsAddProjClip(builder, self.projClip)
+        BidirectionalSequenceLSTMOptionsAddMergeOutputs(builder, self.mergeOutputs)
+        BidirectionalSequenceLSTMOptionsAddTimeMajor(builder, self.timeMajor)
+        BidirectionalSequenceLSTMOptionsAddAsymmetricQuantizeInputs(
+            builder, self.asymmetricQuantizeInputs)
+        bidirectionalSequenceLstmoptions = BidirectionalSequenceLSTMOptionsEnd(builder)
+        return bidirectionalSequenceLstmoptions
+
+
+class ResizeBilinearOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ResizeBilinearOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsResizeBilinearOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ResizeBilinearOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ResizeBilinearOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ResizeBilinearOptions
+    def AlignCorners(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # ResizeBilinearOptions
+    def HalfPixelCenters(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def ResizeBilinearOptionsStart(builder):
+    builder.StartObject(4)
+
+
+def ResizeBilinearOptionsAddAlignCorners(builder, alignCorners):
+    builder.PrependBoolSlot(2, alignCorners, 0)
+
+
+def ResizeBilinearOptionsAddHalfPixelCenters(builder, halfPixelCenters):
+    builder.PrependBoolSlot(3, halfPixelCenters, 0)
+
+
+def ResizeBilinearOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ResizeBilinearOptionsT(object):
+
+    # ResizeBilinearOptionsT
+    def __init__(self):
+        self.alignCorners = False  # type: bool
+        self.halfPixelCenters = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        resizeBilinearOptions = ResizeBilinearOptions()
+        resizeBilinearOptions.Init(buf, pos)
+        return cls.InitFromObj(resizeBilinearOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, resizeBilinearOptions):
+        x = ResizeBilinearOptionsT()
+        x._UnPack(resizeBilinearOptions)
+        return x
+
+    # ResizeBilinearOptionsT
+    def _UnPack(self, resizeBilinearOptions):
+        if resizeBilinearOptions is None:
+            return
+        self.alignCorners = resizeBilinearOptions.AlignCorners()
+        self.halfPixelCenters = resizeBilinearOptions.HalfPixelCenters()
+
+    # ResizeBilinearOptionsT
+    def Pack(self, builder):
+        ResizeBilinearOptionsStart(builder)
+        ResizeBilinearOptionsAddAlignCorners(builder, self.alignCorners)
+        ResizeBilinearOptionsAddHalfPixelCenters(builder, self.halfPixelCenters)
+        resizeBilinearOptions = ResizeBilinearOptionsEnd(builder)
+        return resizeBilinearOptions
+
+
+class ResizeNearestNeighborOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ResizeNearestNeighborOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsResizeNearestNeighborOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ResizeNearestNeighborOptionsBufferHasIdentifier(cls,
+                                                        buf,
+                                                        offset,
+                                                        size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ResizeNearestNeighborOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ResizeNearestNeighborOptions
+    def AlignCorners(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # ResizeNearestNeighborOptions
+    def HalfPixelCenters(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def ResizeNearestNeighborOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def ResizeNearestNeighborOptionsAddAlignCorners(builder, alignCorners):
+    builder.PrependBoolSlot(0, alignCorners, 0)
+
+
+def ResizeNearestNeighborOptionsAddHalfPixelCenters(builder, halfPixelCenters):
+    builder.PrependBoolSlot(1, halfPixelCenters, 0)
+
+
+def ResizeNearestNeighborOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ResizeNearestNeighborOptionsT(object):
+
+    # ResizeNearestNeighborOptionsT
+    def __init__(self):
+        self.alignCorners = False  # type: bool
+        self.halfPixelCenters = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        resizeNearestNeighborOptions = ResizeNearestNeighborOptions()
+        resizeNearestNeighborOptions.Init(buf, pos)
+        return cls.InitFromObj(resizeNearestNeighborOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, resizeNearestNeighborOptions):
+        x = ResizeNearestNeighborOptionsT()
+        x._UnPack(resizeNearestNeighborOptions)
+        return x
+
+    # ResizeNearestNeighborOptionsT
+    def _UnPack(self, resizeNearestNeighborOptions):
+        if resizeNearestNeighborOptions is None:
+            return
+        self.alignCorners = resizeNearestNeighborOptions.AlignCorners()
+        self.halfPixelCenters = resizeNearestNeighborOptions.HalfPixelCenters()
+
+    # ResizeNearestNeighborOptionsT
+    def Pack(self, builder):
+        ResizeNearestNeighborOptionsStart(builder)
+        ResizeNearestNeighborOptionsAddAlignCorners(builder, self.alignCorners)
+        ResizeNearestNeighborOptionsAddHalfPixelCenters(builder, self.halfPixelCenters)
+        resizeNearestNeighborOptions = ResizeNearestNeighborOptionsEnd(builder)
+        return resizeNearestNeighborOptions
+
+
+class CallOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = CallOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsCallOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def CallOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # CallOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # CallOptions
+    def Subgraph(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
+        return 0
+
+
+def CallOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def CallOptionsAddSubgraph(builder, subgraph):
+    builder.PrependUint32Slot(0, subgraph, 0)
+
+
+def CallOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class CallOptionsT(object):
+
+    # CallOptionsT
+    def __init__(self):
+        self.subgraph = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        callOptions = CallOptions()
+        callOptions.Init(buf, pos)
+        return cls.InitFromObj(callOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, callOptions):
+        x = CallOptionsT()
+        x._UnPack(callOptions)
+        return x
+
+    # CallOptionsT
+    def _UnPack(self, callOptions):
+        if callOptions is None:
+            return
+        self.subgraph = callOptions.Subgraph()
+
+    # CallOptionsT
+    def Pack(self, builder):
+        CallOptionsStart(builder)
+        CallOptionsAddSubgraph(builder, self.subgraph)
+        callOptions = CallOptionsEnd(builder)
+        return callOptions
+
+
+class PadOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = PadOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsPadOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def PadOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # PadOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def PadOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def PadOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class PadOptionsT(object):
+
+    # PadOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        padOptions = PadOptions()
+        padOptions.Init(buf, pos)
+        return cls.InitFromObj(padOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, padOptions):
+        x = PadOptionsT()
+        x._UnPack(padOptions)
+        return x
+
+    # PadOptionsT
+    def _UnPack(self, padOptions):
+        if padOptions is None:
+            return
+
+    # PadOptionsT
+    def Pack(self, builder):
+        PadOptionsStart(builder)
+        padOptions = PadOptionsEnd(builder)
+        return padOptions
+
+
+class PadV2Options(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = PadV2Options()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsPadV2Options(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def PadV2OptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # PadV2Options
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def PadV2OptionsStart(builder):
+    builder.StartObject(0)
+
+
+def PadV2OptionsEnd(builder):
+    return builder.EndObject()
+
+
+class PadV2OptionsT(object):
+
+    # PadV2OptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        padV2Options = PadV2Options()
+        padV2Options.Init(buf, pos)
+        return cls.InitFromObj(padV2Options)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, padV2Options):
+        x = PadV2OptionsT()
+        x._UnPack(padV2Options)
+        return x
+
+    # PadV2OptionsT
+    def _UnPack(self, padV2Options):
+        if padV2Options is None:
+            return
+
+    # PadV2OptionsT
+    def Pack(self, builder):
+        PadV2OptionsStart(builder)
+        padV2Options = PadV2OptionsEnd(builder)
+        return padV2Options
+
+
+class ReshapeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ReshapeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsReshapeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ReshapeOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ReshapeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ReshapeOptions
+    def NewShape(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # ReshapeOptions
+    def NewShapeAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # ReshapeOptions
+    def NewShapeLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # ReshapeOptions
+    def NewShapeIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+
+def ReshapeOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def ReshapeOptionsAddNewShape(builder, newShape):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(newShape), 0)
+
+
+def ReshapeOptionsStartNewShapeVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def ReshapeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class ReshapeOptionsT(object):
+
+    # ReshapeOptionsT
+    def __init__(self):
+        self.newShape = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        reshapeOptions = ReshapeOptions()
+        reshapeOptions.Init(buf, pos)
+        return cls.InitFromObj(reshapeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, reshapeOptions):
+        x = ReshapeOptionsT()
+        x._UnPack(reshapeOptions)
+        return x
+
+    # ReshapeOptionsT
+    def _UnPack(self, reshapeOptions):
+        if reshapeOptions is None:
+            return
+        if not reshapeOptions.NewShapeIsNone():
+            if np is None:
+                self.newShape = []
+                for i in range(reshapeOptions.NewShapeLength()):
+                    self.newShape.append(reshapeOptions.NewShape(i))
+            else:
+                self.newShape = reshapeOptions.NewShapeAsNumpy()
+
+    # ReshapeOptionsT
+    def Pack(self, builder):
+        if self.newShape is not None:
+            if np is not None and type(self.newShape) is np.ndarray:
+                newShape = builder.CreateNumpyVector(self.newShape)
+            else:
+                ReshapeOptionsStartNewShapeVector(builder, len(self.newShape))
+                for i in reversed(range(len(self.newShape))):
+                    builder.PrependInt32(self.newShape[i])
+                newShape = builder.EndVector()
+        ReshapeOptionsStart(builder)
+        if self.newShape is not None:
+            ReshapeOptionsAddNewShape(builder, newShape)
+        reshapeOptions = ReshapeOptionsEnd(builder)
+        return reshapeOptions
+
+
+class SpaceToBatchNDOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SpaceToBatchNDOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSpaceToBatchNDOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SpaceToBatchNDOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SpaceToBatchNDOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def SpaceToBatchNDOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def SpaceToBatchNDOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SpaceToBatchNDOptionsT(object):
+
+    # SpaceToBatchNDOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        spaceToBatchNdoptions = SpaceToBatchNDOptions()
+        spaceToBatchNdoptions.Init(buf, pos)
+        return cls.InitFromObj(spaceToBatchNdoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, spaceToBatchNdoptions):
+        x = SpaceToBatchNDOptionsT()
+        x._UnPack(spaceToBatchNdoptions)
+        return x
+
+    # SpaceToBatchNDOptionsT
+    def _UnPack(self, spaceToBatchNdoptions):
+        if spaceToBatchNdoptions is None:
+            return
+
+    # SpaceToBatchNDOptionsT
+    def Pack(self, builder):
+        SpaceToBatchNDOptionsStart(builder)
+        spaceToBatchNdoptions = SpaceToBatchNDOptionsEnd(builder)
+        return spaceToBatchNdoptions
+
+
+class BatchToSpaceNDOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = BatchToSpaceNDOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBatchToSpaceNDOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BatchToSpaceNDOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # BatchToSpaceNDOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def BatchToSpaceNDOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def BatchToSpaceNDOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class BatchToSpaceNDOptionsT(object):
+
+    # BatchToSpaceNDOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        batchToSpaceNdoptions = BatchToSpaceNDOptions()
+        batchToSpaceNdoptions.Init(buf, pos)
+        return cls.InitFromObj(batchToSpaceNdoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, batchToSpaceNdoptions):
+        x = BatchToSpaceNDOptionsT()
+        x._UnPack(batchToSpaceNdoptions)
+        return x
+
+    # BatchToSpaceNDOptionsT
+    def _UnPack(self, batchToSpaceNdoptions):
+        if batchToSpaceNdoptions is None:
+            return
+
+    # BatchToSpaceNDOptionsT
+    def Pack(self, builder):
+        BatchToSpaceNDOptionsStart(builder)
+        batchToSpaceNdoptions = BatchToSpaceNDOptionsEnd(builder)
+        return batchToSpaceNdoptions
+
+
+class SkipGramOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SkipGramOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSkipGramOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SkipGramOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SkipGramOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SkipGramOptions
+    def NgramSize(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # SkipGramOptions
+    def MaxSkipSize(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # SkipGramOptions
+    def IncludeAllNgrams(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def SkipGramOptionsStart(builder):
+    builder.StartObject(3)
+
+
+def SkipGramOptionsAddNgramSize(builder, ngramSize):
+    builder.PrependInt32Slot(0, ngramSize, 0)
+
+
+def SkipGramOptionsAddMaxSkipSize(builder, maxSkipSize):
+    builder.PrependInt32Slot(1, maxSkipSize, 0)
+
+
+def SkipGramOptionsAddIncludeAllNgrams(builder, includeAllNgrams):
+    builder.PrependBoolSlot(2, includeAllNgrams, 0)
+
+
+def SkipGramOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SkipGramOptionsT(object):
+
+    # SkipGramOptionsT
+    def __init__(self):
+        self.ngramSize = 0  # type: int
+        self.maxSkipSize = 0  # type: int
+        self.includeAllNgrams = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        skipGramOptions = SkipGramOptions()
+        skipGramOptions.Init(buf, pos)
+        return cls.InitFromObj(skipGramOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, skipGramOptions):
+        x = SkipGramOptionsT()
+        x._UnPack(skipGramOptions)
+        return x
+
+    # SkipGramOptionsT
+    def _UnPack(self, skipGramOptions):
+        if skipGramOptions is None:
+            return
+        self.ngramSize = skipGramOptions.NgramSize()
+        self.maxSkipSize = skipGramOptions.MaxSkipSize()
+        self.includeAllNgrams = skipGramOptions.IncludeAllNgrams()
+
+    # SkipGramOptionsT
+    def Pack(self, builder):
+        SkipGramOptionsStart(builder)
+        SkipGramOptionsAddNgramSize(builder, self.ngramSize)
+        SkipGramOptionsAddMaxSkipSize(builder, self.maxSkipSize)
+        SkipGramOptionsAddIncludeAllNgrams(builder, self.includeAllNgrams)
+        skipGramOptions = SkipGramOptionsEnd(builder)
+        return skipGramOptions
+
+
+class SpaceToDepthOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SpaceToDepthOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSpaceToDepthOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SpaceToDepthOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SpaceToDepthOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SpaceToDepthOptions
+    def BlockSize(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def SpaceToDepthOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def SpaceToDepthOptionsAddBlockSize(builder, blockSize):
+    builder.PrependInt32Slot(0, blockSize, 0)
+
+
+def SpaceToDepthOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SpaceToDepthOptionsT(object):
+
+    # SpaceToDepthOptionsT
+    def __init__(self):
+        self.blockSize = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        spaceToDepthOptions = SpaceToDepthOptions()
+        spaceToDepthOptions.Init(buf, pos)
+        return cls.InitFromObj(spaceToDepthOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, spaceToDepthOptions):
+        x = SpaceToDepthOptionsT()
+        x._UnPack(spaceToDepthOptions)
+        return x
+
+    # SpaceToDepthOptionsT
+    def _UnPack(self, spaceToDepthOptions):
+        if spaceToDepthOptions is None:
+            return
+        self.blockSize = spaceToDepthOptions.BlockSize()
+
+    # SpaceToDepthOptionsT
+    def Pack(self, builder):
+        SpaceToDepthOptionsStart(builder)
+        SpaceToDepthOptionsAddBlockSize(builder, self.blockSize)
+        spaceToDepthOptions = SpaceToDepthOptionsEnd(builder)
+        return spaceToDepthOptions
+
+
+class DepthToSpaceOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = DepthToSpaceOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsDepthToSpaceOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def DepthToSpaceOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # DepthToSpaceOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # DepthToSpaceOptions
+    def BlockSize(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def DepthToSpaceOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def DepthToSpaceOptionsAddBlockSize(builder, blockSize):
+    builder.PrependInt32Slot(0, blockSize, 0)
+
+
+def DepthToSpaceOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class DepthToSpaceOptionsT(object):
+
+    # DepthToSpaceOptionsT
+    def __init__(self):
+        self.blockSize = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        depthToSpaceOptions = DepthToSpaceOptions()
+        depthToSpaceOptions.Init(buf, pos)
+        return cls.InitFromObj(depthToSpaceOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, depthToSpaceOptions):
+        x = DepthToSpaceOptionsT()
+        x._UnPack(depthToSpaceOptions)
+        return x
+
+    # DepthToSpaceOptionsT
+    def _UnPack(self, depthToSpaceOptions):
+        if depthToSpaceOptions is None:
+            return
+        self.blockSize = depthToSpaceOptions.BlockSize()
+
+    # DepthToSpaceOptionsT
+    def Pack(self, builder):
+        DepthToSpaceOptionsStart(builder)
+        DepthToSpaceOptionsAddBlockSize(builder, self.blockSize)
+        depthToSpaceOptions = DepthToSpaceOptionsEnd(builder)
+        return depthToSpaceOptions
+
+
+class SubOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SubOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSubOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SubOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SubOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SubOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # SubOptions
+    def PotScaleInt16(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return True
+
+
+def SubOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def SubOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def SubOptionsAddPotScaleInt16(builder, potScaleInt16):
+    builder.PrependBoolSlot(1, potScaleInt16, 1)
+
+
+def SubOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SubOptionsT(object):
+
+    # SubOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+        self.potScaleInt16 = True  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        subOptions = SubOptions()
+        subOptions.Init(buf, pos)
+        return cls.InitFromObj(subOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, subOptions):
+        x = SubOptionsT()
+        x._UnPack(subOptions)
+        return x
+
+    # SubOptionsT
+    def _UnPack(self, subOptions):
+        if subOptions is None:
+            return
+        self.fusedActivationFunction = subOptions.FusedActivationFunction()
+        self.potScaleInt16 = subOptions.PotScaleInt16()
+
+    # SubOptionsT
+    def Pack(self, builder):
+        SubOptionsStart(builder)
+        SubOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        SubOptionsAddPotScaleInt16(builder, self.potScaleInt16)
+        subOptions = SubOptionsEnd(builder)
+        return subOptions
+
+
+class DivOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = DivOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsDivOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def DivOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # DivOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # DivOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def DivOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def DivOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def DivOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class DivOptionsT(object):
+
+    # DivOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        divOptions = DivOptions()
+        divOptions.Init(buf, pos)
+        return cls.InitFromObj(divOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, divOptions):
+        x = DivOptionsT()
+        x._UnPack(divOptions)
+        return x
+
+    # DivOptionsT
+    def _UnPack(self, divOptions):
+        if divOptions is None:
+            return
+        self.fusedActivationFunction = divOptions.FusedActivationFunction()
+
+    # DivOptionsT
+    def Pack(self, builder):
+        DivOptionsStart(builder)
+        DivOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        divOptions = DivOptionsEnd(builder)
+        return divOptions
+
+
+class TopKV2Options(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = TopKV2Options()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsTopKV2Options(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def TopKV2OptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # TopKV2Options
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def TopKV2OptionsStart(builder):
+    builder.StartObject(0)
+
+
+def TopKV2OptionsEnd(builder):
+    return builder.EndObject()
+
+
+class TopKV2OptionsT(object):
+
+    # TopKV2OptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        topKv2Options = TopKV2Options()
+        topKv2Options.Init(buf, pos)
+        return cls.InitFromObj(topKv2Options)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, topKv2Options):
+        x = TopKV2OptionsT()
+        x._UnPack(topKv2Options)
+        return x
+
+    # TopKV2OptionsT
+    def _UnPack(self, topKv2Options):
+        if topKv2Options is None:
+            return
+
+    # TopKV2OptionsT
+    def Pack(self, builder):
+        TopKV2OptionsStart(builder)
+        topKv2Options = TopKV2OptionsEnd(builder)
+        return topKv2Options
+
+
+class EmbeddingLookupSparseOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = EmbeddingLookupSparseOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsEmbeddingLookupSparseOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def EmbeddingLookupSparseOptionsBufferHasIdentifier(cls,
+                                                        buf,
+                                                        offset,
+                                                        size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # EmbeddingLookupSparseOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # EmbeddingLookupSparseOptions
+    def Combiner(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def EmbeddingLookupSparseOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def EmbeddingLookupSparseOptionsAddCombiner(builder, combiner):
+    builder.PrependInt8Slot(0, combiner, 0)
+
+
+def EmbeddingLookupSparseOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class EmbeddingLookupSparseOptionsT(object):
+
+    # EmbeddingLookupSparseOptionsT
+    def __init__(self):
+        self.combiner = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        embeddingLookupSparseOptions = EmbeddingLookupSparseOptions()
+        embeddingLookupSparseOptions.Init(buf, pos)
+        return cls.InitFromObj(embeddingLookupSparseOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, embeddingLookupSparseOptions):
+        x = EmbeddingLookupSparseOptionsT()
+        x._UnPack(embeddingLookupSparseOptions)
+        return x
+
+    # EmbeddingLookupSparseOptionsT
+    def _UnPack(self, embeddingLookupSparseOptions):
+        if embeddingLookupSparseOptions is None:
+            return
+        self.combiner = embeddingLookupSparseOptions.Combiner()
+
+    # EmbeddingLookupSparseOptionsT
+    def Pack(self, builder):
+        EmbeddingLookupSparseOptionsStart(builder)
+        EmbeddingLookupSparseOptionsAddCombiner(builder, self.combiner)
+        embeddingLookupSparseOptions = EmbeddingLookupSparseOptionsEnd(builder)
+        return embeddingLookupSparseOptions
+
+
+class GatherOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = GatherOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsGatherOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def GatherOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # GatherOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # GatherOptions
+    def Axis(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # GatherOptions
+    def BatchDims(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def GatherOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def GatherOptionsAddAxis(builder, axis):
+    builder.PrependInt32Slot(0, axis, 0)
+
+
+def GatherOptionsAddBatchDims(builder, batchDims):
+    builder.PrependInt32Slot(1, batchDims, 0)
+
+
+def GatherOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class GatherOptionsT(object):
+
+    # GatherOptionsT
+    def __init__(self):
+        self.axis = 0  # type: int
+        self.batchDims = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        gatherOptions = GatherOptions()
+        gatherOptions.Init(buf, pos)
+        return cls.InitFromObj(gatherOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, gatherOptions):
+        x = GatherOptionsT()
+        x._UnPack(gatherOptions)
+        return x
+
+    # GatherOptionsT
+    def _UnPack(self, gatherOptions):
+        if gatherOptions is None:
+            return
+        self.axis = gatherOptions.Axis()
+        self.batchDims = gatherOptions.BatchDims()
+
+    # GatherOptionsT
+    def Pack(self, builder):
+        GatherOptionsStart(builder)
+        GatherOptionsAddAxis(builder, self.axis)
+        GatherOptionsAddBatchDims(builder, self.batchDims)
+        gatherOptions = GatherOptionsEnd(builder)
+        return gatherOptions
+
+
+class TransposeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = TransposeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsTransposeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def TransposeOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # TransposeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def TransposeOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def TransposeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class TransposeOptionsT(object):
+
+    # TransposeOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        transposeOptions = TransposeOptions()
+        transposeOptions.Init(buf, pos)
+        return cls.InitFromObj(transposeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, transposeOptions):
+        x = TransposeOptionsT()
+        x._UnPack(transposeOptions)
+        return x
+
+    # TransposeOptionsT
+    def _UnPack(self, transposeOptions):
+        if transposeOptions is None:
+            return
+
+    # TransposeOptionsT
+    def Pack(self, builder):
+        TransposeOptionsStart(builder)
+        transposeOptions = TransposeOptionsEnd(builder)
+        return transposeOptions
+
+
+class ExpOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ExpOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsExpOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ExpOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ExpOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def ExpOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def ExpOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ExpOptionsT(object):
+
+    # ExpOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        expOptions = ExpOptions()
+        expOptions.Init(buf, pos)
+        return cls.InitFromObj(expOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, expOptions):
+        x = ExpOptionsT()
+        x._UnPack(expOptions)
+        return x
+
+    # ExpOptionsT
+    def _UnPack(self, expOptions):
+        if expOptions is None:
+            return
+
+    # ExpOptionsT
+    def Pack(self, builder):
+        ExpOptionsStart(builder)
+        expOptions = ExpOptionsEnd(builder)
+        return expOptions
+
+
+class CosOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = CosOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsCosOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def CosOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # CosOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def CosOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def CosOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class CosOptionsT(object):
+
+    # CosOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        cosOptions = CosOptions()
+        cosOptions.Init(buf, pos)
+        return cls.InitFromObj(cosOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, cosOptions):
+        x = CosOptionsT()
+        x._UnPack(cosOptions)
+        return x
+
+    # CosOptionsT
+    def _UnPack(self, cosOptions):
+        if cosOptions is None:
+            return
+
+    # CosOptionsT
+    def Pack(self, builder):
+        CosOptionsStart(builder)
+        cosOptions = CosOptionsEnd(builder)
+        return cosOptions
+
+
+class ReducerOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ReducerOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsReducerOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ReducerOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ReducerOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ReducerOptions
+    def KeepDims(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def ReducerOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def ReducerOptionsAddKeepDims(builder, keepDims):
+    builder.PrependBoolSlot(0, keepDims, 0)
+
+
+def ReducerOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ReducerOptionsT(object):
+
+    # ReducerOptionsT
+    def __init__(self):
+        self.keepDims = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        reducerOptions = ReducerOptions()
+        reducerOptions.Init(buf, pos)
+        return cls.InitFromObj(reducerOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, reducerOptions):
+        x = ReducerOptionsT()
+        x._UnPack(reducerOptions)
+        return x
+
+    # ReducerOptionsT
+    def _UnPack(self, reducerOptions):
+        if reducerOptions is None:
+            return
+        self.keepDims = reducerOptions.KeepDims()
+
+    # ReducerOptionsT
+    def Pack(self, builder):
+        ReducerOptionsStart(builder)
+        ReducerOptionsAddKeepDims(builder, self.keepDims)
+        reducerOptions = ReducerOptionsEnd(builder)
+        return reducerOptions
+
+
+class SqueezeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SqueezeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSqueezeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SqueezeOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SqueezeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SqueezeOptions
+    def SqueezeDims(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # SqueezeOptions
+    def SqueezeDimsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # SqueezeOptions
+    def SqueezeDimsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # SqueezeOptions
+    def SqueezeDimsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+
+def SqueezeOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def SqueezeOptionsAddSqueezeDims(builder, squeezeDims):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(squeezeDims), 0)
+
+
+def SqueezeOptionsStartSqueezeDimsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def SqueezeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class SqueezeOptionsT(object):
+
+    # SqueezeOptionsT
+    def __init__(self):
+        self.squeezeDims = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        squeezeOptions = SqueezeOptions()
+        squeezeOptions.Init(buf, pos)
+        return cls.InitFromObj(squeezeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, squeezeOptions):
+        x = SqueezeOptionsT()
+        x._UnPack(squeezeOptions)
+        return x
+
+    # SqueezeOptionsT
+    def _UnPack(self, squeezeOptions):
+        if squeezeOptions is None:
+            return
+        if not squeezeOptions.SqueezeDimsIsNone():
+            if np is None:
+                self.squeezeDims = []
+                for i in range(squeezeOptions.SqueezeDimsLength()):
+                    self.squeezeDims.append(squeezeOptions.SqueezeDims(i))
+            else:
+                self.squeezeDims = squeezeOptions.SqueezeDimsAsNumpy()
+
+    # SqueezeOptionsT
+    def Pack(self, builder):
+        if self.squeezeDims is not None:
+            if np is not None and type(self.squeezeDims) is np.ndarray:
+                squeezeDims = builder.CreateNumpyVector(self.squeezeDims)
+            else:
+                SqueezeOptionsStartSqueezeDimsVector(builder, len(self.squeezeDims))
+                for i in reversed(range(len(self.squeezeDims))):
+                    builder.PrependInt32(self.squeezeDims[i])
+                squeezeDims = builder.EndVector()
+        SqueezeOptionsStart(builder)
+        if self.squeezeDims is not None:
+            SqueezeOptionsAddSqueezeDims(builder, squeezeDims)
+        squeezeOptions = SqueezeOptionsEnd(builder)
+        return squeezeOptions
+
+
+class SplitOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SplitOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSplitOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SplitOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SplitOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SplitOptions
+    def NumSplits(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def SplitOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def SplitOptionsAddNumSplits(builder, numSplits):
+    builder.PrependInt32Slot(0, numSplits, 0)
+
+
+def SplitOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SplitOptionsT(object):
+
+    # SplitOptionsT
+    def __init__(self):
+        self.numSplits = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        splitOptions = SplitOptions()
+        splitOptions.Init(buf, pos)
+        return cls.InitFromObj(splitOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, splitOptions):
+        x = SplitOptionsT()
+        x._UnPack(splitOptions)
+        return x
+
+    # SplitOptionsT
+    def _UnPack(self, splitOptions):
+        if splitOptions is None:
+            return
+        self.numSplits = splitOptions.NumSplits()
+
+    # SplitOptionsT
+    def Pack(self, builder):
+        SplitOptionsStart(builder)
+        SplitOptionsAddNumSplits(builder, self.numSplits)
+        splitOptions = SplitOptionsEnd(builder)
+        return splitOptions
+
+
+class SplitVOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SplitVOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSplitVOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SplitVOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SplitVOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SplitVOptions
+    def NumSplits(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def SplitVOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def SplitVOptionsAddNumSplits(builder, numSplits):
+    builder.PrependInt32Slot(0, numSplits, 0)
+
+
+def SplitVOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SplitVOptionsT(object):
+
+    # SplitVOptionsT
+    def __init__(self):
+        self.numSplits = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        splitVoptions = SplitVOptions()
+        splitVoptions.Init(buf, pos)
+        return cls.InitFromObj(splitVoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, splitVoptions):
+        x = SplitVOptionsT()
+        x._UnPack(splitVoptions)
+        return x
+
+    # SplitVOptionsT
+    def _UnPack(self, splitVoptions):
+        if splitVoptions is None:
+            return
+        self.numSplits = splitVoptions.NumSplits()
+
+    # SplitVOptionsT
+    def Pack(self, builder):
+        SplitVOptionsStart(builder)
+        SplitVOptionsAddNumSplits(builder, self.numSplits)
+        splitVoptions = SplitVOptionsEnd(builder)
+        return splitVoptions
+
+
+class StridedSliceOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = StridedSliceOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsStridedSliceOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def StridedSliceOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # StridedSliceOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # StridedSliceOptions
+    def BeginMask(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # StridedSliceOptions
+    def EndMask(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # StridedSliceOptions
+    def EllipsisMask(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # StridedSliceOptions
+    def NewAxisMask(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # StridedSliceOptions
+    def ShrinkAxisMask(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # StridedSliceOptions
+    def Offset(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def StridedSliceOptionsStart(builder):
+    builder.StartObject(6)
+
+
+def StridedSliceOptionsAddBeginMask(builder, beginMask):
+    builder.PrependInt32Slot(0, beginMask, 0)
+
+
+def StridedSliceOptionsAddEndMask(builder, endMask):
+    builder.PrependInt32Slot(1, endMask, 0)
+
+
+def StridedSliceOptionsAddEllipsisMask(builder, ellipsisMask):
+    builder.PrependInt32Slot(2, ellipsisMask, 0)
+
+
+def StridedSliceOptionsAddNewAxisMask(builder, newAxisMask):
+    builder.PrependInt32Slot(3, newAxisMask, 0)
+
+
+def StridedSliceOptionsAddShrinkAxisMask(builder, shrinkAxisMask):
+    builder.PrependInt32Slot(4, shrinkAxisMask, 0)
+
+
+def StridedSliceOptionsAddOffset(builder, offset):
+    builder.PrependBoolSlot(5, offset, 0)
+
+
+def StridedSliceOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class StridedSliceOptionsT(object):
+
+    # StridedSliceOptionsT
+    def __init__(self):
+        self.beginMask = 0  # type: int
+        self.endMask = 0  # type: int
+        self.ellipsisMask = 0  # type: int
+        self.newAxisMask = 0  # type: int
+        self.shrinkAxisMask = 0  # type: int
+        self.offset = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        stridedSliceOptions = StridedSliceOptions()
+        stridedSliceOptions.Init(buf, pos)
+        return cls.InitFromObj(stridedSliceOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, stridedSliceOptions):
+        x = StridedSliceOptionsT()
+        x._UnPack(stridedSliceOptions)
+        return x
+
+    # StridedSliceOptionsT
+    def _UnPack(self, stridedSliceOptions):
+        if stridedSliceOptions is None:
+            return
+        self.beginMask = stridedSliceOptions.BeginMask()
+        self.endMask = stridedSliceOptions.EndMask()
+        self.ellipsisMask = stridedSliceOptions.EllipsisMask()
+        self.newAxisMask = stridedSliceOptions.NewAxisMask()
+        self.shrinkAxisMask = stridedSliceOptions.ShrinkAxisMask()
+        self.offset = stridedSliceOptions.Offset()
+
+    # StridedSliceOptionsT
+    def Pack(self, builder):
+        StridedSliceOptionsStart(builder)
+        StridedSliceOptionsAddBeginMask(builder, self.beginMask)
+        StridedSliceOptionsAddEndMask(builder, self.endMask)
+        StridedSliceOptionsAddEllipsisMask(builder, self.ellipsisMask)
+        StridedSliceOptionsAddNewAxisMask(builder, self.newAxisMask)
+        StridedSliceOptionsAddShrinkAxisMask(builder, self.shrinkAxisMask)
+        StridedSliceOptionsAddOffset(builder, self.offset)
+        stridedSliceOptions = StridedSliceOptionsEnd(builder)
+        return stridedSliceOptions
+
+
+class LogSoftmaxOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = LogSoftmaxOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsLogSoftmaxOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def LogSoftmaxOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # LogSoftmaxOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def LogSoftmaxOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def LogSoftmaxOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class LogSoftmaxOptionsT(object):
+
+    # LogSoftmaxOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        logSoftmaxOptions = LogSoftmaxOptions()
+        logSoftmaxOptions.Init(buf, pos)
+        return cls.InitFromObj(logSoftmaxOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, logSoftmaxOptions):
+        x = LogSoftmaxOptionsT()
+        x._UnPack(logSoftmaxOptions)
+        return x
+
+    # LogSoftmaxOptionsT
+    def _UnPack(self, logSoftmaxOptions):
+        if logSoftmaxOptions is None:
+            return
+
+    # LogSoftmaxOptionsT
+    def Pack(self, builder):
+        LogSoftmaxOptionsStart(builder)
+        logSoftmaxOptions = LogSoftmaxOptionsEnd(builder)
+        return logSoftmaxOptions
+
+
+class CastOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = CastOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsCastOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def CastOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # CastOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # CastOptions
+    def InDataType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # CastOptions
+    def OutDataType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def CastOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def CastOptionsAddInDataType(builder, inDataType):
+    builder.PrependInt8Slot(0, inDataType, 0)
+
+
+def CastOptionsAddOutDataType(builder, outDataType):
+    builder.PrependInt8Slot(1, outDataType, 0)
+
+
+def CastOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class CastOptionsT(object):
+
+    # CastOptionsT
+    def __init__(self):
+        self.inDataType = 0  # type: int
+        self.outDataType = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        castOptions = CastOptions()
+        castOptions.Init(buf, pos)
+        return cls.InitFromObj(castOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, castOptions):
+        x = CastOptionsT()
+        x._UnPack(castOptions)
+        return x
+
+    # CastOptionsT
+    def _UnPack(self, castOptions):
+        if castOptions is None:
+            return
+        self.inDataType = castOptions.InDataType()
+        self.outDataType = castOptions.OutDataType()
+
+    # CastOptionsT
+    def Pack(self, builder):
+        CastOptionsStart(builder)
+        CastOptionsAddInDataType(builder, self.inDataType)
+        CastOptionsAddOutDataType(builder, self.outDataType)
+        castOptions = CastOptionsEnd(builder)
+        return castOptions
+
+
+class DequantizeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = DequantizeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsDequantizeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def DequantizeOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # DequantizeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def DequantizeOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def DequantizeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class DequantizeOptionsT(object):
+
+    # DequantizeOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        dequantizeOptions = DequantizeOptions()
+        dequantizeOptions.Init(buf, pos)
+        return cls.InitFromObj(dequantizeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, dequantizeOptions):
+        x = DequantizeOptionsT()
+        x._UnPack(dequantizeOptions)
+        return x
+
+    # DequantizeOptionsT
+    def _UnPack(self, dequantizeOptions):
+        if dequantizeOptions is None:
+            return
+
+    # DequantizeOptionsT
+    def Pack(self, builder):
+        DequantizeOptionsStart(builder)
+        dequantizeOptions = DequantizeOptionsEnd(builder)
+        return dequantizeOptions
+
+
+class MaximumMinimumOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = MaximumMinimumOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsMaximumMinimumOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def MaximumMinimumOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # MaximumMinimumOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def MaximumMinimumOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def MaximumMinimumOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class MaximumMinimumOptionsT(object):
+
+    # MaximumMinimumOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        maximumMinimumOptions = MaximumMinimumOptions()
+        maximumMinimumOptions.Init(buf, pos)
+        return cls.InitFromObj(maximumMinimumOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, maximumMinimumOptions):
+        x = MaximumMinimumOptionsT()
+        x._UnPack(maximumMinimumOptions)
+        return x
+
+    # MaximumMinimumOptionsT
+    def _UnPack(self, maximumMinimumOptions):
+        if maximumMinimumOptions is None:
+            return
+
+    # MaximumMinimumOptionsT
+    def Pack(self, builder):
+        MaximumMinimumOptionsStart(builder)
+        maximumMinimumOptions = MaximumMinimumOptionsEnd(builder)
+        return maximumMinimumOptions
+
+
+class TileOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = TileOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsTileOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def TileOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # TileOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def TileOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def TileOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class TileOptionsT(object):
+
+    # TileOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        tileOptions = TileOptions()
+        tileOptions.Init(buf, pos)
+        return cls.InitFromObj(tileOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, tileOptions):
+        x = TileOptionsT()
+        x._UnPack(tileOptions)
+        return x
+
+    # TileOptionsT
+    def _UnPack(self, tileOptions):
+        if tileOptions is None:
+            return
+
+    # TileOptionsT
+    def Pack(self, builder):
+        TileOptionsStart(builder)
+        tileOptions = TileOptionsEnd(builder)
+        return tileOptions
+
+
+class ArgMaxOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ArgMaxOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsArgMaxOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ArgMaxOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ArgMaxOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ArgMaxOptions
+    def OutputType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def ArgMaxOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def ArgMaxOptionsAddOutputType(builder, outputType):
+    builder.PrependInt8Slot(0, outputType, 0)
+
+
+def ArgMaxOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ArgMaxOptionsT(object):
+
+    # ArgMaxOptionsT
+    def __init__(self):
+        self.outputType = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        argMaxOptions = ArgMaxOptions()
+        argMaxOptions.Init(buf, pos)
+        return cls.InitFromObj(argMaxOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, argMaxOptions):
+        x = ArgMaxOptionsT()
+        x._UnPack(argMaxOptions)
+        return x
+
+    # ArgMaxOptionsT
+    def _UnPack(self, argMaxOptions):
+        if argMaxOptions is None:
+            return
+        self.outputType = argMaxOptions.OutputType()
+
+    # ArgMaxOptionsT
+    def Pack(self, builder):
+        ArgMaxOptionsStart(builder)
+        ArgMaxOptionsAddOutputType(builder, self.outputType)
+        argMaxOptions = ArgMaxOptionsEnd(builder)
+        return argMaxOptions
+
+
+class ArgMinOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ArgMinOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsArgMinOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ArgMinOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ArgMinOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ArgMinOptions
+    def OutputType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def ArgMinOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def ArgMinOptionsAddOutputType(builder, outputType):
+    builder.PrependInt8Slot(0, outputType, 0)
+
+
+def ArgMinOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ArgMinOptionsT(object):
+
+    # ArgMinOptionsT
+    def __init__(self):
+        self.outputType = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        argMinOptions = ArgMinOptions()
+        argMinOptions.Init(buf, pos)
+        return cls.InitFromObj(argMinOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, argMinOptions):
+        x = ArgMinOptionsT()
+        x._UnPack(argMinOptions)
+        return x
+
+    # ArgMinOptionsT
+    def _UnPack(self, argMinOptions):
+        if argMinOptions is None:
+            return
+        self.outputType = argMinOptions.OutputType()
+
+    # ArgMinOptionsT
+    def Pack(self, builder):
+        ArgMinOptionsStart(builder)
+        ArgMinOptionsAddOutputType(builder, self.outputType)
+        argMinOptions = ArgMinOptionsEnd(builder)
+        return argMinOptions
+
+
+class GreaterOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = GreaterOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsGreaterOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def GreaterOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # GreaterOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def GreaterOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def GreaterOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class GreaterOptionsT(object):
+
+    # GreaterOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        greaterOptions = GreaterOptions()
+        greaterOptions.Init(buf, pos)
+        return cls.InitFromObj(greaterOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, greaterOptions):
+        x = GreaterOptionsT()
+        x._UnPack(greaterOptions)
+        return x
+
+    # GreaterOptionsT
+    def _UnPack(self, greaterOptions):
+        if greaterOptions is None:
+            return
+
+    # GreaterOptionsT
+    def Pack(self, builder):
+        GreaterOptionsStart(builder)
+        greaterOptions = GreaterOptionsEnd(builder)
+        return greaterOptions
+
+
+class GreaterEqualOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = GreaterEqualOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsGreaterEqualOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def GreaterEqualOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # GreaterEqualOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def GreaterEqualOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def GreaterEqualOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class GreaterEqualOptionsT(object):
+
+    # GreaterEqualOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        greaterEqualOptions = GreaterEqualOptions()
+        greaterEqualOptions.Init(buf, pos)
+        return cls.InitFromObj(greaterEqualOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, greaterEqualOptions):
+        x = GreaterEqualOptionsT()
+        x._UnPack(greaterEqualOptions)
+        return x
+
+    # GreaterEqualOptionsT
+    def _UnPack(self, greaterEqualOptions):
+        if greaterEqualOptions is None:
+            return
+
+    # GreaterEqualOptionsT
+    def Pack(self, builder):
+        GreaterEqualOptionsStart(builder)
+        greaterEqualOptions = GreaterEqualOptionsEnd(builder)
+        return greaterEqualOptions
+
+
+class LessOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = LessOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsLessOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def LessOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # LessOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def LessOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def LessOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class LessOptionsT(object):
+
+    # LessOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        lessOptions = LessOptions()
+        lessOptions.Init(buf, pos)
+        return cls.InitFromObj(lessOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, lessOptions):
+        x = LessOptionsT()
+        x._UnPack(lessOptions)
+        return x
+
+    # LessOptionsT
+    def _UnPack(self, lessOptions):
+        if lessOptions is None:
+            return
+
+    # LessOptionsT
+    def Pack(self, builder):
+        LessOptionsStart(builder)
+        lessOptions = LessOptionsEnd(builder)
+        return lessOptions
+
+
+class LessEqualOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = LessEqualOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsLessEqualOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def LessEqualOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # LessEqualOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def LessEqualOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def LessEqualOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class LessEqualOptionsT(object):
+
+    # LessEqualOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        lessEqualOptions = LessEqualOptions()
+        lessEqualOptions.Init(buf, pos)
+        return cls.InitFromObj(lessEqualOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, lessEqualOptions):
+        x = LessEqualOptionsT()
+        x._UnPack(lessEqualOptions)
+        return x
+
+    # LessEqualOptionsT
+    def _UnPack(self, lessEqualOptions):
+        if lessEqualOptions is None:
+            return
+
+    # LessEqualOptionsT
+    def Pack(self, builder):
+        LessEqualOptionsStart(builder)
+        lessEqualOptions = LessEqualOptionsEnd(builder)
+        return lessEqualOptions
+
+
+class NegOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = NegOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsNegOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def NegOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # NegOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def NegOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def NegOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class NegOptionsT(object):
+
+    # NegOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        negOptions = NegOptions()
+        negOptions.Init(buf, pos)
+        return cls.InitFromObj(negOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, negOptions):
+        x = NegOptionsT()
+        x._UnPack(negOptions)
+        return x
+
+    # NegOptionsT
+    def _UnPack(self, negOptions):
+        if negOptions is None:
+            return
+
+    # NegOptionsT
+    def Pack(self, builder):
+        NegOptionsStart(builder)
+        negOptions = NegOptionsEnd(builder)
+        return negOptions
+
+
+class SelectOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SelectOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSelectOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SelectOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SelectOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def SelectOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def SelectOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SelectOptionsT(object):
+
+    # SelectOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        selectOptions = SelectOptions()
+        selectOptions.Init(buf, pos)
+        return cls.InitFromObj(selectOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, selectOptions):
+        x = SelectOptionsT()
+        x._UnPack(selectOptions)
+        return x
+
+    # SelectOptionsT
+    def _UnPack(self, selectOptions):
+        if selectOptions is None:
+            return
+
+    # SelectOptionsT
+    def Pack(self, builder):
+        SelectOptionsStart(builder)
+        selectOptions = SelectOptionsEnd(builder)
+        return selectOptions
+
+
+class SliceOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SliceOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSliceOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SliceOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SliceOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def SliceOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def SliceOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SliceOptionsT(object):
+
+    # SliceOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        sliceOptions = SliceOptions()
+        sliceOptions.Init(buf, pos)
+        return cls.InitFromObj(sliceOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, sliceOptions):
+        x = SliceOptionsT()
+        x._UnPack(sliceOptions)
+        return x
+
+    # SliceOptionsT
+    def _UnPack(self, sliceOptions):
+        if sliceOptions is None:
+            return
+
+    # SliceOptionsT
+    def Pack(self, builder):
+        SliceOptionsStart(builder)
+        sliceOptions = SliceOptionsEnd(builder)
+        return sliceOptions
+
+
+class TransposeConvOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = TransposeConvOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsTransposeConvOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def TransposeConvOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # TransposeConvOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # TransposeConvOptions
+    def Padding(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # TransposeConvOptions
+    def StrideW(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # TransposeConvOptions
+    def StrideH(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # TransposeConvOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # TransposeConvOptions
+    def QuantizedBiasType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def TransposeConvOptionsStart(builder):
+    builder.StartObject(5)
+
+
+def TransposeConvOptionsAddPadding(builder, padding):
+    builder.PrependInt8Slot(0, padding, 0)
+
+
+def TransposeConvOptionsAddStrideW(builder, strideW):
+    builder.PrependInt32Slot(1, strideW, 0)
+
+
+def TransposeConvOptionsAddStrideH(builder, strideH):
+    builder.PrependInt32Slot(2, strideH, 0)
+
+
+def TransposeConvOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(3, fusedActivationFunction, 0)
+
+
+def TransposeConvOptionsAddQuantizedBiasType(builder, quantizedBiasType):
+    builder.PrependInt8Slot(4, quantizedBiasType, 0)
+
+
+def TransposeConvOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class TransposeConvOptionsT(object):
+
+    # TransposeConvOptionsT
+    def __init__(self):
+        self.padding = 0  # type: int
+        self.strideW = 0  # type: int
+        self.strideH = 0  # type: int
+        self.fusedActivationFunction = 0  # type: int
+        self.quantizedBiasType = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        transposeConvOptions = TransposeConvOptions()
+        transposeConvOptions.Init(buf, pos)
+        return cls.InitFromObj(transposeConvOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, transposeConvOptions):
+        x = TransposeConvOptionsT()
+        x._UnPack(transposeConvOptions)
+        return x
+
+    # TransposeConvOptionsT
+    def _UnPack(self, transposeConvOptions):
+        if transposeConvOptions is None:
+            return
+        self.padding = transposeConvOptions.Padding()
+        self.strideW = transposeConvOptions.StrideW()
+        self.strideH = transposeConvOptions.StrideH()
+        self.fusedActivationFunction = transposeConvOptions.FusedActivationFunction()
+        self.quantizedBiasType = transposeConvOptions.QuantizedBiasType()
+
+    # TransposeConvOptionsT
+    def Pack(self, builder):
+        TransposeConvOptionsStart(builder)
+        TransposeConvOptionsAddPadding(builder, self.padding)
+        TransposeConvOptionsAddStrideW(builder, self.strideW)
+        TransposeConvOptionsAddStrideH(builder, self.strideH)
+        TransposeConvOptionsAddFusedActivationFunction(builder,
+                                                       self.fusedActivationFunction)
+        TransposeConvOptionsAddQuantizedBiasType(builder, self.quantizedBiasType)
+        transposeConvOptions = TransposeConvOptionsEnd(builder)
+        return transposeConvOptions
+
+
+class ExpandDimsOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ExpandDimsOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsExpandDimsOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ExpandDimsOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ExpandDimsOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def ExpandDimsOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def ExpandDimsOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ExpandDimsOptionsT(object):
+
+    # ExpandDimsOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        expandDimsOptions = ExpandDimsOptions()
+        expandDimsOptions.Init(buf, pos)
+        return cls.InitFromObj(expandDimsOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, expandDimsOptions):
+        x = ExpandDimsOptionsT()
+        x._UnPack(expandDimsOptions)
+        return x
+
+    # ExpandDimsOptionsT
+    def _UnPack(self, expandDimsOptions):
+        if expandDimsOptions is None:
+            return
+
+    # ExpandDimsOptionsT
+    def Pack(self, builder):
+        ExpandDimsOptionsStart(builder)
+        expandDimsOptions = ExpandDimsOptionsEnd(builder)
+        return expandDimsOptions
+
+
+class SparseToDenseOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SparseToDenseOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSparseToDenseOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SparseToDenseOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SparseToDenseOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SparseToDenseOptions
+    def ValidateIndices(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def SparseToDenseOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def SparseToDenseOptionsAddValidateIndices(builder, validateIndices):
+    builder.PrependBoolSlot(0, validateIndices, 0)
+
+
+def SparseToDenseOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SparseToDenseOptionsT(object):
+
+    # SparseToDenseOptionsT
+    def __init__(self):
+        self.validateIndices = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        sparseToDenseOptions = SparseToDenseOptions()
+        sparseToDenseOptions.Init(buf, pos)
+        return cls.InitFromObj(sparseToDenseOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, sparseToDenseOptions):
+        x = SparseToDenseOptionsT()
+        x._UnPack(sparseToDenseOptions)
+        return x
+
+    # SparseToDenseOptionsT
+    def _UnPack(self, sparseToDenseOptions):
+        if sparseToDenseOptions is None:
+            return
+        self.validateIndices = sparseToDenseOptions.ValidateIndices()
+
+    # SparseToDenseOptionsT
+    def Pack(self, builder):
+        SparseToDenseOptionsStart(builder)
+        SparseToDenseOptionsAddValidateIndices(builder, self.validateIndices)
+        sparseToDenseOptions = SparseToDenseOptionsEnd(builder)
+        return sparseToDenseOptions
+
+
+class EqualOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = EqualOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsEqualOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def EqualOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # EqualOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def EqualOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def EqualOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class EqualOptionsT(object):
+
+    # EqualOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        equalOptions = EqualOptions()
+        equalOptions.Init(buf, pos)
+        return cls.InitFromObj(equalOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, equalOptions):
+        x = EqualOptionsT()
+        x._UnPack(equalOptions)
+        return x
+
+    # EqualOptionsT
+    def _UnPack(self, equalOptions):
+        if equalOptions is None:
+            return
+
+    # EqualOptionsT
+    def Pack(self, builder):
+        EqualOptionsStart(builder)
+        equalOptions = EqualOptionsEnd(builder)
+        return equalOptions
+
+
+class NotEqualOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = NotEqualOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsNotEqualOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def NotEqualOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # NotEqualOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def NotEqualOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def NotEqualOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class NotEqualOptionsT(object):
+
+    # NotEqualOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        notEqualOptions = NotEqualOptions()
+        notEqualOptions.Init(buf, pos)
+        return cls.InitFromObj(notEqualOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, notEqualOptions):
+        x = NotEqualOptionsT()
+        x._UnPack(notEqualOptions)
+        return x
+
+    # NotEqualOptionsT
+    def _UnPack(self, notEqualOptions):
+        if notEqualOptions is None:
+            return
+
+    # NotEqualOptionsT
+    def Pack(self, builder):
+        NotEqualOptionsStart(builder)
+        notEqualOptions = NotEqualOptionsEnd(builder)
+        return notEqualOptions
+
+
+class ShapeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ShapeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsShapeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ShapeOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ShapeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ShapeOptions
+    def OutType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def ShapeOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def ShapeOptionsAddOutType(builder, outType):
+    builder.PrependInt8Slot(0, outType, 0)
+
+
+def ShapeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ShapeOptionsT(object):
+
+    # ShapeOptionsT
+    def __init__(self):
+        self.outType = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        shapeOptions = ShapeOptions()
+        shapeOptions.Init(buf, pos)
+        return cls.InitFromObj(shapeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, shapeOptions):
+        x = ShapeOptionsT()
+        x._UnPack(shapeOptions)
+        return x
+
+    # ShapeOptionsT
+    def _UnPack(self, shapeOptions):
+        if shapeOptions is None:
+            return
+        self.outType = shapeOptions.OutType()
+
+    # ShapeOptionsT
+    def Pack(self, builder):
+        ShapeOptionsStart(builder)
+        ShapeOptionsAddOutType(builder, self.outType)
+        shapeOptions = ShapeOptionsEnd(builder)
+        return shapeOptions
+
+
+class RankOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = RankOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsRankOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def RankOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # RankOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def RankOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def RankOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class RankOptionsT(object):
+
+    # RankOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        rankOptions = RankOptions()
+        rankOptions.Init(buf, pos)
+        return cls.InitFromObj(rankOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, rankOptions):
+        x = RankOptionsT()
+        x._UnPack(rankOptions)
+        return x
+
+    # RankOptionsT
+    def _UnPack(self, rankOptions):
+        if rankOptions is None:
+            return
+
+    # RankOptionsT
+    def Pack(self, builder):
+        RankOptionsStart(builder)
+        rankOptions = RankOptionsEnd(builder)
+        return rankOptions
+
+
+class PowOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = PowOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsPowOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def PowOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # PowOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def PowOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def PowOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class PowOptionsT(object):
+
+    # PowOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        powOptions = PowOptions()
+        powOptions.Init(buf, pos)
+        return cls.InitFromObj(powOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, powOptions):
+        x = PowOptionsT()
+        x._UnPack(powOptions)
+        return x
+
+    # PowOptionsT
+    def _UnPack(self, powOptions):
+        if powOptions is None:
+            return
+
+    # PowOptionsT
+    def Pack(self, builder):
+        PowOptionsStart(builder)
+        powOptions = PowOptionsEnd(builder)
+        return powOptions
+
+
+class FakeQuantOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = FakeQuantOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsFakeQuantOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def FakeQuantOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # FakeQuantOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # FakeQuantOptions
+    def Min(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # FakeQuantOptions
+    def Max(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # FakeQuantOptions
+    def NumBits(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # FakeQuantOptions
+    def NarrowRange(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def FakeQuantOptionsStart(builder):
+    builder.StartObject(4)
+
+
+def FakeQuantOptionsAddMin(builder, min):
+    builder.PrependFloat32Slot(0, min, 0.0)
+
+
+def FakeQuantOptionsAddMax(builder, max):
+    builder.PrependFloat32Slot(1, max, 0.0)
+
+
+def FakeQuantOptionsAddNumBits(builder, numBits):
+    builder.PrependInt32Slot(2, numBits, 0)
+
+
+def FakeQuantOptionsAddNarrowRange(builder, narrowRange):
+    builder.PrependBoolSlot(3, narrowRange, 0)
+
+
+def FakeQuantOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class FakeQuantOptionsT(object):
+
+    # FakeQuantOptionsT
+    def __init__(self):
+        self.min = 0.0  # type: float
+        self.max = 0.0  # type: float
+        self.numBits = 0  # type: int
+        self.narrowRange = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        fakeQuantOptions = FakeQuantOptions()
+        fakeQuantOptions.Init(buf, pos)
+        return cls.InitFromObj(fakeQuantOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, fakeQuantOptions):
+        x = FakeQuantOptionsT()
+        x._UnPack(fakeQuantOptions)
+        return x
+
+    # FakeQuantOptionsT
+    def _UnPack(self, fakeQuantOptions):
+        if fakeQuantOptions is None:
+            return
+        self.min = fakeQuantOptions.Min()
+        self.max = fakeQuantOptions.Max()
+        self.numBits = fakeQuantOptions.NumBits()
+        self.narrowRange = fakeQuantOptions.NarrowRange()
+
+    # FakeQuantOptionsT
+    def Pack(self, builder):
+        FakeQuantOptionsStart(builder)
+        FakeQuantOptionsAddMin(builder, self.min)
+        FakeQuantOptionsAddMax(builder, self.max)
+        FakeQuantOptionsAddNumBits(builder, self.numBits)
+        FakeQuantOptionsAddNarrowRange(builder, self.narrowRange)
+        fakeQuantOptions = FakeQuantOptionsEnd(builder)
+        return fakeQuantOptions
+
+
+class PackOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = PackOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsPackOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def PackOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # PackOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # PackOptions
+    def ValuesCount(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # PackOptions
+    def Axis(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def PackOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def PackOptionsAddValuesCount(builder, valuesCount):
+    builder.PrependInt32Slot(0, valuesCount, 0)
+
+
+def PackOptionsAddAxis(builder, axis):
+    builder.PrependInt32Slot(1, axis, 0)
+
+
+def PackOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class PackOptionsT(object):
+
+    # PackOptionsT
+    def __init__(self):
+        self.valuesCount = 0  # type: int
+        self.axis = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        packOptions = PackOptions()
+        packOptions.Init(buf, pos)
+        return cls.InitFromObj(packOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, packOptions):
+        x = PackOptionsT()
+        x._UnPack(packOptions)
+        return x
+
+    # PackOptionsT
+    def _UnPack(self, packOptions):
+        if packOptions is None:
+            return
+        self.valuesCount = packOptions.ValuesCount()
+        self.axis = packOptions.Axis()
+
+    # PackOptionsT
+    def Pack(self, builder):
+        PackOptionsStart(builder)
+        PackOptionsAddValuesCount(builder, self.valuesCount)
+        PackOptionsAddAxis(builder, self.axis)
+        packOptions = PackOptionsEnd(builder)
+        return packOptions
+
+
+class LogicalOrOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = LogicalOrOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsLogicalOrOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def LogicalOrOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # LogicalOrOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def LogicalOrOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def LogicalOrOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class LogicalOrOptionsT(object):
+
+    # LogicalOrOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        logicalOrOptions = LogicalOrOptions()
+        logicalOrOptions.Init(buf, pos)
+        return cls.InitFromObj(logicalOrOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, logicalOrOptions):
+        x = LogicalOrOptionsT()
+        x._UnPack(logicalOrOptions)
+        return x
+
+    # LogicalOrOptionsT
+    def _UnPack(self, logicalOrOptions):
+        if logicalOrOptions is None:
+            return
+
+    # LogicalOrOptionsT
+    def Pack(self, builder):
+        LogicalOrOptionsStart(builder)
+        logicalOrOptions = LogicalOrOptionsEnd(builder)
+        return logicalOrOptions
+
+
+class OneHotOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = OneHotOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsOneHotOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def OneHotOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # OneHotOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # OneHotOptions
+    def Axis(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def OneHotOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def OneHotOptionsAddAxis(builder, axis):
+    builder.PrependInt32Slot(0, axis, 0)
+
+
+def OneHotOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class OneHotOptionsT(object):
+
+    # OneHotOptionsT
+    def __init__(self):
+        self.axis = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        oneHotOptions = OneHotOptions()
+        oneHotOptions.Init(buf, pos)
+        return cls.InitFromObj(oneHotOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, oneHotOptions):
+        x = OneHotOptionsT()
+        x._UnPack(oneHotOptions)
+        return x
+
+    # OneHotOptionsT
+    def _UnPack(self, oneHotOptions):
+        if oneHotOptions is None:
+            return
+        self.axis = oneHotOptions.Axis()
+
+    # OneHotOptionsT
+    def Pack(self, builder):
+        OneHotOptionsStart(builder)
+        OneHotOptionsAddAxis(builder, self.axis)
+        oneHotOptions = OneHotOptionsEnd(builder)
+        return oneHotOptions
+
+
+class AbsOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = AbsOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsAbsOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def AbsOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # AbsOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def AbsOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def AbsOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class AbsOptionsT(object):
+
+    # AbsOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        absOptions = AbsOptions()
+        absOptions.Init(buf, pos)
+        return cls.InitFromObj(absOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, absOptions):
+        x = AbsOptionsT()
+        x._UnPack(absOptions)
+        return x
+
+    # AbsOptionsT
+    def _UnPack(self, absOptions):
+        if absOptions is None:
+            return
+
+    # AbsOptionsT
+    def Pack(self, builder):
+        AbsOptionsStart(builder)
+        absOptions = AbsOptionsEnd(builder)
+        return absOptions
+
+
+class HardSwishOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = HardSwishOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsHardSwishOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def HardSwishOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # HardSwishOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def HardSwishOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def HardSwishOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class HardSwishOptionsT(object):
+
+    # HardSwishOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        hardSwishOptions = HardSwishOptions()
+        hardSwishOptions.Init(buf, pos)
+        return cls.InitFromObj(hardSwishOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, hardSwishOptions):
+        x = HardSwishOptionsT()
+        x._UnPack(hardSwishOptions)
+        return x
+
+    # HardSwishOptionsT
+    def _UnPack(self, hardSwishOptions):
+        if hardSwishOptions is None:
+            return
+
+    # HardSwishOptionsT
+    def Pack(self, builder):
+        HardSwishOptionsStart(builder)
+        hardSwishOptions = HardSwishOptionsEnd(builder)
+        return hardSwishOptions
+
+
+class LogicalAndOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = LogicalAndOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsLogicalAndOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def LogicalAndOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # LogicalAndOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def LogicalAndOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def LogicalAndOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class LogicalAndOptionsT(object):
+
+    # LogicalAndOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        logicalAndOptions = LogicalAndOptions()
+        logicalAndOptions.Init(buf, pos)
+        return cls.InitFromObj(logicalAndOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, logicalAndOptions):
+        x = LogicalAndOptionsT()
+        x._UnPack(logicalAndOptions)
+        return x
+
+    # LogicalAndOptionsT
+    def _UnPack(self, logicalAndOptions):
+        if logicalAndOptions is None:
+            return
+
+    # LogicalAndOptionsT
+    def Pack(self, builder):
+        LogicalAndOptionsStart(builder)
+        logicalAndOptions = LogicalAndOptionsEnd(builder)
+        return logicalAndOptions
+
+
+class LogicalNotOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = LogicalNotOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsLogicalNotOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def LogicalNotOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # LogicalNotOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def LogicalNotOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def LogicalNotOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class LogicalNotOptionsT(object):
+
+    # LogicalNotOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        logicalNotOptions = LogicalNotOptions()
+        logicalNotOptions.Init(buf, pos)
+        return cls.InitFromObj(logicalNotOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, logicalNotOptions):
+        x = LogicalNotOptionsT()
+        x._UnPack(logicalNotOptions)
+        return x
+
+    # LogicalNotOptionsT
+    def _UnPack(self, logicalNotOptions):
+        if logicalNotOptions is None:
+            return
+
+    # LogicalNotOptionsT
+    def Pack(self, builder):
+        LogicalNotOptionsStart(builder)
+        logicalNotOptions = LogicalNotOptionsEnd(builder)
+        return logicalNotOptions
+
+
+class UnpackOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = UnpackOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsUnpackOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def UnpackOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # UnpackOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # UnpackOptions
+    def Num(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # UnpackOptions
+    def Axis(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def UnpackOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def UnpackOptionsAddNum(builder, num):
+    builder.PrependInt32Slot(0, num, 0)
+
+
+def UnpackOptionsAddAxis(builder, axis):
+    builder.PrependInt32Slot(1, axis, 0)
+
+
+def UnpackOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class UnpackOptionsT(object):
+
+    # UnpackOptionsT
+    def __init__(self):
+        self.num = 0  # type: int
+        self.axis = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        unpackOptions = UnpackOptions()
+        unpackOptions.Init(buf, pos)
+        return cls.InitFromObj(unpackOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, unpackOptions):
+        x = UnpackOptionsT()
+        x._UnPack(unpackOptions)
+        return x
+
+    # UnpackOptionsT
+    def _UnPack(self, unpackOptions):
+        if unpackOptions is None:
+            return
+        self.num = unpackOptions.Num()
+        self.axis = unpackOptions.Axis()
+
+    # UnpackOptionsT
+    def Pack(self, builder):
+        UnpackOptionsStart(builder)
+        UnpackOptionsAddNum(builder, self.num)
+        UnpackOptionsAddAxis(builder, self.axis)
+        unpackOptions = UnpackOptionsEnd(builder)
+        return unpackOptions
+
+
+class FloorDivOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = FloorDivOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsFloorDivOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def FloorDivOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # FloorDivOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def FloorDivOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def FloorDivOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class FloorDivOptionsT(object):
+
+    # FloorDivOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        floorDivOptions = FloorDivOptions()
+        floorDivOptions.Init(buf, pos)
+        return cls.InitFromObj(floorDivOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, floorDivOptions):
+        x = FloorDivOptionsT()
+        x._UnPack(floorDivOptions)
+        return x
+
+    # FloorDivOptionsT
+    def _UnPack(self, floorDivOptions):
+        if floorDivOptions is None:
+            return
+
+    # FloorDivOptionsT
+    def Pack(self, builder):
+        FloorDivOptionsStart(builder)
+        floorDivOptions = FloorDivOptionsEnd(builder)
+        return floorDivOptions
+
+
+class SquareOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SquareOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSquareOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SquareOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SquareOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def SquareOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def SquareOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SquareOptionsT(object):
+
+    # SquareOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        squareOptions = SquareOptions()
+        squareOptions.Init(buf, pos)
+        return cls.InitFromObj(squareOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, squareOptions):
+        x = SquareOptionsT()
+        x._UnPack(squareOptions)
+        return x
+
+    # SquareOptionsT
+    def _UnPack(self, squareOptions):
+        if squareOptions is None:
+            return
+
+    # SquareOptionsT
+    def Pack(self, builder):
+        SquareOptionsStart(builder)
+        squareOptions = SquareOptionsEnd(builder)
+        return squareOptions
+
+
+class ZerosLikeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ZerosLikeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsZerosLikeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ZerosLikeOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ZerosLikeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def ZerosLikeOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def ZerosLikeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ZerosLikeOptionsT(object):
+
+    # ZerosLikeOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        zerosLikeOptions = ZerosLikeOptions()
+        zerosLikeOptions.Init(buf, pos)
+        return cls.InitFromObj(zerosLikeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, zerosLikeOptions):
+        x = ZerosLikeOptionsT()
+        x._UnPack(zerosLikeOptions)
+        return x
+
+    # ZerosLikeOptionsT
+    def _UnPack(self, zerosLikeOptions):
+        if zerosLikeOptions is None:
+            return
+
+    # ZerosLikeOptionsT
+    def Pack(self, builder):
+        ZerosLikeOptionsStart(builder)
+        zerosLikeOptions = ZerosLikeOptionsEnd(builder)
+        return zerosLikeOptions
+
+
+class FillOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = FillOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsFillOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def FillOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # FillOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def FillOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def FillOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class FillOptionsT(object):
+
+    # FillOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        fillOptions = FillOptions()
+        fillOptions.Init(buf, pos)
+        return cls.InitFromObj(fillOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, fillOptions):
+        x = FillOptionsT()
+        x._UnPack(fillOptions)
+        return x
+
+    # FillOptionsT
+    def _UnPack(self, fillOptions):
+        if fillOptions is None:
+            return
+
+    # FillOptionsT
+    def Pack(self, builder):
+        FillOptionsStart(builder)
+        fillOptions = FillOptionsEnd(builder)
+        return fillOptions
+
+
+class FloorModOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = FloorModOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsFloorModOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def FloorModOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # FloorModOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def FloorModOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def FloorModOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class FloorModOptionsT(object):
+
+    # FloorModOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        floorModOptions = FloorModOptions()
+        floorModOptions.Init(buf, pos)
+        return cls.InitFromObj(floorModOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, floorModOptions):
+        x = FloorModOptionsT()
+        x._UnPack(floorModOptions)
+        return x
+
+    # FloorModOptionsT
+    def _UnPack(self, floorModOptions):
+        if floorModOptions is None:
+            return
+
+    # FloorModOptionsT
+    def Pack(self, builder):
+        FloorModOptionsStart(builder)
+        floorModOptions = FloorModOptionsEnd(builder)
+        return floorModOptions
+
+
+class RangeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = RangeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsRangeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def RangeOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # RangeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def RangeOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def RangeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class RangeOptionsT(object):
+
+    # RangeOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        rangeOptions = RangeOptions()
+        rangeOptions.Init(buf, pos)
+        return cls.InitFromObj(rangeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, rangeOptions):
+        x = RangeOptionsT()
+        x._UnPack(rangeOptions)
+        return x
+
+    # RangeOptionsT
+    def _UnPack(self, rangeOptions):
+        if rangeOptions is None:
+            return
+
+    # RangeOptionsT
+    def Pack(self, builder):
+        RangeOptionsStart(builder)
+        rangeOptions = RangeOptionsEnd(builder)
+        return rangeOptions
+
+
+class LeakyReluOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = LeakyReluOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsLeakyReluOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def LeakyReluOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # LeakyReluOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # LeakyReluOptions
+    def Alpha(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+
+def LeakyReluOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def LeakyReluOptionsAddAlpha(builder, alpha):
+    builder.PrependFloat32Slot(0, alpha, 0.0)
+
+
+def LeakyReluOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class LeakyReluOptionsT(object):
+
+    # LeakyReluOptionsT
+    def __init__(self):
+        self.alpha = 0.0  # type: float
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        leakyReluOptions = LeakyReluOptions()
+        leakyReluOptions.Init(buf, pos)
+        return cls.InitFromObj(leakyReluOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, leakyReluOptions):
+        x = LeakyReluOptionsT()
+        x._UnPack(leakyReluOptions)
+        return x
+
+    # LeakyReluOptionsT
+    def _UnPack(self, leakyReluOptions):
+        if leakyReluOptions is None:
+            return
+        self.alpha = leakyReluOptions.Alpha()
+
+    # LeakyReluOptionsT
+    def Pack(self, builder):
+        LeakyReluOptionsStart(builder)
+        LeakyReluOptionsAddAlpha(builder, self.alpha)
+        leakyReluOptions = LeakyReluOptionsEnd(builder)
+        return leakyReluOptions
+
+
+class SquaredDifferenceOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SquaredDifferenceOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSquaredDifferenceOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SquaredDifferenceOptionsBufferHasIdentifier(cls, buf, offset,
+                                                    size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SquaredDifferenceOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def SquaredDifferenceOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def SquaredDifferenceOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SquaredDifferenceOptionsT(object):
+
+    # SquaredDifferenceOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        squaredDifferenceOptions = SquaredDifferenceOptions()
+        squaredDifferenceOptions.Init(buf, pos)
+        return cls.InitFromObj(squaredDifferenceOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, squaredDifferenceOptions):
+        x = SquaredDifferenceOptionsT()
+        x._UnPack(squaredDifferenceOptions)
+        return x
+
+    # SquaredDifferenceOptionsT
+    def _UnPack(self, squaredDifferenceOptions):
+        if squaredDifferenceOptions is None:
+            return
+
+    # SquaredDifferenceOptionsT
+    def Pack(self, builder):
+        SquaredDifferenceOptionsStart(builder)
+        squaredDifferenceOptions = SquaredDifferenceOptionsEnd(builder)
+        return squaredDifferenceOptions
+
+
+class MirrorPadOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = MirrorPadOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsMirrorPadOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def MirrorPadOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # MirrorPadOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # MirrorPadOptions
+    def Mode(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def MirrorPadOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def MirrorPadOptionsAddMode(builder, mode):
+    builder.PrependInt8Slot(0, mode, 0)
+
+
+def MirrorPadOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class MirrorPadOptionsT(object):
+
+    # MirrorPadOptionsT
+    def __init__(self):
+        self.mode = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        mirrorPadOptions = MirrorPadOptions()
+        mirrorPadOptions.Init(buf, pos)
+        return cls.InitFromObj(mirrorPadOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, mirrorPadOptions):
+        x = MirrorPadOptionsT()
+        x._UnPack(mirrorPadOptions)
+        return x
+
+    # MirrorPadOptionsT
+    def _UnPack(self, mirrorPadOptions):
+        if mirrorPadOptions is None:
+            return
+        self.mode = mirrorPadOptions.Mode()
+
+    # MirrorPadOptionsT
+    def Pack(self, builder):
+        MirrorPadOptionsStart(builder)
+        MirrorPadOptionsAddMode(builder, self.mode)
+        mirrorPadOptions = MirrorPadOptionsEnd(builder)
+        return mirrorPadOptions
+
+
+class UniqueOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = UniqueOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsUniqueOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def UniqueOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # UniqueOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # UniqueOptions
+    def IdxOutType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 2
+
+
+def UniqueOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def UniqueOptionsAddIdxOutType(builder, idxOutType):
+    builder.PrependInt8Slot(0, idxOutType, 2)
+
+
+def UniqueOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class UniqueOptionsT(object):
+
+    # UniqueOptionsT
+    def __init__(self):
+        self.idxOutType = 2  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        uniqueOptions = UniqueOptions()
+        uniqueOptions.Init(buf, pos)
+        return cls.InitFromObj(uniqueOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, uniqueOptions):
+        x = UniqueOptionsT()
+        x._UnPack(uniqueOptions)
+        return x
+
+    # UniqueOptionsT
+    def _UnPack(self, uniqueOptions):
+        if uniqueOptions is None:
+            return
+        self.idxOutType = uniqueOptions.IdxOutType()
+
+    # UniqueOptionsT
+    def Pack(self, builder):
+        UniqueOptionsStart(builder)
+        UniqueOptionsAddIdxOutType(builder, self.idxOutType)
+        uniqueOptions = UniqueOptionsEnd(builder)
+        return uniqueOptions
+
+
+class ReverseV2Options(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ReverseV2Options()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsReverseV2Options(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ReverseV2OptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ReverseV2Options
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def ReverseV2OptionsStart(builder):
+    builder.StartObject(0)
+
+
+def ReverseV2OptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ReverseV2OptionsT(object):
+
+    # ReverseV2OptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        reverseV2Options = ReverseV2Options()
+        reverseV2Options.Init(buf, pos)
+        return cls.InitFromObj(reverseV2Options)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, reverseV2Options):
+        x = ReverseV2OptionsT()
+        x._UnPack(reverseV2Options)
+        return x
+
+    # ReverseV2OptionsT
+    def _UnPack(self, reverseV2Options):
+        if reverseV2Options is None:
+            return
+
+    # ReverseV2OptionsT
+    def Pack(self, builder):
+        ReverseV2OptionsStart(builder)
+        reverseV2Options = ReverseV2OptionsEnd(builder)
+        return reverseV2Options
+
+
+class AddNOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = AddNOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsAddNOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def AddNOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # AddNOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def AddNOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def AddNOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class AddNOptionsT(object):
+
+    # AddNOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        addNoptions = AddNOptions()
+        addNoptions.Init(buf, pos)
+        return cls.InitFromObj(addNoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, addNoptions):
+        x = AddNOptionsT()
+        x._UnPack(addNoptions)
+        return x
+
+    # AddNOptionsT
+    def _UnPack(self, addNoptions):
+        if addNoptions is None:
+            return
+
+    # AddNOptionsT
+    def Pack(self, builder):
+        AddNOptionsStart(builder)
+        addNoptions = AddNOptionsEnd(builder)
+        return addNoptions
+
+
+class GatherNdOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = GatherNdOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsGatherNdOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def GatherNdOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # GatherNdOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def GatherNdOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def GatherNdOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class GatherNdOptionsT(object):
+
+    # GatherNdOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        gatherNdOptions = GatherNdOptions()
+        gatherNdOptions.Init(buf, pos)
+        return cls.InitFromObj(gatherNdOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, gatherNdOptions):
+        x = GatherNdOptionsT()
+        x._UnPack(gatherNdOptions)
+        return x
+
+    # GatherNdOptionsT
+    def _UnPack(self, gatherNdOptions):
+        if gatherNdOptions is None:
+            return
+
+    # GatherNdOptionsT
+    def Pack(self, builder):
+        GatherNdOptionsStart(builder)
+        gatherNdOptions = GatherNdOptionsEnd(builder)
+        return gatherNdOptions
+
+
+class WhereOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = WhereOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsWhereOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def WhereOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # WhereOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def WhereOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def WhereOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class WhereOptionsT(object):
+
+    # WhereOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        whereOptions = WhereOptions()
+        whereOptions.Init(buf, pos)
+        return cls.InitFromObj(whereOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, whereOptions):
+        x = WhereOptionsT()
+        x._UnPack(whereOptions)
+        return x
+
+    # WhereOptionsT
+    def _UnPack(self, whereOptions):
+        if whereOptions is None:
+            return
+
+    # WhereOptionsT
+    def Pack(self, builder):
+        WhereOptionsStart(builder)
+        whereOptions = WhereOptionsEnd(builder)
+        return whereOptions
+
+
+class ReverseSequenceOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ReverseSequenceOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsReverseSequenceOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ReverseSequenceOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ReverseSequenceOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ReverseSequenceOptions
+    def SeqDim(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # ReverseSequenceOptions
+    def BatchDim(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def ReverseSequenceOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def ReverseSequenceOptionsAddSeqDim(builder, seqDim):
+    builder.PrependInt32Slot(0, seqDim, 0)
+
+
+def ReverseSequenceOptionsAddBatchDim(builder, batchDim):
+    builder.PrependInt32Slot(1, batchDim, 0)
+
+
+def ReverseSequenceOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ReverseSequenceOptionsT(object):
+
+    # ReverseSequenceOptionsT
+    def __init__(self):
+        self.seqDim = 0  # type: int
+        self.batchDim = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        reverseSequenceOptions = ReverseSequenceOptions()
+        reverseSequenceOptions.Init(buf, pos)
+        return cls.InitFromObj(reverseSequenceOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, reverseSequenceOptions):
+        x = ReverseSequenceOptionsT()
+        x._UnPack(reverseSequenceOptions)
+        return x
+
+    # ReverseSequenceOptionsT
+    def _UnPack(self, reverseSequenceOptions):
+        if reverseSequenceOptions is None:
+            return
+        self.seqDim = reverseSequenceOptions.SeqDim()
+        self.batchDim = reverseSequenceOptions.BatchDim()
+
+    # ReverseSequenceOptionsT
+    def Pack(self, builder):
+        ReverseSequenceOptionsStart(builder)
+        ReverseSequenceOptionsAddSeqDim(builder, self.seqDim)
+        ReverseSequenceOptionsAddBatchDim(builder, self.batchDim)
+        reverseSequenceOptions = ReverseSequenceOptionsEnd(builder)
+        return reverseSequenceOptions
+
+
+class MatrixDiagOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = MatrixDiagOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsMatrixDiagOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def MatrixDiagOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # MatrixDiagOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def MatrixDiagOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def MatrixDiagOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class MatrixDiagOptionsT(object):
+
+    # MatrixDiagOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        matrixDiagOptions = MatrixDiagOptions()
+        matrixDiagOptions.Init(buf, pos)
+        return cls.InitFromObj(matrixDiagOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, matrixDiagOptions):
+        x = MatrixDiagOptionsT()
+        x._UnPack(matrixDiagOptions)
+        return x
+
+    # MatrixDiagOptionsT
+    def _UnPack(self, matrixDiagOptions):
+        if matrixDiagOptions is None:
+            return
+
+    # MatrixDiagOptionsT
+    def Pack(self, builder):
+        MatrixDiagOptionsStart(builder)
+        matrixDiagOptions = MatrixDiagOptionsEnd(builder)
+        return matrixDiagOptions
+
+
+class QuantizeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = QuantizeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsQuantizeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def QuantizeOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # QuantizeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def QuantizeOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def QuantizeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class QuantizeOptionsT(object):
+
+    # QuantizeOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        quantizeOptions = QuantizeOptions()
+        quantizeOptions.Init(buf, pos)
+        return cls.InitFromObj(quantizeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, quantizeOptions):
+        x = QuantizeOptionsT()
+        x._UnPack(quantizeOptions)
+        return x
+
+    # QuantizeOptionsT
+    def _UnPack(self, quantizeOptions):
+        if quantizeOptions is None:
+            return
+
+    # QuantizeOptionsT
+    def Pack(self, builder):
+        QuantizeOptionsStart(builder)
+        quantizeOptions = QuantizeOptionsEnd(builder)
+        return quantizeOptions
+
+
+class MatrixSetDiagOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = MatrixSetDiagOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsMatrixSetDiagOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def MatrixSetDiagOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # MatrixSetDiagOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def MatrixSetDiagOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def MatrixSetDiagOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class MatrixSetDiagOptionsT(object):
+
+    # MatrixSetDiagOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        matrixSetDiagOptions = MatrixSetDiagOptions()
+        matrixSetDiagOptions.Init(buf, pos)
+        return cls.InitFromObj(matrixSetDiagOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, matrixSetDiagOptions):
+        x = MatrixSetDiagOptionsT()
+        x._UnPack(matrixSetDiagOptions)
+        return x
+
+    # MatrixSetDiagOptionsT
+    def _UnPack(self, matrixSetDiagOptions):
+        if matrixSetDiagOptions is None:
+            return
+
+    # MatrixSetDiagOptionsT
+    def Pack(self, builder):
+        MatrixSetDiagOptionsStart(builder)
+        matrixSetDiagOptions = MatrixSetDiagOptionsEnd(builder)
+        return matrixSetDiagOptions
+
+
+class IfOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = IfOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsIfOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def IfOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # IfOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # IfOptions
+    def ThenSubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # IfOptions
+    def ElseSubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def IfOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def IfOptionsAddThenSubgraphIndex(builder, thenSubgraphIndex):
+    builder.PrependInt32Slot(0, thenSubgraphIndex, 0)
+
+
+def IfOptionsAddElseSubgraphIndex(builder, elseSubgraphIndex):
+    builder.PrependInt32Slot(1, elseSubgraphIndex, 0)
+
+
+def IfOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class IfOptionsT(object):
+
+    # IfOptionsT
+    def __init__(self):
+        self.thenSubgraphIndex = 0  # type: int
+        self.elseSubgraphIndex = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        ifOptions = IfOptions()
+        ifOptions.Init(buf, pos)
+        return cls.InitFromObj(ifOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, ifOptions):
+        x = IfOptionsT()
+        x._UnPack(ifOptions)
+        return x
+
+    # IfOptionsT
+    def _UnPack(self, ifOptions):
+        if ifOptions is None:
+            return
+        self.thenSubgraphIndex = ifOptions.ThenSubgraphIndex()
+        self.elseSubgraphIndex = ifOptions.ElseSubgraphIndex()
+
+    # IfOptionsT
+    def Pack(self, builder):
+        IfOptionsStart(builder)
+        IfOptionsAddThenSubgraphIndex(builder, self.thenSubgraphIndex)
+        IfOptionsAddElseSubgraphIndex(builder, self.elseSubgraphIndex)
+        ifOptions = IfOptionsEnd(builder)
+        return ifOptions
+
+
+class CallOnceOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = CallOnceOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsCallOnceOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def CallOnceOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # CallOnceOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # CallOnceOptions
+    def InitSubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def CallOnceOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def CallOnceOptionsAddInitSubgraphIndex(builder, initSubgraphIndex):
+    builder.PrependInt32Slot(0, initSubgraphIndex, 0)
+
+
+def CallOnceOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class CallOnceOptionsT(object):
+
+    # CallOnceOptionsT
+    def __init__(self):
+        self.initSubgraphIndex = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        callOnceOptions = CallOnceOptions()
+        callOnceOptions.Init(buf, pos)
+        return cls.InitFromObj(callOnceOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, callOnceOptions):
+        x = CallOnceOptionsT()
+        x._UnPack(callOnceOptions)
+        return x
+
+    # CallOnceOptionsT
+    def _UnPack(self, callOnceOptions):
+        if callOnceOptions is None:
+            return
+        self.initSubgraphIndex = callOnceOptions.InitSubgraphIndex()
+
+    # CallOnceOptionsT
+    def Pack(self, builder):
+        CallOnceOptionsStart(builder)
+        CallOnceOptionsAddInitSubgraphIndex(builder, self.initSubgraphIndex)
+        callOnceOptions = CallOnceOptionsEnd(builder)
+        return callOnceOptions
+
+
+class WhileOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = WhileOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsWhileOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def WhileOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # WhileOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # WhileOptions
+    def CondSubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # WhileOptions
+    def BodySubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def WhileOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def WhileOptionsAddCondSubgraphIndex(builder, condSubgraphIndex):
+    builder.PrependInt32Slot(0, condSubgraphIndex, 0)
+
+
+def WhileOptionsAddBodySubgraphIndex(builder, bodySubgraphIndex):
+    builder.PrependInt32Slot(1, bodySubgraphIndex, 0)
+
+
+def WhileOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class WhileOptionsT(object):
+
+    # WhileOptionsT
+    def __init__(self):
+        self.condSubgraphIndex = 0  # type: int
+        self.bodySubgraphIndex = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        whileOptions = WhileOptions()
+        whileOptions.Init(buf, pos)
+        return cls.InitFromObj(whileOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, whileOptions):
+        x = WhileOptionsT()
+        x._UnPack(whileOptions)
+        return x
+
+    # WhileOptionsT
+    def _UnPack(self, whileOptions):
+        if whileOptions is None:
+            return
+        self.condSubgraphIndex = whileOptions.CondSubgraphIndex()
+        self.bodySubgraphIndex = whileOptions.BodySubgraphIndex()
+
+    # WhileOptionsT
+    def Pack(self, builder):
+        WhileOptionsStart(builder)
+        WhileOptionsAddCondSubgraphIndex(builder, self.condSubgraphIndex)
+        WhileOptionsAddBodySubgraphIndex(builder, self.bodySubgraphIndex)
+        whileOptions = WhileOptionsEnd(builder)
+        return whileOptions
+
+
+class NonMaxSuppressionV4Options(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = NonMaxSuppressionV4Options()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsNonMaxSuppressionV4Options(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def NonMaxSuppressionV4OptionsBufferHasIdentifier(cls,
+                                                      buf,
+                                                      offset,
+                                                      size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # NonMaxSuppressionV4Options
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def NonMaxSuppressionV4OptionsStart(builder):
+    builder.StartObject(0)
+
+
+def NonMaxSuppressionV4OptionsEnd(builder):
+    return builder.EndObject()
+
+
+class NonMaxSuppressionV4OptionsT(object):
+
+    # NonMaxSuppressionV4OptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        nonMaxSuppressionV4Options = NonMaxSuppressionV4Options()
+        nonMaxSuppressionV4Options.Init(buf, pos)
+        return cls.InitFromObj(nonMaxSuppressionV4Options)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, nonMaxSuppressionV4Options):
+        x = NonMaxSuppressionV4OptionsT()
+        x._UnPack(nonMaxSuppressionV4Options)
+        return x
+
+    # NonMaxSuppressionV4OptionsT
+    def _UnPack(self, nonMaxSuppressionV4Options):
+        if nonMaxSuppressionV4Options is None:
+            return
+
+    # NonMaxSuppressionV4OptionsT
+    def Pack(self, builder):
+        NonMaxSuppressionV4OptionsStart(builder)
+        nonMaxSuppressionV4Options = NonMaxSuppressionV4OptionsEnd(builder)
+        return nonMaxSuppressionV4Options
+
+
+class NonMaxSuppressionV5Options(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = NonMaxSuppressionV5Options()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsNonMaxSuppressionV5Options(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def NonMaxSuppressionV5OptionsBufferHasIdentifier(cls,
+                                                      buf,
+                                                      offset,
+                                                      size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # NonMaxSuppressionV5Options
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def NonMaxSuppressionV5OptionsStart(builder):
+    builder.StartObject(0)
+
+
+def NonMaxSuppressionV5OptionsEnd(builder):
+    return builder.EndObject()
+
+
+class NonMaxSuppressionV5OptionsT(object):
+
+    # NonMaxSuppressionV5OptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        nonMaxSuppressionV5Options = NonMaxSuppressionV5Options()
+        nonMaxSuppressionV5Options.Init(buf, pos)
+        return cls.InitFromObj(nonMaxSuppressionV5Options)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, nonMaxSuppressionV5Options):
+        x = NonMaxSuppressionV5OptionsT()
+        x._UnPack(nonMaxSuppressionV5Options)
+        return x
+
+    # NonMaxSuppressionV5OptionsT
+    def _UnPack(self, nonMaxSuppressionV5Options):
+        if nonMaxSuppressionV5Options is None:
+            return
+
+    # NonMaxSuppressionV5OptionsT
+    def Pack(self, builder):
+        NonMaxSuppressionV5OptionsStart(builder)
+        nonMaxSuppressionV5Options = NonMaxSuppressionV5OptionsEnd(builder)
+        return nonMaxSuppressionV5Options
+
+
+class ScatterNdOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ScatterNdOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsScatterNdOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ScatterNdOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ScatterNdOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def ScatterNdOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def ScatterNdOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ScatterNdOptionsT(object):
+
+    # ScatterNdOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        scatterNdOptions = ScatterNdOptions()
+        scatterNdOptions.Init(buf, pos)
+        return cls.InitFromObj(scatterNdOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, scatterNdOptions):
+        x = ScatterNdOptionsT()
+        x._UnPack(scatterNdOptions)
+        return x
+
+    # ScatterNdOptionsT
+    def _UnPack(self, scatterNdOptions):
+        if scatterNdOptions is None:
+            return
+
+    # ScatterNdOptionsT
+    def Pack(self, builder):
+        ScatterNdOptionsStart(builder)
+        scatterNdOptions = ScatterNdOptionsEnd(builder)
+        return scatterNdOptions
+
+
+class SelectV2Options(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SelectV2Options()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSelectV2Options(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SelectV2OptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SelectV2Options
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def SelectV2OptionsStart(builder):
+    builder.StartObject(0)
+
+
+def SelectV2OptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SelectV2OptionsT(object):
+
+    # SelectV2OptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        selectV2Options = SelectV2Options()
+        selectV2Options.Init(buf, pos)
+        return cls.InitFromObj(selectV2Options)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, selectV2Options):
+        x = SelectV2OptionsT()
+        x._UnPack(selectV2Options)
+        return x
+
+    # SelectV2OptionsT
+    def _UnPack(self, selectV2Options):
+        if selectV2Options is None:
+            return
+
+    # SelectV2OptionsT
+    def Pack(self, builder):
+        SelectV2OptionsStart(builder)
+        selectV2Options = SelectV2OptionsEnd(builder)
+        return selectV2Options
+
+
+class DensifyOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = DensifyOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsDensifyOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def DensifyOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # DensifyOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def DensifyOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def DensifyOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class DensifyOptionsT(object):
+
+    # DensifyOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        densifyOptions = DensifyOptions()
+        densifyOptions.Init(buf, pos)
+        return cls.InitFromObj(densifyOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, densifyOptions):
+        x = DensifyOptionsT()
+        x._UnPack(densifyOptions)
+        return x
+
+    # DensifyOptionsT
+    def _UnPack(self, densifyOptions):
+        if densifyOptions is None:
+            return
+
+    # DensifyOptionsT
+    def Pack(self, builder):
+        DensifyOptionsStart(builder)
+        densifyOptions = DensifyOptionsEnd(builder)
+        return densifyOptions
+
+
+class SegmentSumOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SegmentSumOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSegmentSumOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SegmentSumOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SegmentSumOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def SegmentSumOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def SegmentSumOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SegmentSumOptionsT(object):
+
+    # SegmentSumOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        segmentSumOptions = SegmentSumOptions()
+        segmentSumOptions.Init(buf, pos)
+        return cls.InitFromObj(segmentSumOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, segmentSumOptions):
+        x = SegmentSumOptionsT()
+        x._UnPack(segmentSumOptions)
+        return x
+
+    # SegmentSumOptionsT
+    def _UnPack(self, segmentSumOptions):
+        if segmentSumOptions is None:
+            return
+
+    # SegmentSumOptionsT
+    def Pack(self, builder):
+        SegmentSumOptionsStart(builder)
+        segmentSumOptions = SegmentSumOptionsEnd(builder)
+        return segmentSumOptions
+
+
+class BatchMatMulOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = BatchMatMulOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBatchMatMulOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BatchMatMulOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # BatchMatMulOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # BatchMatMulOptions
+    def AdjointLhs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # BatchMatMulOptions
+    def AdjointRhs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # BatchMatMulOptions
+    def AsymmetricQuantizeInputs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def BatchMatMulOptionsStart(builder):
+    builder.StartObject(3)
+
+
+def BatchMatMulOptionsAddAdjointLhs(builder, adjointLhs):
+    builder.PrependBoolSlot(0, adjointLhs, 0)
+
+
+def BatchMatMulOptionsAddAdjointRhs(builder, adjointRhs):
+    builder.PrependBoolSlot(1, adjointRhs, 0)
+
+
+def BatchMatMulOptionsAddAsymmetricQuantizeInputs(builder, asymmetricQuantizeInputs):
+    builder.PrependBoolSlot(2, asymmetricQuantizeInputs, 0)
+
+
+def BatchMatMulOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class BatchMatMulOptionsT(object):
+
+    # BatchMatMulOptionsT
+    def __init__(self):
+        self.adjointLhs = False  # type: bool
+        self.adjointRhs = False  # type: bool
+        self.asymmetricQuantizeInputs = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        batchMatMulOptions = BatchMatMulOptions()
+        batchMatMulOptions.Init(buf, pos)
+        return cls.InitFromObj(batchMatMulOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, batchMatMulOptions):
+        x = BatchMatMulOptionsT()
+        x._UnPack(batchMatMulOptions)
+        return x
+
+    # BatchMatMulOptionsT
+    def _UnPack(self, batchMatMulOptions):
+        if batchMatMulOptions is None:
+            return
+        self.adjointLhs = batchMatMulOptions.AdjointLhs()
+        self.adjointRhs = batchMatMulOptions.AdjointRhs()
+        self.asymmetricQuantizeInputs = batchMatMulOptions.AsymmetricQuantizeInputs()
+
+    # BatchMatMulOptionsT
+    def Pack(self, builder):
+        BatchMatMulOptionsStart(builder)
+        BatchMatMulOptionsAddAdjointLhs(builder, self.adjointLhs)
+        BatchMatMulOptionsAddAdjointRhs(builder, self.adjointRhs)
+        BatchMatMulOptionsAddAsymmetricQuantizeInputs(builder,
+                                                      self.asymmetricQuantizeInputs)
+        batchMatMulOptions = BatchMatMulOptionsEnd(builder)
+        return batchMatMulOptions
+
+
+class CumsumOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = CumsumOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsCumsumOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def CumsumOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # CumsumOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # CumsumOptions
+    def Exclusive(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # CumsumOptions
+    def Reverse(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def CumsumOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def CumsumOptionsAddExclusive(builder, exclusive):
+    builder.PrependBoolSlot(0, exclusive, 0)
+
+
+def CumsumOptionsAddReverse(builder, reverse):
+    builder.PrependBoolSlot(1, reverse, 0)
+
+
+def CumsumOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class CumsumOptionsT(object):
+
+    # CumsumOptionsT
+    def __init__(self):
+        self.exclusive = False  # type: bool
+        self.reverse = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        cumsumOptions = CumsumOptions()
+        cumsumOptions.Init(buf, pos)
+        return cls.InitFromObj(cumsumOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, cumsumOptions):
+        x = CumsumOptionsT()
+        x._UnPack(cumsumOptions)
+        return x
+
+    # CumsumOptionsT
+    def _UnPack(self, cumsumOptions):
+        if cumsumOptions is None:
+            return
+        self.exclusive = cumsumOptions.Exclusive()
+        self.reverse = cumsumOptions.Reverse()
+
+    # CumsumOptionsT
+    def Pack(self, builder):
+        CumsumOptionsStart(builder)
+        CumsumOptionsAddExclusive(builder, self.exclusive)
+        CumsumOptionsAddReverse(builder, self.reverse)
+        cumsumOptions = CumsumOptionsEnd(builder)
+        return cumsumOptions
+
+
+class BroadcastToOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = BroadcastToOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBroadcastToOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BroadcastToOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # BroadcastToOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def BroadcastToOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def BroadcastToOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class BroadcastToOptionsT(object):
+
+    # BroadcastToOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        broadcastToOptions = BroadcastToOptions()
+        broadcastToOptions.Init(buf, pos)
+        return cls.InitFromObj(broadcastToOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, broadcastToOptions):
+        x = BroadcastToOptionsT()
+        x._UnPack(broadcastToOptions)
+        return x
+
+    # BroadcastToOptionsT
+    def _UnPack(self, broadcastToOptions):
+        if broadcastToOptions is None:
+            return
+
+    # BroadcastToOptionsT
+    def Pack(self, builder):
+        BroadcastToOptionsStart(builder)
+        broadcastToOptions = BroadcastToOptionsEnd(builder)
+        return broadcastToOptions
+
+
+class Rfft2dOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Rfft2dOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsRfft2dOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def Rfft2dOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Rfft2dOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def Rfft2dOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def Rfft2dOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class Rfft2dOptionsT(object):
+
+    # Rfft2dOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        rfft2dOptions = Rfft2dOptions()
+        rfft2dOptions.Init(buf, pos)
+        return cls.InitFromObj(rfft2dOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, rfft2dOptions):
+        x = Rfft2dOptionsT()
+        x._UnPack(rfft2dOptions)
+        return x
+
+    # Rfft2dOptionsT
+    def _UnPack(self, rfft2dOptions):
+        if rfft2dOptions is None:
+            return
+
+    # Rfft2dOptionsT
+    def Pack(self, builder):
+        Rfft2dOptionsStart(builder)
+        rfft2dOptions = Rfft2dOptionsEnd(builder)
+        return rfft2dOptions
+
+
+class HashtableOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = HashtableOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsHashtableOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def HashtableOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # HashtableOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # HashtableOptions
+    def TableId(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # HashtableOptions
+    def KeyDtype(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # HashtableOptions
+    def ValueDtype(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def HashtableOptionsStart(builder):
+    builder.StartObject(3)
+
+
+def HashtableOptionsAddTableId(builder, tableId):
+    builder.PrependInt32Slot(0, tableId, 0)
+
+
+def HashtableOptionsAddKeyDtype(builder, keyDtype):
+    builder.PrependInt8Slot(1, keyDtype, 0)
+
+
+def HashtableOptionsAddValueDtype(builder, valueDtype):
+    builder.PrependInt8Slot(2, valueDtype, 0)
+
+
+def HashtableOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class HashtableOptionsT(object):
+
+    # HashtableOptionsT
+    def __init__(self):
+        self.tableId = 0  # type: int
+        self.keyDtype = 0  # type: int
+        self.valueDtype = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        hashtableOptions = HashtableOptions()
+        hashtableOptions.Init(buf, pos)
+        return cls.InitFromObj(hashtableOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, hashtableOptions):
+        x = HashtableOptionsT()
+        x._UnPack(hashtableOptions)
+        return x
+
+    # HashtableOptionsT
+    def _UnPack(self, hashtableOptions):
+        if hashtableOptions is None:
+            return
+        self.tableId = hashtableOptions.TableId()
+        self.keyDtype = hashtableOptions.KeyDtype()
+        self.valueDtype = hashtableOptions.ValueDtype()
+
+    # HashtableOptionsT
+    def Pack(self, builder):
+        HashtableOptionsStart(builder)
+        HashtableOptionsAddTableId(builder, self.tableId)
+        HashtableOptionsAddKeyDtype(builder, self.keyDtype)
+        HashtableOptionsAddValueDtype(builder, self.valueDtype)
+        hashtableOptions = HashtableOptionsEnd(builder)
+        return hashtableOptions
+
+
+class HashtableFindOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = HashtableFindOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsHashtableFindOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def HashtableFindOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # HashtableFindOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def HashtableFindOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def HashtableFindOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class HashtableFindOptionsT(object):
+
+    # HashtableFindOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        hashtableFindOptions = HashtableFindOptions()
+        hashtableFindOptions.Init(buf, pos)
+        return cls.InitFromObj(hashtableFindOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, hashtableFindOptions):
+        x = HashtableFindOptionsT()
+        x._UnPack(hashtableFindOptions)
+        return x
+
+    # HashtableFindOptionsT
+    def _UnPack(self, hashtableFindOptions):
+        if hashtableFindOptions is None:
+            return
+
+    # HashtableFindOptionsT
+    def Pack(self, builder):
+        HashtableFindOptionsStart(builder)
+        hashtableFindOptions = HashtableFindOptionsEnd(builder)
+        return hashtableFindOptions
+
+
+class HashtableImportOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = HashtableImportOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsHashtableImportOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def HashtableImportOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # HashtableImportOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def HashtableImportOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def HashtableImportOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class HashtableImportOptionsT(object):
+
+    # HashtableImportOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        hashtableImportOptions = HashtableImportOptions()
+        hashtableImportOptions.Init(buf, pos)
+        return cls.InitFromObj(hashtableImportOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, hashtableImportOptions):
+        x = HashtableImportOptionsT()
+        x._UnPack(hashtableImportOptions)
+        return x
+
+    # HashtableImportOptionsT
+    def _UnPack(self, hashtableImportOptions):
+        if hashtableImportOptions is None:
+            return
+
+    # HashtableImportOptionsT
+    def Pack(self, builder):
+        HashtableImportOptionsStart(builder)
+        hashtableImportOptions = HashtableImportOptionsEnd(builder)
+        return hashtableImportOptions
+
+
+class HashtableSizeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = HashtableSizeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsHashtableSizeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def HashtableSizeOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # HashtableSizeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def HashtableSizeOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def HashtableSizeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class HashtableSizeOptionsT(object):
+
+    # HashtableSizeOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        hashtableSizeOptions = HashtableSizeOptions()
+        hashtableSizeOptions.Init(buf, pos)
+        return cls.InitFromObj(hashtableSizeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, hashtableSizeOptions):
+        x = HashtableSizeOptionsT()
+        x._UnPack(hashtableSizeOptions)
+        return x
+
+    # HashtableSizeOptionsT
+    def _UnPack(self, hashtableSizeOptions):
+        if hashtableSizeOptions is None:
+            return
+
+    # HashtableSizeOptionsT
+    def Pack(self, builder):
+        HashtableSizeOptionsStart(builder)
+        hashtableSizeOptions = HashtableSizeOptionsEnd(builder)
+        return hashtableSizeOptions
+
+
+class VarHandleOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = VarHandleOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsVarHandleOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def VarHandleOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # VarHandleOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # VarHandleOptions
+    def Container(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+    # VarHandleOptions
+    def SharedName(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+
+def VarHandleOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def VarHandleOptionsAddContainer(builder, container):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(container), 0)
+
+
+def VarHandleOptionsAddSharedName(builder, sharedName):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(sharedName), 0)
+
+
+def VarHandleOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class VarHandleOptionsT(object):
+
+    # VarHandleOptionsT
+    def __init__(self):
+        self.container = None  # type: str
+        self.sharedName = None  # type: str
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        varHandleOptions = VarHandleOptions()
+        varHandleOptions.Init(buf, pos)
+        return cls.InitFromObj(varHandleOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, varHandleOptions):
+        x = VarHandleOptionsT()
+        x._UnPack(varHandleOptions)
+        return x
+
+    # VarHandleOptionsT
+    def _UnPack(self, varHandleOptions):
+        if varHandleOptions is None:
+            return
+        self.container = varHandleOptions.Container()
+        self.sharedName = varHandleOptions.SharedName()
+
+    # VarHandleOptionsT
+    def Pack(self, builder):
+        if self.container is not None:
+            container = builder.CreateString(self.container)
+        if self.sharedName is not None:
+            sharedName = builder.CreateString(self.sharedName)
+        VarHandleOptionsStart(builder)
+        if self.container is not None:
+            VarHandleOptionsAddContainer(builder, container)
+        if self.sharedName is not None:
+            VarHandleOptionsAddSharedName(builder, sharedName)
+        varHandleOptions = VarHandleOptionsEnd(builder)
+        return varHandleOptions
+
+
+class ReadVariableOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ReadVariableOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsReadVariableOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ReadVariableOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ReadVariableOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def ReadVariableOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def ReadVariableOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ReadVariableOptionsT(object):
+
+    # ReadVariableOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        readVariableOptions = ReadVariableOptions()
+        readVariableOptions.Init(buf, pos)
+        return cls.InitFromObj(readVariableOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, readVariableOptions):
+        x = ReadVariableOptionsT()
+        x._UnPack(readVariableOptions)
+        return x
+
+    # ReadVariableOptionsT
+    def _UnPack(self, readVariableOptions):
+        if readVariableOptions is None:
+            return
+
+    # ReadVariableOptionsT
+    def Pack(self, builder):
+        ReadVariableOptionsStart(builder)
+        readVariableOptions = ReadVariableOptionsEnd(builder)
+        return readVariableOptions
+
+
+class AssignVariableOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = AssignVariableOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsAssignVariableOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def AssignVariableOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # AssignVariableOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def AssignVariableOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def AssignVariableOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class AssignVariableOptionsT(object):
+
+    # AssignVariableOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        assignVariableOptions = AssignVariableOptions()
+        assignVariableOptions.Init(buf, pos)
+        return cls.InitFromObj(assignVariableOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, assignVariableOptions):
+        x = AssignVariableOptionsT()
+        x._UnPack(assignVariableOptions)
+        return x
+
+    # AssignVariableOptionsT
+    def _UnPack(self, assignVariableOptions):
+        if assignVariableOptions is None:
+            return
+
+    # AssignVariableOptionsT
+    def Pack(self, builder):
+        AssignVariableOptionsStart(builder)
+        assignVariableOptions = AssignVariableOptionsEnd(builder)
+        return assignVariableOptions
+
+
+class RandomOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = RandomOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsRandomOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def RandomOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # RandomOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # RandomOptions
+    def Seed(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+    # RandomOptions
+    def Seed2(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos)
+        return 0
+
+
+def RandomOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def RandomOptionsAddSeed(builder, seed):
+    builder.PrependInt64Slot(0, seed, 0)
+
+
+def RandomOptionsAddSeed2(builder, seed2):
+    builder.PrependInt64Slot(1, seed2, 0)
+
+
+def RandomOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class RandomOptionsT(object):
+
+    # RandomOptionsT
+    def __init__(self):
+        self.seed = 0  # type: int
+        self.seed2 = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        randomOptions = RandomOptions()
+        randomOptions.Init(buf, pos)
+        return cls.InitFromObj(randomOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, randomOptions):
+        x = RandomOptionsT()
+        x._UnPack(randomOptions)
+        return x
+
+    # RandomOptionsT
+    def _UnPack(self, randomOptions):
+        if randomOptions is None:
+            return
+        self.seed = randomOptions.Seed()
+        self.seed2 = randomOptions.Seed2()
+
+    # RandomOptionsT
+    def Pack(self, builder):
+        RandomOptionsStart(builder)
+        RandomOptionsAddSeed(builder, self.seed)
+        RandomOptionsAddSeed2(builder, self.seed2)
+        randomOptions = RandomOptionsEnd(builder)
+        return randomOptions
+
+
+class BucketizeOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = BucketizeOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBucketizeOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BucketizeOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # BucketizeOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # BucketizeOptions
+    def Boundaries(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Float32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # BucketizeOptions
+    def BoundariesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Float32Flags, o)
+        return 0
+
+    # BucketizeOptions
+    def BoundariesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # BucketizeOptions
+    def BoundariesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+
+def BucketizeOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def BucketizeOptionsAddBoundaries(builder, boundaries):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(boundaries), 0)
+
+
+def BucketizeOptionsStartBoundariesVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def BucketizeOptionsEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class BucketizeOptionsT(object):
+
+    # BucketizeOptionsT
+    def __init__(self):
+        self.boundaries = None  # type: List[float]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        bucketizeOptions = BucketizeOptions()
+        bucketizeOptions.Init(buf, pos)
+        return cls.InitFromObj(bucketizeOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, bucketizeOptions):
+        x = BucketizeOptionsT()
+        x._UnPack(bucketizeOptions)
+        return x
+
+    # BucketizeOptionsT
+    def _UnPack(self, bucketizeOptions):
+        if bucketizeOptions is None:
+            return
+        if not bucketizeOptions.BoundariesIsNone():
+            if np is None:
+                self.boundaries = []
+                for i in range(bucketizeOptions.BoundariesLength()):
+                    self.boundaries.append(bucketizeOptions.Boundaries(i))
+            else:
+                self.boundaries = bucketizeOptions.BoundariesAsNumpy()
+
+    # BucketizeOptionsT
+    def Pack(self, builder):
+        if self.boundaries is not None:
+            if np is not None and type(self.boundaries) is np.ndarray:
+                boundaries = builder.CreateNumpyVector(self.boundaries)
+            else:
+                BucketizeOptionsStartBoundariesVector(builder, len(self.boundaries))
+                for i in reversed(range(len(self.boundaries))):
+                    builder.PrependFloat32(self.boundaries[i])
+                boundaries = builder.EndVector()
+        BucketizeOptionsStart(builder)
+        if self.boundaries is not None:
+            BucketizeOptionsAddBoundaries(builder, boundaries)
+        bucketizeOptions = BucketizeOptionsEnd(builder)
+        return bucketizeOptions
+
+
+class GeluOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = GeluOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsGeluOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def GeluOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # GeluOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # GeluOptions
+    def Approximate(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def GeluOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def GeluOptionsAddApproximate(builder, approximate):
+    builder.PrependBoolSlot(0, approximate, 0)
+
+
+def GeluOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class GeluOptionsT(object):
+
+    # GeluOptionsT
+    def __init__(self):
+        self.approximate = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        geluOptions = GeluOptions()
+        geluOptions.Init(buf, pos)
+        return cls.InitFromObj(geluOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, geluOptions):
+        x = GeluOptionsT()
+        x._UnPack(geluOptions)
+        return x
+
+    # GeluOptionsT
+    def _UnPack(self, geluOptions):
+        if geluOptions is None:
+            return
+        self.approximate = geluOptions.Approximate()
+
+    # GeluOptionsT
+    def Pack(self, builder):
+        GeluOptionsStart(builder)
+        GeluOptionsAddApproximate(builder, self.approximate)
+        geluOptions = GeluOptionsEnd(builder)
+        return geluOptions
+
+
+class DynamicUpdateSliceOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = DynamicUpdateSliceOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsDynamicUpdateSliceOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def DynamicUpdateSliceOptionsBufferHasIdentifier(cls,
+                                                     buf,
+                                                     offset,
+                                                     size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # DynamicUpdateSliceOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def DynamicUpdateSliceOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def DynamicUpdateSliceOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class DynamicUpdateSliceOptionsT(object):
+
+    # DynamicUpdateSliceOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        dynamicUpdateSliceOptions = DynamicUpdateSliceOptions()
+        dynamicUpdateSliceOptions.Init(buf, pos)
+        return cls.InitFromObj(dynamicUpdateSliceOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, dynamicUpdateSliceOptions):
+        x = DynamicUpdateSliceOptionsT()
+        x._UnPack(dynamicUpdateSliceOptions)
+        return x
+
+    # DynamicUpdateSliceOptionsT
+    def _UnPack(self, dynamicUpdateSliceOptions):
+        if dynamicUpdateSliceOptions is None:
+            return
+
+    # DynamicUpdateSliceOptionsT
+    def Pack(self, builder):
+        DynamicUpdateSliceOptionsStart(builder)
+        dynamicUpdateSliceOptions = DynamicUpdateSliceOptionsEnd(builder)
+        return dynamicUpdateSliceOptions
+
+
+class UnsortedSegmentProdOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = UnsortedSegmentProdOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsUnsortedSegmentProdOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def UnsortedSegmentProdOptionsBufferHasIdentifier(cls,
+                                                      buf,
+                                                      offset,
+                                                      size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # UnsortedSegmentProdOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def UnsortedSegmentProdOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def UnsortedSegmentProdOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class UnsortedSegmentProdOptionsT(object):
+
+    # UnsortedSegmentProdOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        unsortedSegmentProdOptions = UnsortedSegmentProdOptions()
+        unsortedSegmentProdOptions.Init(buf, pos)
+        return cls.InitFromObj(unsortedSegmentProdOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, unsortedSegmentProdOptions):
+        x = UnsortedSegmentProdOptionsT()
+        x._UnPack(unsortedSegmentProdOptions)
+        return x
+
+    # UnsortedSegmentProdOptionsT
+    def _UnPack(self, unsortedSegmentProdOptions):
+        if unsortedSegmentProdOptions is None:
+            return
+
+    # UnsortedSegmentProdOptionsT
+    def Pack(self, builder):
+        UnsortedSegmentProdOptionsStart(builder)
+        unsortedSegmentProdOptions = UnsortedSegmentProdOptionsEnd(builder)
+        return unsortedSegmentProdOptions
+
+
+class UnsortedSegmentMaxOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = UnsortedSegmentMaxOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsUnsortedSegmentMaxOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def UnsortedSegmentMaxOptionsBufferHasIdentifier(cls,
+                                                     buf,
+                                                     offset,
+                                                     size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # UnsortedSegmentMaxOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def UnsortedSegmentMaxOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def UnsortedSegmentMaxOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class UnsortedSegmentMaxOptionsT(object):
+
+    # UnsortedSegmentMaxOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        unsortedSegmentMaxOptions = UnsortedSegmentMaxOptions()
+        unsortedSegmentMaxOptions.Init(buf, pos)
+        return cls.InitFromObj(unsortedSegmentMaxOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, unsortedSegmentMaxOptions):
+        x = UnsortedSegmentMaxOptionsT()
+        x._UnPack(unsortedSegmentMaxOptions)
+        return x
+
+    # UnsortedSegmentMaxOptionsT
+    def _UnPack(self, unsortedSegmentMaxOptions):
+        if unsortedSegmentMaxOptions is None:
+            return
+
+    # UnsortedSegmentMaxOptionsT
+    def Pack(self, builder):
+        UnsortedSegmentMaxOptionsStart(builder)
+        unsortedSegmentMaxOptions = UnsortedSegmentMaxOptionsEnd(builder)
+        return unsortedSegmentMaxOptions
+
+
+class UnsortedSegmentSumOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = UnsortedSegmentSumOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsUnsortedSegmentSumOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def UnsortedSegmentSumOptionsBufferHasIdentifier(cls,
+                                                     buf,
+                                                     offset,
+                                                     size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # UnsortedSegmentSumOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def UnsortedSegmentSumOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def UnsortedSegmentSumOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class UnsortedSegmentSumOptionsT(object):
+
+    # UnsortedSegmentSumOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        unsortedSegmentSumOptions = UnsortedSegmentSumOptions()
+        unsortedSegmentSumOptions.Init(buf, pos)
+        return cls.InitFromObj(unsortedSegmentSumOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, unsortedSegmentSumOptions):
+        x = UnsortedSegmentSumOptionsT()
+        x._UnPack(unsortedSegmentSumOptions)
+        return x
+
+    # UnsortedSegmentSumOptionsT
+    def _UnPack(self, unsortedSegmentSumOptions):
+        if unsortedSegmentSumOptions is None:
+            return
+
+    # UnsortedSegmentSumOptionsT
+    def Pack(self, builder):
+        UnsortedSegmentSumOptionsStart(builder)
+        unsortedSegmentSumOptions = UnsortedSegmentSumOptionsEnd(builder)
+        return unsortedSegmentSumOptions
+
+
+class ATan2Options(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ATan2Options()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsATan2Options(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ATan2OptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ATan2Options
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def ATan2OptionsStart(builder):
+    builder.StartObject(0)
+
+
+def ATan2OptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ATan2OptionsT(object):
+
+    # ATan2OptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        atan2Options = ATan2Options()
+        atan2Options.Init(buf, pos)
+        return cls.InitFromObj(atan2Options)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, atan2Options):
+        x = ATan2OptionsT()
+        x._UnPack(atan2Options)
+        return x
+
+    # ATan2OptionsT
+    def _UnPack(self, atan2Options):
+        if atan2Options is None:
+            return
+
+    # ATan2OptionsT
+    def Pack(self, builder):
+        ATan2OptionsStart(builder)
+        atan2Options = ATan2OptionsEnd(builder)
+        return atan2Options
+
+
+class UnsortedSegmentMinOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = UnsortedSegmentMinOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsUnsortedSegmentMinOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def UnsortedSegmentMinOptionsBufferHasIdentifier(cls,
+                                                     buf,
+                                                     offset,
+                                                     size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # UnsortedSegmentMinOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def UnsortedSegmentMinOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def UnsortedSegmentMinOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class UnsortedSegmentMinOptionsT(object):
+
+    # UnsortedSegmentMinOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        unsortedSegmentMinOptions = UnsortedSegmentMinOptions()
+        unsortedSegmentMinOptions.Init(buf, pos)
+        return cls.InitFromObj(unsortedSegmentMinOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, unsortedSegmentMinOptions):
+        x = UnsortedSegmentMinOptionsT()
+        x._UnPack(unsortedSegmentMinOptions)
+        return x
+
+    # UnsortedSegmentMinOptionsT
+    def _UnPack(self, unsortedSegmentMinOptions):
+        if unsortedSegmentMinOptions is None:
+            return
+
+    # UnsortedSegmentMinOptionsT
+    def Pack(self, builder):
+        UnsortedSegmentMinOptionsStart(builder)
+        unsortedSegmentMinOptions = UnsortedSegmentMinOptionsEnd(builder)
+        return unsortedSegmentMinOptions
+
+
+class SignOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SignOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSignOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SignOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SignOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def SignOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def SignOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SignOptionsT(object):
+
+    # SignOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        signOptions = SignOptions()
+        signOptions.Init(buf, pos)
+        return cls.InitFromObj(signOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, signOptions):
+        x = SignOptionsT()
+        x._UnPack(signOptions)
+        return x
+
+    # SignOptionsT
+    def _UnPack(self, signOptions):
+        if signOptions is None:
+            return
+
+    # SignOptionsT
+    def Pack(self, builder):
+        SignOptionsStart(builder)
+        signOptions = SignOptionsEnd(builder)
+        return signOptions
+
+
+class BitcastOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = BitcastOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBitcastOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BitcastOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # BitcastOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def BitcastOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def BitcastOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class BitcastOptionsT(object):
+
+    # BitcastOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        bitcastOptions = BitcastOptions()
+        bitcastOptions.Init(buf, pos)
+        return cls.InitFromObj(bitcastOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, bitcastOptions):
+        x = BitcastOptionsT()
+        x._UnPack(bitcastOptions)
+        return x
+
+    # BitcastOptionsT
+    def _UnPack(self, bitcastOptions):
+        if bitcastOptions is None:
+            return
+
+    # BitcastOptionsT
+    def Pack(self, builder):
+        BitcastOptionsStart(builder)
+        bitcastOptions = BitcastOptionsEnd(builder)
+        return bitcastOptions
+
+
+class BitwiseXorOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = BitwiseXorOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBitwiseXorOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BitwiseXorOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # BitwiseXorOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def BitwiseXorOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def BitwiseXorOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class BitwiseXorOptionsT(object):
+
+    # BitwiseXorOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        bitwiseXorOptions = BitwiseXorOptions()
+        bitwiseXorOptions.Init(buf, pos)
+        return cls.InitFromObj(bitwiseXorOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, bitwiseXorOptions):
+        x = BitwiseXorOptionsT()
+        x._UnPack(bitwiseXorOptions)
+        return x
+
+    # BitwiseXorOptionsT
+    def _UnPack(self, bitwiseXorOptions):
+        if bitwiseXorOptions is None:
+            return
+
+    # BitwiseXorOptionsT
+    def Pack(self, builder):
+        BitwiseXorOptionsStart(builder)
+        bitwiseXorOptions = BitwiseXorOptionsEnd(builder)
+        return bitwiseXorOptions
+
+
+class RightShiftOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = RightShiftOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsRightShiftOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def RightShiftOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # RightShiftOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def RightShiftOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def RightShiftOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class RightShiftOptionsT(object):
+
+    # RightShiftOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        rightShiftOptions = RightShiftOptions()
+        rightShiftOptions.Init(buf, pos)
+        return cls.InitFromObj(rightShiftOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, rightShiftOptions):
+        x = RightShiftOptionsT()
+        x._UnPack(rightShiftOptions)
+        return x
+
+    # RightShiftOptionsT
+    def _UnPack(self, rightShiftOptions):
+        if rightShiftOptions is None:
+            return
+
+    # RightShiftOptionsT
+    def Pack(self, builder):
+        RightShiftOptionsStart(builder)
+        rightShiftOptions = RightShiftOptionsEnd(builder)
+        return rightShiftOptions
+
+
+class DilateOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = DilateOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsDilateOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def DilateOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # DilateOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def DilateOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def DilateOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class DilateOptionsT(object):
+
+    # DilateOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        dilateOptions = DilateOptions()
+        dilateOptions.Init(buf, pos)
+        return cls.InitFromObj(dilateOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, dilateOptions):
+        x = DilateOptionsT()
+        x._UnPack(dilateOptions)
+        return x
+
+    # DilateOptionsT
+    def _UnPack(self, dilateOptions):
+        if dilateOptions is None:
+            return
+
+    # DilateOptionsT
+    def Pack(self, builder):
+        DilateOptionsStart(builder)
+        dilateOptions = DilateOptionsEnd(builder)
+        return dilateOptions
+
+
+class ReduceWindowOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ReduceWindowOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsReduceWindowOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ReduceWindowOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # ReduceWindowOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ReduceWindowOptions
+    def ReduceFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def ReduceWindowOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def ReduceWindowOptionsAddReduceFunction(builder, reduceFunction):
+    builder.PrependInt32Slot(0, reduceFunction, 0)
+
+
+def ReduceWindowOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class ReduceWindowOptionsT(object):
+
+    # ReduceWindowOptionsT
+    def __init__(self):
+        self.reduceFunction = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        reduceWindowOptions = ReduceWindowOptions()
+        reduceWindowOptions.Init(buf, pos)
+        return cls.InitFromObj(reduceWindowOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, reduceWindowOptions):
+        x = ReduceWindowOptionsT()
+        x._UnPack(reduceWindowOptions)
+        return x
+
+    # ReduceWindowOptionsT
+    def _UnPack(self, reduceWindowOptions):
+        if reduceWindowOptions is None:
+            return
+        self.reduceFunction = reduceWindowOptions.ReduceFunction()
+
+    # ReduceWindowOptionsT
+    def Pack(self, builder):
+        ReduceWindowOptionsStart(builder)
+        ReduceWindowOptionsAddReduceFunction(builder, self.reduceFunction)
+        reduceWindowOptions = ReduceWindowOptionsEnd(builder)
+        return reduceWindowOptions
+
+
+class GRUOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = GRUOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsGRUOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def GRUOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # GRUOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # GRUOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # GRUOptions
+    def ReturnSequences(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+    # GRUOptions
+    def TimeMajor(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def GRUOptionsStart(builder):
+    builder.StartObject(3)
+
+
+def GRUOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(0, fusedActivationFunction, 0)
+
+
+def GRUOptionsAddReturnSequences(builder, returnSequences):
+    builder.PrependBoolSlot(1, returnSequences, 0)
+
+
+def GRUOptionsAddTimeMajor(builder, timeMajor):
+    builder.PrependBoolSlot(2, timeMajor, 0)
+
+
+def GRUOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class GRUOptionsT(object):
+
+    # GRUOptionsT
+    def __init__(self):
+        self.fusedActivationFunction = 0  # type: int
+        self.returnSequences = False  # type: bool
+        self.timeMajor = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        gruoptions = GRUOptions()
+        gruoptions.Init(buf, pos)
+        return cls.InitFromObj(gruoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, gruoptions):
+        x = GRUOptionsT()
+        x._UnPack(gruoptions)
+        return x
+
+    # GRUOptionsT
+    def _UnPack(self, gruoptions):
+        if gruoptions is None:
+            return
+        self.fusedActivationFunction = gruoptions.FusedActivationFunction()
+        self.returnSequences = gruoptions.ReturnSequences()
+        self.timeMajor = gruoptions.TimeMajor()
+
+    # GRUOptionsT
+    def Pack(self, builder):
+        GRUOptionsStart(builder)
+        GRUOptionsAddFusedActivationFunction(builder, self.fusedActivationFunction)
+        GRUOptionsAddReturnSequences(builder, self.returnSequences)
+        GRUOptionsAddTimeMajor(builder, self.timeMajor)
+        gruoptions = GRUOptionsEnd(builder)
+        return gruoptions
+
+
+class BCQGatherOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = BCQGatherOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBCQGatherOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BCQGatherOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # BCQGatherOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # BCQGatherOptions
+    def InputHiddenSize(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # BCQGatherOptions
+    def Axis(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def BCQGatherOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def BCQGatherOptionsAddInputHiddenSize(builder, inputHiddenSize):
+    builder.PrependInt32Slot(0, inputHiddenSize, 0)
+
+
+def BCQGatherOptionsAddAxis(builder, axis):
+    builder.PrependInt32Slot(1, axis, 0)
+
+
+def BCQGatherOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class BCQGatherOptionsT(object):
+
+    # BCQGatherOptionsT
+    def __init__(self):
+        self.inputHiddenSize = 0  # type: int
+        self.axis = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        bcqgatherOptions = BCQGatherOptions()
+        bcqgatherOptions.Init(buf, pos)
+        return cls.InitFromObj(bcqgatherOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, bcqgatherOptions):
+        x = BCQGatherOptionsT()
+        x._UnPack(bcqgatherOptions)
+        return x
+
+    # BCQGatherOptionsT
+    def _UnPack(self, bcqgatherOptions):
+        if bcqgatherOptions is None:
+            return
+        self.inputHiddenSize = bcqgatherOptions.InputHiddenSize()
+        self.axis = bcqgatherOptions.Axis()
+
+    # BCQGatherOptionsT
+    def Pack(self, builder):
+        BCQGatherOptionsStart(builder)
+        BCQGatherOptionsAddInputHiddenSize(builder, self.inputHiddenSize)
+        BCQGatherOptionsAddAxis(builder, self.axis)
+        bcqgatherOptions = BCQGatherOptionsEnd(builder)
+        return bcqgatherOptions
+
+
+class BCQFullyConnectedOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = BCQFullyConnectedOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBCQFullyConnectedOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BCQFullyConnectedOptionsBufferHasIdentifier(cls, buf, offset,
+                                                    size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # BCQFullyConnectedOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # BCQFullyConnectedOptions
+    def WeightsHiddenSize(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # BCQFullyConnectedOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def BCQFullyConnectedOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def BCQFullyConnectedOptionsAddWeightsHiddenSize(builder, weightsHiddenSize):
+    builder.PrependInt32Slot(0, weightsHiddenSize, 0)
+
+
+def BCQFullyConnectedOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(1, fusedActivationFunction, 0)
+
+
+def BCQFullyConnectedOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class BCQFullyConnectedOptionsT(object):
+
+    # BCQFullyConnectedOptionsT
+    def __init__(self):
+        self.weightsHiddenSize = 0  # type: int
+        self.fusedActivationFunction = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        bcqfullyConnectedOptions = BCQFullyConnectedOptions()
+        bcqfullyConnectedOptions.Init(buf, pos)
+        return cls.InitFromObj(bcqfullyConnectedOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, bcqfullyConnectedOptions):
+        x = BCQFullyConnectedOptionsT()
+        x._UnPack(bcqfullyConnectedOptions)
+        return x
+
+    # BCQFullyConnectedOptionsT
+    def _UnPack(self, bcqfullyConnectedOptions):
+        if bcqfullyConnectedOptions is None:
+            return
+        self.weightsHiddenSize = bcqfullyConnectedOptions.WeightsHiddenSize()
+        self.fusedActivationFunction = bcqfullyConnectedOptions.FusedActivationFunction()
+
+    # BCQFullyConnectedOptionsT
+    def Pack(self, builder):
+        BCQFullyConnectedOptionsStart(builder)
+        BCQFullyConnectedOptionsAddWeightsHiddenSize(builder, self.weightsHiddenSize)
+        BCQFullyConnectedOptionsAddFusedActivationFunction(builder,
+                                                           self.fusedActivationFunction)
+        bcqfullyConnectedOptions = BCQFullyConnectedOptionsEnd(builder)
+        return bcqfullyConnectedOptions
+
+
+class InstanceNormOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = InstanceNormOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsInstanceNormOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def InstanceNormOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # InstanceNormOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # InstanceNormOptions
+    def Epsilon(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # InstanceNormOptions
+    def FusedActivationFunction(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+
+def InstanceNormOptionsStart(builder):
+    builder.StartObject(2)
+
+
+def InstanceNormOptionsAddEpsilon(builder, epsilon):
+    builder.PrependFloat32Slot(0, epsilon, 0.0)
+
+
+def InstanceNormOptionsAddFusedActivationFunction(builder, fusedActivationFunction):
+    builder.PrependInt8Slot(1, fusedActivationFunction, 0)
+
+
+def InstanceNormOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class InstanceNormOptionsT(object):
+
+    # InstanceNormOptionsT
+    def __init__(self):
+        self.epsilon = 0.0  # type: float
+        self.fusedActivationFunction = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        instanceNormOptions = InstanceNormOptions()
+        instanceNormOptions.Init(buf, pos)
+        return cls.InitFromObj(instanceNormOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, instanceNormOptions):
+        x = InstanceNormOptionsT()
+        x._UnPack(instanceNormOptions)
+        return x
+
+    # InstanceNormOptionsT
+    def _UnPack(self, instanceNormOptions):
+        if instanceNormOptions is None:
+            return
+        self.epsilon = instanceNormOptions.Epsilon()
+        self.fusedActivationFunction = instanceNormOptions.FusedActivationFunction()
+
+    # InstanceNormOptionsT
+    def Pack(self, builder):
+        InstanceNormOptionsStart(builder)
+        InstanceNormOptionsAddEpsilon(builder, self.epsilon)
+        InstanceNormOptionsAddFusedActivationFunction(builder,
+                                                      self.fusedActivationFunction)
+        instanceNormOptions = InstanceNormOptionsEnd(builder)
+        return instanceNormOptions
+
+
+class OperatorCode(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = OperatorCode()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsOperatorCode(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def OperatorCodeBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # OperatorCode
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # OperatorCode
+    def DeprecatedBuiltinCode(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # OperatorCode
+    def CustomCode(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+    # OperatorCode
+    def Version(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 1
+
+    # OperatorCode
+    def BuiltinCode(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+
+def OperatorCodeStart(builder):
+    builder.StartObject(4)
+
+
+def OperatorCodeAddDeprecatedBuiltinCode(builder, deprecatedBuiltinCode):
+    builder.PrependInt8Slot(0, deprecatedBuiltinCode, 0)
+
+
+def OperatorCodeAddCustomCode(builder, customCode):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(customCode), 0)
+
+
+def OperatorCodeAddVersion(builder, version):
+    builder.PrependInt32Slot(2, version, 1)
+
+
+def OperatorCodeAddBuiltinCode(builder, builtinCode):
+    builder.PrependInt32Slot(3, builtinCode, 0)
+
+
+def OperatorCodeEnd(builder):
+    return builder.EndObject()
+
+
+class OperatorCodeT(object):
+
+    # OperatorCodeT
+    def __init__(self):
+        self.deprecatedBuiltinCode = 0  # type: int
+        self.customCode = None  # type: str
+        self.version = 1  # type: int
+        self.builtinCode = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        operatorCode = OperatorCode()
+        operatorCode.Init(buf, pos)
+        return cls.InitFromObj(operatorCode)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, operatorCode):
+        x = OperatorCodeT()
+        x._UnPack(operatorCode)
+        return x
+
+    # OperatorCodeT
+    def _UnPack(self, operatorCode):
+        if operatorCode is None:
+            return
+        self.deprecatedBuiltinCode = operatorCode.DeprecatedBuiltinCode()
+        self.customCode = operatorCode.CustomCode()
+        self.version = operatorCode.Version()
+        self.builtinCode = operatorCode.BuiltinCode()
+
+    # OperatorCodeT
+    def Pack(self, builder):
+        if self.customCode is not None:
+            customCode = builder.CreateString(self.customCode)
+        OperatorCodeStart(builder)
+        OperatorCodeAddDeprecatedBuiltinCode(builder, self.deprecatedBuiltinCode)
+        if self.customCode is not None:
+            OperatorCodeAddCustomCode(builder, customCode)
+        OperatorCodeAddVersion(builder, self.version)
+        OperatorCodeAddBuiltinCode(builder, self.builtinCode)
+        operatorCode = OperatorCodeEnd(builder)
+        return operatorCode
+
+
+class Operator(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Operator()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsOperator(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def OperatorBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Operator
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Operator
+    def OpcodeIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
+        return 0
+
+    # Operator
+    def Inputs(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # Operator
+    def InputsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # Operator
+    def InputsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Operator
+    def InputsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # Operator
+    def Outputs(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # Operator
+    def OutputsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # Operator
+    def OutputsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Operator
+    def OutputsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+    # Operator
+    def BuiltinOptionsType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos)
+        return 0
+
+    # Operator
+    def BuiltinOptions(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            from flatbuffers.table import Table
+            obj = Table(bytearray(), 0)
+            self._tab.Union(obj, o)
+            return obj
+        return None
+
+    # Operator
+    def CustomOptions(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Uint8Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
+        return 0
+
+    # Operator
+    def CustomOptionsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o)
+        return 0
+
+    # Operator
+    def CustomOptionsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Operator
+    def CustomOptionsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        return o == 0
+
+    # Operator
+    def CustomOptionsFormat(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # Operator
+    def MutatingVariableInputs(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.BoolFlags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
+        return 0
+
+    # Operator
+    def MutatingVariableInputsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.BoolFlags, o)
+        return 0
+
+    # Operator
+    def MutatingVariableInputsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Operator
+    def MutatingVariableInputsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        return o == 0
+
+    # Operator
+    def Intermediates(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # Operator
+    def IntermediatesAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # Operator
+    def IntermediatesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Operator
+    def IntermediatesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
+        return o == 0
+
+    # Operator
+    def LargeCustomOptionsOffset(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos)
+        return 0
+
+    # Operator
+    def LargeCustomOptionsSize(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos)
+        return 0
+
+    # Operator
+    def BuiltinOptions2Type(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(26))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos)
+        return 0
+
+    # Operator
+    def BuiltinOptions2(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(28))
+        if o != 0:
+            from flatbuffers.table import Table
+            obj = Table(bytearray(), 0)
+            self._tab.Union(obj, o)
+            return obj
+        return None
+
+
+def OperatorStart(builder):
+    builder.StartObject(13)
+
+
+def OperatorAddOpcodeIndex(builder, opcodeIndex):
+    builder.PrependUint32Slot(0, opcodeIndex, 0)
+
+
+def OperatorAddInputs(builder, inputs):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(inputs), 0)
+
+
+def OperatorStartInputsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def OperatorAddOutputs(builder, outputs):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(outputs), 0)
+
+
+def OperatorStartOutputsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def OperatorAddBuiltinOptionsType(builder, builtinOptionsType):
+    builder.PrependUint8Slot(3, builtinOptionsType, 0)
+
+
+def OperatorAddBuiltinOptions(builder, builtinOptions):
+    builder.PrependUOffsetTRelativeSlot(
+        4, flatbuffers.number_types.UOffsetTFlags.py_type(builtinOptions), 0)
+
+
+def OperatorAddCustomOptions(builder, customOptions):
+    builder.PrependUOffsetTRelativeSlot(
+        5, flatbuffers.number_types.UOffsetTFlags.py_type(customOptions), 0)
+
+
+def OperatorStartCustomOptionsVector(builder, numElems):
+    return builder.StartVector(1, numElems, 1)
+
+
+def OperatorAddCustomOptionsFormat(builder, customOptionsFormat):
+    builder.PrependInt8Slot(6, customOptionsFormat, 0)
+
+
+def OperatorAddMutatingVariableInputs(builder, mutatingVariableInputs):
+    builder.PrependUOffsetTRelativeSlot(
+        7, flatbuffers.number_types.UOffsetTFlags.py_type(mutatingVariableInputs), 0)
+
+
+def OperatorStartMutatingVariableInputsVector(builder, numElems):
+    return builder.StartVector(1, numElems, 1)
+
+
+def OperatorAddIntermediates(builder, intermediates):
+    builder.PrependUOffsetTRelativeSlot(
+        8, flatbuffers.number_types.UOffsetTFlags.py_type(intermediates), 0)
+
+
+def OperatorStartIntermediatesVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def OperatorAddLargeCustomOptionsOffset(builder, largeCustomOptionsOffset):
+    builder.PrependUint64Slot(9, largeCustomOptionsOffset, 0)
+
+
+def OperatorAddLargeCustomOptionsSize(builder, largeCustomOptionsSize):
+    builder.PrependUint64Slot(10, largeCustomOptionsSize, 0)
+
+
+def OperatorAddBuiltinOptions2Type(builder, builtinOptions2Type):
+    builder.PrependUint8Slot(11, builtinOptions2Type, 0)
+
+
+def OperatorAddBuiltinOptions2(builder, builtinOptions2):
+    builder.PrependUOffsetTRelativeSlot(
+        12, flatbuffers.number_types.UOffsetTFlags.py_type(builtinOptions2), 0)
+
+
+def OperatorEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List, Union
+except:
+    pass
+
+
+class OperatorT(object):
+
+    # OperatorT
+    def __init__(self):
+        self.opcodeIndex = 0  # type: int
+        self.inputs = None  # type: List[int]
+        self.outputs = None  # type: List[int]
+        self.builtinOptionsType = 0  # type: int
+        self.builtinOptions = None  # type: Union[None, Conv2DOptionsT, DepthwiseConv2DOptionsT, ConcatEmbeddingsOptionsT, LSHProjectionOptionsT, Pool2DOptionsT, SVDFOptionsT, RNNOptionsT, FullyConnectedOptionsT, SoftmaxOptionsT, ConcatenationOptionsT, AddOptionsT, L2NormOptionsT, LocalResponseNormalizationOptionsT, LSTMOptionsT, ResizeBilinearOptionsT, CallOptionsT, ReshapeOptionsT, SkipGramOptionsT, SpaceToDepthOptionsT, EmbeddingLookupSparseOptionsT, MulOptionsT, PadOptionsT, GatherOptionsT, BatchToSpaceNDOptionsT, SpaceToBatchNDOptionsT, TransposeOptionsT, ReducerOptionsT, SubOptionsT, DivOptionsT, SqueezeOptionsT, SequenceRNNOptionsT, StridedSliceOptionsT, ExpOptionsT, TopKV2OptionsT, SplitOptionsT, LogSoftmaxOptionsT, CastOptionsT, DequantizeOptionsT, MaximumMinimumOptionsT, ArgMaxOptionsT, LessOptionsT, NegOptionsT, PadV2OptionsT, GreaterOptionsT, GreaterEqualOptionsT, LessEqualOptionsT, SelectOptionsT, SliceOptionsT, TransposeConvOptionsT, SparseToDenseOptionsT, TileOptionsT, ExpandDimsOptionsT, EqualOptionsT, NotEqualOptionsT, ShapeOptionsT, PowOptionsT, ArgMinOptionsT, FakeQuantOptionsT, PackOptionsT, LogicalOrOptionsT, OneHotOptionsT, LogicalAndOptionsT, LogicalNotOptionsT, UnpackOptionsT, FloorDivOptionsT, SquareOptionsT, ZerosLikeOptionsT, FillOptionsT, BidirectionalSequenceLSTMOptionsT, BidirectionalSequenceRNNOptionsT, UnidirectionalSequenceLSTMOptionsT, FloorModOptionsT, RangeOptionsT, ResizeNearestNeighborOptionsT, LeakyReluOptionsT, SquaredDifferenceOptionsT, MirrorPadOptionsT, AbsOptionsT, SplitVOptionsT, UniqueOptionsT, ReverseV2OptionsT, AddNOptionsT, GatherNdOptionsT, CosOptionsT, WhereOptionsT, RankOptionsT, ReverseSequenceOptionsT, MatrixDiagOptionsT, QuantizeOptionsT, MatrixSetDiagOptionsT, HardSwishOptionsT, IfOptionsT, WhileOptionsT, DepthToSpaceOptionsT, NonMaxSuppressionV4OptionsT, NonMaxSuppressionV5OptionsT, ScatterNdOptionsT, SelectV2OptionsT, DensifyOptionsT, SegmentSumOptionsT, BatchMatMulOptionsT, CumsumOptionsT, CallOnceOptionsT, BroadcastToOptionsT, Rfft2dOptionsT, Conv3DOptionsT, HashtableOptionsT, HashtableFindOptionsT, HashtableImportOptionsT, HashtableSizeOptionsT, VarHandleOptionsT, ReadVariableOptionsT, AssignVariableOptionsT, RandomOptionsT, BucketizeOptionsT, GeluOptionsT, DynamicUpdateSliceOptionsT, UnsortedSegmentProdOptionsT, UnsortedSegmentMaxOptionsT, UnsortedSegmentMinOptionsT, UnsortedSegmentSumOptionsT, ATan2OptionsT, SignOptionsT, BitcastOptionsT, BitwiseXorOptionsT, RightShiftOptionsT, GRUOptionsT, BCQGatherOptionsT, BCQFullyConnectedOptionsT, InstanceNormOptionsT]
+        self.customOptions = None  # type: List[int]
+        self.customOptionsFormat = 0  # type: int
+        self.mutatingVariableInputs = None  # type: List[bool]
+        self.intermediates = None  # type: List[int]
+        self.largeCustomOptionsOffset = 0  # type: int
+        self.largeCustomOptionsSize = 0  # type: int
+        self.builtinOptions2Type = 0  # type: int
+        self.builtinOptions2 = None  # type: Union[None, StablehloConcatenateOptionsT, StablehloBroadcastInDimOptionsT, StablehloSliceOptionsT, StablehloConvolutionOptionsT, StablehloCustomCallOptionsT, StablehloReduceOptionsT, StablehloScatterOptionsT, StablehloCompareOptionsT, StablehloDynamicSliceOptionsT, StablehloPadOptionsT, StablehloIotaOptionsT, StablehloDotGeneralOptionsT, StablehloReduceWindowOptionsT, StablehloSortOptionsT, StablehloWhileOptionsT, StablehloGatherOptionsT, StablehloTransposeOptionsT, DilateOptionsT, StablehloRngBitGeneratorOptionsT, ReduceWindowOptionsT]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        operator = Operator()
+        operator.Init(buf, pos)
+        return cls.InitFromObj(operator)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, operator):
+        x = OperatorT()
+        x._UnPack(operator)
+        return x
+
+    # OperatorT
+    def _UnPack(self, operator):
+        if operator is None:
+            return
+        self.opcodeIndex = operator.OpcodeIndex()
+        if not operator.InputsIsNone():
+            if np is None:
+                self.inputs = []
+                for i in range(operator.InputsLength()):
+                    self.inputs.append(operator.Inputs(i))
+            else:
+                self.inputs = operator.InputsAsNumpy()
+        if not operator.OutputsIsNone():
+            if np is None:
+                self.outputs = []
+                for i in range(operator.OutputsLength()):
+                    self.outputs.append(operator.Outputs(i))
+            else:
+                self.outputs = operator.OutputsAsNumpy()
+        self.builtinOptionsType = operator.BuiltinOptionsType()
+        self.builtinOptions = BuiltinOptionsCreator(self.builtinOptionsType,
+                                                    operator.BuiltinOptions())
+        if not operator.CustomOptionsIsNone():
+            if np is None:
+                self.customOptions = []
+                for i in range(operator.CustomOptionsLength()):
+                    self.customOptions.append(operator.CustomOptions(i))
+            else:
+                self.customOptions = operator.CustomOptionsAsNumpy()
+        self.customOptionsFormat = operator.CustomOptionsFormat()
+        if not operator.MutatingVariableInputsIsNone():
+            if np is None:
+                self.mutatingVariableInputs = []
+                for i in range(operator.MutatingVariableInputsLength()):
+                    self.mutatingVariableInputs.append(operator.MutatingVariableInputs(i))
+            else:
+                self.mutatingVariableInputs = operator.MutatingVariableInputsAsNumpy()
+        if not operator.IntermediatesIsNone():
+            if np is None:
+                self.intermediates = []
+                for i in range(operator.IntermediatesLength()):
+                    self.intermediates.append(operator.Intermediates(i))
+            else:
+                self.intermediates = operator.IntermediatesAsNumpy()
+        self.largeCustomOptionsOffset = operator.LargeCustomOptionsOffset()
+        self.largeCustomOptionsSize = operator.LargeCustomOptionsSize()
+        self.builtinOptions2Type = operator.BuiltinOptions2Type()
+        self.builtinOptions2 = BuiltinOptions2Creator(self.builtinOptions2Type,
+                                                      operator.BuiltinOptions2())
+
+    # OperatorT
+    def Pack(self, builder):
+        if self.inputs is not None:
+            if np is not None and type(self.inputs) is np.ndarray:
+                inputs = builder.CreateNumpyVector(self.inputs)
+            else:
+                OperatorStartInputsVector(builder, len(self.inputs))
+                for i in reversed(range(len(self.inputs))):
+                    builder.PrependInt32(self.inputs[i])
+                inputs = builder.EndVector()
+        if self.outputs is not None:
+            if np is not None and type(self.outputs) is np.ndarray:
+                outputs = builder.CreateNumpyVector(self.outputs)
+            else:
+                OperatorStartOutputsVector(builder, len(self.outputs))
+                for i in reversed(range(len(self.outputs))):
+                    builder.PrependInt32(self.outputs[i])
+                outputs = builder.EndVector()
+        if self.builtinOptions is not None:
+            builtinOptions = self.builtinOptions.Pack(builder)
+        if self.customOptions is not None:
+            if np is not None and type(self.customOptions) is np.ndarray:
+                customOptions = builder.CreateNumpyVector(self.customOptions)
+            else:
+                OperatorStartCustomOptionsVector(builder, len(self.customOptions))
+                for i in reversed(range(len(self.customOptions))):
+                    builder.PrependUint8(self.customOptions[i])
+                customOptions = builder.EndVector()
+        if self.mutatingVariableInputs is not None:
+            if np is not None and type(self.mutatingVariableInputs) is np.ndarray:
+                mutatingVariableInputs = builder.CreateNumpyVector(
+                    self.mutatingVariableInputs)
+            else:
+                OperatorStartMutatingVariableInputsVector(
+                    builder, len(self.mutatingVariableInputs))
+                for i in reversed(range(len(self.mutatingVariableInputs))):
+                    builder.PrependBool(self.mutatingVariableInputs[i])
+                mutatingVariableInputs = builder.EndVector()
+        if self.intermediates is not None:
+            if np is not None and type(self.intermediates) is np.ndarray:
+                intermediates = builder.CreateNumpyVector(self.intermediates)
+            else:
+                OperatorStartIntermediatesVector(builder, len(self.intermediates))
+                for i in reversed(range(len(self.intermediates))):
+                    builder.PrependInt32(self.intermediates[i])
+                intermediates = builder.EndVector()
+        if self.builtinOptions2 is not None:
+            builtinOptions2 = self.builtinOptions2.Pack(builder)
+        OperatorStart(builder)
+        OperatorAddOpcodeIndex(builder, self.opcodeIndex)
+        if self.inputs is not None:
+            OperatorAddInputs(builder, inputs)
+        if self.outputs is not None:
+            OperatorAddOutputs(builder, outputs)
+        OperatorAddBuiltinOptionsType(builder, self.builtinOptionsType)
+        if self.builtinOptions is not None:
+            OperatorAddBuiltinOptions(builder, builtinOptions)
+        if self.customOptions is not None:
+            OperatorAddCustomOptions(builder, customOptions)
+        OperatorAddCustomOptionsFormat(builder, self.customOptionsFormat)
+        if self.mutatingVariableInputs is not None:
+            OperatorAddMutatingVariableInputs(builder, mutatingVariableInputs)
+        if self.intermediates is not None:
+            OperatorAddIntermediates(builder, intermediates)
+        OperatorAddLargeCustomOptionsOffset(builder, self.largeCustomOptionsOffset)
+        OperatorAddLargeCustomOptionsSize(builder, self.largeCustomOptionsSize)
+        OperatorAddBuiltinOptions2Type(builder, self.builtinOptions2Type)
+        if self.builtinOptions2 is not None:
+            OperatorAddBuiltinOptions2(builder, builtinOptions2)
+        operator = OperatorEnd(builder)
+        return operator
+
+
+class SubGraph(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SubGraph()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSubGraph(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SubGraphBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SubGraph
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SubGraph
+    def Tensors(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = Tensor()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # SubGraph
+    def TensorsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # SubGraph
+    def TensorsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # SubGraph
+    def Inputs(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # SubGraph
+    def InputsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # SubGraph
+    def InputsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # SubGraph
+    def InputsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # SubGraph
+    def Outputs(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # SubGraph
+    def OutputsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # SubGraph
+    def OutputsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # SubGraph
+    def OutputsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+    # SubGraph
+    def Operators(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = Operator()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # SubGraph
+    def OperatorsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # SubGraph
+    def OperatorsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        return o == 0
+
+    # SubGraph
+    def Name(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+
+def SubGraphStart(builder):
+    builder.StartObject(6)
+
+
+def SubGraphAddTensors(builder, tensors):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(tensors), 0)
+
+
+def SubGraphStartTensorsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def SubGraphAddInputs(builder, inputs):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(inputs), 0)
+
+
+def SubGraphStartInputsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def SubGraphAddOutputs(builder, outputs):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(outputs), 0)
+
+
+def SubGraphStartOutputsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def SubGraphAddOperators(builder, operators):
+    builder.PrependUOffsetTRelativeSlot(
+        3, flatbuffers.number_types.UOffsetTFlags.py_type(operators), 0)
+
+
+def SubGraphStartOperatorsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def SubGraphAddName(builder, name):
+    builder.PrependUOffsetTRelativeSlot(
+        4, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
+
+
+def SubGraphEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class SubGraphT(object):
+
+    # SubGraphT
+    def __init__(self):
+        self.tensors = None  # type: List[TensorT]
+        self.inputs = None  # type: List[int]
+        self.outputs = None  # type: List[int]
+        self.operators = None  # type: List[OperatorT]
+        self.name = None  # type: str
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        subGraph = SubGraph()
+        subGraph.Init(buf, pos)
+        return cls.InitFromObj(subGraph)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, subGraph):
+        x = SubGraphT()
+        x._UnPack(subGraph)
+        return x
+
+    # SubGraphT
+    def _UnPack(self, subGraph):
+        if subGraph is None:
+            return
+        if not subGraph.TensorsIsNone():
+            self.tensors = []
+            for i in range(subGraph.TensorsLength()):
+                if subGraph.Tensors(i) is None:
+                    self.tensors.append(None)
+                else:
+                    tensor_ = TensorT.InitFromObj(subGraph.Tensors(i))
+                    self.tensors.append(tensor_)
+        if not subGraph.InputsIsNone():
+            if np is None:
+                self.inputs = []
+                for i in range(subGraph.InputsLength()):
+                    self.inputs.append(subGraph.Inputs(i))
+            else:
+                self.inputs = subGraph.InputsAsNumpy()
+        if not subGraph.OutputsIsNone():
+            if np is None:
+                self.outputs = []
+                for i in range(subGraph.OutputsLength()):
+                    self.outputs.append(subGraph.Outputs(i))
+            else:
+                self.outputs = subGraph.OutputsAsNumpy()
+        if not subGraph.OperatorsIsNone():
+            self.operators = []
+            for i in range(subGraph.OperatorsLength()):
+                if subGraph.Operators(i) is None:
+                    self.operators.append(None)
+                else:
+                    operator_ = OperatorT.InitFromObj(subGraph.Operators(i))
+                    self.operators.append(operator_)
+        self.name = subGraph.Name()
+
+    # SubGraphT
+    def Pack(self, builder):
+        if self.tensors is not None:
+            tensorslist = []
+            for i in range(len(self.tensors)):
+                tensorslist.append(self.tensors[i].Pack(builder))
+            SubGraphStartTensorsVector(builder, len(self.tensors))
+            for i in reversed(range(len(self.tensors))):
+                builder.PrependUOffsetTRelative(tensorslist[i])
+            tensors = builder.EndVector()
+        if self.inputs is not None:
+            if np is not None and type(self.inputs) is np.ndarray:
+                inputs = builder.CreateNumpyVector(self.inputs)
+            else:
+                SubGraphStartInputsVector(builder, len(self.inputs))
+                for i in reversed(range(len(self.inputs))):
+                    builder.PrependInt32(self.inputs[i])
+                inputs = builder.EndVector()
+        if self.outputs is not None:
+            if np is not None and type(self.outputs) is np.ndarray:
+                outputs = builder.CreateNumpyVector(self.outputs)
+            else:
+                SubGraphStartOutputsVector(builder, len(self.outputs))
+                for i in reversed(range(len(self.outputs))):
+                    builder.PrependInt32(self.outputs[i])
+                outputs = builder.EndVector()
+        if self.operators is not None:
+            operatorslist = []
+            for i in range(len(self.operators)):
+                operatorslist.append(self.operators[i].Pack(builder))
+            SubGraphStartOperatorsVector(builder, len(self.operators))
+            for i in reversed(range(len(self.operators))):
+                builder.PrependUOffsetTRelative(operatorslist[i])
+            operators = builder.EndVector()
+        if self.name is not None:
+            name = builder.CreateString(self.name)
+        SubGraphStart(builder)
+        if self.tensors is not None:
+            SubGraphAddTensors(builder, tensors)
+        if self.inputs is not None:
+            SubGraphAddInputs(builder, inputs)
+        if self.outputs is not None:
+            SubGraphAddOutputs(builder, outputs)
+        if self.operators is not None:
+            SubGraphAddOperators(builder, operators)
+        if self.name is not None:
+            SubGraphAddName(builder, name)
+        subGraph = SubGraphEnd(builder)
+        return subGraph
+
+
+class Buffer(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Buffer()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsBuffer(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def BufferBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Buffer
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Buffer
+    def Data(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Uint8Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
+        return 0
+
+    # Buffer
+    def DataAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Uint8Flags, o)
+        return 0
+
+    # Buffer
+    def DataLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Buffer
+    def DataIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # Buffer
+    def Offset(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos)
+        return 0
+
+    # Buffer
+    def Size(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos)
+        return 0
+
+
+def BufferStart(builder):
+    builder.StartObject(3)
+
+
+def BufferAddData(builder, data):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(data), 0)
+
+
+def BufferStartDataVector(builder, numElems):
+    return builder.StartVector(1, numElems, 1)
+
+
+def BufferAddOffset(builder, offset):
+    builder.PrependUint64Slot(1, offset, 0)
+
+
+def BufferAddSize(builder, size):
+    builder.PrependUint64Slot(2, size, 0)
+
+
+def BufferEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class BufferT(object):
+
+    # BufferT
+    def __init__(self):
+        self.data = None  # type: List[int]
+        self.offset = 0  # type: int
+        self.size = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        buffer = Buffer()
+        buffer.Init(buf, pos)
+        return cls.InitFromObj(buffer)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, buffer):
+        x = BufferT()
+        x._UnPack(buffer)
+        return x
+
+    # BufferT
+    def _UnPack(self, buffer):
+        if buffer is None:
+            return
+        if not buffer.DataIsNone():
+            if np is None:
+                self.data = []
+                for i in range(buffer.DataLength()):
+                    self.data.append(buffer.Data(i))
+            else:
+                self.data = buffer.DataAsNumpy()
+        self.offset = buffer.Offset()
+        self.size = buffer.Size()
+
+    # BufferT
+    def Pack(self, builder):
+        if self.data is not None:
+            if np is not None and type(self.data) is np.ndarray:
+                data = builder.CreateNumpyVector(self.data)
+            else:
+                BufferStartDataVector(builder, len(self.data))
+                for i in reversed(range(len(self.data))):
+                    builder.PrependUint8(self.data[i])
+                data = builder.EndVector()
+        BufferStart(builder)
+        if self.data is not None:
+            BufferAddData(builder, data)
+        BufferAddOffset(builder, self.offset)
+        BufferAddSize(builder, self.size)
+        buffer = BufferEnd(builder)
+        return buffer
+
+
+class Metadata(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Metadata()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsMetadata(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def MetadataBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Metadata
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Metadata
+    def Name(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+    # Metadata
+    def Buffer(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
+        return 0
+
+
+def MetadataStart(builder):
+    builder.StartObject(2)
+
+
+def MetadataAddName(builder, name):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
+
+
+def MetadataAddBuffer(builder, buffer):
+    builder.PrependUint32Slot(1, buffer, 0)
+
+
+def MetadataEnd(builder):
+    return builder.EndObject()
+
+
+class MetadataT(object):
+
+    # MetadataT
+    def __init__(self):
+        self.name = None  # type: str
+        self.buffer = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        metadata = Metadata()
+        metadata.Init(buf, pos)
+        return cls.InitFromObj(metadata)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, metadata):
+        x = MetadataT()
+        x._UnPack(metadata)
+        return x
+
+    # MetadataT
+    def _UnPack(self, metadata):
+        if metadata is None:
+            return
+        self.name = metadata.Name()
+        self.buffer = metadata.Buffer()
+
+    # MetadataT
+    def Pack(self, builder):
+        if self.name is not None:
+            name = builder.CreateString(self.name)
+        MetadataStart(builder)
+        if self.name is not None:
+            MetadataAddName(builder, name)
+        MetadataAddBuffer(builder, self.buffer)
+        metadata = MetadataEnd(builder)
+        return metadata
+
+
+class TensorMap(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = TensorMap()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsTensorMap(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def TensorMapBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # TensorMap
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # TensorMap
+    def Name(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+    # TensorMap
+    def TensorIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
+        return 0
+
+
+def TensorMapStart(builder):
+    builder.StartObject(2)
+
+
+def TensorMapAddName(builder, name):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0)
+
+
+def TensorMapAddTensorIndex(builder, tensorIndex):
+    builder.PrependUint32Slot(1, tensorIndex, 0)
+
+
+def TensorMapEnd(builder):
+    return builder.EndObject()
+
+
+class TensorMapT(object):
+
+    # TensorMapT
+    def __init__(self):
+        self.name = None  # type: str
+        self.tensorIndex = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        tensorMap = TensorMap()
+        tensorMap.Init(buf, pos)
+        return cls.InitFromObj(tensorMap)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, tensorMap):
+        x = TensorMapT()
+        x._UnPack(tensorMap)
+        return x
+
+    # TensorMapT
+    def _UnPack(self, tensorMap):
+        if tensorMap is None:
+            return
+        self.name = tensorMap.Name()
+        self.tensorIndex = tensorMap.TensorIndex()
+
+    # TensorMapT
+    def Pack(self, builder):
+        if self.name is not None:
+            name = builder.CreateString(self.name)
+        TensorMapStart(builder)
+        if self.name is not None:
+            TensorMapAddName(builder, name)
+        TensorMapAddTensorIndex(builder, self.tensorIndex)
+        tensorMap = TensorMapEnd(builder)
+        return tensorMap
+
+
+class SignatureDef(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SignatureDef()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSignatureDef(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SignatureDefBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # SignatureDef
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SignatureDef
+    def Inputs(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = TensorMap()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # SignatureDef
+    def InputsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # SignatureDef
+    def InputsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        return o == 0
+
+    # SignatureDef
+    def Outputs(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = TensorMap()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # SignatureDef
+    def OutputsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # SignatureDef
+    def OutputsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # SignatureDef
+    def SignatureKey(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+    # SignatureDef
+    def SubgraphIndex(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
+        return 0
+
+
+def SignatureDefStart(builder):
+    builder.StartObject(5)
+
+
+def SignatureDefAddInputs(builder, inputs):
+    builder.PrependUOffsetTRelativeSlot(
+        0, flatbuffers.number_types.UOffsetTFlags.py_type(inputs), 0)
+
+
+def SignatureDefStartInputsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def SignatureDefAddOutputs(builder, outputs):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(outputs), 0)
+
+
+def SignatureDefStartOutputsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def SignatureDefAddSignatureKey(builder, signatureKey):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(signatureKey), 0)
+
+
+def SignatureDefAddSubgraphIndex(builder, subgraphIndex):
+    builder.PrependUint32Slot(4, subgraphIndex, 0)
+
+
+def SignatureDefEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class SignatureDefT(object):
+
+    # SignatureDefT
+    def __init__(self):
+        self.inputs = None  # type: List[TensorMapT]
+        self.outputs = None  # type: List[TensorMapT]
+        self.signatureKey = None  # type: str
+        self.subgraphIndex = 0  # type: int
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        signatureDef = SignatureDef()
+        signatureDef.Init(buf, pos)
+        return cls.InitFromObj(signatureDef)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, signatureDef):
+        x = SignatureDefT()
+        x._UnPack(signatureDef)
+        return x
+
+    # SignatureDefT
+    def _UnPack(self, signatureDef):
+        if signatureDef is None:
+            return
+        if not signatureDef.InputsIsNone():
+            self.inputs = []
+            for i in range(signatureDef.InputsLength()):
+                if signatureDef.Inputs(i) is None:
+                    self.inputs.append(None)
+                else:
+                    tensorMap_ = TensorMapT.InitFromObj(signatureDef.Inputs(i))
+                    self.inputs.append(tensorMap_)
+        if not signatureDef.OutputsIsNone():
+            self.outputs = []
+            for i in range(signatureDef.OutputsLength()):
+                if signatureDef.Outputs(i) is None:
+                    self.outputs.append(None)
+                else:
+                    tensorMap_ = TensorMapT.InitFromObj(signatureDef.Outputs(i))
+                    self.outputs.append(tensorMap_)
+        self.signatureKey = signatureDef.SignatureKey()
+        self.subgraphIndex = signatureDef.SubgraphIndex()
+
+    # SignatureDefT
+    def Pack(self, builder):
+        if self.inputs is not None:
+            inputslist = []
+            for i in range(len(self.inputs)):
+                inputslist.append(self.inputs[i].Pack(builder))
+            SignatureDefStartInputsVector(builder, len(self.inputs))
+            for i in reversed(range(len(self.inputs))):
+                builder.PrependUOffsetTRelative(inputslist[i])
+            inputs = builder.EndVector()
+        if self.outputs is not None:
+            outputslist = []
+            for i in range(len(self.outputs)):
+                outputslist.append(self.outputs[i].Pack(builder))
+            SignatureDefStartOutputsVector(builder, len(self.outputs))
+            for i in reversed(range(len(self.outputs))):
+                builder.PrependUOffsetTRelative(outputslist[i])
+            outputs = builder.EndVector()
+        if self.signatureKey is not None:
+            signatureKey = builder.CreateString(self.signatureKey)
+        SignatureDefStart(builder)
+        if self.inputs is not None:
+            SignatureDefAddInputs(builder, inputs)
+        if self.outputs is not None:
+            SignatureDefAddOutputs(builder, outputs)
+        if self.signatureKey is not None:
+            SignatureDefAddSignatureKey(builder, signatureKey)
+        SignatureDefAddSubgraphIndex(builder, self.subgraphIndex)
+        signatureDef = SignatureDefEnd(builder)
+        return signatureDef
+
+
+class Model(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = Model()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsModel(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ModelBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x49\x52\x30", size_prefixed=size_prefixed)
+
+    # Model
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # Model
+    def Version(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
+        return 0
+
+    # Model
+    def OperatorCodes(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = OperatorCode()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # Model
+    def OperatorCodesLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Model
+    def OperatorCodesIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        return o == 0
+
+    # Model
+    def Subgraphs(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = SubGraph()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # Model
+    def SubgraphsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Model
+    def SubgraphsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        return o == 0
+
+    # Model
+    def Description(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.String(o + self._tab.Pos)
+        return None
+
+    # Model
+    def Buffers(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = Buffer()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # Model
+    def BuffersLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Model
+    def BuffersIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        return o == 0
+
+    # Model
+    def MetadataBuffer(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # Model
+    def MetadataBufferAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # Model
+    def MetadataBufferLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Model
+    def MetadataBufferIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        return o == 0
+
+    # Model
+    def Metadata(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = Metadata()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # Model
+    def MetadataLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Model
+    def MetadataIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        return o == 0
+
+    # Model
+    def SignatureDefs(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            x = self._tab.Vector(o)
+            x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4
+            x = self._tab.Indirect(x)
+            obj = SignatureDef()
+            obj.Init(self._tab.Bytes, x)
+            return obj
+        return None
+
+    # Model
+    def SignatureDefsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # Model
+    def SignatureDefsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        return o == 0
+
+
+def ModelStart(builder):
+    builder.StartObject(8)
+
+
+def ModelAddVersion(builder, version):
+    builder.PrependUint32Slot(0, version, 0)
+
+
+def ModelAddOperatorCodes(builder, operatorCodes):
+    builder.PrependUOffsetTRelativeSlot(
+        1, flatbuffers.number_types.UOffsetTFlags.py_type(operatorCodes), 0)
+
+
+def ModelStartOperatorCodesVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def ModelAddSubgraphs(builder, subgraphs):
+    builder.PrependUOffsetTRelativeSlot(
+        2, flatbuffers.number_types.UOffsetTFlags.py_type(subgraphs), 0)
+
+
+def ModelStartSubgraphsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def ModelAddDescription(builder, description):
+    builder.PrependUOffsetTRelativeSlot(
+        3, flatbuffers.number_types.UOffsetTFlags.py_type(description), 0)
+
+
+def ModelAddBuffers(builder, buffers):
+    builder.PrependUOffsetTRelativeSlot(
+        4, flatbuffers.number_types.UOffsetTFlags.py_type(buffers), 0)
+
+
+def ModelStartBuffersVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def ModelAddMetadataBuffer(builder, metadataBuffer):
+    builder.PrependUOffsetTRelativeSlot(
+        5, flatbuffers.number_types.UOffsetTFlags.py_type(metadataBuffer), 0)
+
+
+def ModelStartMetadataBufferVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def ModelAddMetadata(builder, metadata):
+    builder.PrependUOffsetTRelativeSlot(
+        6, flatbuffers.number_types.UOffsetTFlags.py_type(metadata), 0)
+
+
+def ModelStartMetadataVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def ModelAddSignatureDefs(builder, signatureDefs):
+    builder.PrependUOffsetTRelativeSlot(
+        7, flatbuffers.number_types.UOffsetTFlags.py_type(signatureDefs), 0)
+
+
+def ModelStartSignatureDefsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def ModelEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List
+except:
+    pass
+
+
+class ModelT(object):
+
+    # ModelT
+    def __init__(self):
+        self.version = 0  # type: int
+        self.operatorCodes = None  # type: List[OperatorCodeT]
+        self.subgraphs = None  # type: List[SubGraphT]
+        self.description = None  # type: str
+        self.buffers = None  # type: List[BufferT]
+        self.metadataBuffer = None  # type: List[int]
+        self.metadata = None  # type: List[MetadataT]
+        self.signatureDefs = None  # type: List[SignatureDefT]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        model = Model()
+        model.Init(buf, pos)
+        return cls.InitFromObj(model)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, model):
+        x = ModelT()
+        x._UnPack(model)
+        return x
+
+    # ModelT
+    def _UnPack(self, model):
+        if model is None:
+            return
+        self.version = model.Version()
+        if not model.OperatorCodesIsNone():
+            self.operatorCodes = []
+            for i in range(model.OperatorCodesLength()):
+                if model.OperatorCodes(i) is None:
+                    self.operatorCodes.append(None)
+                else:
+                    operatorCode_ = OperatorCodeT.InitFromObj(model.OperatorCodes(i))
+                    self.operatorCodes.append(operatorCode_)
+        if not model.SubgraphsIsNone():
+            self.subgraphs = []
+            for i in range(model.SubgraphsLength()):
+                if model.Subgraphs(i) is None:
+                    self.subgraphs.append(None)
+                else:
+                    subGraph_ = SubGraphT.InitFromObj(model.Subgraphs(i))
+                    self.subgraphs.append(subGraph_)
+        self.description = model.Description()
+        if not model.BuffersIsNone():
+            self.buffers = []
+            for i in range(model.BuffersLength()):
+                if model.Buffers(i) is None:
+                    self.buffers.append(None)
+                else:
+                    buffer_ = BufferT.InitFromObj(model.Buffers(i))
+                    self.buffers.append(buffer_)
+        if not model.MetadataBufferIsNone():
+            if np is None:
+                self.metadataBuffer = []
+                for i in range(model.MetadataBufferLength()):
+                    self.metadataBuffer.append(model.MetadataBuffer(i))
+            else:
+                self.metadataBuffer = model.MetadataBufferAsNumpy()
+        if not model.MetadataIsNone():
+            self.metadata = []
+            for i in range(model.MetadataLength()):
+                if model.Metadata(i) is None:
+                    self.metadata.append(None)
+                else:
+                    metadata_ = MetadataT.InitFromObj(model.Metadata(i))
+                    self.metadata.append(metadata_)
+        if not model.SignatureDefsIsNone():
+            self.signatureDefs = []
+            for i in range(model.SignatureDefsLength()):
+                if model.SignatureDefs(i) is None:
+                    self.signatureDefs.append(None)
+                else:
+                    signatureDef_ = SignatureDefT.InitFromObj(model.SignatureDefs(i))
+                    self.signatureDefs.append(signatureDef_)
+
+    # ModelT
+    def Pack(self, builder):
+        if self.operatorCodes is not None:
+            operatorCodeslist = []
+            for i in range(len(self.operatorCodes)):
+                operatorCodeslist.append(self.operatorCodes[i].Pack(builder))
+            ModelStartOperatorCodesVector(builder, len(self.operatorCodes))
+            for i in reversed(range(len(self.operatorCodes))):
+                builder.PrependUOffsetTRelative(operatorCodeslist[i])
+            operatorCodes = builder.EndVector()
+        if self.subgraphs is not None:
+            subgraphslist = []
+            for i in range(len(self.subgraphs)):
+                subgraphslist.append(self.subgraphs[i].Pack(builder))
+            ModelStartSubgraphsVector(builder, len(self.subgraphs))
+            for i in reversed(range(len(self.subgraphs))):
+                builder.PrependUOffsetTRelative(subgraphslist[i])
+            subgraphs = builder.EndVector()
+        if self.description is not None:
+            description = builder.CreateString(self.description)
+        if self.buffers is not None:
+            bufferslist = []
+            for i in range(len(self.buffers)):
+                bufferslist.append(self.buffers[i].Pack(builder))
+            ModelStartBuffersVector(builder, len(self.buffers))
+            for i in reversed(range(len(self.buffers))):
+                builder.PrependUOffsetTRelative(bufferslist[i])
+            buffers = builder.EndVector()
+        if self.metadataBuffer is not None:
+            if np is not None and type(self.metadataBuffer) is np.ndarray:
+                metadataBuffer = builder.CreateNumpyVector(self.metadataBuffer)
+            else:
+                ModelStartMetadataBufferVector(builder, len(self.metadataBuffer))
+                for i in reversed(range(len(self.metadataBuffer))):
+                    builder.PrependInt32(self.metadataBuffer[i])
+                metadataBuffer = builder.EndVector()
+        if self.metadata is not None:
+            metadatalist = []
+            for i in range(len(self.metadata)):
+                metadatalist.append(self.metadata[i].Pack(builder))
+            ModelStartMetadataVector(builder, len(self.metadata))
+            for i in reversed(range(len(self.metadata))):
+                builder.PrependUOffsetTRelative(metadatalist[i])
+            metadata = builder.EndVector()
+        if self.signatureDefs is not None:
+            signatureDefslist = []
+            for i in range(len(self.signatureDefs)):
+                signatureDefslist.append(self.signatureDefs[i].Pack(builder))
+            ModelStartSignatureDefsVector(builder, len(self.signatureDefs))
+            for i in reversed(range(len(self.signatureDefs))):
+                builder.PrependUOffsetTRelative(signatureDefslist[i])
+            signatureDefs = builder.EndVector()
+        ModelStart(builder)
+        ModelAddVersion(builder, self.version)
+        if self.operatorCodes is not None:
+            ModelAddOperatorCodes(builder, operatorCodes)
+        if self.subgraphs is not None:
+            ModelAddSubgraphs(builder, subgraphs)
+        if self.description is not None:
+            ModelAddDescription(builder, description)
+        if self.buffers is not None:
+            ModelAddBuffers(builder, buffers)
+        if self.metadataBuffer is not None:
+            ModelAddMetadataBuffer(builder, metadataBuffer)
+        if self.metadata is not None:
+            ModelAddMetadata(builder, metadata)
+        if self.signatureDefs is not None:
+            ModelAddSignatureDefs(builder, signatureDefs)
+        model = ModelEnd(builder)
+        return model
diff --git a/tools/circle_plus_gen/schema/circle_traininfo_generated.py b/tools/circle_plus_gen/schema/circle_traininfo_generated.py
new file mode 100644 (file)
index 0000000..c814cfb
--- /dev/null
@@ -0,0 +1,787 @@
+# generated based on commit(b3ff53668e165843d99a108d16ab14bc2cfca669)
+# automatically generated by the FlatBuffers compiler, do not modify
+
+# namespace: circle
+
+import flatbuffers
+from flatbuffers.compat import import_numpy
+np = import_numpy()
+
+
+class Optimizer(object):
+    SGD = 0
+    ADAM = 1
+
+
+class OptimizerOptions(object):
+    NONE = 0
+    SGDOptions = 1
+    AdamOptions = 2
+
+
+def OptimizerOptionsCreator(unionType, table):
+    from flatbuffers.table import Table
+    if not isinstance(table, Table):
+        return None
+    if unionType == OptimizerOptions().SGDOptions:
+        return SGDOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == OptimizerOptions().AdamOptions:
+        return AdamOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    return None
+
+
+class LossFn(object):
+    SPARSE_CATEGORICAL_CROSSENTROPY = 0
+    CATEGORICAL_CROSSENTROPY = 1
+    MEAN_SQUARED_ERROR = 2
+
+
+class LossFnOptions(object):
+    NONE = 0
+    SparseCategoricalCrossentropyOptions = 1
+    CategoricalCrossentropyOptions = 2
+    MeanSquaredErrorOptions = 3
+
+
+def LossFnOptionsCreator(unionType, table):
+    from flatbuffers.table import Table
+    if not isinstance(table, Table):
+        return None
+    if unionType == LossFnOptions().SparseCategoricalCrossentropyOptions:
+        return SparseCategoricalCrossentropyOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == LossFnOptions().CategoricalCrossentropyOptions:
+        return CategoricalCrossentropyOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    if unionType == LossFnOptions().MeanSquaredErrorOptions:
+        return MeanSquaredErrorOptionsT.InitFromBuf(table.Bytes, table.Pos)
+    return None
+
+
+class LossReductionType(object):
+    SumOverBatchSize = 0
+    Sum = 1
+
+
+class SGDOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SGDOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSGDOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SGDOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x54\x52\x30", size_prefixed=size_prefixed)
+
+    # SGDOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SGDOptions
+    def LearningRate(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+
+def SGDOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def SGDOptionsAddLearningRate(builder, learningRate):
+    builder.PrependFloat32Slot(0, learningRate, 0.0)
+
+
+def SGDOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SGDOptionsT(object):
+
+    # SGDOptionsT
+    def __init__(self):
+        self.learningRate = 0.0  # type: float
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        sgdoptions = SGDOptions()
+        sgdoptions.Init(buf, pos)
+        return cls.InitFromObj(sgdoptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, sgdoptions):
+        x = SGDOptionsT()
+        x._UnPack(sgdoptions)
+        return x
+
+    # SGDOptionsT
+    def _UnPack(self, sgdoptions):
+        if sgdoptions is None:
+            return
+        self.learningRate = sgdoptions.LearningRate()
+
+    # SGDOptionsT
+    def Pack(self, builder):
+        SGDOptionsStart(builder)
+        SGDOptionsAddLearningRate(builder, self.learningRate)
+        sgdoptions = SGDOptionsEnd(builder)
+        return sgdoptions
+
+
+class AdamOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = AdamOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsAdamOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def AdamOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x54\x52\x30", size_prefixed=size_prefixed)
+
+    # AdamOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # AdamOptions
+    def LearningRate(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # AdamOptions
+    def Beta1(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # AdamOptions
+    def Beta2(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+    # AdamOptions
+    def Epsilon(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos)
+        return 0.0
+
+
+def AdamOptionsStart(builder):
+    builder.StartObject(4)
+
+
+def AdamOptionsAddLearningRate(builder, learningRate):
+    builder.PrependFloat32Slot(0, learningRate, 0.0)
+
+
+def AdamOptionsAddBeta1(builder, beta1):
+    builder.PrependFloat32Slot(1, beta1, 0.0)
+
+
+def AdamOptionsAddBeta2(builder, beta2):
+    builder.PrependFloat32Slot(2, beta2, 0.0)
+
+
+def AdamOptionsAddEpsilon(builder, epsilon):
+    builder.PrependFloat32Slot(3, epsilon, 0.0)
+
+
+def AdamOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class AdamOptionsT(object):
+
+    # AdamOptionsT
+    def __init__(self):
+        self.learningRate = 0.0  # type: float
+        self.beta1 = 0.0  # type: float
+        self.beta2 = 0.0  # type: float
+        self.epsilon = 0.0  # type: float
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        adamOptions = AdamOptions()
+        adamOptions.Init(buf, pos)
+        return cls.InitFromObj(adamOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, adamOptions):
+        x = AdamOptionsT()
+        x._UnPack(adamOptions)
+        return x
+
+    # AdamOptionsT
+    def _UnPack(self, adamOptions):
+        if adamOptions is None:
+            return
+        self.learningRate = adamOptions.LearningRate()
+        self.beta1 = adamOptions.Beta1()
+        self.beta2 = adamOptions.Beta2()
+        self.epsilon = adamOptions.Epsilon()
+
+    # AdamOptionsT
+    def Pack(self, builder):
+        AdamOptionsStart(builder)
+        AdamOptionsAddLearningRate(builder, self.learningRate)
+        AdamOptionsAddBeta1(builder, self.beta1)
+        AdamOptionsAddBeta2(builder, self.beta2)
+        AdamOptionsAddEpsilon(builder, self.epsilon)
+        adamOptions = AdamOptionsEnd(builder)
+        return adamOptions
+
+
+class SparseCategoricalCrossentropyOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = SparseCategoricalCrossentropyOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsSparseCategoricalCrossentropyOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def SparseCategoricalCrossentropyOptionsBufferHasIdentifier(
+            cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x54\x52\x30", size_prefixed=size_prefixed)
+
+    # SparseCategoricalCrossentropyOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # SparseCategoricalCrossentropyOptions
+    def FromLogits(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def SparseCategoricalCrossentropyOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def SparseCategoricalCrossentropyOptionsAddFromLogits(builder, fromLogits):
+    builder.PrependBoolSlot(0, fromLogits, 0)
+
+
+def SparseCategoricalCrossentropyOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class SparseCategoricalCrossentropyOptionsT(object):
+
+    # SparseCategoricalCrossentropyOptionsT
+    def __init__(self):
+        self.fromLogits = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        sparseCategoricalCrossentropyOptions = SparseCategoricalCrossentropyOptions()
+        sparseCategoricalCrossentropyOptions.Init(buf, pos)
+        return cls.InitFromObj(sparseCategoricalCrossentropyOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, sparseCategoricalCrossentropyOptions):
+        x = SparseCategoricalCrossentropyOptionsT()
+        x._UnPack(sparseCategoricalCrossentropyOptions)
+        return x
+
+    # SparseCategoricalCrossentropyOptionsT
+    def _UnPack(self, sparseCategoricalCrossentropyOptions):
+        if sparseCategoricalCrossentropyOptions is None:
+            return
+        self.fromLogits = sparseCategoricalCrossentropyOptions.FromLogits()
+
+    # SparseCategoricalCrossentropyOptionsT
+    def Pack(self, builder):
+        SparseCategoricalCrossentropyOptionsStart(builder)
+        SparseCategoricalCrossentropyOptionsAddFromLogits(builder, self.fromLogits)
+        sparseCategoricalCrossentropyOptions = SparseCategoricalCrossentropyOptionsEnd(
+            builder)
+        return sparseCategoricalCrossentropyOptions
+
+
+class CategoricalCrossentropyOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = CategoricalCrossentropyOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsCategoricalCrossentropyOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def CategoricalCrossentropyOptionsBufferHasIdentifier(cls,
+                                                          buf,
+                                                          offset,
+                                                          size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x54\x52\x30", size_prefixed=size_prefixed)
+
+    # CategoricalCrossentropyOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # CategoricalCrossentropyOptions
+    def FromLogits(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return bool(
+                self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos))
+        return False
+
+
+def CategoricalCrossentropyOptionsStart(builder):
+    builder.StartObject(1)
+
+
+def CategoricalCrossentropyOptionsAddFromLogits(builder, fromLogits):
+    builder.PrependBoolSlot(0, fromLogits, 0)
+
+
+def CategoricalCrossentropyOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class CategoricalCrossentropyOptionsT(object):
+
+    # CategoricalCrossentropyOptionsT
+    def __init__(self):
+        self.fromLogits = False  # type: bool
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        categoricalCrossentropyOptions = CategoricalCrossentropyOptions()
+        categoricalCrossentropyOptions.Init(buf, pos)
+        return cls.InitFromObj(categoricalCrossentropyOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, categoricalCrossentropyOptions):
+        x = CategoricalCrossentropyOptionsT()
+        x._UnPack(categoricalCrossentropyOptions)
+        return x
+
+    # CategoricalCrossentropyOptionsT
+    def _UnPack(self, categoricalCrossentropyOptions):
+        if categoricalCrossentropyOptions is None:
+            return
+        self.fromLogits = categoricalCrossentropyOptions.FromLogits()
+
+    # CategoricalCrossentropyOptionsT
+    def Pack(self, builder):
+        CategoricalCrossentropyOptionsStart(builder)
+        CategoricalCrossentropyOptionsAddFromLogits(builder, self.fromLogits)
+        categoricalCrossentropyOptions = CategoricalCrossentropyOptionsEnd(builder)
+        return categoricalCrossentropyOptions
+
+
+class MeanSquaredErrorOptions(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = MeanSquaredErrorOptions()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsMeanSquaredErrorOptions(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def MeanSquaredErrorOptionsBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x54\x52\x30", size_prefixed=size_prefixed)
+
+    # MeanSquaredErrorOptions
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+
+def MeanSquaredErrorOptionsStart(builder):
+    builder.StartObject(0)
+
+
+def MeanSquaredErrorOptionsEnd(builder):
+    return builder.EndObject()
+
+
+class MeanSquaredErrorOptionsT(object):
+
+    # MeanSquaredErrorOptionsT
+    def __init__(self):
+        pass
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        meanSquaredErrorOptions = MeanSquaredErrorOptions()
+        meanSquaredErrorOptions.Init(buf, pos)
+        return cls.InitFromObj(meanSquaredErrorOptions)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, meanSquaredErrorOptions):
+        x = MeanSquaredErrorOptionsT()
+        x._UnPack(meanSquaredErrorOptions)
+        return x
+
+    # MeanSquaredErrorOptionsT
+    def _UnPack(self, meanSquaredErrorOptions):
+        if meanSquaredErrorOptions is None:
+            return
+
+    # MeanSquaredErrorOptionsT
+    def Pack(self, builder):
+        MeanSquaredErrorOptionsStart(builder)
+        meanSquaredErrorOptions = MeanSquaredErrorOptionsEnd(builder)
+        return meanSquaredErrorOptions
+
+
+class ModelTraining(object):
+    __slots__ = ['_tab']
+
+    @classmethod
+    def GetRootAs(cls, buf, offset=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
+        x = ModelTraining()
+        x.Init(buf, n + offset)
+        return x
+
+    @classmethod
+    def GetRootAsModelTraining(cls, buf, offset=0):
+        """This method is deprecated. Please switch to GetRootAs."""
+        return cls.GetRootAs(buf, offset)
+
+    @classmethod
+    def ModelTrainingBufferHasIdentifier(cls, buf, offset, size_prefixed=False):
+        return flatbuffers.util.BufferHasIdentifier(
+            buf, offset, b"\x43\x54\x52\x30", size_prefixed=size_prefixed)
+
+    # ModelTraining
+    def Init(self, buf, pos):
+        self._tab = flatbuffers.table.Table(buf, pos)
+
+    # ModelTraining
+    def Version(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos)
+        return 0
+
+    # ModelTraining
+    def Optimizer(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # ModelTraining
+    def OptimizerOptType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos)
+        return 0
+
+    # ModelTraining
+    def OptimizerOpt(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
+        if o != 0:
+            from flatbuffers.table import Table
+            obj = Table(bytearray(), 0)
+            self._tab.Union(obj, o)
+            return obj
+        return None
+
+    # ModelTraining
+    def Lossfn(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # ModelTraining
+    def LossfnOptType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos)
+        return 0
+
+    # ModelTraining
+    def LossfnOpt(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
+        if o != 0:
+            from flatbuffers.table import Table
+            obj = Table(bytearray(), 0)
+            self._tab.Union(obj, o)
+            return obj
+        return None
+
+    # ModelTraining
+    def Epochs(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # ModelTraining
+    def BatchSize(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos)
+        return 0
+
+    # ModelTraining
+    def LossReductionType(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
+        if o != 0:
+            return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos)
+        return 0
+
+    # ModelTraining
+    def TrainableOps(self, j):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24))
+        if o != 0:
+            a = self._tab.Vector(o)
+            return self._tab.Get(
+                flatbuffers.number_types.Int32Flags,
+                a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4))
+        return 0
+
+    # ModelTraining
+    def TrainableOpsAsNumpy(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24))
+        if o != 0:
+            return self._tab.GetVectorAsNumpy(flatbuffers.number_types.Int32Flags, o)
+        return 0
+
+    # ModelTraining
+    def TrainableOpsLength(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24))
+        if o != 0:
+            return self._tab.VectorLen(o)
+        return 0
+
+    # ModelTraining
+    def TrainableOpsIsNone(self):
+        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24))
+        return o == 0
+
+
+def ModelTrainingStart(builder):
+    builder.StartObject(11)
+
+
+def ModelTrainingAddVersion(builder, version):
+    builder.PrependUint32Slot(0, version, 0)
+
+
+def ModelTrainingAddOptimizer(builder, optimizer):
+    builder.PrependInt8Slot(1, optimizer, 0)
+
+
+def ModelTrainingAddOptimizerOptType(builder, optimizerOptType):
+    builder.PrependUint8Slot(2, optimizerOptType, 0)
+
+
+def ModelTrainingAddOptimizerOpt(builder, optimizerOpt):
+    builder.PrependUOffsetTRelativeSlot(
+        3, flatbuffers.number_types.UOffsetTFlags.py_type(optimizerOpt), 0)
+
+
+def ModelTrainingAddLossfn(builder, lossfn):
+    builder.PrependInt8Slot(4, lossfn, 0)
+
+
+def ModelTrainingAddLossfnOptType(builder, lossfnOptType):
+    builder.PrependUint8Slot(5, lossfnOptType, 0)
+
+
+def ModelTrainingAddLossfnOpt(builder, lossfnOpt):
+    builder.PrependUOffsetTRelativeSlot(
+        6, flatbuffers.number_types.UOffsetTFlags.py_type(lossfnOpt), 0)
+
+
+def ModelTrainingAddEpochs(builder, epochs):
+    builder.PrependInt32Slot(7, epochs, 0)
+
+
+def ModelTrainingAddBatchSize(builder, batchSize):
+    builder.PrependInt32Slot(8, batchSize, 0)
+
+
+def ModelTrainingAddLossReductionType(builder, lossReductionType):
+    builder.PrependInt8Slot(9, lossReductionType, 0)
+
+
+def ModelTrainingAddTrainableOps(builder, trainableOps):
+    builder.PrependUOffsetTRelativeSlot(
+        10, flatbuffers.number_types.UOffsetTFlags.py_type(trainableOps), 0)
+
+
+def ModelTrainingStartTrainableOpsVector(builder, numElems):
+    return builder.StartVector(4, numElems, 4)
+
+
+def ModelTrainingEnd(builder):
+    return builder.EndObject()
+
+
+try:
+    from typing import List, Union
+except:
+    pass
+
+
+class ModelTrainingT(object):
+
+    # ModelTrainingT
+    def __init__(self):
+        self.version = 0  # type: int
+        self.optimizer = 0  # type: int
+        self.optimizerOptType = 0  # type: int
+        self.optimizerOpt = None  # type: Union[None, SGDOptionsT, AdamOptionsT]
+        self.lossfn = 0  # type: int
+        self.lossfnOptType = 0  # type: int
+        self.lossfnOpt = None  # type: Union[None, SparseCategoricalCrossentropyOptionsT, CategoricalCrossentropyOptionsT, MeanSquaredErrorOptionsT]
+        self.epochs = 0  # type: int
+        self.batchSize = 0  # type: int
+        self.lossReductionType = 0  # type: int
+        self.trainableOps = None  # type: List[int]
+
+    @classmethod
+    def InitFromBuf(cls, buf, pos):
+        modelTraining = ModelTraining()
+        modelTraining.Init(buf, pos)
+        return cls.InitFromObj(modelTraining)
+
+    @classmethod
+    def InitFromPackedBuf(cls, buf, pos=0):
+        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)
+        return cls.InitFromBuf(buf, pos + n)
+
+    @classmethod
+    def InitFromObj(cls, modelTraining):
+        x = ModelTrainingT()
+        x._UnPack(modelTraining)
+        return x
+
+    # ModelTrainingT
+    def _UnPack(self, modelTraining):
+        if modelTraining is None:
+            return
+        self.version = modelTraining.Version()
+        self.optimizer = modelTraining.Optimizer()
+        self.optimizerOptType = modelTraining.OptimizerOptType()
+        self.optimizerOpt = OptimizerOptionsCreator(self.optimizerOptType,
+                                                    modelTraining.OptimizerOpt())
+        self.lossfn = modelTraining.Lossfn()
+        self.lossfnOptType = modelTraining.LossfnOptType()
+        self.lossfnOpt = LossFnOptionsCreator(self.lossfnOptType,
+                                              modelTraining.LossfnOpt())
+        self.epochs = modelTraining.Epochs()
+        self.batchSize = modelTraining.BatchSize()
+        self.lossReductionType = modelTraining.LossReductionType()
+        if not modelTraining.TrainableOpsIsNone():
+            if np is None:
+                self.trainableOps = []
+                for i in range(modelTraining.TrainableOpsLength()):
+                    self.trainableOps.append(modelTraining.TrainableOps(i))
+            else:
+                self.trainableOps = modelTraining.TrainableOpsAsNumpy()
+
+    # ModelTrainingT
+    def Pack(self, builder):
+        if self.optimizerOpt is not None:
+            optimizerOpt = self.optimizerOpt.Pack(builder)
+        if self.lossfnOpt is not None:
+            lossfnOpt = self.lossfnOpt.Pack(builder)
+        if self.trainableOps is not None:
+            if np is not None and type(self.trainableOps) is np.ndarray:
+                trainableOps = builder.CreateNumpyVector(self.trainableOps)
+            else:
+                ModelTrainingStartTrainableOpsVector(builder, len(self.trainableOps))
+                for i in reversed(range(len(self.trainableOps))):
+                    builder.PrependInt32(self.trainableOps[i])
+                trainableOps = builder.EndVector()
+        ModelTrainingStart(builder)
+        ModelTrainingAddVersion(builder, self.version)
+        ModelTrainingAddOptimizer(builder, self.optimizer)
+        ModelTrainingAddOptimizerOptType(builder, self.optimizerOptType)
+        if self.optimizerOpt is not None:
+            ModelTrainingAddOptimizerOpt(builder, optimizerOpt)
+        ModelTrainingAddLossfn(builder, self.lossfn)
+        ModelTrainingAddLossfnOptType(builder, self.lossfnOptType)
+        if self.lossfnOpt is not None:
+            ModelTrainingAddLossfnOpt(builder, lossfnOpt)
+        ModelTrainingAddEpochs(builder, self.epochs)
+        ModelTrainingAddBatchSize(builder, self.batchSize)
+        ModelTrainingAddLossReductionType(builder, self.lossReductionType)
+        if self.trainableOps is not None:
+            ModelTrainingAddTrainableOps(builder, trainableOps)
+        modelTraining = ModelTrainingEnd(builder)
+        return modelTraining
diff --git a/tools/circle_plus_gen/test/__init__.py b/tools/circle_plus_gen/test/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tools/circle_plus_gen/test/test_circle_plus.py b/tools/circle_plus_gen/test/test_circle_plus.py
new file mode 100644 (file)
index 0000000..70e7b8d
--- /dev/null
@@ -0,0 +1,31 @@
+import unittest
+import hashlib
+import os
+
+from lib.circle_plus import CirclePlus
+
+
+def get_md5sum(file: str):
+    with open(file, 'rb') as f:
+        return hashlib.md5(f.read()).hexdigest()
+
+
+class TestCirclePlus(unittest.TestCase):
+    def setUp(self):
+        # sample.circle has a single operator(fully connected)
+        circle_file = "./example/sample.circle"
+        assert get_md5sum(circle_file) == 'df287dea52cf5bf16bc9dc720e8bca04'
+
+        self.circle_model = CirclePlus.from_file(circle_file)
+
+    def test_get_number_of_operators(self):
+        num_op = self.circle_model.get_number_of_operators()
+        self.assertEqual(num_op, 1)
+
+    def test_get_operator_names(self):
+        ops = self.circle_model.get_operator_names()
+        self.assertEqual(ops, ['FULLY_CONNECTED'])
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tools/cross/aarch64/sources.list.bionic b/tools/cross/aarch64/sources.list.bionic
deleted file mode 100644 (file)
index 2109557..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
-deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
-
-deb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
-deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
-
-deb http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
-deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
-
-deb http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
-deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
diff --git a/tools/cross/aarch64/sources.list.noble b/tools/cross/aarch64/sources.list.noble
new file mode 100644 (file)
index 0000000..cf87df2
--- /dev/null
@@ -0,0 +1,11 @@
+deb http://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe
+
+deb http://ports.ubuntu.com/ubuntu-ports/ noble-updates main restricted universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ noble-updates main restricted universe
+
+deb http://ports.ubuntu.com/ubuntu-ports/ noble-backports main restricted
+deb-src http://ports.ubuntu.com/ubuntu-ports/ noble-backports main restricted
+
+deb http://ports.ubuntu.com/ubuntu-ports/ noble-security main restricted universe multiverse
+deb-src http://ports.ubuntu.com/ubuntu-ports/ noble-security main restricted universe multiverse
diff --git a/tools/cross/arm/sources.list.bionic b/tools/cross/arm/sources.list.bionic
deleted file mode 100644 (file)
index 2109557..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
-deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
-
-deb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
-deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
-
-deb http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
-deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
-
-deb http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
-deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
diff --git a/tools/cross/arm/sources.list.noble b/tools/cross/arm/sources.list.noble
new file mode 100644 (file)
index 0000000..cf87df2
--- /dev/null
@@ -0,0 +1,11 @@
+deb http://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ noble main restricted universe
+
+deb http://ports.ubuntu.com/ubuntu-ports/ noble-updates main restricted universe
+deb-src http://ports.ubuntu.com/ubuntu-ports/ noble-updates main restricted universe
+
+deb http://ports.ubuntu.com/ubuntu-ports/ noble-backports main restricted
+deb-src http://ports.ubuntu.com/ubuntu-ports/ noble-backports main restricted
+
+deb http://ports.ubuntu.com/ubuntu-ports/ noble-security main restricted universe multiverse
+deb-src http://ports.ubuntu.com/ubuntu-ports/ noble-security main restricted universe multiverse
index e3e86f4..bde36ce 100755 (executable)
 usage()
 {
     echo "Usage: $0 [--ndk-version=NDKVersion] [--install-dir=InstallDir]"
-    echo "  NDKVersion : r20(default) or higher"
+    echo "  NDKVersion : r26d(default) or other version"
     echo "  InstallDir : Path to be installed"
     exit 1
 }
 
 __CrossDir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
-__NDKVersion=r20
+__NDKVersion=r26d
 __UnprocessedBuildArgs=
 
 while [[ $# -gt 0 ]]
@@ -59,7 +59,7 @@ do
     shift
 done
 
-__InstallDir=${__InstallDir:-"${__CrossDir}/ndk/${__NDKVersion}"}
+__InstallDir=${__InstallDir:-"${__CrossDir}/ndk"}
 
 NDK_DIR=android-ndk-${__NDKVersion}
 NDK_ZIP=${NDK_DIR}-linux-x86_64.zip
@@ -82,4 +82,3 @@ fi
 echo "Unzipping Android NDK"
 unzip -qq -o $__InstallDir/$NDK_ZIP -d $__InstallDir
 rm $__InstallDir/$NDK_ZIP
-mv  $__InstallDir/${NDK_DIR} "$__InstallDir/ndk" # This is necessary since Tensorflow Lite does include like `#include "ndk/sources/..."`
index 0cefa4a..8f1d2fd 100755 (executable)
 # Setup Android Cross-Build Environment (ANDROID SDK)
 SCRIPT_HOME=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) # absolute path to directory where script is
 INSTALL_PATH=$SCRIPT_HOME/android_sdk # path to directory where android sdk will be installed
-PLATFORMS_PACKAGE_VERSION="28" # version of platfroms package which will be installed
-BUILD_TOOLS_PACKAGE_VERSION="28.0.0" # version of build-tools package which will be installed
-COMMAND_LINE_TOOLS_ARCHIVE="commandlinetools-linux-6200805_latest.zip" # command line tools archive name from site https://developer.android.com/studio/#downloads
+PLATFORMS_PACKAGE_VERSION="29" # version of platfroms package which will be installed
+BUILD_TOOLS_PACKAGE_VERSION="29.0.3" # version of build-tools package which will be installed
+NDK_VERSION="26.3.11579264" # version of ndk which will be installed
+COMMAND_LINE_TOOLS_ARCHIVE="commandlinetools-linux-6514223_latest.zip" # command line tools archive name from site https://developer.android.com/studio/#downloads for bootstrap
+COMMAND_LINE_TOOLS_VERSION="10.0" # version of command line tools which will be installed
 
 
 usage() {
@@ -27,6 +29,7 @@ usage() {
  printf "  --install-dir                 - absolute path to directory where android sdk will be installed, by default: $INSTALL_PATH\n"
  printf "  --platforms-package-version   - version of platforms package which will be installed, by default: $PLATFORMS_PACKAGE_VERSION\n"
  printf "  --build-tools-package-version - version of build-tools package which will be installed, by default: $BUILD_TOOLS_PACKAGE_VERSION\n"
+ printf "  --command-line-tools-version  - version of cmdline-tools package which will be installed, by default: $COMMAND_LINE_TOOLS_VERSION\n"
  printf "  --command-line-tools-archive  - name of command line tools archive from site https://developer.android.com/studio/#downloads, by default: $COMMAND_LINE_TOOLS_ARCHIVE\n"
  printf "  --help                        - show this text\n"
 }
@@ -35,8 +38,8 @@ check_that_available() {
   local util_name=${1}
   local possible_util_alias=${2}
   if ! [ -x "$(command -v $util_name)" ]; then
-    printf "ERROR: this script uses $util_name utility, "
-    printf "please install it and repeat try (e.g. for ubuntu execute command: sudo apt install $possible_util_alias)"
+    printf "ERROR: this script uses $util_name utility, \n"
+    printf "please install it and repeat try (e.g. for ubuntu execute command: sudo apt install $possible_util_alias)\n"
     exit 1
   fi
 }
@@ -44,7 +47,7 @@ check_that_available() {
 check_preconditions() {
   check_that_available wget wget
   check_that_available unzip unzip
-  check_that_available java default-jdk
+  check_that_available java 'default-jdk or openjdk-{version}-jdk. SDK command line tools require proper openjdk version'
 }
 
 check_that_android_sdk_have_not_been_installed_yet() {
@@ -61,19 +64,19 @@ make_environment() {
   check_that_android_sdk_have_not_been_installed_yet $root
   mkdir -p $root
 
-  pushd $root
+  pushd $root > /dev/null
   export ANDROID_HOME=$root
-  export PATH=$PATH:/$ANDROID_HOME/tools/bin
-  export PATH=$PATH:/$ANDROID_HOME/platform-tools
+  export PATH=$PATH:$ANDROID_HOME/cmdline-tools/${COMMAND_LINE_TOOLS_VERSION}/bin
+  export PATH=$PATH:$ANDROID_HOME/platform-tools
   export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions'
-  popd
+  popd > /dev/null
 }
 
-download_command_line_tools() {
+install_command_line_tools() {
   local root=${1}
   local download_url=https://dl.google.com/android/repository
-
-  pushd $root
+  temp_dir=$(mktemp -d)
+  pushd $temp_dir > /dev/null
   wget $download_url/$COMMAND_LINE_TOOLS_ARCHIVE
   if [ ${?} -ne 0 ]; then
     echo "seems like '$COMMAND_LINE_TOOLS_ARCHIVE' not found. Please, go to https://developer.android.com/studio/#downloads "
@@ -81,23 +84,15 @@ download_command_line_tools() {
     echo "and put it as --command-line-tools-archive-name parameter value"
     exit 1
   fi
-  popd
-}
 
-extract_command_line_tools() {
-  local root=${1}
-
-  pushd $root
   unzip $COMMAND_LINE_TOOLS_ARCHIVE
   rm $COMMAND_LINE_TOOLS_ARCHIVE
-  popd
-}
 
-install_command_line_tools() {
-  local root=${1}
+  yes | tools/bin/sdkmanager --sdk_root=${root} --licenses
+  tools/bin/sdkmanager --sdk_root=${root} "cmdline-tools;${COMMAND_LINE_TOOLS_VERSION}"
+  popd > /dev/null
 
-  download_command_line_tools $root
-  extract_command_line_tools $root
+  rm -rf $temp_dir
 }
 
 check_that_given_version_of_package_available() {
@@ -115,16 +110,23 @@ check_that_given_version_of_package_available() {
 install_android_sdk() {
   local root=${1}
 
-  pushd $root
-  yes | sdkmanager --sdk_root=${ANDROID_HOME} --licenses > /dev/null
+  pushd $root > /dev/null
   check_that_given_version_of_package_available "platforms;android-" ${PLATFORMS_PACKAGE_VERSION}
   check_that_given_version_of_package_available "build-tools;" ${BUILD_TOOLS_PACKAGE_VERSION}
-  sdkmanager --sdk_root=${ANDROID_HOME} "platform-tools"
-  sdkmanager --sdk_root=${ANDROID_HOME} "platforms;android-$PLATFORMS_PACKAGE_VERSION"
-  sdkmanager --sdk_root=${ANDROID_HOME} "build-tools;$BUILD_TOOLS_PACKAGE_VERSION"
-  popd
+  sdkmanager --sdk_root=${root} "platform-tools" "emulator"
+  sdkmanager --sdk_root=${root} "platforms;android-$PLATFORMS_PACKAGE_VERSION"
+  sdkmanager --sdk_root=${root} "build-tools;$BUILD_TOOLS_PACKAGE_VERSION"
+  popd > /dev/null
 }
 
+install_android_ndk() {
+  local root=${1}
+
+  pushd $root > /dev/null
+  sdkmanager --sdk_root=${root} "ndk;$NDK_VERSION"
+  echo "Android NDK is installed on $root"/ndk/$NDK_VERSION" directory"
+  popd > /dev/null
+}
 
 while [[ $# -gt 0 ]]; do
   key="$(echo $1 | awk '{print tolower($0)}')"
@@ -148,6 +150,11 @@ while [[ $# -gt 0 ]]; do
       BUILD_TOOLS_PACKAGE_VERSION=${1}
       shift
       ;;
+    --ndk-version)
+      shift
+      NDK_VERSION=${1}
+      shift
+      ;;
     --command-line-tools-archive)
       shift
       COMMAND_LINE_TOOLS_ARCHIVE=${1}
@@ -164,4 +171,5 @@ done
 check_preconditions
 make_environment $INSTALL_PATH
 install_command_line_tools $INSTALL_PATH
+install_android_ndk $INSTALL_PATH
 install_android_sdk $INSTALL_PATH
index 7af7bf7..78b08bb 100755 (executable)
@@ -1,9 +1,13 @@
 #!/usr/bin/env bash
+
+source /etc/lsb-release
+
 usage()
 {
     echo "Usage: $0 [BuildArch] [LinuxCodeName] [--setproxy=IP] [--skipunmount]"
     echo "BuildArch can be: arm(default), aarch64"
-    echo "LinuxCodeName - optional, Code name for Linux, can be: bionic, focal(default), jammy"
+    echo "LinuxCodeName - optional, Code name for Linux, can be: focal, jammy, noble"
+    echo "                          default is host codename: ${DISTRIB_CODENAME} (DISTRIB_CODENAME in /etc/lsb-release)"
     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."
@@ -16,7 +20,7 @@ __UbuntuRepo="http://ports.ubuntu.com/"
 
 __BuildArch=arm
 __QemuArch=armhf
-__LinuxCodeName=focal
+__LinuxCodeName=$DISTRIB_CODENAME
 __SkipUnmount=0
 __IsProxySet=0
 __Apt=""
@@ -24,6 +28,8 @@ __Apt=""
 # install cmake to find cmake package configuration for target file system
 __UbuntuPackages="build-essential"
 __UbuntuPackages+=" cmake"
+# install python3-dev for python API
+__UbuntuPackages+=" python3-dev"
 
 # other development supports
 __UbuntuPackages+=" ocl-icd-opencl-dev"
@@ -51,15 +57,15 @@ for i in "$@" ; do
             __BuildArch=aarch64
             __QemuArch=arm64
             ;;
-        bionic)
-            __LinuxCodeName=bionic
-            ;;
         focal)
             __LinuxCodeName=focal
             ;;
         jammy)
             __LinuxCodeName=jammy
             ;;
+        noble)
+            __LinuxCodeName=noble
+            ;;
         --setproxy*)
             proxyip="${i#*=}"
             __Apt="Acquire::http::proxy \"http://$proxyip/\";\n"
@@ -103,8 +109,6 @@ if [[ -n $__LinuxCodeName ]]; then
     chroot $__RootfsDir apt-get -f -y install
     chroot $__RootfsDir apt-get -y install $__UbuntuPackages
     machine=$(chroot $__RootfsDir gcc -dumpmachine)
-    chroot $__RootfsDir ln -s /usr/lib/${machine}/libhdf5_serial.a /usr/lib/${machine}/libhdf5.a
-    chroot $__RootfsDir ln -s /usr/lib/${machine}/libhdf5_serial.so /usr/lib/${machine}/libhdf5.so
     chroot $__RootfsDir symlinks -cr /usr
 
     if [ $__SkipUnmount == 0 ]; then
index 3d46125..d389a24 100644 (file)
@@ -16,7 +16,7 @@ usage: main.py [-h] [-s] [-d Dataset] [-o Dir] [-p Prefix] [-l N] [-t N]
 
 Convert a dataset of tensorflow to onert format
 
-options:
+optional arguments:
   -h, --help            show this help message and exit
   -s, --show-datasets   show dataset list
   -d Dataset, --dataset-name Dataset
@@ -25,10 +25,12 @@ options:
                         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)
+  --split [Split [Split ...]]
+                        Which split of the data to load (default: "train, test")
+  --length [N [N ...]]  Data number for items described in split (default: "1000, 100")
+  -m Model, --model Model
+                        Model name to use generated data (default: mnist)
+                        Supported models: mnist, mobilenetv2
 
 ## Example
 ### Install required packages
@@ -49,18 +51,45 @@ robotics:mt_opt_sd]
 ```
 
 ### Convert dataset to onert format
+
+Convert `fashion_mnist` dataset for use in `mnist` model
 ```
 $ python3 main.py \
  --dataset-name fashion_mnist \
  --prefix-name fashion-mnist \
- --train-length 2000 \
- --test-length 200
+ --model mnist
+Shape of images : (28, 28, 1)
+Shape of labels: () <dtype: 'int64'>
+class names[:10]  : ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
+class length      : 10
+The data files are created!
+```
+```
+$ tree out
+out
+├── fashion-mnist.test.input.100.bin
+├── fashion-mnist.test.output.100.bin
+├── fashion-mnist.train.input.1000.bin
+└── fashion-mnist.train.output.1000.bin
+```
+
+Convert `imagenet_a` dataset for use in `MobileNetV2` model
+```
+$ python3 main.py \
+ --dataset-name imagenet_a \
+ --prefix-name imagenet_a \
+ --split test \
+ --length 1000 \
+ --model mobilenetv2
+Shape of images : (224, 224, 3)
+Shape of labels: () <dtype: 'int64'>
+class names[:10]  : ['n01440764', 'n01443537', 'n01484850', 'n01491361', 'n01494475', 'n01496331', 'n01498041', 'n01514668', 'n01514859', 'n01518878']
+class length      : 1000
+The data files are created!
 ```
 ```
 $ 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
+├── imagenet_a.test.input.1000.bin
+└── imagenet_a.test.output.1000.bin
 ```
index daa7b5f..ded858a 100644 (file)
@@ -5,7 +5,8 @@ import argparse
 
 def _create_parser():
     parser = argparse.ArgumentParser(
-        description='Convert a dataset of tensorflow to onert format')
+        description='Convert a dataset of tensorflow to onert format',
+        formatter_class=argparse.RawTextHelpFormatter)
     parser.add_argument(
         '-s', '--show-datasets', action='store_true', help='show dataset list')
     parser.add_argument(
@@ -30,19 +31,29 @@ def _create_parser():
         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)')
+        '--split',
+        nargs='*',
+        type=str,
+        default=['train', 'test'],
+        metavar='Split',
+        help='Which split of the data to load (default: "train test")')
     parser.add_argument(
-        '-t',
-        '--test-length',
+        '--length',
+        nargs='*',
         type=int,
-        default=100,
+        default=[1000, 100],
         metavar='N',
-        help='Number of data for training (default: 100)')
+        help='Data number for items described in split (default: "1000 100")')
+    models = ['mnist', 'mobilenetv2']
+    parser.add_argument(
+        '-m',
+        '--model',
+        type=str,
+        default='mnist',
+        choices=models,
+        metavar='Model',
+        help=('Model name to use generated data (default: mnist)\n'
+              'Supported models: ' + ', '.join(models)))
 
     return parser
 
index d633200..ac5ae17 100644 (file)
@@ -7,15 +7,52 @@ from pathlib import Path
 dataset_root_dir = Path(__file__).parent.absolute() / 'data'
 
 
+class Mnist():
+    def check(dataset_name):
+        supported_dataset_list = ['fashion_mnist', 'mnist']
+        if dataset_name in supported_dataset_list:
+            return
+        print(f'{dataset_name} does not fit Mnist')
+        exit(1)
+
+    def preprocess_input(image, label):
+        """Preprocess input data for Mnist."""
+
+        def _normalize_img(image):
+            """Normalize images: `uint8` -> `float32`."""
+            return tf.cast(image, tf.float32) / 255.
+
+        return _normalize_img(image), label
+
+
+class MobileNetV2():
+    def check(dataset_name):
+        supported_dataset_list = ['imagenet_a']
+        if dataset_name in supported_dataset_list:
+            return
+        print(f'{dataset_name} does not fit MobileNetV2')
+        exit(1)
+
+    def preprocess_input(image, label):
+        """Preprocess input data for MobileNetV2."""
+
+        def _resize_img(image):
+            _image = tf.cast(image, tf.float32) / 255.
+            _image = tf.image.resize_with_crop_or_pad(_image, 224, 224)
+            return _image
+
+        return _resize_img(image), label
+
+
 class DatasetLoader():
     '''
     Loader of tensorflow datasets
     '''
 
-    def load(self, dataset_name):
-        (ds_train, ds_test), ds_info = tfds.load(
+    def load(self, dataset_name, splits, model_name):
+        ds_dict, ds_info = tfds.load(
             dataset_name,
-            split=['train', 'test'],
+            split=splits,
             data_dir=dataset_root_dir,
             shuffle_files=True,
             as_supervised=True,
@@ -23,15 +60,15 @@ class DatasetLoader():
         )
 
         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:
+        self.ds_dict = []
+        if model_name == 'mnist':
+            Mnist.check(dataset_name)
+            self.ds_dict = [data.map(Mnist.preprocess_input) for data in ds_dict]
+        elif model_name == 'mobilenetv2':
+            MobileNetV2.check(dataset_name)
+            self.ds_dict = [data.map(MobileNetV2.preprocess_input) for data in ds_dict]
+
+        for images, labels in self.ds_dict[0]:
             print(f'Shape of images : {images.shape}')
             print(f'Shape of labels: {labels.shape} {labels.dtype}')
             break
@@ -39,11 +76,11 @@ class DatasetLoader():
     def get_dataset_names(self):
         return tfds.list_builders()
 
-    def class_names(self):
+    def class_names(self, num=10):
         '''
         Get class names
         '''
-        return self.ds_info.features['label'].names
+        return self.ds_info.features['label'].names[:num]
 
     def num_classes(self):
         '''
@@ -51,30 +88,21 @@ class DatasetLoader():
         '''
         return self.ds_info.features['label'].num_classes
 
-    def get_num_train_examples(self):
+    def get_dataset_info(self):
         '''
-        Get examples for training
+        Get examples for each data
         '''
-        return self.ds_info.splits['train'].num_examples
+        dict_num = {}
+        for key in self.ds_info.splits.keys():
+            dict_num[key] = self.ds_info.splits[key].num_examples
+        return dict_num
 
-    def get_num_test_examples(self):
-        '''
-        Get examples for testing
-        '''
-        return self.ds_info.splits['test'].num_examples
-
-    def prefetched_datasets(self):
+    def prefetched_dataset(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()
+        ds_dict = [d.cache() for d in self.ds_dict]
+        return ds_dict
index 77e3399..6f587d1 100644 (file)
@@ -7,6 +7,10 @@ from argparser import parse_args
 # You can see arguments' information in argparser.py
 args = parse_args()
 
+if len(args.split) != len(args.length):
+    print(f'length and split should have the same count')
+    exit(1)
+
 ################################################################################
 # Load a dataset of tensorflow
 ################################################################################
@@ -21,6 +25,7 @@ from datasets import DatasetLoader
 from pathlib import Path
 import tensorflow as tf
 import numpy as np
+import re
 
 ds_loader = DatasetLoader()
 
@@ -30,13 +35,11 @@ if args.show_datasets:
     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}')
+ds_loader.load(args.dataset_name, args.split, args.model)
+ds_dict = ds_loader.prefetched_dataset()
+ds_info = ds_loader.get_dataset_info()
+print(f'class names[:10]  : {ds_loader.class_names(num=10)}')
+print(f'class length      : {ds_loader.num_classes()}')
 
 ################################################################################
 # Convert tensorlfow dataset to onert format
@@ -46,16 +49,17 @@ 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)
+split_length = dict(zip(args.split, args.length))
 
-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)
+for key in split_length.keys():
+    if key not in ds_info.keys():
+        print(f'Oops! The given split is not included in {args.dataset_name}')
+        exit(1)
+
+for key in split_length.keys():
+    if ds_info[key] < split_length[key]:
+        print(f'Oops! The number of data in the dataset is less than {v}')
+        exit(1)
 
 
 def _only_image(image, _):
@@ -73,22 +77,29 @@ def _label_to_array(label):
     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'
-]
+def _replace_key(key):
+    for ch in ['[', ':', ']']:
+        key = key.replace(ch, '_')
+    return key
 
-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]
+file_path_list = []
+for k, v in split_length.items():
+    _k = _replace_key(k)
+    file_path_list.append(f'{prefix_name}{_k}.input.{v}.bin')
+    file_path_list.append(f'{prefix_name}{_k}.output.{v}.bin')
+
+ds_list = []
+for i, v in enumerate(split_length.values()):
+    ds_list.append(ds_dict[i].take(v).map(_only_image)),
+    ds_list.append(
+        [_label_to_array(label) for label in ds_dict[i].take(v).map(_only_label)])
+
+if len(file_path_list) != len(ds_list):
+    print(f'file_path_list and ds_list should have the same length')
+    exit(1)
+
+for i, file_path in enumerate(file_path_list):
     with open(file_path, 'wb') as f:
         ds = ds_list[i]
         for tensor in ds:
index 204810b..b6a3b04 100644 (file)
 
 #include "Args.h"
 
+#include <arser/arser.h>
+
 #include <iostream>
-#include <boost/filesystem.hpp>
+#include <filesystem>
 
 namespace kbenchmark
 {
@@ -26,46 +28,44 @@ Args::Args(const int argc, char **argv) noexcept { Initialize(argc, argv); }
 
 void Args::Initialize(const int argc, char **argv)
 {
-  // General options
-  po::options_description general("General options");
-  // clang-format off
-  general.add_options()("help,h", "Display available options")
-    ("config,c", po::value<std::string>(&_config)->required(), "Configuration filename")
-    ("kernel,k", po::value<std::vector<std::string>>(&_kernel)->multitoken()->composing()->required(), "Kernel library name, support multiple kernel libraries")
-    ("reporter,r", po::value<std::string>(&_reporter)->default_value("standard"), "Set reporter types(standard, html, junit, csv)")
-    ("filter,f", po::value<std::string>(&_filter)->default_value(".*"), "Only run benchmarks whose name matches the regular expression pattern")
-    ("verbose,v", po::value<int>(&_verbose)->default_value(0)->implicit_value(true), "Show verbose output")
-    ("output,o", po::value<std::string>(&_output)->default_value(""), "Set additional strings for output file name")
-  ;
-  // clang-format on
+  arser::Arser arser;
 
-  po::variables_map vm;
-  po::store(po::parse_command_line(argc, argv, general), vm);
+  arser.add_argument("--config", "-c")
+    .type(arser::DataType::STR)
+    .required()
+    .help("Configuration filename");
+  arser.add_argument("--kernel", "-k")
+    .type(arser::DataType::STR)
+    .accumulated()
+    .help("Kernel library name, support multiple kernel libraries");
+  arser.add_argument("--reporter", "-r")
+    .type(arser::DataType::STR)
+    .default_value("standard")
+    .help("Set reporter types(standard, html, junit, csv)");
+  arser.add_argument("--filter", "-f")
+    .type(arser::DataType::STR)
+    .default_value(".*")
+    .help("Only run benchmarks whose name matches the regular expression pattern");
+  arser.add_argument("--verbose", "-v")
+    .type(arser::DataType::INT32)
+    .default_value(0)
+    .help("Show verbose output");
+  arser.add_argument("--output", "-o")
+    .type(arser::DataType::STR)
+    .default_value("")
+    .help("Set additional strings for output file name");
 
   try
   {
-    po::notify(vm);
+    arser.parse(argc, argv);
   }
-  catch (const boost::program_options::required_option &e)
+  catch (const std::runtime_error &err)
   {
-    if (vm.count("help"))
-    {
-      std::cout << general << std::endl;
-      exit(0);
-    }
-    else
-    {
-      throw e;
-    }
-  }
-
-  if (vm.count("help"))
-  {
-    std::cout << general << std::endl;
+    std::cout << err.what() << std::endl;
     exit(0);
   }
 
-  if (vm.count("config"))
+  _config = arser.get<std::string>("--config");
   {
     if (_config.substr(_config.find_last_of(".") + 1) != "config")
     {
@@ -73,18 +73,19 @@ void Args::Initialize(const int argc, char **argv)
       exit(1);
     }
 
-    if (!boost::filesystem::exists(_config))
+    if (!std::filesystem::exists(_config))
     {
       std::cerr << _config << " file not found" << std::endl;
       exit(1);
     }
   }
 
-  if (vm.count("kernel"))
+  _kernel = arser.get<std::vector<std::string>>("--kernel");
+  if (_kernel.size() > 0)
   {
     for (auto &k : _kernel)
     {
-      if (!boost::filesystem::exists(k))
+      if (!std::filesystem::exists(k))
       {
         std::cerr << k << " file not found" << std::endl;
         exit(1);
@@ -92,7 +93,8 @@ void Args::Initialize(const int argc, char **argv)
     }
   }
 
-  if (vm.count("reporter"))
+  _reporter = arser.get<std::string>("--reporter");
+  if (!_reporter.empty())
   {
     if (_reporter != "junit" && _reporter != "csv" && _reporter != "html" &&
         _reporter != "standard")
@@ -101,6 +103,10 @@ void Args::Initialize(const int argc, char **argv)
       exit(1);
     }
   }
+
+  _filter = arser.get<std::string>("--filter");
+  _output = arser.get<std::string>("--output");
+  _verbose = arser.get<int>("--verbose");
 }
 
 } // namespace kbenchmark
index efd5081..aa1b73d 100644 (file)
@@ -2,18 +2,12 @@ if(NOT BUILD_KBENCHMARK)
   return()
 endif(NOT BUILD_KBENCHMARK)
 
-nnas_find_package(Nonius QUIET)
+nnfw_find_package(Nonius QUIET)
 
 if(NOT Nonius_FOUND)
   return()
 endif(NOT Nonius_FOUND)
 
-nnfw_find_package(Boost REQUIRED program_options system filesystem)
-
-if(NOT Boost_FOUND)
-  return()
-endif(NOT Boost_FOUND)
-
 # driver
 file(GLOB_RECURSE SOURCES "*.cc")
 
@@ -22,7 +16,7 @@ target_compile_options(kbenchmark PRIVATE -Wno-psabi)
 target_include_directories(kbenchmark PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
 target_link_libraries(kbenchmark PUBLIC nonius)
 target_link_libraries(kbenchmark PUBLIC dl)
-target_link_libraries(kbenchmark PUBLIC pthread boost_program_options boost_system boost_filesystem)
+target_link_libraries(kbenchmark PUBLIC pthread arser)
 install(TARGETS kbenchmark DESTINATION bin)
 
 # kernel libraries
diff --git a/tools/tflite_accuracy/CMakeLists.txt b/tools/tflite_accuracy/CMakeLists.txt
deleted file mode 100644 (file)
index b545ac6..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-if(NOT BUILD_TFLITE_ACCURACY)
-  return()
-endif(NOT BUILD_TFLITE_ACCURACY)
-
-list(APPEND TFLITE_ACCURACY_SRCS "src/tflite_accuracy.cc")
-
-add_executable(tflite_accuracy ${TFLITE_ACCURACY_SRCS})
-target_include_directories(tflite_accuracy PRIVATE src)
-target_link_libraries(tflite_accuracy tensorflow-lite ${LIB_PTHREAD} dl nnfw_lib_tflite)
-target_link_libraries(tflite_accuracy boost_program_options boost_system boost_filesystem)
-
-install(TARGETS tflite_accuracy DESTINATION bin)
-
diff --git a/tools/tflite_accuracy/README.md b/tools/tflite_accuracy/README.md
deleted file mode 100644 (file)
index 98cd203..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-Using the batch execution tool
-==============================
-
-The batch execution tool (`tflite_accuracy`) can be used to run experiments
-where execution time and accuracy are to be measured on a test set.
-`tflite_accuracy` reads a neural network model from a file and a series of
-input images from a directory, runs each image through the network,
-and collect statistics, such as execution time and accuracy.
-
-In order to run this tool, you'll need:
-
-* a model in `.tflite` format;
-* a set of preprocessed input images in binary format, properly named
-(see below).
-
-`tflite_accuracy` expects all the input images to be located in the same directory
-in the file system. Each image file is the binary dump of the network's
-input tensor. So, if the network's input tensor is a `float32` tensor of 
-format (1, 224, 224, 3) containing 1 image of height 224, width 224, and
-3 channels, each image file is expected to be a series of 224 * 224 * 3 
-`float32` values.
-
-`tflite_accuracy` does **not** perform any preprocessing on the input tensor
-(e.g., subtraction of mean or division by standard deviation). Each image 
-file is treated as the final value of the input tensor, so all the
-necessary preprocessing should be done prior to invoking the tool.
-
-In order to calculate accuracy on the image set, `tflite_accuracy` needs to know
-the correct label corresponding to each image. This information is
-extracted from the file's name: the first four characters in the name are
-assumed to be the numerical code of the image's class. So, a file named
-`0123_0123456789.bin` is assumed to represent an image belonging to class
-`123`. The remainder of the name (`0123456789` in the example) is assumed 
-to be an identifier of the image itself.
-
-The width and height each image can be informed via the command line
-argument `--imgsize`, whose default value is 224.
diff --git a/tools/tflite_accuracy/src/labels.h b/tools/tflite_accuracy/src/labels.h
deleted file mode 100644 (file)
index 1e5170e..0000000
+++ /dev/null
@@ -1,1023 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LABELS_H_
-#define LABELS_H_
-
-// Labels used for image classification (imagenet dataset)
-static const char *labels[] = {"background",
-                               "tench",
-                               "goldfish",
-                               "great white shark",
-                               "tiger shark",
-                               "hammerhead",
-                               "electric ray",
-                               "stingray",
-                               "cock",
-                               "hen",
-                               "ostrich",
-                               "brambling",
-                               "goldfinch",
-                               "house finch",
-                               "junco",
-                               "indigo bunting",
-                               "robin",
-                               "bulbul",
-                               "jay",
-                               "magpie",
-                               "chickadee",
-                               "water ouzel",
-                               "kite",
-                               "bald eagle",
-                               "vulture",
-                               "great grey owl",
-                               "European fire salamander",
-                               "common newt",
-                               "eft",
-                               "spotted salamander",
-                               "axolotl",
-                               "bullfrog",
-                               "tree frog",
-                               "tailed frog",
-                               "loggerhead",
-                               "leatherback turtle",
-                               "mud turtle",
-                               "terrapin",
-                               "box turtle",
-                               "banded gecko",
-                               "common iguana",
-                               "American chameleon",
-                               "whiptail",
-                               "agama",
-                               "frilled lizard",
-                               "alligator lizard",
-                               "Gila monster",
-                               "green lizard",
-                               "African chameleon",
-                               "Komodo dragon",
-                               "African crocodile",
-                               "American alligator",
-                               "triceratops",
-                               "thunder snake",
-                               "ringneck snake",
-                               "hognose snake",
-                               "green snake",
-                               "king snake",
-                               "garter snake",
-                               "water snake",
-                               "vine snake",
-                               "night snake",
-                               "boa constrictor",
-                               "rock python",
-                               "Indian cobra",
-                               "green mamba",
-                               "sea snake",
-                               "horned viper",
-                               "diamondback",
-                               "sidewinder",
-                               "trilobite",
-                               "harvestman",
-                               "scorpion",
-                               "black and gold garden spider",
-                               "barn spider",
-                               "garden spider",
-                               "black widow",
-                               "tarantula",
-                               "wolf spider",
-                               "tick",
-                               "centipede",
-                               "black grouse",
-                               "ptarmigan",
-                               "ruffed grouse",
-                               "prairie chicken",
-                               "peacock",
-                               "quail",
-                               "partridge",
-                               "African grey",
-                               "macaw",
-                               "sulphur-crested cockatoo",
-                               "lorikeet",
-                               "coucal",
-                               "bee eater",
-                               "hornbill",
-                               "hummingbird",
-                               "jacamar",
-                               "toucan",
-                               "drake",
-                               "red-breasted merganser",
-                               "goose",
-                               "black swan",
-                               "tusker",
-                               "echidna",
-                               "platypus",
-                               "wallaby",
-                               "koala",
-                               "wombat",
-                               "jellyfish",
-                               "sea anemone",
-                               "brain coral",
-                               "flatworm",
-                               "nematode",
-                               "conch",
-                               "snail",
-                               "slug",
-                               "sea slug",
-                               "chiton",
-                               "chambered nautilus",
-                               "Dungeness crab",
-                               "rock crab",
-                               "fiddler crab",
-                               "king crab",
-                               "American lobster",
-                               "spiny lobster",
-                               "crayfish",
-                               "hermit crab",
-                               "isopod",
-                               "white stork",
-                               "black stork",
-                               "spoonbill",
-                               "flamingo",
-                               "little blue heron",
-                               "American egret",
-                               "bittern",
-                               "crane",
-                               "limpkin",
-                               "European gallinule",
-                               "American coot",
-                               "bustard",
-                               "ruddy turnstone",
-                               "red-backed sandpiper",
-                               "redshank",
-                               "dowitcher",
-                               "oystercatcher",
-                               "pelican",
-                               "king penguin",
-                               "albatross",
-                               "grey whale",
-                               "killer whale",
-                               "dugong",
-                               "sea lion",
-                               "Chihuahua",
-                               "Japanese spaniel",
-                               "Maltese dog",
-                               "Pekinese",
-                               "Shih-Tzu",
-                               "Blenheim spaniel",
-                               "papillon",
-                               "toy terrier",
-                               "Rhodesian ridgeback",
-                               "Afghan hound",
-                               "basset",
-                               "beagle",
-                               "bloodhound",
-                               "bluetick",
-                               "black-and-tan coonhound",
-                               "Walker hound",
-                               "English foxhound",
-                               "redbone",
-                               "borzoi",
-                               "Irish wolfhound",
-                               "Italian greyhound",
-                               "whippet",
-                               "Ibizan hound",
-                               "Norwegian elkhound",
-                               "otterhound",
-                               "Saluki",
-                               "Scottish deerhound",
-                               "Weimaraner",
-                               "Staffordshire bullterrier",
-                               "American Staffordshire terrier",
-                               "Bedlington terrier",
-                               "Border terrier",
-                               "Kerry blue terrier",
-                               "Irish terrier",
-                               "Norfolk terrier",
-                               "Norwich terrier",
-                               "Yorkshire terrier",
-                               "wire-haired fox terrier",
-                               "Lakeland terrier",
-                               "Sealyham terrier",
-                               "Airedale",
-                               "cairn",
-                               "Australian terrier",
-                               "Dandie Dinmont",
-                               "Boston bull",
-                               "miniature schnauzer",
-                               "giant schnauzer",
-                               "standard schnauzer",
-                               "Scotch terrier",
-                               "Tibetan terrier",
-                               "silky terrier",
-                               "soft-coated wheaten terrier",
-                               "West Highland white terrier",
-                               "Lhasa",
-                               "flat-coated retriever",
-                               "curly-coated retriever",
-                               "golden retriever",
-                               "Labrador retriever",
-                               "Chesapeake Bay retriever",
-                               "German short-haired pointer",
-                               "vizsla",
-                               "English setter",
-                               "Irish setter",
-                               "Gordon setter",
-                               "Brittany spaniel",
-                               "clumber",
-                               "English springer",
-                               "Welsh springer spaniel",
-                               "cocker spaniel",
-                               "Sussex spaniel",
-                               "Irish water spaniel",
-                               "kuvasz",
-                               "schipperke",
-                               "groenendael",
-                               "malinois",
-                               "briard",
-                               "kelpie",
-                               "komondor",
-                               "Old English sheepdog",
-                               "Shetland sheepdog",
-                               "collie",
-                               "Border collie",
-                               "Bouvier des Flandres",
-                               "Rottweiler",
-                               "German shepherd",
-                               "Doberman",
-                               "miniature pinscher",
-                               "Greater Swiss Mountain dog",
-                               "Bernese mountain dog",
-                               "Appenzeller",
-                               "EntleBucher",
-                               "boxer",
-                               "bull mastiff",
-                               "Tibetan mastiff",
-                               "French bulldog",
-                               "Great Dane",
-                               "Saint Bernard",
-                               "Eskimo dog",
-                               "malamute",
-                               "Siberian husky",
-                               "dalmatian",
-                               "affenpinscher",
-                               "basenji",
-                               "pug",
-                               "Leonberg",
-                               "Newfoundland",
-                               "Great Pyrenees",
-                               "Samoyed",
-                               "Pomeranian",
-                               "chow",
-                               "keeshond",
-                               "Brabancon griffon",
-                               "Pembroke",
-                               "Cardigan",
-                               "toy poodle",
-                               "miniature poodle",
-                               "standard poodle",
-                               "Mexican hairless",
-                               "timber wolf",
-                               "white wolf",
-                               "red wolf",
-                               "coyote",
-                               "dingo",
-                               "dhole",
-                               "African hunting dog",
-                               "hyena",
-                               "red fox",
-                               "kit fox",
-                               "Arctic fox",
-                               "grey fox",
-                               "tabby",
-                               "tiger cat",
-                               "Persian cat",
-                               "Siamese cat",
-                               "Egyptian cat",
-                               "cougar",
-                               "lynx",
-                               "leopard",
-                               "snow leopard",
-                               "jaguar",
-                               "lion",
-                               "tiger",
-                               "cheetah",
-                               "brown bear",
-                               "American black bear",
-                               "ice bear",
-                               "sloth bear",
-                               "mongoose",
-                               "meerkat",
-                               "tiger beetle",
-                               "ladybug",
-                               "ground beetle",
-                               "long-horned beetle",
-                               "leaf beetle",
-                               "dung beetle",
-                               "rhinoceros beetle",
-                               "weevil",
-                               "fly",
-                               "bee",
-                               "ant",
-                               "grasshopper",
-                               "cricket",
-                               "walking stick",
-                               "cockroach",
-                               "mantis",
-                               "cicada",
-                               "leafhopper",
-                               "lacewing",
-                               "dragonfly",
-                               "damselfly",
-                               "admiral",
-                               "ringlet",
-                               "monarch",
-                               "cabbage butterfly",
-                               "sulphur butterfly",
-                               "lycaenid",
-                               "starfish",
-                               "sea urchin",
-                               "sea cucumber",
-                               "wood rabbit",
-                               "hare",
-                               "Angora",
-                               "hamster",
-                               "porcupine",
-                               "fox squirrel",
-                               "marmot",
-                               "beaver",
-                               "guinea pig",
-                               "sorrel",
-                               "zebra",
-                               "hog",
-                               "wild boar",
-                               "warthog",
-                               "hippopotamus",
-                               "ox",
-                               "water buffalo",
-                               "bison",
-                               "ram",
-                               "bighorn",
-                               "ibex",
-                               "hartebeest",
-                               "impala",
-                               "gazelle",
-                               "Arabian camel",
-                               "llama",
-                               "weasel",
-                               "mink",
-                               "polecat",
-                               "black-footed ferret",
-                               "otter",
-                               "skunk",
-                               "badger",
-                               "armadillo",
-                               "three-toed sloth",
-                               "orangutan",
-                               "gorilla",
-                               "chimpanzee",
-                               "gibbon",
-                               "siamang",
-                               "guenon",
-                               "patas",
-                               "baboon",
-                               "macaque",
-                               "langur",
-                               "colobus",
-                               "proboscis monkey",
-                               "marmoset",
-                               "capuchin",
-                               "howler monkey",
-                               "titi",
-                               "spider monkey",
-                               "squirrel monkey",
-                               "Madagascar cat",
-                               "indri",
-                               "Indian elephant",
-                               "African elephant",
-                               "lesser panda",
-                               "giant panda",
-                               "barracouta",
-                               "eel",
-                               "coho",
-                               "rock beauty",
-                               "anemone fish",
-                               "sturgeon",
-                               "gar",
-                               "lionfish",
-                               "puffer",
-                               "abacus",
-                               "abaya",
-                               "academic gown",
-                               "accordion",
-                               "acoustic guitar",
-                               "aircraft carrier",
-                               "airliner",
-                               "airship",
-                               "altar",
-                               "ambulance",
-                               "amphibian",
-                               "analog clock",
-                               "apiary",
-                               "apron",
-                               "ashcan",
-                               "assault rifle",
-                               "backpack",
-                               "bakery",
-                               "balance beam",
-                               "balloon",
-                               "ballpoint",
-                               "Band Aid",
-                               "banjo",
-                               "bannister",
-                               "barbell",
-                               "barber chair",
-                               "barbershop",
-                               "barn",
-                               "barometer",
-                               "barrel",
-                               "barrow",
-                               "baseball",
-                               "basketball",
-                               "bassinet",
-                               "bassoon",
-                               "bathing cap",
-                               "bath towel",
-                               "bathtub",
-                               "beach wagon",
-                               "beacon",
-                               "beaker",
-                               "bearskin",
-                               "beer bottle",
-                               "beer glass",
-                               "bell cote",
-                               "bib",
-                               "bicycle-built-for-two",
-                               "bikini",
-                               "binder",
-                               "binoculars",
-                               "birdhouse",
-                               "boathouse",
-                               "bobsled",
-                               "bolo tie",
-                               "bonnet",
-                               "bookcase",
-                               "bookshop",
-                               "bottlecap",
-                               "bow",
-                               "bow tie",
-                               "brass",
-                               "brassiere",
-                               "breakwater",
-                               "breastplate",
-                               "broom",
-                               "bucket",
-                               "buckle",
-                               "bulletproof vest",
-                               "bullet train",
-                               "butcher shop",
-                               "cab",
-                               "caldron",
-                               "candle",
-                               "cannon",
-                               "canoe",
-                               "can opener",
-                               "cardigan",
-                               "car mirror",
-                               "carousel",
-                               "carpenter's kit",
-                               "carton",
-                               "car wheel",
-                               "cash machine",
-                               "cassette",
-                               "cassette player",
-                               "castle",
-                               "catamaran",
-                               "CD player",
-                               "cello",
-                               "cellular telephone",
-                               "chain",
-                               "chainlink fence",
-                               "chain mail",
-                               "chain saw",
-                               "chest",
-                               "chiffonier",
-                               "chime",
-                               "china cabinet",
-                               "Christmas stocking",
-                               "church",
-                               "cinema",
-                               "cleaver",
-                               "cliff dwelling",
-                               "cloak",
-                               "clog",
-                               "cocktail shaker",
-                               "coffee mug",
-                               "coffeepot",
-                               "coil",
-                               "combination lock",
-                               "computer keyboard",
-                               "confectionery",
-                               "container ship",
-                               "convertible",
-                               "corkscrew",
-                               "cornet",
-                               "cowboy boot",
-                               "cowboy hat",
-                               "cradle",
-                               "crane",
-                               "crash helmet",
-                               "crate",
-                               "crib",
-                               "Crock Pot",
-                               "croquet ball",
-                               "crutch",
-                               "cuirass",
-                               "dam",
-                               "desk",
-                               "desktop computer",
-                               "dial telephone",
-                               "diaper",
-                               "digital clock",
-                               "digital watch",
-                               "dining table",
-                               "dishrag",
-                               "dishwasher",
-                               "disk brake",
-                               "dock",
-                               "dogsled",
-                               "dome",
-                               "doormat",
-                               "drilling platform",
-                               "drum",
-                               "drumstick",
-                               "dumbbell",
-                               "Dutch oven",
-                               "electric fan",
-                               "electric guitar",
-                               "electric locomotive",
-                               "entertainment center",
-                               "envelope",
-                               "espresso maker",
-                               "face powder",
-                               "feather boa",
-                               "file",
-                               "fireboat",
-                               "fire engine",
-                               "fire screen",
-                               "flagpole",
-                               "flute",
-                               "folding chair",
-                               "football helmet",
-                               "forklift",
-                               "fountain",
-                               "fountain pen",
-                               "four-poster",
-                               "freight car",
-                               "French horn",
-                               "frying pan",
-                               "fur coat",
-                               "garbage truck",
-                               "gasmask",
-                               "gas pump",
-                               "goblet",
-                               "go-kart",
-                               "golf ball",
-                               "golfcart",
-                               "gondola",
-                               "gong",
-                               "gown",
-                               "grand piano",
-                               "greenhouse",
-                               "grille",
-                               "grocery store",
-                               "guillotine",
-                               "hair slide",
-                               "hair spray",
-                               "half track",
-                               "hammer",
-                               "hamper",
-                               "hand blower",
-                               "hand-held computer",
-                               "handkerchief",
-                               "hard disc",
-                               "harmonica",
-                               "harp",
-                               "harvester",
-                               "hatchet",
-                               "holster",
-                               "home theater",
-                               "honeycomb",
-                               "hook",
-                               "hoopskirt",
-                               "horizontal bar",
-                               "horse cart",
-                               "hourglass",
-                               "iPod",
-                               "iron",
-                               "jack-o'-lantern",
-                               "jean",
-                               "jeep",
-                               "jersey",
-                               "jigsaw puzzle",
-                               "jinrikisha",
-                               "joystick",
-                               "kimono",
-                               "knee pad",
-                               "knot",
-                               "lab coat",
-                               "ladle",
-                               "lampshade",
-                               "laptop",
-                               "lawn mower",
-                               "lens cap",
-                               "letter opener",
-                               "library",
-                               "lifeboat",
-                               "lighter",
-                               "limousine",
-                               "liner",
-                               "lipstick",
-                               "Loafer",
-                               "lotion",
-                               "loudspeaker",
-                               "loupe",
-                               "lumbermill",
-                               "magnetic compass",
-                               "mailbag",
-                               "mailbox",
-                               "maillot",
-                               "maillot",
-                               "manhole cover",
-                               "maraca",
-                               "marimba",
-                               "mask",
-                               "matchstick",
-                               "maypole",
-                               "maze",
-                               "measuring cup",
-                               "medicine chest",
-                               "megalith",
-                               "microphone",
-                               "microwave",
-                               "military uniform",
-                               "milk can",
-                               "minibus",
-                               "miniskirt",
-                               "minivan",
-                               "missile",
-                               "mitten",
-                               "mixing bowl",
-                               "mobile home",
-                               "Model T",
-                               "modem",
-                               "monastery",
-                               "monitor",
-                               "moped",
-                               "mortar",
-                               "mortarboard",
-                               "mosque",
-                               "mosquito net",
-                               "motor scooter",
-                               "mountain bike",
-                               "mountain tent",
-                               "mouse",
-                               "mousetrap",
-                               "moving van",
-                               "muzzle",
-                               "nail",
-                               "neck brace",
-                               "necklace",
-                               "nipple",
-                               "notebook",
-                               "obelisk",
-                               "oboe",
-                               "ocarina",
-                               "odometer",
-                               "oil filter",
-                               "organ",
-                               "oscilloscope",
-                               "overskirt",
-                               "oxcart",
-                               "oxygen mask",
-                               "packet",
-                               "paddle",
-                               "paddlewheel",
-                               "padlock",
-                               "paintbrush",
-                               "pajama",
-                               "palace",
-                               "panpipe",
-                               "paper towel",
-                               "parachute",
-                               "parallel bars",
-                               "park bench",
-                               "parking meter",
-                               "passenger car",
-                               "patio",
-                               "pay-phone",
-                               "pedestal",
-                               "pencil box",
-                               "pencil sharpener",
-                               "perfume",
-                               "Petri dish",
-                               "photocopier",
-                               "pick",
-                               "pickelhaube",
-                               "picket fence",
-                               "pickup",
-                               "pier",
-                               "piggy bank",
-                               "pill bottle",
-                               "pillow",
-                               "ping-pong ball",
-                               "pinwheel",
-                               "pirate",
-                               "pitcher",
-                               "plane",
-                               "planetarium",
-                               "plastic bag",
-                               "plate rack",
-                               "plow",
-                               "plunger",
-                               "Polaroid camera",
-                               "pole",
-                               "police van",
-                               "poncho",
-                               "pool table",
-                               "pop bottle",
-                               "pot",
-                               "potter's wheel",
-                               "power drill",
-                               "prayer rug",
-                               "printer",
-                               "prison",
-                               "projectile",
-                               "projector",
-                               "puck",
-                               "punching bag",
-                               "purse",
-                               "quill",
-                               "quilt",
-                               "racer",
-                               "racket",
-                               "radiator",
-                               "radio",
-                               "radio telescope",
-                               "rain barrel",
-                               "recreational vehicle",
-                               "reel",
-                               "reflex camera",
-                               "refrigerator",
-                               "remote control",
-                               "restaurant",
-                               "revolver",
-                               "rifle",
-                               "rocking chair",
-                               "rotisserie",
-                               "rubber eraser",
-                               "rugby ball",
-                               "rule",
-                               "running shoe",
-                               "safe",
-                               "safety pin",
-                               "saltshaker",
-                               "sandal",
-                               "sarong",
-                               "sax",
-                               "scabbard",
-                               "scale",
-                               "school bus",
-                               "schooner",
-                               "scoreboard",
-                               "screen",
-                               "screw",
-                               "screwdriver",
-                               "seat belt",
-                               "sewing machine",
-                               "shield",
-                               "shoe shop",
-                               "shoji",
-                               "shopping basket",
-                               "shopping cart",
-                               "shovel",
-                               "shower cap",
-                               "shower curtain",
-                               "ski",
-                               "ski mask",
-                               "sleeping bag",
-                               "slide rule",
-                               "sliding door",
-                               "slot",
-                               "snorkel",
-                               "snowmobile",
-                               "snowplow",
-                               "soap dispenser",
-                               "soccer ball",
-                               "sock",
-                               "solar dish",
-                               "sombrero",
-                               "soup bowl",
-                               "space bar",
-                               "space heater",
-                               "space shuttle",
-                               "spatula",
-                               "speedboat",
-                               "spider web",
-                               "spindle",
-                               "sports car",
-                               "spotlight",
-                               "stage",
-                               "steam locomotive",
-                               "steel arch bridge",
-                               "steel drum",
-                               "stethoscope",
-                               "stole",
-                               "stone wall",
-                               "stopwatch",
-                               "stove",
-                               "strainer",
-                               "streetcar",
-                               "stretcher",
-                               "studio couch",
-                               "stupa",
-                               "submarine",
-                               "suit",
-                               "sundial",
-                               "sunglass",
-                               "sunglasses",
-                               "sunscreen",
-                               "suspension bridge",
-                               "swab",
-                               "sweatshirt",
-                               "swimming trunks",
-                               "swing",
-                               "switch",
-                               "syringe",
-                               "table lamp",
-                               "tank",
-                               "tape player",
-                               "teapot",
-                               "teddy",
-                               "television",
-                               "tennis ball",
-                               "thatch",
-                               "theater curtain",
-                               "thimble",
-                               "thresher",
-                               "throne",
-                               "tile roof",
-                               "toaster",
-                               "tobacco shop",
-                               "toilet seat",
-                               "torch",
-                               "totem pole",
-                               "tow truck",
-                               "toyshop",
-                               "tractor",
-                               "trailer truck",
-                               "tray",
-                               "trench coat",
-                               "tricycle",
-                               "trimaran",
-                               "tripod",
-                               "triumphal arch",
-                               "trolleybus",
-                               "trombone",
-                               "tub",
-                               "turnstile",
-                               "typewriter keyboard",
-                               "umbrella",
-                               "unicycle",
-                               "upright",
-                               "vacuum",
-                               "vase",
-                               "vault",
-                               "velvet",
-                               "vending machine",
-                               "vestment",
-                               "viaduct",
-                               "violin",
-                               "volleyball",
-                               "waffle iron",
-                               "wall clock",
-                               "wallet",
-                               "wardrobe",
-                               "warplane",
-                               "washbasin",
-                               "washer",
-                               "water bottle",
-                               "water jug",
-                               "water tower",
-                               "whiskey jug",
-                               "whistle",
-                               "wig",
-                               "window screen",
-                               "window shade",
-                               "Windsor tie",
-                               "wine bottle",
-                               "wing",
-                               "wok",
-                               "wooden spoon",
-                               "wool",
-                               "worm fence",
-                               "wreck",
-                               "yawl",
-                               "yurt",
-                               "web site",
-                               "comic book",
-                               "crossword puzzle",
-                               "street sign",
-                               "traffic light",
-                               "book jacket",
-                               "menu",
-                               "plate",
-                               "guacamole",
-                               "consomme",
-                               "hot pot",
-                               "trifle",
-                               "ice cream",
-                               "ice lolly",
-                               "French loaf",
-                               "bagel",
-                               "pretzel",
-                               "cheeseburger",
-                               "hotdog",
-                               "mashed potato",
-                               "head cabbage",
-                               "broccoli",
-                               "cauliflower",
-                               "zucchini",
-                               "spaghetti squash",
-                               "acorn squash",
-                               "butternut squash",
-                               "cucumber",
-                               "artichoke",
-                               "bell pepper",
-                               "cardoon",
-                               "mushroom",
-                               "Granny Smith",
-                               "strawberry",
-                               "orange",
-                               "lemon",
-                               "fig",
-                               "pineapple",
-                               "banana",
-                               "jackfruit",
-                               "custard apple",
-                               "pomegranate",
-                               "hay",
-                               "carbonara",
-                               "chocolate sauce",
-                               "dough",
-                               "meat loaf",
-                               "pizza",
-                               "potpie",
-                               "burrito",
-                               "red wine",
-                               "espresso",
-                               "cup",
-                               "eggnog",
-                               "alp",
-                               "bubble",
-                               "cliff",
-                               "coral reef",
-                               "geyser",
-                               "lakeside",
-                               "promontory",
-                               "sandbar",
-                               "seashore",
-                               "valley",
-                               "volcano",
-                               "ballplayer",
-                               "groom",
-                               "scuba diver",
-                               "rapeseed",
-                               "daisy",
-                               "yellow lady's slipper",
-                               "corn",
-                               "acorn",
-                               "hip",
-                               "buckeye",
-                               "coral fungus",
-                               "agaric",
-                               "gyromitra",
-                               "stinkhorn",
-                               "earthstar",
-                               "hen-of-the-woods",
-                               "bolete",
-                               "ear",
-                               "toilet tissue"};
-
-#endif /* LABELS_H_ */
diff --git a/tools/tflite_accuracy/src/tflite_accuracy.cc b/tools/tflite_accuracy/src/tflite_accuracy.cc
deleted file mode 100644 (file)
index 66c19a8..0000000
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 <algorithm>
-#include <atomic>
-#include <chrono>
-#include <forward_list>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <numeric>
-#include <stdexcept>
-#include <string>
-#include <thread>
-
-#include <boost/filesystem.hpp>
-#include <boost/format.hpp>
-#include <boost/program_options.hpp>
-
-#include <cmath>
-#include <cstdint>
-#include <signal.h>
-
-#include <tensorflow/lite/context.h>
-#include <tensorflow/lite/interpreter.h>
-#include <tensorflow/lite/model.h>
-
-#include "labels.h"
-#include "tflite/ext/nnapi_delegate.h"
-#include "tflite/ext/kernels/register.h"
-
-const std::string kDefaultImagesDir = "res/input/";
-const std::string kDefaultModelFile = "res/model.tflite";
-
-template <typename... Args> void Print(const char *fmt, Args... args)
-{
-#if __cplusplus >= 201703L
-  std::cerr << boost::str(boost::format(fmt) % ... % std::forward<Args>(args)) << std::endl;
-#else
-  boost::format f(fmt);
-  using unroll = int[];
-  unroll{0, (f % std::forward<Args>(args), 0)...};
-  std::cerr << boost::str(f) << std::endl;
-#endif
-}
-
-template <typename DataType> struct BaseLabelData
-{
-  explicit BaseLabelData(int label = -1, DataType confidence = 0)
-    : label(label), confidence(confidence)
-  {
-  }
-
-  static std::vector<BaseLabelData<DataType>> FindLabels(const DataType *output_tensor,
-                                                         unsigned int top_n = 5)
-  {
-    top_n = top_n > 1000 ? 1000 : top_n;
-    size_t n = 0;
-    std::vector<size_t> indices(1000);
-    std::generate(indices.begin(), indices.end(), [&n]() { return n++; });
-    std::sort(indices.begin(), indices.end(), [output_tensor](const size_t &i1, const size_t &i2) {
-      return output_tensor[i1] > output_tensor[i2];
-    });
-    std::vector<BaseLabelData<DataType>> results(top_n);
-    for (unsigned int i = 0; i < top_n; ++i)
-    {
-      results[i].label = indices[i];
-      results[i].confidence = output_tensor[indices[i]];
-    }
-    return results;
-  }
-
-  int label;
-  DataType confidence;
-};
-
-class BaseRunner
-{
-public:
-  virtual ~BaseRunner() = default;
-
-  /**
-   * @brief Run a model for each file in a directory, and collect and print
-   * statistics.
-   */
-  virtual void IterateInDirectory(const std::string &dir_path, const int labels_offset) = 0;
-
-  /**
-   * @brief Request that the iteration be stopped after the current file.
-   */
-  virtual void ScheduleInterruption() = 0;
-};
-
-template <typename DataType_> class Runner : public BaseRunner
-{
-public:
-  using DataType = DataType_;
-  using LabelData = BaseLabelData<DataType>;
-
-  const int kInputSize;
-  const int KOutputSize = 1001 * sizeof(DataType);
-
-  Runner(std::unique_ptr<tflite::Interpreter> interpreter,
-         std::unique_ptr<tflite::FlatBufferModel> model,
-         std::unique_ptr<::nnfw::tflite::NNAPIDelegate> delegate, unsigned img_size)
-    : interpreter(std::move(interpreter)), model(std::move(model)), delegate(std::move(delegate)),
-      interrupted(false), kInputSize(1 * img_size * img_size * 3 * sizeof(DataType))
-  {
-    inference_times.reserve(500);
-    top1.reserve(500);
-    top5.reserve(500);
-  }
-
-  virtual ~Runner() = default;
-
-  /**
-   * @brief Get the model's input tensor.
-   */
-  virtual DataType *GetInputTensor() = 0;
-
-  /**
-   * @brief Get the model's output tensor.
-   */
-  virtual DataType *GetOutputTensor() = 0;
-
-  /**
-   * @brief Load Image file into tensor.
-   * @return Class number if present in filename, -1 otherwise.
-   */
-  virtual int LoadFile(const boost::filesystem::path &input_file)
-  {
-    DataType *input_tensor = GetInputTensor();
-    if (input_file.extension() == ".bin")
-    {
-      // Load data as raw tensor
-      std::ifstream input_stream(input_file.string(), std::ifstream::binary);
-      input_stream.read(reinterpret_cast<char *>(input_tensor), kInputSize);
-      input_stream.close();
-      int class_num = boost::lexical_cast<int>(input_file.filename().string().substr(0, 4));
-      return class_num;
-    }
-    else
-    {
-      // Load data as image file
-      throw std::runtime_error("Runner can only load *.bin files");
-    }
-  }
-
-  void Invoke()
-  {
-    TfLiteStatus status;
-    if (delegate)
-    {
-      status = delegate->Invoke(interpreter.get());
-    }
-    else
-    {
-      status = interpreter->Invoke();
-    }
-    if (status != kTfLiteOk)
-    {
-      throw std::runtime_error("Failed to invoke interpreter.");
-    }
-  }
-
-  int Process()
-  {
-    auto t0 = std::chrono::high_resolution_clock::now();
-    Invoke();
-    auto t1 = std::chrono::high_resolution_clock::now();
-    std::chrono::duration<double> fs = t1 - t0;
-    auto d = std::chrono::duration_cast<std::chrono::milliseconds>(fs);
-    inference_times.push_back(d.count());
-    if (d > std::chrono::milliseconds(10))
-    {
-      Print("  -- inference duration: %lld ms", d.count());
-    }
-    else
-    {
-      auto du = std::chrono::duration_cast<std::chrono::microseconds>(fs);
-      Print("  -- inference duration: %lld us", du.count());
-    }
-    return 0;
-  }
-
-  void DumpOutputTensor(const std::string &output_file)
-  {
-    DataType *output_tensor = GetOutputTensor();
-    std::ofstream output_stream(output_file, std::ofstream::binary);
-    output_stream.write(reinterpret_cast<char *>(output_tensor), KOutputSize);
-  }
-
-  void PrintExecutionSummary() const
-  {
-    Print("Execution summary:");
-    Print("  -- # of processed images: %d", num_images);
-    if (num_images == 0)
-    {
-      return;
-    }
-    // Inference time - mean
-    double mean = std::accumulate(inference_times.begin(), inference_times.end(), 0.0) / num_images;
-    Print("  -- mean inference time: %.1f ms", mean);
-    // Inference time - std
-    std::vector<double> diff(num_images);
-    std::transform(inference_times.begin(), inference_times.end(), diff.begin(),
-                   [mean](size_t n) { return n - mean; });
-    double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
-    double std_inference_time = std::sqrt(sq_sum / num_images);
-    Print("  -- std inference time: %.1f ms", std_inference_time);
-    // Top-1 and Top-5 accuracies
-    float num_top1 = std::accumulate(top1.begin(), top1.end(), 0);
-    float num_top5 = std::accumulate(top5.begin(), top5.end(), 0);
-    Print("  -- top1: %.3f, top5: %.3f", num_top1 / num_images, num_top5 / num_images);
-  }
-
-  virtual void ScheduleInterruption() override { interrupted = true; }
-
-  virtual void IterateInDirectory(const std::string &dir_path, const int labels_offset) override
-  {
-    interrupted = false;
-    namespace fs = boost::filesystem;
-    if (!fs::is_directory(dir_path))
-    {
-      throw std::runtime_error("Could not open input directory.");
-    }
-
-    inference_times.clear();
-    top1.clear();
-    top5.clear();
-    int class_num;
-    num_images = 0;
-    std::vector<LabelData> lds;
-    fs::directory_iterator end;
-    for (auto it = fs::directory_iterator(dir_path); it != end; ++it)
-    {
-      if (interrupted)
-      {
-        break;
-      }
-      if (!fs::is_regular_file(*it))
-      {
-        continue;
-      }
-      Print("File : %s", it->path().string());
-      try
-      {
-        class_num = LoadFile(*it) + labels_offset;
-        Print("Class: %d", class_num);
-      }
-      catch (std::exception &e)
-      {
-        Print("%s", e.what());
-        continue;
-      }
-      int status = Process();
-      if (status == 0)
-      {
-        DataType *output_tensor = GetOutputTensor();
-        lds = LabelData::FindLabels(output_tensor, 5);
-        bool is_top1 = lds[0].label == class_num;
-        bool is_top5 = false;
-        for (const auto &ld : lds)
-        {
-          is_top5 = is_top5 || (ld.label == class_num);
-          Print("  -- label: %s (%d), prob: %.3f", ld.label >= 0 ? labels[ld.label] : "", ld.label,
-                static_cast<float>(ld.confidence));
-        }
-        Print("  -- top1: %d, top5: %d", is_top1, is_top5);
-        top1.push_back(is_top1);
-        top5.push_back(is_top5);
-      }
-      ++num_images;
-    }
-    PrintExecutionSummary();
-  }
-
-protected:
-  std::unique_ptr<tflite::Interpreter> interpreter;
-  std::unique_ptr<tflite::FlatBufferModel> model;
-  std::unique_ptr<::nnfw::tflite::NNAPIDelegate> delegate;
-
-  std::vector<size_t> inference_times;
-  std::vector<bool> top1;
-  std::vector<bool> top5;
-  uint num_images;
-  std::atomic_bool interrupted;
-};
-
-class FloatRunner : public Runner<float>
-{
-public:
-  using Runner<float>::DataType;
-
-  FloatRunner(std::unique_ptr<tflite::Interpreter> interpreter,
-              std::unique_ptr<tflite::FlatBufferModel> model,
-              std::unique_ptr<::nnfw::tflite::NNAPIDelegate> delegate, unsigned img_size)
-    : Runner<float>(std::move(interpreter), std::move(model), std::move(delegate), img_size)
-  {
-  }
-
-  virtual ~FloatRunner() = default;
-
-  virtual DataType *GetInputTensor() override
-  {
-    return interpreter->tensor(interpreter->inputs()[0])->data.f;
-  }
-
-  virtual DataType *GetOutputTensor() override
-  {
-    return interpreter->tensor(interpreter->outputs()[0])->data.f;
-  }
-};
-
-class QuantizedRunner : public Runner<uint8_t>
-{
-public:
-  using Runner<uint8_t>::DataType;
-
-  QuantizedRunner(std::unique_ptr<tflite::Interpreter> interpreter,
-                  std::unique_ptr<tflite::FlatBufferModel> model,
-                  std::unique_ptr<::nnfw::tflite::NNAPIDelegate> delegate, unsigned img_size)
-    : Runner<uint8_t>(std::move(interpreter), std::move(model), std::move(delegate), img_size)
-  {
-  }
-
-  virtual ~QuantizedRunner() = default;
-
-  virtual DataType *GetInputTensor() override
-  {
-    return interpreter->tensor(interpreter->inputs()[0])->data.uint8;
-  }
-
-  virtual DataType *GetOutputTensor() override
-  {
-    return interpreter->tensor(interpreter->outputs()[0])->data.uint8;
-  }
-};
-
-enum class Target
-{
-  TfLiteCpu,      /**< Use Tensorflow Lite's CPU kernels. */
-  TfLiteDelegate, /**< Use Tensorflow Lite's NN API delegate. */
-  NnfwDelegate    /**< Use NNFW's NN API delegate. */
-};
-
-std::unique_ptr<BaseRunner> MakeRunner(const std::string &model_path, unsigned img_size,
-                                       Target target = Target::NnfwDelegate)
-{
-  auto model = tflite::FlatBufferModel::BuildFromFile(model_path.c_str());
-  if (not model)
-  {
-    throw std::runtime_error(model_path + ": file not found or corrupted.");
-  }
-  Print("Model loaded.");
-
-  std::unique_ptr<tflite::Interpreter> interpreter;
-  nnfw::tflite::BuiltinOpResolver resolver;
-  tflite::InterpreterBuilder(*model, resolver)(&interpreter);
-  if (not interpreter)
-  {
-    throw std::runtime_error("interpreter construction failed.");
-  }
-  if (target == Target::TfLiteCpu)
-  {
-    interpreter->SetNumThreads(std::max(std::thread::hardware_concurrency(), 1U));
-  }
-  else
-  {
-    interpreter->SetNumThreads(1);
-  }
-  if (target == Target::TfLiteDelegate)
-  {
-    interpreter->UseNNAPI(true);
-  }
-
-  int input_index = interpreter->inputs()[0];
-  interpreter->ResizeInputTensor(input_index,
-                                 {1, static_cast<int>(img_size), static_cast<int>(img_size), 3});
-  if (interpreter->AllocateTensors() != kTfLiteOk)
-  {
-    throw std::runtime_error("tensor allocation failed.");
-  }
-
-  if (target == Target::TfLiteDelegate)
-  {
-    // Do a fake run to load NN API functions.
-    interpreter->Invoke();
-  }
-
-  std::unique_ptr<::nnfw::tflite::NNAPIDelegate> delegate;
-  if (target == Target::NnfwDelegate)
-  {
-    delegate.reset(new ::nnfw::tflite::NNAPIDelegate);
-    delegate->BuildGraph(&(interpreter.get()->primary_subgraph()));
-  }
-
-  if (interpreter->tensor(input_index)->type == kTfLiteFloat32)
-  {
-    return std::unique_ptr<FloatRunner>(
-      new FloatRunner(std::move(interpreter), std::move(model), std::move(delegate), img_size));
-  }
-  else if (interpreter->tensor(input_index)->type == kTfLiteUInt8)
-  {
-    return std::unique_ptr<QuantizedRunner>(
-      new QuantizedRunner(std::move(interpreter), std::move(model), std::move(delegate), img_size));
-  }
-  throw std::invalid_argument("data type of model's input tensor is not supported.");
-}
-
-Target GetTarget(const std::string &str)
-{
-  static const std::map<std::string, Target> target_names{
-    {"tflite-cpu", Target::TfLiteCpu},
-    {"tflite-delegate", Target::TfLiteDelegate},
-    {"nnfw-delegate", Target::NnfwDelegate}};
-  if (target_names.find(str) == target_names.end())
-  {
-    throw std::invalid_argument(
-      str + ": invalid target. Run with --help for a list of available targets.");
-  }
-  return target_names.at(str);
-}
-
-// We need a global pointer to the runner for the SIGINT handler
-BaseRunner *runner_ptr = nullptr;
-void HandleSigInt(int)
-{
-  if (runner_ptr != nullptr)
-  {
-    Print("Interrupted. Execution will stop after current image.");
-    runner_ptr->ScheduleInterruption();
-    runner_ptr = nullptr;
-  }
-  else
-  {
-    exit(1);
-  }
-}
-
-int main(int argc, char *argv[])
-try
-{
-  namespace po = boost::program_options;
-  po::options_description desc("Run a model on multiple binary images and print"
-                               " statistics");
-  // clang-format off
-  desc.add_options()
-    ("help", "print this message and quit")
-    ("model", po::value<std::string>()->default_value(kDefaultModelFile), "tflite file")
-    ("input", po::value<std::string>()->default_value(kDefaultImagesDir), "directory with input images")
-    ("offset", po::value<int>()->default_value(1), "labels offset")
-    ("target", po::value<std::string>()->default_value("nnfw-delegate"),
-      "how the model will be run (available targets: tflite-cpu, tflite-delegate, nnfw-delegate)")
-    ("imgsize", po::value<unsigned>()->default_value(224), "the width and height of the image");
-  // clang-fomrat on
-  po::variables_map vm;
-  po::store(po::parse_command_line(argc, argv, desc), vm);
-  if (vm.count("help"))
-  {
-    std::cerr << desc << std::endl;
-    return 0;
-  }
-
-  auto runner = MakeRunner(vm["model"].as<std::string>(), vm["imgsize"].as<unsigned>(),
-                           GetTarget(vm["target"].as<std::string>()));
-  runner_ptr = runner.get();
-
-  struct sigaction sigint_handler;
-  sigint_handler.sa_handler = HandleSigInt;
-  sigemptyset(&sigint_handler.sa_mask);
-  sigint_handler.sa_flags = 0;
-  sigaction(SIGINT, &sigint_handler, nullptr);
-
-  Print("Running TensorFlow Lite...");
-  runner->IterateInDirectory(vm["input"].as<std::string>(), vm["offset"].as<int>());
-  Print("Done.");
-  return 0;
-}
-catch (std::exception &e)
-{
-  Print("%s: %s", argv[0], e.what());
-  return 1;
-}